aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Farrugia <mark.farrugia@fiberdyne.com.au>2018-11-01 12:17:10 +1100
committerMark Farrugia <mark.farrugia@fiberdyne.com.au>2018-11-01 14:57:07 +1100
commit52db7a23a234080d3a28dfe60191c239cc04613b (patch)
treea7b2332b51d6fee70f0f8cfec245fe4ca9e8d6dc
parent0765c6c497379a9f850d15be3b3cbdaba59fe7fc (diff)
Only expose streams mapped to audiopaths on configure() cb
When the configure() callback occurs for each audiopath, we only want those streams that are mapped to the given audiopath to be exposed to the audiopath. E.g. only streams mapped to loopback should be propagated to loopback via configure() callback, rather than all streams. Signed-off-by: Mark Farrugia <mark.farrugia@fiberdyne.com.au>
-rw-r--r--core.c88
-rw-r--r--core.h18
-rw-r--r--dummy/dummy.c13
-rw-r--r--loopback/loopback.c40
-rw-r--r--sound/avirt.h48
5 files changed, 106 insertions, 101 deletions
diff --git a/core.c b/core.c
index 827ee5c..f31c61a 100644
--- a/core.c
+++ b/core.c
@@ -44,9 +44,9 @@ struct snd_avirt_audiopath_obj {
static struct kset *snd_avirt_audiopath_kset;
static struct kobject *kobj;
-#define to_audiopath_obj(d) \
+#define to_audiopath_obj(d) \
container_of(d, struct snd_avirt_audiopath_obj, kobj)
-#define to_audiopath_attr(a) \
+#define to_audiopath_attr(a) \
container_of(a, struct snd_avirt_audiopath_attribute, attr)
/**
@@ -188,6 +188,15 @@ static struct snd_avirt_audiopath_obj *
return snd_avirt_audiopath;
}
+/**
+ * destroy_snd_avirt_audiopath_obj - destroys an Audio Path object
+ * @name: the Audio Path object
+ */
+static void destroy_snd_avirt_audiopath_obj(struct snd_avirt_audiopath_obj *p)
+{
+ kobject_put(&p->kobj);
+}
+
static struct snd_pcm *pcm_create(struct snd_avirt_stream *stream)
{
bool playback = false, capture = false;
@@ -223,13 +232,22 @@ static struct snd_pcm *pcm_create(struct snd_avirt_stream *stream)
return pcm;
}
-/**
- * destroy_snd_avirt_audiopath_obj - destroys an Audio Path object
- * @name: the Audio Path object
- */
-static void destroy_snd_avirt_audiopath_obj(struct snd_avirt_audiopath_obj *p)
+static int snd_avirt_streams_get(const char *map,
+ struct snd_avirt_stream_array *stream_array)
{
- kobject_put(&p->kobj);
+ struct list_head *entry;
+ struct config_item *item;
+ struct snd_avirt_stream *stream;
+
+ list_for_each (entry, &core.stream_group->cg_children) {
+ item = container_of(entry, struct config_item, ci_entry);
+ stream = snd_avirt_stream_from_config_item(item);
+ if (!strcmp(map, stream->map)) {
+ stream_array->streams[stream_array->count++] = stream;
+ }
+ }
+
+ return 0;
}
/**
@@ -258,6 +276,7 @@ struct snd_avirt_audiopath *snd_avirt_audiopath_get(const char *uid)
int snd_avirt_audiopath_register(struct snd_avirt_audiopath *audiopath)
{
struct snd_avirt_audiopath_obj *audiopath_obj;
+ struct snd_avirt_stream_array stream_array;
if (!audiopath) {
D_ERRORK("Audio Path is NULL!");
@@ -277,11 +296,11 @@ int snd_avirt_audiopath_register(struct snd_avirt_audiopath *audiopath)
list_add_tail(&audiopath_obj->list, &audiopath_list);
// If we have already sealed the streams, configure this AP
- if (core.streams_sealed)
- audiopath->configure(core.card, core.stream_group,
- core.stream_count);
-
- *info = &coreinfo;
+ if (core.streams_sealed) {
+ stream_array.count = 0;
+ snd_avirt_streams_get(audiopath->uid, &stream_array);
+ audiopath->configure(core.card, &stream_array);
+ }
return 0;
}
@@ -317,34 +336,6 @@ int snd_avirt_audiopath_deregister(struct snd_avirt_audiopath *audiopath)
EXPORT_SYMBOL_GPL(snd_avirt_audiopath_deregister);
/**
- * snd_avirt_stream_count - get the stream count for the given direction
- * @direction: The direction to get the stream count for
- * @return: The stream count
- */
-int snd_avirt_stream_count(unsigned int direction)
-{
- struct list_head *entry;
- struct config_item *item;
- struct snd_avirt_stream *stream;
- unsigned int count = 0;
-
- if (direction > 1)
- return -ERANGE;
-
- list_for_each(entry, &core.stream_group->cg_children) {
- item = container_of(entry, struct config_item, ci_entry);
- stream = snd_avirt_stream_from_config_item(item);
- if (!stream)
- return -EFAULT;
- if (stream->direction == direction)
- count++;
- }
-
- return count;
-}
-EXPORT_SYMBOL_GPL(snd_avirt_stream_count);
-
-/**
* snd_avirt_stream_create - Create audio stream, including it's ALSA PCM device
* @name: The name designated to the audio stream
* @direction: The PCM direction (SNDRV_PCM_STREAM_PLAYBACK or
@@ -356,6 +347,11 @@ struct snd_avirt_stream *snd_avirt_stream_create(const char *name,
{
struct snd_avirt_stream *stream;
+ if ((core.stream_count + 1) > MAX_STREAMS) {
+ D_ERRORK("Cannot add stream %s, PCMs are maxxed out!", name);
+ return ERR_PTR(-EPERM);
+ }
+
stream = kzalloc(sizeof(*stream), GFP_KERNEL);
if (!stream)
return ERR_PTR(-ENOMEM);
@@ -373,9 +369,10 @@ struct snd_avirt_stream *snd_avirt_stream_create(const char *name,
int snd_avirt_streams_seal(void)
{
- int err = 0;
+ int err = 0, i = 0;
struct snd_avirt_audiopath_obj *ap_obj;
struct snd_avirt_stream *stream;
+ struct snd_avirt_stream_array stream_array;
struct config_item *item;
struct list_head *entry;
@@ -396,8 +393,11 @@ int snd_avirt_streams_seal(void)
list_for_each_entry(ap_obj, &audiopath_list, list) {
D_INFOK("configure() AP uid: %s", ap_obj->path->uid);
- ap_obj->path->configure(core.card, core.stream_group,
- core.stream_count);
+ for (i = 0; i < MAX_STREAMS; i++)
+ stream_array.streams[i] = NULL;
+ stream_array.count = 0;
+ snd_avirt_streams_get(ap_obj->path->uid, &stream_array);
+ ap_obj->path->configure(core.card, &stream_array);
}
err = snd_card_register(core.card);
diff --git a/core.h b/core.h
index 16f186a..8804573 100644
--- a/core.h
+++ b/core.h
@@ -68,4 +68,22 @@ struct snd_avirt_stream *snd_avirt_stream_find_by_device(unsigned int device);
struct snd_avirt_stream *snd_avirt_stream_create(const char *name,
int direction);
+/**
+ * snd_avirt_audiopath_get - retrieves the Audio Path by it's UID
+ * @uid: Unique ID for the Audio Path
+ * @return: Corresponding Audio Path
+ */
+struct snd_avirt_audiopath *snd_avirt_audiopath_get(const char *uid);
+
+/**
+ * snd_avirt_stream_from_config_item - Convert config_item to a snd_avirt_stream
+ * @item: The config_item to convert from
+ * @return: The item's snd_avirt_stream if successful, NULL otherwise
+ */
+static inline struct snd_avirt_stream *
+snd_avirt_stream_from_config_item(struct config_item *item)
+{
+ return item ? container_of(item, struct snd_avirt_stream, item) : NULL;
+}
+
#endif /* __SOUND_AVIRT_CORE_H */
diff --git a/dummy/dummy.c b/dummy/dummy.c
index 7c85531..872ade9 100644
--- a/dummy/dummy.c
+++ b/dummy/dummy.c
@@ -240,17 +240,14 @@ static struct snd_pcm_ops dummyap_pcm_ops = {
* Dummy Audio Path AVIRT registration
******************************************************************************/
static int dummy_configure(struct snd_card *card,
- struct config_group *snd_avirt_stream_group,
- unsigned int stream_count)
+ struct snd_avirt_stream_array *stream_array)
{
// Do something with streams
+ int idx = 0;
+ struct snd_avirt_stream *stream;
- struct list_head *entry;
- list_for_each (entry, &snd_avirt_stream_group->cg_children) {
- struct config_item *item =
- container_of(entry, struct config_item, ci_entry);
- struct snd_avirt_stream *stream =
- snd_avirt_stream_from_config_item(item);
+ for (idx = 0; idx < stream_array->count; idx++) {
+ stream = stream_array->streams[idx];
AP_INFOK("stream name:%s device:%d channels:%d", stream->name,
stream->device, stream->channels);
}
diff --git a/loopback/loopback.c b/loopback/loopback.c
index c3e06be..9646706 100644
--- a/loopback/loopback.c
+++ b/loopback/loopback.c
@@ -78,6 +78,8 @@ struct loopback {
struct loopback_cable *cables[MAX_STREAMS];
struct snd_pcm *pcm[MAX_STREAMS];
struct loopback_setup setup[MAX_STREAMS];
+ int playback_count;
+ int capture_count;
};
struct loopback_pcm {
@@ -932,13 +934,13 @@ static int loopback_mixer_new(struct loopback *loopback, int notify)
struct snd_pcm *pcm;
struct snd_kcontrol *kctl;
struct loopback_setup *setup;
- int dev, dev_count, idx, err;
+ int dev_idx, dev_count, idx, err;
strcpy(card->mixername, "Loopback Mixer");
- dev_count = snd_avirt_stream_count(SNDRV_PCM_STREAM_PLAYBACK);
- for (dev = 0; dev < dev_count; dev++) {
- pcm = loopback->pcm[dev];
- setup = &loopback->setup[dev];
+ dev_count = loopback->playback_count + loopback->capture_count;
+ for (dev_idx = 0; dev_idx < dev_count; dev_idx++) {
+ pcm = loopback->pcm[dev_idx];
+ setup = &loopback->setup[dev_idx];
setup->notify = notify;
setup->rate_shift = NO_PITCH;
setup->format = SNDRV_PCM_FORMAT_S16_LE;
@@ -948,7 +950,7 @@ static int loopback_mixer_new(struct loopback *loopback, int notify)
kctl = snd_ctl_new1(&loopback_controls[idx], loopback);
if (!kctl)
return -ENOMEM;
- kctl->id.device = dev;
+ kctl->id.device = pcm->device;
kctl->id.subdevice = 0;
switch (idx) {
case ACTIVE_IDX:
@@ -1043,25 +1045,29 @@ static int loopback_proc_new(struct loopback *loopback, int cidx)
}
static int loopbackap_configure(struct snd_card *card,
- struct config_group *snd_avirt_stream_group,
- unsigned int stream_count)
+ struct snd_avirt_stream_array *stream_array)
{
- int err;
- struct list_head *entry;
+ int err, idx;
+ struct snd_avirt_stream *stream;
loopback = kzalloc(sizeof(struct loopback), GFP_KERNEL);
if (!loopback)
return -ENOMEM;
loopback->card = card;
+ loopback->playback_count = 0;
+ loopback->capture_count = 0;
mutex_init(&loopback->cable_lock);
- list_for_each (entry, &snd_avirt_stream_group->cg_children) {
- struct config_item *item =
- container_of(entry, struct config_item, ci_entry);
- struct snd_avirt_stream *stream =
- snd_avirt_stream_from_config_item(item);
- loopback->pcm[stream->device] = stream->pcm;
-
+ for (idx = 0; idx < stream_array->count; idx++) {
+ stream = stream_array->streams[idx];
+ if (!stream)
+ return -EFAULT;
+ loopback->pcm[loopback->playback_count +
+ loopback->capture_count] = stream->pcm;
+ if (stream->direction)
+ loopback->playback_count++;
+ else
+ loopback->capture_count++;
AP_INFOK("stream name:%s device:%d channels:%d", stream->name,
stream->device, stream->channels);
}
diff --git a/sound/avirt.h b/sound/avirt.h
index b077bbc..55db1eb 100644
--- a/sound/avirt.h
+++ b/sound/avirt.h
@@ -17,23 +17,24 @@
#define MAX_STREAMS 16
#define MAX_NAME_LEN 80
-#define DINFO(logname, fmt, args...) \
+#define DINFO(logname, fmt, args...) \
snd_printk(KERN_INFO "AVIRT: %s: " fmt "\n", logname, ##args)
-#define DERROR(logname, fmt, args...) \
+#define DERROR(logname, fmt, args...) \
snd_printk(KERN_ERR "AVIRT: %s: " fmt "\n", logname, ##args)
-#define DDEBUG(logname, fmt, args...) \
+#define DDEBUG(logname, fmt, args...) \
snd_printk(KERN_DEBUG "AVIRT: %s: " fmt "\n", logname, ##args)
+struct snd_avirt_stream_array; /* Forward declaration */
+
/**
* AVIRT Audio Path configure function type
* Each Audio Path registers this at snd_avirt_audiopath_register time.
* It is then called by the core once AVIRT has been configured
*/
-typedef int (*snd_avirt_audiopath_configure)(struct snd_card *card,
- struct config_group *stream_group,
- unsigned int stream_count);
+typedef int (*snd_avirt_audiopath_configure)(
+ struct snd_card *card, struct snd_avirt_stream_array *stream_array);
/**
* AVIRT Audio Path info
@@ -49,7 +50,7 @@ struct snd_avirt_audiopath {
void *context;
};
-/*
+/**
* Audio stream configuration
*/
struct snd_avirt_stream {
@@ -63,6 +64,14 @@ struct snd_avirt_stream {
};
/**
+ * Audio stream group
+ */
+struct snd_avirt_stream_array {
+ struct snd_avirt_stream *streams[MAX_STREAMS];
+ int count;
+};
+
+/**
* snd_avirt_audiopath_register - register Audio Path with AVIRT
* @audiopath: Audio Path to be registered
* @return: 0 on success or error code otherwise
@@ -77,31 +86,6 @@ int snd_avirt_audiopath_register(struct snd_avirt_audiopath *audiopath);
int snd_avirt_audiopath_deregister(struct snd_avirt_audiopath *audiopath);
/**
- * snd_avirt_audiopath_get - retrieves the Audio Path by it's UID
- * @uid: Unique ID for the Audio Path
- * @return: Corresponding Audio Path
- */
-struct snd_avirt_audiopath *snd_avirt_audiopath_get(const char *uid);
-
-/**
- * snd_avirt_stream_count - get the stream count for the given direction
- * @direction: The direction to get the stream count for
- * @return: The stream count
- */
-int snd_avirt_stream_count(unsigned int direction);
-
-/**
- * snd_avirt_stream_from_config_item - Convert config_item to a snd_avirt_stream
- * @item: The config_item to convert from
- * @return: The item's snd_avirt_stream if successful, NULL otherwise
- */
-static inline struct snd_avirt_stream *
- snd_avirt_stream_from_config_item(struct config_item *item)
-{
- return item ? container_of(item, struct snd_avirt_stream, item) : NULL;
-}
-
-/**
* snd_avirt_pcm_period_elapsed - PCM buffer complete callback
* @substream: pointer to ALSA PCM substream
*