1#ifndef fooprotocolnativehfoo 2#define fooprotocolnativehfoo 3 4/*** 5 This file is part of PulseAudio. 6 7 Copyright 2004-2006 Lennart Poettering 8 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB 9 10 PulseAudio is free software; you can redistribute it and/or modify 11 it under the terms of the GNU Lesser General Public License as published 12 by the Free Software Foundation; either version 2.1 of the License, 13 or (at your option) any later version. 14 15 PulseAudio is distributed in the hope that it will be useful, but 16 WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 General Public License for more details. 19 20 You should have received a copy of the GNU Lesser General Public License 21 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 22***/ 23// GCC does not warn for unused *static inline* functions, but clang does. 24#ifdef __clang__ 25#pragma clang diagnostic push 26#pragma clang diagnostic ignored "-Wunused-function" 27#endif 28 29#include <pulsecore/core.h> 30#include <pulsecore/ipacl.h> 31#include <pulsecore/auth-cookie.h> 32#include <pulsecore/iochannel.h> 33#include <pulsecore/module.h> 34#include <pulsecore/modargs.h> 35#include <pulsecore/strlist.h> 36#include <pulsecore/hook-list.h> 37#include <pulsecore/pstream.h> 38#include <pulsecore/tagstruct.h> 39 40typedef struct pa_native_protocol pa_native_protocol; 41 42typedef struct pa_native_connection pa_native_connection; 43 44typedef struct pa_native_options { 45 PA_REFCNT_DECLARE; 46 47 pa_module *module; 48 49 bool auth_anonymous; 50 bool srbchannel; 51 char *auth_group; 52 pa_ip_acl *auth_ip_acl; 53 pa_auth_cookie *auth_cookie; 54} pa_native_options; 55 56typedef enum pa_native_hook { 57 PA_NATIVE_HOOK_SERVERS_CHANGED, 58 PA_NATIVE_HOOK_CONNECTION_PUT, 59 PA_NATIVE_HOOK_CONNECTION_UNLINK, 60 PA_NATIVE_HOOK_MAX 61} pa_native_hook_t; 62 63 64struct pa_native_protocol; 65 66typedef struct record_stream { 67 pa_msgobject parent; 68 69 pa_native_connection *connection; 70 uint32_t index; 71 72 pa_source_output *source_output; 73 pa_memblockq *memblockq; 74 75 bool adjust_latency : 1; 76 bool early_requests : 1; 77 78 /* Requested buffer attributes */ 79 pa_buffer_attr buffer_attr_req; 80 /* Fixed-up and adjusted buffer attributes */ 81 pa_buffer_attr buffer_attr; 82 83 pa_atomic_t on_the_fly; 84 pa_usec_t configured_source_latency; 85 size_t drop_initial; 86 87 /* Only updated after SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY */ 88 size_t on_the_fly_snapshot; 89 pa_usec_t current_monitor_latency; 90 pa_usec_t current_source_latency; 91} record_stream; 92 93#define RECORD_STREAM(o) (record_stream_cast(o)) 94PA_DEFINE_PRIVATE_CLASS(record_stream, pa_msgobject); 95 96typedef struct output_stream { 97 pa_msgobject parent; 98} output_stream; 99 100#define OUTPUT_STREAM(o) (output_stream_cast(o)) 101PA_DEFINE_PRIVATE_CLASS(output_stream, pa_msgobject); 102 103typedef struct playback_stream { 104 output_stream parent; 105 106 pa_native_connection *connection; 107 uint32_t index; 108 109 pa_sink_input *sink_input; 110 pa_memblockq *memblockq; 111 112 bool adjust_latency : 1; 113 bool early_requests : 1; 114 115 bool is_underrun : 1; 116 bool drain_request : 1; 117 uint32_t drain_tag; 118 uint32_t syncid; 119 120 /* Optimization to avoid too many rewinds with a lot of small blocks */ 121 pa_atomic_t seek_or_post_in_queue; 122 int64_t seek_windex; 123 124 pa_atomic_t missing; 125 pa_usec_t configured_sink_latency; 126 /* Requested buffer attributes */ 127 pa_buffer_attr buffer_attr_req; 128 /* Fixed-up and adjusted buffer attributes */ 129 pa_buffer_attr buffer_attr; 130 131 /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */ 132 int64_t read_index, write_index; 133 size_t render_memblockq_length; 134 pa_usec_t current_sink_latency; 135 uint64_t playing_for, underrun_for; 136} playback_stream; 137 138#define PLAYBACK_STREAM(o) (playback_stream_cast(o)) 139PA_DEFINE_PRIVATE_CLASS(playback_stream, output_stream); 140 141typedef struct upload_stream { 142 output_stream parent; 143 144 pa_native_connection *connection; 145 uint32_t index; 146 147 pa_memchunk memchunk; 148 size_t length; 149 char *name; 150 pa_sample_spec sample_spec; 151 pa_channel_map channel_map; 152 pa_proplist *proplist; 153} upload_stream; 154 155#define UPLOAD_STREAM(o) (upload_stream_cast(o)) 156PA_DEFINE_PRIVATE_CLASS(upload_stream, output_stream); 157 158struct pa_native_connection { 159 pa_msgobject parent; 160 pa_native_protocol *protocol; 161 pa_native_options *options; 162 bool authorized : 1; 163 bool is_local : 1; 164 uint32_t version; 165 pa_client *client; 166 /* R/W mempool, one per client connection, for srbchannel transport. 167 * Both server and client can write to this shm area. 168 * 169 * Note: This will be NULL if our connection with the client does 170 * not support srbchannels */ 171 pa_mempool *rw_mempool; 172 pa_pstream *pstream; 173 pa_pdispatch *pdispatch; 174 pa_idxset *record_streams, *output_streams; 175 uint32_t rrobin_index; 176 pa_subscription *subscription; 177 pa_time_event *auth_timeout_event; 178 pa_srbchannel *srbpending; 179}; 180 181#define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o)) 182PA_DEFINE_PRIVATE_CLASS(pa_native_connection, pa_msgobject); 183 184struct pa_native_protocol { 185 PA_REFCNT_DECLARE; 186 187 pa_core *core; 188 pa_idxset *connections; 189 190 pa_strlist *servers; 191 pa_hook hooks[PA_NATIVE_HOOK_MAX]; 192 193 pa_hashmap *extensions; 194}; 195 196enum { 197 SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY = PA_SOURCE_OUTPUT_MESSAGE_MAX 198}; 199 200enum { 201 SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */ 202 SINK_INPUT_MESSAGE_DRAIN, /* disabled prebuf, get playback started. */ 203 SINK_INPUT_MESSAGE_FLUSH, 204 SINK_INPUT_MESSAGE_TRIGGER, 205 SINK_INPUT_MESSAGE_SEEK, 206 SINK_INPUT_MESSAGE_PREBUF_FORCE, 207 SINK_INPUT_MESSAGE_UPDATE_LATENCY, 208 SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR 209}; 210 211enum { 212 PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, /* data requested from sink input from the main loop */ 213 PLAYBACK_STREAM_MESSAGE_UNDERFLOW, 214 PLAYBACK_STREAM_MESSAGE_OVERFLOW, 215 PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, 216 PLAYBACK_STREAM_MESSAGE_STARTED, 217 PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH, 218 PLAYBACK_STREAM_MESSAGE_UNDERFLOW_OHOS, 219}; 220 221enum { 222 RECORD_STREAM_MESSAGE_POST_DATA /* data from source output to main loop */ 223}; 224 225enum { 226 CONNECTION_MESSAGE_RELEASE, 227 CONNECTION_MESSAGE_REVOKE 228}; 229 230/* Called from IO context */ 231static void playback_stream_request_bytes(playback_stream *s) 232{ 233 size_t m; 234 235 playback_stream_assert_ref(s); 236 237 m = pa_memblockq_pop_missing(s->memblockq); 238 if (m <= 0) { 239 return; 240 } 241 /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu really missing=%lli)", */ 242 /* (unsigned long) m, */ 243 /* pa_memblockq_get_tlength(s->memblockq), */ 244 /* pa_memblockq_get_minreq(s->memblockq), */ 245 /* pa_memblockq_get_length(s->memblockq), */ 246 /* (long long) pa_memblockq_get_tlength(s->memblockq) - (long long) pa_memblockq_get_length(s->memblockq)); */ 247#ifdef PROTOCOL_NATIVE_DEBUG 248 pa_log("request_bytes(%lu)", (unsigned long) m); 249#endif 250 251 if (pa_atomic_add(&s->missing, (int) m) <= 0) { 252 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), 253 PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL); 254 } 255} 256 257pa_native_protocol* pa_native_protocol_get(pa_core *core); 258pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p); 259void pa_native_protocol_unref(pa_native_protocol *p); 260void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *a); 261void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m); 262 263pa_hook *pa_native_protocol_hooks(pa_native_protocol *p); 264 265void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name); 266void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name); 267pa_strlist *pa_native_protocol_servers(pa_native_protocol *p); 268 269typedef int (*pa_native_protocol_ext_cb_t)( 270 pa_native_protocol *p, 271 pa_module *m, 272 pa_native_connection *c, 273 uint32_t tag, 274 pa_tagstruct *t); 275 276int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb); 277void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m); 278 279pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c); 280pa_client* pa_native_connection_get_client(pa_native_connection *c); 281 282pa_native_options* pa_native_options_new(void); 283pa_native_options* pa_native_options_ref(pa_native_options *o); 284void pa_native_options_unref(pa_native_options *o); 285int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma); 286 287#endif 288