]> git.sesse.net Git - vlc/blob - src/control/audio.c
NEWS update
[vlc] / src / control / audio.c
1 /*****************************************************************************
2  * libvlc_audio.c: New libvlc audio control API
3  *****************************************************************************
4  * Copyright (C) 2006 the VideoLAN team
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
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 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 General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, 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
31 #include <vlc/libvlc.h>
32 #include <vlc/libvlc_media.h>
33 #include <vlc/libvlc_media_player.h>
34
35 #include <vlc_common.h>
36 #include <vlc_input.h>
37 #include <vlc_aout.h>
38 #include <vlc_modules.h>
39
40 #include "libvlc_internal.h"
41 #include "media_player_internal.h"
42
43 /*
44  * Remember to release the returned aout_instance_t since it is locked at
45  * the end of this function.
46  */
47 static aout_instance_t *GetAOut( libvlc_media_player_t *mp )
48 {
49     assert( mp != NULL );
50
51     input_thread_t *p_input = libvlc_get_input_thread( mp );
52     if( p_input == NULL )
53         return NULL;
54
55     aout_instance_t * p_aout = input_GetAout( p_input );
56     vlc_object_release( p_input );
57     if( p_aout == NULL )
58         libvlc_printerr( "No active audio output" );
59     return p_aout;
60 }
61
62 /*****************************************
63  * Get the list of available audio outputs
64  *****************************************/
65 libvlc_audio_output_t *
66         libvlc_audio_output_list_get( libvlc_instance_t *p_instance )
67 {
68     VLC_UNUSED( p_instance );
69     libvlc_audio_output_t *p_list = NULL,
70                           *p_actual = NULL,
71                           *p_previous = NULL;
72     module_t **module_list = module_list_get( NULL );
73
74     for (size_t i = 0; module_list[i]; i++)
75     {
76         module_t *p_module = module_list[i];
77
78         if( module_provides( p_module, "audio output" ) )
79         {
80             if( p_actual == NULL)
81             {
82                 p_actual = ( libvlc_audio_output_t * )
83                     malloc( sizeof( libvlc_audio_output_t ) );
84                 if( p_actual == NULL )
85                 {
86                     libvlc_printerr( "Not enough memory" );
87                     libvlc_audio_output_list_release( p_list );
88                     module_list_free( module_list );
89                     return NULL;
90                 }
91                 if( p_list == NULL )
92                 {
93                     p_list = p_actual;
94                     p_previous = p_actual;
95                 }
96             }
97             p_actual->psz_name = strdup( module_get_object( p_module ) );
98             p_actual->psz_description = strdup( module_get_name( p_module, true )  );
99             p_actual->p_next = NULL;
100             if( p_previous != p_actual ) /* not first item */
101                 p_previous->p_next = p_actual;
102             p_previous = p_actual;
103             p_actual = p_actual->p_next;
104         }
105     }
106
107     module_list_free( module_list );
108
109     return p_list;
110 }
111
112 /********************************************
113  * Free the list of available audio outputs
114  ***********************************************/
115 void libvlc_audio_output_list_release( libvlc_audio_output_t *p_list )
116 {
117     libvlc_audio_output_t *p_actual, *p_before;
118     p_actual = p_list;
119
120     while ( p_actual )
121     {
122         free( p_actual->psz_name );
123         free( p_actual->psz_description );
124         p_before = p_actual;
125         p_actual = p_before->p_next;
126         free( p_before );
127     }
128 }
129
130
131 /***********************
132  * Set the audio output.
133  ***********************/
134 int libvlc_audio_output_set( libvlc_media_player_t *mp, const char *psz_name )
135 {
136     if( !module_exists( psz_name ) )
137         return -1;
138     var_SetString( mp, "aout", psz_name );
139     return 0;
140 }
141
142 /****************************
143  * Get count of devices.
144  *****************************/
145 int libvlc_audio_output_device_count( libvlc_instance_t *p_instance,
146                                       const char *psz_audio_output )
147 {
148     char *psz_config_name;
149     if( !psz_audio_output )
150         return 0;
151     if( asprintf( &psz_config_name, "%s-audio-device", psz_audio_output ) == -1 )
152         return 0;
153
154     module_config_t *p_module_config = config_FindConfig(
155         VLC_OBJECT( p_instance->p_libvlc_int ), psz_config_name );
156
157     if( p_module_config && p_module_config->pf_update_list )
158     {
159         vlc_value_t val;
160         val.psz_string = strdup( p_module_config->value.psz );
161
162         p_module_config->pf_update_list(
163             VLC_OBJECT( p_instance->p_libvlc_int ), psz_config_name, val, val, NULL );
164         free( val.psz_string );
165         free( psz_config_name );
166
167         return p_module_config->i_list;
168     }
169
170     free( psz_config_name );
171     return 0;
172 }
173
174 /********************************
175  * Get long name of device
176  *********************************/
177 char * libvlc_audio_output_device_longname( libvlc_instance_t *p_instance,
178                                             const char *psz_audio_output,
179                                             int i_device )
180 {
181     char *psz_config_name;
182     if( !psz_audio_output )
183         return NULL;
184     if( asprintf( &psz_config_name, "%s-audio-device", psz_audio_output ) == -1 )
185         return NULL;
186
187     module_config_t *p_module_config = config_FindConfig(
188         VLC_OBJECT( p_instance->p_libvlc_int ), psz_config_name );
189
190     if( p_module_config )
191     {
192         // refresh if there arent devices
193         if( p_module_config->i_list < 2 && p_module_config->pf_update_list )
194         {
195             vlc_value_t val;
196             val.psz_string = strdup( p_module_config->value.psz );
197
198             p_module_config->pf_update_list(
199                 VLC_OBJECT( p_instance->p_libvlc_int ), psz_config_name, val, val, NULL );
200             free( val.psz_string );
201         }
202         free( psz_config_name );
203
204         if( i_device >= 0 && i_device < p_module_config->i_list )
205         {
206             if( p_module_config->ppsz_list_text[i_device] )
207                 return strdup( p_module_config->ppsz_list_text[i_device] );
208             else
209                 return strdup( p_module_config->ppsz_list[i_device] );
210         }
211     }
212
213     free( psz_config_name );
214     return NULL;
215 }
216
217 /********************************
218  * Get id name of device
219  *********************************/
220 char * libvlc_audio_output_device_id( libvlc_instance_t *p_instance,
221                                       const char *psz_audio_output,
222                                       int i_device )
223 {
224     char *psz_config_name;
225     if( !psz_audio_output )
226         return NULL;
227     if( asprintf( &psz_config_name, "%s-audio-device", psz_audio_output ) == -1)
228         return NULL;
229
230     module_config_t *p_module_config = config_FindConfig(
231         VLC_OBJECT( p_instance->p_libvlc_int ), psz_config_name );
232
233     if( p_module_config )
234     {
235         // refresh if there arent devices
236         if( p_module_config->i_list < 2 && p_module_config->pf_update_list )
237         {
238             vlc_value_t val;
239             val.psz_string = strdup( p_module_config->value.psz );
240
241             p_module_config->pf_update_list(
242                 VLC_OBJECT( p_instance->p_libvlc_int ), psz_config_name, val, val, NULL );
243             free( val.psz_string );
244         }
245         free( psz_config_name );
246
247         if( i_device >= 0 && i_device < p_module_config->i_list )
248             return strdup( p_module_config->ppsz_list[i_device] );
249
250     }
251
252     free( psz_config_name );
253     return NULL;
254 }
255
256 /*****************************
257  * Set device for using
258  *****************************/
259 void libvlc_audio_output_device_set( libvlc_media_player_t *mp,
260                                      const char *psz_audio_output,
261                                      const char *psz_device_id )
262 {
263     char *psz_config_name;
264     if( !psz_audio_output || !psz_device_id )
265         return;
266     if( asprintf( &psz_config_name, "%s-audio-device", psz_audio_output ) == -1 )
267         return;
268     if( !var_Type( mp, psz_audio_output ) )
269         /* Don't recreate the same variable over and over and over... */
270         var_Create( mp, psz_audio_output, VLC_VAR_STRING );
271     var_SetString( mp, psz_config_name, psz_device_id );
272     free( psz_config_name );
273 }
274
275 /*****************************************************************************
276  * libvlc_audio_output_get_device_type : Get the current audio device type
277  *****************************************************************************/
278 int libvlc_audio_output_get_device_type( libvlc_media_player_t *mp )
279 {
280     aout_instance_t *p_aout = GetAOut( mp );
281     if( p_aout )
282     {
283         int i_device_type = var_GetInteger( p_aout, "audio-device" );
284         vlc_object_release( p_aout );
285         return i_device_type;
286     }
287     return libvlc_AudioOutputDevice_Error;
288 }
289
290 /*****************************************************************************
291  * libvlc_audio_output_set_device_type : Set the audio device type
292  *****************************************************************************/
293 void libvlc_audio_output_set_device_type( libvlc_media_player_t *mp,
294                                           int device_type )
295 {
296     aout_instance_t *p_aout = GetAOut( mp );
297     if( !p_aout )
298         return;
299     if( var_SetInteger( p_aout, "audio-device", device_type ) < 0 )
300         libvlc_printerr( "Error setting audio device" );
301     vlc_object_release( p_aout );
302 }
303
304 /*****************************************************************************
305  * libvlc_audio_get_mute : Get the volume state, true if muted
306  *****************************************************************************/
307 void libvlc_audio_toggle_mute( libvlc_media_player_t *mp )
308 {
309     aout_ToggleMute( mp, NULL );
310 }
311
312 int libvlc_audio_get_mute( libvlc_media_player_t *mp )
313 {
314     return (libvlc_audio_get_volume(mp) == 0);
315 }
316
317 void libvlc_audio_set_mute( libvlc_media_player_t *mp, int mute )
318 {
319     aout_SetMute( VLC_OBJECT(mp), NULL, !!mute );
320 }
321
322 /*****************************************************************************
323  * libvlc_audio_get_volume : Get the current volume (range 0-200 %)
324  *****************************************************************************/
325 int libvlc_audio_get_volume( libvlc_media_player_t *mp )
326 {
327     audio_volume_t i_volume;
328
329     aout_VolumeGet( mp, &i_volume );
330
331     return (i_volume*200+AOUT_VOLUME_MAX/2)/AOUT_VOLUME_MAX;
332 }
333
334
335 /*****************************************************************************
336  * libvlc_audio_set_volume : Set the current volume
337  *****************************************************************************/
338 int libvlc_audio_set_volume( libvlc_media_player_t *mp, int i_volume )
339 {
340     if( i_volume < 0 || i_volume > 200 )
341     {
342         libvlc_printerr( "Volume out of range" );
343         return -1;
344     }
345
346     i_volume = (i_volume * AOUT_VOLUME_MAX + 100) / 200;
347     aout_VolumeSet( mp, i_volume );
348     return 0;
349 }
350
351 /*****************************************************************************
352  * libvlc_audio_get_track_count : Get the number of available audio tracks
353  *****************************************************************************/
354 int libvlc_audio_get_track_count( libvlc_media_player_t *p_mi )
355 {
356     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
357     int i_track_count;
358
359     if( !p_input_thread )
360         return -1;
361
362     i_track_count = var_CountChoices( p_input_thread, "audio-es" );
363
364     vlc_object_release( p_input_thread );
365     return i_track_count;
366 }
367
368 /*****************************************************************************
369  * libvlc_audio_get_track_description : Get the description of available audio tracks
370  *****************************************************************************/
371 libvlc_track_description_t *
372         libvlc_audio_get_track_description( libvlc_media_player_t *p_mi )
373 {
374     return libvlc_get_track_description( p_mi, "audio-es" );
375 }
376
377 /*****************************************************************************
378  * libvlc_audio_get_track : Get the current audio track
379  *****************************************************************************/
380 int libvlc_audio_get_track( libvlc_media_player_t *p_mi )
381 {
382     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
383     vlc_value_t val_list;
384     vlc_value_t val;
385     int i_track = -1;
386     int i;
387
388     if( !p_input_thread )
389         return -1;
390
391     if( var_Get( p_input_thread, "audio-es", &val ) < 0 )
392     {
393         vlc_object_release( p_input_thread );
394         libvlc_printerr( "Audio track information not found" );
395         return -1;
396     }
397
398     var_Change( p_input_thread, "audio-es", VLC_VAR_GETCHOICES, &val_list, NULL );
399     for( i = 0; i < val_list.p_list->i_count; i++ )
400     {
401         if( val_list.p_list->p_values[i].i_int == val.i_int )
402         {
403             i_track = i;
404             break;
405         }
406     }
407     var_FreeList( &val_list, NULL );
408     vlc_object_release( p_input_thread );
409     return i_track;
410 }
411
412 /*****************************************************************************
413  * libvlc_audio_set_track : Set the current audio track
414  *****************************************************************************/
415 int libvlc_audio_set_track( libvlc_media_player_t *p_mi, int i_track )
416 {
417     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
418     vlc_value_t val_list;
419     vlc_value_t newval;
420     int i_ret;
421
422     if( !p_input_thread )
423         return -1;
424
425     var_Change( p_input_thread, "audio-es", VLC_VAR_GETCHOICES, &val_list, NULL );
426     if( (i_track < 0) || (i_track > val_list.p_list->i_count) )
427     {
428         libvlc_printerr( "Audio track out of range" );
429         i_ret = -1;
430         goto end;
431     }
432
433     newval = val_list.p_list->p_values[i_track];
434     i_ret = var_Set( p_input_thread, "audio-es", newval );
435     if( i_ret < 0 )
436     {
437         libvlc_printerr( "Audio track out of range" ); /* Race... */
438         i_ret = -1;
439         goto end;
440     }
441     i_ret = 0;
442
443 end:
444     var_FreeList( &val_list, NULL );
445     vlc_object_release( p_input_thread );
446     return i_ret;
447 }
448
449 /*****************************************************************************
450  * libvlc_audio_get_channel : Get the current audio channel
451  *****************************************************************************/
452 int libvlc_audio_get_channel( libvlc_media_player_t *mp )
453 {
454     aout_instance_t *p_aout = GetAOut( mp );
455     if( !p_aout )
456         return 0;
457
458     int val = var_GetInteger( p_aout, "audio-channels" );
459     vlc_object_release( p_aout );
460     return val;
461 }
462
463 /*****************************************************************************
464  * libvlc_audio_set_channel : Set the current audio channel
465  *****************************************************************************/
466 int libvlc_audio_set_channel( libvlc_media_player_t *mp, int channel )
467 {
468     aout_instance_t *p_aout = GetAOut( mp );
469     int ret = 0;
470
471     if( !p_aout )
472         return -1;
473
474     if( var_SetInteger( p_aout, "audio-channels", channel ) < 0 )
475     {
476         libvlc_printerr( "Audio channel out of range" );
477         ret = -1;
478     }
479     vlc_object_release( p_aout );
480     return ret;
481 }
482
483 /*****************************************************************************
484  * libvlc_audio_get_delay : Get the current audio delay
485  *****************************************************************************/
486 int64_t libvlc_audio_get_delay( libvlc_media_player_t *p_mi )
487 {
488     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
489     int64_t val = 0;
490     if( p_input_thread != NULL )
491     {
492       val = var_GetTime( p_input_thread, "audio-delay" );
493       vlc_object_release( p_input_thread );
494     }
495     return val;
496 }
497
498 /*****************************************************************************
499  * libvlc_audio_set_delay : Set the current audio delay
500  *****************************************************************************/
501 int libvlc_audio_set_delay( libvlc_media_player_t *p_mi, int64_t i_delay )
502 {
503     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
504     int ret = 0;
505     if( p_input_thread != NULL )
506     {
507       var_SetTime( p_input_thread, "audio-delay", i_delay );
508       vlc_object_release( p_input_thread );
509     }
510     else
511     {
512       ret = -1;
513     }
514     return ret;
515 }