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.

663 lines
22KB

  1. /*
  2. Copyright (C) 2011 Devin Anderson
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include <memory>
  16. #include <new>
  17. #include <stdexcept>
  18. #include <alsa/asoundlib.h>
  19. #include "JackALSARawMidiDriver.h"
  20. #include "JackALSARawMidiUtil.h"
  21. #include "JackEngineControl.h"
  22. #include "JackError.h"
  23. #include "JackMidiUtil.h"
  24. #include "driver_interface.h"
  25. using Jack::JackALSARawMidiDriver;
  26. JackALSARawMidiDriver::JackALSARawMidiDriver(const char *name,
  27. const char *alias,
  28. JackLockedEngine *engine,
  29. JackSynchro *table):
  30. JackMidiDriver(name, alias, engine, table)
  31. {
  32. thread = new JackThread(this);
  33. fds[0] = -1;
  34. fds[1] = -1;
  35. input_ports = 0;
  36. output_ports = 0;
  37. output_port_timeouts = 0;
  38. poll_fds = 0;
  39. }
  40. JackALSARawMidiDriver::~JackALSARawMidiDriver()
  41. {
  42. delete thread;
  43. }
  44. int
  45. JackALSARawMidiDriver::Attach()
  46. {
  47. const char *alias;
  48. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  49. jack_port_id_t index;
  50. jack_nframes_t latency = buffer_size;
  51. jack_latency_range_t latency_range;
  52. const char *name;
  53. JackPort *port;
  54. latency_range.max = latency;
  55. latency_range.min = latency;
  56. for (int i = 0; i < fCaptureChannels; i++) {
  57. JackALSARawMidiInputPort *input_port = input_ports[i];
  58. name = input_port->GetName();
  59. fEngine->PortRegister(fClientControl.fRefNum, name,
  60. JACK_DEFAULT_MIDI_TYPE,
  61. CaptureDriverFlags, buffer_size, &index);
  62. if (index == NO_PORT) {
  63. jack_error("JackALSARawMidiDriver::Attach - cannot register input "
  64. "port with name '%s'.", name);
  65. // XX: Do we need to deallocate ports?
  66. return -1;
  67. }
  68. alias = input_port->GetAlias();
  69. port = fGraphManager->GetPort(index);
  70. port->SetAlias(alias);
  71. port->SetLatencyRange(JackCaptureLatency, &latency_range);
  72. fCapturePortList[i] = index;
  73. jack_info("JackALSARawMidiDriver::Attach - input port registered "
  74. "(name='%s', alias='%s').", name, alias);
  75. }
  76. if (! fEngineControl->fSyncMode) {
  77. latency += buffer_size;
  78. latency_range.max = latency;
  79. latency_range.min = latency;
  80. }
  81. for (int i = 0; i < fPlaybackChannels; i++) {
  82. JackALSARawMidiOutputPort *output_port = output_ports[i];
  83. name = output_port->GetName();
  84. fEngine->PortRegister(fClientControl.fRefNum, name,
  85. JACK_DEFAULT_MIDI_TYPE,
  86. PlaybackDriverFlags, buffer_size, &index);
  87. if (index == NO_PORT) {
  88. jack_error("JackALSARawMidiDriver::Attach - cannot register "
  89. "output port with name '%s'.", name);
  90. // XX: Do we need to deallocate ports?
  91. return -1;
  92. }
  93. alias = output_port->GetAlias();
  94. port = fGraphManager->GetPort(index);
  95. port->SetAlias(alias);
  96. port->SetLatencyRange(JackPlaybackLatency, &latency_range);
  97. fPlaybackPortList[i] = index;
  98. jack_info("JackALSARawMidiDriver::Attach - output port registered "
  99. "(name='%s', alias='%s').", name, alias);
  100. }
  101. return 0;
  102. }
  103. int
  104. JackALSARawMidiDriver::Close()
  105. {
  106. // Generic MIDI driver close
  107. int result = JackMidiDriver::Close();
  108. if (input_ports) {
  109. for (int i = 0; i < fCaptureChannels; i++) {
  110. delete input_ports[i];
  111. }
  112. delete[] input_ports;
  113. input_ports = 0;
  114. }
  115. if (output_ports) {
  116. for (int i = 0; i < fPlaybackChannels; i++) {
  117. delete output_ports[i];
  118. }
  119. delete[] output_ports;
  120. output_ports = 0;
  121. }
  122. return result;
  123. }
  124. bool
  125. JackALSARawMidiDriver::Execute()
  126. {
  127. jack_nframes_t timeout_frame = 0;
  128. for (;;) {
  129. struct timespec timeout;
  130. struct timespec *timeout_ptr;
  131. if (! timeout_frame) {
  132. timeout_ptr = 0;
  133. } else {
  134. // The timeout value is relative to the time that
  135. // 'GetMicroSeconds()' is called, not the time that 'poll()' is
  136. // called. This means that the amount of time that passes between
  137. // 'GetMicroSeconds()' and 'ppoll()' is time that will be lost
  138. // while waiting for 'poll() to timeout.
  139. //
  140. // I tried to replace the timeout with a 'timerfd' with absolute
  141. // times, but, strangely, it actually slowed things down, and made
  142. // the code a lot more complicated.
  143. //
  144. // I wonder about using the 'epoll' interface instead of 'ppoll()'.
  145. // The problem with the 'epoll' interface is that the timeout
  146. // resolution of 'epoll_wait()' is set in milliseconds. We need
  147. // microsecond resolution. Without microsecond resolution, we
  148. // impose the same jitter as USB MIDI.
  149. //
  150. // Another problem is that 'ppoll()' returns later than the wait
  151. // time. The problem can be minimized with high precision timers.
  152. timeout_ptr = &timeout;
  153. jack_time_t next_time = GetTimeFromFrames(timeout_frame);
  154. jack_time_t now = GetMicroSeconds();
  155. if (next_time <= now) {
  156. timeout.tv_sec = 0;
  157. timeout.tv_nsec = 0;
  158. } else {
  159. jack_time_t wait_time = next_time - now;
  160. timeout.tv_sec = wait_time / 1000000;
  161. timeout.tv_nsec = (wait_time % 1000000) * 1000;
  162. }
  163. }
  164. int poll_result = ppoll(poll_fds, poll_fd_count, timeout_ptr, 0);
  165. // Getting the current frame value here allows us to use it for
  166. // incoming MIDI bytes. This makes sense, as the data has already
  167. // arrived at this point.
  168. jack_nframes_t current_frame = GetCurrentFrame();
  169. if (poll_result == -1) {
  170. if (errno == EINTR) {
  171. continue;
  172. }
  173. jack_error("JackALSARawMidiDriver::Execute - poll error: %s",
  174. strerror(errno));
  175. break;
  176. }
  177. jack_nframes_t port_timeout;
  178. timeout_frame = 0;
  179. if (! poll_result) {
  180. // No I/O events occurred. So, only handle timeout events on
  181. // output ports.
  182. for (int i = 0; i < fPlaybackChannels; i++) {
  183. port_timeout = output_port_timeouts[i];
  184. if (port_timeout && (port_timeout <= current_frame)) {
  185. if (! output_ports[i]->ProcessPollEvents(false, true,
  186. &port_timeout)) {
  187. jack_error("JackALSARawMidiDriver::Execute - a fatal "
  188. "error occurred while processing ALSA "
  189. "output events.");
  190. goto cleanup;
  191. }
  192. output_port_timeouts[i] = port_timeout;
  193. }
  194. if (port_timeout && ((! timeout_frame) ||
  195. (port_timeout < timeout_frame))) {
  196. timeout_frame = port_timeout;
  197. }
  198. }
  199. continue;
  200. }
  201. // See if it's time to shutdown.
  202. unsigned short revents = poll_fds[0].revents;
  203. if (revents) {
  204. if (revents & (~ POLLHUP)) {
  205. jack_error("JackALSARawMidiDriver::Execute - unexpected poll "
  206. "event on pipe file descriptor.");
  207. }
  208. break;
  209. }
  210. // Handle I/O events *and* timeout events on output ports.
  211. for (int i = 0; i < fPlaybackChannels; i++) {
  212. port_timeout = output_port_timeouts[i];
  213. bool timeout = port_timeout && (port_timeout <= current_frame);
  214. if (! output_ports[i]->ProcessPollEvents(true, timeout,
  215. &port_timeout)) {
  216. jack_error("JackALSARawMidiDriver::Execute - a fatal error "
  217. "occurred while processing ALSA output events.");
  218. goto cleanup;
  219. }
  220. output_port_timeouts[i] = port_timeout;
  221. if (port_timeout && ((! timeout_frame) ||
  222. (port_timeout < timeout_frame))) {
  223. timeout_frame = port_timeout;
  224. }
  225. }
  226. // Handle I/O events on input ports. We handle these last because we
  227. // already computed the arrival time above, and will impose a delay on
  228. // the events by 'period-size' frames anyway, which gives us a bit of
  229. // borrowed time.
  230. for (int i = 0; i < fCaptureChannels; i++) {
  231. if (! input_ports[i]->ProcessPollEvents(current_frame)) {
  232. jack_error("JackALSARawMidiDriver::Execute - a fatal error "
  233. "occurred while processing ALSA input events.");
  234. goto cleanup;
  235. }
  236. }
  237. }
  238. cleanup:
  239. close(fds[0]);
  240. fds[0] = -1;
  241. jack_info("JackALSARawMidiDriver::Execute - ALSA thread exiting.");
  242. return false;
  243. }
  244. void
  245. JackALSARawMidiDriver::
  246. FreeDeviceInfo(std::vector<snd_rawmidi_info_t *> *in_info_list,
  247. std::vector<snd_rawmidi_info_t *> *out_info_list)
  248. {
  249. size_t length = in_info_list->size();
  250. for (size_t i = 0; i < length; i++) {
  251. snd_rawmidi_info_free(in_info_list->at(i));
  252. }
  253. length = out_info_list->size();
  254. for (size_t i = 0; i < length; i++) {
  255. snd_rawmidi_info_free(out_info_list->at(i));
  256. }
  257. }
  258. void
  259. JackALSARawMidiDriver::
  260. GetDeviceInfo(snd_ctl_t *control, snd_rawmidi_info_t *info,
  261. std::vector<snd_rawmidi_info_t *> *info_list)
  262. {
  263. snd_rawmidi_info_set_subdevice(info, 0);
  264. int code = snd_ctl_rawmidi_info(control, info);
  265. if (code) {
  266. if (code != -ENOENT) {
  267. HandleALSAError("GetDeviceInfo", "snd_ctl_rawmidi_info", code);
  268. }
  269. return;
  270. }
  271. unsigned int count = snd_rawmidi_info_get_subdevices_count(info);
  272. for (unsigned int i = 0; i < count; i++) {
  273. snd_rawmidi_info_set_subdevice(info, i);
  274. int code = snd_ctl_rawmidi_info(control, info);
  275. if (code) {
  276. HandleALSAError("GetDeviceInfo", "snd_ctl_rawmidi_info", code);
  277. continue;
  278. }
  279. snd_rawmidi_info_t *info_copy;
  280. code = snd_rawmidi_info_malloc(&info_copy);
  281. if (code) {
  282. HandleALSAError("GetDeviceInfo", "snd_rawmidi_info_malloc", code);
  283. continue;
  284. }
  285. snd_rawmidi_info_copy(info_copy, info);
  286. try {
  287. info_list->push_back(info_copy);
  288. } catch (std::bad_alloc &e) {
  289. snd_rawmidi_info_free(info_copy);
  290. jack_error("JackALSARawMidiDriver::GetDeviceInfo - "
  291. "std::vector::push_back: %s", e.what());
  292. }
  293. }
  294. }
  295. void
  296. JackALSARawMidiDriver::HandleALSAError(const char *driver_func,
  297. const char *alsa_func, int code)
  298. {
  299. jack_error("JackALSARawMidiDriver::%s - %s: %s", driver_func, alsa_func,
  300. snd_strerror(code));
  301. }
  302. bool
  303. JackALSARawMidiDriver::Init()
  304. {
  305. set_threaded_log_function();
  306. if (thread->AcquireSelfRealTime(fEngineControl->fServerPriority + 1)) {
  307. jack_error("JackALSARawMidiDriver::Init - could not acquire realtime "
  308. "scheduling. Continuing anyway.");
  309. }
  310. return true;
  311. }
  312. int
  313. JackALSARawMidiDriver::Open(bool capturing, bool playing, int in_channels,
  314. int out_channels, bool monitor,
  315. const char *capture_driver_name,
  316. const char *playback_driver_name,
  317. jack_nframes_t capture_latency,
  318. jack_nframes_t playback_latency)
  319. {
  320. snd_rawmidi_info_t *info;
  321. int code = snd_rawmidi_info_malloc(&info);
  322. if (code) {
  323. HandleALSAError("Open", "snd_rawmidi_info_malloc", code);
  324. return -1;
  325. }
  326. std::vector<snd_rawmidi_info_t *> in_info_list;
  327. std::vector<snd_rawmidi_info_t *> out_info_list;
  328. for (int card = -1;;) {
  329. int code = snd_card_next(&card);
  330. if (code) {
  331. HandleALSAError("Open", "snd_card_next", code);
  332. continue;
  333. }
  334. if (card == -1) {
  335. break;
  336. }
  337. char name[32];
  338. snprintf(name, sizeof(name), "hw:%d", card);
  339. snd_ctl_t *control;
  340. code = snd_ctl_open(&control, name, SND_CTL_NONBLOCK);
  341. if (code) {
  342. HandleALSAError("Open", "snd_ctl_open", code);
  343. continue;
  344. }
  345. for (int device = -1;;) {
  346. code = snd_ctl_rawmidi_next_device(control, &device);
  347. if (code) {
  348. HandleALSAError("Open", "snd_ctl_rawmidi_next_device", code);
  349. continue;
  350. }
  351. if (device == -1) {
  352. break;
  353. }
  354. snd_rawmidi_info_set_device(info, device);
  355. snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_INPUT);
  356. GetDeviceInfo(control, info, &in_info_list);
  357. snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_OUTPUT);
  358. GetDeviceInfo(control, info, &out_info_list);
  359. }
  360. snd_ctl_close(control);
  361. }
  362. snd_rawmidi_info_free(info);
  363. size_t potential_inputs = in_info_list.size();
  364. size_t potential_outputs = out_info_list.size();
  365. if (! (potential_inputs || potential_outputs)) {
  366. jack_error("JackALSARawMidiDriver::Open - no ALSA raw MIDI input or "
  367. "output ports found.");
  368. FreeDeviceInfo(&in_info_list, &out_info_list);
  369. return -1;
  370. }
  371. size_t num_inputs = 0;
  372. size_t num_outputs = 0;
  373. if (potential_inputs) {
  374. try {
  375. input_ports = new JackALSARawMidiInputPort *[potential_inputs];
  376. } catch (std::exception e) {
  377. jack_error("JackALSARawMidiDriver::Open - while creating input "
  378. "port array: %s", e.what());
  379. FreeDeviceInfo(&in_info_list, &out_info_list);
  380. return -1;
  381. }
  382. }
  383. if (potential_outputs) {
  384. try {
  385. output_ports = new JackALSARawMidiOutputPort *[potential_outputs];
  386. } catch (std::exception e) {
  387. jack_error("JackALSARawMidiDriver::Open - while creating output "
  388. "port array: %s", e.what());
  389. FreeDeviceInfo(&in_info_list, &out_info_list);
  390. goto delete_input_ports;
  391. }
  392. }
  393. for (size_t i = 0; i < potential_inputs; i++) {
  394. snd_rawmidi_info_t *info = in_info_list.at(i);
  395. try {
  396. input_ports[num_inputs] = new JackALSARawMidiInputPort(info, i);
  397. num_inputs++;
  398. } catch (std::exception e) {
  399. jack_error("JackALSARawMidiDriver::Open - while creating new "
  400. "JackALSARawMidiInputPort: %s", e.what());
  401. }
  402. snd_rawmidi_info_free(info);
  403. }
  404. for (size_t i = 0; i < potential_outputs; i++) {
  405. snd_rawmidi_info_t *info = out_info_list.at(i);
  406. try {
  407. output_ports[num_outputs] = new JackALSARawMidiOutputPort(info, i);
  408. num_outputs++;
  409. } catch (std::exception e) {
  410. jack_error("JackALSARawMidiDriver::Open - while creating new "
  411. "JackALSARawMidiOutputPort: %s", e.what());
  412. }
  413. snd_rawmidi_info_free(info);
  414. }
  415. if (! (num_inputs || num_outputs)) {
  416. jack_error("JackALSARawMidiDriver::Open - none of the potential "
  417. "inputs or outputs were successfully opened.");
  418. } else if (JackMidiDriver::Open(capturing, playing, num_inputs,
  419. num_outputs, monitor, capture_driver_name,
  420. playback_driver_name, capture_latency,
  421. playback_latency)) {
  422. jack_error("JackALSARawMidiDriver::Open - JackMidiDriver::Open error");
  423. } else {
  424. return 0;
  425. }
  426. if (output_ports) {
  427. for (size_t i = 0; i < num_outputs; i++) {
  428. delete output_ports[i];
  429. }
  430. delete[] output_ports;
  431. output_ports = 0;
  432. }
  433. delete_input_ports:
  434. if (input_ports) {
  435. for (size_t i = 0; i < num_inputs; i++) {
  436. delete input_ports[i];
  437. }
  438. delete[] input_ports;
  439. input_ports = 0;
  440. }
  441. return -1;
  442. }
  443. int
  444. JackALSARawMidiDriver::Read()
  445. {
  446. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  447. for (int i = 0; i < fCaptureChannels; i++) {
  448. if (! input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size)) {
  449. return -1;
  450. }
  451. }
  452. return 0;
  453. }
  454. int
  455. JackALSARawMidiDriver::Start()
  456. {
  457. jack_info("JackALSARawMidiDriver::Start - Starting 'alsarawmidi' driver.");
  458. JackMidiDriver::Start();
  459. poll_fd_count = 1;
  460. for (int i = 0; i < fCaptureChannels; i++) {
  461. poll_fd_count += input_ports[i]->GetPollDescriptorCount();
  462. }
  463. for (int i = 0; i < fPlaybackChannels; i++) {
  464. poll_fd_count += output_ports[i]->GetPollDescriptorCount();
  465. }
  466. try {
  467. poll_fds = new pollfd[poll_fd_count];
  468. } catch (std::exception e) {
  469. jack_error("JackALSARawMidiDriver::Start - creating poll descriptor "
  470. "structures failed: %s", e.what());
  471. return -1;
  472. }
  473. if (fPlaybackChannels) {
  474. try {
  475. output_port_timeouts = new jack_nframes_t[fPlaybackChannels];
  476. } catch (std::exception e) {
  477. jack_error("JackALSARawMidiDriver::Start - creating array for "
  478. "output port timeout values failed: %s", e.what());
  479. goto free_poll_descriptors;
  480. }
  481. }
  482. struct pollfd *poll_fd_iter;
  483. try {
  484. CreateNonBlockingPipe(fds);
  485. } catch (std::exception e) {
  486. jack_error("JackALSARawMidiDriver::Start - while creating wake pipe: "
  487. "%s", e.what());
  488. goto free_output_port_timeouts;
  489. }
  490. poll_fds[0].events = POLLERR | POLLIN | POLLNVAL;
  491. poll_fds[0].fd = fds[0];
  492. poll_fd_iter = poll_fds + 1;
  493. for (int i = 0; i < fCaptureChannels; i++) {
  494. JackALSARawMidiInputPort *input_port = input_ports[i];
  495. input_port->PopulatePollDescriptors(poll_fd_iter);
  496. poll_fd_iter += input_port->GetPollDescriptorCount();
  497. }
  498. for (int i = 0; i < fPlaybackChannels; i++) {
  499. JackALSARawMidiOutputPort *output_port = output_ports[i];
  500. output_port->PopulatePollDescriptors(poll_fd_iter);
  501. poll_fd_iter += output_port->GetPollDescriptorCount();
  502. output_port_timeouts[i] = 0;
  503. }
  504. jack_info("JackALSARawMidiDriver::Start - starting ALSA thread ...");
  505. if (! thread->StartSync()) {
  506. jack_info("JackALSARawMidiDriver::Start - started ALSA thread.");
  507. return 0;
  508. }
  509. jack_error("JackALSARawMidiDriver::Start - failed to start MIDI "
  510. "processing thread.");
  511. DestroyNonBlockingPipe(fds);
  512. fds[1] = -1;
  513. fds[0] = -1;
  514. free_output_port_timeouts:
  515. delete[] output_port_timeouts;
  516. output_port_timeouts = 0;
  517. free_poll_descriptors:
  518. delete[] poll_fds;
  519. poll_fds = 0;
  520. return -1;
  521. }
  522. int
  523. JackALSARawMidiDriver::Stop()
  524. {
  525. jack_info("JackALSARawMidiDriver::Stop - stopping 'alsarawmidi' driver.");
  526. JackMidiDriver::Stop();
  527. if (fds[1] != -1) {
  528. close(fds[1]);
  529. fds[1] = -1;
  530. }
  531. int result;
  532. const char *verb;
  533. switch (thread->GetStatus()) {
  534. case JackThread::kIniting:
  535. case JackThread::kStarting:
  536. result = thread->Kill();
  537. verb = "kill";
  538. break;
  539. case JackThread::kRunning:
  540. result = thread->Stop();
  541. verb = "stop";
  542. break;
  543. default:
  544. result = 0;
  545. verb = 0;
  546. }
  547. if (fds[0] != -1) {
  548. close(fds[0]);
  549. fds[0] = -1;
  550. }
  551. if (output_port_timeouts) {
  552. delete[] output_port_timeouts;
  553. output_port_timeouts = 0;
  554. }
  555. if (poll_fds) {
  556. delete[] poll_fds;
  557. poll_fds = 0;
  558. }
  559. if (result) {
  560. jack_error("JackALSARawMidiDriver::Stop - could not %s MIDI "
  561. "processing thread.", verb);
  562. }
  563. return result;
  564. }
  565. int
  566. JackALSARawMidiDriver::Write()
  567. {
  568. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  569. for (int i = 0; i < fPlaybackChannels; i++) {
  570. if (! output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size)) {
  571. return -1;
  572. }
  573. }
  574. return 0;
  575. }
  576. #ifdef __cplusplus
  577. extern "C" {
  578. #endif
  579. // singleton kind of driver
  580. static Jack::JackALSARawMidiDriver* driver = NULL;
  581. SERVER_EXPORT jack_driver_desc_t *
  582. driver_get_descriptor()
  583. {
  584. // X: There could be parameters here regarding setting I/O buffer
  585. // sizes. I don't think MIDI drivers can accept parameters right
  586. // now without being set as the main driver.
  587. return jack_driver_descriptor_construct("alsarawmidi", JackDriverSlave, "Alternative ALSA raw MIDI backend.", NULL);
  588. }
  589. SERVER_EXPORT Jack::JackDriverClientInterface *
  590. driver_initialize(Jack::JackLockedEngine *engine, Jack::JackSynchro *table,
  591. const JSList *params)
  592. {
  593. // singleton kind of driver
  594. if (!driver) {
  595. driver = new Jack::JackALSARawMidiDriver("system_midi", "alsarawmidi", engine, table);
  596. if (driver->Open(1, 1, 0, 0, false, "midi in", "midi out", 0, 0) == 0) {
  597. return driver;
  598. } else {
  599. delete driver;
  600. return NULL;
  601. }
  602. } else {
  603. jack_info("JackALSARawMidiDriver already allocated, cannot be loaded twice");
  604. return NULL;
  605. }
  606. }
  607. #ifdef __cplusplus
  608. }
  609. #endif