summaryrefslogtreecommitdiff
path: root/src/mixer.cc
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2014-09-25 17:08:44 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2014-09-25 17:08:44 +0200
commit4f6b15ea26b5fa09f300f67e4ce1057c2b39a3aa (patch)
tree45d7bb4a9a90ef603b5a7a65a4d4d4309a7a1538 /src/mixer.cc
parent0602763044f0f0f9163f2a888627213347d3dbb7 (diff)
New API, new name, new version.
Diffstat (limited to 'src/mixer.cc')
-rw-r--r--src/mixer.cc321
1 files changed, 321 insertions, 0 deletions
diff --git a/src/mixer.cc b/src/mixer.cc
new file mode 100644
index 0000000..5a6efb7
--- /dev/null
+++ b/src/mixer.cc
@@ -0,0 +1,321 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * mixer.cc
+ *
+ * Tue Sep 23 14:38:54 CEST 2014
+ * Copyright 2014 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of LibAudioIO.
+ *
+ * LibAudioIO is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * LibAudioIO is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with LibAudioIO; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "mixer.h"
+
+#include <string>
+#include <stdlib.h>
+
+#define fERROR (strtof("-INF", NULL))
+
+Mixer::Mixer(snd_mixer_t *handle, snd_mixer_elem_t *elem)
+{
+ this->handle = handle;
+ this->elem = elem;
+
+ /*
+ if (snd_mixer_selem_has_capture_volume(elem) ||
+ snd_mixer_selem_has_capture_switch(elem)) {
+ printf("Capture channels:\n");
+ if(snd_mixer_selem_is_capture_mono(elem)) {
+ printf(" Mono");
+ } else {
+ for(int ichn = 0; ichn <= (int)SND_MIXER_SCHN_LAST; ichn++) {
+ snd_mixer_selem_channel_id_t chn = (snd_mixer_selem_channel_id_t)ichn;
+ if(!snd_mixer_selem_has_capture_channel(elem, chn)) continue;
+ printf(" - %s\n", snd_mixer_selem_channel_name(chn));
+ }
+ }
+ }
+ */
+
+
+
+
+
+
+
+ /*
+ snd_mixer_selem_id_t *mixer;
+
+ // Open mixer device
+ if(snd_mixer_open(&mixhnd, 0) != 0)
+ throw MixerInitilisationFailed();
+
+ if(snd_mixer_attach_hctl(mixhnd, hctl) != 0)
+ throw MixerInitilisationFailed();
+
+ if(snd_mixer_selem_register(mixhnd, NULL, NULL) < 0)
+ throw MixerInitilisationFailed();
+
+ if(snd_mixer_load(mixhnd) < 0)
+ throw MixerInitilisationFailed();
+
+ // Obtain mixer element
+ snd_mixer_selem_id_alloca(&mixer);
+ if(mixer == NULL) throw MixerInitilisationFailed();
+ snd_mixer_selem_id_set_name(mixer, mixer_interface);
+
+ elem = snd_mixer_find_selem(mixhnd, mixer);
+ if(elem == NULL) throw MixerInitilisationFailed();
+ */
+
+ /*
+ // Obtain mixer enumeration element "Input Source" and set it to 2 (line).
+ snd_mixer_selem_id_set_name(mixer, "Input Source");
+
+ snd_mixer_elem_t *iselem = snd_mixer_find_selem(mixhnd, mixer);
+ if(iselem == NULL) return;
+
+ if(snd_mixer_selem_is_enumerated(iselem)) {
+ // Set to line-in
+ for(int i = 0; i < 3; i++) {
+ char name[16];
+ snd_mixer_selem_get_enum_item_name(iselem, i, sizeof(name), name);
+ if(std::string(name) == "Line") {
+ snd_mixer_selem_set_enum_item(iselem, SND_MIXER_SCHN_MONO, i);
+ }
+ }
+ }
+ */
+}
+
+Mixer::~Mixer()
+{
+ if(handle) snd_mixer_close(handle);
+}
+
+snd_mixer_selem_channel_id_t Mixer::chanId(int idx)
+{
+ int num = 0;
+ if(snd_mixer_selem_is_capture_mono(elem)) {
+ if(idx == 0) return SND_MIXER_SCHN_MONO;
+ } else {
+ for(int ichn = 0; ichn <= (int)SND_MIXER_SCHN_LAST; ichn++) {
+ snd_mixer_selem_channel_id_t chn = (snd_mixer_selem_channel_id_t)ichn;
+ if(!snd_mixer_selem_has_capture_channel(elem, chn) &&
+ !snd_mixer_selem_has_playback_channel(elem, chn)) continue;
+ if(idx == num) return chn;
+ num++;
+ }
+ }
+ return SND_MIXER_SCHN_UNKNOWN;
+}
+
+int Mixer::numberOfChannels()
+{
+ int num = 0;
+ if(snd_mixer_selem_is_capture_mono(elem)) {
+ num = 1;
+ } else {
+ for(int ichn = 0; ichn <= (int)SND_MIXER_SCHN_LAST; ichn++) {
+ snd_mixer_selem_channel_id_t chn = (snd_mixer_selem_channel_id_t)ichn;
+ if(!snd_mixer_selem_has_capture_channel(elem, chn)) continue;
+ num++;
+ }
+ }
+
+ return num;
+}
+
+bool Mixer::isCapture()
+{
+ return snd_mixer_selem_has_capture_volume(elem) ||
+ snd_mixer_selem_has_capture_switch(elem);
+}
+
+bool Mixer::isPlayback()
+{
+ return snd_mixer_selem_has_playback_volume(elem);
+}
+
+bool Mixer::isEnum()
+{
+ return snd_mixer_selem_is_enumerated(elem);
+}
+
+void Mixer::setEnumValue(std::string value)
+{
+ if(!isEnum()) return;
+}
+
+std::string Mixer::enumValue()
+{
+ if(!isEnum()) return "";
+
+ int i;
+ unsigned int idx;
+ char itemname[40];
+ for(i = 0; !snd_mixer_selem_get_enum_item(elem,
+ (snd_mixer_selem_channel_id_t)i,
+ &idx); i++) {
+ snd_mixer_selem_get_enum_item_name(elem, idx,
+ sizeof(itemname) - 1, itemname);
+ return itemname;
+ }
+
+ return "";
+}
+
+std::vector<std::string> Mixer::enumValues()
+{
+ std::vector<std::string> values;
+ if(!isEnum()) return values;
+
+ int i, items;
+ char itemname[40];
+ items = snd_mixer_selem_get_enum_items(elem);
+ for (i = 0; i < items; i++) {
+ snd_mixer_selem_get_enum_item_name(elem, (snd_mixer_selem_channel_id_t)i,
+ sizeof(itemname) - 1, itemname);
+ values.push_back(itemname);
+ }
+
+ return values;
+}
+
+int Mixer::setLevel(int channel, float level)
+{
+ int err;
+ long int value = level * 100;
+ // dir: -1 := exact or first below
+ // 0 := exact (error if not?)
+ // 1 := exact or first above
+ int dir = 1;
+
+ if(isCapture()) {
+ err = snd_mixer_selem_set_capture_dB(elem, chanId(channel), value, dir);
+ if(err) {
+ printf("snd_mixer_selem_set_capture_dB: %s, %d\n",
+ snd_strerror(err), err);
+ return 1;
+ }
+ }
+
+ if(isPlayback()) {
+ err = snd_mixer_selem_set_playback_dB(elem, chanId(channel), value, dir);
+ if(err) {
+ printf("snd_mixer_selem_set_playback_dB: %s, %d\n",
+ snd_strerror(err), err);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+float Mixer::level(int channel)
+{
+ int err;
+ long int value;
+
+ if(isCapture()) {
+ err = snd_mixer_selem_get_capture_dB(elem, chanId(channel), &value);
+ if(err) {
+ printf("snd_mixer_selem_get_capture_dB: %s, %d\n",
+ snd_strerror(err), err);
+ return fERROR;
+ }
+ } else if(isPlayback()) {
+ err = snd_mixer_selem_get_playback_dB(elem, chanId(channel), &value);
+ if(err) {
+ printf("snd_mixer_selem_get_playback_dB: %s, %d\n",
+ snd_strerror(err), err);
+ return fERROR;
+ }
+ } else {
+ return fERROR;
+ }
+
+ return (float)value / 100.0;
+}
+
+Mixer::range_t Mixer::range()
+{
+ Mixer::range_t range;
+
+ int err;
+ long int lvl_min, lvl_max;
+
+ if(isCapture()) {
+ err = snd_mixer_selem_get_capture_dB_range(elem, &lvl_min, &lvl_max);
+
+ if(err) {
+ printf("snd_mixer_selem_get_capture_dB_range: %s, %d\n",
+ snd_strerror(err), err);
+ }
+ } else if(isPlayback()) {
+ err = snd_mixer_selem_get_playback_dB_range(elem, &lvl_min, &lvl_max);
+
+ if(err) {
+ printf("snd_mixer_selem_get_playback_dB_range: %s, %d\n",
+ snd_strerror(err), err);
+ }
+ } else {
+ range.min = fERROR;
+ range.max = fERROR;
+ return range;
+ }
+
+ range.min = (float)lvl_min / 100.0;
+ range.max = (float)lvl_max / 100.0;
+
+ return range;
+}
+
+void Mixer::setCapture(bool capture)
+{
+ if(!isCapture()) return;
+ int c = capture?1:0;
+ int err;
+ err = snd_mixer_selem_set_capture_switch_all(elem, c);
+ if(err) {
+ printf("snd_mixer_selem_set_capture_switch_all: %s, %d\n",
+ snd_strerror(err), err);
+ }
+}
+
+bool Mixer::capture()
+{
+ if(!isCapture()) return false;
+
+ int err;
+
+ int num = numberOfChannels();
+ for(int idx = 0; idx < num; idx++) {
+ int value;
+ err = snd_mixer_selem_get_capture_switch(elem, chanId(idx), &value);
+ if(err) {
+ printf(" snd_mixer_selem_get_capture_switch: %s, %d\n",
+ snd_strerror(err), err);
+ return false;
+ }
+ if(value == 0) return false;
+ }
+
+ return true;
+}