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"
35#define BOOLSTR(a) ((a) ? "true" : "false")
37#define FETCHSIZE_L 1000
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"
49template<
class T>
class autoptr
52 explicit autoptr(
const autoptr&);
53 autoptr& operator=(
const autoptr&);
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; }
63WSAPI::WSAPI(
const std::string& server,
unsigned port,
const std::string& securityPin)
64: m_mutex(new OS::Mutex)
68, m_securityPin(securityPin)
73 m_checked = InitWSAPI();
81WSAPI& WSAPI::WithAuthorization(
const std::string& user,
const std::string& password)
84 m_authPassword = password;
88WSAPI& WSAPI::WithSSL(
bool yesno)
93 DBG(DBG_ERROR,
"%s: SSL support is not available\n", __FUNCTION__);
103WSAPI::Query::Query(
WSAPI& api)
107 m_request =
new WSRequest(m_api.m_server, m_api.m_port, m_api.m_ssl);
110WSAPI::Query::~Query()
116WSRequest& WSAPI::Query::Request()
121WSResponse * WSAPI::Query::Execute(
int maxRedirs,
bool trustedLocation,
bool followAny)
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)
129 if (m_api.LoginUser())
132 m_request->SetHeader(ws_header_to_str(WS_HEADER_Authorization), m_api.m_authToken);
133 response =
new WSResponse(*m_request, maxRedirs, trustedLocation, followAny);
144bool WSAPI::InitWSAPI()
148 memset(m_serviceVersion, 0,
sizeof(m_serviceVersion));
150 WSServiceVersion_t& mythwsv = m_serviceVersion[WS_Myth];
153 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
156 if (mythwsv.ranking > MYTH_API_VERSION_MAX_RANKING) {}
157 else if (mythwsv.ranking >= 0x00020000)
158 status = CheckServerHostName2_0() && CheckVersion2_0();
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);
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);
182 static const char * WSServiceRoot[WS_INVALID + 1] =
192 std::string url(WSServiceRoot[
id]);
193 url.append(
"/version");
195 qry.Request().RequestAccept(WS_ACCEPT);
196 qry.Request().RequestService(url, WS_METHOD_Get);
198 if (resp->IsSuccessful())
201 const JSON::Document json(*resp);
202 const JSON::Node& root = json.GetRoot();
203 if (json.IsValid() && root.IsObject())
205 const JSON::Node& field = root.GetObjectValue(
"String");
206 if (field.IsString())
208 const std::string& val = field.GetStringValue();
209 if (sscanf(val.c_str(),
"%u.%u", &(wsv.major), &(wsv.minor)) == 2)
211 wsv.ranking = ((wsv.major & 0xFFFF) << 16) | (wsv.minor & 0xFFFF);
223bool WSAPI::CheckServerHostName2_0()
225 m_serverHostName.clear();
228 qry.Request().RequestAccept(WS_ACCEPT);
229 qry.Request().RequestService(
"/Myth/GetHostName", WS_METHOD_Get);
231 if (!resp->IsSuccessful())
233 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
237 const JSON::Document json(*resp);
238 const JSON::Node& root = json.GetRoot();
239 if (json.IsValid() && root.IsObject())
241 const JSON::Node& field = root.GetObjectValue(
"String");
242 if (field.IsString())
244 const std::string& val = field.GetStringValue();
245 m_serverHostName = val;
246 m_namedCache[val] = m_server;
253bool WSAPI::CheckVersion2_0()
255 m_version.protocol = 0;
256 m_version.schema = 0;
257 m_version.version.clear();
258 WSServiceVersion_t& wsv = m_serviceVersion[WS_Myth];
261 qry.Request().RequestAccept(WS_ACCEPT);
262 qry.Request().RequestService(
"/Myth/GetConnectionInfo", WS_METHOD_Get);
263 if (!m_securityPin.empty())
266 qry.Request().SetContentParam(
"Pin", m_securityPin);
268 autoptr<WSResponse> resp(qry.Execute());
269 if (!resp->IsSuccessful())
271 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
275 const JSON::Document json(*resp);
276 const JSON::Node& root = json.GetRoot();
277 if (json.IsValid() && root.IsObject())
279 const JSON::Node& con = root.GetObjectValue(
"ConnectionInfo");
282 const JSON::Node& ver = con.GetObjectValue(
"Version");
284 if (m_version.protocol)
291unsigned WSAPI::CheckService()
293 OS::LockGuard lock(*m_mutex);
294 if (m_checked || (m_checked = InitWSAPI()))
295 return (
unsigned)m_version.protocol;
299WSServiceVersion_t WSAPI::CheckService(WSServiceId_t
id)
301 OS::LockGuard lock(*m_mutex);
302 if (m_checked || (m_checked = InitWSAPI()))
303 return m_serviceVersion[id];
304 return m_serviceVersion[WS_INVALID];
307void WSAPI::InvalidateService()
313std::string WSAPI::GetServerHostName()
315 return m_serverHostName;
318std::string WSAPI::GetBaseURL()
324 url.append(
"https://");
326 url.append(
"http://");
327 url.append(m_server);
328 uint32_to_string(m_port, &buf);
329 url.append(
":").append(buf.data);
333VersionPtr WSAPI::GetVersion()
335 return VersionPtr(
new Version(m_version));
338std::string WSAPI::ResolveHostName(
const std::string& hostname)
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())
344 Myth::SettingPtr addr = this->
GetHostSetting(
"BackendServerIP6", hostname);
345 if (addr && !addr->value.empty() && addr->value !=
"::1")
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());
353 if (addr && !addr->value.empty())
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());
360 DBG(DBG_ERROR,
"%s: unknown host (%s)\n", __FUNCTION__, hostname.c_str());
361 return std::string();
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())
380 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
383 const JSON::Document json(resp);
384 const JSON::Node& root = json.GetRoot();
385 if (!json.IsValid() || !root.IsObject())
387 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
390 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
393 const JSON::Node& val = root.GetObjectValue(
"String");
396 m_authToken = val.GetStringValue();
397 if (!m_authToken.empty())
399 DBG(DBG_ERROR,
"%s: invalid user or password\n", __FUNCTION__);
404SettingPtr WSAPI::GetSetting2_0(
const std::string& key,
const std::string& hostname)
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);
415 if (!resp->IsSuccessful())
417 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
420 const JSON::Document json(*resp);
421 const JSON::Node& root = json.GetRoot();
422 if (!json.IsValid() || !root.IsObject())
424 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
427 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
430 const JSON::Node& slist = root.GetObjectValue(
"SettingList");
432 const JSON::Node& sts = slist.GetObjectValue(
"Settings");
437 const JSON::Node& val = sts.GetObjectValue(
static_cast<size_t>(0));
440 ret.reset(
new Setting());
441 ret->key = sts.GetObjectKey(0);
442 ret->value = val.GetStringValue();
449SettingPtr WSAPI::GetSetting5_0(
const std::string& key,
const std::string& hostname)
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())
462 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
465 const JSON::Document json(*resp);
466 const JSON::Node& root = json.GetRoot();
467 if (!json.IsValid() || !root.IsObject())
469 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
472 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
475 const JSON::Node& val = root.GetObjectValue(
"String");
478 ret.reset(
new Setting());
480 ret->value = val.GetStringValue();
487 std::string hostname;
489 hostname = TcpSocket::GetMyHostName();
493SettingMapPtr WSAPI::GetSettings2_0(
const std::string& hostname)
495 SettingMapPtr ret(
new SettingMap);
499 qry.Request().RequestAccept(WS_ACCEPT);
500 qry.Request().RequestService(
"/Myth/GetSetting", WS_METHOD_Get);
501 qry.Request().SetContentParam(
"HostName", hostname);
503 if (!resp->IsSuccessful())
505 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
508 const JSON::Document json(*resp);
509 const JSON::Node& root = json.GetRoot();
510 if (!json.IsValid() || !root.IsObject())
512 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
515 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
518 const JSON::Node& slist = root.GetObjectValue(
"SettingList");
520 const JSON::Node& sts = slist.GetObjectValue(
"Settings");
523 size_t s = sts.Size();
524 for (
size_t i = 0; i < s; ++i)
526 const JSON::Node& val = sts.GetObjectValue(i);
529 SettingPtr setting(
new Setting());
530 setting->key = sts.GetObjectKey(i);
531 setting->value = val.GetStringValue();
532 ret->insert(SettingMap::value_type(setting->key, setting));
539SettingMapPtr WSAPI::GetSettings5_0(
const std::string& hostname)
541 SettingMapPtr ret(
new SettingMap);
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())
551 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
554 const JSON::Document json(*resp);
555 const JSON::Node& root = json.GetRoot();
556 if (!json.IsValid() || !root.IsObject())
558 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
561 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
564 const JSON::Node& slist = root.GetObjectValue(
"SettingList");
566 const JSON::Node& sts = slist.GetObjectValue(
"Settings");
569 size_t s = sts.Size();
570 for (
size_t i = 0; i < s; ++i)
572 const JSON::Node& val = sts.GetObjectValue(i);
575 SettingPtr setting(
new Setting());
576 setting->key = sts.GetObjectKey(i);
577 setting->value = val.GetStringValue();
578 ret->insert(SettingMap::value_type(setting->key, setting));
587 std::string hostname;
589 hostname = TcpSocket::GetMyHostName();
593bool WSAPI::PutSetting2_0(
const std::string& key,
const std::string& value,
bool myhost)
597 qry.Request().RequestAccept(WS_ACCEPT);
598 qry.Request().RequestService(
"/Myth/PutSetting", WS_METHOD_Post);
599 std::string hostname;
601 hostname = TcpSocket::GetMyHostName();
602 qry.Request().SetContentParam(
"HostName", hostname);
603 qry.Request().SetContentParam(
"Key", key);
604 qry.Request().SetContentParam(
"Value", value);
606 if (!resp->IsSuccessful())
608 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
611 const JSON::Document json(*resp);
612 const JSON::Node& root = json.GetRoot();
613 if (!json.IsValid() || !root.IsObject())
615 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
618 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
620 const JSON::Node& field = root.GetObjectValue(
"bool");
621 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
630CaptureCardListPtr WSAPI::GetCaptureCardList1_4()
632 CaptureCardListPtr ret(
new CaptureCardList);
633 unsigned proto = (unsigned)m_version.protocol;
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())
646 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
649 const JSON::Document json(*resp);
650 const JSON::Node& root = json.GetRoot();
651 if (!json.IsValid() || !root.IsObject())
653 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
656 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
659 const JSON::Node& clist = root.GetObjectValue(
"CaptureCardList");
661 const JSON::Node& cards = clist.GetObjectValue(
"CaptureCards");
663 size_t cs = cards.Size();
664 for (
size_t ci = 0; ci < cs; ++ci)
666 const JSON::Node& card = cards.GetArrayElement(ci);
667 CaptureCardPtr captureCard(
new CaptureCard());
669 JSON::BindObject(card, captureCard.get(), bindcard);
670 ret->push_back(captureCard);
679VideoSourceListPtr WSAPI::GetVideoSourceList1_2()
681 VideoSourceListPtr ret(
new VideoSourceList);
682 unsigned proto = (unsigned)m_version.protocol;
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())
694 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
697 const JSON::Document json(*resp);
698 const JSON::Node& root = json.GetRoot();
699 if (!json.IsValid() || !root.IsObject())
701 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
704 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
707 const JSON::Node& slist = root.GetObjectValue(
"VideoSourceList");
709 const JSON::Node& vsrcs = slist.GetObjectValue(
"VideoSources");
711 size_t vs = vsrcs.Size();
712 for (
size_t vi = 0; vi < vs; ++vi)
714 const JSON::Node& vsrc = vsrcs.GetArrayElement(vi);
715 VideoSourcePtr videoSource(
new VideoSource());
717 JSON::BindObject(vsrc, videoSource.get(), bindvsrc);
718 ret->push_back(videoSource);
723ChannelListPtr WSAPI::GetChannelList1_2(uint32_t sourceid,
bool onlyVisible)
725 ChannelListPtr ret(
new ChannelList);
727 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
728 unsigned proto = (unsigned)m_version.protocol;
736 qry.Request().RequestAccept(WS_ACCEPT);
737 qry.Request().RequestService(
"/Channel/GetChannelInfoList", WS_METHOD_Get);
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);
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())
753 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
756 const JSON::Document json(*resp);
757 const JSON::Node& root = json.GetRoot();
758 if (!json.IsValid() || !root.IsObject())
760 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
763 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
766 const JSON::Node& clist = root.GetObjectValue(
"ChannelInfoList");
767 ItemList list = ItemList();
768 JSON::BindObject(clist, &list, bindlist);
770 if (list.protoVer != proto)
777 const JSON::Node& chans = clist.GetObjectValue(
"ChannelInfos");
779 size_t cs = chans.Size();
780 for (
size_t ci = 0; ci < cs; ++ci)
783 const JSON::Node& chan = chans.GetArrayElement(ci);
784 ChannelPtr channel(
new Channel());
786 JSON::BindObject(chan, channel.get(), bindchan);
787 if (channel->chanId && !channel->chanNum.empty() && (!onlyVisible || channel->visible))
788 ret->push_back(channel);
790 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
793 while (count == req_count);
798ChannelListPtr WSAPI::GetChannelList1_5(uint32_t sourceid,
bool onlyVisible)
800 ChannelListPtr ret(
new ChannelList);
803 unsigned proto = (unsigned)m_version.protocol;
811 qry.Request().RequestAccept(WS_ACCEPT);
812 qry.Request().RequestService(
"/Channel/GetChannelInfoList", WS_METHOD_Get);
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);
828 autoptr<WSResponse> resp(qry.Execute());
829 if (!resp->IsSuccessful())
831 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
834 const JSON::Document json(*resp);
835 const JSON::Node& root = json.GetRoot();
836 if (!json.IsValid() || !root.IsObject())
838 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
841 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
844 const JSON::Node& clist = root.GetObjectValue(
"ChannelInfoList");
845 ItemList list = ItemList();
846 JSON::BindObject(clist, &list, bindlist);
848 if (list.protoVer != proto)
855 const JSON::Node& chans = clist.GetObjectValue(
"ChannelInfos");
857 size_t cs = chans.Size();
858 for (
size_t ci = 0; ci < cs; ++ci)
861 const JSON::Node& chan = chans.GetArrayElement(ci);
862 ChannelPtr channel(
new Channel());
864 JSON::BindObject(chan, channel.get(), bindchan);
865 if (channel->chanId && !channel->chanNum.empty())
866 ret->push_back(channel);
868 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
877ChannelPtr WSAPI::GetChannel1_2(uint32_t chanid)
881 unsigned proto = (unsigned)m_version.protocol;
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);
893 autoptr<WSResponse> resp(qry.Execute());
894 if (!resp->IsSuccessful())
896 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
899 const JSON::Document json(*resp);
900 const JSON::Node& root = json.GetRoot();
901 if (!json.IsValid() || !root.IsObject())
903 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
906 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
909 const JSON::Node& chan = root.GetObjectValue(
"ChannelInfo");
910 ChannelPtr channel(
new Channel());
912 JSON::BindObject(chan, channel.get(), bindchan);
913 if (channel->chanId == chanid)
922std::map<uint32_t, ProgramMapPtr> WSAPI::GetProgramGuide1_0(time_t starttime, time_t endtime)
924 std::map<uint32_t, ProgramMapPtr> ret;
927 unsigned proto = (unsigned)m_version.protocol;
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");
946 autoptr<WSResponse> resp(qry.Execute());
947 if (!resp->IsSuccessful())
949 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
952 const JSON::Document json(*resp);
953 const JSON::Node& root = json.GetRoot();
954 if (!json.IsValid() || !root.IsObject())
956 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
959 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
962 const JSON::Node& glist = root.GetObjectValue(
"ProgramGuide");
963 ItemList list = ItemList();
964 JSON::BindObject(glist, &list, bindlist);
966 if (list.protoVer != proto)
972 const JSON::Node& chans = glist.GetObjectValue(
"Channels");
974 size_t cs = chans.Size();
975 for (
size_t ci = 0; ci < cs; ++ci)
977 const JSON::Node& chan = chans.GetArrayElement(ci);
979 JSON::BindObject(chan, &channel, bindchan);
980 ProgramMapPtr pmap(
new ProgramMap);
981 ret.insert(std::make_pair(channel.chanId, pmap));
983 const JSON::Node& progs = chan.GetObjectValue(
"Programs");
985 size_t ps = progs.Size();
986 for (
size_t pi = 0; pi < ps; ++pi)
989 const JSON::Node& prog = progs.GetArrayElement(pi);
990 ProgramPtr program(
new Program());
992 JSON::BindObject(prog, program.get(), bindprog);
993 program->channel = channel;
994 pmap->insert(std::make_pair(program->startTime, program));
997 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
1002ProgramMapPtr WSAPI::GetProgramGuide1_0(uint32_t chanid, time_t starttime, time_t endtime)
1004 ProgramMapPtr ret(
new ProgramMap);
1007 unsigned proto = (unsigned)m_version.protocol;
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");
1027 autoptr<WSResponse> resp(qry.Execute());
1028 if (!resp->IsSuccessful())
1030 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1033 const JSON::Document json(*resp);
1034 const JSON::Node& root = json.GetRoot();
1035 if (!json.IsValid() || !root.IsObject())
1037 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1040 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1043 const JSON::Node& glist = root.GetObjectValue(
"ProgramGuide");
1044 ItemList list = ItemList();
1045 JSON::BindObject(glist, &list, bindlist);
1047 if (list.protoVer != proto)
1049 InvalidateService();
1053 const JSON::Node& chans = glist.GetObjectValue(
"Channels");
1055 size_t cs = chans.Size();
1056 for (
size_t ci = 0; ci < cs; ++ci)
1058 const JSON::Node& chan = chans.GetArrayElement(ci);
1060 JSON::BindObject(chan, &channel, bindchan);
1061 if (channel.chanId != chanid)
1064 const JSON::Node& progs = chan.GetObjectValue(
"Programs");
1066 size_t ps = progs.Size();
1067 for (
size_t pi = 0; pi < ps; ++pi)
1070 const JSON::Node& prog = progs.GetArrayElement(pi);
1071 ProgramPtr program(
new Program());
1073 JSON::BindObject(prog, program.get(), bindprog);
1074 program->channel = channel;
1075 ret->insert(std::make_pair(program->startTime, program));
1079 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
1084std::map<uint32_t, ProgramMapPtr> WSAPI::GetProgramGuide2_2(time_t starttime, time_t endtime)
1086 std::map<uint32_t, ProgramMapPtr> ret;
1088 uint32_t req_index = 0, req_count = FETCHSIZE, count = 0;
1089 unsigned proto = (unsigned)m_version.protocol;
1092 double d = difftime(endtime, starttime);
1094 req_count = FETCHSIZE / (int)(1.0 + d / (3 * 86400));
1103 qry.Request().RequestAccept(WS_ACCEPT);
1104 qry.Request().RequestService(
"/Guide/GetProgramGuide", WS_METHOD_Get);
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");
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())
1123 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1126 const JSON::Document json(*resp);
1127 const JSON::Node& root = json.GetRoot();
1128 if (!json.IsValid() || !root.IsObject())
1130 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1133 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1136 const JSON::Node& glist = root.GetObjectValue(
"ProgramGuide");
1137 ItemList list = ItemList();
1138 JSON::BindObject(glist, &list, bindlist);
1140 if (list.protoVer != proto)
1142 InvalidateService();
1147 const JSON::Node& chans = glist.GetObjectValue(
"Channels");
1149 size_t cs = chans.Size();
1150 for (
size_t ci = 0; ci < cs; ++ci)
1153 const JSON::Node& chan = chans.GetArrayElement(ci);
1155 JSON::BindObject(chan, &channel, bindchan);
1156 ProgramMapPtr pmap(
new ProgramMap);
1157 ret.insert(std::make_pair(channel.chanId, pmap));
1159 const JSON::Node& progs = chan.GetObjectValue(
"Programs");
1161 size_t ps = progs.Size();
1162 for (
size_t pi = 0; pi < ps; ++pi)
1164 const JSON::Node& prog = progs.GetArrayElement(pi);
1165 ProgramPtr program(
new Program());
1167 JSON::BindObject(prog, program.get(), bindprog);
1168 program->channel = channel;
1169 pmap->insert(std::make_pair(program->startTime, program));
1172 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
1175 while (count == req_count);
1180ProgramMapPtr WSAPI::GetProgramList2_2(uint32_t chanid, time_t starttime, time_t endtime)
1182 ProgramMapPtr ret(
new ProgramMap);
1184 uint32_t req_index = 0, req_count = FETCHSIZE_L, count = 0;
1185 unsigned proto = (unsigned)m_version.protocol;
1194 qry.Request().RequestAccept(WS_ACCEPT);
1195 qry.Request().RequestService(
"/Guide/GetProgramList", WS_METHOD_Get);
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");
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())
1216 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1219 const JSON::Document json(*resp);
1220 const JSON::Node& root = json.GetRoot();
1221 if (!json.IsValid() || !root.IsObject())
1223 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1226 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1229 const JSON::Node& plist = root.GetObjectValue(
"ProgramList");
1230 ItemList list = ItemList();
1231 JSON::BindObject(plist, &list, bindlist);
1233 if (list.protoVer != proto)
1235 InvalidateService();
1240 const JSON::Node& progs = plist.GetObjectValue(
"Programs");
1242 size_t ps = progs.Size();
1243 for (
size_t pi = 0; pi < ps; ++pi)
1246 const JSON::Node& prog = progs.GetArrayElement(pi);
1247 ProgramPtr program(
new Program());
1249 JSON::BindObject(prog, program.get(), bindprog);
1251 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
1252 JSON::BindObject(chan, &(program->channel), bindchan);
1253 ret->insert(std::make_pair(program->startTime, program));
1255 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
1258 while (count == req_count);
1267ProgramListPtr WSAPI::GetRecordedList1_5(
unsigned n,
bool descending)
1269 ProgramListPtr ret(
new ProgramList);
1271 uint32_t req_index = 0, req_count = FETCHSIZE, count = 0, total = 0;
1272 unsigned proto = (unsigned)m_version.protocol;
1283 qry.Request().RequestAccept(WS_ACCEPT);
1284 qry.Request().RequestService(
"/Dvr/GetRecordedList", WS_METHOD_Get);
1289 if (n && req_count > (n - total))
1290 req_count = (n - total);
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));
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())
1303 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1306 const JSON::Document json(*resp);
1307 const JSON::Node& root = json.GetRoot();
1308 if (!json.IsValid() || !root.IsObject())
1310 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1313 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1316 const JSON::Node& plist = root.GetObjectValue(
"ProgramList");
1317 ItemList list = ItemList();
1318 JSON::BindObject(plist, &list, bindlist);
1320 if (list.protoVer != proto)
1322 InvalidateService();
1327 const JSON::Node& progs = plist.GetObjectValue(
"Programs");
1329 size_t ps = progs.Size();
1330 for (
size_t pi = 0; pi < ps; ++pi)
1333 const JSON::Node& prog = progs.GetArrayElement(pi);
1334 ProgramPtr program(
new Program());
1336 JSON::BindObject(prog, program.get(), bindprog);
1338 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
1339 JSON::BindObject(chan, &(program->channel), bindchan);
1341 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
1342 JSON::BindObject(reco, &(program->recording), bindreco);
1344 if (!prog.GetObjectValue(
"Artwork").IsNull())
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)
1350 const JSON::Node& artw = arts.GetArrayElement(pa);
1351 Artwork artwork = Artwork();
1352 JSON::BindObject(artw, &artwork, bindartw);
1353 program->artwork.push_back(artwork);
1356 ret->push_back(program);
1359 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
1362 while (count == req_count && (!n || n > total));
1367ProgramPtr WSAPI::GetRecorded1_5(uint32_t chanid, time_t recstartts)
1371 unsigned proto = (unsigned)m_version.protocol;
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())
1389 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1392 const JSON::Document json(*resp);
1393 const JSON::Node& root = json.GetRoot();
1394 if (!json.IsValid() || !root.IsObject())
1396 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1399 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1401 const JSON::Node& prog = root.GetObjectValue(
"Program");
1402 ProgramPtr program(
new Program());
1404 JSON::BindObject(prog, program.get(), bindprog);
1406 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
1407 JSON::BindObject(chan, &(program->channel), bindchan);
1409 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
1410 JSON::BindObject(reco, &(program->recording), bindreco);
1412 if (!prog.GetObjectValue(
"Artwork").IsNull())
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)
1418 const JSON::Node& artw = arts.GetArrayElement(pa);
1419 Artwork artwork = Artwork();
1420 JSON::BindObject(artw, &artwork, bindartw);
1421 program->artwork.push_back(artwork);
1425 if (program->recording.startTs != INVALID_TIME)
1430ProgramPtr WSAPI::GetRecorded6_0(uint32_t recordedid)
1434 unsigned proto = (unsigned)m_version.protocol;
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())
1450 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1453 const JSON::Document json(*resp);
1454 const JSON::Node& root = json.GetRoot();
1455 if (!json.IsValid() || !root.IsObject())
1457 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1460 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1462 const JSON::Node& prog = root.GetObjectValue(
"Program");
1463 ProgramPtr program(
new Program());
1465 JSON::BindObject(prog, program.get(), bindprog);
1467 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
1468 JSON::BindObject(chan, &(program->channel), bindchan);
1470 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
1471 JSON::BindObject(reco, &(program->recording), bindreco);
1473 if (!prog.GetObjectValue(
"Artwork").IsNull())
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)
1479 const JSON::Node& artw = arts.GetArrayElement(pa);
1480 Artwork artwork = Artwork();
1481 JSON::BindObject(artw, &artwork, bindartw);
1482 program->artwork.push_back(artwork);
1486 if (program->recording.startTs != INVALID_TIME)
1491bool WSAPI::DeleteRecording2_1(uint32_t chanid, time_t recstartts,
bool forceDelete,
bool allowRerecord)
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())
1508 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1511 const JSON::Document json(*resp);
1512 const JSON::Node& root = json.GetRoot();
1513 if (!json.IsValid() || !root.IsObject())
1515 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1518 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1520 const JSON::Node& field = root.GetObjectValue(
"bool");
1521 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
1526bool WSAPI::DeleteRecording6_0(uint32_t recordedid,
bool forceDelete,
bool allowRerecord)
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())
1541 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1544 const JSON::Document json(*resp);
1545 const JSON::Node& root = json.GetRoot();
1546 if (!json.IsValid() || !root.IsObject())
1548 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1551 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1553 const JSON::Node& field = root.GetObjectValue(
"bool");
1554 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
1559bool WSAPI::UnDeleteRecording2_1(uint32_t chanid, time_t recstartts)
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())
1574 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1577 const JSON::Document json(*resp);
1578 const JSON::Node& root = json.GetRoot();
1579 if (!json.IsValid() || !root.IsObject())
1581 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1584 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1586 const JSON::Node& field = root.GetObjectValue(
"bool");
1587 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
1592bool WSAPI::UnDeleteRecording6_0(uint32_t recordedid)
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())
1605 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1608 const JSON::Document json(*resp);
1609 const JSON::Node& root = json.GetRoot();
1610 if (!json.IsValid() || !root.IsObject())
1612 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1615 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1617 const JSON::Node& field = root.GetObjectValue(
"bool");
1618 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
1623bool WSAPI::UpdateRecordedWatchedStatus4_5(uint32_t chanid, time_t recstartts,
bool watched)
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())
1639 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1642 const JSON::Document json(*resp);
1643 const JSON::Node& root = json.GetRoot();
1644 if (!json.IsValid() || !root.IsObject())
1646 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1649 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1651 const JSON::Node& field = root.GetObjectValue(
"bool");
1652 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
1657bool WSAPI::UpdateRecordedWatchedStatus6_0(uint32_t recordedid,
bool watched)
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())
1671 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1674 const JSON::Document json(*resp);
1675 const JSON::Node& root = json.GetRoot();
1676 if (!json.IsValid() || !root.IsObject())
1678 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1681 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1683 const JSON::Node& field = root.GetObjectValue(
"bool");
1684 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
1689MarkListPtr WSAPI::GetRecordedCommBreak6_1(uint32_t recordedid,
int unit)
1692 MarkListPtr ret(
new MarkList);
1693 unsigned proto = (unsigned)m_version.protocol;
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);
1705 qry.Request().SetContentParam(
"OffsetType",
"Position");
1707 qry.Request().SetContentParam(
"OffsetType",
"Duration");
1708 autoptr<WSResponse> resp(qry.Execute());
1709 if (!resp->IsSuccessful())
1711 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1714 const JSON::Document json(*resp);
1715 const JSON::Node& root = json.GetRoot();
1716 if (!json.IsValid() || !root.IsObject())
1718 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1721 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1724 const JSON::Node& slist = root.GetObjectValue(
"CutList");
1726 const JSON::Node& vcuts = slist.GetObjectValue(
"Cuttings");
1728 size_t vs = vcuts.Size();
1729 for (
size_t vi = 0; vi < vs; ++vi)
1731 const JSON::Node& vcut = vcuts.GetArrayElement(vi);
1732 MarkPtr mark(
new Mark());
1734 JSON::BindObject(vcut, mark.get(), bindcut);
1735 ret->push_back(mark);
1740MarkListPtr WSAPI::GetRecordedCutList6_1(uint32_t recordedid,
int unit)
1743 MarkListPtr ret(
new MarkList);
1744 unsigned proto = (unsigned)m_version.protocol;
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);
1756 qry.Request().SetContentParam(
"OffsetType",
"Position");
1758 qry.Request().SetContentParam(
"OffsetType",
"Duration");
1759 autoptr<WSResponse> resp(qry.Execute());
1760 if (!resp->IsSuccessful())
1762 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1765 const JSON::Document json(*resp);
1766 const JSON::Node& root = json.GetRoot();
1767 if (!json.IsValid() || !root.IsObject())
1769 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1772 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1775 const JSON::Node& slist = root.GetObjectValue(
"CutList");
1777 const JSON::Node& vcuts = slist.GetObjectValue(
"Cuttings");
1779 size_t vs = vcuts.Size();
1780 for (
size_t vi = 0; vi < vs; ++vi)
1782 const JSON::Node& vcut = vcuts.GetArrayElement(vi);
1783 MarkPtr mark(
new Mark());
1785 JSON::BindObject(vcut, mark.get(), bindcut);
1786 ret->push_back(mark);
1791bool WSAPI::SetSavedBookmark6_2(uint32_t recordedid,
int unit, int64_t value)
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);
1802 qry.Request().SetContentParam(
"OffsetType",
"Duration");
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())
1810 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1813 const JSON::Document json(*resp);
1814 const JSON::Node& root = json.GetRoot();
1815 if (!json.IsValid() || !root.IsObject())
1817 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1820 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1822 const JSON::Node& field = root.GetObjectValue(
"bool");
1823 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
1828int64_t WSAPI::GetSavedBookmark6_2(uint32_t recordedid,
int unit)
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);
1839 qry.Request().SetContentParam(
"OffsetType",
"Duration");
1841 qry.Request().SetContentParam(
"OffsetType",
"Position");
1842 autoptr<WSResponse> resp(qry.Execute());
1843 if (!resp->IsSuccessful())
1845 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1848 const JSON::Document json(*resp);
1849 const JSON::Node& root = json.GetRoot();
1850 if (!json.IsValid() || !root.IsObject())
1852 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1855 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1858 const JSON::Node& field = root.GetObjectValue(
"long");
1860 value = field.GetBigIntValue();
1861 else if (!field.IsString() || string_to_int64(field.GetStringValue().c_str(), &value))
1866static void ProcessRecordIN(
unsigned proto, RecordSchedule& record)
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);
1875RecordScheduleListPtr WSAPI::GetRecordScheduleList1_5()
1877 RecordScheduleListPtr ret(
new RecordScheduleList);
1879 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
1880 unsigned proto = (unsigned)m_version.protocol;
1888 qry.Request().RequestAccept(WS_ACCEPT);
1889 qry.Request().RequestService(
"/Dvr/GetRecordScheduleList", WS_METHOD_Get);
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);
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())
1903 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1906 const JSON::Document json(*resp);
1907 const JSON::Node& root = json.GetRoot();
1908 if (!json.IsValid() || !root.IsObject())
1910 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1913 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1916 const JSON::Node& rlist = root.GetObjectValue(
"RecRuleList");
1917 ItemList list = ItemList();
1918 JSON::BindObject(rlist, &list, bindlist);
1920 if (list.protoVer != proto)
1922 InvalidateService();
1927 const JSON::Node& recs = rlist.GetObjectValue(
"RecRules");
1929 size_t rs = recs.Size();
1930 for (
size_t ri = 0; ri < rs; ++ri)
1933 const JSON::Node& rec = recs.GetArrayElement(ri);
1934 RecordSchedulePtr record(
new RecordSchedule());
1936 JSON::BindObject(rec, record.get(), bindrec);
1937 ProcessRecordIN(proto, *record);
1938 ret->push_back(record);
1940 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
1943 while (count == req_count);
1948RecordSchedulePtr WSAPI::GetRecordSchedule1_5(uint32_t recordid)
1950 RecordSchedulePtr ret;
1952 unsigned proto = (unsigned)m_version.protocol;
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())
1965 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1968 const JSON::Document json(*resp);
1969 const JSON::Node& root = json.GetRoot();
1970 if (!json.IsValid() || !root.IsObject())
1972 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1975 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1977 const JSON::Node& rec = root.GetObjectValue(
"RecRule");
1978 RecordSchedulePtr record(
new RecordSchedule());
1980 JSON::BindObject(rec, record.get(), bindrec);
1982 if (record->recordId > 0)
1984 ProcessRecordIN(proto, *record);
1990static void ProcessRecordOUT(
unsigned proto, RecordSchedule& record)
1994 time_t st = record.startTime;
1995 localtime_r(&st, &stm);
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;
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);
2007bool WSAPI::AddRecordSchedule1_5(RecordSchedule& record)
2011 unsigned proto = (unsigned)m_version.protocol;
2013 ProcessRecordOUT(proto, record);
2017 qry.Request().RequestAccept(WS_ACCEPT);
2018 qry.Request().RequestService(
"/Dvr/AddRecordSchedule", WS_METHOD_Post);
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);
2072 autoptr<WSResponse> resp(qry.Execute());
2073 if (!resp->IsSuccessful())
2075 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2078 const JSON::Document json(*resp);
2079 const JSON::Node& root = json.GetRoot();
2080 if (!json.IsValid() || !root.IsObject())
2082 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2085 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2087 const JSON::Node& field = root.GetObjectValue(
"int");
2089 recordid = (uint32_t) field.GetBigIntValue();
2090 else if (!field.IsString() || string_to_uint32(field.GetStringValue().c_str(), &recordid))
2092 record.recordId = recordid;
2096bool WSAPI::AddRecordSchedule1_7(RecordSchedule& record)
2100 unsigned proto = (unsigned)m_version.protocol;
2102 ProcessRecordOUT(proto, record);
2106 qry.Request().RequestAccept(WS_ACCEPT);
2107 qry.Request().RequestService(
"/Dvr/AddRecordSchedule", WS_METHOD_Post);
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);
2165 autoptr<WSResponse> resp(qry.Execute());
2166 if (!resp->IsSuccessful())
2168 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2171 const JSON::Document json(*resp);
2172 const JSON::Node& root = json.GetRoot();
2173 if (!json.IsValid() || !root.IsObject())
2175 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2178 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2180 const JSON::Node& field = root.GetObjectValue(
"uint");
2182 recordid = (uint32_t) field.GetBigIntValue();
2183 else if (!field.IsString() || string_to_uint32(field.GetStringValue().c_str(), &recordid))
2185 record.recordId = recordid;
2189bool WSAPI::UpdateRecordSchedule1_7(RecordSchedule& record)
2192 unsigned proto = (unsigned)m_version.protocol;
2194 ProcessRecordOUT(proto, record);
2198 qry.Request().RequestAccept(WS_ACCEPT);
2199 qry.Request().RequestService(
"/Dvr/UpdateRecordSchedule", WS_METHOD_Post);
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);
2259 autoptr<WSResponse> resp(qry.Execute());
2260 if (!resp->IsSuccessful())
2262 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2265 const JSON::Document json(*resp);
2266 const JSON::Node& root = json.GetRoot();
2267 if (!json.IsValid() || !root.IsObject())
2269 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2272 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2274 const JSON::Node& field = root.GetObjectValue(
"bool");
2275 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
2280bool WSAPI::DisableRecordSchedule1_5(uint32_t recordid)
2286 qry.Request().RequestAccept(WS_ACCEPT);
2287 qry.Request().RequestService(
"/Dvr/DisableRecordSchedule", WS_METHOD_Post);
2289 uint32_to_string(recordid, &buf);
2290 qry.Request().SetContentParam(
"RecordId", buf.data);
2292 autoptr<WSResponse> resp(qry.Execute());
2293 if (!resp->IsSuccessful())
2295 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2298 const JSON::Document json(*resp);
2299 const JSON::Node& root = json.GetRoot();
2300 if (!json.IsValid() || !root.IsObject())
2302 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2305 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2307 const JSON::Node& field = root.GetObjectValue(
"bool");
2308 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
2313bool WSAPI::EnableRecordSchedule1_5(uint32_t recordid)
2319 qry.Request().RequestAccept(WS_ACCEPT);
2320 qry.Request().RequestService(
"/Dvr/EnableRecordSchedule", WS_METHOD_Post);
2322 uint32_to_string(recordid, &buf);
2323 qry.Request().SetContentParam(
"RecordId", buf.data);
2325 autoptr<WSResponse> resp(qry.Execute());
2326 if (!resp->IsSuccessful())
2328 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2331 const JSON::Document json(*resp);
2332 const JSON::Node& root = json.GetRoot();
2333 if (!json.IsValid() || !root.IsObject())
2335 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2338 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2340 const JSON::Node& field = root.GetObjectValue(
"bool");
2341 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
2346bool WSAPI::RemoveRecordSchedule1_5(uint32_t recordid)
2352 qry.Request().RequestAccept(WS_ACCEPT);
2353 qry.Request().RequestService(
"/Dvr/RemoveRecordSchedule", WS_METHOD_Post);
2355 uint32_to_string(recordid, &buf);
2356 qry.Request().SetContentParam(
"RecordId", buf.data);
2358 autoptr<WSResponse> resp(qry.Execute());
2359 if (!resp->IsSuccessful())
2361 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2364 const JSON::Document json(*resp);
2365 const JSON::Node& root = json.GetRoot();
2366 if (!json.IsValid() || !root.IsObject())
2368 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2371 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2373 const JSON::Node& field = root.GetObjectValue(
"bool");
2374 if (field.IsTrue() || (field.IsString() && strcmp(field.GetStringValue().c_str(),
"true") == 0))
2379ProgramListPtr WSAPI::GetUpcomingList1_5()
2382 ProgramListPtr ret = GetUpcomingList2_2();
2385 for (Myth::ProgramList::iterator it = recordings->begin(); it != recordings->end(); ++it)
2387 if ((*it)->recording.status == RS_RECORDING)
2388 ret->push_back(*it);
2393ProgramListPtr WSAPI::GetUpcomingList2_2()
2395 ProgramListPtr ret(
new ProgramList);
2397 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
2398 unsigned proto = (unsigned)m_version.protocol;
2408 qry.Request().RequestAccept(WS_ACCEPT);
2409 qry.Request().RequestService(
"/Dvr/GetUpcomingList", WS_METHOD_Get);
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");
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())
2424 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2427 const JSON::Document json(*resp);
2428 const JSON::Node& root = json.GetRoot();
2429 if (!json.IsValid() || !root.IsObject())
2431 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2434 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2437 const JSON::Node& plist = root.GetObjectValue(
"ProgramList");
2438 ItemList list = ItemList();
2439 JSON::BindObject(plist, &list, bindlist);
2441 if (list.protoVer != proto)
2443 InvalidateService();
2448 const JSON::Node& progs = plist.GetObjectValue(
"Programs");
2450 size_t ps = progs.Size();
2451 for (
size_t pi = 0; pi < ps; ++pi)
2454 const JSON::Node& prog = progs.GetArrayElement(pi);
2455 ProgramPtr program(
new Program());
2457 JSON::BindObject(prog, program.get(), bindprog);
2459 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
2460 JSON::BindObject(chan, &(program->channel), bindchan);
2462 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
2463 JSON::BindObject(reco, &(program->recording), bindreco);
2464 ret->push_back(program);
2466 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
2469 while (count == req_count);
2474ProgramListPtr WSAPI::GetConflictList1_5()
2476 ProgramListPtr ret(
new ProgramList);
2478 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
2479 unsigned proto = (unsigned)m_version.protocol;
2489 qry.Request().RequestAccept(WS_ACCEPT);
2490 qry.Request().RequestService(
"/Dvr/GetConflictList", WS_METHOD_Get);
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);
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())
2504 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2507 const JSON::Document json(*resp);
2508 const JSON::Node& root = json.GetRoot();
2509 if (!json.IsValid() || !root.IsObject())
2511 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2514 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2517 const JSON::Node& plist = root.GetObjectValue(
"ProgramList");
2518 ItemList list = ItemList();
2519 JSON::BindObject(plist, &list, bindlist);
2521 if (list.protoVer != proto)
2523 InvalidateService();
2528 const JSON::Node& progs = plist.GetObjectValue(
"Programs");
2530 size_t ps = progs.Size();
2531 for (
size_t pi = 0; pi < ps; ++pi)
2534 const JSON::Node& prog = progs.GetArrayElement(pi);
2535 ProgramPtr program(
new Program());
2537 JSON::BindObject(prog, program.get(), bindprog);
2539 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
2540 JSON::BindObject(chan, &(program->channel), bindchan);
2542 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
2543 JSON::BindObject(reco, &(program->recording), bindreco);
2544 ret->push_back(program);
2546 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
2549 while (count == req_count);
2554ProgramListPtr WSAPI::GetExpiringList1_5()
2556 ProgramListPtr ret(
new ProgramList);
2558 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
2559 unsigned proto = (unsigned)m_version.protocol;
2569 qry.Request().RequestAccept(WS_ACCEPT);
2570 qry.Request().RequestService(
"/Dvr/GetExpiringList", WS_METHOD_Get);
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);
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())
2584 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2587 const JSON::Document json(*resp);
2588 const JSON::Node& root = json.GetRoot();
2589 if (!json.IsValid() || !root.IsObject())
2591 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2594 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2597 const JSON::Node& plist = root.GetObjectValue(
"ProgramList");
2598 ItemList list = ItemList();
2599 JSON::BindObject(plist, &list, bindlist);
2601 if (list.protoVer != proto)
2603 InvalidateService();
2608 const JSON::Node& progs = plist.GetObjectValue(
"Programs");
2610 size_t ps = progs.Size();
2611 for (
size_t pi = 0; pi < ps; ++pi)
2614 const JSON::Node& prog = progs.GetArrayElement(pi);
2615 ProgramPtr program(
new Program());
2617 JSON::BindObject(prog, program.get(), bindprog);
2619 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
2620 JSON::BindObject(chan, &(program->channel), bindchan);
2622 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
2623 JSON::BindObject(reco, &(program->recording), bindreco);
2624 ret->push_back(program);
2626 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
2629 while (count == req_count);
2634StringListPtr WSAPI::GetRecGroupList1_5()
2636 StringListPtr ret(
new StringList);
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())
2645 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2648 const JSON::Document json(*resp);
2649 const JSON::Node& root = json.GetRoot();
2650 if (!json.IsValid() || !root.IsObject())
2652 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2655 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2658 const JSON::Node& list = root.GetObjectValue(
"StringList");
2661 size_t s = list.Size();
2662 for (
size_t i = 0; i < s; ++i)
2664 const JSON::Node& val = list.GetArrayElement(i);
2667 ret->push_back(val.GetStringValue());
2678WSStreamPtr WSAPI::GetFile1_32(
const std::string& filename,
const std::string& sgname)
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())
2691 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2694 ret.reset(
new WSStream(resp.release()));
2698WSStreamPtr WSAPI::GetChannelIcon1_32(uint32_t chanid,
unsigned width,
unsigned height)
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);
2711 uint32_to_string(width, &buf);
2712 qry.Request().SetContentParam(
"Width", buf.data);
2716 uint32_to_string(height, &buf);
2717 qry.Request().SetContentParam(
"Height", buf.data);
2719 autoptr<WSResponse> resp(qry.Execute(1,
false,
true));
2720 if (!resp->IsSuccessful())
2722 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2725 ret.reset(
new WSStream(resp.release()));
2729std::string WSAPI::GetChannelIconUrl1_32(uint32_t chanid,
unsigned width,
unsigned height)
2734 uri.append(GetBaseURL());
2735 uri.append(
"/Guide/GetChannelIcon");
2736 uint32_to_string(chanid, &buf);
2737 uri.append(
"?ChanId=").append(buf.data);
2740 uint32_to_string(width, &buf);
2741 uri.append(
"&Width=").append(buf.data);
2745 uint32_to_string(height, &buf);
2746 uri.append(
"&Height=").append(buf.data);
2751WSStreamPtr WSAPI::GetPreviewImage1_32(uint32_t chanid, time_t recstartts,
unsigned width,
unsigned height)
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);
2766 uint32_to_string(width, &buf);
2767 qry.Request().SetContentParam(
"Width", buf.data);
2771 uint32_to_string(height, &buf);
2772 qry.Request().SetContentParam(
"Height", buf.data);
2774 autoptr<WSResponse> resp(qry.Execute(1,
false,
true));
2775 if (!resp->IsSuccessful())
2777 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2780 ret.reset(
new WSStream(resp.release()));
2784std::string WSAPI::GetPreviewImageUrl1_32(uint32_t chanid, time_t recstartts,
unsigned width,
unsigned height)
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));
2797 uint32_to_string(width, &buf);
2798 uri.append(
"&Width=").append(buf.data);
2802 uint32_to_string(height, &buf);
2803 uri.append(
"&Height=").append(buf.data);
2808WSStreamPtr WSAPI::GetRecordingArtwork1_32(
const std::string& type,
const std::string& inetref, uint16_t season,
unsigned width,
unsigned height)
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);
2823 uint32_to_string(width, &buf);
2824 qry.Request().SetContentParam(
"Width", buf.data);
2828 uint32_to_string(height, &buf);
2829 qry.Request().SetContentParam(
"Height", buf.data);
2831 autoptr<WSResponse> resp(qry.Execute(1,
false,
true));
2832 if (!resp->IsSuccessful())
2834 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2837 ret.reset(
new WSStream(resp.release()));
2841std::string WSAPI::GetRecordingArtworkUrl1_32(
const std::string& type,
const std::string& inetref, uint16_t season,
unsigned width,
unsigned height)
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);
2854 uint32_to_string(width, &buf);
2855 uri.append(
"&Width=").append(buf.data);
2859 uint32_to_string(height, &buf);
2860 uri.append(
"&Height=").append(buf.data);
2865ArtworkListPtr WSAPI::GetRecordingArtworkList1_32(uint32_t chanid, time_t recstartts)
2867 ArtworkListPtr ret(
new ArtworkList);
2869 unsigned proto = (unsigned)m_version.protocol;
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())
2884 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2887 const JSON::Document json(*resp);
2888 const JSON::Node& root = json.GetRoot();
2889 if (!json.IsValid() || !root.IsObject())
2891 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2894 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2896 const JSON::Node& list = root.GetObjectValue(
"ArtworkInfoList");
2898 const JSON::Node& arts = list.GetObjectValue(
"ArtworkInfos");
2899 size_t as = arts.Size();
2900 for (
size_t pa = 0; pa < as; ++pa)
2902 const JSON::Node& artw = arts.GetArrayElement(pa);
2903 ArtworkPtr artwork(
new Artwork());
2904 JSON::BindObject(artw, artwork.get(), bindartw);
2905 ret->push_back(artwork);
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.
ProgramListPtr GetRecordedList(unsigned n=0, bool descending=false)
GET Dvr/GetRecordedList.
SettingMapPtr GetSettings(bool myhost)
GET Myth/GetSetting.
bool GetServiceVersion(WSServiceId_t id, WSServiceVersion_t &version)
SettingMapPtr GetHostSettings(const std::string &hostname)
GET Myth/GetSetting.
const bindings_t * getChannelBindArray(unsigned proto)
Returns bindings for Myth::Channel.
const bindings_t * getVideoSourceBindArray(unsigned proto)
Returns bindings for Myth::VideoSource.
const bindings_t * getRecordScheduleBindArray(unsigned proto)
Returns bindings for Myth::RecordSchedule.
const bindings_t * getCaptureCardBindArray(unsigned proto)
Returns bindings for Myth::CaptureCard.
const bindings_t * getRecordingBindArray(unsigned proto)
Returns bindings for Myth::Recording.
const bindings_t * getCuttingBindArray(unsigned proto)
Returns bindings for Myth::Mark.
const bindings_t * getListBindArray(unsigned proto)
Returns bindings for Myth::List.
const bindings_t * getVersionBindArray(unsigned ranking)
Returns bindings for Myth::Version.
const bindings_t * getArtworkBindArray(unsigned proto)
Returns bindings for Myth::Artwork.
const bindings_t * getProgramBindArray(unsigned proto)
Returns bindings for Myth::Program.
This is the main namespace that encloses all public classes.