Partially sync files.el from XEmacs 21.5 for wildcard support.
[sxemacs] / src / media / sound-pulse.c
1 /* sound-pulse.c - play a sound over the Pulse Audio Server
2
3   Copyright (C) 2006, 2007, 2008 Sebastian Freundt
4
5   Author:  Sebastian Freundt <hroptatyr@sxemacs.org>
6
7   * This file is part of SXEmacs.
8   *
9   * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions
11   * are met:
12   *
13   * 1. Redistributions of source code must retain the above copyright
14   *    notice, this list of conditions and the following disclaimer.
15   *
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.
19   *
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.
23   *
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.
35   */
36
37 /* Synched up with: Not in FSF. */
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #include "lisp.h"
44
45 #include <unistd.h>
46 #include <fcntl.h>
47 #include <stdio.h>
48 #include <errno.h>
49 #include <string.h>
50
51 #include "media.h"
52 #include "sound.h"
53 #include "sound-pulse.h"
54
55 Lisp_Object Qpulse;
56
57 #define MYSELF ADRIVER_PULSE
58
59 #define __PULSE_DEBUG__(args...)        fprintf(stderr, "PULSE " args)
60 #ifndef PULSE_DEBUG_FLAG
61 #define PULSE_DEBUG(args...)
62 #else
63 #define PULSE_DEBUG(args...)            __PULSE_DEBUG__(args)
64 #endif
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)
74
75 \f
76 static int sound_pulse_init_mainloop(ad_device_data*);
77 static void
78 time_ev_cb(pa_mainloop_api*, pa_time_event*, const struct timeval*, void*);
79
80 struct sound_pulse_data_s {
81         Lisp_Object stream; /* media has to deal with this actually */
82         Lisp_Object client;
83         Lisp_Object role;
84         Lisp_Object sink;
85         Lisp_Object source;
86         Lisp_Object server;
87         int ml_running_p;
88         int ml_threaded_p;
89         pa_threaded_mainloop *tml;
90         pa_mainloop *ml;
91         pa_mainloop_api *mlapi;
92         pa_context *ctx;
93         const pa_sink_info *sink_info;
94         struct sxe_semaphore_s ctxsem;
95 };
96
97 struct sound_pulse_aj_data_s {
98         int volume;
99         pa_cvolume chanvol;
100         struct pa_sample_spec sampspec;
101         struct pa_channel_map chanmap;
102         pa_buffer_attr buffattr;
103         pa_stream *stream;
104         pa_context *ctx;
105
106         /* event trickery */
107         pa_time_event *time_ev;
108
109         /* coercion stuff */
110         media_sample_format_t *msf;
111         int coe_ch_cnt;
112         audio_coerce_chain_t coe_chain[4];
113         sxe_mse_rerate_args *rrargs;
114 };
115
116 \f
117 DECLARE_AUDIO_DEVICE_SIMPLE_METHS(sound_pulse);
118 DEFINE_AUDIO_DEVICE_SIMPLE(sound_pulse);
119
120 \f
121 static Lisp_Object
122 sound_pulse_mark(ad_device_data *devdata)
123 {
124         sound_pulse_data_t spd = (sound_pulse_data_t)devdata;
125         if (spd == NULL)
126                 return Qnil;
127
128         mark_object(spd->stream);
129         mark_object(spd->client);
130         mark_object(spd->sink);
131         mark_object(spd->source);
132         mark_object(spd->server);
133         return Qnil;
134 }
135
136 static void
137 sound_pulse_print(Lisp_Object device, Lisp_Object pcfun, int ef)
138 {
139         sound_pulse_data_t spd = NULL;
140         pa_context_state_t st;
141
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;
148                 return;
149         }
150
151         /* info about the connected output plugin */
152         write_c_string(" :server ", pcfun);
153         if (NILP(spd->server))
154                 write_c_string("#default", pcfun);
155         else
156                 print_internal(spd->server, pcfun, ef);
157
158         write_c_string(" :sink ", pcfun);
159         if (NILP(spd->sink)) {
160                 write_c_string("#default", pcfun);
161         } else {
162                 print_internal(spd->sink, pcfun, ef);
163         }
164
165 #if 0
166         if (spd->sink_info) {
167                 write_c_string(" (", pcfun);
168                 write_c_string(spd->sink_info->description, pcfun);
169                 write_c_string(")", pcfun);
170         } else {
171                 write_c_string(" (sink does not exist)", pcfun);
172         }
173 #endif
174
175         write_c_string(" :source ", pcfun);
176         if (NILP(spd->source))
177                 write_c_string("#default", pcfun);
178         else
179                 print_internal(spd->source, pcfun, ef);
180
181         write_c_string(" :server-state ", pcfun);
182
183         if (!spd->ctx) {
184                 write_c_string("#b0rked", pcfun);
185                 return;
186         }
187
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);
194                 break;
195
196         case PA_CONTEXT_READY:
197                 write_c_string("#connected", pcfun);
198                 break;
199
200         case PA_CONTEXT_TERMINATED:
201                 write_c_string("#terminated", pcfun);
202                 break;
203
204         case PA_CONTEXT_FAILED:
205         default:
206                 write_c_string("#failed", pcfun);
207                 break;
208         }
209
210         write_c_string(" :api ", pcfun);
211         if (spd->ml_threaded_p) {
212                 write_fmt_str(pcfun, "#threaded :mainloop 0x%lx",
213                                  (long unsigned int)spd->tml);
214         } else {
215                 write_fmt_str(pcfun, "#non-threaded :mainloop 0x%lx",
216                               (long unsigned int)spd->ml);
217         }
218         return;
219 }
220
221 \f
222 static ad_device_data *
223 sound_pulse_create(Lisp_Object pulse_options)
224 {
225         /* result */
226         sound_pulse_data_t spd = NULL;
227         /* option keywords */
228         Lisp_Object opt_server = Qnil;
229         Lisp_Object opt_sink = Qnil;
230         Lisp_Object opt_source = Qnil;
231         Lisp_Object opt_client = Qnil;
232         Lisp_Object opt_role = Qnil;
233         Lisp_Object opt_stream = Qnil;
234         Lisp_Object opt_immediate = Qnil;
235         Lisp_Object opt_threaded = Qnil;
236         Lisp_Object opt_force = Qnil;
237
238         /* parse options */
239         opt_server = Fplist_get(pulse_options, intern(":server"), Qnil);
240         if (!NILP(opt_server) && !STRINGP(opt_server)) {
241                 wrong_type_argument(Qstringp, opt_server);
242                 return NULL;
243         }
244
245         opt_sink = Fplist_get(pulse_options, intern(":sink"), Qnil);
246         if (!NILP(opt_sink) && !STRINGP(opt_sink)) {
247                 wrong_type_argument(Qstringp, opt_sink);
248                 return NULL;
249         }
250
251         opt_client = Fplist_get(pulse_options, intern(":client"), Qnil);
252         if (!NILP(opt_client) && !STRINGP(opt_client)) {
253                 wrong_type_argument(Qstringp, opt_client);
254                 return NULL;
255         }
256
257         opt_role = Fplist_get(pulse_options, intern(":role"), Qnil);
258         if (!NILP(opt_role) && !STRINGP(opt_role)) {
259                 wrong_type_argument(Qstringp, opt_role);
260                 return NULL;
261         }
262
263         opt_stream = Fplist_get(pulse_options, intern(":stream"), Qnil);
264         if (!NILP(opt_stream) && !STRINGP(opt_stream)) {
265                 wrong_type_argument(Qstringp, opt_stream);
266                 return NULL;
267         }
268
269         opt_immediate = Fplist_get(pulse_options, intern(":immediate"), Qt);
270         opt_threaded = Fplist_get(pulse_options, intern(":threaded"), Qt);
271         opt_force = Fplist_get(pulse_options, intern(":force"), Qnil);
272
273         /* initialise and fill */
274         spd = xnew_and_zero(struct sound_pulse_data_s);
275         spd->server = opt_server;
276         spd->client = opt_client;
277         spd->role = opt_role;
278         spd->sink = opt_sink;
279         spd->source = opt_source;
280         spd->stream = opt_stream;
281
282         spd->ml_threaded_p = !NILP(opt_threaded);
283
284         if (NILP(opt_immediate))
285                 return (ad_device_data*)spd;
286
287         sound_pulse_init_mainloop(spd);
288
289         if (spd->ml_running_p == 0) /* yeah, finish immediately */
290                 sound_pulse_finish(spd);
291
292         if (NILP(opt_force) && spd->ml_running_p == 0) {
293                 xfree(spd);
294                 spd = NULL;
295                 error(GETTEXT("Error: audio-pulse: "
296                               "Initialising connection to PulseAudio failed."));
297                 return NULL;
298         }
299
300         return (ad_device_data*)spd;
301 }
302
303 static void
304 sound_pulse_finish(ad_device_data *data)
305 {
306         sound_pulse_data_t spd = data;
307         if (spd == NULL)
308                 return;
309
310         if (spd != NULL && 0) {
311                 spd->stream = Qnil;
312                 spd->server = Qnil;
313                 spd->client = Qnil;
314                 spd->role = Qnil;
315                 spd->sink = Qnil;
316                 spd->source = Qnil;
317         }
318
319         spd->ml_running_p = 0;
320
321         /* setting this to 0 is not enough? :\ */
322         if (spd->ctx) {
323                 PULSE_DEBUG_CTX("DRAIN.\n");
324                 pa_context_drain(spd->ctx, NULL, NULL);
325                 PULSE_DEBUG_CTX("STOP.\n");
326                 pa_context_disconnect(spd->ctx);
327                 pa_context_unref(spd->ctx);
328                 SXE_SEMAPH_FINI(&(spd->ctxsem));
329         }
330         spd->ctx = NULL;
331
332         PULSE_DEBUG_ML("Is there a mainloop awake?\n");
333         if (spd->ml_threaded_p) {
334                 if (spd->tml) {
335                         PULSE_DEBUG_ML("STOP.\n");
336                         pa_threaded_mainloop_stop(spd->tml);
337                         PULSE_DEBUG_ML("FREE. bye bye\n");
338                         pa_threaded_mainloop_free(spd->tml);
339                 }
340                 spd->tml = NULL;
341         } else {
342                 if (spd->ml) {
343                         ;
344                         PULSE_DEBUG_ML("FREE. bye bye (non-threaded)\n");
345                         pa_mainloop_free(spd->ml);
346                 }
347                 spd->ml = NULL;
348         }
349
350         PULSE_DEBUG_CTX("finish.\n");
351
352         spd->tml = NULL;
353         spd->ml = NULL;
354         return;
355 }
356
357 \f
358 /** Wait until the specified operation completes */
359 #define wait_for_operation(_m, _o)                                      \
360         do {                                                            \
361                 struct pa_operation *__o = (_o);                        \
362                 while (pa_operation_get_state(__o) ==                   \
363                        PA_OPERATION_RUNNING)                            \
364                         pa_mainloop_iterate((_m), 1, NULL);             \
365                 pa_operation_unref(__o);                                \
366         } while(0)
367
368 /** Wait until no further actions are pending on the connection context */
369 #define wait_for_completion(_c, _m)                                     \
370         do {                                                            \
371                 while (pa_context_is_pending(_c))                       \
372                         pa_mainloop_iterate((_m), 1, NULL);             \
373         } while(0)
374
375
376 static void
377 my_pa_free_cb(void *data)
378 {
379         /* dummy callback which ought to free DATA,
380          * however, we want to recycle the memory as much as possible,
381          * we free it ourselves */
382         PULSE_DEBUG_S("my_pa_free_cb called 0x%lx\n",
383                       (long unsigned int)data);
384         return;
385 }
386
387 \f
388 static inline pa_volume_t
389 _sound_pulse_change_volume(
390         pa_cvolume *cvolp, pa_context *ctx,
391         pa_stream *stream, pa_volume_t volume)
392         __attribute__((always_inline));
393 static inline pa_volume_t
394 _sound_pulse_change_volume(
395         pa_cvolume *cvolp, pa_context *ctx,
396         pa_stream *stream, pa_volume_t volume)
397 {
398         pa_operation *o;
399
400         pa_cvolume_set(cvolp, cvolp->channels,
401                        (volume*PA_VOLUME_NORM)/MEDIA_SAMPLE_VOLUME_NORM);
402
403         if (!(o = pa_context_set_sink_input_volume(
404                       ctx, pa_stream_get_index(stream), cvolp, NULL, NULL))) {
405                 PULSE_CRITICAL("Cannot set volume.\n");
406         } else {
407                 pa_operation_unref(o);
408         }
409         return volume;
410 }
411
412 /* handling of events from the audio job's private queue */
413 #ifdef EF_USE_ASYNEQ
414 static inline void
415 sound_pulse_stop(audio_job_t aj)
416         __attribute__((always_inline));
417 static inline void
418 sound_pulse_stop(audio_job_t aj)
419 {
420         sound_pulse_aj_data_t spsd;
421         pa_stream *stream;
422
423         SXE_MUTEX_LOCK(&aj->mtx);
424         spsd = audio_job_device_data(aj);
425         stream = spsd->stream;
426         PULSE_DEBUG_S("FLUSH. (0x%lx)\n", (long unsigned int)aj);
427         pa_operation_unref(pa_stream_flush(stream, NULL, NULL));
428         pa_stream_disconnect(stream);
429         aj->play_state = MTPSTATE_STOP;
430         SXE_MUTEX_UNLOCK(&aj->mtx);
431         return;
432 }
433
434 static inline void
435 sound_pulse_pause(audio_job_t aj)
436         __attribute__((always_inline));
437 static inline void
438 sound_pulse_pause(audio_job_t aj)
439 {
440         sound_pulse_aj_data_t spsd;
441         sound_pulse_data_t spd;
442         pa_stream *stream;
443         struct timeval tv;
444
445         SXE_MUTEX_LOCK(&aj->mtx);
446         spd = get_audio_device_data(aj->device);
447         spsd = audio_job_device_data(aj);
448         stream = spsd->stream;
449         PULSE_DEBUG_S("CORK. (0x%lx)\n", (long unsigned int)aj);
450         pa_operation_unref(pa_stream_cork(stream, 1, NULL, NULL));
451         aj->play_state = MTPSTATE_PAUSE;
452
453         if (audio_job_queue(aj)) {
454                 spsd->time_ev = spd->mlapi->
455                         time_new(spd->mlapi, &tv, time_ev_cb, aj);
456         }
457
458         SXE_MUTEX_UNLOCK(&aj->mtx);
459         return;
460 }
461
462 static inline void
463 sound_pulse_resume(audio_job_t aj)
464         __attribute__((always_inline));
465 static inline void
466 sound_pulse_resume(audio_job_t aj)
467 {
468         sound_pulse_aj_data_t spsd;
469         sound_pulse_data_t spd;
470         pa_stream *stream;
471
472         SXE_MUTEX_LOCK(&aj->mtx);
473         spd = get_audio_device_data(aj->device);
474         spsd = audio_job_device_data(aj);
475         stream = spsd->stream;
476         PULSE_DEBUG_S("UNCORK. (0x%lx)\n", (long unsigned int)aj);
477
478         if (spsd->time_ev) {
479                 spd->mlapi->time_free(spsd->time_ev);
480                 spsd->time_ev = NULL;
481         }
482
483         pa_operation_unref(pa_stream_cork(stream, 0, NULL, NULL));
484         aj->play_state = MTPSTATE_RUN;
485         SXE_MUTEX_UNLOCK(&aj->mtx);
486         return;
487 }
488
489 static inline void
490 sound_pulse_change_volume(audio_job_t aj, audio_job_event_args_t args)
491 {
492         sound_pulse_aj_data_t spsd;
493         pa_volume_t new_vol = args->volume_args;
494
495         PULSE_DEBUG_AJ("->%d\n", (int)new_vol);
496
497         SXE_MUTEX_LOCK(&aj->mtx);
498         spsd = audio_job_device_data(aj);
499         spsd->volume = _sound_pulse_change_volume(
500                 &spsd->chanvol, spsd->ctx, spsd->stream, new_vol);
501         aj->volume = (int)(spsd->volume);
502         SXE_MUTEX_UNLOCK(&aj->mtx);
503 }
504
505 static inline void
506 sound_pulse_change_rate(audio_job_t aj, audio_job_event_args_t args)
507 {
508         SXE_MUTEX_LOCK(&aj->mtx);
509         aj->ratetrafo = args->rate_args;
510         SXE_MUTEX_UNLOCK(&aj->mtx);
511 }
512
513 static inline void
514 sound_pulse_change_state(audio_job_t aj, audio_job_event_args_t args)
515 {
516         switch (args->state_args) {
517         case aj_pause:
518                 PULSE_DEBUG_AJ("->pause state\n");
519                 sound_pulse_pause(aj);
520                 break;
521         case aj_resume:
522                 PULSE_DEBUG_AJ("->resume state\n");
523                 sound_pulse_resume(aj);
524                 break;
525         case aj_start:
526                 PULSE_DEBUG_AJ("->start state\n");
527                 break;
528         case aj_stop:
529                 PULSE_DEBUG_AJ("->stop state\n");
530                 sound_pulse_stop(aj);
531                 break;
532
533         case no_audio_job_change_states:
534         default:
535                 PULSE_DEBUG_AJ("->unknown state\n");
536                 break;
537         }
538 }
539
540 static inline void
541 sound_pulse_handle_aj_events(audio_job_t aj)
542         __attribute__((always_inline));
543 static inline void
544 sound_pulse_handle_aj_events(audio_job_t aj)
545 {
546         sound_pulse_aj_data_t spsd;
547         pa_stream *stream;
548         audio_job_event_t ev = NULL;
549         event_queue_t eq;
550
551 #if defined EF_USE_ASYNEQ
552         if (audio_job_queue(aj)) {
553                 assert((long unsigned int)audio_job_queue(aj) != 0xB16B00B5);
554         }
555 #endif
556
557         PULSE_DEBUG_AJ("handle aj events called on 0x%lx\n",
558                        (long unsigned int)aj);
559
560         SXE_MUTEX_LOCK(&aj->mtx);
561         spsd = audio_job_device_data(aj);
562         eq = audio_job_queue(aj);
563         SXE_MUTEX_UNLOCK(&aj->mtx);
564         stream = spsd->stream;
565         if ((ev = eq_noseeum_dequeue(eq)) == NULL) {
566                 return;
567         }
568         if (stream == NULL || pa_stream_get_state(stream) != PA_STREAM_READY) {
569                 return;
570         }
571
572         PULSE_DEBUG_AJ("Event 0x%lx\n", (long unsigned int)ev);
573         switch (audio_job_event_kind(ev)) {
574         case aj_change_state:
575                 PULSE_DEBUG_AJ("change state event\n");
576                 sound_pulse_change_state(aj, &audio_job_event_args(ev));
577                 break;
578         case aj_change_volume:
579                 PULSE_DEBUG_AJ("change volume event\n");
580                 sound_pulse_change_volume(aj, &audio_job_event_args(ev));
581                 break;
582         case aj_change_rate:
583                 PULSE_DEBUG_AJ("change rate event\n");
584                 sound_pulse_change_rate(aj, &audio_job_event_args(ev));
585                 break;
586
587         case no_audio_job_event_kinds:
588         default:
589                 PULSE_CRITICAL("unknown event\n");
590                 break;
591         }
592         free_audio_job_event(ev);
593 }
594
595 static void
596 time_ev_cb(pa_mainloop_api *m, pa_time_event *e,
597            const struct timeval *tv, void *userdata)
598 {
599         /* check an audio-job's queue for incoming events */
600         struct timeval next;    /* for rescheduling this construction */
601         audio_job_t aj = userdata;
602         sound_pulse_aj_data_t spsd = audio_job_device_data(aj);;
603
604         sound_pulse_handle_aj_events(userdata);
605
606         if (spsd->time_ev != NULL) {
607                 /* reschedule the thing */
608                 pa_gettimeofday(&next);
609                 pa_timeval_add(&next, 25000);
610                 m->time_restart(e, &next);
611         }
612 }
613 #endif  /* EF_USE_ASYNEQ */
614
615 /* This is called whenever stream draining has completed */
616 static void
617 stream_drain_complete(pa_stream *stream, int success, void *userdata)
618 {
619         audio_job_t aj = userdata;
620
621         PULSE_DEBUG_S("drain_complete cb called (0x%lx)\n",
622                       (long unsigned int)aj);
623
624         if (UNLIKELY(!success)) {
625                 PULSE_CRITICAL("Failed to drain stream 0x%lx\n",
626                                (long unsigned int)aj);
627         }
628
629         pa_stream_disconnect(stream);
630         PULSE_DEBUG_S("leaving stream_drain cb (0x%lx)\n",
631                       (long unsigned int)aj);
632         return;
633 }
634
635 /* This is called whenever new data may be written to the stream */
636 static void
637 stream_write_callback(pa_stream *stream, size_t length, void *userdata)
638 {
639         audio_job_t aj = NULL;
640         media_substream *mss = NULL;
641         int resolution __attribute__((unused));
642         int channels;
643         media_thread_play_state mtp;
644         size_t len, tmplen;
645         size_t real_frm_sz __attribute__((unused));
646         long int i;
647         /* pulse and subthread stuff */
648         sound_pulse_aj_data_t spsd;
649         pa_context *ctx __attribute__((unused)) = NULL;
650         sxe_media_sample_t *tmpbuf;
651
652         assert(stream && length);
653
654         if (((aj = userdata) == NULL) ||
655             ((mss = aj->substream) == NULL)) {
656                 PULSE_CRITICAL("This idiot of mainloop gave us wrong data: "
657                                "aj:0x%lx mss:0x%lx\n",
658                                (long unsigned int)aj,
659                                (long unsigned int)mss);
660
661                 PULSE_DEBUG_S("FLUSH.\n");
662                 pa_operation_unref(
663                         pa_stream_flush(
664                                 stream, stream_drain_complete, aj));
665                 pa_stream_disconnect(stream);
666                 return;
667         }
668
669         PULSE_DEBUG_S("stream_write cb called on 0x%lx\n",
670                       (long unsigned int)aj);
671         if (audio_job_queue(aj)) {
672                 PULSE_DEBUG_S("checking queue\n");
673                 sound_pulse_handle_aj_events(userdata);
674         }
675         SXE_MUTEX_LOCK(&aj->mtx);
676         spsd = audio_job_device_data(aj);
677         resolution = aj->resolution;
678         real_frm_sz = SOUND_MAX_SAMPLE_WIDTH * (channels = aj->channels);
679         ctx = spsd->ctx;
680
681 #ifndef EF_USE_ASYNEQ
682         /* Set the playback volume of the stream */
683         if (aj->volume != spsd->volume) {
684                 spsd->volume = _sound_pulse_change_volume(
685                         &spsd->chanvol, ctx, stream, (pa_volume_t)aj->volume);
686         }
687 #endif  /* !EF_USE_ASYNEQ */
688
689         mtp = aj->play_state;
690         switch (mtp) {
691         case MTPSTATE_RUN:
692                 /* set up length, rerate args and tmpbuf */
693                 tmplen = length * (spsd->rrargs->tweak = aj->ratetrafo);
694                 /* It's unlikely but I hit these constraints personally once so
695                    let's handle them here.
696                    Problem is that a request of 10000 samples from ffmpeg might
697                    yield 11560 samples because the decode is not that
698                    fine-tunable because a muxed'n'encoded packet likely (if not
699                    always) contains a bunch of raw samples (==
700                    demuxed'n'decoded).
701                    Thence we add an extra 25% threshold here to be maximum
702                    sure not to ask for our own suicide.  Of course the media
703                    driver itself ought to make sure not to flood the buffer
704                    accidentally.  This however is not possible at the moment,
705                    look at the signature of the media_stream_meth to get the
706                    enlightenment.
707                 */
708                 if (UNLIKELY(tmplen > 4 * aj->buffer_alloc_size / 5)) {
709                         tmplen = 4 * aj->buffer_alloc_size / 5;
710                 }
711                 tmplen /= aj->framesize;
712                 tmpbuf = (sxe_media_sample_t*)aj->buffer;
713                 PULSE_DEBUG_S("asking for %u frames, fetching %u instead "
714                               "(0x%lx)\n",
715                               length/aj->framesize, tmplen,
716                               (long unsigned int)aj);
717                 len = media_stream_meth(mss->up, read)(mss, aj->buffer, tmplen);
718                 PULSE_DEBUG_S("reader sent %u frames down the pipe\n", len);
719                 /* result `len' has number of frames */
720                 if (len == 0) {
721                         tmplen = 0;
722                         break;
723                 }
724
725                 /* coerce the stuff, tmplen is in samples */
726                 tmplen = channels*len;
727                 for (i = 0; i < spsd->coe_ch_cnt; i++) {
728                         PULSE_DEBUG_COE("calling coerce "
729                                         "%lu on b:0x%lx l:%lu\n",
730                                         (long unsigned int)i,
731                                         (long unsigned int)tmpbuf,
732                                         (long unsigned int)tmplen);
733                         tmplen = CALL_MEDIA_SAMPLE_EFFECT(
734                                 spsd->coe_chain, i, tmpbuf, tmpbuf, tmplen);
735                 }
736
737                 MEDIA_SAMPLE_FORMAT_DOWNSAMPLE(spsd->msf)(
738                         aj->buffer, aj->buffer, tmplen);
739
740                 tmplen = tmplen * sizeof(int16_t);
741
742                 break;
743         case MTPSTATE_PAUSE:
744 #if !defined EF_USE_ASYNEQ
745                 /* fill buffer with zeros */
746                 tmplen = (len = length) * channels * sizeof(int16_t);
747                 memset(aj->buffer, 0, tmplen);
748                 break;
749 #endif
750
751         case MTPSTATE_UNKNOWN:
752         case NUMBER_OF_MEDIA_THREAD_PLAY_STATES:
753         case MTPSTATE_STOP:
754         default:
755                 PULSE_DEBUG_S("MTPSTATE == STOP, "
756                               "hence leaving stream_write cb\n");
757                 SXE_MUTEX_UNLOCK(&aj->mtx);
758                 return;
759         }
760
761         if (LIKELY(len > 0)) {
762                 PULSE_DEBUG_S("writing %u frames == %u samples == %u bytes "
763                               "(0x%lx)\n",
764                               tmplen/aj->framesize,
765                               tmplen*aj->channels / aj->framesize,
766                               tmplen,
767                               (long unsigned int)aj);
768                 pa_stream_write(stream, aj->buffer, tmplen,
769                                 my_pa_free_cb, 0, PA_SEEK_RELATIVE);
770         }
771
772         if (tmplen < length) {
773                 PULSE_DEBUG_S("DRAIN. (0x%lx)\n", (long unsigned int)aj);
774                 aj->play_state = MTPSTATE_STOP;
775                 pa_operation_unref(
776                         pa_stream_drain(
777                                 stream, stream_drain_complete, aj));
778         }
779
780         SXE_MUTEX_UNLOCK(&aj->mtx);
781         PULSE_DEBUG_S("leaving stream_write cb\n");
782         return;
783 }
784
785 /* This routine is called whenever the stream state changes */
786 static void
787 stream_state_callback(pa_stream *s, void *userdata)
788 {
789         sxe_semaphore_t sem = userdata;
790         pa_context_state_t st;
791
792         assert(s);
793
794         st = pa_stream_get_state(s);
795         switch ((unsigned int)st) {
796         case PA_STREAM_CREATING:
797                 PULSE_DEBUG_S("CREATING.\n");
798                 break;
799         case PA_STREAM_TERMINATED:
800                 PULSE_DEBUG_S("TERMINATED.\n");
801                 PULSE_DEBUG_PT("trigger local semaphore\n");
802                 SXE_SEMAPH_TRIGGER(sem);
803                 break;
804
805         case PA_STREAM_READY:
806                 PULSE_DEBUG_S("READY.\n");
807                 break;
808
809         case PA_STREAM_FAILED:
810         default:
811                 PULSE_DEBUG_S("FAILED.\n");
812                 PULSE_DEBUG_PT("trigger local semaphore\n");
813                 SXE_SEMAPH_TRIGGER(sem);
814                 break;
815         }
816         return;
817 }
818
819 \f
820 static int
821 sound_pulse_play(audio_job_t aj)
822 {
823         /* stream stuff */
824         mtype_audio_properties *mtap;
825         Lisp_Media_Stream *ms;
826         media_substream *mss;
827         /* device stuff */
828         Lisp_Object device;
829         sound_pulse_data_t spd = NULL;
830         Lisp_Audio_Device *lad = NULL;
831         /* pulse stuff */
832         struct sound_pulse_aj_data_s _spsd, *spsd = &_spsd;
833         struct pa_sample_spec *ssp = &spsd->sampspec;
834         struct pa_channel_map *cmapp = &spsd->chanmap;
835         pa_buffer_attr *bap = &spsd->buffattr;
836         pa_stream *stream = NULL;
837         int r = 0;
838         char *stream_name = NULL;
839         char *sink_name = NULL;
840         sxe_mse_rerate_args _rrargs, *rrargs = &_rrargs;
841         /* semaphore stuff */
842         struct sxe_semaphore_s _sem, *sem = &_sem;
843         /* cache stuff */
844         int alloced_myself = 0;
845
846         /* unpack the media thread */
847         SOUND_UNPACK_MT(aj, device, ms, mss, lad, spd, mtap);
848
849         /* Set up a new main loop - if it's not already running */
850         if (!(r = spd->ml_running_p)) {
851                 PULSE_DEBUG_ML("trying to restart main loop...\n");
852                 r = sound_pulse_init_mainloop(spd);
853                 PULSE_DEBUG_ML("result was: %d\n", r);
854         }
855
856         if (r == 0 || spd->ml_running_p == 0) {
857                 warn_when_safe(Qpulse, Qerror,
858                                GETTEXT("Failed to (re)connect to server."));
859                 XAUDIO_DEVICE_STATE(device) = ASTATE_DEAD;
860                 goto finish;
861         }
862
863         /* prepare pulse sample specs */
864         ssp->rate = mtap->samplerate;
865         ssp->channels = mtap->channels;
866
867         /* prepare pulse channel map and output format */
868         pa_channel_map_init_auto(cmapp, ssp->channels, PA_CHANNEL_MAP_ALSA);
869         ssp->format = PA_SAMPLE_S16NE;
870
871         if (spd->ml_running_p && spd->ml_threaded_p) {
872                 PULSE_DEBUG_ML("lock.\n");
873                 pa_threaded_mainloop_lock(spd->tml);
874         }
875
876         stream_name = (NILP(spd->stream) ? "SXEmacs stream" :
877                        (char*)XSTRING_DATA(spd->stream));
878         sink_name = (NILP(spd->sink) ? NULL :
879                      (char*)XSTRING_DATA(spd->sink));
880
881         /* create the stream */
882         PULSE_DEBUG_S("Creating stream...\n");
883         if (!spd->ml_running_p ||
884             !(stream = pa_stream_new(spd->ctx, stream_name, ssp, cmapp))) {
885                 PULSE_CRITICAL("SXEmacs critical: [pulse] stream is NULL. "
886                                "Mainloop not running?!\n");
887                 goto finish;
888         }
889         PULSE_DEBUG_S("Created stream 0x%lx\n", (long unsigned int)stream);
890
891         /* obviously our device is alive
892          * This does NOT mean that you can hear the sounds */
893         XAUDIO_DEVICE_STATE(device) = ASTATE_ALIVE;
894
895         /* rewind the media substream */
896         media_stream_meth(ms, rewind)(mss);
897         SXE_MUTEX_LOCK(&aj->mtx);
898         if (aj->buffer_alloc_size == 0) {
899                 PULSE_DEBUG_CACHE("worker buffer (sz:%ld) too small, "
900                                   "reallocate (sz:%ld)\n",
901                                   (long int)aj->buffer_alloc_size,
902                                   (long int)SOUND_MAX_AUDIO_FRAME_SIZE);
903                 alloced_myself = 1;
904                 aj->buffer = xmalloc_atomic(SOUND_MAX_AUDIO_FRAME_SIZE);
905                 aj->buffer_alloc_size = SOUND_MAX_AUDIO_FRAME_SIZE;
906         }
907         aj->resolution = mtap->samplerate * mtap->channels;
908         aj->framesize = mtap->channels * sizeof(int16_t);
909         aj->channels = mtap->channels;
910         SXE_MUTEX_UNLOCK(&aj->mtx);
911
912         /* initialise buffer attributes */
913         bap->maxlength = mtap->samplerate * aj->framesize;
914         bap->tlength = 9 * bap->maxlength / 10;
915         bap->minreq = bap->tlength / 10;
916         bap->prebuf = bap->tlength / SOUND_MAX_SAMPLE_WIDTH;
917         bap->fragsize = bap->minreq;
918
919         pa_cvolume_set(&spsd->chanvol, ssp->channels,
920                        ((pa_volume_t)aj->volume*PA_VOLUME_NORM)/
921                        MEDIA_SAMPLE_VOLUME_NORM);
922         spsd->ctx = spd->ctx;
923         spsd->stream = stream;
924         spsd->time_ev = NULL;
925         audio_job_device_data(aj) = spsd;
926
927         /* initialise our thread semaphore */
928         PULSE_DEBUG_PT("init pulse local semaphore\n");
929         SXE_SEMAPH_INIT(sem);
930
931         /* coercion stuff */
932         spsd->msf = MEDIA_SAMPLE_FORMAT(sxe_msf_S16);
933         spsd->coe_ch_cnt = 0;
934         /* the rerate effect */
935         ADD_MEDIA_SAMPLE_EFFECT(
936                 spsd->coe_chain, spsd->coe_ch_cnt,
937                 MEDIA_SAMPLE_EFFECT(sxe_mse_rerate), rrargs);
938         rrargs->num_channels = mtap->channels;
939         rrargs->srcrate = rrargs->tgtrate = 1;
940         spsd->rrargs = rrargs;
941
942         PULSE_DEBUG_S("setting up stream.\n");
943         pa_stream_set_state_callback(stream, stream_state_callback, sem);
944         pa_stream_set_write_callback(stream, stream_write_callback, aj);
945
946         /* we better check if ml is still running */
947         if (!spd->ml_running_p)
948                 goto finish;
949         pa_stream_connect_playback(
950                 stream, sink_name, bap, 0, &spsd->chanvol, NULL);
951
952         if (spd->ml_running_p && spd->ml_threaded_p) {
953                 WITH_SXE_SEMAPH_SYNCH(
954                         sem,
955                         PULSE_DEBUG_ML("unlock.\n");
956                         pa_threaded_mainloop_unlock(spd->tml);
957                         PULSE_DEBUG_MX("play.\n"););
958                 PULSE_DEBUG_PT("ACK, shall finish.\n");
959         } else if (spd->ml_running_p) {
960                 /* iterate by hand */
961                 pa_stream_state_t state;
962                 while (spd->ml_running_p) {
963                         pa_mainloop_iterate(spd->ml, 1, NULL);
964                         state = pa_stream_get_state(stream);
965                         if (!(state == PA_STREAM_READY ||
966                               state == PA_STREAM_CREATING)) {
967                                 break;
968                         }
969                 }
970         }
971
972         /* ... and outta here */
973         PULSE_DEBUG_S("finish.\n");
974
975         /* close and shutdown */
976 finish:
977         SXE_MUTEX_LOCK(&aj->mtx);
978         if (alloced_myself && aj->buffer) {
979                 PULSE_DEBUG_S("freeing stream buffer.\n");
980                 xfree(aj->buffer);
981         }
982         aj->buffer = NULL;
983         aj->buffer_alloc_size = 0;
984
985         /* device data could be finished already, hence we refetch it */
986         spd = get_audio_device_data(aj->device);
987         SXE_MUTEX_UNLOCK(&aj->mtx);
988
989         if (spd && spd->ml_running_p && spd->ml_threaded_p) {
990                 PULSE_DEBUG_ML("lock.\n");
991                 pa_threaded_mainloop_lock(spd->tml);
992         }
993
994 #ifdef EF_USE_ASYNEQ
995         /* kick those timers */
996         if (spsd->time_ev != NULL) {
997                 spd->mlapi->time_free(spsd->time_ev);
998         }
999         spsd->time_ev = NULL;
1000 #endif
1001
1002 #if 1
1003         if (stream) {
1004                 PULSE_DEBUG_S("unref.\n");
1005                 pa_stream_unref(stream);
1006                 stream = NULL;
1007         }
1008 #endif
1009
1010         if (spd && spd->ml_running_p && spd->ml_threaded_p) {
1011                 PULSE_DEBUG_ML("unlock.\n");
1012                 pa_threaded_mainloop_unlock(spd->tml);
1013         }
1014
1015         SXE_MUTEX_LOCK(&aj->mtx);
1016         audio_job_device_data(aj) = NULL;
1017         SXE_MUTEX_UNLOCK(&aj->mtx);
1018
1019         /* finish the pulse device data if pulse is not running anymore */
1020         if (spd && !spd->ml_running_p) {
1021                 SXE_MUTEX_LOCK(&aj->mtx);
1022                 XAUDIO_DEVICE_STATE(aj->device) = ASTATE_DEAD;
1023                 SXE_MUTEX_UNLOCK(&aj->mtx);
1024                 sound_pulse_finish(spd);
1025                 return 0;
1026         }
1027
1028         /* deinitialise our thread semaphore */
1029         PULSE_DEBUG_PT("deinit pulse local semaphore\n");
1030         SXE_SEMAPH_FINI(sem);
1031
1032         return 1;
1033 }
1034
1035 \f
1036 #define CHECK_DEAD_GOTO(label)                                          \
1037         do {                                                            \
1038                 if (!spd->ctx ||                                        \
1039                     pa_context_get_state(spd->ctx) != PA_CONTEXT_READY) { \
1040                         PULSE_CRITICAL("Uh oh, operation failed.\n");   \
1041                         goto label;                                     \
1042                 }                                                       \
1043         } while(0)
1044
1045 static void
1046 sink_info_callback(pa_context *c, const pa_sink_info *i, int eol, void *data)
1047 {
1048         sound_pulse_data_t spd = data;
1049
1050         if (eol < 0) {
1051                 PULSE_DEBUG_CTX("No sink info\n");
1052                 spd->sink_info = NULL;
1053         } else if (i == NULL) {
1054                 ;
1055         } else {
1056                 PULSE_DEBUG_CTX("Name: %s, Index: %d\nDescr: %s\n",
1057                                 i->name, i->index, i->description);
1058                 spd->sink_info = NULL;
1059         }
1060
1061         return;
1062 }
1063
1064 /* This is called whenever the context status changes */
1065 static void
1066 context_state_callback(pa_context *c, void *userdata)
1067 {
1068         sound_pulse_data_t spd = userdata;
1069         pa_operation *o;
1070         char *sink_name = NULL;
1071
1072         assert(c);
1073
1074         switch (pa_context_get_state(c)) {
1075         case PA_CONTEXT_UNCONNECTED:
1076         case PA_CONTEXT_CONNECTING:
1077         case PA_CONTEXT_AUTHORIZING:
1078         case PA_CONTEXT_SETTING_NAME:
1079                 PULSE_DEBUG_CTX("CONN/AUTH.\n");
1080                 spd->ml_running_p = 0;
1081                 break;
1082
1083         case PA_CONTEXT_READY:
1084                 PULSE_DEBUG_CTX("ESTA.\n");
1085                 sink_name = (NILP(spd->sink) ? NULL :
1086                              (char*)XSTRING_DATA(spd->sink));
1087
1088                 /* query sinks */
1089                 if (!(o = pa_context_get_sink_info_by_name(
1090                               spd->ctx, sink_name,
1091                               sink_info_callback, spd))) {
1092                         PULSE_DEBUG_CTX("Hm, no sink info ... what now?\n");
1093                 } else {
1094                         ;
1095                 }
1096
1097                 pa_operation_unref(o);
1098                 spd->ml_running_p = 1;
1099                 pa_threaded_mainloop_signal(spd->tml, 0);
1100                 break;
1101
1102         case PA_CONTEXT_TERMINATED:
1103                 PULSE_DEBUG_CTX("DEAD.\n");
1104                 spd->ml_running_p = 0;
1105                 pa_threaded_mainloop_signal(spd->tml, 0);
1106                 break;
1107
1108         case PA_CONTEXT_FAILED:
1109         default:
1110                 PULSE_DEBUG_CTX("FAIL.\n");
1111                 spd->ml_running_p = 0;
1112                 PULSE_DEBUG_CTX("triggering semaphore.\n");
1113                 pa_threaded_mainloop_signal(spd->tml, 0);
1114                 break;
1115         }
1116         return;
1117 }
1118
1119 /* mainloop in an extra thread API */
1120 static int
1121 sound_pulse_init_mainloop(ad_device_data *devdata)
1122 {
1123         /* device stuff */
1124         sound_pulse_data_t spd = (sound_pulse_data_t)devdata;
1125         /* some predeclarations to avoid ugly trigraphs */
1126         const char *client =
1127                 (NILP(spd->client) ? "SXEmacs" :
1128                  (const char*)XSTRING_DATA(spd->client));
1129         const char *server =
1130                 (NILP(spd->server) ? NULL :
1131                  (const char*)XSTRING_DATA(spd->server));
1132         const char *role =
1133                 (NILP(spd->role) ? "event" :
1134                  (const char*)XSTRING_DATA(spd->role));
1135         int threadedp = spd->ml_threaded_p;
1136
1137         /* cannot use Pulse on incomplete or corrupt audio devices */
1138         if (spd == NULL)
1139                 return 0;
1140
1141         SXE_SEMAPH_INIT(&(spd->ctxsem));
1142
1143         setenv("PULSE_PROP_media.role", role, 1);
1144
1145         /* Set up a new main loop */
1146         if (threadedp)
1147                 spd->tml = pa_threaded_mainloop_new();
1148         else
1149                 spd->ml = pa_mainloop_new();
1150
1151         if (!spd->tml && !spd->ml) {
1152                 message(GETTEXT("audio-pulse: "
1153                                 "Failed to connect to server."));
1154                 return 0;
1155         }
1156
1157         if (threadedp)
1158                 spd->mlapi = pa_threaded_mainloop_get_api(spd->tml);
1159         else
1160                 spd->mlapi = pa_mainloop_get_api(spd->ml);
1161
1162         /* Create a new connection context */
1163         if (!(spd->ctx = pa_context_new(spd->mlapi, client))) {
1164                 message(GETTEXT("audio-pulse: "
1165                                 "pa_context_new() failed."));
1166                 spd->ml = NULL;
1167                 spd->tml = NULL;
1168                 return 0;
1169         }
1170
1171         /* initialise callback semaphore */
1172         if (threadedp) {
1173                 spd->ml_running_p = 0;
1174                 pa_context_set_state_callback(
1175                         spd->ctx, context_state_callback, spd);
1176
1177                 /* Connect the context */
1178                 if (pa_context_connect(spd->ctx, server, 0, NULL) < 0) {
1179                         PULSE_DEBUG_ML("failed to connect to server\n");
1180                         goto fail;
1181                 }
1182
1183                 PULSE_DEBUG_ML("locking mainloop\n");
1184                 pa_threaded_mainloop_lock(spd->tml);
1185
1186                 if (pa_threaded_mainloop_start(spd->tml) < 0) {
1187                         PULSE_DEBUG_ML("failed to start mainloop\n");
1188                         goto unlock_and_fail;
1189                 }
1190
1191                 /* Wait until the context is ready */
1192                 pa_threaded_mainloop_wait(spd->tml);
1193
1194                 if (pa_context_get_state(spd->ctx) != PA_CONTEXT_READY) {
1195                         PULSE_DEBUG_ML("failed to connect to server\n");
1196                         goto unlock_and_fail;
1197                 }
1198         } else {
1199                 /* Connect the context */
1200                 pa_context_connect(spd->ctx, server, 0, NULL);
1201                 /* iterate manually */
1202                 while (1) {
1203                         pa_context_state_t st;
1204
1205                         pa_mainloop_iterate(spd->ml, 1, NULL);
1206                         st = pa_context_get_state(spd->ctx);
1207
1208                         switch ((unsigned int)st) {
1209                         case PA_CONTEXT_CONNECTING:
1210                         case PA_CONTEXT_AUTHORIZING:
1211                         case PA_CONTEXT_SETTING_NAME:
1212                                 spd->ml_running_p = 0;
1213                                 break;
1214
1215                         case PA_CONTEXT_READY:
1216                                 PULSE_DEBUG_CTX("ESTA.\n");
1217                                 PULSE_DEBUG_CTX("READY.\n");
1218                                 return (spd->ml_running_p = 1);
1219
1220                         case PA_CONTEXT_TERMINATED:
1221                                 PULSE_DEBUG_CTX("DEAD.\n");
1222                                 return (spd->ml_running_p = 0);
1223
1224                         case PA_CONTEXT_FAILED:
1225                         default:
1226                                 PULSE_DEBUG_CTX("FAIL.\n");
1227                                 return (spd->ml_running_p = 0);
1228                         }
1229                 }
1230         }
1231
1232         /* clean up */
1233         PULSE_DEBUG_ML("READY: %d.\n", spd->ml_running_p);
1234
1235 unlock_and_fail:
1236         if (threadedp && spd->tml) {
1237                 pa_threaded_mainloop_unlock(spd->tml);
1238         }
1239 fail:
1240         /* indicate success */
1241         return spd->ml_running_p;
1242 }
1243
1244 /* DEFUN("pulse-get-sink-info-list", Fpulse_get_sink_info_list, 1, 1, 0,  */
1245
1246
1247 #undef MYSELF
1248
1249 /* sound-pulse.c ends here */