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.

847 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. internal_input = 0;
  68. internal_output = 0;
  69. }
  70. JackCoreMidiDriver::~JackCoreMidiDriver()
  71. {}
  72. bool JackCoreMidiDriver::Init()
  73. {
  74. return OpenAux();
  75. }
  76. bool JackCoreMidiDriver::OpenAux()
  77. {
  78. int pi_count = 0;
  79. int po_count = 0;
  80. int vi_count = 0;
  81. int vo_count = 0;
  82. ItemCount potential_po_count;
  83. ItemCount potential_pi_count;
  84. CFStringRef name = CFStringCreateWithCString(0, "JackMidi",
  85. CFStringGetSystemEncoding());
  86. if (! name) {
  87. jack_error("JackCoreMidiDriver::Open - failed to allocate memory for "
  88. "client name string");
  89. return false;
  90. }
  91. OSStatus status = MIDIClientCreate(name, HandleNotificationEvent, this,
  92. &client);
  93. CFRelease(name);
  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;
  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;
  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;
  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;
  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;
  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;
  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;
  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;
  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;
  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;
  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. destroy:
  231. if (physical_input_ports) {
  232. for (int i = 0; i < pi_count; i++) {
  233. delete physical_input_ports[i];
  234. }
  235. delete[] physical_input_ports;
  236. physical_input_ports = 0;
  237. }
  238. if (physical_output_ports) {
  239. for (int i = 0; i < po_count; i++) {
  240. delete physical_output_ports[i];
  241. }
  242. delete[] physical_output_ports;
  243. physical_output_ports = 0;
  244. }
  245. if (virtual_input_ports) {
  246. for (int i = 0; i < vi_count; i++) {
  247. delete virtual_input_ports[i];
  248. }
  249. delete[] virtual_input_ports;
  250. virtual_input_ports = 0;
  251. }
  252. if (virtual_output_ports) {
  253. for (int i = 0; i < vo_count; i++) {
  254. delete virtual_output_ports[i];
  255. }
  256. delete[] virtual_output_ports;
  257. virtual_output_ports = 0;
  258. }
  259. if (internal_output) {
  260. status = MIDIPortDispose(internal_output);
  261. if (status != noErr) {
  262. WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status);
  263. }
  264. }
  265. if (internal_input) {
  266. status = MIDIPortDispose(internal_input);
  267. if (status != noErr) {
  268. WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status);
  269. }
  270. }
  271. if (client) {
  272. status = MIDIClientDispose(client);
  273. if (status != noErr) {
  274. WriteMacOSError("JackCoreMidiDriver::Open", "MIDIClientDispose",
  275. status);
  276. }
  277. }
  278. // Default open
  279. if (! JackMidiDriver::Open(capturing, playing,
  280. in_channels + pi_count,
  281. out_channels + po_count, monitor,
  282. capture_driver_name,
  283. playback_driver_name, capture_latency,
  284. playback_latency)) {
  285. client = 0;
  286. num_physical_inputs = 0;
  287. num_physical_outputs = 0;
  288. num_virtual_inputs = 0;
  289. num_virtual_outputs = 0;
  290. return true;
  291. } else {
  292. return false;
  293. }
  294. }
  295. bool JackCoreMidiDriver::Execute()
  296. {
  297. CFRunLoopRun();
  298. return false;
  299. }
  300. int
  301. JackCoreMidiDriver::Attach()
  302. {
  303. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  304. jack_port_id_t index;
  305. jack_nframes_t latency = buffer_size;
  306. jack_latency_range_t latency_range;
  307. const char *name;
  308. JackPort *port;
  309. JackCoreMidiPort *port_obj;
  310. latency_range.max = latency;
  311. latency_range.min = latency;
  312. // Physical inputs
  313. for (int i = 0; i < num_physical_inputs; i++) {
  314. port_obj = physical_input_ports[i];
  315. name = port_obj->GetName();
  316. if (fEngine->PortRegister(fClientControl.fRefNum, name,
  317. JACK_DEFAULT_MIDI_TYPE,
  318. CaptureDriverFlags, buffer_size, &index) < 0) {
  319. jack_error("JackCoreMidiDriver::Attach - cannot register physical "
  320. "input port with name '%s'.", name);
  321. // X: Do we need to deallocate ports?
  322. return -1;
  323. }
  324. port = fGraphManager->GetPort(index);
  325. port->SetAlias(port_obj->GetAlias());
  326. port->SetLatencyRange(JackCaptureLatency, &latency_range);
  327. fCapturePortList[i] = index;
  328. }
  329. // Virtual inputs
  330. for (int i = 0; i < num_virtual_inputs; i++) {
  331. port_obj = virtual_input_ports[i];
  332. name = port_obj->GetName();
  333. if (fEngine->PortRegister(fClientControl.fRefNum, name,
  334. JACK_DEFAULT_MIDI_TYPE,
  335. CaptureDriverFlags, buffer_size, &index) < 0) {
  336. jack_error("JackCoreMidiDriver::Attach - cannot register virtual "
  337. "input port with name '%s'.", name);
  338. // X: Do we need to deallocate ports?
  339. return -1;
  340. }
  341. port = fGraphManager->GetPort(index);
  342. port->SetAlias(port_obj->GetAlias());
  343. port->SetLatencyRange(JackCaptureLatency, &latency_range);
  344. fCapturePortList[num_physical_inputs + i] = index;
  345. }
  346. if (! fEngineControl->fSyncMode) {
  347. latency += buffer_size;
  348. latency_range.max = latency;
  349. latency_range.min = latency;
  350. }
  351. // Physical outputs
  352. for (int i = 0; i < num_physical_outputs; i++) {
  353. port_obj = physical_output_ports[i];
  354. name = port_obj->GetName();
  355. fEngine->PortRegister(fClientControl.fRefNum, name,
  356. JACK_DEFAULT_MIDI_TYPE,
  357. PlaybackDriverFlags, buffer_size, &index);
  358. if (index == NO_PORT) {
  359. jack_error("JackCoreMidiDriver::Attach - cannot register physical "
  360. "output port with name '%s'.", name);
  361. // X: Do we need to deallocate ports?
  362. return -1;
  363. }
  364. port = fGraphManager->GetPort(index);
  365. port->SetAlias(port_obj->GetAlias());
  366. port->SetLatencyRange(JackPlaybackLatency, &latency_range);
  367. fPlaybackPortList[i] = index;
  368. }
  369. // Virtual outputs
  370. for (int i = 0; i < num_virtual_outputs; i++) {
  371. port_obj = virtual_output_ports[i];
  372. name = port_obj->GetName();
  373. fEngine->PortRegister(fClientControl.fRefNum, name,
  374. JACK_DEFAULT_MIDI_TYPE,
  375. PlaybackDriverFlags, buffer_size, &index);
  376. if (index == NO_PORT) {
  377. jack_error("JackCoreMidiDriver::Attach - cannot register virtual "
  378. "output port with name '%s'.", name);
  379. // X: Do we need to deallocate ports?
  380. return -1;
  381. }
  382. port = fGraphManager->GetPort(index);
  383. port->SetAlias(port_obj->GetAlias());
  384. port->SetLatencyRange(JackPlaybackLatency, &latency_range);
  385. fPlaybackPortList[num_physical_outputs + i] = index;
  386. }
  387. return 0;
  388. }
  389. int
  390. JackCoreMidiDriver::Close()
  391. {
  392. fThread.Kill();
  393. return CloseAux();
  394. }
  395. int
  396. JackCoreMidiDriver::CloseAux()
  397. {
  398. // Generic MIDI driver close
  399. int result = JackMidiDriver::Close();
  400. OSStatus status;
  401. if (physical_input_ports) {
  402. for (int i = 0; i < num_physical_inputs; i++) {
  403. delete physical_input_ports[i];
  404. }
  405. delete[] physical_input_ports;
  406. num_physical_inputs = 0;
  407. physical_input_ports = 0;
  408. if (internal_input) {
  409. status = MIDIPortDispose(internal_input);
  410. if (status != noErr) {
  411. WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose",
  412. status);
  413. result = -1;
  414. }
  415. internal_input = 0;
  416. }
  417. }
  418. if (physical_output_ports) {
  419. for (int i = 0; i < num_physical_outputs; i++) {
  420. delete physical_output_ports[i];
  421. }
  422. delete[] physical_output_ports;
  423. num_physical_outputs = 0;
  424. physical_output_ports = 0;
  425. if (internal_output) {
  426. status = MIDIPortDispose(internal_output);
  427. if (status != noErr) {
  428. WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose",
  429. status);
  430. result = -1;
  431. }
  432. internal_output = 0;
  433. }
  434. }
  435. if (virtual_input_ports) {
  436. for (int i = 0; i < num_virtual_inputs; i++) {
  437. delete virtual_input_ports[i];
  438. }
  439. delete[] virtual_input_ports;
  440. num_virtual_inputs = 0;
  441. virtual_input_ports = 0;
  442. }
  443. if (virtual_output_ports) {
  444. for (int i = 0; i < num_virtual_outputs; i++) {
  445. delete virtual_output_ports[i];
  446. }
  447. delete[] virtual_output_ports;
  448. num_virtual_outputs = 0;
  449. virtual_output_ports = 0;
  450. }
  451. if (client) {
  452. status = MIDIClientDispose(client);
  453. if (status != noErr) {
  454. WriteMacOSError("JackCoreMidiDriver::Close", "MIDIClientDispose",
  455. status);
  456. result = -1;
  457. }
  458. client = 0;
  459. }
  460. return result;
  461. }
  462. void
  463. JackCoreMidiDriver::Restart()
  464. {
  465. JackLock lock(this);
  466. SaveConnections();
  467. Stop();
  468. Detach();
  469. CloseAux();
  470. OpenAux();
  471. Attach();
  472. Start();
  473. RestoreConnections();
  474. }
  475. void
  476. JackCoreMidiDriver::HandleNotification(const MIDINotification *message)
  477. {
  478. switch (message->messageID) {
  479. case kMIDIMsgSetupChanged:
  480. Restart();
  481. break;
  482. case kMIDIMsgObjectAdded:
  483. break;
  484. case kMIDIMsgObjectRemoved:
  485. break;
  486. }
  487. }
  488. int
  489. JackCoreMidiDriver::Open(bool capturing_aux, bool playing_aux, int in_channels_aux,
  490. int out_channels_aux, bool monitor_aux,
  491. const char* capture_driver_name_aux,
  492. const char* playback_driver_name_aux,
  493. jack_nframes_t capture_latency_aux,
  494. jack_nframes_t playback_latency_aux)
  495. {
  496. strcpy(capture_driver_name, capture_driver_name_aux);
  497. strcpy(playback_driver_name, playback_driver_name_aux);
  498. capturing = capturing_aux;
  499. playing = playing_aux;
  500. in_channels = in_channels_aux;
  501. out_channels = out_channels_aux;
  502. monitor = monitor_aux;
  503. capture_latency = capture_latency_aux;
  504. playback_latency = playback_latency_aux;
  505. fThread.StartSync();
  506. int count = 0;
  507. while (fThread.GetStatus() != JackThread::kRunning && ++count < WAIT_COUNTER) {
  508. JackSleep(100000);
  509. jack_log("JackCoreMidiDriver::Open wait count = %d", count);
  510. }
  511. if (count == WAIT_COUNTER) {
  512. jack_info("Cannot open CoreMIDI driver");
  513. fThread.Kill();
  514. return -1;
  515. } else {
  516. JackSleep(10000);
  517. jack_info("CoreMIDI driver is running...");
  518. }
  519. return 0;
  520. }
  521. int
  522. JackCoreMidiDriver::Start()
  523. {
  524. jack_info("JackCoreMidiDriver::Start - Starting driver.");
  525. JackMidiDriver::Start();
  526. int pi_count = 0;
  527. int po_count = 0;
  528. int vi_count = 0;
  529. int vo_count = 0;
  530. jack_info("JackCoreMidiDriver::Start - Enabling physical input ports.");
  531. for (; pi_count < num_physical_inputs; pi_count++) {
  532. if (physical_input_ports[pi_count]->Start() < 0) {
  533. jack_error("JackCoreMidiDriver::Start - Failed to enable physical "
  534. "input port.");
  535. goto stop_physical_input_ports;
  536. }
  537. }
  538. jack_info("JackCoreMidiDriver::Start - Enabling physical output ports.");
  539. for (; po_count < num_physical_outputs; po_count++) {
  540. if (physical_output_ports[po_count]->Start() < 0) {
  541. jack_error("JackCoreMidiDriver::Start - Failed to enable physical "
  542. "output port.");
  543. goto stop_physical_output_ports;
  544. }
  545. }
  546. jack_info("JackCoreMidiDriver::Start - Enabling virtual input ports.");
  547. for (; vi_count < num_virtual_inputs; vi_count++) {
  548. if (virtual_input_ports[vi_count]->Start() < 0) {
  549. jack_error("JackCoreMidiDriver::Start - Failed to enable virtual "
  550. "input port.");
  551. goto stop_virtual_input_ports;
  552. }
  553. }
  554. jack_info("JackCoreMidiDriver::Start - Enabling virtual output ports.");
  555. for (; vo_count < num_virtual_outputs; vo_count++) {
  556. if (virtual_output_ports[vo_count]->Start() < 0) {
  557. jack_error("JackCoreMidiDriver::Start - Failed to enable virtual "
  558. "output port.");
  559. goto stop_virtual_output_ports;
  560. }
  561. }
  562. jack_info("JackCoreMidiDriver::Start - Driver started.");
  563. return 0;
  564. stop_virtual_output_ports:
  565. for (int i = 0; i < vo_count; i++) {
  566. if (virtual_output_ports[i]->Stop() < 0) {
  567. jack_error("JackCoreMidiDriver::Start - Failed to disable virtual "
  568. "output port.");
  569. }
  570. }
  571. stop_virtual_input_ports:
  572. for (int i = 0; i < vi_count; i++) {
  573. if (virtual_input_ports[i]->Stop() < 0) {
  574. jack_error("JackCoreMidiDriver::Start - Failed to disable virtual "
  575. "input port.");
  576. }
  577. }
  578. stop_physical_output_ports:
  579. for (int i = 0; i < po_count; i++) {
  580. if (physical_output_ports[i]->Stop() < 0) {
  581. jack_error("JackCoreMidiDriver::Start - Failed to disable "
  582. "physical output port.");
  583. }
  584. }
  585. stop_physical_input_ports:
  586. for (int i = 0; i < pi_count; i++) {
  587. if (physical_input_ports[i]->Stop() < 0) {
  588. jack_error("JackCoreMidiDriver::Start - Failed to disable "
  589. "physical input port.");
  590. }
  591. }
  592. return -1;
  593. }
  594. int
  595. JackCoreMidiDriver::Stop()
  596. {
  597. int result = 0;
  598. JackMidiDriver::Stop();
  599. jack_info("JackCoreMidiDriver::Stop - disabling physical input ports.");
  600. for (int i = 0; i < num_physical_inputs; i++) {
  601. if (physical_input_ports[i]->Stop() < 0) {
  602. jack_error("JackCoreMidiDriver::Stop - Failed to disable physical "
  603. "input port.");
  604. result = -1;
  605. }
  606. }
  607. jack_info("JackCoreMidiDriver::Stop - disabling physical output ports.");
  608. for (int i = 0; i < num_physical_outputs; i++) {
  609. if (physical_output_ports[i]->Stop() < 0) {
  610. jack_error("JackCoreMidiDriver::Stop - Failed to disable physical "
  611. "output port.");
  612. result = -1;
  613. }
  614. }
  615. jack_info("JackCoreMidiDriver::Stop - disabling virtual input ports.");
  616. for (int i = 0; i < num_virtual_inputs; i++) {
  617. if (virtual_input_ports[i]->Stop() < 0) {
  618. jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual "
  619. "input port.");
  620. result = -1;
  621. }
  622. }
  623. jack_info("JackCoreMidiDriver::Stop - disabling virtual output ports.");
  624. for (int i = 0; i < num_virtual_outputs; i++) {
  625. if (virtual_output_ports[i]->Stop() < 0) {
  626. jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual "
  627. "output port.");
  628. result = -1;
  629. }
  630. }
  631. return result;
  632. }
  633. int
  634. JackCoreMidiDriver::ProcessRead()
  635. {
  636. int res;
  637. if (Trylock()) {
  638. res = (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
  639. Unlock();
  640. } else {
  641. res = -1;
  642. }
  643. return res;
  644. }
  645. int
  646. JackCoreMidiDriver::ProcessWrite()
  647. {
  648. int res;
  649. if (Trylock()) {
  650. res = (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
  651. Unlock();
  652. } else {
  653. res = -1;
  654. }
  655. return res;
  656. }
  657. int
  658. JackCoreMidiDriver::Read()
  659. {
  660. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  661. for (int i = 0; i < num_physical_inputs; i++) {
  662. physical_input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size);
  663. }
  664. for (int i = 0; i < num_virtual_inputs; i++) {
  665. virtual_input_ports[i]->
  666. ProcessJack(GetInputBuffer(num_physical_inputs + i), buffer_size);
  667. }
  668. return 0;
  669. }
  670. int
  671. JackCoreMidiDriver::Write()
  672. {
  673. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  674. for (int i = 0; i < num_physical_outputs; i++) {
  675. physical_output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size);
  676. }
  677. for (int i = 0; i < num_virtual_outputs; i++) {
  678. virtual_output_ports[i]->
  679. ProcessJack(GetOutputBuffer(num_physical_outputs + i), buffer_size);
  680. }
  681. return 0;
  682. }
  683. #ifdef __cplusplus
  684. extern "C" {
  685. #endif
  686. // singleton kind of driver
  687. static Jack::JackDriverClientInterface* driver = NULL;
  688. SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
  689. {
  690. jack_driver_desc_t * desc;
  691. jack_driver_desc_filler_t filler;
  692. jack_driver_param_value_t value;
  693. desc = jack_driver_descriptor_construct("coremidi", JackDriverSlave, "Apple CoreMIDI API based MIDI backend", &filler);
  694. value.ui = 0;
  695. jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL);
  696. jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL);
  697. return desc;
  698. }
  699. SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
  700. {
  701. const JSList * node;
  702. const jack_driver_param_t * param;
  703. int virtual_in = 0;
  704. int virtual_out = 0;
  705. for (node = params; node; node = jack_slist_next (node)) {
  706. param = (const jack_driver_param_t *) node->data;
  707. switch (param->character) {
  708. case 'i':
  709. virtual_in = param->value.ui;
  710. break;
  711. case 'o':
  712. virtual_out = param->value.ui;
  713. break;
  714. }
  715. }
  716. // singleton kind of driver
  717. if (!driver) {
  718. driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table);
  719. if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) {
  720. return driver;
  721. } else {
  722. delete driver;
  723. return NULL;
  724. }
  725. } else {
  726. jack_info("JackCoreMidiDriver already allocated, cannot be loaded twice");
  727. return NULL;
  728. }
  729. }
  730. #ifdef __cplusplus
  731. }
  732. #endif