jack1 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.

1184 lines
32KB

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