From 525cf902d9f1bb02d3e6f97183d40cfe6c0a7ea2 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Marc-Andr=C3=A9=20Lureau?= <marc-andre.lureau@nokia.com>
Date: Fri, 3 Apr 2009 02:06:37 +0300
Subject: [PATCH] pulse: add resume when pulseaudio is killed
---
pulse/pcm_pulse.c | 45 ++++++++++++++++++++++++++++++++----
pulse/pulse.c | 66 +++++++++++++++++++++++++++++++++++++++++-----------
pulse/pulse.h | 2 +
3 files changed, 94 insertions(+), 19 deletions(-)
diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c
index db8d1e1..2abfec3 100644
|
a
|
b
|
|
| 269 | 269 | |
| 270 | 270 | pa_threaded_mainloop_lock(pcm->p->mainloop); |
| 271 | 271 | |
| 272 | | assert(pcm->stream); |
| | 272 | if (!pcm->stream) { |
| | 273 | ret = -ESTRPIPE; |
| | 274 | goto finish; |
| | 275 | } |
| 273 | 276 | |
| 274 | 277 | ret = pulse_check_connection(pcm->p); |
| 275 | 278 | if (ret < 0) |
| … |
… |
|
| 309 | 312 | |
| 310 | 313 | pa_threaded_mainloop_lock(pcm->p->mainloop); |
| 311 | 314 | |
| 312 | | assert(pcm->stream); |
| | 315 | if (!pcm->stream) { |
| | 316 | err = -ESTRPIPE; |
| | 317 | goto finish; |
| | 318 | } |
| 313 | 319 | |
| 314 | 320 | for (;;) { |
| 315 | 321 | err = pulse_check_connection(pcm->p); |
| … |
… |
|
| 358 | 364 | |
| 359 | 365 | pa_threaded_mainloop_lock(pcm->p->mainloop); |
| 360 | 366 | |
| 361 | | assert(pcm->stream); |
| | 367 | if (!pcm->stream) { |
| | 368 | ret = -ESTRPIPE; |
| | 369 | goto finish; |
| | 370 | } |
| 362 | 371 | |
| 363 | 372 | ret = pulse_check_connection(pcm->p); |
| 364 | 373 | if (ret < 0) |
| … |
… |
|
| 413 | 422 | |
| 414 | 423 | pa_threaded_mainloop_lock(pcm->p->mainloop); |
| 415 | 424 | |
| 416 | | assert(pcm->stream); |
| | 425 | if (!pcm->stream) { |
| | 426 | ret = -ESTRPIPE; |
| | 427 | goto finish; |
| | 428 | } |
| 417 | 429 | |
| 418 | 430 | ret = pulse_check_connection(pcm->p); |
| 419 | 431 | if (ret < 0) |
| … |
… |
|
| 553 | 565 | pcm->stream = NULL; |
| 554 | 566 | } |
| 555 | 567 | |
| 556 | | err = pulse_check_connection(pcm->p); |
| | 568 | err = pulse_check_connection_reconnect(pcm->p); |
| 557 | 569 | if (err < 0) |
| 558 | 570 | goto finish; |
| 559 | 571 | |
| … |
… |
|
| 638 | 650 | return err; |
| 639 | 651 | } |
| 640 | 652 | |
| | 653 | static int pulse_resume(snd_pcm_ioplug_t * io) |
| | 654 | { |
| | 655 | int ret = 0; |
| | 656 | snd_pcm_pulse_t *pcm = io->private_data; |
| | 657 | |
| | 658 | assert(pcm); |
| | 659 | assert(pcm->p); |
| | 660 | |
| | 661 | pa_threaded_mainloop_lock(pcm->p->mainloop); |
| | 662 | |
| | 663 | if (!pcm->stream) { |
| | 664 | ret = pulse_check_connection_reconnect(pcm->p); |
| | 665 | goto finish; |
| | 666 | } |
| | 667 | |
| | 668 | finish: |
| | 669 | pa_threaded_mainloop_unlock(pcm->p->mainloop); |
| | 670 | |
| | 671 | return ret; |
| | 672 | } |
| | 673 | |
| 641 | 674 | static int pulse_hw_params(snd_pcm_ioplug_t * io, |
| 642 | 675 | snd_pcm_hw_params_t * params) |
| 643 | 676 | { |
| … |
… |
|
| 748 | 781 | .delay = pulse_delay, |
| 749 | 782 | .poll_revents = pulse_pcm_poll_revents, |
| 750 | 783 | .prepare = pulse_prepare, |
| | 784 | .resume = pulse_resume, |
| 751 | 785 | .hw_params = pulse_hw_params, |
| 752 | 786 | .close = pulse_close, |
| 753 | 787 | }; |
| … |
… |
|
| 761 | 795 | .delay = pulse_delay, |
| 762 | 796 | .poll_revents = pulse_pcm_poll_revents, |
| 763 | 797 | .prepare = pulse_prepare, |
| | 798 | .resume = pulse_resume, |
| 764 | 799 | .hw_params = pulse_hw_params, |
| 765 | 800 | .close = pulse_close, |
| 766 | 801 | }; |
diff --git a/pulse/pulse.c b/pulse/pulse.c
index 3940238..ca246ab 100644
|
a
|
b
|
|
| 27 | 27 | |
| 28 | 28 | #include "pulse.h" |
| 29 | 29 | |
| | 30 | static void context_state_cb(pa_context * c, void *userdata); |
| | 31 | |
| | 32 | static void make_new_context(snd_pulse_t *p) |
| | 33 | { |
| | 34 | char proc[PATH_MAX], buf[PATH_MAX + 20]; |
| | 35 | |
| | 36 | assert(p); |
| | 37 | assert(!p->context); |
| | 38 | |
| | 39 | if (pa_get_binary_name(proc, sizeof(proc))) |
| | 40 | snprintf(buf, sizeof(buf), "ALSA plug-in [%s]", |
| | 41 | pa_path_get_filename(proc)); |
| | 42 | else |
| | 43 | snprintf(buf, sizeof(buf), "ALSA plug-in"); |
| | 44 | buf[sizeof(buf)-1] = 0; |
| | 45 | |
| | 46 | p->context = |
| | 47 | pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), buf); |
| | 48 | assert(p->context); |
| | 49 | |
| | 50 | pa_context_set_state_callback(p->context, context_state_cb, p); |
| | 51 | } |
| | 52 | |
| 30 | 53 | int pulse_check_connection(snd_pulse_t * p) |
| 31 | 54 | { |
| 32 | 55 | pa_context_state_t state; |
| … |
… |
|
| 43 | 66 | return 0; |
| 44 | 67 | } |
| 45 | 68 | |
| | 69 | int pulse_check_connection_reconnect(snd_pulse_t * p) |
| | 70 | { |
| | 71 | assert(p); |
| | 72 | assert(p->context); |
| | 73 | assert(p->mainloop); |
| | 74 | |
| | 75 | if (pulse_check_connection(p) < 0) { |
| | 76 | pa_context_disconnect(p->context); |
| | 77 | pa_context_unref(p->context); |
| | 78 | p->context = NULL; |
| | 79 | p->state = PULSE_STATE_INIT; |
| | 80 | pa_threaded_mainloop_unlock(p->mainloop); /* I don't think it is a good idea from here... */ |
| | 81 | make_new_context(p); |
| | 82 | pulse_connect(p, p->server); |
| | 83 | pa_threaded_mainloop_lock(p->mainloop); |
| | 84 | } |
| | 85 | |
| | 86 | return 0; |
| | 87 | } |
| | 88 | |
| 46 | 89 | void pulse_stream_state_cb(pa_stream * s, void *userdata) |
| 47 | 90 | { |
| 48 | 91 | snd_pulse_t *p = userdata; |
| … |
… |
|
| 164 | 207 | { |
| 165 | 208 | snd_pulse_t *p; |
| 166 | 209 | int fd[2] = { -1, -1 }; |
| 167 | | char proc[PATH_MAX], buf[PATH_MAX + 20]; |
| 168 | 210 | |
| 169 | 211 | p = calloc(1, sizeof(snd_pulse_t)); |
| 170 | 212 | |
| … |
… |
|
| 188 | 230 | if (!p->mainloop) |
| 189 | 231 | goto fail; |
| 190 | 232 | |
| 191 | | if (pa_get_binary_name(proc, sizeof(proc))) |
| 192 | | snprintf(buf, sizeof(buf), "ALSA plug-in [%s]", |
| 193 | | pa_path_get_filename(proc)); |
| 194 | | else |
| 195 | | snprintf(buf, sizeof(buf), "ALSA plug-in"); |
| 196 | | buf[sizeof(buf)-1] = 0; |
| 197 | | |
| 198 | | p->context = |
| 199 | | pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), buf); |
| 200 | | assert(p->context); |
| 201 | | |
| 202 | | pa_context_set_state_callback(p->context, context_state_cb, p); |
| | 233 | make_new_context(p); |
| 203 | 234 | |
| 204 | 235 | if (pa_threaded_mainloop_start(p->mainloop) < 0) |
| 205 | 236 | goto fail; |
| … |
… |
|
| 238 | 269 | close(p->thread_fd); |
| 239 | 270 | close(p->main_fd); |
| 240 | 271 | |
| | 272 | if (p->server) |
| | 273 | free(p->server); |
| | 274 | |
| 241 | 275 | free(p); |
| 242 | 276 | } |
| 243 | 277 | |
| … |
… |
|
| 250 | 284 | assert(p->mainloop); |
| 251 | 285 | assert(p->state == PULSE_STATE_INIT); |
| 252 | 286 | |
| | 287 | if (!p->server) |
| | 288 | p->server = server ? strdup(server) : NULL; |
| | 289 | |
| 253 | 290 | pa_threaded_mainloop_lock(p->mainloop); |
| 254 | 291 | |
| 255 | | err = pa_context_connect(p->context, server, 0, NULL); |
| | 292 | usleep(300000); /* FIXME: there is a race when re-connecting immediately and autospawn */ |
| | 293 | err = pa_context_connect(p->context, server, PA_CONTEXT_NOFAIL, NULL); |
| 256 | 294 | if (err < 0) |
| 257 | 295 | goto error; |
| 258 | 296 | |
diff --git a/pulse/pulse.h b/pulse/pulse.h
index 7bf1a5b..a91fda2 100644
|
a
|
b
|
|
| 29 | 29 | typedef struct snd_pulse { |
| 30 | 30 | pa_threaded_mainloop *mainloop; |
| 31 | 31 | pa_context *context; |
| | 32 | char *server; |
| 32 | 33 | |
| 33 | 34 | int thread_fd, main_fd; |
| 34 | 35 | |
| … |
… |
|
| 40 | 41 | } snd_pulse_t; |
| 41 | 42 | |
| 42 | 43 | int pulse_check_connection(snd_pulse_t * p); |
| | 44 | int pulse_check_connection_reconnect(snd_pulse_t * p); |
| 43 | 45 | |
| 44 | 46 | void pulse_stream_state_cb(pa_stream * s, void *userdata); |
| 45 | 47 | void pulse_stream_success_cb(pa_stream * s, int success, void *userdata); |