1 /*****************************************************************************
2 * jack.c: JACK audio input module
3 *****************************************************************************
4 * Copyright (C) 2007-2008 VLC authors and VideoLAN
5 * Copyright (C) 2007 Société des arts technologiques
6 * Copyright (C) 2007 Savoir-faire Linux
8 * Authors: Arnaud Sala <arnaud.sala at savoirfairelinux.com>
9 * Julien Plissonneau Duquene <... at savoirfairelinux.com>
10 * Pierre-Luc Beaudoin <pierre-luc.beaudoin at savoirfairelinux.com>
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU Lesser General Public License as published by
14 * the Free Software Foundation; either version 2.1 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
28 * \file modules/access/jack.c
29 * \brief JACK audio input functions
32 /*****************************************************************************
34 *****************************************************************************/
40 #include <vlc_common.h>
41 #include <vlc_plugin.h>
42 #include <vlc_demux.h>
44 #include <vlc_strings.h>
46 #include <jack/jack.h>
47 #include <jack/ringbuffer.h>
49 #include <sys/types.h>
52 /*****************************************************************************
54 *****************************************************************************/
55 static int Open ( vlc_object_t
* );
56 static void Close( vlc_object_t
* );
58 #define PACE_TEXT N_( "Pace" )
59 #define PACE_LONGTEXT N_( \
60 "Read the audio stream at VLC pace rather than Jack pace." )
61 #define AUTO_CONNECT_TEXT N_( "Auto connection" )
62 #define AUTO_CONNECT_LONGTEXT N_( \
63 "Automatically connect VLC input ports to available output ports." )
64 #define CHANNELS_TEXT N_( "Channels" )
65 #define CHANNELS_LONGTEXT N_( \
66 "Number of input channels VLC should expose to the jack server." )
67 #define PORTS_TEXT N_( "Ports" )
68 #define PORTS_LONGTEXT N_( \
69 "Output ports in jack that VLC should read from, URI-encoded and " \
70 "separated with a comma." )
73 set_description( N_("JACK audio input") )
74 set_capability( "access", 0 )
75 set_shortname( N_( "JACK Input" ) )
76 set_category( CAT_INPUT
)
77 set_subcategory( SUBCAT_INPUT_ACCESS
)
79 add_bool( "jack-input-use-vlc-pace", false,
80 PACE_TEXT
, PACE_LONGTEXT
, true )
81 add_bool( "jack-input-auto-connect", false,
82 AUTO_CONNECT_TEXT
, AUTO_CONNECT_LONGTEXT
, false )
84 /* Channels, potentially from MRL. */
85 add_integer( "jack-input-channels", 0,
86 CHANNELS_TEXT
, CHANNELS_LONGTEXT
, false )
89 /* Ports, potentially from MRL. */
90 add_string( "jack-input-ports", NULL
,
91 PORTS_TEXT
, PORTS_LONGTEXT
, false )
94 add_shortcut( "jack" )
95 set_callbacks( Open
, Close
)
98 /*****************************************************************************
100 *****************************************************************************/
104 /* Audio properties */
105 vlc_fourcc_t i_acodec_raw
;
106 unsigned int i_channels
;
108 int i_audio_max_frame_size
;
110 block_t
*p_block_audio
;
111 es_out_id_t
*p_es_audio
;
114 /* Jack properties */
115 jack_client_t
*p_jack_client
;
116 jack_port_t
**pp_jack_port_input
;
117 jack_default_audio_sample_t
**pp_jack_buffer
;
118 jack_ringbuffer_t
*p_jack_ringbuffer
;
119 jack_nframes_t jack_buffer_size
;
120 jack_nframes_t jack_sample_rate
;
121 size_t jack_sample_size
;
123 char **pp_jack_port_table
;
127 static int Demux( demux_t
* );
128 static int Control( demux_t
*p_demux
, int i_query
, va_list args
);
130 static void Port_finder( demux_t
* );
131 static int Process( jack_nframes_t i_frames
, void *p_arg
);
133 static block_t
*GrabJack( demux_t
* );
135 /*****************************************************************************
136 * Open: Connect to the JACK server
137 *****************************************************************************/
138 static int Open( vlc_object_t
*p_this
)
140 demux_t
*p_demux
= ( demux_t
* )p_this
;
145 if (p_demux
->out
== NULL
)
148 p_demux
->pf_demux
= Demux
;
149 p_demux
->pf_control
= Control
;
151 /* Allocate structure */
152 p_demux
->p_sys
= p_sys
= vlc_obj_calloc( p_this
, 1, sizeof( demux_sys_t
) );
157 var_LocationParse( p_demux
, p_demux
->psz_location
, "jack-input-" );
158 p_sys
->i_channels
= var_GetInteger( p_demux
, "jack-input-channels" );
159 p_sys
->psz_ports
= var_GetString( p_demux
, "jack-input-ports" );
162 var_Create( p_demux
, "jack-input-use-vlc-pace",
163 VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
164 var_Create( p_demux
, "jack-input-auto-connect",
165 VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
167 /* JACK connexions */
168 /* define name and connect to jack server */
169 char p_vlc_client_name
[32];
170 sprintf( p_vlc_client_name
, "vlc-input-%d", getpid() );
171 p_sys
->p_jack_client
= jack_client_open( p_vlc_client_name
, JackNullOption
, NULL
);
172 if( p_sys
->p_jack_client
== NULL
)
174 msg_Err( p_demux
, "failed to connect to JACK server" );
178 /* find some specifics ports if user entered a regexp */
179 if( p_sys
->psz_ports
)
181 Port_finder( p_demux
);
182 if( p_sys
->i_channels
== 0 )
184 p_sys
->i_channels
= p_sys
->i_match_ports
;
188 /* allocate input ports */
189 if( p_sys
->i_channels
== 0 ) p_sys
->i_channels
= 2 ; /* default number of port */
190 p_sys
->pp_jack_port_input
= malloc(
191 p_sys
->i_channels
* sizeof( jack_port_t
* ) );
192 if( p_sys
->pp_jack_port_input
== NULL
)
194 jack_client_close( p_sys
->p_jack_client
);
198 /* allocate ringbuffer */
199 /* The length of the ringbuffer is critical, it must be large enought
200 to keep all data between 2 GrabJack() calls. We assume 1 sec is ok */
201 p_sys
->p_jack_ringbuffer
= jack_ringbuffer_create( p_sys
->i_channels
202 * jack_get_sample_rate( p_sys
->p_jack_client
)
203 * sizeof( jack_default_audio_sample_t
) );
204 if( p_sys
->p_jack_ringbuffer
== NULL
)
206 free( p_sys
->pp_jack_port_input
);
207 jack_client_close( p_sys
->p_jack_client
);
211 /* register input ports */
212 for( unsigned i
= 0; i
< p_sys
->i_channels
; i
++ )
214 char p_input_name
[32];
215 snprintf( p_input_name
, 32, "vlc_in_%d", i
+1 );
216 p_sys
->pp_jack_port_input
[i
] = jack_port_register(
217 p_sys
->p_jack_client
, p_input_name
, JACK_DEFAULT_AUDIO_TYPE
,
218 JackPortIsInput
, 0 );
219 if( p_sys
->pp_jack_port_input
[i
] == NULL
)
221 msg_Err( p_demux
, "failed to register a JACK port" );
222 jack_ringbuffer_free( p_sys
->p_jack_ringbuffer
);
223 free( p_sys
->pp_jack_port_input
);
224 jack_client_close( p_sys
->p_jack_client
);
229 /* allocate buffer for input ports */
230 p_sys
->pp_jack_buffer
= malloc ( p_sys
->i_channels
231 * sizeof( jack_default_audio_sample_t
* ) );
232 if( p_sys
->pp_jack_buffer
== NULL
)
234 for( unsigned i
= 0; i
< p_sys
->i_channels
; i
++ )
235 jack_port_unregister( p_sys
->p_jack_client
, p_sys
->pp_jack_port_input
[i
] );
236 jack_ringbuffer_free( p_sys
->p_jack_ringbuffer
);
237 free( p_sys
->pp_jack_port_input
);
238 jack_client_close( p_sys
->p_jack_client
);
242 /* set process callback */
243 jack_set_process_callback( p_sys
->p_jack_client
, Process
, p_demux
);
245 /* tell jack server we are ready */
246 if ( jack_activate( p_sys
->p_jack_client
) )
248 msg_Err( p_demux
, "failed to activate JACK client" );
249 free( p_sys
->pp_jack_buffer
);
250 for( unsigned i
= 0; i
< p_sys
->i_channels
; i
++ )
251 jack_port_unregister( p_sys
->p_jack_client
, p_sys
->pp_jack_port_input
[i
] );
252 jack_ringbuffer_free( p_sys
->p_jack_ringbuffer
);
253 free( p_sys
->pp_jack_port_input
);
254 jack_client_close( p_sys
->p_jack_client
);
258 /* connect vlc input to specifics jack output ports if requested */
259 /* if( var_GetBool( p_demux, "jack-input-auto-connect" ) && p_sys->psz_ports ) */
260 if( p_sys
->psz_ports
)
262 for( int j
= 0; j
< p_sys
->i_match_ports
; j
++ )
264 int i_input_ports
= j
% p_sys
->i_channels
;
265 jack_connect( p_sys
->p_jack_client
, p_sys
->pp_jack_port_table
[j
],
266 jack_port_name( p_sys
->pp_jack_port_input
[i_input_ports
] ) );
270 /* connect vlc input to all jack output ports if requested */
271 if( var_GetBool( p_demux
, "jack-input-auto-connect" ) && !p_sys
->psz_ports
)
273 const char **pp_jack_port_output
= jack_get_ports( p_sys
->p_jack_client
,
274 NULL
, NULL
, JackPortIsOutput
);
276 while( pp_jack_port_output
&& pp_jack_port_output
[i_out_ports
] )
281 for( int j
= 0; j
< i_out_ports
; j
++ )
283 int i_input_ports
= j
% p_sys
->i_channels
;
284 jack_connect( p_sys
->p_jack_client
, pp_jack_port_output
[j
],
285 jack_port_name( p_sys
->pp_jack_port_input
[i_input_ports
] ) );
288 free( pp_jack_port_output
);
291 /* info about jack server */
292 /* get buffers size */
293 p_sys
->jack_buffer_size
= jack_get_buffer_size( p_sys
->p_jack_client
);
294 /* get sample rate */
295 p_sys
->jack_sample_rate
= jack_get_sample_rate( p_sys
->p_jack_client
);
296 /* get sample size */
297 p_sys
->jack_sample_size
= sizeof( jack_default_audio_sample_t
);
299 /* Define output format */
300 es_format_Init( &fmt
, AUDIO_ES
, VLC_CODEC_FL32
);
301 fmt
.audio
.i_channels
= p_sys
->i_channels
;
302 fmt
.audio
.i_rate
= p_sys
->jack_sample_rate
;
303 fmt
.audio
.i_bitspersample
= p_sys
->jack_sample_size
* 8;
304 fmt
.audio
.i_blockalign
= fmt
.audio
.i_bitspersample
/ 8;
305 fmt
.i_bitrate
= fmt
.audio
.i_rate
* fmt
.audio
.i_bitspersample
306 * fmt
.audio
.i_channels
;
308 p_sys
->p_es_audio
= es_out_Add( p_demux
->out
, &fmt
);
309 date_Init( &p_sys
->pts
, fmt
.audio
.i_rate
, 1 );
310 date_Set( &p_sys
->pts
, VLC_TICK_0
);
316 /*****************************************************************************
317 * Close: Disconnect from jack server and release associated resources
318 *****************************************************************************/
319 static void Close( vlc_object_t
*p_this
)
321 demux_t
*p_demux
= ( demux_t
* )p_this
;
322 demux_sys_t
*p_sys
= p_demux
->p_sys
;
324 msg_Dbg( p_demux
,"Module unloaded" );
325 if( p_sys
->p_block_audio
) block_Release( p_sys
->p_block_audio
);
326 if( p_sys
->p_jack_client
) jack_client_close( p_sys
->p_jack_client
);
327 if( p_sys
->p_jack_ringbuffer
) jack_ringbuffer_free( p_sys
->p_jack_ringbuffer
);
328 free( p_sys
->pp_jack_port_input
);
329 free( p_sys
->pp_jack_buffer
);
330 free( p_sys
->pp_jack_port_table
);
331 free( p_sys
->psz_ports
);
335 /*****************************************************************************
337 *****************************************************************************/
338 static int Control( demux_t
*p_demux
, int i_query
, va_list args
)
341 demux_sys_t
*p_sys
= p_demux
->p_sys
;
345 /* Special for access_demux */
346 case DEMUX_CAN_PAUSE
:
348 pb
= va_arg( args
, bool * );
352 case DEMUX_SET_PAUSE_STATE
:
354 case DEMUX_CAN_CONTROL_PACE
:
355 pb
= va_arg( args
, bool * );
356 *pb
= var_GetBool( p_demux
, "jack-input-use-vlc-pace" );
359 case DEMUX_GET_PTS_DELAY
:
360 *va_arg( args
, vlc_tick_t
* ) =
361 VLC_TICK_FROM_MS( var_InheritInteger( p_demux
, "live-caching" ) );
365 *va_arg( args
, vlc_tick_t
* ) = date_Get(&p_sys
->pts
);
368 /* TODO implement others */
377 /*****************************************************************************
379 *****************************************************************************/
380 static int Demux( demux_t
*p_demux
)
386 p_sys
= p_demux
->p_sys
;
387 p_es
= p_sys
->p_es_audio
;
388 p_block
= GrabJack( p_demux
);
392 es_out_SetPCR( p_demux
->out
, p_block
->i_pts
);
393 es_out_Send( p_demux
->out
, p_es
, p_block
);
400 /*****************************************************************************
401 * Process Callback : fill ringbuffer with Jack audio data
402 *****************************************************************************/
403 int Process( jack_nframes_t i_frames
, void *p_arg
)
405 demux_t
*p_demux
= ( demux_t
* )p_arg
;
406 demux_sys_t
*p_sys
= p_demux
->p_sys
;
408 /* Get and interlace buffers */
409 for ( unsigned i
= 0; i
< p_sys
->i_channels
; i
++ )
411 p_sys
->pp_jack_buffer
[i
] = jack_port_get_buffer(
412 p_sys
->pp_jack_port_input
[i
], i_frames
);
415 /* fill ring buffer with signal */
416 for( unsigned j
= 0; j
< i_frames
; j
++ )
418 for( unsigned i
= 0; i
<p_sys
->i_channels
; i
++ )
420 if( jack_ringbuffer_write_space( p_sys
->p_jack_ringbuffer
) <
421 p_sys
->jack_sample_size
) {
422 msg_Err( p_demux
, "buffer overflow");
423 return 0; // buffer overflow
425 size_t i_write
= jack_ringbuffer_write( p_sys
->p_jack_ringbuffer
,
426 ( char * ) (p_sys
->pp_jack_buffer
[i
]+j
),
427 p_sys
->jack_sample_size
);
428 if (i_write
!= p_sys
->jack_sample_size
) {
429 msg_Warn( p_demux
, "error writing on ring buffer");
438 /*****************************************************************************
439 * GrabJack: grab audio data in the Jack buffer
440 *****************************************************************************/
441 static block_t
*GrabJack( demux_t
*p_demux
)
443 demux_sys_t
*p_sys
= p_demux
->p_sys
;
446 /* read signal from ring buffer */
447 size_t i_read
= jack_ringbuffer_read_space( p_sys
->p_jack_ringbuffer
);
449 if( i_read
< 100 ) /* avoid small read */
450 { /* vlc has too much free time on its hands? */
451 #undef vlc_tick_sleep
452 #warning Hmm.... looks wrong
453 vlc_tick_sleep(1000);
457 if( p_sys
->p_block_audio
)
459 p_block
= p_sys
->p_block_audio
;
463 p_block
= block_Alloc( i_read
);
467 msg_Warn( p_demux
, "cannot get block" );
471 //Find the previous power of 2, this algo assumes size_t has the same size on all arch
474 i_read
|= i_read
>> 1;
475 i_read
|= i_read
>> 2;
476 i_read
|= i_read
>> 4;
477 i_read
|= i_read
>> 8;
478 i_read
|= i_read
>> 16;
481 i_read
= jack_ringbuffer_read( p_sys
->p_jack_ringbuffer
, ( char * ) p_block
->p_buffer
, i_read
);
483 p_block
->i_dts
= p_block
->i_pts
= date_Increment( &p_sys
->pts
,
484 i_read
/(p_sys
->i_channels
* p_sys
->jack_sample_size
) );
486 p_sys
->p_block_audio
= p_block
;
487 p_block
->i_buffer
= i_read
;
488 p_sys
->p_block_audio
= 0;
494 /*****************************************************************************
495 * Port_finder: compare ports with the regexp entered
496 *****************************************************************************/
497 static void Port_finder( demux_t
*p_demux
)
499 demux_sys_t
*p_sys
= p_demux
->p_sys
;
500 char *psz_expr
= p_sys
->psz_ports
;
503 char *psz_uri
= NULL
;
504 const char **pp_jack_port_output
= NULL
;
506 int i_total_out_ports
=0;
507 p_sys
->pp_jack_port_table
= NULL
;
509 /* parse the ports part of the MRL */
510 for( token
= strtok_r( psz_expr
, ",", &state
); token
;
511 token
= strtok_r( NULL
, ",", &state
) )
513 psz_uri
= vlc_uri_decode_duplicate( token
);
514 /* get the ports which match the regexp */
515 pp_jack_port_output
= jack_get_ports( p_sys
->p_jack_client
,
516 psz_uri
, NULL
, JackPortIsOutput
);
517 if( pp_jack_port_output
== NULL
)
518 msg_Err( p_demux
, "port(s) asked not found:%s", psz_uri
);
521 while( pp_jack_port_output
[i_out_ports
] )
523 /* alloc an array to store all the matched ports */
524 p_sys
->pp_jack_port_table
= xrealloc( p_sys
->pp_jack_port_table
,
525 (i_out_ports
* sizeof( char * ) + i_total_out_ports
* sizeof( char * ) ) );
527 for(int i
=0; i
<i_out_ports
;i
++)
528 p_sys
->pp_jack_port_table
[i_total_out_ports
+i
] = ( char * ) pp_jack_port_output
[i
];
530 i_total_out_ports
+= i_out_ports
;
532 free( pp_jack_port_output
);
537 p_sys
->i_match_ports
= i_total_out_ports
;