Keep multiview captions and controls below video and use logarithmic volume

This commit is contained in:
evgeny committed 2026-11-01 22:23:09 +01:00
1 parent 213a1010c2
commit 5a8807bf89
3 files changed
+24 -9

No files matched your search

+15 -6
View File
@@ -29,10 +29,12 @@ QString text(const char* value) { return QCoreApplication::translate("ChatGui",
StreamGridWindow::StreamGridWindow(uint64_t group, QWidget* parent)
: QWidget(parent), m_group(group), m_owner(++nextOwner) {
setWindowTitle(text("All active streams")); resize(1100, 750); m_clock.start();
auto* layout = new QVBoxLayout(this); auto* controls = new QHBoxLayout;
m_status = new QLabel(text("Connecting…"), this); controls->addWidget(m_status, 1);
auto* fullscreen = new QPushButton(text("Fullscreen"), this); controls->addWidget(fullscreen);
m_close = new QPushButton(text("Close player"), this); controls->addWidget(m_close); layout->addLayout(controls);
auto* layout = new QVBoxLayout(this);
m_controls = new QWidget(this); m_controls->setObjectName(QStringLiteral("streamGridControls"));
auto* controls = new QHBoxLayout(m_controls); controls->setContentsMargins(0, 0, 0, 0);
m_status = new QLabel(text("Connecting…"), m_controls); controls->addWidget(m_status, 1);
auto* fullscreen = new QPushButton(text("Fullscreen"), m_controls); controls->addWidget(fullscreen);
m_close = new QPushButton(text("Close player"), m_controls); controls->addWidget(m_close);
connect(fullscreen, &QPushButton::clicked, this, [this] { if (isFullScreen()) showNormal(); else showFullScreen(); });
connect(m_close, &QPushButton::clicked, this, [this] { if (m_focused) restoreGrid(); else close(); });
auto* escape = new QShortcut(QKeySequence(Qt::Key_Escape), this); escape->setContext(Qt::WidgetWithChildrenShortcut);
@@ -44,6 +46,7 @@ StreamGridWindow::StreamGridWindow(uint64_t group, QWidget* parent)
m_empty = new QLabel(text("Waiting for active streams…"), this); m_empty->setAlignment(Qt::AlignCenter);
layout->addWidget(m_empty);
m_grid = new QGridLayout; m_grid->setSpacing(4); layout->addLayout(m_grid, 1);
layout->addWidget(m_controls);
m_watching = gui_stream_watch(m_group, m_owner);
connect(&m_timer, &QTimer::timeout, this, &StreamGridWindow::tick); m_timer.start(250);
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop multiview opened group=%llx owner=%llu",
@@ -59,8 +62,8 @@ void StreamGridWindow::createTile(Tile& tile) {
tile.widget->setObjectName(QStringLiteral("streamPreview_%1").arg(tile.source));
auto* layout = new QVBoxLayout(tile.widget); layout->setContentsMargins(3, 3, 3, 3); layout->setSpacing(2);
tile.title = new QLabel(tile.name, tile.widget); tile.title->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
tile.title->setToolTip(tile.name); layout->addWidget(tile.title);
tile.status = new QLabel(text("Connecting…"), tile.widget); layout->addWidget(tile.status);
tile.title->setToolTip(tile.name);
tile.status = new QLabel(text("Connecting…"), tile.widget);
#ifdef HAVE_STREAM_CAPTURE
auto* preview = new VideoRenderWidget(tile.widget);
tile.video = preview;
@@ -68,12 +71,16 @@ void StreamGridWindow::createTile(Tile& tile) {
tile.video = new QLabel(text("Video capture requires Qt Multimedia and FFmpeg"), tile.widget);
#endif
tile.video->setToolTip(text("Manage stream")); layout->addWidget(tile.video, 1);
layout->addWidget(tile.title); layout->addWidget(tile.status);
updatePreview(tile);
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop multiview local preview group=%llx source=%llx epoch=%llx decoder=0 audio=0",
(unsigned long long)m_group, (unsigned long long)tile.source, (unsigned long long)tile.epoch);
} else {
tile.player = new StreamPlayerWindow(m_group, tile.source, tile.epoch, tile.name, this, true);
tile.widget = tile.player; tile.video = tile.player->findChild<VideoRenderWidget*>();
connect(tile.player, &StreamPlayerWindow::fullscreenRequested, this,
[this] { if (isFullScreen()) showNormal(); else showFullScreen(); });
connect(tile.player, &StreamPlayerWindow::closeRequested, this, &StreamGridWindow::restoreGrid);
}
if (!tile.video) {
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop multiview tile has no video source=%llx", (unsigned long long)tile.source); return;
@@ -215,12 +222,14 @@ void StreamGridWindow::arrange() {
for (int i = 0; i < m_side; ++i) { m_grid->setRowStretch(i, 1); m_grid->setColumnStretch(i, 1); }
for (size_t i = 0; i < m_tiles.size(); ++i) {
auto& tile = m_tiles[i];
if (tile.player) tile.player->setWindowControlsVisible(m_focused == tile.source);
if (m_focused && m_focused != tile.source) { tile.widget->hide(); continue; }
if (m_focused) m_grid->addWidget(tile.widget, 0, 0, m_side, m_side);
else m_grid->addWidget(tile.widget, static_cast<int>(i) / m_side, static_cast<int>(i) % m_side);
tile.widget->show();
}
m_empty->setVisible(m_tiles.empty());
m_controls->setVisible(!m_focused);
m_close->setText(text(m_focused ? "All active streams" : "Close player"));
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop multiview layout group=%llx tiles=%zu grid=%dx%d focused=%llx",
(unsigned long long)m_group, m_tiles.size(), m_side, m_side, (unsigned long long)m_focused);
+1
View File
@@ -64,6 +64,7 @@ private:
std::vector<Tile> m_tiles; // Каждый widget принадлежит окну; удаляется целиком при смене идентичности/stop.
// Элементы интерфейса принадлежат QObject-дереву этого окна.
QGridLayout* m_grid = nullptr;
QWidget* m_controls = nullptr; // Общая нижняя панель сетки; при focus её заменяет нижняя панель выбранного player.
QLabel* m_status = nullptr;
QLabel* m_empty = nullptr;
QPushButton* m_close = nullptr;
+8 -3
View File
@@ -25,6 +25,7 @@
#include <algorithm>
#include <cstring>
#include <cerrno>
#include <cmath>
extern "C" {
#include "../../../lib/debug_config.h"
@@ -199,7 +200,7 @@ StreamPlayerWindow::StreamPlayerWindow(uint64_t group, uint64_t source, uint64_t
auto* volumeBox = new QWidget(bar); auto* volumeLayout = new QVBoxLayout(volumeBox);
volumeLayout->setContentsMargins(0, 0, 0, 0); volumeLayout->setSpacing(0);
auto* volume = new StreamVolumeSlider(volumeBox); volume->setObjectName(QStringLiteral("streamVolume"));
volume->setAccessibleName(text("Stream volume")); volume->setToolTip(QStringLiteral("100%")); volumeLayout->addWidget(volume);
volume->setAccessibleName(text("Stream volume")); volume->setToolTip(QStringLiteral("0 dB")); volumeLayout->addWidget(volume);
auto* volumeLabel = new QLabel(text("Volume"), volumeBox); volumeLabel->setAlignment(Qt::AlignCenter);
volumeLayout->addWidget(volumeLabel); controls->addWidget(volumeBox);
m_fullscreen = new QPushButton(text("Fullscreen"), bar); m_fullscreen->setObjectName(QStringLiteral("streamFullscreen"));
@@ -210,8 +211,12 @@ StreamPlayerWindow::StreamPlayerWindow(uint64_t group, uint64_t source, uint64_t
setWindowControlsVisible(false); layout->setContentsMargins(3, 3, 3, 3); layout->setSpacing(2); setMinimumSize(0, 0);
}
connect(volume, &QSlider::valueChanged, this, [this, volume](int value) {
m_playback->volume = value / 100.0f; volume->setToolTip(QStringLiteral("%1%").arg(value));
DEBUG_DEBUG(DEBUG_CATEGORY_STREAM, "desktop viewer volume id=%llu percent=%d", (unsigned long long)m_playback->id, value);
const float decibels = (value - 100) * 0.6f;
const float gain = value ? std::pow(10.0f, decibels / 20.0f) : 0.0f;
m_playback->volume = gain;
volume->setToolTip(value ? QStringLiteral("%1 dB").arg(decibels, 0, 'f', 1) : QStringLiteral("−∞ dB"));
DEBUG_DEBUG(DEBUG_CATEGORY_STREAM, "desktop viewer volume id=%llu position=%d gain=%.6f",
(unsigned long long)m_playback->id, value, gain);
});
connect(m_fullscreen, &QPushButton::clicked, this, [this, embedded] {
if (embedded) emit fullscreenRequested(); else if (isFullScreen()) showNormal(); else showFullScreen();