MythTV master
MythExternControl.h
Go to the documentation of this file.
1/* -*- Mode: c++ -*-
2 *
3 * Copyright (C) John Poet 2018
4 *
5 * This file is part of MythTV
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef MYTHEXTERNCONTROL_H
22#define MYTHEXTERNCONTROL_H
23
24#include "MythExternRecApp.h"
25
26#include <atomic>
27#include <vector>
28#include <queue>
29#include <condition_variable>
30#include <thread>
31
32#include <QString>
33
35
36class Buffer : QObject
37{
38 Q_OBJECT
39
40 public:
41 static constexpr uint16_t kMaxQueue { 500 };
42
43 explicit Buffer(MythExternControl * parent);
44 ~Buffer(void) override = default;
45 void Start(void) {
46 m_thread = std::thread(&Buffer::Run, this);
47 }
48 void Join(void) {
49 if (m_thread.joinable())
50 m_thread.join();
51 }
52 bool Fill(const QByteArray & buffer);
53
54 std::chrono::time_point<std::chrono::system_clock> HeartBeat(void) const
55 { return m_heartbeat; }
56
57 protected:
58 void Run(void);
59
60 private:
61 using block_t = std::vector<uint8_t>;
62 using stack_t = std::queue<block_t>;
63
65
66 std::thread m_thread;
67
69 bool m_dataSeen {false};
70
71 std::chrono::time_point<std::chrono::system_clock> m_heartbeat;
72};
73
74class Commands : public QObject
75{
76 Q_OBJECT
77
78 public:
79 explicit Commands(MythExternControl * parent)
80 : m_parent(parent) {}
81 ~Commands(void) override = default;
82 void Start(void) {
83 m_thread = std::thread(&Commands::Run, this);
84 }
85 void Join(void) {
86 if (m_thread.joinable())
87 m_thread.join();
88 }
89
90 bool SendStatus(const QString & command,
91 const QString & status,
92 const QString & serial,
93 const QString & response = "");
94 bool ProcessCommand(const QString & query);
95
96 protected:
97 void Run(void);
98 bool Open(void);
99 void Close(void);
100 void StartStreaming(const QString & serial);
101 void StopStreaming(const QString & serial, bool silent);
102 void LockTimeout(const QString & serial) const;
103 void HasTuner(const QString & serial) const;
104 void HasPictureAttributes(const QString & serial) const;
105 void SetBlockSize(const QString & serial, int blksz);
106 void TuneChannel(const QString & serial, const QVariantMap & args);
107 void TuneStatus(const QString & serial);
108 void LoadChannels(const QString & serial);
109 void FirstChannel(const QString & serial);
110 void NextChannel(const QString & serial);
111 void Cleanup(void);
112
113 private:
114 std::thread m_thread;
115
116 size_t m_repCmdCnt { 0 };
119
121 int m_apiVersion { -1 };
122};
123
124class MythExternControl : public QObject
125{
126 Q_OBJECT
127
128 friend class Buffer;
129 friend class Commands;
130
131 public:
132 MythExternControl(void);
133 ~MythExternControl(void) override;
134
135 QString Desc(void) const { return QString("%1: ").arg(m_desc); }
136
137 void Terminate(void);
138
139 void Error(const QString & msg);
140 void Fatal(const QString & msg);
141
142 QString ErrorString(void) const { return m_errmsg; }
143 void ClearError(void) { m_errmsg.clear(); }
144
145 signals:
146 void Open(void);
147 void Close(void);
148 void StartStreaming(const QString & serial);
149 void StopStreaming(const QString & serial, bool silent);
150 void LockTimeout(const QString & serial);
151 void HasTuner(const QString & serial);
152 void HasPictureAttributes(const QString & serial);
153 void SetBlockSize(const QString & serial, int blksz);
154 void TuneChannel(const QString & serial, const QVariantMap & args);
155 void TuneStatus(const QString & serial);
156 void LoadChannels(const QString & serial);
157 void FirstChannel(const QString & serial);
158 void NextChannel(const QString & serial);
159 void Cleanup(void);
160 void DataStarted(void);
161
162 public slots:
163 void SetDescription(const QString & desc) { m_desc = desc; }
164 void SendMessage(const QString & command,
165 const QString & serial,
166 const QString & message,
167 const QString & status = "");
168
169 void ErrorMessage(const QString & msg);
170 void Opened(void);
171 void Done(void);
172 void Streaming(bool val);
173 void Fill(const QByteArray & buffer) { m_buffer.Fill(buffer); }
174
175 protected:
178 QString m_desc;
179
180 std::atomic<bool> m_run {true};
181 std::atomic<bool> m_commandsRunning {true};
182 std::atomic<bool> m_bufferRunning {true};
183 std::mutex m_runMutex;
184 std::condition_variable m_runCond;
185 std::mutex m_msgMutex;
186
187 bool m_fatal {false};
188 QString m_errmsg;
189
190 std::mutex m_flowMutex;
191 std::condition_variable m_flowCond;
192 std::atomic<bool> m_streaming {false};
193 std::atomic<bool> m_xon {false};
194 std::atomic<bool> m_ready {false};
195};
196
197#endif // MYTHEXTERNCONTROL_H
std::thread m_thread
stack_t m_data
std::queue< block_t > stack_t
~Buffer(void) override=default
std::chrono::time_point< std::chrono::system_clock > m_heartbeat
MythExternControl * m_parent
static constexpr uint16_t kMaxQueue
bool m_dataSeen
bool Fill(const QByteArray &buffer)
void Start(void)
std::vector< uint8_t > block_t
Buffer(MythExternControl *parent)
void Run(void)
std::chrono::time_point< std::chrono::system_clock > HeartBeat(void) const
void Join(void)
size_t m_repCmdCnt
bool Open(void)
bool ProcessCommand(const QString &query)
void HasPictureAttributes(const QString &serial) const
void StopStreaming(const QString &serial, bool silent)
void Cleanup(void)
void HasTuner(const QString &serial) const
QString m_prevMsgBuf
void TuneStatus(const QString &serial)
void LoadChannels(const QString &serial)
void StartStreaming(const QString &serial)
std::thread m_thread
void TuneChannel(const QString &serial, const QVariantMap &args)
void FirstChannel(const QString &serial)
void Close(void)
void Start(void)
MythExternControl * m_parent
void NextChannel(const QString &serial)
void Join(void)
void SetBlockSize(const QString &serial, int blksz)
void LockTimeout(const QString &serial) const
Commands(MythExternControl *parent)
bool SendStatus(const QString &command, const QString &status, const QString &serial, const QString &response="")
~Commands(void) override=default
void Run(void)
QString m_prevStatus
void ErrorMessage(const QString &msg)
void TuneStatus(const QString &serial)
void StartStreaming(const QString &serial)
void SetBlockSize(const QString &serial, int blksz)
void HasTuner(const QString &serial)
std::atomic< bool > m_streaming
void Error(const QString &msg)
void HasPictureAttributes(const QString &serial)
QString ErrorString(void) const
std::condition_variable m_runCond
void Fill(const QByteArray &buffer)
~MythExternControl(void) override
std::atomic< bool > m_xon
void SendMessage(const QString &command, const QString &serial, const QString &message, const QString &status="")
void FirstChannel(const QString &serial)
void DataStarted(void)
void Cleanup(void)
void Fatal(const QString &msg)
std::atomic< bool > m_run
void TuneChannel(const QString &serial, const QVariantMap &args)
void NextChannel(const QString &serial)
std::atomic< bool > m_commandsRunning
void LoadChannels(const QString &serial)
void Streaming(bool val)
void SetDescription(const QString &desc)
void StopStreaming(const QString &serial, bool silent)
std::condition_variable m_flowCond
void LockTimeout(const QString &serial)
std::atomic< bool > m_bufferRunning
void Close(void)
QString Desc(void) const
std::atomic< bool > m_ready
unsigned short uint16_t
Definition: iso6937tables.h:3