LCOV - code coverage report
Current view: top level - pulse - stream.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 0 1508 0.0 %
Date: 2012-07-17 Functions: 0 82 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 1618 0.0 %

           Branch data     Line data    Source code
       1                 :            : /***
       2                 :            :   This file is part of PulseAudio.
       3                 :            : 
       4                 :            :   Copyright 2004-2006 Lennart Poettering
       5                 :            :   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
       6                 :            : 
       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.
      11                 :            : 
      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.
      16                 :            : 
      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
      20                 :            :   USA.
      21                 :            : ***/
      22                 :            : 
      23                 :            : #ifdef HAVE_CONFIG_H
      24                 :            : #include <config.h>
      25                 :            : #endif
      26                 :            : 
      27                 :            : #include <string.h>
      28                 :            : #include <stdio.h>
      29                 :            : #include <string.h>
      30                 :            : 
      31                 :            : #include <pulse/def.h>
      32                 :            : #include <pulse/timeval.h>
      33                 :            : #include <pulse/rtclock.h>
      34                 :            : #include <pulse/xmalloc.h>
      35                 :            : #include <pulse/fork-detect.h>
      36                 :            : 
      37                 :            : #include <pulsecore/pstream-util.h>
      38                 :            : #include <pulsecore/log.h>
      39                 :            : #include <pulsecore/hashmap.h>
      40                 :            : #include <pulsecore/macro.h>
      41                 :            : #include <pulsecore/core-rtclock.h>
      42                 :            : #include <pulsecore/core-util.h>
      43                 :            : 
      44                 :            : #include "internal.h"
      45                 :            : #include "stream.h"
      46                 :            : 
      47                 :            : #define AUTO_TIMING_INTERVAL_START_USEC (10*PA_USEC_PER_MSEC)
      48                 :            : #define AUTO_TIMING_INTERVAL_END_USEC (1500*PA_USEC_PER_MSEC)
      49                 :            : 
      50                 :            : #define SMOOTHER_ADJUST_TIME (1000*PA_USEC_PER_MSEC)
      51                 :            : #define SMOOTHER_HISTORY_TIME (5000*PA_USEC_PER_MSEC)
      52                 :            : #define SMOOTHER_MIN_HISTORY (4)
      53                 :            : 
      54                 :          0 : pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) {
      55                 :          0 :     return pa_stream_new_with_proplist(c, name, ss, map, NULL);
      56                 :            : }
      57                 :            : 
      58                 :            : static void reset_callbacks(pa_stream *s) {
      59                 :          0 :     s->read_callback = NULL;
      60                 :          0 :     s->read_userdata = NULL;
      61                 :          0 :     s->write_callback = NULL;
      62                 :          0 :     s->write_userdata = NULL;
      63                 :          0 :     s->state_callback = NULL;
      64                 :          0 :     s->state_userdata = NULL;
      65                 :          0 :     s->overflow_callback = NULL;
      66                 :          0 :     s->overflow_userdata = NULL;
      67                 :          0 :     s->underflow_callback = NULL;
      68                 :          0 :     s->underflow_userdata = NULL;
      69                 :          0 :     s->latency_update_callback = NULL;
      70                 :          0 :     s->latency_update_userdata = NULL;
      71                 :          0 :     s->moved_callback = NULL;
      72                 :          0 :     s->moved_userdata = NULL;
      73                 :          0 :     s->suspended_callback = NULL;
      74                 :          0 :     s->suspended_userdata = NULL;
      75                 :          0 :     s->started_callback = NULL;
      76                 :          0 :     s->started_userdata = NULL;
      77                 :          0 :     s->event_callback = NULL;
      78                 :          0 :     s->event_userdata = NULL;
      79                 :          0 :     s->buffer_attr_callback = NULL;
      80                 :          0 :     s->buffer_attr_userdata = NULL;
      81                 :            : }
      82                 :            : 
      83                 :          0 : static pa_stream *pa_stream_new_with_proplist_internal(
      84                 :            :         pa_context *c,
      85                 :            :         const char *name,
      86                 :            :         const pa_sample_spec *ss,
      87                 :            :         const pa_channel_map *map,
      88                 :            :         pa_format_info * const *formats,
      89                 :            :         unsigned int n_formats,
      90                 :            :         pa_proplist *p) {
      91                 :            : 
      92                 :            :     pa_stream *s;
      93                 :            :     unsigned int i;
      94                 :            : 
      95         [ #  # ]:          0 :     pa_assert(c);
      96         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(c) >= 1);
      97 [ #  # ][ #  # ]:          0 :     pa_assert((ss == NULL && map == NULL) || (formats == NULL && n_formats == 0));
      98         [ #  # ]:          0 :     pa_assert(n_formats < PA_MAX_FORMATS);
      99                 :            : 
     100         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
     101 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(c, name || (p && pa_proplist_contains(p, PA_PROP_MEDIA_NAME)), PA_ERR_INVALID);
                 [ #  # ]
     102                 :            : 
     103                 :          0 :     s = pa_xnew(pa_stream, 1);
     104                 :          0 :     PA_REFCNT_INIT(s);
     105                 :          0 :     s->context = c;
     106                 :          0 :     s->mainloop = c->mainloop;
     107                 :            : 
     108                 :          0 :     s->direction = PA_STREAM_NODIRECTION;
     109                 :          0 :     s->state = PA_STREAM_UNCONNECTED;
     110                 :          0 :     s->flags = 0;
     111                 :            : 
     112         [ #  # ]:          0 :     if (ss)
     113                 :          0 :         s->sample_spec = *ss;
     114                 :            :     else
     115                 :          0 :         pa_sample_spec_init(&s->sample_spec);
     116                 :            : 
     117         [ #  # ]:          0 :     if (map)
     118                 :          0 :         s->channel_map = *map;
     119                 :            :     else
     120                 :          0 :         pa_channel_map_init(&s->channel_map);
     121                 :            : 
     122                 :          0 :     s->n_formats = 0;
     123         [ #  # ]:          0 :     if (formats) {
     124                 :          0 :         s->n_formats = n_formats;
     125         [ #  # ]:          0 :         for (i = 0; i < n_formats; i++)
     126                 :          0 :             s->req_formats[i] = pa_format_info_copy(formats[i]);
     127                 :            :     }
     128                 :            : 
     129                 :            :     /* We'll get the final negotiated format after connecting */
     130                 :          0 :     s->format = NULL;
     131                 :            : 
     132                 :          0 :     s->direct_on_input = PA_INVALID_INDEX;
     133                 :            : 
     134         [ #  # ]:          0 :     s->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
     135         [ #  # ]:          0 :     if (name)
     136                 :          0 :         pa_proplist_sets(s->proplist, PA_PROP_MEDIA_NAME, name);
     137                 :            : 
     138                 :          0 :     s->channel = 0;
     139                 :          0 :     s->channel_valid = FALSE;
     140                 :          0 :     s->syncid = c->csyncid++;
     141                 :          0 :     s->stream_index = PA_INVALID_INDEX;
     142                 :            : 
     143                 :          0 :     s->requested_bytes = 0;
     144                 :          0 :     memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
     145                 :            : 
     146                 :            :     /* We initialize the target length here, so that if the user
     147                 :            :      * passes no explicit buffering metrics the default is similar to
     148                 :            :      * what older PA versions provided. */
     149                 :            : 
     150                 :          0 :     s->buffer_attr.maxlength = (uint32_t) -1;
     151         [ #  # ]:          0 :     if (ss)
     152                 :          0 :         s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */
     153                 :            :     else {
     154                 :            :         /* FIXME: We assume a worst-case compressed format corresponding to
     155                 :            :          * 48000 Hz, 2 ch, S16 PCM, but this can very well be incorrect */
     156                 :          0 :         pa_sample_spec tmp_ss = {
     157                 :            :             .format   = PA_SAMPLE_S16NE,
     158                 :            :             .rate     = 48000,
     159                 :            :             .channels = 2,
     160                 :            :         };
     161                 :          0 :         s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes(250*PA_USEC_PER_MSEC, &tmp_ss); /* 250ms of buffering */
     162                 :            :     }
     163                 :          0 :     s->buffer_attr.minreq = (uint32_t) -1;
     164                 :          0 :     s->buffer_attr.prebuf = (uint32_t) -1;
     165                 :          0 :     s->buffer_attr.fragsize = (uint32_t) -1;
     166                 :            : 
     167                 :          0 :     s->device_index = PA_INVALID_INDEX;
     168                 :          0 :     s->device_name = NULL;
     169                 :          0 :     s->suspended = FALSE;
     170                 :          0 :     s->corked = FALSE;
     171                 :            : 
     172                 :          0 :     s->write_memblock = NULL;
     173                 :          0 :     s->write_data = NULL;
     174                 :            : 
     175                 :          0 :     pa_memchunk_reset(&s->peek_memchunk);
     176                 :          0 :     s->peek_data = NULL;
     177                 :          0 :     s->record_memblockq = NULL;
     178                 :            : 
     179                 :          0 :     memset(&s->timing_info, 0, sizeof(s->timing_info));
     180                 :          0 :     s->timing_info_valid = FALSE;
     181                 :            : 
     182                 :          0 :     s->previous_time = 0;
     183                 :          0 :     s->latest_underrun_at_index = -1;
     184                 :            : 
     185                 :          0 :     s->read_index_not_before = 0;
     186                 :          0 :     s->write_index_not_before = 0;
     187         [ #  # ]:          0 :     for (i = 0; i < PA_MAX_WRITE_INDEX_CORRECTIONS; i++)
     188                 :          0 :         s->write_index_corrections[i].valid = 0;
     189                 :          0 :     s->current_write_index_correction = 0;
     190                 :            : 
     191                 :          0 :     s->auto_timing_update_event = NULL;
     192                 :          0 :     s->auto_timing_update_requested = FALSE;
     193                 :          0 :     s->auto_timing_interval_usec = AUTO_TIMING_INTERVAL_START_USEC;
     194                 :            : 
     195                 :            :     reset_callbacks(s);
     196                 :            : 
     197                 :          0 :     s->smoother = NULL;
     198                 :            : 
     199                 :            :     /* Refcounting is strictly one-way: from the "bigger" to the "smaller" object. */
     200 [ #  # ][ #  # ]:          0 :     PA_LLIST_PREPEND(pa_stream, c->streams, s);
     201                 :          0 :     pa_stream_ref(s);
     202                 :            : 
     203                 :          0 :     return s;
     204                 :            : }
     205                 :            : 
     206                 :          0 : pa_stream *pa_stream_new_with_proplist(
     207                 :            :         pa_context *c,
     208                 :            :         const char *name,
     209                 :            :         const pa_sample_spec *ss,
     210                 :            :         const pa_channel_map *map,
     211                 :            :         pa_proplist *p) {
     212                 :            : 
     213                 :            :     pa_channel_map tmap;
     214                 :            : 
     215 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID);
     216 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE && ss->format != PA_SAMPLE_S32BE), PA_ERR_NOTSUPPORTED);
     217 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15 || (ss->format != PA_SAMPLE_S24LE && ss->format != PA_SAMPLE_S24BE), PA_ERR_NOTSUPPORTED);
     218 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15 || (ss->format != PA_SAMPLE_S24_32LE && ss->format != PA_SAMPLE_S24_32BE), PA_ERR_NOTSUPPORTED);
     219 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID);
                 [ #  # ]
     220                 :            : 
     221         [ #  # ]:          0 :     if (!map)
     222         [ #  # ]:          0 :         PA_CHECK_VALIDITY_RETURN_NULL(c, map = pa_channel_map_init_auto(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT), PA_ERR_INVALID);
     223                 :            : 
     224                 :          0 :     return pa_stream_new_with_proplist_internal(c, name, ss, map, NULL, 0, p);
     225                 :            : }
     226                 :            : 
     227                 :          0 : pa_stream *pa_stream_new_extended(
     228                 :            :         pa_context *c,
     229                 :            :         const char *name,
     230                 :            :         pa_format_info * const *formats,
     231                 :            :         unsigned int n_formats,
     232                 :            :         pa_proplist *p) {
     233                 :            : 
     234         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 21, PA_ERR_NOTSUPPORTED);
     235                 :            : 
     236                 :          0 :     return pa_stream_new_with_proplist_internal(c, name, NULL, NULL, formats, n_formats, p);
     237                 :            : }
     238                 :            : 
     239                 :          0 : static void stream_unlink(pa_stream *s) {
     240                 :            :     pa_operation *o, *n;
     241         [ #  # ]:          0 :     pa_assert(s);
     242                 :            : 
     243         [ #  # ]:          0 :     if (!s->context)
     244                 :          0 :         return;
     245                 :            : 
     246                 :            :     /* Detach from context */
     247                 :            : 
     248                 :            :     /* Unref all operation objects that point to us */
     249         [ #  # ]:          0 :     for (o = s->context->operations; o; o = n) {
     250                 :          0 :         n = o->next;
     251                 :            : 
     252         [ #  # ]:          0 :         if (o->stream == s)
     253                 :          0 :             pa_operation_cancel(o);
     254                 :            :     }
     255                 :            : 
     256                 :            :     /* Drop all outstanding replies for this stream */
     257         [ #  # ]:          0 :     if (s->context->pdispatch)
     258                 :          0 :         pa_pdispatch_unregister_reply(s->context->pdispatch, s);
     259                 :            : 
     260         [ #  # ]:          0 :     if (s->channel_valid) {
     261         [ #  # ]:          0 :         pa_hashmap_remove((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, PA_UINT32_TO_PTR(s->channel));
     262                 :          0 :         s->channel = 0;
     263                 :          0 :         s->channel_valid = FALSE;
     264                 :            :     }
     265                 :            : 
     266 [ #  # ][ #  # ]:          0 :     PA_LLIST_REMOVE(pa_stream, s->context->streams, s);
         [ #  # ][ #  # ]
     267                 :          0 :     pa_stream_unref(s);
     268                 :            : 
     269                 :          0 :     s->context = NULL;
     270                 :            : 
     271         [ #  # ]:          0 :     if (s->auto_timing_update_event) {
     272         [ #  # ]:          0 :         pa_assert(s->mainloop);
     273                 :          0 :         s->mainloop->time_free(s->auto_timing_update_event);
     274                 :            :     }
     275                 :            : 
     276                 :            :     reset_callbacks(s);
     277                 :            : }
     278                 :            : 
     279                 :          0 : static void stream_free(pa_stream *s) {
     280                 :            :     unsigned int i;
     281                 :            : 
     282         [ #  # ]:          0 :     pa_assert(s);
     283                 :            : 
     284                 :          0 :     stream_unlink(s);
     285                 :            : 
     286         [ #  # ]:          0 :     if (s->write_memblock) {
     287         [ #  # ]:          0 :         if (s->write_data)
     288                 :          0 :             pa_memblock_release(s->write_memblock);
     289                 :          0 :         pa_memblock_unref(s->write_memblock);
     290                 :            :     }
     291                 :            : 
     292         [ #  # ]:          0 :     if (s->peek_memchunk.memblock) {
     293         [ #  # ]:          0 :         if (s->peek_data)
     294                 :          0 :             pa_memblock_release(s->peek_memchunk.memblock);
     295                 :          0 :         pa_memblock_unref(s->peek_memchunk.memblock);
     296                 :            :     }
     297                 :            : 
     298         [ #  # ]:          0 :     if (s->record_memblockq)
     299                 :          0 :         pa_memblockq_free(s->record_memblockq);
     300                 :            : 
     301         [ #  # ]:          0 :     if (s->proplist)
     302                 :          0 :         pa_proplist_free(s->proplist);
     303                 :            : 
     304         [ #  # ]:          0 :     if (s->smoother)
     305                 :          0 :         pa_smoother_free(s->smoother);
     306                 :            : 
     307         [ #  # ]:          0 :     for (i = 0; i < s->n_formats; i++)
     308                 :          0 :         pa_format_info_free(s->req_formats[i]);
     309                 :            : 
     310         [ #  # ]:          0 :     if (s->format)
     311                 :          0 :         pa_format_info_free(s->format);
     312                 :            : 
     313                 :          0 :     pa_xfree(s->device_name);
     314                 :          0 :     pa_xfree(s);
     315                 :          0 : }
     316                 :            : 
     317                 :          0 : void pa_stream_unref(pa_stream *s) {
     318         [ #  # ]:          0 :     pa_assert(s);
     319         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     320                 :            : 
     321         [ #  # ]:          0 :     if (PA_REFCNT_DEC(s) <= 0)
     322                 :          0 :         stream_free(s);
     323                 :          0 : }
     324                 :            : 
     325                 :          0 : pa_stream* pa_stream_ref(pa_stream *s) {
     326         [ #  # ]:          0 :     pa_assert(s);
     327         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     328                 :            : 
     329                 :          0 :     PA_REFCNT_INC(s);
     330                 :          0 :     return s;
     331                 :            : }
     332                 :            : 
     333                 :          0 : pa_stream_state_t pa_stream_get_state(pa_stream *s) {
     334         [ #  # ]:          0 :     pa_assert(s);
     335         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     336                 :            : 
     337                 :          0 :     return s->state;
     338                 :            : }
     339                 :            : 
     340                 :          0 : pa_context* pa_stream_get_context(pa_stream *s) {
     341         [ #  # ]:          0 :     pa_assert(s);
     342         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     343                 :            : 
     344                 :          0 :     return s->context;
     345                 :            : }
     346                 :            : 
     347                 :          0 : uint32_t pa_stream_get_index(pa_stream *s) {
     348         [ #  # ]:          0 :     pa_assert(s);
     349         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     350                 :            : 
     351         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, !pa_detect_fork(), PA_ERR_FORKED, PA_INVALID_INDEX);
     352         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
     353                 :            : 
     354                 :          0 :     return s->stream_index;
     355                 :            : }
     356                 :            : 
     357                 :          0 : void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) {
     358         [ #  # ]:          0 :     pa_assert(s);
     359         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     360                 :            : 
     361         [ #  # ]:          0 :     if (s->state == st)
     362                 :          0 :         return;
     363                 :            : 
     364                 :          0 :     pa_stream_ref(s);
     365                 :            : 
     366                 :          0 :     s->state = st;
     367                 :            : 
     368         [ #  # ]:          0 :     if (s->state_callback)
     369                 :          0 :         s->state_callback(s, s->state_userdata);
     370                 :            : 
     371         [ #  # ]:          0 :     if ((st == PA_STREAM_FAILED || st == PA_STREAM_TERMINATED))
     372                 :          0 :         stream_unlink(s);
     373                 :            : 
     374                 :          0 :     pa_stream_unref(s);
     375                 :            : }
     376                 :            : 
     377                 :          0 : static void request_auto_timing_update(pa_stream *s, pa_bool_t force) {
     378         [ #  # ]:          0 :     pa_assert(s);
     379         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     380                 :            : 
     381         [ #  # ]:          0 :     if (!(s->flags & PA_STREAM_AUTO_TIMING_UPDATE))
     382                 :          0 :         return;
     383                 :            : 
     384 [ #  # ][ #  # ]:          0 :     if (s->state == PA_STREAM_READY &&
     385         [ #  # ]:          0 :         (force || !s->auto_timing_update_requested)) {
     386                 :            :         pa_operation *o;
     387                 :            : 
     388                 :            : /*         pa_log("Automatically requesting new timing data"); */
     389                 :            : 
     390         [ #  # ]:          0 :         if ((o = pa_stream_update_timing_info(s, NULL, NULL))) {
     391                 :          0 :             pa_operation_unref(o);
     392                 :          0 :             s->auto_timing_update_requested = TRUE;
     393                 :            :         }
     394                 :            :     }
     395                 :            : 
     396         [ #  # ]:          0 :     if (s->auto_timing_update_event) {
     397 [ #  # ][ #  # ]:          0 :         if (s->suspended && !force) {
     398         [ #  # ]:          0 :             pa_assert(s->mainloop);
     399                 :          0 :             s->mainloop->time_free(s->auto_timing_update_event);
     400                 :          0 :             s->auto_timing_update_event = NULL;
     401                 :            :         } else {
     402         [ #  # ]:          0 :             if (force)
     403                 :          0 :                 s->auto_timing_interval_usec = AUTO_TIMING_INTERVAL_START_USEC;
     404                 :            : 
     405                 :          0 :             pa_context_rttime_restart(s->context, s->auto_timing_update_event, pa_rtclock_now() + s->auto_timing_interval_usec);
     406                 :            : 
     407                 :          0 :             s->auto_timing_interval_usec = PA_MIN(AUTO_TIMING_INTERVAL_END_USEC, s->auto_timing_interval_usec*2);
     408                 :            :         }
     409                 :            :     }
     410                 :            : }
     411                 :            : 
     412                 :          0 : void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     413                 :          0 :     pa_context *c = userdata;
     414                 :            :     pa_stream *s;
     415                 :            :     uint32_t channel;
     416                 :            : 
     417         [ #  # ]:          0 :     pa_assert(pd);
     418         [ #  # ]:          0 :     pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED);
     419         [ #  # ]:          0 :     pa_assert(t);
     420         [ #  # ]:          0 :     pa_assert(c);
     421         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(c) >= 1);
     422                 :            : 
     423                 :          0 :     pa_context_ref(c);
     424                 :            : 
     425   [ #  #  #  # ]:          0 :     if (pa_tagstruct_getu32(t, &channel) < 0 ||
     426                 :          0 :         !pa_tagstruct_eof(t)) {
     427                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     428                 :          0 :         goto finish;
     429                 :            :     }
     430                 :            : 
     431 [ #  # ][ #  # ]:          0 :     if (!(s = pa_hashmap_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, PA_UINT32_TO_PTR(channel))))
     432                 :            :         goto finish;
     433                 :            : 
     434         [ #  # ]:          0 :     if (s->state != PA_STREAM_READY)
     435                 :            :         goto finish;
     436                 :            : 
     437                 :          0 :     pa_context_set_error(c, PA_ERR_KILLED);
     438                 :          0 :     pa_stream_set_state(s, PA_STREAM_FAILED);
     439                 :            : 
     440                 :            : finish:
     441                 :          0 :     pa_context_unref(c);
     442                 :          0 : }
     443                 :            : 
     444                 :          0 : static void check_smoother_status(pa_stream *s, pa_bool_t aposteriori, pa_bool_t force_start, pa_bool_t force_stop) {
     445                 :            :     pa_usec_t x;
     446                 :            : 
     447         [ #  # ]:          0 :     pa_assert(s);
     448 [ #  # ][ #  # ]:          0 :     pa_assert(!force_start || !force_stop);
     449                 :            : 
     450         [ #  # ]:          0 :     if (!s->smoother)
     451                 :            :         return;
     452                 :            : 
     453                 :          0 :     x = pa_rtclock_now();
     454                 :            : 
     455         [ #  # ]:          0 :     if (s->timing_info_valid) {
     456         [ #  # ]:          0 :         if (aposteriori)
     457                 :          0 :             x -= s->timing_info.transport_usec;
     458                 :            :         else
     459                 :          0 :             x += s->timing_info.transport_usec;
     460                 :            :     }
     461                 :            : 
     462 [ #  # ][ #  # ]:          0 :     if (s->suspended || s->corked || force_stop)
                 [ #  # ]
     463                 :          0 :         pa_smoother_pause(s->smoother, x);
     464 [ #  # ][ #  # ]:          0 :     else if (force_start || s->buffer_attr.prebuf == 0) {
     465                 :            : 
     466 [ #  # ][ #  # ]:          0 :         if (!s->timing_info_valid &&
     467         [ #  # ]:          0 :             !aposteriori &&
     468         [ #  # ]:          0 :             !force_start &&
     469         [ #  # ]:          0 :             !force_stop &&
     470                 :          0 :             s->context->version >= 13) {
     471                 :            : 
     472                 :            :             /* If the server supports STARTED events we take them as
     473                 :            :              * indications when audio really starts/stops playing, if
     474                 :            :              * we don't have any timing info yet -- instead of trying
     475                 :            :              * to be smart and guessing the server time. Otherwise the
     476                 :            :              * unknown transport delay adds too much noise to our time
     477                 :            :              * calculations. */
     478                 :            : 
     479                 :            :             return;
     480                 :            :         }
     481                 :            : 
     482                 :          0 :         pa_smoother_resume(s->smoother, x, TRUE);
     483                 :            :     }
     484                 :            : 
     485                 :            :     /* Please note that we have no idea if playback actually started
     486                 :            :      * if prebuf is non-zero! */
     487                 :            : }
     488                 :            : 
     489                 :            : static void auto_timing_update_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata);
     490                 :            : 
     491                 :          0 : void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     492                 :          0 :     pa_context *c = userdata;
     493                 :            :     pa_stream *s;
     494                 :            :     uint32_t channel;
     495                 :            :     const char *dn;
     496                 :            :     pa_bool_t suspended;
     497                 :            :     uint32_t di;
     498                 :          0 :     pa_usec_t usec = 0;
     499                 :          0 :     uint32_t maxlength = 0, fragsize = 0, minreq = 0, tlength = 0, prebuf = 0;
     500                 :            : 
     501         [ #  # ]:          0 :     pa_assert(pd);
     502         [ #  # ]:          0 :     pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_MOVED || command == PA_COMMAND_RECORD_STREAM_MOVED);
     503         [ #  # ]:          0 :     pa_assert(t);
     504         [ #  # ]:          0 :     pa_assert(c);
     505         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(c) >= 1);
     506                 :            : 
     507                 :          0 :     pa_context_ref(c);
     508                 :            : 
     509         [ #  # ]:          0 :     if (c->version < 12) {
     510                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     511                 :          0 :         goto finish;
     512                 :            :     }
     513                 :            : 
     514   [ #  #  #  # ]:          0 :     if (pa_tagstruct_getu32(t, &channel) < 0 ||
     515         [ #  # ]:          0 :         pa_tagstruct_getu32(t, &di) < 0 ||
     516         [ #  # ]:          0 :         pa_tagstruct_gets(t, &dn) < 0 ||
     517                 :          0 :         pa_tagstruct_get_boolean(t, &suspended) < 0) {
     518                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     519                 :          0 :         goto finish;
     520                 :            :     }
     521                 :            : 
     522         [ #  # ]:          0 :     if (c->version >= 13) {
     523                 :            : 
     524         [ #  # ]:          0 :         if (command == PA_COMMAND_RECORD_STREAM_MOVED) {
     525   [ #  #  #  # ]:          0 :             if (pa_tagstruct_getu32(t, &maxlength) < 0 ||
     526         [ #  # ]:          0 :                 pa_tagstruct_getu32(t, &fragsize) < 0 ||
     527                 :          0 :                 pa_tagstruct_get_usec(t, &usec) < 0) {
     528                 :          0 :                 pa_context_fail(c, PA_ERR_PROTOCOL);
     529                 :          0 :                 goto finish;
     530                 :            :             }
     531                 :            :         } else {
     532   [ #  #  #  # ]:          0 :             if (pa_tagstruct_getu32(t, &maxlength) < 0 ||
     533         [ #  # ]:          0 :                 pa_tagstruct_getu32(t, &tlength) < 0 ||
     534         [ #  # ]:          0 :                 pa_tagstruct_getu32(t, &prebuf) < 0 ||
     535         [ #  # ]:          0 :                 pa_tagstruct_getu32(t, &minreq) < 0 ||
     536                 :          0 :                 pa_tagstruct_get_usec(t, &usec) < 0) {
     537                 :          0 :                 pa_context_fail(c, PA_ERR_PROTOCOL);
     538                 :          0 :                 goto finish;
     539                 :            :             }
     540                 :            :         }
     541                 :            :     }
     542                 :            : 
     543         [ #  # ]:          0 :     if (!pa_tagstruct_eof(t)) {
     544                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     545                 :          0 :         goto finish;
     546                 :            :     }
     547                 :            : 
     548 [ #  # ][ #  # ]:          0 :     if (!dn || di == PA_INVALID_INDEX) {
     549                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     550                 :          0 :         goto finish;
     551                 :            :     }
     552                 :            : 
     553 [ #  # ][ #  # ]:          0 :     if (!(s = pa_hashmap_get(command == PA_COMMAND_PLAYBACK_STREAM_MOVED ? c->playback_streams : c->record_streams, PA_UINT32_TO_PTR(channel))))
     554                 :            :         goto finish;
     555                 :            : 
     556         [ #  # ]:          0 :     if (s->state != PA_STREAM_READY)
     557                 :            :         goto finish;
     558                 :            : 
     559         [ #  # ]:          0 :     if (c->version >= 13) {
     560         [ #  # ]:          0 :         if (s->direction == PA_STREAM_RECORD)
     561                 :          0 :             s->timing_info.configured_source_usec = usec;
     562                 :            :         else
     563                 :          0 :             s->timing_info.configured_sink_usec = usec;
     564                 :            : 
     565                 :          0 :         s->buffer_attr.maxlength = maxlength;
     566                 :          0 :         s->buffer_attr.fragsize = fragsize;
     567                 :          0 :         s->buffer_attr.tlength = tlength;
     568                 :          0 :         s->buffer_attr.prebuf = prebuf;
     569                 :          0 :         s->buffer_attr.minreq = minreq;
     570                 :            :     }
     571                 :            : 
     572                 :          0 :     pa_xfree(s->device_name);
     573                 :          0 :     s->device_name = pa_xstrdup(dn);
     574                 :          0 :     s->device_index = di;
     575                 :            : 
     576                 :          0 :     s->suspended = suspended;
     577                 :            : 
     578 [ #  # ][ #  # ]:          0 :     if ((s->flags & PA_STREAM_AUTO_TIMING_UPDATE) && !suspended && !s->auto_timing_update_event) {
                 [ #  # ]
     579                 :          0 :         s->auto_timing_interval_usec = AUTO_TIMING_INTERVAL_START_USEC;
     580                 :          0 :         s->auto_timing_update_event = pa_context_rttime_new(s->context, pa_rtclock_now() + s->auto_timing_interval_usec, &auto_timing_update_callback, s);
     581                 :          0 :         request_auto_timing_update(s, TRUE);
     582                 :            :     }
     583                 :            : 
     584                 :          0 :     check_smoother_status(s, TRUE, FALSE, FALSE);
     585                 :          0 :     request_auto_timing_update(s, TRUE);
     586                 :            : 
     587         [ #  # ]:          0 :     if (s->moved_callback)
     588                 :          0 :         s->moved_callback(s, s->moved_userdata);
     589                 :            : 
     590                 :            : finish:
     591                 :          0 :     pa_context_unref(c);
     592                 :          0 : }
     593                 :            : 
     594                 :          0 : void pa_command_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     595                 :          0 :     pa_context *c = userdata;
     596                 :            :     pa_stream *s;
     597                 :            :     uint32_t channel;
     598                 :          0 :     pa_usec_t usec = 0;
     599                 :          0 :     uint32_t maxlength = 0, fragsize = 0, minreq = 0, tlength = 0, prebuf = 0;
     600                 :            : 
     601         [ #  # ]:          0 :     pa_assert(pd);
     602         [ #  # ]:          0 :     pa_assert(command == PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED || command == PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED);
     603         [ #  # ]:          0 :     pa_assert(t);
     604         [ #  # ]:          0 :     pa_assert(c);
     605         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(c) >= 1);
     606                 :            : 
     607                 :          0 :     pa_context_ref(c);
     608                 :            : 
     609         [ #  # ]:          0 :     if (c->version < 15) {
     610                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     611                 :          0 :         goto finish;
     612                 :            :     }
     613                 :            : 
     614         [ #  # ]:          0 :     if (pa_tagstruct_getu32(t, &channel) < 0) {
     615                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     616                 :          0 :         goto finish;
     617                 :            :     }
     618                 :            : 
     619         [ #  # ]:          0 :     if (command == PA_COMMAND_RECORD_STREAM_MOVED) {
     620   [ #  #  #  # ]:          0 :         if (pa_tagstruct_getu32(t, &maxlength) < 0 ||
     621         [ #  # ]:          0 :             pa_tagstruct_getu32(t, &fragsize) < 0 ||
     622                 :          0 :             pa_tagstruct_get_usec(t, &usec) < 0) {
     623                 :          0 :             pa_context_fail(c, PA_ERR_PROTOCOL);
     624                 :          0 :             goto finish;
     625                 :            :         }
     626                 :            :     } else {
     627   [ #  #  #  # ]:          0 :         if (pa_tagstruct_getu32(t, &maxlength) < 0 ||
     628         [ #  # ]:          0 :             pa_tagstruct_getu32(t, &tlength) < 0 ||
     629         [ #  # ]:          0 :             pa_tagstruct_getu32(t, &prebuf) < 0 ||
     630         [ #  # ]:          0 :             pa_tagstruct_getu32(t, &minreq) < 0 ||
     631                 :          0 :             pa_tagstruct_get_usec(t, &usec) < 0) {
     632                 :          0 :             pa_context_fail(c, PA_ERR_PROTOCOL);
     633                 :          0 :             goto finish;
     634                 :            :         }
     635                 :            :     }
     636                 :            : 
     637         [ #  # ]:          0 :     if (!pa_tagstruct_eof(t)) {
     638                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     639                 :          0 :         goto finish;
     640                 :            :     }
     641                 :            : 
     642 [ #  # ][ #  # ]:          0 :     if (!(s = pa_hashmap_get(command == PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED ? c->playback_streams : c->record_streams, PA_UINT32_TO_PTR(channel))))
     643                 :            :         goto finish;
     644                 :            : 
     645         [ #  # ]:          0 :     if (s->state != PA_STREAM_READY)
     646                 :            :         goto finish;
     647                 :            : 
     648         [ #  # ]:          0 :     if (s->direction == PA_STREAM_RECORD)
     649                 :          0 :         s->timing_info.configured_source_usec = usec;
     650                 :            :     else
     651                 :          0 :         s->timing_info.configured_sink_usec = usec;
     652                 :            : 
     653                 :          0 :     s->buffer_attr.maxlength = maxlength;
     654                 :          0 :     s->buffer_attr.fragsize = fragsize;
     655                 :          0 :     s->buffer_attr.tlength = tlength;
     656                 :          0 :     s->buffer_attr.prebuf = prebuf;
     657                 :          0 :     s->buffer_attr.minreq = minreq;
     658                 :            : 
     659                 :          0 :     request_auto_timing_update(s, TRUE);
     660                 :            : 
     661         [ #  # ]:          0 :     if (s->buffer_attr_callback)
     662                 :          0 :         s->buffer_attr_callback(s, s->buffer_attr_userdata);
     663                 :            : 
     664                 :            : finish:
     665                 :          0 :     pa_context_unref(c);
     666                 :          0 : }
     667                 :            : 
     668                 :          0 : void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     669                 :          0 :     pa_context *c = userdata;
     670                 :            :     pa_stream *s;
     671                 :            :     uint32_t channel;
     672                 :            :     pa_bool_t suspended;
     673                 :            : 
     674         [ #  # ]:          0 :     pa_assert(pd);
     675         [ #  # ]:          0 :     pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_SUSPENDED || command == PA_COMMAND_RECORD_STREAM_SUSPENDED);
     676         [ #  # ]:          0 :     pa_assert(t);
     677         [ #  # ]:          0 :     pa_assert(c);
     678         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(c) >= 1);
     679                 :            : 
     680                 :          0 :     pa_context_ref(c);
     681                 :            : 
     682         [ #  # ]:          0 :     if (c->version < 12) {
     683                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     684                 :          0 :         goto finish;
     685                 :            :     }
     686                 :            : 
     687   [ #  #  #  # ]:          0 :     if (pa_tagstruct_getu32(t, &channel) < 0 ||
     688         [ #  # ]:          0 :         pa_tagstruct_get_boolean(t, &suspended) < 0 ||
     689                 :          0 :         !pa_tagstruct_eof(t)) {
     690                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     691                 :          0 :         goto finish;
     692                 :            :     }
     693                 :            : 
     694 [ #  # ][ #  # ]:          0 :     if (!(s = pa_hashmap_get(command == PA_COMMAND_PLAYBACK_STREAM_SUSPENDED ? c->playback_streams : c->record_streams, PA_UINT32_TO_PTR(channel))))
     695                 :            :         goto finish;
     696                 :            : 
     697         [ #  # ]:          0 :     if (s->state != PA_STREAM_READY)
     698                 :            :         goto finish;
     699                 :            : 
     700                 :          0 :     s->suspended = suspended;
     701                 :            : 
     702 [ #  # ][ #  # ]:          0 :     if ((s->flags & PA_STREAM_AUTO_TIMING_UPDATE) && !suspended && !s->auto_timing_update_event) {
                 [ #  # ]
     703                 :          0 :         s->auto_timing_interval_usec = AUTO_TIMING_INTERVAL_START_USEC;
     704                 :          0 :         s->auto_timing_update_event = pa_context_rttime_new(s->context, pa_rtclock_now() + s->auto_timing_interval_usec, &auto_timing_update_callback, s);
     705                 :          0 :         request_auto_timing_update(s, TRUE);
     706                 :            :     }
     707                 :            : 
     708                 :          0 :     check_smoother_status(s, TRUE, FALSE, FALSE);
     709                 :          0 :     request_auto_timing_update(s, TRUE);
     710                 :            : 
     711         [ #  # ]:          0 :     if (s->suspended_callback)
     712                 :          0 :         s->suspended_callback(s, s->suspended_userdata);
     713                 :            : 
     714                 :            : finish:
     715                 :          0 :     pa_context_unref(c);
     716                 :          0 : }
     717                 :            : 
     718                 :          0 : void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     719                 :          0 :     pa_context *c = userdata;
     720                 :            :     pa_stream *s;
     721                 :            :     uint32_t channel;
     722                 :            : 
     723         [ #  # ]:          0 :     pa_assert(pd);
     724         [ #  # ]:          0 :     pa_assert(command == PA_COMMAND_STARTED);
     725         [ #  # ]:          0 :     pa_assert(t);
     726         [ #  # ]:          0 :     pa_assert(c);
     727         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(c) >= 1);
     728                 :            : 
     729                 :          0 :     pa_context_ref(c);
     730                 :            : 
     731         [ #  # ]:          0 :     if (c->version < 13) {
     732                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     733                 :          0 :         goto finish;
     734                 :            :     }
     735                 :            : 
     736   [ #  #  #  # ]:          0 :     if (pa_tagstruct_getu32(t, &channel) < 0 ||
     737                 :          0 :         !pa_tagstruct_eof(t)) {
     738                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     739                 :          0 :         goto finish;
     740                 :            :     }
     741                 :            : 
     742         [ #  # ]:          0 :     if (!(s = pa_hashmap_get(c->playback_streams, PA_UINT32_TO_PTR(channel))))
     743                 :            :         goto finish;
     744                 :            : 
     745         [ #  # ]:          0 :     if (s->state != PA_STREAM_READY)
     746                 :            :         goto finish;
     747                 :            : 
     748                 :          0 :     check_smoother_status(s, TRUE, TRUE, FALSE);
     749                 :          0 :     request_auto_timing_update(s, TRUE);
     750                 :            : 
     751         [ #  # ]:          0 :     if (s->started_callback)
     752                 :          0 :         s->started_callback(s, s->started_userdata);
     753                 :            : 
     754                 :            : finish:
     755                 :          0 :     pa_context_unref(c);
     756                 :          0 : }
     757                 :            : 
     758                 :          0 : void pa_command_stream_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     759                 :          0 :     pa_context *c = userdata;
     760                 :            :     pa_stream *s;
     761                 :            :     uint32_t channel;
     762                 :          0 :     pa_proplist *pl = NULL;
     763                 :            :     const char *event;
     764                 :            : 
     765         [ #  # ]:          0 :     pa_assert(pd);
     766         [ #  # ]:          0 :     pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_EVENT || command == PA_COMMAND_RECORD_STREAM_EVENT);
     767         [ #  # ]:          0 :     pa_assert(t);
     768         [ #  # ]:          0 :     pa_assert(c);
     769         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(c) >= 1);
     770                 :            : 
     771                 :          0 :     pa_context_ref(c);
     772                 :            : 
     773         [ #  # ]:          0 :     if (c->version < 15) {
     774                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     775                 :          0 :         goto finish;
     776                 :            :     }
     777                 :            : 
     778                 :          0 :     pl = pa_proplist_new();
     779                 :            : 
     780   [ #  #  #  # ]:          0 :     if (pa_tagstruct_getu32(t, &channel) < 0 ||
     781         [ #  # ]:          0 :         pa_tagstruct_gets(t, &event) < 0 ||
     782         [ #  # ]:          0 :         pa_tagstruct_get_proplist(t, pl) < 0 ||
     783         [ #  # ]:          0 :         !pa_tagstruct_eof(t) || !event) {
     784                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     785                 :          0 :         goto finish;
     786                 :            :     }
     787                 :            : 
     788 [ #  # ][ #  # ]:          0 :     if (!(s = pa_hashmap_get(command == PA_COMMAND_PLAYBACK_STREAM_EVENT ? c->playback_streams : c->record_streams, PA_UINT32_TO_PTR(channel))))
     789                 :            :         goto finish;
     790                 :            : 
     791         [ #  # ]:          0 :     if (s->state != PA_STREAM_READY)
     792                 :            :         goto finish;
     793                 :            : 
     794         [ #  # ]:          0 :     if (pa_streq(event, PA_STREAM_EVENT_FORMAT_LOST)) {
     795                 :            :         /* Let client know what the running time was when the stream had to be killed  */
     796                 :            :         pa_usec_t stream_time;
     797         [ #  # ]:          0 :         if (pa_stream_get_time(s, &stream_time) == 0)
     798                 :          0 :             pa_proplist_setf(pl, "stream-time", "%llu", (unsigned long long) stream_time);
     799                 :            :     }
     800                 :            : 
     801         [ #  # ]:          0 :     if (s->event_callback)
     802                 :          0 :         s->event_callback(s, event, pl, s->event_userdata);
     803                 :            : 
     804                 :            : finish:
     805                 :          0 :     pa_context_unref(c);
     806                 :            : 
     807         [ #  # ]:          0 :     if (pl)
     808                 :          0 :         pa_proplist_free(pl);
     809                 :          0 : }
     810                 :            : 
     811                 :          0 : void pa_command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     812                 :            :     pa_stream *s;
     813                 :          0 :     pa_context *c = userdata;
     814                 :            :     uint32_t bytes, channel;
     815                 :            : 
     816         [ #  # ]:          0 :     pa_assert(pd);
     817         [ #  # ]:          0 :     pa_assert(command == PA_COMMAND_REQUEST);
     818         [ #  # ]:          0 :     pa_assert(t);
     819         [ #  # ]:          0 :     pa_assert(c);
     820         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(c) >= 1);
     821                 :            : 
     822                 :          0 :     pa_context_ref(c);
     823                 :            : 
     824   [ #  #  #  # ]:          0 :     if (pa_tagstruct_getu32(t, &channel) < 0 ||
     825         [ #  # ]:          0 :         pa_tagstruct_getu32(t, &bytes) < 0 ||
     826                 :          0 :         !pa_tagstruct_eof(t)) {
     827                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     828                 :          0 :         goto finish;
     829                 :            :     }
     830                 :            : 
     831         [ #  # ]:          0 :     if (!(s = pa_hashmap_get(c->playback_streams, PA_UINT32_TO_PTR(channel))))
     832                 :            :         goto finish;
     833                 :            : 
     834         [ #  # ]:          0 :     if (s->state != PA_STREAM_READY)
     835                 :            :         goto finish;
     836                 :            : 
     837                 :          0 :     s->requested_bytes += bytes;
     838                 :            : 
     839                 :            :     /* pa_log("got request for %lli, now at %lli", (long long) bytes, (long long) s->requested_bytes); */
     840                 :            : 
     841 [ #  # ][ #  # ]:          0 :     if (s->requested_bytes > 0 && s->write_callback)
     842                 :          0 :         s->write_callback(s, (size_t) s->requested_bytes, s->write_userdata);
     843                 :            : 
     844                 :            : finish:
     845                 :          0 :     pa_context_unref(c);
     846                 :          0 : }
     847                 :            : 
     848                 :          0 : int64_t pa_stream_get_underflow_index(pa_stream *p)
     849                 :            : {
     850         [ #  # ]:          0 :     pa_assert(p);
     851                 :          0 :     return p->latest_underrun_at_index;
     852                 :            : }
     853                 :            : 
     854                 :          0 : void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     855                 :            :     pa_stream *s;
     856                 :          0 :     pa_context *c = userdata;
     857                 :            :     uint32_t channel;
     858                 :          0 :     int64_t offset = -1;
     859                 :            : 
     860         [ #  # ]:          0 :     pa_assert(pd);
     861         [ #  # ]:          0 :     pa_assert(command == PA_COMMAND_OVERFLOW || command == PA_COMMAND_UNDERFLOW);
     862         [ #  # ]:          0 :     pa_assert(t);
     863         [ #  # ]:          0 :     pa_assert(c);
     864         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(c) >= 1);
     865                 :            : 
     866                 :          0 :     pa_context_ref(c);
     867                 :            : 
     868         [ #  # ]:          0 :     if (pa_tagstruct_getu32(t, &channel) < 0) {
     869                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     870                 :          0 :         goto finish;
     871                 :            :     }
     872                 :            : 
     873         [ #  # ]:          0 :     if (c->version >= 23 && command == PA_COMMAND_UNDERFLOW) {
     874         [ #  # ]:          0 :         if (pa_tagstruct_gets64(t, &offset) < 0) {
     875                 :          0 :             pa_context_fail(c, PA_ERR_PROTOCOL);
     876                 :          0 :             goto finish;
     877                 :            :         }
     878                 :            :     }
     879                 :            : 
     880         [ #  # ]:          0 :     if (!pa_tagstruct_eof(t)) {
     881                 :          0 :         pa_context_fail(c, PA_ERR_PROTOCOL);
     882                 :          0 :         goto finish;
     883                 :            :     }
     884                 :            : 
     885         [ #  # ]:          0 :     if (!(s = pa_hashmap_get(c->playback_streams, PA_UINT32_TO_PTR(channel))))
     886                 :            :         goto finish;
     887                 :            : 
     888         [ #  # ]:          0 :     if (s->state != PA_STREAM_READY)
     889                 :            :         goto finish;
     890                 :            : 
     891         [ #  # ]:          0 :     if (offset != -1)
     892                 :          0 :         s->latest_underrun_at_index = offset;
     893                 :            : 
     894         [ #  # ]:          0 :     if (s->buffer_attr.prebuf > 0)
     895                 :          0 :         check_smoother_status(s, TRUE, FALSE, TRUE);
     896                 :            : 
     897                 :          0 :     request_auto_timing_update(s, TRUE);
     898                 :            : 
     899         [ #  # ]:          0 :     if (command == PA_COMMAND_OVERFLOW) {
     900         [ #  # ]:          0 :         if (s->overflow_callback)
     901                 :          0 :             s->overflow_callback(s, s->overflow_userdata);
     902         [ #  # ]:          0 :     } else if (command == PA_COMMAND_UNDERFLOW) {
     903         [ #  # ]:          0 :         if (s->underflow_callback)
     904                 :          0 :             s->underflow_callback(s, s->underflow_userdata);
     905                 :            :     }
     906                 :            : 
     907                 :            : finish:
     908                 :          0 :     pa_context_unref(c);
     909                 :          0 : }
     910                 :            : 
     911                 :          0 : static void invalidate_indexes(pa_stream *s, pa_bool_t r, pa_bool_t w) {
     912         [ #  # ]:          0 :     pa_assert(s);
     913         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     914                 :            : 
     915                 :            : /*     pa_log("invalidate r:%u w:%u tag:%u", r, w, s->context->ctag); */
     916                 :            : 
     917         [ #  # ]:          0 :     if (s->state != PA_STREAM_READY)
     918                 :          0 :         return;
     919                 :            : 
     920         [ #  # ]:          0 :     if (w) {
     921                 :          0 :         s->write_index_not_before = s->context->ctag;
     922                 :            : 
     923         [ #  # ]:          0 :         if (s->timing_info_valid)
     924                 :          0 :             s->timing_info.write_index_corrupt = TRUE;
     925                 :            : 
     926                 :            : /*         pa_log("write_index invalidated"); */
     927                 :            :     }
     928                 :            : 
     929         [ #  # ]:          0 :     if (r) {
     930                 :          0 :         s->read_index_not_before = s->context->ctag;
     931                 :            : 
     932         [ #  # ]:          0 :         if (s->timing_info_valid)
     933                 :          0 :             s->timing_info.read_index_corrupt = TRUE;
     934                 :            : 
     935                 :            : /*         pa_log("read_index invalidated"); */
     936                 :            :     }
     937                 :            : 
     938                 :          0 :     request_auto_timing_update(s, TRUE);
     939                 :            : }
     940                 :            : 
     941                 :          0 : static void auto_timing_update_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
     942                 :          0 :     pa_stream *s = userdata;
     943                 :            : 
     944         [ #  # ]:          0 :     pa_assert(s);
     945         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     946                 :            : 
     947                 :          0 :     pa_stream_ref(s);
     948                 :          0 :     request_auto_timing_update(s, FALSE);
     949                 :          0 :     pa_stream_unref(s);
     950                 :          0 : }
     951                 :            : 
     952                 :          0 : static void create_stream_complete(pa_stream *s) {
     953         [ #  # ]:          0 :     pa_assert(s);
     954         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     955         [ #  # ]:          0 :     pa_assert(s->state == PA_STREAM_CREATING);
     956                 :            : 
     957                 :          0 :     pa_stream_set_state(s, PA_STREAM_READY);
     958                 :            : 
     959 [ #  # ][ #  # ]:          0 :     if (s->requested_bytes > 0 && s->write_callback)
     960                 :          0 :         s->write_callback(s, (size_t) s->requested_bytes, s->write_userdata);
     961                 :            : 
     962         [ #  # ]:          0 :     if (s->flags & PA_STREAM_AUTO_TIMING_UPDATE) {
     963                 :          0 :         s->auto_timing_interval_usec = AUTO_TIMING_INTERVAL_START_USEC;
     964         [ #  # ]:          0 :         pa_assert(!s->auto_timing_update_event);
     965                 :          0 :         s->auto_timing_update_event = pa_context_rttime_new(s->context, pa_rtclock_now() + s->auto_timing_interval_usec, &auto_timing_update_callback, s);
     966                 :            : 
     967                 :          0 :         request_auto_timing_update(s, TRUE);
     968                 :            :     }
     969                 :            : 
     970                 :          0 :     check_smoother_status(s, TRUE, FALSE, FALSE);
     971                 :          0 : }
     972                 :            : 
     973                 :          0 : static void patch_buffer_attr(pa_stream *s, pa_buffer_attr *attr, pa_stream_flags_t *flags) {
     974                 :            :     const char *e;
     975                 :            : 
     976         [ #  # ]:          0 :     pa_assert(s);
     977         [ #  # ]:          0 :     pa_assert(attr);
     978                 :            : 
     979         [ #  # ]:          0 :     if ((e = getenv("PULSE_LATENCY_MSEC"))) {
     980                 :            :         uint32_t ms;
     981                 :            : 
     982 [ #  # ][ #  # ]:          0 :         if (pa_atou(e, &ms) < 0 || ms <= 0)
     983                 :          0 :             pa_log_debug("Failed to parse $PULSE_LATENCY_MSEC: %s", e);
     984                 :            :         else {
     985                 :          0 :             attr->maxlength = (uint32_t) -1;
     986                 :          0 :             attr->tlength = pa_usec_to_bytes(ms * PA_USEC_PER_MSEC, &s->sample_spec);
     987                 :          0 :             attr->minreq = (uint32_t) -1;
     988                 :          0 :             attr->prebuf = (uint32_t) -1;
     989                 :          0 :             attr->fragsize = attr->tlength;
     990                 :            :         }
     991                 :            : 
     992         [ #  # ]:          0 :         if (flags)
     993                 :          0 :             *flags |= PA_STREAM_ADJUST_LATENCY;
     994                 :            :     }
     995                 :            : 
     996         [ #  # ]:          0 :     if (s->context->version >= 13)
     997                 :          0 :         return;
     998                 :            : 
     999                 :            :     /* Version older than 0.9.10 didn't do server side buffer_attr
    1000                 :            :      * selection, hence we have to fake it on the client side. */
    1001                 :            : 
    1002                 :            :     /* We choose fairly conservative values here, to not confuse
    1003                 :            :      * old clients with extremely large playback buffers */
    1004                 :            : 
    1005         [ #  # ]:          0 :     if (attr->maxlength == (uint32_t) -1)
    1006                 :          0 :         attr->maxlength = 4*1024*1024; /* 4MB is the maximum queue length PulseAudio <= 0.9.9 supported. */
    1007                 :            : 
    1008         [ #  # ]:          0 :     if (attr->tlength == (uint32_t) -1)
    1009                 :          0 :         attr->tlength = (uint32_t) pa_usec_to_bytes(250*PA_USEC_PER_MSEC, &s->sample_spec); /* 250ms of buffering */
    1010                 :            : 
    1011         [ #  # ]:          0 :     if (attr->minreq == (uint32_t) -1)
    1012                 :          0 :         attr->minreq = (attr->tlength)/5; /* Ask for more data when there are only 200ms left in the playback buffer */
    1013                 :            : 
    1014         [ #  # ]:          0 :     if (attr->prebuf == (uint32_t) -1)
    1015                 :          0 :         attr->prebuf = attr->tlength; /* Start to play only when the playback is fully filled up once */
    1016                 :            : 
    1017         [ #  # ]:          0 :     if (attr->fragsize == (uint32_t) -1)
    1018                 :          0 :         attr->fragsize = attr->tlength; /* Pass data to the app only when the buffer is filled up once */
    1019                 :            : }
    1020                 :            : 
    1021                 :          0 : void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
    1022                 :          0 :     pa_stream *s = userdata;
    1023                 :          0 :     uint32_t requested_bytes = 0;
    1024                 :            : 
    1025         [ #  # ]:          0 :     pa_assert(pd);
    1026         [ #  # ]:          0 :     pa_assert(s);
    1027         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1028         [ #  # ]:          0 :     pa_assert(s->state == PA_STREAM_CREATING);
    1029                 :            : 
    1030                 :          0 :     pa_stream_ref(s);
    1031                 :            : 
    1032         [ #  # ]:          0 :     if (command != PA_COMMAND_REPLY) {
    1033         [ #  # ]:          0 :         if (pa_context_handle_error(s->context, command, t, FALSE) < 0)
    1034                 :            :             goto finish;
    1035                 :            : 
    1036                 :          0 :         pa_stream_set_state(s, PA_STREAM_FAILED);
    1037                 :          0 :         goto finish;
    1038                 :            :     }
    1039                 :            : 
    1040 [ #  # ][ #  # ]:          0 :     if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
    1041         [ #  # ]:          0 :         s->channel == PA_INVALID_INDEX ||
    1042 [ #  # ][ #  # ]:          0 :         ((s->direction != PA_STREAM_UPLOAD) && (pa_tagstruct_getu32(t, &s->stream_index) < 0 || s->stream_index == PA_INVALID_INDEX)) ||
                 [ #  # ]
    1043         [ #  # ]:          0 :         ((s->direction != PA_STREAM_RECORD) && pa_tagstruct_getu32(t, &requested_bytes) < 0)) {
    1044                 :          0 :         pa_context_fail(s->context, PA_ERR_PROTOCOL);
    1045                 :          0 :         goto finish;
    1046                 :            :     }
    1047                 :            : 
    1048                 :          0 :     s->requested_bytes = (int64_t) requested_bytes;
    1049                 :            : 
    1050         [ #  # ]:          0 :     if (s->context->version >= 9) {
    1051         [ #  # ]:          0 :         if (s->direction == PA_STREAM_PLAYBACK) {
    1052   [ #  #  #  # ]:          0 :             if (pa_tagstruct_getu32(t, &s->buffer_attr.maxlength) < 0 ||
    1053         [ #  # ]:          0 :                 pa_tagstruct_getu32(t, &s->buffer_attr.tlength) < 0 ||
    1054         [ #  # ]:          0 :                 pa_tagstruct_getu32(t, &s->buffer_attr.prebuf) < 0 ||
    1055                 :          0 :                 pa_tagstruct_getu32(t, &s->buffer_attr.minreq) < 0) {
    1056                 :          0 :                 pa_context_fail(s->context, PA_ERR_PROTOCOL);
    1057                 :          0 :                 goto finish;
    1058                 :            :             }
    1059         [ #  # ]:          0 :         } else if (s->direction == PA_STREAM_RECORD) {
    1060   [ #  #  #  # ]:          0 :             if (pa_tagstruct_getu32(t, &s->buffer_attr.maxlength) < 0 ||
    1061                 :          0 :                 pa_tagstruct_getu32(t, &s->buffer_attr.fragsize) < 0) {
    1062                 :          0 :                 pa_context_fail(s->context, PA_ERR_PROTOCOL);
    1063                 :          0 :                 goto finish;
    1064                 :            :             }
    1065                 :            :         }
    1066                 :            :     }
    1067                 :            : 
    1068 [ #  # ][ #  # ]:          0 :     if (s->context->version >= 12 && s->direction != PA_STREAM_UPLOAD) {
    1069                 :            :         pa_sample_spec ss;
    1070                 :            :         pa_channel_map cm;
    1071                 :          0 :         const char *dn = NULL;
    1072                 :            :         pa_bool_t suspended;
    1073                 :            : 
    1074   [ #  #  #  # ]:          0 :         if (pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
    1075         [ #  # ]:          0 :             pa_tagstruct_get_channel_map(t, &cm) < 0 ||
    1076         [ #  # ]:          0 :             pa_tagstruct_getu32(t, &s->device_index) < 0 ||
    1077         [ #  # ]:          0 :             pa_tagstruct_gets(t, &dn) < 0 ||
    1078                 :          0 :             pa_tagstruct_get_boolean(t, &suspended) < 0) {
    1079                 :          0 :             pa_context_fail(s->context, PA_ERR_PROTOCOL);
    1080                 :          0 :             goto finish;
    1081                 :            :         }
    1082                 :            : 
    1083 [ #  # ][ #  # ]:          0 :         if (!dn || s->device_index == PA_INVALID_INDEX ||
                 [ #  # ]
    1084         [ #  # ]:          0 :             ss.channels != cm.channels ||
    1085         [ #  # ]:          0 :             !pa_channel_map_valid(&cm) ||
    1086         [ #  # ]:          0 :             !pa_sample_spec_valid(&ss) ||
    1087         [ #  # ]:          0 :             (s->n_formats == 0 && (
    1088 [ #  # ][ #  # ]:          0 :                 (!(s->flags & PA_STREAM_FIX_FORMAT) && ss.format != s->sample_spec.format) ||
    1089 [ #  # ][ #  # ]:          0 :                 (!(s->flags & PA_STREAM_FIX_RATE) && ss.rate != s->sample_spec.rate) ||
    1090         [ #  # ]:          0 :                 (!(s->flags & PA_STREAM_FIX_CHANNELS) && !pa_channel_map_equal(&cm, &s->channel_map))))) {
    1091                 :          0 :             pa_context_fail(s->context, PA_ERR_PROTOCOL);
    1092                 :          0 :             goto finish;
    1093                 :            :         }
    1094                 :            : 
    1095                 :          0 :         pa_xfree(s->device_name);
    1096                 :          0 :         s->device_name = pa_xstrdup(dn);
    1097                 :          0 :         s->suspended = suspended;
    1098                 :            : 
    1099                 :          0 :         s->channel_map = cm;
    1100                 :          0 :         s->sample_spec = ss;
    1101                 :            :     }
    1102                 :            : 
    1103 [ #  # ][ #  # ]:          0 :     if (s->context->version >= 13 && s->direction != PA_STREAM_UPLOAD) {
    1104                 :            :         pa_usec_t usec;
    1105                 :            : 
    1106         [ #  # ]:          0 :         if (pa_tagstruct_get_usec(t, &usec) < 0) {
    1107                 :          0 :             pa_context_fail(s->context, PA_ERR_PROTOCOL);
    1108                 :          0 :             goto finish;
    1109                 :            :         }
    1110                 :            : 
    1111         [ #  # ]:          0 :         if (s->direction == PA_STREAM_RECORD)
    1112                 :          0 :             s->timing_info.configured_source_usec = usec;
    1113                 :            :         else
    1114                 :          0 :             s->timing_info.configured_sink_usec = usec;
    1115                 :            :     }
    1116                 :            : 
    1117 [ #  # ][ #  # ]:          0 :     if ((s->context->version >= 21 && s->direction == PA_STREAM_PLAYBACK)
    1118         [ #  # ]:          0 :         || s->context->version >= 22) {
    1119                 :            : 
    1120                 :          0 :         pa_format_info *f = pa_format_info_new();
    1121                 :          0 :         pa_tagstruct_get_format_info(t, f);
    1122                 :            : 
    1123         [ #  # ]:          0 :         if (pa_format_info_valid(f))
    1124                 :          0 :             s->format = f;
    1125                 :            :         else {
    1126                 :          0 :             pa_format_info_free(f);
    1127         [ #  # ]:          0 :             if (s->n_formats > 0) {
    1128                 :            :                 /* We used the extended API, so we should have got back a proper format */
    1129                 :          0 :                 pa_context_fail(s->context, PA_ERR_PROTOCOL);
    1130                 :          0 :                 goto finish;
    1131                 :            :             }
    1132                 :            :         }
    1133                 :            :     }
    1134                 :            : 
    1135         [ #  # ]:          0 :     if (!pa_tagstruct_eof(t)) {
    1136                 :          0 :         pa_context_fail(s->context, PA_ERR_PROTOCOL);
    1137                 :          0 :         goto finish;
    1138                 :            :     }
    1139                 :            : 
    1140         [ #  # ]:          0 :     if (s->direction == PA_STREAM_RECORD) {
    1141         [ #  # ]:          0 :         pa_assert(!s->record_memblockq);
    1142                 :            : 
    1143                 :          0 :         s->record_memblockq = pa_memblockq_new(
    1144                 :            :                 "client side record memblockq",
    1145                 :            :                 0,
    1146                 :          0 :                 s->buffer_attr.maxlength,
    1147                 :            :                 0,
    1148                 :          0 :                 &s->sample_spec,
    1149                 :            :                 1,
    1150                 :            :                 0,
    1151                 :            :                 0,
    1152                 :            :                 NULL);
    1153                 :            :     }
    1154                 :            : 
    1155                 :          0 :     s->channel_valid = TRUE;
    1156         [ #  # ]:          0 :     pa_hashmap_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, PA_UINT32_TO_PTR(s->channel), s);
    1157                 :            : 
    1158                 :          0 :     create_stream_complete(s);
    1159                 :            : 
    1160                 :            : finish:
    1161                 :          0 :     pa_stream_unref(s);
    1162                 :          0 : }
    1163                 :            : 
    1164                 :          0 : static int create_stream(
    1165                 :            :         pa_stream_direction_t direction,
    1166                 :            :         pa_stream *s,
    1167                 :            :         const char *dev,
    1168                 :            :         const pa_buffer_attr *attr,
    1169                 :            :         pa_stream_flags_t flags,
    1170                 :            :         const pa_cvolume *volume,
    1171                 :            :         pa_stream *sync_stream) {
    1172                 :            : 
    1173                 :            :     pa_tagstruct *t;
    1174                 :            :     uint32_t tag;
    1175                 :          0 :     pa_bool_t volume_set = !!volume;
    1176                 :            :     pa_cvolume cv;
    1177                 :            :     uint32_t i;
    1178                 :            : 
    1179         [ #  # ]:          0 :     pa_assert(s);
    1180         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1181         [ #  # ]:          0 :     pa_assert(direction == PA_STREAM_PLAYBACK || direction == PA_STREAM_RECORD);
    1182                 :            : 
    1183         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    1184         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
    1185         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direct_on_input == PA_INVALID_INDEX || direction == PA_STREAM_RECORD, PA_ERR_BADSTATE);
    1186         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !(flags & ~(PA_STREAM_START_CORKED|
    1187                 :            :                                               PA_STREAM_INTERPOLATE_TIMING|
    1188                 :            :                                               PA_STREAM_NOT_MONOTONIC|
    1189                 :            :                                               PA_STREAM_AUTO_TIMING_UPDATE|
    1190                 :            :                                               PA_STREAM_NO_REMAP_CHANNELS|
    1191                 :            :                                               PA_STREAM_NO_REMIX_CHANNELS|
    1192                 :            :                                               PA_STREAM_FIX_FORMAT|
    1193                 :            :                                               PA_STREAM_FIX_RATE|
    1194                 :            :                                               PA_STREAM_FIX_CHANNELS|
    1195                 :            :                                               PA_STREAM_DONT_MOVE|
    1196                 :            :                                               PA_STREAM_VARIABLE_RATE|
    1197                 :            :                                               PA_STREAM_PEAK_DETECT|
    1198                 :            :                                               PA_STREAM_START_MUTED|
    1199                 :            :                                               PA_STREAM_ADJUST_LATENCY|
    1200                 :            :                                               PA_STREAM_EARLY_REQUESTS|
    1201                 :            :                                               PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND|
    1202                 :            :                                               PA_STREAM_START_UNMUTED|
    1203                 :            :                                               PA_STREAM_FAIL_ON_SUSPEND|
    1204                 :            :                                               PA_STREAM_RELATIVE_VOLUME|
    1205                 :            :                                               PA_STREAM_PASSTHROUGH)), PA_ERR_INVALID);
    1206                 :            : 
    1207                 :            : 
    1208 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->context->version >= 12 || !(flags & PA_STREAM_VARIABLE_RATE), PA_ERR_NOTSUPPORTED);
    1209 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->context->version >= 13 || !(flags & PA_STREAM_PEAK_DETECT), PA_ERR_NOTSUPPORTED);
    1210         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
    1211                 :            :     /* Although some of the other flags are not supported on older
    1212                 :            :      * version, we don't check for them here, because it doesn't hurt
    1213                 :            :      * when they are passed but actually not supported. This makes
    1214                 :            :      * client development easier */
    1215                 :            : 
    1216 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, direction == PA_STREAM_PLAYBACK || !(flags & (PA_STREAM_START_MUTED)), PA_ERR_INVALID);
    1217 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, direction == PA_STREAM_RECORD || !(flags & (PA_STREAM_PEAK_DETECT)), PA_ERR_INVALID);
    1218 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !volume || s->n_formats || (pa_sample_spec_valid(&s->sample_spec) && volume->channels == s->sample_spec.channels), PA_ERR_INVALID);
         [ #  # ][ #  # ]
    1219 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID);
                 [ #  # ]
    1220         [ #  # ]:          0 :     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);
    1221                 :            : 
    1222                 :          0 :     pa_stream_ref(s);
    1223                 :            : 
    1224                 :          0 :     s->direction = direction;
    1225                 :            : 
    1226         [ #  # ]:          0 :     if (sync_stream)
    1227                 :          0 :         s->syncid = sync_stream->syncid;
    1228                 :            : 
    1229         [ #  # ]:          0 :     if (attr)
    1230                 :          0 :         s->buffer_attr = *attr;
    1231                 :          0 :     patch_buffer_attr(s, &s->buffer_attr, &flags);
    1232                 :            : 
    1233                 :          0 :     s->flags = flags;
    1234                 :          0 :     s->corked = !!(flags & PA_STREAM_START_CORKED);
    1235                 :            : 
    1236         [ #  # ]:          0 :     if (flags & PA_STREAM_INTERPOLATE_TIMING) {
    1237                 :            :         pa_usec_t x;
    1238                 :            : 
    1239                 :          0 :         x = pa_rtclock_now();
    1240                 :            : 
    1241         [ #  # ]:          0 :         pa_assert(!s->smoother);
    1242                 :          0 :         s->smoother = pa_smoother_new(
    1243                 :            :                 SMOOTHER_ADJUST_TIME,
    1244                 :            :                 SMOOTHER_HISTORY_TIME,
    1245                 :          0 :                 !(flags & PA_STREAM_NOT_MONOTONIC),
    1246                 :            :                 TRUE,
    1247                 :            :                 SMOOTHER_MIN_HISTORY,
    1248                 :            :                 x,
    1249                 :            :                 TRUE);
    1250                 :            :     }
    1251                 :            : 
    1252         [ #  # ]:          0 :     if (!dev)
    1253         [ #  # ]:          0 :         dev = s->direction == PA_STREAM_PLAYBACK ? s->context->conf->default_sink : s->context->conf->default_source;
    1254                 :            : 
    1255         [ #  # ]:          0 :     t = pa_tagstruct_command(
    1256                 :            :             s->context,
    1257                 :          0 :             (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM),
    1258                 :            :             &tag);
    1259                 :            : 
    1260         [ #  # ]:          0 :     if (s->context->version < 13)
    1261                 :          0 :         pa_tagstruct_puts(t, pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME));
    1262                 :            : 
    1263                 :          0 :     pa_tagstruct_put(
    1264                 :            :             t,
    1265                 :            :             PA_TAG_SAMPLE_SPEC, &s->sample_spec,
    1266                 :            :             PA_TAG_CHANNEL_MAP, &s->channel_map,
    1267                 :            :             PA_TAG_U32, PA_INVALID_INDEX,
    1268                 :            :             PA_TAG_STRING, dev,
    1269                 :            :             PA_TAG_U32, s->buffer_attr.maxlength,
    1270                 :          0 :             PA_TAG_BOOLEAN, s->corked,
    1271                 :            :             PA_TAG_INVALID);
    1272                 :            : 
    1273         [ #  # ]:          0 :     if (!volume) {
    1274         [ #  # ]:          0 :         if (pa_sample_spec_valid(&s->sample_spec))
    1275                 :          0 :             volume = pa_cvolume_reset(&cv, s->sample_spec.channels);
    1276                 :            :         else {
    1277                 :            :             /* This is not really relevant, since no volume was set, and
    1278                 :            :              * the real number of channels is embedded in the format_info
    1279                 :            :              * structure */
    1280                 :          0 :             volume = pa_cvolume_reset(&cv, PA_CHANNELS_MAX);
    1281                 :            :         }
    1282                 :            :     }
    1283                 :            : 
    1284         [ #  # ]:          0 :     if (s->direction == PA_STREAM_PLAYBACK) {
    1285                 :          0 :         pa_tagstruct_put(
    1286                 :            :                 t,
    1287                 :            :                 PA_TAG_U32, s->buffer_attr.tlength,
    1288                 :            :                 PA_TAG_U32, s->buffer_attr.prebuf,
    1289                 :            :                 PA_TAG_U32, s->buffer_attr.minreq,
    1290                 :            :                 PA_TAG_U32, s->syncid,
    1291                 :            :                 PA_TAG_INVALID);
    1292                 :            : 
    1293                 :          0 :         pa_tagstruct_put_cvolume(t, volume);
    1294                 :            :     } else
    1295                 :          0 :         pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
    1296                 :            : 
    1297         [ #  # ]:          0 :     if (s->context->version >= 12) {
    1298                 :          0 :         pa_tagstruct_put(
    1299                 :            :                 t,
    1300                 :            :                 PA_TAG_BOOLEAN, flags & PA_STREAM_NO_REMAP_CHANNELS,
    1301                 :            :                 PA_TAG_BOOLEAN, flags & PA_STREAM_NO_REMIX_CHANNELS,
    1302                 :            :                 PA_TAG_BOOLEAN, flags & PA_STREAM_FIX_FORMAT,
    1303                 :            :                 PA_TAG_BOOLEAN, flags & PA_STREAM_FIX_RATE,
    1304                 :            :                 PA_TAG_BOOLEAN, flags & PA_STREAM_FIX_CHANNELS,
    1305                 :            :                 PA_TAG_BOOLEAN, flags & PA_STREAM_DONT_MOVE,
    1306                 :            :                 PA_TAG_BOOLEAN, flags & PA_STREAM_VARIABLE_RATE,
    1307                 :            :                 PA_TAG_INVALID);
    1308                 :            :     }
    1309                 :            : 
    1310         [ #  # ]:          0 :     if (s->context->version >= 13) {
    1311                 :            : 
    1312         [ #  # ]:          0 :         if (s->direction == PA_STREAM_PLAYBACK)
    1313                 :          0 :             pa_tagstruct_put_boolean(t, flags & PA_STREAM_START_MUTED);
    1314                 :            :         else
    1315                 :          0 :             pa_tagstruct_put_boolean(t, flags & PA_STREAM_PEAK_DETECT);
    1316                 :            : 
    1317                 :          0 :         pa_tagstruct_put(
    1318                 :            :                 t,
    1319                 :            :                 PA_TAG_BOOLEAN, flags & PA_STREAM_ADJUST_LATENCY,
    1320                 :            :                 PA_TAG_PROPLIST, s->proplist,
    1321                 :            :                 PA_TAG_INVALID);
    1322                 :            : 
    1323         [ #  # ]:          0 :         if (s->direction == PA_STREAM_RECORD)
    1324                 :          0 :             pa_tagstruct_putu32(t, s->direct_on_input);
    1325                 :            :     }
    1326                 :            : 
    1327         [ #  # ]:          0 :     if (s->context->version >= 14) {
    1328                 :            : 
    1329         [ #  # ]:          0 :         if (s->direction == PA_STREAM_PLAYBACK)
    1330                 :          0 :             pa_tagstruct_put_boolean(t, volume_set);
    1331                 :            : 
    1332                 :          0 :         pa_tagstruct_put_boolean(t, flags & PA_STREAM_EARLY_REQUESTS);
    1333                 :            :     }
    1334                 :            : 
    1335         [ #  # ]:          0 :     if (s->context->version >= 15) {
    1336                 :            : 
    1337         [ #  # ]:          0 :         if (s->direction == PA_STREAM_PLAYBACK)
    1338                 :          0 :             pa_tagstruct_put_boolean(t, flags & (PA_STREAM_START_MUTED|PA_STREAM_START_UNMUTED));
    1339                 :            : 
    1340                 :          0 :         pa_tagstruct_put_boolean(t, flags & PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND);
    1341                 :          0 :         pa_tagstruct_put_boolean(t, flags & PA_STREAM_FAIL_ON_SUSPEND);
    1342                 :            :     }
    1343                 :            : 
    1344 [ #  # ][ #  # ]:          0 :     if (s->context->version >= 17 && s->direction == PA_STREAM_PLAYBACK)
    1345                 :          0 :         pa_tagstruct_put_boolean(t, flags & PA_STREAM_RELATIVE_VOLUME);
    1346                 :            : 
    1347 [ #  # ][ #  # ]:          0 :     if (s->context->version >= 18 && s->direction == PA_STREAM_PLAYBACK)
    1348                 :          0 :         pa_tagstruct_put_boolean(t, flags & (PA_STREAM_PASSTHROUGH));
    1349                 :            : 
    1350 [ #  # ][ #  # ]:          0 :     if ((s->context->version >= 21 && s->direction == PA_STREAM_PLAYBACK)
    1351         [ #  # ]:          0 :         || s->context->version >= 22) {
    1352                 :            : 
    1353                 :          0 :         pa_tagstruct_putu8(t, s->n_formats);
    1354         [ #  # ]:          0 :         for (i = 0; i < s->n_formats; i++)
    1355                 :          0 :             pa_tagstruct_put_format_info(t, s->req_formats[i]);
    1356                 :            :     }
    1357                 :            : 
    1358 [ #  # ][ #  # ]:          0 :     if (s->context->version >= 22 && s->direction == PA_STREAM_RECORD) {
    1359                 :          0 :         pa_tagstruct_put_cvolume(t, volume);
    1360                 :          0 :         pa_tagstruct_put_boolean(t, flags & PA_STREAM_START_MUTED);
    1361                 :          0 :         pa_tagstruct_put_boolean(t, volume_set);
    1362                 :          0 :         pa_tagstruct_put_boolean(t, flags & (PA_STREAM_START_MUTED|PA_STREAM_START_UNMUTED));
    1363                 :          0 :         pa_tagstruct_put_boolean(t, flags & PA_STREAM_RELATIVE_VOLUME);
    1364                 :          0 :         pa_tagstruct_put_boolean(t, flags & (PA_STREAM_PASSTHROUGH));
    1365                 :            :     }
    1366                 :            : 
    1367                 :          0 :     pa_pstream_send_tagstruct(s->context->pstream, t);
    1368                 :          0 :     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL);
    1369                 :            : 
    1370                 :          0 :     pa_stream_set_state(s, PA_STREAM_CREATING);
    1371                 :            : 
    1372                 :          0 :     pa_stream_unref(s);
    1373                 :          0 :     return 0;
    1374                 :            : }
    1375                 :            : 
    1376                 :          0 : int pa_stream_connect_playback(
    1377                 :            :         pa_stream *s,
    1378                 :            :         const char *dev,
    1379                 :            :         const pa_buffer_attr *attr,
    1380                 :            :         pa_stream_flags_t flags,
    1381                 :            :         const pa_cvolume *volume,
    1382                 :            :         pa_stream *sync_stream) {
    1383                 :            : 
    1384         [ #  # ]:          0 :     pa_assert(s);
    1385         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1386                 :            : 
    1387                 :          0 :     return create_stream(PA_STREAM_PLAYBACK, s, dev, attr, flags, volume, sync_stream);
    1388                 :            : }
    1389                 :            : 
    1390                 :          0 : int pa_stream_connect_record(
    1391                 :            :         pa_stream *s,
    1392                 :            :         const char *dev,
    1393                 :            :         const pa_buffer_attr *attr,
    1394                 :            :         pa_stream_flags_t flags) {
    1395                 :            : 
    1396         [ #  # ]:          0 :     pa_assert(s);
    1397         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1398                 :            : 
    1399                 :          0 :     return create_stream(PA_STREAM_RECORD, s, dev, attr, flags, NULL, NULL);
    1400                 :            : }
    1401                 :            : 
    1402                 :          0 : int pa_stream_begin_write(
    1403                 :            :         pa_stream *s,
    1404                 :            :         void **data,
    1405                 :            :         size_t *nbytes) {
    1406                 :            : 
    1407         [ #  # ]:          0 :     pa_assert(s);
    1408         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1409                 :            : 
    1410         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    1411         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    1412         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK || s->direction == PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    1413         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, data, PA_ERR_INVALID);
    1414 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, nbytes && *nbytes != 0, PA_ERR_INVALID);
    1415                 :            : 
    1416         [ #  # ]:          0 :     if (*nbytes != (size_t) -1) {
    1417                 :            :         size_t m, fs;
    1418                 :            : 
    1419                 :          0 :         m = pa_mempool_block_size_max(s->context->mempool);
    1420                 :          0 :         fs = pa_frame_size(&s->sample_spec);
    1421                 :            : 
    1422                 :          0 :         m = (m / fs) * fs;
    1423         [ #  # ]:          0 :         if (*nbytes > m)
    1424                 :          0 :             *nbytes = m;
    1425                 :            :     }
    1426                 :            : 
    1427         [ #  # ]:          0 :     if (!s->write_memblock) {
    1428                 :          0 :         s->write_memblock = pa_memblock_new(s->context->mempool, *nbytes);
    1429                 :          0 :         s->write_data = pa_memblock_acquire(s->write_memblock);
    1430                 :            :     }
    1431                 :            : 
    1432                 :          0 :     *data = s->write_data;
    1433                 :          0 :     *nbytes = pa_memblock_get_length(s->write_memblock);
    1434                 :            : 
    1435                 :          0 :     return 0;
    1436                 :            : }
    1437                 :            : 
    1438                 :          0 : int pa_stream_cancel_write(
    1439                 :            :         pa_stream *s) {
    1440                 :            : 
    1441         [ #  # ]:          0 :     pa_assert(s);
    1442         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1443                 :            : 
    1444         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    1445         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    1446         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK || s->direction == PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    1447         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->write_memblock, PA_ERR_BADSTATE);
    1448                 :            : 
    1449         [ #  # ]:          0 :     pa_assert(s->write_data);
    1450                 :            : 
    1451                 :          0 :     pa_memblock_release(s->write_memblock);
    1452                 :          0 :     pa_memblock_unref(s->write_memblock);
    1453                 :          0 :     s->write_memblock = NULL;
    1454                 :          0 :     s->write_data = NULL;
    1455                 :            : 
    1456                 :          0 :     return 0;
    1457                 :            : }
    1458                 :            : 
    1459                 :          0 : int pa_stream_write(
    1460                 :            :         pa_stream *s,
    1461                 :            :         const void *data,
    1462                 :            :         size_t length,
    1463                 :            :         pa_free_cb_t free_cb,
    1464                 :            :         int64_t offset,
    1465                 :            :         pa_seek_mode_t seek) {
    1466                 :            : 
    1467         [ #  # ]:          0 :     pa_assert(s);
    1468         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1469         [ #  # ]:          0 :     pa_assert(data);
    1470                 :            : 
    1471         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    1472         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    1473         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK || s->direction == PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    1474         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, seek <= PA_SEEK_RELATIVE_END, PA_ERR_INVALID);
    1475 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK || (seek == PA_SEEK_RELATIVE && offset == 0), PA_ERR_INVALID);
    1476 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context,
                 [ #  # ]
    1477                 :            :                       !s->write_memblock ||
    1478                 :            :                       ((data >= s->write_data) &&
    1479                 :            :                        ((const char*) data + length <= (const char*) s->write_data + pa_memblock_get_length(s->write_memblock))),
    1480                 :            :                       PA_ERR_INVALID);
    1481 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !free_cb || !s->write_memblock, PA_ERR_INVALID);
    1482                 :            : 
    1483         [ #  # ]:          0 :     if (s->write_memblock) {
    1484                 :            :         pa_memchunk chunk;
    1485                 :            : 
    1486                 :            :         /* pa_stream_write_begin() was called before */
    1487                 :            : 
    1488                 :          0 :         pa_memblock_release(s->write_memblock);
    1489                 :            : 
    1490                 :          0 :         chunk.memblock = s->write_memblock;
    1491                 :          0 :         chunk.index = (const char *) data - (const char *) s->write_data;
    1492                 :          0 :         chunk.length = length;
    1493                 :            : 
    1494                 :          0 :         s->write_memblock = NULL;
    1495                 :          0 :         s->write_data = NULL;
    1496                 :            : 
    1497                 :          0 :         pa_pstream_send_memblock(s->context->pstream, s->channel, offset, seek, &chunk);
    1498                 :          0 :         pa_memblock_unref(chunk.memblock);
    1499                 :            : 
    1500                 :            :     } else {
    1501                 :            :         pa_seek_mode_t t_seek = seek;
    1502                 :            :         int64_t t_offset = offset;
    1503                 :            :         size_t t_length = length;
    1504                 :            :         const void *t_data = data;
    1505                 :            : 
    1506                 :            :         /* pa_stream_write_begin() was not called before */
    1507                 :            : 
    1508         [ #  # ]:          0 :         while (t_length > 0) {
    1509                 :            :             pa_memchunk chunk;
    1510                 :            : 
    1511                 :          0 :             chunk.index = 0;
    1512                 :            : 
    1513 [ #  # ][ #  # ]:          0 :             if (free_cb && !pa_pstream_get_shm(s->context->pstream)) {
    1514                 :          0 :                 chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) t_data, t_length, free_cb, 1);
    1515                 :          0 :                 chunk.length = t_length;
    1516                 :            :             } else {
    1517                 :            :                 void *d;
    1518                 :            : 
    1519                 :          0 :                 chunk.length = PA_MIN(t_length, pa_mempool_block_size_max(s->context->mempool));
    1520                 :          0 :                 chunk.memblock = pa_memblock_new(s->context->mempool, chunk.length);
    1521                 :            : 
    1522                 :          0 :                 d = pa_memblock_acquire(chunk.memblock);
    1523                 :          0 :                 memcpy(d, t_data, chunk.length);
    1524                 :          0 :                 pa_memblock_release(chunk.memblock);
    1525                 :            :             }
    1526                 :            : 
    1527                 :          0 :             pa_pstream_send_memblock(s->context->pstream, s->channel, t_offset, t_seek, &chunk);
    1528                 :            : 
    1529                 :          0 :             t_offset = 0;
    1530                 :          0 :             t_seek = PA_SEEK_RELATIVE;
    1531                 :            : 
    1532                 :          0 :             t_data = (const uint8_t*) t_data + chunk.length;
    1533                 :          0 :             t_length -= chunk.length;
    1534                 :            : 
    1535                 :          0 :             pa_memblock_unref(chunk.memblock);
    1536                 :            :         }
    1537                 :            : 
    1538 [ #  # ][ #  # ]:          0 :         if (free_cb && pa_pstream_get_shm(s->context->pstream))
    1539                 :          0 :             free_cb((void*) data);
    1540                 :            :     }
    1541                 :            : 
    1542                 :            :     /* This is obviously wrong since we ignore the seeking index . But
    1543                 :            :      * that's OK, the server side applies the same error */
    1544         [ #  # ]:          0 :     s->requested_bytes -= (seek == PA_SEEK_RELATIVE ? offset : 0) + (int64_t) length;
    1545                 :            : 
    1546                 :            :     /* pa_log("wrote %lli, now at %lli", (long long) length, (long long) s->requested_bytes); */
    1547                 :            : 
    1548         [ #  # ]:          0 :     if (s->direction == PA_STREAM_PLAYBACK) {
    1549                 :            : 
    1550                 :            :         /* Update latency request correction */
    1551         [ #  # ]:          0 :         if (s->write_index_corrections[s->current_write_index_correction].valid) {
    1552                 :            : 
    1553         [ #  # ]:          0 :             if (seek == PA_SEEK_ABSOLUTE) {
    1554                 :          0 :                 s->write_index_corrections[s->current_write_index_correction].corrupt = FALSE;
    1555                 :          0 :                 s->write_index_corrections[s->current_write_index_correction].absolute = TRUE;
    1556                 :          0 :                 s->write_index_corrections[s->current_write_index_correction].value = offset + (int64_t) length;
    1557         [ #  # ]:          0 :             } else if (seek == PA_SEEK_RELATIVE) {
    1558         [ #  # ]:          0 :                 if (!s->write_index_corrections[s->current_write_index_correction].corrupt)
    1559                 :          0 :                     s->write_index_corrections[s->current_write_index_correction].value += offset + (int64_t) length;
    1560                 :            :             } else
    1561                 :          0 :                 s->write_index_corrections[s->current_write_index_correction].corrupt = TRUE;
    1562                 :            :         }
    1563                 :            : 
    1564                 :            :         /* Update the write index in the already available latency data */
    1565         [ #  # ]:          0 :         if (s->timing_info_valid) {
    1566                 :            : 
    1567         [ #  # ]:          0 :             if (seek == PA_SEEK_ABSOLUTE) {
    1568                 :          0 :                 s->timing_info.write_index_corrupt = FALSE;
    1569                 :          0 :                 s->timing_info.write_index = offset + (int64_t) length;
    1570         [ #  # ]:          0 :             } else if (seek == PA_SEEK_RELATIVE) {
    1571         [ #  # ]:          0 :                 if (!s->timing_info.write_index_corrupt)
    1572                 :          0 :                     s->timing_info.write_index += offset + (int64_t) length;
    1573                 :            :             } else
    1574                 :          0 :                 s->timing_info.write_index_corrupt = TRUE;
    1575                 :            :         }
    1576                 :            : 
    1577 [ #  # ][ #  # ]:          0 :         if (!s->timing_info_valid || s->timing_info.write_index_corrupt)
    1578                 :          0 :             request_auto_timing_update(s, TRUE);
    1579                 :            :     }
    1580                 :            : 
    1581                 :            :     return 0;
    1582                 :            : }
    1583                 :            : 
    1584                 :          0 : int pa_stream_peek(pa_stream *s, const void **data, size_t *length) {
    1585         [ #  # ]:          0 :     pa_assert(s);
    1586         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1587         [ #  # ]:          0 :     pa_assert(data);
    1588         [ #  # ]:          0 :     pa_assert(length);
    1589                 :            : 
    1590         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    1591         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    1592         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE);
    1593                 :            : 
    1594         [ #  # ]:          0 :     if (!s->peek_memchunk.memblock) {
    1595                 :            : 
    1596         [ #  # ]:          0 :         if (pa_memblockq_peek(s->record_memblockq, &s->peek_memchunk) < 0) {
    1597                 :          0 :             *data = NULL;
    1598                 :          0 :             *length = 0;
    1599                 :          0 :             return 0;
    1600                 :            :         }
    1601                 :            : 
    1602                 :          0 :         s->peek_data = pa_memblock_acquire(s->peek_memchunk.memblock);
    1603                 :            :     }
    1604                 :            : 
    1605         [ #  # ]:          0 :     pa_assert(s->peek_data);
    1606                 :          0 :     *data = (uint8_t*) s->peek_data + s->peek_memchunk.index;
    1607                 :          0 :     *length = s->peek_memchunk.length;
    1608                 :          0 :     return 0;
    1609                 :            : }
    1610                 :            : 
    1611                 :          0 : int pa_stream_drop(pa_stream *s) {
    1612         [ #  # ]:          0 :     pa_assert(s);
    1613         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1614                 :            : 
    1615         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    1616         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    1617         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE);
    1618         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->peek_memchunk.memblock, PA_ERR_BADSTATE);
    1619                 :            : 
    1620                 :          0 :     pa_memblockq_drop(s->record_memblockq, s->peek_memchunk.length);
    1621                 :            : 
    1622                 :            :     /* Fix the simulated local read index */
    1623 [ #  # ][ #  # ]:          0 :     if (s->timing_info_valid && !s->timing_info.read_index_corrupt)
    1624                 :          0 :         s->timing_info.read_index += (int64_t) s->peek_memchunk.length;
    1625                 :            : 
    1626         [ #  # ]:          0 :     pa_assert(s->peek_data);
    1627                 :          0 :     pa_memblock_release(s->peek_memchunk.memblock);
    1628                 :          0 :     pa_memblock_unref(s->peek_memchunk.memblock);
    1629                 :          0 :     pa_memchunk_reset(&s->peek_memchunk);
    1630                 :            : 
    1631                 :          0 :     return 0;
    1632                 :            : }
    1633                 :            : 
    1634                 :          0 : size_t pa_stream_writable_size(pa_stream *s) {
    1635         [ #  # ]:          0 :     pa_assert(s);
    1636         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1637                 :            : 
    1638         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, !pa_detect_fork(), PA_ERR_FORKED, (size_t) -1);
    1639         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (size_t) -1);
    1640         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_RECORD, PA_ERR_BADSTATE, (size_t) -1);
    1641                 :            : 
    1642                 :          0 :     return s->requested_bytes > 0 ? (size_t) s->requested_bytes : 0;
    1643                 :            : }
    1644                 :            : 
    1645                 :          0 : size_t pa_stream_readable_size(pa_stream *s) {
    1646         [ #  # ]:          0 :     pa_assert(s);
    1647         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1648                 :            : 
    1649         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, !pa_detect_fork(), PA_ERR_FORKED, (size_t) -1);
    1650         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (size_t) -1);
    1651         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, (size_t) -1);
    1652                 :            : 
    1653                 :          0 :     return pa_memblockq_get_length(s->record_memblockq);
    1654                 :            : }
    1655                 :            : 
    1656                 :          0 : pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) {
    1657                 :            :     pa_operation *o;
    1658                 :            :     pa_tagstruct *t;
    1659                 :            :     uint32_t tag;
    1660                 :            : 
    1661         [ #  # ]:          0 :     pa_assert(s);
    1662         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1663                 :            : 
    1664         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    1665         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    1666         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
    1667                 :            : 
    1668                 :            :     /* Ask for a timing update before we cork/uncork to get the best
    1669                 :            :      * accuracy for the transport latency suitable for the
    1670                 :            :      * check_smoother_status() call in the started callback */
    1671                 :          0 :     request_auto_timing_update(s, TRUE);
    1672                 :            : 
    1673                 :          0 :     o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
    1674                 :            : 
    1675                 :          0 :     t = pa_tagstruct_command(s->context, PA_COMMAND_DRAIN_PLAYBACK_STREAM, &tag);
    1676                 :          0 :     pa_tagstruct_putu32(t, s->channel);
    1677                 :          0 :     pa_pstream_send_tagstruct(s->context->pstream, t);
    1678                 :          0 :     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);
    1679                 :            : 
    1680                 :            :     /* This might cause the read index to continue again, hence
    1681                 :            :      * let's request a timing update */
    1682                 :          0 :     request_auto_timing_update(s, TRUE);
    1683                 :            : 
    1684                 :          0 :     return o;
    1685                 :            : }
    1686                 :            : 
    1687                 :          0 : static pa_usec_t calc_time(pa_stream *s, pa_bool_t ignore_transport) {
    1688                 :            :     pa_usec_t usec;
    1689                 :            : 
    1690         [ #  # ]:          0 :     pa_assert(s);
    1691         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1692         [ #  # ]:          0 :     pa_assert(s->state == PA_STREAM_READY);
    1693         [ #  # ]:          0 :     pa_assert(s->direction != PA_STREAM_UPLOAD);
    1694         [ #  # ]:          0 :     pa_assert(s->timing_info_valid);
    1695 [ #  # ][ #  # ]:          0 :     pa_assert(s->direction != PA_STREAM_PLAYBACK || !s->timing_info.read_index_corrupt);
    1696 [ #  # ][ #  # ]:          0 :     pa_assert(s->direction != PA_STREAM_RECORD || !s->timing_info.write_index_corrupt);
    1697                 :            : 
    1698         [ #  # ]:          0 :     if (s->direction == PA_STREAM_PLAYBACK) {
    1699                 :            :         /* The last byte that was written into the output device
    1700                 :            :          * had this time value associated */
    1701                 :          0 :         usec = pa_bytes_to_usec(s->timing_info.read_index < 0 ? 0 : (uint64_t) s->timing_info.read_index, &s->sample_spec);
    1702                 :            : 
    1703 [ #  # ][ #  # ]:          0 :         if (!s->corked && !s->suspended) {
    1704                 :            : 
    1705         [ #  # ]:          0 :             if (!ignore_transport)
    1706                 :            :                 /* Because the latency info took a little time to come
    1707                 :            :                  * to us, we assume that the real output time is actually
    1708                 :            :                  * a little ahead */
    1709                 :          0 :                 usec += s->timing_info.transport_usec;
    1710                 :            : 
    1711                 :            :             /* However, the output device usually maintains a buffer
    1712                 :            :                too, hence the real sample currently played is a little
    1713                 :            :                back  */
    1714         [ #  # ]:          0 :             if (s->timing_info.sink_usec >= usec)
    1715                 :            :                 usec = 0;
    1716                 :            :             else
    1717                 :          0 :                 usec -= s->timing_info.sink_usec;
    1718                 :            :         }
    1719                 :            : 
    1720                 :            :     } else {
    1721         [ #  # ]:          0 :         pa_assert(s->direction == PA_STREAM_RECORD);
    1722                 :            : 
    1723                 :            :         /* The last byte written into the server side queue had
    1724                 :            :          * this time value associated */
    1725                 :          0 :         usec = pa_bytes_to_usec(s->timing_info.write_index < 0 ? 0 : (uint64_t) s->timing_info.write_index, &s->sample_spec);
    1726                 :            : 
    1727 [ #  # ][ #  # ]:          0 :         if (!s->corked && !s->suspended) {
    1728                 :            : 
    1729         [ #  # ]:          0 :             if (!ignore_transport)
    1730                 :            :                 /* Add transport latency */
    1731                 :          0 :                 usec += s->timing_info.transport_usec;
    1732                 :            : 
    1733                 :            :             /* Add latency of data in device buffer */
    1734                 :          0 :             usec += s->timing_info.source_usec;
    1735                 :            : 
    1736                 :            :             /* If this is a monitor source, we need to correct the
    1737                 :            :              * time by the playback device buffer */
    1738         [ #  # ]:          0 :             if (s->timing_info.sink_usec >= usec)
    1739                 :            :                 usec = 0;
    1740                 :            :             else
    1741                 :          0 :                 usec -= s->timing_info.sink_usec;
    1742                 :            :         }
    1743                 :            :     }
    1744                 :            : 
    1745                 :          0 :     return usec;
    1746                 :            : }
    1747                 :            : 
    1748                 :          0 : static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
    1749                 :          0 :     pa_operation *o = userdata;
    1750                 :            :     struct timeval local, remote, now;
    1751                 :            :     pa_timing_info *i;
    1752                 :          0 :     pa_bool_t playing = FALSE;
    1753                 :          0 :     uint64_t underrun_for = 0, playing_for = 0;
    1754                 :            : 
    1755         [ #  # ]:          0 :     pa_assert(pd);
    1756         [ #  # ]:          0 :     pa_assert(o);
    1757         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(o) >= 1);
    1758                 :            : 
    1759 [ #  # ][ #  # ]:          0 :     if (!o->context || !o->stream)
    1760                 :            :         goto finish;
    1761                 :            : 
    1762                 :          0 :     i = &o->stream->timing_info;
    1763                 :            : 
    1764                 :          0 :     o->stream->timing_info_valid = FALSE;
    1765                 :          0 :     i->write_index_corrupt = TRUE;
    1766                 :          0 :     i->read_index_corrupt = TRUE;
    1767                 :            : 
    1768         [ #  # ]:          0 :     if (command != PA_COMMAND_REPLY) {
    1769         [ #  # ]:          0 :         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
    1770                 :            :             goto finish;
    1771                 :            : 
    1772                 :            :     } else {
    1773                 :            : 
    1774   [ #  #  #  # ]:          0 :         if (pa_tagstruct_get_usec(t, &i->sink_usec) < 0 ||
    1775         [ #  # ]:          0 :             pa_tagstruct_get_usec(t, &i->source_usec) < 0 ||
    1776         [ #  # ]:          0 :             pa_tagstruct_get_boolean(t, &playing) < 0 ||
    1777         [ #  # ]:          0 :             pa_tagstruct_get_timeval(t, &local) < 0 ||
    1778         [ #  # ]:          0 :             pa_tagstruct_get_timeval(t, &remote) < 0 ||
    1779         [ #  # ]:          0 :             pa_tagstruct_gets64(t, &i->write_index) < 0 ||
    1780                 :          0 :             pa_tagstruct_gets64(t, &i->read_index) < 0) {
    1781                 :            : 
    1782                 :          0 :             pa_context_fail(o->context, PA_ERR_PROTOCOL);
    1783                 :          0 :             goto finish;
    1784                 :            :         }
    1785                 :            : 
    1786 [ #  # ][ #  # ]:          0 :         if (o->context->version >= 13 &&
    1787                 :          0 :             o->stream->direction == PA_STREAM_PLAYBACK)
    1788   [ #  #  #  # ]:          0 :             if (pa_tagstruct_getu64(t, &underrun_for) < 0 ||
    1789                 :          0 :                 pa_tagstruct_getu64(t, &playing_for) < 0) {
    1790                 :            : 
    1791                 :          0 :                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
    1792                 :          0 :                 goto finish;
    1793                 :            :             }
    1794                 :            : 
    1795                 :            : 
    1796         [ #  # ]:          0 :         if (!pa_tagstruct_eof(t)) {
    1797                 :          0 :             pa_context_fail(o->context, PA_ERR_PROTOCOL);
    1798                 :          0 :             goto finish;
    1799                 :            :         }
    1800                 :          0 :         o->stream->timing_info_valid = TRUE;
    1801                 :          0 :         i->write_index_corrupt = FALSE;
    1802                 :          0 :         i->read_index_corrupt = FALSE;
    1803                 :            : 
    1804                 :          0 :         i->playing = (int) playing;
    1805         [ #  # ]:          0 :         i->since_underrun = (int64_t) (playing ? playing_for : underrun_for);
    1806                 :            : 
    1807                 :          0 :         pa_gettimeofday(&now);
    1808                 :            : 
    1809                 :            :         /* Calculate timestamps */
    1810 [ #  # ][ #  # ]:          0 :         if (pa_timeval_cmp(&local, &remote) <= 0 && pa_timeval_cmp(&remote, &now) <= 0) {
    1811                 :            :             /* local and remote seem to have synchronized clocks */
    1812                 :            : 
    1813         [ #  # ]:          0 :             if (o->stream->direction == PA_STREAM_PLAYBACK)
    1814                 :          0 :                 i->transport_usec = pa_timeval_diff(&remote, &local);
    1815                 :            :             else
    1816                 :          0 :                 i->transport_usec = pa_timeval_diff(&now, &remote);
    1817                 :            : 
    1818                 :          0 :             i->synchronized_clocks = TRUE;
    1819                 :          0 :             i->timestamp = remote;
    1820                 :            :         } else {
    1821                 :            :             /* clocks are not synchronized, let's estimate latency then */
    1822                 :          0 :             i->transport_usec = pa_timeval_diff(&now, &local)/2;
    1823                 :          0 :             i->synchronized_clocks = FALSE;
    1824                 :          0 :             i->timestamp = local;
    1825                 :          0 :             pa_timeval_add(&i->timestamp, i->transport_usec);
    1826                 :            :         }
    1827                 :            : 
    1828                 :            :         /* Invalidate read and write indexes if necessary */
    1829         [ #  # ]:          0 :         if (tag < o->stream->read_index_not_before)
    1830                 :          0 :             i->read_index_corrupt = TRUE;
    1831                 :            : 
    1832         [ #  # ]:          0 :         if (tag < o->stream->write_index_not_before)
    1833                 :          0 :             i->write_index_corrupt = TRUE;
    1834                 :            : 
    1835         [ #  # ]:          0 :         if (o->stream->direction == PA_STREAM_PLAYBACK) {
    1836                 :            :             /* Write index correction */
    1837                 :            : 
    1838                 :            :             int n, j;
    1839                 :          0 :             uint32_t ctag = tag;
    1840                 :            : 
    1841                 :            :             /* Go through the saved correction values and add up the
    1842                 :            :              * total correction.*/
    1843         [ #  # ]:          0 :             for (n = 0, j = o->stream->current_write_index_correction+1;
    1844                 :            :                  n < PA_MAX_WRITE_INDEX_CORRECTIONS;
    1845                 :          0 :                  n++, j = (j + 1) % PA_MAX_WRITE_INDEX_CORRECTIONS) {
    1846                 :            : 
    1847                 :            :                 /* Step over invalid data or out-of-date data */
    1848 [ #  # ][ #  # ]:          0 :                 if (!o->stream->write_index_corrections[j].valid ||
    1849                 :          0 :                     o->stream->write_index_corrections[j].tag < ctag)
    1850                 :          0 :                     continue;
    1851                 :            : 
    1852                 :            :                 /* Make sure that everything is in order */
    1853                 :          0 :                 ctag = o->stream->write_index_corrections[j].tag+1;
    1854                 :            : 
    1855                 :            :                 /* Now fix the write index */
    1856         [ #  # ]:          0 :                 if (o->stream->write_index_corrections[j].corrupt) {
    1857                 :            :                     /* A corrupting seek was made */
    1858                 :          0 :                     i->write_index_corrupt = TRUE;
    1859         [ #  # ]:          0 :                 } else if (o->stream->write_index_corrections[j].absolute) {
    1860                 :            :                     /* An absolute seek was made */
    1861                 :          0 :                     i->write_index = o->stream->write_index_corrections[j].value;
    1862                 :          0 :                     i->write_index_corrupt = FALSE;
    1863         [ #  # ]:          0 :                 } else if (!i->write_index_corrupt) {
    1864                 :            :                     /* A relative seek was made */
    1865                 :          0 :                     i->write_index += o->stream->write_index_corrections[j].value;
    1866                 :            :                 }
    1867                 :            :             }
    1868                 :            : 
    1869                 :            :             /* Clear old correction entries */
    1870         [ #  # ]:          0 :             for (n = 0; n < PA_MAX_WRITE_INDEX_CORRECTIONS; n++) {
    1871         [ #  # ]:          0 :                 if (!o->stream->write_index_corrections[n].valid)
    1872                 :          0 :                     continue;
    1873                 :            : 
    1874         [ #  # ]:          0 :                 if (o->stream->write_index_corrections[n].tag <= tag)
    1875                 :          0 :                     o->stream->write_index_corrections[n].valid = FALSE;
    1876                 :            :             }
    1877                 :            :         }
    1878                 :            : 
    1879         [ #  # ]:          0 :         if (o->stream->direction == PA_STREAM_RECORD) {
    1880                 :            :             /* Read index correction */
    1881                 :            : 
    1882         [ #  # ]:          0 :             if (!i->read_index_corrupt)
    1883                 :          0 :                 i->read_index -= (int64_t) pa_memblockq_get_length(o->stream->record_memblockq);
    1884                 :            :         }
    1885                 :            : 
    1886                 :            :         /* Update smoother if we're not corked */
    1887 [ #  # ][ #  # ]:          0 :         if (o->stream->smoother && !o->stream->corked) {
    1888                 :            :             pa_usec_t u, x;
    1889                 :            : 
    1890                 :          0 :             u = x = pa_rtclock_now() - i->transport_usec;
    1891                 :            : 
    1892 [ #  # ][ #  # ]:          0 :             if (o->stream->direction == PA_STREAM_PLAYBACK && o->context->version >= 13) {
    1893                 :            :                 pa_usec_t su;
    1894                 :            : 
    1895                 :            :                 /* If we weren't playing then it will take some time
    1896                 :            :                  * until the audio will actually come out through the
    1897                 :            :                  * speakers. Since we follow that timing here, we need
    1898                 :            :                  * to try to fix this up */
    1899                 :            : 
    1900                 :          0 :                 su = pa_bytes_to_usec((uint64_t) i->since_underrun, &o->stream->sample_spec);
    1901                 :            : 
    1902         [ #  # ]:          0 :                 if (su < i->sink_usec)
    1903                 :          0 :                     x += i->sink_usec - su;
    1904                 :            :             }
    1905                 :            : 
    1906         [ #  # ]:          0 :             if (!i->playing)
    1907                 :          0 :                 pa_smoother_pause(o->stream->smoother, x);
    1908                 :            : 
    1909                 :            :             /* Update the smoother */
    1910 [ #  # ][ #  # ]:          0 :             if ((o->stream->direction == PA_STREAM_PLAYBACK && !i->read_index_corrupt) ||
                 [ #  # ]
    1911         [ #  # ]:          0 :                 (o->stream->direction == PA_STREAM_RECORD && !i->write_index_corrupt))
    1912                 :          0 :                 pa_smoother_put(o->stream->smoother, u, calc_time(o->stream, TRUE));
    1913                 :            : 
    1914         [ #  # ]:          0 :             if (i->playing)
    1915                 :          0 :                 pa_smoother_resume(o->stream->smoother, x, TRUE);
    1916                 :            :         }
    1917                 :            :     }
    1918                 :            : 
    1919                 :          0 :     o->stream->auto_timing_update_requested = FALSE;
    1920                 :            : 
    1921         [ #  # ]:          0 :     if (o->stream->latency_update_callback)
    1922                 :          0 :         o->stream->latency_update_callback(o->stream, o->stream->latency_update_userdata);
    1923                 :            : 
    1924 [ #  # ][ #  # ]:          0 :     if (o->callback && o->stream && o->stream->state == PA_STREAM_READY) {
                 [ #  # ]
    1925                 :          0 :         pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback;
    1926                 :          0 :         cb(o->stream, o->stream->timing_info_valid, o->userdata);
    1927                 :            :     }
    1928                 :            : 
    1929                 :            : finish:
    1930                 :            : 
    1931                 :          0 :     pa_operation_done(o);
    1932                 :          0 :     pa_operation_unref(o);
    1933                 :          0 : }
    1934                 :            : 
    1935                 :          0 : pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) {
    1936                 :            :     uint32_t tag;
    1937                 :            :     pa_operation *o;
    1938                 :            :     pa_tagstruct *t;
    1939                 :            :     struct timeval now;
    1940                 :          0 :     int cidx = 0;
    1941                 :            : 
    1942         [ #  # ]:          0 :     pa_assert(s);
    1943         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1944                 :            : 
    1945         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    1946         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    1947         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    1948                 :            : 
    1949         [ #  # ]:          0 :     if (s->direction == PA_STREAM_PLAYBACK) {
    1950                 :            :         /* Find a place to store the write_index correction data for this entry */
    1951                 :          0 :         cidx = (s->current_write_index_correction + 1) % PA_MAX_WRITE_INDEX_CORRECTIONS;
    1952                 :            : 
    1953                 :            :         /* Check if we could allocate a correction slot. If not, there are too many outstanding queries */
    1954         [ #  # ]:          0 :         PA_CHECK_VALIDITY_RETURN_NULL(s->context, !s->write_index_corrections[cidx].valid, PA_ERR_INTERNAL);
    1955                 :            :     }
    1956                 :          0 :     o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
    1957                 :            : 
    1958         [ #  # ]:          0 :     t = pa_tagstruct_command(
    1959                 :            :             s->context,
    1960                 :          0 :             (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY),
    1961                 :            :             &tag);
    1962                 :          0 :     pa_tagstruct_putu32(t, s->channel);
    1963                 :          0 :     pa_tagstruct_put_timeval(t, pa_gettimeofday(&now));
    1964                 :            : 
    1965                 :          0 :     pa_pstream_send_tagstruct(s->context->pstream, t);
    1966                 :          0 :     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);
    1967                 :            : 
    1968         [ #  # ]:          0 :     if (s->direction == PA_STREAM_PLAYBACK) {
    1969                 :            :         /* Fill in initial correction data */
    1970                 :            : 
    1971                 :          0 :         s->current_write_index_correction = cidx;
    1972                 :            : 
    1973                 :          0 :         s->write_index_corrections[cidx].valid = TRUE;
    1974                 :          0 :         s->write_index_corrections[cidx].absolute = FALSE;
    1975                 :          0 :         s->write_index_corrections[cidx].corrupt = FALSE;
    1976                 :          0 :         s->write_index_corrections[cidx].tag = tag;
    1977                 :          0 :         s->write_index_corrections[cidx].value = 0;
    1978                 :            :     }
    1979                 :            : 
    1980                 :            :     return o;
    1981                 :            : }
    1982                 :            : 
    1983                 :          0 : void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
    1984                 :          0 :     pa_stream *s = userdata;
    1985                 :            : 
    1986         [ #  # ]:          0 :     pa_assert(pd);
    1987         [ #  # ]:          0 :     pa_assert(s);
    1988         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    1989                 :            : 
    1990                 :          0 :     pa_stream_ref(s);
    1991                 :            : 
    1992         [ #  # ]:          0 :     if (command != PA_COMMAND_REPLY) {
    1993         [ #  # ]:          0 :         if (pa_context_handle_error(s->context, command, t, FALSE) < 0)
    1994                 :            :             goto finish;
    1995                 :            : 
    1996                 :          0 :         pa_stream_set_state(s, PA_STREAM_FAILED);
    1997                 :          0 :         goto finish;
    1998         [ #  # ]:          0 :     } else if (!pa_tagstruct_eof(t)) {
    1999                 :          0 :         pa_context_fail(s->context, PA_ERR_PROTOCOL);
    2000                 :          0 :         goto finish;
    2001                 :            :     }
    2002                 :            : 
    2003                 :          0 :     pa_stream_set_state(s, PA_STREAM_TERMINATED);
    2004                 :            : 
    2005                 :            : finish:
    2006                 :          0 :     pa_stream_unref(s);
    2007                 :          0 : }
    2008                 :            : 
    2009                 :          0 : int pa_stream_disconnect(pa_stream *s) {
    2010                 :            :     pa_tagstruct *t;
    2011                 :            :     uint32_t tag;
    2012                 :            : 
    2013         [ #  # ]:          0 :     pa_assert(s);
    2014         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2015                 :            : 
    2016         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2017         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->channel_valid, PA_ERR_BADSTATE);
    2018         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
    2019                 :            : 
    2020                 :          0 :     pa_stream_ref(s);
    2021                 :            : 
    2022 [ #  # ][ #  # ]:          0 :     t = pa_tagstruct_command(
    2023                 :            :             s->context,
    2024                 :          0 :             (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
    2025                 :          0 :                         (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)),
    2026                 :            :             &tag);
    2027                 :          0 :     pa_tagstruct_putu32(t, s->channel);
    2028                 :          0 :     pa_pstream_send_tagstruct(s->context->pstream, t);
    2029                 :          0 :     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s, NULL);
    2030                 :            : 
    2031                 :          0 :     pa_stream_unref(s);
    2032                 :          0 :     return 0;
    2033                 :            : }
    2034                 :            : 
    2035                 :          0 : void pa_stream_set_read_callback(pa_stream *s, pa_stream_request_cb_t cb, void *userdata) {
    2036         [ #  # ]:          0 :     pa_assert(s);
    2037         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2038                 :            : 
    2039         [ #  # ]:          0 :     if (pa_detect_fork())
    2040                 :            :         return;
    2041                 :            : 
    2042         [ #  # ]:          0 :     if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
    2043                 :            :         return;
    2044                 :            : 
    2045                 :          0 :     s->read_callback = cb;
    2046                 :          0 :     s->read_userdata = userdata;
    2047                 :            : }
    2048                 :            : 
    2049                 :          0 : void pa_stream_set_write_callback(pa_stream *s, pa_stream_request_cb_t cb, void *userdata) {
    2050         [ #  # ]:          0 :     pa_assert(s);
    2051         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2052                 :            : 
    2053         [ #  # ]:          0 :     if (pa_detect_fork())
    2054                 :            :         return;
    2055                 :            : 
    2056         [ #  # ]:          0 :     if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
    2057                 :            :         return;
    2058                 :            : 
    2059                 :          0 :     s->write_callback = cb;
    2060                 :          0 :     s->write_userdata = userdata;
    2061                 :            : }
    2062                 :            : 
    2063                 :          0 : void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
    2064         [ #  # ]:          0 :     pa_assert(s);
    2065         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2066                 :            : 
    2067         [ #  # ]:          0 :     if (pa_detect_fork())
    2068                 :            :         return;
    2069                 :            : 
    2070         [ #  # ]:          0 :     if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
    2071                 :            :         return;
    2072                 :            : 
    2073                 :          0 :     s->state_callback = cb;
    2074                 :          0 :     s->state_userdata = userdata;
    2075                 :            : }
    2076                 :            : 
    2077                 :          0 : void pa_stream_set_overflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
    2078         [ #  # ]:          0 :     pa_assert(s);
    2079         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2080                 :            : 
    2081         [ #  # ]:          0 :     if (pa_detect_fork())
    2082                 :            :         return;
    2083                 :            : 
    2084         [ #  # ]:          0 :     if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
    2085                 :            :         return;
    2086                 :            : 
    2087                 :          0 :     s->overflow_callback = cb;
    2088                 :          0 :     s->overflow_userdata = userdata;
    2089                 :            : }
    2090                 :            : 
    2091                 :          0 : void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
    2092         [ #  # ]:          0 :     pa_assert(s);
    2093         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2094                 :            : 
    2095         [ #  # ]:          0 :     if (pa_detect_fork())
    2096                 :            :         return;
    2097                 :            : 
    2098         [ #  # ]:          0 :     if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
    2099                 :            :         return;
    2100                 :            : 
    2101                 :          0 :     s->underflow_callback = cb;
    2102                 :          0 :     s->underflow_userdata = userdata;
    2103                 :            : }
    2104                 :            : 
    2105                 :          0 : void pa_stream_set_latency_update_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
    2106         [ #  # ]:          0 :     pa_assert(s);
    2107         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2108                 :            : 
    2109         [ #  # ]:          0 :     if (pa_detect_fork())
    2110                 :            :         return;
    2111                 :            : 
    2112         [ #  # ]:          0 :     if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
    2113                 :            :         return;
    2114                 :            : 
    2115                 :          0 :     s->latency_update_callback = cb;
    2116                 :          0 :     s->latency_update_userdata = userdata;
    2117                 :            : }
    2118                 :            : 
    2119                 :          0 : void pa_stream_set_moved_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
    2120         [ #  # ]:          0 :     pa_assert(s);
    2121         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2122                 :            : 
    2123         [ #  # ]:          0 :     if (pa_detect_fork())
    2124                 :            :         return;
    2125                 :            : 
    2126         [ #  # ]:          0 :     if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
    2127                 :            :         return;
    2128                 :            : 
    2129                 :          0 :     s->moved_callback = cb;
    2130                 :          0 :     s->moved_userdata = userdata;
    2131                 :            : }
    2132                 :            : 
    2133                 :          0 : void pa_stream_set_suspended_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
    2134         [ #  # ]:          0 :     pa_assert(s);
    2135         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2136                 :            : 
    2137         [ #  # ]:          0 :     if (pa_detect_fork())
    2138                 :            :         return;
    2139                 :            : 
    2140         [ #  # ]:          0 :     if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
    2141                 :            :         return;
    2142                 :            : 
    2143                 :          0 :     s->suspended_callback = cb;
    2144                 :          0 :     s->suspended_userdata = userdata;
    2145                 :            : }
    2146                 :            : 
    2147                 :          0 : void pa_stream_set_started_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
    2148         [ #  # ]:          0 :     pa_assert(s);
    2149         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2150                 :            : 
    2151         [ #  # ]:          0 :     if (pa_detect_fork())
    2152                 :            :         return;
    2153                 :            : 
    2154         [ #  # ]:          0 :     if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
    2155                 :            :         return;
    2156                 :            : 
    2157                 :          0 :     s->started_callback = cb;
    2158                 :          0 :     s->started_userdata = userdata;
    2159                 :            : }
    2160                 :            : 
    2161                 :          0 : void pa_stream_set_event_callback(pa_stream *s, pa_stream_event_cb_t cb, void *userdata) {
    2162         [ #  # ]:          0 :     pa_assert(s);
    2163         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2164                 :            : 
    2165         [ #  # ]:          0 :     if (pa_detect_fork())
    2166                 :            :         return;
    2167                 :            : 
    2168         [ #  # ]:          0 :     if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
    2169                 :            :         return;
    2170                 :            : 
    2171                 :          0 :     s->event_callback = cb;
    2172                 :          0 :     s->event_userdata = userdata;
    2173                 :            : }
    2174                 :            : 
    2175                 :          0 : void pa_stream_set_buffer_attr_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
    2176         [ #  # ]:          0 :     pa_assert(s);
    2177         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2178                 :            : 
    2179         [ #  # ]:          0 :     if (pa_detect_fork())
    2180                 :            :         return;
    2181                 :            : 
    2182         [ #  # ]:          0 :     if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
    2183                 :            :         return;
    2184                 :            : 
    2185                 :          0 :     s->buffer_attr_callback = cb;
    2186                 :          0 :     s->buffer_attr_userdata = userdata;
    2187                 :            : }
    2188                 :            : 
    2189                 :          0 : void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
    2190                 :          0 :     pa_operation *o = userdata;
    2191                 :          0 :     int success = 1;
    2192                 :            : 
    2193         [ #  # ]:          0 :     pa_assert(pd);
    2194         [ #  # ]:          0 :     pa_assert(o);
    2195         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(o) >= 1);
    2196                 :            : 
    2197         [ #  # ]:          0 :     if (!o->context)
    2198                 :            :         goto finish;
    2199                 :            : 
    2200         [ #  # ]:          0 :     if (command != PA_COMMAND_REPLY) {
    2201         [ #  # ]:          0 :         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
    2202                 :            :             goto finish;
    2203                 :            : 
    2204                 :            :         success = 0;
    2205         [ #  # ]:          0 :     } else if (!pa_tagstruct_eof(t)) {
    2206                 :          0 :         pa_context_fail(o->context, PA_ERR_PROTOCOL);
    2207                 :          0 :         goto finish;
    2208                 :            :     }
    2209                 :            : 
    2210         [ #  # ]:          0 :     if (o->callback) {
    2211                 :          0 :         pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback;
    2212                 :          0 :         cb(o->stream, success, o->userdata);
    2213                 :            :     }
    2214                 :            : 
    2215                 :            : finish:
    2216                 :          0 :     pa_operation_done(o);
    2217                 :          0 :     pa_operation_unref(o);
    2218                 :          0 : }
    2219                 :            : 
    2220                 :          0 : pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata) {
    2221                 :            :     pa_operation *o;
    2222                 :            :     pa_tagstruct *t;
    2223                 :            :     uint32_t tag;
    2224                 :            : 
    2225         [ #  # ]:          0 :     pa_assert(s);
    2226         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2227                 :            : 
    2228         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2229         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2230         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2231                 :            : 
    2232                 :            :     /* Ask for a timing update before we cork/uncork to get the best
    2233                 :            :      * accuracy for the transport latency suitable for the
    2234                 :            :      * check_smoother_status() call in the started callback */
    2235                 :          0 :     request_auto_timing_update(s, TRUE);
    2236                 :            : 
    2237                 :          0 :     s->corked = b;
    2238                 :            : 
    2239                 :          0 :     o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
    2240                 :            : 
    2241         [ #  # ]:          0 :     t = pa_tagstruct_command(
    2242                 :            :             s->context,
    2243                 :          0 :             (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CORK_PLAYBACK_STREAM : PA_COMMAND_CORK_RECORD_STREAM),
    2244                 :            :             &tag);
    2245                 :          0 :     pa_tagstruct_putu32(t, s->channel);
    2246                 :          0 :     pa_tagstruct_put_boolean(t, !!b);
    2247                 :          0 :     pa_pstream_send_tagstruct(s->context->pstream, t);
    2248                 :          0 :     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);
    2249                 :            : 
    2250                 :          0 :     check_smoother_status(s, FALSE, FALSE, FALSE);
    2251                 :            : 
    2252                 :            :     /* This might cause the indexes to hang/start again, hence let's
    2253                 :            :      * request a timing update, after the cork/uncork, too */
    2254                 :          0 :     request_auto_timing_update(s, TRUE);
    2255                 :            : 
    2256                 :          0 :     return o;
    2257                 :            : }
    2258                 :            : 
    2259                 :          0 : static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, pa_stream_success_cb_t cb, void *userdata) {
    2260                 :            :     pa_tagstruct *t;
    2261                 :            :     pa_operation *o;
    2262                 :            :     uint32_t tag;
    2263                 :            : 
    2264         [ #  # ]:          0 :     pa_assert(s);
    2265         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2266                 :            : 
    2267         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2268         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2269                 :            : 
    2270                 :          0 :     o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
    2271                 :            : 
    2272                 :          0 :     t = pa_tagstruct_command(s->context, command, &tag);
    2273                 :          0 :     pa_tagstruct_putu32(t, s->channel);
    2274                 :          0 :     pa_pstream_send_tagstruct(s->context->pstream, t);
    2275                 :          0 :     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);
    2276                 :            : 
    2277                 :          0 :     return o;
    2278                 :            : }
    2279                 :            : 
    2280                 :          0 : pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) {
    2281                 :            :     pa_operation *o;
    2282                 :            : 
    2283         [ #  # ]:          0 :     pa_assert(s);
    2284         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2285                 :            : 
    2286         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2287         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2288         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2289                 :            : 
    2290                 :            :     /* Ask for a timing update *before* the flush, so that the
    2291                 :            :      * transport usec is as up to date as possible when we get the
    2292                 :            :      * underflow message and update the smoother status*/
    2293                 :          0 :     request_auto_timing_update(s, TRUE);
    2294                 :            : 
    2295 [ #  # ][ #  # ]:          0 :     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)))
    2296                 :            :         return NULL;
    2297                 :            : 
    2298         [ #  # ]:          0 :     if (s->direction == PA_STREAM_PLAYBACK) {
    2299                 :            : 
    2300         [ #  # ]:          0 :         if (s->write_index_corrections[s->current_write_index_correction].valid)
    2301                 :          0 :             s->write_index_corrections[s->current_write_index_correction].corrupt = TRUE;
    2302                 :            : 
    2303         [ #  # ]:          0 :         if (s->buffer_attr.prebuf > 0)
    2304                 :          0 :             check_smoother_status(s, FALSE, FALSE, TRUE);
    2305                 :            : 
    2306                 :            :         /* This will change the write index, but leave the
    2307                 :            :          * read index untouched. */
    2308                 :          0 :         invalidate_indexes(s, FALSE, TRUE);
    2309                 :            : 
    2310                 :            :     } else
    2311                 :            :         /* For record streams this has no influence on the write
    2312                 :            :          * index, but the read index might jump. */
    2313                 :          0 :         invalidate_indexes(s, TRUE, FALSE);
    2314                 :            : 
    2315                 :            :     /* Note that we do not update requested_bytes here. This is
    2316                 :            :      * because we cannot really know how data actually was dropped
    2317                 :            :      * from the write index due to this. This 'error' will be applied
    2318                 :            :      * by both client and server and hence we should be fine. */
    2319                 :            : 
    2320                 :            :     return o;
    2321                 :            : }
    2322                 :            : 
    2323                 :          0 : pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) {
    2324                 :            :     pa_operation *o;
    2325                 :            : 
    2326         [ #  # ]:          0 :     pa_assert(s);
    2327         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2328                 :            : 
    2329         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2330         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2331         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
    2332         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
    2333                 :            : 
    2334                 :            :     /* Ask for a timing update before we cork/uncork to get the best
    2335                 :            :      * accuracy for the transport latency suitable for the
    2336                 :            :      * check_smoother_status() call in the started callback */
    2337                 :          0 :     request_auto_timing_update(s, TRUE);
    2338                 :            : 
    2339         [ #  # ]:          0 :     if (!(o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata)))
    2340                 :            :         return NULL;
    2341                 :            : 
    2342                 :            :     /* This might cause the read index to hang again, hence
    2343                 :            :      * let's request a timing update */
    2344                 :          0 :     request_auto_timing_update(s, TRUE);
    2345                 :            : 
    2346                 :          0 :     return o;
    2347                 :            : }
    2348                 :            : 
    2349                 :          0 : pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) {
    2350                 :            :     pa_operation *o;
    2351                 :            : 
    2352         [ #  # ]:          0 :     pa_assert(s);
    2353         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2354                 :            : 
    2355         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2356         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2357         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
    2358         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
    2359                 :            : 
    2360                 :            :     /* Ask for a timing update before we cork/uncork to get the best
    2361                 :            :      * accuracy for the transport latency suitable for the
    2362                 :            :      * check_smoother_status() call in the started callback */
    2363                 :          0 :     request_auto_timing_update(s, TRUE);
    2364                 :            : 
    2365         [ #  # ]:          0 :     if (!(o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata)))
    2366                 :            :         return NULL;
    2367                 :            : 
    2368                 :            :     /* This might cause the read index to start moving again, hence
    2369                 :            :      * let's request a timing update */
    2370                 :          0 :     request_auto_timing_update(s, TRUE);
    2371                 :            : 
    2372                 :          0 :     return o;
    2373                 :            : }
    2374                 :            : 
    2375                 :          0 : pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_success_cb_t cb, void *userdata) {
    2376                 :            :     pa_operation *o;
    2377                 :            : 
    2378         [ #  # ]:          0 :     pa_assert(s);
    2379         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2380         [ #  # ]:          0 :     pa_assert(name);
    2381                 :            : 
    2382         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2383         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2384         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2385                 :            : 
    2386         [ #  # ]:          0 :     if (s->context->version >= 13) {
    2387                 :          0 :         pa_proplist *p = pa_proplist_new();
    2388                 :            : 
    2389                 :          0 :         pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
    2390                 :          0 :         o = pa_stream_proplist_update(s, PA_UPDATE_REPLACE, p, cb, userdata);
    2391                 :          0 :         pa_proplist_free(p);
    2392                 :            :     } else {
    2393                 :            :         pa_tagstruct *t;
    2394                 :            :         uint32_t tag;
    2395                 :            : 
    2396                 :          0 :         o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
    2397         [ #  # ]:          0 :         t = pa_tagstruct_command(
    2398                 :            :                 s->context,
    2399                 :          0 :                 (uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_NAME : PA_COMMAND_SET_PLAYBACK_STREAM_NAME),
    2400                 :            :                 &tag);
    2401                 :          0 :         pa_tagstruct_putu32(t, s->channel);
    2402                 :          0 :         pa_tagstruct_puts(t, name);
    2403                 :          0 :         pa_pstream_send_tagstruct(s->context->pstream, t);
    2404                 :          0 :         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);
    2405                 :            :     }
    2406                 :            : 
    2407                 :          0 :     return o;
    2408                 :            : }
    2409                 :            : 
    2410                 :          0 : int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) {
    2411                 :            :     pa_usec_t usec;
    2412                 :            : 
    2413         [ #  # ]:          0 :     pa_assert(s);
    2414         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2415                 :            : 
    2416         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2417         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2418         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2419         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->timing_info_valid, PA_ERR_NODATA);
    2420 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->timing_info.read_index_corrupt, PA_ERR_NODATA);
    2421 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_RECORD || !s->timing_info.write_index_corrupt, PA_ERR_NODATA);
    2422                 :            : 
    2423         [ #  # ]:          0 :     if (s->smoother)
    2424                 :          0 :         usec = pa_smoother_get(s->smoother, pa_rtclock_now());
    2425                 :            :     else
    2426                 :          0 :         usec = calc_time(s, FALSE);
    2427                 :            : 
    2428                 :            :     /* Make sure the time runs monotonically */
    2429         [ #  # ]:          0 :     if (!(s->flags & PA_STREAM_NOT_MONOTONIC)) {
    2430         [ #  # ]:          0 :         if (usec < s->previous_time)
    2431                 :          0 :             usec = s->previous_time;
    2432                 :            :         else
    2433                 :          0 :             s->previous_time = usec;
    2434                 :            :     }
    2435                 :            : 
    2436         [ #  # ]:          0 :     if (r_usec)
    2437                 :          0 :         *r_usec = usec;
    2438                 :            : 
    2439                 :            :     return 0;
    2440                 :            : }
    2441                 :            : 
    2442                 :          0 : static pa_usec_t time_counter_diff(pa_stream *s, pa_usec_t a, pa_usec_t b, int *negative) {
    2443         [ #  # ]:          0 :     pa_assert(s);
    2444         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2445                 :            : 
    2446         [ #  # ]:          0 :     if (negative)
    2447                 :          0 :         *negative = 0;
    2448                 :            : 
    2449         [ #  # ]:          0 :     if (a >= b)
    2450                 :          0 :         return a-b;
    2451                 :            :     else {
    2452 [ #  # ][ #  # ]:          0 :         if (negative && s->direction == PA_STREAM_RECORD) {
    2453                 :          0 :             *negative = 1;
    2454                 :          0 :             return b-a;
    2455                 :            :         } else
    2456                 :            :             return 0;
    2457                 :            :     }
    2458                 :            : }
    2459                 :            : 
    2460                 :          0 : int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) {
    2461                 :            :     pa_usec_t t, c;
    2462                 :            :     int r;
    2463                 :            :     int64_t cindex;
    2464                 :            : 
    2465         [ #  # ]:          0 :     pa_assert(s);
    2466         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2467         [ #  # ]:          0 :     pa_assert(r_usec);
    2468                 :            : 
    2469         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2470         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2471         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2472         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->timing_info_valid, PA_ERR_NODATA);
    2473 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->timing_info.write_index_corrupt, PA_ERR_NODATA);
    2474 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_RECORD || !s->timing_info.read_index_corrupt, PA_ERR_NODATA);
    2475                 :            : 
    2476         [ #  # ]:          0 :     if ((r = pa_stream_get_time(s, &t)) < 0)
    2477                 :            :         return r;
    2478                 :            : 
    2479         [ #  # ]:          0 :     if (s->direction == PA_STREAM_PLAYBACK)
    2480                 :          0 :         cindex = s->timing_info.write_index;
    2481                 :            :     else
    2482                 :          0 :         cindex = s->timing_info.read_index;
    2483                 :            : 
    2484         [ #  # ]:          0 :     if (cindex < 0)
    2485                 :          0 :         cindex = 0;
    2486                 :            : 
    2487                 :          0 :     c = pa_bytes_to_usec((uint64_t) cindex, &s->sample_spec);
    2488                 :            : 
    2489         [ #  # ]:          0 :     if (s->direction == PA_STREAM_PLAYBACK)
    2490                 :          0 :         *r_usec = time_counter_diff(s, c, t, negative);
    2491                 :            :     else
    2492                 :          0 :         *r_usec = time_counter_diff(s, t, c, negative);
    2493                 :            : 
    2494                 :            :     return 0;
    2495                 :            : }
    2496                 :            : 
    2497                 :          0 : const pa_timing_info* pa_stream_get_timing_info(pa_stream *s) {
    2498         [ #  # ]:          0 :     pa_assert(s);
    2499         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2500                 :            : 
    2501         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2502         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2503         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2504         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->timing_info_valid, PA_ERR_NODATA);
    2505                 :            : 
    2506                 :          0 :     return &s->timing_info;
    2507                 :            : }
    2508                 :            : 
    2509                 :          0 : const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s) {
    2510         [ #  # ]:          0 :     pa_assert(s);
    2511         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2512                 :            : 
    2513         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2514                 :            : 
    2515                 :          0 :     return &s->sample_spec;
    2516                 :            : }
    2517                 :            : 
    2518                 :          0 : const pa_channel_map* pa_stream_get_channel_map(pa_stream *s) {
    2519         [ #  # ]:          0 :     pa_assert(s);
    2520         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2521                 :            : 
    2522         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2523                 :            : 
    2524                 :          0 :     return &s->channel_map;
    2525                 :            : }
    2526                 :            : 
    2527                 :          0 : const pa_format_info* pa_stream_get_format_info(pa_stream *s) {
    2528         [ #  # ]:          0 :     pa_assert(s);
    2529         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2530                 :            : 
    2531                 :            :     /* We don't have the format till routing is done */
    2532         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2533         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2534                 :            : 
    2535                 :          0 :     return s->format;
    2536                 :            : }
    2537                 :          0 : const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s) {
    2538         [ #  # ]:          0 :     pa_assert(s);
    2539         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2540                 :            : 
    2541         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2542         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2543         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 9, PA_ERR_NOTSUPPORTED);
    2544                 :            : 
    2545                 :          0 :     return &s->buffer_attr;
    2546                 :            : }
    2547                 :            : 
    2548                 :          0 : static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
    2549                 :          0 :     pa_operation *o = userdata;
    2550                 :          0 :     int success = 1;
    2551                 :            : 
    2552         [ #  # ]:          0 :     pa_assert(pd);
    2553         [ #  # ]:          0 :     pa_assert(o);
    2554         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(o) >= 1);
    2555                 :            : 
    2556         [ #  # ]:          0 :     if (!o->context)
    2557                 :            :         goto finish;
    2558                 :            : 
    2559         [ #  # ]:          0 :     if (command != PA_COMMAND_REPLY) {
    2560         [ #  # ]:          0 :         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
    2561                 :            :             goto finish;
    2562                 :            : 
    2563                 :            :         success = 0;
    2564                 :            :     } else {
    2565         [ #  # ]:          0 :         if (o->stream->direction == PA_STREAM_PLAYBACK) {
    2566   [ #  #  #  # ]:          0 :             if (pa_tagstruct_getu32(t, &o->stream->buffer_attr.maxlength) < 0 ||
    2567         [ #  # ]:          0 :                 pa_tagstruct_getu32(t, &o->stream->buffer_attr.tlength) < 0 ||
    2568         [ #  # ]:          0 :                 pa_tagstruct_getu32(t, &o->stream->buffer_attr.prebuf) < 0 ||
    2569                 :          0 :                 pa_tagstruct_getu32(t, &o->stream->buffer_attr.minreq) < 0) {
    2570                 :          0 :                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
    2571                 :          0 :                 goto finish;
    2572                 :            :             }
    2573         [ #  # ]:          0 :         } else if (o->stream->direction == PA_STREAM_RECORD) {
    2574   [ #  #  #  # ]:          0 :             if (pa_tagstruct_getu32(t, &o->stream->buffer_attr.maxlength) < 0 ||
    2575                 :          0 :                 pa_tagstruct_getu32(t, &o->stream->buffer_attr.fragsize) < 0) {
    2576                 :          0 :                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
    2577                 :          0 :                 goto finish;
    2578                 :            :             }
    2579                 :            :         }
    2580                 :            : 
    2581         [ #  # ]:          0 :         if (o->stream->context->version >= 13) {
    2582                 :            :             pa_usec_t usec;
    2583                 :            : 
    2584         [ #  # ]:          0 :             if (pa_tagstruct_get_usec(t, &usec) < 0) {
    2585                 :          0 :                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
    2586                 :          0 :                 goto finish;
    2587                 :            :             }
    2588                 :            : 
    2589         [ #  # ]:          0 :             if (o->stream->direction == PA_STREAM_RECORD)
    2590                 :          0 :                 o->stream->timing_info.configured_source_usec = usec;
    2591                 :            :             else
    2592                 :          0 :                 o->stream->timing_info.configured_sink_usec = usec;
    2593                 :            :         }
    2594                 :            : 
    2595         [ #  # ]:          0 :         if (!pa_tagstruct_eof(t)) {
    2596                 :          0 :             pa_context_fail(o->context, PA_ERR_PROTOCOL);
    2597                 :          0 :             goto finish;
    2598                 :            :         }
    2599                 :            :     }
    2600                 :            : 
    2601         [ #  # ]:          0 :     if (o->callback) {
    2602                 :          0 :         pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback;
    2603                 :          0 :         cb(o->stream, success, o->userdata);
    2604                 :            :     }
    2605                 :            : 
    2606                 :            : finish:
    2607                 :          0 :     pa_operation_done(o);
    2608                 :          0 :     pa_operation_unref(o);
    2609                 :          0 : }
    2610                 :            : 
    2611                 :            : 
    2612                 :          0 : pa_operation* pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr, pa_stream_success_cb_t cb, void *userdata) {
    2613                 :            :     pa_operation *o;
    2614                 :            :     pa_tagstruct *t;
    2615                 :            :     uint32_t tag;
    2616                 :            :     pa_buffer_attr copy;
    2617                 :            : 
    2618         [ #  # ]:          0 :     pa_assert(s);
    2619         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2620         [ #  # ]:          0 :     pa_assert(attr);
    2621                 :            : 
    2622         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2623         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2624         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2625         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED);
    2626                 :            : 
    2627                 :            :     /* Ask for a timing update before we cork/uncork to get the best
    2628                 :            :      * accuracy for the transport latency suitable for the
    2629                 :            :      * check_smoother_status() call in the started callback */
    2630                 :          0 :     request_auto_timing_update(s, TRUE);
    2631                 :            : 
    2632                 :          0 :     o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
    2633                 :            : 
    2634         [ #  # ]:          0 :     t = pa_tagstruct_command(
    2635                 :            :             s->context,
    2636                 :          0 :             (uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR : PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR),
    2637                 :            :             &tag);
    2638                 :          0 :     pa_tagstruct_putu32(t, s->channel);
    2639                 :            : 
    2640                 :          0 :     copy = *attr;
    2641                 :          0 :     patch_buffer_attr(s, &copy, NULL);
    2642                 :          0 :     attr = &copy;
    2643                 :            : 
    2644                 :          0 :     pa_tagstruct_putu32(t, attr->maxlength);
    2645                 :            : 
    2646         [ #  # ]:          0 :     if (s->direction == PA_STREAM_PLAYBACK)
    2647                 :          0 :         pa_tagstruct_put(
    2648                 :            :                 t,
    2649                 :            :                 PA_TAG_U32, attr->tlength,
    2650                 :            :                 PA_TAG_U32, attr->prebuf,
    2651                 :            :                 PA_TAG_U32, attr->minreq,
    2652                 :            :                 PA_TAG_INVALID);
    2653                 :            :     else
    2654                 :          0 :         pa_tagstruct_putu32(t, attr->fragsize);
    2655                 :            : 
    2656         [ #  # ]:          0 :     if (s->context->version >= 13)
    2657                 :          0 :         pa_tagstruct_put_boolean(t, !!(s->flags & PA_STREAM_ADJUST_LATENCY));
    2658                 :            : 
    2659         [ #  # ]:          0 :     if (s->context->version >= 14)
    2660                 :          0 :         pa_tagstruct_put_boolean(t, !!(s->flags & PA_STREAM_EARLY_REQUESTS));
    2661                 :            : 
    2662                 :          0 :     pa_pstream_send_tagstruct(s->context->pstream, t);
    2663                 :          0 :     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);
    2664                 :            : 
    2665                 :            :     /* This might cause changes in the read/write index, hence let's
    2666                 :            :      * request a timing update */
    2667                 :          0 :     request_auto_timing_update(s, TRUE);
    2668                 :            : 
    2669                 :          0 :     return o;
    2670                 :            : }
    2671                 :            : 
    2672                 :          0 : uint32_t pa_stream_get_device_index(pa_stream *s) {
    2673         [ #  # ]:          0 :     pa_assert(s);
    2674         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2675                 :            : 
    2676         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, !pa_detect_fork(), PA_ERR_FORKED, PA_INVALID_INDEX);
    2677         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
    2678         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE, PA_INVALID_INDEX);
    2679         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED, PA_INVALID_INDEX);
    2680         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->device_index != PA_INVALID_INDEX, PA_ERR_BADSTATE, PA_INVALID_INDEX);
    2681                 :            : 
    2682                 :          0 :     return s->device_index;
    2683                 :            : }
    2684                 :            : 
    2685                 :          0 : const char *pa_stream_get_device_name(pa_stream *s) {
    2686         [ #  # ]:          0 :     pa_assert(s);
    2687         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2688                 :            : 
    2689         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2690         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2691         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2692         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED);
    2693         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->device_name, PA_ERR_BADSTATE);
    2694                 :            : 
    2695                 :          0 :     return s->device_name;
    2696                 :            : }
    2697                 :            : 
    2698                 :          0 : int pa_stream_is_suspended(pa_stream *s) {
    2699         [ #  # ]:          0 :     pa_assert(s);
    2700         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2701                 :            : 
    2702         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2703         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2704         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2705         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED);
    2706                 :            : 
    2707                 :          0 :     return s->suspended;
    2708                 :            : }
    2709                 :            : 
    2710                 :          0 : int pa_stream_is_corked(pa_stream *s) {
    2711         [ #  # ]:          0 :     pa_assert(s);
    2712         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2713                 :            : 
    2714         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2715         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2716         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2717                 :            : 
    2718                 :          0 :     return s->corked;
    2719                 :            : }
    2720                 :            : 
    2721                 :          0 : static void stream_update_sample_rate_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
    2722                 :          0 :     pa_operation *o = userdata;
    2723                 :          0 :     int success = 1;
    2724                 :            : 
    2725         [ #  # ]:          0 :     pa_assert(pd);
    2726         [ #  # ]:          0 :     pa_assert(o);
    2727         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(o) >= 1);
    2728                 :            : 
    2729         [ #  # ]:          0 :     if (!o->context)
    2730                 :            :         goto finish;
    2731                 :            : 
    2732         [ #  # ]:          0 :     if (command != PA_COMMAND_REPLY) {
    2733         [ #  # ]:          0 :         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
    2734                 :            :             goto finish;
    2735                 :            : 
    2736                 :            :         success = 0;
    2737                 :            :     } else {
    2738                 :            : 
    2739         [ #  # ]:          0 :         if (!pa_tagstruct_eof(t)) {
    2740                 :          0 :             pa_context_fail(o->context, PA_ERR_PROTOCOL);
    2741                 :          0 :             goto finish;
    2742                 :            :         }
    2743                 :            :     }
    2744                 :            : 
    2745                 :          0 :     o->stream->sample_spec.rate = PA_PTR_TO_UINT(o->private);
    2746         [ #  # ]:          0 :     pa_assert(pa_sample_spec_valid(&o->stream->sample_spec));
    2747                 :            : 
    2748         [ #  # ]:          0 :     if (o->callback) {
    2749                 :          0 :         pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback;
    2750                 :          0 :         cb(o->stream, success, o->userdata);
    2751                 :            :     }
    2752                 :            : 
    2753                 :            : finish:
    2754                 :          0 :     pa_operation_done(o);
    2755                 :          0 :     pa_operation_unref(o);
    2756                 :          0 : }
    2757                 :            : 
    2758                 :            : 
    2759                 :          0 : pa_operation *pa_stream_update_sample_rate(pa_stream *s, uint32_t rate, pa_stream_success_cb_t cb, void *userdata) {
    2760                 :            :     pa_operation *o;
    2761                 :            :     pa_tagstruct *t;
    2762                 :            :     uint32_t tag;
    2763                 :            : 
    2764         [ #  # ]:          0 :     pa_assert(s);
    2765         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2766                 :            : 
    2767         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2768         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, rate > 0 && rate <= PA_RATE_MAX, PA_ERR_INVALID);
    2769         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2770         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2771         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->flags & PA_STREAM_VARIABLE_RATE, PA_ERR_BADSTATE);
    2772         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED);
    2773                 :            : 
    2774                 :          0 :     o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
    2775                 :          0 :     o->private = PA_UINT_TO_PTR(rate);
    2776                 :            : 
    2777         [ #  # ]:          0 :     t = pa_tagstruct_command(
    2778                 :            :             s->context,
    2779                 :          0 :             (uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE : PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE),
    2780                 :            :             &tag);
    2781                 :          0 :     pa_tagstruct_putu32(t, s->channel);
    2782                 :          0 :     pa_tagstruct_putu32(t, rate);
    2783                 :            : 
    2784                 :          0 :     pa_pstream_send_tagstruct(s->context->pstream, t);
    2785                 :          0 :     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);
    2786                 :            : 
    2787                 :          0 :     return o;
    2788                 :            : }
    2789                 :            : 
    2790                 :          0 : 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) {
    2791                 :            :     pa_operation *o;
    2792                 :            :     pa_tagstruct *t;
    2793                 :            :     uint32_t tag;
    2794                 :            : 
    2795         [ #  # ]:          0 :     pa_assert(s);
    2796         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2797                 :            : 
    2798         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2799         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
    2800         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2801         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2802         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 13, PA_ERR_NOTSUPPORTED);
    2803                 :            : 
    2804                 :          0 :     o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
    2805                 :            : 
    2806         [ #  # ]:          0 :     t = pa_tagstruct_command(
    2807                 :            :             s->context,
    2808                 :          0 :             (uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST : PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST),
    2809                 :            :             &tag);
    2810                 :          0 :     pa_tagstruct_putu32(t, s->channel);
    2811                 :          0 :     pa_tagstruct_putu32(t, (uint32_t) mode);
    2812                 :          0 :     pa_tagstruct_put_proplist(t, p);
    2813                 :            : 
    2814                 :          0 :     pa_pstream_send_tagstruct(s->context->pstream, t);
    2815                 :          0 :     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);
    2816                 :            : 
    2817                 :            :     /* Please note that we don't update s->proplist here, because we
    2818                 :            :      * don't export that field */
    2819                 :            : 
    2820                 :          0 :     return o;
    2821                 :            : }
    2822                 :            : 
    2823                 :          0 : pa_operation *pa_stream_proplist_remove(pa_stream *s, const char *const keys[], pa_stream_success_cb_t cb, void *userdata) {
    2824                 :            :     pa_operation *o;
    2825                 :            :     pa_tagstruct *t;
    2826                 :            :     uint32_t tag;
    2827                 :            :     const char * const*k;
    2828                 :            : 
    2829         [ #  # ]:          0 :     pa_assert(s);
    2830         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2831                 :            : 
    2832         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2833 [ #  # ][ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, keys && keys[0], PA_ERR_INVALID);
    2834         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
    2835         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
    2836         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 13, PA_ERR_NOTSUPPORTED);
    2837                 :            : 
    2838                 :          0 :     o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
    2839                 :            : 
    2840         [ #  # ]:          0 :     t = pa_tagstruct_command(
    2841                 :            :             s->context,
    2842                 :          0 :             (uint32_t) (s->direction == PA_STREAM_RECORD ? PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST : PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST),
    2843                 :            :             &tag);
    2844                 :          0 :     pa_tagstruct_putu32(t, s->channel);
    2845                 :            : 
    2846         [ #  # ]:          0 :     for (k = keys; *k; k++)
    2847                 :          0 :         pa_tagstruct_puts(t, *k);
    2848                 :            : 
    2849                 :          0 :     pa_tagstruct_puts(t, NULL);
    2850                 :            : 
    2851                 :          0 :     pa_pstream_send_tagstruct(s->context->pstream, t);
    2852                 :          0 :     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);
    2853                 :            : 
    2854                 :            :     /* Please note that we don't update s->proplist here, because we
    2855                 :            :      * don't export that field */
    2856                 :            : 
    2857                 :          0 :     return o;
    2858                 :            : }
    2859                 :            : 
    2860                 :          0 : int pa_stream_set_monitor_stream(pa_stream *s, uint32_t sink_input_idx) {
    2861         [ #  # ]:          0 :     pa_assert(s);
    2862         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2863                 :            : 
    2864         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
    2865         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, sink_input_idx != PA_INVALID_INDEX, PA_ERR_INVALID);
    2866         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
    2867         [ #  # ]:          0 :     PA_CHECK_VALIDITY(s->context, s->context->version >= 13, PA_ERR_NOTSUPPORTED);
    2868                 :            : 
    2869                 :          0 :     s->direct_on_input = sink_input_idx;
    2870                 :            : 
    2871                 :          0 :     return 0;
    2872                 :            : }
    2873                 :            : 
    2874                 :          0 : uint32_t pa_stream_get_monitor_stream(pa_stream *s) {
    2875         [ #  # ]:          0 :     pa_assert(s);
    2876         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
    2877                 :            : 
    2878         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, !pa_detect_fork(), PA_ERR_FORKED, PA_INVALID_INDEX);
    2879         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direct_on_input != PA_INVALID_INDEX, PA_ERR_BADSTATE, PA_INVALID_INDEX);
    2880         [ #  # ]:          0 :     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->context->version >= 13, PA_ERR_NOTSUPPORTED, PA_INVALID_INDEX);
    2881                 :            : 
    2882                 :          0 :     return s->direct_on_input;
    2883                 :            : }

Generated by: LCOV version 1.9