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