Problems receiving Notifications from IOKit (CoreFoundation) for plugged Devices - usb

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...

Related

Setting sound output/input

I've been looking all over the web, but I don't know if it is possible: can a Cocoa Mac OS X app change the sound input/output device? If so, how come?
can a Cocoa Mac OS X app change the sound input/output device?
Yes, by setting the relevant Audio System Object property.
If so, how come?
Probably because the user might want to change the default input or output device from within an application, rather than having to jump over to the Sound prefpane before and after or use the Sound menu extra.
I know this is an old post but I've been struggling these days trying to find a way of changing the sound input/output device using code and I finally found how to do it. In case someone else runs into the same problem, here's the answer!
There's a command line utility called SwitchAudio-OSX (https://code.google.com/p/switchaudio-osx/) that allows you to switch the audio source from the terminal. It is open-source and you can find the latest version here: https://github.com/deweller/switchaudio-osx.
Anyway, you can use these lines to change the sound input/output device:
UInt32 propertySize = sizeof(UInt32);
AudioHardwareSetProperty(kAudioHardwarePropertyDefaultInputDevice, propertySize, &newDeviceID); // To change the input device
AudioHardwareSetProperty(kAudioHardwarePropertyDefaultOutputDevice, propertySize, &newDeviceID); // To change the output device
AudioHardwareSetProperty(kAudioHardwarePropertyDefaultSystemOutputDevice, propertySize, &newDeviceID); // To change the system output device
Where newDeviceID is an instance of AudioDeviceID and represents the id of the device you want to select. Also, a list of all available devices can be obtained using this code:
AudioDeviceID dev_array[64];
AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &propertySize, dev_array);
int numberOfDevices = (propertySize / sizeof(AudioDeviceID));

Prevent webcam light from illuminating when accessing microphone in Silverlight 4

I'm writing a small audio recorder component in Silverlight 4. It works fine, but I've noticed that when I'm recording audio, the light on my webcam turns on indicating that the camera is active.
While I know that I'm not doing anything insidious with the webcam, my users would have every right to be suspicious. Is it possible to tell Silverlight that I'm only interested in microphone access and not activate the webcam?
FWIW here's how I'm accessing the mic:
private CaptureSource _source = new CaptureSource();
private MemoryAudioSink _sink; // Inherits from AudioSink. Doesn't do much more
// than store PCM audio stream in memory
private void Record_Click(object sender, RoutedEventArgs e)
{
if (( CaptureDeviceConfiguration.AllowedDeviceAccess ||
CaptureDeviceConfiguration.RequestDeviceAccess() ) &&
_source.State == CaptureState.Stopped)
{
_sink = new MemoryAudioSink();
_sink.CaptureSource = _source;
_source.Start();
}
}
CaptureSource will frequently grab the default video input device, even if you don't tell it to. Though you aren't using the camera, Silverlight is indeed accessing it. Hopefully, MS will fix this odd behavior in a later version of Silverlight.
In the meantime, just explicitly set VideoCaptureDevice to null:
var _audioCaptureSource = new CaptureSource {VideoCaptureDevice = null};
This would depend on the webcam driver - Silverlight would have no control over this.
I'm guessing its related to your use of CaptureSource. Microsoft's web site claims that:
Silverlight 4 APIs only use
CaptureSource in a video scenario
where audio may not be relevant.
Is there a way to get audio without creating your own CaptureSource?

What's the modern equivalent of GetNextEvent in Cocoa?

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.

Does anyone know of a Cocoa/Obj-C library that can be used to gather application usage data

I would like to be able to gather info like how often certain windows are opened, what types of user data are accessed, how often menu items are clicked, etc. Does anyone know of a 3rd party (open source or commercial) Cocoa/Obj-C library or plugin that would allow me to gather this info?
I have used pinch media in the past, and they merged with Flurry. Library was simple to use and was setup in around 40 minutes.
I don't know any library for that but at least to get informed about when the user switches the front application you can install an event handler like this:
EventTypeSpec eventType;
eventType.eventClass = kEventClassApplication;
eventType.eventKind = kEventAppFrontSwitched;
EventHandlerUPP handlerUPP = NewEventHandlerUPP(FrontAppSwitchedDetector_callback);
OSStatus status=InstallApplicationEventHandler(handlerUPP,1,&eventType,self,&_eventHandlerRef);
... and when receiving an callback you may get the current front application process:
pascal OSStatus FrontAppSwitchedDetector_callback(EventHandlerCallRef nextHandler,EventRef theEvent,void* userData)
{
ProcessSerialNumber newSerial;
GetFrontProcess(&newSerial);
//to something with that ....
return (CallNextEventHandler(nextHandler, theEvent));
}

How to know a video source (webcam) is available or not without creating capture window?

It is quite tricky because I wanna to take the result as a sign for later process. If a window flashes, it would be weird to user.
(This is not an answer, just refreshing the question and adding some details:)
Suppose you need to open a video capture driver (webcam) with code like this (delphi, but easy understandable):
result:= SendMessage(hCapWnd, WM_CAP_DRIVER_CONNECT, FDriverNo, 0);
It works fine, except when camera/webcam is busy (opened by another application, for example moviemaker). Then the capture driver suddenly shows a "select video source" window that blocks your application (but not moviemaker, which keeps recording). SendMessage function becomes modal and will not return until undesired window is closed.
Is there a way to detect if a capture driver is busy with another application before connecting to it?
Thanks
This function return number of available webcams and scanners on your mashine(с++).
int GetNumCam()
{
int MemberIndex = 0;
HDEVINFO dev;
SP_DEVINFO_DATA DeviceInfoData;
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
dev = SetupDiGetClassDevsA(&GUID_DEVINTERFACE_IMAGE, NULL,NULL,DIGCF_PRESENT);
if (dev == NULL)
{
MessageBoxA(0,"it is null..","vse propalo",0);
return -1;
}
else
{
while(SetupDiEnumDeviceInfo(dev,MemberIndex, &DeviceInfoData))
{
MemberIndex++;
}
}
return MemberIndex;
}
I wonder if sending a broadcast message could do. I mean, suppose you send a VFW info request message to all windows in system. Then, all windows actually doing VFW processing will answer their status info and you will know which of them are doing video processing; some kind of shouting "anybody here...?"
But it looks like brute force, or even hacking. May be I'll test it... may be not. I am sure there must be a smarter way to know if a video capture driver is busy with another application.
(btw... anybody here?)
I was afraid it would happen.
First I enumerated all opened windows in system, then executed this instruction for each HWND, which just asks for driver information (pascal syntax):
SendMessage(h, WM_CAP_DRIVER_GET_NAME, length(driver)*sizeof(char), LPARAM(PChar(driver))
According to Msdn help, WM_CAP_DRIVER_GET_NAME results are:
"Returns TRUE if successful or FALSE if the capture window is not connected to a capture driver"
(Bold is mine). So it appears a good way to know:
1-If the window is capturing. So it is applyable to ALL windows, don't matter if they are capturing or not.
2-And if so, it tells you which driver is using.
However, after first test round, the results were:
- Task Manager (it was running) crashed and closed
- Explorer crashed and closed (reopened again automatically)
- Belkin Wireless monitor (my pc's WiFi driver) crashed and closed
- Eset Nod32 antivirus crashed, did not closed
The first conclussion can be that this is a bad way to locate which applications are capturing video in a system. But I must ensure to dismiss the possibility of a bug.
I'll keep reporting.
This is not a good solution my any means but I found out that if you disable and enable the camera in device manager immediately before sending the WM_CAP_DRIVER_CONNECT message then for some reason the video source window does not appear and the function returns and works OK.
So for a script I was working on I had to download devcon.exe and I put "devcon disable *PID_3450*MI_00*" and "devcon enable *PID_3450*MI_00*" immediately before my WM_CAP_DRIVER_CONNECT and it seems to work consistently. Unfortunately you need to run as administrator to be able to disable/enable devices. Again not a proper fix by any means...
(Hardware ID of my cam is USB\VID_0AC8&PID_3450&MI_00)