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.

622 lines
20KB

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