]>
code.delx.au - pulseaudio/blob - polyp/module-esound-sink.c
4 This file is part of polypaudio.
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.
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.
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
36 #include "iochannel.h"
43 #include "module-esound-sink-symdef.h"
44 #include "socket-client.h"
48 PA_MODULE_AUTHOR ( "Lennart Poettering" )
49 PA_MODULE_DESCRIPTION ( "Esound " )
50 PA_MODULE_VERSION ( PACKAGE_VERSION
)
51 PA_MODULE_USAGE ( "sink_name=<name for the sink> server=<address> cookie=<filename> format=<sample format> channels=<number of channels> rate=<sample rate>" )
53 #define DEFAULT_SINK_NAME "esound_output"
59 struct pa_iochannel
* io
;
60 struct pa_socket_client
* client
;
62 struct pa_defer_event
* defer_event
;
64 struct pa_memchunk memchunk
;
65 struct pa_module
* module
;
68 size_t write_length
, write_index
;
71 size_t read_length
, read_index
;
73 enum { STATE_AUTH
, STATE_LATENCY
, STATE_RUNNING
, STATE_DEAD
} state
;
81 static const char * const valid_modargs
[] = {
91 static void cancel ( struct userdata
* u
) {
94 u
-> state
= STATE_DEAD
;
97 pa_iochannel_free ( u
-> io
);
101 if ( u
-> defer_event
) {
102 u
-> core
-> mainloop
-> defer_free ( u
-> defer_event
);
103 u
-> defer_event
= NULL
;
107 pa_sink_disconnect ( u
-> sink
);
108 pa_sink_unref ( u
-> sink
);
113 pa_module_unload_request ( u
-> module
);
118 static int do_write ( struct userdata
* u
) {
122 if (! pa_iochannel_is_writable ( u
-> io
))
126 assert ( u
-> write_index
< u
-> write_length
);
128 if (( r
= pa_iochannel_write ( u
-> io
, ( uint8_t *) u
-> write_data
+ u
-> write_index
, u
-> write_length
- u
-> write_index
)) <= 0 ) {
129 pa_log ( __FILE__
": write() failed: %s \n " , strerror ( errno
));
134 assert ( u
-> write_index
<= u
-> write_length
);
136 if ( u
-> write_index
== u
-> write_length
) {
138 u
-> write_data
= NULL
;
139 u
-> write_index
= u
-> write_length
= 0 ;
141 } else if ( u
-> state
== STATE_RUNNING
) {
142 pa_module_set_used ( u
-> module
, pa_idxset_ncontents ( u
-> sink
-> inputs
) + pa_idxset_ncontents ( u
-> sink
-> monitor_source
-> outputs
));
144 if (! u
-> memchunk
. length
)
145 if ( pa_sink_render ( u
-> sink
, PIPE_BUF
, & u
-> memchunk
) < 0 )
148 assert ( u
-> memchunk
. memblock
&& u
-> memchunk
. length
);
150 if (( r
= pa_iochannel_write ( u
-> io
, ( uint8_t *) u
-> memchunk
. memblock
-> data
+ u
-> memchunk
. index
, u
-> memchunk
. length
)) < 0 ) {
151 pa_log ( __FILE__
": write() failed: %s \n " , strerror ( errno
));
155 u
-> memchunk
. index
+= r
;
156 u
-> memchunk
. length
-= r
;
158 if ( u
-> memchunk
. length
<= 0 ) {
159 pa_memblock_unref ( u
-> memchunk
. memblock
);
160 u
-> memchunk
. memblock
= NULL
;
167 static int handle_response ( struct userdata
* u
) {
172 assert ( u
-> read_length
== sizeof ( int32_t ));
174 /* Process auth data */
175 if (!*( int32_t *) u
-> read_data
) {
176 pa_log ( __FILE__
": Authentication failed: %s \n " , strerror ( errno
));
180 /* Request latency data */
181 assert (! u
-> write_data
);
182 *( int32_t *) ( u
-> write_data
= pa_xmalloc ( u
-> write_length
= sizeof ( int32_t ))) = ESD_PROTO_LATENCY
;
185 u
-> state
= STATE_LATENCY
;
187 /* Space for next response */
188 assert ( u
-> read_length
>= sizeof ( int32_t ));
190 u
-> read_length
= sizeof ( int32_t );
194 case STATE_LATENCY
: {
196 assert ( u
-> read_length
== sizeof ( int32_t ));
198 /* Process latency info */
199 u
-> latency
= ( pa_usec_t
) (( double ) (*( int32_t *) u
-> read_data
) * 1000000 / 44100 );
200 if ( u
-> latency
> 10000000 ) {
201 pa_log ( __FILE__
": WARNING! Invalid latency information received from server \n " );
206 assert (! u
-> write_data
);
207 p
= u
-> write_data
= pa_xmalloc0 ( u
-> write_length
= sizeof ( int32_t )* 3 + ESD_NAME_MAX
);
208 *( p
++) = ESD_PROTO_STREAM_PLAY
;
211 pa_strlcpy (( char *) p
, "Polypaudio Tunnel" , ESD_NAME_MAX
);
214 u
-> state
= STATE_RUNNING
;
216 /* Don't read any further */
217 pa_xfree ( u
-> read_data
);
219 u
-> read_index
= u
-> read_length
= 0 ;
231 static int do_read ( struct userdata
* u
) {
234 if (! pa_iochannel_is_readable ( u
-> io
))
237 if ( u
-> state
== STATE_AUTH
|| u
-> state
== STATE_LATENCY
) {
243 assert ( u
-> read_index
< u
-> read_length
);
245 if (( r
= pa_iochannel_read ( u
-> io
, ( uint8_t *) u
-> read_data
+ u
-> read_index
, u
-> read_length
- u
-> read_index
)) <= 0 ) {
246 pa_log ( __FILE__
": read() failed: %s \n " , r
< 0 ? strerror ( errno
) : "EOF" );
252 assert ( u
-> read_index
<= u
-> read_length
);
254 if ( u
-> read_index
== u
-> read_length
)
255 return handle_response ( u
);
261 static void do_work ( struct userdata
* u
) {
264 u
-> core
-> mainloop
-> defer_enable ( u
-> defer_event
, 0 );
266 if ( do_read ( u
) < 0 || do_write ( u
) < 0 )
270 static void notify_cb ( struct pa_sink
* s
) {
271 struct userdata
* u
= s
-> userdata
;
274 if ( pa_iochannel_is_writable ( u
-> io
))
275 u
-> core
-> mainloop
-> defer_enable ( u
-> defer_event
, 1 );
278 static pa_usec_t
get_latency_cb ( struct pa_sink
* s
) {
279 struct userdata
* u
= s
-> userdata
;
284 ( u
-> memchunk
. memblock
? pa_bytes_to_usec ( u
-> memchunk
. length
, & s
-> sample_spec
) : 0 );
287 static void defer_callback ( struct pa_mainloop_api
* m
, struct pa_defer_event
* e
, void * userdata
) {
288 struct userdata
* u
= userdata
;
293 static void io_callback ( struct pa_iochannel
* io
, void * userdata
) {
294 struct userdata
* u
= userdata
;
299 static void on_connection ( struct pa_socket_client
* c
, struct pa_iochannel
* io
, void * userdata
) {
300 struct userdata
* u
= userdata
;
302 pa_socket_client_unref ( u
-> client
);
306 pa_log ( __FILE__
": connection failed: %s \n " , strerror ( errno
));
312 pa_iochannel_set_callback ( u
-> io
, io_callback
, u
);
315 int pa__init ( struct pa_core
* c
, struct pa_module
* m
) {
316 struct userdata
* u
= NULL
;
318 struct pa_sample_spec ss
;
319 struct pa_modargs
* ma
= NULL
;
322 if (!( ma
= pa_modargs_new ( m
-> argument
, valid_modargs
))) {
323 pa_log ( __FILE__
": failed to parse module arguments \n " );
327 ss
= c
-> default_sample_spec
;
328 if ( pa_modargs_get_sample_spec ( ma
, & ss
) < 0 ) {
329 pa_log ( __FILE__
": invalid sample format specification \n " );
333 if (( ss
. format
!= PA_SAMPLE_U8
&& ss
. format
!= PA_SAMPLE_S16NE
) ||
335 pa_log ( __FILE__
": esound sample type support is limited to mono/stereo and U8 or S16NE sample data \n " );
339 u
= pa_xmalloc0 ( sizeof ( struct userdata
));
344 ( ss
. format
== PA_SAMPLE_U8
? ESD_BITS8
: ESD_BITS16
) |
345 ( ss
. channels
== 2 ? ESD_STEREO
: ESD_MONO
);
350 u
-> read_data
= u
-> write_data
= NULL
;
351 u
-> read_index
= u
-> write_index
= u
-> read_length
= u
-> write_length
= 0 ;
352 u
-> state
= STATE_AUTH
;
355 if (!( u
-> sink
= pa_sink_new ( c
, pa_modargs_get_value ( ma
, "sink_name" , DEFAULT_SINK_NAME
), 0 , & ss
))) {
356 pa_log ( __FILE__
": failed to create sink. \n " );
360 if (!( u
-> client
= pa_socket_client_new_string ( u
-> core
-> mainloop
, p
= pa_modargs_get_value ( ma
, "server" , ESD_UNIX_SOCKET_NAME
), ESD_DEFAULT_PORT
))) {
361 pa_log ( __FILE__
": failed to connect to server. \n " );
364 pa_socket_client_set_callback ( u
-> client
, on_connection
, u
);
366 /* Prepare the initial request */
367 u
-> write_data
= pa_xmalloc ( u
-> write_length
= ESD_KEY_LEN
+ sizeof ( int32_t ));
368 if ( pa_authkey_load_auto ( pa_modargs_get_value ( ma
, "cookie" , ".esd_auth" ), u
-> write_data
, ESD_KEY_LEN
) < 0 ) {
369 pa_log ( __FILE__
": failed to load cookie \n " );
372 *( int32_t *) (( uint8_t *) u
-> write_data
+ ESD_KEY_LEN
) = ESD_ENDIAN_KEY
;
374 /* Reserve space for the response */
375 u
-> read_data
= pa_xmalloc ( u
-> read_length
= sizeof ( int32_t ));
377 u
-> sink
-> notify
= notify_cb
;
378 u
-> sink
-> get_latency
= get_latency_cb
;
379 u
-> sink
-> userdata
= u
;
380 pa_sink_set_owner ( u
-> sink
, m
);
381 u
-> sink
-> description
= pa_sprintf_malloc ( "Esound sink '%s'" , p
);
383 u
-> memchunk
. memblock
= NULL
;
384 u
-> memchunk
. length
= 0 ;
386 u
-> defer_event
= c
-> mainloop
-> defer_new ( c
-> mainloop
, defer_callback
, u
);
387 c
-> mainloop
-> defer_enable ( u
-> defer_event
, 0 );
403 void pa__done ( struct pa_core
* c
, struct pa_module
* m
) {
407 if (!( u
= m
-> userdata
))
413 if ( u
-> memchunk
. memblock
)
414 pa_memblock_unref ( u
-> memchunk
. memblock
);
417 pa_socket_client_unref ( u
-> client
);
419 pa_xfree ( u
-> read_data
);
420 pa_xfree ( u
-> write_data
);