diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c index e3962ff60..0df52f036 100644 --- a/spa/plugins/alsa/alsa-pcm.c +++ b/spa/plugins/alsa/alsa-pcm.c @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -442,9 +443,31 @@ int spa_alsa_parse_prop_params(struct state *state, struct spa_pod *params) return changed; } +#define CHECK(s,msg,...) if ((err = (s)) < 0) { spa_log_error(state->log, msg ": %s", ##__VA_ARGS__, snd_strerror(err)); return err; } + +static ssize_t log_write(void *cookie, const char *buf, size_t size) +{ + struct state *state = cookie; + int len; + + while (size > 0) { + len = strcspn(buf, "\n"); + if (len > 0) + spa_log_debug(state->log, "%.*s", (int)len, buf); + buf += len + 1; + size -= len + 1; + } + return size; +} + +static cookie_io_functions_t io_funcs = { + .write = log_write, +}; + int spa_alsa_init(struct state *state, const struct spa_dict *info) { uint32_t i; + int err; snd_config_update_free_global(); @@ -481,20 +504,31 @@ int spa_alsa_init(struct state *state, const struct spa_dict *info) spa_log_error(state->log, "can't create card %u", state->card_index); return -errno; } + state->log_file = fopencookie(state, "w", io_funcs); + if (state->log_file == NULL) { + spa_log_error(state->log, "can't create log file"); + return -errno; + } + CHECK(snd_output_stdio_attach(&state->output, state->log_file, 0), "attach failed"); + return 0; } int spa_alsa_clear(struct state *state) { + int err; + release_card(state->card); state->card = NULL; state->card_index = SPA_ID_INVALID; - return 0; -} + if ((err = snd_output_close(state->output)) < 0) + spa_log_warn(state->log, "output close failed: %s", snd_strerror(err)); + fclose(state->log_file); -#define CHECK(s,msg,...) if ((err = (s)) < 0) { spa_log_error(state->log, msg ": %s", ##__VA_ARGS__, snd_strerror(err)); return err; } + return err; +} int spa_alsa_open(struct state *state, const char *params) { @@ -505,8 +539,6 @@ int spa_alsa_open(struct state *state, const char *params) if (state->opened) return 0; - CHECK(snd_output_stdio_attach(&state->output, stderr, 0), "attach failed"); - spa_scnprintf(device_name, sizeof(device_name), "%s%s%s", state->card->ucm_prefix ? state->card->ucm_prefix : "", props->device, params ? params : ""); @@ -538,7 +570,8 @@ int spa_alsa_open(struct state *state, const char *params) return 0; error_exit_close: - spa_log_info(state->log, "%p: Device '%s' closing", state, state->props.device); + spa_log_info(state->log, "%p: Device '%s' closing: %s", state, state->props.device, + spa_strerror(err)); snd_pcm_close(state->hndl); return err; } @@ -557,9 +590,6 @@ int spa_alsa_close(struct state *state) spa_log_warn(state->log, "%s: close failed: %s", state->props.device, snd_strerror(err)); - if ((err = snd_output_close(state->output)) < 0) - spa_log_warn(state->log, "output close failed: %s", snd_strerror(err)); - spa_system_close(state->data_system, state->timerfd); if (state->have_format) @@ -922,6 +952,14 @@ skip_channels: return 1; } +static void debug_hw_params(struct state *state, const char *prefix, snd_pcm_hw_params_t *params) +{ + if (SPA_UNLIKELY(spa_log_level_enabled(state->log, SPA_LOG_LEVEL_DEBUG))) { + spa_log_debug(state->log, "%s:", prefix); + snd_pcm_hw_params_dump(params, state->output); + fflush(state->log_file); + } +} static int enum_pcm_formats(struct state *state, uint32_t index, uint32_t *next, struct spa_pod **result, struct spa_pod_builder *b) { @@ -939,8 +977,7 @@ static int enum_pcm_formats(struct state *state, uint32_t index, uint32_t *next, snd_pcm_hw_params_alloca(¶ms); CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration: no configurations available"); - if (SPA_UNLIKELY(spa_log_level_enabled(state->log, SPA_LOG_LEVEL_DEBUG))) - snd_pcm_hw_params_dump(params, state->output); + debug_hw_params(state, __func__, params); CHECK(snd_pcm_hw_params_set_rate_resample(hndl, params, 0), "set_rate_resample"); @@ -1088,8 +1125,7 @@ static int enum_iec958_formats(struct state *state, uint32_t index, uint32_t *ne snd_pcm_hw_params_alloca(¶ms); CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration: no configurations available"); - if (SPA_UNLIKELY(spa_log_level_enabled(state->log, SPA_LOG_LEVEL_DEBUG))) - snd_pcm_hw_params_dump(params, state->output); + debug_hw_params(state, __func__, params); CHECK(snd_pcm_hw_params_set_rate_resample(hndl, params, 0), "set_rate_resample"); @@ -1152,8 +1188,7 @@ static int enum_dsd_formats(struct state *state, uint32_t index, uint32_t *next, snd_pcm_hw_params_alloca(¶ms); CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration: no configurations available"); - if (SPA_UNLIKELY(spa_log_level_enabled(state->log, SPA_LOG_LEVEL_DEBUG))) - snd_pcm_hw_params_dump(params, state->output); + debug_hw_params(state, __func__, params); snd_pcm_format_mask_alloca(&fmask); snd_pcm_hw_params_get_format_mask(params, fmask); @@ -1396,8 +1431,7 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_ /* choose all parameters */ CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration for playback: no configurations available"); - if (SPA_UNLIKELY(spa_log_level_enabled(state->log, SPA_LOG_LEVEL_DEBUG))) - snd_pcm_hw_params_dump(params, state->output); + debug_hw_params(state, __func__, params); /* set hardware resampling, no resample */ CHECK(snd_pcm_hw_params_set_rate_resample(hndl, params, 0), "set_rate_resample"); @@ -1586,6 +1620,12 @@ static int set_swparams(struct state *state) /* write the parameters to the playback device */ CHECK(snd_pcm_sw_params(hndl, params), "sw_params"); + if (SPA_UNLIKELY(spa_log_level_enabled(state->log, SPA_LOG_LEVEL_DEBUG))) { + spa_log_debug(state->log, "state after sw_params:"); + snd_pcm_dump(hndl, state->output); + fflush(state->log_file); + } + return 0; } @@ -2468,8 +2508,6 @@ int spa_alsa_start(struct state *state) state->following, state->matching, state->resample); CHECK(set_swparams(state), "swparams"); - if (SPA_UNLIKELY(spa_log_level_enabled(state->log, SPA_LOG_LEVEL_DEBUG))) - snd_pcm_dump(state->hndl, state->output); if ((err = snd_pcm_prepare(state->hndl)) < 0 && err != -EBUSY) { spa_log_error(state->log, "%s: snd_pcm_prepare error: %s", diff --git a/spa/plugins/alsa/alsa-pcm.h b/spa/plugins/alsa/alsa-pcm.h index 6f16e3696..91385f40d 100644 --- a/spa/plugins/alsa/alsa-pcm.h +++ b/spa/plugins/alsa/alsa-pcm.h @@ -106,6 +106,8 @@ struct state { struct spa_system *data_system; struct spa_loop *data_loop; + FILE *log_file; + uint32_t card_index; struct card *card; snd_pcm_stream_t stream;