diff --git a/src/examples/media-session/alsa-monitor.c b/src/examples/media-session/alsa-monitor.c index 38a2f9215..d97a45a66 100644 --- a/src/examples/media-session/alsa-monitor.c +++ b/src/examples/media-session/alsa-monitor.c @@ -908,6 +908,7 @@ static struct device *alsa_create_device(struct impl *impl, uint32_t id, if (impl->conn && (card = spa_dict_lookup(info->props, SPA_KEY_API_ALSA_CARD)) != NULL) { const char *reserve; + const char *path = spa_dict_lookup(info->props, SPA_KEY_API_ALSA_PATH); device->priority -= atol(card) * 64; @@ -920,9 +921,10 @@ static struct device *alsa_create_device(struct impl *impl, uint32_t id, if (device->reserve == NULL) { pw_log_warn("can't create device reserve for %s: %m", reserve); + } else if (path) { + rd_device_set_application_device_name(device->reserve, path); } else { - rd_device_set_application_device_name(device->reserve, - spa_dict_lookup(info->props, SPA_KEY_API_ALSA_PATH)); + pw_log_warn("empty reserve device path for %s", reserve); } } if (device->reserve != NULL) diff --git a/src/examples/media-session/policy-node.c b/src/examples/media-session/policy-node.c index 5f9aca3f3..583c283ab 100644 --- a/src/examples/media-session/policy-node.c +++ b/src/examples/media-session/policy-node.c @@ -536,7 +536,7 @@ static int find_node(void *data, struct node *node) return 0; } - if (strcmp(node->media, find->media) != 0) { + if (node->media && strcmp(node->media, find->media) != 0) { pw_log_debug(".. incompatible media %s <-> %s", node->media, find->media); return 0; } diff --git a/src/examples/media-session/restore-stream.c b/src/examples/media-session/restore-stream.c index f37b3fed8..c5c373c9c 100644 --- a/src/examples/media-session/restore-stream.c +++ b/src/examples/media-session/restore-stream.c @@ -158,11 +158,13 @@ static char *serialize_props(struct stream *str, const struct spa_pod *param) SPA_POD_OBJECT_FOREACH(obj, prop) { switch (prop->key) { case SPA_PROP_volume: - spa_pod_get_float(&prop->value, &val); + if (spa_pod_get_float(&prop->value, &val) < 0) + continue; fprintf(f, "%s\"volume\": %f", (comma ? ", " : ""), val); break; case SPA_PROP_mute: - spa_pod_get_bool(&prop->value, &b); + if (spa_pod_get_bool(&prop->value, &b) < 0) + continue; fprintf(f, "%s\"mute\": %s", (comma ? ", " : ""), b ? "true" : "false"); break; case SPA_PROP_channelVolumes: diff --git a/src/modules/module-protocol-pulse/collect.c b/src/modules/module-protocol-pulse/collect.c index 32bbfa075..13f312ac5 100644 --- a/src/modules/module-protocol-pulse/collect.c +++ b/src/modules/module-protocol-pulse/collect.c @@ -615,7 +615,8 @@ static uint32_t collect_transport_codec_info(struct pw_manager_object *card, /* Codec description list */ spa_pod_parser_pod(&prs, (struct spa_pod *)labels); - spa_pod_parser_push_struct(&prs, &f); + if (spa_pod_parser_push_struct(&prs, &f) < 0) + continue; while (1) { int32_t id; diff --git a/src/modules/module-protocol-pulse/ext-stream-restore.c b/src/modules/module-protocol-pulse/ext-stream-restore.c index 868e33401..e7b75f52c 100644 --- a/src/modules/module-protocol-pulse/ext-stream-restore.c +++ b/src/modules/module-protocol-pulse/ext-stream-restore.c @@ -212,13 +212,14 @@ static int do_extension_stream_restore_write(struct client *client, uint32_t com spa_zero(map); spa_zero(vol); - message_get(m, - TAG_STRING, &name, - TAG_CHANNEL_MAP, &map, - TAG_CVOLUME, &vol, - TAG_STRING, &device_name, - TAG_BOOLEAN, &mute, - TAG_INVALID); + if (message_get(m, + TAG_STRING, &name, + TAG_CHANNEL_MAP, &map, + TAG_CVOLUME, &vol, + TAG_STRING, &device_name, + TAG_BOOLEAN, &mute, + TAG_INVALID) < 0) + return -EPROTO; if (name == NULL || name[0] == '\0') return -EPROTO; @@ -247,9 +248,10 @@ static int do_extension_stream_restore_write(struct client *client, uint32_t com if (key_from_name(name, key, sizeof(key)) >= 0) { pw_log_debug("%s -> %s: %s", name, key, ptr); - pw_manager_set_metadata(client->manager, - client->metadata_routes, - PW_ID_CORE, key, "Spa:String:JSON", "%s", ptr); + if (pw_manager_set_metadata(client->manager, + client->metadata_routes, + PW_ID_CORE, key, "Spa:String:JSON", "%s", ptr) < 0) + pw_log_warn(NAME ": failed to set metadata %s = %s", key, ptr); } free(ptr); } diff --git a/src/modules/module-protocol-pulse/format.c b/src/modules/module-protocol-pulse/format.c index f4424cd3f..1528dda1a 100644 --- a/src/modules/module-protocol-pulse/format.c +++ b/src/modules/module-protocol-pulse/format.c @@ -537,7 +537,8 @@ static int format_parse_param(const struct spa_pod *param, struct sample_spec *s struct spa_audio_info info = { 0 }; uint32_t i; - spa_format_parse(param, &info.media_type, &info.media_subtype); + if (spa_format_parse(param, &info.media_type, &info.media_subtype) < 0) + return -ENOTSUP; if (info.media_type != SPA_MEDIA_TYPE_audio || info.media_subtype != SPA_MEDIA_SUBTYPE_raw || diff --git a/src/modules/module-protocol-pulse/manager.c b/src/modules/module-protocol-pulse/manager.c index f95ae3692..84436c594 100644 --- a/src/modules/module-protocol-pulse/manager.c +++ b/src/modules/module-protocol-pulse/manager.c @@ -522,11 +522,13 @@ destroy_proxy(void *data) { struct object *o = data; + spa_assert(o->info); + if (o->info->events) spa_hook_remove(&o->object_listener); spa_hook_remove(&o->proxy_listener); - if (o->info && o->info->destroy) + if (o->info->destroy) o->info->destroy(o); o->this.proxy = NULL; diff --git a/src/modules/module-protocol-pulse/message.c b/src/modules/module-protocol-pulse/message.c index 4bdbf15d4..89a7d06ff 100644 --- a/src/modules/module-protocol-pulse/message.c +++ b/src/modules/module-protocol-pulse/message.c @@ -326,7 +326,7 @@ static int read_format_info(struct message *m, struct format_info *info) static int message_get(struct message *m, ...) { va_list va; - int res; + int res = 0; va_start(va, m); @@ -342,102 +342,109 @@ static int message_get(struct message *m, ...) switch (dtag) { case TAG_STRING: if (tag != TAG_STRING) - return -EINVAL; + goto invalid; if ((res = read_string(m, va_arg(va, char**))) < 0) - return res; + goto done; break; case TAG_STRING_NULL: if (tag != TAG_STRING) - return -EINVAL; + goto invalid; *va_arg(va, char**) = NULL; break; case TAG_U8: if (dtag != tag) - return -EINVAL; + goto invalid; if ((res = read_u8(m, va_arg(va, uint8_t*))) < 0) - return res; + goto done; break; case TAG_U32: if (dtag != tag) - return -EINVAL; + goto invalid; if ((res = read_u32(m, va_arg(va, uint32_t*))) < 0) - return res; + goto done; break; case TAG_S64: case TAG_U64: case TAG_USEC: if (dtag != tag) - return -EINVAL; + goto invalid; if ((res = read_u64(m, va_arg(va, uint64_t*))) < 0) - return res; + goto done; break; case TAG_SAMPLE_SPEC: if (dtag != tag) - return -EINVAL; + goto invalid; if ((res = read_sample_spec(m, va_arg(va, struct sample_spec*))) < 0) - return res; + goto done; break; case TAG_ARBITRARY: { const void **val = va_arg(va, const void**); size_t *len = va_arg(va, size_t*); if (dtag != tag) - return -EINVAL; + goto invalid; if ((res = read_arbitrary(m, val, len)) < 0) - return res; + goto done; break; } case TAG_BOOLEAN_TRUE: if (tag != TAG_BOOLEAN) - return -EINVAL; + goto invalid; *va_arg(va, bool*) = true; break; case TAG_BOOLEAN_FALSE: if (tag != TAG_BOOLEAN) - return -EINVAL; + goto invalid; *va_arg(va, bool*) = false; break; case TAG_TIMEVAL: if (dtag != tag) - return -EINVAL; + goto invalid; if ((res = read_timeval(m, va_arg(va, struct timeval*))) < 0) - return res; + goto done; break; case TAG_CHANNEL_MAP: if (dtag != tag) - return -EINVAL; + goto invalid; if ((res = read_channel_map(m, va_arg(va, struct channel_map*))) < 0) - return res; + goto done; break; case TAG_CVOLUME: if (dtag != tag) - return -EINVAL; + goto invalid; if ((res = read_cvolume(m, va_arg(va, struct volume*))) < 0) - return res; + goto done; break; case TAG_PROPLIST: if (dtag != tag) - return -EINVAL; + goto invalid; if ((res = read_props(m, va_arg(va, struct pw_properties*), true)) < 0) - return res; + goto done; break; case TAG_VOLUME: if (dtag != tag) - return -EINVAL; + goto invalid; if ((res = read_volume(m, va_arg(va, float*))) < 0) - return res; + goto done; break; case TAG_FORMAT_INFO: if (dtag != tag) - return -EINVAL; + goto invalid; if ((res = read_format_info(m, va_arg(va, struct format_info*))) < 0) - return res; + goto done; break; } } + res = 0; + goto done; + +invalid: + res = -EINVAL; + +done: va_end(va); - return 0; + return res; } static int ensure_size(struct message *m, uint32_t size) diff --git a/src/modules/module-protocol-pulse/pulse-server.c b/src/modules/module-protocol-pulse/pulse-server.c index 145186742..e6c678876 100644 --- a/src/modules/module-protocol-pulse/pulse-server.c +++ b/src/modules/module-protocol-pulse/pulse-server.c @@ -1914,7 +1914,7 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui struct channel_map map; uint32_t sink_index, syncid; const char *sink_name; - struct buffer_attr attr; + struct buffer_attr attr = { 0 }; bool corked = false, no_remap = false, no_remix = false, @@ -2178,8 +2178,8 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint fail_on_suspend = false, relative_volume = false, passthrough = false; - uint32_t direct_on_input_idx; - struct volume volume; + uint32_t direct_on_input_idx = SPA_ID_INVALID; + struct volume volume = VOLUME_INIT; struct pw_properties *props = NULL; uint8_t n_formats = 0; struct stream *stream = NULL; @@ -2287,6 +2287,8 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint TAG_BOOLEAN, &passthrough, TAG_INVALID)) < 0) goto error_protocol; + } else { + volume_set = false; } if (sample_spec_valid(&ss)) { if (n_params < MAX_FORMATS && @@ -4576,7 +4578,10 @@ error: static uint64_t bytes_to_usec(uint64_t length, const struct sample_spec *ss) { uint64_t u; - u = length / sample_spec_frame_size(ss); + uint64_t frame_size = sample_spec_frame_size(ss); + if (frame_size == 0) + return 0; + u = length / frame_size; u *= SPA_USEC_PER_SEC; u /= ss->rate; return u; diff --git a/src/modules/module-protocol-pulse/volume.c b/src/modules/module-protocol-pulse/volume.c index cb72f780d..33a228d14 100644 --- a/src/modules/module-protocol-pulse/volume.c +++ b/src/modules/module-protocol-pulse/volume.c @@ -91,13 +91,15 @@ static int volume_parse_param(const struct spa_pod *param, struct volume_info *i SPA_POD_OBJECT_FOREACH(obj, prop) { switch (prop->key) { case SPA_PROP_volume: - spa_pod_get_float(&prop->value, &info->level); + if (spa_pod_get_float(&prop->value, &info->level) < 0) + continue; SPA_FLAG_UPDATE(info->flags, VOLUME_HW_VOLUME, prop->flags & SPA_POD_PROP_FLAG_HARDWARE); break; case SPA_PROP_mute: - spa_pod_get_bool(&prop->value, &info->mute); + if (spa_pod_get_bool(&prop->value, &info->mute) < 0) + continue; SPA_FLAG_UPDATE(info->flags, VOLUME_HW_MUTE, prop->flags & SPA_POD_PROP_FLAG_HARDWARE); break; @@ -108,7 +110,8 @@ static int volume_parse_param(const struct spa_pod *param, struct volume_info *i prop->flags & SPA_POD_PROP_FLAG_HARDWARE); break; case SPA_PROP_volumeBase: - spa_pod_get_float(&prop->value, &info->base); + if (spa_pod_get_float(&prop->value, &info->base) < 0) + continue; break; case SPA_PROP_volumeStep: {