]> git.sesse.net Git - vlc/blob - src/audio_output/intf.c
aout: separate volume and mute callbacks
[vlc] / src / audio_output / intf.c
1 /*****************************************************************************
2  * intf.c : audio output API towards the interface modules
3  *****************************************************************************
4  * Copyright (C) 2002-2007 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
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.
13  *
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.
18  *
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 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_aout_intf.h>
34
35 #include <stdio.h>
36 #include <stdlib.h>                            /* calloc(), malloc(), free() */
37 #include <string.h>
38 #include <math.h>
39
40 #include <vlc_aout.h>
41 #include "aout_internal.h"
42
43 #include <vlc_playlist.h>
44
45 static audio_output_t *findAout (vlc_object_t *obj)
46 {
47     input_thread_t *(*pf_find_input) (vlc_object_t *);
48
49     pf_find_input = var_GetAddress (obj, "find-input-callback");
50     if (unlikely(pf_find_input == NULL))
51         return NULL;
52
53     input_thread_t *p_input = pf_find_input (obj);
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     return p_aout;
60 }
61 #define findAout(o) findAout(VLC_OBJECT(o))
62
63 /** Start a volume change transaction. */
64 static void prepareVolume (vlc_object_t *obj, audio_output_t **aoutp,
65                            float *vol, bool *mute)
66 {
67     audio_output_t *aout = findAout (obj);
68
69     /* FIXME: we need interlocking even if aout does not exist! */
70     *aoutp = aout;
71     if (aout != NULL)
72     {
73         obj = VLC_OBJECT(aout); /* use aout volume if aout exists */
74         aout_lock_volume (aout);
75     }
76     if (vol != NULL)
77         *vol = var_InheritInteger (obj, "volume") / (float)AOUT_VOLUME_DEFAULT;
78     if (mute != NULL)
79         *mute = var_InheritBool (obj, "mute");
80 }
81
82 /** Commit a volume change transaction. */
83 static int commitVolume (vlc_object_t *obj, audio_output_t *aout,
84                          float vol, bool mute)
85 {
86     long volume = lroundf (vol * AOUT_VOLUME_DEFAULT);
87     int ret = 0;
88
89     if (aout != NULL)
90     {
91         /* apply volume to the pipeline */
92         aout_lock (aout);
93         if (aout->mute_set != NULL)
94             ret = aout->mute_set (aout, mute);
95         else
96             ret = -1;
97         if (ret == 0 && aout->volume_set != NULL)
98             ret = aout->volume_set (aout, vol);
99         aout_unlock (aout);
100
101         if (ret == 0)
102         {   /* update aout volume if it maintains its own */
103             var_SetInteger (aout, "volume", volume);
104             var_SetBool (aout, "mute", mute);
105         }
106         aout_unlock_volume (aout);
107
108         vlc_object_release (aout);
109     }
110     if (ret == 0)
111     {   /* update caller (input manager) volume */
112         var_SetInteger (obj, "volume", volume);
113         var_SetBool (obj, "mute", mute);
114         if (var_InheritBool (obj, "volume-save"))
115             config_PutInt (obj, "volume", volume);
116     }
117     return ret;
118 }
119
120 /** Cancel a volume change transaction. */
121 static void cancelVolume (vlc_object_t *obj, audio_output_t *aout)
122 {
123     (void) obj;
124     if (aout != NULL)
125     {
126         aout_unlock_volume (aout);
127         vlc_object_release (aout);
128     }
129 }
130
131 #undef aout_VolumeGet
132 /**
133  * Gets the volume of the output device (independent of mute).
134  * \return Current audio volume (0 = silent, 1 = nominal),
135  * or a strictly negative value if undefined.
136  */
137 float aout_VolumeGet (vlc_object_t *obj)
138 {
139     audio_output_t *aout;
140     float vol;
141
142     prepareVolume (obj, &aout, &vol, NULL);
143     cancelVolume (obj, aout);
144     return vol;
145 }
146
147 #undef aout_VolumeSet
148 /**
149  * Sets the volume of the output device.
150  * The mute status is not changed.
151  */
152 int aout_VolumeSet (vlc_object_t *obj, float vol)
153 {
154     audio_output_t *aout;
155     bool mute;
156
157     prepareVolume (obj, &aout, NULL, &mute);
158     return commitVolume (obj, aout, vol, mute);
159 }
160
161 #undef aout_VolumeUp
162 /**
163  * Raises the volume.
164  * \param value how much to increase (> 0) or decrease (< 0) the volume
165  * \param volp if non-NULL, will contain contain the resulting volume
166  */
167 int aout_VolumeUp (vlc_object_t *obj, int value, float *volp)
168 {
169     audio_output_t *aout;
170     int ret;
171     float vol;
172     bool mute;
173
174     value *= var_InheritInteger (obj, "volume-step");
175
176     prepareVolume (obj, &aout, &vol, &mute);
177     vol += value / (float)AOUT_VOLUME_DEFAULT;
178     if (vol < 0.)
179         vol = 0.;
180     if (vol > (AOUT_VOLUME_MAX / AOUT_VOLUME_DEFAULT))
181         vol = AOUT_VOLUME_MAX / AOUT_VOLUME_DEFAULT;
182     ret = commitVolume (obj, aout, vol, mute);
183     if (volp != NULL)
184         *volp = vol;
185     return ret;
186 }
187
188 #undef aout_MuteToggle
189 /**
190  * Toggles the mute state.
191  */
192 int aout_MuteToggle (vlc_object_t *obj)
193 {
194     audio_output_t *aout;
195     float vol;
196     bool mute;
197
198     prepareVolume (obj, &aout, &vol, &mute);
199     mute = !mute;
200     return commitVolume (obj, aout, vol, mute);
201 }
202
203 #undef aout_MuteGet
204 /**
205  * Gets the output mute status.
206  * \return 0 if not muted, 1 if muted, -1 if undefined.
207  */
208 int aout_MuteGet (vlc_object_t *obj)
209 {
210     audio_output_t *aout;
211     bool mute;
212
213     prepareVolume (obj, &aout, NULL, &mute);
214     cancelVolume (obj, aout);
215     return mute;
216 }
217
218 #undef aout_MuteSet
219 /**
220  * Sets mute status.
221  */
222 int aout_MuteSet (vlc_object_t *obj, bool mute)
223 {
224     audio_output_t *aout;
225     float vol;
226
227     prepareVolume (obj, &aout, &vol, NULL);
228     return commitVolume (obj, aout, vol, mute);
229 }
230
231
232 /*
233  * Pipelines management
234  */
235
236 /*****************************************************************************
237  * aout_ChannelsRestart : change the audio device or channels and restart
238  *****************************************************************************/
239 int aout_ChannelsRestart( vlc_object_t * p_this, const char * psz_variable,
240                           vlc_value_t oldval, vlc_value_t newval,
241                           void *p_data )
242 {
243     audio_output_t * p_aout = (audio_output_t *)p_this;
244     (void)oldval; (void)newval; (void)p_data;
245
246     if ( !strcmp( psz_variable, "audio-device" ) )
247     {
248         /* This is supposed to be a significant change and supposes
249          * rebuilding the channel choices. */
250         var_Destroy( p_aout, "audio-channels" );
251     }
252     aout_RequestRestart (p_aout);
253     return 0;
254 }
255
256 #undef aout_EnableFilter
257 /** Enable or disable an audio filter
258  * \param p_this a vlc object
259  * \param psz_name name of the filter
260  * \param b_add are we adding or removing the filter ?
261  */
262 void aout_EnableFilter( vlc_object_t *p_this, const char *psz_name,
263                         bool b_add )
264 {
265     audio_output_t *p_aout = findAout( p_this );
266
267     if( aout_ChangeFilterString( p_this, VLC_OBJECT(p_aout), "audio-filter", psz_name, b_add ) )
268     {
269         if( p_aout )
270             aout_InputRequestRestart( p_aout );
271     }
272
273     if( p_aout )
274         vlc_object_release( p_aout );
275 }