]> git.sesse.net Git - vlc/blob - lib/audio.c
aout: add --stereo-mode to replace audio-channels variable (fixes #6)
[vlc] / lib / audio.c
1 /*****************************************************************************
2  * libvlc_audio.c: New libvlc audio control API
3  *****************************************************************************
4  * Copyright (C) 2006 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Filippo Carone <filippo@carone.org>
8  *          Jean-Paul Saman <jpsaman _at_ m2x _dot_ nl>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <assert.h>
30 #include <math.h>
31
32 #include <vlc/libvlc.h>
33 #include <vlc/libvlc_media.h>
34 #include <vlc/libvlc_media_player.h>
35
36 #include <vlc_common.h>
37 #include <vlc_input.h>
38 #include <vlc_aout_intf.h>
39 #include <vlc_aout.h>
40 #include <vlc_modules.h>
41
42 #include "libvlc_internal.h"
43 #include "media_player_internal.h"
44
45 /*
46  * Remember to release the returned audio_output_t since it is locked at
47  * the end of this function.
48  */
49 static audio_output_t *GetAOut( libvlc_media_player_t *mp )
50 {
51     assert( mp != NULL );
52
53     input_thread_t *p_input = libvlc_get_input_thread( mp );
54     if( p_input == NULL )
55         return NULL;
56
57     audio_output_t * p_aout = input_GetAout( p_input );
58     vlc_object_release( p_input );
59     if( p_aout == NULL )
60         libvlc_printerr( "No active audio output" );
61     return p_aout;
62 }
63
64 /*****************************************
65  * Get the list of available audio outputs
66  *****************************************/
67 libvlc_audio_output_t *
68         libvlc_audio_output_list_get( libvlc_instance_t *p_instance )
69 {
70     size_t count;
71     module_t **module_list = module_list_get( &count );
72     libvlc_audio_output_t *list = NULL;
73
74     for (size_t i = 0; i < count; i++)
75     {
76         module_t *module = module_list[i];
77
78         if( !module_provides( module, "audio output" ) )
79             continue;
80
81         libvlc_audio_output_t *item = malloc( sizeof( *item ) );
82         if( unlikely(item == NULL) )
83         {
84     error:
85             libvlc_printerr( "Not enough memory" );
86             libvlc_audio_output_list_release( list );
87             list = NULL;
88             break;
89         }
90
91         item->psz_name = strdup( module_get_object( module ) );
92         item->psz_description = strdup( module_get_name( module, true ) );
93         if( unlikely(item->psz_name == NULL || item->psz_description == NULL) )
94         {
95             free( item );
96             goto error;
97         }
98         item->p_next = list;
99         list = item;
100     }
101     module_list_free( module_list );
102
103     VLC_UNUSED( p_instance );
104     return list;
105 }
106
107 /********************************************
108  * Free the list of available audio outputs
109  ***********************************************/
110 void libvlc_audio_output_list_release( libvlc_audio_output_t *list )
111 {
112     while( list != NULL )
113     {
114         libvlc_audio_output_t *next = list->p_next;
115
116         free( list->psz_name );
117         free( list->psz_description );
118         free( list );
119         list = next;
120     }
121 }
122
123
124 /***********************
125  * Set the audio output.
126  ***********************/
127 int libvlc_audio_output_set( libvlc_media_player_t *mp, const char *psz_name )
128 {
129     char *value;
130
131     if( !module_exists( psz_name )
132      || asprintf( &value, "%s,none", psz_name ) == -1 )
133         return -1;
134     var_SetString( mp, "aout", value );
135     free( value );
136     return 0;
137 }
138
139 libvlc_audio_output_device_t *
140 libvlc_audio_output_device_list_get( libvlc_instance_t *p_instance,
141                                      const char *aout )
142 {
143     char varname[32];
144     if( (size_t)snprintf( varname, sizeof(varname), "%s-output-device", aout )
145                                                            >= sizeof(varname) )
146         return NULL;
147
148     libvlc_audio_output_device_t *list = NULL, **pp = &list;
149     char **values, **texts;
150     ssize_t count = config_GetPszChoices( VLC_OBJECT(p_instance->p_libvlc_int),
151                                           varname, &values, &texts );
152     for( ssize_t i = 0; i < count; i++ )
153     {
154         libvlc_audio_output_device_t *item = malloc( sizeof(*item) );
155         if( unlikely(item == NULL) )
156             break;
157
158         *pp = item;
159         pp = &item->p_next;
160         item->psz_device = values[i];
161         item->psz_description = texts[i];
162     }
163
164     *pp = NULL;
165     free( texts );
166     free( values );
167     (void) p_instance;
168     return list;
169 }
170
171 void libvlc_audio_output_device_list_release( libvlc_audio_output_device_t *l )
172 {
173     while( l != NULL )
174     {
175         libvlc_audio_output_device_t *next = l->p_next;
176
177         free( l->psz_description );
178         free( l->psz_device );
179         free( l );
180         l = next;
181     }
182 }
183
184 int libvlc_audio_output_device_count( libvlc_instance_t *p_instance,
185                                       const char *psz_audio_output )
186 {
187     (void) p_instance; (void) psz_audio_output;
188     return 0;
189 }
190
191 char *libvlc_audio_output_device_longname( libvlc_instance_t *p_instance,
192                                            const char *psz_audio_output,
193                                            int i_device )
194 {
195     (void) p_instance; (void) psz_audio_output; (void) i_device;
196     return NULL;
197 }
198
199 char *libvlc_audio_output_device_id( libvlc_instance_t *p_instance,
200                                      const char *psz_audio_output,
201                                      int i_device )
202 {
203     (void) p_instance; (void) psz_audio_output; (void) i_device;
204     return NULL;
205 }
206
207 /*****************************
208  * Set device for using
209  *****************************/
210 void libvlc_audio_output_device_set( libvlc_media_player_t *mp,
211                                      const char *psz_audio_output,
212                                      const char *psz_device_id )
213 {
214     char *psz_config_name;
215     if( !psz_audio_output || !psz_device_id )
216         return;
217     if( asprintf( &psz_config_name, "%s-audio-device", psz_audio_output ) == -1 )
218         return;
219     if( !var_Type( mp, psz_config_name ) )
220         /* Don't recreate the same variable over and over and over... */
221         var_Create( mp, psz_config_name, VLC_VAR_STRING );
222     var_SetString( mp, psz_config_name, psz_device_id );
223     free( psz_config_name );
224 }
225
226 /*****************************************************************************
227  * libvlc_audio_output_get_device_type : Get the current audio device type
228  *****************************************************************************/
229 int libvlc_audio_output_get_device_type( libvlc_media_player_t *mp )
230 {
231     audio_output_t *p_aout = GetAOut( mp );
232     if( p_aout )
233     {
234         int i_device_type = var_GetInteger( p_aout, "audio-device" );
235         vlc_object_release( p_aout );
236         return i_device_type;
237     }
238     return libvlc_AudioOutputDevice_Error;
239 }
240
241 /*****************************************************************************
242  * libvlc_audio_output_set_device_type : Set the audio device type
243  *****************************************************************************/
244 void libvlc_audio_output_set_device_type( libvlc_media_player_t *mp,
245                                           int device_type )
246 {
247     audio_output_t *p_aout = GetAOut( mp );
248     if( !p_aout )
249         return;
250     if( var_SetInteger( p_aout, "audio-device", device_type ) < 0 )
251         libvlc_printerr( "Error setting audio device" );
252     vlc_object_release( p_aout );
253 }
254
255 void libvlc_audio_toggle_mute( libvlc_media_player_t *mp )
256 {
257     aout_MuteToggle( mp );
258 }
259
260 int libvlc_audio_get_mute( libvlc_media_player_t *mp )
261 {
262     return aout_MuteGet( mp );
263 }
264
265 void libvlc_audio_set_mute( libvlc_media_player_t *mp, int mute )
266 {
267     aout_MuteSet( VLC_OBJECT(mp), mute != 0 );
268 }
269
270 int libvlc_audio_get_volume( libvlc_media_player_t *mp )
271 {
272     float vol = aout_VolumeGet( mp );
273     return ( vol >= 0.f ) ? lroundf( vol * 100.f ) : -1;
274 }
275
276 int libvlc_audio_set_volume( libvlc_media_player_t *mp, int volume )
277 {
278     float vol = volume / 100.f;
279     if (vol < 0.f)
280     {
281         libvlc_printerr( "Volume out of range" );
282         return -1;
283     }
284     aout_VolumeSet (mp, vol);
285     return 0;
286 }
287
288 /*****************************************************************************
289  * libvlc_audio_get_track_count : Get the number of available audio tracks
290  *****************************************************************************/
291 int libvlc_audio_get_track_count( libvlc_media_player_t *p_mi )
292 {
293     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
294     int i_track_count;
295
296     if( !p_input_thread )
297         return -1;
298
299     i_track_count = var_CountChoices( p_input_thread, "audio-es" );
300
301     vlc_object_release( p_input_thread );
302     return i_track_count;
303 }
304
305 /*****************************************************************************
306  * libvlc_audio_get_track_description : Get the description of available audio tracks
307  *****************************************************************************/
308 libvlc_track_description_t *
309         libvlc_audio_get_track_description( libvlc_media_player_t *p_mi )
310 {
311     return libvlc_get_track_description( p_mi, "audio-es" );
312 }
313
314 /*****************************************************************************
315  * libvlc_audio_get_track : Get the current audio track
316  *****************************************************************************/
317 int libvlc_audio_get_track( libvlc_media_player_t *p_mi )
318 {
319     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
320     vlc_value_t val_list;
321     vlc_value_t val;
322     int i_track = -1;
323     int i;
324
325     if( !p_input_thread )
326         return -1;
327
328     if( var_Get( p_input_thread, "audio-es", &val ) < 0 )
329     {
330         vlc_object_release( p_input_thread );
331         libvlc_printerr( "Audio track information not found" );
332         return -1;
333     }
334
335     var_Change( p_input_thread, "audio-es", VLC_VAR_GETCHOICES, &val_list, NULL );
336     for( i = 0; i < val_list.p_list->i_count; i++ )
337     {
338         if( val_list.p_list->p_values[i].i_int == val.i_int )
339         {
340             i_track = i;
341             break;
342         }
343     }
344     var_FreeList( &val_list, NULL );
345     vlc_object_release( p_input_thread );
346     return i_track;
347 }
348
349 /*****************************************************************************
350  * libvlc_audio_set_track : Set the current audio track
351  *****************************************************************************/
352 int libvlc_audio_set_track( libvlc_media_player_t *p_mi, int i_track )
353 {
354     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
355     vlc_value_t val_list;
356     vlc_value_t newval;
357     int i_ret;
358
359     if( !p_input_thread )
360         return -1;
361
362     var_Change( p_input_thread, "audio-es", VLC_VAR_GETCHOICES, &val_list, NULL );
363     if( (i_track < 0) || (i_track > val_list.p_list->i_count) )
364     {
365         libvlc_printerr( "Audio track out of range" );
366         i_ret = -1;
367         goto end;
368     }
369
370     newval = val_list.p_list->p_values[i_track];
371     i_ret = var_Set( p_input_thread, "audio-es", newval );
372     if( i_ret < 0 )
373     {
374         libvlc_printerr( "Audio track out of range" ); /* Race... */
375         i_ret = -1;
376         goto end;
377     }
378     i_ret = 0;
379
380 end:
381     var_FreeList( &val_list, NULL );
382     vlc_object_release( p_input_thread );
383     return i_ret;
384 }
385
386 /*****************************************************************************
387  * libvlc_audio_get_channel : Get the current audio channel
388  *****************************************************************************/
389 int libvlc_audio_get_channel( libvlc_media_player_t *mp )
390 {
391     audio_output_t *p_aout = GetAOut( mp );
392     if( !p_aout )
393         return 0;
394
395     int val = var_GetInteger( p_aout, "stereo-mode" );
396     vlc_object_release( p_aout );
397     return val;
398 }
399
400 /*****************************************************************************
401  * libvlc_audio_set_channel : Set the current audio channel
402  *****************************************************************************/
403 int libvlc_audio_set_channel( libvlc_media_player_t *mp, int channel )
404 {
405     audio_output_t *p_aout = GetAOut( mp );
406     int ret = 0;
407
408     if( !p_aout )
409         return -1;
410
411     if( var_SetInteger( p_aout, "stereo-mode", channel ) < 0 )
412     {
413         libvlc_printerr( "Audio channel out of range" );
414         ret = -1;
415     }
416     vlc_object_release( p_aout );
417     return ret;
418 }
419
420 /*****************************************************************************
421  * libvlc_audio_get_delay : Get the current audio delay
422  *****************************************************************************/
423 int64_t libvlc_audio_get_delay( libvlc_media_player_t *p_mi )
424 {
425     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
426     int64_t val = 0;
427     if( p_input_thread != NULL )
428     {
429       val = var_GetTime( p_input_thread, "audio-delay" );
430       vlc_object_release( p_input_thread );
431     }
432     return val;
433 }
434
435 /*****************************************************************************
436  * libvlc_audio_set_delay : Set the current audio delay
437  *****************************************************************************/
438 int libvlc_audio_set_delay( libvlc_media_player_t *p_mi, int64_t i_delay )
439 {
440     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
441     int ret = 0;
442     if( p_input_thread != NULL )
443     {
444       var_SetTime( p_input_thread, "audio-delay", i_delay );
445       vlc_object_release( p_input_thread );
446     }
447     else
448     {
449       ret = -1;
450     }
451     return ret;
452 }