1 /*****************************************************************************
2 * jack.c : JACK audio output module
3 *****************************************************************************
4 * Copyright (C) 2006 VLC authors and VideoLAN
6 * Authors: Cyril Deguet <asmax _at_ videolan.org>
7 * Jon Griffiths <jon_p_griffiths _At_ yahoo _DOT_ com>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 * \file modules/audio_output/jack.c
25 * \brief JACK audio output functions
27 /*****************************************************************************
29 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
39 #include <jack/jack.h>
40 #include <jack/ringbuffer.h>
43 #include <unistd.h> /* write(), close() */
45 typedef jack_default_audio_sample_t jack_sample_t
;
47 /*****************************************************************************
48 * aout_sys_t: JACK audio output method descriptor
49 *****************************************************************************
50 * This structure is part of the audio output thread descriptor.
51 * It describes some JACK specific variables.
52 *****************************************************************************/
55 jack_ringbuffer_t
*p_jack_ringbuffer
;
56 jack_client_t
*p_jack_client
;
57 jack_port_t
**p_jack_ports
;
58 jack_sample_t
**p_jack_buffers
;
59 unsigned int i_channels
;
61 jack_nframes_t latency
;
64 vlc_tick_t paused
; /**< Time when (last) paused */
67 /*****************************************************************************
69 *****************************************************************************/
70 static int Open ( vlc_object_t
* );
71 static void Close ( vlc_object_t
* );
72 static void Play ( audio_output_t
* p_aout
, block_t
*, vlc_tick_t
);
73 static void Pause ( audio_output_t
*aout
, bool paused
, vlc_tick_t date
);
74 static void Flush ( audio_output_t
*p_aout
);
75 static int TimeGet ( audio_output_t
*, vlc_tick_t
* );
76 static int Process ( jack_nframes_t i_frames
, void *p_arg
);
77 static int GraphChange ( void *p_arg
);
79 #include "audio_output/volume.h"
81 #define AUTO_CONNECT_OPTION "jack-auto-connect"
82 #define AUTO_CONNECT_TEXT N_("Automatically connect to writable clients")
83 #define AUTO_CONNECT_LONGTEXT N_( \
84 "If enabled, this option will automatically connect sound output to the " \
85 "first writable JACK clients found." )
87 #define CONNECT_REGEX_OPTION "jack-connect-regex"
88 #define CONNECT_REGEX_TEXT N_("Connect to clients matching")
89 #define CONNECT_REGEX_LONGTEXT N_( \
90 "If automatic connection is enabled, only JACK clients whose names " \
91 "match this regular expression will be considered for connection." )
93 #define JACK_NAME_TEXT N_( "JACK client name" )
95 /*****************************************************************************
97 *****************************************************************************/
99 set_shortname( "JACK" )
100 set_description( N_("JACK audio output") )
101 set_capability( "audio output", 100 )
102 set_category( CAT_AUDIO
)
103 set_subcategory( SUBCAT_AUDIO_AOUT
)
104 add_bool( AUTO_CONNECT_OPTION
, true, AUTO_CONNECT_TEXT
,
105 AUTO_CONNECT_LONGTEXT
, false )
106 add_string( CONNECT_REGEX_OPTION
, "system", CONNECT_REGEX_TEXT
,
107 CONNECT_REGEX_LONGTEXT
, false )
108 add_string( "jack-name", "", JACK_NAME_TEXT
, JACK_NAME_TEXT
, false)
111 set_callbacks( Open
, Close
)
115 static int Start( audio_output_t
*p_aout
, audio_sample_format_t
*restrict fmt
)
118 aout_sys_t
*p_sys
= p_aout
->sys
;
119 int status
= VLC_SUCCESS
;
123 if( aout_FormatNbChannels( fmt
) == 0 )
127 p_sys
->paused
= VLC_TICK_INVALID
;
129 /* Connect to the JACK server */
130 psz_name
= var_InheritString( p_aout
, "jack-name" );
131 if( !psz_name
|| !*psz_name
)
134 if( asprintf( &psz_name
, "vlc_%d", getpid()) == -1 )
138 p_sys
->p_jack_client
= jack_client_open( psz_name
,
139 JackNullOption
| JackNoStartServer
,
141 if( p_sys
->p_jack_client
== NULL
)
143 msg_Err( p_aout
, "failed to connect to JACK server" );
144 status
= VLC_EGENERIC
;
148 /* Set the process callback */
149 jack_set_process_callback( p_sys
->p_jack_client
, Process
, p_aout
);
150 jack_set_graph_order_callback ( p_sys
->p_jack_client
, GraphChange
, p_aout
);
152 /* JACK only supports fl32 format */
153 fmt
->i_format
= VLC_CODEC_FL32
;
154 // TODO add buffer size callback
155 p_sys
->i_rate
= fmt
->i_rate
= jack_get_sample_rate( p_sys
->p_jack_client
);
158 p_aout
->pause
= Pause
;
159 p_aout
->flush
= Flush
;
160 p_aout
->time_get
= TimeGet
;
161 aout_SoftVolumeStart( p_aout
);
163 p_sys
->i_channels
= aout_FormatNbChannels( fmt
);
164 aout_FormatPrepare(fmt
);
166 p_sys
->p_jack_ports
= malloc( p_sys
->i_channels
*
167 sizeof(jack_port_t
*) );
168 if( p_sys
->p_jack_ports
== NULL
)
174 p_sys
->p_jack_buffers
= malloc( p_sys
->i_channels
*
175 sizeof(jack_sample_t
*) );
176 if( p_sys
->p_jack_buffers
== NULL
)
182 const size_t buf_sz
=
183 samples_from_vlc_tick(AOUT_MAX_ADVANCE_TIME
, fmt
->i_rate
* fmt
->i_bytes_per_frame
);
184 p_sys
->p_jack_ringbuffer
= jack_ringbuffer_create( buf_sz
);
186 if( p_sys
->p_jack_ringbuffer
== NULL
)
192 if( jack_ringbuffer_mlock( p_sys
->p_jack_ringbuffer
))
194 msg_Warn( p_aout
, "failed to lock JACK ringbuffer in memory" );
197 /* Create the output ports */
198 for( i
= 0; i
< p_sys
->i_channels
; i
++ )
200 char *psz_name_output
;
201 if( asprintf( &psz_name_output
, "%s_out_%d", psz_name
, i
+ 1) != -1 )
203 p_sys
->p_jack_ports
[i
] = jack_port_register( p_sys
->p_jack_client
,
204 psz_name_output
, JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0 );
205 free( psz_name_output
);
208 if( p_sys
->p_jack_ports
[i
] == NULL
)
210 msg_Err( p_aout
, "failed to register a JACK port" );
211 status
= VLC_EGENERIC
;
216 /* Tell the JACK server we are ready */
217 i_error
= jack_activate( p_sys
->p_jack_client
);
220 msg_Err( p_aout
, "failed to activate JACK client (error %d)", i_error
);
221 status
= VLC_EGENERIC
;
225 /* Auto connect ports if we were asked to */
226 if( var_InheritBool( p_aout
, AUTO_CONNECT_OPTION
) )
228 unsigned int i_in_ports
;
229 char *psz_regex
= var_InheritString( p_aout
, CONNECT_REGEX_OPTION
);
230 const char **pp_in_ports
= jack_get_ports( p_sys
->p_jack_client
,
234 /* Count the number of returned ports */
236 while( pp_in_ports
&& pp_in_ports
[i_in_ports
] )
241 /* Tie the output ports to JACK input ports */
242 for( i
= 0; i_in_ports
> 0 && i
< p_sys
->i_channels
; i
++ )
244 const char* psz_in
= pp_in_ports
[i
% i_in_ports
];
245 const char* psz_out
= jack_port_name( p_sys
->p_jack_ports
[i
] );
247 i_error
= jack_connect( p_sys
->p_jack_client
, psz_out
, psz_in
);
250 msg_Err( p_aout
, "failed to connect port %s to port %s (error %d)",
251 psz_out
, psz_in
, i_error
);
255 msg_Dbg( p_aout
, "connecting port %s to port %s",
262 msg_Dbg( p_aout
, "JACK audio output initialized (%d channels, rate=%d)",
263 p_sys
->i_channels
, fmt
->i_rate
);
264 fmt
->channel_type
= AUDIO_CHANNEL_TYPE_BITMAP
;
267 /* Clean up, if an error occurred */
268 if( status
!= VLC_SUCCESS
)
270 if( p_sys
->p_jack_client
)
272 jack_deactivate( p_sys
->p_jack_client
);
273 jack_client_close( p_sys
->p_jack_client
);
275 if( p_sys
->p_jack_ringbuffer
)
276 jack_ringbuffer_free( p_sys
->p_jack_ringbuffer
);
278 free( p_sys
->p_jack_ports
);
279 free( p_sys
->p_jack_buffers
);
285 static void Play(audio_output_t
* p_aout
, block_t
* p_block
, vlc_tick_t date
)
287 aout_sys_t
*p_sys
= p_aout
->sys
;
288 jack_ringbuffer_t
*rb
= p_sys
->p_jack_ringbuffer
;
289 const size_t bytes_per_frame
= p_sys
->i_channels
* sizeof(jack_sample_t
);
291 while (p_block
->i_buffer
> 0) {
293 /* move data to buffer */
294 const size_t write_space
= jack_ringbuffer_write_space(rb
);
295 const size_t bytes
= p_block
->i_buffer
< write_space
?
296 p_block
->i_buffer
: write_space
;
298 /* If our audio thread is not reading fast enough */
299 if( unlikely( bytes
== 0 ) ) {
300 msg_Warn( p_aout
, "%"PRIuPTR
" frames of audio dropped",
301 p_block
->i_buffer
/ bytes_per_frame
);
305 jack_ringbuffer_write( rb
, (const char *) p_block
->p_buffer
, bytes
);
307 p_block
->p_buffer
+= bytes
;
308 p_block
->i_buffer
-= bytes
;
311 block_Release(p_block
);
316 * Pause or unpause playback
318 static void Pause(audio_output_t
*aout
, bool paused
, vlc_tick_t date
)
320 aout_sys_t
*sys
= aout
->sys
;
326 msg_Dbg(aout
, "resuming after %"PRId64
" us", date
);
327 sys
->paused
= VLC_TICK_INVALID
;
331 static void Flush(audio_output_t
*p_aout
)
333 aout_sys_t
* p_sys
= p_aout
->sys
;
334 jack_ringbuffer_t
*rb
= p_sys
->p_jack_ringbuffer
;
336 /* reset ringbuffer read and write pointers */
337 jack_ringbuffer_reset(rb
);
340 static int TimeGet(audio_output_t
*p_aout
, vlc_tick_t
*delay
)
342 aout_sys_t
* p_sys
= p_aout
->sys
;
343 jack_ringbuffer_t
*rb
= p_sys
->p_jack_ringbuffer
;
344 const size_t bytes_per_frame
= p_sys
->i_channels
* sizeof(jack_sample_t
);
346 *delay
= p_sys
->latency
+
347 vlc_tick_from_samples(jack_ringbuffer_read_space(rb
) / bytes_per_frame
,
353 /*****************************************************************************
354 * Process: callback for JACK
355 *****************************************************************************/
356 int Process( jack_nframes_t i_frames
, void *p_arg
)
358 unsigned int i
, j
, frames_from_rb
= 0;
359 size_t bytes_read
= 0;
361 audio_output_t
*p_aout
= (audio_output_t
*) p_arg
;
362 aout_sys_t
*p_sys
= p_aout
->sys
;
364 /* Get the next audio data buffer unless paused */
366 if( p_sys
->paused
== VLC_TICK_INVALID
)
367 frames_from_rb
= i_frames
;
369 /* Get the JACK buffers to write to */
370 for( i
= 0; i
< p_sys
->i_channels
; i
++ )
372 p_sys
->p_jack_buffers
[i
] = jack_port_get_buffer( p_sys
->p_jack_ports
[i
],
376 /* Copy in the audio data */
377 for( j
= 0; j
< frames_from_rb
; j
++ )
379 for( i
= 0; i
< p_sys
->i_channels
; i
++ )
381 jack_sample_t
*p_dst
= p_sys
->p_jack_buffers
[i
] + j
;
382 bytes_read
+= jack_ringbuffer_read( p_sys
->p_jack_ringbuffer
,
383 (char *) p_dst
, sizeof(jack_sample_t
) );
387 /* Fill any remaining buffer with silence */
388 frames_read
= (bytes_read
/ sizeof(jack_sample_t
)) / p_sys
->i_channels
;
389 if( frames_read
< i_frames
)
391 for( i
= 0; i
< p_sys
->i_channels
; i
++ )
393 memset( p_sys
->p_jack_buffers
[i
] + frames_read
, 0,
394 sizeof( jack_sample_t
) * (i_frames
- frames_read
) );
401 /*****************************************************************************
402 * GraphChange: callback when JACK reorders it's process graph.
403 We update latency information.
404 *****************************************************************************/
406 static int GraphChange( void *p_arg
)
408 audio_output_t
*p_aout
= (audio_output_t
*) p_arg
;
409 aout_sys_t
*p_sys
= p_aout
->sys
;
411 jack_latency_range_t port_latency
;
415 for( i
= 0; i
< p_sys
->i_channels
; ++i
)
417 jack_port_get_latency_range( p_sys
->p_jack_ports
[i
], JackPlaybackLatency
,
419 p_sys
->latency
= __MAX( p_sys
->latency
, port_latency
.max
);
422 msg_Dbg(p_aout
, "JACK graph reordered. Our maximum latency=%d.",
428 /*****************************************************************************
429 * Close: close the JACK client
430 *****************************************************************************/
431 static void Stop( audio_output_t
*p_aout
)
434 aout_sys_t
*p_sys
= p_aout
->sys
;
436 i_error
= jack_deactivate( p_sys
->p_jack_client
);
439 msg_Err( p_aout
, "jack_deactivate failed (error %d)", i_error
);
442 i_error
= jack_client_close( p_sys
->p_jack_client
);
445 msg_Err( p_aout
, "jack_client_close failed (error %d)", i_error
);
447 free( p_sys
->p_jack_ports
);
448 free( p_sys
->p_jack_buffers
);
449 jack_ringbuffer_free( p_sys
->p_jack_ringbuffer
);
452 static int Open(vlc_object_t
*obj
)
454 audio_output_t
*aout
= (audio_output_t
*)obj
;
455 aout_sys_t
*sys
= calloc(1, sizeof (*sys
));
457 if( unlikely( sys
== NULL
) )
462 aout_SoftVolumeInit(aout
);
466 static void Close(vlc_object_t
*obj
)
468 audio_output_t
*aout
= (audio_output_t
*)obj
;
469 aout_sys_t
*sys
= aout
->sys
;