forked from charlieroberts/midiStroke
-
Notifications
You must be signed in to change notification settings - Fork 0
/
KeyStroke.m
149 lines (124 loc) · 5.12 KB
/
KeyStroke.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#import "KeyStroke.h"
@implementation KeyStroke
static void notifyProc(const MIDINotification *message, void *refCon) // if MIDI setup is changed
{
KeyStroke *key = (KeyStroke *)refCon; // create reference to the KeyStroke object that created the port
[key rescanForSources]; // rescan all available midi sources
[key setupSourcePopup];
}
static void readProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
{
KeyStroke *key = (KeyStroke *)refCon; // creates reference for midiMe object from refCon created with Input Port creation method
[key midiProcess:(MIDIPacketList *)pktlist endpoint:(MIDIPortRef *)connRefCon];
}
- (void)midiProcess:(MIDIPacketList *)pktlist endpoint:(MIDIPortRef *)connRefCon {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
NSString *type;
int packetStart = packet->data[0];
if ((packetStart>>4) == 0x09) { type = @"nOn"; } // noteOn
if ((packetStart>>4) == 0x08) { type = @"nOff"; } // noteOff
if ((packetStart>>4) == 0x0b) { type = @"cc"; } // cc
if ((packetStart>>4) == 0x0e) { type = @"pb"; } // pitchbend
if ((packetStart) == 0xfe) { type = @"as"; } // activeSensing
if ((packetStart>>4) == 0x0c) { type = @"pgm"; } // program change
if ((type == @"nOn" && packet->data[2] != 0) || type == @"cc" || type == @"pgm") {
[convert midiConvert:(MIDIPacket *)packet endpoint:(MIDIPortRef *)connRefCon];
}
[pool release];
}
- (void) awakeFromNib {
connected = FALSE;
[mainWindow setFrameUsingName:@"msWin"];
MIDIClientCreate(CFSTR("midiMonitor"), notifyProc, self, &client);
MIDIInputPortCreate(client, CFSTR("Input Port"), readProc, self, &inPort);
[self rescanForSources]; // rescan all available midi sources
[self setupSourcePopup];
defaults = [NSUserDefaults standardUserDefaults];
[self loadDefaultSource];
}
-(void)rescanForSources
{
MIDIEndpointRef *sources;
int i, j;
num_sources = MIDIGetNumberOfSources();
sources = (MIDIEndpointRef *)malloc(sizeof(MIDIEndpointRef) * num_sources);
j = 0;
for (i = 0; i < num_sources; i++) {
MIDIEndpointRef source;
source = MIDIGetSource(i);
sources[j++] = source;
}
sourcesArray = CFArrayCreate(NULL, (void *)sources, j, NULL);
free(sources);
}
- (CFArrayRef) getSourcesArray { return sourcesArray; }
- (void)setupSourcePopup
{
CFArrayRef sourceArray;
int numSources, i;
[sourcePopup removeAllItems];
sourceArray = [self getSourcesArray];
numSources = CFArrayGetCount(sourceArray);
[sourcePopup addItemWithTitle:@"None"];
for (i = 0; i < numSources; i++) {
CFStringRef pName;
CFStringRef pModel;
MIDIEndpointRef source;
source = (MIDIEndpointRef)CFArrayGetValueAtIndex(sourceArray, i);
NSMutableString *mNum = [NSMutableString string];
MIDIObjectGetStringProperty(source, kMIDIPropertyName, &pName);
OSStatus modelCheck = MIDIObjectGetStringProperty(source, kMIDIPropertyModel, &pModel);
if(modelCheck != kMIDIUnknownProperty && pModel != nil) {
[mNum appendString:(NSString *)pModel];
[mNum appendString:@" "];
}
if( pName != nil ) {
[mNum appendString:(NSString *)pName];
[sourcePopup insertItemWithTitle:mNum atIndex:i+1];
}
}
CFRelease(sourceArray);
}
- (void) loadDefaultSource {
NSString *src = [defaults stringForKey:@"MIDI Source"];
if(src != nil) {
int index = [sourcePopup indexOfItemWithTitle:src];
if (index != -1) { // if the source is found...
if(index != 0) { // ..and not equal to None...
chosenInput1 = MIDIGetSource(index - 1); // get the chosen source and store the endpoint ref
MIDIPortConnectSource(inPort, chosenInput1, chosenInput1);
connected = TRUE;
[sourcePopup selectItemWithTitle:src];
}
}else{ // last used midi source is not connected
NSAlert *noPopup = [[NSAlert alloc] init];
NSMutableString *msgString = [NSMutableString stringWithFormat :@"Your last selected MIDI source (%@) is unavailable. Please choose another MIDI input.", src];
[noPopup setMessageText:msgString];
[noPopup runModal];
[noPopup release];
}
}
}
- (IBAction)selectSource:(id)sender {
if ([sender indexOfSelectedItem] != 0) { // if they have not chosen "none" in the popup window
if(connected) { // if there is already a source connected...
MIDIPortDisconnectSource(inPort, chosenInput1); // ... disconnect it
}
chosenInput1 = MIDIGetSource([sender indexOfSelectedItem]-1); // get the chosen source and store the endpoint ref
MIDIPortConnectSource(inPort, chosenInput1, chosenInput1); // MIDIPortConnectSource(inPort, src, refCon);
connected = TRUE;
[defaults setObject:[sender titleOfSelectedItem] forKey:@"MIDI Source"];
}else{ // if the user has selected "None" from the menu...
if (connected) { // ... and if there is a source connected...
MIDIPortDisconnectSource(inPort, chosenInput1); // ... disconnect it
connected = FALSE;
[defaults setObject:@"None" forKey:@"MIDI Source"];
}
}
}
- (void) dealloc {
CFRelease(sourcesArray);
[super dealloc];
}
@end