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.

320 lines
6.7KB

  1. #include <stdio.h>
  2. #include <errno.h>
  3. #include <unistd.h>
  4. #include <sndfile.h>
  5. #include <pthread.h>
  6. #include <glib.h>
  7. #include <jack/jack.h>
  8. typedef struct _thread_info {
  9. pthread_t thread_id;
  10. SNDFILE *sf;
  11. nframes_t duration;
  12. jack_client_t *client;
  13. unsigned int channels;
  14. int can_capture;
  15. char *path;
  16. int status;
  17. int process_go;
  18. } thread_info_t;
  19. unsigned int nports;
  20. jack_port_t **ports;
  21. pthread_mutex_t buffer_lock = PTHREAD_MUTEX_INITIALIZER;
  22. pthread_cond_t data_ready = PTHREAD_COND_INITIALIZER;
  23. typedef struct _sample_buffer {
  24. nframes_t nframes;
  25. sample_t **data;
  26. } sample_buffer_t;
  27. sample_buffer_t *
  28. sample_buffer_new (nframes_t nframes, unsigned int nchans)
  29. {
  30. sample_buffer_t *buf;
  31. unsigned int i;
  32. buf = (sample_buffer_t *) malloc (sizeof (sample_buffer_t));
  33. buf->nframes = nframes;
  34. buf->data = (sample_t **) malloc (sizeof (sample_t *) * nchans);
  35. for (i = 0; i < nchans; i++) {
  36. buf->data[i] = (sample_t *) malloc (sizeof (sample_t) * nframes);
  37. }
  38. return buf;
  39. }
  40. GSList *pending_writes = NULL;
  41. GSList *free_buffers = NULL;
  42. sample_buffer_t *
  43. get_free_buffer (nframes_t nframes, unsigned int nchans)
  44. {
  45. sample_buffer_t *buf;
  46. if (free_buffers == NULL) {
  47. buf = sample_buffer_new (nframes, nchans);
  48. } else {
  49. buf = (sample_buffer_t *) free_buffers->data;
  50. free_buffers = g_slist_next (free_buffers);
  51. }
  52. return buf;
  53. }
  54. sample_buffer_t *
  55. get_write_buffer ()
  56. {
  57. sample_buffer_t *buf;
  58. if (pending_writes == NULL) {
  59. return NULL;
  60. }
  61. buf = (sample_buffer_t *) pending_writes->data;
  62. pending_writes = g_slist_next (pending_writes);
  63. return buf;
  64. }
  65. void
  66. put_write_buffer (sample_buffer_t *buf)
  67. {
  68. pending_writes = g_slist_append (pending_writes, buf);
  69. }
  70. void
  71. put_free_buffer (sample_buffer_t *buf)
  72. {
  73. free_buffers = g_slist_prepend (free_buffers, buf);
  74. }
  75. void *
  76. disk_thread (void *arg)
  77. {
  78. sample_buffer_t *buf;
  79. thread_info_t *info = (thread_info_t *) arg;
  80. int i;
  81. unsigned int chn;
  82. nframes_t total_captured = 0;
  83. int done = 0;
  84. double *fbuf;
  85. pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  86. pthread_mutex_lock (&buffer_lock);
  87. /* preload the buffer cache */
  88. for (i = 0; i < 5; i++) {
  89. buf = sample_buffer_new (jack_get_buffer_size (info->client), info->channels);
  90. put_free_buffer (buf);
  91. }
  92. info->status = 0;
  93. while (!done) {
  94. pthread_cond_wait (&data_ready, &buffer_lock);
  95. while ((buf = get_write_buffer ()) != 0) {
  96. pthread_mutex_unlock (&buffer_lock);
  97. /* grrr ... libsndfile doesn't do float data yet, only double */
  98. if (info->can_capture) {
  99. fbuf = (double *) malloc (sizeof (double) * buf->nframes * info->channels);
  100. for (chn = 0; chn < info->channels; chn++) {
  101. for (i = 0; i < buf->nframes; i++) {
  102. fbuf[chn+(i*info->channels)] = buf->data[chn][i];
  103. }
  104. }
  105. if (sf_writef_double (info->sf, fbuf, buf->nframes, 1) != buf->nframes) {
  106. char errstr[256];
  107. sf_error_str (0, errstr, sizeof (errstr) - 1);
  108. fprintf (stderr, "cannot write data to sndfile (%s)\n", errstr);
  109. info->status = -1;
  110. done = 1;
  111. break;
  112. }
  113. free (fbuf);
  114. total_captured += buf->nframes;
  115. if (total_captured >= info->duration) {
  116. printf ("disk thread finished\n");
  117. done = 1;
  118. break;
  119. }
  120. }
  121. pthread_mutex_lock (&buffer_lock);
  122. put_free_buffer (buf);
  123. }
  124. }
  125. pthread_mutex_unlock (&buffer_lock);
  126. return 0;
  127. }
  128. int
  129. process (nframes_t nframes, void *arg)
  130. {
  131. thread_info_t *info = (thread_info_t *) arg;
  132. sample_t *in;
  133. sample_buffer_t *buf;
  134. unsigned int i;
  135. if (!info->process_go) {
  136. return 0;
  137. }
  138. pthread_mutex_lock (&buffer_lock);
  139. buf = get_free_buffer (nframes, nports);
  140. for (i = 0; i < nports; i++) {
  141. in = (sample_t *) jack_port_get_buffer (ports[i], nframes);
  142. memcpy (buf->data[i], in, sizeof (sample_t) * nframes);
  143. }
  144. /* we don't like taking locks, but until we have a lock
  145. free ringbuffer written in C, this is what has to be done
  146. */
  147. put_write_buffer (buf);
  148. /* tell the disk thread that there is work to do */
  149. pthread_cond_signal (&data_ready);
  150. pthread_mutex_unlock (&buffer_lock);
  151. return 0;
  152. }
  153. void
  154. jack_shutdown (void *arg)
  155. {
  156. fprintf (stderr, "JACK shutdown\n");
  157. exit (0);
  158. }
  159. void
  160. setup_disk_thread (thread_info_t *info)
  161. {
  162. SF_INFO sf_info;
  163. sf_info.samplerate = jack_get_sample_rate (info->client);
  164. sf_info.channels = info->channels;
  165. sf_info.format = SF_FORMAT_WAV|SF_FORMAT_PCM;
  166. sf_info.pcmbitwidth = 16;
  167. // sf_info.samples = info->duration * sf_info.samplerate;
  168. if ((info->sf = sf_open_write (info->path, &sf_info)) == NULL) {
  169. char errstr[256];
  170. sf_error_str (0, errstr, sizeof (errstr) - 1);
  171. fprintf (stderr, "cannot open sndfile \"%s\" for output (%s)\n", info->path, errstr);
  172. jack_client_close (info->client);
  173. exit (1);
  174. }
  175. info->duration = 2 * 48000;
  176. info->can_capture = 0;
  177. pthread_create (&info->thread_id, NULL, disk_thread, info);
  178. }
  179. void
  180. run_disk_thread (thread_info_t *info)
  181. {
  182. info->can_capture = 1;
  183. pthread_join (info->thread_id, NULL);
  184. sf_close (info->sf);
  185. if (info->status) {
  186. unlink (info->path);
  187. }
  188. }
  189. void
  190. setup_ports (int argc, char *argv[], thread_info_t *info)
  191. {
  192. char **source_names;
  193. int i;
  194. nports = argc - 2;
  195. source_names = (char **) malloc (sizeof (char **) * nports);
  196. ports = (jack_port_t **) malloc (sizeof (jack_port_t *) * nports);
  197. for (i = 2; i < argc; i++) {
  198. source_names[i-2] = argv[i];
  199. }
  200. for (i = 0; i < nports; i++) {
  201. char name[64];
  202. sprintf (name, "input%d\n", i+1);
  203. if ((ports[i] = jack_port_register (info->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == 0) {
  204. fprintf (stderr, "cannot register input port \"%s\"!\n", name);
  205. jack_client_close (info->client);
  206. exit (1);
  207. }
  208. }
  209. for (i = 0; i < nports; i++) {
  210. if (jack_port_connect (info->client, source_names[i], jack_port_name (ports[i]))) {
  211. fprintf (stderr, "cannot connect input port %s to %s\n", jack_port_name (ports[i]), source_names[i]);
  212. jack_client_close (info->client);
  213. exit (1);
  214. }
  215. }
  216. info->process_go = 1;
  217. free (source_names);
  218. }
  219. int
  220. main (int argc, char *argv[])
  221. {
  222. jack_client_t *client;
  223. thread_info_t thread_info;
  224. if (argc < 3) {
  225. fprintf (stderr, "usage: jackrec filename port1 [ port2 ... ]\n");
  226. return 1;
  227. }
  228. if ((client = jack_client_new ("jackrec")) == 0) {
  229. fprintf (stderr, "jack server not running?\n");
  230. return 1;
  231. }
  232. thread_info.client = client;
  233. thread_info.path = argv[1];
  234. thread_info.channels = argc - 2;
  235. thread_info.process_go = 0;
  236. setup_disk_thread (&thread_info);
  237. jack_set_process_callback (client, process, &thread_info);
  238. jack_on_shutdown (client, jack_shutdown, NULL);
  239. if (jack_activate (client)) {
  240. fprintf (stderr, "cannot activate client");
  241. }
  242. setup_ports (argc, argv, &thread_info);
  243. run_disk_thread (&thread_info);
  244. jack_client_close (client);
  245. exit (0);
  246. }