1 /* vdagent-audio.c vdagentd audio handling code
3 Copyright 2015 Red Hat, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <alsa/asoundlib.h>
27 #include <alsa/mixer.h>
28 #include <alsa/error.h>
29 #include "vdagent-audio.h"
34 static snd_mixer_elem_t
*
35 get_alsa_default_mixer_by_name(snd_mixer_t
**handle
, const char *name
)
37 snd_mixer_selem_id_t
*sid
;
40 if ((err
= snd_mixer_open(handle
, 0)) < 0)
43 if ((err
= snd_mixer_attach(*handle
, "default")) < 0)
46 if ((err
= snd_mixer_selem_register(*handle
, NULL
, NULL
)) < 0)
49 if ((err
= snd_mixer_load(*handle
)) < 0)
52 snd_mixer_selem_id_alloca(&sid
);
53 snd_mixer_selem_id_set_index(sid
, 0);
54 snd_mixer_selem_id_set_name(sid
, name
);
55 return snd_mixer_find_selem(*handle
, sid
);
58 syslog(LOG_WARNING
, "%s fail: %s", __func__
, snd_strerror(err
));
62 static bool set_alsa_capture(uint8_t mute
, uint8_t nchannels
, uint16_t *volume
)
64 snd_mixer_t
*handle
= NULL
;
70 e
= get_alsa_default_mixer_by_name (&handle
, "Capture");
72 syslog(LOG_WARNING
, "vdagent-audio: can't get default alsa mixer");
77 alsa_mute
= (mute
) ? ALSA_MUTE
: ALSA_UNMUTE
;
78 snd_mixer_selem_set_capture_switch_all(e
, alsa_mute
);
80 snd_mixer_selem_get_capture_volume_range(e
, &min
, &max
);
83 vol
= CLAMP(volume
[0], min
, max
);
84 snd_mixer_selem_set_capture_volume(e
, SND_MIXER_SCHN_MONO
, vol
);
85 syslog(LOG_DEBUG
, "vdagent-audio: (capture-mono) %lu (%%%0.2f)",
86 vol
, (float) (100*vol
/max
));
88 case 2: /* LEFT-RIGHT */
89 vol
= CLAMP(volume
[0], min
, max
);
90 snd_mixer_selem_set_capture_volume(e
, SND_MIXER_SCHN_FRONT_LEFT
, vol
);
91 syslog(LOG_DEBUG
, "vdagent-audio: (capture-left) %lu (%%%0.2f)",
92 vol
, (float) (100*vol
/max
));
93 vol
= CLAMP(volume
[1], min
, max
);
94 snd_mixer_selem_set_capture_volume(e
, SND_MIXER_SCHN_FRONT_RIGHT
, vol
);
95 syslog(LOG_DEBUG
, "vdagent-audio: (capture-right) %lu (%%%0.2f)",
96 vol
, (float) (100*vol
/max
));
99 syslog(LOG_WARNING
, "vdagent-audio: number of channels not supported");
104 snd_mixer_close(handle
);
108 static bool set_alsa_playback (uint8_t mute
, uint8_t nchannels
, uint16_t *volume
)
110 snd_mixer_t
*handle
= NULL
;
116 e
= get_alsa_default_mixer_by_name (&handle
, "Master");
118 syslog(LOG_WARNING
, "vdagent-audio: can't get default alsa mixer");
123 alsa_mute
= (mute
) ? ALSA_MUTE
: ALSA_UNMUTE
;
124 snd_mixer_selem_set_playback_switch_all(e
, alsa_mute
);
126 snd_mixer_selem_get_playback_volume_range(e
, &min
, &max
);
129 vol
= CLAMP(volume
[0], min
, max
);
130 snd_mixer_selem_set_playback_volume(e
, SND_MIXER_SCHN_MONO
, vol
);
131 syslog(LOG_DEBUG
, "vdagent-audio: (playback-mono) %lu (%%%0.2f)",
132 vol
, (float) (100*vol
/max
));
134 case 2: /* LEFT-RIGHT */
135 vol
= CLAMP(volume
[0], min
, max
);
136 snd_mixer_selem_set_playback_volume(e
, SND_MIXER_SCHN_FRONT_LEFT
, vol
);
137 syslog(LOG_DEBUG
, "vdagent-audio: (playback-left) %lu (%%%0.2f)",
138 vol
, (float) (100*vol
/max
));
139 vol
= CLAMP(volume
[1], min
, max
);
140 snd_mixer_selem_set_playback_volume(e
, SND_MIXER_SCHN_FRONT_RIGHT
, vol
);
141 syslog(LOG_DEBUG
, "vdagent-audio: (playback-right) %lu (%%%0.2f)",
142 vol
, (float) (100*vol
/max
));
145 syslog(LOG_WARNING
, "vdagent-audio: number of channels not supported");
150 snd_mixer_close(handle
);
154 void vdagent_audio_playback_sync(uint8_t mute
, uint8_t nchannels
, uint16_t *volume
)
156 syslog(LOG_DEBUG
, "%s mute=%s nchannels=%u",
157 __func__
, (mute
) ? "yes" : "no", nchannels
);
158 if (set_alsa_playback (mute
, nchannels
, volume
) == false)
159 syslog(LOG_WARNING
, "Fail to sync playback volume");
162 void vdagent_audio_record_sync(uint8_t mute
, uint8_t nchannels
, uint16_t *volume
)
164 syslog(LOG_DEBUG
, "%s mute=%s nchannels=%u",
165 __func__
, (mute
) ? "yes" : "no", nchannels
);
166 if (set_alsa_capture (mute
, nchannels
, volume
) == false)
167 syslog(LOG_WARNING
, "Fail to sync record volume");