On Nov 7, 2011, at 5:45 PM, Brian Willoughby wrote: Mark, it seems like you're sending Tom off if the wrong direction if you're suggesting that he has to customize every UI object in his application to avoid everything coming to a halt when the mouse button is held down.
I think I miscommunicated here. I don't think that the NSButton action behavior is related to the halting of the sequencer, at least not explicitly. I was just trying to say that Tom needs to do something to let the NSButton know to fire it's action on mouseDown. The default for NSButton is to call -sendAction on mouseUp.
You can do this either by subclassing NSButton, or by calling - (NSInteger)sendActionOn:(NSInteger)mask
The fact that the NSTimer isn't firing while the mouse button is held down sounds to me like an unrelated problem. Most likely, this is just a bug in Tom's code which will require looking at a sample to track down.
I don't see any issue from running this whole thing from the main NSRunLoop. The programming will be much simpler without concurrency, though using another thread may be desirable if Tom needs to do heavy lifting processor-wise.
It's difficult for me to say without Tom's source, but everyone should keep in mind that NSTimer works with a Run Loop, and the default run loop is shared by the entire application for UI. If Tom's NSTimer is attached to the main run loop, then all UI code will be competing with his MIDI code.
Timers aren't super accurate anyhow, but Tom says that they are accurate enough for what he's doing. Depending on how far in advance Tom is scheduling his timer and how much stuff he's got on the main runloop, he may be just fine here. If he created another thread, that thread would be competing with the UI thread (and other threads) for processor time anyhow. Plus concurrent programming is HARD, so I would avoid it if possible. The better solution would be to create a separate Run Loop, or, more likely, just create a new NSThread and use the automatically-create Run Loop for that thread. Dedicating a thread to the timing of MIDI is far more sensible that rewriting AppKit to avoid all blocking API (of which there are many).
This is assuming that AppKit is blocking the main RunLoop at all, which I highly doubt it is doing. For example, AppKit needs to send a UI heartbeat to the CoreAppServices daemon, or you'll get a beachball (which isn't happening in this case). What Tom needs to do is look at the output of 'sample' and get acquainted with why his NSTimer isn't being re-set. See the documentation for NSTimer, NSRunLoop and NSThread - and be sure to follow all links in the documentation to related concepts. Just because it's easy to use NSTimer without doing your homework doesn't mean you're going to get the best results in every situation. :-)
I agree here. My caveat: be very averse to creating a new NSThread. You have k problems, so you spawn a new thread... now you have 2^k problems ;) When at all possible: prefer asynchronous / event-driven solutions to synchronous / concurrent solutions.
_Mark |