156
160
* Media poll function
162
* NOTE: to facilitate orderly thread termination, media_poll_func MUST end up waiting in CFRunLoopRun.
163
* Early returns must be avoided, even if there is nothing useful to be done here. See DarwinSysExit.
166
static void dummy(void *) { }; // stub for dummy runloop source
159
168
static void *media_poll_func(void *)
161
170
media_poll_loop = CFRunLoopGetCurrent();
163
172
mach_port_t masterPort;
164
kern_return_t kernResult = IOMasterPort(bootstrap_port, &masterPort);
165
if (kernResult != KERN_SUCCESS) {
173
kern_return_t kernResult;
174
CFMutableDictionaryRef matchingDictionary;
175
CFRunLoopSourceRef loopSource = NULL;
176
CFRunLoopSourceRef dummySource = NULL;
178
if ((kernResult = IOMasterPort(bootstrap_port, &masterPort)) != KERN_SUCCESS)
166
179
fprintf(stderr, "IOMasterPort() returned %d\n", kernResult);
170
CFMutableDictionaryRef matchingDictionary = IOServiceMatching(kIOCDMediaClass);
171
if (matchingDictionary == NULL) {
180
else if ((matchingDictionary = IOServiceMatching(kIOCDMediaClass)) == NULL)
172
181
fprintf(stderr, "IOServiceMatching() returned a NULL dictionary\n");
175
matchingDictionary = (CFMutableDictionaryRef)CFRetain(matchingDictionary);
177
IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
178
CFRunLoopAddSource(media_poll_loop,
179
IONotificationPortGetRunLoopSource(notificationPort),
180
kCFRunLoopDefaultMode);
182
io_iterator_t mediaArrivedIterator;
183
kernResult = IOServiceAddMatchingNotification(notificationPort,
184
kIOMatchedNotification,
186
(IOServiceMatchingCallback)media_arrived,
187
(void *)MEDIA_CD, &mediaArrivedIterator);
188
if (kernResult != KERN_SUCCESS)
189
fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
190
media_arrived(MEDIA_CD, mediaArrivedIterator);
192
io_iterator_t mediaRemovedIterator;
193
kernResult = IOServiceAddMatchingNotification(notificationPort,
194
kIOTerminatedNotification,
196
(IOServiceMatchingCallback)media_removed,
197
(void *)MEDIA_CD, &mediaRemovedIterator);
198
if (kernResult != KERN_SUCCESS)
199
fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
200
media_removed(MEDIA_CD, mediaRemovedIterator);
183
matchingDictionary = (CFMutableDictionaryRef)CFRetain(matchingDictionary);
184
IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
185
loopSource = IONotificationPortGetRunLoopSource(notificationPort);
186
CFRunLoopAddSource(media_poll_loop, loopSource, kCFRunLoopDefaultMode);
188
io_iterator_t mediaArrivedIterator;
189
kernResult = IOServiceAddMatchingNotification(notificationPort,
190
kIOMatchedNotification,
192
(IOServiceMatchingCallback)media_arrived,
193
(void *)MEDIA_CD, &mediaArrivedIterator);
194
if (kernResult != KERN_SUCCESS)
195
fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
196
media_arrived(MEDIA_CD, mediaArrivedIterator);
198
io_iterator_t mediaRemovedIterator;
199
kernResult = IOServiceAddMatchingNotification(notificationPort,
200
kIOTerminatedNotification,
202
(IOServiceMatchingCallback)media_removed,
203
(void *)MEDIA_CD, &mediaRemovedIterator);
204
if (kernResult != KERN_SUCCESS)
205
fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
206
media_removed(MEDIA_CD, mediaRemovedIterator);
209
if (loopSource == NULL) {
210
// add a dummy runloop source to prevent premature return from CFRunLoopRun
211
CFRunLoopSourceContext context = { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, dummy };
212
dummySource = CFRunLoopSourceCreate(NULL, 0, &context);
213
CFRunLoopAddSource(media_poll_loop, dummySource, kCFRunLoopDefaultMode);
218
if (dummySource != NULL)
219
CFRelease(dummySource);