Wednesday, February 24, 2010

Compiling CyberLink UPNP into iPhone SDK

Recently I was asked about a post to a forum I made back in 2008 when I first started hacking around with UPNP applications on the iPhone. At the time I was working on an application to control my Sonos devices using my iPhone as remote. Although I was successful, shortly after I got my first stable prototype running the "official" version was released and was plenty good enough for what I wanted so I abandoned the project. I did not however abandon UPNP on the iPhone as it remains a large missing link in the iPhone SDK.

UPNP is used by many connected home devices to notify other like minded devices of their presence, capability and services. Responding to UDP broadcasts a device and service description is made available in XML  for digestion by client programs. Most media servers and streamers speak UPNP along with some wireless photo frames.

UPNP is missing along with all the other XML based web services provision in iPhone SDK for... er reasons best known to Apple I guess but there exists a well used and stable open source UPNP library for C, C++ and Obj-C that compiles into the iPhone SDK with a bit of hacking.

CyberLink UPNP is an open source C framework for UPNP written and maintained by Satoshi Konno. The C source files and Objective C wrappers are available from the sourceforge project which you can get to from the CyberGarage site. However all the example code and the framework project are linked against the MacOSX Cocoa framework not the iPhone Foundation framework. This means that in order to compile it for use on iPhone you need to repackage the whole thing into a Cocoa Touch static library.

It has been a while since I repackaged it for my needs so it would take me a deal of time to recreate a detailed step by step but the main tasks are:

  1. Locate and download all the source code from sourceforge.
  2. Create a new Cocoa Touch static library project.
  3. Copy all the source files into your new project.
  4. Get rid of all the #import cocoa cocoa.h lines and replace with #import foundation foundation.h (easiest to do this in the prefix headers)
  5. Change the use of imports to "CGUpnpDevice.h" for the classes used. Or create a UPnP.h combined header.
  6. Compile, track down and squash the errors, rinse repeat.
The most elegant way to then use the static library in your projects is to use a shared build folder and implement the modular shared library scheme discussed in Clint Harris' excellent tutorial. Good luck and happy hacking!

10 comments:

Greg said...

Hello,

I tried to compiling Cyberlink but I don't understand the steps:
- Copy all the source files into your new project. (I download clinkc-2.3 and I have somes directory lib and src,... Which source I need to copy ?)
- Get rid of all the #import lines and replace with #import (easiest to do this in the prefix headers) - I don't understand this point.

Perhaps you can share a sample code ?

Thanks

Rick said...

point 4 got mangled. I have emailed you with some sample code.

Tin CNTT said...

I met the same problem with Greg, Could you please share me a sample code?

Thanks

Anonymous said...

I met the same issue with Greg. Could you please share a sample code?

Thanks

alibaba said...

Hello Rick,

I'm creating an UPNP client for iPhone. I got sample SDk "Cyberlink" and followed your steps.

But I didn't understand your steps 3-4.

can you elaborate the steps.

Or can you provide me a sample how to use the SDK..?

Thanks.

Chris said...

Hello Rick,

Can you tell me, How to build static library from CyberLink sdk source code.?

- Which files to use from CyberLink source code to build static library.?

Thanks,
Chris.

Niraj Pendal said...

Can you share some sample code??

Rick said...

Sorry to leave this topic unanswered for so long. I have been a little preoccupied with my new daughter.

It seems that the contents of the release from cybergarage have changed since I compiled the static library. Most notable the Objective C wrapper classes are missing.

I will wrap up and share an Xcode project that should be able to be used to compile your own static library, possibly with some rejigging of the links to libXML.

Hopefully I can get this done in the next few days.

Rick said...

I have made a new post with a link to download my Xcode project. hope this helps. http://rick-hawkins.blogspot.com/2010/08/compiling-cyberlink-upnp-for-ios-redux.html

Anonymous said...

In My iPhone application I have to execute the code below for each time I want to Send a UPnP action to my device. Each connect takes 2 Seconds. Any one has managed to stay connected so you only have to discover a device (server) once and avoid running the code below over and over again for each time you want to send an action.

Thanks for any help


CGUpnpControlPoint *ctrlPoint= [[CGUpnpControlPoint alloc] init];
[ctrlPoint search];
NSArray *devArray = [ctrlPoint devices];
CGUpnpDevice *dev1;
int numberOfDevices = [devArray count];
NSLog(@" total number of devives %d", numberOfDevices);

int lookUpRCX =0;

for(lookUpRCX=0; lookUpRCX <= numberOfDevices - 1; lookUpRCX++)
{
dev1 = [devArray objectAtIndex:lookUpRCX];
NSString *radioDev = [dev1 friendlyName];

BOOL isItRadio = [ radioDev isEqualToString:@"My Device"];
if( isItRadio )
{
NSLog(@" Device %d in Array %@", lookUpRCX, rodioDev );
break;
}
else NSLog(@" Device %d in Array %@", lookUpRCX, radioDev );
/////[rotelDev release];
}
CGUpnpService *rsx_Service = [dev1 getServiceForType:@"urn:myupnp-com:service:Radio:0.0"];
if (rsx_Service) {

/// do some stuff
}