241 lines
10 KiB
Objective-C
241 lines
10 KiB
Objective-C
//
|
|
// MIKMIDIConnectionManager.h
|
|
// MIKMIDI
|
|
//
|
|
// Created by Andrew Madsen on 11/5/15.
|
|
// Copyright © 2015 Mixed In Key. All rights reserved.
|
|
//
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import "MIKMIDICompilerCompatibility.h"
|
|
#import "MIKMIDISourceEndpoint.h"
|
|
|
|
@class MIKMIDIDevice;
|
|
@class MIKMIDINoteOnCommand;
|
|
|
|
@protocol MIKMIDIConnectionManagerDelegate;
|
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
/**
|
|
* MIKMIDIConnectionManager can be used to manage a set of connected devices. It can be configured to automatically
|
|
* connect to devices as they are added, and disconnect from them as they are removed. It also supports saving
|
|
* the list of connected to NSUserDefaults and restoring them upon relaunch.
|
|
*
|
|
* The use of MIKMIDIConnectionManager is optional. It is meant to be useful in implementing functionality that
|
|
* many MIDI device enabled apps need. However, simple connection to devices or MIDI endpoints can be done with
|
|
* MIKMIDIDeviceManager directly, if desired.
|
|
*/
|
|
@interface MIKMIDIConnectionManager : NSObject
|
|
|
|
/**
|
|
* This method will throw an exception if called. Use -initWithName:delegate:eventHandler: instead.
|
|
*
|
|
* @return nil
|
|
*/
|
|
- (instancetype)init NS_UNAVAILABLE;
|
|
|
|
/**
|
|
* Initializes an instance of MIKMIDIConnectionManager. The passed in name is used to independently
|
|
* store and load the connection manager's configuration using NSUserDefaults. The passed in name
|
|
* should be unique across your application, and the same from launch to launch.
|
|
*
|
|
* @param name The name to give the connection manager. Must not be nil or empty.
|
|
* @param delegate The delegate of the connection manager
|
|
* @param eventHandler An MIKMIDIEventHandlerBlock to be called with incoming MIDI messages from any connected device.
|
|
*
|
|
* @return An initialized MIKMIDIConnectionManager instance.
|
|
*/
|
|
- (instancetype)initWithName:(NSString *)name
|
|
delegate:(nullable id<MIKMIDIConnectionManagerDelegate>)delegate
|
|
eventHandler:(nullable MIKMIDIEventHandlerBlock)eventHandler NS_DESIGNATED_INITIALIZER;
|
|
|
|
/**
|
|
* Initializes an instance of MIKMIDIConnectionManager. The passed in name is used to independently
|
|
* store and load the connection manager's configuration using NSUserDefaults. The passed in name
|
|
* should be unique across your application, and the same from launch to launch. This is the same
|
|
* as calling -initWithName:delegate:eventHandler: with a nil delegate and eventHandler.
|
|
*
|
|
* @param name The name to give the connection manager. Must not be nil or empty.
|
|
*
|
|
* @return An initialized MIKMIDIConnectionManager instance.
|
|
*/
|
|
- (instancetype)initWithName:(NSString *)name;
|
|
|
|
/**
|
|
* Connect to the specified device. When MIDI messages are received, the connection manager's event handler
|
|
* block will be executed.
|
|
*
|
|
* @param device An MIKMIDIDevice instance.
|
|
* @param error If an error occurs, upon returns contains an NSError object that describes the problem.
|
|
* If you are not interested in possible errors, you may pass in NULL.
|
|
*
|
|
* @return YES if the connection was successful, NO if an error occurred.
|
|
*/
|
|
- (BOOL)connectToDevice:(MIKMIDIDevice *)device error:(NSError **)error;
|
|
|
|
/**
|
|
* Disconnect from a connected device. No further messages from the specified device will be processed.
|
|
*
|
|
* Note that you don't need to call this method when a previously-connected device was removed from the system.
|
|
* Disconnection in that situation is handled automatically.
|
|
*
|
|
* @param device An MIKMIDIDevice instance.
|
|
*/
|
|
- (void)disconnectFromDevice:(MIKMIDIDevice *)device;
|
|
|
|
/**
|
|
* This method can be used to determine if the receiver is connected to a given MIDI device.
|
|
*
|
|
* @param device An MIKMIDIDevice instance.
|
|
*
|
|
* @return YES if the receiver is connected to and processing MIDI input from the device, NO otherwise.
|
|
*/
|
|
- (BOOL)isConnectedToDevice:(MIKMIDIDevice *)device;
|
|
|
|
/**
|
|
* If YES (the default), the connection manager will automatically save its configuration at appropriate
|
|
* times. If this property is NO, -saveConfiguration can still be used to manually trigger saving the
|
|
* receiver's configuration. Note that -loadConfiguration must always be called manually, e.g. at launch.
|
|
*/
|
|
@property (nonatomic) BOOL automaticallySavesConfiguration;
|
|
|
|
/**
|
|
* Save the receiver's list of connected devices to disk for later restoration.
|
|
*/
|
|
- (void)saveConfiguration;
|
|
|
|
/**
|
|
* Load and reconnect to the devices previously saved to disk by a call to -saveConfiguration. For
|
|
* this to work, the receiver's name must be the same as it was upon the previous call to -saveConfiguration.
|
|
*
|
|
* @note: This method will only connect to new devices. It will not disconnect from devices not found in the
|
|
* saved configuration.
|
|
*/
|
|
- (void)loadConfiguration;
|
|
|
|
/**
|
|
* The name of the receiver. Used for configuration save/load.
|
|
*/
|
|
@property (nonatomic, copy, readonly) NSString *name;
|
|
|
|
/**
|
|
* An MIKMIDIEventHandlerBlock to be called with incoming MIDI messages from any connected device.
|
|
*
|
|
* If you need to determine which device sent the passed in messages, call source.entity.device on the
|
|
* passed in MIKMIDISourceEndpoint argument.
|
|
*/
|
|
@property (nonatomic, copy, null_resettable) MIKMIDIEventHandlerBlock eventHandler;
|
|
|
|
/**
|
|
* A delegate, used to customize MIKMIDIConnectionManager behavior.
|
|
*/
|
|
@property (nonatomic, weak, nullable) id<MIKMIDIConnectionManagerDelegate>delegate;
|
|
|
|
/**
|
|
* Controls whether the receiver's availableDevices property includes virtual devices (i.e. devices made
|
|
* up of automatically paired virtual sources and destinations).
|
|
*
|
|
* If this property is YES (the default), the connection manager will attempt to automtically related
|
|
* associated virtual sources and destinations and create "virtual" MIKMIDIDevice instances for them.
|
|
*
|
|
* If this property is NO, the connection manager's availableDevices array will _only_ contain non-virtual
|
|
* MIKMIDIDevices.
|
|
*
|
|
* For most applications, this should be left at the default YES, as even many physical MIDI devices present as
|
|
* "virtual" devices in software.
|
|
*
|
|
* @note: The caveat here is that this relies on some heuristics to match up source endpoints with destination endpoints.
|
|
* These heuristics are based on the way certain common MIDI devices behave, but may not be universal, and therefore
|
|
* may miss, or fail to properly associate endpoints for some devices. If this is a problem for your application,
|
|
* you should obtain and connect to virtual sources/endpoints using MIKMIDIDeviceManager directly instead.
|
|
*/
|
|
@property (nonatomic) BOOL includesVirtualDevices; // Default is YES
|
|
|
|
/**
|
|
* An array of available MIDI devices.
|
|
*
|
|
* This property is observable using Key Value Observing.
|
|
*/
|
|
@property (nonatomic, strong, readonly) MIKArrayOf(MIKMIDIDevice *) *availableDevices;
|
|
|
|
/**
|
|
* The set of MIDI devices to which the receiver is connected.
|
|
*
|
|
* This property is observable using Key Value Observing.
|
|
*/
|
|
@property (nonatomic, strong, readonly) MIKSetOf(MIKMIDIDevice *) *connectedDevices;
|
|
|
|
@end
|
|
|
|
|
|
/**
|
|
* Specifies behavior for connecting to a newly connected device. See
|
|
* -connectionManager:shouldConnectToNewlyAddedDevice:
|
|
*/
|
|
typedef NS_ENUM(NSInteger, MIKMIDIAutoConnectBehavior) {
|
|
|
|
/** Do not connect to the newly added device */
|
|
MIKMIDIAutoConnectBehaviorDoNotConnect,
|
|
|
|
/** Connect to the newly added device */
|
|
MIKMIDIAutoConnectBehaviorConnect,
|
|
|
|
/** Connect to the newly added device only if it was previously connected (ie. in the saved configuration data) */
|
|
MIKMIDIAutoConnectBehaviorConnectOnlyIfPreviouslyConnected,
|
|
|
|
/** Connect to the newly added device if it was previously connected, or is unknown in the configuration data.*/
|
|
MIKMIDIAutoConnectBehaviorConnectIfPreviouslyConnectedOrNew,
|
|
};
|
|
|
|
/**
|
|
* Protocol containing method(s) to be implemented by delegates of MIKMIDIConnectionManager.
|
|
*/
|
|
@protocol MIKMIDIConnectionManagerDelegate <NSObject>
|
|
|
|
@optional
|
|
|
|
/**
|
|
* A connection manager's delegate can implement this method to determine whether or not to automatically connect
|
|
* to a newly added MIDI device. See MIKMIDIAutoConnectBehavior for possible return values.
|
|
*
|
|
* If this method is not implemented, the default behavior is MIKMIDIAutoConnectBehaviorConnectIfPreviouslyConnectedOrNew.
|
|
*
|
|
* @param manager An instance of MIKMIDIConnectionManager.
|
|
* @param device The newly added MIDI device.
|
|
*
|
|
* @return One of the values defined in MIKMIDIAutoConnectBehavior.
|
|
*/
|
|
- (MIKMIDIAutoConnectBehavior)connectionManager:(MIKMIDIConnectionManager *)manager shouldConnectToNewlyAddedDevice:(MIKMIDIDevice *)device;
|
|
|
|
/**
|
|
* A connection manager's delegate can implement this method to be notified when a device is connected,
|
|
* either because -connectToDevice:error: was called, or because the device was plugged, and the manager
|
|
* automatically connected to it. You can for example use this method to update UI in response to a device being connected.
|
|
*
|
|
* @param manager An instance of MIKMIDIConnectionManager.
|
|
* @param device The MIKMIDIDevice that was disconnected.
|
|
*/
|
|
- (void)connectionManager:(MIKMIDIConnectionManager *)manager deviceWasConnected:(MIKMIDIDevice *)device;
|
|
|
|
/**
|
|
* A connection manager's delegate can implement this method to be notified when a connected device is disconnected,
|
|
* either because -disconnectFromDevice: was called, or because the device was unplugged.
|
|
*
|
|
* If a MIDI device is disconnected between sending a note on message and sending the corresponding note off command,
|
|
* this can cause a "stuck note" because the note off command will now never be delivered. e.g. a MIDI piano keyboard
|
|
* that is disconnected with a key held down. This method includes an array of these unterminated note on commands (if any)
|
|
* so that the receiver can appropriately deal with this situation. For example, corresponding note off commands could
|
|
* be generated and sent through whatever processing chain is processing incoming MIDI commands to terminate stuck notes.
|
|
*
|
|
* @param manager An instance of MIKMIDIConnectionManager.
|
|
* @param device The MIKMIDIDevice that was disconnected.
|
|
* @param commands An array of note on messages for which corresponding note off messages have not yet been received.
|
|
*/
|
|
- (void)connectionManager:(MIKMIDIConnectionManager *)manager deviceWasDisconnected:(MIKMIDIDevice *)device withUnterminatedNoteOnCommands:(MIKArrayOf(MIKMIDINoteOnCommand *) *)commands;
|
|
|
|
@end
|
|
|
|
NS_ASSUME_NONNULL_END
|
|
|