mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
props: improve property introspection
Make a new PropInfo parameter that allows us to iterate all properties. Make some new fields to set labels and names for properties. We will be able to add more things to describe the properties this way. Use the Props param to simply query or set properties. We can now make int enum properties and describe all possible values with labels, we don't need to register types anymore. This then makes it possible to enumerate the v4l2 controls and make them available as control params.
This commit is contained in:
parent
1c19342487
commit
e5e360d5df
13 changed files with 611 additions and 175 deletions
|
|
@ -53,16 +53,11 @@ extern "C" {
|
||||||
/** enumerate output property io areas */
|
/** enumerate output property io areas */
|
||||||
#define SPA_TYPE_PARAM_ID_IO_PROPS__Out SPA_TYPE_PARAM_ID_IO_PROPS_BASE "Out"
|
#define SPA_TYPE_PARAM_ID_IO_PROPS__Out SPA_TYPE_PARAM_ID_IO_PROPS_BASE "Out"
|
||||||
|
|
||||||
/* an io area to exchange properties */
|
/* an io area to exchange properties. Contents can include
|
||||||
|
* SPA_TYPE_PARAM__PropInfo */
|
||||||
#define SPA_TYPE_PARAM_IO__Prop SPA_TYPE_PARAM_IO_BASE "Prop"
|
#define SPA_TYPE_PARAM_IO__Prop SPA_TYPE_PARAM_IO_BASE "Prop"
|
||||||
#define SPA_TYPE_PARAM_IO_PROP_BASE SPA_TYPE_PARAM_IO__Prop ":"
|
#define SPA_TYPE_PARAM_IO_PROP_BASE SPA_TYPE_PARAM_IO__Prop ":"
|
||||||
|
|
||||||
/** associated property if any */
|
|
||||||
#define SPA_TYPE_PARAM_IO_PROP__id SPA_TYPE_PARAM_IO_PROP_BASE "id"
|
|
||||||
/** associated type of property if any */
|
|
||||||
#define SPA_TYPE_PARAM_IO_PROP__type SPA_TYPE_PARAM_IO_PROP_BASE "type"
|
|
||||||
|
|
||||||
|
|
||||||
struct spa_type_param_io {
|
struct spa_type_param_io {
|
||||||
uint32_t id; /**< id to configure the io area */
|
uint32_t id; /**< id to configure the io area */
|
||||||
uint32_t size; /**< size of io area */
|
uint32_t size; /**< size of io area */
|
||||||
|
|
@ -74,8 +69,6 @@ struct spa_type_param_io {
|
||||||
uint32_t idPropsIn; /**< id to enumerate input properties io */
|
uint32_t idPropsIn; /**< id to enumerate input properties io */
|
||||||
uint32_t idPropsOut; /**< id to enumerate output properties io */
|
uint32_t idPropsOut; /**< id to enumerate output properties io */
|
||||||
uint32_t Prop; /**< object type of property area */
|
uint32_t Prop; /**< object type of property area */
|
||||||
uint32_t propId; /**< property id */
|
|
||||||
uint32_t propType; /**< property type */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
@ -93,8 +86,6 @@ spa_type_param_io_map(struct spa_type_map *map,
|
||||||
type->idPropsIn = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID_IO_PROPS__In);
|
type->idPropsIn = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID_IO_PROPS__In);
|
||||||
type->idPropsOut = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID_IO_PROPS__Out);
|
type->idPropsOut = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID_IO_PROPS__Out);
|
||||||
type->Prop = spa_type_map_get_id(map, SPA_TYPE_PARAM_IO__Prop);
|
type->Prop = spa_type_map_get_id(map, SPA_TYPE_PARAM_IO__Prop);
|
||||||
type->propId = spa_type_map_get_id(map, SPA_TYPE_PARAM_IO_PROP__id);
|
|
||||||
type->propType = spa_type_map_get_id(map, SPA_TYPE_PARAM_IO_PROP__type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,23 @@ extern "C" {
|
||||||
#define SPA_TYPE_PARAM_LIST_BASE SPA_TYPE_PARAM__List ":"
|
#define SPA_TYPE_PARAM_LIST_BASE SPA_TYPE_PARAM__List ":"
|
||||||
#define SPA_TYPE_PARAM_LIST__id SPA_TYPE_PARAM_LIST_BASE "id"
|
#define SPA_TYPE_PARAM_LIST__id SPA_TYPE_PARAM_LIST_BASE "id"
|
||||||
|
|
||||||
|
/** Enum Property info */
|
||||||
|
#define SPA_TYPE_PARAM_ID__PropInfo SPA_TYPE_PARAM_ID_BASE "PropInfo"
|
||||||
|
|
||||||
|
#define SPA_TYPE_PARAM__PropInfo SPA_TYPE_PARAM_BASE "PropInfo"
|
||||||
|
#define SPA_TYPE_PARAM_PROP_INFO_BASE SPA_TYPE_PARAM__PropInfo ":"
|
||||||
|
|
||||||
|
/** associated id of the property */
|
||||||
|
#define SPA_TYPE_PARAM_PROP_INFO__id SPA_TYPE_PARAM_PROP_INFO_BASE "id"
|
||||||
|
/** name of property */
|
||||||
|
#define SPA_TYPE_PARAM_PROP_INFO__name SPA_TYPE_PARAM_PROP_INFO_BASE "name"
|
||||||
|
/** associated type and range/enums of property */
|
||||||
|
#define SPA_TYPE_PARAM_PROP_INFO__type SPA_TYPE_PARAM_PROP_INFO_BASE "type"
|
||||||
|
/** associated labels of property if any, this is a struct with pairs of values,
|
||||||
|
* the first one is of the type of the property, the second one is a string with
|
||||||
|
* a user readable label for the value. */
|
||||||
|
#define SPA_TYPE_PARAM_PROP_INFO__labels SPA_TYPE_PARAM_PROP_INFO_BASE "labels"
|
||||||
|
|
||||||
/** Property parameter id, deals with SPA_TYPE__Props */
|
/** Property parameter id, deals with SPA_TYPE__Props */
|
||||||
#define SPA_TYPE_PARAM_ID__Props SPA_TYPE_PARAM_ID_BASE "Props"
|
#define SPA_TYPE_PARAM_ID__Props SPA_TYPE_PARAM_ID_BASE "Props"
|
||||||
|
|
||||||
|
|
@ -73,6 +90,12 @@ struct spa_type_param {
|
||||||
uint32_t idList; /**< id of the list param */
|
uint32_t idList; /**< id of the list param */
|
||||||
uint32_t List; /**< list object type */
|
uint32_t List; /**< list object type */
|
||||||
uint32_t listId; /**< id in the list object */
|
uint32_t listId; /**< id in the list object */
|
||||||
|
uint32_t idPropInfo; /**< id to enumerate property info */
|
||||||
|
uint32_t PropInfo; /**< property info object */
|
||||||
|
uint32_t propId; /**< property id */
|
||||||
|
uint32_t propName; /**< property name */
|
||||||
|
uint32_t propType; /**< property type */
|
||||||
|
uint32_t propLabels; /**< property labels */
|
||||||
uint32_t idProps; /**< id to enumerate properties */
|
uint32_t idProps; /**< id to enumerate properties */
|
||||||
uint32_t idEnumFormat; /**< id to enumerate formats */
|
uint32_t idEnumFormat; /**< id to enumerate formats */
|
||||||
uint32_t idFormat; /**< id to get/set format parameter */
|
uint32_t idFormat; /**< id to get/set format parameter */
|
||||||
|
|
@ -88,6 +111,12 @@ spa_type_param_map(struct spa_type_map *map,
|
||||||
type->idList = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__List);
|
type->idList = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__List);
|
||||||
type->List = spa_type_map_get_id(map, SPA_TYPE_PARAM__List);
|
type->List = spa_type_map_get_id(map, SPA_TYPE_PARAM__List);
|
||||||
type->listId = spa_type_map_get_id(map, SPA_TYPE_PARAM_LIST__id);
|
type->listId = spa_type_map_get_id(map, SPA_TYPE_PARAM_LIST__id);
|
||||||
|
type->idPropInfo = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__PropInfo);
|
||||||
|
type->PropInfo = spa_type_map_get_id(map, SPA_TYPE_PARAM__PropInfo);
|
||||||
|
type->propId = spa_type_map_get_id(map, SPA_TYPE_PARAM_PROP_INFO__id);
|
||||||
|
type->propName = spa_type_map_get_id(map, SPA_TYPE_PARAM_PROP_INFO__name);
|
||||||
|
type->propType = spa_type_map_get_id(map, SPA_TYPE_PARAM_PROP_INFO__type);
|
||||||
|
type->propLabels = spa_type_map_get_id(map, SPA_TYPE_PARAM_PROP_INFO__labels);
|
||||||
type->idProps = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__Props);
|
type->idProps = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__Props);
|
||||||
type->idEnumFormat = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__EnumFormat);
|
type->idEnumFormat = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__EnumFormat);
|
||||||
type->idFormat = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__Format);
|
type->idFormat = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__Format);
|
||||||
|
|
|
||||||
|
|
@ -66,28 +66,76 @@ static int impl_node_enum_params(struct spa_node *node,
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
|
|
||||||
if (id == t->param.idList) {
|
if (id == t->param.idList) {
|
||||||
if (*index > 0)
|
uint32_t list[] = { t->param.idPropInfo,
|
||||||
return 0;
|
t->param.idProps };
|
||||||
|
|
||||||
param = spa_pod_builder_object(&b,
|
if (*index < SPA_N_ELEMENTS(list))
|
||||||
id, t->param.List,
|
param = spa_pod_builder_object(&b, id, t->param.List,
|
||||||
":", t->param.listId, "I", t->param.idProps);
|
":", t->param.listId, "I", list[*index]);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (id == t->param.idPropInfo) {
|
||||||
|
struct props *p = &this->props;
|
||||||
|
|
||||||
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_device,
|
||||||
|
":", t->param.propName, "s", "The ALSA device",
|
||||||
|
":", t->param.propType, "S", p->device, sizeof(p->device));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_device_name,
|
||||||
|
":", t->param.propName, "s", "The ALSA device name",
|
||||||
|
":", t->param.propType, "S-r", p->device_name, sizeof(p->device_name));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_card_name,
|
||||||
|
":", t->param.propName, "s", "The ALSA card name",
|
||||||
|
":", t->param.propType, "S-r", p->card_name, sizeof(p->card_name));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_min_latency,
|
||||||
|
":", t->param.propName, "s", "The minimum latency",
|
||||||
|
":", t->param.propType, "ir", p->min_latency,
|
||||||
|
2, 1, INT32_MAX);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_max_latency,
|
||||||
|
":", t->param.propName, "s", "The maximum latency",
|
||||||
|
":", t->param.propType, "ir", p->max_latency,
|
||||||
|
2, 1, INT32_MAX);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (id == t->param.idProps) {
|
else if (id == t->param.idProps) {
|
||||||
struct props *p = &this->props;
|
struct props *p = &this->props;
|
||||||
|
|
||||||
if (*index > 0)
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->props,
|
||||||
|
":", t->prop_device, "S", p->device, sizeof(p->device),
|
||||||
|
":", t->prop_device_name, "S-r", p->device_name, sizeof(p->device_name),
|
||||||
|
":", t->prop_card_name, "S-r", p->card_name, sizeof(p->card_name),
|
||||||
|
":", t->prop_min_latency, "i", p->min_latency,
|
||||||
|
":", t->prop_max_latency, "i", p->max_latency);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
param = spa_pod_builder_object(&b,
|
|
||||||
id, t->props,
|
|
||||||
":", t->prop_device, "S", p->device, sizeof(p->device),
|
|
||||||
":", t->prop_device_name, "S-r", p->device_name, sizeof(p->device_name),
|
|
||||||
":", t->prop_card_name, "S-r", p->card_name, sizeof(p->card_name),
|
|
||||||
":", t->prop_min_latency, "ir", p->min_latency,
|
|
||||||
2, 1, INT32_MAX,
|
|
||||||
":", t->prop_max_latency, "ir", p->max_latency,
|
|
||||||
2, 1, INT32_MAX);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
@ -120,7 +168,8 @@ static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flag
|
||||||
}
|
}
|
||||||
spa_pod_object_parse(param,
|
spa_pod_object_parse(param,
|
||||||
":", t->prop_device, "?S", p->device, sizeof(p->device),
|
":", t->prop_device, "?S", p->device, sizeof(p->device),
|
||||||
":", t->prop_min_latency, "?i", &p->min_latency, NULL);
|
":", t->prop_min_latency, "?i", &p->min_latency,
|
||||||
|
":", t->prop_max_latency, "?i", &p->max_latency, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ static int impl_node_enum_params(struct spa_node *node,
|
||||||
struct spa_pod *param;
|
struct spa_pod *param;
|
||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
struct spa_pod_builder b = { 0 };
|
struct spa_pod_builder b = { 0 };
|
||||||
|
struct props *p;
|
||||||
|
|
||||||
|
|
||||||
spa_return_val_if_fail(node != NULL, -EINVAL);
|
spa_return_val_if_fail(node != NULL, -EINVAL);
|
||||||
spa_return_val_if_fail(index != NULL, -EINVAL);
|
spa_return_val_if_fail(index != NULL, -EINVAL);
|
||||||
|
|
@ -60,31 +62,69 @@ static int impl_node_enum_params(struct spa_node *node,
|
||||||
|
|
||||||
this = SPA_CONTAINER_OF(node, struct state, node);
|
this = SPA_CONTAINER_OF(node, struct state, node);
|
||||||
t = &this->type;
|
t = &this->type;
|
||||||
|
p = &this->props;
|
||||||
|
|
||||||
next:
|
next:
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
|
|
||||||
if (id == t->param.idList) {
|
if (id == t->param.idList) {
|
||||||
if (*index > 0)
|
uint32_t list[] = { t->param.idPropInfo,
|
||||||
return 0;
|
t->param.idProps };
|
||||||
|
|
||||||
param = spa_pod_builder_object(&b,
|
if (*index < SPA_N_ELEMENTS(list))
|
||||||
id, t->param.List,
|
param = spa_pod_builder_object(&b, id, t->param.List,
|
||||||
":", t->param.listId, "I", t->param.idProps);
|
":", t->param.listId, "I", list[*index]);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (id == t->param.idPropInfo) {
|
||||||
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_device,
|
||||||
|
":", t->param.propName, "s", "The ALSA device",
|
||||||
|
":", t->param.propType, "S", p->device, sizeof(p->device));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_device_name,
|
||||||
|
":", t->param.propName, "s", "The ALSA device name",
|
||||||
|
":", t->param.propType, "S-r", p->device_name, sizeof(p->device_name));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_card_name,
|
||||||
|
":", t->param.propName, "s", "The ALSA card name",
|
||||||
|
":", t->param.propType, "S-r", p->card_name, sizeof(p->card_name));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_min_latency,
|
||||||
|
":", t->param.propName, "s", "The minimum latency",
|
||||||
|
":", t->param.propType, "ir", p->min_latency,
|
||||||
|
2, 1, INT32_MAX);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (id == t->param.idProps) {
|
else if (id == t->param.idProps) {
|
||||||
struct props *p = &this->props;
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
if (*index > 0)
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->props,
|
||||||
|
":", t->prop_device, "S", p->device, sizeof(p->device),
|
||||||
|
":", t->prop_device_name, "S-r", p->device_name, sizeof(p->device_name),
|
||||||
|
":", t->prop_card_name, "S-r", p->card_name, sizeof(p->card_name),
|
||||||
|
":", t->prop_min_latency, "i", p->min_latency);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
param = spa_pod_builder_object(&b,
|
|
||||||
id, t->props,
|
|
||||||
":", t->prop_device, "S", p->device, sizeof(p->device),
|
|
||||||
":", t->prop_device_name, "S-r", p->device_name, sizeof(p->device_name),
|
|
||||||
":", t->prop_card_name, "S-r", p->card_name, sizeof(p->card_name),
|
|
||||||
":", t->prop_min_latency, "ir", p->min_latency,
|
|
||||||
2, 1, INT32_MAX);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
|
||||||
|
|
@ -534,16 +534,16 @@ impl_node_port_enum_params(struct spa_node *node,
|
||||||
id, t->param_io.Prop,
|
id, t->param_io.Prop,
|
||||||
":", t->param_io.id, "I", t->io_prop_volume,
|
":", t->param_io.id, "I", t->io_prop_volume,
|
||||||
":", t->param_io.size, "i", sizeof(struct spa_pod_double),
|
":", t->param_io.size, "i", sizeof(struct spa_pod_double),
|
||||||
":", t->param_io.propId, "I", t->prop_volume,
|
":", t->param.propId, "I", t->prop_volume,
|
||||||
":", t->param_io.propType, "dru", p->volume, 2, 0.0, 10.0);
|
":", t->param.propType, "dru", p->volume, 2, 0.0, 10.0);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
param = spa_pod_builder_object(&b,
|
param = spa_pod_builder_object(&b,
|
||||||
id, t->param_io.Prop,
|
id, t->param_io.Prop,
|
||||||
":", t->param_io.id, "I", t->io_prop_mute,
|
":", t->param_io.id, "I", t->io_prop_mute,
|
||||||
":", t->param_io.size, "i", sizeof(struct spa_pod_bool),
|
":", t->param_io.size, "i", sizeof(struct spa_pod_bool),
|
||||||
":", t->param_io.propId, "I", t->prop_mute,
|
":", t->param.propId, "I", t->prop_mute,
|
||||||
":", t->param_io.propType, "b", p->mute);
|
":", t->param.propType, "b", p->mute);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,6 @@ struct type {
|
||||||
uint32_t io_prop_wave;
|
uint32_t io_prop_wave;
|
||||||
uint32_t io_prop_freq;
|
uint32_t io_prop_freq;
|
||||||
uint32_t io_prop_volume;
|
uint32_t io_prop_volume;
|
||||||
uint32_t wave_sine;
|
|
||||||
uint32_t wave_square;
|
|
||||||
struct spa_type_io io;
|
struct spa_type_io io;
|
||||||
struct spa_type_param param;
|
struct spa_type_param param;
|
||||||
struct spa_type_meta meta;
|
struct spa_type_meta meta;
|
||||||
|
|
@ -86,8 +84,6 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
|
||||||
type->io_prop_wave = spa_type_map_get_id(map, SPA_TYPE_IO_PROP_BASE "waveType");
|
type->io_prop_wave = spa_type_map_get_id(map, SPA_TYPE_IO_PROP_BASE "waveType");
|
||||||
type->io_prop_freq = spa_type_map_get_id(map, SPA_TYPE_IO_PROP_BASE "frequency");
|
type->io_prop_freq = spa_type_map_get_id(map, SPA_TYPE_IO_PROP_BASE "frequency");
|
||||||
type->io_prop_volume = spa_type_map_get_id(map, SPA_TYPE_IO_PROP_BASE "volume");
|
type->io_prop_volume = spa_type_map_get_id(map, SPA_TYPE_IO_PROP_BASE "volume");
|
||||||
type->wave_sine = spa_type_map_get_id(map, SPA_TYPE_PROPS__waveType ":sine");
|
|
||||||
type->wave_square = spa_type_map_get_id(map, SPA_TYPE_PROPS__waveType ":square");
|
|
||||||
spa_type_io_map(map, &type->io);
|
spa_type_io_map(map, &type->io);
|
||||||
spa_type_param_map(map, &type->param);
|
spa_type_param_map(map, &type->param);
|
||||||
spa_type_meta_map(map, &type->meta);
|
spa_type_meta_map(map, &type->meta);
|
||||||
|
|
@ -103,6 +99,16 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
|
||||||
spa_type_param_io_map(map, &type->param_io);
|
spa_type_param_io_map(map, &type->param_io);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum wave_type {
|
||||||
|
WAVE_SINE,
|
||||||
|
WAVE_SQUARE,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFAULT_LIVE false
|
||||||
|
#define DEFAULT_WAVE WAVE_SINE
|
||||||
|
#define DEFAULT_FREQ 440.0
|
||||||
|
#define DEFAULT_VOLUME 1.0
|
||||||
|
|
||||||
struct props {
|
struct props {
|
||||||
bool live;
|
bool live;
|
||||||
uint32_t wave;
|
uint32_t wave;
|
||||||
|
|
@ -110,6 +116,14 @@ struct props {
|
||||||
double volume;
|
double volume;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void reset_props(struct props *props)
|
||||||
|
{
|
||||||
|
props->live = DEFAULT_LIVE;
|
||||||
|
props->wave = DEFAULT_WAVE;
|
||||||
|
props->freq = DEFAULT_FREQ;
|
||||||
|
props->volume = DEFAULT_VOLUME;
|
||||||
|
}
|
||||||
|
|
||||||
#define MAX_BUFFERS 16
|
#define MAX_BUFFERS 16
|
||||||
#define MAX_PORTS 1
|
#define MAX_PORTS 1
|
||||||
|
|
||||||
|
|
@ -170,19 +184,6 @@ struct impl {
|
||||||
|
|
||||||
#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS)
|
#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS)
|
||||||
|
|
||||||
#define DEFAULT_LIVE false
|
|
||||||
#define DEFAULT_WAVE wave_sine
|
|
||||||
#define DEFAULT_FREQ 440.0
|
|
||||||
#define DEFAULT_VOLUME 1.0
|
|
||||||
|
|
||||||
static void reset_props(struct impl *this, struct props *props)
|
|
||||||
{
|
|
||||||
props->live = DEFAULT_LIVE;
|
|
||||||
props->wave = this->type.DEFAULT_WAVE;
|
|
||||||
props->freq = DEFAULT_FREQ;
|
|
||||||
props->volume = DEFAULT_VOLUME;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int impl_node_enum_params(struct spa_node *node,
|
static int impl_node_enum_params(struct spa_node *node,
|
||||||
uint32_t id, uint32_t *index,
|
uint32_t id, uint32_t *index,
|
||||||
const struct spa_pod *filter,
|
const struct spa_pod *filter,
|
||||||
|
|
@ -206,29 +207,71 @@ static int impl_node_enum_params(struct spa_node *node,
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
|
|
||||||
if (id == t->param.idList) {
|
if (id == t->param.idList) {
|
||||||
if (*index > 0)
|
uint32_t list[] = { t->param.idPropInfo,
|
||||||
return 0;
|
t->param.idProps };
|
||||||
|
|
||||||
param = spa_pod_builder_object(&b,
|
if (*index < SPA_N_ELEMENTS(list))
|
||||||
id, t->param.List,
|
param = spa_pod_builder_object(&b, id, t->param.List,
|
||||||
":", t->param.listId, "I", t->param.idProps);
|
":", t->param.listId, "I", list[*index]);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (id == t->param.idPropInfo) {
|
||||||
|
struct props *p = &this->props;
|
||||||
|
|
||||||
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_live,
|
||||||
|
":", t->param.propName, "s", "Configure live mode of the source",
|
||||||
|
":", t->param.propType, "b", p->live);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_wave,
|
||||||
|
":", t->param.propName, "s", "Select the waveform",
|
||||||
|
":", t->param.propType, "i", p->wave,
|
||||||
|
":", t->param.propLabels, "[-i",
|
||||||
|
"i", WAVE_SINE, "s", "Sine wave",
|
||||||
|
"i", WAVE_SQUARE, "s", "Square wave", "]");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_freq,
|
||||||
|
":", t->param.propName, "s", "Select the frequency",
|
||||||
|
":", t->param.propType, "dr", p->freq,
|
||||||
|
2, 0.0, 50000000.0);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_volume,
|
||||||
|
":", t->param.propName, "s", "Select the volume",
|
||||||
|
":", t->param.propType, "dr", p->volume,
|
||||||
|
2, 0.0, 10.0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (id == t->param.idProps) {
|
else if (id == t->param.idProps) {
|
||||||
struct props *p = &this->props;
|
struct props *p = &this->props;
|
||||||
|
|
||||||
if (*index > 0)
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->props,
|
||||||
|
":", t->prop_live, "b", p->live,
|
||||||
|
":", t->prop_wave, "i", p->wave,
|
||||||
|
":", t->prop_freq, "d", p->freq,
|
||||||
|
":", t->prop_volume, "d", p->volume);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
param = spa_pod_builder_object(&b,
|
|
||||||
id, t->props,
|
|
||||||
":", t->prop_live, "b", p->live,
|
|
||||||
":", t->prop_wave, "Ie", p->wave,
|
|
||||||
2, t->wave_sine,
|
|
||||||
t->wave_square,
|
|
||||||
":", t->prop_freq, "dr", p->freq,
|
|
||||||
2, 0.0, 50000000.0,
|
|
||||||
":", t->prop_volume, "dr", p->volume,
|
|
||||||
2, 0.0, 10.0);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
@ -256,12 +299,12 @@ static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flag
|
||||||
struct props *p = &this->props;
|
struct props *p = &this->props;
|
||||||
|
|
||||||
if (param == NULL) {
|
if (param == NULL) {
|
||||||
reset_props(this, p);
|
reset_props(p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spa_pod_object_parse(param,
|
spa_pod_object_parse(param,
|
||||||
":",t->prop_live, "?b", &p->live,
|
":",t->prop_live, "?b", &p->live,
|
||||||
":",t->prop_wave, "?I", &p->wave,
|
":",t->prop_wave, "?i", &p->wave,
|
||||||
":",t->prop_freq, "?d", &p->freq,
|
":",t->prop_freq, "?d", &p->freq,
|
||||||
":",t->prop_volume, "?d", &p->volume,
|
":",t->prop_volume, "?d", &p->volume,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
@ -695,26 +738,27 @@ impl_node_port_enum_params(struct spa_node *node,
|
||||||
id, t->param_io.Prop,
|
id, t->param_io.Prop,
|
||||||
":", t->param_io.id, "I", t->io_prop_wave,
|
":", t->param_io.id, "I", t->io_prop_wave,
|
||||||
":", t->param_io.size, "i", sizeof(struct spa_pod_id),
|
":", t->param_io.size, "i", sizeof(struct spa_pod_id),
|
||||||
":", t->param_io.propId, "I", t->prop_wave,
|
":", t->param.propId, "I", t->prop_wave,
|
||||||
":", t->param_io.propType, "Ie", p->wave,
|
":", t->param.propType, "i", p->wave,
|
||||||
2, t->wave_sine,
|
":", t->param.propLabels, "[-i",
|
||||||
t->wave_square);
|
"i", WAVE_SINE, "s", "Sine wave",
|
||||||
|
"i", WAVE_SQUARE, "s", "Square wave", "]");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
param = spa_pod_builder_object(&b,
|
param = spa_pod_builder_object(&b,
|
||||||
id, t->param_io.Prop,
|
id, t->param_io.Prop,
|
||||||
":", t->param_io.id, "I", t->io_prop_freq,
|
":", t->param_io.id, "I", t->io_prop_freq,
|
||||||
":", t->param_io.size, "i", sizeof(struct spa_pod_double),
|
":", t->param_io.size, "i", sizeof(struct spa_pod_double),
|
||||||
":", t->param_io.propId, "I", t->prop_freq,
|
":", t->param.propId, "I", t->prop_freq,
|
||||||
":", t->param_io.propType, "dr", p->freq, 2, 0.0, 50000000.0);
|
":", t->param.propType, "dr", p->freq, 2, 0.0, 50000000.0);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
param = spa_pod_builder_object(&b,
|
param = spa_pod_builder_object(&b,
|
||||||
id, t->param_io.Prop,
|
id, t->param_io.Prop,
|
||||||
":", t->param_io.id, "I", t->io_prop_volume,
|
":", t->param_io.id, "I", t->io_prop_volume,
|
||||||
":", t->param_io.size, "i", sizeof(struct spa_pod_double),
|
":", t->param_io.size, "i", sizeof(struct spa_pod_double),
|
||||||
":", t->param_io.propId, "I", t->prop_volume,
|
":", t->param.propId, "I", t->prop_volume,
|
||||||
":", t->param_io.propType, "dr", p->volume, 2, 0.0, 10.0);
|
":", t->param.propType, "dr", p->volume, 2, 0.0, 10.0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1141,7 +1185,7 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
|
|
||||||
this->node = impl_node;
|
this->node = impl_node;
|
||||||
this->clock = impl_clock;
|
this->clock = impl_clock;
|
||||||
reset_props(this, &this->props);
|
reset_props(&this->props);
|
||||||
|
|
||||||
this->io_wave = &this->props.wave;
|
this->io_wave = &this->props.wave;
|
||||||
this->io_freq = &this->props.freq;
|
this->io_freq = &this->props.freq;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#include <spa/param/video/format-utils.h>
|
#include <spa/param/video/format-utils.h>
|
||||||
#include <spa/param/buffers.h>
|
#include <spa/param/buffers.h>
|
||||||
#include <spa/param/meta.h>
|
#include <spa/param/meta.h>
|
||||||
|
#include <spa/param/io.h>
|
||||||
|
|
||||||
#include <lib/debug.h>
|
#include <lib/debug.h>
|
||||||
#include <lib/pod.h>
|
#include <lib/pod.h>
|
||||||
|
|
@ -82,6 +83,7 @@ struct type {
|
||||||
struct spa_type_command_node command_node;
|
struct spa_type_command_node command_node;
|
||||||
struct spa_type_param_buffers param_buffers;
|
struct spa_type_param_buffers param_buffers;
|
||||||
struct spa_type_param_meta param_meta;
|
struct spa_type_param_meta param_meta;
|
||||||
|
struct spa_type_param_io param_io;
|
||||||
struct spa_type_meta meta;
|
struct spa_type_meta meta;
|
||||||
struct spa_type_data data;
|
struct spa_type_data data;
|
||||||
};
|
};
|
||||||
|
|
@ -95,8 +97,8 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
|
||||||
type->prop_device = spa_type_map_get_id(map, SPA_TYPE_PROPS__device);
|
type->prop_device = spa_type_map_get_id(map, SPA_TYPE_PROPS__device);
|
||||||
type->prop_device_name = spa_type_map_get_id(map, SPA_TYPE_PROPS__deviceName);
|
type->prop_device_name = spa_type_map_get_id(map, SPA_TYPE_PROPS__deviceName);
|
||||||
type->prop_device_fd = spa_type_map_get_id(map, SPA_TYPE_PROPS__deviceFd);
|
type->prop_device_fd = spa_type_map_get_id(map, SPA_TYPE_PROPS__deviceFd);
|
||||||
spa_type_io_map(map, &type->io);
|
spa_type_meta_map(map, &type->meta);
|
||||||
spa_type_param_map(map, &type->param);
|
spa_type_data_map(map, &type->data);
|
||||||
spa_type_media_type_map(map, &type->media_type);
|
spa_type_media_type_map(map, &type->media_type);
|
||||||
spa_type_media_subtype_map(map, &type->media_subtype);
|
spa_type_media_subtype_map(map, &type->media_subtype);
|
||||||
spa_type_media_subtype_video_map(map, &type->media_subtype_video);
|
spa_type_media_subtype_video_map(map, &type->media_subtype_video);
|
||||||
|
|
@ -104,10 +106,11 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
|
||||||
spa_type_video_format_map(map, &type->video_format);
|
spa_type_video_format_map(map, &type->video_format);
|
||||||
spa_type_event_node_map(map, &type->event_node);
|
spa_type_event_node_map(map, &type->event_node);
|
||||||
spa_type_command_node_map(map, &type->command_node);
|
spa_type_command_node_map(map, &type->command_node);
|
||||||
|
spa_type_param_map(map, &type->param);
|
||||||
spa_type_param_buffers_map(map, &type->param_buffers);
|
spa_type_param_buffers_map(map, &type->param_buffers);
|
||||||
spa_type_param_meta_map(map, &type->param_meta);
|
spa_type_param_meta_map(map, &type->param_meta);
|
||||||
spa_type_meta_map(map, &type->meta);
|
spa_type_io_map(map, &type->io);
|
||||||
spa_type_data_map(map, &type->data);
|
spa_type_param_io_map(map, &type->param_io);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct port {
|
struct port {
|
||||||
|
|
@ -129,6 +132,7 @@ struct port {
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
bool opened;
|
bool opened;
|
||||||
|
bool have_query_ext_ctrl;
|
||||||
struct v4l2_capability cap;
|
struct v4l2_capability cap;
|
||||||
struct v4l2_format fmt;
|
struct v4l2_format fmt;
|
||||||
enum v4l2_buf_type type;
|
enum v4l2_buf_type type;
|
||||||
|
|
@ -194,23 +198,58 @@ static int impl_node_enum_params(struct spa_node *node,
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
|
|
||||||
if (id == t->param.idList) {
|
if (id == t->param.idList) {
|
||||||
if (*index > 0)
|
uint32_t list[] = { t->param.idPropInfo,
|
||||||
return 0;
|
t->param.idProps };
|
||||||
|
|
||||||
param = spa_pod_builder_object(&b,
|
if (*index < SPA_N_ELEMENTS(list))
|
||||||
id, t->param.List,
|
param = spa_pod_builder_object(&b, id, t->param.List,
|
||||||
":", t->param.listId, "I", t->param.idProps);
|
":", t->param.listId, "I", list[*index]);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (id == t->param.idPropInfo) {
|
||||||
|
struct props *p = &this->props;
|
||||||
|
|
||||||
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_device,
|
||||||
|
":", t->param.propName, "s", "The V4L2 device",
|
||||||
|
":", t->param.propType, "S", p->device, sizeof(p->device));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_device_name,
|
||||||
|
":", t->param.propName, "s", "The V4L2 device name",
|
||||||
|
":", t->param.propType, "S-r", p->device_name, sizeof(p->device_name));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_device_fd,
|
||||||
|
":", t->param.propName, "s", "The V4L2 fd",
|
||||||
|
":", t->param.propType, "i-r", p->device_fd);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (id == t->param.idProps) {
|
else if (id == t->param.idProps) {
|
||||||
struct props *p = &this->props;
|
struct props *p = &this->props;
|
||||||
|
|
||||||
if (*index > 0)
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->props,
|
||||||
|
":", t->prop_device, "S", p->device, sizeof(p->device),
|
||||||
|
":", t->prop_device_name, "S-r", p->device_name, sizeof(p->device_name),
|
||||||
|
":", t->prop_device_fd, "i-r", p->device_fd);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
param = spa_pod_builder_object(&b, t->param.idProps, t->props,
|
|
||||||
":", t->prop_device, "S", p->device, sizeof(p->device),
|
|
||||||
":", t->prop_device_name, "S-r", p->device_name, sizeof(p->device_name),
|
|
||||||
":", t->prop_device_fd, "i-r", p->device_fd);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
@ -547,7 +586,8 @@ static int impl_node_port_enum_params(struct spa_node *node,
|
||||||
uint32_t list[] = { t->param.idEnumFormat,
|
uint32_t list[] = { t->param.idEnumFormat,
|
||||||
t->param.idFormat,
|
t->param.idFormat,
|
||||||
t->param.idBuffers,
|
t->param.idBuffers,
|
||||||
t->param.idMeta };
|
t->param.idMeta,
|
||||||
|
t->param_io.idPropsIn };
|
||||||
|
|
||||||
if (*index < SPA_N_ELEMENTS(list))
|
if (*index < SPA_N_ELEMENTS(list))
|
||||||
param = spa_pod_builder_object(&b, id, t->param.List,
|
param = spa_pod_builder_object(&b, id, t->param.List,
|
||||||
|
|
@ -588,6 +628,9 @@ static int impl_node_port_enum_params(struct spa_node *node,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (id == t->param_io.idPropsIn) {
|
||||||
|
return spa_v4l2_enum_controls(this, index, filter, result, builder);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
|
|
@ -1010,6 +1053,7 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_LIVE;
|
this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_LIVE;
|
||||||
|
|
||||||
this->out_ports[0].export_buf = true;
|
this->out_ports[0].export_buf = true;
|
||||||
|
this->out_ports[0].have_query_ext_ctrl = true;
|
||||||
|
|
||||||
if (info && (str = spa_dict_lookup(info, "device.path"))) {
|
if (info && (str = spa_dict_lookup(info, "device.path"))) {
|
||||||
strncpy(this->props.device, str, 63);
|
strncpy(this->props.device, str, 63);
|
||||||
|
|
|
||||||
|
|
@ -821,7 +821,7 @@ spa_v4l2_enum_format(struct impl *this,
|
||||||
static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, bool try_only)
|
static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format, bool try_only)
|
||||||
{
|
{
|
||||||
struct port *port = &this->out_ports[0];
|
struct port *port = &this->out_ports[0];
|
||||||
int cmd;
|
int res, cmd;
|
||||||
struct v4l2_format reqfmt, fmt;
|
struct v4l2_format reqfmt, fmt;
|
||||||
struct v4l2_streamparm streamparm;
|
struct v4l2_streamparm streamparm;
|
||||||
const struct format_info *info = NULL;
|
const struct format_info *info = NULL;
|
||||||
|
|
@ -858,7 +858,7 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format,
|
||||||
if (info == NULL || size == NULL || framerate == NULL) {
|
if (info == NULL || size == NULL || framerate == NULL) {
|
||||||
spa_log_error(port->log, "v4l2: unknown media type %d %d %d", format->media_type,
|
spa_log_error(port->log, "v4l2: unknown media type %d %d %d", format->media_type,
|
||||||
format->media_subtype, video_format);
|
format->media_subtype, video_format);
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -876,13 +876,14 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format,
|
||||||
|
|
||||||
reqfmt = fmt;
|
reqfmt = fmt;
|
||||||
|
|
||||||
if (spa_v4l2_open(this) < 0)
|
if ((res = spa_v4l2_open(this)) < 0)
|
||||||
return -1;
|
return res;
|
||||||
|
|
||||||
cmd = try_only ? VIDIOC_TRY_FMT : VIDIOC_S_FMT;
|
cmd = try_only ? VIDIOC_TRY_FMT : VIDIOC_S_FMT;
|
||||||
if (xioctl(port->fd, cmd, &fmt) < 0) {
|
if (xioctl(port->fd, cmd, &fmt) < 0) {
|
||||||
|
res = -errno;
|
||||||
perror("VIDIOC_S_FMT");
|
perror("VIDIOC_S_FMT");
|
||||||
return -1;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* some cheap USB cam's won't accept any change */
|
/* some cheap USB cam's won't accept any change */
|
||||||
|
|
@ -897,7 +898,7 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format,
|
||||||
if (reqfmt.fmt.pix.pixelformat != fmt.fmt.pix.pixelformat ||
|
if (reqfmt.fmt.pix.pixelformat != fmt.fmt.pix.pixelformat ||
|
||||||
reqfmt.fmt.pix.width != fmt.fmt.pix.width ||
|
reqfmt.fmt.pix.width != fmt.fmt.pix.width ||
|
||||||
reqfmt.fmt.pix.height != fmt.fmt.pix.height)
|
reqfmt.fmt.pix.height != fmt.fmt.pix.height)
|
||||||
return -1;
|
return -EINVAL;
|
||||||
|
|
||||||
if (try_only)
|
if (try_only)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -915,6 +916,185 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int query_ext_ctrl_ioctl(struct port *port, struct v4l2_query_ext_ctrl *qctrl)
|
||||||
|
{
|
||||||
|
struct v4l2_queryctrl qc;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (port->have_query_ext_ctrl) {
|
||||||
|
res = ioctl(port->fd, VIDIOC_QUERY_EXT_CTRL, qctrl);
|
||||||
|
if (errno != ENOTTY)
|
||||||
|
return res;
|
||||||
|
port->have_query_ext_ctrl = false;
|
||||||
|
}
|
||||||
|
qc.id = qctrl->id;
|
||||||
|
res = ioctl(port->fd, VIDIOC_QUERYCTRL, &qc);
|
||||||
|
if (res == 0) {
|
||||||
|
qctrl->type = qc.type;
|
||||||
|
memcpy(qctrl->name, qc.name, sizeof(qctrl->name));
|
||||||
|
qctrl->minimum = qc.minimum;
|
||||||
|
if (qc.type == V4L2_CTRL_TYPE_BITMASK) {
|
||||||
|
qctrl->maximum = (__u32)qc.maximum;
|
||||||
|
qctrl->default_value = (__u32)qc.default_value;
|
||||||
|
} else {
|
||||||
|
qctrl->maximum = qc.maximum;
|
||||||
|
qctrl->default_value = qc.default_value;
|
||||||
|
}
|
||||||
|
qctrl->step = qc.step;
|
||||||
|
qctrl->flags = qc.flags;
|
||||||
|
qctrl->elems = 1;
|
||||||
|
qctrl->nr_of_dims = 0;
|
||||||
|
memset(qctrl->dims, 0, sizeof(qctrl->dims));
|
||||||
|
switch (qctrl->type) {
|
||||||
|
case V4L2_CTRL_TYPE_INTEGER64:
|
||||||
|
qctrl->elem_size = sizeof(__s64);
|
||||||
|
break;
|
||||||
|
case V4L2_CTRL_TYPE_STRING:
|
||||||
|
qctrl->elem_size = qc.maximum + 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qctrl->elem_size = sizeof(__s32);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memset(qctrl->reserved, 0, sizeof(qctrl->reserved));
|
||||||
|
}
|
||||||
|
qctrl->id = qc.id;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
spa_v4l2_enum_controls(struct impl *this,
|
||||||
|
uint32_t *index,
|
||||||
|
const struct spa_pod *filter,
|
||||||
|
struct spa_pod **result,
|
||||||
|
struct spa_pod_builder *builder)
|
||||||
|
{
|
||||||
|
struct port *port = &this->out_ports[0];
|
||||||
|
struct type *t = &this->type;
|
||||||
|
struct v4l2_query_ext_ctrl queryctrl;
|
||||||
|
struct spa_pod *param;
|
||||||
|
struct spa_pod_builder b = { 0 };
|
||||||
|
uint8_t buffer[1024];
|
||||||
|
int res;
|
||||||
|
const unsigned next_fl = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
|
||||||
|
|
||||||
|
if ((res = spa_v4l2_open(this)) < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
next:
|
||||||
|
spa_zero(queryctrl);
|
||||||
|
|
||||||
|
if (*index == 0)
|
||||||
|
*index |= next_fl;
|
||||||
|
|
||||||
|
queryctrl.id = *index;
|
||||||
|
spa_log_debug(port->log, "test control %08x", queryctrl.id);
|
||||||
|
|
||||||
|
if (query_ext_ctrl_ioctl(port, &queryctrl) != 0) {
|
||||||
|
if (errno == EINVAL) {
|
||||||
|
if (queryctrl.id != next_fl)
|
||||||
|
goto enum_end;
|
||||||
|
|
||||||
|
if (*index & next_fl)
|
||||||
|
*index = V4L2_CID_USER_BASE;
|
||||||
|
else if (*index >= V4L2_CID_USER_BASE && *index < V4L2_CID_LASTP1)
|
||||||
|
(*index)++;
|
||||||
|
else if (*index >= V4L2_CID_LASTP1)
|
||||||
|
*index = V4L2_CID_PRIVATE_BASE;
|
||||||
|
else
|
||||||
|
goto enum_end;
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
res = -errno;
|
||||||
|
perror("VIDIOC_QUERYCTRL");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (*index & next_fl)
|
||||||
|
(*index) = queryctrl.id | next_fl;
|
||||||
|
else
|
||||||
|
(*index)++;
|
||||||
|
|
||||||
|
if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
spa_log_debug(port->log, "Control %s", queryctrl.name);
|
||||||
|
|
||||||
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
switch (queryctrl.type) {
|
||||||
|
case V4L2_CTRL_TYPE_INTEGER:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
t->param_io.idPropsIn, t->param_io.Prop,
|
||||||
|
":", t->param_io.size, "i", sizeof(struct spa_pod_int),
|
||||||
|
":", t->param.propType, "isu", queryctrl.default_value,
|
||||||
|
3, queryctrl.minimum,
|
||||||
|
queryctrl.maximum,
|
||||||
|
queryctrl.step,
|
||||||
|
":", t->param.propName, "s", queryctrl.name);
|
||||||
|
break;
|
||||||
|
case V4L2_CTRL_TYPE_BOOLEAN:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
t->param_io.idPropsIn, t->param_io.Prop,
|
||||||
|
":", t->param_io.size, "i", sizeof(struct spa_pod_bool),
|
||||||
|
":", t->param.propType, "b-u", queryctrl.default_value,
|
||||||
|
":", t->param.propName, "s", queryctrl.name);
|
||||||
|
break;
|
||||||
|
case V4L2_CTRL_TYPE_MENU:
|
||||||
|
{
|
||||||
|
struct v4l2_querymenu querymenu;
|
||||||
|
|
||||||
|
spa_pod_builder_push_object(&b, t->param_io.idPropsIn, t->param_io.Prop);
|
||||||
|
spa_pod_builder_add(&b,
|
||||||
|
":", t->param_io.size, "i", sizeof(struct spa_pod_int),
|
||||||
|
":", t->param.propName, "s", queryctrl.name,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
spa_pod_builder_push_prop(&b, t->param.propType, SPA_POD_PROP_FLAG_UNSET);
|
||||||
|
spa_pod_builder_int(&b, queryctrl.default_value);
|
||||||
|
spa_pod_builder_pop(&b);
|
||||||
|
|
||||||
|
spa_zero(querymenu);
|
||||||
|
querymenu.id = queryctrl.id;
|
||||||
|
|
||||||
|
spa_pod_builder_push_prop(&b, t->param.propLabels, 0);
|
||||||
|
spa_pod_builder_push_struct(&b);
|
||||||
|
for (querymenu.index = queryctrl.minimum;
|
||||||
|
querymenu.index <= queryctrl.maximum;
|
||||||
|
querymenu.index++) {
|
||||||
|
if (ioctl(port->fd, VIDIOC_QUERYMENU, &querymenu) == 0) {
|
||||||
|
spa_pod_builder_int(&b, querymenu.index);
|
||||||
|
spa_pod_builder_string(&b, (const char *)querymenu.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spa_pod_builder_pop(&b);
|
||||||
|
spa_pod_builder_pop(&b);
|
||||||
|
param = spa_pod_builder_pop(&b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case V4L2_CTRL_TYPE_INTEGER_MENU:
|
||||||
|
case V4L2_CTRL_TYPE_BITMASK:
|
||||||
|
case V4L2_CTRL_TYPE_BUTTON:
|
||||||
|
case V4L2_CTRL_TYPE_INTEGER64:
|
||||||
|
case V4L2_CTRL_TYPE_STRING:
|
||||||
|
default:
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (spa_pod_filter(builder, result, param, filter) < 0)
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
res = 1;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
spa_v4l2_close(this);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
|
||||||
|
enum_end:
|
||||||
|
res = 0;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
static int mmap_read(struct impl *this)
|
static int mmap_read(struct impl *this)
|
||||||
{
|
{
|
||||||
struct port *port = &this->out_ports[0];
|
struct port *port = &this->out_ports[0];
|
||||||
|
|
|
||||||
|
|
@ -262,20 +262,21 @@ static int draw(struct impl *this, char *data)
|
||||||
{
|
{
|
||||||
DrawingData dd;
|
DrawingData dd;
|
||||||
int res;
|
int res;
|
||||||
uint32_t pattern;
|
|
||||||
|
|
||||||
init_colors();
|
init_colors();
|
||||||
|
|
||||||
if ((res = drawing_data_init(&dd, this, data)) < 0)
|
if ((res = drawing_data_init(&dd, this, data)) < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
pattern = this->props.pattern;
|
switch (this->props.pattern) {
|
||||||
if (pattern == this->type.pattern_smpte_snow)
|
case PATTERN_SMPTE_SNOW:
|
||||||
draw_smpte_snow(&dd);
|
draw_smpte_snow(&dd);
|
||||||
else if (pattern == this->type.pattern_snow)
|
break;
|
||||||
|
case PATTERN_SNOW:
|
||||||
draw_snow(&dd);
|
draw_snow(&dd);
|
||||||
else
|
break;
|
||||||
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,6 @@ struct type {
|
||||||
uint32_t props;
|
uint32_t props;
|
||||||
uint32_t prop_live;
|
uint32_t prop_live;
|
||||||
uint32_t prop_pattern;
|
uint32_t prop_pattern;
|
||||||
uint32_t pattern_smpte_snow;
|
|
||||||
uint32_t pattern_snow;
|
|
||||||
struct spa_type_io io;
|
struct spa_type_io io;
|
||||||
struct spa_type_param param;
|
struct spa_type_param param;
|
||||||
struct spa_type_meta meta;
|
struct spa_type_meta meta;
|
||||||
|
|
@ -74,8 +72,6 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
|
||||||
type->props = spa_type_map_get_id(map, SPA_TYPE__Props);
|
type->props = spa_type_map_get_id(map, SPA_TYPE__Props);
|
||||||
type->prop_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live);
|
type->prop_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live);
|
||||||
type->prop_pattern = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType);
|
type->prop_pattern = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType);
|
||||||
type->pattern_smpte_snow = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType ":smpte-snow");
|
|
||||||
type->pattern_snow = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType ":snow");
|
|
||||||
spa_type_io_map(map, &type->io);
|
spa_type_io_map(map, &type->io);
|
||||||
spa_type_param_map(map, &type->param);
|
spa_type_param_map(map, &type->param);
|
||||||
spa_type_meta_map(map, &type->meta);
|
spa_type_meta_map(map, &type->meta);
|
||||||
|
|
@ -90,11 +86,25 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
|
||||||
spa_type_param_meta_map(map, &type->param_meta);
|
spa_type_param_meta_map(map, &type->param_meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum pattern {
|
||||||
|
PATTERN_SMPTE_SNOW,
|
||||||
|
PATTERN_SNOW,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFAULT_LIVE false
|
||||||
|
#define DEFAULT_PATTERN PATTERN_SMPTE_SNOW
|
||||||
|
|
||||||
struct props {
|
struct props {
|
||||||
bool live;
|
bool live;
|
||||||
uint32_t pattern;
|
uint32_t pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void reset_props(struct props *props)
|
||||||
|
{
|
||||||
|
props->live = DEFAULT_LIVE;
|
||||||
|
props->pattern = DEFAULT_PATTERN;
|
||||||
|
}
|
||||||
|
|
||||||
#define MAX_BUFFERS 16
|
#define MAX_BUFFERS 16
|
||||||
#define MAX_PORTS 1
|
#define MAX_PORTS 1
|
||||||
|
|
||||||
|
|
@ -145,15 +155,6 @@ struct impl {
|
||||||
|
|
||||||
#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS)
|
#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS)
|
||||||
|
|
||||||
#define DEFAULT_LIVE false
|
|
||||||
#define DEFAULT_PATTERN pattern_smpte_snow
|
|
||||||
|
|
||||||
static void reset_props(struct impl *this, struct props *props)
|
|
||||||
{
|
|
||||||
props->live = DEFAULT_LIVE;
|
|
||||||
props->pattern = this->type.DEFAULT_PATTERN;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int impl_node_enum_params(struct spa_node *node,
|
static int impl_node_enum_params(struct spa_node *node,
|
||||||
uint32_t id, uint32_t *index,
|
uint32_t id, uint32_t *index,
|
||||||
const struct spa_pod *filter,
|
const struct spa_pod *filter,
|
||||||
|
|
@ -176,25 +177,53 @@ static int impl_node_enum_params(struct spa_node *node,
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
|
|
||||||
if (id == t->param.idList) {
|
if (id == t->param.idList) {
|
||||||
if (*index > 0)
|
uint32_t list[] = { t->param.idPropInfo,
|
||||||
return 0;
|
t->param.idProps };
|
||||||
|
|
||||||
param = spa_pod_builder_object(&b,
|
if (*index < SPA_N_ELEMENTS(list))
|
||||||
id, t->param.List,
|
param = spa_pod_builder_object(&b, id, t->param.List,
|
||||||
":", t->param.listId, "I", t->param.idProps);
|
":", t->param.listId, "I", list[*index]);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (id == t->param.idPropInfo) {
|
||||||
|
struct props *p = &this->props;
|
||||||
|
|
||||||
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_live,
|
||||||
|
":", t->param.propName, "s", "Configure live mode of the source",
|
||||||
|
":", t->param.propType, "b", p->live);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_pattern,
|
||||||
|
":", t->param.propName, "s", "The pattern",
|
||||||
|
":", t->param.propType, "i", p->pattern,
|
||||||
|
":", t->param.propLabels, "[-i",
|
||||||
|
"i", PATTERN_SMPTE_SNOW, "s", "SMPTE snow",
|
||||||
|
"i", PATTERN_SNOW, "s", "Snow", "]");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (id == t->param.idProps) {
|
else if (id == t->param.idProps) {
|
||||||
struct props *p = &this->props;
|
struct props *p = &this->props;
|
||||||
|
|
||||||
if (*index > 0)
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->props,
|
||||||
|
":", t->prop_live, "b", p->live,
|
||||||
|
":", t->prop_pattern, "i", p->pattern);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
param = spa_pod_builder_object(&b,
|
|
||||||
id, t->props,
|
|
||||||
":", t->prop_live, "b", p->live,
|
|
||||||
":", t->prop_pattern, "Ie", p->pattern,
|
|
||||||
2, t->pattern_smpte_snow,
|
|
||||||
t->pattern_snow);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
@ -221,9 +250,13 @@ static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flag
|
||||||
if (id == t->param.idProps) {
|
if (id == t->param.idProps) {
|
||||||
struct props *p = &this->props;
|
struct props *p = &this->props;
|
||||||
|
|
||||||
|
if (param == NULL) {
|
||||||
|
reset_props(p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
spa_pod_object_parse(param,
|
spa_pod_object_parse(param,
|
||||||
":", t->prop_live, "?b", &p->live,
|
":", t->prop_live, "?b", &p->live,
|
||||||
":", t->prop_pattern, "?I", &p->pattern,
|
":", t->prop_pattern, "?i", &p->pattern,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (p->live)
|
if (p->live)
|
||||||
|
|
@ -993,7 +1026,7 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
|
|
||||||
this->node = impl_node;
|
this->node = impl_node;
|
||||||
this->clock = impl_clock;
|
this->clock = impl_clock;
|
||||||
reset_props(this, &this->props);
|
reset_props(&this->props);
|
||||||
|
|
||||||
spa_list_init(&this->empty);
|
spa_list_init(&this->empty);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,13 +35,22 @@
|
||||||
|
|
||||||
#define NAME "volume"
|
#define NAME "volume"
|
||||||
|
|
||||||
#define MAX_BUFFERS 16
|
#define DEFAULT_VOLUME 1.0
|
||||||
|
#define DEFAULT_MUTE false
|
||||||
|
|
||||||
struct props {
|
struct props {
|
||||||
double volume;
|
double volume;
|
||||||
bool mute;
|
bool mute;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void reset_props(struct props *props)
|
||||||
|
{
|
||||||
|
props->volume = DEFAULT_VOLUME;
|
||||||
|
props->mute = DEFAULT_MUTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_BUFFERS 16
|
||||||
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
struct spa_buffer *outbuf;
|
struct spa_buffer *outbuf;
|
||||||
bool outstanding;
|
bool outstanding;
|
||||||
|
|
@ -136,15 +145,6 @@ struct impl {
|
||||||
#define GET_OUT_PORT(this,p) (&this->out_ports[p])
|
#define GET_OUT_PORT(this,p) (&this->out_ports[p])
|
||||||
#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p))
|
#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p))
|
||||||
|
|
||||||
#define DEFAULT_VOLUME 1.0
|
|
||||||
#define DEFAULT_MUTE false
|
|
||||||
|
|
||||||
static void reset_props(struct props *props)
|
|
||||||
{
|
|
||||||
props->volume = DEFAULT_VOLUME;
|
|
||||||
props->mute = DEFAULT_MUTE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int impl_node_enum_params(struct spa_node *node,
|
static int impl_node_enum_params(struct spa_node *node,
|
||||||
uint32_t id, uint32_t *index,
|
uint32_t id, uint32_t *index,
|
||||||
const struct spa_pod *filter,
|
const struct spa_pod *filter,
|
||||||
|
|
@ -156,6 +156,7 @@ static int impl_node_enum_params(struct spa_node *node,
|
||||||
struct spa_pod_builder b = { 0 };
|
struct spa_pod_builder b = { 0 };
|
||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
struct spa_pod *param;
|
struct spa_pod *param;
|
||||||
|
struct props *p;
|
||||||
|
|
||||||
spa_return_val_if_fail(node != NULL, -EINVAL);
|
spa_return_val_if_fail(node != NULL, -EINVAL);
|
||||||
spa_return_val_if_fail(index != NULL, -EINVAL);
|
spa_return_val_if_fail(index != NULL, -EINVAL);
|
||||||
|
|
@ -163,28 +164,52 @@ static int impl_node_enum_params(struct spa_node *node,
|
||||||
|
|
||||||
this = SPA_CONTAINER_OF(node, struct impl, node);
|
this = SPA_CONTAINER_OF(node, struct impl, node);
|
||||||
t = &this->type;
|
t = &this->type;
|
||||||
|
p = &this->props;
|
||||||
|
|
||||||
next:
|
next:
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
|
|
||||||
if (id == t->param.idList) {
|
if (id == t->param.idList) {
|
||||||
if (*index > 0)
|
uint32_t list[] = { t->param.idPropInfo,
|
||||||
return 0;
|
t->param.idProps };
|
||||||
|
|
||||||
param = spa_pod_builder_object(&b,
|
if (*index < SPA_N_ELEMENTS(list))
|
||||||
id, t->param.List,
|
param = spa_pod_builder_object(&b, id, t->param.List,
|
||||||
":", t->param.listId, "I", t->param.idProps);
|
":", t->param.listId, "I", list[*index]);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (id == t->param.idPropInfo) {
|
||||||
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_volume,
|
||||||
|
":", t->param.propName, "s", "The volume",
|
||||||
|
":", t->param.propType, "dr", p->volume, 2, 0.0, 10.0);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->param.PropInfo,
|
||||||
|
":", t->param.propId, "I", t->prop_mute,
|
||||||
|
":", t->param.propName, "s", "Mute",
|
||||||
|
":", t->param.propType, "b", p->mute);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (id == t->param.idProps) {
|
else if (id == t->param.idProps) {
|
||||||
struct props *p = &this->props;
|
switch (*index) {
|
||||||
|
case 0:
|
||||||
if(*index > 0)
|
param = spa_pod_builder_object(&b,
|
||||||
|
id, t->props,
|
||||||
|
":", t->prop_volume, "d", p->volume,
|
||||||
|
":", t->prop_mute, "b", p->mute);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
param = spa_pod_builder_object(&b,
|
|
||||||
id, t->props,
|
|
||||||
":", t->prop_volume, "dr", p->volume, 2, 0.0, 10.0,
|
|
||||||
":", t->prop_mute, "b", p->mute);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
|
||||||
|
|
@ -365,7 +365,7 @@ static int make_nodes(struct data *data, const char *device)
|
||||||
|
|
||||||
spa_pod_object_parse(param,
|
spa_pod_object_parse(param,
|
||||||
":", data->type.param_io.id, "I", &id,
|
":", data->type.param_io.id, "I", &id,
|
||||||
":", data->type.param_io.propId, "?I", &propId,
|
":", data->type.param.propId, "?I", &propId,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (propId == data->type.props_freq) {
|
if (propId == data->type.props_freq) {
|
||||||
|
|
|
||||||
|
|
@ -324,8 +324,8 @@ static int impl_port_enum_params(struct spa_node *node,
|
||||||
id, t->param_io.Prop,
|
id, t->param_io.Prop,
|
||||||
":", t->param_io.id, "I", d->type.io_prop_volume,
|
":", t->param_io.id, "I", d->type.io_prop_volume,
|
||||||
":", t->param_io.size, "i", sizeof(struct spa_pod_double),
|
":", t->param_io.size, "i", sizeof(struct spa_pod_double),
|
||||||
":", t->param_io.propId, "I", d->type.prop_volume,
|
":", t->param.propId, "I", d->type.prop_volume,
|
||||||
":", t->param_io.propType, "dru", p->volume, 2, 0.0, 10.0);
|
":", t->param.propType, "dru", p->volume, 2, 0.0, 10.0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue