hammerspoon/Pods/MIKMIDI/Source/MIKMIDIEntity.m

187 lines
5.4 KiB
Objective-C

//
// MIKMIDIEntity.m
// MIDI Testbed
//
// Created by Andrew Madsen on 3/7/13.
// Copyright (c) 2013 Mixed In Key. All rights reserved.
//
#import "MIKMIDIEntity.h"
#import "MIKMIDIObject_SubclassMethods.h"
#import "MIKMIDISourceEndpoint.h"
#import "MIKMIDIDestinationEndpoint.h"
#import "MIKMIDIUtilities.h"
#if !__has_feature(objc_arc)
#error MIKMIDIEntity.m must be compiled with ARC. Either turn on ARC for the project or set the -fobjc-arc flag for MIKMIDIEntity.m in the Build Phases for this target
#endif
@interface MIKMIDIEntity ()
@property (nonatomic, weak, readwrite) MIKMIDIDevice *device;
@property (nonatomic, strong) NSMutableArray *internalSources;
- (void)addInternalSourcesObject:(MIKMIDISourceEndpoint *)source;
- (void)removeInternalSourcesObject:(MIKMIDISourceEndpoint *)source;
@property (nonatomic, strong) NSMutableArray *internalDestinations;
- (void)addInternalDestinationsObject:(MIKMIDIDestinationEndpoint *)destination;
- (void)removeInternalDestinationsObject:(MIKMIDIDestinationEndpoint *)destination;
@end
@interface MIKMIDIEndpoint (Private)
@property (nonatomic, weak, readwrite) MIKMIDIEntity *entity;
@end
@implementation MIKMIDIEntity
+ (void)load { [MIKMIDIObject registerSubclass:[self class]]; }
+ (NSArray *)representedMIDIObjectTypes; { return @[@(kMIDIObjectType_Entity)]; }
+ (BOOL)canInitWithObjectRef:(MIDIObjectRef)objectRef
{
if (!objectRef) return YES; // To allow creating 'virtual' entities
return [super canInitWithObjectRef:objectRef];
}
- (id)initWithObjectRef:(MIDIObjectRef)objectRef
{
self = [super initWithObjectRef:objectRef];
if (self) {
if (objectRef) [self retrieveEndpoints];
}
return self;
}
+ (instancetype)entityWithVirtualEndpoints:(NSArray *)endpoints;
{
return [[self alloc] initWithVirtualEndpoints:endpoints];
}
- (instancetype)initWithVirtualEndpoints:(NSArray *)endpoints;
{
self = [self initWithObjectRef:0];
if (self) {
self.isVirtual = YES;
NSMutableArray *sources = [NSMutableArray array];
NSMutableArray *destinations = [NSMutableArray array];
for (MIKMIDIEndpoint *endpoint in endpoints) {
if ([endpoint isKindOfClass:[MIKMIDISourceEndpoint class]]) {
endpoint.entity = self;
[sources addObject:endpoint];
} else if ([endpoint isKindOfClass:[MIKMIDIDestinationEndpoint class]]) {
endpoint.entity = self;
[destinations addObject:endpoint];
}
}
_internalSources = sources;
_internalDestinations = destinations;
}
return self;
}
- (BOOL)isEqual:(id)object
{
if (![super isEqual:object]) return NO;
return [self.sources isEqualToArray:[(MIKMIDIEntity *)object sources]] &&
[self.destinations isEqualToArray:[(MIKMIDIEntity *)object destinations]];
}
- (NSString *)description
{
NSMutableString *result = [NSMutableString stringWithFormat:@"%@:\r Sources: {\r", [super description]];
for (MIKMIDISourceEndpoint *source in self.sources) {
[result appendFormat:@" %@,\r", source];
}
[result appendString:@" }\r Destinations: {\r"];
for (MIKMIDIDestinationEndpoint *destination in self.destinations) {
[result appendFormat:@" %@,\r", destination];
}
[result appendString:@" }"];
return result;
}
#pragma mark - Private
- (void)retrieveEndpoints
{
NSMutableArray *sources = [NSMutableArray array];
ItemCount numSources = MIDIEntityGetNumberOfSources(self.objectRef);
for (ItemCount i=0; i<numSources; i++) {
MIDIEndpointRef sourceRef = MIDIEntityGetSource(self.objectRef, i);
MIKMIDISourceEndpoint *source = [MIKMIDISourceEndpoint MIDIObjectWithObjectRef:sourceRef];
if (!source) continue;
source.entity = self;
[sources addObject:source];
}
self.internalSources = sources;
NSMutableArray *destinations = [NSMutableArray array];
ItemCount numDestinations = MIDIEntityGetNumberOfDestinations(self.objectRef);
for (ItemCount i=0; i<numDestinations; i++) {
MIDIEndpointRef destinationRef = MIDIEntityGetDestination(self.objectRef, i);
MIKMIDISourceEndpoint *destination = [MIKMIDISourceEndpoint MIDIObjectWithObjectRef:destinationRef];
if (!destination) continue;
destination.entity = self;
[destinations addObject:destination];
}
self.internalDestinations = destinations;
}
#pragma mark - Properties
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
if ([key isEqualToString:@"sources"]) {
keyPaths = [keyPaths setByAddingObject:@"internalSources"];
}
if ([key isEqualToString:@"destinations"]) {
keyPaths = [keyPaths setByAddingObject:@"internalDestinations"];
}
return keyPaths;
}
- (MIDIObjectRef)objectRef
{
if (self.isVirtual) {
MIKMIDIObject *endpoint = [self.sources count] ? [self.sources firstObject] : [self.destinations firstObject];
return endpoint.objectRef;
}
return [super objectRef];
}
- (NSArray *)sources { return [self.internalSources copy]; }
- (void)addInternalSourcesObject:(MIKMIDISourceEndpoint *)source
{
[self.internalSources addObject:source];
}
- (void)removeInternalSourcesObject:(MIKMIDISourceEndpoint *)source
{
[self.internalSources removeObject:source];
}
- (NSArray *)destinations { return [self.internalDestinations copy]; }
- (void)addInternalDestinationsObject:(MIKMIDIDestinationEndpoint *)destination
{
[self.internalDestinations addObject:destination];
}
- (void)removeInternalDestinationsObject:(MIKMIDIDestinationEndpoint *)destination
{
[self.internalDestinations removeObject:destination];
}
@end