49
49
pa_sample_spec sample_spec;
50
50
pa_channel_map channel_map;
52
51
int operation_success;
55
static gboolean check_pulse_health(xmms_pulse *p, int *rerror) {
56
if (!p->context || pa_context_get_state(p->context) != PA_CONTEXT_READY ||
57
!p->stream || pa_stream_get_state(p->stream) != PA_STREAM_READY) {
55
static gboolean check_pulse_health (xmms_pulse *p, int *rerror) {
56
if (!p->context || pa_context_get_state (p->context) != PA_CONTEXT_READY ||
57
!p->stream || pa_stream_get_state (p->stream) != PA_STREAM_READY) {
59
pa_context_get_state(p->context) == PA_CONTEXT_FAILED) ||
59
pa_context_get_state (p->context) == PA_CONTEXT_FAILED) ||
61
pa_stream_get_state(p->stream) == PA_STREAM_FAILED)) {
61
pa_stream_get_state (p->stream) == PA_STREAM_FAILED)) {
63
*(rerror) = pa_context_errno(p->context);
63
*(rerror) = pa_context_errno (p->context);
65
65
*(rerror) = PA_ERR_BADSTATE;
72
72
* Callbacks to handle updates from the Pulse daemon.
74
static void signal_mainloop(void *userdata) {
74
static void signal_mainloop (void *userdata) {
75
75
xmms_pulse *p = userdata;
78
pa_threaded_mainloop_signal(p->mainloop, 0);
78
pa_threaded_mainloop_signal (p->mainloop, 0);
81
static void context_state_cb(pa_context *c, void *userdata) {
81
static void context_state_cb (pa_context *c, void *userdata) {
84
switch (pa_context_get_state(c)) {
84
switch (pa_context_get_state (c)) {
85
85
case PA_CONTEXT_READY:
86
86
case PA_CONTEXT_TERMINATED:
87
87
case PA_CONTEXT_FAILED:
88
signal_mainloop(userdata);
88
signal_mainloop (userdata);
90
90
case PA_CONTEXT_UNCONNECTED:
91
91
case PA_CONTEXT_CONNECTING:
113
static void stream_latency_update_cb(pa_stream *s, void *userdata) {
114
signal_mainloop(userdata);
117
static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
118
signal_mainloop(userdata);
121
static void drain_result_cb(pa_stream *s, int success, void *userdata) {
113
static void stream_latency_update_cb (pa_stream *s, void *userdata) {
114
signal_mainloop (userdata);
117
static void stream_request_cb (pa_stream *s, size_t length, void *userdata) {
118
signal_mainloop (userdata);
121
static void drain_result_cb (pa_stream *s, int success, void *userdata) {
122
122
xmms_pulse *p = userdata;
126
126
p->operation_success = success;
127
signal_mainloop(userdata);
127
signal_mainloop (userdata);
146
p = g_new0(xmms_pulse, 1);
146
p = g_new0 (xmms_pulse, 1);
150
p->mainloop = pa_threaded_mainloop_new();
152
p->mainloop = pa_threaded_mainloop_new ();
151
153
if (!p->mainloop)
154
p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name);
156
p->context = pa_context_new (pa_threaded_mainloop_get_api (p->mainloop), name);
158
pa_context_set_state_callback(p->context, context_state_cb, p);
160
pa_context_set_state_callback (p->context, context_state_cb, p);
160
if (pa_context_connect(p->context, server, 0, NULL) < 0) {
161
error = pa_context_errno(p->context);
162
if (pa_context_connect (p->context, server, 0, NULL) < 0) {
163
error = pa_context_errno (p->context);
165
pa_threaded_mainloop_lock(p->mainloop);
167
pa_threaded_mainloop_lock (p->mainloop);
167
if (pa_threaded_mainloop_start(p->mainloop) < 0)
169
if (pa_threaded_mainloop_start (p->mainloop) < 0)
168
170
goto unlock_and_fail;
170
172
/* Wait until the context is ready */
171
pa_threaded_mainloop_wait(p->mainloop);
173
pa_threaded_mainloop_wait (p->mainloop);
173
if (pa_context_get_state(p->context) != PA_CONTEXT_READY) {
174
error = pa_context_errno(p->context);
175
if (pa_context_get_state (p->context) != PA_CONTEXT_READY) {
176
error = pa_context_errno (p->context);
175
177
goto unlock_and_fail;
178
pa_threaded_mainloop_unlock(p->mainloop);
180
pa_threaded_mainloop_unlock (p->mainloop);
182
pa_threaded_mainloop_unlock(p->mainloop);
184
pa_threaded_mainloop_unlock (p->mainloop);
186
xmms_pulse_backend_free(p);
188
xmms_pulse_backend_free (p);
191
void xmms_pulse_backend_free(xmms_pulse *p) {
193
void xmms_pulse_backend_free (xmms_pulse *p) {
195
xmms_pulse_backend_close_stream(p);
197
xmms_pulse_backend_close_stream (p);
197
pa_threaded_mainloop_stop(p->mainloop);
199
pa_threaded_mainloop_stop (p->mainloop);
199
pa_context_unref(p->context);
201
pa_context_unref (p->context);
201
pa_threaded_mainloop_free(p->mainloop);
203
pa_threaded_mainloop_free (p->mainloop);
207
gboolean xmms_pulse_backend_set_stream(xmms_pulse *p, const char *stream_name,
209
xmms_sample_format_t format,
210
int samplerate, int channels,
209
gboolean xmms_pulse_backend_set_stream (xmms_pulse *p, const char *stream_name,
211
xmms_sample_format_t format,
212
int samplerate, int channels,
212
214
pa_sample_format_t pa_format = PA_SAMPLE_INVALID;
213
216
int error = PA_ERR_INTERNAL;
218
221
/* Convert the XMMS2 sample format to the pulse format. */
219
for (i = 0; i < G_N_ELEMENTS(xmms_pulse_formats); i++) {
222
for (i = 0; i < G_N_ELEMENTS (xmms_pulse_formats); i++) {
220
223
if (xmms_pulse_formats[i].xmms_fmt == format) {
221
224
pa_format = xmms_pulse_formats[i].pulse_fmt;
234
237
/* The existing stream needs to be shut down. */
236
xmms_pulse_backend_close_stream(p);
239
xmms_pulse_backend_close_stream (p);
238
pa_threaded_mainloop_lock(p->mainloop);
241
pa_threaded_mainloop_lock (p->mainloop);
241
244
/* Configure the new stream. */
242
245
p->sample_spec.format = pa_format;
243
246
p->sample_spec.rate = samplerate;
244
247
p->sample_spec.channels = channels;
245
pa_channel_map_init_auto(&p->channel_map, channels, PA_CHANNEL_MAP_DEFAULT);
248
pa_channel_map_init_auto (&p->channel_map, channels, PA_CHANNEL_MAP_DEFAULT);
247
250
/* Create and set up the new stream. */
248
p->stream = pa_stream_new(p->context, stream_name, &p->sample_spec, &p->channel_map);
251
p->stream = pa_stream_new (p->context, stream_name, &p->sample_spec, &p->channel_map);
249
252
if (!p->stream) {
250
error = pa_context_errno(p->context);
253
error = pa_context_errno (p->context);
251
254
goto unlock_and_fail;
254
pa_stream_set_state_callback(p->stream, stream_state_cb, p);
255
pa_stream_set_write_callback(p->stream, stream_request_cb, p);
256
pa_stream_set_latency_update_callback(p->stream, stream_latency_update_cb, p);
258
ret = pa_stream_connect_playback(
259
p->stream, sink, NULL,
260
PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE,
257
pa_stream_set_state_callback (p->stream, stream_state_cb, p);
258
pa_stream_set_write_callback (p->stream, stream_request_cb, p);
259
pa_stream_set_latency_update_callback (p->stream, stream_latency_update_cb, p);
261
pa_cvolume_set (&cvol, p->sample_spec.channels,
262
PA_VOLUME_NORM * p->volume / 100);
264
ret = pa_stream_connect_playback (p->stream, sink, NULL,
265
PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE,
264
error = pa_context_errno(p->context);
269
error = pa_context_errno (p->context);
265
270
goto unlock_and_fail;
268
273
/* Wait until the stream is ready */
269
while (pa_stream_get_state(p->stream) == PA_STREAM_CREATING) {
270
pa_threaded_mainloop_wait(p->mainloop);
272
if (pa_stream_get_state(p->stream) != PA_STREAM_READY) {
273
error = pa_context_errno(p->context);
274
while (pa_stream_get_state (p->stream) == PA_STREAM_CREATING) {
275
pa_threaded_mainloop_wait (p->mainloop);
277
if (pa_stream_get_state (p->stream) != PA_STREAM_READY) {
278
error = pa_context_errno (p->context);
274
279
goto unlock_and_fail;
277
pa_threaded_mainloop_unlock(p->mainloop);
282
pa_threaded_mainloop_unlock (p->mainloop);
281
pa_threaded_mainloop_unlock(p->mainloop);
286
pa_threaded_mainloop_unlock (p->mainloop);
285
pa_stream_unref(p->stream);
290
pa_stream_unref (p->stream);
286
291
p->stream = NULL;
291
void xmms_pulse_backend_close_stream(xmms_pulse *p)
296
void xmms_pulse_backend_close_stream (xmms_pulse *p)
295
pa_threaded_mainloop_lock(p->mainloop);
300
pa_threaded_mainloop_lock (p->mainloop);
297
302
/* We're killing it anyway, sod errors. */
298
xmms_pulse_backend_drain(p, NULL);
303
xmms_pulse_backend_drain (p, NULL);
300
pa_stream_disconnect(p->stream);
301
pa_stream_unref(p->stream);
305
pa_stream_disconnect (p->stream);
306
pa_stream_unref (p->stream);
302
307
p->stream = NULL;
304
pa_threaded_mainloop_unlock(p->mainloop);
309
pa_threaded_mainloop_unlock (p->mainloop);
307
gboolean xmms_pulse_backend_write(xmms_pulse *p, const char *data,
308
size_t length, int *rerror)
312
gboolean xmms_pulse_backend_write (xmms_pulse *p, const char *data,
313
size_t length, int *rerror)
312
317
if (!data || !length) {
318
pa_threaded_mainloop_lock(p->mainloop);
319
if (!check_pulse_health(p, rerror))
323
pa_threaded_mainloop_lock (p->mainloop);
324
if (!check_pulse_health (p, rerror))
320
325
goto unlock_and_fail;
322
327
while (length > 0) {
326
while (!(buf_len = pa_stream_writable_size(p->stream))) {
327
pa_threaded_mainloop_wait(p->mainloop);
328
if (!check_pulse_health(p, rerror))
331
while (!(buf_len = pa_stream_writable_size (p->stream))) {
332
pa_threaded_mainloop_wait (p->mainloop);
333
if (!check_pulse_health (p, rerror))
329
334
goto unlock_and_fail;
332
337
if (buf_len == (size_t)-1) {
334
*rerror = pa_context_errno((p)->context);
339
*rerror = pa_context_errno ((p)->context);
335
340
goto unlock_and_fail;
337
342
if (buf_len > length)
338
343
buf_len = length;
340
ret = pa_stream_write(p->stream, data, buf_len, NULL, 0, PA_SEEK_RELATIVE);
345
ret = pa_stream_write (p->stream, data, buf_len, NULL, 0, PA_SEEK_RELATIVE);
343
*rerror = pa_context_errno((p)->context);
348
*rerror = pa_context_errno ((p)->context);
344
349
goto unlock_and_fail;
348
353
length -= buf_len;
351
pa_threaded_mainloop_unlock(p->mainloop);
356
pa_threaded_mainloop_unlock (p->mainloop);
355
pa_threaded_mainloop_unlock(p->mainloop);
360
pa_threaded_mainloop_unlock (p->mainloop);
360
gboolean xmms_pulse_backend_drain(xmms_pulse *p, int *rerror) {
365
gboolean xmms_pulse_backend_drain (xmms_pulse *p, int *rerror) {
361
366
pa_operation *o = NULL;
364
if (!check_pulse_health(p, rerror))
369
if (!check_pulse_health (p, rerror))
365
370
goto unlock_and_fail;
367
o = pa_stream_drain(p->stream, drain_result_cb, p);
372
o = pa_stream_drain (p->stream, drain_result_cb, p);
370
*rerror = pa_context_errno((p)->context);
375
*rerror = pa_context_errno ((p)->context);
371
376
goto unlock_and_fail;
374
379
p->operation_success = 0;
375
while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
376
pa_threaded_mainloop_wait(p->mainloop);
377
if (!check_pulse_health(p, rerror))
380
while (pa_operation_get_state (o) != PA_OPERATION_DONE) {
381
pa_threaded_mainloop_wait (p->mainloop);
382
if (!check_pulse_health (p, rerror))
378
383
goto unlock_and_fail;
380
pa_operation_unref(o);
385
pa_operation_unref (o);
382
387
if (!p->operation_success) {
384
*rerror = pa_context_errno((p)->context);
389
*rerror = pa_context_errno ((p)->context);
385
390
goto unlock_and_fail;
392
pa_operation_cancel(o);
393
pa_operation_unref(o);
397
pa_operation_cancel (o);
398
pa_operation_unref (o);
400
gboolean xmms_pulse_backend_flush(xmms_pulse *p, int *rerror) {
405
gboolean xmms_pulse_backend_flush (xmms_pulse *p, int *rerror) {
403
pa_threaded_mainloop_lock(p->mainloop);
404
if (!check_pulse_health(p, rerror))
408
pa_threaded_mainloop_lock (p->mainloop);
409
if (!check_pulse_health (p, rerror))
405
410
goto unlock_and_fail;
407
o = pa_stream_flush(p->stream, drain_result_cb, p);
412
o = pa_stream_flush (p->stream, drain_result_cb, p);
410
*rerror = pa_context_errno((p)->context);
415
*rerror = pa_context_errno ((p)->context);
411
416
goto unlock_and_fail;
414
419
p->operation_success = 0;
415
while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
416
pa_threaded_mainloop_wait(p->mainloop);
417
if (!check_pulse_health(p, rerror))
420
while (pa_operation_get_state (o) != PA_OPERATION_DONE) {
421
pa_threaded_mainloop_wait (p->mainloop);
422
if (!check_pulse_health (p, rerror))
418
423
goto unlock_and_fail;
420
pa_operation_unref(o);
425
pa_operation_unref (o);
422
427
if (!p->operation_success) {
424
*rerror = pa_context_errno((p)->context);
429
*rerror = pa_context_errno ((p)->context);
425
430
goto unlock_and_fail;
428
pa_threaded_mainloop_unlock(p->mainloop);
433
pa_threaded_mainloop_unlock (p->mainloop);
433
pa_operation_cancel(o);
434
pa_operation_unref(o);
438
pa_operation_cancel (o);
439
pa_operation_unref (o);
437
pa_threaded_mainloop_unlock(p->mainloop);
442
pa_threaded_mainloop_unlock (p->mainloop);
442
int xmms_pulse_backend_get_latency(xmms_pulse *p, int *rerror) {
447
int xmms_pulse_backend_get_latency (xmms_pulse *p, int *rerror) {
447
pa_threaded_mainloop_lock(p->mainloop);
452
pa_threaded_mainloop_lock (p->mainloop);
450
if (!check_pulse_health(p, rerror))
455
if (!check_pulse_health (p, rerror))
451
456
goto unlock_and_fail;
453
if (pa_stream_get_latency(p->stream, &t, &negative) >= 0)
458
if (pa_stream_get_latency (p->stream, &t, &negative) >= 0)
456
r = pa_context_errno(p->context);
461
r = pa_context_errno (p->context);
457
462
if (r != PA_ERR_NODATA) {
460
465
goto unlock_and_fail;
462
467
/* Wait until latency data is available again */
463
pa_threaded_mainloop_wait(p->mainloop);
468
pa_threaded_mainloop_wait (p->mainloop);
466
pa_threaded_mainloop_unlock(p->mainloop);
471
pa_threaded_mainloop_unlock (p->mainloop);
468
473
return negative ? 0 : t;
471
pa_threaded_mainloop_unlock(p->mainloop);
476
pa_threaded_mainloop_unlock (p->mainloop);
481
void volume_set_cb (pa_context *c, int success, void *udata) {
482
int *res = (int *) udata;
487
int xmms_pulse_backend_volume_set (xmms_pulse *p, unsigned int vol) {
496
pa_threaded_mainloop_lock (p->mainloop);
498
if (p->stream != NULL) {
499
pa_cvolume_set (&cvol, p->sample_spec.channels,
500
PA_VOLUME_NORM * vol / 100);
502
idx = pa_stream_get_index (p->stream);
504
o = pa_context_set_sink_input_volume (p->context, idx, &cvol,
505
volume_set_cb, &res);
507
/* wait for result to land */
508
while (pa_operation_get_state (o) != PA_OPERATION_DONE) {
509
pa_threaded_mainloop_wait (p->mainloop);
512
pa_operation_unref (o);
514
/* The cb set res to 1 or 0 depending on success */
522
pa_threaded_mainloop_unlock (p->mainloop);
528
void volume_get_cb (pa_context *c, const pa_sink_input_info *i,
529
int eol, void *udata) {
530
unsigned int *vol = (unsigned int *) udata;
534
if (i != NULL && i->volume.channels > 0 && *vol == -1) {
535
for (j = 0; j < i->volume.channels; j++) {
536
total += i->volume.values[j] * 100.0 / PA_VOLUME_NORM;
539
*vol = (unsigned int) ceil (total / i->volume.channels);
544
int xmms_pulse_backend_volume_get (xmms_pulse *p, unsigned int *vol) {
552
pa_threaded_mainloop_lock (p->mainloop);
556
if (p->stream != NULL) {
557
idx = pa_stream_get_index (p->stream);
559
o = pa_context_get_sink_input_info (p->context, idx,
563
while (pa_operation_get_state (o) != PA_OPERATION_DONE) {
564
pa_threaded_mainloop_wait (p->mainloop);
567
pa_operation_unref (o);
571
pa_threaded_mainloop_unlock (p->mainloop);