Files
utun2/tools/chatgui/src/callwindow.h
T

112 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* GUI-представление одного звонка. Владелец задаёт ID/имя/состояние и удаляет окно по closed (обычно deleteLater).
* Все методы/сигналы — GUI-поток. CallVideoEngine и отдельное окно видео принадлежат этому QWidget;
* аудио обслуживает общий CallAudioEngine, его native lifecycle координирует MainWindow. */
#pragma once
#include <QWidget>
#include <QImage>
#include <cstdint>
#include "call_camera_capture.h"
class QLabel;
class QPushButton;
class QMenu;
class QMenuBar;
class QTimer;
class QSpinBox;
class CallVideoEngine;
class CallVideoWindow;
/* GUI-окно звонка: Outgoing (соединение), Ringing (доставлен вызов), Incoming (принять/отклонить),
* Active (разговор/таймер), Ended (завершён), WaitDecision (явное разрешение звонить занятому телефону).
* Команды передаются через typed API моста без заимствованного instance/heap payload в GUI.
* Кнопки при отказе постановки сохраняют состояние и показывают ошибку.
* Close переводит локальное состояние в Ended, останавливает видео/таймер и отправляет Decline для Incoming,
* Hangup для остальных живых состояний; повторный close/закрытие Ended не отправляет команду.
* Окно закрывается и при отказе очереди с WARN; завершение native-сессии подтверждают события ядра. */
class CallWindow : public QWidget {
Q_OBJECT
public:
enum State { Outgoing, Ringing, Incoming, Active, Ended, WaitDecision };
explicit CallWindow(QWidget* parent = nullptr); // Создаёт UI и дочерний видеодвижок, но не native-звонок.
~CallWindow() override; // Снимает video callbacks и останавливает движок; native-команда отправляется только через closeEvent/кнопки.
void setCallId(quint64 id) { m_callId = id; } // Ненулевой ID до действий пользователя; setter сам не запускает сессию.
quint64 callId() const { return m_callId; } // ID для команд моста и сигнала closed.
void setPeerName(const QString& name); // Имя, буквенная аватарка и заголовок отдельного видеоокна.
void setBgpPath(const QString& path); // Текст пути; показывается в диагностике Active при непустой строке.
void setConnectionType(uint8_t type, quint64 nextHop); // 0/1/2/3 — нет/direct/reverse/indirect; nextHop в tooltip только для 3.
// rtt/buffer/minimum/maximum/reserve — мс; tempo=100 для 1x, dropped/underruns — счётчики; min/max за 10с.
void setAudioStats(int rtt, int buffer, int tempo, int dropped, int underruns, int minimum, int maximum, int reserve);
void setState(State s); // Локальное GUI-состояние; каждый Active сбрасывает длительность/mute, Ended останавливает видео/таймер.
State state() const { return m_state; } // Текущее локальное состояние представления.
signals:
void closed(quint64 callId); // После локальной очистки/постановки команды; удаления QWidget и ожидания native-ответа здесь нет.
protected:
void closeEvent(QCloseEvent* event) override;
private slots:
void onAccept(); // После принятия команды мостом прекращает гудок и переводит GUI в Active.
void onDecline(); // Ставит Decline; закрытие по native-результату выполняет MainWindow.
void onHangup(); // Ставит Hangup; при отказе сохраняет окно и показывает ошибку.
void updateDuration(); // Только Active: прошедшее wall-clock время в минуты:секунды.
void onMuteToggled(bool checked); // Меняет mute общего аудиодвижка, иконку и подпись.
void onDeviceChanged(); // Применяет backend ID выбранного аудиовыхода m_output.
private:
void updateButtons(); // Видимость действий по State, затем общая раскладка видео.
void populateOutputDevices(); // Выходы SoundManager: пустой ID — default, текущий выбор из CallAudioEngine.
void refreshVideoModes(); // Уникальные размеры выбранной камеры, затем доступные FPS; сохраняет текущий допустимый режим.
void updateVideoMenuButtons(); // Текущие camera/codec/resolution/FPS/bitrate/output внутри кнопок, полные названия в подсказках.
void applyVideo(); // Применяет выбранную камеру/режим; без доступного режима отправку видео отключает.
void updateVideoPresentation(); // Отдельное remote-видео, локальный preview, настройки и диагностические подписи.
CallVideoEngine* m_video; // Дочерний TX/RX/показ; start по таймеру 100мс только при Active и совпадающем активном аудиозвонке.
QPushButton* m_videoEnabled; // Круглая checkable-кнопка отправки видео; наличие camera mode проверяется отдельно.
QMenuBar* m_videoMenuBar; // Общий стиль трансляции: кнопки 48x48, значки 40x36, переключение раскрытых меню одним кликом.
QMenu *m_camera, *m_resolution, *m_fps, *m_codec, *m_bitrate, *m_output; // checked QAction/data хранит выбранный вариант.
CallCameraDevices m_cameras; // Последний полный снимок worker; режимы не переносятся между разными ID камер.
QList<StreamVideoMode> m_modes; // Допустимые пары resolution/FPS текущей камеры.
QSpinBox *m_videoMin, *m_videoMax; // Диапазон 300..4000 кбит/с; native port получает бит/с.
QLabel *m_localPreview, *m_videoStatus; // Малый локальный preview и статус/ошибка видеодвижка.
QWidget *m_videoControls, *m_panel; // Сворачиваемые настройки и центральная панель шириной до 640.
CallVideoWindow* m_videoWindow; // Дочернее Qt::Window; закрытие скрывает картинку, звонок продолжает работать.
QPushButton *m_settingsBtn, *m_showVideoBtn; // Раскрытие настроек и повторное открытие remote-видео.
QPushButton* m_diagnosticsBtn; // Независимый checkable-переключатель блока метрик, по умолчанию выключен.
QWidget* m_diagnostics; // Тип соединения, BGP-путь, аудиобуфер/RTT/latency; скрытие не останавливает сбор метрик.
QImage m_remoteImage, m_localImage; // Последние shared-кадры; видеодвижок очищает их при stop.
bool m_receivingVideo = false; // Active + непустой remote-кадр; не признак видимости отдельного окна.
quint64 m_videoCall = 0; // ID, с которым запущен видеодвижок; 0 после Ended/close.
bool m_videoRangeReady = false; // Начальный native bitrate range уже прочитан после start видео.
quint64 m_callId = 0; // ID UI-сессии, по нему MainWindow индексирует окна.
State m_state = Outgoing; // Локальное состояние окна, не подтверждение готовности native-транспорта.
qint64 m_startMs = 0; // Wall-clock QDateTime в мс на последнем переходе Active.
QLabel* m_avatarLabel; // Буквенная аватарка 80×80.
QLabel* m_peerLabel; // Имя собеседника.
QLabel* m_statusLabel; // Состояние вызова либо ошибка capture/постановки команды.
QLabel* m_durationLabel; // Минуты:секунды с последнего Active.
QLabel* m_bgpPathLabel; // BGP-путь, скрыт вне Active.
QLabel* m_connectionLabel; // Тип соединения и relay tooltip.
QLabel* m_statsLabel; // Буфер/tempo/RTT/счётчики и доступная диагностика output latency.
QPushButton* m_acceptBtn; // Accept для Incoming; Active устанавливается после принятия команды мостом.
QPushButton* m_continueBtn; /* явное разрешение начать вызов занятого телефона */
QPushButton* m_declineBtn; // Decline для Incoming; результат закрывает окно через MainWindow.
QPushButton* m_hangupBtn; // Завершение остальных живых состояний.
QPushButton* m_muteBtn; // Checkable mute общего CallAudioEngine, виден при Active.
QTimer* m_durationTimer; // GUI 1с; запускается в Active, останавливается в Ended/close.
QWidget* m_acceptCell; // Кнопка Accept и её подпись, показываются вместе.
QWidget* m_declineCell; // Кнопка Decline и подпись.
QWidget* m_hangupCell; // Кнопка Hangup и подпись.
QWidget* m_muteCell; // Кнопка mute и подпись.
QWidget* m_videoCell; // Кнопка камеры и подпись справа от mute в общей центрированной строке.
QWidget* m_settingsCell; // Шестерёнка настроек видео и подпись справа от камеры.
QWidget* m_diagnosticsCell; // Кнопка диагностики и подпись справа от настроек в нижней строке действий.
QLabel* m_muteCaption; // Меняется между Mute/Unmute.
};