i'm making a simple processing app for a presentation which currently does one thing : it listens to a microphone and emulates a right arrow key down event when it hears sound. I'm using it to synchronize a synth with the OSX finder, so when i play music it iterates through the files of a folder, as if i was pressing repeatedly on the right arrow on my keyboard.
my problem is that the app gets stuck when it hits the last file in a folder. The app needs to be aware of that so it can emulate a left arrow keydown event & a down arrow keydown event to go up a directory and carry on iterating.
I've tried calling applescript from processing to do that, which kind of works, but it's too slow and takes the focus away from the finder, then gives it back, which just looks glitchy (which is important as i'm making this app for a presentation).
I'm guessing i could maybe use a daemon polling which element is currently being selected in the finder, and sending that path to the processing app, and taking action if the path doesn't change after a keypress ; but then i'm not sure how to do that. Can python or bash poll that kind of info from the finder?
thank you!
import processing.sound.*;
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
Amplitude amp;
AudioIn in;
Robot robot;
void setup() {
size(1, 1);
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
exit();
}
Sound s = new Sound(this);
s.inputDevice(3);
// select audio device ; if not available will fall back to default input
amp = new Amplitude(this);
in = new AudioIn(this, 0);
in.start();
amp.input(in);
in.play();
// playback of audio input : will larsen if you use computer's mic
}
void draw() {
// println(amp.analyze());
if(amp.analyze()>0.3){
println("go");
// if sound is louder than 0.3 press right key
robot.keyPress(KeyEvent.VK_RIGHT);
robot.keyRelease(KeyEvent.VK_RIGHT);
delay(200);
// prob not the right delay
}
}
Related
I've got a Simulation built and need to add a GUI onto it to choose x amounts of steps to simulate. The program right now only shows me the end result and I need it to show the simulation.
I can see in the command window its running, but just wont show movement of characters.
The simulation is a 2d grid of a room and people moving around based on who they are next and how happy they would be. Without the GUI the program works fine so I assumed if putting the code from the main arg in the non GUI code into the action performed for my simulate button it would work.
Right now this is the actionPerformed method:
private void simButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
Simulator simulator = new Simulator(50, 50, 43);
// simulate the project for 10 rounds
simulator.simulate(10);
// simulator.setVisible(true);
}
I have a watchface with a companion app for phone. It uses Wearable.DataApi to sync changes between the phone and watch. I have a DataApi.DataListener setup and sync changes made on the watch or phone side. I have no issue with a phone and ONE watch communicating.
The issue is when i have multiple watches using the same watch face if changes on watch or phone side are made quickly it seems to go into a loop and start flashing the changes on all devices. So if im changing the color by tapping watch if I press a few times quickly to do that all devices start cycling through all colors and takes some time before it catches up and stops.
If I change options slowly there is no problem. I put a log in the DataApi listener and I see both uri's making the change but just seems to loop for some reason when changed quickly. Is there anyway to prevent this?
I know this might not seem like a big issue but if a user has 2 watches and accidently changes an option or options quickly it will start with the options and or colors changing. I want to prevent that from happening.
This is how im adding my listener in the onConnected method
Wearable.DataApi.addListener(mGoogleApiClient, dataListener);
And this is my listener method
DataApi.DataListener dataListener = new DataApi.DataListener() {
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
Log.d(TAG, "onDataChanged");
for (DataEvent event : dataEvents) {
Log.d(TAG, "dataEvent.uri: " + event.getDataItem().getUri().toString());
DataMap item = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
/////other code to set data/////
}
updateCanvas();
}
};
You should be able to avoid this by filtering out dataEvents that originated from the local node (i.e., the device that the code is running on).
Get the local node ID with code like this:
NodeApi.GetLocalNodeResult nodeResult = Wearable.NodeApi.getLocalNode(googleApiClient).await();
String localNodeID = getLocalNodeResult.getNode().getId();
Then, put code like this inside your for loop to do the filtering:
Uri uri = item.getUri();
String nodeID = uri.getHost();
if (nodeID.equals(localNodeID)) {
// Skip changes originating on this device
continue;
}
I implemented another version of this project with Java Swing, but because it could not support multi-touch functionality, I am rewriting it using JavaFX.
So I want the program to wait either for a user clicks a Button object or for a timeout, say 5 seconds - this means that the program would present a Button on the screen at one point and does not proceed to the next phase until either the Button is pressed or 5 seconds pass without it being pressed.
Clearly, detecting a click is elementary because adding ActionEvent would solve it. The tricky part is measuring the time. When implementing with Swing objects, I would have a while loop and have Thread.sleep(very_short_time_interval) inside to periodically check the elapsed time:
lastUpdate = System.currentTimeMillis();
while ((!pressed) && (System.currentTimeMillis() - lastUpdate <= timeout)) {
Thread.sleep(50);
}
The purpose of the Thread.sleep() in the pseudo-code above was to prevent the while loop from executing too often. Though it does not seem like the best practice, this trick apparently worked when used with Swing objects. But I realized after trying out the same thing with JavaFX Button objects, it turns the shape of the mouse pointer to a circulating ring, indicating the process is busy on Windows. What is worse is the button would not recognize mouse inputs during this busy phase. I am guessing JavaFX objects are heavier than Swing objects and is causing this problem as a result.
So my question is, would there be another way, possibly native function in JavaFX to make a Button expire without requiring a while loop? Or would there be some lighter weight objects than Button that works in a similar manner (listening to mouse clicks) that could work with the original while approach?
You can use a PauseTransition to wait for n-seconds. On its setOnFinished you can add an action to be performed. If the button has been pressed, you can cancel the transition on its action.
final PauseTransition pt = new PauseTransition(Duration.millis(5000));
pt.setOnFinished( ( ActionEvent event ) -> {
doSomething();
});
button.setOnAction( (ActionEvent event) -> {
doSomething();
pt.stop(); // If the button has been pressed, stop the Transition
});
pt.play();
I'm restarting development of a game I was working on, and have successfully converted it over to XNA 4.0 using the cheat sheet. Most of it works, some of it doesn't, and I'm in the process of fixing what doesn't work.
One thing that I had was a state system that was heavily based on the state system used as an example of XNA Unleashed, the ebook. I didn't have much in it.... basically just the ability to pause the game.
When I paused the game, the action of the game would stop, and the word "PAUSED" would appear in block letters across the screen, and you'd see the paused action. However, now it seems that the sprite batch automatically clears out everything between frames, so when I pause the game now, the screen clears, leaving PAUSED over a purple background. Back then, I believe that adding "SaveStateMode.SaveState" would prevent that from happening, but that functionality was removed. When I did some research, I found out that it was removed because it was essentially useless, that's all handled in the game state manager.
However, I can't find any documentation on this. Where should I start? Right now, my code looks like this:
In the Playing Game State update method:
if (input.WasPressed(0, Buttons.Start, Keys.Enter))
{
GameManager.PushState((GameState)ThisGame.PausedGameState.Value);
}
public void PushState(GameState newState)
{
AddState(newState);
//Let everyone know we just changed states
if (OnStateChange != null)
{
OnStateChange(this, null);
}
}
private void AddState(GameState state)
{
states.Push(state);
Game.Components.Add(state);
//Register the event for this state
OnStateChange += state.StateChanged;
}
//PausedGameState Draw method:
public override void Draw(GameTime gameTime)
{
ThisGame.SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null);
DrawPaused(); //draws the Paused Text
ThisGame.SpriteBatch.End();
}
The goal is to make "PAUSED" appear over the screen, with a snapshot of where the gameplay left off... and not "PAUSED" over a cleared purple screen.
Do you suppose that GraphicsDevice.Clear() somehow got called after the state changed to paused? What does the DrawPaused() method do in your code?
I'm trying to use CGAssociateMouseAndMouseCursorPosition(NO) in a program. This disconnects the mouse from the on screen cursor when your application is "in the foreground". Unfortunately it also disconnects it when Mission Control or the application switcher or who knows what else comes up.
So far I know:
The application is still active.
The window is still key.
Nothing is sent to the default notification center when these things come up.
The application stops receiving mouse moved events, but an NSEvent addGlobalMonitorForEventsMatchingMask:handler: also does not receive them, which is strange to say the least. It should receive any events not delivered to my application. (I was planning to detect the missing events to know when to associate the mouse again.
So, is there a way to detect when my application is no longer in control, specifically because Mission Control or the switch has taken over? They really expect the mouse to work and I need to restore that association for them.
I share your surprise that a global event monitor isn't seeing the events. In a similar situation, I used a Quartz Event Tap for a similar purpose. The Cocoa global event monitor is quite similar to event taps, so I figured it would work.
I put the tap on kCGAnnotatedSessionEventTap and compared the result from CGEventGetIntegerValueField(event, kCGEventTargetUnixProcessID) to getpid() to determine when the events were going to another app (e.g. Mission Control or Exposé). (I disable the tab when my app resigns active status, so it should only receive events destined for another app when this sort of overlay UI is presented.)
By the way, you mentioned monitoring the default notification center, but, if there's a notification about Mission Control or the like, it's more likely to come to the distributed notification center (NSDistributedNotificationCenter). So, it's worth checking that.
I needed to check for mission control being active and ended up with an approach along the lines of Ken's answer.
Sharing is caring so here is the smallest sensible complete code that worked for me: (Swift 5)
import Foundation
import AppKit
let dockPid = NSRunningApplication.runningApplications(withBundleIdentifier: "com.apple.dock").first?.processIdentifier
var eventTargetPid: Int32?
let eventTap = CGEvent.tapCreate(
tap: .cgAnnotatedSessionEventTap,
place: .headInsertEventTap,
options: .listenOnly,
eventsOfInterest: CGEventMask(
(1 << CGEventType.mouseMoved.rawValue)
| (1 << CGEventType.keyDown.rawValue)
),
callback: { (tapProxy, type, event, _:UnsafeMutableRawPointer?) -> Unmanaged<CGEvent>? in
// Now, each time the mouse moves this var will receive the event's target pid
eventTargetPid = Int32(event.getIntegerValueField(.eventTargetUnixProcessID))
return nil
},
userInfo: nil
)!
// Add the event tap to our runloop
CFRunLoopAddSource(
CFRunLoopGetCurrent(),
CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0),
.commonModes
)
let periodSeconds = 1.0
// Add a timer for periodic checking
CFRunLoopAddTimer(CFRunLoopGetCurrent(), CFRunLoopTimerCreateWithHandler(
kCFAllocatorDefault,
CFAbsoluteTimeGetCurrent() + periodSeconds, periodSeconds, 0, 0,
{ timer in
guard eventTargetPid != dockPid else {
print("Dock")
return
}
print("Not dock")
// Do things. This code will not run if the dock is getting events, which seems to always be the case if mission control or command switcher are active
}), .commonModes)
CFRunLoopRun()
This simply checks whether the dock was the one to receive the last event of interest (here that includes mouse movement and key-downs).
It covers most cases, but will report the wrong value between the command switcher or mission-control hiding and the first event being sent to a non-dock app. This is fine in my use-case but could be an issue for other ones.
Also, of course, when the dock at the bottom is active, this will detect that too.
Have you tried asking NSRunningApplication?