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 
34 class MythExternControl;
35 
36 class Buffer : QObject
37 {
38  Q_OBJECT
39 
40  public:
41  enum constants {MAX_QUEUE = 500};
42 
43  Buffer(MythExternControl * parent);
44  ~Buffer(void) = 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 
70  std::chrono::time_point<std::chrono::system_clock> m_heartbeat;
71 };
72 
73 class Commands : public QObject
74 {
75  Q_OBJECT
76 
77  public:
79  : m_parent(parent)
80  , m_apiVersion(-1) {}
81  ~Commands(void) = 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, const QString & status);
91  bool SendStatus(const QString & command, const QString & serial,
92  const QString & status);
93  bool ProcessCommand(const QString & cmd);
94 
95  protected:
96  void Run(void);
97  bool Open(void);
98  void Close(void);
99  void StartStreaming(const QString & serial);
100  void StopStreaming(const QString & serial, bool silent);
101  void LockTimeout(const QString & serial) const;
102  void HasTuner(const QString & serial) const;
103  void HasPictureAttributes(const QString & serial) const;
104  void SetBlockSize(const QString & serial, int blksz);
105  void TuneChannel(const QString & serial, const QString & channum);
106  void LoadChannels(const QString & serial);
107  void FirstChannel(const QString & serial);
108  void NextChannel(const QString & serial);
109 
110  private:
111  std::thread m_thread;
112 
115 };
116 
117 class MythExternControl : public QObject
118 {
119  Q_OBJECT
120 
121  friend class Buffer;
122  friend class Commands;
123 
124  public:
125  MythExternControl(void);
126  ~MythExternControl(void);
127 
128  QString Desc(void) const { return QString("%1: ").arg(m_desc); }
129 
130  void Terminate(void);
131 
132  void Error(const QString & msg);
133  void Fatal(const QString & msg);
134 
135  QString ErrorString(void) const { return m_errmsg; }
136  void ClearError(void) { m_errmsg.clear(); }
137 
138  signals:
139  void Open(void);
140  void Close(void);
141  void StartStreaming(const QString & serial);
142  void StopStreaming(const QString & serial, bool silent);
143  void LockTimeout(const QString & serial) const;
144  void HasTuner(const QString & serial) const;
145  void HasPictureAttributes(const QString & serial) const;
146  void SetBlockSize(const QString & serial, int blksz);
147  void TuneChannel(const QString & serial, const QString & channum);
148  void LoadChannels(const QString & serial);
149  void FirstChannel(const QString & serial);
150  void NextChannel(const QString & serial);
151 
152  public slots:
153  void SetDescription(const QString & desc) { m_desc = desc; }
154  void SendMessage(const QString & cmd, const QString & serial,
155  const QString & msg);
156  void ErrorMessage(const QString & msg);
157  void Opened(void);
158  void Done(void);
159  void Streaming(bool val);
160  void Fill(const QByteArray & buffer) { m_buffer.Fill(buffer); }
161 
162  protected:
165  QString m_desc;
166 
167  std::atomic<bool> m_run;
168  std::atomic<bool> m_commands_running;
169  std::atomic<bool> m_buffer_running;
170  std::mutex m_run_mutex;
171  std::condition_variable m_run_cond;
172  std::mutex m_msg_mutex;
173 
174  bool m_fatal;
175  QString m_errmsg;
176 
177  std::mutex m_flow_mutex;
178  std::condition_variable m_flow_cond;
179  std::atomic<bool> m_streaming;
180  std::atomic<bool> m_xon;
181  std::atomic<bool> m_ready;
182 };
183 
184 #endif
std::atomic< bool > m_run
std::atomic< bool > m_commands_running
Commands(MythExternControl *parent)
unsigned int slots[4]
Definition: element.c:38
MythExternControl * m_parent
void Join(void)
void TuneChannel(const QString &serial, const QString &channum)
void ErrorMessage(const QString &msg)
std::condition_variable m_run_cond
~Commands(void)=default
void NextChannel(const QString &serial)
void Run(void)
Buffer(MythExternControl *parent)
void TuneChannel(const QString &serial, const QString &channum)
~Buffer(void)=default
std::atomic< bool > m_buffer_running
void Fill(const QByteArray &buffer)
void StopStreaming(const QString &serial, bool silent)
bool Open(void)
void Error(const QString &msg)
void LockTimeout(const QString &serial) const
bool Fill(const QByteArray &buffer)
void LoadChannels(const QString &serial)
void StopStreaming(const QString &serial, bool silent)
std::thread m_thread
QString ErrorString(void) const
void FirstChannel(const QString &serial)
void HasTuner(const QString &serial) const
void Run(void)
std::condition_variable m_flow_cond
void SetBlockSize(const QString &serial, int blksz)
void Start(void)
std::vector< uint8_t > block_t
void FirstChannel(const QString &serial)
std::thread m_thread
void HasPictureAttributes(const QString &serial) const
std::atomic< bool > m_ready
void SetBlockSize(const QString &serial, int blksz)
void SetDescription(const QString &desc)
void StartStreaming(const QString &serial)
std::chrono::time_point< std::chrono::system_clock > HeartBeat(void) const
MythExternControl * m_parent
std::atomic< bool > m_streaming
void Close(void)
bool SendStatus(const QString &command, const QString &status)
void Fatal(const QString &msg)
bool ProcessCommand(const QString &cmd)
void Join(void)
void Streaming(bool val)
void HasPictureAttributes(const QString &serial) const
std::queue< block_t > stack_t
QString Desc(void) const
void HasTuner(const QString &serial) const
void Start(void)
void StartStreaming(const QString &serial)
void SendMessage(const QString &cmd, const QString &serial, const QString &msg)
stack_t m_data
std::chrono::time_point< std::chrono::system_clock > m_heartbeat
void NextChannel(const QString &serial)
void LoadChannels(const QString &serial)
void Close(void)
std::atomic< bool > m_xon
void LockTimeout(const QString &serial) const