]> code.delx.au - pulseaudio/blob - src/modules/module-tunnel.c
unbreak module-tunnel
[pulseaudio] / src / modules / module-tunnel.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <unistd.h>
27 #include <assert.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33
34 #include <polyp/version.h>
35
36 #include <polypcore/module.h>
37 #include <polypcore/util.h>
38 #include <polypcore/modargs.h>
39 #include <polypcore/log.h>
40 #include <polypcore/core-subscribe.h>
41 #include <polypcore/xmalloc.h>
42 #include <polypcore/sink-input.h>
43 #include <polypcore/pdispatch.h>
44 #include <polypcore/pstream.h>
45 #include <polypcore/pstream-util.h>
46 #include <polypcore/authkey.h>
47 #include <polypcore/socket-client.h>
48 #include <polypcore/socket-util.h>
49 #include <polypcore/authkey-prop.h>
50
51 #ifdef TUNNEL_SINK
52 #include "module-tunnel-sink-symdef.h"
53 PA_MODULE_DESCRIPTION("Tunnel module for sinks")
54 PA_MODULE_USAGE("server=<address> sink=<remote sink name> cookie=<filename> format=<sample format> channels=<number of channels> rate=<sample rate> sink_name=<name for the local sink>")
55 #else
56 #include "module-tunnel-source-symdef.h"
57 PA_MODULE_DESCRIPTION("Tunnel module for sources")
58 PA_MODULE_USAGE("server=<address> source=<remote source name> cookie=<filename> format=<sample format> channels=<number of channels> rate=<sample rate> source_name=<name for the local source>")
59 #endif
60
61 PA_MODULE_AUTHOR("Lennart Poettering")
62 PA_MODULE_VERSION(PACKAGE_VERSION)
63
64 #define DEFAULT_SINK_NAME "tunnel"
65 #define DEFAULT_SOURCE_NAME "tunnel"
66
67 #define DEFAULT_TLENGTH (44100*2*2/10) //(10240*8)
68 #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2)
69 #define DEFAULT_MINREQ 512
70 #define DEFAULT_PREBUF (DEFAULT_TLENGTH-DEFAULT_MINREQ)
71 #define DEFAULT_FRAGSIZE 1024
72
73 #define DEFAULT_TIMEOUT 5
74
75 #define LATENCY_INTERVAL 10
76
77 static const char* const valid_modargs[] = {
78 "server",
79 "cookie",
80 "format",
81 "channels",
82 "rate",
83 #ifdef TUNNEL_SINK
84 "sink_name",
85 "sink",
86 #else
87 "source_name",
88 "source",
89 #endif
90 NULL,
91 };
92
93 static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
94 static void command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
95
96 #ifdef TUNNEL_SINK
97 static void command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
98 #endif
99
100 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
101 #ifdef TUNNEL_SINK
102 [PA_COMMAND_REQUEST] = command_request,
103 #endif
104 [PA_COMMAND_PLAYBACK_STREAM_KILLED] = command_stream_killed,
105 [PA_COMMAND_RECORD_STREAM_KILLED] = command_stream_killed,
106 [PA_COMMAND_SUBSCRIBE_EVENT] = command_subscribe_event,
107 };
108
109 struct userdata {
110 pa_socket_client *client;
111 pa_pstream *pstream;
112 pa_pdispatch *pdispatch;
113
114 char *server_name;
115 #ifdef TUNNEL_SINK
116 char *sink_name;
117 pa_sink *sink;
118 uint32_t requested_bytes;
119 #else
120 char *source_name;
121 pa_source *source;
122 #endif
123
124 pa_module *module;
125 pa_core *core;
126
127 uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
128
129 uint32_t version;
130 uint32_t ctag;
131 uint32_t device_index;
132 uint32_t channel;
133
134 pa_usec_t host_latency;
135
136 pa_time_event *time_event;
137
138 int auth_cookie_in_property;
139 };
140
141 static void close_stuff(struct userdata *u) {
142 assert(u);
143
144 if (u->pstream) {
145 pa_pstream_close(u->pstream);
146 pa_pstream_unref(u->pstream);
147 u->pstream = NULL;
148 }
149
150 if (u->pdispatch) {
151 pa_pdispatch_unref(u->pdispatch);
152 u->pdispatch = NULL;
153 }
154
155 if (u->client) {
156 pa_socket_client_unref(u->client);
157 u->client = NULL;
158 }
159
160 #ifdef TUNNEL_SINK
161 if (u->sink) {
162 pa_sink_disconnect(u->sink);
163 pa_sink_unref(u->sink);
164 u->sink = NULL;
165 }
166 #else
167 if (u->source) {
168 pa_source_disconnect(u->source);
169 pa_source_unref(u->source);
170 u->source = NULL;
171 }
172 #endif
173
174 if (u->time_event) {
175 u->core->mainloop->time_free(u->time_event);
176 u->time_event = NULL;
177 }
178 }
179
180 static void die(struct userdata *u) {
181 assert(u);
182 close_stuff(u);
183 pa_module_unload_request(u->module);
184 }
185
186 static void command_stream_killed(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
187 struct userdata *u = userdata;
188 assert(pd && t && u && u->pdispatch == pd);
189
190 pa_log(__FILE__": stream killed");
191 die(u);
192 }
193
194 static void request_info(struct userdata *u);
195
196 static void command_subscribe_event(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
197 struct userdata *u = userdata;
198 pa_subscription_event_type_t e;
199 uint32_t idx;
200
201 assert(pd && t && u);
202 assert(command == PA_COMMAND_SUBSCRIBE_EVENT);
203
204 if (pa_tagstruct_getu32(t, &e) < 0 ||
205 pa_tagstruct_getu32(t, &idx) < 0 ||
206 !pa_tagstruct_eof(t)) {
207 pa_log(__FILE__": invalid protocol reply");
208 die(u);
209 return;
210 }
211
212 #ifdef TUNNEL_SINK
213 if (e != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE))
214 return;
215 #else
216 if (e != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE))
217 return;
218 #endif
219
220 request_info(u);
221 }
222
223 #ifdef TUNNEL_SINK
224 static void send_prebuf_request(struct userdata *u) {
225 pa_tagstruct *t;
226
227 t = pa_tagstruct_new(NULL, 0);
228 pa_tagstruct_putu32(t, PA_COMMAND_PREBUF_PLAYBACK_STREAM);
229 pa_tagstruct_putu32(t, u->ctag++);
230 pa_tagstruct_putu32(t, u->channel);
231 pa_pstream_send_tagstruct(u->pstream, t);
232 }
233
234 static void send_bytes(struct userdata *u) {
235 assert(u);
236
237 if (!u->pstream)
238 return;
239
240 while (u->requested_bytes > 0) {
241 pa_memchunk chunk;
242 if (pa_sink_render(u->sink, u->requested_bytes, &chunk) < 0) {
243
244 if (u->requested_bytes >= DEFAULT_TLENGTH-DEFAULT_PREBUF)
245 send_prebuf_request(u);
246
247 return;
248 }
249
250 pa_pstream_send_memblock(u->pstream, u->channel, 0, PA_SEEK_RELATIVE, &chunk);
251 pa_memblock_unref(chunk.memblock);
252
253 if (chunk.length > u->requested_bytes)
254 u->requested_bytes = 0;
255 else
256 u->requested_bytes -= chunk.length;
257 }
258 }
259
260 static void command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
261 struct userdata *u = userdata;
262 uint32_t bytes, channel;
263 assert(pd && command == PA_COMMAND_REQUEST && t && u && u->pdispatch == pd);
264
265 if (pa_tagstruct_getu32(t, &channel) < 0 ||
266 pa_tagstruct_getu32(t, &bytes) < 0 ||
267 !pa_tagstruct_eof(t)) {
268 pa_log(__FILE__": invalid protocol reply");
269 die(u);
270 return;
271 }
272
273 if (channel != u->channel) {
274 pa_log(__FILE__": recieved data for invalid channel");
275 die(u);
276 return;
277 }
278
279 u->requested_bytes += bytes;
280 send_bytes(u);
281 }
282
283 #endif
284
285 static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
286 struct userdata *u = userdata;
287 pa_usec_t sink_usec, source_usec, transport_usec;
288 int playing;
289 int64_t write_index, read_index;
290 struct timeval local, remote, now;
291 assert(pd && u);
292
293 if (command != PA_COMMAND_REPLY) {
294 if (command == PA_COMMAND_ERROR)
295 pa_log(__FILE__": failed to get latency.");
296 else
297 pa_log(__FILE__": protocol error.");
298 die(u);
299 return;
300 }
301
302 if (pa_tagstruct_get_usec(t, &sink_usec) < 0 ||
303 pa_tagstruct_get_usec(t, &source_usec) < 0 ||
304 pa_tagstruct_get_boolean(t, &playing) < 0 ||
305 pa_tagstruct_get_timeval(t, &local) < 0 ||
306 pa_tagstruct_get_timeval(t, &remote) < 0 ||
307 pa_tagstruct_gets64(t, &write_index) < 0 ||
308 pa_tagstruct_gets64(t, &read_index) < 0 ||
309 !pa_tagstruct_eof(t)) {
310 pa_log(__FILE__": invalid reply. (latency)");
311 die(u);
312 return;
313 }
314
315 pa_gettimeofday(&now);
316
317 if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) {
318 /* local and remote seem to have synchronized clocks */
319 #ifdef TUNNEL_SINK
320 transport_usec = pa_timeval_diff(&remote, &local);
321 #else
322 transport_usec = pa_timeval_diff(&now, &remote);
323 #endif
324 } else
325 transport_usec = pa_timeval_diff(&now, &local)/2;
326
327 #ifdef TUNNEL_SINK
328 u->host_latency = sink_usec + transport_usec;
329 #else
330 u->host_latency = source_usec + transport_usec;
331 if (u->host_latency > sink_usec)
332 u->host_latency -= sink_usec;
333 else
334 u->host_latency = 0;
335 #endif
336
337 /* pa_log(__FILE__": estimated host latency: %0.0f usec", (double) u->host_latency); */
338 }
339
340 static void request_latency(struct userdata *u) {
341 pa_tagstruct *t;
342 struct timeval now;
343 uint32_t tag;
344 assert(u);
345
346 t = pa_tagstruct_new(NULL, 0);
347 #ifdef TUNNEL_SINK
348 pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
349 #else
350 pa_tagstruct_putu32(t, PA_COMMAND_GET_RECORD_LATENCY);
351 #endif
352 pa_tagstruct_putu32(t, tag = u->ctag++);
353 pa_tagstruct_putu32(t, u->channel);
354
355 pa_gettimeofday(&now);
356 pa_tagstruct_put_timeval(t, &now);
357
358 pa_pstream_send_tagstruct(u->pstream, t);
359 pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u);
360 }
361
362 static void stream_get_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
363 struct userdata *u = userdata;
364 uint32_t idx, owner_module, monitor_source;
365 pa_usec_t latency;
366 const char *name, *description, *monitor_source_name, *driver;
367 int mute;
368 uint32_t flags;
369 pa_sample_spec sample_spec;
370 pa_channel_map channel_map;
371 pa_cvolume volume;
372 assert(pd && u);
373
374 if (command != PA_COMMAND_REPLY) {
375 if (command == PA_COMMAND_ERROR)
376 pa_log(__FILE__": failed to get info.");
377 else
378 pa_log(__FILE__": protocol error.");
379 die(u);
380 return;
381 }
382
383 if (pa_tagstruct_getu32(t, &idx) < 0 ||
384 pa_tagstruct_gets(t, &name) < 0 ||
385 pa_tagstruct_gets(t, &description) < 0 ||
386 pa_tagstruct_get_sample_spec(t, &sample_spec) < 0 ||
387 pa_tagstruct_get_channel_map(t, &channel_map) < 0 ||
388 pa_tagstruct_getu32(t, &owner_module) < 0 ||
389 pa_tagstruct_get_cvolume(t, &volume) < 0 ||
390 pa_tagstruct_get_boolean(t, &mute) < 0 ||
391 pa_tagstruct_getu32(t, &monitor_source) < 0 ||
392 pa_tagstruct_gets(t, &monitor_source_name) < 0 ||
393 pa_tagstruct_get_usec(t, &latency) < 0 ||
394 pa_tagstruct_gets(t, &driver) < 0 ||
395 pa_tagstruct_getu32(t, &flags) < 0 ||
396 !pa_tagstruct_eof(t)) {
397 pa_log(__FILE__": invalid reply. (get_info)");
398 die(u);
399 return;
400 }
401
402 #ifdef TUNNEL_SINK
403 assert(u->sink);
404 if ((!!mute == !!u->sink->hw_muted) &&
405 pa_cvolume_equal(&volume, &u->sink->hw_volume))
406 return;
407 #else
408 assert(u->source);
409 if ((!!mute == !!u->source->hw_muted) &&
410 pa_cvolume_equal(&volume, &u->source->hw_volume))
411 return;
412 #endif
413
414 #ifdef TUNNEL_SINK
415 memcpy(&u->sink->hw_volume, &volume, sizeof(pa_cvolume));
416 u->sink->hw_muted = !!mute;
417
418 pa_subscription_post(u->sink->core,
419 PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE,
420 u->sink->index);
421 #else
422 memcpy(&u->source->hw_volume, &volume, sizeof(pa_cvolume));
423 u->source->hw_muted = !!mute;
424
425 pa_subscription_post(u->source->core,
426 PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE,
427 u->source->index);
428 #endif
429 }
430
431 static void request_info(struct userdata *u) {
432 pa_tagstruct *t;
433 uint32_t tag;
434 assert(u);
435
436 t = pa_tagstruct_new(NULL, 0);
437 #ifdef TUNNEL_SINK
438 pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
439 #else
440 pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
441 #endif
442 pa_tagstruct_putu32(t, tag = u->ctag++);
443
444 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
445 #ifdef TUNNEL_SINK
446 pa_tagstruct_puts(t, u->sink_name);
447 #else
448 pa_tagstruct_puts(t, u->source_name);
449 #endif
450
451 pa_pstream_send_tagstruct(u->pstream, t);
452 pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_info_callback, u);
453 }
454
455 static void start_subscribe(struct userdata *u) {
456 pa_tagstruct *t;
457 uint32_t tag;
458 assert(u);
459
460 t = pa_tagstruct_new(NULL, 0);
461 pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
462 pa_tagstruct_putu32(t, tag = u->ctag++);
463
464 #ifdef TUNNEL_SINK
465 pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SINK);
466 #else
467 pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SOURCE);
468 #endif
469
470 pa_pstream_send_tagstruct(u->pstream, t);
471 }
472
473 static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
474 struct userdata *u = userdata;
475 assert(pd && u && u->pdispatch == pd);
476
477 if (command != PA_COMMAND_REPLY) {
478 if (command == PA_COMMAND_ERROR)
479 pa_log(__FILE__": failed to create stream.");
480 else
481 pa_log(__FILE__": protocol error.");
482 die(u);
483 return;
484 }
485
486 if (pa_tagstruct_getu32(t, &u->channel) < 0 ||
487 pa_tagstruct_getu32(t, &u->device_index) < 0 ||
488 #ifdef TUNNEL_SINK
489 pa_tagstruct_getu32(t, &u->requested_bytes) < 0 ||
490 #endif
491 !pa_tagstruct_eof(t)) {
492 pa_log(__FILE__": invalid reply. (create stream)");
493 die(u);
494 return;
495 }
496
497 start_subscribe(u);
498 request_info(u);
499
500 request_latency(u);
501 #ifdef TUNNEL_SINK
502 send_bytes(u);
503 #endif
504 }
505
506 static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
507 struct userdata *u = userdata;
508 pa_tagstruct *reply;
509 char name[256], un[128], hn[128];
510 #ifdef TUNNEL_SINK
511 pa_cvolume volume;
512 #endif
513 assert(pd && u && u->pdispatch == pd);
514
515 if (command != PA_COMMAND_REPLY ||
516 pa_tagstruct_getu32(t, &u->version) < 0 ||
517 !pa_tagstruct_eof(t)) {
518 if (command == PA_COMMAND_ERROR)
519 pa_log(__FILE__": failed to authenticate");
520 else
521 pa_log(__FILE__": protocol error.");
522 die(u);
523 return;
524 }
525
526 /* Minimum supported protocol version */
527 if (u->version < 8) {
528 pa_log(__FILE__": incompatible protocol version");
529 die(u);
530 return;
531 }
532
533 #ifdef TUNNEL_SINK
534 snprintf(name, sizeof(name), "Tunnel from host '%s', user '%s', sink '%s'",
535 pa_get_host_name(hn, sizeof(hn)),
536 pa_get_user_name(un, sizeof(un)),
537 u->sink->name);
538 #else
539 snprintf(name, sizeof(name), "Tunnel from host '%s', user '%s', source '%s'",
540 pa_get_host_name(hn, sizeof(hn)),
541 pa_get_user_name(un, sizeof(un)),
542 u->source->name);
543 #endif
544
545 reply = pa_tagstruct_new(NULL, 0);
546 pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME);
547 pa_tagstruct_putu32(reply, tag = u->ctag++);
548 pa_tagstruct_puts(reply, name);
549 pa_pstream_send_tagstruct(u->pstream, reply);
550 /* We ignore the server's reply here */
551
552 reply = pa_tagstruct_new(NULL, 0);
553 #ifdef TUNNEL_SINK
554 pa_tagstruct_putu32(reply, PA_COMMAND_CREATE_PLAYBACK_STREAM);
555 pa_tagstruct_putu32(reply, tag = u->ctag++);
556 pa_tagstruct_puts(reply, name);
557 pa_tagstruct_put_sample_spec(reply, &u->sink->sample_spec);
558 pa_tagstruct_put_channel_map(reply, &u->sink->channel_map);
559 pa_tagstruct_putu32(reply, PA_INVALID_INDEX);
560 pa_tagstruct_puts(reply, u->sink_name);
561 pa_tagstruct_putu32(reply, DEFAULT_MAXLENGTH);
562 pa_tagstruct_put_boolean(reply, 0);
563 pa_tagstruct_putu32(reply, DEFAULT_TLENGTH);
564 pa_tagstruct_putu32(reply, DEFAULT_PREBUF);
565 pa_tagstruct_putu32(reply, DEFAULT_MINREQ);
566 pa_tagstruct_putu32(reply, 0);
567 pa_cvolume_reset(&volume, u->sink->sample_spec.channels);
568 pa_tagstruct_put_cvolume(reply, &volume);
569 #else
570 pa_tagstruct_putu32(reply, PA_COMMAND_CREATE_RECORD_STREAM);
571 pa_tagstruct_putu32(reply, tag = u->ctag++);
572 pa_tagstruct_puts(reply, name);
573 pa_tagstruct_put_sample_spec(reply, &u->source->sample_spec);
574 pa_tagstruct_put_channel_map(reply, &u->source->channel_map);
575 pa_tagstruct_putu32(reply, PA_INVALID_INDEX);
576 pa_tagstruct_puts(reply, u->source_name);
577 pa_tagstruct_putu32(reply, DEFAULT_MAXLENGTH);
578 pa_tagstruct_put_boolean(reply, 0);
579 pa_tagstruct_putu32(reply, DEFAULT_FRAGSIZE);
580 #endif
581
582 pa_pstream_send_tagstruct(u->pstream, reply);
583 pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u);
584 }
585
586 static void pstream_die_callback(pa_pstream *p, void *userdata) {
587 struct userdata *u = userdata;
588 assert(p && u);
589
590 pa_log(__FILE__": stream died.");
591 die(u);
592 }
593
594
595 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void*creds, void *userdata) {
596 struct userdata *u = userdata;
597 assert(p && packet && u);
598
599 if (pa_pdispatch_run(u->pdispatch, packet, creds, u) < 0) {
600 pa_log(__FILE__": invalid packet");
601 die(u);
602 }
603 }
604
605 #ifndef TUNNEL_SINK
606 static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) {
607 struct userdata *u = userdata;
608 assert(p && chunk && u);
609
610 if (channel != u->channel) {
611 pa_log(__FILE__": recieved memory block on bad channel.");
612 die(u);
613 return;
614 }
615
616 pa_source_post(u->source, chunk);
617 }
618 #endif
619
620 static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata) {
621 struct userdata *u = userdata;
622 pa_tagstruct *t;
623 uint32_t tag;
624 assert(sc && u && u->client == sc);
625
626 pa_socket_client_unref(u->client);
627 u->client = NULL;
628
629 if (!io) {
630 pa_log(__FILE__": connection failed.");
631 pa_module_unload_request(u->module);
632 return;
633 }
634
635 u->pstream = pa_pstream_new(u->core->mainloop, io, u->core->memblock_stat);
636 u->pdispatch = pa_pdispatch_new(u->core->mainloop, command_table, PA_COMMAND_MAX);
637
638 pa_pstream_set_die_callback(u->pstream, pstream_die_callback, u);
639 pa_pstream_set_recieve_packet_callback(u->pstream, pstream_packet_callback, u);
640 #ifndef TUNNEL_SINK
641 pa_pstream_set_recieve_memblock_callback(u->pstream, pstream_memblock_callback, u);
642 #endif
643
644 t = pa_tagstruct_new(NULL, 0);
645 pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
646 pa_tagstruct_putu32(t, tag = u->ctag++);
647 pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION);
648 pa_tagstruct_put_arbitrary(t, u->auth_cookie, sizeof(u->auth_cookie));
649 pa_pstream_send_tagstruct(u->pstream, t);
650 pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, u);
651
652 }
653
654 #ifdef TUNNEL_SINK
655 static void sink_notify(pa_sink*sink) {
656 struct userdata *u;
657 assert(sink && sink->userdata);
658 u = sink->userdata;
659
660 send_bytes(u);
661 }
662
663 static pa_usec_t sink_get_latency(pa_sink *sink) {
664 struct userdata *u;
665 uint32_t l;
666 pa_usec_t usec = 0;
667 assert(sink && sink->userdata);
668 u = sink->userdata;
669
670 l = DEFAULT_TLENGTH;
671
672 if (l > u->requested_bytes) {
673 l -= u->requested_bytes;
674 usec += pa_bytes_to_usec(l, &u->sink->sample_spec);
675 }
676
677 usec += u->host_latency;
678
679 return usec;
680 }
681
682 static int sink_get_hw_volume(pa_sink *sink) {
683 struct userdata *u;
684 assert(sink && sink->userdata);
685 u = sink->userdata;
686
687 return 0;
688 }
689
690 static int sink_set_hw_volume(pa_sink *sink) {
691 struct userdata *u;
692 pa_tagstruct *t;
693 uint32_t tag;
694 assert(sink && sink->userdata);
695 u = sink->userdata;
696
697 t = pa_tagstruct_new(NULL, 0);
698 pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME);
699 pa_tagstruct_putu32(t, tag = u->ctag++);
700
701 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
702 pa_tagstruct_puts(t, u->sink_name);
703 pa_tagstruct_put_cvolume(t, &sink->hw_volume);
704 pa_pstream_send_tagstruct(u->pstream, t);
705
706 return 0;
707 }
708
709 static int sink_get_hw_mute(pa_sink *sink) {
710 struct userdata *u;
711 assert(sink && sink->userdata);
712 u = sink->userdata;
713
714 return 0;
715 }
716
717 static int sink_set_hw_mute(pa_sink *sink) {
718 struct userdata *u;
719 pa_tagstruct *t;
720 uint32_t tag;
721 assert(sink && sink->userdata);
722 u = sink->userdata;
723
724 t = pa_tagstruct_new(NULL, 0);
725 pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_MUTE);
726 pa_tagstruct_putu32(t, tag = u->ctag++);
727
728 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
729 pa_tagstruct_puts(t, u->sink_name);
730 pa_tagstruct_put_boolean(t, !!sink->hw_muted);
731 pa_pstream_send_tagstruct(u->pstream, t);
732
733 return 0;
734 }
735 #else
736 static pa_usec_t source_get_latency(pa_source *source) {
737 struct userdata *u;
738 assert(source && source->userdata);
739 u = source->userdata;
740
741 return u->host_latency;
742 }
743
744 static int source_get_hw_volume(pa_source *source) {
745 struct userdata *u;
746 assert(source && source->userdata);
747 u = source->userdata;
748
749 return 0;
750 }
751
752 static int source_set_hw_volume(pa_source *source) {
753 struct userdata *u;
754 pa_tagstruct *t;
755 uint32_t tag;
756 assert(source && source->userdata);
757 u = source->userdata;
758
759 t = pa_tagstruct_new(NULL, 0);
760 pa_tagstruct_putu32(t, PA_COMMAND_SET_SOURCE_VOLUME);
761 pa_tagstruct_putu32(t, tag = u->ctag++);
762
763 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
764 pa_tagstruct_puts(t, u->source_name);
765 pa_tagstruct_put_cvolume(t, &source->hw_volume);
766 pa_pstream_send_tagstruct(u->pstream, t);
767
768 return 0;
769 }
770
771 static int source_get_hw_mute(pa_source *source) {
772 struct userdata *u;
773 assert(source && source->userdata);
774 u = source->userdata;
775
776 return 0;
777 }
778
779 static int source_set_hw_mute(pa_source *source) {
780 struct userdata *u;
781 pa_tagstruct *t;
782 uint32_t tag;
783 assert(source && source->userdata);
784 u = source->userdata;
785
786 t = pa_tagstruct_new(NULL, 0);
787 pa_tagstruct_putu32(t, PA_COMMAND_SET_SOURCE_MUTE);
788 pa_tagstruct_putu32(t, tag = u->ctag++);
789
790 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
791 pa_tagstruct_puts(t, u->source_name);
792 pa_tagstruct_put_boolean(t, !!source->hw_muted);
793 pa_pstream_send_tagstruct(u->pstream, t);
794
795 return 0;
796 }
797 #endif
798
799 static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
800 struct userdata *u = userdata;
801 struct timeval ntv;
802 assert(m && e && u);
803
804 request_latency(u);
805
806 pa_gettimeofday(&ntv);
807 ntv.tv_sec += LATENCY_INTERVAL;
808 m->time_restart(e, &ntv);
809 }
810
811 static int load_key(struct userdata *u, const char*fn) {
812 assert(u);
813
814 u->auth_cookie_in_property = 0;
815
816 if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) {
817 pa_log_debug(__FILE__": using already loaded auth cookie.");
818 pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
819 u->auth_cookie_in_property = 1;
820 return 0;
821 }
822
823 if (!fn)
824 fn = PA_NATIVE_COOKIE_FILE;
825
826 if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0)
827 return -1;
828
829 pa_log_debug(__FILE__": loading cookie from disk.");
830
831 if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0)
832 u->auth_cookie_in_property = 1;
833
834 return 0;
835 }
836
837 int pa__init(pa_core *c, pa_module*m) {
838 pa_modargs *ma = NULL;
839 struct userdata *u = NULL;
840 pa_sample_spec ss;
841 struct timeval ntv;
842 assert(c && m);
843
844 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
845 pa_log(__FILE__": failed to parse module arguments");
846 goto fail;
847 }
848
849 u = pa_xmalloc(sizeof(struct userdata));
850 m->userdata = u;
851 u->module = m;
852 u->core = c;
853 u->client = NULL;
854 u->pdispatch = NULL;
855 u->pstream = NULL;
856 u->server_name = NULL;
857 #ifdef TUNNEL_SINK
858 u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));;
859 u->sink = NULL;
860 u->requested_bytes = 0;
861 #else
862 u->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));;
863 u->source = NULL;
864 #endif
865 u->ctag = 1;
866 u->device_index = u->channel = PA_INVALID_INDEX;
867 u->host_latency = 0;
868 u->auth_cookie_in_property = 0;
869 u->time_event = NULL;
870
871 if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0)
872 goto fail;
873
874 if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) {
875 pa_log(__FILE__": no server specified.");
876 goto fail;
877 }
878
879 ss = c->default_sample_spec;
880 if (pa_modargs_get_sample_spec(ma, &ss) < 0) {
881 pa_log(__FILE__": invalid sample format specification");
882 goto fail;
883 }
884
885 if (!(u->client = pa_socket_client_new_string(c->mainloop, u->server_name, PA_NATIVE_DEFAULT_PORT))) {
886 pa_log(__FILE__": failed to connect to server '%s'", u->server_name);
887 goto fail;
888 }
889
890 if (!u->client)
891 goto fail;
892
893 pa_socket_client_set_callback(u->client, on_connection, u);
894
895 #ifdef TUNNEL_SINK
896 if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
897 pa_log(__FILE__": failed to create sink.");
898 goto fail;
899 }
900
901 u->sink->notify = sink_notify;
902 u->sink->get_latency = sink_get_latency;
903 u->sink->get_hw_volume = sink_get_hw_volume;
904 u->sink->set_hw_volume = sink_set_hw_volume;
905 u->sink->get_hw_mute = sink_get_hw_mute;
906 u->sink->set_hw_mute = sink_set_hw_mute;
907 u->sink->userdata = u;
908 u->sink->description = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->sink_name ? u->sink_name : "", u->sink_name ? "@" : "", u->server_name);
909
910 pa_sink_set_owner(u->sink, m);
911 #else
912 if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) {
913 pa_log(__FILE__": failed to create source.");
914 goto fail;
915 }
916
917 u->source->get_latency = source_get_latency;
918 u->source->get_hw_volume = source_get_hw_volume;
919 u->source->set_hw_volume = source_set_hw_volume;
920 u->source->get_hw_mute = source_get_hw_mute;
921 u->source->set_hw_mute = source_set_hw_mute;
922 u->source->userdata = u;
923 u->source->description = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->source_name ? u->source_name : "", u->source_name ? "@" : "", u->server_name);
924
925 pa_source_set_owner(u->source, m);
926 #endif
927
928 pa_gettimeofday(&ntv);
929 ntv.tv_sec += LATENCY_INTERVAL;
930 u->time_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, u);
931
932 pa_modargs_free(ma);
933
934 return 0;
935
936 fail:
937 pa__done(c, m);
938
939 if (ma)
940 pa_modargs_free(ma);
941 return -1;
942 }
943
944 void pa__done(pa_core *c, pa_module*m) {
945 struct userdata* u;
946 assert(c && m);
947
948 if (!(u = m->userdata))
949 return;
950
951 close_stuff(u);
952
953 if (u->auth_cookie_in_property)
954 pa_authkey_prop_unref(c, PA_NATIVE_COOKIE_PROPERTY_NAME);
955
956 #ifdef TUNNEL_SINK
957 pa_xfree(u->sink_name);
958 #else
959 pa_xfree(u->source_name);
960 #endif
961 pa_xfree(u->server_name);
962
963 pa_xfree(u);
964 }
965
966