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)
158 CFNetServiceUnscheduleFromRunLoop(service, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
160 CFNetServiceClientContext context;
163 context.retain = NULL;
164 context.release = NULL;
165 context.copyDescription = NULL;
166 if (!CFNetServiceSetClient(service, NULL, &context))
167 VUserLog(
"Error: Failed to clear the client callback.");
169 CFNetServiceCancel(service);
175 void VuoOsc_deviceCallback(CFNetServiceBrowserRef browser, CFOptionFlags flags, CFTypeRef domainOrService, CFStreamError *error,
void *info)
177 if (error->domain || error->error)
179 if (error->domain == kCFStreamErrorDomainCustom || error->error == 0)
183 else if (error->domain == kCFStreamErrorDomainMacOSStatus)
190 VUserLog(
"Error: %ld:%d", error->domain, error->error);
195 if (flags & kCFNetServiceFlagIsDomain)
198 bool deviceAdded = !(flags & kCFNetServiceFlagRemove);
200 CFNetServiceRef service = (CFNetServiceRef)domainOrService;
206 CFNetServiceClientContext context;
209 context.retain = NULL;
210 context.release = NULL;
211 context.copyDescription = NULL;
213 VUserLog(
"Error: Failed to set the client callback.");
215 CFNetServiceScheduleWithRunLoop(service, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
218 if (!CFNetServiceResolveWithTimeout(service, 0, &error))
219 VUserLog(
"Error: Failed to schedule service resolution (%ld:%d).",error.domain,error.error);
223 CFStringRef nameCF = CFNetServiceGetName(service);
229 bool removedAnyInputs =
false;
236 removedAnyInputs =
true;
239 if (removedAnyInputs)
244 bool removedAnyOutputs =
false;
251 removedAnyOutputs =
true;
254 if (removedAnyOutputs)
283 CFNetServiceClientContext context;
286 context.retain = NULL;
287 context.release = NULL;
288 context.copyDescription = NULL;
293 VUserLog(
"Error: Failed to create browser.");
297 CFNetServiceBrowserScheduleWithRunLoop(
VuoOsc_browser, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
300 if (!CFNetServiceBrowserSearchForServices(
VuoOsc_browser, CFSTR(
""), CFSTR(
"_osc._udp"), &error))
301 VUserLog(
"Error: Failed to activate browser (%ld:%d).", error.domain, error.error);
316 VUserLog(
"Error: Unbalanced VuoOsc_use() / _disuse() calls.");
323 error.domain = kCFStreamErrorDomainCustom;
327 CFNetServiceBrowserUnscheduleFromRunLoop(
VuoOsc_browser, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
385 #define setRealizedDevice(newDevice) \
386 realizedDevice->name = VuoText_make(newDevice.name); \
387 realizedDevice->ipAddress = VuoText_make(newDevice.ipAddress); \
388 realizedDevice->port = newDevice.port;
417 __block
bool found =
false;
422 if (device.port == item.port)
424 VDebugLog(
"Matched by port: %s",json_object_to_json_string(VuoOscInputDevice_getJson(item)));
425 setRealizedDevice(item);
437 VDebugLog(
"Matched by name: %s",json_object_to_json_string(VuoOscInputDevice_getJson(item)));
438 setRealizedDevice(item);
478 __block
bool found =
false;
483 if (device.port == item.port)
485 VDebugLog(
"Matched by port: %s",json_object_to_json_string(VuoOscOutputDevice_getJson(item)));
486 setRealizedDevice(item);
498 VDebugLog(
"Matched by name: %s",json_object_to_json_string(VuoOscOutputDevice_getJson(item)));
499 setRealizedDevice(item);