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