JackCoreMidiDriver.cpp 24.2 KB
Newer Older
1
2
/*
Copyright (C) 2009 Grame
3
Copyright (C) 2011 Devin Anderson
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

21
22
23
24
#include <stdexcept>

#include <mach/mach_time.h>

25
#include "JackCoreMidiDriver.h"
26
#include "JackCoreMidiUtil.h"
27
#include "JackEngineControl.h"
28

29
using Jack::JackCoreMidiDriver;
30

31
32
33
///////////////////////////////////////////////////////////////////////////////
// Static callbacks
///////////////////////////////////////////////////////////////////////////////
34

35
36
37
void
JackCoreMidiDriver::HandleInputEvent(const MIDIPacketList *packet_list,
                                     void *driver, void *port)
38
{
39
40
    ((JackCoreMidiPhysicalInputPort *) port)->ProcessCoreMidi(packet_list);
}
41

42
43
44
void
JackCoreMidiDriver::HandleNotificationEvent(const MIDINotification *message,
                                            void *driver)
45
{
46
    ((JackCoreMidiDriver *) driver)->HandleNotification(message);
47
48
}

49
50
51
52
53
54
55
56
///////////////////////////////////////////////////////////////////////////////
// Class
///////////////////////////////////////////////////////////////////////////////

JackCoreMidiDriver::JackCoreMidiDriver(const char *name, const char *alias,
                                       JackLockedEngine *engine,
                                       JackSynchro *table):
    JackMidiDriver(name, alias, engine, table)
57
{
58
59
60
61
    mach_timebase_info_data_t info;
    kern_return_t result = mach_timebase_info(&info);
    if (result != KERN_SUCCESS) {
        throw std::runtime_error(mach_error_string(result));
62
    }
63
64
65
66
67
68
69
70
71
72
73
74
75
    client = 0;
    fCaptureChannels = 0;
    fPlaybackChannels = 0;
    num_physical_inputs = 0;
    num_physical_outputs = 0;
    num_virtual_inputs = 0;
    num_virtual_outputs = 0;
    physical_input_ports = 0;
    physical_output_ports = 0;
    time_ratio = (((double) info.numer) / info.denom) / 1000.0;
    virtual_input_ports = 0;
    virtual_output_ports = 0;
}
76

77
JackCoreMidiDriver::~JackCoreMidiDriver()
sletz's avatar
sletz committed
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
int
JackCoreMidiDriver::Attach()
{
    jack_nframes_t buffer_size = fEngineControl->fBufferSize;
    jack_port_id_t index;
    jack_nframes_t latency = buffer_size;
    jack_latency_range_t latency_range;
    const char *name;
    JackPort *port;
    JackCoreMidiPort *port_obj;
    latency_range.max = latency;
    latency_range.min = latency;

    // Physical inputs
    for (int i = 0; i < num_physical_inputs; i++) {
        port_obj = physical_input_ports[i];
        name = port_obj->GetName();
        index = fGraphManager->AllocatePort(fClientControl.fRefNum, name,
                                            JACK_DEFAULT_MIDI_TYPE,
                                            CaptureDriverFlags, buffer_size);
        if (index == NO_PORT) {
            jack_error("JackCoreMidiDriver::Attach - cannot register physical "
                       "input port with name '%s'.", name);
            // X: Do we need to deallocate ports?
            return -1;
        }
        port = fGraphManager->GetPort(index);
        port->SetAlias(port_obj->GetAlias());
        port->SetLatencyRange(JackCaptureLatency, &latency_range);
        fCapturePortList[i] = index;
    }
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
    // Virtual inputs
    for (int i = 0; i < num_virtual_inputs; i++) {
        port_obj = virtual_input_ports[i];
        name = port_obj->GetName();
        index = fGraphManager->AllocatePort(fClientControl.fRefNum, name,
                                            JACK_DEFAULT_MIDI_TYPE,
                                            CaptureDriverFlags, buffer_size);
        if (index == NO_PORT) {
            jack_error("JackCoreMidiDriver::Attach - cannot register virtual "
                       "input port with name '%s'.", name);
            // X: Do we need to deallocate ports?
            return -1;
        }
        port = fGraphManager->GetPort(index);
        port->SetAlias(port_obj->GetAlias());
        port->SetLatencyRange(JackCaptureLatency, &latency_range);
        fCapturePortList[num_physical_inputs + i] = index;
    }
130

131
132
133
134
135
    if (! fEngineControl->fSyncMode) {
        latency += buffer_size;
        latency_range.max = latency;
        latency_range.min = latency;
    }
136

137
138
139
140
141
142
143
144
145
146
147
148
    // Physical outputs
    for (int i = 0; i < num_physical_outputs; i++) {
        port_obj = physical_output_ports[i];
        name = port_obj->GetName();
        index = fGraphManager->AllocatePort(fClientControl.fRefNum, name,
                                            JACK_DEFAULT_MIDI_TYPE,
                                            PlaybackDriverFlags, buffer_size);
        if (index == NO_PORT) {
            jack_error("JackCoreMidiDriver::Attach - cannot register physical "
                       "output port with name '%s'.", name);
            // X: Do we need to deallocate ports?
            return -1;
149
        }
150
151
152
153
154
        port = fGraphManager->GetPort(index);
        port->SetAlias(port_obj->GetAlias());
        port->SetLatencyRange(JackPlaybackLatency, &latency_range);
        fPlaybackPortList[i] = index;
    }
155

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
    // Virtual outputs
    for (int i = 0; i < num_virtual_outputs; i++) {
        port_obj = virtual_output_ports[i];
        name = port_obj->GetName();
        index = fGraphManager->AllocatePort(fClientControl.fRefNum, name,
                                            JACK_DEFAULT_MIDI_TYPE,
                                            PlaybackDriverFlags, buffer_size);
        if (index == NO_PORT) {
            jack_error("JackCoreMidiDriver::Attach - cannot register virtual "
                       "output port with name '%s'.", name);
            // X: Do we need to deallocate ports?
            return -1;
        }
        port = fGraphManager->GetPort(index);
        port->SetAlias(port_obj->GetAlias());
        port->SetLatencyRange(JackPlaybackLatency, &latency_range);
        fPlaybackPortList[num_physical_outputs + i] = index;
173
174
    }

175
    return 0;
176
177
}

178
179
int
JackCoreMidiDriver::Close()
180
{
sletz's avatar
sletz committed
181
182
183
    // Generic MIDI driver close
    int result = JackMidiDriver::Close();

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
    OSStatus status;
    if (physical_input_ports) {
        for (int i = 0; i < num_physical_inputs; i++) {
            delete physical_input_ports[i];
        }
        delete[] physical_input_ports;
        num_physical_inputs = 0;
        physical_input_ports = 0;
        status = MIDIPortDispose(internal_input);
        if (status != noErr) {
            WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose",
                            status);
            result = -1;
        }
    }
    if (physical_output_ports) {
        for (int i = 0; i < num_physical_outputs; i++) {
            delete physical_output_ports[i];
        }
        delete[] physical_output_ports;
        num_physical_outputs = 0;
        physical_output_ports = 0;
        status = MIDIPortDispose(internal_output);
        if (status != noErr) {
            WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose",
                            status);
            result = -1;
        }
    }
    if (virtual_input_ports) {
        for (int i = 0; i < num_virtual_inputs; i++) {
            delete virtual_input_ports[i];
        }
        delete[] virtual_input_ports;
        num_virtual_inputs = 0;
        virtual_input_ports = 0;
    }
    if (virtual_output_ports) {
        for (int i = 0; i < num_virtual_outputs; i++) {
            delete virtual_output_ports[i];
        }
        delete[] virtual_output_ports;
        num_virtual_outputs = 0;
        virtual_output_ports = 0;
    }
    if (client) {
        status = MIDIClientDispose(client);
        if (status != noErr) {
            WriteMacOSError("JackCoreMidiDriver::Close", "MIDIClientDispose",
                            status);
            result = -1;
        }
        client = 0;
    }
    return result;
239
240
}

241
242
void
JackCoreMidiDriver::HandleNotification(const MIDINotification *message)
243
{
244
    // Empty
245
246
}

247
248
249
250
251
252
253
254
255
256
257
258
int
JackCoreMidiDriver::Open(bool capturing, bool playing, int in_channels,
                         int out_channels, bool monitor,
                         const char* capture_driver_name,
                         const char* playback_driver_name,
                         jack_nframes_t capture_latency,
                         jack_nframes_t playback_latency)
{
    int pi_count = 0;
    int po_count = 0;
    int vi_count = 0;
    int vo_count = 0;
259
260
261
    ItemCount potential_po_count;
    ItemCount potential_pi_count;

262
263
264
265
266
    CFStringRef name = CFStringCreateWithCString(0, "JackMidi",
                                                 CFStringGetSystemEncoding());
    if (! name) {
        jack_error("JackCoreMidiDriver::Open - failed to allocate memory for "
                   "client name string");
267
        return -1;
268
    }
269

270
271
    OSStatus status = MIDIClientCreate(name, HandleNotificationEvent, this,
                                       &client);
272

273
274
275
276
277
278
279
280
281
    CFRelease(name);
    if (status != noErr) {
        WriteMacOSError("JackCoreMidiDriver::Close", "MIDIClientCreate",
                        status);
        return -1;
    }
    char *client_name = fClientControl.fName;

    // Allocate and connect physical inputs
282
    potential_pi_count = MIDIGetNumberOfSources();
283
284
285
286
287
288
289
290
291
292
    if (potential_pi_count) {
        status = MIDIInputPortCreate(client, CFSTR("Physical Input Port"),
                                     HandleInputEvent, this, &internal_input);
        if (status != noErr) {
            WriteMacOSError("JackCoreMidiDriver::Open", "MIDIInputPortCreate",
                            status);
            goto destroy_virtual_output_ports;
        }
        try {
            physical_input_ports =
293
                new JackCoreMidiPhysicalInputPort*[potential_pi_count];
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
        } catch (std::exception e) {
            jack_error("JackCoreMidiDriver::Open - while creating physical "
                       "input port array: %s", e.what());
            goto destroy_internal_input_port;
        }
        for (ItemCount i = 0; i < potential_pi_count; i++) {
            try {
                physical_input_ports[pi_count] =
                    new JackCoreMidiPhysicalInputPort(fAliasName, client_name,
                                                      capture_driver_name, i,
                                                      client, internal_input,
                                                      time_ratio);
            } catch (std::exception e) {
                jack_error("JackCoreMidiDriver::Open - while creating "
                           "physical input port: %s", e.what());
Stephane Letz's avatar
Stephane Letz committed
309
                goto destroy_internal_input_port;
310
311
            }
            pi_count++;
312
313
        }
    }
314

315
    // Allocate and connect physical outputs
316
    potential_po_count = MIDIGetNumberOfDestinations();
317
318
319
320
321
322
323
324
325
326
    if (potential_po_count) {
        status = MIDIOutputPortCreate(client, CFSTR("Physical Output Port"),
                                      &internal_output);
        if (status != noErr) {
            WriteMacOSError("JackCoreMidiDriver::Open", "MIDIOutputPortCreate",
                            status);
            goto destroy_physical_input_ports;
        }
        try {
            physical_output_ports =
327
                new JackCoreMidiPhysicalOutputPort*[potential_po_count];
328
329
330
331
332
333
334
335
336
337
338
        } catch (std::exception e) {
            jack_error("JackCoreMidiDriver::Open - while creating physical "
                       "output port array: %s", e.what());
            goto destroy_internal_output_port;
        }
        for (ItemCount i = 0; i < potential_po_count; i++) {
            try {
                physical_output_ports[po_count] =
                    new JackCoreMidiPhysicalOutputPort(fAliasName, client_name,
                                                       playback_driver_name, i,
                                                       client, internal_output,
339
                                                       time_ratio);
340
341
342
            } catch (std::exception e) {
                jack_error("JackCoreMidiDriver::Open - while creating "
                           "physical output port: %s", e.what());
Stephane Letz's avatar
Stephane Letz committed
343
                goto destroy_internal_output_port;
344
345
346
            }
            po_count++;
        }
347
    }
348

349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
    // Allocate and connect virtual inputs
    if (in_channels) {
        try {
            virtual_input_ports =
                new JackCoreMidiVirtualInputPort*[in_channels];
        } catch (std::exception e) {
            jack_error("JackCoreMidiDriver::Open - while creating virtual "
                       "input port array: %s", e.what());
            goto destroy_client;
        }
        for (vi_count = 0; vi_count < in_channels; vi_count++) {
            try {
                virtual_input_ports[vi_count] =
                    new JackCoreMidiVirtualInputPort(fAliasName, client_name,
                                                     capture_driver_name,
                                                     vi_count + pi_count, client,
                                                     time_ratio);
            } catch (std::exception e) {
                jack_error("JackCoreMidiDriver::Open - while creating virtual "
                           "input port: %s", e.what());
                goto destroy_virtual_input_ports;
            }
        }
    }

    // Allocate and connect virtual outputs
    if (out_channels) {
        try {
            virtual_output_ports =
                new JackCoreMidiVirtualOutputPort*[out_channels];
        } catch (std::exception e) {
            jack_error("JackCoreMidiDriver::Open - while creating virtual "
                       "output port array: %s", e.what());
            goto destroy_virtual_input_ports;
        }
        for (vo_count = 0; vo_count < out_channels; vo_count++) {
            try {
                virtual_output_ports[vo_count] =
                    new JackCoreMidiVirtualOutputPort(fAliasName, client_name,
                                                      playback_driver_name,
                                                      vo_count + po_count, client,
                                                      time_ratio);
            } catch (std::exception e) {
                jack_error("JackCoreMidiDriver::Open - while creating virtual "
                           "output port: %s", e.what());
                goto destroy_virtual_output_ports;
            }
        }
    }


400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
    if (! (pi_count || po_count || in_channels || out_channels)) {
        jack_error("JackCoreMidiDriver::Open - no CoreMIDI inputs or outputs "
                   "found, and no virtual ports allocated.");
    } else if (! JackMidiDriver::Open(capturing, playing,
                                      in_channels + pi_count,
                                      out_channels + po_count, monitor,
                                      capture_driver_name,
                                      playback_driver_name, capture_latency,
                                      playback_latency)) {
        num_physical_inputs = pi_count;
        num_physical_outputs = po_count;
        num_virtual_inputs = in_channels;
        num_virtual_outputs = out_channels;
        return 0;
    }
415

416
417
418
419
    // Cleanup
    if (physical_output_ports) {
        for (int i = 0; i < po_count; i++) {
            delete physical_output_ports[i];
420
        }
421
422
        delete[] physical_output_ports;
        physical_output_ports = 0;
423
    }
424
425
426
427
 destroy_internal_output_port:
    status = MIDIPortDispose(internal_output);
    if (status != noErr) {
        WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status);
428
    }
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
 destroy_physical_input_ports:
    if (physical_input_ports) {
        for (int i = 0; i < pi_count; i++) {
            delete physical_input_ports[i];
        }
        delete[] physical_input_ports;
        physical_input_ports = 0;
    }
 destroy_internal_input_port:
    status = MIDIPortDispose(internal_input);
    if (status != noErr) {
        WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status);
    }
 destroy_virtual_output_ports:
    if (virtual_output_ports) {
        for (int i = 0; i < vo_count; i++) {
            delete virtual_output_ports[i];
        }
        delete[] virtual_output_ports;
        virtual_output_ports = 0;
    }
 destroy_virtual_input_ports:
    if (virtual_input_ports) {
        for (int i = 0; i < vi_count; i++) {
            delete virtual_input_ports[i];
        }
        delete[] virtual_input_ports;
        virtual_input_ports = 0;
    }
 destroy_client:
    status = MIDIClientDispose(client);
    if (status != noErr) {
        WriteMacOSError("JackCoreMidiDriver::Open", "MIDIClientDispose",
                        status);
    }
    client = 0;
    return -1;
}
467

468
469
470
471
472
473
474
475
476
477
478
int
JackCoreMidiDriver::Read()
{
    jack_nframes_t buffer_size = fEngineControl->fBufferSize;
    for (int i = 0; i < num_physical_inputs; i++) {
        physical_input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size);
    }
    for (int i = 0; i < num_virtual_inputs; i++) {
        virtual_input_ports[i]->
            ProcessJack(GetInputBuffer(num_physical_inputs + i), buffer_size);
    }
479
480
    return 0;
}
481

482
483
int
JackCoreMidiDriver::Start()
484
{
485
    jack_info("JackCoreMidiDriver::Start - Starting driver.");
486

487
    JackMidiDriver::Start();
488

489
490
491
492
    int pi_count = 0;
    int po_count = 0;
    int vi_count = 0;
    int vo_count = 0;
493

494
    jack_info("JackCoreMidiDriver::Start - Enabling physical input ports.");
495

496
497
498
499
500
501
    for (; pi_count < num_physical_inputs; pi_count++) {
        if (physical_input_ports[pi_count]->Start() < 0) {
            jack_error("JackCoreMidiDriver::Start - Failed to enable physical "
                       "input port.");
            goto stop_physical_input_ports;
        }
502
    }
503

504
    jack_info("JackCoreMidiDriver::Start - Enabling physical output ports.");
505

506
507
508
509
510
    for (; po_count < num_physical_outputs; po_count++) {
        if (physical_output_ports[po_count]->Start() < 0) {
            jack_error("JackCoreMidiDriver::Start - Failed to enable physical "
                       "output port.");
            goto stop_physical_output_ports;
511
512
513
        }
    }

514
    jack_info("JackCoreMidiDriver::Start - Enabling virtual input ports.");
515

516
517
518
519
520
    for (; vi_count < num_virtual_inputs; vi_count++) {
        if (virtual_input_ports[vi_count]->Start() < 0) {
            jack_error("JackCoreMidiDriver::Start - Failed to enable virtual "
                       "input port.");
            goto stop_virtual_input_ports;
521
        }
522
    }
523

524
525
526
527
528
529
530
    jack_info("JackCoreMidiDriver::Start - Enabling virtual output ports.");

    for (; vo_count < num_virtual_outputs; vo_count++) {
        if (virtual_output_ports[vo_count]->Start() < 0) {
            jack_error("JackCoreMidiDriver::Start - Failed to enable virtual "
                       "output port.");
            goto stop_virtual_output_ports;
531
532
533
        }
    }

534
    jack_info("JackCoreMidiDriver::Start - Driver started.");
535

536
    return 0;
537

538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
 stop_virtual_output_ports:
    for (int i = 0; i < vo_count; i++) {
        if (virtual_output_ports[i]->Stop() < 0) {
            jack_error("JackCoreMidiDriver::Start - Failed to disable virtual "
                       "output port.");
        }
    }
 stop_virtual_input_ports:
    for (int i = 0; i < vi_count; i++) {
        if (virtual_input_ports[i]->Stop() < 0) {
            jack_error("JackCoreMidiDriver::Start - Failed to disable virtual "
                       "input port.");
        }
    }
 stop_physical_output_ports:
    for (int i = 0; i < po_count; i++) {
        if (physical_output_ports[i]->Stop() < 0) {
            jack_error("JackCoreMidiDriver::Start - Failed to disable "
                       "physical output port.");
        }
    }
 stop_physical_input_ports:
    for (int i = 0; i < pi_count; i++) {
        if (physical_input_ports[i]->Stop() < 0) {
            jack_error("JackCoreMidiDriver::Start - Failed to disable "
                       "physical input port.");
        }
    }
566

567
568
    return -1;
}
569

570
571
572
573
int
JackCoreMidiDriver::Stop()
{
    int result = 0;
574

575
    jack_info("JackCoreMidiDriver::Stop - disabling physical input ports.");
576

577
578
579
580
581
    for (int i = 0; i < num_physical_inputs; i++) {
        if (physical_input_ports[i]->Stop() < 0) {
            jack_error("JackCoreMidiDriver::Stop - Failed to disable physical "
                       "input port.");
            result = -1;
582
583
        }
    }
584

585
    jack_info("JackCoreMidiDriver::Stop - disabling physical output ports.");
586

587
588
589
590
591
592
593
    for (int i = 0; i < num_physical_outputs; i++) {
        if (physical_output_ports[i]->Stop() < 0) {
            jack_error("JackCoreMidiDriver::Stop - Failed to disable physical "
                       "output port.");
            result = -1;
        }
    }
594

595
    jack_info("JackCoreMidiDriver::Stop - disabling virtual input ports.");
596

597
598
599
600
601
602
603
    for (int i = 0; i < num_virtual_inputs; i++) {
        if (virtual_input_ports[i]->Stop() < 0) {
            jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual "
                       "input port.");
            result = -1;
        }
    }
604

605
    jack_info("JackCoreMidiDriver::Stop - disabling virtual output ports.");
606

607
608
609
610
611
    for (int i = 0; i < num_virtual_outputs; i++) {
        if (virtual_output_ports[i]->Stop() < 0) {
            jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual "
                       "output port.");
            result = -1;
612
613
        }
    }
614

615
    return result;
616
617
}

618
619
620
621
622
623
624
625
626
627
628
629
630
631
int
JackCoreMidiDriver::Write()
{
    jack_nframes_t buffer_size = fEngineControl->fBufferSize;
    for (int i = 0; i < num_physical_outputs; i++) {
        physical_output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size);
    }
    for (int i = 0; i < num_virtual_outputs; i++) {
        virtual_output_ports[i]->
            ProcessJack(GetOutputBuffer(num_physical_outputs + i),
                        buffer_size);
    }
    return 0;
}
632

633
#ifdef __cplusplus
634
extern "C" {
635
636
#endif

637
    SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
638
639
640
641
642
643
644
645
646
647
    {
        jack_driver_desc_t * desc;
        unsigned int i;

        desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
        strcpy(desc->name, "coremidi");                                     // size MUST be less then JACK_DRIVER_NAME_MAX + 1
        strcpy(desc->desc, "Apple CoreMIDI API based MIDI backend");      // size MUST be less then JACK_DRIVER_PARAM_DESC + 1

        desc->nparams = 2;
        desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
648

649
650
651
        i = 0;
        strcpy(desc->params[i].name, "inchannels");
        desc->params[i].character = 'i';
sletz's avatar
sletz committed
652
        desc->params[i].type = JackDriverParamUInt;
653
654
655
656
657
658
659
        desc->params[i].value.ui = 0;
        strcpy(desc->params[i].short_desc, "CoreMIDI virtual bus");
        strcpy(desc->params[i].long_desc, desc->params[i].short_desc);

        i++;
        strcpy(desc->params[i].name, "outchannels");
        desc->params[i].character = 'o';
sletz's avatar
sletz committed
660
        desc->params[i].type = JackDriverParamUInt;
661
662
663
664
665
666
667
        desc->params[i].value.ui = 0;
        strcpy(desc->params[i].short_desc, "CoreMIDI virtual bus");
        strcpy(desc->params[i].long_desc, desc->params[i].short_desc);

        return desc;
    }

668
    SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
    {
        const JSList * node;
        const jack_driver_param_t * param;
        int virtual_in = 0;
        int virtual_out = 0;

        for (node = params; node; node = jack_slist_next (node)) {
            param = (const jack_driver_param_t *) node->data;

            switch (param->character) {

                case 'i':
                    virtual_in = param->value.ui;
                    break;

                case 'o':
                    virtual_out = param->value.ui;
                    break;
                }
        }
689

690
691
692
693
694
695
696
697
698
699
700
701
        Jack::JackDriverClientInterface* driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table);
        if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) {
            return driver;
        } else {
            delete driver;
            return NULL;
        }
    }

#ifdef __cplusplus
}
#endif