Developer's Guide - Step by step
Firstly, an app can implement one or more (but usually/preferably all) of the following
concepts:
- Fast Switch Receiver - you want other (sender) apps to be able to
fast switch to your app and include your app in their own list.
- Fast Switch Sender - you want to be able to fast switch from your
app to registered receivers and list other apps in your app.
- Fast-switch MIDI Receiver - you want to allow users to switch to
and from your app via MIDI messages.
|
Implementing Fast Switch Receiver
Step 1 - update your app's Info.plist
First, your app's Info.plist needs an URL Name and Scheme. The following
code snippet can be copied/pasted into your own Info.plist. This is the
example entry. Make sure that you change the two values to match
your application.
CFBundleURLTypes
CFBundleURLName
com.example.appname
CFBundleURLSchemes
appname
|
Change the CFBundleURLName and CFBundleURLSchemes array
to match your app!
|
Note: The value you specify in the string of CFBundleURLSchemes should be all
lower case, as it will translate to an URL of appname://
Step 2 - register your app with the OMAC Registry
Use the quicklink at the top of this page to request your app be added
to the registry. Detailed instructions for the information that should be
provided are on the registration form.
Once your app is registered and released with corresponding changes to
the Info.plist in the AppStore, sender apps will be able to detect and
fast-switch to your application.
Implementing Fast Switch MIDI Receiver
A free to use class is available (use quicklinks above) that you may
download and use in your own application code.
This guide will assume you use the free class and have
downloaded the zip file, unpacked it somewhere and added to your project.
Obviously your app needs either its own virtual destination or it should
listen to a virtual source that will produce the messages. Currently this is
'MidiBridge', but you're best off declaring an OMAC compliant virtual
CoreMIDI pair for your own app.
Step 1 - use the OMACApplicationRegistry class to process switching
messages in your app's MIDI engine
// Code snippet to be included in an app's MIDI Engine when a new MIDI
// message is received. You can use a static pointer for efficiency in
// creating an omac registry object.
// Assuming that your MIDI message is in an unsigned char array like so:
// unsigned char midi_message_data;
// unsigned short midi_message_length;
#import "OMACApplicationRegistry.h"
// check/process OMAC app switching message
static OMACApplicationRegistry* omac = nil;
// use OMAC macro to avoid function call overhead
if (IS_OMAC_MIDI_MESSAGE(midi_message_data))
{
// create a static omac instance if not already done. Only pass nil
// as AppName if you instantiate the omac instance in your app startup
if (omac == nil) omac = [OMACApplicationRegistry instanceWithAppName:nil];
// ask the object to process the OMAC switching message
[omac processMIDIMessage:midi_message_data:midi_message_length];
}
|
Step 2 - Notify the registry that your app supports MIDI switching
Use the email address below to let us know and we'll update the
registry entry for your app to indicate that it supports MIDI switching.
Best to do this once your app is released, though!
Implementing Fast Switch Sender
A free to use class is available (use quicklinks above) that you may
download and use in your own application code. It includes DNS versioning
and background thread updating. Of course, you can create your own class
if you prefer. This guide will assume you use the free class and have
downloaded the zip file and unpacked it somewhere.
Step 1 - Add the class and plist to your project
You should add the OMACApplicationRegistry.[hm] and omac_apps.plist to
your project. In particular, the plist will be included in your app bundle
so that in the event of a user not having internet connectivity to access
the registry, there will still be something for the class to use.
Step 2 - Implement the class in your code
This is best explained by example and assumes that you have a
ViewController class that you will be using the registry with:
In your ViewController's header file:
#import "OMACApplicationRegistry.h"
// your ViewController should confirm to the OMACApplicationRegistryDelegate
// protocol if you want to update the shared property list in the background.
// If you don't want background thread updates (ie. you're OK with updating the
// plist on your main thread when you start, then no need to conform to the
// protocol. However, background thread updates are recommended
@interface myViewController : UIViewController
{
...
}
|
In your ViewController's implementation file:
- (void)viewDidLoad
{
...
// OMACApplicationRegistry initialisation
// You can set the following global variable to YES and the class
// will log/trace to the console. Don't leave this as YES in a
// production build!!!!
OMACTrace = NO;
// Obtain the shared instance of the registry object. The name
// you pass in *must* match the Application Name that you registered
// your app with in the registry. You only need to pass this name in
// once (first call to instanceWithAppName). If the instance failed
// then it will return a nil.
OMACApplicationRegistry* omac;
omac = [OMACApplicationRegistry instanceWithAppName:@"MyApp"];
if (omac != nil)
{
// If you are going to perform any plisgt update in a background
// thread, then specify a delegate (you must conform to the
// protocol). If no delegate is specified then the update method
// will execute on the current thread.
omac.delegate = self;
// update (if necessary) the property list. If current version of
// the property list is up-to-date, then no update will be fetched
// NB. Any updated property list is stored in the application's
// Library/Caches directory
enum OMACUpdateStatus status;
status = [omac update];
// you can check the return status of update. If running the update
// in the background, this will return eOMACUpdateStarted and your
// completion method (see below) will receive the actual status on
// completion. If not backgrounding the status will be one of the
// OMACUpdateStatus values in the header
if (status > eOMACUpdateStarted)
{
// something went wrong
}
}
...
}
// update completion method
- (void)OMACUpdateComplete:(enum eOMACUpdateStatus)status
{
NSLog(@"OMACUpdateComplete status: %i", status);
// get a filtered list of app objects and do something with
// them in UI code oir something. The filtered list will be
// sorted by installed apps first, then other apps, both in
// app name alpha order. Our own app and apps that are not
// supported on the current device/IOS will be excluded
NSArray* apps = [omac filteredApps];
NSLog(@"%i OMAC app(s)", apps.count);
for (OMACApplication* app in apps)
{
NSLog(@"app: '%@', dev: '%@', url: '%@'", app.name, app.developer, app.launchURL);
NSLog(@" desc: '%@', virt_port: '%@'", app.description, app.virtualPortName);
NSLog(@" installed: %i, min_ios: %f", app.installed, app.minimumCoreFoundation);
NSLog(@" app_store: '%@', vid: '%@'", app.appStoreURL, app.videoURL);
NSLog(@" platforms: %@", app.supportedPlatforms.description);
}
// To switch/launch an OMAC app from your own app, locate the
// OMACApplication object in the filteredApps list and call the
// launch method, eg: [app launch]
}
- (void)dealloc
{
// cleanup OMAC
[OMACApplicationRegistry shutdown];
...
}
|
Once you have implemented the OMACApplicationRegistry class in your
app, the shared property list will be updated automatically when a
new version is published.