Jack2  1.9.9
JackCoreMidiDriver.cpp
1 /*
2 Copyright (C) 2009 Grame
3 Copyright (C) 2011 Devin Anderson
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 
19 */
20 
21 #include "JackCompilerDeps.h"
22 #include "JackCoreMidiDriver.h"
23 #include "JackCoreMidiUtil.h"
24 #include "JackEngineControl.h"
25 #include "driver_interface.h"
26 
27 #include <stdexcept>
28 #include <mach/mach_time.h>
29 
31 
32 static char capture_driver_name[256];
33 static char playback_driver_name[256];
34 
35 static int in_channels, out_channels;
36 static bool capturing, playing, monitor;
37 
38 static jack_nframes_t capture_latency, playback_latency;
39 
41 // Static callbacks
43 
44 void
45 JackCoreMidiDriver::HandleInputEvent(const MIDIPacketList *packet_list,
46  void *driver, void *port)
47 {
48  ((JackCoreMidiPhysicalInputPort *) port)->ProcessCoreMidi(packet_list);
49 }
50 
51 void
52 JackCoreMidiDriver::HandleNotificationEvent(const MIDINotification *message,
53  void *driver)
54 {
55  ((JackCoreMidiDriver *) driver)->HandleNotification(message);
56 }
57 
59 // Class
61 
62 JackCoreMidiDriver::JackCoreMidiDriver(const char *name, const char *alias,
63  JackLockedEngine *engine,
64  JackSynchro *table):
65  JackMidiDriver(name, alias, engine, table),fThread(this)
66 {
67  mach_timebase_info_data_t info;
68  kern_return_t result = mach_timebase_info(&info);
69  if (result != KERN_SUCCESS) {
70  throw std::runtime_error(mach_error_string(result));
71  }
72  client = 0;
73  fCaptureChannels = 0;
74  fPlaybackChannels = 0;
75  num_physical_inputs = 0;
76  num_physical_outputs = 0;
77  num_virtual_inputs = 0;
78  num_virtual_outputs = 0;
79  physical_input_ports = 0;
80  physical_output_ports = 0;
81  time_ratio = (((double) info.numer) / info.denom) / 1000.0;
82  virtual_input_ports = 0;
83  virtual_output_ports = 0;
84  internal_input = 0;
85  internal_output = 0;
86 }
87 
88 JackCoreMidiDriver::~JackCoreMidiDriver()
89 {}
90 
92 {
93  return OpenAux();
94 }
95 
96 bool JackCoreMidiDriver::OpenAux()
97 {
98  int pi_count = 0;
99  int po_count = 0;
100  int vi_count = 0;
101  int vo_count = 0;
102  ItemCount potential_po_count;
103  ItemCount potential_pi_count;
104 
105  CFStringRef name = CFStringCreateWithCString(0, "JackMidi",
106  CFStringGetSystemEncoding());
107  if (! name) {
108  jack_error("JackCoreMidiDriver::Open - failed to allocate memory for "
109  "client name string");
110  return false;
111  }
112 
113  OSStatus status = MIDIClientCreate(name, HandleNotificationEvent, this,
114  &client);
115 
116  CFRelease(name);
117 
118  if (status != noErr) {
119  WriteMacOSError("JackCoreMidiDriver::Open", "MIDIClientCreate",
120  status);
121  return false;
122  }
123 
124  char *client_name = fClientControl.fName;
125 
126  // Allocate and connect physical inputs
127  potential_pi_count = MIDIGetNumberOfSources();
128  if (potential_pi_count) {
129  status = MIDIInputPortCreate(client, CFSTR("Physical Input Port"),
130  HandleInputEvent, this, &internal_input);
131  if (status != noErr) {
132  WriteMacOSError("JackCoreMidiDriver::Open", "MIDIInputPortCreate",
133  status);
134  goto destroy;
135  }
136 
137  try {
138  physical_input_ports =
139  new JackCoreMidiPhysicalInputPort*[potential_pi_count];
140  } catch (std::exception e) {
141  jack_error("JackCoreMidiDriver::Open - while creating physical "
142  "input port array: %s", e.what());
143  goto destroy;
144  }
145 
146  for (ItemCount i = 0; i < potential_pi_count; i++) {
147  try {
148  physical_input_ports[pi_count] =
149  new JackCoreMidiPhysicalInputPort(fAliasName, client_name,
150  capture_driver_name, i,
151  client, internal_input,
152  time_ratio);
153  } catch (std::exception e) {
154  jack_error("JackCoreMidiDriver::Open - while creating "
155  "physical input port: %s", e.what());
156  goto destroy;
157  }
158  pi_count++;
159  }
160  }
161 
162  // Allocate and connect physical outputs
163  potential_po_count = MIDIGetNumberOfDestinations();
164  if (potential_po_count) {
165  status = MIDIOutputPortCreate(client, CFSTR("Physical Output Port"),
166  &internal_output);
167  if (status != noErr) {
168  WriteMacOSError("JackCoreMidiDriver::Open", "MIDIOutputPortCreate",
169  status);
170  goto destroy;
171  }
172 
173  try {
174  physical_output_ports =
175  new JackCoreMidiPhysicalOutputPort*[potential_po_count];
176  } catch (std::exception e) {
177  jack_error("JackCoreMidiDriver::Open - while creating physical "
178  "output port array: %s", e.what());
179  goto destroy;
180  }
181 
182  for (ItemCount i = 0; i < potential_po_count; i++) {
183  try {
184  physical_output_ports[po_count] =
185  new JackCoreMidiPhysicalOutputPort(fAliasName, client_name,
186  playback_driver_name, i,
187  client, internal_output,
188  time_ratio);
189  } catch (std::exception e) {
190  jack_error("JackCoreMidiDriver::Open - while creating "
191  "physical output port: %s", e.what());
192  goto destroy;
193  }
194  po_count++;
195  }
196  }
197 
198  // Allocate and connect virtual inputs
199  if (in_channels) {
200  try {
201  virtual_input_ports =
202  new JackCoreMidiVirtualInputPort*[in_channels];
203  } catch (std::exception e) {
204  jack_error("JackCoreMidiDriver::Open - while creating virtual "
205  "input port array: %s", e.what());
206  goto destroy;
207 
208  }
209  for (vi_count = 0; vi_count < in_channels; vi_count++) {
210  try {
211  virtual_input_ports[vi_count] =
212  new JackCoreMidiVirtualInputPort(fAliasName, client_name,
213  capture_driver_name,
214  vi_count + pi_count, client,
215  time_ratio);
216  } catch (std::exception e) {
217  jack_error("JackCoreMidiDriver::Open - while creating virtual "
218  "input port: %s", e.what());
219  goto destroy;
220  }
221  }
222  }
223 
224  // Allocate and connect virtual outputs
225  if (out_channels) {
226  try {
227  virtual_output_ports =
228  new JackCoreMidiVirtualOutputPort*[out_channels];
229  } catch (std::exception e) {
230  jack_error("JackCoreMidiDriver::Open - while creating virtual "
231  "output port array: %s", e.what());
232  goto destroy;
233  }
234  for (vo_count = 0; vo_count < out_channels; vo_count++) {
235  try {
236  virtual_output_ports[vo_count] =
237  new JackCoreMidiVirtualOutputPort(fAliasName, client_name,
238  playback_driver_name,
239  vo_count + po_count, client,
240  time_ratio);
241  } catch (std::exception e) {
242  jack_error("JackCoreMidiDriver::Open - while creating virtual "
243  "output port: %s", e.what());
244  goto destroy;
245  }
246  }
247  }
248 
249 
250  if (! (pi_count || po_count || in_channels || out_channels)) {
251  jack_error("JackCoreMidiDriver::Open - no CoreMIDI inputs or outputs "
252  "found, and no virtual ports allocated.");
253  }
254 
255  if (! JackMidiDriver::Open(capturing, playing,
256  in_channels + pi_count,
257  out_channels + po_count, monitor,
258  capture_driver_name,
259  playback_driver_name, capture_latency,
260  playback_latency)) {
261  num_physical_inputs = pi_count;
262  num_physical_outputs = po_count;
263  num_virtual_inputs = in_channels;
264  num_virtual_outputs = out_channels;
265  return true;
266  }
267 
268  destroy:
269 
270  if (physical_input_ports) {
271  for (int i = 0; i < pi_count; i++) {
272  delete physical_input_ports[i];
273  }
274  delete[] physical_input_ports;
275  physical_input_ports = 0;
276  }
277 
278  if (physical_output_ports) {
279  for (int i = 0; i < po_count; i++) {
280  delete physical_output_ports[i];
281  }
282  delete[] physical_output_ports;
283  physical_output_ports = 0;
284  }
285 
286  if (virtual_input_ports) {
287  for (int i = 0; i < vi_count; i++) {
288  delete virtual_input_ports[i];
289  }
290  delete[] virtual_input_ports;
291  virtual_input_ports = 0;
292  }
293 
294  if (virtual_output_ports) {
295  for (int i = 0; i < vo_count; i++) {
296  delete virtual_output_ports[i];
297  }
298  delete[] virtual_output_ports;
299  virtual_output_ports = 0;
300  }
301 
302  if (internal_output) {
303  status = MIDIPortDispose(internal_output);
304  if (status != noErr) {
305  WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status);
306  }
307  }
308 
309  if (internal_input) {
310  status = MIDIPortDispose(internal_input);
311  if (status != noErr) {
312  WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status);
313  }
314  }
315 
316  if (client) {
317  status = MIDIClientDispose(client);
318  if (status != noErr) {
319  WriteMacOSError("JackCoreMidiDriver::Open", "MIDIClientDispose",
320  status);
321  }
322  }
323 
324  // Default open
325  if (! JackMidiDriver::Open(capturing, playing,
326  in_channels + pi_count,
327  out_channels + po_count, monitor,
328  capture_driver_name,
329  playback_driver_name, capture_latency,
330  playback_latency)) {
331  client = 0;
332  num_physical_inputs = 0;
333  num_physical_outputs = 0;
334  num_virtual_inputs = 0;
335  num_virtual_outputs = 0;
336  return true;
337  } else {
338  return false;
339  }
340 }
341 
342 bool JackCoreMidiDriver::Execute()
343 {
344  CFRunLoopRun();
345  return false;
346 }
347 
348 int
349 JackCoreMidiDriver::Attach()
350 {
351  jack_nframes_t buffer_size = fEngineControl->fBufferSize;
352  jack_port_id_t index;
353  jack_nframes_t latency = buffer_size;
354  jack_latency_range_t latency_range;
355  const char *name;
356  JackPort *port;
357  JackCoreMidiPort *port_obj;
358  latency_range.max = latency;
359  latency_range.min = latency;
360 
361  // Physical inputs
362  for (int i = 0; i < num_physical_inputs; i++) {
363  port_obj = physical_input_ports[i];
364  name = port_obj->GetName();
365  if (fEngine->PortRegister(fClientControl.fRefNum, name,
366  JACK_DEFAULT_MIDI_TYPE,
367  CaptureDriverFlags, buffer_size, &index) < 0) {
368  jack_error("JackCoreMidiDriver::Attach - cannot register physical "
369  "input port with name '%s'.", name);
370  // X: Do we need to deallocate ports?
371  return -1;
372  }
373  port = fGraphManager->GetPort(index);
374  port->SetAlias(port_obj->GetAlias());
375  port->SetLatencyRange(JackCaptureLatency, &latency_range);
376  fCapturePortList[i] = index;
377  }
378 
379  // Virtual inputs
380  for (int i = 0; i < num_virtual_inputs; i++) {
381  port_obj = virtual_input_ports[i];
382  name = port_obj->GetName();
383  if (fEngine->PortRegister(fClientControl.fRefNum, name,
384  JACK_DEFAULT_MIDI_TYPE,
385  CaptureDriverFlags, buffer_size, &index) < 0) {
386  jack_error("JackCoreMidiDriver::Attach - cannot register virtual "
387  "input port with name '%s'.", name);
388  // X: Do we need to deallocate ports?
389  return -1;
390  }
391  port = fGraphManager->GetPort(index);
392  port->SetAlias(port_obj->GetAlias());
393  port->SetLatencyRange(JackCaptureLatency, &latency_range);
394  fCapturePortList[num_physical_inputs + i] = index;
395  }
396 
397  if (! fEngineControl->fSyncMode) {
398  latency += buffer_size;
399  latency_range.max = latency;
400  latency_range.min = latency;
401  }
402 
403  // Physical outputs
404  for (int i = 0; i < num_physical_outputs; i++) {
405  port_obj = physical_output_ports[i];
406  name = port_obj->GetName();
407  fEngine->PortRegister(fClientControl.fRefNum, name,
408  JACK_DEFAULT_MIDI_TYPE,
409  PlaybackDriverFlags, buffer_size, &index);
410  if (index == NO_PORT) {
411  jack_error("JackCoreMidiDriver::Attach - cannot register physical "
412  "output port with name '%s'.", name);
413  // X: Do we need to deallocate ports?
414  return -1;
415  }
416  port = fGraphManager->GetPort(index);
417  port->SetAlias(port_obj->GetAlias());
418  port->SetLatencyRange(JackPlaybackLatency, &latency_range);
419  fPlaybackPortList[i] = index;
420  }
421 
422  // Virtual outputs
423  for (int i = 0; i < num_virtual_outputs; i++) {
424  port_obj = virtual_output_ports[i];
425  name = port_obj->GetName();
426  fEngine->PortRegister(fClientControl.fRefNum, name,
427  JACK_DEFAULT_MIDI_TYPE,
428  PlaybackDriverFlags, buffer_size, &index);
429  if (index == NO_PORT) {
430  jack_error("JackCoreMidiDriver::Attach - cannot register virtual "
431  "output port with name '%s'.", name);
432  // X: Do we need to deallocate ports?
433  return -1;
434  }
435  port = fGraphManager->GetPort(index);
436  port->SetAlias(port_obj->GetAlias());
437  port->SetLatencyRange(JackPlaybackLatency, &latency_range);
438  fPlaybackPortList[num_physical_outputs + i] = index;
439  }
440 
441  return 0;
442 }
443 
444 int
445 JackCoreMidiDriver::Close()
446 {
447  fThread.Kill();
448  return CloseAux();
449 }
450 
451 int
452 JackCoreMidiDriver::CloseAux()
453 {
454  // Generic MIDI driver close
455  int result = JackMidiDriver::Close();
456 
457  OSStatus status;
458  if (physical_input_ports) {
459  for (int i = 0; i < num_physical_inputs; i++) {
460  delete physical_input_ports[i];
461  }
462  delete[] physical_input_ports;
463  num_physical_inputs = 0;
464  physical_input_ports = 0;
465  if (internal_input) {
466  status = MIDIPortDispose(internal_input);
467  if (status != noErr) {
468  WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose",
469  status);
470  result = -1;
471  }
472  internal_input = 0;
473  }
474  }
475  if (physical_output_ports) {
476  for (int i = 0; i < num_physical_outputs; i++) {
477  delete physical_output_ports[i];
478  }
479  delete[] physical_output_ports;
480  num_physical_outputs = 0;
481  physical_output_ports = 0;
482  if (internal_output) {
483  status = MIDIPortDispose(internal_output);
484  if (status != noErr) {
485  WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose",
486  status);
487  result = -1;
488  }
489  internal_output = 0;
490  }
491  }
492  if (virtual_input_ports) {
493  for (int i = 0; i < num_virtual_inputs; i++) {
494  delete virtual_input_ports[i];
495  }
496  delete[] virtual_input_ports;
497  num_virtual_inputs = 0;
498  virtual_input_ports = 0;
499  }
500  if (virtual_output_ports) {
501  for (int i = 0; i < num_virtual_outputs; i++) {
502  delete virtual_output_ports[i];
503  }
504  delete[] virtual_output_ports;
505  num_virtual_outputs = 0;
506  virtual_output_ports = 0;
507  }
508 
509  if (client) {
510  status = MIDIClientDispose(client);
511  if (status != noErr) {
512  WriteMacOSError("JackCoreMidiDriver::Close", "MIDIClientDispose",
513  status);
514  result = -1;
515  }
516  client = 0;
517  }
518  return result;
519 }
520 
521 void
522 JackCoreMidiDriver::Restart()
523 {
524  JackLock lock(this);
525 
526  SaveConnections();
527  Stop();
528  Detach();
529  CloseAux();
530  OpenAux();
531  Attach();
532  Start();
533  RestoreConnections();
534 }
535 
536 void
537 JackCoreMidiDriver::HandleNotification(const MIDINotification *message)
538 {
539  switch (message->messageID) {
540 
541  case kMIDIMsgSetupChanged:
542  Restart();
543  break;
544 
545  case kMIDIMsgObjectAdded:
546  break;
547 
548  case kMIDIMsgObjectRemoved:
549  break;
550 
551  }
552 }
553 
554 int
555 JackCoreMidiDriver::Open(bool capturing_aux, bool playing_aux, int in_channels_aux,
556  int out_channels_aux, bool monitor_aux,
557  const char* capture_driver_name_aux,
558  const char* playback_driver_name_aux,
559  jack_nframes_t capture_latency_aux,
560  jack_nframes_t playback_latency_aux)
561 {
562 
563  strcpy(capture_driver_name, capture_driver_name_aux);
564  strcpy(playback_driver_name, playback_driver_name_aux);
565 
566  capturing = capturing_aux;
567  playing = playing_aux;
568  in_channels = in_channels_aux;
569  out_channels = out_channels_aux;
570  monitor = monitor_aux;
571  capture_latency = capture_latency_aux;
572  playback_latency = playback_latency_aux;
573 
574  fThread.StartSync();
575 
576  int count = 0;
577  while (fThread.GetStatus() != JackThread::kRunning && ++count < WAIT_COUNTER) {
578  JackSleep(100000);
579  jack_log("JackCoreMidiDriver::Open wait count = %d", count);
580 
581  }
582  if (count == WAIT_COUNTER) {
583  jack_info("Cannot open CoreMIDI driver");
584  fThread.Kill();
585  return -1;
586  } else {
587  JackSleep(10000);
588  jack_info("CoreMIDI driver is running...");
589  }
590 
591  return 0;
592 }
593 
594 int
595 JackCoreMidiDriver::Start()
596 {
597  jack_info("JackCoreMidiDriver::Start - Starting driver.");
598 
599  JackMidiDriver::Start();
600 
601  int pi_count = 0;
602  int po_count = 0;
603  int vi_count = 0;
604  int vo_count = 0;
605 
606  jack_info("JackCoreMidiDriver::Start - Enabling physical input ports.");
607 
608  for (; pi_count < num_physical_inputs; pi_count++) {
609  if (physical_input_ports[pi_count]->Start() < 0) {
610  jack_error("JackCoreMidiDriver::Start - Failed to enable physical "
611  "input port.");
612  goto stop_physical_input_ports;
613  }
614  }
615 
616  jack_info("JackCoreMidiDriver::Start - Enabling physical output ports.");
617 
618  for (; po_count < num_physical_outputs; po_count++) {
619  if (physical_output_ports[po_count]->Start() < 0) {
620  jack_error("JackCoreMidiDriver::Start - Failed to enable physical "
621  "output port.");
622  goto stop_physical_output_ports;
623  }
624  }
625 
626  jack_info("JackCoreMidiDriver::Start - Enabling virtual input ports.");
627 
628  for (; vi_count < num_virtual_inputs; vi_count++) {
629  if (virtual_input_ports[vi_count]->Start() < 0) {
630  jack_error("JackCoreMidiDriver::Start - Failed to enable virtual "
631  "input port.");
632  goto stop_virtual_input_ports;
633  }
634  }
635 
636  jack_info("JackCoreMidiDriver::Start - Enabling virtual output ports.");
637 
638  for (; vo_count < num_virtual_outputs; vo_count++) {
639  if (virtual_output_ports[vo_count]->Start() < 0) {
640  jack_error("JackCoreMidiDriver::Start - Failed to enable virtual "
641  "output port.");
642  goto stop_virtual_output_ports;
643  }
644  }
645 
646  jack_info("JackCoreMidiDriver::Start - Driver started.");
647 
648  return 0;
649 
650  stop_virtual_output_ports:
651  for (int i = 0; i < vo_count; i++) {
652  if (virtual_output_ports[i]->Stop() < 0) {
653  jack_error("JackCoreMidiDriver::Start - Failed to disable virtual "
654  "output port.");
655  }
656  }
657  stop_virtual_input_ports:
658  for (int i = 0; i < vi_count; i++) {
659  if (virtual_input_ports[i]->Stop() < 0) {
660  jack_error("JackCoreMidiDriver::Start - Failed to disable virtual "
661  "input port.");
662  }
663  }
664  stop_physical_output_ports:
665  for (int i = 0; i < po_count; i++) {
666  if (physical_output_ports[i]->Stop() < 0) {
667  jack_error("JackCoreMidiDriver::Start - Failed to disable "
668  "physical output port.");
669  }
670  }
671  stop_physical_input_ports:
672  for (int i = 0; i < pi_count; i++) {
673  if (physical_input_ports[i]->Stop() < 0) {
674  jack_error("JackCoreMidiDriver::Start - Failed to disable "
675  "physical input port.");
676  }
677  }
678 
679  return -1;
680 }
681 
682 int
683 JackCoreMidiDriver::Stop()
684 {
685  int result = 0;
686 
687  JackMidiDriver::Stop();
688 
689  jack_info("JackCoreMidiDriver::Stop - disabling physical input ports.");
690 
691  for (int i = 0; i < num_physical_inputs; i++) {
692  if (physical_input_ports[i]->Stop() < 0) {
693  jack_error("JackCoreMidiDriver::Stop - Failed to disable physical "
694  "input port.");
695  result = -1;
696  }
697  }
698 
699  jack_info("JackCoreMidiDriver::Stop - disabling physical output ports.");
700 
701  for (int i = 0; i < num_physical_outputs; i++) {
702  if (physical_output_ports[i]->Stop() < 0) {
703  jack_error("JackCoreMidiDriver::Stop - Failed to disable physical "
704  "output port.");
705  result = -1;
706  }
707  }
708 
709  jack_info("JackCoreMidiDriver::Stop - disabling virtual input ports.");
710 
711  for (int i = 0; i < num_virtual_inputs; i++) {
712  if (virtual_input_ports[i]->Stop() < 0) {
713  jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual "
714  "input port.");
715  result = -1;
716  }
717  }
718 
719  jack_info("JackCoreMidiDriver::Stop - disabling virtual output ports.");
720 
721  for (int i = 0; i < num_virtual_outputs; i++) {
722  if (virtual_output_ports[i]->Stop() < 0) {
723  jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual "
724  "output port.");
725  result = -1;
726  }
727  }
728 
729  return result;
730 }
731 
732 int
733 JackCoreMidiDriver::ProcessRead()
734 {
735  int res;
736  if (Trylock()) {
737  res = (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
738  Unlock();
739  } else {
740  res = -1;
741  }
742  return res;
743 }
744 
745 int
746 JackCoreMidiDriver::ProcessWrite()
747 {
748  int res;
749  if (Trylock()) {
750  res = (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
751  Unlock();
752  } else {
753  res = -1;
754  }
755  return res;
756 }
757 
758 int
759 JackCoreMidiDriver::Read()
760 {
761  jack_nframes_t buffer_size = fEngineControl->fBufferSize;
762  for (int i = 0; i < num_physical_inputs; i++) {
763  physical_input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size);
764  }
765  for (int i = 0; i < num_virtual_inputs; i++) {
766  virtual_input_ports[i]->
767  ProcessJack(GetInputBuffer(num_physical_inputs + i), buffer_size);
768  }
769  return 0;
770 }
771 
772 int
773 JackCoreMidiDriver::Write()
774 {
775  jack_nframes_t buffer_size = fEngineControl->fBufferSize;
776  for (int i = 0; i < num_physical_outputs; i++) {
777  physical_output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size);
778  }
779  for (int i = 0; i < num_virtual_outputs; i++) {
780  virtual_output_ports[i]->
781  ProcessJack(GetOutputBuffer(num_physical_outputs + i), buffer_size);
782  }
783  return 0;
784 }
785 
786 #ifdef __cplusplus
787 extern "C" {
788 #endif
789 
790  // singleton kind of driver
791  static Jack::JackDriverClientInterface* driver = NULL;
792 
793  SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
794  {
795  jack_driver_desc_t * desc;
798 
799  desc = jack_driver_descriptor_construct("coremidi", JackDriverSlave, "Apple CoreMIDI API based MIDI backend", &filler);
800 
801  value.ui = 0;
802  jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL);
803  jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL);
804 
805  return desc;
806  }
807 
808  SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
809  {
810  const JSList * node;
811  const jack_driver_param_t * param;
812  int virtual_in = 0;
813  int virtual_out = 0;
814 
815  for (node = params; node; node = jack_slist_next (node)) {
816  param = (const jack_driver_param_t *) node->data;
817 
818  switch (param->character) {
819 
820  case 'i':
821  virtual_in = param->value.ui;
822  break;
823 
824  case 'o':
825  virtual_out = param->value.ui;
826  break;
827  }
828  }
829 
830  // singleton kind of driver
831  if (!driver) {
832  driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table);
833  if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) {
834  return driver;
835  } else {
836  delete driver;
837  return NULL;
838  }
839  } else {
840  jack_info("JackCoreMidiDriver already allocated, cannot be loaded twice");
841  return NULL;
842  }
843  }
844 
845 #ifdef __cplusplus
846 }
847 #endif
The base class for MIDI drivers: drivers with MIDI ports.
Inter process synchronization using using Mach semaphore.
Locked Engine, access to methods is serialized using a mutex.
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:91
jack_nframes_t min
Definition: types.h:268
SERVER_EXPORT void jack_info(const char *fmt,...)
Definition: JackError.cpp:99
JackCoreMidiDriver(const char *name, const char *alias, JackLockedEngine *engine, JackSynchro *table)
jack_nframes_t max
Definition: types.h:272
The base interface for drivers clients.
Definition: JackDriver.h:122
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:107