PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/jack-1.9.8/jack-1.9.8/linux/freebob/JackFreebobDriver.cpp

#
C++ | 1108 lines | 814 code | 196 blank | 98 comment | 130 complexity | ee4262ffaa978e4903ee69d56d002b2f MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. Copyright (C) 2001 Paul Davis
  3. Copyright (C) 2004 Grame
  4. Copyright (C) 2007 Pieter Palmers
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #include <iostream>
  18. #include <unistd.h>
  19. #include <math.h>
  20. #include <stdio.h>
  21. #include <memory.h>
  22. #include <unistd.h>
  23. #include <stdlib.h>
  24. #include <errno.h>
  25. #include <stdarg.h>
  26. #include <signal.h>
  27. #include <sys/types.h>
  28. #include <sys/time.h>
  29. #include <regex.h>
  30. #include <string.h>
  31. #include "JackFreebobDriver.h"
  32. #include "JackEngineControl.h"
  33. #include "JackClientControl.h"
  34. #include "JackPort.h"
  35. #include "JackGraphManager.h"
  36. #include "JackLockedEngine.h"
  37. namespace Jack
  38. {
  39. #define jack_get_microseconds GetMicroSeconds
  40. #define SAMPLE_MAX_24BIT 8388608.0f
  41. #define SAMPLE_MAX_16BIT 32768.0f
  42. int
  43. JackFreebobDriver::freebob_driver_read (freebob_driver_t * driver, jack_nframes_t nframes)
  44. {
  45. jack_default_audio_sample_t* buf = NULL;
  46. freebob_sample_t nullbuffer[nframes];
  47. void *addr_of_nullbuffer = (void *)nullbuffer;
  48. freebob_streaming_stream_type stream_type;
  49. printEnter();
  50. // make sure all buffers have a valid buffer if not connected
  51. for (unsigned int i = 0; i < driver->capture_nchannels; i++) {
  52. stream_type = freebob_streaming_get_playback_stream_type(driver->dev, i);
  53. if (stream_type == freebob_stream_type_audio) {
  54. freebob_streaming_set_playback_stream_buffer(driver->dev, i,
  55. (char *)(nullbuffer), freebob_buffer_type_float);
  56. } else if (stream_type == freebob_stream_type_midi) {
  57. // these should be read/written with the per-stream functions
  58. } else { // empty other buffers without doing something with them
  59. freebob_streaming_set_playback_stream_buffer(driver->dev, i,
  60. (char *)(nullbuffer), freebob_buffer_type_uint24);
  61. }
  62. }
  63. for (int i = 0; i < fCaptureChannels; i++) {
  64. stream_type = freebob_streaming_get_capture_stream_type(driver->dev, i);
  65. if (stream_type == freebob_stream_type_audio) {
  66. if (fGraphManager->GetConnectionsNum(fCapturePortList[i]) > 0) {
  67. buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[i], nframes);
  68. if (!buf) {
  69. buf = (jack_default_audio_sample_t *)addr_of_nullbuffer;
  70. }
  71. freebob_streaming_set_capture_stream_buffer(driver->dev, i, (char *)(buf), freebob_buffer_type_float);
  72. }
  73. } else if (stream_type == freebob_stream_type_midi) {
  74. // these should be read/written with the per-stream functions
  75. } else { // empty other buffers without doing something with them
  76. freebob_streaming_set_capture_stream_buffer(driver->dev, i, (char *)(nullbuffer), freebob_buffer_type_uint24);
  77. }
  78. }
  79. // now transfer the buffers
  80. freebob_streaming_transfer_capture_buffers(driver->dev);
  81. printExit();
  82. return 0;
  83. }
  84. int
  85. JackFreebobDriver::freebob_driver_write (freebob_driver_t * driver, jack_nframes_t nframes)
  86. {
  87. jack_default_audio_sample_t* buf = NULL;
  88. freebob_streaming_stream_type stream_type;
  89. freebob_sample_t nullbuffer[nframes];
  90. void *addr_of_nullbuffer = (void*)nullbuffer;
  91. memset(&nullbuffer, 0, nframes*sizeof(freebob_sample_t));
  92. printEnter();
  93. driver->process_count++;
  94. assert(driver->dev);
  95. // make sure all buffers output silence if not connected
  96. for (unsigned int i = 0; i < driver->playback_nchannels; i++) {
  97. stream_type = freebob_streaming_get_playback_stream_type(driver->dev, i);
  98. if (stream_type == freebob_stream_type_audio) {
  99. freebob_streaming_set_playback_stream_buffer(driver->dev, i,
  100. (char *)(nullbuffer), freebob_buffer_type_float);
  101. } else if (stream_type == freebob_stream_type_midi) {
  102. // these should be read/written with the per-stream functions
  103. } else { // empty other buffers without doing something with them
  104. freebob_streaming_set_playback_stream_buffer(driver->dev, i,
  105. (char *)(nullbuffer), freebob_buffer_type_uint24);
  106. }
  107. }
  108. for (int i = 0; i < fPlaybackChannels; i++) {
  109. stream_type = freebob_streaming_get_playback_stream_type(driver->dev, i);
  110. if (stream_type == freebob_stream_type_audio) {
  111. // Ouput ports
  112. if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
  113. buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[i], nframes);
  114. if (!buf) {
  115. buf = (jack_default_audio_sample_t *)addr_of_nullbuffer;
  116. }
  117. freebob_streaming_set_playback_stream_buffer(driver->dev, i, (char *)(buf), freebob_buffer_type_float);
  118. }
  119. }
  120. }
  121. freebob_streaming_transfer_playback_buffers(driver->dev);
  122. printExit();
  123. return 0;
  124. }
  125. jack_nframes_t
  126. JackFreebobDriver::freebob_driver_wait (freebob_driver_t *driver, int extra_fd, int *status,
  127. float *delayed_usecs)
  128. {
  129. int nframes;
  130. jack_time_t wait_enter;
  131. jack_time_t wait_ret;
  132. printEnter();
  133. wait_enter = jack_get_microseconds ();
  134. if (wait_enter > driver->wait_next) {
  135. /*
  136. * This processing cycle was delayed past the
  137. * next due interrupt! Do not account this as
  138. * a wakeup delay:
  139. */
  140. driver->wait_next = 0;
  141. driver->wait_late++;
  142. }
  143. // *status = -2; interrupt
  144. // *status = -3; timeout
  145. // *status = -4; extra FD
  146. nframes = freebob_streaming_wait(driver->dev);
  147. wait_ret = jack_get_microseconds ();
  148. if (driver->wait_next && wait_ret > driver->wait_next) {
  149. *delayed_usecs = wait_ret - driver->wait_next;
  150. }
  151. driver->wait_last = wait_ret;
  152. driver->wait_next = wait_ret + driver->period_usecs;
  153. // driver->engine->transport_cycle_start (driver->engine, wait_ret);
  154. if (nframes < 0) {
  155. *status = 0;
  156. return 0;
  157. }
  158. *status = 0;
  159. fBeginDateUst = wait_ret;
  160. // FIXME: this should do something more usefull
  161. *delayed_usecs = 0;
  162. printExit();
  163. return nframes - nframes % driver->period_size;
  164. }
  165. int
  166. JackFreebobDriver::freebob_driver_start (freebob_driver_t *driver)
  167. {
  168. int retval = 0;
  169. #ifdef FREEBOB_DRIVER_WITH_MIDI
  170. if (driver->midi_handle) {
  171. if ((retval = freebob_driver_midi_start(driver->midi_handle))) {
  172. printError("Could not start MIDI threads");
  173. return retval;
  174. }
  175. }
  176. #endif
  177. if ((retval = freebob_streaming_start(driver->dev))) {
  178. printError("Could not start streaming threads");
  179. #ifdef FREEBOB_DRIVER_WITH_MIDI
  180. if (driver->midi_handle) {
  181. freebob_driver_midi_stop(driver->midi_handle);
  182. }
  183. #endif
  184. return retval;
  185. }
  186. return 0;
  187. }
  188. int
  189. JackFreebobDriver::freebob_driver_stop (freebob_driver_t *driver)
  190. {
  191. int retval = 0;
  192. #ifdef FREEBOB_DRIVER_WITH_MIDI
  193. if (driver->midi_handle) {
  194. if ((retval = freebob_driver_midi_stop(driver->midi_handle))) {
  195. printError("Could not stop MIDI threads");
  196. return retval;
  197. }
  198. }
  199. #endif
  200. if ((retval = freebob_streaming_stop(driver->dev))) {
  201. printError("Could not stop streaming threads");
  202. return retval;
  203. }
  204. return 0;
  205. }
  206. int
  207. JackFreebobDriver::freebob_driver_restart (freebob_driver_t *driver)
  208. {
  209. if (Stop())
  210. return -1;
  211. return Start();
  212. }
  213. int
  214. JackFreebobDriver::SetBufferSize (jack_nframes_t nframes)
  215. {
  216. printError("Buffer size change requested but not supported!!!");
  217. /*
  218. driver->period_size = nframes;
  219. driver->period_usecs =
  220. (jack_time_t) floor ((((float) nframes) / driver->sample_rate)
  221. * 1000000.0f);
  222. */
  223. /* tell the engine to change its buffer size */
  224. //driver->engine->set_buffer_size (driver->engine, nframes);
  225. return -1; // unsupported
  226. }
  227. typedef void (*JackDriverFinishFunction) (jack_driver_t *);
  228. freebob_driver_t *
  229. JackFreebobDriver::freebob_driver_new (char *name,
  230. freebob_jack_settings_t *params)
  231. {
  232. freebob_driver_t *driver;
  233. assert(params);
  234. if (freebob_get_api_version() != 1) {
  235. printMessage("Incompatible libfreebob version! (%s)", freebob_get_version());
  236. return NULL;
  237. }
  238. printMessage("Starting Freebob backend (%s)", freebob_get_version());
  239. driver = (freebob_driver_t*)calloc (1, sizeof (freebob_driver_t));
  240. /* Setup the jack interfaces */
  241. jack_driver_nt_init ((jack_driver_nt_t *) driver);
  242. /* driver->nt_attach = (JackDriverNTAttachFunction) freebob_driver_attach;
  243. driver->nt_detach = (JackDriverNTDetachFunction) freebob_driver_detach;
  244. driver->nt_start = (JackDriverNTStartFunction) freebob_driver_start;
  245. driver->nt_stop = (JackDriverNTStopFunction) freebob_driver_stop;
  246. driver->nt_run_cycle = (JackDriverNTRunCycleFunction) freebob_driver_run_cycle;
  247. driver->null_cycle = (JackDriverNullCycleFunction) freebob_driver_null_cycle;
  248. driver->write = (JackDriverReadFunction) freebob_driver_write;
  249. driver->read = (JackDriverReadFunction) freebob_driver_read;
  250. driver->nt_bufsize = (JackDriverNTBufSizeFunction) freebob_driver_bufsize;
  251. */
  252. /* copy command line parameter contents to the driver structure */
  253. memcpy(&driver->settings, params, sizeof(freebob_jack_settings_t));
  254. /* prepare all parameters */
  255. driver->sample_rate = params->sample_rate;
  256. driver->period_size = params->period_size;
  257. fBeginDateUst = 0;
  258. driver->period_usecs =
  259. (jack_time_t) floor ((((float) driver->period_size) * 1000000.0f) / driver->sample_rate);
  260. // driver->client = client;
  261. driver->engine = NULL;
  262. memset(&driver->device_options, 0, sizeof(driver->device_options));
  263. driver->device_options.sample_rate = params->sample_rate;
  264. driver->device_options.period_size = params->period_size;
  265. driver->device_options.nb_buffers = params->buffer_size;
  266. driver->device_options.node_id = params->node_id;
  267. driver->device_options.port = params->port;
  268. driver->capture_frame_latency = params->capture_frame_latency;
  269. driver->playback_frame_latency = params->playback_frame_latency;
  270. if (!params->capture_ports) {
  271. driver->device_options.directions |= FREEBOB_IGNORE_CAPTURE;
  272. }
  273. if (!params->playback_ports) {
  274. driver->device_options.directions |= FREEBOB_IGNORE_PLAYBACK;
  275. }
  276. debugPrint(DEBUG_LEVEL_STARTUP, " Driver compiled on %s %s", __DATE__, __TIME__);
  277. debugPrint(DEBUG_LEVEL_STARTUP, " Created driver %s", name);
  278. debugPrint(DEBUG_LEVEL_STARTUP, " period_size: %d", driver->period_size);
  279. debugPrint(DEBUG_LEVEL_STARTUP, " period_usecs: %d", driver->period_usecs);
  280. debugPrint(DEBUG_LEVEL_STARTUP, " sample rate: %d", driver->sample_rate);
  281. return (freebob_driver_t *) driver;
  282. }
  283. void
  284. JackFreebobDriver::freebob_driver_delete (freebob_driver_t *driver)
  285. {
  286. free (driver);
  287. }
  288. #ifdef FREEBOB_DRIVER_WITH_MIDI
  289. /*
  290. * MIDI support
  291. */
  292. // the thread that will queue the midi events from the seq to the stream buffers
  293. void *
  294. JackFreebobDriver::freebob_driver_midi_queue_thread(void *arg)
  295. {
  296. freebob_driver_midi_handle_t *m = (freebob_driver_midi_handle_t *)arg;
  297. assert(m);
  298. snd_seq_event_t *ev;
  299. unsigned char work_buffer[MIDI_TRANSMIT_BUFFER_SIZE];
  300. int bytes_to_send;
  301. int b;
  302. int i;
  303. printMessage("MIDI queue thread started");
  304. while (1) {
  305. // get next event, if one is present
  306. while ((snd_seq_event_input(m->seq_handle, &ev) > 0)) {
  307. // get the port this event is originated from
  308. freebob_midi_port_t *port = NULL;
  309. for (i = 0;i < m->nb_output_ports;i++) {
  310. if (m->output_ports[i]->seq_port_nr == ev->dest.port) {
  311. port = m->output_ports[i];
  312. break;
  313. }
  314. }
  315. if (!port) {
  316. printError(" Could not find target port for event: dst=%d src=%d", ev->dest.port, ev->source.port);
  317. break;
  318. }
  319. // decode it to the work buffer
  320. if ((bytes_to_send = snd_midi_event_decode ( port->parser,
  321. work_buffer,
  322. MIDI_TRANSMIT_BUFFER_SIZE,
  323. ev)) < 0) { // failed
  324. printError(" Error decoding event for port %d (errcode=%d)", port->seq_port_nr, bytes_to_send);
  325. bytes_to_send = 0;
  326. //return -1;
  327. }
  328. for (b = 0;b < bytes_to_send;b++) {
  329. freebob_sample_t tmp_event = work_buffer[b];
  330. if (freebob_streaming_write(m->dev, port->stream_nr, &tmp_event, 1) < 1) {
  331. printError(" Midi send buffer overrun");
  332. }
  333. }
  334. }
  335. // sleep for some time
  336. usleep(MIDI_THREAD_SLEEP_TIME_USECS);
  337. }
  338. return NULL;
  339. }
  340. // the dequeue thread (maybe we need one thread per stream)
  341. void *
  342. JackFreebobDriver::freebob_driver_midi_dequeue_thread (void *arg)
  343. {
  344. freebob_driver_midi_handle_t *m = (freebob_driver_midi_handle_t *)arg;
  345. int i;
  346. int s;
  347. int samples_read;
  348. assert(m);
  349. while (1) {
  350. // read incoming events
  351. for (i = 0;i < m->nb_input_ports;i++) {
  352. unsigned int buff[64];
  353. freebob_midi_port_t *port = m->input_ports[i];
  354. if (!port) {
  355. printError(" something went wrong when setting up the midi input port map (%d)", i);
  356. }
  357. do {
  358. samples_read = freebob_streaming_read(m->dev, port->stream_nr, buff, 64);
  359. for (s = 0;s < samples_read;s++) {
  360. unsigned int *byte = (buff + s) ;
  361. snd_seq_event_t ev;
  362. if ((snd_midi_event_encode_byte(port->parser, (*byte) & 0xFF, &ev)) > 0) {
  363. // a midi message is complete, send it out to ALSA
  364. snd_seq_ev_set_subs(&ev);
  365. snd_seq_ev_set_direct(&ev);
  366. snd_seq_ev_set_source(&ev, port->seq_port_nr);
  367. snd_seq_event_output_direct(port->seq_handle, &ev);
  368. }
  369. }
  370. } while (samples_read > 0);
  371. }
  372. // sleep for some time
  373. usleep(MIDI_THREAD_SLEEP_TIME_USECS);
  374. }
  375. return NULL;
  376. }
  377. freebob_driver_midi_handle_t *
  378. JackFreebobDriver::freebob_driver_midi_init(freebob_driver_t *driver)
  379. {
  380. char buf[256];
  381. channel_t chn;
  382. int nchannels;
  383. int i = 0;
  384. freebob_device_t *dev = driver->dev;
  385. assert(dev);
  386. freebob_driver_midi_handle_t *m = calloc(1, sizeof(freebob_driver_midi_handle_t));
  387. if (!m) {
  388. printError("not enough memory to create midi structure");
  389. return NULL;
  390. }
  391. if (snd_seq_open(&m->seq_handle, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0) {
  392. printError("Error opening ALSA sequencer.");
  393. free(m);
  394. return NULL;
  395. }
  396. snd_seq_set_client_name(m->seq_handle, "FreeBoB Jack MIDI");
  397. // find out the number of midi in/out ports we need to setup
  398. nchannels = freebob_streaming_get_nb_capture_streams(dev);
  399. m->nb_input_ports = 0;
  400. for (chn = 0; chn < nchannels; chn++) {
  401. if (freebob_streaming_get_capture_stream_type(dev, chn) == freebob_stream_type_midi) {
  402. m->nb_input_ports++;
  403. }
  404. }
  405. m->input_ports = calloc(m->nb_input_ports, sizeof(freebob_midi_port_t *));
  406. if (!m->input_ports) {
  407. printError("not enough memory to create midi structure");
  408. free(m);
  409. return NULL;
  410. }
  411. i = 0;
  412. for (chn = 0; chn < nchannels; chn++) {
  413. if (freebob_streaming_get_capture_stream_type(dev, chn) == freebob_stream_type_midi) {
  414. m->input_ports[i] = calloc(1, sizeof(freebob_midi_port_t));
  415. if (!m->input_ports[i]) {
  416. // fixme
  417. printError("Could not allocate memory for seq port");
  418. continue;
  419. }
  420. freebob_streaming_get_capture_stream_name(dev, chn, buf, sizeof(buf));
  421. printMessage("Register MIDI IN port %s", buf);
  422. m->input_ports[i]->seq_port_nr = snd_seq_create_simple_port(m->seq_handle, buf,
  423. SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ,
  424. SND_SEQ_PORT_TYPE_MIDI_GENERIC);
  425. if (m->input_ports[i]->seq_port_nr < 0) {
  426. printError("Could not create seq port");
  427. m->input_ports[i]->stream_nr = -1;
  428. m->input_ports[i]->seq_port_nr = -1;
  429. } else {
  430. m->input_ports[i]->stream_nr = chn;
  431. m->input_ports[i]->seq_handle = m->seq_handle;
  432. if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(m->input_ports[i]->parser)) < 0) {
  433. printError("could not init parser for MIDI IN port %d", i);
  434. m->input_ports[i]->stream_nr = -1;
  435. m->input_ports[i]->seq_port_nr = -1;
  436. }
  437. }
  438. i++;
  439. }
  440. }
  441. // playback
  442. nchannels = freebob_streaming_get_nb_playback_streams(dev);
  443. m->nb_output_ports = 0;
  444. for (chn = 0; chn < nchannels; chn++) {
  445. if (freebob_streaming_get_playback_stream_type(dev, chn) == freebob_stream_type_midi) {
  446. m->nb_output_ports++;
  447. }
  448. }
  449. m->output_ports = calloc(m->nb_output_ports, sizeof(freebob_midi_port_t *));
  450. if (!m->output_ports) {
  451. printError("not enough memory to create midi structure");
  452. for (i = 0; i < m->nb_input_ports; i++) {
  453. free(m->input_ports[i]);
  454. }
  455. free(m->input_ports);
  456. free(m);
  457. return NULL;
  458. }
  459. i = 0;
  460. for (chn = 0; chn < nchannels; chn++) {
  461. if (freebob_streaming_get_playback_stream_type(dev, chn) == freebob_stream_type_midi) {
  462. m->output_ports[i] = calloc(1, sizeof(freebob_midi_port_t));
  463. if (!m->output_ports[i]) {
  464. // fixme
  465. printError("Could not allocate memory for seq port");
  466. continue;
  467. }
  468. freebob_streaming_get_playback_stream_name(dev, chn, buf, sizeof(buf));
  469. printMessage("Register MIDI OUT port %s", buf);
  470. m->output_ports[i]->seq_port_nr = snd_seq_create_simple_port(m->seq_handle, buf,
  471. SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
  472. SND_SEQ_PORT_TYPE_MIDI_GENERIC);
  473. if (m->output_ports[i]->seq_port_nr < 0) {
  474. printError("Could not create seq port");
  475. m->output_ports[i]->stream_nr = -1;
  476. m->output_ports[i]->seq_port_nr = -1;
  477. } else {
  478. m->output_ports[i]->stream_nr = chn;
  479. m->output_ports[i]->seq_handle = m->seq_handle;
  480. if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(m->output_ports[i]->parser)) < 0) {
  481. printError("could not init parser for MIDI OUT port %d", i);
  482. m->output_ports[i]->stream_nr = -1;
  483. m->output_ports[i]->seq_port_nr = -1;
  484. }
  485. }
  486. i++;
  487. }
  488. }
  489. m->dev = dev;
  490. m->driver = driver;
  491. return m;
  492. }
  493. int
  494. JackFreebobDriver::freebob_driver_midi_start (freebob_driver_midi_handle_t *m)
  495. {
  496. assert(m);
  497. // start threads
  498. m->queue_thread_realtime = (m->driver->engine->control->real_time ? 1 : 0);
  499. m->queue_thread_priority =
  500. m->driver->engine->control->client_priority +
  501. FREEBOB_RT_PRIORITY_MIDI_RELATIVE;
  502. if (m->queue_thread_priority > 98) {
  503. m->queue_thread_priority = 98;
  504. }
  505. if (m->queue_thread_realtime) {
  506. printMessage("MIDI threads running with Realtime scheduling, priority %d",
  507. m->queue_thread_priority);
  508. } else {
  509. printMessage("MIDI threads running without Realtime scheduling");
  510. }
  511. if (jack_client_create_thread(NULL, &m->queue_thread, m->queue_thread_priority, m->queue_thread_realtime, freebob_driver_midi_queue_thread, (void *)m)) {
  512. printError(" cannot create midi queueing thread");
  513. return -1;
  514. }
  515. if (jack_client_create_thread(NULL, &m->dequeue_thread, m->queue_thread_priority, m->queue_thread_realtime, freebob_driver_midi_dequeue_thread, (void *)m)) {
  516. printError(" cannot create midi dequeueing thread");
  517. return -1;
  518. }
  519. return 0;
  520. }
  521. int
  522. JackFreebobDriver::freebob_driver_midi_stop (freebob_driver_midi_handle_t *m)
  523. {
  524. assert(m);
  525. pthread_cancel (m->queue_thread);
  526. pthread_join (m->queue_thread, NULL);
  527. pthread_cancel (m->dequeue_thread);
  528. pthread_join (m->dequeue_thread, NULL);
  529. return 0;
  530. }
  531. void
  532. JackFreebobDriver::freebob_driver_midi_finish (freebob_driver_midi_handle_t *m)
  533. {
  534. assert(m);
  535. int i;
  536. // TODO: add state info here, if not stopped then stop
  537. for (i = 0;i < m->nb_input_ports;i++) {
  538. free(m->input_ports[i]);
  539. }
  540. free(m->input_ports);
  541. for (i = 0;i < m->nb_output_ports;i++) {
  542. free(m->output_ports[i]);
  543. }
  544. free(m->output_ports);
  545. free(m);
  546. }
  547. #endif
  548. int JackFreebobDriver::Attach()
  549. {
  550. JackPort* port;
  551. jack_port_id_t port_index;
  552. char buf[REAL_JACK_PORT_NAME_SIZE];
  553. char portname[REAL_JACK_PORT_NAME_SIZE];
  554. jack_latency_range_t range;
  555. freebob_driver_t* driver = (freebob_driver_t*)fDriver;
  556. jack_log("JackFreebobDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
  557. g_verbose = (fEngineControl->fVerbose ? 1 : 0);
  558. driver->device_options.verbose = (fEngineControl->fVerbose ? 1 : 0);
  559. /* packetizer thread options */
  560. driver->device_options.realtime = (fEngineControl->fRealTime ? 1 : 0);
  561. driver->device_options.packetizer_priority = fEngineControl->fServerPriority +
  562. FREEBOB_RT_PRIORITY_PACKETIZER_RELATIVE;
  563. if (driver->device_options.packetizer_priority > 98) {
  564. driver->device_options.packetizer_priority = 98;
  565. }
  566. // initialize the thread
  567. driver->dev = freebob_streaming_init(&driver->device_info, driver->device_options);
  568. if (!driver->dev) {
  569. printError("FREEBOB: Error creating virtual device");
  570. return -1;
  571. }
  572. #ifdef FREEBOB_DRIVER_WITH_MIDI
  573. driver->midi_handle = freebob_driver_midi_init(driver);
  574. if (!driver->midi_handle) {
  575. printError("-----------------------------------------------------------");
  576. printError("Error creating midi device!");
  577. printError("FreeBob will run without MIDI support.");
  578. printError("Consult the above error messages to solve the problem. ");
  579. printError("-----------------------------------------------------------\n\n");
  580. }
  581. #endif
  582. if (driver->device_options.realtime) {
  583. printMessage("Streaming thread running with Realtime scheduling, priority %d",
  584. driver->device_options.packetizer_priority);
  585. } else {
  586. printMessage("Streaming thread running without Realtime scheduling");
  587. }
  588. /* ports */
  589. // capture
  590. driver->capture_nchannels = freebob_streaming_get_nb_capture_streams(driver->dev);
  591. driver->capture_nchannels_audio = 0;
  592. for (unsigned int i = 0; i < driver->capture_nchannels; i++) {
  593. freebob_streaming_get_capture_stream_name(driver->dev, i, portname, sizeof(portname));
  594. snprintf(buf, sizeof(buf), "%s:%s", fClientControl.fName, portname);
  595. if (freebob_streaming_get_capture_stream_type(driver->dev, i) != freebob_stream_type_audio) {
  596. printMessage ("Don't register capture port %s", buf);
  597. } else {
  598. printMessage ("Registering capture port %s", buf);
  599. if (fEngine->PortRegister(fClientControl.fRefNum, buf,
  600. JACK_DEFAULT_AUDIO_TYPE,
  601. CaptureDriverFlags,
  602. fEngineControl->fBufferSize, &port_index) < 0) {
  603. jack_error("driver: cannot register port for %s", buf);
  604. return -1;
  605. }
  606. port = fGraphManager->GetPort(port_index);
  607. range.min = range.max = driver->period_size + driver->capture_frame_latency;
  608. port->SetLatencyRange(JackCaptureLatency, &range);
  609. fCapturePortList[i] = port_index;
  610. jack_log("JackFreebobDriver::Attach fCapturePortList[i] %ld ", port_index);
  611. driver->capture_nchannels_audio++;
  612. }
  613. }
  614. // playback
  615. driver->playback_nchannels = freebob_streaming_get_nb_playback_streams(driver->dev);
  616. driver->playback_nchannels_audio = 0;
  617. for (unsigned int i = 0; i < driver->playback_nchannels; i++) {
  618. freebob_streaming_get_playback_stream_name(driver->dev, i, portname, sizeof(portname));
  619. snprintf(buf, sizeof(buf), "%s:%s", fClientControl.fName, portname);
  620. if (freebob_streaming_get_playback_stream_type(driver->dev, i) != freebob_stream_type_audio) {
  621. printMessage ("Don't register playback port %s", buf);
  622. } else {
  623. printMessage ("Registering playback port %s", buf);
  624. if (fEngine->PortRegister(fClientControl.fRefNum, buf,
  625. JACK_DEFAULT_AUDIO_TYPE,
  626. PlaybackDriverFlags,
  627. fEngineControl->fBufferSize, &port_index) < 0) {
  628. jack_error("driver: cannot register port for %s", buf);
  629. return -1;
  630. }
  631. port = fGraphManager->GetPort(port_index);
  632. // Add one buffer more latency if "async" mode is used...
  633. range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency;
  634. port->SetLatencyRange(JackPlaybackLatency, &range);
  635. fPlaybackPortList[i] = port_index;
  636. jack_log("JackFreebobDriver::Attach fPlaybackPortList[i] %ld ", port_index);
  637. driver->playback_nchannels_audio++;
  638. }
  639. }
  640. fCaptureChannels = driver->capture_nchannels_audio;
  641. fPlaybackChannels = driver->playback_nchannels_audio;
  642. assert(fCaptureChannels < DRIVER_PORT_NUM);
  643. assert(fPlaybackChannels < DRIVER_PORT_NUM);
  644. // this makes no sense...
  645. assert(fCaptureChannels + fPlaybackChannels > 0);
  646. return 0;
  647. }
  648. int JackFreebobDriver::Detach()
  649. {
  650. freebob_driver_t* driver = (freebob_driver_t*)fDriver;
  651. jack_log("JackFreebobDriver::Detach");
  652. // finish the libfreebob streaming
  653. freebob_streaming_finish(driver->dev);
  654. driver->dev = NULL;
  655. #ifdef FREEBOB_DRIVER_WITH_MIDI
  656. if (driver->midi_handle) {
  657. freebob_driver_midi_finish(driver->midi_handle);
  658. }
  659. driver->midi_handle = NULL;
  660. #endif
  661. return JackAudioDriver::Detach(); // Generic JackAudioDriver Detach
  662. }
  663. int JackFreebobDriver::Open(freebob_jack_settings_t *params)
  664. {
  665. // Generic JackAudioDriver Open
  666. if (JackAudioDriver::Open(
  667. params->period_size, params->sample_rate,
  668. params->playback_ports, params->playback_ports,
  669. 0, 0, 0, "", "",
  670. params->capture_frame_latency, params->playback_frame_latency) != 0) {
  671. return -1;
  672. }
  673. fDriver = (jack_driver_t *)freebob_driver_new ((char*)"freebob_pcm", params);
  674. if (fDriver) {
  675. // FreeBoB driver may have changed the in/out values
  676. fCaptureChannels = ((freebob_driver_t *)fDriver)->capture_nchannels_audio;
  677. fPlaybackChannels = ((freebob_driver_t *)fDriver)->playback_nchannels_audio;
  678. return 0;
  679. } else {
  680. JackAudioDriver::Close();
  681. return -1;
  682. }
  683. }
  684. int JackFreebobDriver::Close()
  685. {
  686. // Generic audio driver close
  687. int res = JackAudioDriver::Close();
  688. freebob_driver_delete((freebob_driver_t*)fDriver);
  689. return res;
  690. }
  691. int JackFreebobDriver::Start()
  692. {
  693. int res = JackAudioDriver::Start();
  694. if (res >= 0) {
  695. res = freebob_driver_start((freebob_driver_t *)fDriver);
  696. if (res < 0) {
  697. JackAudioDriver::Stop();
  698. }
  699. }
  700. return res;
  701. }
  702. int JackFreebobDriver::Stop()
  703. {
  704. int res = freebob_driver_stop((freebob_driver_t *)fDriver);
  705. if (JackAudioDriver::Stop() < 0) {
  706. res = -1;
  707. }
  708. return res;
  709. }
  710. int JackFreebobDriver::Read()
  711. {
  712. printEnter();
  713. /* Taken from freebob_driver_run_cycle */
  714. freebob_driver_t* driver = (freebob_driver_t*)fDriver;
  715. int wait_status = 0;
  716. fDelayedUsecs = 0.f;
  717. retry:
  718. jack_nframes_t nframes = freebob_driver_wait (driver, -1, &wait_status,
  719. &fDelayedUsecs);
  720. if ((wait_status < 0)) {
  721. printError( "wait status < 0! (= %d)", wait_status);
  722. return -1;
  723. }
  724. if (nframes == 0) {
  725. /* we detected an xrun and restarted: notify
  726. * clients about the delay.
  727. */
  728. jack_log("FreeBoB XRun");
  729. NotifyXRun(fBeginDateUst, fDelayedUsecs);
  730. goto retry; /* recoverable error*/
  731. }
  732. if (nframes != fEngineControl->fBufferSize)
  733. jack_log("JackFreebobDriver::Read warning nframes = %ld", nframes);
  734. // Has to be done before read
  735. JackDriver::CycleIncTime();
  736. printExit();
  737. return freebob_driver_read((freebob_driver_t *)fDriver, fEngineControl->fBufferSize);
  738. }
  739. int JackFreebobDriver::Write()
  740. {
  741. printEnter();
  742. int res = freebob_driver_write((freebob_driver_t *)fDriver, fEngineControl->fBufferSize);
  743. printExit();
  744. return res;
  745. }
  746. void
  747. JackFreebobDriver::jack_driver_init (jack_driver_t *driver)
  748. {
  749. memset (driver, 0, sizeof (*driver));
  750. driver->attach = 0;
  751. driver->detach = 0;
  752. driver->write = 0;
  753. driver->read = 0;
  754. driver->null_cycle = 0;
  755. driver->bufsize = 0;
  756. driver->start = 0;
  757. driver->stop = 0;
  758. }
  759. void
  760. JackFreebobDriver::jack_driver_nt_init (jack_driver_nt_t * driver)
  761. {
  762. memset (driver, 0, sizeof (*driver));
  763. jack_driver_init ((jack_driver_t *) driver);
  764. driver->attach = 0;
  765. driver->detach = 0;
  766. driver->bufsize = 0;
  767. driver->stop = 0;
  768. driver->start = 0;
  769. driver->nt_bufsize = 0;
  770. driver->nt_start = 0;
  771. driver->nt_stop = 0;
  772. driver->nt_attach = 0;
  773. driver->nt_detach = 0;
  774. driver->nt_run_cycle = 0;
  775. }
  776. } // end of namespace
  777. #ifdef __cplusplus
  778. extern "C"
  779. {
  780. #endif
  781. const jack_driver_desc_t *
  782. driver_get_descriptor () {
  783. jack_driver_desc_t * desc;
  784. jack_driver_desc_filler_t filler;
  785. jack_driver_param_value_t value;
  786. desc = jack_driver_descriptor_construct("freebob", JackDriverMaster, "Linux FreeBob API based audio backend", &filler);
  787. strcpy(value.str, "hw:0");
  788. jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "The FireWire device to use. Format is: 'hw:port[,node]'.", NULL);
  789. value.ui = 1024;
  790. jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
  791. value.ui = 3;
  792. jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods of playback latency", NULL);
  793. value.ui = 48000U;
  794. jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
  795. value.i = 0;
  796. jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamBool, &value, NULL, "Provide capture ports.", NULL);
  797. jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamBool, &value, NULL, "Provide playback ports.", NULL);
  798. value.i = 1;
  799. jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports.", NULL);
  800. value.ui = 0;
  801. jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency (frames)", NULL);
  802. jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency (frames)", NULL);
  803. value.ui = 0;
  804. jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Number of input channels to provide (note: currently ignored)", NULL);
  805. jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Number of output channels to provide (note: currently ignored)", NULL);
  806. return desc;
  807. }
  808. Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) {
  809. unsigned int port = 0;
  810. unsigned int node_id = -1;
  811. int nbitems;
  812. const JSList * node;
  813. const jack_driver_param_t * param;
  814. freebob_jack_settings_t cmlparams;
  815. const char *device_name = "hw:0";
  816. cmlparams.period_size_set = 0;
  817. cmlparams.sample_rate_set = 0;
  818. cmlparams.buffer_size_set = 0;
  819. cmlparams.port_set = 0;
  820. cmlparams.node_id_set = 0;
  821. /* default values */
  822. cmlparams.period_size = 1024;
  823. cmlparams.sample_rate = 48000;
  824. cmlparams.buffer_size = 3;
  825. cmlparams.port = 0;
  826. cmlparams.node_id = -1;
  827. cmlparams.playback_ports = 0;
  828. cmlparams.capture_ports = 0;
  829. cmlparams.playback_frame_latency = 0;
  830. cmlparams.capture_frame_latency = 0;
  831. for (node = params; node; node = jack_slist_next (node)) {
  832. param = (jack_driver_param_t *) node->data;
  833. switch (param->character) {
  834. case 'd':
  835. device_name = param->value.str;
  836. break;
  837. case 'p':
  838. cmlparams.period_size = param->value.ui;
  839. cmlparams.period_size_set = 1;
  840. break;
  841. case 'n':
  842. cmlparams.buffer_size = param->value.ui;
  843. cmlparams.buffer_size_set = 1;
  844. break;
  845. case 'r':
  846. cmlparams.sample_rate = param->value.ui;
  847. cmlparams.sample_rate_set = 1;
  848. break;
  849. case 'C':
  850. cmlparams.capture_ports = 1;
  851. break;
  852. case 'P':
  853. cmlparams.playback_ports = 1;
  854. break;
  855. case 'D':
  856. cmlparams.capture_ports = 1;
  857. cmlparams.playback_ports = 1;
  858. break;
  859. case 'I':
  860. cmlparams.capture_frame_latency = param->value.ui;
  861. break;
  862. case 'O':
  863. cmlparams.playback_frame_latency = param->value.ui;
  864. break;
  865. // ignore these for now
  866. case 'i':
  867. break;
  868. case 'o':
  869. break;
  870. }
  871. }
  872. /* duplex is the default */
  873. if (!cmlparams.playback_ports && !cmlparams.capture_ports) {
  874. cmlparams.playback_ports = TRUE;
  875. cmlparams.capture_ports = TRUE;
  876. }
  877. nbitems = sscanf(device_name, "hw:%u,%u", &port, &node_id);
  878. if (nbitems < 2) {
  879. nbitems = sscanf(device_name, "hw:%u", &port);
  880. if (nbitems < 1) {
  881. printError("device (-d) argument not valid\n");
  882. return NULL;
  883. } else {
  884. cmlparams.port = port;
  885. cmlparams.port_set = 1;
  886. cmlparams.node_id = -1;
  887. cmlparams.node_id_set = 0;
  888. }
  889. } else {
  890. cmlparams.port = port;
  891. cmlparams.port_set = 1;
  892. cmlparams.node_id = node_id;
  893. cmlparams.node_id_set = 1;
  894. }
  895. jack_error("Freebob using Firewire port %d, node %d", cmlparams.port, cmlparams.node_id);
  896. Jack::JackFreebobDriver* freebob_driver = new Jack::JackFreebobDriver("system", "freebob_pcm", engine, table);
  897. Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(freebob_driver);
  898. // Special open for FreeBoB driver...
  899. if (freebob_driver->Open(&cmlparams) == 0) {
  900. return threaded_driver;
  901. } else {
  902. delete threaded_driver; // Delete the decorated driver
  903. return NULL;
  904. }
  905. }
  906. #ifdef __cplusplus
  907. }
  908. #endif