audio: keep volume level internally (not only in AO)
[mplayer.git] / mixer.c
blob25fb79f76c4761d33e64ac1792b7e95ebc5248f5
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <string.h>
21 #include <libavutil/common.h>
23 #include "config.h"
24 #include "libao2/audio_out.h"
25 #include "libaf/af.h"
26 #include "mp_msg.h"
27 #include "mixer.h"
30 static void checkvolume(struct mixer *mixer)
32 if (!mixer->ao)
33 return;
35 ao_control_vol_t vol;
36 if (mixer->softvol || CONTROL_OK != ao_control(mixer->ao,
37 AOCONTROL_GET_VOLUME, &vol)) {
38 if (!mixer->afilter)
39 return;
40 float db_vals[AF_NCH];
41 if (!af_control_any_rev(mixer->afilter,
42 AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_GET, db_vals))
43 db_vals[0] = db_vals[1] = 1.0;
44 else
45 af_from_dB(2, db_vals, db_vals, 20.0, -200.0, 60.0);
46 vol.left = (db_vals[0] / (mixer->softvol_max / 100.0)) * 100.0;
47 vol.right = (db_vals[1] / (mixer->softvol_max / 100.0)) * 100.0;
49 float l = mixer->vol_l;
50 float r = mixer->vol_r;
51 if (mixer->muted)
52 l = r = 0;
53 /* Try to detect cases where the volume has been changed by some external
54 * action (such as something else changing a shared system-wide volume).
55 * We don't test for exact equality, as some AOs may round the value
56 * we last set to some nearby supported value. 3 has been the default
57 * volume step for increase/decrease keys, and is apparently big enough
58 * to step to the next possible value in most setups.
60 if (FFABS(vol.left - l) >= 3 || FFABS(vol.right - r) >= 3) {
61 mixer->vol_l = vol.left;
62 mixer->vol_r = vol.right;
63 mixer->muted = false;
67 void mixer_getvolume(mixer_t *mixer, float *l, float *r)
69 checkvolume(mixer);
70 *l = mixer->vol_l;
71 *r = mixer->vol_r;
74 static void setvolume_internal(mixer_t *mixer, float l, float r)
76 struct ao_control_vol vol = {.left = l, .right = r};
77 if (mixer->softvol || CONTROL_OK != ao_control(mixer->ao,
78 AOCONTROL_SET_VOLUME, &vol)) {
79 // af_volume uses values in dB
80 float db_vals[AF_NCH];
81 int i;
82 db_vals[0] = (l / 100.0) * (mixer->softvol_max / 100.0);
83 db_vals[1] = (r / 100.0) * (mixer->softvol_max / 100.0);
84 for (i = 2; i < AF_NCH; i++)
85 db_vals[i] = ((l + r) / 100.0) * (mixer->softvol_max / 100.0) / 2.0;
86 af_to_dB(AF_NCH, db_vals, db_vals, 20.0);
87 if (!af_control_any_rev(mixer->afilter,
88 AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals)) {
89 mp_tmsg(MSGT_GLOBAL, MSGL_INFO,
90 "[Mixer] No hardware mixing, inserting volume filter.\n");
91 if (af_add(mixer->afilter, "volume")) {
92 if (!af_control_any_rev(mixer->afilter,
93 AF_CONTROL_VOLUME_LEVEL|AF_CONTROL_SET, db_vals)) {
94 mp_tmsg(MSGT_GLOBAL, MSGL_ERR,
95 "[Mixer] No volume control available.\n");
96 return;
103 void mixer_setvolume(mixer_t *mixer, float l, float r)
105 checkvolume(mixer); // to check mute status
106 mixer->vol_l = av_clip(l, 0, 100);
107 mixer->vol_r = av_clip(r, 0, 100);
108 if (!mixer->ao || mixer->muted)
109 return;
110 setvolume_internal(mixer, mixer->vol_l, mixer->vol_r);
113 void mixer_getbothvolume(mixer_t *mixer, float *b)
115 float mixer_l, mixer_r;
116 mixer_getvolume(mixer, &mixer_l, &mixer_r);
117 *b = (mixer_l + mixer_r) / 2;
120 void mixer_setmute(struct mixer *mixer, bool mute)
122 checkvolume(mixer);
123 if (mute != mixer->muted) {
124 mixer->muted = mute;
125 setvolume_internal(mixer, mixer->vol_l * !mute, mixer->vol_r * !mute);
129 bool mixer_getmute(struct mixer *mixer)
131 checkvolume(mixer);
132 return mixer->muted;
135 static void addvolume(struct mixer *mixer, float d)
137 checkvolume(mixer);
138 mixer_setvolume(mixer, mixer->vol_l + d, mixer->vol_r + d);
139 if (d > 0)
140 mixer_setmute(mixer, false);
143 void mixer_incvolume(mixer_t *mixer)
145 addvolume(mixer, mixer->volstep);
148 void mixer_decvolume(mixer_t *mixer)
150 addvolume(mixer, -mixer->volstep);
153 void mixer_getbalance(mixer_t *mixer, float *val)
155 *val = 0.f;
156 if (!mixer->afilter)
157 return;
158 af_control_any_rev(mixer->afilter, AF_CONTROL_PAN_BALANCE | AF_CONTROL_GET,
159 val);
162 void mixer_setbalance(mixer_t *mixer, float val)
164 float level[AF_NCH];
165 int i;
166 af_control_ext_t arg_ext = { .arg = level };
167 af_instance_t *af_pan_balance;
169 if (!mixer->afilter)
170 return;
172 if (af_control_any_rev(mixer->afilter,
173 AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val))
174 return;
176 if (!(af_pan_balance = af_add(mixer->afilter, "pan"))) {
177 mp_tmsg(MSGT_GLOBAL, MSGL_ERR,
178 "[Mixer] No balance control available.\n");
179 return;
182 af_init(mixer->afilter);
183 /* make all other channels pass thru since by default pan blocks all */
184 memset(level, 0, sizeof(level));
185 for (i = 2; i < AF_NCH; i++) {
186 arg_ext.ch = i;
187 level[i] = 1.f;
188 af_pan_balance->control(af_pan_balance,
189 AF_CONTROL_PAN_LEVEL | AF_CONTROL_SET,
190 &arg_ext);
191 level[i] = 0.f;
194 af_pan_balance->control(af_pan_balance,
195 AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val);