14 #include <CoreServices/CoreServices.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
23 "title" :
"VuoOscDevices",
25 "CoreServices.framework",
29 "VuoList_VuoOscInputDevice",
30 "VuoList_VuoOscOutputDevice"
71 if (error->domain || error->error)
73 VUserLog(
"Error: CFStreamError (%ld:%d)", error->domain, error->error);
77 CFStringRef nameCF = CFNetServiceGetName(service);
81 CFDataRef txt = CFNetServiceGetTXTData(service);
82 CFDictionaryRef txtDict = CFNetServiceCreateDictionaryWithTXTData(NULL, txt);
83 CFDataRef typeData = (CFDataRef)CFDictionaryGetValue(txtDict, CFSTR(
"type"));
96 SInt32 port = CFNetServiceGetPortNumber(service);
98 CFArrayRef addresses = CFNetServiceGetAddressing(service);
99 CFIndex addressCount = CFArrayGetCount(addresses);
101 for (CFIndex i = 0; i < addressCount; ++i)
103 struct sockaddr *socketAddress = (
struct sockaddr *)CFDataGetBytePtr((CFDataRef)CFArrayGetValueAtIndex(addresses, i));
106 if (!socketAddress || socketAddress->sa_family != AF_INET)
110 if (!inet_ntop(AF_INET, &((
struct sockaddr_in *)socketAddress)->sin_addr, ip,
sizeof(ip)))
112 VUserLog(
"Error: Couldn't get IP address for '%s': %s", name, strerror(errno));
126 for (
int i = 1; i <= deviceCount; ++i)
141 for (
int i = 1; i <= deviceCount; ++i)
159 void VuoOsc_deviceCallback(CFNetServiceBrowserRef browser, CFOptionFlags flags, CFTypeRef domainOrService, CFStreamError *error,
void *info)
161 if (error->domain || error->error)
163 if (error->domain == kCFStreamErrorDomainCustom || error->error == 0)
167 else if (error->domain == kCFStreamErrorDomainMacOSStatus)
174 VUserLog(
"Error: %ld:%d", error->domain, error->error);
179 if (flags & kCFNetServiceFlagIsDomain)
182 bool deviceAdded = !(flags & kCFNetServiceFlagRemove);
184 CFNetServiceRef service = (CFNetServiceRef)domainOrService;
190 CFNetServiceClientContext context;
193 context.retain = NULL;
194 context.release = NULL;
195 context.copyDescription = NULL;
197 VUserLog(
"Error: Failed to set the client callback.");
199 CFNetServiceScheduleWithRunLoop(service, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
202 if (!CFNetServiceResolveWithTimeout(service, 0, &error))
203 VUserLog(
"Error: Failed to schedule service resolution (%ld:%d).",error.domain,error.error);
207 CFStringRef nameCF = CFNetServiceGetName(service);
213 bool removedAnyInputs =
false;
220 removedAnyInputs =
true;
223 if (removedAnyInputs)
228 bool removedAnyOutputs =
false;
235 removedAnyOutputs =
true;
238 if (removedAnyOutputs)
244 CFNetServiceUnscheduleFromRunLoop(service, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
246 CFNetServiceClientContext context;
249 context.retain = NULL;
250 context.release = NULL;
251 context.copyDescription = NULL;
252 if (!CFNetServiceSetClient(service, NULL, &context))
253 VUserLog(
"Error: Failed to clear the client callback.");
255 CFNetServiceCancel(service);
280 CFNetServiceClientContext context;
283 context.retain = NULL;
284 context.release = NULL;
285 context.copyDescription = NULL;
290 VUserLog(
"Error: Failed to create browser.");
294 CFNetServiceBrowserScheduleWithRunLoop(
VuoOsc_browser, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
297 if (!CFNetServiceBrowserSearchForServices(
VuoOsc_browser, CFSTR(
""), CFSTR(
"_osc._udp"), &error))
298 VUserLog(
"Error: Failed to activate browser (%ld:%d).", error.domain, error.error);
313 VUserLog(
"Error: Unbalanced VuoOsc_use() / _disuse() calls.");
320 error.domain = kCFStreamErrorDomainCustom;
324 CFNetServiceBrowserUnscheduleFromRunLoop(
VuoOsc_browser, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
382 #define setRealizedDevice(newDevice) \
383 realizedDevice->name = VuoText_make(newDevice.name); \
384 realizedDevice->ipAddress = VuoText_make(newDevice.ipAddress); \
385 realizedDevice->port = newDevice.port;
414 __block
bool found =
false;
419 if (device.port == item.port)
421 VDebugLog(
"Matched by port: %s",json_object_to_json_string(VuoOscInputDevice_getJson(item)));
422 setRealizedDevice(item);
434 VDebugLog(
"Matched by name: %s",json_object_to_json_string(VuoOscInputDevice_getJson(item)));
435 setRealizedDevice(item);
475 __block
bool found =
false;
480 if (device.port == item.port)
482 VDebugLog(
"Matched by port: %s",json_object_to_json_string(VuoOscOutputDevice_getJson(item)));
483 setRealizedDevice(item);
495 VDebugLog(
"Matched by name: %s",json_object_to_json_string(VuoOscOutputDevice_getJson(item)));
496 setRealizedDevice(item);