• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
40 typedef struct pa_native_protocol pa_native_protocol;
41 
42 typedef struct pa_native_connection pa_native_connection;
43 
44 typedef 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 
56 typedef 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 
64 struct pa_native_protocol;
65 
66 typedef 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))
94 PA_DEFINE_PRIVATE_CLASS(record_stream, pa_msgobject);
95 
96 typedef struct output_stream {
97     pa_msgobject parent;
98 } output_stream;
99 
100 #define OUTPUT_STREAM(o) (output_stream_cast(o))
101 PA_DEFINE_PRIVATE_CLASS(output_stream, pa_msgobject);
102 
103 typedef 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))
139 PA_DEFINE_PRIVATE_CLASS(playback_stream, output_stream);
140 
141 typedef 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))
156 PA_DEFINE_PRIVATE_CLASS(upload_stream, output_stream);
157 
158 struct 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))
182 PA_DEFINE_PRIVATE_CLASS(pa_native_connection, pa_msgobject);
183 
184 struct 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 
196 enum {
197     SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY = PA_SOURCE_OUTPUT_MESSAGE_MAX
198 };
199 
200 enum {
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 
211 enum {
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 
221 enum {
222     RECORD_STREAM_MESSAGE_POST_DATA         /* data from source output to main loop */
223 };
224 
225 enum {
226     CONNECTION_MESSAGE_RELEASE,
227     CONNECTION_MESSAGE_REVOKE
228 };
229 
230 /* Called from IO context */
playback_stream_request_bytes(playback_stream * s)231 static 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 
257 pa_native_protocol* pa_native_protocol_get(pa_core *core);
258 pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p);
259 void pa_native_protocol_unref(pa_native_protocol *p);
260 void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *a);
261 void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m);
262 
263 pa_hook *pa_native_protocol_hooks(pa_native_protocol *p);
264 
265 void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name);
266 void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name);
267 pa_strlist *pa_native_protocol_servers(pa_native_protocol *p);
268 
269 typedef 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 
276 int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb);
277 void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m);
278 
279 pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c);
280 pa_client* pa_native_connection_get_client(pa_native_connection *c);
281 
282 pa_native_options* pa_native_options_new(void);
283 pa_native_options* pa_native_options_ref(pa_native_options *o);
284 void pa_native_options_unref(pa_native_options *o);
285 int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma);
286 
287 #endif
288