22 #include <pulse/pulseaudio.h>
23 #include <pulse/error.h>
56 int eol,
void *userdata)
64 pa_threaded_mainloop_signal(
s->mainloop, 0);
66 if (dev->flags & PA_SINK_FLAT_VOLUME)
67 s->base_volume = dev->base_volume;
69 s->base_volume = PA_VOLUME_NORM;
79 if (!(
op = pa_context_get_sink_info_by_name(
s->ctx,
s->device,
84 while (pa_operation_get_state(
op) == PA_OPERATION_RUNNING)
85 pa_threaded_mainloop_wait(
s->mainloop);
86 pa_operation_unref(
op);
91 int eol,
void *userdata)
101 pa_volume_t vol = pa_cvolume_avg(&
i->volume);
102 if (
s->mute < 0 || (
s->mute && !
i->mute) || (!
s->mute &&
i->mute)) {
107 vol = pa_sw_volume_divide(vol,
s->base_volume);
108 if (
s->last_volume != vol) {
109 val = (double)vol / PA_VOLUME_NORM;
111 s->last_volume = vol;
122 enum pa_operation_state op_state;
123 pa_mainloop *ml =
NULL;
130 if (!(
op = pa_context_get_sink_input_info(
ctx, pa_stream_get_index(
s->stream),
136 while ((op_state = pa_operation_get_state(
op)) == PA_OPERATION_RUNNING)
137 pa_mainloop_iterate(ml, 1,
NULL);
138 pa_operation_unref(
op);
139 if (op_state != PA_OPERATION_DONE) {
152 uint32_t idx,
void *userdata)
160 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
161 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE)
171 int64_t
val = nbytes;
173 if (stream !=
s->stream)
177 pa_threaded_mainloop_signal(
s->mainloop, 0);
196 if (stream !=
s->stream)
199 switch (pa_stream_get_state(
s->stream)) {
200 case PA_STREAM_READY:
201 case PA_STREAM_FAILED:
202 case PA_STREAM_TERMINATED:
203 pa_threaded_mainloop_signal(
s->mainloop, 0);
211 pa_stream_state_t
state;
213 while ((
state = pa_stream_get_state(
s->stream)) != PA_STREAM_READY) {
214 if (
state == PA_STREAM_FAILED ||
state == PA_STREAM_TERMINATED)
216 pa_threaded_mainloop_wait(
s->mainloop);
228 switch (pa_context_get_state(
ctx)) {
229 case PA_CONTEXT_READY:
230 case PA_CONTEXT_FAILED:
231 case PA_CONTEXT_TERMINATED:
232 pa_threaded_mainloop_signal(
s->mainloop, 0);
240 pa_context_state_t
state;
242 while ((
state = pa_context_get_state(
s->ctx)) != PA_CONTEXT_READY) {
243 if (
state == PA_CONTEXT_FAILED ||
state == PA_CONTEXT_TERMINATED)
245 pa_threaded_mainloop_wait(
s->mainloop);
254 if (stream !=
s->stream)
258 pa_threaded_mainloop_signal(
s->mainloop, 0);
264 pa_threaded_mainloop_unlock(
s->mainloop);
269 while (
s->last_result == 2)
270 pa_threaded_mainloop_wait(
s->mainloop);
271 pa_operation_unref(
op);
272 pa_threaded_mainloop_unlock(
s->mainloop);
273 if (
s->last_result != 0)
275 return s->last_result;
281 pa_threaded_mainloop_lock(
s->mainloop);
289 pa_threaded_mainloop_lock(
s->mainloop);
302 pa_threaded_mainloop_signal(
s->mainloop, 0);
308 pa_threaded_mainloop_unlock(
s->mainloop);
313 while (
s->last_result == 2)
314 pa_threaded_mainloop_wait(
s->mainloop);
315 pa_operation_unref(
op);
316 pa_threaded_mainloop_unlock(
s->mainloop);
317 if (
s->last_result != 0)
319 return s->last_result;
325 pa_threaded_mainloop_lock(
s->mainloop);
326 op = pa_context_set_sink_input_mute(
s->ctx, pa_stream_get_index(
s->stream),
336 const pa_sample_spec *
ss = pa_stream_get_sample_spec(
s->stream);
338 vol = pa_sw_volume_multiply(
lrint(volume * PA_VOLUME_NORM),
s->base_volume);
339 pa_cvolume_set(&cvol,
ss->channels, PA_VOLUME_NORM);
340 pa_sw_cvolume_multiply_scalar(&cvol, &cvol, vol);
341 pa_threaded_mainloop_lock(
s->mainloop);
342 op = pa_context_set_sink_input_volume(
s->ctx, pa_stream_get_index(
s->stream),
351 pa_threaded_mainloop_lock(
s->mainloop);
358 channel_map->channels = 0;
360 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
362 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
364 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
366 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE;
368 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
370 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
372 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
374 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
376 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
378 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
380 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
382 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_CENTER;
384 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
386 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
388 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
390 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_LEFT;
392 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_CENTER;
394 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
396 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
398 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
400 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX0;
402 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX1;
404 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX2;
406 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX3;
408 channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE;
416 pa_threaded_mainloop_lock(
s->mainloop);
418 pa_stream_disconnect(
s->stream);
419 pa_stream_set_state_callback(
s->stream,
NULL,
NULL);
420 pa_stream_set_write_callback(
s->stream,
NULL,
NULL);
421 pa_stream_set_overflow_callback(
s->stream,
NULL,
NULL);
422 pa_stream_set_underflow_callback(
s->stream,
NULL,
NULL);
423 pa_stream_unref(
s->stream);
427 pa_context_disconnect(
s->ctx);
428 pa_context_set_state_callback(
s->ctx,
NULL,
NULL);
429 pa_context_set_subscribe_callback(
s->ctx,
NULL,
NULL);
430 pa_context_unref(
s->ctx);
433 pa_threaded_mainloop_unlock(
s->mainloop);
434 pa_threaded_mainloop_stop(
s->mainloop);
435 pa_threaded_mainloop_free(
s->mainloop);
447 pa_sample_spec sample_spec;
448 pa_buffer_attr buffer_attributes = { -1, -1, -1, -1, -1 };
449 pa_channel_map channel_map;
450 pa_mainloop_api *mainloop_api;
451 const char *stream_name =
s->stream_name;
452 static const pa_stream_flags_t stream_flags = PA_STREAM_INTERPOLATE_TIMING |
453 PA_STREAM_AUTO_TIMING_UPDATE |
454 PA_STREAM_NOT_MONOTONIC;
464 stream_name =
h->url;
466 stream_name =
"Playback";
470 if (
s->buffer_duration) {
471 int64_t bytes =
s->buffer_duration;
475 buffer_attributes.tlength =
FFMAX(
s->buffer_size,
av_clip64(bytes, 0, UINT32_MAX - 1));
477 "Buffer duration: %ums recalculated into %"PRId64
" bytes buffer.\n",
478 s->buffer_duration, bytes);
480 }
else if (
s->buffer_size)
481 buffer_attributes.tlength =
s->buffer_size;
483 buffer_attributes.prebuf =
s->prebuf;
485 buffer_attributes.minreq =
s->minreq;
490 if (!pa_sample_spec_valid(&sample_spec)) {
495 if (sample_spec.channels == 1) {
496 channel_map.channels = 1;
497 channel_map.map[0] = PA_CHANNEL_POSITION_MONO;
503 if (channel_map.channels != sample_spec.channels) {
505 channel_map.channels = 0;
508 channel_map.channels = 0;
510 if (!channel_map.channels)
512 else if (!pa_channel_map_valid(&channel_map)) {
518 s->mainloop = pa_threaded_mainloop_new();
523 if ((
ret = pa_threaded_mainloop_start(
s->mainloop)) < 0) {
525 pa_threaded_mainloop_free(
s->mainloop);
530 pa_threaded_mainloop_lock(
s->mainloop);
532 mainloop_api = pa_threaded_mainloop_get_api(
s->mainloop);
539 s->ctx = pa_context_new(mainloop_api,
s->name);
548 if ((
ret = pa_context_connect(
s->ctx,
s->server, 0,
NULL)) < 0) {
559 s->stream = pa_stream_new(
s->ctx, stream_name, &sample_spec,
560 channel_map.channels ? &channel_map :
NULL);
577 if ((
ret = pa_stream_connect_playback(
s->stream,
s->device, &buffer_attributes,
590 buffer_attributes = *pa_stream_get_buffer_attr(
s->stream);
591 s->buffer_size = buffer_attributes.tlength;
592 s->prebuf = buffer_attributes.prebuf;
593 s->minreq = buffer_attributes.minreq;
595 s->buffer_size,
s->prebuf,
s->minreq);
597 pa_threaded_mainloop_unlock(
s->mainloop);
602 pa_threaded_mainloop_lock(
s->mainloop);
608 s->last_volume = PA_VOLUME_INVALID;
609 pa_threaded_mainloop_lock(
s->mainloop);
614 pa_threaded_mainloop_unlock(
s->mainloop);
620 pa_threaded_mainloop_unlock(
s->mainloop);
629 int64_t writable_size;
646 pa_threaded_mainloop_lock(
s->mainloop);
647 if (!PA_STREAM_IS_GOOD(pa_stream_get_state(
s->stream))) {
651 while (pa_stream_writable_size(
s->stream) <
s->minreq) {
652 if (
s->nonblocking) {
653 pa_threaded_mainloop_unlock(
s->mainloop);
656 pa_threaded_mainloop_wait(
s->mainloop);
663 if ((writable_size = pa_stream_writable_size(
s->stream)) >=
s->minreq)
666 pa_threaded_mainloop_unlock(
s->mainloop);
670 pa_threaded_mainloop_unlock(
s->mainloop);
686 pkt.
dts = (*frame)->pkt_dts;
697 pa_threaded_mainloop_lock(
s->mainloop);
698 pa_stream_get_latency(
s->stream, &latency, &neg);
699 pa_threaded_mainloop_unlock(
s->mainloop);
703 *dts =
s->timestamp - (neg ? -latency : latency);
713 void *
data,
size_t data_size)
743 s->last_volume = PA_VOLUME_INVALID;
744 pa_threaded_mainloop_lock(
s->mainloop);
746 pa_threaded_mainloop_unlock(
s->mainloop);
750 pa_threaded_mainloop_lock(
s->mainloop);
752 pa_threaded_mainloop_unlock(
s->mainloop);
760 #define OFFSET(a) offsetof(PulseData, a)
761 #define E AV_OPT_FLAG_ENCODING_PARAM
767 {
"buffer_size",
"set buffer size in bytes",
OFFSET(buffer_size),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX,
E },
768 {
"buffer_duration",
"set buffer duration in millisecs",
OFFSET(buffer_duration),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX,
E },