e3df4d28fc86ca8839826dcbdbf34b2e2ac39e04
[alsa-plugins.git] / jack / pcm_jack.c
1 /*
2  *  PCM - JACK plugin
3  *
4  *  Copyright (c) 2003 by Maarten de Boer <mdeboer@iua.upf.es>
5  *                2005 Takashi Iwai <tiwai@suse.de>
6  *
7  *   This library is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU Lesser General Public License as
9  *   published by the Free Software Foundation; either version 2.1 of
10  *   the License, or (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU Lesser General Public License for more details.
16  *
17  *   You should have received a copy of the GNU Lesser General Public
18  *   License along with this library; if not, write to the Free Software
19  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 #include <stdbool.h>
24 #include <byteswap.h>
25 #include <sys/shm.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <jack/jack.h>
29 #include <alsa/asoundlib.h>
30 #include <alsa/pcm_external.h>
31
32 typedef enum _jack_format {
33         SND_PCM_JACK_FORMAT_RAW
34 } snd_pcm_jack_format_t;
35
36 typedef struct {
37         snd_pcm_ioplug_t io;
38
39         int fd;
40         int activated;          /* jack is activated? */
41
42         char **port_names;
43         unsigned int num_ports;
44         snd_pcm_uframes_t boundary;
45         snd_pcm_uframes_t hw_ptr;
46         unsigned int sample_bits;
47         snd_pcm_uframes_t min_avail;
48
49         unsigned int channels;
50         snd_pcm_channel_area_t *areas;
51
52         jack_port_t **ports;
53         jack_client_t *client;
54
55         /* JACK thread -> ALSA thread */
56         bool xrun_detected;
57 } snd_pcm_jack_t;
58
59 static int snd_pcm_jack_stop(snd_pcm_ioplug_t *io);
60
61
62 static int pcm_poll_block_check(snd_pcm_ioplug_t *io)
63 {
64         static char buf[32];
65         snd_pcm_sframes_t avail;
66         snd_pcm_jack_t *jack = io->private_data;
67
68         if (io->state == SND_PCM_STATE_RUNNING ||
69             (io->state == SND_PCM_STATE_PREPARED && io->stream == SND_PCM_STREAM_CAPTURE)) {
70                 avail = snd_pcm_avail_update(io->pcm);
71                 if (avail >= 0 && avail < jack->min_avail) {
72                         while (read(io->poll_fd, &buf, sizeof(buf)) == sizeof(buf))
73                                 ;
74                         return 1;
75                 }
76         }
77
78         return 0;
79 }
80
81 static int pcm_poll_unblock_check(snd_pcm_ioplug_t *io)
82 {
83         static char buf[1];
84         snd_pcm_sframes_t avail;
85         snd_pcm_jack_t *jack = io->private_data;
86
87         avail = snd_pcm_avail_update(io->pcm);
88         if (avail < 0 || avail >= jack->min_avail) {
89                 write(jack->fd, &buf, 1);
90                 return 1;
91         }
92
93         return 0;
94 }
95
96 static void snd_pcm_jack_free(snd_pcm_jack_t *jack)
97 {
98         if (jack) {
99                 unsigned int i;
100                 if (jack->client)
101                         jack_client_close(jack->client);
102                 if (jack->port_names) {
103                         for (i = 0; i < jack->num_ports; i++)
104                                 free(jack->port_names[i]);
105                         free(jack->port_names);
106                 }
107                 if (jack->fd >= 0)
108                         close(jack->fd);
109                 if (jack->io.poll_fd >= 0)
110                         close(jack->io.poll_fd);
111                 free(jack->areas);
112                 free(jack->ports);
113                 free(jack);
114         }
115 }
116
117 static int snd_pcm_jack_close(snd_pcm_ioplug_t *io)
118 {
119         snd_pcm_jack_t *jack = io->private_data;
120         snd_pcm_jack_free(jack);
121         return 0;
122 }
123
124 static int snd_pcm_jack_poll_revents(snd_pcm_ioplug_t *io,
125                                      struct pollfd *pfds, unsigned int nfds,
126                                      unsigned short *revents)
127 {
128         assert(pfds && nfds == 1 && revents);
129
130         *revents = pfds[0].revents & ~(POLLIN | POLLOUT);
131         if (pfds[0].revents & POLLIN && !pcm_poll_block_check(io))
132                 *revents |= (io->stream == SND_PCM_STREAM_PLAYBACK) ? POLLOUT : POLLIN;
133         return 0;
134 }
135
136 static snd_pcm_sframes_t snd_pcm_jack_pointer(snd_pcm_ioplug_t *io)
137 {
138         snd_pcm_jack_t *jack = io->private_data;
139
140         if (jack->xrun_detected)
141                 return -EPIPE;
142
143 #ifdef SND_PCM_IOPLUG_FLAG_BOUNDARY_WA
144         return jack->hw_ptr;
145 #else
146         return jack->hw_ptr % io->buffer_size;
147 #endif
148 }
149
150 static int
151 snd_pcm_jack_process_cb(jack_nframes_t nframes, snd_pcm_ioplug_t *io)
152 {
153         snd_pcm_jack_t *jack = io->private_data;
154         snd_pcm_uframes_t xfer = 0;
155         unsigned int channel;
156         
157         for (channel = 0; channel < io->channels; channel++) {
158                 jack->areas[channel].addr = 
159                         jack_port_get_buffer (jack->ports[channel], nframes);
160                 jack->areas[channel].first = 0;
161                 jack->areas[channel].step = jack->sample_bits;
162         }
163
164         if (io->state == SND_PCM_STATE_RUNNING) {
165                 snd_pcm_uframes_t hw_ptr = jack->hw_ptr;
166                 const snd_pcm_uframes_t hw_avail = snd_pcm_ioplug_hw_avail(io, hw_ptr,
167                                                                            io->appl_ptr);
168
169                 if (hw_avail > 0) {
170                         const snd_pcm_channel_area_t *areas = snd_pcm_ioplug_mmap_areas(io);
171                         const snd_pcm_uframes_t offset = hw_ptr % io->buffer_size;
172
173                         xfer = nframes;
174                         if (xfer > hw_avail)
175                                 xfer = hw_avail;
176
177                         if (io->stream == SND_PCM_STREAM_PLAYBACK)
178                                 snd_pcm_areas_copy_wrap(jack->areas, 0, nframes,
179                                                         areas, offset,
180                                                         io->buffer_size,
181                                                         io->channels, xfer,
182                                                         io->format);
183                         else
184                                 snd_pcm_areas_copy_wrap(areas, offset,
185                                                         io->buffer_size,
186                                                         jack->areas, 0, nframes,
187                                                         io->channels, xfer,
188                                                         io->format);
189
190                         hw_ptr += xfer;
191                         if (hw_ptr >= jack->boundary)
192                                 hw_ptr -= jack->boundary;
193                         jack->hw_ptr = hw_ptr;
194                 }
195         }
196
197         /* check if requested frames were copied */
198         if (xfer < nframes) {
199                 /* always fill the not yet written JACK buffer with silence */
200                 if (io->stream == SND_PCM_STREAM_PLAYBACK) {
201                         const snd_pcm_uframes_t frames = nframes - xfer;
202
203                         snd_pcm_areas_silence(jack->areas, xfer, io->channels,
204                                               frames, io->format);
205                 }
206
207                 if (io->state == SND_PCM_STATE_PREPARED) {
208                         /* After activating this JACK client with
209                          * jack_activate() this process callback will be called.
210                          * But the processing of snd_pcm_jack_start() would take
211                          * a while longer due to the jack_connect() calls.
212                          * Therefore the device was already started
213                          * but it is not yet in RUNNING state.
214                          * Due to this expected behaviour it is not an Xrun.
215                          */
216                 } else {
217                         /* report Xrun to user application */
218                         jack->xrun_detected = true;
219                 }
220         }
221
222         pcm_poll_unblock_check(io); /* unblock socket for polling if needed */
223
224         return 0;
225 }
226
227 static int snd_pcm_jack_prepare(snd_pcm_ioplug_t *io)
228 {
229         snd_pcm_jack_t *jack = io->private_data;
230         unsigned int i;
231         snd_pcm_sw_params_t *swparams;
232         int err;
233
234         jack->hw_ptr = 0;
235         jack->xrun_detected = false;
236
237         jack->min_avail = io->period_size;
238         snd_pcm_sw_params_alloca(&swparams);
239         err = snd_pcm_sw_params_current(io->pcm, swparams);
240         if (err == 0) {
241                 snd_pcm_sw_params_get_avail_min(swparams, &jack->min_avail);
242                 /* get boundary for available calulation */
243                 snd_pcm_sw_params_get_boundary(swparams, &jack->boundary);
244         }
245
246         /* deactivate jack connections if this is XRUN recovery */
247         snd_pcm_jack_stop(io);
248
249         if (io->stream == SND_PCM_STREAM_PLAYBACK)
250                 pcm_poll_unblock_check(io); /* playback pcm initially accepts writes */
251         else
252                 pcm_poll_block_check(io); /* block capture pcm if that's XRUN recovery */
253
254         if (jack->ports)
255                 return 0;
256
257         jack->ports = calloc(io->channels, sizeof(jack_port_t*));
258
259         for (i = 0; i < io->channels; i++) {
260                 char port_name[32];
261                 if (io->stream == SND_PCM_STREAM_PLAYBACK) {
262
263                         sprintf(port_name, "out_%03d", i);
264                         jack->ports[i] = jack_port_register(jack->client, port_name,
265                                                             JACK_DEFAULT_AUDIO_TYPE,
266                                                             JackPortIsOutput, 0);
267                 } else {
268                         sprintf(port_name, "in_%03d", i);
269                         jack->ports[i] = jack_port_register(jack->client, port_name,
270                                                             JACK_DEFAULT_AUDIO_TYPE,
271                                                             JackPortIsInput, 0);
272                 }
273         }
274
275         jack_set_process_callback(jack->client,
276                                   (JackProcessCallback)snd_pcm_jack_process_cb, io);
277         return 0;
278 }
279
280 static int snd_pcm_jack_start(snd_pcm_ioplug_t *io)
281 {
282         snd_pcm_jack_t *jack = io->private_data;
283         unsigned int i;
284         
285         if (jack_activate (jack->client))
286                 return -EIO;
287
288         jack->activated = 1;
289
290         for (i = 0; i < io->channels && i < jack->num_ports; i++) {
291                 if (jack->port_names[i]) {
292                         const char *src, *dst;
293                         if (io->stream == SND_PCM_STREAM_PLAYBACK) {
294                                 src = jack_port_name(jack->ports[i]);
295                                 dst = jack->port_names[i];
296                         } else {
297                                 src = jack->port_names[i];
298                                 dst = jack_port_name(jack->ports[i]);
299                         }
300                         if (jack_connect(jack->client, src, dst)) {
301                                 fprintf(stderr, "cannot connect %s to %s\n", src, dst);
302                                 return -EIO;
303                         }
304                 }
305         }
306         
307         return 0;
308 }
309
310 static int snd_pcm_jack_stop(snd_pcm_ioplug_t *io)
311 {
312         snd_pcm_jack_t *jack = io->private_data;
313         
314         if (jack->activated) {
315                 jack_deactivate(jack->client);
316                 jack->activated = 0;
317         }
318 #if 0
319         unsigned i;
320         for (i = 0; i < io->channels; i++) {
321                 if (jack->ports[i]) {
322                         jack_port_unregister(jack->client, jack->ports[i]);
323                         jack->ports[i] = NULL;
324                 }
325         }
326 #endif
327         return 0;
328 }
329
330 static snd_pcm_ioplug_callback_t jack_pcm_callback = {
331         .close = snd_pcm_jack_close,
332         .start = snd_pcm_jack_start,
333         .stop = snd_pcm_jack_stop,
334         .pointer = snd_pcm_jack_pointer,
335         .prepare = snd_pcm_jack_prepare,
336         .poll_revents = snd_pcm_jack_poll_revents,
337 };
338
339 #define ARRAY_SIZE(ary) (sizeof(ary)/sizeof(ary[0]))
340
341 static int jack_set_hw_constraint(snd_pcm_jack_t *jack)
342 {
343         unsigned int access_list[] = {
344                 SND_PCM_ACCESS_MMAP_INTERLEAVED,
345                 SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
346                 SND_PCM_ACCESS_RW_INTERLEAVED,
347                 SND_PCM_ACCESS_RW_NONINTERLEAVED
348         };
349         unsigned int format = SND_PCM_FORMAT_FLOAT;
350         unsigned int rate = jack_get_sample_rate(jack->client);
351         int err;
352
353         jack->sample_bits = snd_pcm_format_physical_width(format);
354         if ((err = snd_pcm_ioplug_set_param_list(&jack->io, SND_PCM_IOPLUG_HW_ACCESS,
355                                                  ARRAY_SIZE(access_list), access_list)) < 0 ||
356             (err = snd_pcm_ioplug_set_param_list(&jack->io, SND_PCM_IOPLUG_HW_FORMAT,
357                                                  1, &format)) < 0 ||
358             (err = snd_pcm_ioplug_set_param_minmax(&jack->io, SND_PCM_IOPLUG_HW_CHANNELS,
359                                                    jack->channels, jack->channels)) < 0 ||
360             (err = snd_pcm_ioplug_set_param_minmax(&jack->io, SND_PCM_IOPLUG_HW_RATE,
361                                                    rate, rate)) < 0 ||
362             (err = snd_pcm_ioplug_set_param_minmax(&jack->io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
363                                                    128, 64*1024)) < 0 ||
364             (err = snd_pcm_ioplug_set_param_minmax(&jack->io, SND_PCM_IOPLUG_HW_PERIODS,
365                                                    2, 64)) < 0)
366                 return err;
367
368         return 0;
369 }
370
371 static int parse_ports(snd_pcm_jack_t *jack, snd_config_t *conf)
372 {
373         snd_config_iterator_t i, next;
374         char **ports = NULL;
375         unsigned int cnt = 0;
376         unsigned int channel;
377
378         if (conf) {
379                 snd_config_for_each(i, next, conf) {
380                         snd_config_t *n = snd_config_iterator_entry(i);
381                         const char *id;
382                         if (snd_config_get_id(n, &id) < 0)
383                                 continue;
384                         cnt++;
385                 }
386                 jack->port_names = ports = calloc(cnt, sizeof(char*));
387                 if (ports == NULL)
388                         return -ENOMEM;
389                 jack->num_ports = cnt;
390                 snd_config_for_each(i, next, conf) {
391                         snd_config_t *n = snd_config_iterator_entry(i);
392                         const char *id;
393                         const char *port;
394
395                         if (snd_config_get_id(n, &id) < 0)
396                                 continue;
397                         channel = atoi(id);
398                         if (snd_config_get_string(n, &port) < 0)
399                                 continue;
400                         ports[channel] = port ? strdup(port) : NULL;
401                 }
402         }
403         return 0;
404 }
405
406 static int make_nonblock(int fd)
407 {
408         int fl;
409
410         if ((fl = fcntl(fd, F_GETFL)) < 0)
411                 return fl;
412
413         if (fl & O_NONBLOCK)
414                 return 0;
415
416         return fcntl(fd, F_SETFL, fl | O_NONBLOCK);
417 }
418
419 static int snd_pcm_jack_open(snd_pcm_t **pcmp, const char *name,
420                              const char *client_name,
421                              snd_config_t *playback_conf,
422                              snd_config_t *capture_conf,
423                              snd_pcm_stream_t stream, int mode)
424 {
425         snd_pcm_jack_t *jack;
426         int err;
427         int fd[2];
428         static unsigned int num = 0;
429         char jack_client_name[32];
430         
431         assert(pcmp);
432         jack = calloc(1, sizeof(*jack));
433         if (!jack)
434                 return -ENOMEM;
435
436         jack->fd = -1;
437         jack->io.poll_fd = -1;
438
439         err = parse_ports(jack, stream == SND_PCM_STREAM_PLAYBACK ?
440                           playback_conf : capture_conf);
441         if (err) {
442                 snd_pcm_jack_free(jack);
443                 return err;
444         }
445
446         jack->channels = jack->num_ports;
447         if (jack->channels == 0) {
448                 SNDERR("define the %s_ports section",
449                        stream == SND_PCM_STREAM_PLAYBACK ? "playback" : "capture");
450                 snd_pcm_jack_free(jack);
451                 return -EINVAL;
452         }
453
454         if (client_name == NULL)
455                 err = snprintf(jack_client_name, sizeof(jack_client_name),
456                                "alsa-jack.%s%s.%d.%d", name,
457                                stream == SND_PCM_STREAM_PLAYBACK ? "P" : "C",
458                                getpid(), num++);
459         else
460                 err = snprintf(jack_client_name, sizeof(jack_client_name),
461                                "%s", client_name);
462
463         if (err >= (int)sizeof(jack_client_name)) {
464                 fprintf(stderr, "%s: WARNING: JACK client name '%s' truncated to %d characters, might not be unique\n",
465                         __func__, jack_client_name, (int)strlen(jack_client_name));
466         }
467
468         jack->client = jack_client_open(jack_client_name, JackNoStartServer, NULL);
469
470         if (jack->client == 0) {
471                 snd_pcm_jack_free(jack);
472                 return -ENOENT;
473         }
474
475         jack->areas = calloc(jack->channels, sizeof(snd_pcm_channel_area_t));
476         if (! jack->areas) {
477                 snd_pcm_jack_free(jack);
478                 return -ENOMEM;
479         }
480
481         socketpair(AF_LOCAL, SOCK_STREAM, 0, fd);
482         
483         make_nonblock(fd[0]);
484         make_nonblock(fd[1]);
485
486         jack->fd = fd[0];
487
488         jack->io.version = SND_PCM_IOPLUG_VERSION;
489         jack->io.name = "ALSA <-> JACK PCM I/O Plugin";
490         jack->io.callback = &jack_pcm_callback;
491         jack->io.private_data = jack;
492         jack->io.poll_fd = fd[1];
493         jack->io.poll_events = POLLIN;
494         jack->io.mmap_rw = 1;
495
496 #ifdef SND_PCM_IOPLUG_FLAG_BOUNDARY_WA
497         jack->io.flags = SND_PCM_IOPLUG_FLAG_BOUNDARY_WA;
498 #else
499 #warning hw_ptr updates of buffer_size will not be recognized by the ALSA library. Consider to update your ALSA library.
500 #endif
501
502         err = snd_pcm_ioplug_create(&jack->io, name, stream, mode);
503         if (err < 0) {
504                 snd_pcm_jack_free(jack);
505                 return err;
506         }
507
508         err = jack_set_hw_constraint(jack);
509         if (err < 0) {
510                 snd_pcm_ioplug_delete(&jack->io);
511                 return err;
512         }
513
514         *pcmp = jack->io.pcm;
515
516         return 0;
517 }
518
519
520 SND_PCM_PLUGIN_DEFINE_FUNC(jack)
521 {
522         snd_config_iterator_t i, next;
523         snd_config_t *playback_conf = NULL;
524         snd_config_t *capture_conf = NULL;
525         const char *client_name = NULL;
526         int err;
527         
528         snd_config_for_each(i, next, conf) {
529                 snd_config_t *n = snd_config_iterator_entry(i);
530                 const char *id;
531                 if (snd_config_get_id(n, &id) < 0)
532                         continue;
533                 if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0 || strcmp(id, "hint") == 0)
534                         continue;
535                 if (strcmp(id, "name") == 0) {
536                         snd_config_get_string(n, &client_name);
537                         continue;
538                 }
539                 if (strcmp(id, "playback_ports") == 0) {
540                         if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
541                                 SNDERR("Invalid type for %s", id);
542                                 return -EINVAL;
543                         }
544                         playback_conf = n;
545                         continue;
546                 }
547                 if (strcmp(id, "capture_ports") == 0) {
548                         if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
549                                 SNDERR("Invalid type for %s", id);
550                                 return -EINVAL;
551                         }
552                         capture_conf = n;
553                         continue;
554                 }
555                 SNDERR("Unknown field %s", id);
556                 return -EINVAL;
557         }
558
559         err = snd_pcm_jack_open(pcmp, name, client_name, playback_conf, capture_conf, stream, mode);
560
561         return err;
562 }
563
564 SND_PCM_PLUGIN_SYMBOL(jack);