[alsa-devel] [PATCH 04/13] bebob: Add functionality to change sampling rate and control interface

Takashi Sakamoto o-takashi at sakamocchi.jp
Sat Nov 23 07:09:16 CET 2013


This commit adds the functionality to change sampling rate. To debug this,
this commit also adds control interface. I plan to extend this control
interface for the other functionality.

Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
 sound/firewire/bebob/Makefile        |   2 +-
 sound/firewire/bebob/bebob.c         |   4 +
 sound/firewire/bebob/bebob.h         |   4 +
 sound/firewire/bebob/bebob_control.c | 148 +++++++++++++++++++++++++++++++++++
 sound/firewire/bebob/bebob_stream.c  |   2 +
 5 files changed, 159 insertions(+), 1 deletion(-)
 create mode 100644 sound/firewire/bebob/bebob_control.c

diff --git a/sound/firewire/bebob/Makefile b/sound/firewire/bebob/Makefile
index 6e44fa0..bec01cd 100644
--- a/sound/firewire/bebob/Makefile
+++ b/sound/firewire/bebob/Makefile
@@ -1,3 +1,3 @@
-snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o \
+snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob_control.o \
 		  bebob.o
 obj-m += snd-bebob.o
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c
index e5aa96e..71a3896 100644
--- a/sound/firewire/bebob/bebob.c
+++ b/sound/firewire/bebob/bebob.c
@@ -177,6 +177,10 @@ snd_bebob_probe(struct fw_unit *unit,
 	if (err < 0)
 		goto error;
 
+	err = snd_bebob_create_control_devices(bebob);
+	if (err < 0)
+		goto error;
+
 	snd_bebob_proc_init(bebob);
 
 	err = snd_bebob_stream_discover(bebob);
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h
index 2d60165..d87999e 100644
--- a/sound/firewire/bebob/bebob.h
+++ b/sound/firewire/bebob/bebob.h
@@ -30,6 +30,7 @@
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/info.h>
+#include <sound/control.h>
 
 #include "../packets-buffer.h"
 #include "../iso-resources.h"
@@ -74,6 +75,7 @@ struct snd_bebob {
 	struct snd_bebob_stream_formation
 		rx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES];
 
+	struct snd_ctl_elem_id *ctl_id_freq;
 };
 
 static inline int
@@ -149,6 +151,8 @@ void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob);
 
 void snd_bebob_proc_init(struct snd_bebob *bebob);
 
+int snd_bebob_create_control_devices(struct snd_bebob *bebob);
+
 #define SND_BEBOB_DEV_ENTRY(vendor, model) \
 { \
 	.match_flags	= IEEE1394_MATCH_VENDOR_ID | \
diff --git a/sound/firewire/bebob/bebob_control.c b/sound/firewire/bebob/bebob_control.c
new file mode 100644
index 0000000..f9a9229
--- /dev/null
+++ b/sound/firewire/bebob/bebob_control.c
@@ -0,0 +1,148 @@
+/*
+ * bebob_control.c - a part of driver for BeBoB based devices
+ *
+ * Copyright (c) 2013 Takashi Sakamoto
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2.
+ *
+ * This driver 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "bebob.h"
+
+
+/*
+ * Global Control: Sampling Rate Control
+ *
+ * refer to snd_bebob_rate_table.
+ */
+static int
+control_sampling_rate_info(struct snd_kcontrol *kctl,
+			   struct snd_ctl_elem_info *einf)
+{
+	struct snd_bebob *bebob = snd_kcontrol_chip(kctl);
+	unsigned int i, value;
+
+	/* maximum value for user */
+	einf->value.enumerated.items = 0;
+	for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++)
+		if ((bebob->tx_stream_formations[i].pcm > 0) &&
+		    (bebob->rx_stream_formations[i].pcm > 0))
+			einf->value.enumerated.items++;
+
+	einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	einf->count = 1;
+
+	if (einf->value.enumerated.item >= einf->value.enumerated.items)
+		einf->value.enumerated.item = einf->value.enumerated.items - 1;
+
+	/* skip unsupported sampling rates */
+	value = einf->value.enumerated.item;
+	for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++) {
+		if ((bebob->tx_stream_formations[i].pcm == 0) ||
+		    (bebob->rx_stream_formations[i].pcm == 0))
+			continue;
+		else if (value == 0)
+			break;
+		else
+			value--;
+	}
+
+	sprintf(einf->value.enumerated.name, "%dHz", snd_bebob_rate_table[i]);
+
+	return 0;
+}
+static int
+control_sampling_rate_get(struct snd_kcontrol *kctl,
+			  struct snd_ctl_elem_value *uval)
+{
+	struct snd_bebob *bebob = snd_kcontrol_chip(kctl);
+	unsigned int i, sampling_rate, index;
+	int err;
+
+	mutex_lock(&bebob->mutex);
+
+	err = snd_bebob_stream_get_rate(bebob, &sampling_rate);
+	if (err < 0)
+		goto end;
+
+	for (index = 0; index < ARRAY_SIZE(snd_bebob_rate_table); index++)
+		if (snd_bebob_rate_table[index] == sampling_rate)
+			break;
+
+	uval->value.enumerated.item[0] = 0;
+	for (i = 0; i < index; i++)
+		if ((bebob->tx_stream_formations[i].pcm != 0) ||
+		    (bebob->rx_stream_formations[i].pcm != 0))
+			uval->value.enumerated.item[0]++;
+
+end:
+	mutex_unlock(&bebob->mutex);
+	return err;
+}
+static int
+control_sampling_rate_put(struct snd_kcontrol *kctl,
+			  struct snd_ctl_elem_value *uval)
+{
+	struct snd_bebob *bebob = snd_kcontrol_chip(kctl);
+	unsigned int index, sampling_rate;
+	int value, changed = 0;
+
+	/* get index from user value*/
+	value = uval->value.enumerated.item[0];
+	for (index = 0; index < ARRAY_SIZE(snd_bebob_rate_table); index++) {
+		if ((bebob->tx_stream_formations[index].pcm == 0) ||
+		    (bebob->rx_stream_formations[index].pcm == 0))
+			continue;
+		else if (value == 0)
+			break;
+		else
+			value--;
+	}
+
+	sampling_rate = snd_bebob_rate_table[index];
+
+	mutex_lock(&bebob->mutex);
+	if (snd_bebob_stream_set_rate(bebob, sampling_rate) < 0)
+		goto end;
+
+	/* prevent from failure of getting command just after setting */
+	msleep(100);
+	changed = 1;
+
+	snd_ctl_notify(bebob->card, SNDRV_CTL_EVENT_MASK_VALUE,
+		       bebob->ctl_id_freq);
+end:
+	mutex_unlock(&bebob->mutex);
+	return changed;
+}
+
+static struct snd_kcontrol_new global_sampling_rate_control = {
+	.name	= "Sampling Rate",
+	.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,
+	.access	= SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info	= control_sampling_rate_info,
+	.get	= control_sampling_rate_get,
+	.put	= control_sampling_rate_put
+};
+
+int snd_bebob_create_control_devices(struct snd_bebob *bebob)
+{
+	int err = 0;
+	struct snd_kcontrol *kctl;
+
+	kctl = snd_ctl_new1(&global_sampling_rate_control, bebob);
+	err = snd_ctl_add(bebob->card, kctl);
+	if (err < 0)
+		goto end;
+	bebob->ctl_id_freq = &kctl->id;
+end:
+	return err;
+}
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c
index 6852945..773dffb 100644
--- a/sound/firewire/bebob/bebob_stream.c
+++ b/sound/firewire/bebob/bebob_stream.c
@@ -368,6 +368,8 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob,
 		err = snd_bebob_stream_set_rate(bebob, rate);
 		if (err < 0)
 			goto end;
+		snd_ctl_notify(bebob->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       bebob->ctl_id_freq);
 
 		err = make_both_connections(bebob, rate);
 		if (err < 0)
-- 
1.8.3.2



More information about the Alsa-devel mailing list