qt: playlist: use item title if available
[vlc.git] / modules / audio_output / jack.c
blobd21150f2a41cdab2b6ccd1b039731754155e9ae7
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 *****************************************************************************/
23 /**
24 * \file modules/audio_output/jack.c
25 * \brief JACK audio output functions
27 /*****************************************************************************
28 * Preamble
29 *****************************************************************************/
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_aout.h>
39 #include <jack/jack.h>
40 #include <jack/ringbuffer.h>
42 #include <stdio.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 *****************************************************************************/
53 typedef struct
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;
60 unsigned int i_rate;
61 jack_nframes_t latency;
62 float soft_gain;
63 bool soft_mute;
64 vlc_tick_t paused; /**< Time when (last) paused */
65 } aout_sys_t;
67 /*****************************************************************************
68 * Local prototypes
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 /*****************************************************************************
96 * Module descriptor
97 *****************************************************************************/
98 vlc_module_begin ()
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)
110 add_sw_gain( )
111 set_callbacks( Open, Close )
112 vlc_module_end ()
115 static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
117 char *psz_name;
118 aout_sys_t *p_sys = p_aout->sys;
119 int status = VLC_SUCCESS;
120 unsigned int i;
121 int i_error;
123 if( aout_FormatNbChannels( fmt ) == 0 )
124 return VLC_EGENERIC;
126 p_sys->latency = 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 )
133 free( psz_name );
134 if( asprintf( &psz_name, "vlc_%d", getpid()) == -1 )
135 return VLC_ENOMEM;
138 p_sys->p_jack_client = jack_client_open( psz_name,
139 JackNullOption | JackNoStartServer,
140 NULL );
141 if( p_sys->p_jack_client == NULL )
143 msg_Err( p_aout, "failed to connect to JACK server" );
144 status = VLC_EGENERIC;
145 goto error_out;
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 );
157 p_aout->play = Play;
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 )
170 status = VLC_ENOMEM;
171 goto error_out;
174 p_sys->p_jack_buffers = malloc( p_sys->i_channels *
175 sizeof(jack_sample_t *) );
176 if( p_sys->p_jack_buffers == NULL )
178 status = VLC_ENOMEM;
179 goto error_out;
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 )
188 status = VLC_ENOMEM;
189 goto error_out;
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;
212 goto error_out;
216 /* Tell the JACK server we are ready */
217 i_error = jack_activate( p_sys->p_jack_client );
218 if( i_error )
220 msg_Err( p_aout, "failed to activate JACK client (error %d)", i_error );
221 status = VLC_EGENERIC;
222 goto error_out;
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,
231 psz_regex, NULL,
232 JackPortIsInput );
233 free( psz_regex );
234 /* Count the number of returned ports */
235 i_in_ports = 0;
236 while( pp_in_ports && pp_in_ports[i_in_ports] )
238 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 );
248 if( i_error )
250 msg_Err( p_aout, "failed to connect port %s to port %s (error %d)",
251 psz_out, psz_in, i_error );
253 else
255 msg_Dbg( p_aout, "connecting port %s to port %s",
256 psz_out, psz_in );
259 free( pp_in_ports );
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;
266 error_out:
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 );
281 free( psz_name );
282 return status;
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 );
302 break;
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);
312 (void) date;
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;
322 if( paused ) {
323 sys->paused = date;
324 } else {
325 date -= sys->paused;
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,
348 p_sys->i_rate);
350 return 0;
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;
360 size_t frames_read;
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],
373 i_frames );
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) );
398 return 0;
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;
410 unsigned int i;
411 jack_latency_range_t port_latency;
413 p_sys->latency = 0;
415 for( i = 0; i < p_sys->i_channels; ++i )
417 jack_port_get_latency_range( p_sys->p_jack_ports[i], JackPlaybackLatency,
418 &port_latency );
419 p_sys->latency = __MAX( p_sys->latency, port_latency.max );
422 msg_Dbg(p_aout, "JACK graph reordered. Our maximum latency=%d.",
423 p_sys->latency);
425 return 0;
428 /*****************************************************************************
429 * Close: close the JACK client
430 *****************************************************************************/
431 static void Stop( audio_output_t *p_aout )
433 int i_error;
434 aout_sys_t *p_sys = p_aout->sys;
436 i_error = jack_deactivate( p_sys->p_jack_client );
437 if( i_error )
439 msg_Err( p_aout, "jack_deactivate failed (error %d)", i_error );
442 i_error = jack_client_close( p_sys->p_jack_client );
443 if( i_error )
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 ) )
458 return VLC_ENOMEM;
459 aout->sys = sys;
460 aout->start = Start;
461 aout->stop = Stop;
462 aout_SoftVolumeInit(aout);
463 return VLC_SUCCESS;
466 static void Close(vlc_object_t *obj)
468 audio_output_t *aout = (audio_output_t *)obj;
469 aout_sys_t *sys = aout->sys;
471 free(sys);