Jack2
1.9.10
|
00001 /* 00002 Copyright (C) 2009 Grame 00003 Copyright (C) 2011 Devin Anderson 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 00019 */ 00020 00021 #include "JackCompilerDeps.h" 00022 #include "JackCoreMidiDriver.h" 00023 #include "JackCoreMidiUtil.h" 00024 #include "JackEngineControl.h" 00025 #include "driver_interface.h" 00026 00027 #include <stdexcept> 00028 #include <mach/mach_time.h> 00029 00030 using Jack::JackCoreMidiDriver; 00031 00032 static char capture_driver_name[256]; 00033 static char playback_driver_name[256]; 00034 00035 static int in_channels, out_channels; 00036 static bool capturing, playing, monitor; 00037 00038 static jack_nframes_t capture_latency, playback_latency; 00039 00041 // Static callbacks 00043 00044 void 00045 JackCoreMidiDriver::HandleInputEvent(const MIDIPacketList *packet_list, 00046 void *driver, void *port) 00047 { 00048 ((JackCoreMidiPhysicalInputPort *) port)->ProcessCoreMidi(packet_list); 00049 } 00050 00051 void 00052 JackCoreMidiDriver::HandleNotificationEvent(const MIDINotification *message, 00053 void *driver) 00054 { 00055 ((JackCoreMidiDriver *) driver)->HandleNotification(message); 00056 } 00057 00059 // Class 00061 00062 JackCoreMidiDriver::JackCoreMidiDriver(const char *name, const char *alias, 00063 JackLockedEngine *engine, 00064 JackSynchro *table): 00065 JackMidiDriver(name, alias, engine, table),fThread(this) 00066 { 00067 mach_timebase_info_data_t info; 00068 kern_return_t result = mach_timebase_info(&info); 00069 if (result != KERN_SUCCESS) { 00070 throw std::runtime_error(mach_error_string(result)); 00071 } 00072 client = 0; 00073 fCaptureChannels = 0; 00074 fPlaybackChannels = 0; 00075 num_physical_inputs = 0; 00076 num_physical_outputs = 0; 00077 num_virtual_inputs = 0; 00078 num_virtual_outputs = 0; 00079 physical_input_ports = 0; 00080 physical_output_ports = 0; 00081 time_ratio = (((double) info.numer) / info.denom) / 1000.0; 00082 virtual_input_ports = 0; 00083 virtual_output_ports = 0; 00084 internal_input = 0; 00085 internal_output = 0; 00086 } 00087 00088 JackCoreMidiDriver::~JackCoreMidiDriver() 00089 {} 00090 00091 bool JackCoreMidiDriver::Init() 00092 { 00093 return OpenAux(); 00094 } 00095 00096 bool JackCoreMidiDriver::OpenAux() 00097 { 00098 int pi_count = 0; 00099 int po_count = 0; 00100 int vi_count = 0; 00101 int vo_count = 0; 00102 ItemCount potential_po_count; 00103 ItemCount potential_pi_count; 00104 00105 CFStringRef name = CFStringCreateWithCString(0, "JackMidi", 00106 CFStringGetSystemEncoding()); 00107 if (! name) { 00108 jack_error("JackCoreMidiDriver::Open - failed to allocate memory for " 00109 "client name string"); 00110 return false; 00111 } 00112 00113 OSStatus status = MIDIClientCreate(name, HandleNotificationEvent, this, 00114 &client); 00115 CFRelease(name); 00116 00117 if (status != noErr) { 00118 WriteMacOSError("JackCoreMidiDriver::Open", "MIDIClientCreate", 00119 status); 00120 return false; 00121 } 00122 00123 char *client_name = fClientControl.fName; 00124 00125 // Allocate and connect physical inputs 00126 potential_pi_count = MIDIGetNumberOfSources(); 00127 if (potential_pi_count) { 00128 status = MIDIInputPortCreate(client, CFSTR("Physical Input Port"), 00129 HandleInputEvent, this, &internal_input); 00130 if (status != noErr) { 00131 WriteMacOSError("JackCoreMidiDriver::Open", "MIDIInputPortCreate", 00132 status); 00133 goto destroy; 00134 } 00135 00136 try { 00137 physical_input_ports = 00138 new JackCoreMidiPhysicalInputPort*[potential_pi_count]; 00139 } catch (std::exception& e) { 00140 jack_error("JackCoreMidiDriver::Open - while creating physical " 00141 "input port array: %s", e.what()); 00142 goto destroy; 00143 } 00144 00145 for (ItemCount i = 0; i < potential_pi_count; i++) { 00146 try { 00147 physical_input_ports[pi_count] = 00148 new JackCoreMidiPhysicalInputPort(fAliasName, client_name, 00149 capture_driver_name, i, 00150 client, internal_input, 00151 time_ratio); 00152 } catch (std::exception& e) { 00153 jack_error("JackCoreMidiDriver::Open - while creating " 00154 "physical input port: %s", e.what()); 00155 goto destroy; 00156 } 00157 pi_count++; 00158 } 00159 } 00160 00161 // Allocate and connect physical outputs 00162 potential_po_count = MIDIGetNumberOfDestinations(); 00163 if (potential_po_count) { 00164 status = MIDIOutputPortCreate(client, CFSTR("Physical Output Port"), 00165 &internal_output); 00166 if (status != noErr) { 00167 WriteMacOSError("JackCoreMidiDriver::Open", "MIDIOutputPortCreate", 00168 status); 00169 goto destroy; 00170 } 00171 00172 try { 00173 physical_output_ports = 00174 new JackCoreMidiPhysicalOutputPort*[potential_po_count]; 00175 } catch (std::exception& e) { 00176 jack_error("JackCoreMidiDriver::Open - while creating physical " 00177 "output port array: %s", e.what()); 00178 goto destroy; 00179 } 00180 00181 for (ItemCount i = 0; i < potential_po_count; i++) { 00182 try { 00183 physical_output_ports[po_count] = 00184 new JackCoreMidiPhysicalOutputPort(fAliasName, client_name, 00185 playback_driver_name, i, 00186 client, internal_output, 00187 time_ratio); 00188 } catch (std::exception& e) { 00189 jack_error("JackCoreMidiDriver::Open - while creating " 00190 "physical output port: %s", e.what()); 00191 goto destroy; 00192 } 00193 po_count++; 00194 } 00195 } 00196 00197 // Allocate and connect virtual inputs 00198 if (in_channels) { 00199 try { 00200 virtual_input_ports = 00201 new JackCoreMidiVirtualInputPort*[in_channels]; 00202 } catch (std::exception& e) { 00203 jack_error("JackCoreMidiDriver::Open - while creating virtual " 00204 "input port array: %s", e.what()); 00205 goto destroy; 00206 00207 } 00208 for (vi_count = 0; vi_count < in_channels; vi_count++) { 00209 try { 00210 virtual_input_ports[vi_count] = 00211 new JackCoreMidiVirtualInputPort(fAliasName, client_name, 00212 capture_driver_name, 00213 vi_count, vi_count + pi_count, client, 00214 time_ratio); 00215 } catch (std::exception& e) { 00216 jack_error("JackCoreMidiDriver::Open - while creating virtual " 00217 "input port: %s", e.what()); 00218 goto destroy; 00219 } 00220 } 00221 } 00222 00223 // Allocate and connect virtual outputs 00224 if (out_channels) { 00225 try { 00226 virtual_output_ports = 00227 new JackCoreMidiVirtualOutputPort*[out_channels]; 00228 } catch (std::exception& e) { 00229 jack_error("JackCoreMidiDriver::Open - while creating virtual " 00230 "output port array: %s", e.what()); 00231 goto destroy; 00232 } 00233 for (vo_count = 0; vo_count < out_channels; vo_count++) { 00234 try { 00235 virtual_output_ports[vo_count] = 00236 new JackCoreMidiVirtualOutputPort(fAliasName, client_name, 00237 playback_driver_name, 00238 vo_count, vo_count + po_count, client, 00239 time_ratio); 00240 } catch (std::exception& e) { 00241 jack_error("JackCoreMidiDriver::Open - while creating virtual " 00242 "output port: %s", e.what()); 00243 goto destroy; 00244 } 00245 } 00246 } 00247 00248 if (! (pi_count || po_count || in_channels || out_channels)) { 00249 jack_error("JackCoreMidiDriver::Open - no CoreMIDI inputs or outputs " 00250 "found, and no virtual ports allocated."); 00251 } 00252 00253 if (! JackMidiDriver::Open(capturing, playing, 00254 in_channels + pi_count, 00255 out_channels + po_count, monitor, 00256 capture_driver_name, 00257 playback_driver_name, capture_latency, 00258 playback_latency)) { 00259 num_physical_inputs = pi_count; 00260 num_physical_outputs = po_count; 00261 num_virtual_inputs = in_channels; 00262 num_virtual_outputs = out_channels; 00263 return true; 00264 } 00265 00266 destroy: 00267 00268 if (physical_input_ports) { 00269 for (int i = 0; i < pi_count; i++) { 00270 delete physical_input_ports[i]; 00271 } 00272 delete[] physical_input_ports; 00273 physical_input_ports = 0; 00274 } 00275 00276 if (physical_output_ports) { 00277 for (int i = 0; i < po_count; i++) { 00278 delete physical_output_ports[i]; 00279 } 00280 delete[] physical_output_ports; 00281 physical_output_ports = 0; 00282 } 00283 00284 if (virtual_input_ports) { 00285 for (int i = 0; i < vi_count; i++) { 00286 delete virtual_input_ports[i]; 00287 } 00288 delete[] virtual_input_ports; 00289 virtual_input_ports = 0; 00290 } 00291 00292 if (virtual_output_ports) { 00293 for (int i = 0; i < vo_count; i++) { 00294 delete virtual_output_ports[i]; 00295 } 00296 delete[] virtual_output_ports; 00297 virtual_output_ports = 0; 00298 } 00299 00300 if (internal_output) { 00301 status = MIDIPortDispose(internal_output); 00302 if (status != noErr) { 00303 WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status); 00304 } 00305 } 00306 00307 if (internal_input) { 00308 status = MIDIPortDispose(internal_input); 00309 if (status != noErr) { 00310 WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status); 00311 } 00312 } 00313 00314 if (client) { 00315 status = MIDIClientDispose(client); 00316 if (status != noErr) { 00317 WriteMacOSError("JackCoreMidiDriver::Open", "MIDIClientDispose", 00318 status); 00319 } 00320 } 00321 00322 // Default open 00323 if (! JackMidiDriver::Open(capturing, playing, 00324 in_channels + pi_count, 00325 out_channels + po_count, monitor, 00326 capture_driver_name, 00327 playback_driver_name, capture_latency, 00328 playback_latency)) { 00329 client = 0; 00330 num_physical_inputs = 0; 00331 num_physical_outputs = 0; 00332 num_virtual_inputs = 0; 00333 num_virtual_outputs = 0; 00334 return true; 00335 } else { 00336 return false; 00337 } 00338 } 00339 00340 bool JackCoreMidiDriver::Execute() 00341 { 00342 CFRunLoopRun(); 00343 return false; 00344 } 00345 00346 int 00347 JackCoreMidiDriver::Attach() 00348 { 00349 jack_nframes_t buffer_size = fEngineControl->fBufferSize; 00350 jack_port_id_t index; 00351 jack_nframes_t latency = buffer_size; 00352 jack_latency_range_t latency_range; 00353 const char *name; 00354 JackPort *port; 00355 JackCoreMidiPort *port_obj; 00356 latency_range.max = latency; 00357 latency_range.min = latency; 00358 00359 // Physical inputs 00360 for (int i = 0; i < num_physical_inputs; i++) { 00361 port_obj = physical_input_ports[i]; 00362 name = port_obj->GetName(); 00363 if (fEngine->PortRegister(fClientControl.fRefNum, name, 00364 JACK_DEFAULT_MIDI_TYPE, 00365 CaptureDriverFlags, buffer_size, &index) < 0) { 00366 jack_error("JackCoreMidiDriver::Attach - cannot register physical " 00367 "input port with name '%s'.", name); 00368 // X: Do we need to deallocate ports? 00369 return -1; 00370 } 00371 port = fGraphManager->GetPort(index); 00372 port->SetAlias(port_obj->GetAlias()); 00373 port->SetLatencyRange(JackCaptureLatency, &latency_range); 00374 fCapturePortList[i] = index; 00375 } 00376 00377 // Virtual inputs 00378 for (int i = 0; i < num_virtual_inputs; i++) { 00379 port_obj = virtual_input_ports[i]; 00380 name = port_obj->GetName(); 00381 if (fEngine->PortRegister(fClientControl.fRefNum, name, 00382 JACK_DEFAULT_MIDI_TYPE, 00383 CaptureDriverFlags, buffer_size, &index) < 0) { 00384 jack_error("JackCoreMidiDriver::Attach - cannot register virtual " 00385 "input port with name '%s'.", name); 00386 // X: Do we need to deallocate ports? 00387 return -1; 00388 } 00389 port = fGraphManager->GetPort(index); 00390 port->SetAlias(port_obj->GetAlias()); 00391 port->SetLatencyRange(JackCaptureLatency, &latency_range); 00392 fCapturePortList[num_physical_inputs + i] = index; 00393 } 00394 00395 if (! fEngineControl->fSyncMode) { 00396 latency += buffer_size; 00397 latency_range.max = latency; 00398 latency_range.min = latency; 00399 } 00400 00401 // Physical outputs 00402 for (int i = 0; i < num_physical_outputs; i++) { 00403 port_obj = physical_output_ports[i]; 00404 name = port_obj->GetName(); 00405 fEngine->PortRegister(fClientControl.fRefNum, name, 00406 JACK_DEFAULT_MIDI_TYPE, 00407 PlaybackDriverFlags, buffer_size, &index); 00408 if (index == NO_PORT) { 00409 jack_error("JackCoreMidiDriver::Attach - cannot register physical " 00410 "output port with name '%s'.", name); 00411 // X: Do we need to deallocate ports? 00412 return -1; 00413 } 00414 port = fGraphManager->GetPort(index); 00415 port->SetAlias(port_obj->GetAlias()); 00416 port->SetLatencyRange(JackPlaybackLatency, &latency_range); 00417 fPlaybackPortList[i] = index; 00418 } 00419 00420 // Virtual outputs 00421 for (int i = 0; i < num_virtual_outputs; i++) { 00422 port_obj = virtual_output_ports[i]; 00423 name = port_obj->GetName(); 00424 fEngine->PortRegister(fClientControl.fRefNum, name, 00425 JACK_DEFAULT_MIDI_TYPE, 00426 PlaybackDriverFlags, buffer_size, &index); 00427 if (index == NO_PORT) { 00428 jack_error("JackCoreMidiDriver::Attach - cannot register virtual " 00429 "output port with name '%s'.", name); 00430 // X: Do we need to deallocate ports? 00431 return -1; 00432 } 00433 port = fGraphManager->GetPort(index); 00434 port->SetAlias(port_obj->GetAlias()); 00435 port->SetLatencyRange(JackPlaybackLatency, &latency_range); 00436 fPlaybackPortList[num_physical_outputs + i] = index; 00437 } 00438 00439 return 0; 00440 } 00441 00442 int 00443 JackCoreMidiDriver::Close() 00444 { 00445 fThread.Kill(); 00446 return CloseAux(); 00447 } 00448 00449 int 00450 JackCoreMidiDriver::CloseAux() 00451 { 00452 // Generic MIDI driver close 00453 int result = JackMidiDriver::Close(); 00454 00455 OSStatus status; 00456 if (physical_input_ports) { 00457 for (int i = 0; i < num_physical_inputs; i++) { 00458 delete physical_input_ports[i]; 00459 } 00460 delete[] physical_input_ports; 00461 num_physical_inputs = 0; 00462 physical_input_ports = 0; 00463 if (internal_input) { 00464 status = MIDIPortDispose(internal_input); 00465 if (status != noErr) { 00466 WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose", 00467 status); 00468 result = -1; 00469 } 00470 internal_input = 0; 00471 } 00472 } 00473 if (physical_output_ports) { 00474 for (int i = 0; i < num_physical_outputs; i++) { 00475 delete physical_output_ports[i]; 00476 } 00477 delete[] physical_output_ports; 00478 num_physical_outputs = 0; 00479 physical_output_ports = 0; 00480 if (internal_output) { 00481 status = MIDIPortDispose(internal_output); 00482 if (status != noErr) { 00483 WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose", 00484 status); 00485 result = -1; 00486 } 00487 internal_output = 0; 00488 } 00489 } 00490 if (virtual_input_ports) { 00491 for (int i = 0; i < num_virtual_inputs; i++) { 00492 delete virtual_input_ports[i]; 00493 } 00494 delete[] virtual_input_ports; 00495 num_virtual_inputs = 0; 00496 virtual_input_ports = 0; 00497 } 00498 if (virtual_output_ports) { 00499 for (int i = 0; i < num_virtual_outputs; i++) { 00500 delete virtual_output_ports[i]; 00501 } 00502 delete[] virtual_output_ports; 00503 num_virtual_outputs = 0; 00504 virtual_output_ports = 0; 00505 } 00506 00507 if (client) { 00508 status = MIDIClientDispose(client); 00509 if (status != noErr) { 00510 WriteMacOSError("JackCoreMidiDriver::Close", "MIDIClientDispose", 00511 status); 00512 result = -1; 00513 } 00514 client = 0; 00515 } 00516 return result; 00517 } 00518 00519 void 00520 JackCoreMidiDriver::Restart() 00521 { 00522 // Lock between this thread and RT thread 00523 JackLock lock(this); 00524 00525 // Lock between this thread and request thread 00526 if (fEngine->Lock()) { 00527 // Use first alias 00528 SaveConnections(1); 00529 Stop(); 00530 Detach(); 00531 CloseAux(); 00532 OpenAux(); 00533 Attach(); 00534 Start(); 00535 // Use first alias and partial port naming 00536 LoadConnections(1, false); 00537 fEngine->Unlock(); 00538 } else { 00539 jack_error("Cannot acquire engine lock..."); 00540 } 00541 } 00542 00543 void 00544 JackCoreMidiDriver::HandleNotification(const MIDINotification *message) 00545 { 00546 switch (message->messageID) { 00547 00548 case kMIDIMsgObjectAdded: { 00549 /* 00550 We don't want to restart when our internal virtual in/out are created. 00551 */ 00552 const MIDIObjectAddRemoveNotification* add_message = reinterpret_cast<const MIDIObjectAddRemoveNotification*>(message); 00553 if (!JackCoreMidiPort::IsInternalPort(add_message->child)) { 00554 Restart(); 00555 } 00556 break; 00557 } 00558 00559 case kMIDIMsgObjectRemoved: { 00560 /* 00561 We don't want to restart when our internal virtual in/out are created. 00562 */ 00563 const MIDIObjectAddRemoveNotification* remove_message = reinterpret_cast<const MIDIObjectAddRemoveNotification*>(message); 00564 if (!JackCoreMidiPort::IsInternalPort(remove_message->child)) { 00565 Restart(); 00566 } 00567 break; 00568 } 00569 } 00570 } 00571 00572 int 00573 JackCoreMidiDriver::Open(bool capturing_aux, bool playing_aux, int in_channels_aux, 00574 int out_channels_aux, bool monitor_aux, 00575 const char* capture_driver_name_aux, 00576 const char* playback_driver_name_aux, 00577 jack_nframes_t capture_latency_aux, 00578 jack_nframes_t playback_latency_aux) 00579 { 00580 00581 strcpy(capture_driver_name, capture_driver_name_aux); 00582 strcpy(playback_driver_name, playback_driver_name_aux); 00583 00584 capturing = capturing_aux; 00585 playing = playing_aux; 00586 in_channels = in_channels_aux; 00587 out_channels = out_channels_aux; 00588 monitor = monitor_aux; 00589 capture_latency = capture_latency_aux; 00590 playback_latency = playback_latency_aux; 00591 00592 fThread.StartSync(); 00593 00594 int count = 0; 00595 while (fThread.GetStatus() != JackThread::kRunning && ++count < WAIT_COUNTER) { 00596 JackSleep(100000); 00597 jack_log("JackCoreMidiDriver::Open wait count = %d", count); 00598 00599 } 00600 if (count == WAIT_COUNTER) { 00601 jack_info("Cannot open CoreMIDI driver"); 00602 fThread.Kill(); 00603 return -1; 00604 } else { 00605 JackSleep(10000); 00606 jack_info("CoreMIDI driver is opened..."); 00607 } 00608 00609 return 0; 00610 } 00611 00612 int 00613 JackCoreMidiDriver::Start() 00614 { 00615 jack_info("JackCoreMidiDriver::Start - Starting driver."); 00616 00617 JackMidiDriver::Start(); 00618 00619 int pi_count = 0; 00620 int po_count = 0; 00621 int vi_count = 0; 00622 int vo_count = 0; 00623 00624 jack_info("JackCoreMidiDriver::Start - Enabling physical input ports."); 00625 00626 for (; pi_count < num_physical_inputs; pi_count++) { 00627 if (physical_input_ports[pi_count]->Start() < 0) { 00628 jack_error("JackCoreMidiDriver::Start - Failed to enable physical " 00629 "input port."); 00630 goto stop_physical_input_ports; 00631 } 00632 } 00633 00634 jack_info("JackCoreMidiDriver::Start - Enabling physical output ports."); 00635 00636 for (; po_count < num_physical_outputs; po_count++) { 00637 if (physical_output_ports[po_count]->Start() < 0) { 00638 jack_error("JackCoreMidiDriver::Start - Failed to enable physical " 00639 "output port."); 00640 goto stop_physical_output_ports; 00641 } 00642 } 00643 00644 jack_info("JackCoreMidiDriver::Start - Enabling virtual input ports."); 00645 00646 for (; vi_count < num_virtual_inputs; vi_count++) { 00647 if (virtual_input_ports[vi_count]->Start() < 0) { 00648 jack_error("JackCoreMidiDriver::Start - Failed to enable virtual " 00649 "input port."); 00650 goto stop_virtual_input_ports; 00651 } 00652 } 00653 00654 jack_info("JackCoreMidiDriver::Start - Enabling virtual output ports."); 00655 00656 for (; vo_count < num_virtual_outputs; vo_count++) { 00657 if (virtual_output_ports[vo_count]->Start() < 0) { 00658 jack_error("JackCoreMidiDriver::Start - Failed to enable virtual " 00659 "output port."); 00660 goto stop_virtual_output_ports; 00661 } 00662 } 00663 00664 jack_info("JackCoreMidiDriver::Start - Driver started."); 00665 00666 return 0; 00667 00668 stop_virtual_output_ports: 00669 for (int i = 0; i < vo_count; i++) { 00670 if (virtual_output_ports[i]->Stop() < 0) { 00671 jack_error("JackCoreMidiDriver::Start - Failed to disable virtual " 00672 "output port."); 00673 } 00674 } 00675 stop_virtual_input_ports: 00676 for (int i = 0; i < vi_count; i++) { 00677 if (virtual_input_ports[i]->Stop() < 0) { 00678 jack_error("JackCoreMidiDriver::Start - Failed to disable virtual " 00679 "input port."); 00680 } 00681 } 00682 stop_physical_output_ports: 00683 for (int i = 0; i < po_count; i++) { 00684 if (physical_output_ports[i]->Stop() < 0) { 00685 jack_error("JackCoreMidiDriver::Start - Failed to disable " 00686 "physical output port."); 00687 } 00688 } 00689 stop_physical_input_ports: 00690 for (int i = 0; i < pi_count; i++) { 00691 if (physical_input_ports[i]->Stop() < 0) { 00692 jack_error("JackCoreMidiDriver::Start - Failed to disable " 00693 "physical input port."); 00694 } 00695 } 00696 00697 return -1; 00698 } 00699 00700 int 00701 JackCoreMidiDriver::Stop() 00702 { 00703 int result = 0; 00704 00705 JackMidiDriver::Stop(); 00706 00707 jack_info("JackCoreMidiDriver::Stop - disabling physical input ports."); 00708 00709 for (int i = 0; i < num_physical_inputs; i++) { 00710 if (physical_input_ports[i]->Stop() < 0) { 00711 jack_error("JackCoreMidiDriver::Stop - Failed to disable physical " 00712 "input port."); 00713 result = -1; 00714 } 00715 } 00716 00717 jack_info("JackCoreMidiDriver::Stop - disabling physical output ports."); 00718 00719 for (int i = 0; i < num_physical_outputs; i++) { 00720 if (physical_output_ports[i]->Stop() < 0) { 00721 jack_error("JackCoreMidiDriver::Stop - Failed to disable physical " 00722 "output port."); 00723 result = -1; 00724 } 00725 } 00726 00727 jack_info("JackCoreMidiDriver::Stop - disabling virtual input ports."); 00728 00729 for (int i = 0; i < num_virtual_inputs; i++) { 00730 if (virtual_input_ports[i]->Stop() < 0) { 00731 jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual " 00732 "input port."); 00733 result = -1; 00734 } 00735 } 00736 00737 jack_info("JackCoreMidiDriver::Stop - disabling virtual output ports."); 00738 00739 for (int i = 0; i < num_virtual_outputs; i++) { 00740 if (virtual_output_ports[i]->Stop() < 0) { 00741 jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual " 00742 "output port."); 00743 result = -1; 00744 } 00745 } 00746 00747 return result; 00748 } 00749 00750 int 00751 JackCoreMidiDriver::ProcessRead() 00752 { 00753 int res; 00754 if (Trylock()) { 00755 res = (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync(); 00756 Unlock(); 00757 } else { 00758 res = -1; 00759 } 00760 return res; 00761 } 00762 00763 int 00764 JackCoreMidiDriver::ProcessWrite() 00765 { 00766 int res; 00767 if (Trylock()) { 00768 res = (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync(); 00769 Unlock(); 00770 } else { 00771 res = -1; 00772 } 00773 return res; 00774 } 00775 00776 int 00777 JackCoreMidiDriver::Read() 00778 { 00779 jack_nframes_t buffer_size = fEngineControl->fBufferSize; 00780 for (int i = 0; i < num_physical_inputs; i++) { 00781 physical_input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size); 00782 } 00783 for (int i = 0; i < num_virtual_inputs; i++) { 00784 virtual_input_ports[i]-> 00785 ProcessJack(GetInputBuffer(num_physical_inputs + i), buffer_size); 00786 } 00787 return 0; 00788 } 00789 00790 int 00791 JackCoreMidiDriver::Write() 00792 { 00793 jack_nframes_t buffer_size = fEngineControl->fBufferSize; 00794 for (int i = 0; i < num_physical_outputs; i++) { 00795 physical_output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size); 00796 } 00797 for (int i = 0; i < num_virtual_outputs; i++) { 00798 virtual_output_ports[i]-> 00799 ProcessJack(GetOutputBuffer(num_physical_outputs + i), buffer_size); 00800 } 00801 return 0; 00802 } 00803 00804 #ifdef __cplusplus 00805 extern "C" { 00806 #endif 00807 00808 // singleton kind of driver 00809 static Jack::JackCoreMidiDriver* driver = NULL; 00810 00811 SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() 00812 { 00813 jack_driver_desc_t * desc; 00814 jack_driver_desc_filler_t filler; 00815 jack_driver_param_value_t value; 00816 00817 desc = jack_driver_descriptor_construct("coremidi", JackDriverSlave, "Apple CoreMIDI API based MIDI backend", &filler); 00818 00819 value.ui = 0; 00820 jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL); 00821 jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL); 00822 00823 return desc; 00824 } 00825 00826 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) 00827 { 00828 const JSList * node; 00829 const jack_driver_param_t * param; 00830 int virtual_in = 2; 00831 int virtual_out = 2; 00832 00833 for (node = params; node; node = jack_slist_next (node)) { 00834 param = (const jack_driver_param_t *) node->data; 00835 00836 switch (param->character) { 00837 00838 case 'i': 00839 virtual_in = param->value.ui; 00840 break; 00841 00842 case 'o': 00843 virtual_out = param->value.ui; 00844 break; 00845 } 00846 } 00847 00848 // singleton kind of driver 00849 if (!driver) { 00850 driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table); 00851 if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) { 00852 return driver; 00853 } else { 00854 delete driver; 00855 return NULL; 00856 } 00857 } else { 00858 jack_info("JackCoreMidiDriver already allocated, cannot be loaded twice"); 00859 return NULL; 00860 } 00861 } 00862 00863 #ifdef __cplusplus 00864 } 00865 #endif