// Moonlight 会话(外部进程) // // 以 QProcess 参数数组直启 moonlight-qt(不拼 shell 命令)。 // 进程启动、串流就绪和终止是不同事件,调用方据此控制过场和状态机。 #ifndef KIOSK_SHELL_MOONLIGHT_SESSION_H #define KIOSK_SHELL_MOONLIGHT_SESSION_H #include #include #include #include #include "desktop_session.h" class QTimer; namespace vdi { class MoonlightOutputParser { public: void reset(); void append(const QByteArray& output); bool isReady() const; bool hasTestDecode() const { return hasTestDecode_; } bool hasRenderer() const { return hasRenderer_; } bool hasTerminalError() const { return hasTerminalError_; } private: QByteArray buffer_; bool hasTestDecode_ = false; bool hasRenderer_ = false; bool hasTerminalError_ = false; }; class MoonlightSession : public QObject { Q_OBJECT public: struct Options { bool vsync = true; bool framePacing = true; bool performanceOverlay = false; bool audioOnHost = true; QString videoCodec = QStringLiteral("H.264"); QString decoder = QStringLiteral("software"); }; enum class EventType { kStarted, kStreamReady, kFailed, kFinished, }; struct Event { EventType type; QString message; }; using EventCallback = std::function; explicit MoonlightSession(QObject* parent = nullptr); ~MoonlightSession() override; void setOptions(const Options& options); bool start(const ConnectionTicket& ticket, EventCallback callback); void stop(); bool isRunning() const; qint64 processId() const; bool activateStreamWindow(); private slots: void onProcessStarted(); void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void onProcessError(QProcess::ProcessError error); void onProcessOutput(); private: void emitEvent(EventType type, const QString& message); void emitTerminalEvent(EventType type, const QString& message); void scheduleReadyEvent(); QProcess* process_ = nullptr; QTimer* readyTimer_ = nullptr; QTimer* killTimer_ = nullptr; Options options_; EventCallback callback_; MoonlightOutputParser outputParser_; QString logPath_; bool stopRequested_ = false; bool terminalEventDelivered_ = false; bool readyEventDelivered_ = false; }; } // namespace vdi #endif // KIOSK_SHELL_MOONLIGHT_SESSION_H