CPPMyth
Library to interoperate with MythTV server
Loading...
Searching...
No Matches
mythwsapi.cpp
1/*
2 * Copyright (C) 2014 Jean-Luc Barriere
3 *
4 * This Program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This Program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; see the file COPYING. If not, write to
16 * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 */
21
22#include "mythwsapi.h"
23#include "private/debug.h"
24#include "private/socket.h"
25#include "private/wsrequest.h"
26#include "private/wsresponse.h"
27#include "private/jsonparser.h"
28#include "private/mythjsonbinder.h"
29#include "private/os/threads/mutex.h"
30#include "private/cppdef.h"
31#include "private/builtin.h"
32#include "private/uriparser.h"
33#include "private/uriencoder.h"
34
35#define BOOLSTR(a) ((a) ? "true" : "false")
36#define FETCHSIZE 100
37#define FETCHSIZE_L 1000
38
39using namespace Myth;
40
41#define WS_ACCEPT "application/json"
42#define WS_ROOT_MYTH "/Myth"
43#define WS_ROOT_CAPTURE "/Capture"
44#define WS_ROOT_CHANNEL "/Channel"
45#define WS_ROOT_GUIDE "/Guide"
46#define WS_ROOT_CONTENT "/Content"
47#define WS_ROOT_DVR "/Dvr"
48
49template<class T> class autoptr
50{
51 T* _p;
52 explicit autoptr(const autoptr&);
53 autoptr& operator=(const autoptr&);
54public:
55 explicit autoptr(T* p) : _p(p) { }
56 ~autoptr() { if (_p) delete _p; }
57 T& operator*() { return *_p; }
58 T* operator->() { return _p; }
59 T* release() { T* p = _p; _p = nullptr; return p; }
60 void reset(T* p) { if (_p) delete _p; _p = p; }
61};
62
63WSAPI::WSAPI(const std::string& server, unsigned port, const std::string& securityPin)
64: m_mutex(new OS::Mutex)
65, m_server(server)
66, m_port(port)
67, m_ssl(false)
68, m_securityPin(securityPin)
69, m_checked(false)
70, m_version()
71, m_serverHostName()
72{
73 m_checked = InitWSAPI();
74}
75
76WSAPI::~WSAPI()
77{
78 SAFE_DELETE(m_mutex);
79}
80
81WSAPI& WSAPI::WithAuthorization(const std::string& user, const std::string& password)
82{
83 m_authUser = user;
84 m_authPassword = password;
85 return *this;
86}
87
88WSAPI& WSAPI::WithSSL(bool yesno)
89{
90#if HAVE_OPENSSL
91 m_ssl = yesno;
92#else
93 DBG(DBG_ERROR, "%s: SSL support is not available\n", __FUNCTION__);
94#endif
95 return *this;
96}
97
102
103WSAPI::Query::Query(WSAPI& api)
104: m_api(api)
105, m_request(nullptr)
106{
107 m_request = new WSRequest(m_api.m_server, m_api.m_port, m_api.m_ssl);
108}
109
110WSAPI::Query::~Query()
111{
112 if (m_request)
113 delete m_request;
114}
115
116WSRequest& WSAPI::Query::Request()
117{
118 return *m_request;
119}
120
121WSResponse * WSAPI::Query::Execute(int maxRedirs, bool trustedLocation, bool followAny)
122{
123 // v36: add authorization header if token is filled
124 if (!m_api.m_authToken.empty())
125 m_request->SetHeader(ws_header_to_str(WS_HEADER_Authorization), m_api.m_authToken);
126 WSResponse * response = new WSResponse(*m_request, maxRedirs, trustedLocation, followAny);
127 if (response->GetStatusCode() == 401)
128 {
129 if (m_api.LoginUser())
130 {
131 delete response;
132 m_request->SetHeader(ws_header_to_str(WS_HEADER_Authorization), m_api.m_authToken);
133 response = new WSResponse(*m_request, maxRedirs, trustedLocation, followAny);
134 }
135 }
136 return response;
137}
138
143
144bool WSAPI::InitWSAPI()
145{
146 bool status = false;
147 // Reset array of version
148 memset(m_serviceVersion, 0, sizeof(m_serviceVersion));
149 // Check the core service Myth
150 WSServiceVersion_t& mythwsv = m_serviceVersion[WS_Myth];
151 if (!GetServiceVersion(WS_Myth, mythwsv))
152 {
153 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
154 return false;
155 }
156 if (mythwsv.ranking > MYTH_API_VERSION_MAX_RANKING) {}
157 else if (mythwsv.ranking >= 0x00020000)
158 status = CheckServerHostName2_0() && CheckVersion2_0();
159
160 // If everything is fine then check other services
161 if (status)
162 {
163 if (GetServiceVersion(WS_Capture, m_serviceVersion[WS_Capture]) &&
164 GetServiceVersion(WS_Channel, m_serviceVersion[WS_Channel]) &&
165 GetServiceVersion(WS_Guide, m_serviceVersion[WS_Guide]) &&
166 GetServiceVersion(WS_Content, m_serviceVersion[WS_Content]) &&
167 GetServiceVersion(WS_Dvr, m_serviceVersion[WS_Dvr]))
168 {
169 DBG(DBG_INFO, "%s: MythTV API service is available: %s:%d(%s) protocol(%d) schema(%d)\n",
170 __FUNCTION__, m_serverHostName.c_str(), m_port, m_version.version.c_str(),
171 (unsigned)m_version.protocol, (unsigned)m_version.schema);
172 return true;
173 }
174 }
175 DBG(DBG_ERROR, "%s: MythTV API service is not supported or unavailable: %s:%d (%u.%u)\n",
176 __FUNCTION__, m_server.c_str(), m_port, mythwsv.major, mythwsv.minor);
177 return false;
178}
179
181{
182 static const char * WSServiceRoot[WS_INVALID + 1] =
183 {
184 WS_ROOT_MYTH,
185 WS_ROOT_CAPTURE,
186 WS_ROOT_CHANNEL,
187 WS_ROOT_GUIDE,
188 WS_ROOT_CONTENT,
189 WS_ROOT_DVR,
190 "/?",
191 };
192 std::string url(WSServiceRoot[id]);
193 url.append("/version");
194 Query qry(*this);
195 qry.Request().RequestAccept(WS_ACCEPT);
196 qry.Request().RequestService(url, WS_METHOD_Get);
197 autoptr<WSResponse> resp(qry.Execute());
198 if (resp->IsSuccessful())
199 {
200 // Parse content response
201 const JSON::Document json(*resp);
202 const JSON::Node& root = json.GetRoot();
203 if (json.IsValid() && root.IsObject())
204 {
205 const JSON::Node& field = root.GetObjectValue("String");
206 if (field.IsString())
207 {
208 const std::string& val = field.GetStringValue();
209 if (sscanf(val.c_str(), "%u.%u", &(wsv.major), &(wsv.minor)) == 2)
210 {
211 wsv.ranking = ((wsv.major & 0xFFFF) << 16) | (wsv.minor & 0xFFFF);
212 return true;
213 }
214 }
215 }
216 }
217 wsv.major = 0;
218 wsv.minor = 0;
219 wsv.ranking = 0;
220 return false;
221}
222
223bool WSAPI::CheckServerHostName2_0()
224{
225 m_serverHostName.clear();
226
227 Query qry(*this);
228 qry.Request().RequestAccept(WS_ACCEPT);
229 qry.Request().RequestService("/Myth/GetHostName", WS_METHOD_Get);
230 autoptr<WSResponse> resp(qry.Execute());
231 if (!resp->IsSuccessful())
232 {
233 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
234 return false;
235 }
236 // Parse content response
237 const JSON::Document json(*resp);
238 const JSON::Node& root = json.GetRoot();
239 if (json.IsValid() && root.IsObject())
240 {
241 const JSON::Node& field = root.GetObjectValue("String");
242 if (field.IsString())
243 {
244 const std::string& val = field.GetStringValue();
245 m_serverHostName = val;
246 m_namedCache[val] = m_server;
247 return true;
248 }
249 }
250 return false;
251}
252
253bool WSAPI::CheckVersion2_0()
254{
255 m_version.protocol = 0;
256 m_version.schema = 0;
257 m_version.version.clear();
258 WSServiceVersion_t& wsv = m_serviceVersion[WS_Myth];
259
260 Query qry(*this);
261 qry.Request().RequestAccept(WS_ACCEPT);
262 qry.Request().RequestService("/Myth/GetConnectionInfo", WS_METHOD_Get);
263 if (!m_securityPin.empty())
264 {
265 // Skip if null or empty
266 qry.Request().SetContentParam("Pin", m_securityPin);
267 }
268 autoptr<WSResponse> resp(qry.Execute());
269 if (!resp->IsSuccessful())
270 {
271 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
272 return false;
273 }
274 // Parse content response
275 const JSON::Document json(*resp);
276 const JSON::Node& root = json.GetRoot();
277 if (json.IsValid() && root.IsObject())
278 {
279 const JSON::Node& con = root.GetObjectValue("ConnectionInfo");
280 if (con.IsObject())
281 {
282 const JSON::Node& ver = con.GetObjectValue("Version");
283 JSON::BindObject(ver, &m_version, MythDTO::getVersionBindArray(wsv.ranking));
284 if (m_version.protocol)
285 return true;
286 }
287 }
288 return false;
289}
290
291unsigned WSAPI::CheckService()
292{
293 OS::LockGuard lock(*m_mutex);
294 if (m_checked || (m_checked = InitWSAPI()))
295 return (unsigned)m_version.protocol;
296 return 0;
297}
298
299WSServiceVersion_t WSAPI::CheckService(WSServiceId_t id)
300{
301 OS::LockGuard lock(*m_mutex);
302 if (m_checked || (m_checked = InitWSAPI()))
303 return m_serviceVersion[id];
304 return m_serviceVersion[WS_INVALID];
305}
306
307void WSAPI::InvalidateService()
308{
309 if (m_checked)
310 m_checked = false;
311}
312
313std::string WSAPI::GetServerHostName()
314{
315 return m_serverHostName;
316}
317
318std::string WSAPI::GetBaseURL()
319{
320 BUILTIN_BUFFER buf;
321 std::string url;
322 url.reserve(47);
323 if (m_ssl)
324 url.append("https://");
325 else
326 url.append("http://");
327 url.append(m_server);
328 uint32_to_string(m_port, &buf);
329 url.append(":").append(buf.data);
330 return url;
331}
332
333VersionPtr WSAPI::GetVersion()
334{
335 return VersionPtr(new Version(m_version));
336}
337
338std::string WSAPI::ResolveHostName(const std::string& hostname)
339{
340 OS::LockGuard lock(*m_mutex);
341 std::map<std::string, std::string>::const_iterator it = m_namedCache.find(hostname);
342 if (it != m_namedCache.end())
343 return it->second;
344 Myth::SettingPtr addr = this->GetHostSetting("BackendServerIP6", hostname);
345 if (addr && !addr->value.empty() && addr->value != "::1")
346 {
347 std::string& ret = m_namedCache[hostname];
348 ret.assign(addr->value);
349 DBG(DBG_DEBUG, "%s: resolving hostname %s as %s\n", __FUNCTION__, hostname.c_str(), ret.c_str());
350 return ret;
351 }
352 addr = this->GetHostSetting("BackendServerIP", hostname);
353 if (addr && !addr->value.empty())
354 {
355 std::string& ret = m_namedCache[hostname];
356 ret.assign(addr->value);
357 DBG(DBG_DEBUG, "%s: resolving hostname %s as %s\n", __FUNCTION__, hostname.c_str(), ret.c_str());
358 return ret;
359 }
360 DBG(DBG_ERROR, "%s: unknown host (%s)\n", __FUNCTION__, hostname.c_str());
361 return std::string();
362}
363
368
370{
371 // Initialize request header
372 WSRequest req(m_server, m_port, m_ssl);
373 req.RequestAccept(WS_ACCEPT);
374 req.RequestService("/Myth/LoginUser", WS_METHOD_Post);
375 req.SetContentParam("UserName", m_authUser);
376 req.SetContentParam("Password", m_authPassword);
377 WSResponse resp(req);
378 if (!resp.IsSuccessful())
379 {
380 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
381 return false;
382 }
383 const JSON::Document json(resp);
384 const JSON::Node& root = json.GetRoot();
385 if (!json.IsValid() || !root.IsObject())
386 {
387 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
388 return false;
389 }
390 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
391
392 // Object: String
393 const JSON::Node& val = root.GetObjectValue("String");
394 if (val.IsString())
395 {
396 m_authToken = val.GetStringValue();
397 if (!m_authToken.empty())
398 return true;
399 DBG(DBG_ERROR, "%s: invalid user or password\n", __FUNCTION__);
400 }
401 return false;
402}
403
404SettingPtr WSAPI::GetSetting2_0(const std::string& key, const std::string& hostname)
405{
406 SettingPtr ret;
407
408 // Initialize request header
409 Query qry(*this);
410 qry.Request().RequestAccept(WS_ACCEPT);
411 qry.Request().RequestService("/Myth/GetSetting", WS_METHOD_Get);
412 qry.Request().SetContentParam("HostName", hostname);
413 qry.Request().SetContentParam("Key", key);
414 autoptr<WSResponse> resp(qry.Execute());
415 if (!resp->IsSuccessful())
416 {
417 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
418 return ret;
419 }
420 const JSON::Document json(*resp);
421 const JSON::Node& root = json.GetRoot();
422 if (!json.IsValid() || !root.IsObject())
423 {
424 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
425 return ret;
426 }
427 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
428
429 // Object: SettingList
430 const JSON::Node& slist = root.GetObjectValue("SettingList");
431 // Object: Settings
432 const JSON::Node& sts = slist.GetObjectValue("Settings");
433 if (sts.IsObject())
434 {
435 if (sts.Size())
436 {
437 const JSON::Node& val = sts.GetObjectValue(static_cast<size_t>(0));
438 if (val.IsString())
439 {
440 ret.reset(new Setting()); // Using default constructor
441 ret->key = sts.GetObjectKey(0);
442 ret->value = val.GetStringValue();
443 }
444 }
445 }
446 return ret;
447}
448
449SettingPtr WSAPI::GetSetting5_0(const std::string& key, const std::string& hostname)
450{
451 SettingPtr ret;
452
453 // Initialize request header
454 Query qry(*this);
455 qry.Request().RequestAccept(WS_ACCEPT);
456 qry.Request().RequestService("/Myth/GetSetting", WS_METHOD_Get);
457 qry.Request().SetContentParam("HostName", hostname);
458 qry.Request().SetContentParam("Key", key);
459 autoptr<WSResponse> resp(qry.Execute());
460 if (!resp->IsSuccessful())
461 {
462 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
463 return ret;
464 }
465 const JSON::Document json(*resp);
466 const JSON::Node& root = json.GetRoot();
467 if (!json.IsValid() || !root.IsObject())
468 {
469 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
470 return ret;
471 }
472 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
473
474 // Object: String
475 const JSON::Node& val = root.GetObjectValue("String");
476 if (val.IsString())
477 {
478 ret.reset(new Setting()); // Using default constructor
479 ret->key = key;
480 ret->value = val.GetStringValue();
481 }
482 return ret;
483}
484
485SettingPtr WSAPI::GetSetting(const std::string& key, bool myhost)
486{
487 std::string hostname;
488 if (myhost)
489 hostname = TcpSocket::GetMyHostName();
490 return GetHostSetting(key, hostname);
491}
492
493SettingMapPtr WSAPI::GetSettings2_0(const std::string& hostname)
494{
495 SettingMapPtr ret(new SettingMap);
496
497 // Initialize request header
498 Query qry(*this);
499 qry.Request().RequestAccept(WS_ACCEPT);
500 qry.Request().RequestService("/Myth/GetSetting", WS_METHOD_Get);
501 qry.Request().SetContentParam("HostName", hostname);
502 autoptr<WSResponse> resp(qry.Execute());
503 if (!resp->IsSuccessful())
504 {
505 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
506 return ret;
507 }
508 const JSON::Document json(*resp);
509 const JSON::Node& root = json.GetRoot();
510 if (!json.IsValid() || !root.IsObject())
511 {
512 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
513 return ret;
514 }
515 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
516
517 // Object: SettingList
518 const JSON::Node& slist = root.GetObjectValue("SettingList");
519 // Object: Settings
520 const JSON::Node& sts = slist.GetObjectValue("Settings");
521 if (sts.IsObject())
522 {
523 size_t s = sts.Size();
524 for (size_t i = 0; i < s; ++i)
525 {
526 const JSON::Node& val = sts.GetObjectValue(i);
527 if (val.IsString())
528 {
529 SettingPtr setting(new Setting()); // Using default constructor
530 setting->key = sts.GetObjectKey(i);
531 setting->value = val.GetStringValue();
532 ret->insert(SettingMap::value_type(setting->key, setting));
533 }
534 }
535 }
536 return ret;
537}
538
539SettingMapPtr WSAPI::GetSettings5_0(const std::string& hostname)
540{
541 SettingMapPtr ret(new SettingMap);
542
543 // Initialize request header
544 Query qry(*this);
545 qry.Request().RequestAccept(WS_ACCEPT);
546 qry.Request().RequestService("/Myth/GetSettingList", WS_METHOD_Get);
547 qry.Request().SetContentParam("HostName", hostname);
548 autoptr<WSResponse> resp(qry.Execute());
549 if (!resp->IsSuccessful())
550 {
551 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
552 return ret;
553 }
554 const JSON::Document json(*resp);
555 const JSON::Node& root = json.GetRoot();
556 if (!json.IsValid() || !root.IsObject())
557 {
558 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
559 return ret;
560 }
561 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
562
563 // Object: SettingList
564 const JSON::Node& slist = root.GetObjectValue("SettingList");
565 // Object: Settings
566 const JSON::Node& sts = slist.GetObjectValue("Settings");
567 if (sts.IsObject())
568 {
569 size_t s = sts.Size();
570 for (size_t i = 0; i < s; ++i)
571 {
572 const JSON::Node& val = sts.GetObjectValue(i);
573 if (val.IsString())
574 {
575 SettingPtr setting(new Setting()); // Using default constructor
576 setting->key = sts.GetObjectKey(i);
577 setting->value = val.GetStringValue();
578 ret->insert(SettingMap::value_type(setting->key, setting));
579 }
580 }
581 }
582 return ret;
583}
584
585SettingMapPtr WSAPI::GetSettings(bool myhost)
586{
587 std::string hostname;
588 if (myhost)
589 hostname = TcpSocket::GetMyHostName();
590 return GetHostSettings(hostname);
591}
592
593bool WSAPI::PutSetting2_0(const std::string& key, const std::string& value, bool myhost)
594{
595 // Initialize request header
596 Query qry(*this);
597 qry.Request().RequestAccept(WS_ACCEPT);
598 qry.Request().RequestService("/Myth/PutSetting", WS_METHOD_Post);
599 std::string hostname;
600 if (myhost)
601 hostname = TcpSocket::GetMyHostName();
602 qry.Request().SetContentParam("HostName", hostname);
603 qry.Request().SetContentParam("Key", key);
604 qry.Request().SetContentParam("Value", value);
605 autoptr<WSResponse> resp(qry.Execute());
606 if (!resp->IsSuccessful())
607 {
608 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
609 return false;
610 }
611 const JSON::Document json(*resp);
612 const JSON::Node& root = json.GetRoot();
613 if (!json.IsValid() || !root.IsObject())
614 {
615 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
616 return false;
617 }
618 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
619
620 const JSON::Node& field = root.GetObjectValue("bool");
621 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
622 return true;
623 return false;
624}
625
630CaptureCardListPtr WSAPI::GetCaptureCardList1_4()
631{
632 CaptureCardListPtr ret(new CaptureCardList);
633 unsigned proto = (unsigned)m_version.protocol;
634
635 // Get bindings for protocol version
636 const bindings_t *bindcard = MythDTO::getCaptureCardBindArray(proto);
637
638 // Initialize request header
639 Query qry(*this);
640 qry.Request().RequestAccept(WS_ACCEPT);
641 qry.Request().RequestService("/Capture/GetCaptureCardList", WS_METHOD_Get);
642 qry.Request().SetContentParam("HostName", m_serverHostName.c_str());
643 autoptr<WSResponse> resp(qry.Execute());
644 if (!resp->IsSuccessful())
645 {
646 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
647 return ret;
648 }
649 const JSON::Document json(*resp);
650 const JSON::Node& root = json.GetRoot();
651 if (!json.IsValid() || !root.IsObject())
652 {
653 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
654 return ret;
655 }
656 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
657
658 // Object: CaptureCardList
659 const JSON::Node& clist = root.GetObjectValue("CaptureCardList");
660 // Object: CaptureCards[]
661 const JSON::Node& cards = clist.GetObjectValue("CaptureCards");
662 // Iterates over the sequence elements.
663 size_t cs = cards.Size();
664 for (size_t ci = 0; ci < cs; ++ci)
665 {
666 const JSON::Node& card = cards.GetArrayElement(ci);
667 CaptureCardPtr captureCard(new CaptureCard()); // Using default constructor
668 // Bind the new captureCard
669 JSON::BindObject(card, captureCard.get(), bindcard);
670 ret->push_back(captureCard);
671 }
672 return ret;
673}
674
679VideoSourceListPtr WSAPI::GetVideoSourceList1_2()
680{
681 VideoSourceListPtr ret(new VideoSourceList);
682 unsigned proto = (unsigned)m_version.protocol;
683
684 // Get bindings for protocol version
685 const bindings_t *bindvsrc = MythDTO::getVideoSourceBindArray(proto);
686
687 // Initialize request header
688 Query qry(*this);
689 qry.Request().RequestAccept(WS_ACCEPT);
690 qry.Request().RequestService("/Channel/GetVideoSourceList", WS_METHOD_Get);
691 autoptr<WSResponse> resp(qry.Execute());
692 if (!resp->IsSuccessful())
693 {
694 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
695 return ret;
696 }
697 const JSON::Document json(*resp);
698 const JSON::Node& root = json.GetRoot();
699 if (!json.IsValid() || !root.IsObject())
700 {
701 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
702 return ret;
703 }
704 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
705
706 // Object: VideoSourceList
707 const JSON::Node& slist = root.GetObjectValue("VideoSourceList");
708 // Object: VideoSources[]
709 const JSON::Node& vsrcs = slist.GetObjectValue("VideoSources");
710 // Iterates over the sequence elements.
711 size_t vs = vsrcs.Size();
712 for (size_t vi = 0; vi < vs; ++vi)
713 {
714 const JSON::Node& vsrc = vsrcs.GetArrayElement(vi);
715 VideoSourcePtr videoSource(new VideoSource()); // Using default constructor
716 // Bind the new videoSource
717 JSON::BindObject(vsrc, videoSource.get(), bindvsrc);
718 ret->push_back(videoSource);
719 }
720 return ret;
721}
722
723ChannelListPtr WSAPI::GetChannelList1_2(uint32_t sourceid, bool onlyVisible)
724{
725 ChannelListPtr ret(new ChannelList);
726 BUILTIN_BUFFER buf;
727 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
728 unsigned proto = (unsigned)m_version.protocol;
729
730 // Get bindings for protocol version
731 const bindings_t *bindlist = MythDTO::getListBindArray(proto);
732 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
733
734 // Initialize request header
735 Query qry(*this);
736 qry.Request().RequestAccept(WS_ACCEPT);
737 qry.Request().RequestService("/Channel/GetChannelInfoList", WS_METHOD_Get);
738
739 do
740 {
741 qry.Request().ClearContent();
742 uint32_to_string(sourceid, &buf);
743 qry.Request().SetContentParam("SourceID", buf.data);
744 int32_to_string(req_index, &buf);
745 qry.Request().SetContentParam("StartIndex", buf.data);
746 int32_to_string(req_count, &buf);
747 qry.Request().SetContentParam("Count", buf.data);
748
749 DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
750 autoptr<WSResponse> resp(qry.Execute());
751 if (!resp->IsSuccessful())
752 {
753 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
754 break;
755 }
756 const JSON::Document json(*resp);
757 const JSON::Node& root = json.GetRoot();
758 if (!json.IsValid() || !root.IsObject())
759 {
760 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
761 break;
762 }
763 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
764
765 // Object: ChannelInfoList
766 const JSON::Node& clist = root.GetObjectValue("ChannelInfoList");
767 ItemList list = ItemList(); // Using default constructor
768 JSON::BindObject(clist, &list, bindlist);
769 // List has ProtoVer. Check it or sound alarm
770 if (list.protoVer != proto)
771 {
772 InvalidateService();
773 break;
774 }
775 count = 0;
776 // Object: ChannelInfos[]
777 const JSON::Node& chans = clist.GetObjectValue("ChannelInfos");
778 // Iterates over the sequence elements.
779 size_t cs = chans.Size();
780 for (size_t ci = 0; ci < cs; ++ci)
781 {
782 ++count;
783 const JSON::Node& chan = chans.GetArrayElement(ci);
784 ChannelPtr channel(new Channel()); // Using default constructor
785 // Bind the new channel
786 JSON::BindObject(chan, channel.get(), bindchan);
787 if (channel->chanId && !channel->chanNum.empty() && (!onlyVisible || channel->visible))
788 ret->push_back(channel);
789 }
790 DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count);
791 req_index += count; // Set next requested index
792 }
793 while (count == req_count);
794
795 return ret;
796}
797
798ChannelListPtr WSAPI::GetChannelList1_5(uint32_t sourceid, bool onlyVisible)
799{
800 ChannelListPtr ret(new ChannelList);
801 BUILTIN_BUFFER buf;
802 int32_t /*req_index = 0, req_count = FETCHSIZE,*/ count = 0;
803 unsigned proto = (unsigned)m_version.protocol;
804
805 // Get bindings for protocol version
806 const bindings_t *bindlist = MythDTO::getListBindArray(proto);
807 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
808
809 // Initialize request header
810 Query qry(*this);
811 qry.Request().RequestAccept(WS_ACCEPT);
812 qry.Request().RequestService("/Channel/GetChannelInfoList", WS_METHOD_Get);
813
814 do
815 {
816 qry.Request().ClearContent();
817 qry.Request().SetContentParam("Details", "true");
818 qry.Request().SetContentParam("OnlyVisible", BOOLSTR(onlyVisible));
819 uint32_to_string(sourceid, &buf);
820 qry.Request().SetContentParam("SourceID", buf.data);
821 // W.A. for bug tracked by ticket 12461
822 //int32_to_string(req_index, &buf);
823 //qry.Request().SetContentParam("StartIndex", buf.data);
824 //int32_to_string(req_count, &buf);
825 //qry.Request().SetContentParam("Count", buf.data);
826
827 //DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
828 autoptr<WSResponse> resp(qry.Execute());
829 if (!resp->IsSuccessful())
830 {
831 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
832 break;
833 }
834 const JSON::Document json(*resp);
835 const JSON::Node& root = json.GetRoot();
836 if (!json.IsValid() || !root.IsObject())
837 {
838 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
839 break;
840 }
841 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
842
843 // Object: ChannelInfoList
844 const JSON::Node& clist = root.GetObjectValue("ChannelInfoList");
845 ItemList list = ItemList(); // Using default constructor
846 JSON::BindObject(clist, &list, bindlist);
847 // List has ProtoVer. Check it or sound alarm
848 if (list.protoVer != proto)
849 {
850 InvalidateService();
851 break;
852 }
853 count = 0;
854 // Object: ChannelInfos[]
855 const JSON::Node& chans = clist.GetObjectValue("ChannelInfos");
856 // Iterates over the sequence elements.
857 size_t cs = chans.Size();
858 for (size_t ci = 0; ci < cs; ++ci)
859 {
860 ++count;
861 const JSON::Node& chan = chans.GetArrayElement(ci);
862 ChannelPtr channel(new Channel()); // Using default constructor
863 // Bind the new channel
864 JSON::BindObject(chan, channel.get(), bindchan);
865 if (channel->chanId && !channel->chanNum.empty())
866 ret->push_back(channel);
867 }
868 DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count);
869 //req_index += count; // Set next requested index
870 }
871 //while (count == req_count);
872 while (false); // W.A. for bug tracked by ticket 12461
873
874 return ret;
875}
876
877ChannelPtr WSAPI::GetChannel1_2(uint32_t chanid)
878{
879 ChannelPtr ret;
880 BUILTIN_BUFFER buf;
881 unsigned proto = (unsigned)m_version.protocol;
882
883 // Get bindings for protocol version
884 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
885
886 // Initialize request header
887 Query qry(*this);
888 qry.Request().RequestAccept(WS_ACCEPT);
889 qry.Request().RequestService("/Channel/GetChannelInfo", WS_METHOD_Get);
890 uint32_to_string(chanid, &buf);
891 qry.Request().SetContentParam("ChanID", buf.data);
892
893 autoptr<WSResponse> resp(qry.Execute());
894 if (!resp->IsSuccessful())
895 {
896 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
897 return ret;
898 }
899 const JSON::Document json(*resp);
900 const JSON::Node& root = json.GetRoot();
901 if (!json.IsValid() || !root.IsObject())
902 {
903 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
904 return ret;
905 }
906 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
907
908 // Object: ChannelInfo
909 const JSON::Node& chan = root.GetObjectValue("ChannelInfo");
910 ChannelPtr channel(new Channel()); // Using default constructor
911 // Bind the new channel
912 JSON::BindObject(chan, channel.get(), bindchan);
913 if (channel->chanId == chanid)
914 ret = channel;
915 return ret;
916}
917
922std::map<uint32_t, ProgramMapPtr> WSAPI::GetProgramGuide1_0(time_t starttime, time_t endtime)
923{
924 std::map<uint32_t, ProgramMapPtr> ret;
925 BUILTIN_BUFFER buf;
926 int32_t count = 0;
927 unsigned proto = (unsigned)m_version.protocol;
928
929 // Get bindings for protocol version
930 const bindings_t *bindlist = MythDTO::getListBindArray(proto);
931 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
932 const bindings_t *bindprog = MythDTO::getProgramBindArray(proto);
933
934 // Initialize request header
935 Query qry(*this);
936 qry.Request().RequestAccept(WS_ACCEPT);
937 qry.Request().RequestService("/Guide/GetProgramGuide", WS_METHOD_Get);
938 qry.Request().SetContentParam("StartChanId", "0");
939 qry.Request().SetContentParam("NumChannels", "0");
940 time_to_iso8601utc(starttime, &buf);
941 qry.Request().SetContentParam("StartTime", buf.data);
942 time_to_iso8601utc(endtime, &buf);
943 qry.Request().SetContentParam("EndTime", buf.data);
944 qry.Request().SetContentParam("Details", "true");
945
946 autoptr<WSResponse> resp(qry.Execute());
947 if (!resp->IsSuccessful())
948 {
949 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
950 return ret;
951 }
952 const JSON::Document json(*resp);
953 const JSON::Node& root = json.GetRoot();
954 if (!json.IsValid() || !root.IsObject())
955 {
956 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
957 return ret;
958 }
959 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
960
961 // Object: ProgramGuide
962 const JSON::Node& glist = root.GetObjectValue("ProgramGuide");
963 ItemList list = ItemList(); // Using default constructor
964 JSON::BindObject(glist, &list, bindlist);
965 // List has ProtoVer. Check it or sound alarm
966 if (list.protoVer != proto)
967 {
968 InvalidateService();
969 return ret;
970 }
971 // Object: Channels[]
972 const JSON::Node& chans = glist.GetObjectValue("Channels");
973 // Iterates over the sequence elements.
974 size_t cs = chans.Size();
975 for (size_t ci = 0; ci < cs; ++ci)
976 {
977 const JSON::Node& chan = chans.GetArrayElement(ci);
978 Channel channel;
979 JSON::BindObject(chan, &channel, bindchan);
980 ProgramMapPtr pmap(new ProgramMap);
981 ret.insert(std::make_pair(channel.chanId, pmap));
982 // Object: Programs[]
983 const JSON::Node& progs = chan.GetObjectValue("Programs");
984 // Iterates over the sequence elements.
985 size_t ps = progs.Size();
986 for (size_t pi = 0; pi < ps; ++pi)
987 {
988 ++count;
989 const JSON::Node& prog = progs.GetArrayElement(pi);
990 ProgramPtr program(new Program()); // Using default constructor
991 // Bind the new program
992 JSON::BindObject(prog, program.get(), bindprog);
993 program->channel = channel;
994 pmap->insert(std::make_pair(program->startTime, program));
995 }
996 }
997 DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count);
998
999 return ret;
1000}
1001
1002ProgramMapPtr WSAPI::GetProgramGuide1_0(uint32_t chanid, time_t starttime, time_t endtime)
1003{
1004 ProgramMapPtr ret(new ProgramMap);
1005 BUILTIN_BUFFER buf;
1006 int32_t count = 0;
1007 unsigned proto = (unsigned)m_version.protocol;
1008
1009 // Get bindings for protocol version
1010 const bindings_t *bindlist = MythDTO::getListBindArray(proto);
1011 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
1012 const bindings_t *bindprog = MythDTO::getProgramBindArray(proto);
1013
1014 // Initialize request header
1015 Query qry(*this);
1016 qry.Request().RequestAccept(WS_ACCEPT);
1017 qry.Request().RequestService("/Guide/GetProgramGuide", WS_METHOD_Get);
1018 uint32_to_string(chanid, &buf);
1019 qry.Request().SetContentParam("StartChanId", buf.data);
1020 qry.Request().SetContentParam("NumChannels", "1");
1021 time_to_iso8601utc(starttime, &buf);
1022 qry.Request().SetContentParam("StartTime", buf.data);
1023 time_to_iso8601utc(endtime, &buf);
1024 qry.Request().SetContentParam("EndTime", buf.data);
1025 qry.Request().SetContentParam("Details", "true");
1026
1027 autoptr<WSResponse> resp(qry.Execute());
1028 if (!resp->IsSuccessful())
1029 {
1030 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1031 return ret;
1032 }
1033 const JSON::Document json(*resp);
1034 const JSON::Node& root = json.GetRoot();
1035 if (!json.IsValid() || !root.IsObject())
1036 {
1037 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1038 return ret;
1039 }
1040 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1041
1042 // Object: ProgramGuide
1043 const JSON::Node& glist = root.GetObjectValue("ProgramGuide");
1044 ItemList list = ItemList(); // Using default constructor
1045 JSON::BindObject(glist, &list, bindlist);
1046 // List has ProtoVer. Check it or sound alarm
1047 if (list.protoVer != proto)
1048 {
1049 InvalidateService();
1050 return ret;
1051 }
1052 // Object: Channels[]
1053 const JSON::Node& chans = glist.GetObjectValue("Channels");
1054 // Iterates over the sequence elements.
1055 size_t cs = chans.Size();
1056 for (size_t ci = 0; ci < cs; ++ci)
1057 {
1058 const JSON::Node& chan = chans.GetArrayElement(ci);
1059 Channel channel;
1060 JSON::BindObject(chan, &channel, bindchan);
1061 if (channel.chanId != chanid)
1062 continue;
1063 // Object: Programs[]
1064 const JSON::Node& progs = chan.GetObjectValue("Programs");
1065 // Iterates over the sequence elements.
1066 size_t ps = progs.Size();
1067 for (size_t pi = 0; pi < ps; ++pi)
1068 {
1069 ++count;
1070 const JSON::Node& prog = progs.GetArrayElement(pi);
1071 ProgramPtr program(new Program()); // Using default constructor
1072 // Bind the new program
1073 JSON::BindObject(prog, program.get(), bindprog);
1074 program->channel = channel;
1075 ret->insert(std::make_pair(program->startTime, program));
1076 }
1077 break;
1078 }
1079 DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count);
1080
1081 return ret;
1082}
1083
1084std::map<uint32_t, ProgramMapPtr> WSAPI::GetProgramGuide2_2(time_t starttime, time_t endtime)
1085{
1086 std::map<uint32_t, ProgramMapPtr> ret;
1087 BUILTIN_BUFFER buf;
1088 uint32_t req_index = 0, req_count = FETCHSIZE, count = 0;
1089 unsigned proto = (unsigned)m_version.protocol;
1090
1091 // Adjust the fetch count according to the number of requested days
1092 double d = difftime(endtime, starttime);
1093 if (d > 0)
1094 req_count = FETCHSIZE / (int)(1.0 + d / (3 * 86400));
1095
1096 // Get bindings for protocol version
1097 const bindings_t *bindlist = MythDTO::getListBindArray(proto);
1098 const bindings_t *bindprog = MythDTO::getProgramBindArray(proto);
1099 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
1100
1101 // Initialize request header
1102 Query qry(*this);
1103 qry.Request().RequestAccept(WS_ACCEPT);
1104 qry.Request().RequestService("/Guide/GetProgramGuide", WS_METHOD_Get);
1105
1106 do
1107 {
1108 qry.Request().ClearContent();
1109 uint32_to_string(req_index, &buf);
1110 qry.Request().SetContentParam("StartIndex", buf.data);
1111 uint32_to_string(req_count, &buf);
1112 qry.Request().SetContentParam("Count", buf.data);
1113 time_to_iso8601utc(starttime, &buf);
1114 qry.Request().SetContentParam("StartTime", buf.data);
1115 time_to_iso8601utc(endtime, &buf);
1116 qry.Request().SetContentParam("EndTime", buf.data);
1117 qry.Request().SetContentParam("Details", "true");
1118
1119 DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
1120 autoptr<WSResponse> resp(qry.Execute());
1121 if (!resp->IsSuccessful())
1122 {
1123 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1124 break;
1125 }
1126 const JSON::Document json(*resp);
1127 const JSON::Node& root = json.GetRoot();
1128 if (!json.IsValid() || !root.IsObject())
1129 {
1130 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1131 break;
1132 }
1133 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1134
1135 // Object: ProgramGuide
1136 const JSON::Node& glist = root.GetObjectValue("ProgramGuide");
1137 ItemList list = ItemList(); // Using default constructor
1138 JSON::BindObject(glist, &list, bindlist);
1139 // List has ProtoVer. Check it or sound alarm
1140 if (list.protoVer != proto)
1141 {
1142 InvalidateService();
1143 break;
1144 }
1145 count = 0;
1146 // Object: Channels[]
1147 const JSON::Node& chans = glist.GetObjectValue("Channels");
1148 // Iterates over the sequence elements.
1149 size_t cs = chans.Size();
1150 for (size_t ci = 0; ci < cs; ++ci)
1151 {
1152 ++count;
1153 const JSON::Node& chan = chans.GetArrayElement(ci);
1154 Channel channel;
1155 JSON::BindObject(chan, &channel, bindchan);
1156 ProgramMapPtr pmap(new ProgramMap);
1157 ret.insert(std::make_pair(channel.chanId, pmap));
1158 // Object: Programs[]
1159 const JSON::Node& progs = chan.GetObjectValue("Programs");
1160 // Iterates over the sequence elements.
1161 size_t ps = progs.Size();
1162 for (size_t pi = 0; pi < ps; ++pi)
1163 {
1164 const JSON::Node& prog = progs.GetArrayElement(pi);
1165 ProgramPtr program(new Program()); // Using default constructor
1166 // Bind the new program
1167 JSON::BindObject(prog, program.get(), bindprog);
1168 program->channel = channel;
1169 pmap->insert(std::make_pair(program->startTime, program));
1170 }
1171 }
1172 DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count);
1173 req_index += count; // Set next requested index
1174 }
1175 while (count == req_count);
1176
1177 return ret;
1178}
1179
1180ProgramMapPtr WSAPI::GetProgramList2_2(uint32_t chanid, time_t starttime, time_t endtime)
1181{
1182 ProgramMapPtr ret(new ProgramMap);
1183 BUILTIN_BUFFER buf;
1184 uint32_t req_index = 0, req_count = FETCHSIZE_L, count = 0;
1185 unsigned proto = (unsigned)m_version.protocol;
1186
1187 // Get bindings for protocol version
1188 const bindings_t *bindlist = MythDTO::getListBindArray(proto);
1189 const bindings_t *bindprog = MythDTO::getProgramBindArray(proto);
1190 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
1191
1192 // Initialize request header
1193 Query qry(*this);
1194 qry.Request().RequestAccept(WS_ACCEPT);
1195 qry.Request().RequestService("/Guide/GetProgramList", WS_METHOD_Get);
1196
1197 do
1198 {
1199 qry.Request().ClearContent();
1200 uint32_to_string(req_index, &buf);
1201 qry.Request().SetContentParam("StartIndex", buf.data);
1202 uint32_to_string(req_count, &buf);
1203 qry.Request().SetContentParam("Count", buf.data);
1204 uint32_to_string(chanid, &buf);
1205 qry.Request().SetContentParam("ChanId", buf.data);
1206 time_to_iso8601utc(starttime, &buf);
1207 qry.Request().SetContentParam("StartTime", buf.data);
1208 time_to_iso8601utc(endtime, &buf);
1209 qry.Request().SetContentParam("EndTime", buf.data);
1210 qry.Request().SetContentParam("Details", "true");
1211
1212 DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
1213 autoptr<WSResponse> resp(qry.Execute());
1214 if (!resp->IsSuccessful())
1215 {
1216 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1217 break;
1218 }
1219 const JSON::Document json(*resp);
1220 const JSON::Node& root = json.GetRoot();
1221 if (!json.IsValid() || !root.IsObject())
1222 {
1223 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1224 break;
1225 }
1226 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1227
1228 // Object: ProgramList
1229 const JSON::Node& plist = root.GetObjectValue("ProgramList");
1230 ItemList list = ItemList(); // Using default constructor
1231 JSON::BindObject(plist, &list, bindlist);
1232 // List has ProtoVer. Check it or sound alarm
1233 if (list.protoVer != proto)
1234 {
1235 InvalidateService();
1236 break;
1237 }
1238 count = 0;
1239 // Object: Programs[]
1240 const JSON::Node& progs = plist.GetObjectValue("Programs");
1241 // Iterates over the sequence elements.
1242 size_t ps = progs.Size();
1243 for (size_t pi = 0; pi < ps; ++pi)
1244 {
1245 ++count;
1246 const JSON::Node& prog = progs.GetArrayElement(pi);
1247 ProgramPtr program(new Program()); // Using default constructor
1248 // Bind the new program
1249 JSON::BindObject(prog, program.get(), bindprog);
1250 // Bind channel of program
1251 const JSON::Node& chan = prog.GetObjectValue("Channel");
1252 JSON::BindObject(chan, &(program->channel), bindchan);
1253 ret->insert(std::make_pair(program->startTime, program));
1254 }
1255 DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count);
1256 req_index += count; // Set next requested index
1257 }
1258 while (count == req_count);
1259
1260 return ret;
1261}
1262
1267ProgramListPtr WSAPI::GetRecordedList1_5(unsigned n, bool descending)
1268{
1269 ProgramListPtr ret(new ProgramList);
1270 BUILTIN_BUFFER buf;
1271 uint32_t req_index = 0, req_count = FETCHSIZE, count = 0, total = 0;
1272 unsigned proto = (unsigned)m_version.protocol;
1273
1274 // Get bindings for protocol version
1275 const bindings_t *bindlist = MythDTO::getListBindArray(proto);
1276 const bindings_t *bindprog = MythDTO::getProgramBindArray(proto);
1277 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
1278 const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto);
1279 const bindings_t *bindartw = MythDTO::getArtworkBindArray(proto);
1280
1281 // Initialize request header
1282 Query qry(*this);
1283 qry.Request().RequestAccept(WS_ACCEPT);
1284 qry.Request().RequestService("/Dvr/GetRecordedList", WS_METHOD_Get);
1285
1286 do
1287 {
1288 // Adjust the packet size
1289 if (n && req_count > (n - total))
1290 req_count = (n - total);
1291
1292 qry.Request().ClearContent();
1293 uint32_to_string(req_index, &buf);
1294 qry.Request().SetContentParam("StartIndex", buf.data);
1295 uint32_to_string(req_count, &buf);
1296 qry.Request().SetContentParam("Count", buf.data);
1297 qry.Request().SetContentParam("Descending", BOOLSTR(descending));
1298
1299 DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
1300 autoptr<WSResponse> resp(qry.Execute());
1301 if (!resp->IsSuccessful())
1302 {
1303 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1304 break;
1305 }
1306 const JSON::Document json(*resp);
1307 const JSON::Node& root = json.GetRoot();
1308 if (!json.IsValid() || !root.IsObject())
1309 {
1310 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1311 break;
1312 }
1313 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1314
1315 // Object: ProgramList
1316 const JSON::Node& plist = root.GetObjectValue("ProgramList");
1317 ItemList list = ItemList(); // Using default constructor
1318 JSON::BindObject(plist, &list, bindlist);
1319 // List has ProtoVer. Check it or sound alarm
1320 if (list.protoVer != proto)
1321 {
1322 InvalidateService();
1323 break;
1324 }
1325 count = 0;
1326 // Object: Programs[]
1327 const JSON::Node& progs = plist.GetObjectValue("Programs");
1328 // Iterates over the sequence elements.
1329 size_t ps = progs.Size();
1330 for (size_t pi = 0; pi < ps; ++pi)
1331 {
1332 ++count;
1333 const JSON::Node& prog = progs.GetArrayElement(pi);
1334 ProgramPtr program(new Program()); // Using default constructor
1335 // Bind the new program
1336 JSON::BindObject(prog, program.get(), bindprog);
1337 // Bind channel of program
1338 const JSON::Node& chan = prog.GetObjectValue("Channel");
1339 JSON::BindObject(chan, &(program->channel), bindchan);
1340 // Bind recording of program
1341 const JSON::Node& reco = prog.GetObjectValue("Recording");
1342 JSON::BindObject(reco, &(program->recording), bindreco);
1343 // Bind artwork list of program
1344 if (!prog.GetObjectValue("Artwork").IsNull())
1345 {
1346 const JSON::Node& arts = prog.GetObjectValue("Artwork").GetObjectValue("ArtworkInfos");
1347 size_t as = arts.Size();
1348 for (size_t pa = 0; pa < as; ++pa)
1349 {
1350 const JSON::Node& artw = arts.GetArrayElement(pa);
1351 Artwork artwork = Artwork(); // Using default constructor
1352 JSON::BindObject(artw, &artwork, bindartw);
1353 program->artwork.push_back(artwork);
1354 }
1355 }
1356 ret->push_back(program);
1357 ++total;
1358 }
1359 DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count);
1360 req_index += count; // Set next requested index
1361 }
1362 while (count == req_count && (!n || n > total));
1363
1364 return ret;
1365}
1366
1367ProgramPtr WSAPI::GetRecorded1_5(uint32_t chanid, time_t recstartts)
1368{
1369 ProgramPtr ret;
1370 BUILTIN_BUFFER buf;
1371 unsigned proto = (unsigned)m_version.protocol;
1372
1373 // Get bindings for protocol version
1374 const bindings_t *bindprog = MythDTO::getProgramBindArray(proto);
1375 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
1376 const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto);
1377 const bindings_t *bindartw = MythDTO::getArtworkBindArray(proto);
1378
1379 Query qry(*this);
1380 qry.Request().RequestAccept(WS_ACCEPT);
1381 qry.Request().RequestService("/Dvr/GetRecorded", WS_METHOD_Get);
1382 uint32_to_string(chanid, &buf);
1383 qry.Request().SetContentParam("ChanId", buf.data);
1384 time_to_iso8601utc(recstartts, &buf);
1385 qry.Request().SetContentParam("StartTime", buf.data);
1386 autoptr<WSResponse> resp(qry.Execute());
1387 if (!resp->IsSuccessful())
1388 {
1389 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1390 return ret;
1391 }
1392 const JSON::Document json(*resp);
1393 const JSON::Node& root = json.GetRoot();
1394 if (!json.IsValid() || !root.IsObject())
1395 {
1396 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1397 return ret;
1398 }
1399 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1400
1401 const JSON::Node& prog = root.GetObjectValue("Program");
1402 ProgramPtr program(new Program()); // Using default constructor
1403 // Bind the new program
1404 JSON::BindObject(prog, program.get(), bindprog);
1405 // Bind channel of program
1406 const JSON::Node& chan = prog.GetObjectValue("Channel");
1407 JSON::BindObject(chan, &(program->channel), bindchan);
1408 // Bind recording of program
1409 const JSON::Node& reco = prog.GetObjectValue("Recording");
1410 JSON::BindObject(reco, &(program->recording), bindreco);
1411 // Bind artwork list of program
1412 if (!prog.GetObjectValue("Artwork").IsNull())
1413 {
1414 const JSON::Node& arts = prog.GetObjectValue("Artwork").GetObjectValue("ArtworkInfos");
1415 size_t as = arts.Size();
1416 for (size_t pa = 0; pa < as; ++pa)
1417 {
1418 const JSON::Node& artw = arts.GetArrayElement(pa);
1419 Artwork artwork = Artwork(); // Using default constructor
1420 JSON::BindObject(artw, &artwork, bindartw);
1421 program->artwork.push_back(artwork);
1422 }
1423 }
1424 // Return valid program
1425 if (program->recording.startTs != INVALID_TIME)
1426 ret = program;
1427 return ret;
1428}
1429
1430ProgramPtr WSAPI::GetRecorded6_0(uint32_t recordedid)
1431{
1432 ProgramPtr ret;
1433 BUILTIN_BUFFER buf;
1434 unsigned proto = (unsigned)m_version.protocol;
1435
1436 // Get bindings for protocol version
1437 const bindings_t *bindprog = MythDTO::getProgramBindArray(proto);
1438 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
1439 const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto);
1440 const bindings_t *bindartw = MythDTO::getArtworkBindArray(proto);
1441
1442 Query qry(*this);
1443 qry.Request().RequestAccept(WS_ACCEPT);
1444 qry.Request().RequestService("/Dvr/GetRecorded", WS_METHOD_Get);
1445 uint32_to_string(recordedid, &buf);
1446 qry.Request().SetContentParam("RecordedId", buf.data);
1447 autoptr<WSResponse> resp(qry.Execute());
1448 if (!resp->IsSuccessful())
1449 {
1450 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1451 return ret;
1452 }
1453 const JSON::Document json(*resp);
1454 const JSON::Node& root = json.GetRoot();
1455 if (!json.IsValid() || !root.IsObject())
1456 {
1457 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1458 return ret;
1459 }
1460 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1461
1462 const JSON::Node& prog = root.GetObjectValue("Program");
1463 ProgramPtr program(new Program()); // Using default constructor
1464 // Bind the new program
1465 JSON::BindObject(prog, program.get(), bindprog);
1466 // Bind channel of program
1467 const JSON::Node& chan = prog.GetObjectValue("Channel");
1468 JSON::BindObject(chan, &(program->channel), bindchan);
1469 // Bind recording of program
1470 const JSON::Node& reco = prog.GetObjectValue("Recording");
1471 JSON::BindObject(reco, &(program->recording), bindreco);
1472 // Bind artwork list of program
1473 if (!prog.GetObjectValue("Artwork").IsNull())
1474 {
1475 const JSON::Node& arts = prog.GetObjectValue("Artwork").GetObjectValue("ArtworkInfos");
1476 size_t as = arts.Size();
1477 for (size_t pa = 0; pa < as; ++pa)
1478 {
1479 const JSON::Node& artw = arts.GetArrayElement(pa);
1480 Artwork artwork = Artwork(); // Using default constructor
1481 JSON::BindObject(artw, &artwork, bindartw);
1482 program->artwork.push_back(artwork);
1483 }
1484 }
1485 // Return valid program
1486 if (program->recording.startTs != INVALID_TIME)
1487 ret = program;
1488 return ret;
1489}
1490
1491bool WSAPI::DeleteRecording2_1(uint32_t chanid, time_t recstartts, bool forceDelete, bool allowRerecord)
1492{
1493 BUILTIN_BUFFER buf;
1494
1495 // Initialize request header
1496 Query qry(*this);
1497 qry.Request().RequestAccept(WS_ACCEPT);
1498 qry.Request().RequestService("/Dvr/DeleteRecording", WS_METHOD_Post);
1499 uint32_to_string(chanid, &buf);
1500 qry.Request().SetContentParam("ChanId", buf.data);
1501 time_to_iso8601utc(recstartts, &buf);
1502 qry.Request().SetContentParam("StartTime", buf.data);
1503 qry.Request().SetContentParam("ForceDelete", BOOLSTR(forceDelete));
1504 qry.Request().SetContentParam("AllowRerecord", BOOLSTR(allowRerecord));
1505 autoptr<WSResponse> resp(qry.Execute());
1506 if (!resp->IsSuccessful())
1507 {
1508 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1509 return false;
1510 }
1511 const JSON::Document json(*resp);
1512 const JSON::Node& root = json.GetRoot();
1513 if (!json.IsValid() || !root.IsObject())
1514 {
1515 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1516 return false;
1517 }
1518 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1519
1520 const JSON::Node& field = root.GetObjectValue("bool");
1521 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
1522 return true;
1523 return false;
1524}
1525
1526bool WSAPI::DeleteRecording6_0(uint32_t recordedid, bool forceDelete, bool allowRerecord)
1527{
1528 BUILTIN_BUFFER buf;
1529
1530 // Initialize request header
1531 Query qry(*this);
1532 qry.Request().RequestAccept(WS_ACCEPT);
1533 qry.Request().RequestService("/Dvr/DeleteRecording", WS_METHOD_Post);
1534 uint32_to_string(recordedid, &buf);
1535 qry.Request().SetContentParam("RecordedId", buf.data);
1536 qry.Request().SetContentParam("ForceDelete", BOOLSTR(forceDelete));
1537 qry.Request().SetContentParam("AllowRerecord", BOOLSTR(allowRerecord));
1538 autoptr<WSResponse> resp(qry.Execute());
1539 if (!resp->IsSuccessful())
1540 {
1541 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1542 return false;
1543 }
1544 const JSON::Document json(*resp);
1545 const JSON::Node& root = json.GetRoot();
1546 if (!json.IsValid() || !root.IsObject())
1547 {
1548 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1549 return false;
1550 }
1551 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1552
1553 const JSON::Node& field = root.GetObjectValue("bool");
1554 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
1555 return true;
1556 return false;
1557}
1558
1559bool WSAPI::UnDeleteRecording2_1(uint32_t chanid, time_t recstartts)
1560{
1561 BUILTIN_BUFFER buf;
1562
1563 // Initialize request header
1564 Query qry(*this);
1565 qry.Request().RequestAccept(WS_ACCEPT);
1566 qry.Request().RequestService("/Dvr/UnDeleteRecording", WS_METHOD_Post);
1567 uint32_to_string(chanid, &buf);
1568 qry.Request().SetContentParam("ChanId", buf.data);
1569 time_to_iso8601utc(recstartts, &buf);
1570 qry.Request().SetContentParam("StartTime", buf.data);
1571 autoptr<WSResponse> resp(qry.Execute());
1572 if (!resp->IsSuccessful())
1573 {
1574 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1575 return false;
1576 }
1577 const JSON::Document json(*resp);
1578 const JSON::Node& root = json.GetRoot();
1579 if (!json.IsValid() || !root.IsObject())
1580 {
1581 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1582 return false;
1583 }
1584 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1585
1586 const JSON::Node& field = root.GetObjectValue("bool");
1587 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
1588 return true;
1589 return false;
1590}
1591
1592bool WSAPI::UnDeleteRecording6_0(uint32_t recordedid)
1593{
1594 BUILTIN_BUFFER buf;
1595
1596 // Initialize request header
1597 Query qry(*this);
1598 qry.Request().RequestAccept(WS_ACCEPT);
1599 qry.Request().RequestService("/Dvr/UnDeleteRecording", WS_METHOD_Post);
1600 uint32_to_string(recordedid, &buf);
1601 qry.Request().SetContentParam("RecordedId", buf.data);
1602 autoptr<WSResponse> resp(qry.Execute());
1603 if (!resp->IsSuccessful())
1604 {
1605 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1606 return false;
1607 }
1608 const JSON::Document json(*resp);
1609 const JSON::Node& root = json.GetRoot();
1610 if (!json.IsValid() || !root.IsObject())
1611 {
1612 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1613 return false;
1614 }
1615 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1616
1617 const JSON::Node& field = root.GetObjectValue("bool");
1618 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
1619 return true;
1620 return false;
1621}
1622
1623bool WSAPI::UpdateRecordedWatchedStatus4_5(uint32_t chanid, time_t recstartts, bool watched)
1624{
1625 BUILTIN_BUFFER buf;
1626
1627 // Initialize request header
1628 Query qry(*this);
1629 qry.Request().RequestAccept(WS_ACCEPT);
1630 qry.Request().RequestService("/Dvr/UpdateRecordedWatchedStatus", WS_METHOD_Post);
1631 uint32_to_string(chanid, &buf);
1632 qry.Request().SetContentParam("ChanId", buf.data);
1633 time_to_iso8601utc(recstartts, &buf);
1634 qry.Request().SetContentParam("StartTime", buf.data);
1635 qry.Request().SetContentParam("Watched", BOOLSTR(watched));
1636 autoptr<WSResponse> resp(qry.Execute());
1637 if (!resp->IsSuccessful())
1638 {
1639 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1640 return false;
1641 }
1642 const JSON::Document json(*resp);
1643 const JSON::Node& root = json.GetRoot();
1644 if (!json.IsValid() || !root.IsObject())
1645 {
1646 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1647 return false;
1648 }
1649 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1650
1651 const JSON::Node& field = root.GetObjectValue("bool");
1652 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
1653 return true;
1654 return false;
1655}
1656
1657bool WSAPI::UpdateRecordedWatchedStatus6_0(uint32_t recordedid, bool watched)
1658{
1659 BUILTIN_BUFFER buf;
1660
1661 // Initialize request header
1662 Query qry(*this);
1663 qry.Request().RequestAccept(WS_ACCEPT);
1664 qry.Request().RequestService("/Dvr/UpdateRecordedWatchedStatus", WS_METHOD_Post);
1665 uint32_to_string(recordedid, &buf);
1666 qry.Request().SetContentParam("RecordedId", buf.data);
1667 qry.Request().SetContentParam("Watched", BOOLSTR(watched));
1668 autoptr<WSResponse> resp(qry.Execute());
1669 if (!resp->IsSuccessful())
1670 {
1671 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1672 return false;
1673 }
1674 const JSON::Document json(*resp);
1675 const JSON::Node& root = json.GetRoot();
1676 if (!json.IsValid() || !root.IsObject())
1677 {
1678 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1679 return false;
1680 }
1681 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1682
1683 const JSON::Node& field = root.GetObjectValue("bool");
1684 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
1685 return true;
1686 return false;
1687}
1688
1689MarkListPtr WSAPI::GetRecordedCommBreak6_1(uint32_t recordedid, int unit)
1690{
1691 BUILTIN_BUFFER buf;
1692 MarkListPtr ret(new MarkList);
1693 unsigned proto = (unsigned)m_version.protocol;
1694
1695 // Get bindings for protocol version
1696 const bindings_t *bindcut = MythDTO::getCuttingBindArray(proto);
1697
1698 // Initialize request header
1699 Query qry(*this);
1700 qry.Request().RequestAccept(WS_ACCEPT);
1701 qry.Request().RequestService("/Dvr/GetRecordedCommBreak", WS_METHOD_Get);
1702 uint32_to_string(recordedid, &buf);
1703 qry.Request().SetContentParam("RecordedId", buf.data);
1704 if (unit == 1)
1705 qry.Request().SetContentParam("OffsetType", "Position");
1706 else if (unit == 2)
1707 qry.Request().SetContentParam("OffsetType", "Duration");
1708 autoptr<WSResponse> resp(qry.Execute());
1709 if (!resp->IsSuccessful())
1710 {
1711 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1712 return ret;
1713 }
1714 const JSON::Document json(*resp);
1715 const JSON::Node& root = json.GetRoot();
1716 if (!json.IsValid() || !root.IsObject())
1717 {
1718 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1719 return ret;
1720 }
1721 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1722
1723 // Object: CutList
1724 const JSON::Node& slist = root.GetObjectValue("CutList");
1725 // Object: Cuttings[]
1726 const JSON::Node& vcuts = slist.GetObjectValue("Cuttings");
1727 // Iterates over the sequence elements.
1728 size_t vs = vcuts.Size();
1729 for (size_t vi = 0; vi < vs; ++vi)
1730 {
1731 const JSON::Node& vcut = vcuts.GetArrayElement(vi);
1732 MarkPtr mark(new Mark()); // Using default constructor
1733 // Bind the new mark
1734 JSON::BindObject(vcut, mark.get(), bindcut);
1735 ret->push_back(mark);
1736 }
1737 return ret;
1738}
1739
1740MarkListPtr WSAPI::GetRecordedCutList6_1(uint32_t recordedid, int unit)
1741{
1742 BUILTIN_BUFFER buf;
1743 MarkListPtr ret(new MarkList);
1744 unsigned proto = (unsigned)m_version.protocol;
1745
1746 // Get bindings for protocol version
1747 const bindings_t *bindcut = MythDTO::getCuttingBindArray(proto);
1748
1749 // Initialize request header
1750 Query qry(*this);
1751 qry.Request().RequestAccept(WS_ACCEPT);
1752 qry.Request().RequestService("/Dvr/GetRecordedCutList", WS_METHOD_Get);
1753 uint32_to_string(recordedid, &buf);
1754 qry.Request().SetContentParam("RecordedId", buf.data);
1755 if (unit == 1)
1756 qry.Request().SetContentParam("OffsetType", "Position");
1757 else if (unit == 2)
1758 qry.Request().SetContentParam("OffsetType", "Duration");
1759 autoptr<WSResponse> resp(qry.Execute());
1760 if (!resp->IsSuccessful())
1761 {
1762 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1763 return ret;
1764 }
1765 const JSON::Document json(*resp);
1766 const JSON::Node& root = json.GetRoot();
1767 if (!json.IsValid() || !root.IsObject())
1768 {
1769 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1770 return ret;
1771 }
1772 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1773
1774 // Object: CutList
1775 const JSON::Node& slist = root.GetObjectValue("CutList");
1776 // Object: Cuttings[]
1777 const JSON::Node& vcuts = slist.GetObjectValue("Cuttings");
1778 // Iterates over the sequence elements.
1779 size_t vs = vcuts.Size();
1780 for (size_t vi = 0; vi < vs; ++vi)
1781 {
1782 const JSON::Node& vcut = vcuts.GetArrayElement(vi);
1783 MarkPtr mark(new Mark()); // Using default constructor
1784 // Bind the new mark
1785 JSON::BindObject(vcut, mark.get(), bindcut);
1786 ret->push_back(mark);
1787 }
1788 return ret;
1789}
1790
1791bool WSAPI::SetSavedBookmark6_2(uint32_t recordedid, int unit, int64_t value)
1792{
1793 BUILTIN_BUFFER buf;
1794
1795 // Initialize request header
1796 Query qry(*this);
1797 qry.Request().RequestAccept(WS_ACCEPT);
1798 qry.Request().RequestService("/Dvr/SetSavedBookmark", WS_METHOD_Post);
1799 uint32_to_string(recordedid, &buf);
1800 qry.Request().SetContentParam("RecordedId", buf.data);
1801 if (unit == 2)
1802 qry.Request().SetContentParam("OffsetType", "Duration");
1803 else
1804 qry.Request().SetContentParam("OffsetType", "Position");
1805 int64_to_string(value, &buf);
1806 qry.Request().SetContentParam("Offset", buf.data);
1807 autoptr<WSResponse> resp(qry.Execute());
1808 if (!resp->IsSuccessful())
1809 {
1810 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1811 return false;
1812 }
1813 const JSON::Document json(*resp);
1814 const JSON::Node& root = json.GetRoot();
1815 if (!json.IsValid() || !root.IsObject())
1816 {
1817 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1818 return false;
1819 }
1820 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1821
1822 const JSON::Node& field = root.GetObjectValue("bool");
1823 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
1824 return true;
1825 return false;
1826}
1827
1828int64_t WSAPI::GetSavedBookmark6_2(uint32_t recordedid, int unit)
1829{
1830 BUILTIN_BUFFER buf;
1831
1832 // Initialize request header
1833 Query qry(*this);
1834 qry.Request().RequestAccept(WS_ACCEPT);
1835 qry.Request().RequestService("/Dvr/GetSavedBookmark", WS_METHOD_Get);
1836 uint32_to_string(recordedid, &buf);
1837 qry.Request().SetContentParam("RecordedId", buf.data);
1838 if (unit == 2)
1839 qry.Request().SetContentParam("OffsetType", "Duration");
1840 else
1841 qry.Request().SetContentParam("OffsetType", "Position");
1842 autoptr<WSResponse> resp(qry.Execute());
1843 if (!resp->IsSuccessful())
1844 {
1845 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1846 return false;
1847 }
1848 const JSON::Document json(*resp);
1849 const JSON::Node& root = json.GetRoot();
1850 if (!json.IsValid() || !root.IsObject())
1851 {
1852 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1853 return false;
1854 }
1855 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1856
1857 int64_t value = 0;
1858 const JSON::Node& field = root.GetObjectValue("long");
1859 if (field.IsInt())
1860 value = field.GetBigIntValue();
1861 else if (!field.IsString() || string_to_int64(field.GetStringValue().c_str(), &value))
1862 return -1;
1863 return value;
1864}
1865
1866static void ProcessRecordIN(unsigned proto, RecordSchedule& record)
1867{
1868 // Converting API codes to internal types
1869 record.type_t = RuleTypeFromString(proto, record.type);
1870 record.searchType_t = SearchTypeFromString(proto, record.searchType);
1871 record.dupMethod_t = DupMethodFromString(proto, record.dupMethod);
1872 record.dupIn_t = DupInFromString(proto, record.dupIn);
1873}
1874
1875RecordScheduleListPtr WSAPI::GetRecordScheduleList1_5()
1876{
1877 RecordScheduleListPtr ret(new RecordScheduleList);
1878 BUILTIN_BUFFER buf;
1879 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
1880 unsigned proto = (unsigned)m_version.protocol;
1881
1882 // Get bindings for protocol version
1883 const bindings_t *bindlist = MythDTO::getListBindArray(proto);
1884 const bindings_t *bindrec = MythDTO::getRecordScheduleBindArray(proto);
1885
1886 // Initialize request header
1887 Query qry(*this);
1888 qry.Request().RequestAccept(WS_ACCEPT);
1889 qry.Request().RequestService("/Dvr/GetRecordScheduleList", WS_METHOD_Get);
1890
1891 do
1892 {
1893 qry.Request().ClearContent();
1894 int32_to_string(req_index, &buf);
1895 qry.Request().SetContentParam("StartIndex", buf.data);
1896 int32_to_string(req_count, &buf);
1897 qry.Request().SetContentParam("Count", buf.data);
1898
1899 DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
1900 autoptr<WSResponse> resp(qry.Execute());
1901 if (!resp->IsSuccessful())
1902 {
1903 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1904 break;
1905 }
1906 const JSON::Document json(*resp);
1907 const JSON::Node& root = json.GetRoot();
1908 if (!json.IsValid() || !root.IsObject())
1909 {
1910 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1911 break;
1912 }
1913 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1914
1915 // Object: RecRuleList
1916 const JSON::Node& rlist = root.GetObjectValue("RecRuleList");
1917 ItemList list = ItemList(); // Using default constructor
1918 JSON::BindObject(rlist, &list, bindlist);
1919 // List has ProtoVer. Check it or sound alarm
1920 if (list.protoVer != proto)
1921 {
1922 InvalidateService();
1923 break;
1924 }
1925 count = 0;
1926 // Object: RecRules[]
1927 const JSON::Node& recs = rlist.GetObjectValue("RecRules");
1928 // Iterates over the sequence elements.
1929 size_t rs = recs.Size();
1930 for (size_t ri = 0; ri < rs; ++ri)
1931 {
1932 ++count;
1933 const JSON::Node& rec = recs.GetArrayElement(ri);
1934 RecordSchedulePtr record(new RecordSchedule()); // Using default constructor
1935 // Bind the new record
1936 JSON::BindObject(rec, record.get(), bindrec);
1937 ProcessRecordIN(proto, *record);
1938 ret->push_back(record);
1939 }
1940 DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count);
1941 req_index += count; // Set next requested index
1942 }
1943 while (count == req_count);
1944
1945 return ret;
1946}
1947
1948RecordSchedulePtr WSAPI::GetRecordSchedule1_5(uint32_t recordid)
1949{
1950 RecordSchedulePtr ret;
1951 BUILTIN_BUFFER buf;
1952 unsigned proto = (unsigned)m_version.protocol;
1953
1954 // Get bindings for protocol version
1955 const bindings_t *bindrec = MythDTO::getRecordScheduleBindArray(proto);
1956
1957 Query qry(*this);
1958 qry.Request().RequestAccept(WS_ACCEPT);
1959 qry.Request().RequestService("/Dvr/GetRecordSchedule", WS_METHOD_Get);
1960 uint32_to_string(recordid, &buf);
1961 qry.Request().SetContentParam("RecordId", buf.data);
1962 autoptr<WSResponse> resp(qry.Execute());
1963 if (!resp->IsSuccessful())
1964 {
1965 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
1966 return ret;
1967 }
1968 const JSON::Document json(*resp);
1969 const JSON::Node& root = json.GetRoot();
1970 if (!json.IsValid() || !root.IsObject())
1971 {
1972 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
1973 return ret;
1974 }
1975 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
1976
1977 const JSON::Node& rec = root.GetObjectValue("RecRule");
1978 RecordSchedulePtr record(new RecordSchedule()); // Using default constructor
1979 // Bind the new record
1980 JSON::BindObject(rec, record.get(), bindrec);
1981 // Return valid record
1982 if (record->recordId > 0)
1983 {
1984 ProcessRecordIN(proto, *record);
1985 ret = record;
1986 }
1987 return ret;
1988}
1989
1990static void ProcessRecordOUT(unsigned proto, RecordSchedule& record)
1991{
1992 char buf[10];
1993 struct tm stm;
1994 time_t st = record.startTime;
1995 localtime_r(&st, &stm);
1996 // Set find time & day
1997 snprintf(buf, sizeof(buf), "%.2d:%.2d:%.2d", stm.tm_hour, stm.tm_min, stm.tm_sec);
1998 record.findTime = buf;
1999 record.findDay = (stm.tm_wday + 1) % 7;
2000 // Converting internal types to API codes
2001 record.type = RuleTypeToString(proto, record.type_t);
2002 record.searchType = SearchTypeToString(proto, record.searchType_t);
2003 record.dupMethod = DupMethodToString(proto, record.dupMethod_t);
2004 record.dupIn = DupInToString(proto, record.dupIn_t);
2005}
2006
2007bool WSAPI::AddRecordSchedule1_5(RecordSchedule& record)
2008{
2009 BUILTIN_BUFFER buf;
2010 uint32_t recordid;
2011 unsigned proto = (unsigned)m_version.protocol;
2012
2013 ProcessRecordOUT(proto, record);
2014
2015 // Initialize request header
2016 Query qry(*this);
2017 qry.Request().RequestAccept(WS_ACCEPT);
2018 qry.Request().RequestService("/Dvr/AddRecordSchedule", WS_METHOD_Post);
2019
2020 qry.Request().SetContentParam("Title", record.title);
2021 qry.Request().SetContentParam("Subtitle", record.subtitle);
2022 qry.Request().SetContentParam("Description", record.description);
2023 qry.Request().SetContentParam("Category", record.category);
2024 time_to_iso8601utc(record.startTime, &buf);
2025 qry.Request().SetContentParam("StartTime", buf.data);
2026 time_to_iso8601utc(record.endTime, &buf);
2027 qry.Request().SetContentParam("EndTime", buf.data);
2028 qry.Request().SetContentParam("SeriesId", record.seriesId);
2029 qry.Request().SetContentParam("ProgramId", record.programId);
2030 uint32_to_string(record.chanId, &buf);
2031 qry.Request().SetContentParam("ChanId", buf.data);
2032 uint32_to_string(record.parentId, &buf);
2033 qry.Request().SetContentParam("ParentId", buf.data);
2034 qry.Request().SetContentParam("Inactive", BOOLSTR(record.inactive));
2035 uint16_to_string(record.season, &buf);
2036 qry.Request().SetContentParam("Season", buf.data);
2037 uint16_to_string(record.episode, &buf);
2038 qry.Request().SetContentParam("Episode", buf.data);
2039 qry.Request().SetContentParam("Inetref", record.inetref);
2040 qry.Request().SetContentParam("Type", record.type);
2041 qry.Request().SetContentParam("SearchType", record.searchType);
2042 int8_to_string(record.recPriority, &buf);
2043 qry.Request().SetContentParam("RecPriority", buf.data);
2044 uint32_to_string(record.preferredInput, &buf);
2045 qry.Request().SetContentParam("PreferredInput", buf.data);
2046 uint8_to_string(record.startOffset, &buf);
2047 qry.Request().SetContentParam("StartOffset", buf.data);
2048 uint8_to_string(record.endOffset, &buf);
2049 qry.Request().SetContentParam("EndOffset", buf.data);
2050 qry.Request().SetContentParam("DupMethod", record.dupMethod);
2051 qry.Request().SetContentParam("DupIn", record.dupIn);
2052 uint32_to_string(record.filter, &buf);
2053 qry.Request().SetContentParam("Filter", buf.data);
2054 qry.Request().SetContentParam("RecProfile", record.recProfile);
2055 qry.Request().SetContentParam("RecGroup", record.recGroup);
2056 qry.Request().SetContentParam("StorageGroup", record.storageGroup);
2057 qry.Request().SetContentParam("PlayGroup", record.playGroup);
2058 qry.Request().SetContentParam("AutoExpire", BOOLSTR(record.autoExpire));
2059 uint32_to_string(record.maxEpisodes, &buf);
2060 qry.Request().SetContentParam("MaxEpisodes", buf.data);
2061 qry.Request().SetContentParam("MaxNewest", BOOLSTR(record.maxNewest));
2062 qry.Request().SetContentParam("AutoCommflag", BOOLSTR(record.autoCommflag));
2063 qry.Request().SetContentParam("AutoTranscode", BOOLSTR(record.autoTranscode));
2064 qry.Request().SetContentParam("AutoMetaLookup", BOOLSTR(record.autoMetaLookup));
2065 qry.Request().SetContentParam("AutoUserJob1", BOOLSTR(record.autoUserJob1));
2066 qry.Request().SetContentParam("AutoUserJob2", BOOLSTR(record.autoUserJob2));
2067 qry.Request().SetContentParam("AutoUserJob3", BOOLSTR(record.autoUserJob3));
2068 qry.Request().SetContentParam("AutoUserJob4", BOOLSTR(record.autoUserJob4));
2069 uint32_to_string(record.transcoder, &buf);
2070 qry.Request().SetContentParam("Transcoder", buf.data);
2071
2072 autoptr<WSResponse> resp(qry.Execute());
2073 if (!resp->IsSuccessful())
2074 {
2075 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2076 return false;
2077 }
2078 const JSON::Document json(*resp);
2079 const JSON::Node& root = json.GetRoot();
2080 if (!json.IsValid() || !root.IsObject())
2081 {
2082 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
2083 return false;
2084 }
2085 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
2086
2087 const JSON::Node& field = root.GetObjectValue("int");
2088 if (field.IsInt())
2089 recordid = (uint32_t) field.GetBigIntValue();
2090 else if (!field.IsString() || string_to_uint32(field.GetStringValue().c_str(), &recordid))
2091 return false;
2092 record.recordId = recordid;
2093 return true;
2094}
2095
2096bool WSAPI::AddRecordSchedule1_7(RecordSchedule& record)
2097{
2098 BUILTIN_BUFFER buf;
2099 uint32_t recordid;
2100 unsigned proto = (unsigned)m_version.protocol;
2101
2102 ProcessRecordOUT(proto, record);
2103
2104 // Initialize request header
2105 Query qry(*this);
2106 qry.Request().RequestAccept(WS_ACCEPT);
2107 qry.Request().RequestService("/Dvr/AddRecordSchedule", WS_METHOD_Post);
2108
2109 qry.Request().SetContentParam("Title", record.title);
2110 qry.Request().SetContentParam("Subtitle", record.subtitle);
2111 qry.Request().SetContentParam("Description", record.description);
2112 qry.Request().SetContentParam("Category", record.category);
2113 time_to_iso8601utc(record.startTime, &buf);
2114 qry.Request().SetContentParam("StartTime", buf.data);
2115 time_to_iso8601utc(record.endTime, &buf);
2116 qry.Request().SetContentParam("EndTime", buf.data);
2117 qry.Request().SetContentParam("SeriesId", record.seriesId);
2118 qry.Request().SetContentParam("ProgramId", record.programId);
2119 uint32_to_string(record.chanId, &buf);
2120 qry.Request().SetContentParam("ChanId", buf.data);
2121 qry.Request().SetContentParam("Station", record.callSign);
2122 int8_to_string(record.findDay, &buf);
2123 qry.Request().SetContentParam("FindDay", buf.data);
2124 qry.Request().SetContentParam("FindTime", record.findTime);
2125 uint32_to_string(record.parentId, &buf);
2126 qry.Request().SetContentParam("ParentId", buf.data);
2127 qry.Request().SetContentParam("Inactive", BOOLSTR(record.inactive));
2128 uint16_to_string(record.season, &buf);
2129 qry.Request().SetContentParam("Season", buf.data);
2130 uint16_to_string(record.episode, &buf);
2131 qry.Request().SetContentParam("Episode", buf.data);
2132 qry.Request().SetContentParam("Inetref", record.inetref);
2133 qry.Request().SetContentParam("Type", record.type);
2134 qry.Request().SetContentParam("SearchType", record.searchType);
2135 int8_to_string(record.recPriority, &buf);
2136 qry.Request().SetContentParam("RecPriority", buf.data);
2137 uint32_to_string(record.preferredInput, &buf);
2138 qry.Request().SetContentParam("PreferredInput", buf.data);
2139 uint8_to_string(record.startOffset, &buf);
2140 qry.Request().SetContentParam("StartOffset", buf.data);
2141 uint8_to_string(record.endOffset, &buf);
2142 qry.Request().SetContentParam("EndOffset", buf.data);
2143 qry.Request().SetContentParam("DupMethod", record.dupMethod);
2144 qry.Request().SetContentParam("DupIn", record.dupIn);
2145 uint32_to_string(record.filter, &buf);
2146 qry.Request().SetContentParam("Filter", buf.data);
2147 qry.Request().SetContentParam("RecProfile", record.recProfile);
2148 qry.Request().SetContentParam("RecGroup", record.recGroup);
2149 qry.Request().SetContentParam("StorageGroup", record.storageGroup);
2150 qry.Request().SetContentParam("PlayGroup", record.playGroup);
2151 qry.Request().SetContentParam("AutoExpire", BOOLSTR(record.autoExpire));
2152 uint32_to_string(record.maxEpisodes, &buf);
2153 qry.Request().SetContentParam("MaxEpisodes", buf.data);
2154 qry.Request().SetContentParam("MaxNewest", BOOLSTR(record.maxNewest));
2155 qry.Request().SetContentParam("AutoCommflag", BOOLSTR(record.autoCommflag));
2156 qry.Request().SetContentParam("AutoTranscode", BOOLSTR(record.autoTranscode));
2157 qry.Request().SetContentParam("AutoMetaLookup", BOOLSTR(record.autoMetaLookup));
2158 qry.Request().SetContentParam("AutoUserJob1", BOOLSTR(record.autoUserJob1));
2159 qry.Request().SetContentParam("AutoUserJob2", BOOLSTR(record.autoUserJob2));
2160 qry.Request().SetContentParam("AutoUserJob3", BOOLSTR(record.autoUserJob3));
2161 qry.Request().SetContentParam("AutoUserJob4", BOOLSTR(record.autoUserJob4));
2162 uint32_to_string(record.transcoder, &buf);
2163 qry.Request().SetContentParam("Transcoder", buf.data);
2164
2165 autoptr<WSResponse> resp(qry.Execute());
2166 if (!resp->IsSuccessful())
2167 {
2168 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2169 return false;
2170 }
2171 const JSON::Document json(*resp);
2172 const JSON::Node& root = json.GetRoot();
2173 if (!json.IsValid() || !root.IsObject())
2174 {
2175 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
2176 return false;
2177 }
2178 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
2179
2180 const JSON::Node& field = root.GetObjectValue("uint");
2181 if (field.IsInt())
2182 recordid = (uint32_t) field.GetBigIntValue();
2183 else if (!field.IsString() || string_to_uint32(field.GetStringValue().c_str(), &recordid))
2184 return false;
2185 record.recordId = recordid;
2186 return true;
2187}
2188
2189bool WSAPI::UpdateRecordSchedule1_7(RecordSchedule& record)
2190{
2191 BUILTIN_BUFFER buf;
2192 unsigned proto = (unsigned)m_version.protocol;
2193
2194 ProcessRecordOUT(proto, record);
2195
2196 // Initialize request header
2197 Query qry(*this);
2198 qry.Request().RequestAccept(WS_ACCEPT);
2199 qry.Request().RequestService("/Dvr/UpdateRecordSchedule", WS_METHOD_Post);
2200
2201 uint32_to_string(record.recordId, &buf);
2202 qry.Request().SetContentParam("RecordId", buf.data);
2203 qry.Request().SetContentParam("Title", record.title);
2204 qry.Request().SetContentParam("Subtitle", record.subtitle);
2205 qry.Request().SetContentParam("Description", record.description);
2206 qry.Request().SetContentParam("Category", record.category);
2207 time_to_iso8601utc(record.startTime, &buf);
2208 qry.Request().SetContentParam("StartTime", buf.data);
2209 time_to_iso8601utc(record.endTime, &buf);
2210 qry.Request().SetContentParam("EndTime", buf.data);
2211 qry.Request().SetContentParam("SeriesId", record.seriesId);
2212 qry.Request().SetContentParam("ProgramId", record.programId);
2213 uint32_to_string(record.chanId, &buf);
2214 qry.Request().SetContentParam("ChanId", buf.data);
2215 qry.Request().SetContentParam("Station", record.callSign);
2216 int8_to_string(record.findDay, &buf);
2217 qry.Request().SetContentParam("FindDay", buf.data);
2218 qry.Request().SetContentParam("FindTime", record.findTime);
2219 uint32_to_string(record.parentId, &buf);
2220 qry.Request().SetContentParam("ParentId", buf.data);
2221 qry.Request().SetContentParam("Inactive", BOOLSTR(record.inactive));
2222 uint16_to_string(record.season, &buf);
2223 qry.Request().SetContentParam("Season", buf.data);
2224 uint16_to_string(record.episode, &buf);
2225 qry.Request().SetContentParam("Episode", buf.data);
2226 qry.Request().SetContentParam("Inetref", record.inetref);
2227 qry.Request().SetContentParam("Type", record.type);
2228 qry.Request().SetContentParam("SearchType", record.searchType);
2229 int8_to_string(record.recPriority, &buf);
2230 qry.Request().SetContentParam("RecPriority", buf.data);
2231 uint32_to_string(record.preferredInput, &buf);
2232 qry.Request().SetContentParam("PreferredInput", buf.data);
2233 uint8_to_string(record.startOffset, &buf);
2234 qry.Request().SetContentParam("StartOffset", buf.data);
2235 uint8_to_string(record.endOffset, &buf);
2236 qry.Request().SetContentParam("EndOffset", buf.data);
2237 qry.Request().SetContentParam("DupMethod", record.dupMethod);
2238 qry.Request().SetContentParam("DupIn", record.dupIn);
2239 uint32_to_string(record.filter, &buf);
2240 qry.Request().SetContentParam("Filter", buf.data);
2241 qry.Request().SetContentParam("RecProfile", record.recProfile);
2242 qry.Request().SetContentParam("RecGroup", record.recGroup);
2243 qry.Request().SetContentParam("StorageGroup", record.storageGroup);
2244 qry.Request().SetContentParam("PlayGroup", record.playGroup);
2245 qry.Request().SetContentParam("AutoExpire", BOOLSTR(record.autoExpire));
2246 uint32_to_string(record.maxEpisodes, &buf);
2247 qry.Request().SetContentParam("MaxEpisodes", buf.data);
2248 qry.Request().SetContentParam("MaxNewest", BOOLSTR(record.maxNewest));
2249 qry.Request().SetContentParam("AutoCommflag", BOOLSTR(record.autoCommflag));
2250 qry.Request().SetContentParam("AutoTranscode", BOOLSTR(record.autoTranscode));
2251 qry.Request().SetContentParam("AutoMetaLookup", BOOLSTR(record.autoMetaLookup));
2252 qry.Request().SetContentParam("AutoUserJob1", BOOLSTR(record.autoUserJob1));
2253 qry.Request().SetContentParam("AutoUserJob2", BOOLSTR(record.autoUserJob2));
2254 qry.Request().SetContentParam("AutoUserJob3", BOOLSTR(record.autoUserJob3));
2255 qry.Request().SetContentParam("AutoUserJob4", BOOLSTR(record.autoUserJob4));
2256 uint32_to_string(record.transcoder, &buf);
2257 qry.Request().SetContentParam("Transcoder", buf.data);
2258
2259 autoptr<WSResponse> resp(qry.Execute());
2260 if (!resp->IsSuccessful())
2261 {
2262 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2263 return false;
2264 }
2265 const JSON::Document json(*resp);
2266 const JSON::Node& root = json.GetRoot();
2267 if (!json.IsValid() || !root.IsObject())
2268 {
2269 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
2270 return false;
2271 }
2272 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
2273
2274 const JSON::Node& field = root.GetObjectValue("bool");
2275 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
2276 return true;
2277 return false;
2278}
2279
2280bool WSAPI::DisableRecordSchedule1_5(uint32_t recordid)
2281{
2282 BUILTIN_BUFFER buf;
2283
2284 // Initialize request header
2285 Query qry(*this);
2286 qry.Request().RequestAccept(WS_ACCEPT);
2287 qry.Request().RequestService("/Dvr/DisableRecordSchedule", WS_METHOD_Post);
2288
2289 uint32_to_string(recordid, &buf);
2290 qry.Request().SetContentParam("RecordId", buf.data);
2291
2292 autoptr<WSResponse> resp(qry.Execute());
2293 if (!resp->IsSuccessful())
2294 {
2295 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2296 return false;
2297 }
2298 const JSON::Document json(*resp);
2299 const JSON::Node& root = json.GetRoot();
2300 if (!json.IsValid() || !root.IsObject())
2301 {
2302 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
2303 return false;
2304 }
2305 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
2306
2307 const JSON::Node& field = root.GetObjectValue("bool");
2308 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
2309 return true;
2310 return false;
2311}
2312
2313bool WSAPI::EnableRecordSchedule1_5(uint32_t recordid)
2314{
2315 BUILTIN_BUFFER buf;
2316
2317 // Initialize request header
2318 Query qry(*this);
2319 qry.Request().RequestAccept(WS_ACCEPT);
2320 qry.Request().RequestService("/Dvr/EnableRecordSchedule", WS_METHOD_Post);
2321
2322 uint32_to_string(recordid, &buf);
2323 qry.Request().SetContentParam("RecordId", buf.data);
2324
2325 autoptr<WSResponse> resp(qry.Execute());
2326 if (!resp->IsSuccessful())
2327 {
2328 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2329 return false;
2330 }
2331 const JSON::Document json(*resp);
2332 const JSON::Node& root = json.GetRoot();
2333 if (!json.IsValid() || !root.IsObject())
2334 {
2335 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
2336 return false;
2337 }
2338 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
2339
2340 const JSON::Node& field = root.GetObjectValue("bool");
2341 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
2342 return true;
2343 return false;
2344}
2345
2346bool WSAPI::RemoveRecordSchedule1_5(uint32_t recordid)
2347{
2348 BUILTIN_BUFFER buf;
2349
2350 // Initialize request header
2351 Query qry(*this);
2352 qry.Request().RequestAccept(WS_ACCEPT);
2353 qry.Request().RequestService("/Dvr/RemoveRecordSchedule", WS_METHOD_Post);
2354
2355 uint32_to_string(recordid, &buf);
2356 qry.Request().SetContentParam("RecordId", buf.data);
2357
2358 autoptr<WSResponse> resp(qry.Execute());
2359 if (!resp->IsSuccessful())
2360 {
2361 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2362 return false;
2363 }
2364 const JSON::Document json(*resp);
2365 const JSON::Node& root = json.GetRoot();
2366 if (!json.IsValid() || !root.IsObject())
2367 {
2368 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
2369 return false;
2370 }
2371 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
2372
2373 const JSON::Node& field = root.GetObjectValue("bool");
2374 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(), "true") == 0))
2375 return true;
2376 return false;
2377}
2378
2379ProgramListPtr WSAPI::GetUpcomingList1_5()
2380{
2381 // Only for backward compatibility (0.27)
2382 ProgramListPtr ret = GetUpcomingList2_2();
2383 // Add being recorded (https://code.mythtv.org/trac/changeset/3084ebc/mythtv)
2384 ProgramListPtr recordings = GetRecordedList(20, true);
2385 for (Myth::ProgramList::iterator it = recordings->begin(); it != recordings->end(); ++it)
2386 {
2387 if ((*it)->recording.status == RS_RECORDING)
2388 ret->push_back(*it);
2389 }
2390 return ret;
2391}
2392
2393ProgramListPtr WSAPI::GetUpcomingList2_2()
2394{
2395 ProgramListPtr ret(new ProgramList);
2396 BUILTIN_BUFFER buf;
2397 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
2398 unsigned proto = (unsigned)m_version.protocol;
2399
2400 // Get bindings for protocol version
2401 const bindings_t *bindlist = MythDTO::getListBindArray(proto);
2402 const bindings_t *bindprog = MythDTO::getProgramBindArray(proto);
2403 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
2404 const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto);
2405
2406 // Initialize request header
2407 Query qry(*this);
2408 qry.Request().RequestAccept(WS_ACCEPT);
2409 qry.Request().RequestService("/Dvr/GetUpcomingList", WS_METHOD_Get);
2410
2411 do
2412 {
2413 qry.Request().ClearContent();
2414 int32_to_string(req_index, &buf);
2415 qry.Request().SetContentParam("StartIndex", buf.data);
2416 int32_to_string(req_count, &buf);
2417 qry.Request().SetContentParam("Count", buf.data);
2418 qry.Request().SetContentParam("ShowAll", "true");
2419
2420 DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
2421 autoptr<WSResponse> resp(qry.Execute());
2422 if (!resp->IsSuccessful())
2423 {
2424 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2425 break;
2426 }
2427 const JSON::Document json(*resp);
2428 const JSON::Node& root = json.GetRoot();
2429 if (!json.IsValid() || !root.IsObject())
2430 {
2431 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
2432 break;
2433 }
2434 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
2435
2436 // Object: ProgramList
2437 const JSON::Node& plist = root.GetObjectValue("ProgramList");
2438 ItemList list = ItemList(); // Using default constructor
2439 JSON::BindObject(plist, &list, bindlist);
2440 // List has ProtoVer. Check it or sound alarm
2441 if (list.protoVer != proto)
2442 {
2443 InvalidateService();
2444 break;
2445 }
2446 count = 0;
2447 // Object: Programs[]
2448 const JSON::Node& progs = plist.GetObjectValue("Programs");
2449 // Iterates over the sequence elements.
2450 size_t ps = progs.Size();
2451 for (size_t pi = 0; pi < ps; ++pi)
2452 {
2453 ++count;
2454 const JSON::Node& prog = progs.GetArrayElement(pi);
2455 ProgramPtr program(new Program()); // Using default constructor
2456 // Bind the new program
2457 JSON::BindObject(prog, program.get(), bindprog);
2458 // Bind channel of program
2459 const JSON::Node& chan = prog.GetObjectValue("Channel");
2460 JSON::BindObject(chan, &(program->channel), bindchan);
2461 // Bind recording of program
2462 const JSON::Node& reco = prog.GetObjectValue("Recording");
2463 JSON::BindObject(reco, &(program->recording), bindreco);
2464 ret->push_back(program);
2465 }
2466 DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count);
2467 req_index += count; // Set next requested index
2468 }
2469 while (count == req_count);
2470
2471 return ret;
2472}
2473
2474ProgramListPtr WSAPI::GetConflictList1_5()
2475{
2476 ProgramListPtr ret(new ProgramList);
2477 BUILTIN_BUFFER buf;
2478 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
2479 unsigned proto = (unsigned)m_version.protocol;
2480
2481 // Get bindings for protocol version
2482 const bindings_t *bindlist = MythDTO::getListBindArray(proto);
2483 const bindings_t *bindprog = MythDTO::getProgramBindArray(proto);
2484 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
2485 const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto);
2486
2487 // Initialize request header
2488 Query qry(*this);
2489 qry.Request().RequestAccept(WS_ACCEPT);
2490 qry.Request().RequestService("/Dvr/GetConflictList", WS_METHOD_Get);
2491
2492 do
2493 {
2494 qry.Request().ClearContent();
2495 int32_to_string(req_index, &buf);
2496 qry.Request().SetContentParam("StartIndex", buf.data);
2497 int32_to_string(req_count, &buf);
2498 qry.Request().SetContentParam("Count", buf.data);
2499
2500 DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
2501 autoptr<WSResponse> resp(qry.Execute());
2502 if (!resp->IsSuccessful())
2503 {
2504 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2505 break;
2506 }
2507 const JSON::Document json(*resp);
2508 const JSON::Node& root = json.GetRoot();
2509 if (!json.IsValid() || !root.IsObject())
2510 {
2511 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
2512 break;
2513 }
2514 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
2515
2516 // Object: ProgramList
2517 const JSON::Node& plist = root.GetObjectValue("ProgramList");
2518 ItemList list = ItemList(); // Using default constructor
2519 JSON::BindObject(plist, &list, bindlist);
2520 // List has ProtoVer. Check it or sound alarm
2521 if (list.protoVer != proto)
2522 {
2523 InvalidateService();
2524 break;
2525 }
2526 count = 0;
2527 // Object: Programs[]
2528 const JSON::Node& progs = plist.GetObjectValue("Programs");
2529 // Iterates over the sequence elements.
2530 size_t ps = progs.Size();
2531 for (size_t pi = 0; pi < ps; ++pi)
2532 {
2533 ++count;
2534 const JSON::Node& prog = progs.GetArrayElement(pi);
2535 ProgramPtr program(new Program()); // Using default constructor
2536 // Bind the new program
2537 JSON::BindObject(prog, program.get(), bindprog);
2538 // Bind channel of program
2539 const JSON::Node& chan = prog.GetObjectValue("Channel");
2540 JSON::BindObject(chan, &(program->channel), bindchan);
2541 // Bind recording of program
2542 const JSON::Node& reco = prog.GetObjectValue("Recording");
2543 JSON::BindObject(reco, &(program->recording), bindreco);
2544 ret->push_back(program);
2545 }
2546 DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count);
2547 req_index += count; // Set next requested index
2548 }
2549 while (count == req_count);
2550
2551 return ret;
2552}
2553
2554ProgramListPtr WSAPI::GetExpiringList1_5()
2555{
2556 ProgramListPtr ret(new ProgramList);
2557 BUILTIN_BUFFER buf;
2558 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
2559 unsigned proto = (unsigned)m_version.protocol;
2560
2561 // Get bindings for protocol version
2562 const bindings_t *bindlist = MythDTO::getListBindArray(proto);
2563 const bindings_t *bindprog = MythDTO::getProgramBindArray(proto);
2564 const bindings_t *bindchan = MythDTO::getChannelBindArray(proto);
2565 const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto);
2566
2567 // Initialize request header
2568 Query qry(*this);
2569 qry.Request().RequestAccept(WS_ACCEPT);
2570 qry.Request().RequestService("/Dvr/GetExpiringList", WS_METHOD_Get);
2571
2572 do
2573 {
2574 qry.Request().ClearContent();
2575 int32_to_string(req_index, &buf);
2576 qry.Request().SetContentParam("StartIndex", buf.data);
2577 int32_to_string(req_count, &buf);
2578 qry.Request().SetContentParam("Count", buf.data);
2579
2580 DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
2581 autoptr<WSResponse> resp(qry.Execute());
2582 if (!resp->IsSuccessful())
2583 {
2584 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2585 break;
2586 }
2587 const JSON::Document json(*resp);
2588 const JSON::Node& root = json.GetRoot();
2589 if (!json.IsValid() || !root.IsObject())
2590 {
2591 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
2592 break;
2593 }
2594 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
2595
2596 // Object: ProgramList
2597 const JSON::Node& plist = root.GetObjectValue("ProgramList");
2598 ItemList list = ItemList(); // Using default constructor
2599 JSON::BindObject(plist, &list, bindlist);
2600 // List has ProtoVer. Check it or sound alarm
2601 if (list.protoVer != proto)
2602 {
2603 InvalidateService();
2604 break;
2605 }
2606 count = 0;
2607 // Object: Programs[]
2608 const JSON::Node& progs = plist.GetObjectValue("Programs");
2609 // Iterates over the sequence elements.
2610 size_t ps = progs.Size();
2611 for (size_t pi = 0; pi < ps; ++pi)
2612 {
2613 ++count;
2614 const JSON::Node& prog = progs.GetArrayElement(pi);
2615 ProgramPtr program(new Program()); // Using default constructor
2616 // Bind the new program
2617 JSON::BindObject(prog, program.get(), bindprog);
2618 // Bind channel of program
2619 const JSON::Node& chan = prog.GetObjectValue("Channel");
2620 JSON::BindObject(chan, &(program->channel), bindchan);
2621 // Bind recording of program
2622 const JSON::Node& reco = prog.GetObjectValue("Recording");
2623 JSON::BindObject(reco, &(program->recording), bindreco);
2624 ret->push_back(program);
2625 }
2626 DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count);
2627 req_index += count; // Set next requested index
2628 }
2629 while (count == req_count);
2630
2631 return ret;
2632}
2633
2634StringListPtr WSAPI::GetRecGroupList1_5()
2635{
2636 StringListPtr ret(new StringList);
2637
2638 // Initialize request header
2639 Query qry(*this);
2640 qry.Request().RequestAccept(WS_ACCEPT);
2641 qry.Request().RequestService("/Dvr/GetRecGroupList", WS_METHOD_Get);
2642 autoptr<WSResponse> resp(qry.Execute());
2643 if (!resp->IsSuccessful())
2644 {
2645 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2646 return ret;
2647 }
2648 const JSON::Document json(*resp);
2649 const JSON::Node& root = json.GetRoot();
2650 if (!json.IsValid() || !root.IsObject())
2651 {
2652 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
2653 return ret;
2654 }
2655 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
2656
2657 // Object: Strings
2658 const JSON::Node& list = root.GetObjectValue("StringList");
2659 if (list.IsArray())
2660 {
2661 size_t s = list.Size();
2662 for (size_t i = 0; i < s; ++i)
2663 {
2664 const JSON::Node& val = list.GetArrayElement(i);
2665 if (val.IsString())
2666 {
2667 ret->push_back(val.GetStringValue());
2668 }
2669 }
2670 }
2671 return ret;
2672}
2673
2678WSStreamPtr WSAPI::GetFile1_32(const std::string& filename, const std::string& sgname)
2679{
2680 WSStreamPtr ret;
2681
2682 // Initialize request header
2683 Query qry(*this);
2684 qry.Request().RequestAccept(WS_ACCEPT);
2685 qry.Request().RequestService("/Content/GetFile", WS_METHOD_Get);
2686 qry.Request().SetContentParam("StorageGroup", sgname);
2687 qry.Request().SetContentParam("FileName", filename);
2688 autoptr<WSResponse> resp(qry.Execute(1, false, true));
2689 if (!resp->IsSuccessful())
2690 {
2691 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2692 return ret;
2693 }
2694 ret.reset(new WSStream(resp.release()));
2695 return ret;
2696}
2697
2698WSStreamPtr WSAPI::GetChannelIcon1_32(uint32_t chanid, unsigned width, unsigned height)
2699{
2700 WSStreamPtr ret;
2701 BUILTIN_BUFFER buf;
2702
2703 // Initialize request header
2704 Query qry(*this);
2705 qry.Request().RequestAccept(WS_ACCEPT);
2706 qry.Request().RequestService("/Guide/GetChannelIcon", WS_METHOD_Get);
2707 uint32_to_string(chanid, &buf);
2708 qry.Request().SetContentParam("ChanId", buf.data);
2709 if (width)
2710 {
2711 uint32_to_string(width, &buf);
2712 qry.Request().SetContentParam("Width", buf.data);
2713 }
2714 if (height)
2715 {
2716 uint32_to_string(height, &buf);
2717 qry.Request().SetContentParam("Height", buf.data);
2718 }
2719 autoptr<WSResponse> resp(qry.Execute(1, false, true));
2720 if (!resp->IsSuccessful())
2721 {
2722 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2723 return ret;
2724 }
2725 ret.reset(new WSStream(resp.release()));
2726 return ret;
2727}
2728
2729std::string WSAPI::GetChannelIconUrl1_32(uint32_t chanid, unsigned width, unsigned height)
2730{
2731 BUILTIN_BUFFER buf;
2732 std::string uri;
2733 uri.reserve(127);
2734 uri.append(GetBaseURL());
2735 uri.append("/Guide/GetChannelIcon");
2736 uint32_to_string(chanid, &buf);
2737 uri.append("?ChanId=").append(buf.data);
2738 if (width)
2739 {
2740 uint32_to_string(width, &buf);
2741 uri.append("&Width=").append(buf.data);
2742 }
2743 if (height)
2744 {
2745 uint32_to_string(height, &buf);
2746 uri.append("&Height=").append(buf.data);
2747 }
2748 return uri;
2749}
2750
2751WSStreamPtr WSAPI::GetPreviewImage1_32(uint32_t chanid, time_t recstartts, unsigned width, unsigned height)
2752{
2753 WSStreamPtr ret;
2754 BUILTIN_BUFFER buf;
2755
2756 // Initialize request header
2757 Query qry(*this);
2758 qry.Request().RequestAccept(WS_ACCEPT);
2759 qry.Request().RequestService("/Content/GetPreviewImage", WS_METHOD_Get);
2760 uint32_to_string(chanid, &buf);
2761 qry.Request().SetContentParam("ChanId", buf.data);
2762 time_to_iso8601utc(recstartts, &buf);
2763 qry.Request().SetContentParam("StartTime", buf.data);
2764 if (width)
2765 {
2766 uint32_to_string(width, &buf);
2767 qry.Request().SetContentParam("Width", buf.data);
2768 }
2769 if (height)
2770 {
2771 uint32_to_string(height, &buf);
2772 qry.Request().SetContentParam("Height", buf.data);
2773 }
2774 autoptr<WSResponse> resp(qry.Execute(1, false, true));
2775 if (!resp->IsSuccessful())
2776 {
2777 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2778 return ret;
2779 }
2780 ret.reset(new WSStream(resp.release()));
2781 return ret;
2782}
2783
2784std::string WSAPI::GetPreviewImageUrl1_32(uint32_t chanid, time_t recstartts, unsigned width, unsigned height)
2785{
2786 BUILTIN_BUFFER buf;
2787 std::string uri;
2788 uri.reserve(127);
2789 uri.append(GetBaseURL());
2790 uri.append("/Content/GetPreviewImage");
2791 uint32_to_string(chanid, &buf);
2792 uri.append("?ChanId=").append(buf.data);
2793 time_to_iso8601utc(recstartts, &buf);
2794 uri.append("&StartTime=").append(urlencode(buf.data));
2795 if (width)
2796 {
2797 uint32_to_string(width, &buf);
2798 uri.append("&Width=").append(buf.data);
2799 }
2800 if (height)
2801 {
2802 uint32_to_string(height, &buf);
2803 uri.append("&Height=").append(buf.data);
2804 }
2805 return uri;
2806}
2807
2808WSStreamPtr WSAPI::GetRecordingArtwork1_32(const std::string& type, const std::string& inetref, uint16_t season, unsigned width, unsigned height)
2809{
2810 WSStreamPtr ret;
2811 BUILTIN_BUFFER buf;
2812
2813 // Initialize request header
2814 Query qry(*this);
2815 qry.Request().RequestAccept(WS_ACCEPT);
2816 qry.Request().RequestService("/Content/GetRecordingArtwork", WS_METHOD_Get);
2817 qry.Request().SetContentParam("Type", type.c_str());
2818 qry.Request().SetContentParam("Inetref", inetref.c_str());
2819 uint16_to_string(season, &buf);
2820 qry.Request().SetContentParam("Season", buf.data);
2821 if (width)
2822 {
2823 uint32_to_string(width, &buf);
2824 qry.Request().SetContentParam("Width", buf.data);
2825 }
2826 if (height)
2827 {
2828 uint32_to_string(height, &buf);
2829 qry.Request().SetContentParam("Height", buf.data);
2830 }
2831 autoptr<WSResponse> resp(qry.Execute(1, false, true));
2832 if (!resp->IsSuccessful())
2833 {
2834 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2835 return ret;
2836 }
2837 ret.reset(new WSStream(resp.release()));
2838 return ret;
2839}
2840
2841std::string WSAPI::GetRecordingArtworkUrl1_32(const std::string& type, const std::string& inetref, uint16_t season, unsigned width, unsigned height)
2842{
2843 BUILTIN_BUFFER buf;
2844 std::string uri;
2845 uri.reserve(127);
2846 uri.append(GetBaseURL());
2847 uri.append("/Content/GetRecordingArtwork");
2848 uri.append("?Type=").append(urlencode(type));
2849 uri.append("&Inetref=").append(urlencode(inetref));
2850 uint16_to_string(season, &buf);
2851 uri.append("&Season=").append(buf.data);
2852 if (width)
2853 {
2854 uint32_to_string(width, &buf);
2855 uri.append("&Width=").append(buf.data);
2856 }
2857 if (height)
2858 {
2859 uint32_to_string(height, &buf);
2860 uri.append("&Height=").append(buf.data);
2861 }
2862 return uri;
2863}
2864
2865ArtworkListPtr WSAPI::GetRecordingArtworkList1_32(uint32_t chanid, time_t recstartts)
2866{
2867 ArtworkListPtr ret(new ArtworkList);
2868 BUILTIN_BUFFER buf;
2869 unsigned proto = (unsigned)m_version.protocol;
2870
2871 // Get bindings for protocol version
2872 const bindings_t *bindartw = MythDTO::getArtworkBindArray(proto);
2873
2874 Query qry(*this);
2875 qry.Request().RequestAccept(WS_ACCEPT);
2876 qry.Request().RequestService("/Content/GetRecordingArtworkList", WS_METHOD_Get);
2877 uint32_to_string(chanid, &buf);
2878 qry.Request().SetContentParam("ChanId", buf.data);
2879 time_to_iso8601utc(recstartts, &buf);
2880 qry.Request().SetContentParam("StartTime", buf.data);
2881 autoptr<WSResponse> resp(qry.Execute());
2882 if (!resp->IsSuccessful())
2883 {
2884 DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__);
2885 return ret;
2886 }
2887 const JSON::Document json(*resp);
2888 const JSON::Node& root = json.GetRoot();
2889 if (!json.IsValid() || !root.IsObject())
2890 {
2891 DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__);
2892 return ret;
2893 }
2894 DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__);
2895
2896 const JSON::Node& list = root.GetObjectValue("ArtworkInfoList");
2897 // Bind artwork list
2898 const JSON::Node& arts = list.GetObjectValue("ArtworkInfos");
2899 size_t as = arts.Size();
2900 for (size_t pa = 0; pa < as; ++pa)
2901 {
2902 const JSON::Node& artw = arts.GetArrayElement(pa);
2903 ArtworkPtr artwork(new Artwork()); // Using default constructor
2904 JSON::BindObject(artw, artwork.get(), bindartw);
2905 ret->push_back(artwork);
2906 }
2907 return ret;
2908}
bool LoginUser()
GET Myth/LoginUser From v36.
SettingPtr GetSetting(const std::string &key, bool myhost)
GET Myth/GetSetting.
SettingPtr GetHostSetting(const std::string &key, const std::string &hostname)
GET Myth/GetSetting.
Definition mythwsapi.h:86
ProgramListPtr GetRecordedList(unsigned n=0, bool descending=false)
GET Dvr/GetRecordedList.
Definition mythwsapi.h:191
SettingMapPtr GetSettings(bool myhost)
GET Myth/GetSetting.
bool GetServiceVersion(WSServiceId_t id, WSServiceVersion_t &version)
SettingMapPtr GetHostSettings(const std::string &hostname)
GET Myth/GetSetting.
Definition mythwsapi.h:102
const bindings_t * getChannelBindArray(unsigned proto)
Returns bindings for Myth::Channel.
Definition mythdto.cpp:40
const bindings_t * getVideoSourceBindArray(unsigned proto)
Returns bindings for Myth::VideoSource.
Definition mythdto.cpp:77
const bindings_t * getRecordScheduleBindArray(unsigned proto)
Returns bindings for Myth::RecordSchedule.
Definition mythdto.cpp:84
const bindings_t * getCaptureCardBindArray(unsigned proto)
Returns bindings for Myth::CaptureCard.
Definition mythdto.cpp:70
const bindings_t * getRecordingBindArray(unsigned proto)
Returns bindings for Myth::Recording.
Definition mythdto.cpp:47
const bindings_t * getCuttingBindArray(unsigned proto)
Returns bindings for Myth::Mark.
Definition mythdto.cpp:93
const bindings_t * getListBindArray(unsigned proto)
Returns bindings for Myth::List.
Definition mythdto.cpp:34
const bindings_t * getVersionBindArray(unsigned ranking)
Returns bindings for Myth::Version.
Definition mythdto.cpp:28
const bindings_t * getArtworkBindArray(unsigned proto)
Returns bindings for Myth::Artwork.
Definition mythdto.cpp:56
const bindings_t * getProgramBindArray(unsigned proto)
Returns bindings for Myth::Program.
Definition mythdto.cpp:63
This is the main namespace that encloses all public classes.
Definition mythcontrol.h:30