2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 #include <pulse/def.h>
32 #include <pulse/timeval.h>
33 #include <pulse/xmalloc.h>
35 #include <pulsecore/pstream-util.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/hashmap.h>
38 #include <pulsecore/macro.h>
39 #include <pulsecore/rtclock.h>
41 #include "fork-detect.h"
44 #define LATENCY_IPOL_INTERVAL_USEC (333*PA_USEC_PER_MSEC)
46 #define SMOOTHER_ADJUST_TIME (1000*PA_USEC_PER_MSEC)
47 #define SMOOTHER_HISTORY_TIME (5000*PA_USEC_PER_MSEC)
48 #define SMOOTHER_MIN_HISTORY (4)
50 pa_stream
*pa_stream_new(pa_context
*c
, const char *name
, const pa_sample_spec
*ss
, const pa_channel_map
*map
) {
51 return pa_stream_new_with_proplist(c
, name
, ss
, map
, NULL
);
54 static void reset_callbacks(pa_stream
*s
) {
55 s
->read_callback
= NULL
;
56 s
->read_userdata
= NULL
;
57 s
->write_callback
= NULL
;
58 s
->write_userdata
= NULL
;
59 s
->state_callback
= NULL
;
60 s
->state_userdata
= NULL
;
61 s
->overflow_callback
= NULL
;
62 s
->overflow_userdata
= NULL
;
63 s
->underflow_callback
= NULL
;
64 s
->underflow_userdata
= NULL
;
65 s
->latency_update_callback
= NULL
;
66 s
->latency_update_userdata
= NULL
;
67 s
->moved_callback
= NULL
;
68 s
->moved_userdata
= NULL
;
69 s
->suspended_callback
= NULL
;
70 s
->suspended_userdata
= NULL
;
71 s
->started_callback
= NULL
;
72 s
->started_userdata
= NULL
;
73 s
->event_callback
= NULL
;
74 s
->event_userdata
= NULL
;
77 pa_stream
*pa_stream_new_with_proplist(
80 const pa_sample_spec
*ss
,
81 const pa_channel_map
*map
,
89 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
91 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
92 PA_CHECK_VALIDITY_RETURN_NULL(c
, ss
&& pa_sample_spec_valid(ss
), PA_ERR_INVALID
);
93 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 12 || (ss
->format
!= PA_SAMPLE_S32LE
&& ss
->format
!= PA_SAMPLE_S32BE
), PA_ERR_NOTSUPPORTED
);
94 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 15 || (ss
->format
!= PA_SAMPLE_S24LE
&& ss
->format
!= PA_SAMPLE_S24BE
), PA_ERR_NOTSUPPORTED
);
95 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 15 || (ss
->format
!= PA_SAMPLE_S24_32LE
&& ss
->format
!= PA_SAMPLE_S24_32BE
), PA_ERR_NOTSUPPORTED
);
96 PA_CHECK_VALIDITY_RETURN_NULL(c
, !map
|| (pa_channel_map_valid(map
) && map
->channels
== ss
->channels
), PA_ERR_INVALID
);
97 PA_CHECK_VALIDITY_RETURN_NULL(c
, name
|| (p
&& pa_proplist_contains(p
, PA_PROP_MEDIA_NAME
)), PA_ERR_INVALID
);
100 PA_CHECK_VALIDITY_RETURN_NULL(c
, map
= pa_channel_map_init_auto(&tmap
, ss
->channels
, PA_CHANNEL_MAP_DEFAULT
), PA_ERR_INVALID
);
102 s
= pa_xnew(pa_stream
, 1);
105 s
->mainloop
= c
->mainloop
;
107 s
->direction
= PA_STREAM_NODIRECTION
;
108 s
->state
= PA_STREAM_UNCONNECTED
;
111 s
->sample_spec
= *ss
;
112 s
->channel_map
= *map
;
114 s
->direct_on_input
= PA_INVALID_INDEX
;
116 s
->proplist
= p
? pa_proplist_copy(p
) : pa_proplist_new();
118 pa_proplist_sets(s
->proplist
, PA_PROP_MEDIA_NAME
, name
);
121 s
->channel_valid
= FALSE
;
122 s
->syncid
= c
->csyncid
++;
123 s
->stream_index
= PA_INVALID_INDEX
;
125 s
->requested_bytes
= 0;
126 memset(&s
->buffer_attr
, 0, sizeof(s
->buffer_attr
));
128 /* We initialize der target length here, so that if the user
129 * passes no explicit buffering metrics the default is similar to
130 * what older PA versions provided. */
132 s
->buffer_attr
.maxlength
= (uint32_t) -1;
133 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes(250*PA_USEC_PER_MSEC
, ss
); /* 250ms of buffering */
134 s
->buffer_attr
.minreq
= (uint32_t) -1;
135 s
->buffer_attr
.prebuf
= (uint32_t) -1;
136 s
->buffer_attr
.fragsize
= (uint32_t) -1;
138 s
->device_index
= PA_INVALID_INDEX
;
139 s
->device_name
= NULL
;
140 s
->suspended
= FALSE
;
143 pa_memchunk_reset(&s
->peek_memchunk
);
146 s
->record_memblockq
= NULL
;
149 memset(&s
->timing_info
, 0, sizeof(s
->timing_info
));
150 s
->timing_info_valid
= FALSE
;
152 s
->previous_time
= 0;
154 s
->read_index_not_before
= 0;
155 s
->write_index_not_before
= 0;
156 for (i
= 0; i
< PA_MAX_WRITE_INDEX_CORRECTIONS
; i
++)
157 s
->write_index_corrections
[i
].valid
= 0;
158 s
->current_write_index_correction
= 0;
160 s
->auto_timing_update_event
= NULL
;
161 s
->auto_timing_update_requested
= FALSE
;
167 /* Refcounting is strictly one-way: from the "bigger" to the "smaller" object. */
168 PA_LLIST_PREPEND(pa_stream
, c
->streams
, s
);
174 static void stream_unlink(pa_stream
*s
) {
181 /* Detach from context */
183 /* Unref all operatio object that point to us */
184 for (o
= s
->context
->operations
; o
; o
= n
) {
188 pa_operation_cancel(o
);
191 /* Drop all outstanding replies for this stream */
192 if (s
->context
->pdispatch
)
193 pa_pdispatch_unregister_reply(s
->context
->pdispatch
, s
);
195 if (s
->channel_valid
) {
196 pa_dynarray_put((s
->direction
== PA_STREAM_PLAYBACK
) ? s
->context
->playback_streams
: s
->context
->record_streams
, s
->channel
, NULL
);
198 s
->channel_valid
= FALSE
;
201 PA_LLIST_REMOVE(pa_stream
, s
->context
->streams
, s
);
206 if (s
->auto_timing_update_event
) {
207 pa_assert(s
->mainloop
);
208 s
->mainloop
->time_free(s
->auto_timing_update_event
);
214 static void stream_free(pa_stream
*s
) {
219 if (s
->peek_memchunk
.memblock
) {
221 pa_memblock_release(s
->peek_memchunk
.memblock
);
222 pa_memblock_unref(s
->peek_memchunk
.memblock
);
225 if (s
->record_memblockq
)
226 pa_memblockq_free(s
->record_memblockq
);
229 pa_proplist_free(s
->proplist
);
232 pa_smoother_free(s
->smoother
);
234 pa_xfree(s
->device_name
);
238 void pa_stream_unref(pa_stream
*s
) {
240 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
242 if (PA_REFCNT_DEC(s
) <= 0)
246 pa_stream
* pa_stream_ref(pa_stream
*s
) {
248 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
254 pa_stream_state_t
pa_stream_get_state(pa_stream
*s
) {
256 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
261 pa_context
* pa_stream_get_context(pa_stream
*s
) {
263 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
268 uint32_t pa_stream_get_index(pa_stream
*s
) {
270 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
272 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
, PA_INVALID_INDEX
);
273 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
275 return s
->stream_index
;
278 void pa_stream_set_state(pa_stream
*s
, pa_stream_state_t st
) {
280 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
289 if (s
->state_callback
)
290 s
->state_callback(s
, s
->state_userdata
);
292 if ((st
== PA_STREAM_FAILED
|| st
== PA_STREAM_TERMINATED
))
298 static void request_auto_timing_update(pa_stream
*s
, pa_bool_t force
) {
300 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
302 if (!(s
->flags
& PA_STREAM_AUTO_TIMING_UPDATE
))
305 if (s
->state
== PA_STREAM_READY
&&
306 (force
|| !s
->auto_timing_update_requested
)) {
309 /* pa_log("automatically requesting new timing data"); */
311 if ((o
= pa_stream_update_timing_info(s
, NULL
, NULL
))) {
312 pa_operation_unref(o
);
313 s
->auto_timing_update_requested
= TRUE
;
317 if (s
->auto_timing_update_event
) {
319 pa_gettimeofday(&next
);
320 pa_timeval_add(&next
, LATENCY_IPOL_INTERVAL_USEC
);
321 s
->mainloop
->time_restart(s
->auto_timing_update_event
, &next
);
325 void pa_command_stream_killed(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
326 pa_context
*c
= userdata
;
331 pa_assert(command
== PA_COMMAND_PLAYBACK_STREAM_KILLED
|| command
== PA_COMMAND_RECORD_STREAM_KILLED
);
334 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
338 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
339 !pa_tagstruct_eof(t
)) {
340 pa_context_fail(c
, PA_ERR_PROTOCOL
);
344 if (!(s
= pa_dynarray_get(command
== PA_COMMAND_PLAYBACK_STREAM_KILLED
? c
->playback_streams
: c
->record_streams
, channel
)))
347 if (s
->state
!= PA_STREAM_READY
)
350 pa_context_set_error(c
, PA_ERR_KILLED
);
351 pa_stream_set_state(s
, PA_STREAM_FAILED
);
357 static void check_smoother_status(pa_stream
*s
, pa_bool_t aposteriori
, pa_bool_t force_start
, pa_bool_t force_stop
) {
361 pa_assert(!force_start
|| !force_stop
);
366 x
= pa_rtclock_usec();
368 if (s
->timing_info_valid
) {
370 x
-= s
->timing_info
.transport_usec
;
372 x
+= s
->timing_info
.transport_usec
;
374 if (s
->direction
== PA_STREAM_PLAYBACK
)
375 /* it takes a while until the pause/resume is actually
377 x
+= s
->timing_info
.sink_usec
;
379 /* Data froma while back will be dropped */
380 x
-= s
->timing_info
.source_usec
;
383 if (s
->suspended
|| s
->corked
|| force_stop
)
384 pa_smoother_pause(s
->smoother
, x
);
385 else if (force_start
|| s
->buffer_attr
.prebuf
== 0)
386 pa_smoother_resume(s
->smoother
, x
);
388 /* Please note that we have no idea if playback actually started
389 * if prebuf is non-zero! */
392 void pa_command_stream_moved(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
393 pa_context
*c
= userdata
;
400 uint32_t maxlength
= 0, fragsize
= 0, minreq
= 0, tlength
= 0, prebuf
= 0;
403 pa_assert(command
== PA_COMMAND_PLAYBACK_STREAM_MOVED
|| command
== PA_COMMAND_RECORD_STREAM_MOVED
);
406 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
410 if (c
->version
< 12) {
411 pa_context_fail(c
, PA_ERR_PROTOCOL
);
415 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
416 pa_tagstruct_getu32(t
, &di
) < 0 ||
417 pa_tagstruct_gets(t
, &dn
) < 0 ||
418 pa_tagstruct_get_boolean(t
, &suspended
) < 0) {
419 pa_context_fail(c
, PA_ERR_PROTOCOL
);
423 if (c
->version
>= 13) {
425 if (command
== PA_COMMAND_RECORD_STREAM_MOVED
) {
426 if (pa_tagstruct_getu32(t
, &maxlength
) < 0 ||
427 pa_tagstruct_getu32(t
, &fragsize
) < 0 ||
428 pa_tagstruct_get_usec(t
, &usec
) < 0) {
429 pa_context_fail(c
, PA_ERR_PROTOCOL
);
433 if (pa_tagstruct_getu32(t
, &maxlength
) < 0 ||
434 pa_tagstruct_getu32(t
, &tlength
) < 0 ||
435 pa_tagstruct_getu32(t
, &prebuf
) < 0 ||
436 pa_tagstruct_getu32(t
, &minreq
) < 0 ||
437 pa_tagstruct_get_usec(t
, &usec
) < 0) {
438 pa_context_fail(c
, PA_ERR_PROTOCOL
);
444 if (!pa_tagstruct_eof(t
)) {
445 pa_context_fail(c
, PA_ERR_PROTOCOL
);
449 if (!dn
|| di
== PA_INVALID_INDEX
) {
450 pa_context_fail(c
, PA_ERR_PROTOCOL
);
454 if (!(s
= pa_dynarray_get(command
== PA_COMMAND_PLAYBACK_STREAM_MOVED
? c
->playback_streams
: c
->record_streams
, channel
)))
457 if (s
->state
!= PA_STREAM_READY
)
460 if (c
->version
>= 13) {
461 if (s
->direction
== PA_STREAM_RECORD
)
462 s
->timing_info
.configured_source_usec
= usec
;
464 s
->timing_info
.configured_sink_usec
= usec
;
466 s
->buffer_attr
.maxlength
= maxlength
;
467 s
->buffer_attr
.fragsize
= fragsize
;
468 s
->buffer_attr
.tlength
= tlength
;
469 s
->buffer_attr
.prebuf
= prebuf
;
470 s
->buffer_attr
.minreq
= minreq
;
473 pa_xfree(s
->device_name
);
474 s
->device_name
= pa_xstrdup(dn
);
475 s
->device_index
= di
;
477 s
->suspended
= suspended
;
479 check_smoother_status(s
, TRUE
, FALSE
, FALSE
);
480 request_auto_timing_update(s
, TRUE
);
482 if (s
->moved_callback
)
483 s
->moved_callback(s
, s
->moved_userdata
);
489 void pa_command_stream_suspended(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
490 pa_context
*c
= userdata
;
496 pa_assert(command
== PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
|| command
== PA_COMMAND_RECORD_STREAM_SUSPENDED
);
499 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
503 if (c
->version
< 12) {
504 pa_context_fail(c
, PA_ERR_PROTOCOL
);
508 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
509 pa_tagstruct_get_boolean(t
, &suspended
) < 0 ||
510 !pa_tagstruct_eof(t
)) {
511 pa_context_fail(c
, PA_ERR_PROTOCOL
);
515 if (!(s
= pa_dynarray_get(command
== PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
? c
->playback_streams
: c
->record_streams
, channel
)))
518 if (s
->state
!= PA_STREAM_READY
)
521 s
->suspended
= suspended
;
523 check_smoother_status(s
, TRUE
, FALSE
, FALSE
);
524 request_auto_timing_update(s
, TRUE
);
526 if (s
->suspended_callback
)
527 s
->suspended_callback(s
, s
->suspended_userdata
);
533 void pa_command_stream_started(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
534 pa_context
*c
= userdata
;
539 pa_assert(command
== PA_COMMAND_STARTED
);
542 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
546 if (c
->version
< 13) {
547 pa_context_fail(c
, PA_ERR_PROTOCOL
);
551 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
552 !pa_tagstruct_eof(t
)) {
553 pa_context_fail(c
, PA_ERR_PROTOCOL
);
557 if (!(s
= pa_dynarray_get(c
->playback_streams
, channel
)))
560 if (s
->state
!= PA_STREAM_READY
)
563 check_smoother_status(s
, TRUE
, TRUE
, FALSE
);
564 request_auto_timing_update(s
, TRUE
);
566 if (s
->started_callback
)
567 s
->started_callback(s
, s
->started_userdata
);
573 void pa_command_stream_event(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
574 pa_context
*c
= userdata
;
577 pa_proplist
*pl
= NULL
;
581 pa_assert(command
== PA_COMMAND_PLAYBACK_STREAM_EVENT
|| command
== PA_COMMAND_RECORD_STREAM_EVENT
);
584 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
588 if (c
->version
< 15) {
589 pa_context_fail(c
, PA_ERR_PROTOCOL
);
593 pl
= pa_proplist_new();
595 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
596 pa_tagstruct_gets(t
, &event
) < 0 ||
597 pa_tagstruct_get_proplist(t
, pl
) < 0 ||
598 !pa_tagstruct_eof(t
) || !event
) {
599 pa_context_fail(c
, PA_ERR_PROTOCOL
);
603 if (!(s
= pa_dynarray_get(command
== PA_COMMAND_PLAYBACK_STREAM_EVENT
? c
->playback_streams
: c
->record_streams
, channel
)))
606 if (s
->state
!= PA_STREAM_READY
)
609 if (s
->event_callback
)
610 s
->event_callback(s
, event
, pl
, s
->event_userdata
);
616 pa_proplist_free(pl
);
619 void pa_command_request(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
621 pa_context
*c
= userdata
;
622 uint32_t bytes
, channel
;
625 pa_assert(command
== PA_COMMAND_REQUEST
);
628 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
632 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
633 pa_tagstruct_getu32(t
, &bytes
) < 0 ||
634 !pa_tagstruct_eof(t
)) {
635 pa_context_fail(c
, PA_ERR_PROTOCOL
);
639 if (!(s
= pa_dynarray_get(c
->playback_streams
, channel
)))
642 if (s
->state
!= PA_STREAM_READY
)
645 s
->requested_bytes
+= bytes
;
647 if (s
->requested_bytes
> 0 && s
->write_callback
)
648 s
->write_callback(s
, s
->requested_bytes
, s
->write_userdata
);
654 void pa_command_overflow_or_underflow(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
656 pa_context
*c
= userdata
;
660 pa_assert(command
== PA_COMMAND_OVERFLOW
|| command
== PA_COMMAND_UNDERFLOW
);
663 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
667 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
668 !pa_tagstruct_eof(t
)) {
669 pa_context_fail(c
, PA_ERR_PROTOCOL
);
673 if (!(s
= pa_dynarray_get(c
->playback_streams
, channel
)))
676 if (s
->state
!= PA_STREAM_READY
)
679 if (s
->buffer_attr
.prebuf
> 0)
680 check_smoother_status(s
, TRUE
, FALSE
, TRUE
);
682 request_auto_timing_update(s
, TRUE
);
684 if (command
== PA_COMMAND_OVERFLOW
) {
685 if (s
->overflow_callback
)
686 s
->overflow_callback(s
, s
->overflow_userdata
);
687 } else if (command
== PA_COMMAND_UNDERFLOW
) {
688 if (s
->underflow_callback
)
689 s
->underflow_callback(s
, s
->underflow_userdata
);
696 static void invalidate_indexes(pa_stream
*s
, pa_bool_t r
, pa_bool_t w
) {
698 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
700 /* pa_log("invalidate r:%u w:%u tag:%u", r, w, s->context->ctag); */
702 if (s
->state
!= PA_STREAM_READY
)
706 s
->write_index_not_before
= s
->context
->ctag
;
708 if (s
->timing_info_valid
)
709 s
->timing_info
.write_index_corrupt
= TRUE
;
711 /* pa_log("write_index invalidated"); */
715 s
->read_index_not_before
= s
->context
->ctag
;
717 if (s
->timing_info_valid
)
718 s
->timing_info
.read_index_corrupt
= TRUE
;
720 /* pa_log("read_index invalidated"); */
723 request_auto_timing_update(s
, TRUE
);
726 static void auto_timing_update_callback(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*tv
, void *userdata
) {
727 pa_stream
*s
= userdata
;
730 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
733 request_auto_timing_update(s
, FALSE
);
737 static void create_stream_complete(pa_stream
*s
) {
739 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
740 pa_assert(s
->state
== PA_STREAM_CREATING
);
742 pa_stream_set_state(s
, PA_STREAM_READY
);
744 if (s
->requested_bytes
> 0 && s
->write_callback
)
745 s
->write_callback(s
, s
->requested_bytes
, s
->write_userdata
);
747 if (s
->flags
& PA_STREAM_AUTO_TIMING_UPDATE
) {
749 pa_gettimeofday(&tv
);
750 tv
.tv_usec
+= (suseconds_t
) LATENCY_IPOL_INTERVAL_USEC
; /* every 100 ms */
751 pa_assert(!s
->auto_timing_update_event
);
752 s
->auto_timing_update_event
= s
->mainloop
->time_new(s
->mainloop
, &tv
, &auto_timing_update_callback
, s
);
754 request_auto_timing_update(s
, TRUE
);
757 check_smoother_status(s
, TRUE
, FALSE
, FALSE
);
760 static void automatic_buffer_attr(pa_stream
*s
, pa_buffer_attr
*attr
, const pa_sample_spec
*ss
) {
765 if (s
->context
->version
>= 13)
768 /* Version older than 0.9.10 didn't do server side buffer_attr
769 * selection, hence we have to fake it on the client side. */
771 /* We choose fairly conservative values here, to not confuse
772 * old clients with extremely large playback buffers */
774 if (attr
->maxlength
== (uint32_t) -1)
775 attr
->maxlength
= 4*1024*1024; /* 4MB is the maximum queue length PulseAudio <= 0.9.9 supported. */
777 if (attr
->tlength
== (uint32_t) -1)
778 attr
->tlength
= (uint32_t) pa_usec_to_bytes(250*PA_USEC_PER_MSEC
, ss
); /* 250ms of buffering */
780 if (attr
->minreq
== (uint32_t) -1)
781 attr
->minreq
= (attr
->tlength
)/5; /* Ask for more data when there are only 200ms left in the playback buffer */
783 if (attr
->prebuf
== (uint32_t) -1)
784 attr
->prebuf
= attr
->tlength
; /* Start to play only when the playback is fully filled up once */
786 if (attr
->fragsize
== (uint32_t) -1)
787 attr
->fragsize
= attr
->tlength
; /* Pass data to the app only when the buffer is filled up once */
790 void pa_create_stream_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
791 pa_stream
*s
= userdata
;
795 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
796 pa_assert(s
->state
== PA_STREAM_CREATING
);
800 if (command
!= PA_COMMAND_REPLY
) {
801 if (pa_context_handle_error(s
->context
, command
, t
, FALSE
) < 0)
804 pa_stream_set_state(s
, PA_STREAM_FAILED
);
808 if (pa_tagstruct_getu32(t
, &s
->channel
) < 0 ||
809 s
->channel
== PA_INVALID_INDEX
||
810 ((s
->direction
!= PA_STREAM_UPLOAD
) && (pa_tagstruct_getu32(t
, &s
->stream_index
) < 0 || s
->stream_index
== PA_INVALID_INDEX
)) ||
811 ((s
->direction
!= PA_STREAM_RECORD
) && pa_tagstruct_getu32(t
, &s
->requested_bytes
) < 0)) {
812 pa_context_fail(s
->context
, PA_ERR_PROTOCOL
);
816 if (s
->context
->version
>= 9) {
817 if (s
->direction
== PA_STREAM_PLAYBACK
) {
818 if (pa_tagstruct_getu32(t
, &s
->buffer_attr
.maxlength
) < 0 ||
819 pa_tagstruct_getu32(t
, &s
->buffer_attr
.tlength
) < 0 ||
820 pa_tagstruct_getu32(t
, &s
->buffer_attr
.prebuf
) < 0 ||
821 pa_tagstruct_getu32(t
, &s
->buffer_attr
.minreq
) < 0) {
822 pa_context_fail(s
->context
, PA_ERR_PROTOCOL
);
825 } else if (s
->direction
== PA_STREAM_RECORD
) {
826 if (pa_tagstruct_getu32(t
, &s
->buffer_attr
.maxlength
) < 0 ||
827 pa_tagstruct_getu32(t
, &s
->buffer_attr
.fragsize
) < 0) {
828 pa_context_fail(s
->context
, PA_ERR_PROTOCOL
);
834 if (s
->context
->version
>= 12 && s
->direction
!= PA_STREAM_UPLOAD
) {
837 const char *dn
= NULL
;
840 if (pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
841 pa_tagstruct_get_channel_map(t
, &cm
) < 0 ||
842 pa_tagstruct_getu32(t
, &s
->device_index
) < 0 ||
843 pa_tagstruct_gets(t
, &dn
) < 0 ||
844 pa_tagstruct_get_boolean(t
, &suspended
) < 0) {
845 pa_context_fail(s
->context
, PA_ERR_PROTOCOL
);
849 if (!dn
|| s
->device_index
== PA_INVALID_INDEX
||
850 ss
.channels
!= cm
.channels
||
851 !pa_channel_map_valid(&cm
) ||
852 !pa_sample_spec_valid(&ss
) ||
853 (!(s
->flags
& PA_STREAM_FIX_FORMAT
) && ss
.format
!= s
->sample_spec
.format
) ||
854 (!(s
->flags
& PA_STREAM_FIX_RATE
) && ss
.rate
!= s
->sample_spec
.rate
) ||
855 (!(s
->flags
& PA_STREAM_FIX_CHANNELS
) && !pa_channel_map_equal(&cm
, &s
->channel_map
))) {
856 pa_context_fail(s
->context
, PA_ERR_PROTOCOL
);
860 pa_xfree(s
->device_name
);
861 s
->device_name
= pa_xstrdup(dn
);
862 s
->suspended
= suspended
;
868 if (s
->context
->version
>= 13 && s
->direction
!= PA_STREAM_UPLOAD
) {
871 if (pa_tagstruct_get_usec(t
, &usec
) < 0) {
872 pa_context_fail(s
->context
, PA_ERR_PROTOCOL
);
876 if (s
->direction
== PA_STREAM_RECORD
)
877 s
->timing_info
.configured_source_usec
= usec
;
879 s
->timing_info
.configured_sink_usec
= usec
;
882 if (!pa_tagstruct_eof(t
)) {
883 pa_context_fail(s
->context
, PA_ERR_PROTOCOL
);
887 if (s
->direction
== PA_STREAM_RECORD
) {
888 pa_assert(!s
->record_memblockq
);
890 s
->record_memblockq
= pa_memblockq_new(
892 s
->buffer_attr
.maxlength
,
894 pa_frame_size(&s
->sample_spec
),
901 s
->channel_valid
= TRUE
;
902 pa_dynarray_put((s
->direction
== PA_STREAM_RECORD
) ? s
->context
->record_streams
: s
->context
->playback_streams
, s
->channel
, s
);
904 create_stream_complete(s
);
910 static int create_stream(
911 pa_stream_direction_t direction
,
914 const pa_buffer_attr
*attr
,
915 pa_stream_flags_t flags
,
916 const pa_cvolume
*volume
,
917 pa_stream
*sync_stream
) {
921 pa_bool_t volume_set
= FALSE
;
924 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
925 pa_assert(direction
== PA_STREAM_PLAYBACK
|| direction
== PA_STREAM_RECORD
);
927 PA_CHECK_VALIDITY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
928 PA_CHECK_VALIDITY(s
->context
, s
->state
== PA_STREAM_UNCONNECTED
, PA_ERR_BADSTATE
);
929 PA_CHECK_VALIDITY(s
->context
, s
->direct_on_input
== PA_INVALID_INDEX
|| direction
== PA_STREAM_RECORD
, PA_ERR_BADSTATE
);
930 PA_CHECK_VALIDITY(s
->context
, !(flags
& ~(PA_STREAM_START_CORKED
|
931 PA_STREAM_INTERPOLATE_TIMING
|
932 PA_STREAM_NOT_MONOTONIC
|
933 PA_STREAM_AUTO_TIMING_UPDATE
|
934 PA_STREAM_NO_REMAP_CHANNELS
|
935 PA_STREAM_NO_REMIX_CHANNELS
|
936 PA_STREAM_FIX_FORMAT
|
938 PA_STREAM_FIX_CHANNELS
|
940 PA_STREAM_VARIABLE_RATE
|
941 PA_STREAM_PEAK_DETECT
|
942 PA_STREAM_START_MUTED
|
943 PA_STREAM_ADJUST_LATENCY
|
944 PA_STREAM_EARLY_REQUESTS
|
945 PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
|
946 PA_STREAM_START_UNMUTED
|
947 PA_STREAM_FAIL_ON_SUSPEND
)), PA_ERR_INVALID
);
949 PA_CHECK_VALIDITY(s
->context
, s
->context
->version
>= 12 || !(flags
& PA_STREAM_VARIABLE_RATE
), PA_ERR_NOTSUPPORTED
);
950 PA_CHECK_VALIDITY(s
->context
, s
->context
->version
>= 13 || !(flags
& PA_STREAM_PEAK_DETECT
), PA_ERR_NOTSUPPORTED
);
951 PA_CHECK_VALIDITY(s
->context
, s
->context
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
952 /* Althought some of the other flags are not supported on older
953 * version, we don't check for them here, because it doesn't hurt
954 * when they are passed but actually not supported. This makes
955 * client development easier */
957 PA_CHECK_VALIDITY(s
->context
, direction
== PA_STREAM_PLAYBACK
|| !(flags
& (PA_STREAM_START_MUTED
)), PA_ERR_INVALID
);
958 PA_CHECK_VALIDITY(s
->context
, direction
== PA_STREAM_RECORD
|| !(flags
& (PA_STREAM_PEAK_DETECT
)), PA_ERR_INVALID
);
959 PA_CHECK_VALIDITY(s
->context
, !volume
|| volume
->channels
== s
->sample_spec
.channels
, PA_ERR_INVALID
);
960 PA_CHECK_VALIDITY(s
->context
, !sync_stream
|| (direction
== PA_STREAM_PLAYBACK
&& sync_stream
->direction
== PA_STREAM_PLAYBACK
), PA_ERR_INVALID
);
961 PA_CHECK_VALIDITY(s
->context
, (flags
& (PA_STREAM_ADJUST_LATENCY
|PA_STREAM_EARLY_REQUESTS
)) != (PA_STREAM_ADJUST_LATENCY
|PA_STREAM_EARLY_REQUESTS
), PA_ERR_INVALID
);
965 s
->direction
= direction
;
967 s
->corked
= !!(flags
& PA_STREAM_START_CORKED
);
970 s
->syncid
= sync_stream
->syncid
;
973 s
->buffer_attr
= *attr
;
974 automatic_buffer_attr(s
, &s
->buffer_attr
, &s
->sample_spec
);
976 if (flags
& PA_STREAM_INTERPOLATE_TIMING
) {
980 pa_smoother_free(s
->smoother
);
982 s
->smoother
= pa_smoother_new(SMOOTHER_ADJUST_TIME
, SMOOTHER_HISTORY_TIME
, !(flags
& PA_STREAM_NOT_MONOTONIC
), SMOOTHER_MIN_HISTORY
);
984 x
= pa_rtclock_usec();
985 pa_smoother_set_time_offset(s
->smoother
, x
);
986 pa_smoother_pause(s
->smoother
, x
);
990 dev
= s
->direction
== PA_STREAM_PLAYBACK
? s
->context
->conf
->default_sink
: s
->context
->conf
->default_source
;
992 t
= pa_tagstruct_command(
994 (uint32_t) (s
->direction
== PA_STREAM_PLAYBACK
? PA_COMMAND_CREATE_PLAYBACK_STREAM
: PA_COMMAND_CREATE_RECORD_STREAM
),
997 if (s
->context
->version
< 13)
998 pa_tagstruct_puts(t
, pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
));
1002 PA_TAG_SAMPLE_SPEC
, &s
->sample_spec
,
1003 PA_TAG_CHANNEL_MAP
, &s
->channel_map
,
1004 PA_TAG_U32
, PA_INVALID_INDEX
,
1006 PA_TAG_U32
, s
->buffer_attr
.maxlength
,
1007 PA_TAG_BOOLEAN
, s
->corked
,
1010 if (s
->direction
== PA_STREAM_PLAYBACK
) {
1015 PA_TAG_U32
, s
->buffer_attr
.tlength
,
1016 PA_TAG_U32
, s
->buffer_attr
.prebuf
,
1017 PA_TAG_U32
, s
->buffer_attr
.minreq
,
1018 PA_TAG_U32
, s
->syncid
,
1021 volume_set
= !!volume
;
1024 volume
= pa_cvolume_reset(&cv
, s
->sample_spec
.channels
);
1026 pa_tagstruct_put_cvolume(t
, volume
);
1028 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
1030 if (s
->context
->version
>= 12) {
1033 PA_TAG_BOOLEAN
, flags
& PA_STREAM_NO_REMAP_CHANNELS
,
1034 PA_TAG_BOOLEAN
, flags
& PA_STREAM_NO_REMIX_CHANNELS
,
1035 PA_TAG_BOOLEAN
, flags
& PA_STREAM_FIX_FORMAT
,
1036 PA_TAG_BOOLEAN
, flags
& PA_STREAM_FIX_RATE
,
1037 PA_TAG_BOOLEAN
, flags
& PA_STREAM_FIX_CHANNELS
,
1038 PA_TAG_BOOLEAN
, flags
& PA_STREAM_DONT_MOVE
,
1039 PA_TAG_BOOLEAN
, flags
& PA_STREAM_VARIABLE_RATE
,
1043 if (s
->context
->version
>= 13) {
1045 if (s
->direction
== PA_STREAM_PLAYBACK
)
1046 pa_tagstruct_put_boolean(t
, flags
& PA_STREAM_START_MUTED
);
1048 pa_tagstruct_put_boolean(t
, flags
& PA_STREAM_PEAK_DETECT
);
1052 PA_TAG_BOOLEAN
, flags
& PA_STREAM_ADJUST_LATENCY
,
1053 PA_TAG_PROPLIST
, s
->proplist
,
1056 if (s
->direction
== PA_STREAM_RECORD
)
1057 pa_tagstruct_putu32(t
, s
->direct_on_input
);
1060 if (s
->context
->version
>= 14) {
1062 if (s
->direction
== PA_STREAM_PLAYBACK
)
1063 pa_tagstruct_put_boolean(t
, volume_set
);
1065 pa_tagstruct_put_boolean(t
, flags
& PA_STREAM_EARLY_REQUESTS
);
1068 if (s
->context
->version
>= 15) {
1070 if (s
->direction
== PA_STREAM_PLAYBACK
)
1071 pa_tagstruct_put_boolean(t
, flags
& (PA_STREAM_START_MUTED
|PA_STREAM_START_UNMUTED
));
1073 pa_tagstruct_put_boolean(t
, flags
& PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
);
1074 pa_tagstruct_put_boolean(t
, flags
& PA_STREAM_FAIL_ON_SUSPEND
);
1077 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
1078 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_create_stream_callback
, s
, NULL
);
1080 pa_stream_set_state(s
, PA_STREAM_CREATING
);
1086 int pa_stream_connect_playback(
1089 const pa_buffer_attr
*attr
,
1090 pa_stream_flags_t flags
,
1092 pa_stream
*sync_stream
) {
1095 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1097 return create_stream(PA_STREAM_PLAYBACK
, s
, dev
, attr
, flags
, volume
, sync_stream
);
1100 int pa_stream_connect_record(
1103 const pa_buffer_attr
*attr
,
1104 pa_stream_flags_t flags
) {
1107 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1109 return create_stream(PA_STREAM_RECORD
, s
, dev
, attr
, flags
, NULL
, NULL
);
1112 int pa_stream_write(
1116 void (*free_cb
)(void *p
),
1118 pa_seek_mode_t seek
) {
1121 pa_seek_mode_t t_seek
;
1127 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1130 PA_CHECK_VALIDITY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1131 PA_CHECK_VALIDITY(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
1132 PA_CHECK_VALIDITY(s
->context
, s
->direction
== PA_STREAM_PLAYBACK
|| s
->direction
== PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
1133 PA_CHECK_VALIDITY(s
->context
, seek
<= PA_SEEK_RELATIVE_END
, PA_ERR_INVALID
);
1134 PA_CHECK_VALIDITY(s
->context
, s
->direction
== PA_STREAM_PLAYBACK
|| (seek
== PA_SEEK_RELATIVE
&& offset
== 0), PA_ERR_INVALID
);
1144 while (t_length
> 0) {
1148 if (free_cb
&& !pa_pstream_get_shm(s
->context
->pstream
)) {
1149 chunk
.memblock
= pa_memblock_new_user(s
->context
->mempool
, (void*) t_data
, t_length
, free_cb
, 1);
1150 chunk
.length
= t_length
;
1154 chunk
.length
= PA_MIN(t_length
, pa_mempool_block_size_max(s
->context
->mempool
));
1155 chunk
.memblock
= pa_memblock_new(s
->context
->mempool
, chunk
.length
);
1157 d
= pa_memblock_acquire(chunk
.memblock
);
1158 memcpy(d
, t_data
, chunk
.length
);
1159 pa_memblock_release(chunk
.memblock
);
1162 pa_pstream_send_memblock(s
->context
->pstream
, s
->channel
, t_offset
, t_seek
, &chunk
);
1165 t_seek
= PA_SEEK_RELATIVE
;
1167 t_data
= (const uint8_t*) t_data
+ chunk
.length
;
1168 t_length
-= chunk
.length
;
1170 pa_memblock_unref(chunk
.memblock
);
1173 if (free_cb
&& pa_pstream_get_shm(s
->context
->pstream
))
1174 free_cb((void*) data
);
1176 if (length
< s
->requested_bytes
)
1177 s
->requested_bytes
-= (uint32_t) length
;
1179 s
->requested_bytes
= 0;
1181 /* FIXME!!! ^^^ will break when offset is != 0 and mode is not RELATIVE*/
1183 if (s
->direction
== PA_STREAM_PLAYBACK
) {
1185 /* Update latency request correction */
1186 if (s
->write_index_corrections
[s
->current_write_index_correction
].valid
) {
1188 if (seek
== PA_SEEK_ABSOLUTE
) {
1189 s
->write_index_corrections
[s
->current_write_index_correction
].corrupt
= FALSE
;
1190 s
->write_index_corrections
[s
->current_write_index_correction
].absolute
= TRUE
;
1191 s
->write_index_corrections
[s
->current_write_index_correction
].value
= offset
+ (int64_t) length
;
1192 } else if (seek
== PA_SEEK_RELATIVE
) {
1193 if (!s
->write_index_corrections
[s
->current_write_index_correction
].corrupt
)
1194 s
->write_index_corrections
[s
->current_write_index_correction
].value
+= offset
+ (int64_t) length
;
1196 s
->write_index_corrections
[s
->current_write_index_correction
].corrupt
= TRUE
;
1199 /* Update the write index in the already available latency data */
1200 if (s
->timing_info_valid
) {
1202 if (seek
== PA_SEEK_ABSOLUTE
) {
1203 s
->timing_info
.write_index_corrupt
= FALSE
;
1204 s
->timing_info
.write_index
= offset
+ (int64_t) length
;
1205 } else if (seek
== PA_SEEK_RELATIVE
) {
1206 if (!s
->timing_info
.write_index_corrupt
)
1207 s
->timing_info
.write_index
+= offset
+ (int64_t) length
;
1209 s
->timing_info
.write_index_corrupt
= TRUE
;
1212 if (!s
->timing_info_valid
|| s
->timing_info
.write_index_corrupt
)
1213 request_auto_timing_update(s
, TRUE
);
1219 int pa_stream_peek(pa_stream
*s
, const void **data
, size_t *length
) {
1221 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1225 PA_CHECK_VALIDITY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1226 PA_CHECK_VALIDITY(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
1227 PA_CHECK_VALIDITY(s
->context
, s
->direction
== PA_STREAM_RECORD
, PA_ERR_BADSTATE
);
1229 if (!s
->peek_memchunk
.memblock
) {
1231 if (pa_memblockq_peek(s
->record_memblockq
, &s
->peek_memchunk
) < 0) {
1237 s
->peek_data
= pa_memblock_acquire(s
->peek_memchunk
.memblock
);
1240 pa_assert(s
->peek_data
);
1241 *data
= (uint8_t*) s
->peek_data
+ s
->peek_memchunk
.index
;
1242 *length
= s
->peek_memchunk
.length
;
1246 int pa_stream_drop(pa_stream
*s
) {
1248 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1250 PA_CHECK_VALIDITY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1251 PA_CHECK_VALIDITY(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
1252 PA_CHECK_VALIDITY(s
->context
, s
->direction
== PA_STREAM_RECORD
, PA_ERR_BADSTATE
);
1253 PA_CHECK_VALIDITY(s
->context
, s
->peek_memchunk
.memblock
, PA_ERR_BADSTATE
);
1255 pa_memblockq_drop(s
->record_memblockq
, s
->peek_memchunk
.length
);
1257 /* Fix the simulated local read index */
1258 if (s
->timing_info_valid
&& !s
->timing_info
.read_index_corrupt
)
1259 s
->timing_info
.read_index
+= (int64_t) s
->peek_memchunk
.length
;
1261 pa_assert(s
->peek_data
);
1262 pa_memblock_release(s
->peek_memchunk
.memblock
);
1263 pa_memblock_unref(s
->peek_memchunk
.memblock
);
1264 pa_memchunk_reset(&s
->peek_memchunk
);
1269 size_t pa_stream_writable_size(pa_stream
*s
) {
1271 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1273 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
, (size_t) -1);
1274 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
, (size_t) -1);
1275 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, s
->direction
!= PA_STREAM_RECORD
, PA_ERR_BADSTATE
, (size_t) -1);
1277 return s
->requested_bytes
;
1280 size_t pa_stream_readable_size(pa_stream
*s
) {
1282 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1284 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
, (size_t) -1);
1285 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
, (size_t) -1);
1286 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, s
->direction
== PA_STREAM_RECORD
, PA_ERR_BADSTATE
, (size_t) -1);
1288 return pa_memblockq_get_length(s
->record_memblockq
);
1291 pa_operation
* pa_stream_drain(pa_stream
*s
, pa_stream_success_cb_t cb
, void *userdata
) {
1297 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1299 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1300 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
1301 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
== PA_STREAM_PLAYBACK
, PA_ERR_BADSTATE
);
1303 o
= pa_operation_new(s
->context
, s
, (pa_operation_cb_t
) cb
, userdata
);
1305 t
= pa_tagstruct_command(s
->context
, PA_COMMAND_DRAIN_PLAYBACK_STREAM
, &tag
);
1306 pa_tagstruct_putu32(t
, s
->channel
);
1307 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
1308 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_stream_simple_ack_callback
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
1313 static pa_usec_t
calc_time(pa_stream
*s
, pa_bool_t ignore_transport
) {
1317 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1318 pa_assert(s
->state
== PA_STREAM_READY
);
1319 pa_assert(s
->direction
!= PA_STREAM_UPLOAD
);
1320 pa_assert(s
->timing_info_valid
);
1321 pa_assert(s
->direction
!= PA_STREAM_PLAYBACK
|| !s
->timing_info
.read_index_corrupt
);
1322 pa_assert(s
->direction
!= PA_STREAM_RECORD
|| !s
->timing_info
.write_index_corrupt
);
1324 if (s
->direction
== PA_STREAM_PLAYBACK
) {
1325 /* The last byte that was written into the output device
1326 * had this time value associated */
1327 usec
= pa_bytes_to_usec(s
->timing_info
.read_index
< 0 ? 0 : (uint64_t) s
->timing_info
.read_index
, &s
->sample_spec
);
1329 if (!s
->corked
&& !s
->suspended
) {
1331 if (!ignore_transport
)
1332 /* Because the latency info took a little time to come
1333 * to us, we assume that the real output time is actually
1335 usec
+= s
->timing_info
.transport_usec
;
1337 /* However, the output device usually maintains a buffer
1338 too, hence the real sample currently played is a little
1340 if (s
->timing_info
.sink_usec
>= usec
)
1343 usec
-= s
->timing_info
.sink_usec
;
1347 pa_assert(s
->direction
== PA_STREAM_RECORD
);
1349 /* The last byte written into the server side queue had
1350 * this time value associated */
1351 usec
= pa_bytes_to_usec(s
->timing_info
.write_index
< 0 ? 0 : (uint64_t) s
->timing_info
.write_index
, &s
->sample_spec
);
1353 if (!s
->corked
&& !s
->suspended
) {
1355 if (!ignore_transport
)
1356 /* Add transport latency */
1357 usec
+= s
->timing_info
.transport_usec
;
1359 /* Add latency of data in device buffer */
1360 usec
+= s
->timing_info
.source_usec
;
1362 /* If this is a monitor source, we need to correct the
1363 * time by the playback device buffer */
1364 if (s
->timing_info
.sink_usec
>= usec
)
1367 usec
-= s
->timing_info
.sink_usec
;
1374 static void stream_get_timing_info_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1375 pa_operation
*o
= userdata
;
1376 struct timeval local
, remote
, now
;
1378 pa_bool_t playing
= FALSE
;
1379 uint64_t underrun_for
= 0, playing_for
= 0;
1383 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1385 if (!o
->context
|| !o
->stream
)
1388 i
= &o
->stream
->timing_info
;
1390 o
->stream
->timing_info_valid
= FALSE
;
1391 i
->write_index_corrupt
= TRUE
;
1392 i
->read_index_corrupt
= TRUE
;
1394 if (command
!= PA_COMMAND_REPLY
) {
1395 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
1400 if (pa_tagstruct_get_usec(t
, &i
->sink_usec
) < 0 ||
1401 pa_tagstruct_get_usec(t
, &i
->source_usec
) < 0 ||
1402 pa_tagstruct_get_boolean(t
, &playing
) < 0 ||
1403 pa_tagstruct_get_timeval(t
, &local
) < 0 ||
1404 pa_tagstruct_get_timeval(t
, &remote
) < 0 ||
1405 pa_tagstruct_gets64(t
, &i
->write_index
) < 0 ||
1406 pa_tagstruct_gets64(t
, &i
->read_index
) < 0) {
1408 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
1412 if (o
->context
->version
>= 13 &&
1413 o
->stream
->direction
== PA_STREAM_PLAYBACK
)
1414 if (pa_tagstruct_getu64(t
, &underrun_for
) < 0 ||
1415 pa_tagstruct_getu64(t
, &playing_for
) < 0) {
1417 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
1422 if (!pa_tagstruct_eof(t
)) {
1423 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
1426 o
->stream
->timing_info_valid
= TRUE
;
1427 i
->write_index_corrupt
= FALSE
;
1428 i
->read_index_corrupt
= FALSE
;
1430 i
->playing
= (int) playing
;
1431 i
->since_underrun
= (int64_t) (playing
? playing_for
: underrun_for
);
1433 pa_gettimeofday(&now
);
1435 /* Calculcate timestamps */
1436 if (pa_timeval_cmp(&local
, &remote
) <= 0 && pa_timeval_cmp(&remote
, &now
) <= 0) {
1437 /* local and remote seem to have synchronized clocks */
1439 if (o
->stream
->direction
== PA_STREAM_PLAYBACK
)
1440 i
->transport_usec
= pa_timeval_diff(&remote
, &local
);
1442 i
->transport_usec
= pa_timeval_diff(&now
, &remote
);
1444 i
->synchronized_clocks
= TRUE
;
1445 i
->timestamp
= remote
;
1447 /* clocks are not synchronized, let's estimate latency then */
1448 i
->transport_usec
= pa_timeval_diff(&now
, &local
)/2;
1449 i
->synchronized_clocks
= FALSE
;
1450 i
->timestamp
= local
;
1451 pa_timeval_add(&i
->timestamp
, i
->transport_usec
);
1454 /* Invalidate read and write indexes if necessary */
1455 if (tag
< o
->stream
->read_index_not_before
)
1456 i
->read_index_corrupt
= TRUE
;
1458 if (tag
< o
->stream
->write_index_not_before
)
1459 i
->write_index_corrupt
= TRUE
;
1461 if (o
->stream
->direction
== PA_STREAM_PLAYBACK
) {
1462 /* Write index correction */
1465 uint32_t ctag
= tag
;
1467 /* Go through the saved correction values and add up the
1468 * total correction.*/
1469 for (n
= 0, j
= o
->stream
->current_write_index_correction
+1;
1470 n
< PA_MAX_WRITE_INDEX_CORRECTIONS
;
1471 n
++, j
= (j
+ 1) % PA_MAX_WRITE_INDEX_CORRECTIONS
) {
1473 /* Step over invalid data or out-of-date data */
1474 if (!o
->stream
->write_index_corrections
[j
].valid
||
1475 o
->stream
->write_index_corrections
[j
].tag
< ctag
)
1478 /* Make sure that everything is in order */
1479 ctag
= o
->stream
->write_index_corrections
[j
].tag
+1;
1481 /* Now fix the write index */
1482 if (o
->stream
->write_index_corrections
[j
].corrupt
) {
1483 /* A corrupting seek was made */
1484 i
->write_index_corrupt
= TRUE
;
1485 } else if (o
->stream
->write_index_corrections
[j
].absolute
) {
1486 /* An absolute seek was made */
1487 i
->write_index
= o
->stream
->write_index_corrections
[j
].value
;
1488 i
->write_index_corrupt
= FALSE
;
1489 } else if (!i
->write_index_corrupt
) {
1490 /* A relative seek was made */
1491 i
->write_index
+= o
->stream
->write_index_corrections
[j
].value
;
1495 /* Clear old correction entries */
1496 for (n
= 0; n
< PA_MAX_WRITE_INDEX_CORRECTIONS
; n
++) {
1497 if (!o
->stream
->write_index_corrections
[n
].valid
)
1500 if (o
->stream
->write_index_corrections
[n
].tag
<= tag
)
1501 o
->stream
->write_index_corrections
[n
].valid
= FALSE
;
1505 if (o
->stream
->direction
== PA_STREAM_RECORD
) {
1506 /* Read index correction */
1508 if (!i
->read_index_corrupt
)
1509 i
->read_index
-= (int64_t) pa_memblockq_get_length(o
->stream
->record_memblockq
);
1512 /* Update smoother */
1513 if (o
->stream
->smoother
) {
1516 u
= x
= pa_rtclock_usec() - i
->transport_usec
;
1518 if (o
->stream
->direction
== PA_STREAM_PLAYBACK
&& o
->context
->version
>= 13) {
1521 /* If we weren't playing then it will take some time
1522 * until the audio will actually come out through the
1523 * speakers. Since we follow that timing here, we need
1524 * to try to fix this up */
1526 su
= pa_bytes_to_usec((uint64_t) i
->since_underrun
, &o
->stream
->sample_spec
);
1528 if (su
< i
->sink_usec
)
1529 x
+= i
->sink_usec
- su
;
1533 pa_smoother_pause(o
->stream
->smoother
, x
);
1535 /* Update the smoother */
1536 if ((o
->stream
->direction
== PA_STREAM_PLAYBACK
&& !i
->read_index_corrupt
) ||
1537 (o
->stream
->direction
== PA_STREAM_RECORD
&& !i
->write_index_corrupt
))
1538 pa_smoother_put(o
->stream
->smoother
, u
, calc_time(o
->stream
, TRUE
));
1541 pa_smoother_resume(o
->stream
->smoother
, x
);
1545 o
->stream
->auto_timing_update_requested
= FALSE
;
1547 if (o
->stream
->latency_update_callback
)
1548 o
->stream
->latency_update_callback(o
->stream
, o
->stream
->latency_update_userdata
);
1550 if (o
->callback
&& o
->stream
&& o
->stream
->state
== PA_STREAM_READY
) {
1551 pa_stream_success_cb_t cb
= (pa_stream_success_cb_t
) o
->callback
;
1552 cb(o
->stream
, o
->stream
->timing_info_valid
, o
->userdata
);
1557 pa_operation_done(o
);
1558 pa_operation_unref(o
);
1561 pa_operation
* pa_stream_update_timing_info(pa_stream
*s
, pa_stream_success_cb_t cb
, void *userdata
) {
1569 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1571 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1572 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
1573 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
1575 if (s
->direction
== PA_STREAM_PLAYBACK
) {
1576 /* Find a place to store the write_index correction data for this entry */
1577 cidx
= (s
->current_write_index_correction
+ 1) % PA_MAX_WRITE_INDEX_CORRECTIONS
;
1579 /* Check if we could allocate a correction slot. If not, there are too many outstanding queries */
1580 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !s
->write_index_corrections
[cidx
].valid
, PA_ERR_INTERNAL
);
1582 o
= pa_operation_new(s
->context
, s
, (pa_operation_cb_t
) cb
, userdata
);
1584 t
= pa_tagstruct_command(
1586 (uint32_t) (s
->direction
== PA_STREAM_PLAYBACK
? PA_COMMAND_GET_PLAYBACK_LATENCY
: PA_COMMAND_GET_RECORD_LATENCY
),
1588 pa_tagstruct_putu32(t
, s
->channel
);
1589 pa_tagstruct_put_timeval(t
, pa_gettimeofday(&now
));
1591 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
1592 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_get_timing_info_callback
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
1594 if (s
->direction
== PA_STREAM_PLAYBACK
) {
1595 /* Fill in initial correction data */
1597 s
->current_write_index_correction
= cidx
;
1599 s
->write_index_corrections
[cidx
].valid
= TRUE
;
1600 s
->write_index_corrections
[cidx
].absolute
= FALSE
;
1601 s
->write_index_corrections
[cidx
].corrupt
= FALSE
;
1602 s
->write_index_corrections
[cidx
].tag
= tag
;
1603 s
->write_index_corrections
[cidx
].value
= 0;
1609 void pa_stream_disconnect_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1610 pa_stream
*s
= userdata
;
1614 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1618 if (command
!= PA_COMMAND_REPLY
) {
1619 if (pa_context_handle_error(s
->context
, command
, t
, FALSE
) < 0)
1622 pa_stream_set_state(s
, PA_STREAM_FAILED
);
1624 } else if (!pa_tagstruct_eof(t
)) {
1625 pa_context_fail(s
->context
, PA_ERR_PROTOCOL
);
1629 pa_stream_set_state(s
, PA_STREAM_TERMINATED
);
1635 int pa_stream_disconnect(pa_stream
*s
) {
1640 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1642 PA_CHECK_VALIDITY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1643 PA_CHECK_VALIDITY(s
->context
, s
->channel_valid
, PA_ERR_BADSTATE
);
1644 PA_CHECK_VALIDITY(s
->context
, s
->context
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1648 t
= pa_tagstruct_command(
1650 (uint32_t) (s
->direction
== PA_STREAM_PLAYBACK
? PA_COMMAND_DELETE_PLAYBACK_STREAM
:
1651 (s
->direction
== PA_STREAM_RECORD
? PA_COMMAND_DELETE_RECORD_STREAM
: PA_COMMAND_DELETE_UPLOAD_STREAM
)),
1653 pa_tagstruct_putu32(t
, s
->channel
);
1654 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
1655 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_stream_disconnect_callback
, s
, NULL
);
1661 void pa_stream_set_read_callback(pa_stream
*s
, pa_stream_request_cb_t cb
, void *userdata
) {
1663 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1665 if (pa_detect_fork())
1668 if (s
->state
== PA_STREAM_TERMINATED
|| s
->state
== PA_STREAM_FAILED
)
1671 s
->read_callback
= cb
;
1672 s
->read_userdata
= userdata
;
1675 void pa_stream_set_write_callback(pa_stream
*s
, pa_stream_request_cb_t cb
, void *userdata
) {
1677 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1679 if (pa_detect_fork())
1682 if (s
->state
== PA_STREAM_TERMINATED
|| s
->state
== PA_STREAM_FAILED
)
1685 s
->write_callback
= cb
;
1686 s
->write_userdata
= userdata
;
1689 void pa_stream_set_state_callback(pa_stream
*s
, pa_stream_notify_cb_t cb
, void *userdata
) {
1691 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1693 if (pa_detect_fork())
1696 if (s
->state
== PA_STREAM_TERMINATED
|| s
->state
== PA_STREAM_FAILED
)
1699 s
->state_callback
= cb
;
1700 s
->state_userdata
= userdata
;
1703 void pa_stream_set_overflow_callback(pa_stream
*s
, pa_stream_notify_cb_t cb
, void *userdata
) {
1705 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1707 if (pa_detect_fork())
1710 if (s
->state
== PA_STREAM_TERMINATED
|| s
->state
== PA_STREAM_FAILED
)
1713 s
->overflow_callback
= cb
;
1714 s
->overflow_userdata
= userdata
;
1717 void pa_stream_set_underflow_callback(pa_stream
*s
, pa_stream_notify_cb_t cb
, void *userdata
) {
1719 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1721 if (pa_detect_fork())
1724 if (s
->state
== PA_STREAM_TERMINATED
|| s
->state
== PA_STREAM_FAILED
)
1727 s
->underflow_callback
= cb
;
1728 s
->underflow_userdata
= userdata
;
1731 void pa_stream_set_latency_update_callback(pa_stream
*s
, pa_stream_notify_cb_t cb
, void *userdata
) {
1733 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1735 if (pa_detect_fork())
1738 if (s
->state
== PA_STREAM_TERMINATED
|| s
->state
== PA_STREAM_FAILED
)
1741 s
->latency_update_callback
= cb
;
1742 s
->latency_update_userdata
= userdata
;
1745 void pa_stream_set_moved_callback(pa_stream
*s
, pa_stream_notify_cb_t cb
, void *userdata
) {
1747 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1749 if (pa_detect_fork())
1752 if (s
->state
== PA_STREAM_TERMINATED
|| s
->state
== PA_STREAM_FAILED
)
1755 s
->moved_callback
= cb
;
1756 s
->moved_userdata
= userdata
;
1759 void pa_stream_set_suspended_callback(pa_stream
*s
, pa_stream_notify_cb_t cb
, void *userdata
) {
1761 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1763 if (pa_detect_fork())
1766 if (s
->state
== PA_STREAM_TERMINATED
|| s
->state
== PA_STREAM_FAILED
)
1769 s
->suspended_callback
= cb
;
1770 s
->suspended_userdata
= userdata
;
1773 void pa_stream_set_started_callback(pa_stream
*s
, pa_stream_notify_cb_t cb
, void *userdata
) {
1775 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1777 if (pa_detect_fork())
1780 if (s
->state
== PA_STREAM_TERMINATED
|| s
->state
== PA_STREAM_FAILED
)
1783 s
->started_callback
= cb
;
1784 s
->started_userdata
= userdata
;
1787 void pa_stream_set_event_callback(pa_stream
*s
, pa_stream_event_cb_t cb
, void *userdata
) {
1789 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1791 if (pa_detect_fork())
1794 if (s
->state
== PA_STREAM_TERMINATED
|| s
->state
== PA_STREAM_FAILED
)
1797 s
->event_callback
= cb
;
1798 s
->event_userdata
= userdata
;
1801 void pa_stream_simple_ack_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1802 pa_operation
*o
= userdata
;
1807 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1812 if (command
!= PA_COMMAND_REPLY
) {
1813 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
1817 } else if (!pa_tagstruct_eof(t
)) {
1818 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
1823 pa_stream_success_cb_t cb
= (pa_stream_success_cb_t
) o
->callback
;
1824 cb(o
->stream
, success
, o
->userdata
);
1828 pa_operation_done(o
);
1829 pa_operation_unref(o
);
1832 pa_operation
* pa_stream_cork(pa_stream
*s
, int b
, pa_stream_success_cb_t cb
, void *userdata
) {
1838 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1840 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1841 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
1842 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
1846 o
= pa_operation_new(s
->context
, s
, (pa_operation_cb_t
) cb
, userdata
);
1848 t
= pa_tagstruct_command(
1850 (uint32_t) (s
->direction
== PA_STREAM_PLAYBACK
? PA_COMMAND_CORK_PLAYBACK_STREAM
: PA_COMMAND_CORK_RECORD_STREAM
),
1852 pa_tagstruct_putu32(t
, s
->channel
);
1853 pa_tagstruct_put_boolean(t
, !!b
);
1854 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
1855 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_stream_simple_ack_callback
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
1857 check_smoother_status(s
, FALSE
, FALSE
, FALSE
);
1859 /* This might cause the indexes to hang/start again, hence
1860 * let's request a timing update */
1861 request_auto_timing_update(s
, TRUE
);
1866 static pa_operation
* stream_send_simple_command(pa_stream
*s
, uint32_t command
, pa_stream_success_cb_t cb
, void *userdata
) {
1872 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1874 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1875 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
1877 o
= pa_operation_new(s
->context
, s
, (pa_operation_cb_t
) cb
, userdata
);
1879 t
= pa_tagstruct_command(s
->context
, command
, &tag
);
1880 pa_tagstruct_putu32(t
, s
->channel
);
1881 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
1882 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_stream_simple_ack_callback
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
1887 pa_operation
* pa_stream_flush(pa_stream
*s
, pa_stream_success_cb_t cb
, void *userdata
) {
1891 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1893 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1894 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
1895 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
1897 if (!(o
= stream_send_simple_command(s
, (uint32_t) (s
->direction
== PA_STREAM_PLAYBACK
? PA_COMMAND_FLUSH_PLAYBACK_STREAM
: PA_COMMAND_FLUSH_RECORD_STREAM
), cb
, userdata
)))
1900 if (s
->direction
== PA_STREAM_PLAYBACK
) {
1902 if (s
->write_index_corrections
[s
->current_write_index_correction
].valid
)
1903 s
->write_index_corrections
[s
->current_write_index_correction
].corrupt
= TRUE
;
1905 if (s
->buffer_attr
.prebuf
> 0)
1906 check_smoother_status(s
, FALSE
, FALSE
, TRUE
);
1908 /* This will change the write index, but leave the
1909 * read index untouched. */
1910 invalidate_indexes(s
, FALSE
, TRUE
);
1913 /* For record streams this has no influence on the write
1914 * index, but the read index might jump. */
1915 invalidate_indexes(s
, TRUE
, FALSE
);
1920 pa_operation
* pa_stream_prebuf(pa_stream
*s
, pa_stream_success_cb_t cb
, void *userdata
) {
1924 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1926 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1927 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
1928 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
== PA_STREAM_PLAYBACK
, PA_ERR_BADSTATE
);
1929 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->buffer_attr
.prebuf
> 0, PA_ERR_BADSTATE
);
1931 if (!(o
= stream_send_simple_command(s
, PA_COMMAND_PREBUF_PLAYBACK_STREAM
, cb
, userdata
)))
1934 /* This might cause the read index to hang again, hence
1935 * let's request a timing update */
1936 request_auto_timing_update(s
, TRUE
);
1941 pa_operation
* pa_stream_trigger(pa_stream
*s
, pa_stream_success_cb_t cb
, void *userdata
) {
1945 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1947 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1948 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
1949 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
== PA_STREAM_PLAYBACK
, PA_ERR_BADSTATE
);
1950 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->buffer_attr
.prebuf
> 0, PA_ERR_BADSTATE
);
1952 if (!(o
= stream_send_simple_command(s
, PA_COMMAND_TRIGGER_PLAYBACK_STREAM
, cb
, userdata
)))
1955 /* This might cause the read index to start moving again, hence
1956 * let's request a timing update */
1957 request_auto_timing_update(s
, TRUE
);
1962 pa_operation
* pa_stream_set_name(pa_stream
*s
, const char *name
, pa_stream_success_cb_t cb
, void *userdata
) {
1966 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
1969 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
1970 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
1971 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
1973 if (s
->context
->version
>= 13) {
1974 pa_proplist
*p
= pa_proplist_new();
1976 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
1977 o
= pa_stream_proplist_update(s
, PA_UPDATE_REPLACE
, p
, cb
, userdata
);
1978 pa_proplist_free(p
);
1983 o
= pa_operation_new(s
->context
, s
, (pa_operation_cb_t
) cb
, userdata
);
1984 t
= pa_tagstruct_command(
1986 (uint32_t) (s
->direction
== PA_STREAM_RECORD
? PA_COMMAND_SET_RECORD_STREAM_NAME
: PA_COMMAND_SET_PLAYBACK_STREAM_NAME
),
1988 pa_tagstruct_putu32(t
, s
->channel
);
1989 pa_tagstruct_puts(t
, name
);
1990 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
1991 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_stream_simple_ack_callback
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
1997 int pa_stream_get_time(pa_stream
*s
, pa_usec_t
*r_usec
) {
2001 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2003 PA_CHECK_VALIDITY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2004 PA_CHECK_VALIDITY(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
2005 PA_CHECK_VALIDITY(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
2006 PA_CHECK_VALIDITY(s
->context
, s
->timing_info_valid
, PA_ERR_NODATA
);
2007 PA_CHECK_VALIDITY(s
->context
, s
->direction
!= PA_STREAM_PLAYBACK
|| !s
->timing_info
.read_index_corrupt
, PA_ERR_NODATA
);
2008 PA_CHECK_VALIDITY(s
->context
, s
->direction
!= PA_STREAM_RECORD
|| !s
->timing_info
.write_index_corrupt
, PA_ERR_NODATA
);
2011 usec
= pa_smoother_get(s
->smoother
, pa_rtclock_usec());
2013 usec
= calc_time(s
, FALSE
);
2015 /* Make sure the time runs monotonically */
2016 if (!(s
->flags
& PA_STREAM_NOT_MONOTONIC
)) {
2017 if (usec
< s
->previous_time
)
2018 usec
= s
->previous_time
;
2020 s
->previous_time
= usec
;
2029 static pa_usec_t
time_counter_diff(pa_stream
*s
, pa_usec_t a
, pa_usec_t b
, int *negative
) {
2031 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2039 if (negative
&& s
->direction
== PA_STREAM_RECORD
) {
2047 int pa_stream_get_latency(pa_stream
*s
, pa_usec_t
*r_usec
, int *negative
) {
2053 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2056 PA_CHECK_VALIDITY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2057 PA_CHECK_VALIDITY(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
2058 PA_CHECK_VALIDITY(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
2059 PA_CHECK_VALIDITY(s
->context
, s
->timing_info_valid
, PA_ERR_NODATA
);
2060 PA_CHECK_VALIDITY(s
->context
, s
->direction
!= PA_STREAM_PLAYBACK
|| !s
->timing_info
.write_index_corrupt
, PA_ERR_NODATA
);
2061 PA_CHECK_VALIDITY(s
->context
, s
->direction
!= PA_STREAM_RECORD
|| !s
->timing_info
.read_index_corrupt
, PA_ERR_NODATA
);
2063 if ((r
= pa_stream_get_time(s
, &t
)) < 0)
2066 if (s
->direction
== PA_STREAM_PLAYBACK
)
2067 cindex
= s
->timing_info
.write_index
;
2069 cindex
= s
->timing_info
.read_index
;
2074 c
= pa_bytes_to_usec((uint64_t) cindex
, &s
->sample_spec
);
2076 if (s
->direction
== PA_STREAM_PLAYBACK
)
2077 *r_usec
= time_counter_diff(s
, c
, t
, negative
);
2079 *r_usec
= time_counter_diff(s
, t
, c
, negative
);
2084 const pa_timing_info
* pa_stream_get_timing_info(pa_stream
*s
) {
2086 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2088 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2089 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
2090 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
2091 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->timing_info_valid
, PA_ERR_NODATA
);
2093 return &s
->timing_info
;
2096 const pa_sample_spec
* pa_stream_get_sample_spec(pa_stream
*s
) {
2098 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2100 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2102 return &s
->sample_spec
;
2105 const pa_channel_map
* pa_stream_get_channel_map(pa_stream
*s
) {
2107 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2109 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2111 return &s
->channel_map
;
2114 const pa_buffer_attr
* pa_stream_get_buffer_attr(pa_stream
*s
) {
2116 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2118 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
2119 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
2120 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->context
->version
>= 9, PA_ERR_NOTSUPPORTED
);
2122 return &s
->buffer_attr
;
2125 static void stream_set_buffer_attr_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2126 pa_operation
*o
= userdata
;
2131 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
2136 if (command
!= PA_COMMAND_REPLY
) {
2137 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
2142 if (o
->stream
->direction
== PA_STREAM_PLAYBACK
) {
2143 if (pa_tagstruct_getu32(t
, &o
->stream
->buffer_attr
.maxlength
) < 0 ||
2144 pa_tagstruct_getu32(t
, &o
->stream
->buffer_attr
.tlength
) < 0 ||
2145 pa_tagstruct_getu32(t
, &o
->stream
->buffer_attr
.prebuf
) < 0 ||
2146 pa_tagstruct_getu32(t
, &o
->stream
->buffer_attr
.minreq
) < 0) {
2147 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
2150 } else if (o
->stream
->direction
== PA_STREAM_RECORD
) {
2151 if (pa_tagstruct_getu32(t
, &o
->stream
->buffer_attr
.maxlength
) < 0 ||
2152 pa_tagstruct_getu32(t
, &o
->stream
->buffer_attr
.fragsize
) < 0) {
2153 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
2158 if (o
->stream
->context
->version
>= 13) {
2161 if (pa_tagstruct_get_usec(t
, &usec
) < 0) {
2162 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
2166 if (o
->stream
->direction
== PA_STREAM_RECORD
)
2167 o
->stream
->timing_info
.configured_source_usec
= usec
;
2169 o
->stream
->timing_info
.configured_sink_usec
= usec
;
2172 if (!pa_tagstruct_eof(t
)) {
2173 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
2179 pa_stream_success_cb_t cb
= (pa_stream_success_cb_t
) o
->callback
;
2180 cb(o
->stream
, success
, o
->userdata
);
2184 pa_operation_done(o
);
2185 pa_operation_unref(o
);
2189 pa_operation
* pa_stream_set_buffer_attr(pa_stream
*s
, const pa_buffer_attr
*attr
, pa_stream_success_cb_t cb
, void *userdata
) {
2195 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2198 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2199 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
2200 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
2201 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->context
->version
>= 12, PA_ERR_NOTSUPPORTED
);
2203 o
= pa_operation_new(s
->context
, s
, (pa_operation_cb_t
) cb
, userdata
);
2205 t
= pa_tagstruct_command(
2207 (uint32_t) (s
->direction
== PA_STREAM_RECORD
? PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
: PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
),
2209 pa_tagstruct_putu32(t
, s
->channel
);
2211 pa_tagstruct_putu32(t
, attr
->maxlength
);
2213 if (s
->direction
== PA_STREAM_PLAYBACK
)
2216 PA_TAG_U32
, attr
->tlength
,
2217 PA_TAG_U32
, attr
->prebuf
,
2218 PA_TAG_U32
, attr
->minreq
,
2221 pa_tagstruct_putu32(t
, attr
->fragsize
);
2223 if (s
->context
->version
>= 13)
2224 pa_tagstruct_put_boolean(t
, !!(s
->flags
& PA_STREAM_ADJUST_LATENCY
));
2226 if (s
->context
->version
>= 14)
2227 pa_tagstruct_put_boolean(t
, !!(s
->flags
& PA_STREAM_EARLY_REQUESTS
));
2229 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
2230 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_set_buffer_attr_callback
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
2232 /* This might cause changes in the read/write indexex, hence let's
2233 * request a timing update */
2234 request_auto_timing_update(s
, TRUE
);
2239 uint32_t pa_stream_get_device_index(pa_stream
*s
) {
2241 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2243 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
, PA_INVALID_INDEX
);
2244 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
2245 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
2246 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, s
->context
->version
>= 12, PA_ERR_NOTSUPPORTED
, PA_INVALID_INDEX
);
2247 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, s
->device_index
!= PA_INVALID_INDEX
, PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
2249 return s
->device_index
;
2252 const char *pa_stream_get_device_name(pa_stream
*s
) {
2254 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2256 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2257 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
2258 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
2259 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->context
->version
>= 12, PA_ERR_NOTSUPPORTED
);
2260 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->device_name
, PA_ERR_BADSTATE
);
2262 return s
->device_name
;
2265 int pa_stream_is_suspended(pa_stream
*s
) {
2267 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2269 PA_CHECK_VALIDITY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2270 PA_CHECK_VALIDITY(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
2271 PA_CHECK_VALIDITY(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
2272 PA_CHECK_VALIDITY(s
->context
, s
->context
->version
>= 12, PA_ERR_NOTSUPPORTED
);
2274 return s
->suspended
;
2277 int pa_stream_is_corked(pa_stream
*s
) {
2279 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2281 PA_CHECK_VALIDITY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2282 PA_CHECK_VALIDITY(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
2283 PA_CHECK_VALIDITY(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
2288 static void stream_update_sample_rate_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2289 pa_operation
*o
= userdata
;
2294 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
2299 if (command
!= PA_COMMAND_REPLY
) {
2300 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
2306 if (!pa_tagstruct_eof(t
)) {
2307 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
2312 o
->stream
->sample_spec
.rate
= PA_PTR_TO_UINT(o
->private);
2313 pa_assert(pa_sample_spec_valid(&o
->stream
->sample_spec
));
2316 pa_stream_success_cb_t cb
= (pa_stream_success_cb_t
) o
->callback
;
2317 cb(o
->stream
, success
, o
->userdata
);
2321 pa_operation_done(o
);
2322 pa_operation_unref(o
);
2326 pa_operation
*pa_stream_update_sample_rate(pa_stream
*s
, uint32_t rate
, pa_stream_success_cb_t cb
, void *userdata
) {
2332 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2334 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2335 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, rate
> 0 && rate
<= PA_RATE_MAX
, PA_ERR_INVALID
);
2336 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
2337 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
2338 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->flags
& PA_STREAM_VARIABLE_RATE
, PA_ERR_BADSTATE
);
2339 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->context
->version
>= 12, PA_ERR_NOTSUPPORTED
);
2341 o
= pa_operation_new(s
->context
, s
, (pa_operation_cb_t
) cb
, userdata
);
2342 o
->private = PA_UINT_TO_PTR(rate
);
2344 t
= pa_tagstruct_command(
2346 (uint32_t) (s
->direction
== PA_STREAM_RECORD
? PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
: PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
),
2348 pa_tagstruct_putu32(t
, s
->channel
);
2349 pa_tagstruct_putu32(t
, rate
);
2351 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
2352 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_update_sample_rate_callback
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
2357 pa_operation
*pa_stream_proplist_update(pa_stream
*s
, pa_update_mode_t mode
, pa_proplist
*p
, pa_stream_success_cb_t cb
, void *userdata
) {
2363 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2365 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2366 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
, PA_ERR_INVALID
);
2367 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
2368 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
2369 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->context
->version
>= 13, PA_ERR_NOTSUPPORTED
);
2371 o
= pa_operation_new(s
->context
, s
, (pa_operation_cb_t
) cb
, userdata
);
2373 t
= pa_tagstruct_command(
2375 (uint32_t) (s
->direction
== PA_STREAM_RECORD
? PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
: PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
),
2377 pa_tagstruct_putu32(t
, s
->channel
);
2378 pa_tagstruct_putu32(t
, (uint32_t) mode
);
2379 pa_tagstruct_put_proplist(t
, p
);
2381 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
2382 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_stream_simple_ack_callback
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
2384 /* Please note that we don't update s->proplist here, because we
2385 * don't export that field */
2390 pa_operation
*pa_stream_proplist_remove(pa_stream
*s
, const char *const keys
[], pa_stream_success_cb_t cb
, void *userdata
) {
2394 const char * const*k
;
2397 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2399 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2400 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, keys
&& keys
[0], PA_ERR_INVALID
);
2401 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->state
== PA_STREAM_READY
, PA_ERR_BADSTATE
);
2402 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->direction
!= PA_STREAM_UPLOAD
, PA_ERR_BADSTATE
);
2403 PA_CHECK_VALIDITY_RETURN_NULL(s
->context
, s
->context
->version
>= 13, PA_ERR_NOTSUPPORTED
);
2405 o
= pa_operation_new(s
->context
, s
, (pa_operation_cb_t
) cb
, userdata
);
2407 t
= pa_tagstruct_command(
2409 (uint32_t) (s
->direction
== PA_STREAM_RECORD
? PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
: PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
),
2411 pa_tagstruct_putu32(t
, s
->channel
);
2413 for (k
= keys
; *k
; k
++)
2414 pa_tagstruct_puts(t
, *k
);
2416 pa_tagstruct_puts(t
, NULL
);
2418 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
2419 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_stream_simple_ack_callback
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
2421 /* Please note that we don't update s->proplist here, because we
2422 * don't export that field */
2427 int pa_stream_set_monitor_stream(pa_stream
*s
, uint32_t sink_input_idx
) {
2429 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2431 PA_CHECK_VALIDITY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
);
2432 PA_CHECK_VALIDITY(s
->context
, sink_input_idx
!= PA_INVALID_INDEX
, PA_ERR_INVALID
);
2433 PA_CHECK_VALIDITY(s
->context
, s
->state
== PA_STREAM_UNCONNECTED
, PA_ERR_BADSTATE
);
2434 PA_CHECK_VALIDITY(s
->context
, s
->context
->version
>= 13, PA_ERR_NOTSUPPORTED
);
2436 s
->direct_on_input
= sink_input_idx
;
2441 uint32_t pa_stream_get_monitor_stream(pa_stream
*s
) {
2443 pa_assert(PA_REFCNT_VALUE(s
) >= 1);
2445 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, !pa_detect_fork(), PA_ERR_FORKED
, PA_INVALID_INDEX
);
2446 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, s
->direct_on_input
!= PA_INVALID_INDEX
, PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
2447 PA_CHECK_VALIDITY_RETURN_ANY(s
->context
, s
->context
->version
>= 13, PA_ERR_NOTSUPPORTED
, PA_INVALID_INDEX
);
2449 return s
->direct_on_input
;