jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

795 lines
26KB

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