]> git.sesse.net Git - vlc/blob - lib/audio.c
direct3d11: code cleaning and typos
[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
131     /* Forget the existing audio output */
132     input_resource_ResetAout(mp->input.p_resource);
133
134     /* Create a new audio output */
135     audio_output_t *aout = input_resource_GetAout(mp->input.p_resource);
136     if( aout != NULL )
137         input_resource_PutAout(mp->input.p_resource, aout);
138
139     return 0;
140 }
141
142 libvlc_audio_output_device_t *
143 libvlc_audio_output_device_enum( libvlc_media_player_t *mp )
144 {
145     audio_output_t *aout = GetAOut( mp );
146     if( aout == NULL )
147         return NULL;
148
149     libvlc_audio_output_device_t *list, **pp = &list;
150     char **values, **texts;
151
152     int n = aout_DevicesList( aout, &values, &texts );
153     vlc_object_release( aout );
154     if( n < 0 )
155         goto err;
156
157     for (int i = 0; i < n; i++)
158     {
159         libvlc_audio_output_device_t *item = malloc( sizeof(*item) );
160         if( unlikely(item == NULL) )
161         {
162             free( texts[i] );
163             free( values[i] );
164             continue;
165         }
166
167         *pp = item;
168         pp = &item->p_next;
169         item->psz_device = values[i];
170         item->psz_description = texts[i];
171     }
172
173     free( texts );
174     free( values );
175 err:
176     *pp = NULL;
177     return list;
178 }
179
180 libvlc_audio_output_device_t *
181 libvlc_audio_output_device_list_get( libvlc_instance_t *p_instance,
182                                      const char *aout )
183 {
184     char varname[32];
185     if( (size_t)snprintf( varname, sizeof(varname), "%s-audio-device", aout )
186                                                            >= sizeof(varname) )
187         return NULL;
188
189     libvlc_audio_output_device_t *list = NULL, **pp = &list;
190     char **values, **texts;
191     ssize_t count = config_GetPszChoices( VLC_OBJECT(p_instance->p_libvlc_int),
192                                           varname, &values, &texts );
193     for( ssize_t i = 0; i < count; i++ )
194     {
195         libvlc_audio_output_device_t *item = malloc( sizeof(*item) );
196         if( unlikely(item == NULL) )
197             break;
198
199         *pp = item;
200         pp = &item->p_next;
201         item->psz_device = values[i];
202         item->psz_description = texts[i];
203     }
204
205     *pp = NULL;
206     free( texts );
207     free( values );
208     (void) p_instance;
209     return list;
210 }
211
212 void libvlc_audio_output_device_list_release( libvlc_audio_output_device_t *l )
213 {
214     while( l != NULL )
215     {
216         libvlc_audio_output_device_t *next = l->p_next;
217
218         free( l->psz_description );
219         free( l->psz_device );
220         free( l );
221         l = next;
222     }
223 }
224
225 int libvlc_audio_output_device_count( libvlc_instance_t *p_instance,
226                                       const char *psz_audio_output )
227 {
228     (void) p_instance; (void) psz_audio_output;
229     return 0;
230 }
231
232 char *libvlc_audio_output_device_longname( libvlc_instance_t *p_instance,
233                                            const char *psz_audio_output,
234                                            int i_device )
235 {
236     (void) p_instance; (void) psz_audio_output; (void) i_device;
237     return NULL;
238 }
239
240 char *libvlc_audio_output_device_id( libvlc_instance_t *p_instance,
241                                      const char *psz_audio_output,
242                                      int i_device )
243 {
244     (void) p_instance; (void) psz_audio_output; (void) i_device;
245     return NULL;
246 }
247
248 /*****************************
249  * Set device for using
250  *****************************/
251 void libvlc_audio_output_device_set( libvlc_media_player_t *mp,
252                                      const char *module, const char *devid )
253 {
254     if( devid == NULL )
255         return;
256
257     if( module != NULL )
258     {
259         char *cfg_name;
260
261         if( asprintf( &cfg_name, "%s-audio-device", module ) == -1 )
262             return;
263
264         if( !var_Type( mp, cfg_name ) )
265             /* Don't recreate the same variable over and over and over... */
266             var_Create( mp, cfg_name, VLC_VAR_STRING );
267         var_SetString( mp, cfg_name, devid );
268         free( cfg_name );
269         return;
270     }
271
272     audio_output_t *aout = GetAOut( mp );
273     if( aout == NULL )
274         return;
275
276     aout_DeviceSet( aout, devid );
277     vlc_object_release( aout );
278 }
279
280 char *libvlc_audio_output_device_get( libvlc_media_player_t *mp )
281 {
282     audio_output_t *aout = GetAOut( mp );
283     if( aout == NULL )
284         return NULL;
285
286     char *devid = aout_DeviceGet( aout );
287
288     vlc_object_release( aout );
289
290     return devid;
291 }
292
293 int libvlc_audio_output_get_device_type( libvlc_media_player_t *mp )
294 {
295     (void) mp;
296     return libvlc_AudioOutputDevice_Error;
297 }
298
299 void libvlc_audio_output_set_device_type( libvlc_media_player_t *mp,
300                                           int device_type )
301 {
302     (void) mp; (void) device_type;
303 }
304
305 void libvlc_audio_toggle_mute( libvlc_media_player_t *mp )
306 {
307     int mute = libvlc_audio_get_mute( mp );
308     if( mute != -1 )
309         libvlc_audio_set_mute( mp, !mute );
310 }
311
312 int libvlc_audio_get_mute( libvlc_media_player_t *mp )
313 {
314     int mute = -1;
315
316     audio_output_t *aout = GetAOut( mp );
317     if( aout != NULL )
318     {
319         mute = aout_MuteGet( aout );
320         vlc_object_release( aout );
321     }
322     return mute;
323 }
324
325 void libvlc_audio_set_mute( libvlc_media_player_t *mp, int mute )
326 {
327     audio_output_t *aout = GetAOut( mp );
328     if( aout != NULL )
329     {
330         mute = aout_MuteSet( aout, mute );
331         vlc_object_release( aout );
332     }
333 }
334
335 int libvlc_audio_get_volume( libvlc_media_player_t *mp )
336 {
337     int volume = -1;
338
339     audio_output_t *aout = GetAOut( mp );
340     if( aout != NULL )
341     {
342         float vol = aout_VolumeGet( aout );
343         vlc_object_release( aout );
344         volume = lroundf( vol * 100.f );
345     }
346     return volume;
347 }
348
349 int libvlc_audio_set_volume( libvlc_media_player_t *mp, int volume )
350 {
351     float vol = volume / 100.f;
352     if (!isgreaterequal(vol, 0.f))
353     {
354         libvlc_printerr( "Volume out of range" );
355         return -1;
356     }
357
358     int ret = -1;
359     audio_output_t *aout = GetAOut( mp );
360     if( aout != NULL )
361     {
362         ret = aout_VolumeSet( aout, vol );
363         vlc_object_release( aout );
364     }
365     return ret;
366 }
367
368 /*****************************************************************************
369  * libvlc_audio_get_track_count : Get the number of available audio tracks
370  *****************************************************************************/
371 int libvlc_audio_get_track_count( libvlc_media_player_t *p_mi )
372 {
373     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
374     int i_track_count;
375
376     if( !p_input_thread )
377         return -1;
378
379     i_track_count = var_CountChoices( p_input_thread, "audio-es" );
380
381     vlc_object_release( p_input_thread );
382     return i_track_count;
383 }
384
385 /*****************************************************************************
386  * libvlc_audio_get_track_description : Get the description of available audio tracks
387  *****************************************************************************/
388 libvlc_track_description_t *
389         libvlc_audio_get_track_description( libvlc_media_player_t *p_mi )
390 {
391     return libvlc_get_track_description( p_mi, "audio-es" );
392 }
393
394 /*****************************************************************************
395  * libvlc_audio_get_track : Get the current audio track
396  *****************************************************************************/
397 int libvlc_audio_get_track( libvlc_media_player_t *p_mi )
398 {
399     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
400     if( !p_input_thread )
401         return -1;
402
403     int id = var_GetInteger( p_input_thread, "audio-es" );
404     vlc_object_release( p_input_thread );
405     return id;
406 }
407
408 /*****************************************************************************
409  * libvlc_audio_set_track : Set the current audio track
410  *****************************************************************************/
411 int libvlc_audio_set_track( libvlc_media_player_t *p_mi, int i_track )
412 {
413     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
414     vlc_value_t val_list;
415     int i_ret = -1;
416
417     if( !p_input_thread )
418         return -1;
419
420     var_Change( p_input_thread, "audio-es", VLC_VAR_GETCHOICES, &val_list, NULL );
421     for( int i = 0; i < val_list.p_list->i_count; i++ )
422     {
423         if( i_track == val_list.p_list->p_values[i].i_int )
424         {
425             if( var_SetInteger( p_input_thread, "audio-es", i_track ) < 0 )
426                 break;
427             i_ret = 0;
428             goto end;
429         }
430     }
431     libvlc_printerr( "Track identifier not found" );
432 end:
433     var_FreeList( &val_list, NULL );
434     vlc_object_release( p_input_thread );
435     return i_ret;
436 }
437
438 /*****************************************************************************
439  * libvlc_audio_get_channel : Get the current audio channel
440  *****************************************************************************/
441 int libvlc_audio_get_channel( libvlc_media_player_t *mp )
442 {
443     audio_output_t *p_aout = GetAOut( mp );
444     if( !p_aout )
445         return 0;
446
447     int val = var_GetInteger( p_aout, "stereo-mode" );
448     vlc_object_release( p_aout );
449     return val;
450 }
451
452 /*****************************************************************************
453  * libvlc_audio_set_channel : Set the current audio channel
454  *****************************************************************************/
455 int libvlc_audio_set_channel( libvlc_media_player_t *mp, int channel )
456 {
457     audio_output_t *p_aout = GetAOut( mp );
458     int ret = 0;
459
460     if( !p_aout )
461         return -1;
462
463     if( var_SetInteger( p_aout, "stereo-mode", channel ) < 0 )
464     {
465         libvlc_printerr( "Audio channel out of range" );
466         ret = -1;
467     }
468     vlc_object_release( p_aout );
469     return ret;
470 }
471
472 /*****************************************************************************
473  * libvlc_audio_get_delay : Get the current audio delay
474  *****************************************************************************/
475 int64_t libvlc_audio_get_delay( libvlc_media_player_t *p_mi )
476 {
477     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
478     int64_t val = 0;
479     if( p_input_thread != NULL )
480     {
481       val = var_GetTime( p_input_thread, "audio-delay" );
482       vlc_object_release( p_input_thread );
483     }
484     return val;
485 }
486
487 /*****************************************************************************
488  * libvlc_audio_set_delay : Set the current audio delay
489  *****************************************************************************/
490 int libvlc_audio_set_delay( libvlc_media_player_t *p_mi, int64_t i_delay )
491 {
492     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
493     int ret = 0;
494     if( p_input_thread != NULL )
495     {
496       var_SetTime( p_input_thread, "audio-delay", i_delay );
497       vlc_object_release( p_input_thread );
498     }
499     else
500     {
501       ret = -1;
502     }
503     return ret;
504 }
505
506 /*****************************************************************************
507  * libvlc_audio_equalizer_get_preset_count : Get the number of equalizer presets
508  *****************************************************************************/
509 unsigned libvlc_audio_equalizer_get_preset_count( void )
510 {
511     return NB_PRESETS;
512 }
513
514 /*****************************************************************************
515  * libvlc_audio_equalizer_get_preset_name : Get the name for a preset
516  *****************************************************************************/
517 const char *libvlc_audio_equalizer_get_preset_name( unsigned u_index )
518 {
519     if ( u_index >= NB_PRESETS )
520         return NULL;
521
522     return preset_list_text[ u_index ];
523 }
524
525 /*****************************************************************************
526  * libvlc_audio_equalizer_get_band_count : Get the number of equalizer frequency bands
527  *****************************************************************************/
528 unsigned libvlc_audio_equalizer_get_band_count( void )
529 {
530     return EQZ_BANDS_MAX;
531 }
532
533 /*****************************************************************************
534  * libvlc_audio_equalizer_get_band_frequency : Get the frequency for a band
535  *****************************************************************************/
536 float libvlc_audio_equalizer_get_band_frequency( unsigned u_index )
537 {
538     if ( u_index >= EQZ_BANDS_MAX )
539         return -1.f;
540
541     return f_iso_frequency_table_10b[ u_index ];
542 }
543
544 /*****************************************************************************
545  * libvlc_audio_equalizer_new : Create a new audio equalizer with zeroed values
546  *****************************************************************************/
547 libvlc_equalizer_t *libvlc_audio_equalizer_new( void )
548 {
549     libvlc_equalizer_t *p_equalizer;
550     p_equalizer = malloc( sizeof( *p_equalizer ) );
551     if ( unlikely( p_equalizer == NULL ) )
552         return NULL;
553
554     p_equalizer->f_preamp = 0.f;
555     for ( unsigned i = 0; i < EQZ_BANDS_MAX; i++ )
556         p_equalizer->f_amp[ i ] = 0.f;
557
558     return p_equalizer;
559 }
560
561 /*****************************************************************************
562  * libvlc_audio_equalizer_new_from_preset : Create a new audio equalizer based on a preset
563  *****************************************************************************/
564 libvlc_equalizer_t *libvlc_audio_equalizer_new_from_preset( unsigned u_index )
565 {
566     libvlc_equalizer_t *p_equalizer;
567
568     if ( u_index >= NB_PRESETS )
569         return NULL;
570
571     p_equalizer = malloc( sizeof( *p_equalizer ) );
572     if ( unlikely( p_equalizer == NULL ) )
573         return NULL;
574
575     p_equalizer->f_preamp = eqz_preset_10b[ u_index ].f_preamp;
576
577     for ( unsigned i = 0; i < EQZ_BANDS_MAX; i++ )
578         p_equalizer->f_amp[ i ] = eqz_preset_10b[ u_index ].f_amp[ i ];
579
580     return p_equalizer;
581 }
582
583 /*****************************************************************************
584  * libvlc_audio_equalizer_release : Release a previously created equalizer
585  *****************************************************************************/
586 void libvlc_audio_equalizer_release( libvlc_equalizer_t *p_equalizer )
587 {
588     free( p_equalizer );
589 }
590
591 /*****************************************************************************
592  * libvlc_audio_equalizer_set_preamp : Set the preamp value for an equalizer
593  *****************************************************************************/
594 int libvlc_audio_equalizer_set_preamp( libvlc_equalizer_t *p_equalizer, float f_preamp )
595 {
596     if( isnan(f_preamp) )
597         return -1;
598     if( f_preamp < -20.f )
599         f_preamp = -20.f;
600     else if( f_preamp > 20.f )
601         f_preamp = 20.f;
602
603     p_equalizer->f_preamp = f_preamp;
604     return 0;
605 }
606
607 /*****************************************************************************
608  * libvlc_audio_equalizer_get_preamp : Get the preamp value for an equalizer
609  *****************************************************************************/
610 float libvlc_audio_equalizer_get_preamp( libvlc_equalizer_t *p_equalizer )
611 {
612     return p_equalizer->f_preamp;
613 }
614
615 /*****************************************************************************
616  * libvlc_audio_equalizer_set_amp_at_index : Set the amplification value for an equalizer band
617  *****************************************************************************/
618 int libvlc_audio_equalizer_set_amp_at_index( libvlc_equalizer_t *p_equalizer, float f_amp, unsigned u_band )
619 {
620     if( u_band >= EQZ_BANDS_MAX || isnan(f_amp) )
621         return -1;
622
623
624     if( f_amp < -20.f )
625         f_amp = -20.f;
626     else if( f_amp > 20.f )
627         f_amp = 20.f;
628
629     p_equalizer->f_amp[ u_band ] = f_amp;
630     return 0;
631 }
632
633 /*****************************************************************************
634  * libvlc_audio_equalizer_get_amp_at_index : Get the amplification value for an equalizer band
635  *****************************************************************************/
636 float libvlc_audio_equalizer_get_amp_at_index( libvlc_equalizer_t *p_equalizer, unsigned u_band )
637 {
638     if ( u_band >= EQZ_BANDS_MAX )
639         return nanf("");
640
641     return p_equalizer->f_amp[ u_band ];
642 }