Parent: [ffaa33] (diff)

Child: [dd5fc4] (diff)

Download this file

service.hxx    162 lines (135 with data), 5.5 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* Copyright (C) 2014 J.F.Dockes
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SERVICE_H_X_INCLUDED_
#define _SERVICE_H_X_INCLUDED_
#include <string>
#include <functional>
#include <unordered_map>
#include <upnp/upnp.h>
#include "libupnpp/log.hxx"
#include "libupnpp/soaphelp.hxx"
#include "libupnpp/control/description.hxx"
#include "libupnpp/control/cdircontent.hxx"
namespace UPnPClient {
/** To be implemented by upper-level client code for event
* reporting. Runs in an event thread. This could for example be
* implemented by a Qt Object to generate events for the GUI.
*/
class VarEventReporter {
public:
virtual ~VarEventReporter() {};
// Using char * to avoid any issue with strings and concurrency
virtual void changed(const char *nm, int val) = 0;
virtual void changed(const char *nm, const char *val) = 0;
// Used for track metadata (parsed as content directory entry). Not always
// needed.
virtual void changed(const char *nm, UPnPDirObject meta) {};
};
typedef
std::function<void (const std::unordered_map<std::string, std::string>&)>
evtCBFunc;
class Service {
public:
/** Construct by copying data from device and service objects.
*/
Service(const UPnPDeviceDesc& device,
const UPnPServiceDesc& service, bool doSubscribe = true);
/** An empty one */
Service() : m_reporter(0) {}
virtual ~Service();
/** Retrieve my root device "friendly name". */
std::string getFriendlyName() const {return m_friendlyName;}
/** Return my root device id */
std::string getDeviceId() const {return m_deviceId;}
virtual int runAction(const SoapEncodeInput& args, SoapDecodeOutput& data);
virtual VarEventReporter *getReporter()
{
return m_reporter;
}
virtual void installReporter(VarEventReporter* reporter)
{
m_reporter = reporter;
}
// Can't copy these because this does not make sense for the
// member function callback.
Service(Service const&) = delete;
Service& operator=(Service const&) = delete;
protected:
/** Registered callbacks for the service objects. The map is
* indexed by m_SID, the subscription id which was obtained by
* each object when subscribing to receive the events for its
* device. The map allows the static function registered with
* libupnp to call the appropriate object method when it receives
* an event. */
static std::unordered_map<std::string, evtCBFunc> o_calls;
/** Used by a derived class to register its callback method. This
* creates an entry in the static map, using m_SID, which was
* obtained by subscribe() during construction
*/
void registerCallback(evtCBFunc c);
/** Upper level client code event callbacks */
VarEventReporter *m_reporter;
std::string m_actionURL;
std::string m_eventURL;
std::string m_serviceType;
std::string m_deviceId;
std::string m_friendlyName;
std::string m_manufacturer;
std::string m_modelName;
int runTrivialAction(const std::string& nm) {
SoapEncodeInput args(m_serviceType, nm);
SoapDecodeOutput data;
return runAction(args, data);
}
template <class T> int runSimpleGet(const std::string& actnm,
const std::string& valnm,
T *valuep) {
SoapEncodeInput args(m_serviceType, actnm);
SoapDecodeOutput data;
int ret = runAction(args, data);
if (ret != UPNP_E_SUCCESS) {
return ret;
}
if (!data.get(valnm.c_str(), valuep)) {
LOGERR("Service::runSimpleAction: " << actnm <<
" missing " << valnm << " in response" << endl);
return UPNP_E_BAD_RESPONSE;
}
return 0;
}
template <class T> int runSimpleAction(const std::string& actnm,
const std::string& valnm,
T value) {
SoapEncodeInput args(m_serviceType, actnm);
args(valnm, SoapHelp::val2s(value));
SoapDecodeOutput data;
return runAction(args, data);
}
private:
/** Only actually does something on the first call, to register our
* (static) library callback */
static bool initEvents();
/** The static event callback given to libupnp */
static int srvCB(Upnp_EventType et, void* vevp, void*);
/* Tell the UPnP device (through libupnp) that we want to receive
its events. This is called during construction and sets m_SID */
virtual bool subscribe();
virtual bool unSubscribe();
Upnp_SID m_SID; /* Subscription Id */
};
} // namespace UPnPClient
#endif /* _SERVICE_H_X_INCLUDED_ */