]> git.sesse.net Git - vlc/blob - lib/audio.c
lib: correct and uniformize audio/video track IDs (fixes #7645)
[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.h>
39 #include <vlc_modules.h>
40
41 #include "libvlc_internal.h"
42 #include "media_player_internal.h"
43
44 /*
45  * Remember to release the returned audio_output_t since it is locked at
46  * the end of this function.
47  */
48 static audio_output_t *GetAOut( libvlc_media_player_t *mp )
49 {
50     assert( mp != NULL );
51
52     audio_output_t *p_aout = input_resource_HoldAout( mp->input.p_resource );
53     if( p_aout == NULL )
54         libvlc_printerr( "No active audio output" );
55     return p_aout;
56 }
57
58 /*****************************************
59  * Get the list of available audio outputs
60  *****************************************/
61 libvlc_audio_output_t *
62         libvlc_audio_output_list_get( libvlc_instance_t *p_instance )
63 {
64     size_t count;
65     module_t **module_list = module_list_get( &count );
66     libvlc_audio_output_t *list = NULL;
67
68     for (size_t i = 0; i < count; i++)
69     {
70         module_t *module = module_list[i];
71
72         if( !module_provides( module, "audio output" ) )
73             continue;
74
75         libvlc_audio_output_t *item = malloc( sizeof( *item ) );
76         if( unlikely(item == NULL) )
77         {
78     error:
79             libvlc_printerr( "Not enough memory" );
80             libvlc_audio_output_list_release( list );
81             list = NULL;
82             break;
83         }
84
85         item->psz_name = strdup( module_get_object( module ) );
86         item->psz_description = strdup( module_get_name( module, true ) );
87         if( unlikely(item->psz_name == NULL || item->psz_description == NULL) )
88         {
89             free( item );
90             goto error;
91         }
92         item->p_next = list;
93         list = item;
94     }
95     module_list_free( module_list );
96
97     VLC_UNUSED( p_instance );
98     return list;
99 }
100
101 /********************************************
102  * Free the list of available audio outputs
103  ***********************************************/
104 void libvlc_audio_output_list_release( libvlc_audio_output_t *list )
105 {
106     while( list != NULL )
107     {
108         libvlc_audio_output_t *next = list->p_next;
109
110         free( list->psz_name );
111         free( list->psz_description );
112         free( list );
113         list = next;
114     }
115 }
116
117
118 /***********************
119  * Set the audio output.
120  ***********************/
121 int libvlc_audio_output_set( libvlc_media_player_t *mp, const char *psz_name )
122 {
123     char *value;
124
125     if( !module_exists( psz_name )
126      || asprintf( &value, "%s,none", psz_name ) == -1 )
127         return -1;
128     var_SetString( mp, "aout", value );
129     free( value );
130     return 0;
131 }
132
133 libvlc_audio_output_device_t *
134 libvlc_audio_output_device_list_get( libvlc_instance_t *p_instance,
135                                      const char *aout )
136 {
137     char varname[32];
138     if( (size_t)snprintf( varname, sizeof(varname), "%s-output-device", aout )
139                                                            >= sizeof(varname) )
140         return NULL;
141
142     libvlc_audio_output_device_t *list = NULL, **pp = &list;
143     char **values, **texts;
144     ssize_t count = config_GetPszChoices( VLC_OBJECT(p_instance->p_libvlc_int),
145                                           varname, &values, &texts );
146     for( ssize_t i = 0; i < count; i++ )
147     {
148         libvlc_audio_output_device_t *item = malloc( sizeof(*item) );
149         if( unlikely(item == NULL) )
150             break;
151
152         *pp = item;
153         pp = &item->p_next;
154         item->psz_device = values[i];
155         item->psz_description = texts[i];
156     }
157
158     *pp = NULL;
159     free( texts );
160     free( values );
161     (void) p_instance;
162     return list;
163 }
164
165 void libvlc_audio_output_device_list_release( libvlc_audio_output_device_t *l )
166 {
167     while( l != NULL )
168     {
169         libvlc_audio_output_device_t *next = l->p_next;
170
171         free( l->psz_description );
172         free( l->psz_device );
173         free( l );
174         l = next;
175     }
176 }
177
178 int libvlc_audio_output_device_count( libvlc_instance_t *p_instance,
179                                       const char *psz_audio_output )
180 {
181     (void) p_instance; (void) psz_audio_output;
182     return 0;
183 }
184
185 char *libvlc_audio_output_device_longname( libvlc_instance_t *p_instance,
186                                            const char *psz_audio_output,
187                                            int i_device )
188 {
189     (void) p_instance; (void) psz_audio_output; (void) i_device;
190     return NULL;
191 }
192
193 char *libvlc_audio_output_device_id( libvlc_instance_t *p_instance,
194                                      const char *psz_audio_output,
195                                      int i_device )
196 {
197     (void) p_instance; (void) psz_audio_output; (void) i_device;
198     return NULL;
199 }
200
201 /*****************************
202  * Set device for using
203  *****************************/
204 void libvlc_audio_output_device_set( libvlc_media_player_t *mp,
205                                      const char *psz_audio_output,
206                                      const char *psz_device_id )
207 {
208     char *psz_config_name;
209     if( !psz_audio_output || !psz_device_id )
210         return;
211     if( asprintf( &psz_config_name, "%s-audio-device", psz_audio_output ) == -1 )
212         return;
213     if( !var_Type( mp, psz_config_name ) )
214         /* Don't recreate the same variable over and over and over... */
215         var_Create( mp, psz_config_name, VLC_VAR_STRING );
216     var_SetString( mp, psz_config_name, psz_device_id );
217     free( psz_config_name );
218 }
219
220 /*****************************************************************************
221  * libvlc_audio_output_get_device_type : Get the current audio device type
222  *****************************************************************************/
223 int libvlc_audio_output_get_device_type( libvlc_media_player_t *mp )
224 {
225     audio_output_t *p_aout = GetAOut( mp );
226     if( p_aout )
227     {
228         int i_device_type = var_GetInteger( p_aout, "audio-device" );
229         vlc_object_release( p_aout );
230         return i_device_type;
231     }
232     return libvlc_AudioOutputDevice_Error;
233 }
234
235 /*****************************************************************************
236  * libvlc_audio_output_set_device_type : Set the audio device type
237  *****************************************************************************/
238 void libvlc_audio_output_set_device_type( libvlc_media_player_t *mp,
239                                           int device_type )
240 {
241     audio_output_t *p_aout = GetAOut( mp );
242     if( !p_aout )
243         return;
244     if( var_SetInteger( p_aout, "audio-device", device_type ) < 0 )
245         libvlc_printerr( "Error setting audio device" );
246     vlc_object_release( p_aout );
247 }
248
249 void libvlc_audio_toggle_mute( libvlc_media_player_t *mp )
250 {
251     int mute = libvlc_audio_get_mute( mp );
252     if( mute != -1 )
253         libvlc_audio_set_mute( mp, !mute );
254 }
255
256 int libvlc_audio_get_mute( libvlc_media_player_t *mp )
257 {
258     int mute = -1;
259
260     audio_output_t *aout = GetAOut( mp );
261     if( aout != NULL )
262     {
263         mute = aout_MuteGet( aout );
264         vlc_object_release( aout );
265     }
266     return mute;
267 }
268
269 void libvlc_audio_set_mute( libvlc_media_player_t *mp, int mute )
270 {
271     audio_output_t *aout = GetAOut( mp );
272     if( aout != NULL )
273     {
274         mute = aout_MuteSet( aout, mute );
275         vlc_object_release( aout );
276     }
277 }
278
279 int libvlc_audio_get_volume( libvlc_media_player_t *mp )
280 {
281     int volume = -1;
282
283     audio_output_t *aout = GetAOut( mp );
284     if( aout != NULL )
285     {
286         float vol = aout_VolumeGet( aout );
287         vlc_object_release( aout );
288         volume = lroundf( vol * 100.f );
289     }
290     return volume;
291 }
292
293 int libvlc_audio_set_volume( libvlc_media_player_t *mp, int volume )
294 {
295     float vol = volume / 100.f;
296     if (vol < 0.f)
297     {
298         libvlc_printerr( "Volume out of range" );
299         return -1;
300     }
301
302     int ret = -1;
303     audio_output_t *aout = GetAOut( mp );
304     if( aout != NULL )
305     {
306         ret = aout_VolumeSet( aout, vol );
307         vlc_object_release( aout );
308     }
309     return ret;
310 }
311
312 /*****************************************************************************
313  * libvlc_audio_get_track_count : Get the number of available audio tracks
314  *****************************************************************************/
315 int libvlc_audio_get_track_count( libvlc_media_player_t *p_mi )
316 {
317     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
318     int i_track_count;
319
320     if( !p_input_thread )
321         return -1;
322
323     i_track_count = var_CountChoices( p_input_thread, "audio-es" );
324
325     vlc_object_release( p_input_thread );
326     return i_track_count;
327 }
328
329 /*****************************************************************************
330  * libvlc_audio_get_track_description : Get the description of available audio tracks
331  *****************************************************************************/
332 libvlc_track_description_t *
333         libvlc_audio_get_track_description( libvlc_media_player_t *p_mi )
334 {
335     return libvlc_get_track_description( p_mi, "audio-es" );
336 }
337
338 /*****************************************************************************
339  * libvlc_audio_get_track : Get the current audio track
340  *****************************************************************************/
341 int libvlc_audio_get_track( libvlc_media_player_t *p_mi )
342 {
343     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
344     if( !p_input_thread )
345         return -1;
346
347     int id = var_GetInteger( p_input_thread, "audio-es" );
348     vlc_object_release( p_input_thread );
349     return id;
350 }
351
352 /*****************************************************************************
353  * libvlc_audio_set_track : Set the current audio track
354  *****************************************************************************/
355 int libvlc_audio_set_track( libvlc_media_player_t *p_mi, int i_track )
356 {
357     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
358     vlc_value_t val_list;
359     int i_ret;
360
361     if( !p_input_thread )
362         return -1;
363
364     var_Change( p_input_thread, "audio-es", VLC_VAR_GETCHOICES, &val_list, NULL );
365     for( int i = 0; i < val_list.p_list->i_count; i++ )
366     {
367         if( i_track == val_list.p_list->p_values[i].i_int )
368         {
369             if( var_SetInteger( p_input_thread, "audio-es", i_track ) < 0 )
370                 break;
371             i_ret = 0;
372             goto end;
373         }
374     }
375     libvlc_printerr( "Track identifier not found" );
376 end:
377     var_FreeList( &val_list, NULL );
378     vlc_object_release( p_input_thread );
379     return i_ret;
380 }
381
382 /*****************************************************************************
383  * libvlc_audio_get_channel : Get the current audio channel
384  *****************************************************************************/
385 int libvlc_audio_get_channel( libvlc_media_player_t *mp )
386 {
387     audio_output_t *p_aout = GetAOut( mp );
388     if( !p_aout )
389         return 0;
390
391     int val = var_GetInteger( p_aout, "stereo-mode" );
392     vlc_object_release( p_aout );
393     return val;
394 }
395
396 /*****************************************************************************
397  * libvlc_audio_set_channel : Set the current audio channel
398  *****************************************************************************/
399 int libvlc_audio_set_channel( libvlc_media_player_t *mp, int channel )
400 {
401     audio_output_t *p_aout = GetAOut( mp );
402     int ret = 0;
403
404     if( !p_aout )
405         return -1;
406
407     if( var_SetInteger( p_aout, "stereo-mode", channel ) < 0 )
408     {
409         libvlc_printerr( "Audio channel out of range" );
410         ret = -1;
411     }
412     vlc_object_release( p_aout );
413     return ret;
414 }
415
416 /*****************************************************************************
417  * libvlc_audio_get_delay : Get the current audio delay
418  *****************************************************************************/
419 int64_t libvlc_audio_get_delay( libvlc_media_player_t *p_mi )
420 {
421     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
422     int64_t val = 0;
423     if( p_input_thread != NULL )
424     {
425       val = var_GetTime( p_input_thread, "audio-delay" );
426       vlc_object_release( p_input_thread );
427     }
428     return val;
429 }
430
431 /*****************************************************************************
432  * libvlc_audio_set_delay : Set the current audio delay
433  *****************************************************************************/
434 int libvlc_audio_set_delay( libvlc_media_player_t *p_mi, int64_t i_delay )
435 {
436     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
437     int ret = 0;
438     if( p_input_thread != NULL )
439     {
440       var_SetTime( p_input_thread, "audio-delay", i_delay );
441       vlc_object_release( p_input_thread );
442     }
443     else
444     {
445       ret = -1;
446     }
447     return ret;
448 }