configure: update FFmpeg revision (bc63a76).
[vaapi:mplayer.git] / mixer.c
1 /*
2  * This file is part of MPlayer.
3  *
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.
8  *
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.
13  *
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.
17  */
18
19 #include <string.h>
20 #ifndef __MINGW32__
21 #include <sys/ioctl.h>
22 #endif
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <unistd.h>
26
27 #include "config.h"
28 #include "libao2/audio_out.h"
29 #include "libaf/af.h"
30 #include "mixer.h"
31 #include "mp_msg.h"
32 #include "help_mp.h"
33
34 char * mixer_device=NULL;
35 char * mixer_channel=NULL;
36 int soft_vol = 0;
37 float soft_vol_max = 110.0;
38
39 void mixer_getvolume(mixer_t *mixer, float *l, float *r)
40 {
41   ao_control_vol_t vol;
42   *l=0; *r=0;
43   if(mixer->audio_out){
44     if(soft_vol ||
45         CONTROL_OK != mixer->audio_out->control(AOCONTROL_GET_VOLUME,&vol)) {
46       if (!mixer->afilter)
47         return;
48       else {
49         float db_vals[AF_NCH];
50         if (!af_control_any_rev(mixer->afilter,
51                AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_GET, db_vals))
52           db_vals[0] = db_vals[1] = 1.0;
53         else
54         af_from_dB (2, db_vals, db_vals, 20.0, -200.0, 60.0);
55         vol.left = (db_vals[0] / (soft_vol_max / 100.0)) * 100.0;
56         vol.right = (db_vals[1] / (soft_vol_max / 100.0)) * 100.0;
57       }
58     }
59     *r=vol.right;
60     *l=vol.left;
61   }
62 }
63
64 void mixer_setvolume(mixer_t *mixer, float l, float r)
65 {
66   ao_control_vol_t vol;
67   vol.right=r; vol.left=l;
68   if(mixer->audio_out){
69     if(soft_vol ||
70         CONTROL_OK != mixer->audio_out->control(AOCONTROL_SET_VOLUME,&vol)) {
71       if (!mixer->afilter)
72         return;
73       else {
74         // af_volume uses values in dB
75         float db_vals[AF_NCH];
76         int i;
77         db_vals[0] = (l / 100.0) * (soft_vol_max / 100.0);
78         db_vals[1] = (r / 100.0) * (soft_vol_max / 100.0);
79         for (i = 2; i < AF_NCH; i++) {
80           db_vals[i] = ((l + r) / 100.0) * (soft_vol_max / 100.0) / 2.0;
81         }
82         af_to_dB (AF_NCH, db_vals, db_vals, 20.0);
83         if (!af_control_any_rev(mixer->afilter,
84                AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals)) {
85           mp_msg(MSGT_GLOBAL, MSGL_INFO, MSGTR_InsertingAfVolume);
86           if (af_add(mixer->afilter, "volume")) {
87             if (!af_control_any_rev(mixer->afilter,
88                    AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals)) {
89               mp_msg(MSGT_GLOBAL, MSGL_ERR, MSGTR_NoVolume);
90               return;
91             }
92             soft_vol = 1;
93           }
94         }
95       }
96     }
97   }
98  mixer->muted=0;
99 }
100
101 void mixer_incvolume(mixer_t *mixer)
102 {
103  float mixer_l, mixer_r;
104  mixer_getvolume(mixer, &mixer_l, &mixer_r);
105  mixer_l += mixer->volstep;
106  if ( mixer_l > 100 ) mixer_l = 100;
107  mixer_r += mixer->volstep;
108  if ( mixer_r > 100 ) mixer_r = 100;
109  mixer_setvolume(mixer, mixer_l, mixer_r);
110 }
111
112 void mixer_decvolume(mixer_t *mixer)
113 {
114  float mixer_l, mixer_r;
115  mixer_getvolume(mixer, &mixer_l, &mixer_r);
116  mixer_l -= mixer->volstep;
117  if ( mixer_l < 0 ) mixer_l = 0;
118  mixer_r -= mixer->volstep;
119  if ( mixer_r < 0 ) mixer_r = 0;
120  mixer_setvolume(mixer, mixer_l, mixer_r);
121 }
122
123 void mixer_getbothvolume(mixer_t *mixer, float *b)
124 {
125  float mixer_l, mixer_r;
126  mixer_getvolume(mixer, &mixer_l, &mixer_r);
127  *b = ( mixer_l + mixer_r ) / 2;
128 }
129
130 void mixer_mute(mixer_t *mixer)
131 {
132  if (mixer->muted) mixer_setvolume(mixer, mixer->last_l, mixer->last_r);
133   else
134    {
135     mixer_getvolume(mixer, &mixer->last_l, &mixer->last_r);
136     mixer_setvolume(mixer, 0, 0);
137     mixer->muted=1;
138    }
139 }
140
141 void mixer_getbalance(mixer_t *mixer, float *val)
142 {
143   *val = 0.f;
144   if(!mixer->afilter)
145     return;
146   af_control_any_rev(mixer->afilter,
147       AF_CONTROL_PAN_BALANCE | AF_CONTROL_GET, val);
148 }
149
150 void mixer_setbalance(mixer_t *mixer, float val)
151 {
152   float level[AF_NCH];
153   int i;
154   af_control_ext_t arg_ext = { .arg = level };
155   af_instance_t* af_pan_balance;
156
157   if(!mixer->afilter)
158     return;
159   if (af_control_any_rev(mixer->afilter,
160         AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val))
161     return;
162
163   if (!(af_pan_balance = af_add(mixer->afilter, "pan"))) {
164     mp_msg(MSGT_GLOBAL, MSGL_ERR, MSGTR_NoBalance);
165     return;
166   }
167
168   af_init(mixer->afilter);
169   /* make all other channels pass thru since by default pan blocks all */
170   memset(level, 0, sizeof(level));
171   for (i = 2; i < AF_NCH; i++) {
172     arg_ext.ch = i;
173     level[i] = 1.f;
174     af_pan_balance->control(af_pan_balance,
175         AF_CONTROL_PAN_LEVEL | AF_CONTROL_SET, &arg_ext);
176     level[i] = 0.f;
177   }
178
179   af_pan_balance->control(af_pan_balance,
180       AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val);
181 }