hammerspoon/Pods/MIKMIDI/Source/MIKMIDIDevice.m

197 lines
4.7 KiB
Objective-C

//
// MIKMIDIDevice.m
// MIDI Testbed
//
// Created by Andrew Madsen on 3/7/13.
// Copyright (c) 2013 Mixed In Key. All rights reserved.
//
#import "MIKMIDIDevice.h"
#import "MIKMIDIObject_SubclassMethods.h"
#import "MIKMIDIEntity.h"
#import "MIKMIDISourceEndpoint.h"
#import "MIKMIDIDestinationEndpoint.h"
#import "MIKMIDIUtilities.h"
#if !__has_feature(objc_arc)
#error MIKMIDIDevice.m must be compiled with ARC. Either turn on ARC for the project or set the -fobjc-arc flag for MIKMIDIDevice.m in the Build Phases for this target
#endif
@interface MIKMIDIDevice ()
@property (nonatomic, strong, readwrite) NSString *manufacturer;
@property (nonatomic, strong, readwrite) NSString *model;
@property (nonatomic, strong) NSMutableArray *internalEntities;
- (void)addInternalEntitiesObject:(MIKMIDIEntity *)entity;
- (void)removeInternalEntitiesObject:(MIKMIDIEntity *)entity;
@end
@interface MIKMIDIEntity (Private)
@property (nonatomic, weak, readwrite) MIKMIDIDevice *device;
@end
@implementation MIKMIDIDevice
+ (void)load { [MIKMIDIObject registerSubclass:[self class]]; }
+ (NSArray *)representedMIDIObjectTypes; { return @[@(kMIDIObjectType_Device)]; }
+ (BOOL)canInitWithObjectRef:(MIDIObjectRef)objectRef
{
if (!objectRef) return YES; // To allow creating 'virtual' devices
return [super canInitWithObjectRef:objectRef];
}
- (id)initWithObjectRef:(MIDIObjectRef)objectRef
{
self = [super initWithObjectRef:objectRef];
if (self) {
if (objectRef) [self retrieveEntities];
}
return self;
}
+ (instancetype)deviceWithVirtualEndpoints:(NSArray *)endpoints;
{
return [[self alloc] initWithVirtualEndpoints:endpoints];
}
- (instancetype)initWithVirtualEndpoints:(NSArray *)endpoints;
{
self = [self initWithObjectRef:0];
if (self) {
self.isVirtual = YES;
MIKMIDIEntity *entity = [MIKMIDIEntity entityWithVirtualEndpoints:endpoints];
entity.device = self;
self.internalEntities = [NSMutableArray arrayWithObject:entity];
}
return self;
}
- (BOOL)isEqual:(id)object
{
if (![super isEqual:object]) return NO;
return [self.entities isEqualToArray:[(MIKMIDIDevice *)object entities]];
}
- (NSUInteger)hash
{
if (!self.isVirtual) {
return [super hash];
}
return [self.entities hash];
}
#pragma mark - Public
- (NSString *)description
{
NSMutableString *result = [NSMutableString stringWithFormat:@"%@:\r Entities: {\r", [super description]];
for (MIKMIDIEntity *entity in self.entities) {
[result appendFormat:@" %@,\r", entity];
}
[result appendString:@" }"];
return result;
}
#pragma mark - Private
- (void)retrieveEntities
{
NSMutableArray *entities = [NSMutableArray array];
ItemCount numEntities = MIDIDeviceGetNumberOfEntities(self.objectRef);
for (ItemCount i=0; i<numEntities; i++) {
MIDIEntityRef entityRef = MIDIDeviceGetEntity(self.objectRef, i);
MIKMIDIEntity *entity = [MIKMIDIEntity MIDIObjectWithObjectRef:entityRef];
if (!entity) continue;
entity.device = self;
[entities addObject:entity];
}
self.internalEntities = entities;
}
#pragma mark - Properties
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
if ([key isEqualToString:@"entities"]) {
keyPaths = [keyPaths setByAddingObject:@"internalEntities"];
}
return keyPaths;
}
- (MIDIObjectRef)objectRef
{
if (self.isVirtual) {
MIKMIDIEntity *entity = [self.entities firstObject];
MIKMIDIEndpoint *endpoint = [entity.sources count] ? [entity.sources firstObject] : [entity.destinations firstObject];
return endpoint.objectRef;
}
return [super objectRef];
}
- (NSString *)manufacturer
{
if (!_manufacturer) {
NSError *error = nil;
NSString *value = MIKStringPropertyFromMIDIObject(self.objectRef, kMIDIPropertyManufacturer, &error);
if (!value) {
NSLog(@"Unable to get MIDI device manufacturer: %@", error);
return nil;
}
self.manufacturer = value;
}
return _manufacturer;
}
- (NSString *)model
{
if (!_model) {
NSError *error = nil;
NSString *value = MIKStringPropertyFromMIDIObject(self.objectRef, kMIDIPropertyModel, &error);
if (!value) {
NSLog(@"Unable to get MIDI device model: %@", error);
return nil;
}
self.model = value;
}
return _model;
}
- (NSString *)name
{
NSString *result = [super name];
if (result) return result;
return self.model;
}
- (NSString *)displayName
{
NSString *result = [super displayName];
if (result) return result;
return self.model;
}
- (NSArray *)entities { return [self.internalEntities copy]; }
- (void)addInternalEntitiesObject:(MIKMIDIEntity *)entity;
{
[self.internalEntities addObject:entity];
}
- (void)removeInternalEntitiesObject:(MIKMIDIEntity *)entity;
{
[self.internalEntities removeObject:entity];
}
@end