mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-04-12 08:21:09 -04:00
Compare commits
28 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95da54a482 | ||
|
|
54d0d4e55a | ||
|
|
31874b3764 | ||
|
|
53b870934b | ||
|
|
aa55e43275 | ||
|
|
cab633b4f8 | ||
|
|
b00e8f8bb2 | ||
|
|
45633303aa | ||
|
|
f4a6648aa5 | ||
|
|
cb9b3861ce | ||
|
|
17f423b8f6 | ||
|
|
55f6c35e78 | ||
|
|
3a62ea0217 | ||
|
|
f26eb9501e | ||
|
|
92f8e16f11 | ||
|
|
c3d7373cf9 | ||
|
|
4c2692342e | ||
|
|
299902bd86 | ||
|
|
d99a932b9c | ||
|
|
b7341d0689 | ||
|
|
5f77a7ae2b | ||
|
|
d3946c0b10 | ||
|
|
8daf4ba6b6 | ||
|
|
86da3e1183 | ||
|
|
e208a465ea | ||
|
|
0d14f44f47 | ||
|
|
5cd734e8c0 | ||
|
|
87d1206fb8 |
28 changed files with 258 additions and 114 deletions
68
NEWS
68
NEWS
|
|
@ -1,3 +1,69 @@
|
||||||
|
# PipeWire 1.6.2 (2026-03-16)
|
||||||
|
|
||||||
|
This is a bugfix release that is API and ABI compatible with the previous
|
||||||
|
1.6.x releases.
|
||||||
|
|
||||||
|
## Highlights
|
||||||
|
- Fix a potential crash when the wrong memory was freed.
|
||||||
|
- Fix a optimization with shared memory over some links that could
|
||||||
|
cause errors later on.
|
||||||
|
- Fix SOFA filter and default control input in LADSPA and LV2.
|
||||||
|
- Some other small fixes and improvements.
|
||||||
|
|
||||||
|
|
||||||
|
## PipeWire
|
||||||
|
- Remove an optimization to skip share mem in links, it causes problems
|
||||||
|
later on. (#5159)
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
- Don't try to free invalid memory or close invalid fds when the client
|
||||||
|
aborted before allocating buffer memory. (#5162)
|
||||||
|
|
||||||
|
## SPA
|
||||||
|
- support ACP_IGNORE_DB in udev.
|
||||||
|
- Use 0x as a prefix for hex values.
|
||||||
|
- Mark Props as write-only in libcamera.
|
||||||
|
- Small optimization in the audio mixer.
|
||||||
|
- Fix initialization of control properties for SOFA and biquads in the
|
||||||
|
filter-graph. (#5152)
|
||||||
|
- Fix min/max default values for LADSPA and LV2.
|
||||||
|
|
||||||
|
## JACK
|
||||||
|
- Fix jack_port_type_id(). Return values that are compatible with JACK1/2.
|
||||||
|
|
||||||
|
|
||||||
|
Older versions:
|
||||||
|
|
||||||
|
# PipeWire 1.6.1 (2026-03-09)
|
||||||
|
|
||||||
|
This is a bugfix release that is API and ABI compatible with the previous
|
||||||
|
1.6.x releases.
|
||||||
|
|
||||||
|
## Highlights
|
||||||
|
- Fix socket activation, which could cause a failure to start PipeWire in
|
||||||
|
some setups.
|
||||||
|
- Fix crashes in many JACK apps when nodes/ports are quickly added/removed
|
||||||
|
such as when there are notifications (like when changing the volume in
|
||||||
|
KDE).
|
||||||
|
- Fix playback of encoded formats in pw-cat again.
|
||||||
|
- Some other smaller fixes and improvements.
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
- Fix socket activation. (#5140)
|
||||||
|
- Remove node.link-group from driver nodes.
|
||||||
|
|
||||||
|
## SPA
|
||||||
|
- Fix the libcamera stop sequence.
|
||||||
|
|
||||||
|
## JACK
|
||||||
|
- Never return NULL from jack_port_by_id(). (#3512)
|
||||||
|
|
||||||
|
## GStreamer
|
||||||
|
- Improve the timestamps on buffers.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
- Fix playback of encoded formats. (#5155)
|
||||||
|
|
||||||
# PipeWire 1.6.0 (2026-02-19)
|
# PipeWire 1.6.0 (2026-02-19)
|
||||||
|
|
||||||
This is the 1.6 release that is API and ABI compatible with previous
|
This is the 1.6 release that is API and ABI compatible with previous
|
||||||
|
|
@ -95,8 +161,6 @@ the 1.4 release last year, including:
|
||||||
- Add some more options to pw-cat to list supported containers
|
- Add some more options to pw-cat to list supported containers
|
||||||
and formats. (#5117)
|
and formats. (#5117)
|
||||||
|
|
||||||
Older versions:
|
|
||||||
|
|
||||||
# PipeWire 1.5.85 (2026-01-19)
|
# PipeWire 1.5.85 (2026-01-19)
|
||||||
|
|
||||||
This is the fifth and hopefully last 1.6 release candidate that
|
This is the fifth and hopefully last 1.6 release candidate that
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
<tab type="usergroup" title="PipeWire Versions">
|
<tab type="usergroup" title="PipeWire Versions">
|
||||||
<tab type="user" url="https://docs.pipewire.org/1.2/" title="1.2.x"/>
|
<tab type="user" url="https://docs.pipewire.org/1.2/" title="1.2.x"/>
|
||||||
<tab type="user" url="https://docs.pipewire.org/1.4/" title="1.4.x"/>
|
<tab type="user" url="https://docs.pipewire.org/1.4/" title="1.4.x"/>
|
||||||
|
<tab type="user" url="https://docs.pipewire.org/1.6/" title="1.6.x"/>
|
||||||
<tab type="user" url="https://docs.pipewire.org/devel/" title="Development"/>
|
<tab type="user" url="https://docs.pipewire.org/devel/" title="Development"/>
|
||||||
</tab>
|
</tab>
|
||||||
</navindex>
|
</navindex>
|
||||||
|
|
|
||||||
|
|
@ -349,10 +349,10 @@ rectangles. For example
|
||||||
params[n_params++] = spa_pod_builder_pop(&b, &f);
|
params[n_params++] = spa_pod_builder_pop(&b, &f);
|
||||||
```
|
```
|
||||||
|
|
||||||
After having received the first \ref SPA_PARAM_PeerCapability param, if it contained the \ref
|
After having received the first \ref SPA_PARAM_PeerCapability param, if it contained the
|
||||||
PW_CAPABILITY_DEVICE_ID set to `true`, the full set of formats can be sent using \ref
|
\ref PW_CAPABILITY_DEVICE_ID_NEGOTIATION set to a supported API version number, the full
|
||||||
pw_stream_update_params following by activating the stream using
|
set of formats can be sent using \ref pw_stream_update_params following by activating the
|
||||||
`pw_stream_set_active(stream, true)`.
|
stream usina supported API version numberstream_set_active(stream, true)`.
|
||||||
|
|
||||||
Note that the first \ref SPA_PARAM_Format received may be the result of the initial format
|
Note that the first \ref SPA_PARAM_Format received may be the result of the initial format
|
||||||
negotian with bare minimum parameters, and will be superseded by the result of the format
|
negotian with bare minimum parameters, and will be superseded by the result of the format
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
project('pipewire', ['c' ],
|
project('pipewire', ['c' ],
|
||||||
version : '1.6.0',
|
version : '1.6.2',
|
||||||
license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ],
|
license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ],
|
||||||
meson_version : '>= 0.61.1',
|
meson_version : '>= 0.61.1',
|
||||||
default_options : [ 'warning_level=3',
|
default_options : [ 'warning_level=3',
|
||||||
|
|
@ -116,6 +116,7 @@ cc_flags = common_flags + [
|
||||||
'-Werror=old-style-definition',
|
'-Werror=old-style-definition',
|
||||||
'-Werror=missing-parameter-type',
|
'-Werror=missing-parameter-type',
|
||||||
'-Werror=strict-prototypes',
|
'-Werror=strict-prototypes',
|
||||||
|
'-Werror=discarded-qualifiers',
|
||||||
]
|
]
|
||||||
add_project_arguments(cc.get_supported_arguments(cc_flags), language: 'c')
|
add_project_arguments(cc.get_supported_arguments(cc_flags), language: 'c')
|
||||||
add_project_arguments(cc_native.get_supported_arguments(cc_flags),
|
add_project_arguments(cc_native.get_supported_arguments(cc_flags),
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ pipewire_jackserver = shared_library('jackserver',
|
||||||
pipewire_jackserver_sources,
|
pipewire_jackserver_sources,
|
||||||
soversion : soversion,
|
soversion : soversion,
|
||||||
version : libjackversion,
|
version : libjackversion,
|
||||||
c_args : pipewire_jack_c_args,
|
c_args : pipewire_jack_c_args + '-DLIBJACKSERVER',
|
||||||
include_directories : [configinc, jack_inc],
|
include_directories : [configinc, jack_inc],
|
||||||
dependencies : [pipewire_dep, mathlib],
|
dependencies : [pipewire_dep, mathlib],
|
||||||
install : true,
|
install : true,
|
||||||
|
|
|
||||||
|
|
@ -492,6 +492,8 @@ struct client {
|
||||||
jack_position_t jack_position;
|
jack_position_t jack_position;
|
||||||
jack_transport_state_t jack_state;
|
jack_transport_state_t jack_state;
|
||||||
struct frame_times jack_times;
|
struct frame_times jack_times;
|
||||||
|
|
||||||
|
struct object dummy_port;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define return_val_if_fail(expr, val) \
|
#define return_val_if_fail(expr, val) \
|
||||||
|
|
@ -4468,6 +4470,11 @@ jack_client_t * jack_client_open (const char *client_name,
|
||||||
0, NULL, &client->info);
|
0, NULL, &client->info);
|
||||||
client->info.change_mask = 0;
|
client->info.change_mask = 0;
|
||||||
|
|
||||||
|
client->dummy_port.type = INTERFACE_Port;
|
||||||
|
snprintf(client->dummy_port.port.name, sizeof(client->dummy_port.port.name), "%s:dummy", client_name);
|
||||||
|
snprintf(client->dummy_port.port.alias1, sizeof(client->dummy_port.port.alias1), "%s:dummy", client_name);
|
||||||
|
snprintf(client->dummy_port.port.alias2, sizeof(client->dummy_port.port.alias2), "%s:dummy", client_name);
|
||||||
|
|
||||||
client->show_monitor = pw_properties_get_bool(client->props, "jack.show-monitor", true);
|
client->show_monitor = pw_properties_get_bool(client->props, "jack.show-monitor", true);
|
||||||
client->show_midi = pw_properties_get_bool(client->props, "jack.show-midi", true);
|
client->show_midi = pw_properties_get_bool(client->props, "jack.show-midi", true);
|
||||||
client->merge_monitor = pw_properties_get_bool(client->props, "jack.merge-monitor", true);
|
client->merge_monitor = pw_properties_get_bool(client->props, "jack.merge-monitor", true);
|
||||||
|
|
@ -4880,9 +4887,21 @@ int jack_activate (jack_client_t *client)
|
||||||
c->activation->pending_sync = true;
|
c->activation->pending_sync = true;
|
||||||
|
|
||||||
spa_list_for_each(o, &c->context.objects, link) {
|
spa_list_for_each(o, &c->context.objects, link) {
|
||||||
|
#if !defined(LIBJACKSERVER)
|
||||||
if (o->type != INTERFACE_Port || o->port.port == NULL ||
|
if (o->type != INTERFACE_Port || o->port.port == NULL ||
|
||||||
o->port.port->client != c || !o->port.port->valid)
|
o->port.port->client != c || !o->port.port->valid)
|
||||||
continue;
|
continue;
|
||||||
|
#else
|
||||||
|
/* emits all foreign active ports, skips own (already announced via jack_port_register) */
|
||||||
|
if (o->type != INTERFACE_Port || o->removed)
|
||||||
|
continue;
|
||||||
|
/* own ports are handled by jack_port_register */
|
||||||
|
if (o->port.port != NULL && o->port.port->client == c)
|
||||||
|
continue;
|
||||||
|
/* only announce ports whose node is active */
|
||||||
|
if (o->port.node != NULL && !node_is_active(c, o->port.node))
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
o->registered = 0;
|
o->registered = 0;
|
||||||
queue_notify(c, NOTIFY_TYPE_PORTREGISTRATION, o, 1, NULL);
|
queue_notify(c, NOTIFY_TYPE_PORTREGISTRATION, o, 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -5318,7 +5337,7 @@ int jack_set_freewheel(jack_client_t* client, int onoff)
|
||||||
pw_thread_loop_lock(c->context.loop);
|
pw_thread_loop_lock(c->context.loop);
|
||||||
str = pw_properties_get(c->props, PW_KEY_NODE_GROUP);
|
str = pw_properties_get(c->props, PW_KEY_NODE_GROUP);
|
||||||
if (str != NULL) {
|
if (str != NULL) {
|
||||||
char *p = strstr(str, ",pipewire.freewheel");
|
const char *p = strstr(str, ",pipewire.freewheel");
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
p = strstr(str, "pipewire.freewheel");
|
p = strstr(str, "pipewire.freewheel");
|
||||||
if (p == NULL && onoff)
|
if (p == NULL && onoff)
|
||||||
|
|
@ -5951,9 +5970,7 @@ static const char *port_name(struct object *o)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
struct client *c = o->client;
|
struct client *c = o->client;
|
||||||
if (c == NULL)
|
if (c != NULL && c->default_as_system && is_port_default(c, o))
|
||||||
return NULL;
|
|
||||||
if (c->default_as_system && is_port_default(c, o))
|
|
||||||
name = o->port.system;
|
name = o->port.system;
|
||||||
else
|
else
|
||||||
name = o->port.name;
|
name = o->port.name;
|
||||||
|
|
@ -6007,7 +6024,16 @@ jack_port_type_id_t jack_port_type_id (const jack_port_t *port)
|
||||||
return_val_if_fail(o != NULL, 0);
|
return_val_if_fail(o != NULL, 0);
|
||||||
if (o->type != INTERFACE_Port)
|
if (o->type != INTERFACE_Port)
|
||||||
return TYPE_ID_OTHER;
|
return TYPE_ID_OTHER;
|
||||||
return o->port.type_id;
|
|
||||||
|
/* map internal type IDs to jack1/jack2 compatible public values */
|
||||||
|
switch (o->port.type_id) {
|
||||||
|
case TYPE_ID_AUDIO: return 0;
|
||||||
|
case TYPE_ID_MIDI:
|
||||||
|
case TYPE_ID_OSC:
|
||||||
|
case TYPE_ID_UMP: return 1; /* all MIDI variants map to 1 */
|
||||||
|
case TYPE_ID_VIDEO: return 3; /* video maps to 3 */
|
||||||
|
default: return o->port.type_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
|
|
@ -6999,13 +7025,11 @@ jack_port_t * jack_port_by_id (jack_client_t *client,
|
||||||
|
|
||||||
pthread_mutex_lock(&c->context.lock);
|
pthread_mutex_lock(&c->context.lock);
|
||||||
res = find_by_serial(c, port_id);
|
res = find_by_serial(c, port_id);
|
||||||
if (res && res->type != INTERFACE_Port)
|
|
||||||
res = NULL;
|
|
||||||
pw_log_debug("%p: port %d -> %p", c, port_id, res);
|
|
||||||
pthread_mutex_unlock(&c->context.lock);
|
pthread_mutex_unlock(&c->context.lock);
|
||||||
|
if (res == NULL || res->type != INTERFACE_Port)
|
||||||
|
res = &c->dummy_port;
|
||||||
|
|
||||||
if (res == NULL)
|
pw_log_debug("%p: port %d -> %p", c, port_id, res);
|
||||||
pw_log_info("%p: port %d not found", c, port_id);
|
|
||||||
|
|
||||||
return object_to_port(res);
|
return object_to_port(res);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -485,13 +485,11 @@ static int add_pro_profile(pa_card *impl, uint32_t index)
|
||||||
if ((n_capture == 1 && n_playback == 1) || is_firewire) {
|
if ((n_capture == 1 && n_playback == 1) || is_firewire) {
|
||||||
PA_IDXSET_FOREACH(m, ap->output_mappings, idx) {
|
PA_IDXSET_FOREACH(m, ap->output_mappings, idx) {
|
||||||
pa_proplist_setf(m->output_proplist, "node.group", "pro-audio-%u", index);
|
pa_proplist_setf(m->output_proplist, "node.group", "pro-audio-%u", index);
|
||||||
pa_proplist_setf(m->output_proplist, "node.link-group", "pro-audio-%u", index);
|
|
||||||
pa_proplist_setf(m->output_proplist, "api.alsa.auto-link", "true");
|
pa_proplist_setf(m->output_proplist, "api.alsa.auto-link", "true");
|
||||||
pa_proplist_setf(m->output_proplist, "api.alsa.disable-tsched", "true");
|
pa_proplist_setf(m->output_proplist, "api.alsa.disable-tsched", "true");
|
||||||
}
|
}
|
||||||
PA_IDXSET_FOREACH(m, ap->input_mappings, idx) {
|
PA_IDXSET_FOREACH(m, ap->input_mappings, idx) {
|
||||||
pa_proplist_setf(m->input_proplist, "node.group", "pro-audio-%u", index);
|
pa_proplist_setf(m->input_proplist, "node.group", "pro-audio-%u", index);
|
||||||
pa_proplist_setf(m->input_proplist, "node.link-group", "pro-audio-%u", index);
|
|
||||||
pa_proplist_setf(m->input_proplist, "api.alsa.auto-link", "true");
|
pa_proplist_setf(m->input_proplist, "api.alsa.auto-link", "true");
|
||||||
pa_proplist_setf(m->input_proplist, "api.alsa.disable-tsched", "true");
|
pa_proplist_setf(m->input_proplist, "api.alsa.disable-tsched", "true");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -538,6 +538,9 @@ static int emit_added_object_info(struct impl *this, struct card *card)
|
||||||
if ((str = udev_device_get_property_value(udev_device, "ACP_PROFILE_SET")) && *str)
|
if ((str = udev_device_get_property_value(udev_device, "ACP_PROFILE_SET")) && *str)
|
||||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_PROFILE_SET, str);
|
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_PROFILE_SET, str);
|
||||||
|
|
||||||
|
if ((str = udev_device_get_property_value(udev_device, "ACP_IGNORE_DB")) && *str)
|
||||||
|
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_IGNORE_DB, str);
|
||||||
|
|
||||||
if ((str = udev_device_get_property_value(udev_device, "SOUND_CLASS")) && *str)
|
if ((str = udev_device_get_property_value(udev_device, "SOUND_CLASS")) && *str)
|
||||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_CLASS, str);
|
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_CLASS, str);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -725,7 +725,7 @@ static int do_port_set_io(struct spa_loop *loop, bool async, uint32_t seq,
|
||||||
port->io[0] = info->data;
|
port->io[0] = info->data;
|
||||||
port->io[1] = info->data;
|
port->io[1] = info->data;
|
||||||
}
|
}
|
||||||
if (!port->active) {
|
if (port->direction == SPA_DIRECTION_INPUT && !port->active) {
|
||||||
spa_list_append(&info->impl->mix_list, &port->mix_link);
|
spa_list_append(&info->impl->mix_list, &port->mix_link);
|
||||||
port->active = true;
|
port->active = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -718,7 +718,7 @@ static int do_port_set_io(struct spa_loop *loop, bool async, uint32_t seq,
|
||||||
port->io[0] = info->data;
|
port->io[0] = info->data;
|
||||||
port->io[1] = info->data;
|
port->io[1] = info->data;
|
||||||
}
|
}
|
||||||
if (!port->active) {
|
if (port->direction == SPA_DIRECTION_INPUT && !port->active) {
|
||||||
spa_list_append(&info->impl->mix_list, &port->mix_link);
|
spa_list_append(&info->impl->mix_list, &port->mix_link);
|
||||||
port->active = true;
|
port->active = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -720,14 +720,12 @@ static const char *bap_features_get_uuid(struct bap_features *feat, size_t i)
|
||||||
/** Get feature name at \a i, or NULL if uuid doesn't match */
|
/** Get feature name at \a i, or NULL if uuid doesn't match */
|
||||||
static const char *bap_features_get_name(struct bap_features *feat, size_t i, const char *uuid)
|
static const char *bap_features_get_name(struct bap_features *feat, size_t i, const char *uuid)
|
||||||
{
|
{
|
||||||
char *pos;
|
|
||||||
|
|
||||||
if (i >= feat->dict.n_items)
|
if (i >= feat->dict.n_items)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!spa_streq(feat->dict.items[i].value, uuid))
|
if (!spa_streq(feat->dict.items[i].value, uuid))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
pos = strchr(feat->dict.items[i].key, ':');
|
const char *pos = strchr(feat->dict.items[i].key, ':');
|
||||||
if (!pos)
|
if (!pos)
|
||||||
return NULL;
|
return NULL;
|
||||||
return pos + 1;
|
return pos + 1;
|
||||||
|
|
@ -1336,7 +1334,6 @@ static struct spa_bt_adapter *adapter_find(struct spa_bt_monitor *monitor, const
|
||||||
static int parse_modalias(const char *modalias, uint16_t *source, uint16_t *vendor,
|
static int parse_modalias(const char *modalias, uint16_t *source, uint16_t *vendor,
|
||||||
uint16_t *product, uint16_t *version)
|
uint16_t *product, uint16_t *version)
|
||||||
{
|
{
|
||||||
char *pos;
|
|
||||||
unsigned int src, i, j, k;
|
unsigned int src, i, j, k;
|
||||||
|
|
||||||
if (spa_strstartswith(modalias, "bluetooth:"))
|
if (spa_strstartswith(modalias, "bluetooth:"))
|
||||||
|
|
@ -1346,7 +1343,7 @@ static int parse_modalias(const char *modalias, uint16_t *source, uint16_t *vend
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
pos = strchr(modalias, ':');
|
const char *pos = strchr(modalias, ':');
|
||||||
if (pos == NULL)
|
if (pos == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1035,8 +1035,8 @@ static struct descriptor *descriptor_load(struct impl *impl, const char *type,
|
||||||
}
|
}
|
||||||
} else if (SPA_FGA_IS_PORT_CONTROL(fp->flags)) {
|
} else if (SPA_FGA_IS_PORT_CONTROL(fp->flags)) {
|
||||||
if (SPA_FGA_IS_PORT_INPUT(fp->flags)) {
|
if (SPA_FGA_IS_PORT_INPUT(fp->flags)) {
|
||||||
spa_log_info(impl->log, "using port %lu ('%s') as control %d", p,
|
spa_log_info(impl->log, "using port %lu ('%s') as control %d %f/%f/%f", p,
|
||||||
fp->name, desc->n_control);
|
fp->name, desc->n_control, fp->def, fp->min, fp->max);
|
||||||
desc->control[desc->n_control++] = p;
|
desc->control[desc->n_control++] = p;
|
||||||
}
|
}
|
||||||
else if (SPA_FGA_IS_PORT_OUTPUT(fp->flags)) {
|
else if (SPA_FGA_IS_PORT_OUTPUT(fp->flags)) {
|
||||||
|
|
@ -1622,6 +1622,7 @@ static int impl_activate(void *object, const struct spa_dict *props)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
node->control_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* then link ports */
|
/* then link ports */
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
#include <spa/utils/result.h>
|
#include <spa/utils/result.h>
|
||||||
#include <spa/utils/defs.h>
|
#include <spa/utils/defs.h>
|
||||||
|
|
@ -113,8 +114,14 @@ static void ladspa_port_update_ranges(struct descriptor *dd, struct spa_fga_port
|
||||||
LADSPA_PortRangeHintDescriptor hint = d->PortRangeHints[p].HintDescriptor;
|
LADSPA_PortRangeHintDescriptor hint = d->PortRangeHints[p].HintDescriptor;
|
||||||
LADSPA_Data lower, upper;
|
LADSPA_Data lower, upper;
|
||||||
|
|
||||||
|
if (hint & LADSPA_HINT_BOUNDED_BELOW)
|
||||||
lower = d->PortRangeHints[p].LowerBound;
|
lower = d->PortRangeHints[p].LowerBound;
|
||||||
|
else
|
||||||
|
lower = -FLT_MAX;
|
||||||
|
if (hint & LADSPA_HINT_BOUNDED_ABOVE)
|
||||||
upper = d->PortRangeHints[p].UpperBound;
|
upper = d->PortRangeHints[p].UpperBound;
|
||||||
|
else
|
||||||
|
upper = FLT_MAX;
|
||||||
|
|
||||||
port->hint = 0;
|
port->hint = 0;
|
||||||
if (hint & LADSPA_HINT_TOGGLED)
|
if (hint & LADSPA_HINT_TOGGLED)
|
||||||
|
|
|
||||||
|
|
@ -560,6 +560,17 @@ static const struct spa_fga_descriptor *lv2_plugin_make_desc(void *plugin, const
|
||||||
fp->min = mins[i];
|
fp->min = mins[i];
|
||||||
fp->max = maxes[i];
|
fp->max = maxes[i];
|
||||||
fp->def = controls[i];
|
fp->def = controls[i];
|
||||||
|
|
||||||
|
if (isnan(fp->min))
|
||||||
|
fp->min = -FLT_MAX;
|
||||||
|
if (isnan(fp->max))
|
||||||
|
fp->max = FLT_MAX;
|
||||||
|
if (isnan(fp->def))
|
||||||
|
fp->def = 0.0f;
|
||||||
|
if (fp->max <= fp->min)
|
||||||
|
fp->max = FLT_MAX;
|
||||||
|
if (fp->def <= fp->min)
|
||||||
|
fp->min = -FLT_MAX;
|
||||||
}
|
}
|
||||||
return &desc->desc;
|
return &desc->desc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,9 +184,6 @@ struct impl {
|
||||||
0, nullptr, 0, this
|
0, nullptr, 0, this
|
||||||
);
|
);
|
||||||
|
|
||||||
if (source.fd >= 0)
|
|
||||||
spa_system_close(system, std::exchange(source.fd, -1));
|
|
||||||
|
|
||||||
camera->requestCompleted.disconnect(this, &impl::requestComplete);
|
camera->requestCompleted.disconnect(this, &impl::requestComplete);
|
||||||
|
|
||||||
if (int res = camera->stop(); res < 0) {
|
if (int res = camera->stop(); res < 0) {
|
||||||
|
|
@ -194,6 +191,9 @@ struct impl {
|
||||||
camera->id().c_str(), spa_strerror(res));
|
camera->id().c_str(), spa_strerror(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (source.fd >= 0)
|
||||||
|
spa_system_close(system, std::exchange(source.fd, -1));
|
||||||
|
|
||||||
completed_requests_rb = SPA_RINGBUFFER_INIT();
|
completed_requests_rb = SPA_RINGBUFFER_INIT();
|
||||||
active = false;
|
active = false;
|
||||||
|
|
||||||
|
|
@ -2163,7 +2163,7 @@ impl::impl(spa_log *log, spa_loop *data_loop, spa_system *system,
|
||||||
&impl_node, this);
|
&impl_node, this);
|
||||||
|
|
||||||
params[NODE_PropInfo] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
|
params[NODE_PropInfo] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
|
||||||
params[NODE_Props] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
|
params[NODE_Props] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE);
|
||||||
params[NODE_EnumFormat] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
|
params[NODE_EnumFormat] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
|
||||||
params[NODE_Format] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
|
params[NODE_Format] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ impl_log_logtv(void *object,
|
||||||
char timestamp[18] = {0};
|
char timestamp[18] = {0};
|
||||||
char topicstr[32] = {0};
|
char topicstr[32] = {0};
|
||||||
char filename[64] = {0};
|
char filename[64] = {0};
|
||||||
char location[1000 + RESERVED_LENGTH], *p, *s;
|
char location[1000 + RESERVED_LENGTH], *p;
|
||||||
static const char * const levels[] = { "-", "E", "W", "I", "D", "T", "*T*" };
|
static const char * const levels[] = { "-", "E", "W", "I", "D", "T", "*T*" };
|
||||||
const char *prefix = "", *suffix = "";
|
const char *prefix = "", *suffix = "";
|
||||||
int size, len;
|
int size, len;
|
||||||
|
|
@ -118,7 +118,7 @@ impl_log_logtv(void *object,
|
||||||
|
|
||||||
|
|
||||||
if (impl->line && line != 0) {
|
if (impl->line && line != 0) {
|
||||||
s = strrchr(file, '/');
|
const char *s = strrchr(file, '/');
|
||||||
spa_scnprintf(filename, sizeof(filename), "[%16.16s:%5i %s()]",
|
spa_scnprintf(filename, sizeof(filename), "[%16.16s:%5i %s()]",
|
||||||
s ? s + 1 : file, line, func);
|
s ? s + 1 : file, line, func);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,9 +98,9 @@ static int emit_info(struct impl *this, bool full)
|
||||||
(this->dev.cap.version >> 8) & 0xFF,
|
(this->dev.cap.version >> 8) & 0xFF,
|
||||||
(this->dev.cap.version) & 0xFF);
|
(this->dev.cap.version) & 0xFF);
|
||||||
ADD_ITEM(SPA_KEY_API_V4L2_CAP_VERSION, version);
|
ADD_ITEM(SPA_KEY_API_V4L2_CAP_VERSION, version);
|
||||||
snprintf(capabilities, sizeof(capabilities), "%08x", this->dev.cap.capabilities);
|
snprintf(capabilities, sizeof(capabilities), "0x%08x", this->dev.cap.capabilities);
|
||||||
ADD_ITEM(SPA_KEY_API_V4L2_CAP_CAPABILITIES, capabilities);
|
ADD_ITEM(SPA_KEY_API_V4L2_CAP_CAPABILITIES, capabilities);
|
||||||
snprintf(device_caps, sizeof(device_caps), "%08x", this->dev.cap.device_caps);
|
snprintf(device_caps, sizeof(device_caps), "0x%08x", this->dev.cap.device_caps);
|
||||||
ADD_ITEM(SPA_KEY_API_V4L2_CAP_DEVICE_CAPS, device_caps);
|
ADD_ITEM(SPA_KEY_API_V4L2_CAP_DEVICE_CAPS, device_caps);
|
||||||
#undef ADD_ITEM
|
#undef ADD_ITEM
|
||||||
info.props = &SPA_DICT_INIT(items, n_items);
|
info.props = &SPA_DICT_INIT(items, n_items);
|
||||||
|
|
|
||||||
|
|
@ -531,6 +531,7 @@ gst_pipewire_src_init (GstPipeWireSrc * src)
|
||||||
src->autoconnect = DEFAULT_AUTOCONNECT;
|
src->autoconnect = DEFAULT_AUTOCONNECT;
|
||||||
src->min_latency = 0;
|
src->min_latency = 0;
|
||||||
src->max_latency = GST_CLOCK_TIME_NONE;
|
src->max_latency = GST_CLOCK_TIME_NONE;
|
||||||
|
src->last_buffer_clock_time = GST_CLOCK_TIME_NONE;
|
||||||
src->n_buffers = 0;
|
src->n_buffers = 0;
|
||||||
src->flushing_on_remove_buffer = FALSE;
|
src->flushing_on_remove_buffer = FALSE;
|
||||||
src->on_disconnect = DEFAULT_ON_DISCONNECT;
|
src->on_disconnect = DEFAULT_ON_DISCONNECT;
|
||||||
|
|
@ -1598,16 +1599,31 @@ gst_pipewire_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
|
||||||
GST_LOG_OBJECT (pwsrc, "EOS, send last buffer");
|
GST_LOG_OBJECT (pwsrc, "EOS, send last buffer");
|
||||||
break;
|
break;
|
||||||
} else if (timeout && pwsrc->last_buffer != NULL) {
|
} else if (timeout && pwsrc->last_buffer != NULL) {
|
||||||
|
buf = gst_buffer_copy (pwsrc->last_buffer);
|
||||||
update_time = TRUE;
|
update_time = TRUE;
|
||||||
buf = gst_buffer_ref(pwsrc->last_buffer);
|
|
||||||
GST_LOG_OBJECT (pwsrc, "timeout, send keepalive buffer");
|
GST_LOG_OBJECT (pwsrc, "timeout, send keepalive buffer");
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
buf = dequeue_buffer (pwsrc);
|
buf = dequeue_buffer (pwsrc);
|
||||||
GST_LOG_OBJECT (pwsrc, "popped buffer %p", buf);
|
GST_LOG_OBJECT (pwsrc, "popped buffer %p", buf);
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
if (pwsrc->resend_last || pwsrc->keepalive_time > 0)
|
if (pwsrc->resend_last || pwsrc->keepalive_time > 0) {
|
||||||
gst_buffer_replace (&pwsrc->last_buffer, buf);
|
GstClock *clock;
|
||||||
|
GstBuffer *old;
|
||||||
|
|
||||||
|
old = pwsrc->last_buffer;
|
||||||
|
pwsrc->last_buffer = gst_buffer_copy (buf);
|
||||||
|
gst_buffer_unref (old);
|
||||||
|
gst_buffer_add_parent_buffer_meta (pwsrc->last_buffer, buf);
|
||||||
|
|
||||||
|
clock = gst_element_get_clock (GST_ELEMENT_CAST (pwsrc));
|
||||||
|
if (clock != NULL) {
|
||||||
|
pwsrc->last_buffer_clock_time = gst_clock_get_time (clock);
|
||||||
|
gst_object_unref (clock);
|
||||||
|
} else {
|
||||||
|
pwsrc->last_buffer_clock_time = GST_CLOCK_TIME_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1632,21 +1648,33 @@ gst_pipewire_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
|
||||||
|
|
||||||
if (update_time) {
|
if (update_time) {
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
GstClockTime pts, dts;
|
GstClockTime current_clock_time;
|
||||||
|
|
||||||
clock = gst_element_get_clock (GST_ELEMENT_CAST (pwsrc));
|
clock = gst_element_get_clock (GST_ELEMENT_CAST (pwsrc));
|
||||||
if (clock != NULL) {
|
if (clock != NULL) {
|
||||||
pts = dts = gst_clock_get_time (clock);
|
current_clock_time = gst_clock_get_time (clock);
|
||||||
gst_object_unref (clock);
|
gst_object_unref (clock);
|
||||||
} else {
|
} else {
|
||||||
pts = dts = GST_CLOCK_TIME_NONE;
|
current_clock_time = GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_BUFFER_PTS (*buffer) = pts;
|
if (GST_CLOCK_TIME_IS_VALID (current_clock_time) &&
|
||||||
GST_BUFFER_DTS (*buffer) = dts;
|
GST_CLOCK_TIME_IS_VALID (pwsrc->last_buffer_clock_time) &&
|
||||||
|
GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (*buffer)) &&
|
||||||
|
GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (*buffer))) {
|
||||||
|
GstClockTime diff;
|
||||||
|
|
||||||
|
diff = current_clock_time - pwsrc->last_buffer_clock_time;
|
||||||
|
|
||||||
|
GST_BUFFER_PTS (*buffer) += diff;
|
||||||
|
GST_BUFFER_DTS (*buffer) += diff;
|
||||||
|
} else {
|
||||||
|
GST_BUFFER_PTS (*buffer) = GST_BUFFER_DTS (*buffer) = current_clock_time;
|
||||||
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (pwsrc, "Sending keepalive buffer pts/dts: %" GST_TIME_FORMAT
|
GST_LOG_OBJECT (pwsrc, "Sending keepalive buffer pts/dts: %" GST_TIME_FORMAT
|
||||||
" (%" G_GUINT64_FORMAT ")", GST_TIME_ARGS (pts), pts);
|
" (%" G_GUINT64_FORMAT ")", GST_TIME_ARGS (current_clock_time),
|
||||||
|
current_clock_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ struct _GstPipeWireSrc {
|
||||||
GstClockTime max_latency;
|
GstClockTime max_latency;
|
||||||
|
|
||||||
GstBuffer *last_buffer;
|
GstBuffer *last_buffer;
|
||||||
|
GstClockTime last_buffer_clock_time;
|
||||||
|
|
||||||
enum spa_meta_videotransform_value transform_value;
|
enum spa_meta_videotransform_value transform_value;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,7 @@ static void clear_data(struct impl *impl, struct spa_data *d)
|
||||||
case SPA_DATA_DmaBuf:
|
case SPA_DATA_DmaBuf:
|
||||||
case SPA_DATA_SyncObj:
|
case SPA_DATA_SyncObj:
|
||||||
pw_log_debug("%p: close fd:%d", impl, (int)d->fd);
|
pw_log_debug("%p: close fd:%d", impl, (int)d->fd);
|
||||||
|
if (d->fd != -1)
|
||||||
close(d->fd);
|
close(d->fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -864,8 +865,11 @@ do_port_use_buffers(struct impl *impl,
|
||||||
|
|
||||||
memcpy(&b->datas[j], d, sizeof(struct spa_data));
|
memcpy(&b->datas[j], d, sizeof(struct spa_data));
|
||||||
|
|
||||||
if (flags & SPA_NODE_BUFFERS_FLAG_ALLOC)
|
if (flags & SPA_NODE_BUFFERS_FLAG_ALLOC) {
|
||||||
|
b->datas[j].fd = -1;
|
||||||
|
b->datas[j].data = SPA_UINT32_TO_PTR(SPA_ID_INVALID);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (d->type) {
|
switch (d->type) {
|
||||||
case SPA_DATA_DmaBuf:
|
case SPA_DATA_DmaBuf:
|
||||||
|
|
|
||||||
|
|
@ -1556,8 +1556,6 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
||||||
pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
|
pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
|
||||||
if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL)
|
if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL)
|
||||||
pw_properties_set(props, PW_KEY_NODE_GROUP, "ffado-group");
|
pw_properties_set(props, PW_KEY_NODE_GROUP, "ffado-group");
|
||||||
if (pw_properties_get(props, PW_KEY_NODE_LINK_GROUP) == NULL)
|
|
||||||
pw_properties_set(props, PW_KEY_NODE_LINK_GROUP, "ffado-group");
|
|
||||||
if (pw_properties_get(props, PW_KEY_NODE_PAUSE_ON_IDLE) == NULL)
|
if (pw_properties_get(props, PW_KEY_NODE_PAUSE_ON_IDLE) == NULL)
|
||||||
pw_properties_set(props, PW_KEY_NODE_PAUSE_ON_IDLE, "false");
|
pw_properties_set(props, PW_KEY_NODE_PAUSE_ON_IDLE, "false");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1393,8 +1393,6 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
||||||
pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
|
pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
|
||||||
if (pw_properties_get(props, PW_KEY_NODE_NETWORK) == NULL)
|
if (pw_properties_get(props, PW_KEY_NODE_NETWORK) == NULL)
|
||||||
pw_properties_set(props, PW_KEY_NODE_NETWORK, "true");
|
pw_properties_set(props, PW_KEY_NODE_NETWORK, "true");
|
||||||
if (pw_properties_get(props, PW_KEY_NODE_LINK_GROUP) == NULL)
|
|
||||||
pw_properties_set(props, PW_KEY_NODE_LINK_GROUP, "jack-group");
|
|
||||||
if (pw_properties_get(props, PW_KEY_NODE_ALWAYS_PROCESS) == NULL)
|
if (pw_properties_get(props, PW_KEY_NODE_ALWAYS_PROCESS) == NULL)
|
||||||
pw_properties_set(props, PW_KEY_NODE_ALWAYS_PROCESS, "true");
|
pw_properties_set(props, PW_KEY_NODE_ALWAYS_PROCESS, "true");
|
||||||
if (pw_properties_get(props, PW_KEY_NODE_LOCK_QUANTUM) == NULL)
|
if (pw_properties_get(props, PW_KEY_NODE_LOCK_QUANTUM) == NULL)
|
||||||
|
|
|
||||||
|
|
@ -907,7 +907,7 @@ static int add_socket(struct pw_protocol *protocol, struct server *s, struct soc
|
||||||
bool activated = false;
|
bool activated = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
int i, n = listen_fd();
|
int i, n = listen_fds();
|
||||||
for (i = 0; i < n; ++i) {
|
for (i = 0; i < n; ++i) {
|
||||||
if (is_socket_unix(LISTEN_FDS_START + i, SOCK_STREAM,
|
if (is_socket_unix(LISTEN_FDS_START + i, SOCK_STREAM,
|
||||||
s->addr.sun_path) > 0) {
|
s->addr.sun_path) > 0) {
|
||||||
|
|
|
||||||
|
|
@ -576,7 +576,7 @@ static bool is_stale_socket(int fd, const struct sockaddr_un *addr_un)
|
||||||
|
|
||||||
static int check_socket_activation(const char *path)
|
static int check_socket_activation(const char *path)
|
||||||
{
|
{
|
||||||
const int n = listen_fd();
|
const int n = listen_fds();
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
const int fd = LISTEN_FDS_START + i;
|
const int fd = LISTEN_FDS_START + i;
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ static inline bool pw_net_addr_is_any(struct sockaddr_storage *addr)
|
||||||
|
|
||||||
/* Returns the number of file descriptors passed for socket activation.
|
/* Returns the number of file descriptors passed for socket activation.
|
||||||
* Returns 0 if none, -1 on error. */
|
* Returns 0 if none, -1 on error. */
|
||||||
static inline int listen_fd(void)
|
static inline int listen_fds(void)
|
||||||
{
|
{
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
int i, flags;
|
int i, flags;
|
||||||
|
|
@ -161,8 +161,6 @@ static inline int listen_fd(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsetenv("LISTEN_FDS");
|
|
||||||
|
|
||||||
return (int)n;
|
return (int)n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,13 +190,11 @@ static inline int is_socket_unix(int fd, int type, const char *path)
|
||||||
if (addr.sun_family != AF_UNIX)
|
if (addr.sun_family != AF_UNIX)
|
||||||
return 0;
|
return 0;
|
||||||
size_t length = strlen(path);
|
size_t length = strlen(path);
|
||||||
if (length > 0) {
|
if (len < offsetof(struct sockaddr_un, sun_path) + length + 1)
|
||||||
if (len < offsetof(struct sockaddr_un, sun_path) + length)
|
|
||||||
return 0;
|
return 0;
|
||||||
if (memcmp(addr.sun_path, path, length) != 0)
|
if (memcmp(addr.sun_path, path, length + 1) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,14 @@ extern "C" {
|
||||||
* \{
|
* \{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**< Link capable of device ID negotiation. The value is either "true" or "false" */
|
/**< Link capable of device ID negotiation. The value is to the version of the
|
||||||
|
* API specification. */
|
||||||
#define PW_CAPABILITY_DEVICE_ID_NEGOTIATION "pipewire.device-id-negotiation"
|
#define PW_CAPABILITY_DEVICE_ID_NEGOTIATION "pipewire.device-id-negotiation"
|
||||||
/**< Link with device ID negotition capability supports negotiating with
|
/**< Link with device ID negotition capability supports negotiating with
|
||||||
* provided list of devices. The value consists of a JSON encoded string array
|
* a specific set of devices. The value of API version 1 consists of a JSON
|
||||||
* of base64 encoded dev_t values. */
|
* object containing a single key "available-devices" that contain a list of
|
||||||
|
* hexadecimal encoded `dev_t` device IDs.
|
||||||
|
*/
|
||||||
#define PW_CAPABILITY_DEVICE_IDS "pipewire.device-ids"
|
#define PW_CAPABILITY_DEVICE_IDS "pipewire.device-ids"
|
||||||
|
|
||||||
#define PW_CAPABILITY_DEVICE_ID "pipewire.device-id" /**< Link capable of device Id negotation */
|
#define PW_CAPABILITY_DEVICE_ID "pipewire.device-id" /**< Link capable of device Id negotation */
|
||||||
|
|
|
||||||
|
|
@ -701,7 +701,10 @@ static int do_allocation(struct pw_impl_link *this)
|
||||||
/* always enable async mode */
|
/* always enable async mode */
|
||||||
alloc_flags = PW_BUFFERS_FLAG_ASYNC;
|
alloc_flags = PW_BUFFERS_FLAG_ASYNC;
|
||||||
|
|
||||||
if (output->node->remote || input->node->remote)
|
/* shared mem can only be used if both nodes are in the same process
|
||||||
|
* and we are sure that the buffers are never going to be shared
|
||||||
|
* because of the exclusive flag */
|
||||||
|
if (output->node->remote || input->node->remote || !output->exclusive)
|
||||||
alloc_flags |= PW_BUFFERS_FLAG_SHARED;
|
alloc_flags |= PW_BUFFERS_FLAG_SHARED;
|
||||||
|
|
||||||
if (output->node->driver)
|
if (output->node->driver)
|
||||||
|
|
|
||||||
|
|
@ -196,55 +196,60 @@ struct data {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct format_info {
|
static const struct format_info {
|
||||||
const char *name;
|
const char *sf_name;
|
||||||
int sf_format;
|
int sf_format;
|
||||||
|
uint32_t sf_width;
|
||||||
|
const char *spa_name;
|
||||||
uint32_t spa_format;
|
uint32_t spa_format;
|
||||||
uint32_t width;
|
uint32_t spa_width;
|
||||||
|
#define FORMAT_ENCODED (1<<0)
|
||||||
|
uint32_t flags;
|
||||||
} format_info[] = {
|
} format_info[] = {
|
||||||
{ "ulaw", SF_FORMAT_ULAW, SPA_AUDIO_FORMAT_ULAW, 1 },
|
{ "ulaw", SF_FORMAT_ULAW, 1, "ulaw", SPA_AUDIO_FORMAT_ULAW, 1, 0 },
|
||||||
{ "alaw", SF_FORMAT_ULAW, SPA_AUDIO_FORMAT_ALAW, 1 },
|
{ "alaw", SF_FORMAT_ULAW, 1, "alaw", SPA_AUDIO_FORMAT_ALAW, 1, 0 },
|
||||||
{ "s8", SF_FORMAT_PCM_S8, SPA_AUDIO_FORMAT_S8, 1 },
|
{ "s8", SF_FORMAT_PCM_S8, 1, "s8", SPA_AUDIO_FORMAT_S8, 1, 0 },
|
||||||
{ "u8", SF_FORMAT_PCM_U8, SPA_AUDIO_FORMAT_U8, 1 },
|
{ "u8", SF_FORMAT_PCM_U8, 1, "u8", SPA_AUDIO_FORMAT_U8, 1, 0 },
|
||||||
{ "s16", SF_FORMAT_PCM_16, SPA_AUDIO_FORMAT_S16, 2 },
|
{ "s16", SF_FORMAT_PCM_16, 2, "s16", SPA_AUDIO_FORMAT_S16, 2, 0 },
|
||||||
{ "s24", SF_FORMAT_PCM_24, SPA_AUDIO_FORMAT_S24, 3 },
|
/* we read and write S24 as S32 with sndfile */
|
||||||
{ "s32", SF_FORMAT_PCM_32, SPA_AUDIO_FORMAT_S32, 4 },
|
{ "s24", SF_FORMAT_PCM_24, 3, "s32", SPA_AUDIO_FORMAT_S32, 4, 0 },
|
||||||
{ "f32", SF_FORMAT_FLOAT, SPA_AUDIO_FORMAT_F32, 4 },
|
{ "s32", SF_FORMAT_PCM_32, 4, "s32", SPA_AUDIO_FORMAT_S32, 4, 0 },
|
||||||
{ "f64", SF_FORMAT_DOUBLE, SPA_AUDIO_FORMAT_F32, 8 },
|
{ "f32", SF_FORMAT_FLOAT, 4, "f32", SPA_AUDIO_FORMAT_F32, 4, 0 },
|
||||||
|
{ "f64", SF_FORMAT_DOUBLE, 8, "f64", SPA_AUDIO_FORMAT_F32, 8, 0 },
|
||||||
|
|
||||||
{ "mp1", SF_FORMAT_MPEG_LAYER_I, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "mp1", SF_FORMAT_MPEG_LAYER_I, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "mp2", SF_FORMAT_MPEG_LAYER_II, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "mp2", SF_FORMAT_MPEG_LAYER_II, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "mp3", SF_FORMAT_MPEG_LAYER_III, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "mp3", SF_FORMAT_MPEG_LAYER_III, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "vorbis", SF_FORMAT_VORBIS, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "vorbis", SF_FORMAT_VORBIS, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "opus", SF_FORMAT_OPUS, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "opus", SF_FORMAT_OPUS, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
|
|
||||||
{ "ima-adpcm", SF_FORMAT_IMA_ADPCM, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "ima-adpcm", SF_FORMAT_IMA_ADPCM, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "ms-adpcm", SF_FORMAT_MS_ADPCM, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "ms-adpcm", SF_FORMAT_MS_ADPCM, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "nms-adpcm-16", SF_FORMAT_NMS_ADPCM_16, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "nms-adpcm-16", SF_FORMAT_NMS_ADPCM_16, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "nms-adpcm-24", SF_FORMAT_NMS_ADPCM_24, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "nms-adpcm-24", SF_FORMAT_NMS_ADPCM_24, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "nms-adpcm-32", SF_FORMAT_NMS_ADPCM_32, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "nms-adpcm-32", SF_FORMAT_NMS_ADPCM_32, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
|
|
||||||
{ "alac-16", SF_FORMAT_ALAC_16, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "alac-16", SF_FORMAT_ALAC_16, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "alac-20", SF_FORMAT_ALAC_20, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "alac-20", SF_FORMAT_ALAC_20, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "alac-24", SF_FORMAT_ALAC_24, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "alac-24", SF_FORMAT_ALAC_24, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "alac-32", SF_FORMAT_ALAC_32, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "alac-32", SF_FORMAT_ALAC_32, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
|
|
||||||
{ "gsm610", SF_FORMAT_GSM610, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "gsm610", SF_FORMAT_GSM610, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "g721-32", SF_FORMAT_G721_32, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "g721-32", SF_FORMAT_G721_32, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "g723-24", SF_FORMAT_G723_24, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "g723-24", SF_FORMAT_G723_24, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "g723-40", SF_FORMAT_G723_40, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "g723-40", SF_FORMAT_G723_40, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "dwvw-12", SF_FORMAT_DWVW_12, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "dwvw-12", SF_FORMAT_DWVW_12, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "dwvw-16", SF_FORMAT_DWVW_16, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "dwvw-16", SF_FORMAT_DWVW_16, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "dwvw-24", SF_FORMAT_DWVW_24, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "dwvw-24", SF_FORMAT_DWVW_24, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "vox", SF_FORMAT_VOX_ADPCM, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "vox", SF_FORMAT_VOX_ADPCM, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "dpcm-16", SF_FORMAT_DPCM_16, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "dpcm-16", SF_FORMAT_DPCM_16, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
{ "dpcm-8", SF_FORMAT_DPCM_8, SPA_AUDIO_FORMAT_F32, 1 },
|
{ "dpcm-8", SF_FORMAT_DPCM_8, 1, "f32", SPA_AUDIO_FORMAT_F32, 4, FORMAT_ENCODED },
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct format_info *format_info_by_name(const char *str)
|
static const struct format_info *format_info_by_name(const char *str)
|
||||||
{
|
{
|
||||||
SPA_FOR_EACH_ELEMENT_VAR(format_info, i)
|
SPA_FOR_EACH_ELEMENT_VAR(format_info, i)
|
||||||
if (spa_streq(str, i->name))
|
if (spa_streq(str, i->sf_name))
|
||||||
return i;
|
return i;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +268,7 @@ static void list_formats(struct data *d)
|
||||||
|
|
||||||
fprintf(stdout, _("Supported formats:\n"));
|
fprintf(stdout, _("Supported formats:\n"));
|
||||||
SPA_FOR_EACH_ELEMENT_VAR(format_info, i)
|
SPA_FOR_EACH_ELEMENT_VAR(format_info, i)
|
||||||
fprintf(stdout, " %s\n", i->name);
|
fprintf(stdout, " %s\n", i->sf_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sf_playback_fill_x8(struct data *d, void *dest, unsigned int n_frames, bool *null_frame)
|
static int sf_playback_fill_x8(struct data *d, void *dest, unsigned int n_frames, bool *null_frame)
|
||||||
|
|
@ -1676,8 +1681,13 @@ static int setup_raw(struct data *data)
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (info->flags & FORMAT_ENCODED) {
|
||||||
|
fprintf(stderr, "raw: raw encoded format %s not supported\n", info->sf_name);
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
data->spa_format = info->spa_format;
|
data->spa_format = info->spa_format;
|
||||||
data->stride = info->width * data->channels;
|
data->stride = info->spa_width * data->channels;
|
||||||
data->fill = data->mode == mode_playback ? raw_play : raw_record;
|
data->fill = data->mode == mode_playback ? raw_play : raw_record;
|
||||||
|
|
||||||
if (spa_streq(data->filename, "-")) {
|
if (spa_streq(data->filename, "-")) {
|
||||||
|
|
@ -1696,7 +1706,7 @@ static int setup_raw(struct data *data)
|
||||||
if (data->verbose)
|
if (data->verbose)
|
||||||
fprintf(stderr, "raw: rate=%u channels=%u fmt=%s samplesize=%u stride=%u\n",
|
fprintf(stderr, "raw: rate=%u channels=%u fmt=%s samplesize=%u stride=%u\n",
|
||||||
data->rate, data->channels,
|
data->rate, data->channels,
|
||||||
info->name, info->width, data->stride);
|
info->spa_name, info->spa_width, data->stride);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -2034,14 +2044,10 @@ static int setup_sndfile(struct data *data)
|
||||||
|
|
||||||
if (data->verbose)
|
if (data->verbose)
|
||||||
fprintf(stderr, "PCM: fmt:%s rate:%u channels:%u width:%u\n",
|
fprintf(stderr, "PCM: fmt:%s rate:%u channels:%u width:%u\n",
|
||||||
fi->name, data->rate, data->channels, fi->width);
|
fi->spa_name, data->rate, data->channels, fi->spa_width);
|
||||||
|
|
||||||
/* we read and write S24 as S32 with sndfile */
|
|
||||||
if (fi->spa_format == SPA_AUDIO_FORMAT_S24)
|
|
||||||
fi = format_info_by_sf_format(SF_FORMAT_PCM_32);
|
|
||||||
|
|
||||||
data->spa_format = fi->spa_format;
|
data->spa_format = fi->spa_format;
|
||||||
data->stride = fi->width * data->channels;
|
data->stride = fi->spa_width * data->channels;
|
||||||
data->fill = data->mode == mode_playback ?
|
data->fill = data->mode == mode_playback ?
|
||||||
playback_fill_fn(data->spa_format) :
|
playback_fill_fn(data->spa_format) :
|
||||||
record_fill_fn(data->spa_format);
|
record_fill_fn(data->spa_format);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue