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.

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