Mercurial > audlegacy-plugins
comparison src/pulse_audio/pulse_audio.c @ 1318:a9a97179a1f9
I will be ready for Audacious 2...
author | Stany HENRY <StrassBoy@gmail.com> |
---|---|
date | Sat, 21 Jul 2007 04:57:53 +0200 |
parents | 3094d9c8a935 |
children | 761e17b23e0c |
comparison
equal
deleted
inserted
replaced
1317:78861d8b86f2 | 1318:a9a97179a1f9 |
---|---|
1 /*** | 1 /*** |
2 This file is part of xmms-pulse. | 2 This file is part of xmms-pulse. |
3 | 3 |
4 xmms-pulse is free software; you can redistribute it and/or modify | 4 xmms-pulse is free software; you can redistribute it and/or modify |
5 it under the terms of the GNU General Public License as published by | 5 it under the terms of the GNU General Public License as published by |
6 the Free Software Foundation; either version 2 of the License, or | 6 the Free Software Foundation; either version 2 of the License, or |
7 (at your option) any later version. | 7 (at your option) any later version. |
8 | 8 |
9 xmms-pulse is distributed in the hope that it will be useful, but | 9 xmms-pulse is distributed in the hope that it will be useful, but |
10 WITHOUT ANY WARRANTY; without even the implied warranty of | 10 WITHOUT ANY WARRANTY; without even the implied warranty of |
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 General Public License for more details. | 12 General Public License for more details. |
13 | 13 |
14 You should have received a copy of the GNU General Public License | 14 You should have received a copy of the GNU General Public License |
15 along with xmms-pulse; if not, write to the Free Software | 15 along with xmms-pulse; if not, write to the Free Software |
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 | 16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 |
17 USA. | 17 USA. |
18 ***/ | 18 ***/ |
30 | 30 |
31 #include <gtk/gtk.h> | 31 #include <gtk/gtk.h> |
32 #include <audacious/plugin.h> | 32 #include <audacious/plugin.h> |
33 #include <audacious/playlist.h> | 33 #include <audacious/playlist.h> |
34 #include <audacious/util.h> | 34 #include <audacious/util.h> |
35 #include <audacious/i18n.h> | |
35 | 36 |
36 #include <pulse/pulseaudio.h> | 37 #include <pulse/pulseaudio.h> |
37 | 38 |
38 static pa_context *context = NULL; | 39 static pa_context *context = NULL; |
39 static pa_stream *stream = NULL; | 40 static pa_stream *stream = NULL; |
79 if (!(str = playlist_get_songtitle(playlist, pos))) | 80 if (!(str = playlist_get_songtitle(playlist, pos))) |
80 return "Playback Stream"; | 81 return "Playback Stream"; |
81 | 82 |
82 snprintf(t, sizeof(t), "%s", u = pa_locale_to_utf8(str)); | 83 snprintf(t, sizeof(t), "%s", u = pa_locale_to_utf8(str)); |
83 pa_xfree(u); | 84 pa_xfree(u); |
84 | 85 |
85 return t; | 86 return t; |
86 } | 87 } |
87 | 88 |
88 static void info_cb(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) { | 89 static void info_cb(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) { |
89 assert(c); | 90 assert(c); |
95 volume_valid = 1; | 96 volume_valid = 1; |
96 } | 97 } |
97 | 98 |
98 static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) { | 99 static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) { |
99 pa_operation *o; | 100 pa_operation *o; |
100 | 101 |
101 assert(c); | 102 assert(c); |
102 | 103 |
103 if (!stream || | 104 if (!stream || |
104 index != pa_stream_get_index(stream) || | 105 index != pa_stream_get_index(stream) || |
105 (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) && | 106 (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) && |
108 | 109 |
109 if (!(o = pa_context_get_sink_input_info(c, index, info_cb, NULL))) { | 110 if (!(o = pa_context_get_sink_input_info(c, index, info_cb, NULL))) { |
110 g_warning("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(c))); | 111 g_warning("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(c))); |
111 return; | 112 return; |
112 } | 113 } |
113 | 114 |
114 pa_operation_unref(o); | 115 pa_operation_unref(o); |
115 } | 116 } |
116 | 117 |
117 static void context_state_cb(pa_context *c, void *userdata) { | 118 static void context_state_cb(pa_context *c, void *userdata) { |
118 assert(c); | 119 assert(c); |
152 static void stream_success_cb(pa_stream *s, int success, void *userdata) { | 153 static void stream_success_cb(pa_stream *s, int success, void *userdata) { |
153 assert(s); | 154 assert(s); |
154 | 155 |
155 if (userdata) | 156 if (userdata) |
156 *(int*) userdata = success; | 157 *(int*) userdata = success; |
157 | 158 |
158 pa_threaded_mainloop_signal(mainloop, 0); | 159 pa_threaded_mainloop_signal(mainloop, 0); |
159 } | 160 } |
160 | 161 |
161 static void context_success_cb(pa_context *c, int success, void *userdata) { | 162 static void context_success_cb(pa_context *c, int success, void *userdata) { |
162 assert(c); | 163 assert(c); |
163 | 164 |
164 if (userdata) | 165 if (userdata) |
165 *(int*) userdata = success; | 166 *(int*) userdata = success; |
166 | 167 |
167 pa_threaded_mainloop_signal(mainloop, 0); | 168 pa_threaded_mainloop_signal(mainloop, 0); |
168 } | 169 } |
169 | 170 |
170 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { | 171 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { |
171 assert(s); | 172 assert(s); |
186 *l = *r = 100; | 187 *l = *r = 100; |
187 | 188 |
188 if (connected) { | 189 if (connected) { |
189 pa_threaded_mainloop_lock(mainloop); | 190 pa_threaded_mainloop_lock(mainloop); |
190 CHECK_DEAD_GOTO(fail, 1); | 191 CHECK_DEAD_GOTO(fail, 1); |
191 | 192 |
192 v = volume; | 193 v = volume; |
193 b = volume_valid; | 194 b = volume_valid; |
194 | 195 |
195 fail: | 196 fail: |
196 pa_threaded_mainloop_unlock(mainloop); | 197 pa_threaded_mainloop_unlock(mainloop); |
197 } else { | 198 } else { |
198 v = volume; | 199 v = volume; |
199 b = volume_valid; | 200 b = volume_valid; |
200 } | 201 } |
201 | 202 |
202 if (b) { | 203 if (b) { |
203 if (v.channels == 2) { | 204 if (v.channels == 2) { |
204 *l = (int) ((v.values[0]*100)/PA_VOLUME_NORM); | 205 *l = (int) ((v.values[0]*100)/PA_VOLUME_NORM); |
205 *r = (int) ((v.values[1]*100)/PA_VOLUME_NORM); | 206 *r = (int) ((v.values[1]*100)/PA_VOLUME_NORM); |
206 } else | 207 } else |
208 } | 209 } |
209 } | 210 } |
210 | 211 |
211 static void volume_time_cb(pa_mainloop_api *api, pa_time_event *e, const struct timeval *tv, void *userdata) { | 212 static void volume_time_cb(pa_mainloop_api *api, pa_time_event *e, const struct timeval *tv, void *userdata) { |
212 pa_operation *o; | 213 pa_operation *o; |
213 | 214 |
214 if (!(o = pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), &volume, NULL, NULL))) | 215 if (!(o = pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), &volume, NULL, NULL))) |
215 g_warning("pa_context_set_sink_input_volume() failed: %s", pa_strerror(pa_context_errno(context))); | 216 g_warning("pa_context_set_sink_input_volume() failed: %s", pa_strerror(pa_context_errno(context))); |
216 else | 217 else |
217 pa_operation_unref(o); | 218 pa_operation_unref(o); |
218 | 219 |
219 /* We don't wait for completion of this command */ | 220 /* We don't wait for completion of this command */ |
262 | 263 |
263 if (!(o = pa_stream_cork(stream, b, stream_success_cb, &success))) { | 264 if (!(o = pa_stream_cork(stream, b, stream_success_cb, &success))) { |
264 g_warning("pa_stream_cork() failed: %s", pa_strerror(pa_context_errno(context))); | 265 g_warning("pa_stream_cork() failed: %s", pa_strerror(pa_context_errno(context))); |
265 goto fail; | 266 goto fail; |
266 } | 267 } |
267 | 268 |
268 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { | 269 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { |
269 CHECK_DEAD_GOTO(fail, 1); | 270 CHECK_DEAD_GOTO(fail, 1); |
270 pa_threaded_mainloop_wait(mainloop); | 271 pa_threaded_mainloop_wait(mainloop); |
271 } | 272 } |
272 | 273 |
273 if (!success) | 274 if (!success) |
274 g_warning("pa_stream_cork() failed: %s", pa_strerror(pa_context_errno(context))); | 275 g_warning("pa_stream_cork() failed: %s", pa_strerror(pa_context_errno(context))); |
275 | 276 |
276 fail: | 277 fail: |
277 | 278 |
278 if (o) | 279 if (o) |
279 pa_operation_unref(o); | 280 pa_operation_unref(o); |
280 | 281 |
281 pa_threaded_mainloop_unlock(mainloop); | 282 pa_threaded_mainloop_unlock(mainloop); |
282 } | 283 } |
283 | 284 |
284 static int pulse_free(void) { | 285 static int pulse_free(void) { |
285 size_t l = 0; | 286 size_t l = 0; |
298 | 299 |
299 /* If this function is called twice with no pulse_write() call in | 300 /* If this function is called twice with no pulse_write() call in |
300 * between this means we should trigger the playback */ | 301 * between this means we should trigger the playback */ |
301 if (do_trigger) { | 302 if (do_trigger) { |
302 int success = 0; | 303 int success = 0; |
303 | 304 |
304 if (!(o = pa_stream_trigger(stream, stream_success_cb, &success))) { | 305 if (!(o = pa_stream_trigger(stream, stream_success_cb, &success))) { |
305 g_warning("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context))); | 306 g_warning("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context))); |
306 goto fail; | 307 goto fail; |
307 } | 308 } |
308 | 309 |
309 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { | 310 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { |
310 CHECK_DEAD_GOTO(fail, 1); | 311 CHECK_DEAD_GOTO(fail, 1); |
311 pa_threaded_mainloop_wait(mainloop); | 312 pa_threaded_mainloop_wait(mainloop); |
312 } | 313 } |
313 | 314 |
314 if (!success) | 315 if (!success) |
315 g_warning("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context))); | 316 g_warning("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context))); |
316 } | 317 } |
317 | 318 |
318 fail: | 319 fail: |
319 if (o) | 320 if (o) |
320 pa_operation_unref(o); | 321 pa_operation_unref(o); |
321 | 322 |
322 pa_threaded_mainloop_unlock(mainloop); | 323 pa_threaded_mainloop_unlock(mainloop); |
323 | 324 |
324 do_trigger = !!l; | 325 do_trigger = !!l; |
325 return (int) l; | 326 return (int) l; |
326 } | 327 } |
327 | 328 |
328 static int pulse_get_written_time(void) { | 329 static int pulse_get_written_time(void) { |
329 int r = 0; | 330 int r = 0; |
330 | 331 |
331 CHECK_CONNECTED(0); | 332 CHECK_CONNECTED(0); |
332 | 333 |
333 pa_threaded_mainloop_lock(mainloop); | 334 pa_threaded_mainloop_lock(mainloop); |
334 CHECK_DEAD_GOTO(fail, 1); | 335 CHECK_DEAD_GOTO(fail, 1); |
335 | 336 |
336 r = (int) (((double) written*1000) / pa_bytes_per_second(pa_stream_get_sample_spec(stream))); | 337 r = (int) (((double) written*1000) / pa_bytes_per_second(pa_stream_get_sample_spec(stream))); |
337 | 338 |
338 fail: | 339 fail: |
339 pa_threaded_mainloop_unlock(mainloop); | 340 pa_threaded_mainloop_unlock(mainloop); |
340 | 341 |
342 } | 343 } |
343 | 344 |
344 static int pulse_get_output_time(void) { | 345 static int pulse_get_output_time(void) { |
345 int r = 0; | 346 int r = 0; |
346 pa_usec_t t; | 347 pa_usec_t t; |
347 | 348 |
348 CHECK_CONNECTED(0); | 349 CHECK_CONNECTED(0); |
349 | 350 |
350 pa_threaded_mainloop_lock(mainloop); | 351 pa_threaded_mainloop_lock(mainloop); |
351 | 352 |
352 for (;;) { | 353 for (;;) { |
353 CHECK_DEAD_GOTO(fail, 1); | 354 CHECK_DEAD_GOTO(fail, 1); |
354 | 355 |
355 if (pa_stream_get_time(stream, &t) >= 0) | 356 if (pa_stream_get_time(stream, &t) >= 0) |
356 break; | 357 break; |
357 | 358 |
358 if (pa_context_errno(context) != PA_ERR_NODATA) { | 359 if (pa_context_errno(context) != PA_ERR_NODATA) { |
359 g_warning("pa_stream_get_time() failed: %s", pa_strerror(pa_context_errno(context))); | 360 g_warning("pa_stream_get_time() failed: %s", pa_strerror(pa_context_errno(context))); |
366 r = (int) (t / 1000); | 367 r = (int) (t / 1000); |
367 | 368 |
368 if (just_flushed) { | 369 if (just_flushed) { |
369 time_offset_msec -= r; | 370 time_offset_msec -= r; |
370 just_flushed = 0; | 371 just_flushed = 0; |
371 } | 372 } |
372 | 373 |
373 r += time_offset_msec; | 374 r += time_offset_msec; |
374 | 375 |
375 fail: | 376 fail: |
376 pa_threaded_mainloop_unlock(mainloop); | 377 pa_threaded_mainloop_unlock(mainloop); |
377 | 378 |
378 return r; | 379 return r; |
379 } | 380 } |
380 | 381 |
381 static int pulse_playing(void) { | 382 static int pulse_playing(void) { |
382 int r = 0; | 383 int r = 0; |
383 const pa_timing_info *i; | 384 const pa_timing_info *i; |
384 | 385 |
385 CHECK_CONNECTED(0); | 386 CHECK_CONNECTED(0); |
386 | 387 |
387 pa_threaded_mainloop_lock(mainloop); | 388 pa_threaded_mainloop_lock(mainloop); |
388 | 389 |
389 for (;;) { | 390 for (;;) { |
390 CHECK_DEAD_GOTO(fail, 1); | 391 CHECK_DEAD_GOTO(fail, 1); |
391 | 392 |
392 if ((i = pa_stream_get_timing_info(stream))) | 393 if ((i = pa_stream_get_timing_info(stream))) |
393 break; | 394 break; |
394 | 395 |
395 if (pa_context_errno(context) != PA_ERR_NODATA) { | 396 if (pa_context_errno(context) != PA_ERR_NODATA) { |
396 g_warning("pa_stream_get_timing_info() failed: %s", pa_strerror(pa_context_errno(context))); | 397 g_warning("pa_stream_get_timing_info() failed: %s", pa_strerror(pa_context_errno(context))); |
397 goto fail; | 398 goto fail; |
398 } | 399 } |
399 | 400 |
419 | 420 |
420 if (!(o = pa_stream_flush(stream, stream_success_cb, &success))) { | 421 if (!(o = pa_stream_flush(stream, stream_success_cb, &success))) { |
421 g_warning("pa_stream_flush() failed: %s", pa_strerror(pa_context_errno(context))); | 422 g_warning("pa_stream_flush() failed: %s", pa_strerror(pa_context_errno(context))); |
422 goto fail; | 423 goto fail; |
423 } | 424 } |
424 | 425 |
425 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { | 426 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { |
426 CHECK_DEAD_GOTO(fail, 1); | 427 CHECK_DEAD_GOTO(fail, 1); |
427 pa_threaded_mainloop_wait(mainloop); | 428 pa_threaded_mainloop_wait(mainloop); |
428 } | 429 } |
429 | 430 |
430 if (!success) | 431 if (!success) |
431 g_warning("pa_stream_flush() failed: %s", pa_strerror(pa_context_errno(context))); | 432 g_warning("pa_stream_flush() failed: %s", pa_strerror(pa_context_errno(context))); |
432 | 433 |
433 written = (uint64_t) (((double) time * pa_bytes_per_second(pa_stream_get_sample_spec(stream))) / 1000); | 434 written = (uint64_t) (((double) time * pa_bytes_per_second(pa_stream_get_sample_spec(stream))) / 1000); |
434 just_flushed = 1; | 435 just_flushed = 1; |
435 time_offset_msec = time; | 436 time_offset_msec = time; |
436 | 437 |
437 fail: | 438 fail: |
438 if (o) | 439 if (o) |
439 pa_operation_unref(o); | 440 pa_operation_unref(o); |
440 | 441 |
441 pa_threaded_mainloop_unlock(mainloop); | 442 pa_threaded_mainloop_unlock(mainloop); |
442 } | 443 } |
443 | 444 |
444 static void pulse_write(void* ptr, int length) { | 445 static void pulse_write(void* ptr, int length) { |
445 | 446 |
450 | 451 |
451 if (pa_stream_write(stream, ptr, length, NULL, PA_SEEK_RELATIVE, 0) < 0) { | 452 if (pa_stream_write(stream, ptr, length, NULL, PA_SEEK_RELATIVE, 0) < 0) { |
452 g_warning("pa_stream_write() failed: %s", pa_strerror(pa_context_errno(context))); | 453 g_warning("pa_stream_write() failed: %s", pa_strerror(pa_context_errno(context))); |
453 goto fail; | 454 goto fail; |
454 } | 455 } |
455 | 456 |
456 do_trigger = 0; | 457 do_trigger = 0; |
457 written += length; | 458 written += length; |
458 | 459 |
459 fail: | 460 fail: |
460 | 461 |
461 pa_threaded_mainloop_unlock(mainloop); | 462 pa_threaded_mainloop_unlock(mainloop); |
462 } | 463 } |
463 | 464 |
464 static void drain(void) { | 465 static void drain(void) { |
465 pa_operation *o = NULL; | 466 pa_operation *o = NULL; |
472 | 473 |
473 if (!(o = pa_stream_drain(stream, stream_success_cb, &success))) { | 474 if (!(o = pa_stream_drain(stream, stream_success_cb, &success))) { |
474 g_warning("pa_stream_drain() failed: %s", pa_strerror(pa_context_errno(context))); | 475 g_warning("pa_stream_drain() failed: %s", pa_strerror(pa_context_errno(context))); |
475 goto fail; | 476 goto fail; |
476 } | 477 } |
477 | 478 |
478 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { | 479 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { |
479 CHECK_DEAD_GOTO(fail, 1); | 480 CHECK_DEAD_GOTO(fail, 1); |
480 pa_threaded_mainloop_wait(mainloop); | 481 pa_threaded_mainloop_wait(mainloop); |
481 } | 482 } |
482 | 483 |
483 if (!success) | 484 if (!success) |
484 g_warning("pa_stream_drain() failed: %s", pa_strerror(pa_context_errno(context))); | 485 g_warning("pa_stream_drain() failed: %s", pa_strerror(pa_context_errno(context))); |
485 | 486 |
486 fail: | 487 fail: |
487 if (o) | 488 if (o) |
488 pa_operation_unref(o); | 489 pa_operation_unref(o); |
489 | 490 |
490 pa_threaded_mainloop_unlock(mainloop); | 491 pa_threaded_mainloop_unlock(mainloop); |
491 } | 492 } |
492 | 493 |
493 static void pulse_close(void) { | 494 static void pulse_close(void) { |
494 | 495 |
508 if (context) { | 509 if (context) { |
509 pa_context_disconnect(context); | 510 pa_context_disconnect(context); |
510 pa_context_unref(context); | 511 pa_context_unref(context); |
511 context = NULL; | 512 context = NULL; |
512 } | 513 } |
513 | 514 |
514 if (mainloop) { | 515 if (mainloop) { |
515 pa_threaded_mainloop_free(mainloop); | 516 pa_threaded_mainloop_free(mainloop); |
516 mainloop = NULL; | 517 mainloop = NULL; |
517 } | 518 } |
518 | 519 |
526 | 527 |
527 g_assert(!mainloop); | 528 g_assert(!mainloop); |
528 g_assert(!context); | 529 g_assert(!context); |
529 g_assert(!stream); | 530 g_assert(!stream); |
530 g_assert(!connected); | 531 g_assert(!connected); |
531 | 532 |
532 if (fmt == FMT_U8) | 533 if (fmt == FMT_U8) |
533 ss.format = PA_SAMPLE_U8; | 534 ss.format = PA_SAMPLE_U8; |
534 else if (fmt == FMT_S16_LE) | 535 else if (fmt == FMT_S16_LE) |
535 ss.format = PA_SAMPLE_S16LE; | 536 ss.format = PA_SAMPLE_S16LE; |
536 else if (fmt == FMT_S16_BE) | 537 else if (fmt == FMT_S16_BE) |
556 g_warning("Failed to allocate main loop"); | 557 g_warning("Failed to allocate main loop"); |
557 goto fail; | 558 goto fail; |
558 } | 559 } |
559 | 560 |
560 pa_threaded_mainloop_lock(mainloop); | 561 pa_threaded_mainloop_lock(mainloop); |
561 | 562 |
562 if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Audacious"))) { | 563 if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Audacious"))) { |
563 g_warning("Failed to allocate context"); | 564 g_warning("Failed to allocate context"); |
564 goto unlock_and_fail; | 565 goto unlock_and_fail; |
565 } | 566 } |
566 | 567 |
610 /* Now subscribe to events */ | 611 /* Now subscribe to events */ |
611 if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) { | 612 if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) { |
612 g_warning("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); | 613 g_warning("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); |
613 goto unlock_and_fail; | 614 goto unlock_and_fail; |
614 } | 615 } |
615 | 616 |
616 success = 0; | 617 success = 0; |
617 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { | 618 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { |
618 CHECK_DEAD_GOTO(fail, 1); | 619 CHECK_DEAD_GOTO(fail, 1); |
619 pa_threaded_mainloop_wait(mainloop); | 620 pa_threaded_mainloop_wait(mainloop); |
620 } | 621 } |
629 /* Now request the initial stream info */ | 630 /* Now request the initial stream info */ |
630 if (!(o = pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_cb, NULL))) { | 631 if (!(o = pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_cb, NULL))) { |
631 g_warning("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context))); | 632 g_warning("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context))); |
632 goto unlock_and_fail; | 633 goto unlock_and_fail; |
633 } | 634 } |
634 | 635 |
635 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { | 636 while (pa_operation_get_state(o) != PA_OPERATION_DONE) { |
636 CHECK_DEAD_GOTO(fail, 1); | 637 CHECK_DEAD_GOTO(fail, 1); |
637 pa_threaded_mainloop_wait(mainloop); | 638 pa_threaded_mainloop_wait(mainloop); |
638 } | 639 } |
639 | 640 |
646 written = 0; | 647 written = 0; |
647 time_offset_msec = 0; | 648 time_offset_msec = 0; |
648 just_flushed = 0; | 649 just_flushed = 0; |
649 connected = 1; | 650 connected = 1; |
650 volume_time_event = NULL; | 651 volume_time_event = NULL; |
651 | 652 |
652 pa_threaded_mainloop_unlock(mainloop); | 653 pa_threaded_mainloop_unlock(mainloop); |
653 | 654 |
654 return TRUE; | 655 return TRUE; |
655 | 656 |
656 unlock_and_fail: | 657 unlock_and_fail: |
657 | 658 |
658 if (o) | 659 if (o) |
659 pa_operation_unref(o); | 660 pa_operation_unref(o); |
660 | 661 |
661 pa_threaded_mainloop_unlock(mainloop); | 662 pa_threaded_mainloop_unlock(mainloop); |
662 | 663 |
663 fail: | 664 fail: |
664 | 665 |
665 pulse_close(); | 666 pulse_close(); |
666 | 667 |
667 return FALSE; | 668 return FALSE; |
668 } | 669 } |
669 | 670 |
670 static void pulse_about(void) { | 671 static void pulse_about(void) { |
671 static GtkWidget *dialog; | 672 static GtkWidget *dialog; |
672 | 673 |
673 if (dialog != NULL) | 674 if (dialog != NULL) |
674 return; | 675 return; |
675 | 676 |
676 dialog = xmms_show_message( | 677 dialog = xmms_show_message( |
677 "About Audacious PulseAudio Output Plugin", | 678 _("About Audacious PulseAudio Output Plugin"), |
678 "Audacious PulseAudio Output Plugin\n\n " | 679 _("Audacious PulseAudio Output Plugin\n\n " |
679 "This program is free software; you can redistribute it and/or modify\n" | 680 "This program is free software; you can redistribute it and/or modify\n" |
680 "it under the terms of the GNU General Public License as published by\n" | 681 "it under the terms of the GNU General Public License as published by\n" |
681 "the Free Software Foundation; either version 2 of the License, or\n" | 682 "the Free Software Foundation; either version 2 of the License, or\n" |
682 "(at your option) any later version.\n" | 683 "(at your option) any later version.\n" |
683 "\n" | 684 "\n" |
687 "GNU General Public License for more details.\n" | 688 "GNU General Public License for more details.\n" |
688 "\n" | 689 "\n" |
689 "You should have received a copy of the GNU General Public License\n" | 690 "You should have received a copy of the GNU General Public License\n" |
690 "along with this program; if not, write to the Free Software\n" | 691 "along with this program; if not, write to the Free Software\n" |
691 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n" | 692 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n" |
692 "USA.", | 693 "USA."), |
693 "OK", | 694 _("OK"), |
694 FALSE, | 695 FALSE, |
695 NULL, | 696 NULL, |
696 NULL); | 697 NULL); |
697 | 698 |
698 gtk_signal_connect( | 699 gtk_signal_connect( |
699 GTK_OBJECT(dialog), | 700 GTK_OBJECT(dialog), |
700 "destroy", | 701 "destroy", |
701 GTK_SIGNAL_FUNC(gtk_widget_destroyed), | 702 GTK_SIGNAL_FUNC(gtk_widget_destroyed), |
702 &dialog); | 703 &dialog); |
705 static OutputPlugin pulse_op = { | 706 static OutputPlugin pulse_op = { |
706 NULL, | 707 NULL, |
707 NULL, | 708 NULL, |
708 "PulseAudio Output Plugin", | 709 "PulseAudio Output Plugin", |
709 NULL, | 710 NULL, |
710 NULL, | 711 NULL, |
711 pulse_about, | 712 pulse_about, |
712 NULL, | 713 NULL, |
713 pulse_get_volume, | 714 pulse_get_volume, |
714 pulse_set_volume, | 715 pulse_set_volume, |
715 pulse_open, | 716 pulse_open, |
716 pulse_write, | 717 pulse_write, |
717 pulse_close, | 718 pulse_close, |
718 pulse_flush, | 719 pulse_flush, |
719 pulse_pause, | 720 pulse_pause, |
720 pulse_free, | 721 pulse_free, |
721 pulse_playing, | 722 pulse_playing, |
722 pulse_get_output_time, | 723 pulse_get_output_time, |
723 pulse_get_written_time, | 724 pulse_get_written_time, |
724 NULL, | 725 NULL, |
725 }; | 726 }; |
726 | 727 |
727 OutputPlugin *pulse_oplist[] = { &pulse_op, NULL }; | 728 OutputPlugin *pulse_oplist[] = { &pulse_op, NULL }; |
728 | 729 |
729 DECLARE_PLUGIN(pulse, NULL, NULL, NULL, pulse_oplist, NULL, NULL, NULL); | 730 DECLARE_PLUGIN(pulse, NULL, NULL, NULL, pulse_oplist, NULL, NULL, NULL); |