From e413873ec15efc84366e747d3c5d48293b959c1f Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sat, 31 Dec 2016 00:06:10 +0100 Subject: [PATCH] Simplify mixer setup. 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 | 26 ++++++++------------ configure.ac | 24 ------------------- mix.h | 11 +++++++-- mixer.c | 67 ++++++++++++++++++++++++---------------------------- oss_mix.c | 26 ++++++++------------ 5 files changed, 60 insertions(+), 94 deletions(-) diff --git a/alsa_mix.c b/alsa_mix.c index 3adee929..6520416f 100644 --- a/alsa_mix.c +++ b/alsa_mix.c @@ -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 +}; diff --git a/configure.ac b/configure.ac index 4fe45795..b2ea0a72 100644 --- a/configure.ac +++ b/configure.ac @@ -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 fe85d746..5d68b2bb 100644 --- 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 d33fa831..0c08e2f6 100644 --- a/mixer.c +++ b/mixer.c @@ -21,10 +21,17 @@ /** 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) diff --git a/oss_mix.c b/oss_mix.c index 8e87452b..7fbdba5b 100644 --- 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 +}; -- 2.39.2