Merge remote-tracking branch 'origin/master' into for-steve
[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 sink;
84         Lisp_Object source;
85         Lisp_Object server;
86         int ml_running_p;
87         int ml_threaded_p;
88         pa_threaded_mainloop *tml;
89         pa_mainloop *ml;
90         pa_mainloop_api *mlapi;
91         pa_context *ctx;
92         const pa_sink_info *sink_info;
93         struct sxe_semaphore_s ctxsem;
94 };
95
96 struct sound_pulse_aj_data_s {
97         int volume;
98         pa_cvolume chanvol;
99         struct pa_sample_spec sampspec;
100         struct pa_channel_map chanmap;
101         pa_buffer_attr buffattr;
102         pa_stream *stream;
103         pa_context *ctx;
104
105         /* event trickery */
106         pa_time_event *time_ev;
107
108         /* coercion stuff */
109         media_sample_format_t *msf;
110         int coe_ch_cnt;
111         audio_coerce_chain_t coe_chain[4];
112         sxe_mse_rerate_args *rrargs;
113 };
114
115 \f
116 DECLARE_AUDIO_DEVICE_SIMPLE_METHS(sound_pulse);
117 DEFINE_AUDIO_DEVICE_SIMPLE(sound_pulse);
118
119 \f
120 static Lisp_Object
121 sound_pulse_mark(ad_device_data *devdata)
122 {
123         sound_pulse_data_t spd = (sound_pulse_data_t)devdata;
124         if (spd == NULL)
125                 return Qnil;
126
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);
132         return Qnil;
133 }
134
135 static void
136 sound_pulse_print(Lisp_Object device, Lisp_Object pcfun, int ef)
137 {
138         sound_pulse_data_t spd = NULL;
139         pa_context_state_t st;
140
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;
147                 return;
148         }
149
150         /* info about the connected output plugin */
151         write_c_string(" :server ", pcfun);
152         if (NILP(spd->server))
153                 write_c_string("#default", pcfun);
154         else
155                 print_internal(spd->server, pcfun, ef);
156
157         write_c_string(" :sink ", pcfun);
158         if (NILP(spd->sink)) {
159                 write_c_string("#default", pcfun);
160         } else {
161                 print_internal(spd->sink, pcfun, ef);
162         }
163
164 #if 0
165         if (spd->sink_info) {
166                 write_c_string(" (", pcfun);
167                 write_c_string(spd->sink_info->description, pcfun);
168                 write_c_string(")", pcfun);
169         } else {
170                 write_c_string(" (sink does not exist)", pcfun);
171         }
172 #endif
173
174         write_c_string(" :source ", pcfun);
175         if (NILP(spd->source))
176                 write_c_string("#default", pcfun);
177         else
178                 print_internal(spd->source, pcfun, ef);
179
180         write_c_string(" :server-state ", pcfun);
181
182         if (!spd->ctx) {
183                 write_c_string("#b0rked", pcfun);
184                 return;
185         }
186
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);
193                 break;
194
195         case PA_CONTEXT_READY:
196                 write_c_string("#connected", pcfun);
197                 break;
198
199         case PA_CONTEXT_TERMINATED:
200                 write_c_string("#terminated", pcfun);
201                 break;
202
203         case PA_CONTEXT_FAILED:
204         default:
205                 write_c_string("#failed", pcfun);
206                 break;
207         }
208
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);
213         } else {
214                 write_fmt_str(pcfun, "#non-threaded :mainloop 0x%lx",
215                               (long unsigned int)spd->ml);
216         }
217         return;
218 }
219
220 \f
221 static ad_device_data *
222 sound_pulse_create(Lisp_Object pulse_options)
223 {
224         /* result */
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;
235
236         /* parse options */
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);
240                 return NULL;
241         }
242
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);
246                 return NULL;
247         }
248
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);
252                 return NULL;
253         }
254
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);
258                 return NULL;
259         }
260
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);
264
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;
272
273         spd->ml_threaded_p = !NILP(opt_threaded);
274
275         if (NILP(opt_immediate))
276                 return (ad_device_data*)spd;
277
278         sound_pulse_init_mainloop(spd);
279
280         if (spd->ml_running_p == 0) /* yeah, finish immediately */
281                 sound_pulse_finish(spd);
282
283         if (NILP(opt_force) && spd->ml_running_p == 0) {
284                 xfree(spd);
285                 spd = NULL;
286                 error(GETTEXT("Error: audio-pulse: "
287                               "Initialising connection to PulseAudio failed."));
288                 return NULL;
289         }
290
291         return (ad_device_data*)spd;
292 }
293
294 static void
295 sound_pulse_finish(ad_device_data *data)
296 {
297         sound_pulse_data_t spd = data;
298         if (spd == NULL)
299                 return;
300
301         if (spd != NULL && 0) {
302                 spd->stream = Qnil;
303                 spd->server = Qnil;
304                 spd->client = Qnil;
305                 spd->sink = Qnil;
306                 spd->source = Qnil;
307         }
308
309         spd->ml_running_p = 0;
310
311         /* setting this to 0 is not enough? :\ */
312         if (spd->ctx) {
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));
319         }
320         spd->ctx = NULL;
321
322         PULSE_DEBUG_ML("Is there a mainloop awake?\n");
323         if (spd->ml_threaded_p) {
324                 if (spd->tml) {
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);
329                 }
330                 spd->tml = NULL;
331         } else {
332                 if (spd->ml) {
333                         ;
334                         PULSE_DEBUG_ML("FREE. bye bye (non-threaded)\n");
335                         pa_mainloop_free(spd->ml);
336                 }
337                 spd->ml = NULL;
338         }
339
340         PULSE_DEBUG_CTX("finish.\n");
341
342         spd->tml = NULL;
343         spd->ml = NULL;
344         return;
345 }
346
347 \f
348 /** Wait until the specified operation completes */
349 #define wait_for_operation(_m, _o)                                      \
350         do {                                                            \
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);                                \
356         } while(0)
357
358 /** Wait until no further actions are pending on the connection context */
359 #define wait_for_completion(_c, _m)                                     \
360         do {                                                            \
361                 while (pa_context_is_pending(_c))                       \
362                         pa_mainloop_iterate((_m), 1, NULL);             \
363         } while(0)
364
365
366 static void
367 my_pa_free_cb(void *data)
368 {
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);
374         return;
375 }
376
377 \f
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)
387 {
388         pa_operation *o;
389
390         pa_cvolume_set(cvolp, cvolp->channels,
391                        (volume*PA_VOLUME_NORM)/MEDIA_SAMPLE_VOLUME_NORM);
392
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");
396         } else {
397                 pa_operation_unref(o);
398         }
399         return volume;
400 }
401
402 /* handling of events from the audio job's private queue */
403 #ifdef EF_USE_ASYNEQ
404 static inline void
405 sound_pulse_stop(audio_job_t aj)
406         __attribute__((always_inline));
407 static inline void
408 sound_pulse_stop(audio_job_t aj)
409 {
410         sound_pulse_aj_data_t spsd;
411         pa_stream *stream;
412
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);
421         return;
422 }
423
424 static inline void
425 sound_pulse_pause(audio_job_t aj)
426         __attribute__((always_inline));
427 static inline void
428 sound_pulse_pause(audio_job_t aj)
429 {
430         sound_pulse_aj_data_t spsd;
431         sound_pulse_data_t spd;
432         pa_stream *stream;
433         struct timeval tv;
434
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;
442
443         if (audio_job_queue(aj)) {
444                 spsd->time_ev = spd->mlapi->
445                         time_new(spd->mlapi, &tv, time_ev_cb, aj);
446         }
447
448         SXE_MUTEX_UNLOCK(&aj->mtx);
449         return;
450 }
451
452 static inline void
453 sound_pulse_resume(audio_job_t aj)
454         __attribute__((always_inline));
455 static inline void
456 sound_pulse_resume(audio_job_t aj)
457 {
458         sound_pulse_aj_data_t spsd;
459         sound_pulse_data_t spd;
460         pa_stream *stream;
461
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);
467
468         if (spsd->time_ev) {
469                 spd->mlapi->time_free(spsd->time_ev);
470                 spsd->time_ev = NULL;
471         }
472
473         pa_operation_unref(pa_stream_cork(stream, 0, NULL, NULL));
474         aj->play_state = MTPSTATE_RUN;
475         SXE_MUTEX_UNLOCK(&aj->mtx);
476         return;
477 }
478
479 static inline void
480 sound_pulse_change_volume(audio_job_t aj, audio_job_event_args_t args)
481 {
482         sound_pulse_aj_data_t spsd;
483         pa_volume_t new_vol = args->volume_args;
484
485         PULSE_DEBUG_AJ("->%d\n", (int)new_vol);
486
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);
493 }
494
495 static inline void
496 sound_pulse_change_rate(audio_job_t aj, audio_job_event_args_t args)
497 {
498         SXE_MUTEX_LOCK(&aj->mtx);
499         aj->ratetrafo = args->rate_args;
500         SXE_MUTEX_UNLOCK(&aj->mtx);
501 }
502
503 static inline void
504 sound_pulse_change_state(audio_job_t aj, audio_job_event_args_t args)
505 {
506         switch (args->state_args) {
507         case aj_pause:
508                 PULSE_DEBUG_AJ("->pause state\n");
509                 sound_pulse_pause(aj);
510                 break;
511         case aj_resume:
512                 PULSE_DEBUG_AJ("->resume state\n");
513                 sound_pulse_resume(aj);
514                 break;
515         case aj_start:
516                 PULSE_DEBUG_AJ("->start state\n");
517                 break;
518         case aj_stop:
519                 PULSE_DEBUG_AJ("->stop state\n");
520                 sound_pulse_stop(aj);
521                 break;
522
523         case no_audio_job_change_states:
524         default:
525                 PULSE_DEBUG_AJ("->unknown state\n");
526                 break;
527         }
528 }
529
530 static inline void
531 sound_pulse_handle_aj_events(audio_job_t aj)
532         __attribute__((always_inline));
533 static inline void
534 sound_pulse_handle_aj_events(audio_job_t aj)
535 {
536         sound_pulse_aj_data_t spsd;
537         pa_stream *stream;
538         audio_job_event_t ev = NULL;
539         event_queue_t eq;
540
541 #if defined EF_USE_ASYNEQ
542         if (audio_job_queue(aj)) {
543                 assert((long unsigned int)audio_job_queue(aj) != 0xB16B00B5);
544         }
545 #endif
546
547         PULSE_DEBUG_AJ("handle aj events called on 0x%lx\n",
548                        (long unsigned int)aj);
549
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) {
556                 return;
557         }
558         if (stream == NULL || pa_stream_get_state(stream) != PA_STREAM_READY) {
559                 return;
560         }
561
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));
567                 break;
568         case aj_change_volume:
569                 PULSE_DEBUG_AJ("change volume event\n");
570                 sound_pulse_change_volume(aj, &audio_job_event_args(ev));
571                 break;
572         case aj_change_rate:
573                 PULSE_DEBUG_AJ("change rate event\n");
574                 sound_pulse_change_rate(aj, &audio_job_event_args(ev));
575                 break;
576
577         case no_audio_job_event_kinds:
578         default:
579                 PULSE_CRITICAL("unknown event\n");
580                 break;
581         }
582         free_audio_job_event(ev);
583 }
584
585 static void
586 time_ev_cb(pa_mainloop_api *m, pa_time_event *e,
587            const struct timeval *tv, void *userdata)
588 {
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);;
593
594         sound_pulse_handle_aj_events(userdata);
595
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);
601         }
602 }
603 #endif  /* EF_USE_ASYNEQ */
604
605 /* This is called whenever stream draining has completed */
606 static void
607 stream_drain_complete(pa_stream *stream, int success, void *userdata)
608 {
609         audio_job_t aj = userdata;
610
611         PULSE_DEBUG_S("drain_complete cb called (0x%lx)\n",
612                       (long unsigned int)aj);
613
614         if (UNLIKELY(!success)) {
615                 PULSE_CRITICAL("Failed to drain stream 0x%lx\n",
616                                (long unsigned int)aj);
617         }
618
619         pa_stream_disconnect(stream);
620         PULSE_DEBUG_S("leaving stream_drain cb (0x%lx)\n",
621                       (long unsigned int)aj);
622         return;
623 }
624
625 /* This is called whenever new data may be written to the stream */
626 static void
627 stream_write_callback(pa_stream *stream, size_t length, void *userdata)
628 {
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;
634         long int i;
635         /* pulse and subthread stuff */
636         sound_pulse_aj_data_t spsd;
637         pa_context *ctx = NULL;
638         sxe_media_sample_t *tmpbuf;
639
640         assert(stream && length);
641
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);
648
649                 PULSE_DEBUG_S("FLUSH.\n");
650                 pa_operation_unref(
651                         pa_stream_flush(
652                                 stream, stream_drain_complete, aj));
653                 pa_stream_disconnect(stream);
654                 return;
655         }
656
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);
662         }
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);
667         ctx = spsd->ctx;
668
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);
674         }
675 #endif  /* !EF_USE_ASYNEQ */
676
677         mtp = aj->play_state;
678         switch (mtp) {
679         case MTPSTATE_RUN:
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 (==
688                    demuxed'n'decoded).
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
694                    enlightenment.
695                 */
696                 if (UNLIKELY(tmplen > 4 * aj->buffer_alloc_size / 5)) {
697                         tmplen = 4 * aj->buffer_alloc_size / 5;
698                 }
699                 tmplen /= aj->framesize;
700                 tmpbuf = (sxe_media_sample_t*)aj->buffer;
701                 PULSE_DEBUG_S("asking for %u frames, fetching %u instead "
702                               "(0x%lx)\n",
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 */
708                 if (len == 0) {
709                         tmplen = 0;
710                         break;
711                 }
712
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);
723                 }
724
725                 MEDIA_SAMPLE_FORMAT_DOWNSAMPLE(spsd->msf)(
726                         aj->buffer, aj->buffer, tmplen);
727
728                 tmplen = tmplen * sizeof(int16_t);
729
730                 break;
731         case MTPSTATE_PAUSE:
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);
736                 break;
737 #endif
738
739         case MTPSTATE_UNKNOWN:
740         case NUMBER_OF_MEDIA_THREAD_PLAY_STATES:
741         case MTPSTATE_STOP:
742         default:
743                 PULSE_DEBUG_S("MTPSTATE == STOP, "
744                               "hence leaving stream_write cb\n");
745                 SXE_MUTEX_UNLOCK(&aj->mtx);
746                 return;
747         }
748
749         if (LIKELY(len > 0)) {
750                 PULSE_DEBUG_S("writing %u frames == %u samples == %u bytes "
751                               "(0x%lx)\n",
752                               tmplen/aj->framesize,
753                               tmplen*aj->channels / aj->framesize,
754                               tmplen,
755                               (long unsigned int)aj);
756                 pa_stream_write(stream, aj->buffer, tmplen,
757                                 my_pa_free_cb, 0, PA_SEEK_RELATIVE);
758         }
759
760         if (tmplen < length) {
761                 PULSE_DEBUG_S("DRAIN. (0x%lx)\n", (long unsigned int)aj);
762                 aj->play_state = MTPSTATE_STOP;
763                 pa_operation_unref(
764                         pa_stream_drain(
765                                 stream, stream_drain_complete, aj));
766         }
767
768         SXE_MUTEX_UNLOCK(&aj->mtx);
769         PULSE_DEBUG_S("leaving stream_write cb\n");
770         return;
771 }
772
773 /* This routine is called whenever the stream state changes */
774 static void
775 stream_state_callback(pa_stream *s, void *userdata)
776 {
777         sxe_semaphore_t sem = userdata;
778         pa_context_state_t st;
779
780         assert(s);
781
782         st = pa_stream_get_state(s);
783         switch ((unsigned int)st) {
784         case PA_STREAM_CREATING:
785                 PULSE_DEBUG_S("CREATING.\n");
786                 break;
787         case PA_STREAM_TERMINATED:
788                 PULSE_DEBUG_S("TERMINATED.\n");
789                 PULSE_DEBUG_PT("trigger local semaphore\n");
790                 SXE_SEMAPH_TRIGGER(sem);
791                 break;
792
793         case PA_STREAM_READY:
794                 PULSE_DEBUG_S("READY.\n");
795                 break;
796
797         case PA_STREAM_FAILED:
798         default:
799                 PULSE_DEBUG_S("FAILED.\n");
800                 PULSE_DEBUG_PT("trigger local semaphore\n");
801                 SXE_SEMAPH_TRIGGER(sem);
802                 break;
803         }
804         return;
805 }
806
807 \f
808 static int
809 sound_pulse_play(audio_job_t aj)
810 {
811         /* stream stuff */
812         mtype_audio_properties *mtap;
813         Lisp_Media_Stream *ms;
814         media_substream *mss;
815         /* device stuff */
816         Lisp_Object device;
817         sound_pulse_data_t spd = NULL;
818         Lisp_Audio_Device *lad = NULL;
819         /* pulse stuff */
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;
825         int r = 0;
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;
831         /* cache stuff */
832         int alloced_myself = 0;
833
834         /* unpack the media thread */
835         SOUND_UNPACK_MT(aj, device, ms, mss, lad, spd, mtap);
836
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);
842         }
843
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;
848                 goto finish;
849         }
850
851         /* prepare pulse sample specs */
852         ssp->rate = mtap->samplerate;
853         ssp->channels = mtap->channels;
854
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;
858
859         if (spd->ml_running_p && spd->ml_threaded_p) {
860                 PULSE_DEBUG_ML("lock.\n");
861                 pa_threaded_mainloop_lock(spd->tml);
862         }
863
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));
868
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");
875                 goto finish;
876         }
877         PULSE_DEBUG_S("Created stream 0x%lx\n", (long unsigned int)stream);
878
879         /* obviously our device is alive
880          * This does NOT mean that you can hear the sounds */
881         XAUDIO_DEVICE_STATE(device) = ASTATE_ALIVE;
882
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);
891                 alloced_myself = 1;
892                 aj->buffer = xmalloc_atomic(SOUND_MAX_AUDIO_FRAME_SIZE);
893                 aj->buffer_alloc_size = SOUND_MAX_AUDIO_FRAME_SIZE;
894         }
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);
899
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;
906
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;
914
915         /* initialise our thread semaphore */
916         PULSE_DEBUG_PT("init pulse local semaphore\n");
917         SXE_SEMAPH_INIT(sem);
918
919         /* coercion stuff */
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;
929
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);
933
934         /* we better check if ml is still running */
935         if (!spd->ml_running_p)
936                 goto finish;
937         pa_stream_connect_playback(
938                 stream, sink_name, bap, 0, &spsd->chanvol, NULL);
939
940         if (spd->ml_running_p && spd->ml_threaded_p) {
941                 WITH_SXE_SEMAPH_SYNCH(
942                         sem,
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)) {
955                                 break;
956                         }
957                 }
958         }
959
960         /* ... and outta here */
961         PULSE_DEBUG_S("finish.\n");
962
963         /* close and shutdown */
964 finish:
965         SXE_MUTEX_LOCK(&aj->mtx);
966         if (alloced_myself && aj->buffer) {
967                 PULSE_DEBUG_S("freeing stream buffer.\n");
968                 xfree(aj->buffer);
969         }
970         aj->buffer = NULL;
971         aj->buffer_alloc_size = 0;
972
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);
976
977         if (spd && spd->ml_running_p && spd->ml_threaded_p) {
978                 PULSE_DEBUG_ML("lock.\n");
979                 pa_threaded_mainloop_lock(spd->tml);
980         }
981
982 #ifdef EF_USE_ASYNEQ
983         /* kick those timers */
984         if (spsd->time_ev != NULL) {
985                 spd->mlapi->time_free(spsd->time_ev);
986         }
987         spsd->time_ev = NULL;
988 #endif
989
990 #if 1
991         if (stream) {
992                 PULSE_DEBUG_S("unref.\n");
993                 pa_stream_unref(stream);
994                 stream = NULL;
995         }
996 #endif
997
998         if (spd && spd->ml_running_p && spd->ml_threaded_p) {
999                 PULSE_DEBUG_ML("unlock.\n");
1000                 pa_threaded_mainloop_unlock(spd->tml);
1001         }
1002
1003         SXE_MUTEX_LOCK(&aj->mtx);
1004         audio_job_device_data(aj) = NULL;
1005         SXE_MUTEX_UNLOCK(&aj->mtx);
1006
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);
1013                 return 0;
1014         }
1015
1016         /* deinitialise our thread semaphore */
1017         PULSE_DEBUG_PT("deinit pulse local semaphore\n");
1018         SXE_SEMAPH_FINI(sem);
1019
1020         return 1;
1021 }
1022
1023 \f
1024 #define CHECK_DEAD_GOTO(label)                                          \
1025         do {                                                            \
1026                 if (!spd->ctx ||                                        \
1027                     pa_context_get_state(spd->ctx) != PA_CONTEXT_READY) { \
1028                         PULSE_CRITICAL("Uh oh, operation failed.\n");   \
1029                         goto label;                                     \
1030                 }                                                       \
1031         } while(0)
1032
1033 static void
1034 sink_info_callback(pa_context *c, const pa_sink_info *i, int eol, void *data)
1035 {
1036         sound_pulse_data_t spd = data;
1037
1038         if (eol < 0) {
1039                 PULSE_DEBUG_CTX("No sink info\n");
1040                 spd->sink_info = NULL;
1041         } else if (i == NULL) {
1042                 ;
1043         } else {
1044                 PULSE_DEBUG_CTX("Name: %s, Index: %d\nDescr: %s\n",
1045                                 i->name, i->index, i->description);
1046                 spd->sink_info = NULL;
1047         }
1048
1049         return;
1050 }
1051
1052 /* This is called whenever the context status changes */
1053 static void
1054 context_state_callback(pa_context *c, void *userdata)
1055 {
1056         sound_pulse_data_t spd = userdata;
1057         pa_operation *o;
1058         char *sink_name = NULL;
1059
1060         assert(c);
1061
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;
1069                 break;
1070
1071         case PA_CONTEXT_READY:
1072                 PULSE_DEBUG_CTX("ESTA.\n");
1073                 sink_name = (NILP(spd->sink) ? NULL :
1074                              (char*)XSTRING_DATA(spd->sink));
1075
1076                 /* query sinks */
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");
1081                 } else {
1082                         ;
1083                 }
1084
1085                 pa_operation_unref(o);
1086                 spd->ml_running_p = 1;
1087                 pa_threaded_mainloop_signal(spd->tml, 0);
1088                 break;
1089
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);
1094                 break;
1095
1096         case PA_CONTEXT_FAILED:
1097         default:
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);
1102                 break;
1103         }
1104         return;
1105 }
1106
1107 /* mainloop in an extra thread API */
1108 static int
1109 sound_pulse_init_mainloop(ad_device_data *devdata)
1110 {
1111         /* device stuff */
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;
1121
1122         /* cannot use Pulse on incomplete or corrupt audio devices */
1123         if (spd == NULL)
1124                 return 0;
1125
1126         SXE_SEMAPH_INIT(&(spd->ctxsem));
1127
1128         /* Set up a new main loop */
1129         if (threadedp)
1130                 spd->tml = pa_threaded_mainloop_new();
1131         else
1132                 spd->ml = pa_mainloop_new();
1133
1134         if (!spd->tml && !spd->ml) {
1135                 message(GETTEXT("audio-pulse: "
1136                                 "Failed to connect to server."));
1137                 return 0;
1138         }
1139
1140         if (threadedp)
1141                 spd->mlapi = pa_threaded_mainloop_get_api(spd->tml);
1142         else
1143                 spd->mlapi = pa_mainloop_get_api(spd->ml);
1144
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."));
1149                 spd->ml = NULL;
1150                 spd->tml = NULL;
1151                 return 0;
1152         }
1153
1154         /* initialise callback semaphore */
1155         if (threadedp) {
1156                 spd->ml_running_p = 0;
1157                 pa_context_set_state_callback(
1158                         spd->ctx, context_state_callback, spd);
1159
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");
1163                         goto fail;
1164                 }
1165
1166                 PULSE_DEBUG_ML("locking mainloop\n");
1167                 pa_threaded_mainloop_lock(spd->tml);
1168
1169                 if (pa_threaded_mainloop_start(spd->tml) < 0) {
1170                         PULSE_DEBUG_ML("failed to start mainloop\n");
1171                         goto unlock_and_fail;
1172                 }
1173
1174                 /* Wait until the context is ready */
1175                 pa_threaded_mainloop_wait(spd->tml);
1176
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;
1180                 }
1181         } else {
1182                 /* Connect the context */
1183                 pa_context_connect(spd->ctx, server, 0, NULL);
1184                 /* iterate manually */
1185                 while (1) {
1186                         pa_context_state_t st;
1187
1188                         pa_mainloop_iterate(spd->ml, 1, NULL);
1189                         st = pa_context_get_state(spd->ctx);
1190
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;
1196                                 break;
1197
1198                         case PA_CONTEXT_READY:
1199                                 PULSE_DEBUG_CTX("ESTA.\n");
1200                                 PULSE_DEBUG_CTX("READY.\n");
1201                                 return (spd->ml_running_p = 1);
1202
1203                         case PA_CONTEXT_TERMINATED:
1204                                 PULSE_DEBUG_CTX("DEAD.\n");
1205                                 return (spd->ml_running_p = 0);
1206
1207                         case PA_CONTEXT_FAILED:
1208                         default:
1209                                 PULSE_DEBUG_CTX("FAIL.\n");
1210                                 return (spd->ml_running_p = 0);
1211                         }
1212                 }
1213         }
1214
1215         /* clean up */
1216         PULSE_DEBUG_ML("READY: %d.\n", spd->ml_running_p);
1217
1218 unlock_and_fail:
1219         if (threadedp && spd->tml) {
1220                 pa_threaded_mainloop_unlock(spd->tml);
1221         }
1222 fail:
1223         /* indicate success */
1224         return spd->ml_running_p;
1225 }
1226
1227 /* DEFUN("pulse-get-sink-info-list", Fpulse_get_sink_info_list, 1, 1, 0,  */
1228
1229
1230 #undef MYSELF
1231
1232 /* sound-pulse.c ends here */