diff --git a/src/radio/radio.c b/src/radio/radio.c index 90f43d00..89526f92 100644 --- a/src/radio/radio.c +++ b/src/radio/radio.c @@ -24,6 +24,7 @@ #include "../routing_layer/topo_group.h" #include "../routing_layer/topo_node_sqlite.h" #include "../chat/chat_event.h" +#include "../stream/stream.h" #include "radio.h" #include "radio_proto.h" @@ -492,6 +493,15 @@ int radio_member_muted(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t n return 0; } +int radio_member_silenced(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id) { + return radio_member_muted(inst, group_id, node_id) || stream_radio_muted(inst, group_id, node_id); +} + +void radio_refresh_member_mute(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id) { + struct radio_instance* ri = radio_inst(inst); + if (ri && ri->mute_fn) ri->mute_fn(inst, group_id, node_id, radio_member_silenced(inst, group_id, node_id), ri->mute_arg); +} + void radio_forget_member_mute(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id) { if (!inst || !inst->topo_groups) return; struct radio_ctx* ctx = radio_of(topo_groups_find(inst->topo_groups, group_id)); @@ -535,8 +545,7 @@ int radio_set_member_muted(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64 } if (muted && slot < 0) ctx->muted_members[ctx->muted_count++] = node_id; else if (!muted && slot >= 0) ctx->muted_members[slot] = ctx->muted_members[--ctx->muted_count]; - struct radio_instance* ri = radio_inst(inst); - if (ri && ri->mute_fn) ri->mute_fn(inst, group_id, node_id, muted, ri->mute_arg); + radio_refresh_member_mute(inst, group_id, node_id); DEBUG_INFO(DEBUG_CATEGORY_RADIO, "radio: local member mute grp=%016llx node=%016llx muted=%d", (unsigned long long)group_id, (unsigned long long)node_id, muted); return 0; diff --git a/src/radio/radio.h b/src/radio/radio.h index 18819216..c5a21b00 100644 --- a/src/radio/radio.h +++ b/src/radio/radio.h @@ -35,6 +35,10 @@ void radio_set_frame_cb(struct UTUN_INSTANCE* inst, radio_frame_fn fn, void* arg /* Локальные настройки участников: только uasync, без изменения подписки и пересылки. */ int radio_member_muted(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id); +/* Итог для воспроизведения: ручное отключение или просмотр трансляции источника со звуком. */ +int radio_member_silenced(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id); +/* Изменилось временное подавление; настройки в БД и подписка остаются прежними. */ +void radio_refresh_member_mute(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id); int radio_set_member_muted(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id, int muted); /* После удаления записи участника из БД удалить её из локального кэша. */ void radio_forget_member_mute(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id); diff --git a/src/stream/stream.h b/src/stream/stream.h index b1879d18..6f8b9ea7 100644 --- a/src/stream/stream.h +++ b/src/stream/stream.h @@ -69,11 +69,15 @@ int stream_sources_json(struct UTUN_INSTANCE *inst, uint64_t group_id, char **ou int stream_watch_sources(struct UTUN_INSTANCE *inst, uint64_t group_id); /* Локальный owner удерживает эффективный ACTIVE; желаемый frontend-режим ядро восстанавливает после последнего close. */ int stream_service_needs_activity(const struct UTUN_INSTANCE *inst); +/* Только локальный viewer этой группы/эпохи подавляет рацию источника со включённым звуком. */ +int stream_radio_muted(struct UTUN_INSTANCE *inst, uint64_t group_id, uint64_t source_id); /* out заранее NULL. parameters=NULL — 6+2, часть до 1300 байт и одна подпись пачки внутри RS. * Одна публикация этого узла в группе; новый запуск получает новый source_epoch. */ int stream_publish_open(struct UTUN_INSTANCE *inst, uint64_t group_id, const struct stream_parameters *parameters, struct STREAM_HANDLE **out); +/* Меняет подписанное состояние звука, не формат медиатреков. Только uasync; raw publisher начинает с 0. */ +int stream_publish_set_audio_enabled(struct STREAM_HANDLE *handle, int enabled); /* Параметры берутся из подписанного профиля источника; дубликаты локальных владельцев делят один буфер. * WAIT — источник ещё не объявил/не подтвердил трансляцию. Offline не создаёт ложного онлайн-кандидата. */ int stream_subscribe_open(struct UTUN_INSTANCE *inst, uint64_t group_id, uint64_t source_id, struct STREAM_HANDLE **out);