build-sys: move user/system to respective dir
[vd_agent.git] / src / vdagent / vdagent-audio.c
blob6b11cd88bb668e4b925b9121bd6171c68694109e
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/>.
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <glib.h>
24 #include <syslog.h>
25 #include <stdbool.h>
26 #include <alsa/asoundlib.h>
27 #include <alsa/mixer.h>
28 #include <alsa/error.h>
29 #include "vdagent-audio.h"
31 #define ALSA_MUTE 0
32 #define ALSA_UNMUTE 1
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;
38 int err = 0;
40 if ((err = snd_mixer_open(handle, 0)) < 0)
41 goto fail;
43 if ((err = snd_mixer_attach(*handle, "default")) < 0)
44 goto fail;
46 if ((err = snd_mixer_selem_register(*handle, NULL, NULL)) < 0)
47 goto fail;
49 if ((err = snd_mixer_load(*handle)) < 0)
50 goto fail;
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);
57 fail:
58 syslog(LOG_WARNING, "%s fail: %s", __func__, snd_strerror(err));
59 return NULL;
62 static bool set_alsa_capture(uint8_t mute, uint8_t nchannels, uint16_t *volume)
64 snd_mixer_t *handle = NULL;
65 snd_mixer_elem_t *e;
66 long min, max, vol;
67 bool ret = true;
68 int alsa_mute;
70 e = get_alsa_default_mixer_by_name (&handle, "Capture");
71 if (e == NULL) {
72 syslog(LOG_WARNING, "vdagent-audio: can't get default alsa mixer");
73 ret = false;
74 goto end;
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);
81 switch (nchannels) {
82 case 1: /* MONO */
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));
87 break;
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));
97 break;
98 default:
99 syslog(LOG_WARNING, "vdagent-audio: number of channels not supported");
100 ret = false;
102 end:
103 if (handle != NULL)
104 snd_mixer_close(handle);
105 return ret;
108 static bool set_alsa_playback (uint8_t mute, uint8_t nchannels, uint16_t *volume)
110 snd_mixer_t *handle = NULL;
111 snd_mixer_elem_t* e;
112 long min, max, vol;
113 bool ret = true;
114 int alsa_mute;
116 e = get_alsa_default_mixer_by_name (&handle, "Master");
117 if (e == NULL) {
118 syslog(LOG_WARNING, "vdagent-audio: can't get default alsa mixer");
119 ret = false;
120 goto end;
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);
127 switch (nchannels) {
128 case 1: /* MONO */
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));
133 break;
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));
143 break;
144 default:
145 syslog(LOG_WARNING, "vdagent-audio: number of channels not supported");
146 ret = false;
148 end:
149 if (handle != NULL)
150 snd_mixer_close(handle);
151 return ret;
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");