73 lines
3.4 KiB
C++
73 lines
3.4 KiB
C++
/* Окно всех активных трансляций одного канала. Собственный catalogue owner не зависит от выбранного чата.
|
|
* Плитка сохраняет player/decoder/часы при перекладке; новая эпоха заменяет только соответствующий player.
|
|
* Своя плитка получает setLocalPreview до кодирования, без reader/audio; клик запрашивает управление.
|
|
* Чужая плитка разворачивается без пересоздания players; Esc/повторный клик возвращает сетку.
|
|
* Пропавшему источнику даётся дочитать FIN, затем плитка удаляется. Пустое окно ждёт новые публикации. */
|
|
#pragma once
|
|
#include <QWidget>
|
|
#include <QTimer>
|
|
#include <QElapsedTimer>
|
|
#include <QPointer>
|
|
#include <QVariant>
|
|
#include <vector>
|
|
#include <cstdint>
|
|
|
|
class StreamPlayerWindow;
|
|
class QGridLayout;
|
|
class QLabel;
|
|
class QPushButton;
|
|
class QCloseEvent;
|
|
|
|
class StreamGridWindow : public QWidget {
|
|
Q_OBJECT
|
|
public:
|
|
explicit StreamGridWindow(uint64_t group, QWidget* parent = nullptr);
|
|
~StreamGridWindow() override;
|
|
uint64_t group() const { return m_group; }
|
|
void onSources(const uint8_t* data, int length);
|
|
void setLocalPreview(uint64_t group, const QVariant& frame); // Последний QVideoFrame локального publisher, GUI-поток.
|
|
int tileCount() const { return static_cast<int>(m_tiles.size()); }
|
|
int gridSide() const { return m_side; }
|
|
uint64_t focusedSource() const { return m_focused; }
|
|
signals:
|
|
void publishRequested(quint64 group); // Открыть управление своей публикацией, сохранив это окно.
|
|
protected:
|
|
void closeEvent(QCloseEvent* event) override;
|
|
bool eventFilter(QObject* watched, QEvent* event) override;
|
|
private:
|
|
struct Tile {
|
|
uint64_t source, epoch;
|
|
QString name;
|
|
bool self = false, previewPresented = false;
|
|
QWidget* widget = nullptr; // Владеет player либо прямым preview, удаляется целиком.
|
|
QWidget* video = nullptr; // Поверхность изображения; сюда направлены клики.
|
|
StreamPlayerWindow* player = nullptr;
|
|
QLabel* status = nullptr; // Статус прямого preview; у remote им владеет player.
|
|
qint64 removeAt = -1, retryAt = 0;
|
|
unsigned failures = 0;
|
|
};
|
|
uint64_t m_group, m_owner;
|
|
std::vector<Tile> m_tiles;
|
|
QGridLayout* m_grid = nullptr;
|
|
QLabel* m_status = nullptr;
|
|
QLabel* m_empty = nullptr;
|
|
QPushButton* m_close = nullptr;
|
|
QVariant m_preview; // Только последний кадр издателя; сеть/декодер для self не открываются.
|
|
QTimer m_timer;
|
|
QElapsedTimer m_clock;
|
|
int m_side = 0;
|
|
bool m_watching = false, m_closed = false;
|
|
uint64_t m_focused = 0; // Source развёрнутой чужой плитки; 0 — сетка.
|
|
Qt::WindowStates m_gridWindowState;
|
|
QPointer<QObject> m_pressed;
|
|
QPoint m_pressPosition;
|
|
bool m_dragged = false;
|
|
void createTile(Tile& tile);
|
|
void updatePreview(Tile& tile);
|
|
void activateTile(uint64_t source);
|
|
void restoreGrid();
|
|
void arrange();
|
|
void tick();
|
|
void stop();
|
|
};
|