Jack2
1.9.8
|
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 <stdexcept> 00022 00023 #include <mach/mach_time.h> 00024 00025 #include "JackCoreMidiDriver.h" 00026 #include "JackCoreMidiUtil.h" 00027 #include "JackEngineControl.h" 00028 00029 using Jack::JackCoreMidiDriver; 00030 00031 static char capture_driver_name[256]; 00032 static char playback_driver_name[256]; 00033 00034 static int in_channels, out_channels; 00035 static bool capturing, playing, monitor; 00036 00037 static jack_nframes_t capture_latency, playback_latency; 00038 00040 // Static callbacks 00042 00043 void 00044 JackCoreMidiDriver::HandleInputEvent(const MIDIPacketList *packet_list, 00045 void *driver, void *port) 00046 { 00047 ((JackCoreMidiPhysicalInputPort *) port)->ProcessCoreMidi(packet_list); 00048 } 00049 00050 void 00051 JackCoreMidiDriver::HandleNotificationEvent(const MIDINotification *message, 00052 void *driver) 00053 { 00054 ((JackCoreMidiDriver *) driver)->HandleNotification(message); 00055 } 00056 00058 // Class 00060 00061 JackCoreMidiDriver::JackCoreMidiDriver(const char *name, const char *alias, 00062 JackLockedEngine *engine, 00063 JackSynchro *table): 00064 JackMidiDriver(name, alias, engine, table),fThread(this) 00065 { 00066 mach_timebase_info_data_t info; 00067 kern_return_t result = mach_timebase_info(&info); 00068 if (result != KERN_SUCCESS) { 00069 throw std::runtime_error(mach_error_string(result)); 00070 } 00071 client = 0; 00072 fCaptureChannels = 0; 00073 fPlaybackChannels = 0; 00074 num_physical_inputs = 0; 00075 num_physical_outputs = 0; 00076 num_virtual_inputs = 0; 00077 num_virtual_outputs = 0; 00078 physical_input_ports = 0; 00079 physical_output_ports = 0; 00080 time_ratio = (((double) info.numer) / info.denom) / 1000.0; 00081 virtual_input_ports = 0; 00082 virtual_output_ports = 0; 00083 internal_input = 0; 00084 internal_output = 0; 00085 } 00086 00087 JackCoreMidiDriver::~JackCoreMidiDriver() 00088 {} 00089 00090 bool JackCoreMidiDriver::Init() 00091 { 00092 return OpenAux(); 00093 } 00094 00095 bool JackCoreMidiDriver::OpenAux() 00096 { 00097 int pi_count = 0; 00098 int po_count = 0; 00099 int vi_count = 0; 00100 int vo_count = 0; 00101 ItemCount potential_po_count; 00102 ItemCount potential_pi_count; 00103 00104 CFStringRef name = CFStringCreateWithCString(0, "JackMidi", 00105 CFStringGetSystemEncoding()); 00106 if (! name) { 00107 jack_error("JackCoreMidiDriver::Open - failed to allocate memory for " 00108 "client name string"); 00109 return false; 00110 } 00111 00112 OSStatus status = MIDIClientCreate(name, HandleNotificationEvent, this, 00113 &client); 00114 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 + 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 + 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 00249 if (! (pi_count || po_count || in_channels || out_channels)) { 00250 jack_error("JackCoreMidiDriver::Open - no CoreMIDI inputs or outputs " 00251 "found, and no virtual ports allocated."); 00252 } 00253 00254 if (! JackMidiDriver::Open(capturing, playing, 00255 in_channels + pi_count, 00256 out_channels + po_count, monitor, 00257 capture_driver_name, 00258 playback_driver_name, capture_latency, 00259 playback_latency)) { 00260 num_physical_inputs = pi_count; 00261 num_physical_outputs = po_count; 00262 num_virtual_inputs = in_channels; 00263 num_virtual_outputs = out_channels; 00264 return true; 00265 } 00266 00267 destroy: 00268 00269 if (physical_input_ports) { 00270 for (int i = 0; i < pi_count; i++) { 00271 delete physical_input_ports[i]; 00272 } 00273 delete[] physical_input_ports; 00274 physical_input_ports = 0; 00275 } 00276 00277 if (physical_output_ports) { 00278 for (int i = 0; i < po_count; i++) { 00279 delete physical_output_ports[i]; 00280 } 00281 delete[] physical_output_ports; 00282 physical_output_ports = 0; 00283 } 00284 00285 if (virtual_input_ports) { 00286 for (int i = 0; i < vi_count; i++) { 00287 delete virtual_input_ports[i]; 00288 } 00289 delete[] virtual_input_ports; 00290 virtual_input_ports = 0; 00291 } 00292 00293 if (virtual_output_ports) { 00294 for (int i = 0; i < vo_count; i++) { 00295 delete virtual_output_ports[i]; 00296 } 00297 delete[] virtual_output_ports; 00298 virtual_output_ports = 0; 00299 } 00300 00301 if (internal_output) { 00302 status = MIDIPortDispose(internal_output); 00303 if (status != noErr) { 00304 WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status); 00305 } 00306 } 00307 00308 if (internal_input) { 00309 status = MIDIPortDispose(internal_input); 00310 if (status != noErr) { 00311 WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status); 00312 } 00313 } 00314 00315 if (client) { 00316 status = MIDIClientDispose(client); 00317 if (status != noErr) { 00318 WriteMacOSError("JackCoreMidiDriver::Open", "MIDIClientDispose", 00319 status); 00320 } 00321 } 00322 00323 // Default open 00324 if (! JackMidiDriver::Open(capturing, playing, 00325 in_channels + pi_count, 00326 out_channels + po_count, monitor, 00327 capture_driver_name, 00328 playback_driver_name, capture_latency, 00329 playback_latency)) { 00330 client = 0; 00331 num_physical_inputs = 0; 00332 num_physical_outputs = 0; 00333 num_virtual_inputs = 0; 00334 num_virtual_outputs = 0; 00335 return true; 00336 } else { 00337 return false; 00338 } 00339 } 00340 00341 bool JackCoreMidiDriver::Execute() 00342 { 00343 CFRunLoopRun(); 00344 return false; 00345 } 00346 00347 int 00348 JackCoreMidiDriver::Attach() 00349 { 00350 jack_nframes_t buffer_size = fEngineControl->fBufferSize; 00351 jack_port_id_t index; 00352 jack_nframes_t latency = buffer_size; 00353 jack_latency_range_t latency_range; 00354 const char *name; 00355 JackPort *port; 00356 JackCoreMidiPort *port_obj; 00357 latency_range.max = latency; 00358 latency_range.min = latency; 00359 00360 // Physical inputs 00361 for (int i = 0; i < num_physical_inputs; i++) { 00362 port_obj = physical_input_ports[i]; 00363 name = port_obj->GetName(); 00364 if (fEngine->PortRegister(fClientControl.fRefNum, name, 00365 JACK_DEFAULT_MIDI_TYPE, 00366 CaptureDriverFlags, buffer_size, &index) < 0) { 00367 jack_error("JackCoreMidiDriver::Attach - cannot register physical " 00368 "input port with name '%s'.", name); 00369 // X: Do we need to deallocate ports? 00370 return -1; 00371 } 00372 port = fGraphManager->GetPort(index); 00373 port->SetAlias(port_obj->GetAlias()); 00374 port->SetLatencyRange(JackCaptureLatency, &latency_range); 00375 fCapturePortList[i] = index; 00376 } 00377 00378 // Virtual inputs 00379 for (int i = 0; i < num_virtual_inputs; i++) { 00380 port_obj = virtual_input_ports[i]; 00381 name = port_obj->GetName(); 00382 if (fEngine->PortRegister(fClientControl.fRefNum, name, 00383 JACK_DEFAULT_MIDI_TYPE, 00384 CaptureDriverFlags, buffer_size, &index) < 0) { 00385 jack_error("JackCoreMidiDriver::Attach - cannot register virtual " 00386 "input port with name '%s'.", name); 00387 // X: Do we need to deallocate ports? 00388 return -1; 00389 } 00390 port = fGraphManager->GetPort(index); 00391 port->SetAlias(port_obj->GetAlias()); 00392 port->SetLatencyRange(JackCaptureLatency, &latency_range); 00393 fCapturePortList[num_physical_inputs + i] = index; 00394 } 00395 00396 if (! fEngineControl->fSyncMode) { 00397 latency += buffer_size; 00398 latency_range.max = latency; 00399 latency_range.min = latency; 00400 } 00401 00402 // Physical outputs 00403 for (int i = 0; i < num_physical_outputs; i++) { 00404 port_obj = physical_output_ports[i]; 00405 name = port_obj->GetName(); 00406 fEngine->PortRegister(fClientControl.fRefNum, name, 00407 JACK_DEFAULT_MIDI_TYPE, 00408 PlaybackDriverFlags, buffer_size, &index); 00409 if (index == NO_PORT) { 00410 jack_error("JackCoreMidiDriver::Attach - cannot register physical " 00411 "output port with name '%s'.", name); 00412 // X: Do we need to deallocate ports? 00413 return -1; 00414 } 00415 port = fGraphManager->GetPort(index); 00416 port->SetAlias(port_obj->GetAlias()); 00417 port->SetLatencyRange(JackPlaybackLatency, &latency_range); 00418 fPlaybackPortList[i] = index; 00419 } 00420 00421 // Virtual outputs 00422 for (int i = 0; i < num_virtual_outputs; i++) { 00423 port_obj = virtual_output_ports[i]; 00424 name = port_obj->GetName(); 00425 fEngine->PortRegister(fClientControl.fRefNum, name, 00426 JACK_DEFAULT_MIDI_TYPE, 00427 PlaybackDriverFlags, buffer_size, &index); 00428 if (index == NO_PORT) { 00429 jack_error("JackCoreMidiDriver::Attach - cannot register virtual " 00430 "output port with name '%s'.", name); 00431 // X: Do we need to deallocate ports? 00432 return -1; 00433 } 00434 port = fGraphManager->GetPort(index); 00435 port->SetAlias(port_obj->GetAlias()); 00436 port->SetLatencyRange(JackPlaybackLatency, &latency_range); 00437 fPlaybackPortList[num_physical_outputs + i] = index; 00438 } 00439 00440 return 0; 00441 } 00442 00443 int 00444 JackCoreMidiDriver::Close() 00445 { 00446 fThread.Kill(); 00447 return CloseAux(); 00448 } 00449 00450 int 00451 JackCoreMidiDriver::CloseAux() 00452 { 00453 // Generic MIDI driver close 00454 int result = JackMidiDriver::Close(); 00455 00456 OSStatus status; 00457 if (physical_input_ports) { 00458 for (int i = 0; i < num_physical_inputs; i++) { 00459 delete physical_input_ports[i]; 00460 } 00461 delete[] physical_input_ports; 00462 num_physical_inputs = 0; 00463 physical_input_ports = 0; 00464 if (internal_input) { 00465 status = MIDIPortDispose(internal_input); 00466 if (status != noErr) { 00467 WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose", 00468 status); 00469 result = -1; 00470 } 00471 internal_input = 0; 00472 } 00473 } 00474 if (physical_output_ports) { 00475 for (int i = 0; i < num_physical_outputs; i++) { 00476 delete physical_output_ports[i]; 00477 } 00478 delete[] physical_output_ports; 00479 num_physical_outputs = 0; 00480 physical_output_ports = 0; 00481 if (internal_output) { 00482 status = MIDIPortDispose(internal_output); 00483 if (status != noErr) { 00484 WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose", 00485 status); 00486 result = -1; 00487 } 00488 internal_output = 0; 00489 } 00490 } 00491 if (virtual_input_ports) { 00492 for (int i = 0; i < num_virtual_inputs; i++) { 00493 delete virtual_input_ports[i]; 00494 } 00495 delete[] virtual_input_ports; 00496 num_virtual_inputs = 0; 00497 virtual_input_ports = 0; 00498 } 00499 if (virtual_output_ports) { 00500 for (int i = 0; i < num_virtual_outputs; i++) { 00501 delete virtual_output_ports[i]; 00502 } 00503 delete[] virtual_output_ports; 00504 num_virtual_outputs = 0; 00505 virtual_output_ports = 0; 00506 } 00507 00508 if (client) { 00509 status = MIDIClientDispose(client); 00510 if (status != noErr) { 00511 WriteMacOSError("JackCoreMidiDriver::Close", "MIDIClientDispose", 00512 status); 00513 result = -1; 00514 } 00515 client = 0; 00516 } 00517 return result; 00518 } 00519 00520 void 00521 JackCoreMidiDriver::Restart() 00522 { 00523 JackLock lock(this); 00524 00525 SaveConnections(); 00526 Stop(); 00527 Detach(); 00528 CloseAux(); 00529 OpenAux(); 00530 Attach(); 00531 Start(); 00532 RestoreConnections(); 00533 } 00534 00535 void 00536 JackCoreMidiDriver::HandleNotification(const MIDINotification *message) 00537 { 00538 switch (message->messageID) { 00539 00540 case kMIDIMsgSetupChanged: 00541 Restart(); 00542 break; 00543 00544 case kMIDIMsgObjectAdded: 00545 break; 00546 00547 case kMIDIMsgObjectRemoved: 00548 break; 00549 00550 } 00551 } 00552 00553 int 00554 JackCoreMidiDriver::Open(bool capturing_aux, bool playing_aux, int in_channels_aux, 00555 int out_channels_aux, bool monitor_aux, 00556 const char* capture_driver_name_aux, 00557 const char* playback_driver_name_aux, 00558 jack_nframes_t capture_latency_aux, 00559 jack_nframes_t playback_latency_aux) 00560 { 00561 00562 strcpy(capture_driver_name, capture_driver_name_aux); 00563 strcpy(playback_driver_name, playback_driver_name_aux); 00564 00565 capturing = capturing_aux; 00566 playing = playing_aux; 00567 in_channels = in_channels_aux; 00568 out_channels = out_channels_aux; 00569 monitor = monitor_aux; 00570 capture_latency = capture_latency_aux; 00571 playback_latency = playback_latency_aux; 00572 00573 fThread.StartSync(); 00574 00575 int count = 0; 00576 while (fThread.GetStatus() != JackThread::kRunning && ++count < WAIT_COUNTER) { 00577 JackSleep(100000); 00578 jack_log("JackCoreMidiDriver::Open wait count = %d", count); 00579 00580 } 00581 if (count == WAIT_COUNTER) { 00582 jack_info("Cannot open CoreMIDI driver"); 00583 fThread.Kill(); 00584 return -1; 00585 } else { 00586 JackSleep(10000); 00587 jack_info("CoreMIDI driver is running..."); 00588 } 00589 00590 return 0; 00591 } 00592 00593 int 00594 JackCoreMidiDriver::Start() 00595 { 00596 jack_info("JackCoreMidiDriver::Start - Starting driver."); 00597 00598 JackMidiDriver::Start(); 00599 00600 int pi_count = 0; 00601 int po_count = 0; 00602 int vi_count = 0; 00603 int vo_count = 0; 00604 00605 jack_info("JackCoreMidiDriver::Start - Enabling physical input ports."); 00606 00607 for (; pi_count < num_physical_inputs; pi_count++) { 00608 if (physical_input_ports[pi_count]->Start() < 0) { 00609 jack_error("JackCoreMidiDriver::Start - Failed to enable physical " 00610 "input port."); 00611 goto stop_physical_input_ports; 00612 } 00613 } 00614 00615 jack_info("JackCoreMidiDriver::Start - Enabling physical output ports."); 00616 00617 for (; po_count < num_physical_outputs; po_count++) { 00618 if (physical_output_ports[po_count]->Start() < 0) { 00619 jack_error("JackCoreMidiDriver::Start - Failed to enable physical " 00620 "output port."); 00621 goto stop_physical_output_ports; 00622 } 00623 } 00624 00625 jack_info("JackCoreMidiDriver::Start - Enabling virtual input ports."); 00626 00627 for (; vi_count < num_virtual_inputs; vi_count++) { 00628 if (virtual_input_ports[vi_count]->Start() < 0) { 00629 jack_error("JackCoreMidiDriver::Start - Failed to enable virtual " 00630 "input port."); 00631 goto stop_virtual_input_ports; 00632 } 00633 } 00634 00635 jack_info("JackCoreMidiDriver::Start - Enabling virtual output ports."); 00636 00637 for (; vo_count < num_virtual_outputs; vo_count++) { 00638 if (virtual_output_ports[vo_count]->Start() < 0) { 00639 jack_error("JackCoreMidiDriver::Start - Failed to enable virtual " 00640 "output port."); 00641 goto stop_virtual_output_ports; 00642 } 00643 } 00644 00645 jack_info("JackCoreMidiDriver::Start - Driver started."); 00646 00647 return 0; 00648 00649 stop_virtual_output_ports: 00650 for (int i = 0; i < vo_count; i++) { 00651 if (virtual_output_ports[i]->Stop() < 0) { 00652 jack_error("JackCoreMidiDriver::Start - Failed to disable virtual " 00653 "output port."); 00654 } 00655 } 00656 stop_virtual_input_ports: 00657 for (int i = 0; i < vi_count; i++) { 00658 if (virtual_input_ports[i]->Stop() < 0) { 00659 jack_error("JackCoreMidiDriver::Start - Failed to disable virtual " 00660 "input port."); 00661 } 00662 } 00663 stop_physical_output_ports: 00664 for (int i = 0; i < po_count; i++) { 00665 if (physical_output_ports[i]->Stop() < 0) { 00666 jack_error("JackCoreMidiDriver::Start - Failed to disable " 00667 "physical output port."); 00668 } 00669 } 00670 stop_physical_input_ports: 00671 for (int i = 0; i < pi_count; i++) { 00672 if (physical_input_ports[i]->Stop() < 0) { 00673 jack_error("JackCoreMidiDriver::Start - Failed to disable " 00674 "physical input port."); 00675 } 00676 } 00677 00678 return -1; 00679 } 00680 00681 int 00682 JackCoreMidiDriver::Stop() 00683 { 00684 int result = 0; 00685 00686 JackMidiDriver::Stop(); 00687 00688 jack_info("JackCoreMidiDriver::Stop - disabling physical input ports."); 00689 00690 for (int i = 0; i < num_physical_inputs; i++) { 00691 if (physical_input_ports[i]->Stop() < 0) { 00692 jack_error("JackCoreMidiDriver::Stop - Failed to disable physical " 00693 "input port."); 00694 result = -1; 00695 } 00696 } 00697 00698 jack_info("JackCoreMidiDriver::Stop - disabling physical output ports."); 00699 00700 for (int i = 0; i < num_physical_outputs; i++) { 00701 if (physical_output_ports[i]->Stop() < 0) { 00702 jack_error("JackCoreMidiDriver::Stop - Failed to disable physical " 00703 "output port."); 00704 result = -1; 00705 } 00706 } 00707 00708 jack_info("JackCoreMidiDriver::Stop - disabling virtual input ports."); 00709 00710 for (int i = 0; i < num_virtual_inputs; i++) { 00711 if (virtual_input_ports[i]->Stop() < 0) { 00712 jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual " 00713 "input port."); 00714 result = -1; 00715 } 00716 } 00717 00718 jack_info("JackCoreMidiDriver::Stop - disabling virtual output ports."); 00719 00720 for (int i = 0; i < num_virtual_outputs; i++) { 00721 if (virtual_output_ports[i]->Stop() < 0) { 00722 jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual " 00723 "output port."); 00724 result = -1; 00725 } 00726 } 00727 00728 return result; 00729 } 00730 00731 int 00732 JackCoreMidiDriver::ProcessRead() 00733 { 00734 int res; 00735 if (Trylock()) { 00736 res = (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync(); 00737 Unlock(); 00738 } else { 00739 res = -1; 00740 } 00741 return res; 00742 } 00743 00744 int 00745 JackCoreMidiDriver::ProcessWrite() 00746 { 00747 int res; 00748 if (Trylock()) { 00749 res = (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync(); 00750 Unlock(); 00751 } else { 00752 res = -1; 00753 } 00754 return res; 00755 } 00756 00757 int 00758 JackCoreMidiDriver::Read() 00759 { 00760 jack_nframes_t buffer_size = fEngineControl->fBufferSize; 00761 for (int i = 0; i < num_physical_inputs; i++) { 00762 physical_input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size); 00763 } 00764 for (int i = 0; i < num_virtual_inputs; i++) { 00765 virtual_input_ports[i]-> 00766 ProcessJack(GetInputBuffer(num_physical_inputs + i), buffer_size); 00767 } 00768 return 0; 00769 } 00770 00771 int 00772 JackCoreMidiDriver::Write() 00773 { 00774 jack_nframes_t buffer_size = fEngineControl->fBufferSize; 00775 for (int i = 0; i < num_physical_outputs; i++) { 00776 physical_output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size); 00777 } 00778 for (int i = 0; i < num_virtual_outputs; i++) { 00779 virtual_output_ports[i]-> 00780 ProcessJack(GetOutputBuffer(num_physical_outputs + i), buffer_size); 00781 } 00782 return 0; 00783 } 00784 00785 #ifdef __cplusplus 00786 extern "C" { 00787 #endif 00788 00789 // singleton kind of driver 00790 static Jack::JackDriverClientInterface* driver = NULL; 00791 00792 SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() 00793 { 00794 jack_driver_desc_t * desc; 00795 jack_driver_desc_filler_t filler; 00796 jack_driver_param_value_t value; 00797 00798 desc = jack_driver_descriptor_construct("coremidi", JackDriverSlave, "Apple CoreMIDI API based MIDI backend", &filler); 00799 00800 value.ui = 0; 00801 jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL); 00802 jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL); 00803 00804 return desc; 00805 } 00806 00807 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) 00808 { 00809 const JSList * node; 00810 const jack_driver_param_t * param; 00811 int virtual_in = 0; 00812 int virtual_out = 0; 00813 00814 for (node = params; node; node = jack_slist_next (node)) { 00815 param = (const jack_driver_param_t *) node->data; 00816 00817 switch (param->character) { 00818 00819 case 'i': 00820 virtual_in = param->value.ui; 00821 break; 00822 00823 case 'o': 00824 virtual_out = param->value.ui; 00825 break; 00826 } 00827 } 00828 00829 // singleton kind of driver 00830 if (!driver) { 00831 driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table); 00832 if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) { 00833 return driver; 00834 } else { 00835 delete driver; 00836 return NULL; 00837 } 00838 } else { 00839 jack_info("JackCoreMidiDriver already allocated, cannot be loaded twice"); 00840 return NULL; 00841 } 00842 } 00843 00844 #ifdef __cplusplus 00845 } 00846 #endif