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.

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