1 /* sound-pulse.c - play a sound over the Pulse Audio Server
3 Copyright (C) 2006, 2007, 2008 Sebastian Freundt
5 Author: Sebastian Freundt <hroptatyr@sxemacs.org>
7 * This file is part of SXEmacs.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the author nor the names of any contributors
21 * may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 /* Synched up with: Not in FSF. */
53 #include "sound-pulse.h"
57 #define MYSELF ADRIVER_PULSE
59 #define __PULSE_DEBUG__(args...) fprintf(stderr, "PULSE " args)
60 #ifndef PULSE_DEBUG_FLAG
61 #define PULSE_DEBUG(args...)
63 #define PULSE_DEBUG(args...) __PULSE_DEBUG__(args)
65 #define PULSE_DEBUG_CTX(args...) PULSE_DEBUG("[connection]: " args)
66 #define PULSE_DEBUG_ML(args...) PULSE_DEBUG("[mainloop]: " args)
67 #define PULSE_DEBUG_MX(args...) PULSE_DEBUG("[semaphore]: " args)
68 #define PULSE_DEBUG_S(args...) PULSE_DEBUG("[stream]: " args)
69 #define PULSE_DEBUG_PT(args...) PULSE_DEBUG("[pthread]: " args)
70 #define PULSE_DEBUG_COE(args...) PULSE_DEBUG("[coerce]: " args)
71 #define PULSE_DEBUG_AJ(args...) PULSE_DEBUG("[audio-job]: " args)
72 #define PULSE_DEBUG_CACHE(args...) PULSE_DEBUG("[cache]: " args)
73 #define PULSE_CRITICAL(args...) __PULSE_DEBUG__("CRITICAL: " args)
76 static int sound_pulse_init_mainloop(ad_device_data*);
78 time_ev_cb(pa_mainloop_api*, pa_time_event*, const struct timeval*, void*);
80 struct sound_pulse_data_s {
81 Lisp_Object stream; /* media has to deal with this actually */
88 pa_threaded_mainloop *tml;
90 pa_mainloop_api *mlapi;
92 const pa_sink_info *sink_info;
93 struct sxe_semaphore_s ctxsem;
96 struct sound_pulse_aj_data_s {
99 struct pa_sample_spec sampspec;
100 struct pa_channel_map chanmap;
101 pa_buffer_attr buffattr;
106 pa_time_event *time_ev;
109 media_sample_format_t *msf;
111 audio_coerce_chain_t coe_chain[4];
112 sxe_mse_rerate_args *rrargs;
116 DECLARE_AUDIO_DEVICE_SIMPLE_METHS(sound_pulse);
117 DEFINE_AUDIO_DEVICE_SIMPLE(sound_pulse);
121 sound_pulse_mark(ad_device_data *devdata)
123 sound_pulse_data_t spd = (sound_pulse_data_t)devdata;
127 mark_object(spd->stream);
128 mark_object(spd->client);
129 mark_object(spd->sink);
130 mark_object(spd->source);
131 mark_object(spd->server);
136 sound_pulse_print(Lisp_Object device, Lisp_Object pcfun, int ef)
138 sound_pulse_data_t spd = NULL;
139 pa_context_state_t st;
141 spd = get_audio_device_data(device);
142 /* cannot use incomplete or corrupt audio devices */
143 if (XAUDIO_DEVICE_DRIVER(device) != MYSELF || spd == NULL) {
144 write_c_string(" VOID", pcfun);
145 /* now that we are here, mark AO device as dead */
146 XAUDIO_DEVICE_STATE(device) = ASTATE_DEAD;
150 /* info about the connected output plugin */
151 write_c_string(" :server ", pcfun);
152 if (NILP(spd->server))
153 write_c_string("#default", pcfun);
155 print_internal(spd->server, pcfun, ef);
157 write_c_string(" :sink ", pcfun);
158 if (NILP(spd->sink)) {
159 write_c_string("#default", pcfun);
161 print_internal(spd->sink, pcfun, ef);
165 if (spd->sink_info) {
166 write_c_string(" (", pcfun);
167 write_c_string(spd->sink_info->description, pcfun);
168 write_c_string(")", pcfun);
170 write_c_string(" (sink does not exist)", pcfun);
174 write_c_string(" :source ", pcfun);
175 if (NILP(spd->source))
176 write_c_string("#default", pcfun);
178 print_internal(spd->source, pcfun, ef);
180 write_c_string(" :server-state ", pcfun);
183 write_c_string("#b0rked", pcfun);
187 st = pa_context_get_state(spd->ctx);
188 switch ((unsigned int)st) {
189 case PA_CONTEXT_CONNECTING:
190 case PA_CONTEXT_AUTHORIZING:
191 case PA_CONTEXT_SETTING_NAME:
192 write_c_string("#busy", pcfun);
195 case PA_CONTEXT_READY:
196 write_c_string("#connected", pcfun);
199 case PA_CONTEXT_TERMINATED:
200 write_c_string("#terminated", pcfun);
203 case PA_CONTEXT_FAILED:
205 write_c_string("#failed", pcfun);
209 write_c_string(" :api ", pcfun);
210 if (spd->ml_threaded_p) {
211 write_fmt_str(pcfun, "#threaded :mainloop 0x%lx",
212 (long unsigned int)spd->tml);
214 write_fmt_str(pcfun, "#non-threaded :mainloop 0x%lx",
215 (long unsigned int)spd->ml);
221 static ad_device_data *
222 sound_pulse_create(Lisp_Object pulse_options)
225 sound_pulse_data_t spd = NULL;
226 /* option keywords */
227 Lisp_Object opt_server = Qnil;
228 Lisp_Object opt_sink = Qnil;
229 Lisp_Object opt_source = Qnil;
230 Lisp_Object opt_client = Qnil;
231 Lisp_Object opt_stream = Qnil;
232 Lisp_Object opt_immediate = Qnil;
233 Lisp_Object opt_threaded = Qnil;
234 Lisp_Object opt_force = Qnil;
237 opt_server = Fplist_get(pulse_options, intern(":server"), Qnil);
238 if (!NILP(opt_server) && !STRINGP(opt_server)) {
239 wrong_type_argument(Qstringp, opt_server);
243 opt_sink = Fplist_get(pulse_options, intern(":sink"), Qnil);
244 if (!NILP(opt_sink) && !STRINGP(opt_sink)) {
245 wrong_type_argument(Qstringp, opt_sink);
249 opt_client = Fplist_get(pulse_options, intern(":client"), Qnil);
250 if (!NILP(opt_client) && !STRINGP(opt_client)) {
251 wrong_type_argument(Qstringp, opt_client);
255 opt_stream = Fplist_get(pulse_options, intern(":stream"), Qnil);
256 if (!NILP(opt_stream) && !STRINGP(opt_stream)) {
257 wrong_type_argument(Qstringp, opt_stream);
261 opt_immediate = Fplist_get(pulse_options, intern(":immediate"), Qt);
262 opt_threaded = Fplist_get(pulse_options, intern(":threaded"), Qt);
263 opt_force = Fplist_get(pulse_options, intern(":force"), Qnil);
265 /* initialise and fill */
266 spd = xnew_and_zero(struct sound_pulse_data_s);
267 spd->server = opt_server;
268 spd->client = opt_client;
269 spd->sink = opt_sink;
270 spd->source = opt_source;
271 spd->stream = opt_stream;
273 spd->ml_threaded_p = !NILP(opt_threaded);
275 if (NILP(opt_immediate))
276 return (ad_device_data*)spd;
278 sound_pulse_init_mainloop(spd);
280 if (spd->ml_running_p == 0) /* yeah, finish immediately */
281 sound_pulse_finish(spd);
283 if (NILP(opt_force) && spd->ml_running_p == 0) {
286 error(GETTEXT("Error: audio-pulse: "
287 "Initialising connection to PulseAudio failed."));
291 return (ad_device_data*)spd;
295 sound_pulse_finish(ad_device_data *data)
297 sound_pulse_data_t spd = data;
301 if (spd != NULL && 0) {
309 spd->ml_running_p = 0;
311 /* setting this to 0 is not enough? :\ */
313 PULSE_DEBUG_CTX("DRAIN.\n");
314 pa_context_drain(spd->ctx, NULL, NULL);
315 PULSE_DEBUG_CTX("STOP.\n");
316 pa_context_disconnect(spd->ctx);
317 pa_context_unref(spd->ctx);
318 SXE_SEMAPH_FINI(&(spd->ctxsem));
322 PULSE_DEBUG_ML("Is there a mainloop awake?\n");
323 if (spd->ml_threaded_p) {
325 PULSE_DEBUG_ML("STOP.\n");
326 pa_threaded_mainloop_stop(spd->tml);
327 PULSE_DEBUG_ML("FREE. bye bye\n");
328 pa_threaded_mainloop_free(spd->tml);
334 PULSE_DEBUG_ML("FREE. bye bye (non-threaded)\n");
335 pa_mainloop_free(spd->ml);
340 PULSE_DEBUG_CTX("finish.\n");
348 /** Wait until the specified operation completes */
349 #define wait_for_operation(_m, _o) \
351 struct pa_operation *__o = (_o); \
352 while (pa_operation_get_state(__o) == \
353 PA_OPERATION_RUNNING) \
354 pa_mainloop_iterate((_m), 1, NULL); \
355 pa_operation_unref(__o); \
358 /** Wait until no further actions are pending on the connection context */
359 #define wait_for_completion(_c, _m) \
361 while (pa_context_is_pending(_c)) \
362 pa_mainloop_iterate((_m), 1, NULL); \
367 my_pa_free_cb(void *data)
369 /* dummy callback which ought to free DATA,
370 * however, we want to recycle the memory as much as possible,
371 * we free it ourselves */
372 PULSE_DEBUG_S("my_pa_free_cb called 0x%lx\n",
373 (long unsigned int)data);
378 static inline pa_volume_t
379 _sound_pulse_change_volume(
380 pa_cvolume *cvolp, pa_context *ctx,
381 pa_stream *stream, pa_volume_t volume)
382 __attribute__((always_inline));
383 static inline pa_volume_t
384 _sound_pulse_change_volume(
385 pa_cvolume *cvolp, pa_context *ctx,
386 pa_stream *stream, pa_volume_t volume)
390 pa_cvolume_set(cvolp, cvolp->channels,
391 (volume*PA_VOLUME_NORM)/MEDIA_SAMPLE_VOLUME_NORM);
393 if (!(o = pa_context_set_sink_input_volume(
394 ctx, pa_stream_get_index(stream), cvolp, NULL, NULL))) {
395 PULSE_CRITICAL("Cannot set volume.\n");
397 pa_operation_unref(o);
402 /* handling of events from the audio job's private queue */
405 sound_pulse_stop(audio_job_t aj)
406 __attribute__((always_inline));
408 sound_pulse_stop(audio_job_t aj)
410 sound_pulse_aj_data_t spsd;
413 SXE_MUTEX_LOCK(&aj->mtx);
414 spsd = audio_job_device_data(aj);
415 stream = spsd->stream;
416 PULSE_DEBUG_S("FLUSH. (0x%lx)\n", (long unsigned int)aj);
417 pa_operation_unref(pa_stream_flush(stream, NULL, NULL));
418 pa_stream_disconnect(stream);
419 aj->play_state = MTPSTATE_STOP;
420 SXE_MUTEX_UNLOCK(&aj->mtx);
425 sound_pulse_pause(audio_job_t aj)
426 __attribute__((always_inline));
428 sound_pulse_pause(audio_job_t aj)
430 sound_pulse_aj_data_t spsd;
431 sound_pulse_data_t spd;
435 SXE_MUTEX_LOCK(&aj->mtx);
436 spd = get_audio_device_data(aj->device);
437 spsd = audio_job_device_data(aj);
438 stream = spsd->stream;
439 PULSE_DEBUG_S("CORK. (0x%lx)\n", (long unsigned int)aj);
440 pa_operation_unref(pa_stream_cork(stream, 1, NULL, NULL));
441 aj->play_state = MTPSTATE_PAUSE;
443 if (audio_job_queue(aj)) {
444 spsd->time_ev = spd->mlapi->
445 time_new(spd->mlapi, &tv, time_ev_cb, aj);
448 SXE_MUTEX_UNLOCK(&aj->mtx);
453 sound_pulse_resume(audio_job_t aj)
454 __attribute__((always_inline));
456 sound_pulse_resume(audio_job_t aj)
458 sound_pulse_aj_data_t spsd;
459 sound_pulse_data_t spd;
462 SXE_MUTEX_LOCK(&aj->mtx);
463 spd = get_audio_device_data(aj->device);
464 spsd = audio_job_device_data(aj);
465 stream = spsd->stream;
466 PULSE_DEBUG_S("UNCORK. (0x%lx)\n", (long unsigned int)aj);
469 spd->mlapi->time_free(spsd->time_ev);
470 spsd->time_ev = NULL;
473 pa_operation_unref(pa_stream_cork(stream, 0, NULL, NULL));
474 aj->play_state = MTPSTATE_RUN;
475 SXE_MUTEX_UNLOCK(&aj->mtx);
480 sound_pulse_change_volume(audio_job_t aj, audio_job_event_args_t args)
482 sound_pulse_aj_data_t spsd;
483 pa_volume_t new_vol = args->volume_args;
485 PULSE_DEBUG_AJ("->%d\n", (int)new_vol);
487 SXE_MUTEX_LOCK(&aj->mtx);
488 spsd = audio_job_device_data(aj);
489 spsd->volume = _sound_pulse_change_volume(
490 &spsd->chanvol, spsd->ctx, spsd->stream, new_vol);
491 aj->volume = (int)(spsd->volume);
492 SXE_MUTEX_UNLOCK(&aj->mtx);
496 sound_pulse_change_rate(audio_job_t aj, audio_job_event_args_t args)
498 SXE_MUTEX_LOCK(&aj->mtx);
499 aj->ratetrafo = args->rate_args;
500 SXE_MUTEX_UNLOCK(&aj->mtx);
504 sound_pulse_change_state(audio_job_t aj, audio_job_event_args_t args)
506 switch (args->state_args) {
508 PULSE_DEBUG_AJ("->pause state\n");
509 sound_pulse_pause(aj);
512 PULSE_DEBUG_AJ("->resume state\n");
513 sound_pulse_resume(aj);
516 PULSE_DEBUG_AJ("->start state\n");
519 PULSE_DEBUG_AJ("->stop state\n");
520 sound_pulse_stop(aj);
523 case no_audio_job_change_states:
525 PULSE_DEBUG_AJ("->unknown state\n");
531 sound_pulse_handle_aj_events(audio_job_t aj)
532 __attribute__((always_inline));
534 sound_pulse_handle_aj_events(audio_job_t aj)
536 sound_pulse_aj_data_t spsd;
538 audio_job_event_t ev = NULL;
541 #if defined EF_USE_ASYNEQ
542 if (audio_job_queue(aj)) {
543 assert((long unsigned int)audio_job_queue(aj) != 0xB16B00B5);
547 PULSE_DEBUG_AJ("handle aj events called on 0x%lx\n",
548 (long unsigned int)aj);
550 SXE_MUTEX_LOCK(&aj->mtx);
551 spsd = audio_job_device_data(aj);
552 eq = audio_job_queue(aj);
553 SXE_MUTEX_UNLOCK(&aj->mtx);
554 stream = spsd->stream;
555 if ((ev = eq_noseeum_dequeue(eq)) == NULL) {
558 if (stream == NULL || pa_stream_get_state(stream) != PA_STREAM_READY) {
562 PULSE_DEBUG_AJ("Event 0x%lx\n", (long unsigned int)ev);
563 switch (audio_job_event_kind(ev)) {
564 case aj_change_state:
565 PULSE_DEBUG_AJ("change state event\n");
566 sound_pulse_change_state(aj, &audio_job_event_args(ev));
568 case aj_change_volume:
569 PULSE_DEBUG_AJ("change volume event\n");
570 sound_pulse_change_volume(aj, &audio_job_event_args(ev));
573 PULSE_DEBUG_AJ("change rate event\n");
574 sound_pulse_change_rate(aj, &audio_job_event_args(ev));
577 case no_audio_job_event_kinds:
579 PULSE_CRITICAL("unknown event\n");
582 free_audio_job_event(ev);
586 time_ev_cb(pa_mainloop_api *m, pa_time_event *e,
587 const struct timeval *tv, void *userdata)
589 /* check an audio-job's queue for incoming events */
590 struct timeval next; /* for rescheduling this construction */
591 audio_job_t aj = userdata;
592 sound_pulse_aj_data_t spsd = audio_job_device_data(aj);;
594 sound_pulse_handle_aj_events(userdata);
596 if (spsd->time_ev != NULL) {
597 /* reschedule the thing */
598 pa_gettimeofday(&next);
599 pa_timeval_add(&next, 25000);
600 m->time_restart(e, &next);
603 #endif /* EF_USE_ASYNEQ */
605 /* This is called whenever stream draining has completed */
607 stream_drain_complete(pa_stream *stream, int success, void *userdata)
609 audio_job_t aj = userdata;
611 PULSE_DEBUG_S("drain_complete cb called (0x%lx)\n",
612 (long unsigned int)aj);
614 if (UNLIKELY(!success)) {
615 PULSE_CRITICAL("Failed to drain stream 0x%lx\n",
616 (long unsigned int)aj);
619 pa_stream_disconnect(stream);
620 PULSE_DEBUG_S("leaving stream_drain cb (0x%lx)\n",
621 (long unsigned int)aj);
625 /* This is called whenever new data may be written to the stream */
627 stream_write_callback(pa_stream *stream, size_t length, void *userdata)
629 audio_job_t aj = NULL;
630 media_substream *mss = NULL;
631 int resolution, channels;
632 media_thread_play_state mtp;
633 size_t len, tmplen, real_frm_sz;
635 /* pulse and subthread stuff */
636 sound_pulse_aj_data_t spsd;
637 pa_context *ctx = NULL;
638 sxe_media_sample_t *tmpbuf;
640 assert(stream && length);
642 if (((aj = userdata) == NULL) ||
643 ((mss = aj->substream) == NULL)) {
644 PULSE_CRITICAL("This idiot of mainloop gave us wrong data: "
645 "aj:0x%lx mss:0x%lx\n",
646 (long unsigned int)aj,
647 (long unsigned int)mss);
649 PULSE_DEBUG_S("FLUSH.\n");
652 stream, stream_drain_complete, aj));
653 pa_stream_disconnect(stream);
657 PULSE_DEBUG_S("stream_write cb called on 0x%lx\n",
658 (long unsigned int)aj);
659 if (audio_job_queue(aj)) {
660 PULSE_DEBUG_S("checking queue\n");
661 sound_pulse_handle_aj_events(userdata);
663 SXE_MUTEX_LOCK(&aj->mtx);
664 spsd = audio_job_device_data(aj);
665 resolution = aj->resolution;
666 real_frm_sz = SOUND_MAX_SAMPLE_WIDTH * (channels = aj->channels);
669 #ifndef EF_USE_ASYNEQ
670 /* Set the playback volume of the stream */
671 if (aj->volume != spsd->volume) {
672 spsd->volume = _sound_pulse_change_volume(
673 &spsd->chanvol, ctx, stream, (pa_volume_t)aj->volume);
675 #endif /* !EF_USE_ASYNEQ */
677 mtp = aj->play_state;
680 /* set up length, rerate args and tmpbuf */
681 tmplen = length * (spsd->rrargs->tweak = aj->ratetrafo);
682 /* It's unlikely but I hit these constraints personally once so
683 let's handle them here.
684 Problem is that a request of 10000 samples from ffmpeg might
685 yield 11560 samples because the decode is not that
686 fine-tunable because a muxed'n'encoded packet likely (if not
687 always) contains a bunch of raw samples (==
689 Thence we add an extra 25% threshold here to be maximum
690 sure not to ask for our own suicide. Of course the media
691 driver itself ought to make sure not to flood the buffer
692 accidentally. This however is not possible at the moment,
693 look at the signature of the media_stream_meth to get the
696 if (UNLIKELY(tmplen > 4 * aj->buffer_alloc_size / 5)) {
697 tmplen = 4 * aj->buffer_alloc_size / 5;
699 tmplen /= aj->framesize;
700 tmpbuf = (sxe_media_sample_t*)aj->buffer;
701 PULSE_DEBUG_S("asking for %u frames, fetching %u instead "
703 length/aj->framesize, tmplen,
704 (long unsigned int)aj);
705 len = media_stream_meth(mss->up, read)(mss, aj->buffer, tmplen);
706 PULSE_DEBUG_S("reader sent %u frames down the pipe\n", len);
707 /* result `len' has number of frames */
713 /* coerce the stuff, tmplen is in samples */
714 tmplen = channels*len;
715 for (i = 0; i < spsd->coe_ch_cnt; i++) {
716 PULSE_DEBUG_COE("calling coerce "
717 "%lu on b:0x%lx l:%lu\n",
718 (long unsigned int)i,
719 (long unsigned int)tmpbuf,
720 (long unsigned int)tmplen);
721 tmplen = CALL_MEDIA_SAMPLE_EFFECT(
722 spsd->coe_chain, i, tmpbuf, tmpbuf, tmplen);
725 MEDIA_SAMPLE_FORMAT_DOWNSAMPLE(spsd->msf)(
726 aj->buffer, aj->buffer, tmplen);
728 tmplen = tmplen * sizeof(int16_t);
732 #if !defined EF_USE_ASYNEQ
733 /* fill buffer with zeros */
734 tmplen = (len = length) * channels * sizeof(int16_t);
735 memset(aj->buffer, 0, tmplen);
739 case MTPSTATE_UNKNOWN:
740 case NUMBER_OF_MEDIA_THREAD_PLAY_STATES:
743 PULSE_DEBUG_S("MTPSTATE == STOP, "
744 "hence leaving stream_write cb\n");
745 SXE_MUTEX_UNLOCK(&aj->mtx);
749 if (LIKELY(len > 0)) {
750 PULSE_DEBUG_S("writing %u frames == %u samples == %u bytes "
752 tmplen/aj->framesize,
753 tmplen*aj->channels / aj->framesize,
755 (long unsigned int)aj);
756 pa_stream_write(stream, aj->buffer, tmplen,
757 my_pa_free_cb, 0, PA_SEEK_RELATIVE);
760 if (tmplen < length) {
761 PULSE_DEBUG_S("DRAIN. (0x%lx)\n", (long unsigned int)aj);
762 aj->play_state = MTPSTATE_STOP;
765 stream, stream_drain_complete, aj));
768 SXE_MUTEX_UNLOCK(&aj->mtx);
769 PULSE_DEBUG_S("leaving stream_write cb\n");
773 /* This routine is called whenever the stream state changes */
775 stream_state_callback(pa_stream *s, void *userdata)
777 sxe_semaphore_t sem = userdata;
778 pa_context_state_t st;
782 st = pa_stream_get_state(s);
783 switch ((unsigned int)st) {
784 case PA_STREAM_CREATING:
785 PULSE_DEBUG_S("CREATING.\n");
787 case PA_STREAM_TERMINATED:
788 PULSE_DEBUG_S("TERMINATED.\n");
789 PULSE_DEBUG_PT("trigger local semaphore\n");
790 SXE_SEMAPH_TRIGGER(sem);
793 case PA_STREAM_READY:
794 PULSE_DEBUG_S("READY.\n");
797 case PA_STREAM_FAILED:
799 PULSE_DEBUG_S("FAILED.\n");
800 PULSE_DEBUG_PT("trigger local semaphore\n");
801 SXE_SEMAPH_TRIGGER(sem);
809 sound_pulse_play(audio_job_t aj)
812 mtype_audio_properties *mtap;
813 Lisp_Media_Stream *ms;
814 media_substream *mss;
817 sound_pulse_data_t spd = NULL;
818 Lisp_Audio_Device *lad = NULL;
820 struct sound_pulse_aj_data_s _spsd, *spsd = &_spsd;
821 struct pa_sample_spec *ssp = &spsd->sampspec;
822 struct pa_channel_map *cmapp = &spsd->chanmap;
823 pa_buffer_attr *bap = &spsd->buffattr;
824 pa_stream *stream = NULL;
826 char *stream_name = NULL;
827 char *sink_name = NULL;
828 sxe_mse_rerate_args _rrargs, *rrargs = &_rrargs;
829 /* semaphore stuff */
830 struct sxe_semaphore_s _sem, *sem = &_sem;
832 int alloced_myself = 0;
834 /* unpack the media thread */
835 SOUND_UNPACK_MT(aj, device, ms, mss, lad, spd, mtap);
837 /* Set up a new main loop - if it's not already running */
838 if (!(r = spd->ml_running_p)) {
839 PULSE_DEBUG_ML("trying to restart main loop...\n");
840 r = sound_pulse_init_mainloop(spd);
841 PULSE_DEBUG_ML("result was: %d\n", r);
844 if (r == 0 || spd->ml_running_p == 0) {
845 warn_when_safe(Qpulse, Qerror,
846 GETTEXT("Failed to (re)connect to server."));
847 XAUDIO_DEVICE_STATE(device) = ASTATE_DEAD;
851 /* prepare pulse sample specs */
852 ssp->rate = mtap->samplerate;
853 ssp->channels = mtap->channels;
855 /* prepare pulse channel map and output format */
856 pa_channel_map_init_auto(cmapp, ssp->channels, PA_CHANNEL_MAP_ALSA);
857 ssp->format = PA_SAMPLE_S16NE;
859 if (spd->ml_running_p && spd->ml_threaded_p) {
860 PULSE_DEBUG_ML("lock.\n");
861 pa_threaded_mainloop_lock(spd->tml);
864 stream_name = (NILP(spd->stream) ? "SXEmacs stream" :
865 (char*)XSTRING_DATA(spd->stream));
866 sink_name = (NILP(spd->sink) ? NULL :
867 (char*)XSTRING_DATA(spd->sink));
869 /* create the stream */
870 PULSE_DEBUG_S("Creating stream...\n");
871 if (!spd->ml_running_p ||
872 !(stream = pa_stream_new(spd->ctx, stream_name, ssp, cmapp))) {
873 PULSE_CRITICAL("SXEmacs critical: [pulse] stream is NULL. "
874 "Mainloop not running?!\n");
877 PULSE_DEBUG_S("Created stream 0x%lx\n", (long unsigned int)stream);
879 /* obviously our device is alive
880 * This does NOT mean that you can hear the sounds */
881 XAUDIO_DEVICE_STATE(device) = ASTATE_ALIVE;
883 /* rewind the media substream */
884 media_stream_meth(ms, rewind)(mss);
885 SXE_MUTEX_LOCK(&aj->mtx);
886 if (aj->buffer_alloc_size == 0) {
887 PULSE_DEBUG_CACHE("worker buffer (sz:%ld) too small, "
888 "reallocate (sz:%ld)\n",
889 (long int)aj->buffer_alloc_size,
890 (long int)SOUND_MAX_AUDIO_FRAME_SIZE);
892 aj->buffer = xmalloc_atomic(SOUND_MAX_AUDIO_FRAME_SIZE);
893 aj->buffer_alloc_size = SOUND_MAX_AUDIO_FRAME_SIZE;
895 aj->resolution = mtap->samplerate * mtap->channels;
896 aj->framesize = mtap->channels * sizeof(int16_t);
897 aj->channels = mtap->channels;
898 SXE_MUTEX_UNLOCK(&aj->mtx);
900 /* initialise buffer attributes */
901 bap->maxlength = mtap->samplerate * aj->framesize;
902 bap->tlength = 9 * bap->maxlength / 10;
903 bap->minreq = bap->tlength / 10;
904 bap->prebuf = bap->tlength / SOUND_MAX_SAMPLE_WIDTH;
905 bap->fragsize = bap->minreq;
907 pa_cvolume_set(&spsd->chanvol, ssp->channels,
908 ((pa_volume_t)aj->volume*PA_VOLUME_NORM)/
909 MEDIA_SAMPLE_VOLUME_NORM);
910 spsd->ctx = spd->ctx;
911 spsd->stream = stream;
912 spsd->time_ev = NULL;
913 audio_job_device_data(aj) = spsd;
915 /* initialise our thread semaphore */
916 PULSE_DEBUG_PT("init pulse local semaphore\n");
917 SXE_SEMAPH_INIT(sem);
920 spsd->msf = MEDIA_SAMPLE_FORMAT(sxe_msf_S16);
921 spsd->coe_ch_cnt = 0;
922 /* the rerate effect */
923 ADD_MEDIA_SAMPLE_EFFECT(
924 spsd->coe_chain, spsd->coe_ch_cnt,
925 MEDIA_SAMPLE_EFFECT(sxe_mse_rerate), rrargs);
926 rrargs->num_channels = mtap->channels;
927 rrargs->srcrate = rrargs->tgtrate = 1;
928 spsd->rrargs = rrargs;
930 PULSE_DEBUG_S("setting up stream.\n");
931 pa_stream_set_state_callback(stream, stream_state_callback, sem);
932 pa_stream_set_write_callback(stream, stream_write_callback, aj);
934 /* we better check if ml is still running */
935 if (!spd->ml_running_p)
937 pa_stream_connect_playback(
938 stream, sink_name, bap, 0, &spsd->chanvol, NULL);
940 if (spd->ml_running_p && spd->ml_threaded_p) {
941 WITH_SXE_SEMAPH_SYNCH(
943 PULSE_DEBUG_ML("unlock.\n");
944 pa_threaded_mainloop_unlock(spd->tml);
945 PULSE_DEBUG_MX("play.\n"););
946 PULSE_DEBUG_PT("ACK, shall finish.\n");
947 } else if (spd->ml_running_p) {
948 /* iterate by hand */
949 pa_stream_state_t state;
950 while (spd->ml_running_p) {
951 pa_mainloop_iterate(spd->ml, 1, NULL);
952 state = pa_stream_get_state(stream);
953 if (!(state == PA_STREAM_READY ||
954 state == PA_STREAM_CREATING)) {
960 /* ... and outta here */
961 PULSE_DEBUG_S("finish.\n");
963 /* close and shutdown */
965 SXE_MUTEX_LOCK(&aj->mtx);
966 if (alloced_myself && aj->buffer) {
967 PULSE_DEBUG_S("freeing stream buffer.\n");
971 aj->buffer_alloc_size = 0;
973 /* device data could be finished already, hence we refetch it */
974 spd = get_audio_device_data(aj->device);
975 SXE_MUTEX_UNLOCK(&aj->mtx);
977 if (spd && spd->ml_running_p && spd->ml_threaded_p) {
978 PULSE_DEBUG_ML("lock.\n");
979 pa_threaded_mainloop_lock(spd->tml);
983 /* kick those timers */
984 if (spsd->time_ev != NULL) {
985 spd->mlapi->time_free(spsd->time_ev);
987 spsd->time_ev = NULL;
992 PULSE_DEBUG_S("unref.\n");
993 pa_stream_unref(stream);
998 if (spd && spd->ml_running_p && spd->ml_threaded_p) {
999 PULSE_DEBUG_ML("unlock.\n");
1000 pa_threaded_mainloop_unlock(spd->tml);
1003 SXE_MUTEX_LOCK(&aj->mtx);
1004 audio_job_device_data(aj) = NULL;
1005 SXE_MUTEX_UNLOCK(&aj->mtx);
1007 /* finish the pulse device data if pulse is not running anymore */
1008 if (spd && !spd->ml_running_p) {
1009 SXE_MUTEX_LOCK(&aj->mtx);
1010 XAUDIO_DEVICE_STATE(aj->device) = ASTATE_DEAD;
1011 SXE_MUTEX_UNLOCK(&aj->mtx);
1012 sound_pulse_finish(spd);
1016 /* deinitialise our thread semaphore */
1017 PULSE_DEBUG_PT("deinit pulse local semaphore\n");
1018 SXE_SEMAPH_FINI(sem);
1024 #define CHECK_DEAD_GOTO(label) \
1027 pa_context_get_state(spd->ctx) != PA_CONTEXT_READY) { \
1028 PULSE_CRITICAL("Uh oh, operation failed.\n"); \
1034 sink_info_callback(pa_context *c, const pa_sink_info *i, int eol, void *data)
1036 sound_pulse_data_t spd = data;
1039 PULSE_DEBUG_CTX("No sink info\n");
1040 spd->sink_info = NULL;
1041 } else if (i == NULL) {
1044 PULSE_DEBUG_CTX("Name: %s, Index: %d\nDescr: %s\n",
1045 i->name, i->index, i->description);
1046 spd->sink_info = NULL;
1052 /* This is called whenever the context status changes */
1054 context_state_callback(pa_context *c, void *userdata)
1056 sound_pulse_data_t spd = userdata;
1058 char *sink_name = NULL;
1062 switch (pa_context_get_state(c)) {
1063 case PA_CONTEXT_UNCONNECTED:
1064 case PA_CONTEXT_CONNECTING:
1065 case PA_CONTEXT_AUTHORIZING:
1066 case PA_CONTEXT_SETTING_NAME:
1067 PULSE_DEBUG_CTX("CONN/AUTH.\n");
1068 spd->ml_running_p = 0;
1071 case PA_CONTEXT_READY:
1072 PULSE_DEBUG_CTX("ESTA.\n");
1073 sink_name = (NILP(spd->sink) ? NULL :
1074 (char*)XSTRING_DATA(spd->sink));
1077 if (!(o = pa_context_get_sink_info_by_name(
1078 spd->ctx, sink_name,
1079 sink_info_callback, spd))) {
1080 PULSE_DEBUG_CTX("Hm, no sink info ... what now?\n");
1085 pa_operation_unref(o);
1086 spd->ml_running_p = 1;
1087 pa_threaded_mainloop_signal(spd->tml, 0);
1090 case PA_CONTEXT_TERMINATED:
1091 PULSE_DEBUG_CTX("DEAD.\n");
1092 spd->ml_running_p = 0;
1093 pa_threaded_mainloop_signal(spd->tml, 0);
1096 case PA_CONTEXT_FAILED:
1098 PULSE_DEBUG_CTX("FAIL.\n");
1099 spd->ml_running_p = 0;
1100 PULSE_DEBUG_CTX("triggering semaphore.\n");
1101 pa_threaded_mainloop_signal(spd->tml, 0);
1107 /* mainloop in an extra thread API */
1109 sound_pulse_init_mainloop(ad_device_data *devdata)
1112 sound_pulse_data_t spd = (sound_pulse_data_t)devdata;
1113 /* some predeclarations to avoid ugly trigraphs */
1114 const char *client =
1115 (NILP(spd->client) ? "SXEmacs" :
1116 (const char*)XSTRING_DATA(spd->client));
1117 const char *server =
1118 (NILP(spd->server) ? NULL :
1119 (const char*)XSTRING_DATA(spd->server));
1120 int threadedp = spd->ml_threaded_p;
1122 /* cannot use Pulse on incomplete or corrupt audio devices */
1126 SXE_SEMAPH_INIT(&(spd->ctxsem));
1128 /* Set up a new main loop */
1130 spd->tml = pa_threaded_mainloop_new();
1132 spd->ml = pa_mainloop_new();
1134 if (!spd->tml && !spd->ml) {
1135 message(GETTEXT("audio-pulse: "
1136 "Failed to connect to server."));
1141 spd->mlapi = pa_threaded_mainloop_get_api(spd->tml);
1143 spd->mlapi = pa_mainloop_get_api(spd->ml);
1145 /* Create a new connection context */
1146 if (!(spd->ctx = pa_context_new(spd->mlapi, client))) {
1147 message(GETTEXT("audio-pulse: "
1148 "pa_context_new() failed."));
1154 /* initialise callback semaphore */
1156 spd->ml_running_p = 0;
1157 pa_context_set_state_callback(
1158 spd->ctx, context_state_callback, spd);
1160 /* Connect the context */
1161 if (pa_context_connect(spd->ctx, server, 0, NULL) < 0) {
1162 PULSE_DEBUG_ML("failed to connect to server\n");
1166 PULSE_DEBUG_ML("locking mainloop\n");
1167 pa_threaded_mainloop_lock(spd->tml);
1169 if (pa_threaded_mainloop_start(spd->tml) < 0) {
1170 PULSE_DEBUG_ML("failed to start mainloop\n");
1171 goto unlock_and_fail;
1174 /* Wait until the context is ready */
1175 pa_threaded_mainloop_wait(spd->tml);
1177 if (pa_context_get_state(spd->ctx) != PA_CONTEXT_READY) {
1178 PULSE_DEBUG_ML("failed to connect to server\n");
1179 goto unlock_and_fail;
1182 /* Connect the context */
1183 pa_context_connect(spd->ctx, server, 0, NULL);
1184 /* iterate manually */
1186 pa_context_state_t st;
1188 pa_mainloop_iterate(spd->ml, 1, NULL);
1189 st = pa_context_get_state(spd->ctx);
1191 switch ((unsigned int)st) {
1192 case PA_CONTEXT_CONNECTING:
1193 case PA_CONTEXT_AUTHORIZING:
1194 case PA_CONTEXT_SETTING_NAME:
1195 spd->ml_running_p = 0;
1198 case PA_CONTEXT_READY:
1199 PULSE_DEBUG_CTX("ESTA.\n");
1200 PULSE_DEBUG_CTX("READY.\n");
1201 return (spd->ml_running_p = 1);
1203 case PA_CONTEXT_TERMINATED:
1204 PULSE_DEBUG_CTX("DEAD.\n");
1205 return (spd->ml_running_p = 0);
1207 case PA_CONTEXT_FAILED:
1209 PULSE_DEBUG_CTX("FAIL.\n");
1210 return (spd->ml_running_p = 0);
1216 PULSE_DEBUG_ML("READY: %d.\n", spd->ml_running_p);
1219 if (threadedp && spd->tml) {
1220 pa_threaded_mainloop_unlock(spd->tml);
1223 /* indicate success */
1224 return spd->ml_running_p;
1227 /* DEFUN("pulse-get-sink-info-list", Fpulse_get_sink_info_list, 1, 1, 0, */
1232 /* sound-pulse.c ends here */