alsa: make it possible to configure the clock name

When nodes are synchronized to a common clock, the clock name can
be set to the same value on the alsa nodes and no resampling will
be done.
This commit is contained in:
Wim Taymans 2021-12-10 11:04:38 +01:00
parent e1576c53d4
commit 0648297fcb
2 changed files with 26 additions and 18 deletions

View file

@ -121,6 +121,9 @@ static int alsa_set_param(struct state *state, const char *k, const char *s)
state->props.use_chmap = spa_atob(s); state->props.use_chmap = spa_atob(s);
} else if (spa_streq(k, "api.alsa.multi-rate")) { } else if (spa_streq(k, "api.alsa.multi-rate")) {
state->multi_rate = spa_atob(s); state->multi_rate = spa_atob(s);
} else if (spa_streq(k, "clock.name")) {
spa_scnprintf(state->clock_name,
sizeof(state->clock_name), "%s", s);
} else } else
return 0; return 0;
@ -249,6 +252,14 @@ struct spa_pod *spa_alsa_enum_propinfo(struct state *state,
SPA_PROP_INFO_type, SPA_POD_Bool(state->multi_rate), SPA_PROP_INFO_type, SPA_POD_Bool(state->multi_rate),
SPA_PROP_INFO_params, SPA_POD_Bool(true)); SPA_PROP_INFO_params, SPA_POD_Bool(true));
break; break;
case 11:
param = spa_pod_builder_add_object(b,
SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
SPA_PROP_INFO_name, SPA_POD_String("clock.name"),
SPA_PROP_INFO_description, SPA_POD_String("The name of the clock"),
SPA_PROP_INFO_type, SPA_POD_String(state->clock_name),
SPA_PROP_INFO_params, SPA_POD_Bool(true));
break;
default: default:
return NULL; return NULL;
} }
@ -299,6 +310,9 @@ int spa_alsa_add_prop_params(struct state *state, struct spa_pod_builder *b)
spa_pod_builder_string(b, "api.alsa.multi-rate"); spa_pod_builder_string(b, "api.alsa.multi-rate");
spa_pod_builder_bool(b, state->multi_rate); spa_pod_builder_bool(b, state->multi_rate);
spa_pod_builder_string(b, "clock.name");
spa_pod_builder_string(b, state->clock_name);
spa_pod_builder_pop(b, &f[0]); spa_pod_builder_pop(b, &f[0]);
return 0; return 0;
} }
@ -372,6 +386,9 @@ int spa_alsa_init(struct state *state, const struct spa_dict *info)
alsa_set_param(state, k, s); alsa_set_param(state, k, s);
} }
} }
if (state->clock_name[0] == '\0')
snprintf(state->clock_name, sizeof(state->clock_name),
"api.alsa.%d", state->card_index);
if (state->stream == SND_PCM_STREAM_PLAYBACK) { if (state->stream == SND_PCM_STREAM_PLAYBACK) {
state->is_iec958 = spa_strstartswith(state->props.device, "iec958"); state->is_iec958 = spa_strstartswith(state->props.device, "iec958");
@ -400,7 +417,6 @@ int spa_alsa_open(struct state *state, const char *params)
{ {
int err; int err;
struct props *props = &state->props; struct props *props = &state->props;
snd_pcm_info_t *pcminfo;
char device_name[256]; char device_name[256];
if (state->opened) if (state->opened)
@ -429,16 +445,9 @@ int spa_alsa_open(struct state *state, const char *params)
state->timerfd = err; state->timerfd = err;
snd_pcm_info_alloca(&pcminfo); if (state->clock)
snd_pcm_info(state->hndl, pcminfo); spa_scnprintf(state->clock->name, sizeof(state->clock->name),
"%s", state->clock_name);
/* we would love to use the sync_id but it always returns 0, so use the
* card id for now */
state->pcm_card = snd_pcm_info_get_card(pcminfo);
if (state->clock) {
snprintf(state->clock->name, sizeof(state->clock->name),
"api.alsa.%d", state->pcm_card);
}
state->opened = true; state->opened = true;
state->sample_count = 0; state->sample_count = 0;
state->sample_time = 0; state->sample_time = 0;
@ -1636,18 +1645,17 @@ static inline bool is_following(struct state *state)
static int setup_matching(struct state *state) static int setup_matching(struct state *state)
{ {
int card;
state->matching = state->following; state->matching = state->following;
if (state->position == NULL) if (state->position == NULL)
return -ENOTSUP; return -ENOTSUP;
spa_log_debug(state->log, "clock:%s card:%d", state->position->clock.name, state->pcm_card); spa_log_debug(state->log, "driver clock:'%s' our clock:'%s'",
if (sscanf(state->position->clock.name, "api.alsa.%d", &card) == 1 && state->position->clock.name, state->clock_name);
card == state->pcm_card) {
if (spa_streq(state->position->clock.name, state->clock_name))
state->matching = false; state->matching = false;
}
state->resample = ((uint32_t)state->rate != state->rate_denom) || state->matching; state->resample = ((uint32_t)state->rate != state->rate_denom) || state->matching;
return 0; return 0;
} }

View file

@ -128,7 +128,6 @@ struct state {
bool opened; bool opened;
snd_pcm_t *hndl; snd_pcm_t *hndl;
int pcm_card;
bool have_format; bool have_format;
struct spa_audio_info current_format; struct spa_audio_info current_format;
@ -142,6 +141,7 @@ struct state {
struct channel_map default_pos; struct channel_map default_pos;
unsigned int disable_mmap; unsigned int disable_mmap;
unsigned int disable_batch; unsigned int disable_batch;
char clock_name[64];
snd_pcm_uframes_t buffer_frames; snd_pcm_uframes_t buffer_frames;
snd_pcm_uframes_t period_frames; snd_pcm_uframes_t period_frames;