22 #include <pulse/pulseaudio.h>
23 #include <pulse/error.h>
54 int eol,
void *userdata)
62 pa_threaded_mainloop_signal(s->
mainloop, 0);
64 if (dev->flags & PA_SINK_FLAT_VOLUME)
77 if (!(op = pa_context_get_sink_info_by_name(s->
ctx, s->
device,
82 while (pa_operation_get_state(op) == PA_OPERATION_RUNNING)
83 pa_threaded_mainloop_wait(s->
mainloop);
84 pa_operation_unref(op);
89 int eol,
void *userdata)
99 pa_volume_t vol = pa_cvolume_avg(&i->volume);
100 if (s->
mute < 0 || (s->
mute && !i->mute) || (!s->
mute && i->mute)) {
107 val = (double)vol / PA_VOLUME_NORM;
120 enum pa_operation_state op_state;
121 pa_mainloop *ml = NULL;
122 pa_context *ctx = NULL;
128 if (!(op = pa_context_get_sink_input_info(ctx, pa_stream_get_index(s->
stream),
134 while ((op_state = pa_operation_get_state(op)) == PA_OPERATION_RUNNING)
135 pa_mainloop_iterate(ml, 1, NULL);
136 pa_operation_unref(op);
137 if (op_state != PA_OPERATION_DONE) {
149 static void pulse_event(pa_context *ctx, pa_subscription_event_type_t t,
150 uint32_t idx,
void *userdata)
158 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
159 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE)
169 int64_t
val = nbytes;
175 pa_threaded_mainloop_signal(s->
mainloop, 0);
197 switch (pa_stream_get_state(s->
stream)) {
198 case PA_STREAM_READY:
199 case PA_STREAM_FAILED:
200 case PA_STREAM_TERMINATED:
201 pa_threaded_mainloop_signal(s->
mainloop, 0);
209 pa_stream_state_t
state;
211 while ((state = pa_stream_get_state(s->
stream)) != PA_STREAM_READY) {
212 if (state == PA_STREAM_FAILED || state == PA_STREAM_TERMINATED)
214 pa_threaded_mainloop_wait(s->
mainloop);
226 switch (pa_context_get_state(ctx)) {
227 case PA_CONTEXT_READY:
228 case PA_CONTEXT_FAILED:
229 case PA_CONTEXT_TERMINATED:
230 pa_threaded_mainloop_signal(s->
mainloop, 0);
238 pa_context_state_t
state;
240 while ((state = pa_context_get_state(s->
ctx)) != PA_CONTEXT_READY) {
241 if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
243 pa_threaded_mainloop_wait(s->
mainloop);
256 pa_threaded_mainloop_signal(s->
mainloop, 0);
262 pa_threaded_mainloop_unlock(s->
mainloop);
268 pa_threaded_mainloop_wait(s->
mainloop);
269 pa_operation_unref(op);
270 pa_threaded_mainloop_unlock(s->
mainloop);
279 pa_threaded_mainloop_lock(s->
mainloop);
287 pa_threaded_mainloop_lock(s->
mainloop);
300 pa_threaded_mainloop_signal(s->
mainloop, 0);
306 pa_threaded_mainloop_unlock(s->
mainloop);
312 pa_threaded_mainloop_wait(s->
mainloop);
313 pa_operation_unref(op);
314 pa_threaded_mainloop_unlock(s->
mainloop);
323 pa_threaded_mainloop_lock(s->
mainloop);
324 op = pa_context_set_sink_input_mute(s->
ctx, pa_stream_get_index(s->
stream),
334 const pa_sample_spec *ss = pa_stream_get_sample_spec(s->
stream);
336 vol = pa_sw_volume_multiply(lround(volume * PA_VOLUME_NORM), s->
base_volume);
337 pa_cvolume_set(&cvol, ss->channels, PA_VOLUME_NORM);
338 pa_sw_cvolume_multiply_scalar(&cvol, &cvol, vol);
339 pa_threaded_mainloop_lock(s->
mainloop);
340 op = pa_context_set_sink_input_volume(s->
ctx, pa_stream_get_index(s->
stream),
349 pa_threaded_mainloop_lock(s->
mainloop);
356 channel_map->channels = 0;
358 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
360 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
362 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
364 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE;
366 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
368 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
370 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
372 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
374 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
376 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
378 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
380 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_CENTER;
382 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
384 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
386 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
388 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_LEFT;
390 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_CENTER;
392 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
394 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
396 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
398 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX0;
400 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX1;
402 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX2;
404 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX3;
406 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE;
414 pa_threaded_mainloop_lock(s->
mainloop);
416 pa_stream_disconnect(s->
stream);
417 pa_stream_set_state_callback(s->
stream, NULL, NULL);
418 pa_stream_set_write_callback(s->
stream, NULL, NULL);
419 pa_stream_set_overflow_callback(s->
stream, NULL, NULL);
420 pa_stream_set_underflow_callback(s->
stream, NULL, NULL);
421 pa_stream_unref(s->
stream);
425 pa_context_disconnect(s->
ctx);
426 pa_context_set_state_callback(s->
ctx, NULL, NULL);
427 pa_context_set_subscribe_callback(s->
ctx, NULL, NULL);
428 pa_context_unref(s->
ctx);
431 pa_threaded_mainloop_unlock(s->
mainloop);
432 pa_threaded_mainloop_stop(s->
mainloop);
433 pa_threaded_mainloop_free(s->
mainloop);
445 pa_sample_spec sample_spec;
446 pa_buffer_attr buffer_attributes = { -1, -1, -1, -1, -1 };
447 pa_channel_map channel_map;
448 pa_mainloop_api *mainloop_api;
450 static const pa_stream_flags_t stream_flags = PA_STREAM_INTERPOLATE_TIMING |
451 PA_STREAM_AUTO_TIMING_UPDATE |
452 PA_STREAM_NOT_MONOTONIC;
464 stream_name =
"Playback";
473 buffer_attributes.tlength =
FFMAX(s->
buffer_size, av_clip64(bytes, 0, UINT32_MAX - 1));
475 "Buffer duration: %ums recalculated into %"PRId64
" bytes buffer.\n",
477 av_log(s,
AV_LOG_DEBUG,
"Real buffer length is %u bytes\n", buffer_attributes.tlength);
481 buffer_attributes.prebuf = s->
prebuf;
483 buffer_attributes.minreq = s->
minreq;
488 if (!pa_sample_spec_valid(&sample_spec)) {
493 if (sample_spec.channels == 1) {
494 channel_map.channels = 1;
495 channel_map.map[0] = PA_CHANNEL_POSITION_MONO;
501 if (channel_map.channels != sample_spec.channels) {
503 channel_map.channels = 0;
506 channel_map.channels = 0;
508 if (!channel_map.channels)
510 else if (!pa_channel_map_valid(&channel_map)) {
516 s->
mainloop = pa_threaded_mainloop_new();
521 if ((ret = pa_threaded_mainloop_start(s->
mainloop)) < 0) {
523 pa_threaded_mainloop_free(s->
mainloop);
528 pa_threaded_mainloop_lock(s->
mainloop);
530 mainloop_api = pa_threaded_mainloop_get_api(s->
mainloop);
537 s->
ctx = pa_context_new(mainloop_api, s->
name);
546 if ((ret = pa_context_connect(s->
ctx, s->
server, 0, NULL)) < 0) {
557 s->
stream = pa_stream_new(s->
ctx, stream_name, &sample_spec,
558 channel_map.channels ? &channel_map : NULL);
575 if ((ret = pa_stream_connect_playback(s->
stream, s->
device, &buffer_attributes,
576 stream_flags, NULL, NULL)) < 0) {
577 av_log(s,
AV_LOG_ERROR,
"pa_stream_connect_playback failed: %s.\n", pa_strerror(ret));
588 buffer_attributes = *pa_stream_get_buffer_attr(s->
stream);
590 s->
prebuf = buffer_attributes.prebuf;
591 s->
minreq = buffer_attributes.minreq;
595 pa_threaded_mainloop_unlock(s->
mainloop);
600 pa_threaded_mainloop_lock(s->
mainloop);
607 pa_threaded_mainloop_lock(s->
mainloop);
612 pa_threaded_mainloop_unlock(s->
mainloop);
618 pa_threaded_mainloop_unlock(s->
mainloop);
627 int64_t writable_size;
645 pa_threaded_mainloop_lock(s->
mainloop);
646 if (!PA_STREAM_IS_GOOD(pa_stream_get_state(s->
stream))) {
650 while (pa_stream_writable_size(s->
stream) < s->
minreq) {
652 pa_threaded_mainloop_unlock(s->
mainloop);
655 pa_threaded_mainloop_wait(s->
mainloop);
658 if ((ret = pa_stream_write(s->
stream, pkt->
data, pkt->
size, NULL, 0, PA_SEEK_RELATIVE)) < 0) {
662 if ((writable_size = pa_stream_writable_size(s->
stream)) >= s->
minreq)
665 pa_threaded_mainloop_unlock(s->
mainloop);
669 pa_threaded_mainloop_unlock(s->
mainloop);
683 pkt.
data = (*frame)->data[0];
685 pkt.
dts = (*frame)->pkt_dts;
696 pa_threaded_mainloop_lock(s->
mainloop);
697 pa_stream_get_latency(s->
stream, &latency, &neg);
698 pa_threaded_mainloop_unlock(s->
mainloop);
702 *dts = s->
timestamp - (neg ? -latency : latency);
712 void *
data,
size_t data_size)
743 pa_threaded_mainloop_lock(s->
mainloop);
745 pa_threaded_mainloop_unlock(s->
mainloop);
749 pa_threaded_mainloop_lock(s->
mainloop);
751 pa_threaded_mainloop_unlock(s->
mainloop);
759 #define OFFSET(a) offsetof(PulseData, a)
760 #define E AV_OPT_FLAG_ENCODING_PARAM
766 {
"buffer_size",
"set buffer size in bytes",
OFFSET(buffer_size),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX,
E },
767 {
"buffer_duration",
"set buffer duration in millisecs",
OFFSET(buffer_duration),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX,
E },