|
a/libupnpp/control/ohplaylist.cxx |
|
b/libupnpp/control/ohplaylist.cxx |
|
... |
|
... |
12 |
* You should have received a copy of the GNU General Public License
|
12 |
* You should have received a copy of the GNU General Public License
|
13 |
* along with this program; if not, write to the
|
13 |
* along with this program; if not, write to the
|
14 |
* Free Software Foundation, Inc.,
|
14 |
* Free Software Foundation, Inc.,
|
15 |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
15 |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16 |
*/
|
16 |
*/
|
|
|
17 |
#include <arpa/inet.h>
|
17 |
|
18 |
|
18 |
#include <string>
|
19 |
#include <string>
|
19 |
#include <vector>
|
20 |
#include <vector>
|
20 |
|
21 |
|
21 |
using namespace std;
|
22 |
using namespace std;
|
22 |
|
23 |
|
23 |
#include <upnp/upnp.h>
|
24 |
#include <upnp/upnp.h>
|
24 |
|
25 |
|
|
|
26 |
#include "libupnpp/base64.hxx"
|
25 |
#include "libupnpp/soaphelp.hxx"
|
27 |
#include "libupnpp/soaphelp.hxx"
|
26 |
#include "libupnpp/upnpp_p.hxx"
|
28 |
#include "libupnpp/upnpp_p.hxx"
|
27 |
#include "libupnpp/log.hxx"
|
29 |
#include "libupnpp/log.hxx"
|
28 |
#include "libupnpp/expatmm.hxx"
|
30 |
#include "libupnpp/expatmm.hxx"
|
29 |
#include "libupnpp/control/ohplaylist.hxx"
|
31 |
#include "libupnpp/control/ohplaylist.hxx"
|
|
... |
|
... |
38 |
{
|
40 |
{
|
39 |
const string::size_type sz(SType.size()-2);
|
41 |
const string::size_type sz(SType.size()-2);
|
40 |
return !SType.compare(0, sz, st, 0, sz);
|
42 |
return !SType.compare(0, sz, st, 0, sz);
|
41 |
}
|
43 |
}
|
42 |
|
44 |
|
|
|
45 |
|
|
|
46 |
int OHPlaylist::play()
|
|
|
47 |
{
|
|
|
48 |
return runTrivialAction("Play");
|
|
|
49 |
}
|
|
|
50 |
int OHPlaylist::pause()
|
|
|
51 |
{
|
|
|
52 |
return runTrivialAction("Pause");
|
|
|
53 |
}
|
|
|
54 |
int OHPlaylist::stop()
|
|
|
55 |
{
|
|
|
56 |
return runTrivialAction("Stop");
|
|
|
57 |
}
|
|
|
58 |
int OHPlaylist::next()
|
|
|
59 |
{
|
|
|
60 |
return runTrivialAction("Next");
|
|
|
61 |
}
|
|
|
62 |
int OHPlaylist::previous()
|
|
|
63 |
{
|
|
|
64 |
return runTrivialAction("Previous");
|
|
|
65 |
}
|
|
|
66 |
int OHPlaylist::setRepeat(bool onoff)
|
|
|
67 |
{
|
|
|
68 |
return runSimpleAction("SetRepeat", "Value", onoff);
|
|
|
69 |
}
|
|
|
70 |
int OHPlaylist::repeat(bool *on)
|
|
|
71 |
{
|
|
|
72 |
return runSimpleGet("Repeat", "Value", on);
|
|
|
73 |
}
|
|
|
74 |
int OHPlaylist::setShuffle(bool onoff)
|
|
|
75 |
{
|
|
|
76 |
return runSimpleAction("SetShuffle", "Value", onoff);
|
|
|
77 |
}
|
|
|
78 |
int OHPlaylist::shuffle(bool *on)
|
|
|
79 |
{
|
|
|
80 |
return runSimpleGet("Shuffle", "Value", on);
|
|
|
81 |
}
|
|
|
82 |
int OHPlaylist::seekSecondAbsolute(int value)
|
|
|
83 |
{
|
|
|
84 |
return runSimpleAction("SeekSecondAbsolute", "Value", value);
|
|
|
85 |
}
|
|
|
86 |
int OHPlaylist::seekSecondRelative(int value)
|
|
|
87 |
{
|
|
|
88 |
return runSimpleAction("SeekSecondRelative", "Value", value);
|
|
|
89 |
}
|
|
|
90 |
int OHPlaylist::seekId(int value)
|
|
|
91 |
{
|
|
|
92 |
return runSimpleAction("SeekId", "Value", value);
|
|
|
93 |
}
|
|
|
94 |
int OHPlaylist::seekIndex(int value)
|
|
|
95 |
{
|
|
|
96 |
return runSimpleAction("SeekIndex", "Value", value);
|
|
|
97 |
}
|
|
|
98 |
|
|
|
99 |
int OHPlaylist::transportState(TPState* tpp)
|
|
|
100 |
{
|
|
|
101 |
std::string value;
|
|
|
102 |
int ret;
|
|
|
103 |
|
|
|
104 |
if ((ret = runSimpleGet("TransportState", "Value", &value)))
|
|
|
105 |
return ret;
|
|
|
106 |
if (!value.compare("Buffering")) {
|
|
|
107 |
*tpp = TPS_Buffering;
|
|
|
108 |
return 0;
|
|
|
109 |
} else if (!value.compare("Paused")) {
|
|
|
110 |
*tpp = TPS_Paused;
|
|
|
111 |
return 0;
|
|
|
112 |
} else if (!value.compare("Playing")) {
|
|
|
113 |
*tpp = TPS_Playing;
|
|
|
114 |
return 0;
|
|
|
115 |
} else if (!value.compare("Stopped")) {
|
|
|
116 |
*tpp = TPS_Stopped;
|
|
|
117 |
return 0;
|
|
|
118 |
}
|
|
|
119 |
*tpp = TPS_Unknown;
|
|
|
120 |
return UPNP_E_BAD_RESPONSE;
|
|
|
121 |
}
|
|
|
122 |
|
|
|
123 |
int OHPlaylist::id(int *value)
|
|
|
124 |
{
|
|
|
125 |
return runSimpleGet("Id", "Value", value);
|
|
|
126 |
}
|
|
|
127 |
|
|
|
128 |
int OHPlaylist::read(int id, std::string* urip, UPnPDirObject *dirent)
|
|
|
129 |
{
|
|
|
130 |
SoapEncodeInput args(m_serviceType, "Read");
|
|
|
131 |
args("Id", SoapHelp::i2s(id));
|
|
|
132 |
SoapDecodeOutput data;
|
|
|
133 |
int ret = runAction(args, data);
|
|
|
134 |
if (ret != UPNP_E_SUCCESS) {
|
|
|
135 |
return ret;
|
|
|
136 |
}
|
|
|
137 |
if (!data.get("Uri", urip)) {
|
|
|
138 |
LOGERR("OHPlaylist::Read: missing Uri in response" << endl);
|
|
|
139 |
return UPNP_E_BAD_RESPONSE;
|
|
|
140 |
}
|
|
|
141 |
string didl;
|
|
|
142 |
if (!data.get("Metadata", &didl)) {
|
|
|
143 |
LOGERR("OHPlaylist::Read: missing Uri in response" << endl);
|
|
|
144 |
return UPNP_E_BAD_RESPONSE;
|
|
|
145 |
}
|
|
|
146 |
didl = SoapHelp::xmlUnquote(didl);
|
|
|
147 |
|
|
|
148 |
UPnPDirContent dir;
|
|
|
149 |
if (!dir.parse(didl)) {
|
|
|
150 |
LOGERR("OHPlaylist::Read: didl parse failed: " << didl << endl);
|
|
|
151 |
return UPNP_E_BAD_RESPONSE;
|
|
|
152 |
}
|
|
|
153 |
if (dir.m_items.size() != 1) {
|
|
|
154 |
LOGERR("OHPlaylist::Read: " << dir.m_items.size() << " in response!" <<
|
|
|
155 |
endl);
|
|
|
156 |
return UPNP_E_BAD_RESPONSE;
|
|
|
157 |
}
|
|
|
158 |
*dirent = dir.m_items[0];
|
|
|
159 |
return 0;
|
|
|
160 |
}
|
|
|
161 |
|
|
|
162 |
// Tracklist format
|
|
|
163 |
// <TrackList>
|
|
|
164 |
// <Entry>
|
|
|
165 |
// <Id>10</Id>
|
|
|
166 |
// <Uri>http://blabla</Uri>
|
|
|
167 |
// <Metadata>(xmlencoded didl)</Metadata>
|
|
|
168 |
// </Entry>
|
|
|
169 |
// </TrackList>
|
|
|
170 |
|
|
|
171 |
|
|
|
172 |
class OHTrackListParser : public expatmm::inputRefXMLParser {
|
|
|
173 |
public:
|
|
|
174 |
OHTrackListParser(const string& input,
|
|
|
175 |
vector<OHPlaylist::TrackListEntry>* vp)
|
|
|
176 |
: expatmm::inputRefXMLParser(input), m_v(vp)
|
|
|
177 |
{}
|
|
|
178 |
|
|
|
179 |
protected:
|
|
|
180 |
virtual void StartElement(const XML_Char *name, const XML_Char **) {
|
|
|
181 |
m_path.push_back(name);
|
|
|
182 |
}
|
|
|
183 |
virtual void EndElement(const XML_Char *name) {
|
|
|
184 |
if (!strcmp(name, "Entry")) {
|
|
|
185 |
UPnPDirContent dir;
|
|
|
186 |
if (!dir.parse(SoapHelp::xmlUnquote(m_tdidl))) {
|
|
|
187 |
LOGERR("OHPlaylist::ReadList: didl parse failed: "
|
|
|
188 |
<< m_tdidl << endl);
|
|
|
189 |
return;
|
|
|
190 |
}
|
|
|
191 |
if (dir.m_items.size() != 1) {
|
|
|
192 |
LOGERR("OHPlaylist::ReadList: " << dir.m_items.size()
|
|
|
193 |
<< " in response!" << endl);
|
|
|
194 |
return;
|
|
|
195 |
}
|
|
|
196 |
m_tt.dirent = dir.m_items[0];
|
|
|
197 |
m_v->push_back(m_tt);
|
|
|
198 |
m_tt.clear();
|
|
|
199 |
m_tdidl.clear();
|
|
|
200 |
}
|
|
|
201 |
m_path.pop_back();
|
|
|
202 |
}
|
|
|
203 |
virtual void CharacterData(const XML_Char *s, int len) {
|
|
|
204 |
if (s == 0 || *s == 0)
|
|
|
205 |
return;
|
|
|
206 |
string str(s, len);
|
|
|
207 |
if (!m_path.back().compare("Id"))
|
|
|
208 |
m_tt.id = atoi(str.c_str());
|
|
|
209 |
else if (!m_path.back().compare("Uri"))
|
|
|
210 |
m_tt.url = str;
|
|
|
211 |
else if (!m_path.back().compare("Metadata"))
|
|
|
212 |
m_tdidl += str;
|
|
|
213 |
}
|
|
|
214 |
|
|
|
215 |
private:
|
|
|
216 |
vector<OHPlaylist::TrackListEntry>* m_v;
|
|
|
217 |
std::vector<std::string> m_path;
|
|
|
218 |
OHPlaylist::TrackListEntry m_tt;
|
|
|
219 |
string m_tdidl;
|
|
|
220 |
};
|
|
|
221 |
|
|
|
222 |
int OHPlaylist::readList(const std::vector<int>& ids,
|
|
|
223 |
vector<TrackListEntry>* entsp)
|
|
|
224 |
{
|
|
|
225 |
string idsparam;
|
|
|
226 |
for (auto it = ids.begin(); it != ids.end(); it++) {
|
|
|
227 |
idsparam += SoapHelp::i2s(*it) + " ";
|
|
|
228 |
}
|
|
|
229 |
entsp->clear();
|
|
|
230 |
|
|
|
231 |
SoapEncodeInput args(m_serviceType, "ReadList");
|
|
|
232 |
args("IdList", idsparam);
|
|
|
233 |
SoapDecodeOutput data;
|
|
|
234 |
int ret = runAction(args, data);
|
|
|
235 |
if (ret != UPNP_E_SUCCESS) {
|
|
|
236 |
return ret;
|
|
|
237 |
}
|
|
|
238 |
string xml;
|
|
|
239 |
if (!data.get("TrackList", &xml)) {
|
|
|
240 |
LOGERR("OHPlaylist::readlist: missing TrackList in response" << endl);
|
|
|
241 |
return UPNP_E_BAD_RESPONSE;
|
|
|
242 |
}
|
|
|
243 |
OHTrackListParser mparser(xml, entsp);
|
|
|
244 |
if (!mparser.Parse())
|
|
|
245 |
return UPNP_E_BAD_RESPONSE;
|
|
|
246 |
return 0;
|
|
|
247 |
}
|
|
|
248 |
|
|
|
249 |
int OHPlaylist::insert(int afterid, const string& uri, const string& didl,
|
|
|
250 |
int *nid)
|
|
|
251 |
{
|
|
|
252 |
SoapEncodeInput args(m_serviceType, "Insert");
|
|
|
253 |
args("AfterId", SoapHelp::i2s(afterid))
|
|
|
254 |
("Uri", uri)
|
|
|
255 |
("Metadata", didl);
|
|
|
256 |
SoapDecodeOutput data;
|
|
|
257 |
int ret = runAction(args, data);
|
|
|
258 |
if (ret != UPNP_E_SUCCESS) {
|
|
|
259 |
return ret;
|
|
|
260 |
}
|
|
|
261 |
if (!data.get("NewId", nid)) {
|
|
|
262 |
LOGERR("OHPlaylist::insert: missing Newid in response" << endl);
|
|
|
263 |
return UPNP_E_BAD_RESPONSE;
|
|
|
264 |
}
|
|
|
265 |
return 0;
|
|
|
266 |
}
|
|
|
267 |
|
|
|
268 |
|
|
|
269 |
int OHPlaylist::deleteId(int value)
|
|
|
270 |
{
|
|
|
271 |
return runSimpleAction("DeleteId", "Value", value);
|
|
|
272 |
}
|
|
|
273 |
int OHPlaylist::deleteAll()
|
|
|
274 |
{
|
|
|
275 |
return runTrivialAction("DeleteAll");
|
|
|
276 |
}
|
|
|
277 |
int OHPlaylist::tracksMax(int *valuep)
|
|
|
278 |
{
|
|
|
279 |
return runSimpleGet("TracksMax", "Value", valuep);
|
|
|
280 |
}
|
|
|
281 |
|
|
|
282 |
int OHPlaylist::idArray(vector<int> *ids, int *tokp)
|
|
|
283 |
{
|
|
|
284 |
SoapEncodeInput args(m_serviceType, "IdArray");
|
|
|
285 |
SoapDecodeOutput data;
|
|
|
286 |
int ret = runAction(args, data);
|
|
|
287 |
if (ret != UPNP_E_SUCCESS) {
|
|
|
288 |
return ret;
|
|
|
289 |
}
|
|
|
290 |
if (!data.get("Token", tokp)) {
|
|
|
291 |
LOGERR("OHPlaylist::insert: missing Token in response" << endl);
|
|
|
292 |
return UPNP_E_BAD_RESPONSE;
|
|
|
293 |
}
|
|
|
294 |
string arraydata;
|
|
|
295 |
if (!data.get("Array", &arraydata)) {
|
|
|
296 |
LOGERR("OHPlaylist::insert: missing Array in response" << endl);
|
|
|
297 |
return UPNP_E_BAD_RESPONSE;
|
|
|
298 |
}
|
|
|
299 |
|
|
|
300 |
arraydata = base64_decode(arraydata);
|
|
|
301 |
const char *cp = arraydata.c_str();
|
|
|
302 |
while (cp - arraydata.c_str() < int(arraydata.size())) {
|
|
|
303 |
unsigned int *ip = (unsigned int *)cp;
|
|
|
304 |
ids->push_back(ntohl(*ip));
|
|
|
305 |
cp += 4;
|
|
|
306 |
}
|
|
|
307 |
return 0;
|
|
|
308 |
}
|
|
|
309 |
|
|
|
310 |
int OHPlaylist::idArrayChanged(int token, bool *changed)
|
|
|
311 |
{
|
|
|
312 |
SoapEncodeInput args(m_serviceType, "IdArrayChanged");
|
|
|
313 |
args("Token", SoapHelp::i2s(token));
|
|
|
314 |
SoapDecodeOutput data;
|
|
|
315 |
int ret = runAction(args, data);
|
|
|
316 |
if (ret != UPNP_E_SUCCESS) {
|
|
|
317 |
return ret;
|
|
|
318 |
}
|
|
|
319 |
if (!data.get("Value", changed)) {
|
|
|
320 |
LOGERR("OHPlaylist::idArrayChanged: missing Value in response" << endl);
|
|
|
321 |
return UPNP_E_BAD_RESPONSE;
|
|
|
322 |
}
|
|
|
323 |
return 0;
|
|
|
324 |
}
|
|
|
325 |
|
|
|
326 |
int OHPlaylist::protocolInfo(std::string *proto)
|
|
|
327 |
{
|
|
|
328 |
SoapEncodeInput args(m_serviceType, "ProtocolInfo");
|
|
|
329 |
SoapDecodeOutput data;
|
|
|
330 |
int ret = runAction(args, data);
|
|
|
331 |
if (ret != UPNP_E_SUCCESS) {
|
|
|
332 |
return ret;
|
|
|
333 |
}
|
|
|
334 |
if (!data.get("Value", proto)) {
|
|
|
335 |
LOGERR("OHPlaylist::protocolInfo: missing Value in response" << endl);
|
|
|
336 |
return UPNP_E_BAD_RESPONSE;
|
|
|
337 |
}
|
|
|
338 |
return 0;
|
|
|
339 |
}
|
|
|
340 |
|
43 |
} // End namespace UPnPClient
|
341 |
} // End namespace UPnPClient
|
44 |
|
342 |
|