186 lines
4.3 KiB
Objective-C
186 lines
4.3 KiB
Objective-C
//
|
|
// MIKMIDIObject.m
|
|
// MIDI Testbed
|
|
//
|
|
// Created by Andrew Madsen on 3/8/13.
|
|
// Copyright (c) 2013 Mixed In Key. All rights reserved.
|
|
//
|
|
|
|
#import "MIKMIDIObject.h"
|
|
#import "MIKMIDIObject_SubclassMethods.h"
|
|
#import "MIKMIDIDevice.h"
|
|
#import "MIKMIDIEntity.h"
|
|
#import "MIKMIDIEndpoint.h"
|
|
#import "MIKMIDIUtilities.h"
|
|
|
|
#if !__has_feature(objc_arc)
|
|
#error MIKMIDIObject.m must be compiled with ARC. Either turn on ARC for the project or set the -fobjc-arc flag for MIKMIDIObject.m in the Build Phases for this target
|
|
#endif
|
|
|
|
static NSMutableSet *registeredMIKMIDIObjectSubclasses;
|
|
|
|
@interface MIKMIDIObject ()
|
|
|
|
@property (nonatomic, readwrite) MIDIObjectRef objectRef;
|
|
@property (nonatomic, readwrite) MIDIUniqueID uniqueID;
|
|
@property (nonatomic, strong, readwrite) NSString *displayName;
|
|
|
|
@end
|
|
|
|
@implementation MIKMIDIObject
|
|
|
|
+ (void)registerSubclass:(Class)subclass;
|
|
{
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
registeredMIKMIDIObjectSubclasses = [[NSMutableSet alloc] init];
|
|
});
|
|
[registeredMIKMIDIObjectSubclasses addObject:subclass];
|
|
}
|
|
|
|
+ (NSArray *)representedMIDIObjectTypes; { return @[]; }
|
|
|
|
+ (BOOL)canInitWithObjectRef:(MIDIObjectRef)objectRef;
|
|
{
|
|
NSError *error = nil;
|
|
MIDIObjectType objectType = MIKMIDIObjectTypeOfObject(objectRef, &error);
|
|
if (error) {
|
|
NSLog(@"Unable to get object type of %d: %@", (int)objectRef, error);
|
|
return NO;
|
|
}
|
|
return [[self representedMIDIObjectTypes] containsObject:@(objectType)];
|
|
}
|
|
|
|
+ (instancetype)MIDIObjectWithObjectRef:(MIDIObjectRef)objectRef;
|
|
{
|
|
if (objectRef == 0) return nil;
|
|
Class resultSubclass = nil;
|
|
for (Class subclass in registeredMIKMIDIObjectSubclasses) {
|
|
if ([subclass canInitWithObjectRef:objectRef]) {
|
|
resultSubclass = subclass;
|
|
break;
|
|
}
|
|
}
|
|
if (!resultSubclass) return nil;
|
|
|
|
return [[resultSubclass alloc] initWithObjectRef:objectRef];
|
|
}
|
|
|
|
- (id)init
|
|
{
|
|
[NSException raise:NSInternalInconsistencyException format:@"MIKMIDIObjects should be initialized using -initWithObjectRef:"];
|
|
self = nil;
|
|
return nil;
|
|
}
|
|
|
|
- (id)initWithObjectRef:(MIDIObjectRef)objectRef
|
|
{
|
|
if (![[self class] canInitWithObjectRef:objectRef]) {
|
|
self = nil;
|
|
return nil;
|
|
}
|
|
|
|
self = [super init];
|
|
if (self) {
|
|
_objectRef = objectRef;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (BOOL)isEqual:(id)object
|
|
{
|
|
if (object == self) return YES;
|
|
if (![[object class] isEqual:[self class]]) return NO;
|
|
|
|
return self.uniqueID == [(MIKMIDIObject *)object uniqueID];
|
|
}
|
|
|
|
- (NSUInteger)hash
|
|
{
|
|
return @(self.uniqueID).hash;
|
|
}
|
|
|
|
- (NSString *)description
|
|
{
|
|
NSString *name = self.displayName ? self.displayName : self.name;
|
|
return [NSString stringWithFormat:@"%@ %@", [super description], name];
|
|
}
|
|
|
|
#pragma mark - Public
|
|
|
|
- (NSDictionary *)propertiesDictionary
|
|
{
|
|
CFPropertyListRef properties = NULL;
|
|
OSStatus err = MIDIObjectGetProperties(self.objectRef, &properties, true);
|
|
if (err) return @{};
|
|
if (![(__bridge id)properties isKindOfClass:[NSDictionary class]]) return @{};
|
|
return (__bridge NSDictionary *)properties;
|
|
}
|
|
|
|
#pragma mark - Private
|
|
|
|
#pragma mark - Properties
|
|
|
|
@synthesize uniqueID = _uniqueID;
|
|
|
|
- (MIDIUniqueID)uniqueID
|
|
{
|
|
if (!_uniqueID) {
|
|
NSError *error = nil;
|
|
MIDIUniqueID value = MIKIntegerPropertyFromMIDIObject(self.objectRef, kMIDIPropertyUniqueID, &error);
|
|
if (error) {
|
|
NSLog(@"Unable to get MIDI device unique ID: %@", error);
|
|
return 0;
|
|
}
|
|
self.uniqueID = value;
|
|
}
|
|
return _uniqueID;
|
|
}
|
|
|
|
- (BOOL)isOnline
|
|
{
|
|
NSError *error = nil;
|
|
SInt32 offline = MIKIntegerPropertyFromMIDIObject(self.objectRef, kMIDIPropertyOffline, &error);
|
|
if (error) {
|
|
NSLog(@"Unable to get offline status for MIDI object %@", self);
|
|
return NO;
|
|
}
|
|
|
|
return offline == 0;
|
|
}
|
|
|
|
@synthesize name = _name;
|
|
|
|
- (NSString *)name
|
|
{
|
|
if (self.isVirtual && _name) return _name;
|
|
return MIKStringPropertyFromMIDIObject(self.objectRef, kMIDIPropertyName, NULL);
|
|
}
|
|
|
|
- (void)setName:(NSString *)name
|
|
{
|
|
if (self.isVirtual) {
|
|
if (name != _name) {
|
|
_name = name;
|
|
}
|
|
} else {
|
|
NSError *error = nil;
|
|
if (!MIKSetStringPropertyOnMIDIObject(self.objectRef, kMIDIPropertyName, name, &error)) {
|
|
NSLog(@"Unable to set name on %@: %@", self, error);
|
|
}
|
|
}
|
|
}
|
|
|
|
- (NSString *)displayName
|
|
{
|
|
if (!_displayName && _objectRef != 0) {
|
|
NSError *error = nil;
|
|
NSString *value = MIKStringPropertyFromMIDIObject(_objectRef, kMIDIPropertyDisplayName, &error);
|
|
if (value) self.displayName = value;
|
|
}
|
|
|
|
return _displayName ? _displayName : self.name;
|
|
}
|
|
|
|
@end
|