1 /* sound-jack.c - play a sound over the Jack Audio Server
3 Copyright (C) 2006 Sebastian Freundt
5 This file is part of SXEmacs
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 SXEmacs 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 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 /* Synched up with: Not in FSF. */
36 #include "sound-jack.h"
40 #define MYSELF ADRIVER_JACK
41 #define SAMPLE_MAX_32BIT 2147483647.0f
42 #define SAMPLE_MAX_24BIT 8388607.0f
43 #define SAMPLE_MAX_16BIT 32767.0f
44 #define SAMPLE_MAX_8BIT 255.0f
46 static JMP_BUF jack_server_sig;
47 static int sound_jack_process(jack_nframes_t, void*);
48 static void sound_jack_shutdown_cbfun(void*);
49 static void sound_jack_error(const char*);
50 static void sound_jack_silence(float**, int, sound_jack_aj_data_t*);
51 static int sound_jack_write(float**, jack_nframes_t, audio_job_t);
52 static size_t demux_internal();
54 #define __JACK_DEBUG__(args...) fprintf(stderr, "JACK " args)
55 #ifndef JACK_DEBUG_FLAG
56 #define JACK_DEBUG(args...)
58 #define JACK_DEBUG(args...) __JACK_DEBUG__(args)
60 #define JACK_DEBUG_S(args...) JACK_DEBUG("[stream]: " args)
61 #define JACK_DEBUG_AJ(args...) JACK_DEBUG("[audio-job]: " args)
62 #define JACK_CRITICAL(args...) __JACK_DEBUG__("CRITICAL: " args)
65 DECLARE_AUDIO_DEVICE_SIMPLE_METHS(sound_jack);
66 DEFINE_AUDIO_DEVICE_SIMPLE(sound_jack);
70 sound_jack_mark(ad_device_data *devdata)
72 sound_jack_data_t *sjd = devdata;
74 mark_object(sjd->options);
75 mark_object(sjd->server);
81 sound_jack_print(Lisp_Object device, Lisp_Object pcfun, int ef)
83 sound_jack_data_t *sjd = NULL;
85 sjd = get_audio_device_data(device);
86 /* cannot use incomplete or corrupt audio devices */
87 if (XAUDIO_DEVICE_DRIVER(device) != MYSELF || sjd == NULL) {
88 write_c_string(" VOID", pcfun);
89 /* now that we are here, mark AO device as dead */
90 XAUDIO_DEVICE_STATE(device) = ASTATE_DEAD;
94 /* info about the connected output plugin */
95 write_c_string(" :server ", pcfun);
96 if (NILP(sjd->server))
97 write_c_string("#default", pcfun);
99 print_internal(sjd->server, pcfun, ef);
101 write_c_string(" :client ", pcfun);
102 if (NILP(sjd->client))
103 write_c_string("SXEmacs", pcfun);
105 print_internal(sjd->client, pcfun, ef);
111 static ad_device_data *
112 sound_jack_create(Lisp_Object jack_options)
115 sound_jack_data_t *sjd = NULL;
116 /* option keywords */
117 Lisp_Object opt_server = Qnil;
118 Lisp_Object opt_client = Qnil;
121 opt_server = Fplist_get(jack_options, intern(":server"), Qnil);
122 if (!NILP(opt_server) && !STRINGP(opt_server)) {
123 wrong_type_argument(Qstringp, opt_server);
127 opt_client = Fplist_get(jack_options, intern(":client"), Qnil);
128 if (!NILP(opt_client) && !STRINGP(opt_client)) {
129 wrong_type_argument(Qstringp, opt_client);
133 /* initialise and fill */
134 sjd = xnew_and_zero(sound_jack_data_t);
135 sjd->options = jack_options;
136 sjd->server = opt_server;
137 sjd->client = opt_client;
140 return (ad_device_data*)sjd;
144 sound_jack_finish(ad_device_data *data)
146 sound_jack_data_t *sjd = data;
155 static ad_device_data *
156 sound_jack_subthread_create(void)
159 sound_jack_aj_data_t *sjsd = NULL;
161 jack_client_t *client = NULL;
163 const char **ports = NULL;
166 /* Create a new playback client */
167 client = jack_client_open("SXEmacs", 0, NULL);
169 message(GETTEXT("audio-jack: "
170 "cannot open server."));
174 /* initialise and fill */
175 sjsd = xnew_and_zero(sound_jack_aj_data_t);
176 sjsd->client = client;
178 /* list matching ports */
179 port_flags |= JackPortIsInput;
180 port_flags |= JackPortIsPhysical;
181 ports = jack_get_ports(client, NULL, NULL, port_flags);
182 for (sjsd->num_ports = 0; ports && ports[sjsd->num_ports];
183 sjsd->num_ports++); /* just count */
184 if (!sjsd->num_ports) {
185 message(GETTEXT("audio-jack: "
186 "no physical ports available."));
187 jack_client_close(client);
192 JACK_DEBUG("initialised %d ports\n", sjsd->num_ports);
194 /* if (mtap->channels > sjsd->num_ports); */
196 /* create out output ports */
197 for (i = 0; i < sjsd->num_ports; i++) {
199 int sz = snprintf(pname, sizeof(pname), "SXEmacs out_%d", i);
200 assert(sz>=0 && sz<sizeof(pname));
201 sjsd->ports[i] = jack_port_register(
203 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
204 if (!sjsd->ports[i]) {
205 message(GETTEXT("audio-jack: "
206 "not enough ports available."));
207 jack_client_close(client);
213 sjsd->port_ptrs = ports;
215 return (ad_device_data*)sjsd;
219 sound_jack_play(audio_job_t aj)
222 mtype_audio_properties *mtap;
223 Lisp_Media_Stream *ms;
224 media_substream *mss;
227 Lisp_Audio_Device *lad = NULL;
228 sound_jack_data_t *sjd = NULL;
229 sound_jack_aj_data_t *sjsd = NULL;
233 SOUND_UNPACK_MT(aj, device, ms, mss, lad, sjd, mtap);
235 /* get jack device */
236 JACK_DEBUG("creating subthread.\n");
237 if ((sjsd = sound_jack_subthread_create()) == NULL) {
238 message(GETTEXT("audio-jack: "
239 "cannot create connection to jack server."));
243 /* initialise our callback semaphore */
244 SXE_SEMAPH_INIT(&(sjsd->sem));
246 if (SETJMP(jack_server_sig)) {
247 JACK_CRITICAL("Caught a lethal signal.\n");
250 GETTEXT("Jack daemon died or "
251 "send us a lethal signal! "
252 "This instance might have become a total mess! "
253 "Consider a restart."));
257 /* rewind the stream */
258 media_stream_meth(ms, rewind)(mss);
259 SXE_MUTEX_LOCK(&aj->mtx);
260 aj->buffer = xmalloc_atomic(SOUND_MAX_AUDIO_FRAME_SIZE);
261 aj->buffer_alloc_size = SOUND_MAX_AUDIO_FRAME_SIZE;
262 aj->resolution = (mtap->samplerate * MTPSTATE_REACT_TIME) / 1000000;
264 audio_job_device_data(aj) = sjsd;
265 sjsd->samplerate = mtap->samplerate;
266 sjsd->framesize = (sjsd->channels = mtap->channels) * sizeof(int32_t);
267 sjsd->demux_fun = demux_internal;
269 sjsd->ringbufcnt = SOUND_MAX_AUDIO_FRAME_SIZE >> 10;
270 sjsd->readpos = sjsd->writepos = sjsd->overfill = 0;
271 SXE_MUTEX_UNLOCK(&aj->mtx);
273 JACK_DEBUG("setting callback.\n");
274 jack_set_process_callback(sjsd->client, sound_jack_process, aj);
275 jack_set_error_function(sound_jack_error);
276 jack_on_shutdown(sjsd->client, sound_jack_shutdown_cbfun, aj);
279 if (jack_activate(sjsd->client)) {
280 message(GETTEXT("audio-jack: "
281 "activate failed."));
285 for (i = 0; i < sjsd->num_ports; i++) {
286 if (jack_connect(sjsd->client,
287 jack_port_name(sjsd->ports[i]),
288 sjsd->port_ptrs[i])) {
289 message(GETTEXT("audio-jack: "
290 "connecting failed."));
295 JACK_DEBUG("SEMAPHORE WAIT: 0x%x@0x%x@0x%x\n",
296 (unsigned int)&(sjsd->sem),
299 SXE_SEMAPH_SYNCH(&(sjsd->sem));
301 /* close and shutdown */
303 JACK_DEBUG("finish.\n");
305 jack_client_t *cli = sjsd->client;
306 JACK_DEBUG("DISC.\n");
308 for (i = 0; i < sjsd->num_ports; i++) {
310 jack_port_name(sjsd->ports[i]),
313 JACK_DEBUG("CLOSE.\n");
314 jack_client_close(cli);
317 SXE_SEMAPH_FINI(&(sjsd->sem));
319 SXE_MUTEX_LOCK(&aj->mtx);
328 aj->state = MTSTATE_FINISHED;
329 audio_job_device_data(aj) = NULL;
330 SXE_MUTEX_UNLOCK(&aj->mtx);
336 /* pull one channel out of a multi-channel stream */
338 demux_internal(float *dst, char *src,
339 size_t n, int chan, sound_jack_aj_data_t *f);
341 demux_internal(float *dst, char *src,
342 size_t n, int chan, sound_jack_aj_data_t *f)
344 /* dst: destination buffer */
345 /* src: source buffer */
346 /* n: number of samples */
347 /* chan: channel to frob */
348 int off = sizeof(int32_t)*chan;
349 int sr = f->samplerate;
350 int fs = f->framesize;
352 for (sxe_index_t i = 0; i < n; i++) {
353 /* compute frame number to serve */
354 int frame = i * sr/48000 * f->ratetrafo;
355 int srcp = frame*fs + off;
356 dst[i] = ((float)(*(int32_t*)(src+srcp)) / SAMPLE_MAX_24BIT)
360 /* actually read frames were n * samplerate / 48000 */
361 return n * sr/48000 * f->ratetrafo;
368 sound_jack_error(const char *errmsg)
370 JACK_CRITICAL("Strange things happened.\n"
371 "Error message: %s\n",
374 LONGJMP(jack_server_sig, 1);
379 /* shutdown callback */
381 sound_jack_shutdown_cbfun(void *arg)
383 JACK_CRITICAL("Shutdown: %p\n", arg);
385 LONGJMP(jack_server_sig, 1);
392 sound_jack_change_volume(audio_job_t aj, audio_job_event_args_t args)
394 SXE_MUTEX_LOCK(&aj->mtx);
395 aj->volume = args->volume_args;
396 SXE_MUTEX_UNLOCK(&aj->mtx);
400 sound_jack_change_rate(audio_job_t aj, audio_job_event_args_t args)
402 SXE_MUTEX_LOCK(&aj->mtx);
403 aj->ratetrafo = args->rate_args;
404 SXE_MUTEX_UNLOCK(&aj->mtx);
408 sound_jack_change_state(audio_job_t aj, audio_job_event_args_t args)
410 SXE_MUTEX_LOCK(&aj->mtx);
411 switch (args->state_args) {
413 JACK_DEBUG_AJ("->pause state\n");
414 aj->play_state = MTPSTATE_PAUSE;
417 JACK_DEBUG_AJ("->resume state\n");
418 aj->play_state = MTPSTATE_RUN;
421 JACK_DEBUG_AJ("->start state\n");
422 aj->play_state = MTPSTATE_RUN;
425 JACK_DEBUG_AJ("->stop state\n");
426 aj->play_state = MTPSTATE_STOP;
429 case no_audio_job_change_states:
431 JACK_DEBUG_AJ("->unknown state\n");
434 SXE_MUTEX_UNLOCK(&aj->mtx);
438 sound_jack_handle_aj_events(audio_job_t aj)
439 __attribute__((always_inline));
441 sound_jack_handle_aj_events(audio_job_t aj)
443 sound_jack_aj_data_t *sasd;
444 audio_job_event_t ev = NULL;
447 assert(audio_job_queue(aj));
450 SXE_MUTEX_LOCK(&aj->mtx);
451 sasd = audio_job_device_data(aj);
452 SXE_SET_UNUSED(sasd);
454 if ((ev = eq_noseeum_dequeue(audio_job_queue(aj))) == NULL) {
455 SXE_MUTEX_UNLOCK(&aj->mtx);
458 SXE_MUTEX_UNLOCK(&aj->mtx);
460 JACK_DEBUG_AJ("Event 0x%lx\n", (long unsigned int)ev);
461 switch (audio_job_event_kind(ev)) {
462 case aj_change_state:
463 JACK_DEBUG_AJ("change state event\n");
464 sound_jack_change_state(aj, &audio_job_event_args(ev));
466 case aj_change_volume:
467 JACK_DEBUG_AJ("change volume event\n");
468 sound_jack_change_volume(aj, &audio_job_event_args(ev));
471 JACK_DEBUG_AJ("change rate event\n");
472 sound_jack_change_rate(aj, &audio_job_event_args(ev));
475 case no_audio_job_event_kinds:
477 JACK_CRITICAL("unknown event %d\n", audio_job_event_kind(ev));
480 free_audio_job_event(ev);
482 #endif /* EF_USE_ASYNEQ */
485 * JACK Callback function
486 * - nframes number of frames to fill into buffers
487 * - arg contains the media subthread to operate on
490 sound_jack_process(jack_nframes_t nframes, void *userdata)
492 audio_job_t aj = NULL;
493 sound_jack_aj_data_t *sjsd = NULL;
494 media_substream *mss = NULL;
496 media_thread_play_state mtp;
497 float *bufs[MAX_CHANS];
501 SXE_MUTEX_LOCK(&aj->mtx);
505 sjsd = audio_job_device_data(aj);
507 SXE_SET_UNUSED(buffer);
510 /* stuff on the event queue? */
511 if (audio_job_queue(aj)) {
512 sound_jack_handle_aj_events(aj);
516 /* Set the playback volume of the stream */
517 if ((curvol = aj->volume) != sjsd->volume) {
518 sjsd->fvol = (float)curvol / MEDIA_SAMPLE_VOLUME_NORM;
519 sjsd->volume = curvol;
522 if (aj->ratetrafo != sjsd->ratetrafo) {
523 sjsd->ratetrafo = aj->ratetrafo;
526 for (int i = 0; i < sjsd->num_ports; i++) {
527 bufs[i] = jack_port_get_buffer(sjsd->ports[i], nframes);
530 mtp = aj->play_state;
533 sound_jack_write(bufs, nframes, aj);
536 sound_jack_silence(bufs, nframes, sjsd);
539 case MTPSTATE_UNKNOWN:
541 case NUMBER_OF_MEDIA_THREAD_PLAY_STATES:
543 JACK_DEBUG_S("DRAIN. MTP state:%d\n", mtp);
544 SXE_SEMAPH_TRIGGER(&(sjsd->sem));
547 SXE_MUTEX_UNLOCK(&aj->mtx);
552 * fill the buffers with silence
553 * - bufs num_bufs float buffers, each will contain the data of one channel
554 * - cnt number of samples in each buffer
555 * - num_bufs number of buffers
558 sound_jack_silence(float **bufs, int cnt, sound_jack_aj_data_t *sjsd)
561 for (i = 0; i < cnt; i++)
562 for (j = 0; j < sjsd->num_ports; j++)
567 sound_jack_write(float **bufs, jack_nframes_t nframes, audio_job_t aj)
569 sound_jack_aj_data_t *sjsd = audio_job_device_data(aj);
570 size_t len = 0, tmplen = 0, tmpcnt = 0;
571 sound_jack_demux_fun dmx = sjsd->demux_fun;
572 ms_read_fun __read = media_stream_meth(aj->substream->up, read);
574 /* cleanup buffer, move the frame overfill to the beginning */
575 if (sjsd->writepos < aj->buffer_alloc_size >> 1 &&
576 sjsd->underrun < 4) {
577 memcpy(aj->buffer, aj->buffer+sjsd->readpos,
578 sjsd->writepos - sjsd->readpos);
579 sjsd->writepos -= sjsd->readpos;
582 len = __read(aj->substream, aj->buffer+sjsd->writepos, nframes);
587 sjsd->overfill += len;
588 sjsd->writepos += len*sjsd->framesize;
590 /* increase underrun counter to detect the end */
593 } else if (sjsd->overfill > nframes << 2 ||
594 sjsd->underrun >= 4) {
595 JACK_DEBUG("having a rest\n");
597 JACK_DEBUG("resetting write position.\n");
598 memcpy(aj->buffer, aj->buffer+sjsd->readpos,
599 sjsd->writepos - sjsd->readpos);
600 sjsd->writepos -= sjsd->readpos;
604 JACK_DEBUG_S("req:%d p, got:%d p, readpos %d, writepos %d, "
605 "overfill: %d, framesize: %d, sr: %d\n",
606 nframes, len, sjsd->readpos, sjsd->writepos,
607 sjsd->overfill, sjsd->framesize, sjsd->samplerate);
609 /* care for buffer underruns */
610 if (nframes > sjsd->overfill)
611 tmplen = sjsd->overfill;
615 /* output, i loops over the number of ports we have to fill,
616 * while j loops over the actual channels */
617 for (int i = 0, j = 0; i < sjsd->num_ports; i++) {
619 bufs[i], aj->buffer+sjsd->readpos, tmplen, j, sjsd);
620 if (j < sjsd->channels) {
624 /* fill the rest with silence */
625 tmplen = nframes - tmplen;
627 JACK_DEBUG_S("fill up with silence\n");
628 sound_jack_silence(bufs, tmplen, sjsd);
631 /* modify readposition and overfill */
632 sjsd->readpos += tmpcnt * sjsd->framesize;
633 sjsd->overfill -= tmpcnt;
635 /* detect end of track */
636 if (sjsd->underrun >= 4 && sjsd->overfill < 64)
637 aj->play_state = MTPSTATE_STOP;
645 /* sound-jack.c ends here */