MythTV master
eventing.h
Go to the documentation of this file.
1
2// Program Name: Eventing.h
3// Created : Dec. 22, 2006
4//
5// Purpose : uPnp Eventing Base Class Definition
6//
7// Copyright (c) 2006 David Blain <dblain@mythtv.org>
8//
9// Licensed under the GPL v2 or later, see LICENSE for details
10//
12
13#ifndef EVENTING_H_
14#define EVENTING_H_
15
16#include <chrono>
17#include <utility>
18
19#include <QMap>
20#include <QUrl>
21#include <QUuid>
22
23#include "upnpserviceimpl.h"
24#include "httpserver.h"
25
26class QTextStream;
27
29//
31
33{
34 public:
36 {
37 m_ttExpires = 0us;
38 m_ttLastNotified = 0us;
39 m_sUUID = QUuid::createUuid().toString();
40 m_sUUID = m_sUUID.mid( 1, m_sUUID.length() - 2);
41 }
42
43 SubscriberInfo( const QString &url, std::chrono::seconds duration )
44 : m_qURL(url), m_nDuration( duration )
45 {
46 m_ttExpires = 0us;
47 m_ttLastNotified = 0us;
48 m_sUUID = QUuid::createUuid().toString();
49 m_sUUID = m_sUUID.mid( 1, m_sUUID.length() - 2);
50
51 SetExpireTime( m_nDuration );
52 }
53
54 unsigned long IncrementKey()
55 {
56 // When key wraps around to zero again... must make it a 1. (upnp spec)
57 if ((++m_nKey) == 0)
58 m_nKey = 1;
59
60 return m_nKey;
61 }
62
63 std::chrono::microseconds m_ttExpires {};
64 std::chrono::microseconds m_ttLastNotified {};
65
66 QString m_sUUID;
67 QUrl m_qURL;
68 unsigned short m_nKey {0};
69 std::chrono::seconds m_nDuration {0s};
70
71 protected:
72
73 void SetExpireTime( std::chrono::seconds secs )
74 {
75 m_ttExpires = nowAsDuration<std::chrono::microseconds>() + secs;
76 }
77
78
79};
80
82
83using Subscribers = QMap<QString,SubscriberInfo*>;
84
86//
88
90{
91 public:
92
94 QString m_sName;
95 std::chrono::microseconds m_ttLastChanged {};
96
97 public:
98
99 explicit StateVariableBase( QString sName, bool bNotify = false )
100 : m_bNotify(bNotify), m_sName(std::move(sName))
101 {
102 m_ttLastChanged = nowAsDuration<std::chrono::microseconds>();
103 }
104 virtual ~StateVariableBase() = default;
105
106 virtual QString ToString() = 0;
107};
108
110
111template< class T >
113{
114 private:
115
117
118 public:
119
120 // ------------------------------------------------------------------
121
122 explicit StateVariable( const QString &sName, bool bNotify = false ) : StateVariableBase( sName, bNotify ), m_value( T( ) )
123 {
124 }
125
126 // ------------------------------------------------------------------
127
128 StateVariable( const QString &sName, T value, bool bNotify = false ) : StateVariableBase( sName, bNotify ), m_value(value)
129 {
130 }
131
132 // ------------------------------------------------------------------
133
134 QString ToString() override // StateVariableBase
135 {
136 return QString( "%1" ).arg( m_value );
137 }
138
139 // ------------------------------------------------------------------
140
142 {
143 return m_value;
144 }
145
146 // ------------------------------------------------------------------
147
148 void SetValue( const T& value )
149 {
150 if ( m_value != value )
151 {
152 m_value = value;
153 m_ttLastChanged = nowAsDuration<std::chrono::microseconds>();
154 }
155 }
156};
157
159
160template<typename T>
161inline T state_var_init(const T */*unused*/) { return (T)(0); }
162template<>
163inline QString state_var_init(const QString */*unused*/) { return {}; }
164
166{
167 protected:
168
169 virtual void Notify() = 0;
170 using SVMap = QMap<QString, StateVariableBase*>;
172 public:
173
174 // ------------------------------------------------------------------
175
176 StateVariables() = default;
178 {
179 for (const auto *it : std::as_const(m_map))
180 delete it;
181 m_map.clear();
182 }
183
184 // ------------------------------------------------------------------
185
187 {
188 if (pBase != nullptr)
189 m_map.insert(pBase->m_sName, pBase);
190 }
191
192 // ------------------------------------------------------------------
193 template < class T >
194 bool SetValue( const QString &sName, const T& value )
195 {
196 SVMap::iterator it = m_map.find(sName);
197 if (it == m_map.end())
198 return false;
199
200 auto *pVariable = dynamic_cast< StateVariable< T > *>( *it );
201
202 if (pVariable == nullptr)
203 return false; // It's not the expected type.
204
205 if ( pVariable->GetValue() != value)
206 {
207 pVariable->SetValue( value );
208
209 if (pVariable->m_bNotify)
210 Notify();
211 }
212
213 return true;
214 }
215
216 // ------------------------------------------------------------------
217
218 template < class T >
219 T GetValue( const QString &sName )
220 {
221 T *dummy = nullptr;
222 SVMap::iterator it = m_map.find(sName);
223 if (it == m_map.end())
224 return state_var_init(dummy);
225
226 auto *pVariable = dynamic_cast< StateVariable< T > *>( *it );
227
228 if (pVariable != nullptr)
229 return pVariable->GetValue();
230
231 return state_var_init(dummy);
232 }
233
234 uint BuildNotifyBody(QTextStream &ts, std::chrono::microseconds ttLastNotified) const;
235};
236
239//
240// Eventing Class Definition
241//
244
246 public StateVariables,
247 public IPostProcess,
248 public UPnpServiceImpl
249{
250
251 protected:
252
253 QMutex m_mutex;
254
257
258 std::chrono::seconds m_nSubscriptionDuration {30min};
259
260 short m_nHoldCount {0};
261
262 SubscriberInfo *m_pInitializeSubscriber {nullptr};
263
264 protected:
265
266 void Notify ( ) override; // StateVariables
267 void NotifySubscriber ( SubscriberInfo *pInfo );
268 void HandleSubscribe ( HTTPRequest *pRequest );
269 void HandleUnsubscribe( HTTPRequest *pRequest );
270
271 // Implement UPnpServiceImpl methods that we can
272
273 QString GetServiceEventURL() override // UPnpServiceImpl
274 { return m_sEventMethodName; }
275
276 public:
277 Eventing ( const QString &sExtensionName,
278 QString sEventMethodName,
279 const QString &sSharePath );
280 ~Eventing ( ) override;
281
282 QStringList GetBasePaths() override; // HttpServerExtension
283
284 bool ProcessRequest( HTTPRequest *pRequest ) override; // HttpServerExtension
285
286 short HoldEvents ( );
287 short ReleaseEvents ( );
288
289 void ExecutePostProcess( ) override; // IPostProcess
290
291
292};
293
294#endif
QString m_sEventMethodName
Definition: eventing.h:255
QString GetServiceEventURL() override
Provides the URL of the event portion of the service.
Definition: eventing.h:273
QMutex m_mutex
Definition: eventing.h:253
Subscribers m_subscribers
Definition: eventing.h:256
virtual ~StateVariableBase()=default
StateVariableBase(QString sName, bool bNotify=false)
Definition: eventing.h:99
virtual QString ToString()=0
QString m_sName
Definition: eventing.h:94
QString ToString() override
Definition: eventing.h:134
StateVariable(const QString &sName, bool bNotify=false)
Definition: eventing.h:122
StateVariable(const QString &sName, T value, bool bNotify=false)
Definition: eventing.h:128
void SetValue(const T &value)
Definition: eventing.h:148
bool SetValue(const QString &sName, const T &value)
Definition: eventing.h:194
StateVariables()=default
T GetValue(const QString &sName)
Definition: eventing.h:219
virtual void Notify()=0
void AddVariable(StateVariableBase *pBase)
Definition: eventing.h:186
virtual ~StateVariables()
Definition: eventing.h:177
QMap< QString, StateVariableBase * > SVMap
Definition: eventing.h:170
void SetExpireTime(std::chrono::seconds secs)
Definition: eventing.h:73
unsigned long IncrementKey()
Definition: eventing.h:54
QString m_sUUID
Definition: eventing.h:66
SubscriberInfo(const QString &url, std::chrono::seconds duration)
Definition: eventing.h:43
Base class for services we offer to other UPnP devices.
T state_var_init(const T *)
Definition: eventing.h:161
QMap< QString, SubscriberInfo * > Subscribers
Definition: eventing.h:83
unsigned int uint
Definition: freesurround.h:24
STL namespace.
#define UPNP_PUBLIC
Definition: upnpexp.h:9