mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
alsa: implement enum_format
This commit is contained in:
parent
698bddfbb6
commit
4bdbb58276
4 changed files with 114 additions and 96 deletions
|
|
@ -48,18 +48,6 @@ update_state (SpaALSASink *this, SpaNodeState state)
|
||||||
this->node.state = state;
|
this->node.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PROP(f,key,type,...) \
|
|
||||||
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
|
|
||||||
#define PROP_MM(f,key,type,...) \
|
|
||||||
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
|
||||||
#define PROP_U_MM(f,key,type,...) \
|
|
||||||
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
|
||||||
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
|
||||||
#define PROP_U_EN(f,key,type,n,...) \
|
|
||||||
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
|
||||||
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
|
|
||||||
|
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_alsa_sink_node_get_props (SpaNode *node,
|
spa_alsa_sink_node_get_props (SpaNode *node,
|
||||||
SpaProps **props)
|
SpaProps **props)
|
||||||
|
|
@ -268,11 +256,6 @@ spa_alsa_sink_node_port_enum_formats (SpaNode *node,
|
||||||
uint32_t index)
|
uint32_t index)
|
||||||
{
|
{
|
||||||
SpaALSASink *this;
|
SpaALSASink *this;
|
||||||
SpaResult res;
|
|
||||||
SpaFormat *fmt;
|
|
||||||
uint8_t buffer[1024];
|
|
||||||
SpaPODBuilder b = { NULL, };
|
|
||||||
SpaPODFrame f[2];
|
|
||||||
|
|
||||||
spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
||||||
spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
||||||
|
|
@ -281,37 +264,7 @@ spa_alsa_sink_node_port_enum_formats (SpaNode *node,
|
||||||
|
|
||||||
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
||||||
|
|
||||||
next:
|
return spa_alsa_enum_format (this, format, filter, index);
|
||||||
spa_pod_builder_init (&b, buffer, sizeof (buffer));
|
|
||||||
|
|
||||||
switch (index++) {
|
|
||||||
case 0:
|
|
||||||
spa_pod_builder_format (&b, &f[0], this->type.format,
|
|
||||||
this->type.media_type.audio, this->type.media_subtype.raw,
|
|
||||||
PROP_U_EN (&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, 3, this->type.audio_format.S16,
|
|
||||||
this->type.audio_format.S16,
|
|
||||||
this->type.audio_format.S32),
|
|
||||||
PROP_U_MM (&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX),
|
|
||||||
PROP_U_MM (&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
spa_pod_builder_format (&b, &f[0], this->type.format,
|
|
||||||
this->type.media_type.audio, this->type.media_subtype_audio.aac,
|
|
||||||
SPA_POD_TYPE_NONE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return SPA_RESULT_ENUM_END;
|
|
||||||
}
|
|
||||||
fmt = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaFormat);
|
|
||||||
|
|
||||||
spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer));
|
|
||||||
|
|
||||||
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK)
|
|
||||||
goto next;
|
|
||||||
|
|
||||||
*format = SPA_POD_BUILDER_DEREF (&b, 0, SpaFormat);
|
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
|
|
|
||||||
|
|
@ -48,19 +48,6 @@ reset_alsa_props (SpaALSAProps *props)
|
||||||
props->min_latency = default_min_latency;
|
props->min_latency = default_min_latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PROP(f,key,type,...) \
|
|
||||||
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
|
|
||||||
#define PROP_MM(f,key,type,...) \
|
|
||||||
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
|
||||||
#define PROP_U_MM(f,key,type,...) \
|
|
||||||
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
|
||||||
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
|
||||||
#define PROP_EN(f,key,type,n,...) \
|
|
||||||
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
|
|
||||||
#define PROP_U_EN(f,key,type,n,...) \
|
|
||||||
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
|
||||||
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
|
|
||||||
|
|
||||||
static SpaResult
|
static SpaResult
|
||||||
spa_alsa_source_node_get_props (SpaNode *node,
|
spa_alsa_source_node_get_props (SpaNode *node,
|
||||||
SpaProps **props)
|
SpaProps **props)
|
||||||
|
|
@ -305,11 +292,6 @@ spa_alsa_source_node_port_enum_formats (SpaNode *node,
|
||||||
uint32_t index)
|
uint32_t index)
|
||||||
{
|
{
|
||||||
SpaALSASource *this;
|
SpaALSASource *this;
|
||||||
SpaResult res;
|
|
||||||
SpaFormat *fmt;
|
|
||||||
uint8_t buffer[1024];
|
|
||||||
SpaPODBuilder b = { NULL, };
|
|
||||||
SpaPODFrame f[2];
|
|
||||||
|
|
||||||
spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
||||||
spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
||||||
|
|
@ -318,36 +300,7 @@ spa_alsa_source_node_port_enum_formats (SpaNode *node,
|
||||||
|
|
||||||
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
||||||
|
|
||||||
next:
|
return spa_alsa_enum_format (this, format, filter, index);
|
||||||
spa_pod_builder_init (&b, buffer, sizeof (buffer));
|
|
||||||
|
|
||||||
switch (index++) {
|
|
||||||
case 0:
|
|
||||||
spa_pod_builder_format (&b, &f[0], this->type.format,
|
|
||||||
this->type.media_type.audio, this->type.media_subtype.raw,
|
|
||||||
PROP_U_EN (&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, 3, this->type.audio_format.S16,
|
|
||||||
this->type.audio_format.S16,
|
|
||||||
this->type.audio_format.S32),
|
|
||||||
PROP_U_MM (&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX),
|
|
||||||
PROP_U_MM (&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
spa_pod_builder_format (&b, &f[0], this->type.format,
|
|
||||||
this->type.media_type.audio, this->type.media_subtype_audio.aac,
|
|
||||||
SPA_POD_TYPE_NONE);
|
|
||||||
default:
|
|
||||||
return SPA_RESULT_ENUM_END;
|
|
||||||
}
|
|
||||||
fmt = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaFormat);
|
|
||||||
|
|
||||||
spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer));
|
|
||||||
|
|
||||||
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK)
|
|
||||||
goto next;
|
|
||||||
|
|
||||||
*format = SPA_MEMBER (this->format_buffer, 0, SpaFormat);
|
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,98 @@ spa_alsa_format_to_alsa (Type *map, uint32_t format)
|
||||||
return SND_PCM_FORMAT_UNKNOWN;
|
return SND_PCM_FORMAT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpaResult
|
||||||
|
spa_alsa_enum_format (SpaALSAState *state,
|
||||||
|
SpaFormat **format,
|
||||||
|
const SpaFormat *filter,
|
||||||
|
uint32_t index)
|
||||||
|
{
|
||||||
|
snd_pcm_t *hndl;
|
||||||
|
snd_pcm_hw_params_t *params;
|
||||||
|
snd_pcm_format_mask_t *fmask;
|
||||||
|
int err, i, j, dir;
|
||||||
|
unsigned int min, max;
|
||||||
|
SpaPODBuilder b = { NULL, };
|
||||||
|
SpaPODFrame f[2];
|
||||||
|
SpaPODProp *prop;
|
||||||
|
|
||||||
|
if (index == 1)
|
||||||
|
return SPA_RESULT_ENUM_END;
|
||||||
|
|
||||||
|
if ((err = spa_alsa_open (state)) < 0)
|
||||||
|
return SPA_RESULT_ERROR;
|
||||||
|
|
||||||
|
hndl = state->hndl;
|
||||||
|
snd_pcm_hw_params_alloca (¶ms);
|
||||||
|
CHECK (snd_pcm_hw_params_any (hndl, params), "Broken configuration: no configurations available");
|
||||||
|
|
||||||
|
spa_pod_builder_init (&b, state->format_buffer, sizeof (state->format_buffer));
|
||||||
|
|
||||||
|
spa_pod_builder_push_format (&b, &f[0], state->type.format,
|
||||||
|
state->type.media_type.audio,
|
||||||
|
state->type.media_subtype.raw);
|
||||||
|
|
||||||
|
snd_pcm_format_mask_alloca (&fmask);
|
||||||
|
snd_pcm_hw_params_get_format_mask (params, fmask);
|
||||||
|
|
||||||
|
spa_pod_builder_push_prop (&b, &f[1],
|
||||||
|
state->type.format_audio.format,
|
||||||
|
SPA_POD_PROP_RANGE_NONE);
|
||||||
|
prop = SPA_POD_BUILDER_DEREF (&b, f[1].ref, SpaPODProp);
|
||||||
|
|
||||||
|
for (i = 1, j = 0; i < SPA_N_ELEMENTS (format_info); i++) {
|
||||||
|
const FormatInfo *fi = &format_info[i];
|
||||||
|
|
||||||
|
if (snd_pcm_format_mask_test (fmask, fi->format)) {
|
||||||
|
uint32_t f = *SPA_MEMBER (&state->type, fi->format_offset, uint32_t);
|
||||||
|
if (j++ == 0)
|
||||||
|
spa_pod_builder_id (&b, f);
|
||||||
|
spa_pod_builder_id (&b, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j > 1)
|
||||||
|
prop->body.flags |= SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET;
|
||||||
|
spa_pod_builder_pop (&b, &f[1]);
|
||||||
|
|
||||||
|
CHECK (snd_pcm_hw_params_get_rate_min (params, &min, &dir), "get_rate_min");
|
||||||
|
CHECK (snd_pcm_hw_params_get_rate_max (params, &max, &dir), "get_rate_max");
|
||||||
|
|
||||||
|
spa_pod_builder_push_prop (&b, &f[1],
|
||||||
|
state->type.format_audio.rate,
|
||||||
|
SPA_POD_PROP_RANGE_NONE);
|
||||||
|
prop = SPA_POD_BUILDER_DEREF (&b, f[1].ref, SpaPODProp);
|
||||||
|
|
||||||
|
spa_pod_builder_int (&b, SPA_CLAMP (44100, min, max));
|
||||||
|
if (min != max) {
|
||||||
|
spa_pod_builder_int (&b, min);
|
||||||
|
spa_pod_builder_int (&b, max);
|
||||||
|
prop->body.flags |= SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET;
|
||||||
|
}
|
||||||
|
spa_pod_builder_pop (&b, &f[1]);
|
||||||
|
|
||||||
|
CHECK (snd_pcm_hw_params_get_channels_min (params, &min), "get_channels_min");
|
||||||
|
CHECK (snd_pcm_hw_params_get_channels_max (params, &max), "get_channels_max");
|
||||||
|
|
||||||
|
spa_pod_builder_push_prop (&b, &f[1],
|
||||||
|
state->type.format_audio.channels,
|
||||||
|
SPA_POD_PROP_RANGE_NONE);
|
||||||
|
prop = SPA_POD_BUILDER_DEREF (&b, f[1].ref, SpaPODProp);
|
||||||
|
|
||||||
|
spa_pod_builder_int (&b, SPA_CLAMP (2, min, max));
|
||||||
|
if (min != max) {
|
||||||
|
spa_pod_builder_int (&b, min);
|
||||||
|
spa_pod_builder_int (&b, max);
|
||||||
|
prop->body.flags |= SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET;
|
||||||
|
}
|
||||||
|
spa_pod_builder_pop (&b, &f[1]);
|
||||||
|
|
||||||
|
spa_pod_builder_pop (&b, &f[0]);
|
||||||
|
|
||||||
|
*format = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaFormat);
|
||||||
|
|
||||||
|
return SPA_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
spa_alsa_set_format (SpaALSAState *state, SpaAudioInfo *fmt, SpaPortFormatFlags flags)
|
spa_alsa_set_format (SpaALSAState *state, SpaAudioInfo *fmt, SpaPortFormatFlags flags)
|
||||||
{
|
{
|
||||||
|
|
@ -135,6 +227,7 @@ spa_alsa_set_format (SpaALSAState *state, SpaAudioInfo *fmt, SpaPortFormatFlags
|
||||||
/* set the interleaved read/write format */
|
/* set the interleaved read/write format */
|
||||||
CHECK (snd_pcm_hw_params_set_access(hndl, params, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set_access");
|
CHECK (snd_pcm_hw_params_set_access(hndl, params, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set_access");
|
||||||
|
|
||||||
|
|
||||||
/* disable ALSA wakeups, we use a timer */
|
/* disable ALSA wakeups, we use a timer */
|
||||||
if (snd_pcm_hw_params_can_disable_period_wakeup (params))
|
if (snd_pcm_hw_params_can_disable_period_wakeup (params))
|
||||||
CHECK (snd_pcm_hw_params_set_period_wakeup (hndl, params, 0), "set_period_wakeup");
|
CHECK (snd_pcm_hw_params_set_period_wakeup (hndl, params, 0), "set_period_wakeup");
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,25 @@ struct _SpaALSAState {
|
||||||
int64_t last_monotonic;
|
int64_t last_monotonic;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PROP(f,key,type,...) \
|
||||||
|
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
|
||||||
|
#define PROP_MM(f,key,type,...) \
|
||||||
|
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
||||||
|
#define PROP_U_MM(f,key,type,...) \
|
||||||
|
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
||||||
|
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
||||||
|
#define PROP_EN(f,key,type,n,...) \
|
||||||
|
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
|
||||||
|
#define PROP_U_EN(f,key,type,n,...) \
|
||||||
|
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
||||||
|
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
|
||||||
|
|
||||||
|
SpaResult
|
||||||
|
spa_alsa_enum_format (SpaALSAState *state,
|
||||||
|
SpaFormat **format,
|
||||||
|
const SpaFormat *filter,
|
||||||
|
uint32_t index);
|
||||||
|
|
||||||
int spa_alsa_set_format (SpaALSAState *state,
|
int spa_alsa_set_format (SpaALSAState *state,
|
||||||
SpaAudioInfo *info,
|
SpaAudioInfo *info,
|
||||||
SpaPortFormatFlags flags);
|
SpaPortFormatFlags flags);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue