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);