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.

657 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. // I wonder about using the 'epoll' interface instead of 'ppoll()'.
  146. // The 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. // Another problem is that 'ppoll()' returns later than the wait
  152. // time. The problem can be minimized with high precision timers.
  153. timeout_ptr = &timeout;
  154. jack_time_t next_time = GetTimeFromFrames(timeout_frame);
  155. jack_time_t now = GetMicroSeconds();
  156. if (next_time <= now) {
  157. timeout.tv_sec = 0;
  158. timeout.tv_nsec = 0;
  159. } else {
  160. jack_time_t wait_time = next_time - now;
  161. timeout.tv_sec = wait_time / 1000000;
  162. timeout.tv_nsec = (wait_time % 1000000) * 1000;
  163. }
  164. }
  165. int poll_result = ppoll(poll_fds, poll_fd_count, timeout_ptr, 0);
  166. // Getting the current frame value here allows us to use it for
  167. // incoming MIDI bytes. This makes sense, as the data has already
  168. // arrived at this point.
  169. jack_nframes_t current_frame = GetCurrentFrame();
  170. if (poll_result == -1) {
  171. if (errno == EINTR) {
  172. continue;
  173. }
  174. jack_error("JackALSARawMidiDriver::Execute - poll error: %s",
  175. strerror(errno));
  176. break;
  177. }
  178. jack_nframes_t port_timeout;
  179. timeout_frame = 0;
  180. if (! poll_result) {
  181. // No I/O events occurred. So, only handle timeout events on
  182. // output ports.
  183. for (int i = 0; i < fPlaybackChannels; i++) {
  184. port_timeout = output_port_timeouts[i];
  185. if (port_timeout && (port_timeout <= current_frame)) {
  186. if (! output_ports[i]->ProcessPollEvents(false, true,
  187. &port_timeout)) {
  188. jack_error("JackALSARawMidiDriver::Execute - a fatal "
  189. "error occurred while processing ALSA "
  190. "output events.");
  191. goto cleanup;
  192. }
  193. output_port_timeouts[i] = port_timeout;
  194. }
  195. if (port_timeout && ((! timeout_frame) ||
  196. (port_timeout < timeout_frame))) {
  197. timeout_frame = port_timeout;
  198. }
  199. }
  200. continue;
  201. }
  202. // See if it's time to shutdown.
  203. unsigned short revents = poll_fds[0].revents;
  204. if (revents) {
  205. if (revents & (~ POLLHUP)) {
  206. jack_error("JackALSARawMidiDriver::Execute - unexpected poll "
  207. "event on pipe file descriptor.");
  208. }
  209. break;
  210. }
  211. // Handle I/O events *and* timeout events on output ports.
  212. for (int i = 0; i < fPlaybackChannels; i++) {
  213. port_timeout = output_port_timeouts[i];
  214. bool timeout = port_timeout && (port_timeout <= current_frame);
  215. if (! output_ports[i]->ProcessPollEvents(true, timeout,
  216. &port_timeout)) {
  217. jack_error("JackALSARawMidiDriver::Execute - a fatal error "
  218. "occurred while processing ALSA output events.");
  219. goto cleanup;
  220. }
  221. output_port_timeouts[i] = port_timeout;
  222. if (port_timeout && ((! timeout_frame) ||
  223. (port_timeout < timeout_frame))) {
  224. timeout_frame = port_timeout;
  225. }
  226. }
  227. // Handle I/O events on input ports. We handle these last because we
  228. // already computed the arrival time above, and will impose a delay on
  229. // the events by 'period-size' frames anyway, which gives us a bit of
  230. // borrowed time.
  231. for (int i = 0; i < fCaptureChannels; i++) {
  232. if (! input_ports[i]->ProcessPollEvents(current_frame)) {
  233. jack_error("JackALSARawMidiDriver::Execute - a fatal error "
  234. "occurred while processing ALSA input events.");
  235. goto cleanup;
  236. }
  237. }
  238. }
  239. cleanup:
  240. close(fds[0]);
  241. fds[0] = -1;
  242. jack_info("JackALSARawMidiDriver::Execute - ALSA thread exiting.");
  243. return false;
  244. }
  245. void
  246. JackALSARawMidiDriver::
  247. FreeDeviceInfo(std::vector<snd_rawmidi_info_t *> *in_info_list,
  248. std::vector<snd_rawmidi_info_t *> *out_info_list)
  249. {
  250. size_t length = in_info_list->size();
  251. for (size_t i = 0; i < length; i++) {
  252. snd_rawmidi_info_free(in_info_list->at(i));
  253. }
  254. length = out_info_list->size();
  255. for (size_t i = 0; i < length; i++) {
  256. snd_rawmidi_info_free(out_info_list->at(i));
  257. }
  258. }
  259. void
  260. JackALSARawMidiDriver::
  261. GetDeviceInfo(snd_ctl_t *control, snd_rawmidi_info_t *info,
  262. std::vector<snd_rawmidi_info_t *> *info_list)
  263. {
  264. snd_rawmidi_info_set_subdevice(info, 0);
  265. int code = snd_ctl_rawmidi_info(control, info);
  266. if (code) {
  267. if (code != -ENOENT) {
  268. HandleALSAError("GetDeviceInfo", "snd_ctl_rawmidi_info", code);
  269. }
  270. return;
  271. }
  272. unsigned int count = snd_rawmidi_info_get_subdevices_count(info);
  273. for (unsigned int i = 0; i < count; i++) {
  274. snd_rawmidi_info_set_subdevice(info, i);
  275. int code = snd_ctl_rawmidi_info(control, info);
  276. if (code) {
  277. HandleALSAError("GetDeviceInfo", "snd_ctl_rawmidi_info", code);
  278. continue;
  279. }
  280. snd_rawmidi_info_t *info_copy;
  281. code = snd_rawmidi_info_malloc(&info_copy);
  282. if (code) {
  283. HandleALSAError("GetDeviceInfo", "snd_rawmidi_info_malloc", code);
  284. continue;
  285. }
  286. snd_rawmidi_info_copy(info_copy, info);
  287. try {
  288. info_list->push_back(info_copy);
  289. } catch (std::bad_alloc &e) {
  290. snd_rawmidi_info_free(info_copy);
  291. jack_error("JackALSARawMidiDriver::GetDeviceInfo - "
  292. "std::vector::push_back: %s", e.what());
  293. }
  294. }
  295. }
  296. void
  297. JackALSARawMidiDriver::HandleALSAError(const char *driver_func,
  298. const char *alsa_func, int code)
  299. {
  300. jack_error("JackALSARawMidiDriver::%s - %s: %s", driver_func, alsa_func,
  301. snd_strerror(code));
  302. }
  303. bool
  304. JackALSARawMidiDriver::Init()
  305. {
  306. set_threaded_log_function();
  307. if (thread->AcquireSelfRealTime(fEngineControl->fServerPriority + 1)) {
  308. jack_error("JackALSARawMidiDriver::Init - could not acquire realtime "
  309. "scheduling. Continuing anyway.");
  310. }
  311. return true;
  312. }
  313. int
  314. JackALSARawMidiDriver::Open(bool capturing, bool playing, int in_channels,
  315. int out_channels, bool monitor,
  316. const char *capture_driver_name,
  317. const char *playback_driver_name,
  318. jack_nframes_t capture_latency,
  319. jack_nframes_t playback_latency)
  320. {
  321. snd_rawmidi_info_t *info;
  322. int code = snd_rawmidi_info_malloc(&info);
  323. if (code) {
  324. HandleALSAError("Open", "snd_rawmidi_info_malloc", code);
  325. return -1;
  326. }
  327. std::vector<snd_rawmidi_info_t *> in_info_list;
  328. std::vector<snd_rawmidi_info_t *> out_info_list;
  329. for (int card = -1;;) {
  330. int code = snd_card_next(&card);
  331. if (code) {
  332. HandleALSAError("Open", "snd_card_next", code);
  333. continue;
  334. }
  335. if (card == -1) {
  336. break;
  337. }
  338. char name[32];
  339. snprintf(name, sizeof(name), "hw:%d", card);
  340. snd_ctl_t *control;
  341. code = snd_ctl_open(&control, name, SND_CTL_NONBLOCK);
  342. if (code) {
  343. HandleALSAError("Open", "snd_ctl_open", code);
  344. continue;
  345. }
  346. for (int device = -1;;) {
  347. code = snd_ctl_rawmidi_next_device(control, &device);
  348. if (code) {
  349. HandleALSAError("Open", "snd_ctl_rawmidi_next_device", code);
  350. continue;
  351. }
  352. if (device == -1) {
  353. break;
  354. }
  355. snd_rawmidi_info_set_device(info, device);
  356. snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_INPUT);
  357. GetDeviceInfo(control, info, &in_info_list);
  358. snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_OUTPUT);
  359. GetDeviceInfo(control, info, &out_info_list);
  360. }
  361. snd_ctl_close(control);
  362. }
  363. snd_rawmidi_info_free(info);
  364. size_t potential_inputs = in_info_list.size();
  365. size_t potential_outputs = out_info_list.size();
  366. if (! (potential_inputs || potential_outputs)) {
  367. jack_error("JackALSARawMidiDriver::Open - no ALSA raw MIDI input or "
  368. "output ports found.");
  369. FreeDeviceInfo(&in_info_list, &out_info_list);
  370. return -1;
  371. }
  372. size_t num_inputs = 0;
  373. size_t num_outputs = 0;
  374. if (potential_inputs) {
  375. try {
  376. input_ports = new JackALSARawMidiInputPort *[potential_inputs];
  377. } catch (std::exception e) {
  378. jack_error("JackALSARawMidiDriver::Open - while creating input "
  379. "port array: %s", e.what());
  380. FreeDeviceInfo(&in_info_list, &out_info_list);
  381. return -1;
  382. }
  383. }
  384. if (potential_outputs) {
  385. try {
  386. output_ports = new JackALSARawMidiOutputPort *[potential_outputs];
  387. } catch (std::exception e) {
  388. jack_error("JackALSARawMidiDriver::Open - while creating output "
  389. "port array: %s", e.what());
  390. FreeDeviceInfo(&in_info_list, &out_info_list);
  391. goto delete_input_ports;
  392. }
  393. }
  394. for (size_t i = 0; i < potential_inputs; i++) {
  395. snd_rawmidi_info_t *info = in_info_list.at(i);
  396. try {
  397. input_ports[num_inputs] = new JackALSARawMidiInputPort(info, i);
  398. num_inputs++;
  399. } catch (std::exception e) {
  400. jack_error("JackALSARawMidiDriver::Open - while creating new "
  401. "JackALSARawMidiInputPort: %s", e.what());
  402. }
  403. snd_rawmidi_info_free(info);
  404. }
  405. for (size_t i = 0; i < potential_outputs; i++) {
  406. snd_rawmidi_info_t *info = out_info_list.at(i);
  407. try {
  408. output_ports[num_outputs] = new JackALSARawMidiOutputPort(info, i);
  409. num_outputs++;
  410. } catch (std::exception e) {
  411. jack_error("JackALSARawMidiDriver::Open - while creating new "
  412. "JackALSARawMidiOutputPort: %s", e.what());
  413. }
  414. snd_rawmidi_info_free(info);
  415. }
  416. if (! (num_inputs || num_outputs)) {
  417. jack_error("JackALSARawMidiDriver::Open - none of the potential "
  418. "inputs or outputs were successfully opened.");
  419. } else if (JackMidiDriver::Open(capturing, playing, num_inputs,
  420. num_outputs, monitor, capture_driver_name,
  421. playback_driver_name, capture_latency,
  422. playback_latency)) {
  423. jack_error("JackALSARawMidiDriver::Open - JackMidiDriver::Open error");
  424. } else {
  425. return 0;
  426. }
  427. if (output_ports) {
  428. for (size_t i = 0; i < num_outputs; i++) {
  429. delete output_ports[i];
  430. }
  431. delete[] output_ports;
  432. output_ports = 0;
  433. }
  434. delete_input_ports:
  435. if (input_ports) {
  436. for (size_t i = 0; i < num_inputs; i++) {
  437. delete input_ports[i];
  438. }
  439. delete[] input_ports;
  440. input_ports = 0;
  441. }
  442. return -1;
  443. }
  444. int
  445. JackALSARawMidiDriver::Read()
  446. {
  447. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  448. for (int i = 0; i < fCaptureChannels; i++) {
  449. if (! input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size)) {
  450. return -1;
  451. }
  452. }
  453. return 0;
  454. }
  455. int
  456. JackALSARawMidiDriver::Start()
  457. {
  458. jack_info("JackALSARawMidiDriver::Start - Starting 'alsarawmidi' driver.");
  459. JackMidiDriver::Start();
  460. poll_fd_count = 1;
  461. for (int i = 0; i < fCaptureChannels; i++) {
  462. poll_fd_count += input_ports[i]->GetPollDescriptorCount();
  463. }
  464. for (int i = 0; i < fPlaybackChannels; i++) {
  465. poll_fd_count += output_ports[i]->GetPollDescriptorCount();
  466. }
  467. try {
  468. poll_fds = new pollfd[poll_fd_count];
  469. } catch (std::exception e) {
  470. jack_error("JackALSARawMidiDriver::Start - creating poll descriptor "
  471. "structures failed: %s", e.what());
  472. return -1;
  473. }
  474. if (fPlaybackChannels) {
  475. try {
  476. output_port_timeouts = new jack_nframes_t[fPlaybackChannels];
  477. } catch (std::exception e) {
  478. jack_error("JackALSARawMidiDriver::Start - creating array for "
  479. "output port timeout values failed: %s", e.what());
  480. goto free_poll_descriptors;
  481. }
  482. }
  483. struct pollfd *poll_fd_iter;
  484. try {
  485. CreateNonBlockingPipe(fds);
  486. } catch (std::exception e) {
  487. jack_error("JackALSARawMidiDriver::Start - while creating wake pipe: "
  488. "%s", e.what());
  489. goto free_output_port_timeouts;
  490. }
  491. poll_fds[0].events = POLLERR | POLLIN | POLLNVAL;
  492. poll_fds[0].fd = fds[0];
  493. poll_fd_iter = poll_fds + 1;
  494. for (int i = 0; i < fCaptureChannels; i++) {
  495. JackALSARawMidiInputPort *input_port = input_ports[i];
  496. input_port->PopulatePollDescriptors(poll_fd_iter);
  497. poll_fd_iter += input_port->GetPollDescriptorCount();
  498. }
  499. for (int i = 0; i < fPlaybackChannels; i++) {
  500. JackALSARawMidiOutputPort *output_port = output_ports[i];
  501. output_port->PopulatePollDescriptors(poll_fd_iter);
  502. poll_fd_iter += output_port->GetPollDescriptorCount();
  503. output_port_timeouts[i] = 0;
  504. }
  505. jack_info("JackALSARawMidiDriver::Start - starting ALSA thread ...");
  506. if (! thread->StartSync()) {
  507. jack_info("JackALSARawMidiDriver::Start - started ALSA thread.");
  508. return 0;
  509. }
  510. jack_error("JackALSARawMidiDriver::Start - failed to start MIDI "
  511. "processing thread.");
  512. DestroyNonBlockingPipe(fds);
  513. fds[1] = -1;
  514. fds[0] = -1;
  515. free_output_port_timeouts:
  516. delete[] output_port_timeouts;
  517. output_port_timeouts = 0;
  518. free_poll_descriptors:
  519. delete[] poll_fds;
  520. poll_fds = 0;
  521. return -1;
  522. }
  523. int
  524. JackALSARawMidiDriver::Stop()
  525. {
  526. jack_info("JackALSARawMidiDriver::Stop - stopping 'alsarawmidi' driver.");
  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. SERVER_EXPORT jack_driver_desc_t *
  580. driver_get_descriptor()
  581. {
  582. // X: There could be parameters here regarding setting I/O buffer
  583. // sizes. I don't think MIDI drivers can accept parameters right
  584. // now without being set as the main driver.
  585. return jack_driver_descriptor_construct("alsarawmidi", "Alternative ALSA raw MIDI backend.", NULL);
  586. }
  587. SERVER_EXPORT Jack::JackDriverClientInterface *
  588. driver_initialize(Jack::JackLockedEngine *engine, Jack::JackSynchro *table,
  589. const JSList *params)
  590. {
  591. Jack::JackDriverClientInterface *driver =
  592. new Jack::JackALSARawMidiDriver("system_midi", "alsarawmidi",
  593. engine, table);
  594. if (driver->Open(1, 1, 0, 0, false, "midi in", "midi out", 0, 0)) {
  595. delete driver;
  596. driver = 0;
  597. }
  598. return driver;
  599. }
  600. #ifdef __cplusplus
  601. }
  602. #endif