diff --git a/src/main.c b/src/main.c index 49ce6e125..addf439d2 100644 --- a/src/main.c +++ b/src/main.c @@ -44,6 +44,7 @@ #include "volume.h" #include "log.h" #include "permission.h" +#include "pcm_resample.h" #include "replay_gain_config.h" #include "decoder_list.h" #include "input_init.h" @@ -403,6 +404,13 @@ int mpd_main(int argc, char *argv[]) #ifdef ENABLE_ARCHIVE archive_plugin_init_all(); #endif + + if (!pcm_resample_global_init(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + decoder_plugin_init_all(); update_global_init(); diff --git a/src/pcm_resample.c b/src/pcm_resample.c index a1e4ee149..ce75325a8 100644 --- a/src/pcm_resample.c +++ b/src/pcm_resample.c @@ -26,15 +26,36 @@ #include +#ifdef HAVE_LIBSAMPLERATE +static bool lsr_enabled; +#endif + #ifdef HAVE_LIBSAMPLERATE static bool pcm_resample_lsr_enabled(void) { - return strcmp(config_get_string(CONF_SAMPLERATE_CONVERTER, ""), - "internal") != 0; + return lsr_enabled; } #endif +bool +pcm_resample_global_init(GError **error_r) +{ +#ifdef HAVE_LIBSAMPLERATE + const char *converter = + config_get_string(CONF_SAMPLERATE_CONVERTER, ""); + + lsr_enabled = strcmp(converter, "internal") != 0; + if (lsr_enabled) + return pcm_resample_lsr_global_init(converter, error_r); + else + return true; +#else + (void)error_r; + return true; +#endif +} + void pcm_resample_init(struct pcm_resample_state *state) { memset(state, 0, sizeof(*state)); diff --git a/src/pcm_resample.h b/src/pcm_resample.h index 167f15e8c..1c71124a6 100644 --- a/src/pcm_resample.h +++ b/src/pcm_resample.h @@ -54,6 +54,9 @@ struct pcm_resample_state { struct pcm_buffer buffer; }; +bool +pcm_resample_global_init(GError **error_r); + /** * Initializes a pcm_resample_state object. */ diff --git a/src/pcm_resample_internal.h b/src/pcm_resample_internal.h index 37aae96ef..d8e0ba5a1 100644 --- a/src/pcm_resample_internal.h +++ b/src/pcm_resample_internal.h @@ -32,6 +32,9 @@ #ifdef HAVE_LIBSAMPLERATE +bool +pcm_resample_lsr_global_init(const char *converter, GError **error_r); + void pcm_resample_lsr_deinit(struct pcm_resample_state *state); diff --git a/src/pcm_resample_libsamplerate.c b/src/pcm_resample_libsamplerate.c index ebce488f4..769f904c1 100644 --- a/src/pcm_resample_libsamplerate.c +++ b/src/pcm_resample_libsamplerate.c @@ -30,12 +30,59 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "pcm" +static int lsr_converter = SRC_SINC_FASTEST; + static inline GQuark libsamplerate_quark(void) { return g_quark_from_static_string("libsamplerate"); } +static bool +lsr_parse_converter(const char *s) +{ + assert(s != NULL); + + if (*s == 0) + return true; + + char *endptr; + long l = strtol(s, &endptr, 10); + if (*endptr == 0 && src_get_name(l) != NULL) { + lsr_converter = l; + return true; + } + + size_t length = strlen(s); + for (int i = 0;; ++i) { + const char *name = src_get_name(i); + if (name == NULL) + break; + + if (g_ascii_strncasecmp(s, name, length) == 0) { + lsr_converter = i; + return true; + } + } + + return false; +} + +bool +pcm_resample_lsr_global_init(const char *converter, GError **error_r) +{ + if (!lsr_parse_converter(converter)) { + g_set_error(error_r, libsamplerate_quark(), 0, + "unknown samplerate converter '%s'", converter); + return false; + } + + g_debug("libsamplerate converter '%s'", + src_get_name(lsr_converter)); + + return true; +} + void pcm_resample_lsr_deinit(struct pcm_resample_state *state) { @@ -47,54 +94,14 @@ pcm_resample_lsr_deinit(struct pcm_resample_state *state) pcm_buffer_deinit(&state->buffer); } -static int pcm_resample_get_converter(void) -{ - const char *conf = config_get_string(CONF_SAMPLERATE_CONVERTER, NULL); - long convalgo; - char *test; - const char *test2; - size_t len; - - if (!conf) { - convalgo = SRC_SINC_FASTEST; - goto out; - } - - convalgo = strtol(conf, &test, 10); - if (*test == '\0' && src_get_name(convalgo)) - goto out; - - len = strlen(conf); - for (convalgo = 0 ; ; convalgo++) { - test2 = src_get_name(convalgo); - if (!test2) { - convalgo = SRC_SINC_FASTEST; - break; - } - if (g_ascii_strncasecmp(test2, conf, len) == 0) - goto out; - } - - g_warning("unknown samplerate converter \"%s\"", conf); -out: - g_debug("selecting samplerate converter \"%s\"", - src_get_name(convalgo)); - - return convalgo; -} - static bool pcm_resample_set(struct pcm_resample_state *state, uint8_t channels, unsigned src_rate, unsigned dest_rate, GError **error_r) { - static int convalgo = -1; int error; SRC_DATA *data = &state->data; - if (convalgo < 0) - convalgo = pcm_resample_get_converter(); - /* (re)set the state/ratio if the in or out format changed */ if (channels == state->prev.channels && src_rate == state->prev.src_rate && @@ -109,7 +116,7 @@ pcm_resample_set(struct pcm_resample_state *state, if (state->state) state->state = src_delete(state->state); - state->state = src_new(convalgo, channels, &error); + state->state = src_new(lsr_converter, channels, &error); if (!state->state) { g_set_error(error_r, libsamplerate_quark(), state->error, "libsamplerate initialization has failed: %s",