What's the modern equivalent of GetNextEvent in Cocoa? - objective-c

I'm porting an archaic C++/Carbon program to Obj-C and Cocoa. The current version uses asynchronous usb reads and GetNextEvent to read the data.
When I try to compile this in Objective C, GetNextEvent isn't found because it's in the Carbon framework.
Searching Apple support yields nothing of use.
EDIT TO ADD:
Ok, so what I'm trying to do is run a document scanner through USB. I have set up the USBDeviceInterface and the USBInterfaceInterface (who came up with THAT name???) and I call (*usbInterfaceInterface)->WritePipeTO() to ask the scanner to scan. I believe this works. AT least the flatbed light moves across the page...
Then I try to use *(usbInterfaceInterface))->ReadPipeAsyncTO() to read data. I give this function a callback function, USBDoneProc().
The general structure is:
StartScan()
WaitForScan()
StartScan() calls the WritePipeTO and the ReadPipeAsyncTO
WaitForScan() has this:
while (deviceActive) {
EventRecord event;
GetNextEvent(0,&event);
if (gDataPtr != saveDataPtr) { // more data up the timeout
timeoutTicks = TickCount() + 60 * 60;
saveDataPtr = gDataPtr;
}
if (TickCount() > timeoutTicks) {
deviceActive = false;
}
}
Meanwhile, USBDoneProc incrementing gDataPtr to be the end of the data that we've read so far. It gets called several times during the asynchronous read, called automatically by the callback, as far as I can tell.
If I cake out the GetNextEvent() call in the WORKING code the USBDoneProc doesn't get called until the asynchronous readpipe timesout.
So it looks to me that I need something to give control back to the event handler so that the USBRead interrupts can actually interrupt and make the USBDoneProcget called...
Does that make any sense?
thanks.

I suppose the nearest thing to a Cocoa equivalent would be -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]. But bear in mind that GetNextEvent is archaic even for Carbon. The preferred way of handing events is the "don't call us, we'll call you" scheme, where the app calls NSApplicationMain or RunApplicationEventLoop and events are dispatched to you.
EDIT to add: Does you app have a normal event loop? If so, maybe WaitForScan could start a Carbon timer and return to the event loop. Each time the timer fires, do what you did in the WaitForScan loop.

there is a USB hidapi that works for mac on windows.
http://www.signal11.us/oss/hidapi/
may this could be of help to you?
It works fine (I can list the connected USB devices and connect/write/read to a device);
however, if i USB device is connected/disconnected during the runtime of the application, I don't see the new connected/disconnected devices.
See: https://github.com/signal11/hidapi/issues/14
If I add the following code to hidapi, then hidapi detects the new USB devices.
#include <Carbon/Carbon.h>
void check_apple_events() {
printf("check_apple_events\n");
RgnHandle cursorRgn = NULL;
Boolean gotEvent=TRUE;
EventRecord event;
while (gotEvent) {
gotEvent = WaitNextEvent(everyEvent, &event, 0L, cursorRgn);
}
}
I need to compile this on OSX10.5 because it uses Carbon instead of Cocoa.
I am currently looking how to transform this to Cocoa.
you are also trying to move your code to cocoa, right?
let me know if you find out; I'll post it here if I get it.
regards,
David

Have you considered throwing the whole thing out and using Image Kit's new-in-10.6 scanner support instead? Even if it's custom, writing a TWAIN driver for it might be easier (and is certainly better) than trying to twist Cocoa into a GetNextEvent shape.

Related

How to call a method on the GUI thread in C++/winrt

When responding to an event in a textbox using C++/winrt I need to use ScrollViewer.ChangeView(). Trouble is, nothing happens when the call executes and I expect that is because at that moment the code is in the wrong thread; I have read this is the cause for lack of visible results from ChangeView(). It appears that the proper course is to use CoreDispatcher.RunAsync to update the scroller on the UI thread. The example code for this is provided only in C# and managed C++, however, and it is a tricky matter to figure out how this would look in normal C++. At any rate, I am not getting it. Does anyone have an example of the proper way to call a method on the UI thread in C++/winrt? Thanks.
[UPDATE:] I have found another method that seems to work, which I will show here, though I am still interested in an answer to the above. The other method is to create an IAsyncOperation that boils down to this:
IAsyncOperation<bool> ScrollIt(h,v, zoom){
co_await m_scroll_viewer.ChangeView(h,v,zoom);
}
The documentation entry Concurrency and asynchronous operations with C++/WinRT: Programming with thread affinity in mind explains, how to control, which thread runs certain code. This is particularly helpful in context of asynchronous functions.
C++/WinRT provides helpers winrt::resume_background() and winrt::resume_foreground(). co_await-ing either one switches to the respective thread (either a background thread, or the thread associated with the dispatcher of a control).
The following code illustrates the usage:
IAsyncOperation<bool> ScrollIt(h, v, zoom){
co_await winrt::resume_background();
// Do compute-bound work here.
// Switch to the foreground thread associated with m_scroll_viewer.
co_await winrt::resume_foreground(m_scroll_viewer.Dispatcher());
// Execute GUI-related code
m_scroll_viewer.ChangeView(h, v, zoom);
// Optionally switch back to a background thread.
// Return an appropriate value.
co_return {};
}

pygtk vlc player does not play next track

I'm writing a small custom player based on libvlc. I've used much of the code from https://github.com/hartror/python-libvlc-bindings/blob/master/examples/gtkvlc.py that plays a single track just like I need.
Now I want to swtich to another track after previous has finished. To do that I catch callback "EventType.MediaPlayerEndReached" and in callback handler I write code:
<------>def endCallback(self,event):
<------><------>fname = vlc_controller.GetNextTrack()['url']
<------><------>self.w.set_title(fname)
<------><------>self.vlc.player.set_mrl(fname)
<------><------>self.w.set_title('after set_mrl')
<------><------>self.vlc.player.play()
<------><------>self.w.set_title('after play')
Now when this code gets executed it stucks on self.vlc.player.set_mrl(fname) and does not go any further and as a result I see NO NEXT TRACK.
I've tried different variations of this code using (vlc.stop(), vlc.set_media instead of vlc.set_mrl) but nothing works
Finally....
I think the best choise is to make multi threaded application on python
2 Threads:
Main thread - gtk.loop and displaying video an some other thinks
Additional thread that makes media switching.
For some time I was afraid of multithreading but now I know that this was the best way to do this task
For those facing similar issue in C# (Xamarin), per VLC documentation, calling the VLC object from an event tied to the object may freeze the application. So they said to use the code below inside the trigger event.
ThreadPool.QueueUserWorkItem(_ => PlayNext());
An example would be calling the code above inside the EndReach event.
Where PlayNext() is your own custom method to handle the next action you want to execute.
I struggled with this for about a day before seeing that portion of the documentation.

Problems receiving Notifications from IOKit (CoreFoundation) for plugged Devices

I'm currently developing an application on 10.6.7 which should receive notifications when a new usb device is plugged in. I found out that there is a IOKit function which handles such stuff 'IOServiceAddMatchingNotification'. Because the return value from this specific function is 0, I think that the problem perhaps is in my matching Dictionary, which is given into this function. I declare the Dictionary that way:
CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
Because I wan't to receive a notification for each device, I don't know if this is the right way to create this particular dictionary.
My complete code look like this:
ioKitNotificationPort = IONotificationPortCreate(kIOMasterPortDefault);
notificationRunLoopSource = IONotificationPortGetRunLoopSource(ioKitNotificationPort);
CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode);
CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
addMatchingNotificationResult = IOServiceAddMatchingNotification(ioKitNotificationPort,
kIOPublishNotification,
matchingDict,
deviceAdded,
NULL,
Does anyone has a idea why this won't work?
(Note: The Callback function is a static void c function and the rest is wrapped ins
ide a Obj-C class).
Thanks
Xcode 4, 10.6.7
Weirdly, you must empty the iterator returned by IOServiceAddMatchingNotification before the notification will be armed. I don't see that in the code provided, so that could be in the issue. That iterator is actually what you need to keep around to keep the notification running.
io_iterator_t ioNotification;
addMatchingNotificationResult = IOServiceAddMatchingNotification(ioKitNotificationPort,
kIOPublishNotification,
matchingDict,
deviceAdded,
NULL,
&ioNotification);
while ((service = IOIteratorNext(ioNotification)))
{
NSLog(#"Hey, I found a service!");
IOObjectRelease(service); // yes, you have to release this
}
In my opinion, u should download the source code form IOUSBFamily on opensource.apple.com, and then find the code for USB Prober, this application does exactly the same thing as u described, listening the USB Device attachment.(Further, USB Prober also get the general device and configuration descriptor, maybe it is also the things u need.)
Did you add the VID and PID of the device you wish to look for to your matching dictionary? For the dictionary you have, and VID= yourVid, PID= yourPid, it would be:
CFDictionaryAddValue(matchingDict, usbVendorId, yourVid);
CFDictionaryAddValue(matchingDict, usbProductId, yourPid);
Another thing - after the call to IOServiceAddMatchingNotification succeeds, you need to call your device-added handler with the iterator that was set in the call. That will arm the notification and check for existing devices.
the easiest way to do what i think you are describing is to hook into the DiskArbitration Framework. DA is relatively new to OSX and allows userland applications to examine devices as they get attached. it is what is used to open iTunes when an iPod is attached, launch iPhoto when a camera is attached, etc... if the USB device you are looking for is a storage device then this will work for you. otherwise you will need to go the matching dictionary route...

Objective-c -> class method to main file query

Sorry to bug twice so quickly, but since people were so kind in their informative responces, I figured it couldnt hurt to ask another question.
The same program i tried to make it rather swanky and have a main screen which allows you to click on a button which leads to a limited options screen. This lets you switch the music on or off. Or at least it should do.
The music running code is in the main file (game.m), under the following:
//Music
[Settings setMusicEnabled:YES];
music = [SPSound soundWithContentsOfFile:#"music.caf"];
channel = [[music createChannel] retain];
channel.loop = YES;
channel.volume = 0.25;
if([Settings musicEnabled]){
[channel play];
}
I apologize for the strange format, but it is Sparrow framework. basically, the Settings file contains the class methods I am trying to use. If the methods cause YES, the music is on. If it is No, then the music is off.
settings.m
static BOOL isMusicEnabled;
#implementation Settings
+ (BOOL)musicEnabled
{
return isMusicEnabled;
}
+ (void)setMusicEnabled:(BOOL)value
{
isMusicEnabled = value;
NSLog(#"SME? %i", isMusicEnabled);
}
#end
Now, the options file is working and i tested that section. The program is reading that isMusicEnabled is getting a new value, thus musicEnabled is being altered as well, so there should be a change and the music should be switched off.
However, nothing happens. I have tried to use debugger, but I am not very good at it and I dont understand a lot of the information i am given. I do understand that the problem is sending the message from Settings file to the main/Game file.
I would appriciate anyone's help who could enlighten me as to how this could be solved.
I'm not familiar with Sparrow Framework, but let me make a guess anyway.
[channel play]; starts playing the music in background until the channel is asked to stop playing.
Changing the isMusicEnabled does not trigger any code to stop the currently playing music. When you change the value in Settings, you should inform the channel to stop (most probably by somehow accessing the channel and calling [channel stop].
There's another problem - isMusicEnabled is just a variable in memory, your program will not remember its state between restarts. And Settings are usually supposed to be remembered.
To summarize I see two problems: persisting settings between restarts first and informing about change of settings second. To remember settings I suggest you look into NSUserDefaults class. To inform the channel to stop playing you have couple of options - depending on you skills. Easiest is to simply access the channel variable from within the setMusicEnabled and call stop. Another option would be to use notifications, but for a beginner programmer that is more complicated (look for NSNotificationCenter if interested).

Cocoa: int main function

I'm curious, what role does the int main function play in a Cocoa program? Virtually all of the sample code I've been looking at has only the following code in main.m:
#import <Cocoa/Cocoa.h>
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **) argv);
}
What exactly is this doing, and where does the program actually start stepping through commands? It seems my conceptions need readjustment.
Since a Cocoa project starts like any other, the entry point for the Operating system is main. However the Cocoa Architecture is constructed to actually start the processing of your program from NSApplicationMain, which is responsible for loading the initial window from your application and starting up the Events loop used to process GUI events.
Apple has a very in depth discussion on this under the Cocoa Fundamentals Guide : The Core Application Architecture on Mac OS X
If you want to learn how control passes from "launch this" to the main() function, the execve man page has the details. You would also want to read about dyld. main() is a part of the Unix standard. Every single program that you can run effectively has a main().
As others have mentioned, NSApplicationMain passes control to Cocoa. The documentation is quite specific as to what it does.
One interesting note, NSApplicationMain doesn't actually every return. That is, if you were to separate the call to NSApplicationMain from the return in your main function and put code in between, that code would never be executed.
main() is the entry point for your program.
When you run your program that is the first function called. Your program ends when you exit that function.
Also note that this does not come from Objective-C. This is simple C.
Have a look at
Wikipedia's page on it
Value returned from main is returned by the process to operating system when the process is done.
Shell stores the value returned by last process and you can get it back with $? :
> ls
a b c
> echo $?
0
> ls x
x: No such file or directory
> echo $?
1
ls is an application like anything else.
You can use the return value to chain multiple processes together using shell script or anything else that can execute a process and check for return value.
I'm wondering where the code begins
executing (like why does an NSView
subclass execute and draw without me
explicitly calling it?) and if I'm not
supposed to stick my main loop in int
main() where does it go?
In an xcode project you have a main.m file that contains the 'int main' function. You won't actually find the code that calls the NSView draw explicitly, this code is hidden deep within an iPhone or Mac OS X framework. Just know that there is an event loop hidden deep within your 'int main' that checks for changes so that it knows when to update your view. You don't need to know where this event loop is, it's not useful information since you can override methods or create and assign delegates that can do things when this happens.
To get a better answer, you'll need to explain what you mean by a 'main loop' that you wanted to put inside the 'int main' function.
It's just weird to me coming off a
little experience in C++. It looks
unnatural that the main function would
be so empty.
You can encapsulate a billion lines of code into one function and put it into 'int main'. Don't be deceived by a main only having a few lines, that is done on purpose. Good programming teaches us to keep code in specific containers so that it is well organized. Apple chose to make the "real" launch point of their iPhone apps in this single line of code inside the main.m file:
int retVal = UIApplicationMain(argc, argv, nil, #"SillyAppDelegate");
From that one piece of code, an app's delegate is launched and won't return control to the main function until it is done.