| 
							- /*
 - Copyright (C) 2009 Grame
 - Copyright (C) 2011 Devin Anderson
 - 
 - 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.
 - 
 - */
 - 
 - #include "JackCompilerDeps.h"
 - #include "JackCoreMidiDriver.h"
 - #include "JackCoreMidiUtil.h"
 - #include "JackEngineControl.h"
 - #include "driver_interface.h"
 - 
 - #include <stdexcept>
 - #include <mach/mach_time.h>
 - #include <mach/mach_error.h>
 - 
 - using Jack::JackCoreMidiDriver;
 - 
 - static char capture_driver_name[256];
 - static char playback_driver_name[256];
 - 
 - static int in_channels, out_channels;
 - static bool capturing, playing, monitor;
 - 
 - static jack_nframes_t capture_latency, playback_latency;
 - 
 - ///////////////////////////////////////////////////////////////////////////////
 - // Static callbacks
 - ///////////////////////////////////////////////////////////////////////////////
 - 
 - void
 - JackCoreMidiDriver::HandleInputEvent(const MIDIPacketList *packet_list,
 -                                      void *driver, void *port)
 - {
 -     ((JackCoreMidiPhysicalInputPort *) port)->ProcessCoreMidi(packet_list);
 - }
 - 
 - void
 - JackCoreMidiDriver::HandleNotificationEvent(const MIDINotification *message,
 -                                             void *driver)
 - {
 -     ((JackCoreMidiDriver *) driver)->HandleNotification(message);
 - }
 - 
 - ///////////////////////////////////////////////////////////////////////////////
 - // Class
 - ///////////////////////////////////////////////////////////////////////////////
 - 
 - JackCoreMidiDriver::JackCoreMidiDriver(const char *name, const char *alias,
 -                                        JackLockedEngine *engine,
 -                                        JackSynchro *table):
 -     JackMidiDriver(name, alias, engine, table),fThread(this)
 - {
 -     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));
 -     }
 -     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;
 -     internal_input = 0;
 -     internal_output = 0;
 - }
 - 
 - JackCoreMidiDriver::~JackCoreMidiDriver()
 - {}
 - 
 - bool JackCoreMidiDriver::Init()
 - {
 -     return OpenAux();
 - }
 - 
 - bool JackCoreMidiDriver::OpenAux()
 - {
 -     int pi_count = 0;
 -     int po_count = 0;
 -     int vi_count = 0;
 -     int vo_count = 0;
 -     ItemCount potential_po_count;
 -     ItemCount potential_pi_count;
 - 
 -     CFStringRef name = CFStringCreateWithCString(0, "JackMidi",
 -                                                  CFStringGetSystemEncoding());
 -     if (! name) {
 -         jack_error("JackCoreMidiDriver::Open - failed to allocate memory for "
 -                    "client name string");
 -         return false;
 -     }
 - 
 -     OSStatus status = MIDIClientCreate(name, HandleNotificationEvent, this,
 -                                        &client);
 -     CFRelease(name);
 - 
 -     if (status != noErr) {
 -         WriteMacOSError("JackCoreMidiDriver::Open", "MIDIClientCreate",
 -                         status);
 -         return false;
 -     }
 - 
 -     char *client_name = fClientControl.fName;
 - 
 -     // Allocate and connect physical inputs
 -     potential_pi_count = MIDIGetNumberOfSources();
 -     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;
 -         }
 - 
 -         try {
 -             physical_input_ports =
 -                 new JackCoreMidiPhysicalInputPort*[potential_pi_count];
 -         } catch (std::exception& e) {
 -             jack_error("JackCoreMidiDriver::Open - while creating physical "
 -                        "input port array: %s", e.what());
 -             goto destroy;
 -         }
 - 
 -         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());
 -                 goto destroy;
 -             }
 -             pi_count++;
 -         }
 -     }
 - 
 -     // Allocate and connect physical outputs
 -     potential_po_count = MIDIGetNumberOfDestinations();
 -     if (potential_po_count) {
 -         status = MIDIOutputPortCreate(client, CFSTR("Physical Output Port"),
 -                                       &internal_output);
 -         if (status != noErr) {
 -             WriteMacOSError("JackCoreMidiDriver::Open", "MIDIOutputPortCreate",
 -                             status);
 -             goto destroy;
 -         }
 - 
 -         try {
 -             physical_output_ports =
 -                 new JackCoreMidiPhysicalOutputPort*[potential_po_count];
 -         } catch (std::exception& e) {
 -             jack_error("JackCoreMidiDriver::Open - while creating physical "
 -                        "output port array: %s", e.what());
 -             goto destroy;
 -         }
 - 
 -         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,
 -                                                        time_ratio);
 -             } catch (std::exception& e) {
 -                 jack_error("JackCoreMidiDriver::Open - while creating "
 -                            "physical output port: %s", e.what());
 -                 goto destroy;
 -             }
 -             po_count++;
 -         }
 -     }
 - 
 -     // 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;
 - 
 -         }
 -         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, 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;
 -             }
 -         }
 -     }
 - 
 -     // 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;
 -         }
 -         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, 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;
 -             }
 -         }
 -     }
 - 
 -     if (! (pi_count || po_count || in_channels || out_channels)) {
 -         jack_error("JackCoreMidiDriver::Open - no CoreMIDI inputs or outputs "
 -                    "found, and no virtual ports allocated.");
 -     }
 - 
 -     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 true;
 -     }
 - 
 -  destroy:
 - 
 -     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;
 -     }
 - 
 -     if (physical_output_ports) {
 -         for (int i = 0; i < po_count; i++) {
 -             delete physical_output_ports[i];
 -         }
 -         delete[] physical_output_ports;
 -         physical_output_ports = 0;
 -     }
 - 
 -     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;
 -     }
 - 
 -     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;
 -     }
 - 
 -     if (internal_output) {
 -         status = MIDIPortDispose(internal_output);
 -         if (status != noErr) {
 -             WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status);
 -         }
 -     }
 - 
 -     if (internal_input) {
 -         status = MIDIPortDispose(internal_input);
 -         if (status != noErr) {
 -             WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status);
 -         }
 -     }
 - 
 -     if (client) {
 -         status = MIDIClientDispose(client);
 -         if (status != noErr) {
 -             WriteMacOSError("JackCoreMidiDriver::Open", "MIDIClientDispose",
 -                             status);
 -         }
 -     }
 - 
 -     // Default open
 -     if (! JackMidiDriver::Open(capturing, playing,
 -                               in_channels + pi_count,
 -                               out_channels + po_count, monitor,
 -                               capture_driver_name,
 -                               playback_driver_name, capture_latency,
 -                               playback_latency)) {
 -         client = 0;
 -         num_physical_inputs = 0;
 -         num_physical_outputs = 0;
 -         num_virtual_inputs = 0;
 -         num_virtual_outputs = 0;
 -        return true;
 -     } else {
 -         return false;
 -     }
 - }
 - 
 - bool JackCoreMidiDriver::Execute()
 - {
 -     CFRunLoopRun();
 -     return false;
 - }
 - 
 - 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();
 -         if (fEngine->PortRegister(fClientControl.fRefNum, name,
 -                                 JACK_DEFAULT_MIDI_TYPE,
 -                                 CaptureDriverFlags, buffer_size, &index) < 0) {
 -             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);
 -         fEngine->PortSetDefaultMetadata(fClientControl.fRefNum, index,
 -                                         port_obj->GetDeviceName());
 -         fCapturePortList[i] = index;
 -     }
 - 
 -     // Virtual inputs
 -     for (int i = 0; i < num_virtual_inputs; i++) {
 -         port_obj = virtual_input_ports[i];
 -         name = port_obj->GetName();
 -         if (fEngine->PortRegister(fClientControl.fRefNum, name,
 -                                 JACK_DEFAULT_MIDI_TYPE,
 -                                 CaptureDriverFlags, buffer_size, &index) < 0) {
 -             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);
 -         fEngine->PortSetDefaultMetadata(fClientControl.fRefNum, index,
 -                                         port_obj->GetDeviceName());
 -         fCapturePortList[num_physical_inputs + i] = index;
 -     }
 - 
 -     if (! fEngineControl->fSyncMode) {
 -         latency += buffer_size;
 -         latency_range.max = latency;
 -         latency_range.min = latency;
 -     }
 - 
 -     // Physical outputs
 -     for (int i = 0; i < num_physical_outputs; i++) {
 -         port_obj = physical_output_ports[i];
 -         name = port_obj->GetName();
 -         fEngine->PortRegister(fClientControl.fRefNum, name,
 -                             JACK_DEFAULT_MIDI_TYPE,
 -                             PlaybackDriverFlags, buffer_size, &index);
 -         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;
 -         }
 -         port = fGraphManager->GetPort(index);
 -         port->SetAlias(port_obj->GetAlias());
 -         port->SetLatencyRange(JackPlaybackLatency, &latency_range);
 -         fEngine->PortSetDefaultMetadata(fClientControl.fRefNum, index,
 -                                         port_obj->GetDeviceName());
 -         fPlaybackPortList[i] = index;
 -     }
 - 
 -     // Virtual outputs
 -     for (int i = 0; i < num_virtual_outputs; i++) {
 -         port_obj = virtual_output_ports[i];
 -         name = port_obj->GetName();
 -         fEngine->PortRegister(fClientControl.fRefNum, name,
 -                             JACK_DEFAULT_MIDI_TYPE,
 -                             PlaybackDriverFlags, buffer_size, &index);
 -         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);
 -         fEngine->PortSetDefaultMetadata(fClientControl.fRefNum, index,
 -                                         port_obj->GetDeviceName());
 -         fPlaybackPortList[num_physical_outputs + i] = index;
 -     }
 - 
 -     return 0;
 - }
 - 
 - int
 - JackCoreMidiDriver::Close()
 - {
 -     fThread.Kill();
 -     return CloseAux();
 - }
 - 
 - int
 - JackCoreMidiDriver::CloseAux()
 - {
 -     // Generic MIDI driver close
 -     int result = JackMidiDriver::Close();
 - 
 -     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;
 -         if (internal_input) {
 -             status = MIDIPortDispose(internal_input);
 -             if (status != noErr) {
 -                 WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose",
 -                                 status);
 -                 result = -1;
 -             }
 -             internal_input = 0;
 -         }
 -     }
 -     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;
 -         if (internal_output) {
 -             status = MIDIPortDispose(internal_output);
 -             if (status != noErr) {
 -                 WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose",
 -                                 status);
 -                 result = -1;
 -             }
 -             internal_output = 0;
 -         }
 -     }
 -     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;
 - }
 - 
 - void
 - JackCoreMidiDriver::Restart()
 - {
 -     // Lock between this thread and RT thread
 -     JackLock lock(this);
 -     
 -     // Lock between this thread and request thread
 -     if (fEngine->Lock()) {
 -         // Use first alias
 -         SaveConnections(1);
 -         Stop();
 -         Detach();
 -         CloseAux();
 -         OpenAux();
 -         Attach();
 -         Start();
 -         // Use first alias and partial port naming
 -         LoadConnections(1, false);
 -         fEngine->Unlock();
 -     } else {
 -         jack_error("Cannot acquire engine lock...");
 -     }
 - }
 - 
 - void
 - JackCoreMidiDriver::HandleNotification(const MIDINotification *message)
 - {
 -     switch (message->messageID) {
 - 
 -         case kMIDIMsgObjectAdded: {
 -             /*
 -                 We don't want to restart when our internal virtual in/out are created.
 -             */
 -             const MIDIObjectAddRemoveNotification* add_message = reinterpret_cast<const MIDIObjectAddRemoveNotification*>(message);
 -             if (!JackCoreMidiPort::IsInternalPort(add_message->child)) {
 -                 Restart();
 -             }
 -             break;
 -         }
 -         
 -         case kMIDIMsgObjectRemoved: {
 -             /*
 -                 We don't want to restart when our internal virtual in/out are created.
 -             */
 -             const MIDIObjectAddRemoveNotification* remove_message = reinterpret_cast<const MIDIObjectAddRemoveNotification*>(message);
 -             if (!JackCoreMidiPort::IsInternalPort(remove_message->child)) {
 -                 Restart();
 -             }
 -             break;
 -         }
 -     }
 - }
 - 
 - int
 - JackCoreMidiDriver::Open(bool capturing_aux, bool playing_aux, int in_channels_aux,
 -                          int out_channels_aux, bool monitor_aux,
 -                          const char* capture_driver_name_aux,
 -                          const char* playback_driver_name_aux,
 -                          jack_nframes_t capture_latency_aux,
 -                          jack_nframes_t playback_latency_aux)
 - {
 - 
 -     strcpy(capture_driver_name, capture_driver_name_aux);
 -     strcpy(playback_driver_name, playback_driver_name_aux);
 - 
 -     capturing = capturing_aux;
 -     playing = playing_aux;
 -     in_channels = in_channels_aux;
 -     out_channels = out_channels_aux;
 -     monitor = monitor_aux;
 -     capture_latency = capture_latency_aux;
 -     playback_latency = playback_latency_aux;
 - 
 -     fThread.StartSync();
 - 
 -     int count = 0;
 -     while (fThread.GetStatus() != JackThread::kRunning && ++count < WAIT_COUNTER) {
 -         JackSleep(100000);
 -         jack_log("JackCoreMidiDriver::Open wait count = %d", count);
 - 
 -     }
 -     if (count == WAIT_COUNTER) {
 -         jack_info("Cannot open CoreMIDI driver");
 -         fThread.Kill();
 -         return -1;
 -     } else {
 -         JackSleep(10000);
 -         jack_info("CoreMIDI driver is opened...");
 -     }
 - 
 -     return 0;
 - }
 - 
 - int
 - JackCoreMidiDriver::Start()
 - {
 -     jack_info("JackCoreMidiDriver::Start - Starting driver.");
 - 
 -     JackMidiDriver::Start();
 - 
 -     int pi_count = 0;
 -     int po_count = 0;
 -     int vi_count = 0;
 -     int vo_count = 0;
 - 
 -     jack_info("JackCoreMidiDriver::Start - Enabling physical input ports.");
 - 
 -     for (; pi_count < num_physical_inputs; pi_count++) {
 -         if (!physical_input_ports[pi_count]->Start()) {
 -             jack_error("JackCoreMidiDriver::Start - Failed to enable physical "
 -                        "input port.");
 -             goto stop_physical_input_ports;
 -         }
 -     }
 - 
 -     jack_info("JackCoreMidiDriver::Start - Enabling physical output ports.");
 - 
 -     for (; po_count < num_physical_outputs; po_count++) {
 -         if (!physical_output_ports[po_count]->Start()) {
 -             jack_error("JackCoreMidiDriver::Start - Failed to enable physical "
 -                        "output port.");
 -             goto stop_physical_output_ports;
 -         }
 -     }
 - 
 -     jack_info("JackCoreMidiDriver::Start - Enabling virtual input ports.");
 - 
 -     for (; vi_count < num_virtual_inputs; vi_count++) {
 -         if (!virtual_input_ports[vi_count]->Start()) {
 -             jack_error("JackCoreMidiDriver::Start - Failed to enable virtual "
 -                        "input port.");
 -             goto stop_virtual_input_ports;
 -         }
 -     }
 - 
 -     jack_info("JackCoreMidiDriver::Start - Enabling virtual output ports.");
 - 
 -     for (; vo_count < num_virtual_outputs; vo_count++) {
 -         if (!virtual_output_ports[vo_count]->Start()) {
 -             jack_error("JackCoreMidiDriver::Start - Failed to enable virtual "
 -                        "output port.");
 -             goto stop_virtual_output_ports;
 -         }
 -     }
 - 
 -     jack_info("JackCoreMidiDriver::Start - Driver started.");
 - 
 -     return 0;
 - 
 -  stop_virtual_output_ports:
 -     for (int i = 0; i < vo_count; i++) {
 -         if (!virtual_output_ports[i]->Stop()) {
 -             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()) {
 -             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()) {
 -             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()) {
 -             jack_error("JackCoreMidiDriver::Start - Failed to disable "
 -                        "physical input port.");
 -         }
 -     }
 - 
 -     return -1;
 - }
 - 
 - int
 - JackCoreMidiDriver::Stop()
 - {
 -     int result = 0;
 - 
 -     JackMidiDriver::Stop();
 - 
 -     jack_info("JackCoreMidiDriver::Stop - disabling physical input ports.");
 - 
 -     for (int i = 0; i < num_physical_inputs; i++) {
 -         if (!physical_input_ports[i]->Stop()) {
 -             jack_error("JackCoreMidiDriver::Stop - Failed to disable physical "
 -                        "input port.");
 -             result = -1;
 -         }
 -     }
 - 
 -     jack_info("JackCoreMidiDriver::Stop - disabling physical output ports.");
 - 
 -     for (int i = 0; i < num_physical_outputs; i++) {
 -         if (!physical_output_ports[i]->Stop()) {
 -             jack_error("JackCoreMidiDriver::Stop - Failed to disable physical "
 -                        "output port.");
 -             result = -1;
 -         }
 -     }
 - 
 -     jack_info("JackCoreMidiDriver::Stop - disabling virtual input ports.");
 - 
 -     for (int i = 0; i < num_virtual_inputs; i++) {
 -         if (!virtual_input_ports[i]->Stop()) {
 -             jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual "
 -                        "input port.");
 -             result = -1;
 -         }
 -     }
 - 
 -     jack_info("JackCoreMidiDriver::Stop - disabling virtual output ports.");
 - 
 -     for (int i = 0; i < num_virtual_outputs; i++) {
 -         if (!virtual_output_ports[i]->Stop()) {
 -             jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual "
 -                        "output port.");
 -             result = -1;
 -         }
 -     }
 - 
 -     return result;
 - }
 - 
 - int
 - JackCoreMidiDriver::ProcessRead()
 - {
 -     int res;
 -     if (Trylock()) {
 -         res = (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
 -         Unlock();
 -     } else {
 -         res = -1;
 -     }
 -     return res;
 - }
 - 
 - int
 - JackCoreMidiDriver::ProcessWrite()
 - {
 -     int res;
 -     if (Trylock()) {
 -         res = (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
 -         Unlock();
 -     } else {
 -         res = -1;
 -     }
 -     return res;
 - }
 - 
 - 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);
 -     }
 -     return 0;
 - }
 - 
 - 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;
 - }
 - 
 - #ifdef __cplusplus
 - extern "C" {
 - #endif
 - 
 -     // singleton kind of driver
 -     static Jack::JackCoreMidiDriver* driver = NULL;
 - 
 -     SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
 -     {
 -         jack_driver_desc_t * desc;
 -         jack_driver_desc_filler_t filler;
 -         jack_driver_param_value_t value;
 - 
 -         desc = jack_driver_descriptor_construct("coremidi", JackDriverSlave, "Apple CoreMIDI API based MIDI backend", &filler);
 - 
 -         value.ui = 0;
 -         jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL);
 -         jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL);
 - 
 -         return desc;
 -     }
 - 
 -     SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
 -     {
 -         const JSList * node;
 -         const jack_driver_param_t * param;
 -         int virtual_in = 2;
 -         int virtual_out = 2;
 - 
 -         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;
 -                 }
 -         }
 - 
 -         // singleton kind of driver
 -         if (!driver) {
 -             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;
 -             }
 -         } else {
 -             jack_info("JackCoreMidiDriver already allocated, cannot be loaded twice");
 -             return NULL;
 -         }
 -     }
 - 
 - #ifdef __cplusplus
 - }
 - #endif
 
 
  |