532OSC to and from the iPhone with VVOSC

Update (October 2011) Opening and compiling the (original 3.1) OSCDemo project in Xcode 4.1 asks to ‘modernize’ it. Go ahead, modernize it. For sending from the iOS device, also make sure to set the sendiungToIP address, at line 40 of OSCDemoViewController.m. For testing, also don’t forget to set the IP address in OSC Senderin the Quartz Composer patch. Here’s the updated, Xcode 4.1 version of OSCDemo. Update (April 2011) Some users reported a problem where the transmission/reception speeds on newer hardware (iPhone 4, iPad) became unstable and “flaky”. It seems that Bluetooth is causing some interference with OSC. Solution: Make sure Bluetooth is off when you’re using this code. Thanks to Hans Tutschku for finding this solution.
Sending data to and from the iPhone via OSC to applications on other machines should not be that difficult. Unfortunatly it’s not as simple as it should be, but fortunalty Mr Ray (of VIDVOX fame) is so kind to share his code and his implementation of OSC for Objective-C. There are some ancient libraries around, but let’s better keep them buried where they are. First a bit of an excursion on how to deal with external code on the iPhone. Frameworks, Static Libraries or Inclusion? Frameworks are the preferred method of distributing shared code on OSX. The idea behind being, that only one copy of the code can be shared amongst any number of applications. But at the iPhone true multi-tasking is not possible, so shared frameworks are not possible. Heck, they are even forbidden by Apple. But of course their own UIKit Frameworks are fine. You could convert code for reuse to a Static Library, but with iPhone Dev you might deal with the simulator and the device, so you would need to either pre-compile the library for all plattforms or create a specific project, that compile the static library on demand. More on that at 519. Frameworks are also nice, in that you only have to import them to your project and then they just work. Static Libraries need some special care, with header search paths, compiler flags, and of course putting them in a special place in ~/Library. That’s fine if you develop on your own, but if you work with other people and share the code via a source code repository (like SVN), it might be difficult (or annoying) to maintain the same machine state across all the development machines. So I resorted to including the classes directly into my project. That way they get compiled every time and I can poke around the code directly. If you really want a central source of your external classes, just don’t add them to your project by copy but just by reference… Sending OSC From the iPhone Sending OSC data from the iPhone was always quite straightforward:
- (id) init	{
	NSLog(@"OSC init");
	
	manager = [[OSCManager alloc] init];
	[manager setDelegate:self];

	// sending
	NSString *sendingToIP = @"192.168.20.117";
	int sendingToPort = 50000;
	outPort = [manager createNewOutputToAddress:sendingToIP atPort:sendingToPort];

	// receiving
	int receivingOnPort = 51234;
	//inPort = [manager createNewInput]; // default at port 1234
	inPort = [manager createNewInputForPort:receivingOnPort];
	
	return self;
}
Receiving OSC At the iPhone The receiving part seems to catch many people out. Basically it’s nothing more than set the right delegate, as specified in VVOSC:
// called by delegate on message
- (void) receivedOSCMessage:(OSCMessage *)m	{
	NSString *address = [m address];
	OSCValue *value = [m value];
	NSString *message;
		
	if ([address isEqualToString:@"/mouseX"]) {
		message = [NSString stringWithFormat:@"mouseX: %i", [value intValue]];
		NSString *txt = [NSString stringWithFormat:@"%i", [value intValue]];
		[receiveLabel performSelectorOnMainThread:@selector(setText:) withObject:txt waitUntilDone:NO];
	} else if ([address isEqualToString:@"/mouseY"]) {
		message = [NSString stringWithFormat:@"mouseY: %i", [value intValue]];
	} else if ([address isEqualToString:@"/floatArray"]) {
		message = [NSString stringWithFormat:@"floatArray: %f", [value floatValue]];
	}
}

Change Notes As VVOSC is targeted at both Cocoa and Cocoa Touch, there is a compiler directive that takes care of the switching. Or at least it should take care. I was unable to get the original code to run on the iPhone, because the compiler directive IPHONE was not recognized. I am sure I am missing something there… To solve that, I change IPHONE (and !IPHONE) with TARGET_OS_IPHONE (and !TARGET_OS_IPHONE), and that did the trick.. And as this is going to be used for the iPhone only, I allowed myself the luxury of removing any code, that was not meant for execution on the iPhone OS. Here’s the original OSC demo Xcode 3.1-compatible project, hope it helps. Here’s the newer, Xcode 3.2-compatible version (working with Xcode 4.1 on OSX 10.7). Drop me a line, if you have questions, suggestions or improvements.

519A bit about Frameworks and Static Libraries on the iPhone

Frameworks are a way to share code and other resources between application. As sharing code between applications is not really possible on the iPhone (as is dynamic loading of libraries) it does not really make much sense to use Frameworks on the iPhone – except maybe for the nice handling of reusable code. Where with Frameworks the specific files are accessable after the Framework is added to a project, working with Static Libraries is a bit more of an hussle. You not only need to add the library, but also need to make sure to set the right Header Search Paths, which can become troublesome when working with SVN’ed projects. And because the architecture differs on the iPhone (ARM) and the Simulator (i386), having precompiled libraries is not the best solution. But adding a depended library project to your projects kind of negates the advantages of having reusable code by adding unnecessary complications. Recommendation? Just add the desired files to your project. And if you really mind, don’t copy, but only include by reference.