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 char *temp = alloca(256);
140 pa_context_state_t st;
142 spd = get_audio_device_data(device);
143 /* cannot use incomplete or corrupt audio devices */
144 if (XAUDIO_DEVICE_DRIVER(device) != MYSELF || spd == NULL) {
145 write_c_string(" VOID", pcfun);
146 /* now that we are here, mark AO device as dead */
147 XAUDIO_DEVICE_STATE(device) = ASTATE_DEAD;
151 /* info about the connected output plugin */
152 write_c_string(" :server ", pcfun);
153 if (NILP(spd->server))
154 write_c_string("#default", pcfun);
156 print_internal(spd->server, pcfun, ef);
158 write_c_string(" :sink ", pcfun);
159 if (NILP(spd->sink)) {
160 write_c_string("#default", pcfun);
162 print_internal(spd->sink, pcfun, ef);
166 if (spd->sink_info) {
167 write_c_string(" (", pcfun);
168 write_c_string(spd->sink_info->description, pcfun);
169 write_c_string(")", pcfun);
171 write_c_string(" (sink does not exist)", pcfun);
175 write_c_string(" :source ", pcfun);
176 if (NILP(spd->source))
177 write_c_string("#default", pcfun);
179 print_internal(spd->source, pcfun, ef);
181 write_c_string(" :server-state ", pcfun);
184 write_c_string("#b0rked", pcfun);
188 st = pa_context_get_state(spd->ctx);
189 switch ((unsigned int)st) {
190 case PA_CONTEXT_CONNECTING:
191 case PA_CONTEXT_AUTHORIZING:
192 case PA_CONTEXT_SETTING_NAME:
193 write_c_string("#busy", pcfun);
196 case PA_CONTEXT_READY:
197 write_c_string("#connected", pcfun);
200 case PA_CONTEXT_TERMINATED:
201 write_c_string("#terminated", pcfun);
204 case PA_CONTEXT_FAILED:
206 write_c_string("#failed", pcfun);
210 write_c_string(" :api ", pcfun);
211 if (spd->ml_threaded_p) {
212 write_c_string("#threaded", pcfun);
213 snprintf(temp, 255, " :mainloop 0x%lx",
214 (long unsigned int)spd->tml);
216 write_c_string("#non-threaded", pcfun);
217 snprintf(temp, 255, " :mainloop 0x%lx",
218 (long unsigned int)spd->ml);
221 write_c_string(temp, pcfun);
227 static ad_device_data *
228 sound_pulse_create(Lisp_Object pulse_options)
231 sound_pulse_data_t spd = NULL;
232 /* option keywords */
233 Lisp_Object opt_server = Qnil;
234 Lisp_Object opt_sink = Qnil;
235 Lisp_Object opt_source = Qnil;
236 Lisp_Object opt_client = Qnil;
237 Lisp_Object opt_stream = Qnil;
238 Lisp_Object opt_immediate = Qnil;
239 Lisp_Object opt_threaded = Qnil;
240 Lisp_Object opt_force = Qnil;
243 opt_server = Fplist_get(pulse_options, intern(":server"), Qnil);
244 if (!NILP(opt_server) && !STRINGP(opt_server)) {
245 wrong_type_argument(Qstringp, opt_server);
249 opt_sink = Fplist_get(pulse_options, intern(":sink"), Qnil);
250 if (!NILP(opt_sink) && !STRINGP(opt_sink)) {
251 wrong_type_argument(Qstringp, opt_sink);
255 opt_client = Fplist_get(pulse_options, intern(":client"), Qnil);
256 if (!NILP(opt_client) && !STRINGP(opt_client)) {
257 wrong_type_argument(Qstringp, opt_client);
261 opt_stream = Fplist_get(pulse_options, intern(":stream"), Qnil);
262 if (!NILP(opt_stream) && !STRINGP(opt_stream)) {
263 wrong_type_argument(Qstringp, opt_stream);
267 opt_immediate = Fplist_get(pulse_options, intern(":immediate"), Qt);
268 opt_threaded = Fplist_get(pulse_options, intern(":threaded"), Qt);
269 opt_force = Fplist_get(pulse_options, intern(":force"), Qnil);
271 /* initialise and fill */
272 spd = xnew_and_zero(struct sound_pulse_data_s);
273 spd->server = opt_server;
274 spd->client = opt_client;
275 spd->sink = opt_sink;
276 spd->source = opt_source;
277 spd->stream = opt_stream;
279 spd->ml_threaded_p = !NILP(opt_threaded);
281 if (NILP(opt_immediate))
282 return (ad_device_data*)spd;
284 sound_pulse_init_mainloop(spd);
286 if (spd->ml_running_p == 0) /* yeah, finish immediately */
287 sound_pulse_finish(spd);
289 if (NILP(opt_force) && spd->ml_running_p == 0) {
292 error(GETTEXT("Error: audio-pulse: "
293 "Initialising connection to PulseAudio failed."));
297 return (ad_device_data*)spd;
301 sound_pulse_finish(ad_device_data *data)
303 sound_pulse_data_t spd = data;
307 if (spd != NULL && 0) {
315 spd->ml_running_p = 0;
317 /* setting this to 0 is not enough? :\ */
319 PULSE_DEBUG_CTX("DRAIN.\n");
320 pa_context_drain(spd->ctx, NULL, NULL);
321 PULSE_DEBUG_CTX("STOP.\n");
322 pa_context_disconnect(spd->ctx);
323 pa_context_unref(spd->ctx);
324 SXE_SEMAPH_FINI(&(spd->ctxsem));
328 PULSE_DEBUG_ML("Is there a mainloop awake?\n");
329 if (spd->ml_threaded_p) {
331 PULSE_DEBUG_ML("STOP.\n");
332 pa_threaded_mainloop_stop(spd->tml);
333 PULSE_DEBUG_ML("FREE. bye bye\n");
334 pa_threaded_mainloop_free(spd->tml);
340 PULSE_DEBUG_ML("FREE. bye bye (non-threaded)\n");
341 pa_mainloop_free(spd->ml);
346 PULSE_DEBUG_CTX("finish.\n");
354 /** Wait until the specified operation completes */
355 #define wait_for_operation(_m, _o) \
357 struct pa_operation *__o = (_o); \
358 while (pa_operation_get_state(__o) == \
359 PA_OPERATION_RUNNING) \
360 pa_mainloop_iterate((_m), 1, NULL); \
361 pa_operation_unref(__o); \
364 /** Wait until no further actions are pending on the connection context */
365 #define wait_for_completion(_c, _m) \
367 while (pa_context_is_pending(_c)) \
368 pa_mainloop_iterate((_m), 1, NULL); \
373 my_pa_free_cb(void *data)
375 /* dummy callback which ought to free DATA,
376 * however, we want to recycle the memory as much as possible,
377 * we free it ourselves */
378 PULSE_DEBUG_S("my_pa_free_cb called 0x%lx\n",
379 (long unsigned int)data);
384 static inline pa_volume_t
385 _sound_pulse_change_volume(
386 pa_cvolume *cvolp, pa_context *ctx,
387 pa_stream *stream, pa_volume_t volume)
388 __attribute__((always_inline));
389 static inline pa_volume_t
390 _sound_pulse_change_volume(
391 pa_cvolume *cvolp, pa_context *ctx,
392 pa_stream *stream, pa_volume_t volume)
396 pa_cvolume_set(cvolp, cvolp->channels,
397 (volume*PA_VOLUME_NORM)/MEDIA_SAMPLE_VOLUME_NORM);
399 if (!(o = pa_context_set_sink_input_volume(
400 ctx, pa_stream_get_index(stream), cvolp, NULL, NULL))) {
401 PULSE_CRITICAL("Cannot set volume.\n");
403 pa_operation_unref(o);
408 /* handling of events from the audio job's private queue */
411 sound_pulse_stop(audio_job_t aj)
412 __attribute__((always_inline));
414 sound_pulse_stop(audio_job_t aj)
416 sound_pulse_aj_data_t spsd;
419 SXE_MUTEX_LOCK(&aj->mtx);
420 spsd = audio_job_device_data(aj);
421 stream = spsd->stream;
422 PULSE_DEBUG_S("FLUSH. (0x%lx)\n", (long unsigned int)aj);
423 pa_operation_unref(pa_stream_flush(stream, NULL, NULL));
424 pa_stream_disconnect(stream);
425 aj->play_state = MTPSTATE_STOP;
426 SXE_MUTEX_UNLOCK(&aj->mtx);
431 sound_pulse_pause(audio_job_t aj)
432 __attribute__((always_inline));
434 sound_pulse_pause(audio_job_t aj)
436 sound_pulse_aj_data_t spsd;
437 sound_pulse_data_t spd;
441 SXE_MUTEX_LOCK(&aj->mtx);
442 spd = get_audio_device_data(aj->device);
443 spsd = audio_job_device_data(aj);
444 stream = spsd->stream;
445 PULSE_DEBUG_S("CORK. (0x%lx)\n", (long unsigned int)aj);
446 pa_operation_unref(pa_stream_cork(stream, 1, NULL, NULL));
447 aj->play_state = MTPSTATE_PAUSE;
449 if (audio_job_queue(aj)) {
450 spsd->time_ev = spd->mlapi->
451 time_new(spd->mlapi, &tv, time_ev_cb, aj);
454 SXE_MUTEX_UNLOCK(&aj->mtx);
459 sound_pulse_resume(audio_job_t aj)
460 __attribute__((always_inline));
462 sound_pulse_resume(audio_job_t aj)
464 sound_pulse_aj_data_t spsd;
465 sound_pulse_data_t spd;
468 SXE_MUTEX_LOCK(&aj->mtx);
469 spd = get_audio_device_data(aj->device);
470 spsd = audio_job_device_data(aj);
471 stream = spsd->stream;
472 PULSE_DEBUG_S("UNCORK. (0x%lx)\n", (long unsigned int)aj);
475 spd->mlapi->time_free(spsd->time_ev);
476 spsd->time_ev = NULL;
479 pa_operation_unref(pa_stream_cork(stream, 0, NULL, NULL));
480 aj->play_state = MTPSTATE_RUN;
481 SXE_MUTEX_UNLOCK(&aj->mtx);
486 sound_pulse_change_volume(audio_job_t aj, audio_job_event_args_t args)
488 sound_pulse_aj_data_t spsd;
489 pa_volume_t new_vol = args->volume_args;
491 PULSE_DEBUG_AJ("->%d\n", (int)new_vol);
493 SXE_MUTEX_LOCK(&aj->mtx);
494 spsd = audio_job_device_data(aj);
495 spsd->volume = _sound_pulse_change_volume(
496 &spsd->chanvol, spsd->ctx, spsd->stream, new_vol);
497 aj->volume = (int)(spsd->volume);
498 SXE_MUTEX_UNLOCK(&aj->mtx);
502 sound_pulse_change_rate(audio_job_t aj, audio_job_event_args_t args)
504 SXE_MUTEX_LOCK(&aj->mtx);
505 aj->ratetrafo = args->rate_args;
506 SXE_MUTEX_UNLOCK(&aj->mtx);
510 sound_pulse_change_state(audio_job_t aj, audio_job_event_args_t args)
512 switch (args->state_args) {
514 PULSE_DEBUG_AJ("->pause state\n");
515 sound_pulse_pause(aj);
518 PULSE_DEBUG_AJ("->resume state\n");
519 sound_pulse_resume(aj);
522 PULSE_DEBUG_AJ("->start state\n");
525 PULSE_DEBUG_AJ("->stop state\n");
526 sound_pulse_stop(aj);
529 case no_audio_job_change_states:
531 PULSE_DEBUG_AJ("->unknown state\n");
537 sound_pulse_handle_aj_events(audio_job_t aj)
538 __attribute__((always_inline));
540 sound_pulse_handle_aj_events(audio_job_t aj)
542 sound_pulse_aj_data_t spsd;
544 audio_job_event_t ev = NULL;
547 #if defined EF_USE_ASYNEQ
548 if (audio_job_queue(aj)) {
549 assert((long unsigned int)audio_job_queue(aj) != 0xB16B00B5);
553 PULSE_DEBUG_AJ("handle aj events called on 0x%lx\n",
554 (long unsigned int)aj);
556 SXE_MUTEX_LOCK(&aj->mtx);
557 spsd = audio_job_device_data(aj);
558 eq = audio_job_queue(aj);
559 SXE_MUTEX_UNLOCK(&aj->mtx);
560 stream = spsd->stream;
561 if ((ev = eq_noseeum_dequeue(eq)) == NULL) {
564 if (stream == NULL || pa_stream_get_state(stream) != PA_STREAM_READY) {
568 PULSE_DEBUG_AJ("Event 0x%lx\n", (long unsigned int)ev);
569 switch (audio_job_event_kind(ev)) {
570 case aj_change_state:
571 PULSE_DEBUG_AJ("change state event\n");
572 sound_pulse_change_state(aj, &audio_job_event_args(ev));
574 case aj_change_volume:
575 PULSE_DEBUG_AJ("change volume event\n");
576 sound_pulse_change_volume(aj, &audio_job_event_args(ev));
579 PULSE_DEBUG_AJ("change rate event\n");
580 sound_pulse_change_rate(aj, &audio_job_event_args(ev));
583 case no_audio_job_event_kinds:
585 PULSE_CRITICAL("unknown event\n");
588 free_audio_job_event(ev);
592 time_ev_cb(pa_mainloop_api *m, pa_time_event *e,
593 const struct timeval *tv, void *userdata)
595 /* check an audio-job's queue for incoming events */
596 struct timeval next; /* for rescheduling this construction */
597 audio_job_t aj = userdata;
598 sound_pulse_aj_data_t spsd = audio_job_device_data(aj);;
600 sound_pulse_handle_aj_events(userdata);
602 if (spsd->time_ev != NULL) {
603 /* reschedule the thing */
604 pa_gettimeofday(&next);
605 pa_timeval_add(&next, 25000);
606 m->time_restart(e, &next);
609 #endif /* EF_USE_ASYNEQ */
611 /* This is called whenever stream draining has completed */
613 stream_drain_complete(pa_stream *stream, int success, void *userdata)
615 audio_job_t aj = userdata;
617 PULSE_DEBUG_S("drain_complete cb called (0x%lx)\n",
618 (long unsigned int)aj);
620 if (UNLIKELY(!success)) {
621 PULSE_CRITICAL("Failed to drain stream 0x%lx\n",
622 (long unsigned int)aj);
625 pa_stream_disconnect(stream);
626 PULSE_DEBUG_S("leaving stream_drain cb (0x%lx)\n",
627 (long unsigned int)aj);
631 /* This is called whenever new data may be written to the stream */
633 stream_write_callback(pa_stream *stream, size_t length, void *userdata)
635 audio_job_t aj = NULL;
636 media_substream *mss = NULL;
637 int resolution, channels;
638 media_thread_play_state mtp;
639 size_t len, tmplen, real_frm_sz;
641 /* pulse and subthread stuff */
642 sound_pulse_aj_data_t spsd;
643 pa_context *ctx = NULL;
644 sxe_media_sample_t *tmpbuf;
646 assert(stream && length);
648 if (((aj = userdata) == NULL) ||
649 ((mss = aj->substream) == NULL)) {
650 PULSE_CRITICAL("This idiot of mainloop gave us wrong data: "
651 "aj:0x%lx mss:0x%lx\n",
652 (long unsigned int)aj,
653 (long unsigned int)mss);
655 PULSE_DEBUG_S("FLUSH.\n");
658 stream, stream_drain_complete, aj));
659 pa_stream_disconnect(stream);
663 PULSE_DEBUG_S("stream_write cb called on 0x%lx\n",
664 (long unsigned int)aj);
665 if (audio_job_queue(aj)) {
666 PULSE_DEBUG_S("checking queue\n");
667 sound_pulse_handle_aj_events(userdata);
669 SXE_MUTEX_LOCK(&aj->mtx);
670 spsd = audio_job_device_data(aj);
671 resolution = aj->resolution;
672 real_frm_sz = SOUND_MAX_SAMPLE_WIDTH * (channels = aj->channels);
675 #ifndef EF_USE_ASYNEQ
676 /* Set the playback volume of the stream */
677 if (aj->volume != spsd->volume) {
678 spsd->volume = _sound_pulse_change_volume(
679 &spsd->chanvol, ctx, stream, (pa_volume_t)aj->volume);
681 #endif /* !EF_USE_ASYNEQ */
683 mtp = aj->play_state;
686 /* set up length, rerate args and tmpbuf */
687 tmplen = length * (spsd->rrargs->tweak = aj->ratetrafo);
688 /* It's unlikely but I hit these constraints personally once so
689 let's handle them here.
690 Problem is that a request of 10000 samples from ffmpeg might
691 yield 11560 samples because the decode is not that
692 fine-tunable because a muxed'n'encoded packet likely (if not
693 always) contains a bunch of raw samples (==
695 Thence we add an extra 25% threshold here to be maximum
696 sure not to ask for our own suicide. Of course the media
697 driver itself ought to make sure not to flood the buffer
698 accidentally. This however is not possible at the moment,
699 look at the signature of the media_stream_meth to get the
702 if (UNLIKELY(tmplen > 4 * aj->buffer_alloc_size / 5)) {
703 tmplen = 4 * aj->buffer_alloc_size / 5;
705 tmplen /= aj->framesize;
706 tmpbuf = (sxe_media_sample_t*)aj->buffer;
707 PULSE_DEBUG_S("asking for %u frames, fetching %u instead "
709 length/aj->framesize, tmplen,
710 (long unsigned int)aj);
711 len = media_stream_meth(mss->up, read)(mss, aj->buffer, tmplen);
712 PULSE_DEBUG_S("reader sent %u frames down the pipe\n", len);
713 /* result `len' has number of frames */
719 /* coerce the stuff, tmplen is in samples */
720 tmplen = channels*len;
721 for (i = 0; i < spsd->coe_ch_cnt; i++) {
722 PULSE_DEBUG_COE("calling coerce "
723 "%lu on b:0x%lx l:%lu\n",
724 (long unsigned int)i,
725 (long unsigned int)tmpbuf,
726 (long unsigned int)tmplen);
727 tmplen = CALL_MEDIA_SAMPLE_EFFECT(
728 spsd->coe_chain, i, tmpbuf, tmpbuf, tmplen);
731 MEDIA_SAMPLE_FORMAT_DOWNSAMPLE(spsd->msf)(
732 aj->buffer, aj->buffer, tmplen);
734 tmplen = tmplen * sizeof(int16_t);
738 #if !defined EF_USE_ASYNEQ
739 /* fill buffer with zeros */
740 tmplen = (len = length) * channels * sizeof(int16_t);
741 memset(aj->buffer, 0, tmplen);
745 case MTPSTATE_UNKNOWN:
746 case NUMBER_OF_MEDIA_THREAD_PLAY_STATES:
749 PULSE_DEBUG_S("MTPSTATE == STOP, "
750 "hence leaving stream_write cb\n");
751 SXE_MUTEX_UNLOCK(&aj->mtx);
755 if (LIKELY(len > 0)) {
756 PULSE_DEBUG_S("writing %u frames == %u samples == %u bytes "
758 tmplen/aj->framesize,
759 tmplen*aj->channels / aj->framesize,
761 (long unsigned int)aj);
762 pa_stream_write(stream, aj->buffer, tmplen,
763 my_pa_free_cb, 0, PA_SEEK_RELATIVE);
766 if (tmplen < length) {
767 PULSE_DEBUG_S("DRAIN. (0x%lx)\n", (long unsigned int)aj);
768 aj->play_state = MTPSTATE_STOP;
771 stream, stream_drain_complete, aj));
774 SXE_MUTEX_UNLOCK(&aj->mtx);
775 PULSE_DEBUG_S("leaving stream_write cb\n");
779 /* This routine is called whenever the stream state changes */
781 stream_state_callback(pa_stream *s, void *userdata)
783 sxe_semaphore_t sem = userdata;
784 pa_context_state_t st;
788 st = pa_stream_get_state(s);
789 switch ((unsigned int)st) {
790 case PA_STREAM_CREATING:
791 PULSE_DEBUG_S("CREATING.\n");
793 case PA_STREAM_TERMINATED:
794 PULSE_DEBUG_S("TERMINATED.\n");
795 PULSE_DEBUG_PT("trigger local semaphore\n");
796 SXE_SEMAPH_TRIGGER(sem);
799 case PA_STREAM_READY:
800 PULSE_DEBUG_S("READY.\n");
803 case PA_STREAM_FAILED:
805 PULSE_DEBUG_S("FAILED.\n");
806 PULSE_DEBUG_PT("trigger local semaphore\n");
807 SXE_SEMAPH_TRIGGER(sem);
815 sound_pulse_play(audio_job_t aj)
818 mtype_audio_properties *mtap;
819 Lisp_Media_Stream *ms;
820 media_substream *mss;
823 sound_pulse_data_t spd = NULL;
824 Lisp_Audio_Device *lad = NULL;
826 struct sound_pulse_aj_data_s _spsd, *spsd = &_spsd;
827 struct pa_sample_spec *ssp = &spsd->sampspec;
828 struct pa_channel_map *cmapp = &spsd->chanmap;
829 pa_buffer_attr *bap = &spsd->buffattr;
830 pa_stream *stream = NULL;
832 char *stream_name = NULL;
833 char *sink_name = NULL;
834 sxe_mse_rerate_args _rrargs, *rrargs = &_rrargs;
835 /* semaphore stuff */
836 struct sxe_semaphore_s _sem, *sem = &_sem;
838 int alloced_myself = 0;
840 /* unpack the media thread */
841 SOUND_UNPACK_MT(aj, device, ms, mss, lad, spd, mtap);
843 /* Set up a new main loop - if it's not already running */
844 if (!(r = spd->ml_running_p)) {
845 PULSE_DEBUG_ML("trying to restart main loop...\n");
846 r = sound_pulse_init_mainloop(spd);
847 PULSE_DEBUG_ML("result was: %d\n", r);
850 if (r == 0 || spd->ml_running_p == 0) {
851 warn_when_safe(Qpulse, Qerror,
852 GETTEXT("Failed to (re)connect to server."));
853 XAUDIO_DEVICE_STATE(device) = ASTATE_DEAD;
857 /* prepare pulse sample specs */
858 ssp->rate = mtap->samplerate;
859 ssp->channels = mtap->channels;
861 /* prepare pulse channel map and output format */
862 pa_channel_map_init_auto(cmapp, ssp->channels, PA_CHANNEL_MAP_ALSA);
863 ssp->format = PA_SAMPLE_S16NE;
865 if (spd->ml_running_p && spd->ml_threaded_p) {
866 PULSE_DEBUG_ML("lock.\n");
867 pa_threaded_mainloop_lock(spd->tml);
870 stream_name = (NILP(spd->stream) ? "SXEmacs stream" :
871 (char*)XSTRING_DATA(spd->stream));
872 sink_name = (NILP(spd->sink) ? NULL :
873 (char*)XSTRING_DATA(spd->sink));
875 /* create the stream */
876 PULSE_DEBUG_S("Creating stream...\n");
877 if (!spd->ml_running_p ||
878 !(stream = pa_stream_new(spd->ctx, stream_name, ssp, cmapp))) {
879 PULSE_CRITICAL("SXEmacs critical: [pulse] stream is NULL. "
880 "Mainloop not running?!\n");
883 PULSE_DEBUG_S("Created stream 0x%lx\n", (long unsigned int)stream);
885 /* obviously our device is alive
886 * This does NOT mean that you can hear the sounds */
887 XAUDIO_DEVICE_STATE(device) = ASTATE_ALIVE;
889 /* rewind the media substream */
890 media_stream_meth(ms, rewind)(mss);
891 SXE_MUTEX_LOCK(&aj->mtx);
892 if (aj->buffer_alloc_size == 0) {
893 PULSE_DEBUG_CACHE("worker buffer (sz:%ld) too small, "
894 "reallocate (sz:%ld)\n",
895 (long int)aj->buffer_alloc_size,
896 (long int)SOUND_MAX_AUDIO_FRAME_SIZE);
898 aj->buffer = xmalloc_atomic(SOUND_MAX_AUDIO_FRAME_SIZE);
899 aj->buffer_alloc_size = SOUND_MAX_AUDIO_FRAME_SIZE;
901 aj->resolution = mtap->samplerate * mtap->channels;
902 aj->framesize = mtap->channels * sizeof(int16_t);
903 aj->channels = mtap->channels;
904 SXE_MUTEX_UNLOCK(&aj->mtx);
906 /* initialise buffer attributes */
907 bap->maxlength = mtap->samplerate * aj->framesize;
908 bap->tlength = 9 * bap->maxlength / 10;
909 bap->minreq = bap->tlength / 10;
910 bap->prebuf = bap->tlength / SOUND_MAX_SAMPLE_WIDTH;
911 bap->fragsize = bap->minreq;
913 pa_cvolume_set(&spsd->chanvol, ssp->channels,
914 ((pa_volume_t)aj->volume*PA_VOLUME_NORM)/
915 MEDIA_SAMPLE_VOLUME_NORM);
916 spsd->ctx = spd->ctx;
917 spsd->stream = stream;
918 spsd->time_ev = NULL;
919 audio_job_device_data(aj) = spsd;
921 /* initialise our thread semaphore */
922 PULSE_DEBUG_PT("init pulse local semaphore\n");
923 SXE_SEMAPH_INIT(sem);
926 spsd->msf = MEDIA_SAMPLE_FORMAT(sxe_msf_S16);
927 spsd->coe_ch_cnt = 0;
928 /* the rerate effect */
929 ADD_MEDIA_SAMPLE_EFFECT(
930 spsd->coe_chain, spsd->coe_ch_cnt,
931 MEDIA_SAMPLE_EFFECT(sxe_mse_rerate), rrargs);
932 rrargs->num_channels = mtap->channels;
933 rrargs->srcrate = rrargs->tgtrate = 1;
934 spsd->rrargs = rrargs;
936 PULSE_DEBUG_S("setting up stream.\n");
937 pa_stream_set_state_callback(stream, stream_state_callback, sem);
938 pa_stream_set_write_callback(stream, stream_write_callback, aj);
940 /* we better check if ml is still running */
941 if (!spd->ml_running_p)
943 pa_stream_connect_playback(
944 stream, sink_name, bap, 0, &spsd->chanvol, NULL);
946 if (spd->ml_running_p && spd->ml_threaded_p) {
947 WITH_SXE_SEMAPH_SYNCH(
949 PULSE_DEBUG_ML("unlock.\n");
950 pa_threaded_mainloop_unlock(spd->tml);
951 PULSE_DEBUG_MX("play.\n"););
952 PULSE_DEBUG_PT("ACK, shall finish.\n");
953 } else if (spd->ml_running_p) {
954 /* iterate by hand */
955 pa_stream_state_t state;
956 while (spd->ml_running_p) {
957 pa_mainloop_iterate(spd->ml, 1, NULL);
958 state = pa_stream_get_state(stream);
959 if (!(state == PA_STREAM_READY ||
960 state == PA_STREAM_CREATING)) {
966 /* ... and outta here */
967 PULSE_DEBUG_S("finish.\n");
969 /* close and shutdown */
971 SXE_MUTEX_LOCK(&aj->mtx);
972 if (alloced_myself && aj->buffer) {
973 PULSE_DEBUG_S("freeing stream buffer.\n");
977 aj->buffer_alloc_size = 0;
979 /* device data could be finished already, hence we refetch it */
980 spd = get_audio_device_data(aj->device);
981 SXE_MUTEX_UNLOCK(&aj->mtx);
983 if (spd && spd->ml_running_p && spd->ml_threaded_p) {
984 PULSE_DEBUG_ML("lock.\n");
985 pa_threaded_mainloop_lock(spd->tml);
989 /* kick those timers */
990 if (spsd->time_ev != NULL) {
991 spd->mlapi->time_free(spsd->time_ev);
993 spsd->time_ev = NULL;
998 PULSE_DEBUG_S("unref.\n");
999 pa_stream_unref(stream);
1004 if (spd && spd->ml_running_p && spd->ml_threaded_p) {
1005 PULSE_DEBUG_ML("unlock.\n");
1006 pa_threaded_mainloop_unlock(spd->tml);
1009 SXE_MUTEX_LOCK(&aj->mtx);
1010 audio_job_device_data(aj) = NULL;
1011 SXE_MUTEX_UNLOCK(&aj->mtx);
1013 /* finish the pulse device data if pulse is not running anymore */
1014 if (spd && !spd->ml_running_p) {
1015 SXE_MUTEX_LOCK(&aj->mtx);
1016 XAUDIO_DEVICE_STATE(aj->device) = ASTATE_DEAD;
1017 SXE_MUTEX_UNLOCK(&aj->mtx);
1018 sound_pulse_finish(spd);
1022 /* deinitialise our thread semaphore */
1023 PULSE_DEBUG_PT("deinit pulse local semaphore\n");
1024 SXE_SEMAPH_FINI(sem);
1030 #define CHECK_DEAD_GOTO(label) \
1033 pa_context_get_state(spd->ctx) != PA_CONTEXT_READY) { \
1034 PULSE_CRITICAL("Uh oh, operation failed.\n"); \
1040 sink_info_callback(pa_context *c, const pa_sink_info *i, int eol, void *data)
1042 sound_pulse_data_t spd = data;
1045 PULSE_DEBUG_CTX("No sink info\n");
1046 spd->sink_info = NULL;
1047 } else if (i == NULL) {
1050 PULSE_DEBUG_CTX("Name: %s, Index: %d\nDescr: %s\n",
1051 i->name, i->index, i->description);
1052 spd->sink_info = NULL;
1058 /* This is called whenever the context status changes */
1060 context_state_callback(pa_context *c, void *userdata)
1062 sound_pulse_data_t spd = userdata;
1064 char *sink_name = NULL;
1068 switch (pa_context_get_state(c)) {
1069 case PA_CONTEXT_UNCONNECTED:
1070 case PA_CONTEXT_CONNECTING:
1071 case PA_CONTEXT_AUTHORIZING:
1072 case PA_CONTEXT_SETTING_NAME:
1073 PULSE_DEBUG_CTX("CONN/AUTH.\n");
1074 spd->ml_running_p = 0;
1077 case PA_CONTEXT_READY:
1078 PULSE_DEBUG_CTX("ESTA.\n");
1079 sink_name = (NILP(spd->sink) ? NULL :
1080 (char*)XSTRING_DATA(spd->sink));
1083 if (!(o = pa_context_get_sink_info_by_name(
1084 spd->ctx, sink_name,
1085 sink_info_callback, spd))) {
1086 PULSE_DEBUG_CTX("Hm, no sink info ... what now?\n");
1091 pa_operation_unref(o);
1092 spd->ml_running_p = 1;
1093 pa_threaded_mainloop_signal(spd->tml, 0);
1096 case PA_CONTEXT_TERMINATED:
1097 PULSE_DEBUG_CTX("DEAD.\n");
1098 spd->ml_running_p = 0;
1099 pa_threaded_mainloop_signal(spd->tml, 0);
1102 case PA_CONTEXT_FAILED:
1104 PULSE_DEBUG_CTX("FAIL.\n");
1105 spd->ml_running_p = 0;
1106 PULSE_DEBUG_CTX("triggering semaphore.\n");
1107 pa_threaded_mainloop_signal(spd->tml, 0);
1113 /* mainloop in an extra thread API */
1115 sound_pulse_init_mainloop(ad_device_data *devdata)
1118 sound_pulse_data_t spd = (sound_pulse_data_t)devdata;
1119 /* some predeclarations to avoid ugly trigraphs */
1120 const char *client =
1121 (NILP(spd->client) ? "SXEmacs" :
1122 (const char*)XSTRING_DATA(spd->client));
1123 const char *server =
1124 (NILP(spd->server) ? NULL :
1125 (const char*)XSTRING_DATA(spd->server));
1126 int threadedp = spd->ml_threaded_p;
1128 /* cannot use Pulse on incomplete or corrupt audio devices */
1132 SXE_SEMAPH_INIT(&(spd->ctxsem));
1134 /* Set up a new main loop */
1136 spd->tml = pa_threaded_mainloop_new();
1138 spd->ml = pa_mainloop_new();
1140 if (!spd->tml && !spd->ml) {
1141 message(GETTEXT("audio-pulse: "
1142 "Failed to connect to server."));
1147 spd->mlapi = pa_threaded_mainloop_get_api(spd->tml);
1149 spd->mlapi = pa_mainloop_get_api(spd->ml);
1151 /* Create a new connection context */
1152 if (!(spd->ctx = pa_context_new(spd->mlapi, client))) {
1153 message(GETTEXT("audio-pulse: "
1154 "pa_context_new() failed."));
1160 /* initialise callback semaphore */
1162 spd->ml_running_p = 0;
1163 pa_context_set_state_callback(
1164 spd->ctx, context_state_callback, spd);
1166 /* Connect the context */
1167 if (pa_context_connect(spd->ctx, server, 0, NULL) < 0) {
1168 PULSE_DEBUG_ML("failed to connect to server\n");
1172 PULSE_DEBUG_ML("locking mainloop\n");
1173 pa_threaded_mainloop_lock(spd->tml);
1175 if (pa_threaded_mainloop_start(spd->tml) < 0) {
1176 PULSE_DEBUG_ML("failed to start mainloop\n");
1177 goto unlock_and_fail;
1180 /* Wait until the context is ready */
1181 pa_threaded_mainloop_wait(spd->tml);
1183 if (pa_context_get_state(spd->ctx) != PA_CONTEXT_READY) {
1184 PULSE_DEBUG_ML("failed to connect to server\n");
1185 goto unlock_and_fail;
1188 /* Connect the context */
1189 pa_context_connect(spd->ctx, server, 0, NULL);
1190 /* iterate manually */
1192 pa_context_state_t st;
1194 pa_mainloop_iterate(spd->ml, 1, NULL);
1195 st = pa_context_get_state(spd->ctx);
1197 switch ((unsigned int)st) {
1198 case PA_CONTEXT_CONNECTING:
1199 case PA_CONTEXT_AUTHORIZING:
1200 case PA_CONTEXT_SETTING_NAME:
1201 spd->ml_running_p = 0;
1204 case PA_CONTEXT_READY:
1205 PULSE_DEBUG_CTX("ESTA.\n");
1206 PULSE_DEBUG_CTX("READY.\n");
1207 return (spd->ml_running_p = 1);
1209 case PA_CONTEXT_TERMINATED:
1210 PULSE_DEBUG_CTX("DEAD.\n");
1211 return (spd->ml_running_p = 0);
1213 case PA_CONTEXT_FAILED:
1215 PULSE_DEBUG_CTX("FAIL.\n");
1216 return (spd->ml_running_p = 0);
1222 PULSE_DEBUG_ML("READY: %d.\n", spd->ml_running_p);
1225 if (threadedp && spd->tml) {
1226 pa_threaded_mainloop_unlock(spd->tml);
1229 /* indicate success */
1230 return spd->ml_running_p;
1233 /* DEFUN("pulse-get-sink-info-list", Fpulse_get_sink_info_list, 1, 1, 0, */
1238 /* sound-pulse.c ends here */