forked from Figure53/F53OSC
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathMetatoneNetworkManager.m
576 lines (496 loc) · 26 KB
/
MetatoneNetworkManager.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
//
// MetatoneNetworkManager.m
// Metatone
//
// Created by Charles Martin on 10/04/13.
// Copyright (c) 2013 Charles Martin. All rights reserved.
// Modified January 2014 to work with F53OSC
//
#import "MetatoneNetworkManager.h"
#define USE_WEBSOCKET_CLASSIFIER @YES
#define DEFAULT_PORT 51200
#define DEFAULT_ADDRESS @"10.0.1.199"
#define METATONE_CLASSIFIER_HOSTNAME @"metatonetransfer.com"
#define METATONE_CLASSIFIER_PORT 8888
#define METACLASSIFIER_SERVICE_TYPE @"_metatoneclassifier._tcp."
#define METATONE_SERVICE_TYPE @"_metatoneapp._udp."
#define OSCLOGGER_SERVICE_TYPE @"_osclogger._udp."
#define SERVER_DISCONNECTED 0
#define SERVER_CONNECTING 1
#define SERVER_CONNECTED 2
@implementation MetatoneNetworkManager
// Designated Initialisers
// This initialiser just sets web classification to NO to preserve compatibility.
-(MetatoneNetworkManager *) initWithDelegate:(id<MetatoneNetworkManagerDelegate>)delegate shouldOscLog:(bool)osclogging {
return [self initWithDelegate:delegate shouldOscLog:osclogging shouldConnectToWebClassifier:NO];
}
// This initialiser sets web classification by argument.
-(MetatoneNetworkManager *) initWithDelegate: (id<MetatoneNetworkManagerDelegate>) delegate shouldOscLog: (bool) osclogging shouldConnectToWebClassifier: (bool) connectToWeb {
self = [super init];
self.delegate = delegate;
// if ios: [UIDevice currentDevice].name if mac: [[NSHost currentHost] localizedName]
#if TARGET_OS_IPHONE
self.deviceID = [UIDevice currentDevice].name;
#else
self.deviceID = [[NSHost currentHost] localizedName];
#endif
self.appID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
self.oscLogging = osclogging;
self.connectToWebClassifier = connectToWeb;
self.loggingIPAddress = DEFAULT_ADDRESS;
self.loggingPort = DEFAULT_PORT;
self.localIPAddress = [MetatoneNetworkManager getIPAddress];
self.connectedToServer = SERVER_DISCONNECTED;
self.connectedToLocalPerformanceServer = NO;
// Setup OSC Client
self.oscClient = [[F53OSCClient alloc] init];
[self.oscClient setHost:self.loggingIPAddress];
[self.oscClient setPort:self.loggingPort];
[self.oscClient connect];
// Setup OSC Server
self.oscServer = [[F53OSCServer alloc] init];
[self.oscServer setDelegate:self];
[self.oscServer setPort:DEFAULT_PORT];
[self.oscServer startListening];
// Connect WebSocketClassifier
// if (USE_WEBSOCKET_CLASSIFIER) [self connectWebClassifierWebSocket];
if (connectToWeb) [self connectWebClassifierWebSocket];
// register with Bonjour
// if ios: [UIDevice currentDevice].name if mac: [[NSHost currentHost] localizedName]
#if TARGET_OS_IPHONE
self.metatoneNetService = [[NSNetService alloc]
initWithDomain:@""
type:METATONE_SERVICE_TYPE
name:[UIDevice currentDevice].name
port:DEFAULT_PORT];
#else
self.metatoneNetService = [[NSNetService alloc]
initWithDomain:@""
type:METATONE_SERVICE_TYPE
name:[[NSHost currentHost] localizedName]
port:DEFAULT_PORT];
#endif
if (self.metatoneNetService != nil) {
[self.metatoneNetService setDelegate: self];
[self.metatoneNetService publishWithOptions:0];
// if ios: [UIDevice currentDevice].name if mac: [[NSHost currentHost] localizedName]
// NSLog(@"NETWORK MANAGER: Metatone NetService Published - name: %@", [[NSHost currentHost] localizedName]);
}
if (self.oscLogging) {
// try to find an OSC Logger to connect to (but only if "oscLogging" is set).
NSLog(@"NETWORK MANAGER: Browsing for OSC Logger Services...");
self.oscLoggerServiceBrowser = [[NSNetServiceBrowser alloc] init];
[self.oscLoggerServiceBrowser setDelegate:self];
[self.oscLoggerServiceBrowser searchForServicesOfType:OSCLOGGER_SERVICE_TYPE
inDomain:@"local."];
}
// try to find Metatone Apps to connect to (always do this)
NSLog(@"NETWORK MANAGER: Browsing for Metatone App Services...");
self.metatoneServiceBrowser = [[NSNetServiceBrowser alloc] init];
[self.metatoneServiceBrowser setDelegate:self];
[self.metatoneServiceBrowser searchForServicesOfType:METATONE_SERVICE_TYPE
inDomain:@"local."];
// try to find Metatone Web Classifier services locally
NSLog(@"NETWORK MANAGER: Browsing for Metatone Web Classifier Services...");
self.metatoneWebClassifierBrowser = [[NSNetServiceBrowser alloc] init];
[self.metatoneWebClassifierBrowser setDelegate:self];
[self.metatoneWebClassifierBrowser searchForServicesOfType:METACLASSIFIER_SERVICE_TYPE
inDomain:@"local."];
return self;
}
#pragma mark WebSocket Life Cycle
//-(void)connectClassifierWebSocket {
// [self.classifierWebSocket close];
// self.classifierWebSocket.delegate = nil;
// NSString* classifierUrl = [NSString stringWithFormat:@"ws://%@:%d/classifier",METATONE_CLASSIFIER_HOSTNAME,METATONE_CLASSIFIER_PORT];
// self.classifierWebSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:classifierUrl]]];
// [self.classifierWebSocket setDelegate:self];
// NSLog(@"NETWORK MANAGER: Opening Classifier WebSocket.");
// [self.classifierWebSocket open];
//
//}
#pragma mark - Main Web Classifier Connection Methods.
#pragma TODO these two connection methods are problematic - what if they are called when already connected?
- (void) startConnectingToWebClassifier {
self.connectToWebClassifier = YES;
if (self.connectedToServer == SERVER_DISCONNECTED)
{
NSLog(@"NETWORK MANAGER: startConnectingToWebClassifier was called.");
NSLog(@"NETWORK MANAGER: WebSocket.readyState is %ld",(long)self.classifierWebSocket.readyState);
if (self.classifierWebSocket.readyState == SR_CLOSED || self.classifierWebSocket.readyState == SR_CONNECTING)
{
NSLog(@"NETWORK MANAGER: Classifier is closed, now starting to connect to WebClassifier");
[self connectWebClassifierWebSocket];
}
}
}
- (void) stopConnectingToWebClassifier {
NSLog(@"NETWORK MANAGER: stopConnectingToWebClassifier was called.");
self.connectToWebClassifier = NO;
if (!self.connectedToLocalPerformanceServer) [self closeClassifierWebSocket];
}
- (bool) isClassifierConnected {
// Check if web classifier is connected
return (self.connectedToServer == SERVER_CONNECTED);
}
# pragma mark - internal Web Classifier Connection Methods.
-(void)connectWebClassifierWebSocket {
[self connectClassifierWebSocketWithHostname:METATONE_CLASSIFIER_HOSTNAME andPort:METATONE_CLASSIFIER_PORT];
}
-(void)reconnectWebClassifierWebSocket {
[self connectClassifierWebSocketWithHostname:self.webClassifierHostname andPort:self.webClassifierPort];
}
-(void)connectClassifierWebSocketWithHostname:(NSString *)hostname andPort:(int)port {
[self.classifierWebSocket close];
self.classifierWebSocket.delegate = nil;
NSString* classifierUrl = [NSString stringWithFormat:@"ws://%@:%d/classifier",hostname,port];
self.classifierWebSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:classifierUrl]]];
[self.classifierWebSocket setDelegate:self];
NSLog(@"NETWORK MANAGER: Opening Classifier WebSocket: %@:%d",hostname,port);
self.connectedToServer = SERVER_CONNECTING;
[self.classifierWebSocket open];
self.webClassifierHostname = hostname; // set local variable to keep hostname
self.webClassifierPort = port; // set local variable to keep port
}
-(void)closeClassifierWebSocket {
NSLog(@"NETWORK MANAGER: closeClassifierWebSocket was called.");
[self sendMessageOffline];
[self.classifierWebSocket close];
self.connectedToServer = SERVER_DISCONNECTED;
#pragma mark TODO There really should be a "web classifier closed" callback to the delegate.
[self.delegate stoppedSearchingForLoggingServer]; // TODO: change to a more appropriately named method
}
-(void)webSocketDidOpen:(SRWebSocket *)webSocket {
NSLog(@"NETWORK MANAGER: Classifier WebSocket Opened: %@", [webSocket description]);
self.connectedToServer = SERVER_CONNECTED;
[self sendMessageOnline];
[self.delegate loggingServerFoundWithAddress:self.webClassifierHostname andPort:self.webClassifierPort andHostname:self.webClassifierHostname];
}
-(void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean {
NSLog(@"NETWORK MANAGER: Classifier WebSocket Closed: %@, Clean: %d", reason,wasClean);
self.classifierWebSocket = nil;
self.connectedToServer = SERVER_DISCONNECTED;
[self.delegate stoppedSearchingForLoggingServer]; // TODO: change to a more appropriately named method
}
-(void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error {
NSLog(@"NETWORK MANAGER: Classifier WebSocket Failed: %@", [error description]);
self.classifierWebSocket = nil;
self.connectedToServer = SERVER_DISCONNECTED;
[self.delegate stoppedSearchingForLoggingServer]; // TODO: change to a more appropriately named method
}
-(void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
if ([message isKindOfClass:[NSData class]]) {
NSData *messageData = [NSData dataWithBytes:[(NSData *)message bytes] length:[(NSData *)message length]];
[F53OSCParser processOscData:messageData forDestination:self replyToSocket:nil]; // This should activate the "takeMessage" method
}
}
# pragma mark TODO fix up logic about local and remote websockets.
-(void)sendToWebClassifier:(F53OSCMessage *)message {
if (self.classifierWebSocket.readyState == SR_OPEN) {
[self.classifierWebSocket send:[message packetData]];
} else if (self.connectToWebClassifier) {
NSLog(@"NETWORK MANAGER: Can't send to WebSocket - Closed.");
if(USE_WEBSOCKET_CLASSIFIER) [self reconnectWebClassifierWebSocket];
}
}
# pragma mark Searching Lifecycle
-(void) stopSearches
{
[self.metatoneServiceBrowser stop];
[self.oscLoggerServiceBrowser stop];
[self.remoteMetatoneIPAddresses removeAllObjects];
[self.remoteMetatoneNetServices removeAllObjects];
[self.oscClient disconnect];
}
#pragma mark Instantiation
-(NSMutableArray *) remoteMetatoneNetServices {
if (!_remoteMetatoneNetServices) _remoteMetatoneNetServices = [[NSMutableArray alloc] init];
return _remoteMetatoneNetServices;
}
-(NSMutableArray *) remoteMetatoneIPAddresses {
if (!_remoteMetatoneIPAddresses) _remoteMetatoneIPAddresses = [[NSMutableArray alloc] init];
return _remoteMetatoneIPAddresses;
}
# pragma mark NetServiceBrowserDelegate Methods
-(void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didNotSearch:(NSDictionary *)errorDict {
NSLog(@"NETWORK MANAGER: ERROR: Did not search for OSC Logger");
}
-(void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing {
if ([[aNetService type] isEqualToString:METATONE_SERVICE_TYPE]) {
if ([aNetService isEqual:self.metatoneNetService]) {
NSLog(@"NETWORK MANAGER: Found own metatone service - ignoring.");
return;
}
[aNetService setDelegate:self];
[aNetService resolveWithTimeout:5.0];
[self.remoteMetatoneNetServices addObject:aNetService];
}
if ([[aNetService type] isEqualToString:OSCLOGGER_SERVICE_TYPE]) {
self.oscLoggerService = aNetService;
[self.oscLoggerService setDelegate:self];
[self.oscLoggerService resolveWithTimeout:5.0];
//TODO: sort out case of multiple OSC Loggers.
}
if ([[aNetService type] isEqualToString:METACLASSIFIER_SERVICE_TYPE]) {
self.metatoneWebClassifierNetService = aNetService;
[self.metatoneWebClassifierNetService setDelegate:self];
[self.metatoneWebClassifierNetService resolveWithTimeout:5.0];
}
}
-(void)netServiceDidResolveAddress:(NSNetService *)sender {
NSString* firstAddress;
int firstPort;
for (NSData* data in [sender addresses]) {
char addressBuffer[100];
struct sockaddr_in* socketAddress = (struct sockaddr_in*) [data bytes];
int sockFamily = socketAddress->sin_family;
if (sockFamily == AF_INET || sockFamily == AF_INET6) {
const char* addressStr = inet_ntop(sockFamily,
&(socketAddress->sin_addr), addressBuffer,
sizeof(addressBuffer));
int port = ntohs(socketAddress->sin_port);
if (addressStr && port) {
NSLog(@"NETWORK MANAGER: Resolved service of type %@ at %s:%d - %@",
[sender type],
addressStr,
port,
sender.hostName);
firstAddress = [NSString stringWithFormat:@"%s",addressStr];
firstPort = port;
break;
}
}
}
if ([sender.type isEqualToString:OSCLOGGER_SERVICE_TYPE] && firstAddress && firstPort) {
self.loggingHostname = sender.hostName;
self.loggingIPAddress = firstAddress;
self.loggingPort = firstPort;
[self.delegate loggingServerFoundWithAddress:self.loggingIPAddress
andPort:(int)self.loggingPort
andHostname:self.loggingHostname];
[self sendMessageOnline];
NSLog(@"NETWORK MANAGER: Resolved and Connected to an OSC Logger Service.");
}
if ([sender.type isEqualToString:METATONE_SERVICE_TYPE] && firstAddress && firstPort) {
// Save the found address.
// Need to also check if address is already in the array.
if (![firstAddress isEqualToString:self.localIPAddress] && ![firstAddress isEqualToString:@"127.0.0.1"]) {
[self.remoteMetatoneIPAddresses addObject:@[firstAddress,[NSNumber numberWithInt:firstPort]]];
[self.delegate metatoneClientFoundWithAddress:firstAddress andPort:firstPort andHostname:sender.hostName];
NSLog(@"NETWORK MANAGER: Resolved and Connected to a MetatoneApp Service.");
}
}
if ([sender.type isEqualToString:METACLASSIFIER_SERVICE_TYPE] && firstAddress && firstPort) {
// Connect to the webclassifier.
[self connectClassifierWebSocketWithHostname:sender.hostName andPort:firstPort];
self.connectedToLocalPerformanceServer = YES;
}
}
#pragma TODO make sure the search and stop search delegate messages are working depending on server state.
-(void)netServiceBrowserWillSearch:(NSNetServiceBrowser *)aNetServiceBrowser {
// only run this is not currently connected to anything.
NSLog(@"NETWORK MANAGER: Connection Status: %d", self.connectedToServer);
if (self.connectedToServer == SERVER_DISCONNECTED) [self.delegate searchingForLoggingServer];
}
-(void)netServiceBrowserDidStopSearch:(NSNetServiceBrowser *)aNetServiceBrowser {
NSLog(@"NETWORK MANAGER: NetServiceBrowser stopped searching.");
if (self.connectedToServer == SERVER_DISCONNECTED) [self.delegate stoppedSearchingForLoggingServer];
}
# pragma mark OSC Sending Methods
-(void)sendMessageWithAccelerationX:(double)x Y:(double)y Z:(double)z
{
NSArray *contents = @[self.deviceID,
[NSNumber numberWithFloat:x],
[NSNumber numberWithFloat:y],
[NSNumber numberWithFloat:z]];
F53OSCMessage *message = [F53OSCMessage messageWithAddressPattern:@"/metatone/acceleration"
arguments:contents];
[self.oscClient sendPacket:message toHost:self.loggingIPAddress onPort:self.loggingPort];
[self sendToWebClassifier:message]; // hope this works!
}
-(void)sendMessageWithTouch:(CGPoint)point Velocity:(CGFloat)vel
{
NSArray *contents = @[self.deviceID,
[NSNumber numberWithFloat:point.x],
[NSNumber numberWithFloat:point.y],
[NSNumber numberWithFloat:vel]];
F53OSCMessage *message = [F53OSCMessage messageWithAddressPattern:@"/metatone/touch"
arguments:contents];
[self.oscClient sendPacket:message toHost:self.loggingIPAddress onPort:self.loggingPort];
[self sendToWebClassifier:message];
}
-(void)sendMesssageSwitch:(NSString *)name On:(BOOL)on
{
NSString *switchState = on ? @"T" : @"F";
NSArray *contents = @[self.deviceID,
name,
switchState];
F53OSCMessage *message = [F53OSCMessage messageWithAddressPattern:@"/metatone/switch" arguments:contents];
[self.oscClient sendPacket:message toHost:self.loggingIPAddress onPort:self.loggingPort];
[self sendToWebClassifier:message];
}
-(void)sendMessageTouchEnded
{
NSArray *contents = @[self.deviceID];
F53OSCMessage *message = [F53OSCMessage messageWithAddressPattern:@"/metatone/touch/ended" arguments:contents];
[self.oscClient sendPacket:message toHost:self.loggingIPAddress onPort:self.loggingPort];
[self sendToWebClassifier:message];
}
-(void)sendMessageOnline
{
NSLog(@"Constructing Online Message.");
NSArray *contents = @[self.deviceID,self.appID];
F53OSCMessage *message = [F53OSCMessage messageWithAddressPattern:@"/metatone/online" arguments:contents];
[self.oscClient sendPacket:message toHost:self.loggingIPAddress onPort:self.loggingPort];
[self sendToWebClassifier:message];
}
-(void)sendMessageRemoteControl
{
NSLog(@"Sending Remote Control Message.");
NSArray *contents = @[self.deviceID, [self localIPAddress]];
F53OSCMessage *message = [F53OSCMessage messageWithAddressPattern:@"/metatone/remote" arguments:contents];
[self.oscClient sendPacket:message toHost:self.loggingIPAddress onPort:self.loggingPort];
[self sendToWebClassifier:message];
}
-(void)sendMessageOffline
{
NSArray *contents = @[self.deviceID,self.appID];
F53OSCMessage *message = [F53OSCMessage messageWithAddressPattern:@"/metatone/offline"
arguments:contents];
[self.oscClient sendPacket:message toHost:self.loggingIPAddress onPort:self.loggingPort];
[self sendToWebClassifier:message]; // hope this works!
}
-(void)sendMetatoneMessage:(NSString *)name withState:(NSString *)state {
NSArray *contents = @[self.deviceID,
name,
state];
F53OSCMessage *message = [F53OSCMessage messageWithAddressPattern:@"/metatone/app"
arguments:contents];
// Log the metatone messages as well.
[self.oscClient sendPacket:message toHost:self.loggingIPAddress onPort:self.loggingPort];
[self sendToWebClassifier:message]; // hope this works!
// Send to each metatone app on the network.
for (NSArray *address in self.remoteMetatoneIPAddresses) {
[self.oscClient sendPacket:message
toHost:(NSString *)address[0]
onPort:[((NSNumber *)address[1]) integerValue]];
}
}
- (void)sendMetatoneMessageViaServer:(NSString *)name withState:(NSString *)state {
NSArray *contents = @[self.deviceID,
name,
state];
F53OSCMessage *message = [F53OSCMessage messageWithAddressPattern:@"/metatone/app"
arguments:contents];
[self.oscClient sendPacket:message toHost:self.loggingIPAddress onPort:self.loggingPort];
[self sendToWebClassifier:message];
}
#pragma mark OSC Receiving Methods
/// Main method for receiving and parsing OSC Messages.
-(void)takeMessage:(F53OSCMessage *)message {
if ([message.addressPattern isEqualToString:@"/metatone/app"]) {
// InterAppmessage
if ([message.arguments count] == 3) {
if ([message.arguments[0] isKindOfClass:[NSString class]] &&
[message.arguments[1] isKindOfClass:[NSString class]] &&
[message.arguments[2] isKindOfClass:[NSString class]])
{
if (![((NSString *) message.arguments[0]) isEqualToString:self.deviceID]) { // ignore self metatone messages.
[self.delegate didReceiveMetatoneMessageFrom:message.arguments[0] withName:message.arguments[1] andState:message.arguments[2]];}
}
}
} else if ([message.addressPattern isEqualToString:@"/metatone/classifier/gesture"]) {
// Gesture Message
if ([message.arguments count] == 2) [self.delegate didReceiveGestureMessageFor:message.arguments[0] withClass:message.arguments[1]];
} else if ([message.addressPattern isEqualToString:@"/metatone/classifier/ensemble/state"]) {
//Ensemble State
if ([message.arguments count] == 3) [self.delegate didReceiveEnsembleState:message.arguments[0] withSpread:message.arguments[1] withRatio:message.arguments[2]];
} else if ([message.addressPattern isEqualToString:@"/metatone/classifier/ensemble/event/new_idea"]) {
if ([message.arguments count] == 2) [self.delegate didReceiveEnsembleEvent:@"new_idea" forDevice:message.arguments[0] withMeasure:message.arguments[1]];
} else if ([message.addressPattern isEqualToString:@"/metatone/classifier/ensemble/event/solo"]) {
[self.delegate didReceiveEnsembleEvent:@"solo" forDevice:message.arguments[0] withMeasure:message.arguments[1]];
} else if ([message.addressPattern isEqualToString:@"/metatone/classifier/ensemble/event/parts"]) {
[self.delegate didReceiveEnsembleEvent:@"parts" forDevice:message.arguments[0] withMeasure:message.arguments[1]];
} else if ([message.addressPattern isEqualToString:@"/metatone/performance/start"]) {
// performance start
if ([message.arguments count] == 4) [self.delegate didReceivePerformanceStartEvent:message.arguments[0]
forDevice:message.arguments[1]
withType:message.arguments[2]
andComposition:message.arguments[3]];
} else if ([message.addressPattern isEqualToString:@"/metatone/performance/end"]) {
// performance stop
if ([message.arguments count] ==2) [self.delegate didReceivePerformanceEndEvent:message.arguments[0]
forDevice:message.arguments[1]];
} else if ([message.addressPattern isEqualToString:@"/metatone/classifier/hello"]) {
NSLog(@"NETWORK MANAGER: Connection Handshake from Server Received.");
} else if ([message.addressPattern isEqualToString:@"/metatone/playback/touch"]) {
// A returned touch message from the classifier -- play it!
//NSLog(@"Play back a touch of some kind");
if ([message.arguments count] == 4) [self.delegate didReceiveTouchPlayMessageFor:message.arguments[0] X:message.arguments[1] Y:message.arguments[2] vel:message.arguments[3]];
//[NSNumber numberWithFloat:point.x],
//[NSNumber numberWithFloat:point.y],
//[NSNumber numberWithFloat:vel]];
// Message should have three arguments.
} else if ([message.addressPattern isEqualToString:@"/metatone/playback/gesture"]) {
// Gesture Message to be played back!
if ([message.arguments count] == 2) [self.delegate didReceiveGesturePlayMessageFor:message.arguments[0] withClass:message.arguments[1]];
} else {
// Received unknown message:
NSLog(@"NETWORK MANAGER: Received unknown message: %@", [message description]);
}
}
// performance start events should be of the form:
// /metatone/performance/start (string) deviceID (int) type (composition) int
// the type should be
//#define PERFORMANCE_TYPE_LOCAL 0
//#define PERFORMANCE_TYPE_REMOTE 1
//#define EXPERIMENT_TYPE_BOTH 2
//#define EXPERIMENT_TYPE_NONE 3
//#define EXPERIMENT_TYPE_BUTTON 4
//#define EXPERIMENT_TYPE_SERVER 5
//
// the composition is an int that corresponds to one of the available compositions,
// for the experiment, the int can be random (as long as everybody has the same one).
#pragma mark IP Address Methods
/// Get IP Address
+ (NSString *)getIPAddress {
NSString *address = @"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}
/// Attempt to find local broadcast address.
+ (NSString *)getLocalBroadcastAddress {
NSArray *addressComponents = [[MetatoneNetworkManager getIPAddress] componentsSeparatedByString:@"."];
NSString *address = nil;
if ([addressComponents count] == 4)
{
address = @"";
for (int i = 0; i<([addressComponents count] - 1); i++) {
address = [address stringByAppendingString:addressComponents[i]];
address = [address stringByAppendingString:@"."];
}
address = [address stringByAppendingString:@"255"];
}
return address;
}
@end