Simplify mixer setup.
authorAndre Noll <maan@tuebingen.mpg.de>
Fri, 30 Dec 2016 23:06:10 +0000 (00:06 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Sat, 1 Apr 2017 10:49:24 +0000 (12:49 +0200)
The ->init method of the two mixer implementations initialize the
members of the mixer structure. This structure contains only function
pointers. Their values, once set, never change.

Hence we may initialize the structure at compile time and make it
constant.

alsa_mix.c
configure.ac
mix.h
mixer.c
oss_mix.c

index 3adee92..6520416 100644 (file)
@@ -216,19 +216,13 @@ static int alsa_mix_set(struct mixer_handle *h, int val)
        return 1;
 }
 
-/**
- * The init function of the ALSA mixer.
- *
- * \param self The structure to initialize.
- *
- * \sa struct \ref mixer, \ref oss_mix_init().
- */
-void alsa_mix_init(struct mixer *self)
-{
-       self->open = alsa_mix_open;
-       self->get_channels = alsa_mix_get_channels;
-       self->set_channel = alsa_mix_set_channel;
-       self->close = alsa_mix_close;
-       self->get = alsa_mix_get;
-       self->set = alsa_mix_set;
-}
+/** The mixer operations for the ALSA mixer. */
+const struct mixer alsa_mixer = {
+       .name = "alsa",
+       .open = alsa_mix_open,
+       .get_channels = alsa_mix_get_channels,
+       .set_channel = alsa_mix_set_channel,
+       .close = alsa_mix_close,
+       .get = alsa_mix_get,
+       .set = alsa_mix_set
+};
index 4fe4579..b2ea0a7 100644 (file)
@@ -587,36 +587,12 @@ if test $HAVE_OSS = yes -o $HAVE_ALSA = yes; then
        mixer_errlist_objs="mixer exec string fd version"
        if test $HAVE_OSS = yes; then
                mixer_errlist_objs="$mixer_errlist_objs oss_mix"
-               mixers="${mixers}oss "
-               default_mixer="OSS_MIX"
        fi
        if test $HAVE_ALSA = yes; then
                mixer_errlist_objs="$mixer_errlist_objs alsa_mix"
-               mixers="${mixers}alsa "
-               default_mixer="ALSA_MIX"
        fi
        mixer_objs="$mixer_errlist_objs"
        AC_SUBST(mixer_objs, add_dot_o($mixer_objs))
-       enum="$(
-               for i in $mixers; do
-                       printf "${i}_MIX, " | tr '[a-z]' '[A-Z]'
-               done
-       )"
-       AC_DEFINE_UNQUOTED(MIXER_ENUM, $enum NUM_SUPPORTED_MIXERS,
-               enum of supported mixers)
-       AC_DEFINE_UNQUOTED(DEFAULT_MIXER, $default_mixer,
-               use this mixer if none was specified)
-       names="$(for i in $mixers; do printf \"$i\",' ' ; done)"
-       AC_DEFINE_UNQUOTED(MIXER_NAMES, $names, supported mixer names)
-       inits="$(
-               for i in $mixers; do
-                       printf 'extern void '$i'_mix_init(struct mixer *); '
-               done
-       )"
-       AC_DEFINE_UNQUOTED(DECLARE_MIXER_INITS, $inits,
-               init functions of the supported mixers)
-       array="$(for i in $mixers; do printf '{.init = '$i'_mix_init},'; done)"
-       AC_DEFINE_UNQUOTED(MIXER_ARRAY, $array, array of supported mixers)
 else
        build_mixer="no"
        AC_MSG_WARN([no mixer support])
diff --git a/mix.h b/mix.h
index fe85d74..5d68b2b 100644 (file)
--- a/mix.h
+++ b/mix.h
@@ -16,10 +16,14 @@ struct mixer_handle;
 
 /**
  * Operations provided by each mixer plugin.
+ *
+ * Each mixer plugin must define a non-static instance of this structure, with
+ * all pointers initialized to non-NULL values. No other symbols need to be
+ * exported.
  */
 struct mixer {
-       /** Called on startup, must fill in all other members. */
-       void (*init)(struct mixer *self);
+       /** Used to identify the mixer. */
+       const char * const name;
        /** Return a handle that can be passed to other methods. */
        int (*open)(const char *dev, struct mixer_handle **handle);
        /** Returns a string of all valid mixer channels. */
@@ -34,3 +38,6 @@ struct mixer {
        /** Free all resources associated with the given handle. */
        void (*close)(struct mixer_handle **handle);
 };
+
+/** Declared even if unsupported because it does not hurt and avoids ifdefs. */
+extern const struct mixer alsa_mixer, oss_mixer;
diff --git a/mixer.c b/mixer.c
index d33fa83..0c08e2f 100644 (file)
--- a/mixer.c
+++ b/mixer.c
 /** Array of error strings. */
 DEFINE_PARA_ERRLIST;
 
-enum mixer_id {MIXER_ENUM};
-static char *mixer_name[] = {MIXER_NAMES};
-DECLARE_MIXER_INITS;
-static struct mixer supported_mixer[] = {MIXER_ARRAY};
+/* At least one of the two is defined if this file gets compiled. */
+static const struct mixer *mixers[] = {
+#ifdef HAVE_ALSA
+       &alsa_mixer,
+#endif
+#ifdef HAVE_OSS
+       &oss_mixer,
+#endif
+};
+
+#define NUM_SUPPORTED_MIXERS (ARRAY_SIZE(mixers))
 #define FOR_EACH_MIXER(i) for ((i) = 0; (i) < NUM_SUPPORTED_MIXERS; (i)++)
 
 static struct lls_parse_result *lpr, *sub_lpr;
@@ -36,7 +43,7 @@ static struct lls_parse_result *lpr, *sub_lpr;
 #define OPT_STRING_VAL(_cmd, _opt) (lls_string_val(0, OPT_RESULT(_cmd, _opt)))
 #define OPT_UINT32_VAL(_cmd, _opt) (lls_uint32_val(0, OPT_RESULT(_cmd, _opt)))
 
-typedef int (*mixer_subcommand_handler_t)(struct mixer *, struct mixer_handle *);
+typedef int (*mixer_subcommand_handler_t)(const struct mixer *, struct mixer_handle *);
 
 #define EXPORT_CMD(_cmd) const mixer_subcommand_handler_t \
        lsg_mixer_com_ ## _cmd ## _user_data = &com_ ## _cmd;
@@ -59,7 +66,8 @@ static __printf_2_3 void date_log(int ll, const char *fmt, ...)
 }
 __printf_2_3 void (*para_log)(int, const char*, ...) = date_log;
 
-static int set_channel(struct mixer *m, struct mixer_handle *h, const char *channel)
+static int set_channel(const struct mixer *m, struct mixer_handle *h,
+               const char *channel)
 {
 
        PARA_NOTICE_LOG("using %s mixer channel\n", channel?
@@ -106,7 +114,7 @@ static unsigned volume_time(double vol, double old_vol, double new_vol,
 }
 
 /* Fade to new volume in fade_time seconds. */
-static int fade(struct mixer *m, struct mixer_handle *h, uint32_t new_vol,
+static int fade(const struct mixer *m, struct mixer_handle *h, uint32_t new_vol,
                uint32_t fade_time)
 {
        int i, T, old_vol, ret, slept, incr;
@@ -148,7 +156,7 @@ sleep:
        return ret;
 }
 
-static int com_fade(struct mixer *m, struct mixer_handle *h)
+static int com_fade(const struct mixer *m, struct mixer_handle *h)
 {
        uint32_t new_vol = OPT_UINT32_VAL(FADE, FADE_VOL);
        uint32_t fade_time = OPT_UINT32_VAL(FADE, FADE_TIME);
@@ -196,7 +204,7 @@ static void change_afs_mode(const char *afs_mode)
        free(cmd);
 }
 
-static int set_initial_volume(struct mixer *m, struct mixer_handle *h)
+static int set_initial_volume(const struct mixer *m, struct mixer_handle *h)
 {
        int i, ret;
 
@@ -235,7 +243,7 @@ static int set_initial_volume(struct mixer *m, struct mixer_handle *h)
        return 1;
 }
 
-static int com_sleep(struct mixer *m, struct mixer_handle *h)
+static int com_sleep(const struct mixer *m, struct mixer_handle *h)
 {
        time_t t1, wake_time_epoch;
        unsigned int delay;
@@ -328,7 +336,7 @@ static int com_sleep(struct mixer *m, struct mixer_handle *h)
 }
 EXPORT_CMD(sleep);
 
-static int com_snooze(struct mixer *m, struct mixer_handle *h)
+static int com_snooze(const struct mixer *m, struct mixer_handle *h)
 {
        int ret, val;
 
@@ -355,44 +363,31 @@ static int com_snooze(struct mixer *m, struct mixer_handle *h)
 }
 EXPORT_CMD(snooze);
 
-static void init_mixers(void)
-{
-       int i;
-
-       FOR_EACH_MIXER(i) {
-               struct mixer *m = &supported_mixer[i];
-               PARA_DEBUG_LOG("initializing mixer API #%d (%s)\n",
-                       i, mixer_name[i]);
-               m->init(m);
-       }
-}
-
-static int com_set(struct mixer *m, struct mixer_handle *h)
+static int com_set(const struct mixer *m, struct mixer_handle *h)
 {
        return m->set(h, OPT_UINT32_VAL(SET, VAL));
 }
 EXPORT_CMD(set);
 
-static struct mixer *get_mixer_or_die(void)
+static const struct mixer *get_mixer_or_die(void)
 {
        int i;
 
        if (!OPT_GIVEN(PARA_MIXER, MIXER_API))
-               i = DEFAULT_MIXER;
+               i = 0; /* default: use first mixer */
        else
                FOR_EACH_MIXER(i)
-                       if (!strcmp(mixer_name[i],
+                       if (!strcmp(mixers[i]->name,
                                        OPT_STRING_VAL(PARA_MIXER, MIXER_API)))
                                break;
        if (i < NUM_SUPPORTED_MIXERS) {
-               PARA_NOTICE_LOG("using %s mixer API\n", mixer_name[i]);
-               return supported_mixer + i;
+               PARA_NOTICE_LOG("using %s mixer API\n", mixers[i]->name);
+               return mixers[i];
        }
        printf("available mixer APIs: ");
-       FOR_EACH_MIXER(i) {
-               int d = (i == DEFAULT_MIXER);
-               printf("%s%s%s ", d? "[" : "", mixer_name[i], d? "]" : "");
-       }
+       FOR_EACH_MIXER(i)
+               printf("%s%s%s ", i == 0? "[" : "", mixers[i]->name,
+                       i == 0? "]" : "");
        printf("\n");
        exit(EXIT_FAILURE);
 }
@@ -410,7 +405,8 @@ static void show_subcommands(void)
 }
 
 
-static int com_help(__a_unused struct mixer *m, __a_unused struct mixer_handle *h)
+static int com_help(__a_unused const struct mixer *m,
+               __a_unused struct mixer_handle *h)
 {
        const struct lls_command *cmd;
        const struct lls_opt_result *r_l = OPT_RESULT(HELP, LONG);
@@ -536,7 +532,7 @@ int main(int argc, char *argv[])
        int ret;
        char *errctx;
        const char *subcmd;
-       struct mixer *m;
+       const struct mixer *m;
        struct mixer_handle *h;
        unsigned n;
 
@@ -567,7 +563,6 @@ int main(int argc, char *argv[])
        ret = parse_and_merge_config_file(cmd);
        if (ret < 0)
                goto free_lpr;
-       init_mixers();
        m = get_mixer_or_die();
        ret = m->open(OPT_STRING_VAL(PARA_MIXER, MIXER_DEVICE), &h);
        if (ret < 0)
index 8e87452..7fbdba5 100644 (file)
--- a/oss_mix.c
+++ b/oss_mix.c
@@ -135,19 +135,13 @@ static void oss_mix_close(struct mixer_handle **handle)
        *handle = NULL;
 }
 
-/**
- * The init function of the OSS mixer.
- *
- * \param self The structure to initialize.
- *
- * \sa struct \ref mixer, \ref alsa_mix_init().
- */
-void oss_mix_init(struct mixer *self)
-{
-       self->open = oss_mix_open;
-       self->get_channels = oss_mix_get_channels;
-       self->set_channel = oss_mix_set_channel;
-       self->get = oss_mix_get;
-       self->set = oss_mix_set;
-       self->close = oss_mix_close;
-}
+/** The mixer operations for the OSS mixer. */
+const struct mixer oss_mixer = {
+       .name = "oss",
+       .open = oss_mix_open,
+       .get_channels = oss_mix_get_channels,
+       .set_channel = oss_mix_set_channel,
+       .close = oss_mix_close,
+       .get = oss_mix_get,
+       .set = oss_mix_set
+};