~ubuntu-branches/debian/sid/jackd2/sid

« back to all changes in this revision

Viewing changes to macosx/coremidi/JackCoreMidiDriver.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adrian Knoth
  • Date: 2011-03-31 13:54:50 UTC
  • mfrom: (1.1.3 upstream) (2.1.4 experimental)
  • Revision ID: james.westby@ubuntu.com-20110331135450-zafc1di024kzeu31
Tags: 1.9.7~dfsg-1
* New upstream version 1.9.7 (ALSA resume, new latency API)
* Build with --mixed on i386 to be compatible with amd64.
* Don't patch jack_connect for fast consecutive calls anymore, it's now
  using the same code as in jackd1 and waits for the port connection to
  appear.

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
        jack_error("ReadProc : ring buffer is full, skip events...");
46
46
        return;
47
47
    }
48
 
    
 
48
 
49
49
    jack_ringbuffer_write(ringbuffer, (char*)&pktlist->numPackets, sizeof(UInt32));
50
 
    
 
50
 
51
51
    for (unsigned int i = 0; i < pktlist->numPackets; ++i) {
52
 
    
 
52
 
53
53
        MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
54
 
        
 
54
 
55
55
        // TODO : use timestamp
56
 
        
 
56
 
57
57
        // Check available size first..
58
58
        size = jack_ringbuffer_write_space(ringbuffer);
59
59
        if (size < (sizeof(UInt16) + packet->length)) {
64
64
        jack_ringbuffer_write(ringbuffer, (char*)&packet->length, sizeof(UInt16));
65
65
        // Write event actual data
66
66
        jack_ringbuffer_write(ringbuffer, (char*)packet->data, packet->length);
67
 
            
 
67
 
68
68
        packet = MIDIPacketNext(packet);
69
69
    }
70
70
}
83
83
 
84
84
void JackCoreMidiDriver::NotifyProc(const MIDINotification *message, void *refCon)
85
85
{
86
 
        jack_info("NotifyProc %d", message->messageID);
 
86
        jack_log("NotifyProc %d", message->messageID);
87
87
}
88
88
 
89
89
JackCoreMidiDriver::JackCoreMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
106
106
    OSStatus err;
107
107
        CFStringRef coutputStr;
108
108
        std::string str;
109
 
    
 
109
 
110
110
    // Get real input/output number
111
111
    fRealCaptureChannels = MIDIGetNumberOfSources();
112
112
    fRealPlaybackChannels = MIDIGetNumberOfDestinations();
113
 
    
 
113
 
114
114
    // Generic JackMidiDriver Open
115
115
    if (JackMidiDriver::Open(capturing, playing, inchannels + fRealCaptureChannels, outchannels + fRealPlaybackChannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0)
116
116
        return -1;
117
 
    
 
117
 
118
118
    coutputStr = CFStringCreateWithCString(0, "JackMidi", CFStringGetSystemEncoding());
119
119
        err = MIDIClientCreate(coutputStr, NotifyProc, this, &fMidiClient);
120
120
        CFRelease(coutputStr);
122
122
        jack_error("Cannot create CoreMidi client");
123
123
                goto error;
124
124
        }
125
 
    
 
125
 
126
126
        err = MIDIInputPortCreate(fMidiClient, CFSTR("Input port"), ReadProc, this, &fInputPort);
127
127
        if (!fInputPort) {
128
128
                jack_error("Cannot open CoreMidi in port\n");
134
134
                jack_error("Cannot open CoreMidi out port\n");
135
135
                goto error;
136
136
        }
137
 
        
 
137
 
138
138
    fMidiDestination = new MIDIEndpointRef[inchannels + fRealCaptureChannels];
139
139
    assert(fMidiDestination);
140
 
    
 
140
 
141
141
    // Virtual input
142
142
    for (int i = 0; i < inchannels; i++)  {
143
143
        std::stringstream num;
151
151
            goto error;
152
152
        }
153
153
    }
154
 
    
 
154
 
155
155
    // Real input
156
156
    for (int i = 0; i < fRealCaptureChannels; i++)  {
157
157
        fMidiDestination[i + inchannels] = MIDIGetSource(i);
158
158
        MIDIPortConnectSource(fInputPort, fMidiDestination[i + inchannels], fRingBuffer[i + inchannels]);
159
159
    }
160
 
        
 
160
 
161
161
    fMidiSource = new MIDIEndpointRef[outchannels + fRealPlaybackChannels];
162
162
    assert(fMidiSource);
163
163
 
172
172
        if (!fMidiSource[i]) {
173
173
            jack_error("Cannot create CoreMidi source");
174
174
            goto error;
175
 
        }       
 
175
        }
176
176
    }
177
 
    
 
177
 
178
178
     // Real output
179
179
    for (int i = 0; i < fRealPlaybackChannels; i++)  {
180
180
        fMidiSource[i + outchannels] = MIDIGetDestination(i);
181
181
    }
182
 
 
 
182
 
183
183
    return 0;
184
 
    
 
184
 
185
185
error:
186
186
    Close();
187
187
        return -1;
188
188
}
189
 
         
 
189
 
190
190
int JackCoreMidiDriver::Close()
191
191
{
 
192
    // Generic midi driver close
 
193
    int res = JackMidiDriver::Close();
 
194
 
192
195
    if (fInputPort)
193
196
                 MIDIPortDispose(fInputPort);
194
 
         
195
 
    if (fOutputPort) 
 
197
 
 
198
    if (fOutputPort)
196
199
                MIDIPortDispose(fOutputPort);
197
 
    
 
200
 
198
201
    // Only dispose "virtual" endpoints
199
202
    for (int i = 0; i < fCaptureChannels - fRealCaptureChannels; i++)  {
200
 
        if (fMidiDestination)   
 
203
        if (fMidiDestination)
201
204
            MIDIEndpointDispose(fMidiDestination[i]);
202
205
    }
203
206
    delete[] fMidiDestination;
204
 
    
 
207
 
205
208
    // Only dispose "virtual" endpoints
206
209
    for (int i = 0; i < fPlaybackChannels - fRealPlaybackChannels; i++)  {
207
 
        if (fMidiSource[i]) 
 
210
        if (fMidiSource[i])
208
211
            MIDIEndpointDispose(fMidiSource[i]);
209
212
    }
210
213
    delete[] fMidiSource;
211
 
     
212
 
        if (fMidiClient) 
 
214
 
 
215
        if (fMidiClient)
213
216
        MIDIClientDispose(fMidiClient);
214
 
        
215
 
    return 0;
 
217
 
 
218
    return res;
216
219
}
217
220
 
218
221
int JackCoreMidiDriver::Attach()
229
232
    jack_log("JackCoreMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
230
233
 
231
234
    for (i = 0; i < fCaptureChannels; i++) {
232
 
    
 
235
 
233
236
        err = MIDIObjectGetStringProperty(fMidiDestination[i], kMIDIPropertyName, &pname);
234
237
        if (err == noErr) {
235
238
            CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0);
238
241
        } else {
239
242
            snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1);
240
243
        }
241
 
        
 
244
 
242
245
        snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1);
243
246
        if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
244
247
            jack_error("driver: cannot register port for %s", name);
251
254
    }
252
255
 
253
256
    for (i = 0; i < fPlaybackChannels; i++) {
254
 
        
 
257
 
255
258
        err = MIDIObjectGetStringProperty(fMidiSource[i], kMIDIPropertyName, &pname);
256
259
        if (err == noErr) {
257
260
            CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0);
260
263
        } else {
261
264
            snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1);
262
265
        }
263
 
        
 
266
 
264
267
        snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1);
265
268
        if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
266
269
            jack_error("driver: cannot register port for %s", name);
277
280
int JackCoreMidiDriver::Read()
278
281
{
279
282
    for (int chan = 0; chan < fCaptureChannels; chan++)  {
280
 
    
 
283
 
281
284
        if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) {
282
 
        
 
285
 
283
286
            // Get JACK port
284
287
            JackMidiBuffer* midi_buffer = GetInputBuffer(chan);
285
 
   
 
288
 
286
289
            if (jack_ringbuffer_read_space(fRingBuffer[chan]) == 0) {
287
290
                // Reset buffer
288
291
                midi_buffer->Reset(midi_buffer->nframes);
289
292
            } else {
290
 
        
 
293
 
291
294
                while (jack_ringbuffer_read_space(fRingBuffer[chan]) > 0) {
292
 
            
 
295
 
293
296
                    // Read event number
294
297
                    int ev_count = 0;
295
298
                    jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int));
296
 
                
 
299
 
297
300
                    for (int j = 0; j < ev_count; j++)  {
298
301
                        // Read event length
299
302
                        UInt16 event_len;
304
307
                    }
305
308
                }
306
309
            }
307
 
            
 
310
 
308
311
        } else {
309
312
            // Consume ring buffer
310
313
            jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan]));
316
319
int JackCoreMidiDriver::Write()
317
320
{
318
321
    MIDIPacketList* pktlist = (MIDIPacketList*)fMIDIBuffer;
319
 
     
 
322
 
320
323
    for (int chan = 0; chan < fPlaybackChannels; chan++)  {
321
 
    
 
324
 
322
325
         if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chan]) > 0) {
323
 
        
 
326
 
324
327
            MIDIPacket* packet = MIDIPacketListInit(pktlist);
325
328
            JackMidiBuffer* midi_buffer = GetOutputBuffer(chan);
326
 
            
 
329
 
327
330
            // TODO : use timestamp
328
 
            
 
331
 
329
332
            for (unsigned int j = 0; j < midi_buffer->event_count; j++) {
330
333
                JackMidiEvent* ev = &midi_buffer->events[j];
331
334
                packet = MIDIPacketListAdd(pktlist, sizeof(fMIDIBuffer), packet, MIDIGetCurrentHostTime(), ev->size, ev->GetData(midi_buffer));
332
335
            }
333
 
           
 
336
 
334
337
            if (packet) {
335
338
                if (chan < fPlaybackChannels - fRealPlaybackChannels) {
336
339
                    OSStatus err = MIDIReceived(fMidiSource[chan], pktlist);
337
 
                    if (err != noErr) 
 
340
                    if (err != noErr)
338
341
                        jack_error("MIDIReceived error");
339
342
                } else {
340
343
                    OSStatus err = MIDISend(fOutputPort, fMidiSource[chan], pktlist);
341
 
                    if (err != noErr) 
 
344
                    if (err != noErr)
342
345
                        jack_error("MIDISend error");
343
346
                }
344
347
            }
345
348
        }
346
349
    }
347
 
    
 
350
 
348
351
    return 0;
349
352
}
350
353
 
355
358
{
356
359
#endif
357
360
 
358
 
    SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() 
 
361
    SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
359
362
    {
360
363
        jack_driver_desc_t * desc;
361
364
        unsigned int i;
366
369
 
367
370
        desc->nparams = 2;
368
371
        desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
369
 
        
 
372
 
370
373
        i = 0;
371
374
        strcpy(desc->params[i].name, "inchannels");
372
375
        desc->params[i].character = 'i';
386
389
        return desc;
387
390
    }
388
391
 
389
 
    SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) 
 
392
    SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
390
393
    {
391
394
        const JSList * node;
392
395
        const jack_driver_param_t * param;
407
410
                    break;
408
411
                }
409
412
        }
410
 
      
 
413
 
411
414
        Jack::JackDriverClientInterface* driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table);
412
415
        if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) {
413
416
            return driver;