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" 34 #define BOOLSTR(a) ((a) ? "true" : "false") 36 #define FETCHSIZE_L 1000 40 #define WS_ROOT_MYTH "/Myth" 41 #define WS_ROOT_CAPTURE "/Capture" 42 #define WS_ROOT_CHANNEL "/Channel" 43 #define WS_ROOT_GUIDE "/Guide" 44 #define WS_ROOT_CONTENT "/Content" 45 #define WS_ROOT_DVR "/Dvr" 47 static std::string encodeParam(
const std::string& str);
49 WSAPI::WSAPI(
const std::string& server,
unsigned port,
const std::string& securityPin)
50 : m_mutex(new OS::CMutex)
53 , m_securityPin(securityPin)
58 m_checked = InitWSAPI();
66 bool WSAPI::InitWSAPI()
70 memset(m_serviceVersion, 0,
sizeof(m_serviceVersion));
73 if (!GetServiceVersion(WS_Myth, mythwsv))
75 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
78 if (mythwsv.ranking > MYTH_API_VERSION_MAX_RANKING) {}
79 else if (mythwsv.ranking >= 0x00020000)
80 status = CheckServerHostName2_0() & CheckVersion2_0();
85 if (GetServiceVersion(WS_Capture, m_serviceVersion[WS_Capture]) &&
86 GetServiceVersion(WS_Channel, m_serviceVersion[WS_Channel]) &&
87 GetServiceVersion(WS_Guide, m_serviceVersion[WS_Guide]) &&
88 GetServiceVersion(WS_Content, m_serviceVersion[WS_Content]) &&
89 GetServiceVersion(WS_Dvr, m_serviceVersion[WS_Dvr]))
91 DBG(DBG_INFO,
"%s: MythTV API service is available: %s:%d(%s) protocol(%d) schema(%d)\n",
92 __FUNCTION__, m_serverHostName.c_str(), m_port, m_version.version.c_str(),
93 (unsigned)m_version.protocol, (
unsigned)m_version.schema);
97 DBG(DBG_ERROR,
"%s: MythTV API service is not supported or unavailable: %s:%d (%u.%u)\n",
98 __FUNCTION__, m_server.c_str(), m_port, mythwsv.major, mythwsv.minor);
104 static const char * WSServiceRoot[WS_INVALID + 1] =
114 std::string url(WSServiceRoot[
id]);
115 url.append(
"/version");
116 WSRequest req = WSRequest(m_server, m_port);
117 req.RequestAccept(CT_JSON);
118 req.RequestService(url);
119 WSResponse resp(req);
120 if (resp.IsSuccessful())
123 const JSON::Document json(resp);
124 const JSON::Node& root = json.GetRoot();
125 if (json.IsValid() && root.IsObject())
127 const JSON::Node& field = root.GetObjectValue(
"String");
128 if (field.IsString())
130 const std::string& val = field.GetStringValue();
131 if (sscanf(val.c_str(),
"%d.%d", &(wsv.major), &(wsv.minor)) == 2)
133 wsv.ranking = ((wsv.major & 0xFFFF) << 16) | (wsv.minor & 0xFFFF);
145 bool WSAPI::CheckServerHostName2_0()
147 m_serverHostName.clear();
149 WSRequest req = WSRequest(m_server, m_port);
150 req.RequestAccept(CT_JSON);
151 req.RequestService(
"/Myth/GetHostName");
152 WSResponse resp(req);
153 if (!resp.IsSuccessful())
155 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
159 const JSON::Document json(resp);
160 const JSON::Node& root = json.GetRoot();
161 if (json.IsValid() && root.IsObject())
163 const JSON::Node& field = root.GetObjectValue(
"String");
164 if (field.IsString())
166 const std::string& val = field.GetStringValue();
167 m_serverHostName = val;
168 m_namedCache[val] = m_server;
175 bool WSAPI::CheckVersion2_0()
177 m_version.protocol = 0;
178 m_version.schema = 0;
179 m_version.version.clear();
182 WSRequest req = WSRequest(m_server, m_port);
183 req.RequestAccept(CT_JSON);
184 req.RequestService(
"/Myth/GetConnectionInfo");
185 if (!m_securityPin.empty())
188 req.SetContentParam(
"Pin", m_securityPin);
190 WSResponse resp(req);
191 if (!resp.IsSuccessful())
193 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
197 const JSON::Document json(resp);
198 const JSON::Node& root = json.GetRoot();
199 if (json.IsValid() && root.IsObject())
201 const JSON::Node& con = root.GetObjectValue(
"ConnectionInfo");
204 const JSON::Node& ver = con.GetObjectValue(
"Version");
206 if (m_version.protocol)
213 unsigned WSAPI::CheckService()
215 OS::CLockGuard lock(*m_mutex);
216 if (m_checked || (m_checked = InitWSAPI()))
217 return (
unsigned)m_version.protocol;
223 OS::CLockGuard lock(*m_mutex);
224 if (m_checked || (m_checked = InitWSAPI()))
225 return m_serviceVersion[id];
226 return m_serviceVersion[WS_INVALID];
229 void WSAPI::InvalidateService()
235 std::string WSAPI::GetServerHostName()
237 return m_serverHostName;
240 VersionPtr WSAPI::GetVersion()
242 return VersionPtr(
new Version(m_version));
245 std::string WSAPI::ResolveHostName(
const std::string& hostname)
247 OS::CLockGuard lock(*m_mutex);
248 std::map<std::string, std::string>::const_iterator it = m_namedCache.find(hostname);
249 if (it != m_namedCache.end())
251 Myth::SettingPtr addr = this->GetSetting(
"BackendServerIP6", hostname);
252 if (addr && !addr->value.empty() && addr->value !=
"::1")
254 std::string& ret = m_namedCache[hostname];
255 ret.assign(addr->value);
256 DBG(DBG_DEBUG,
"%s: resolving hostname %s as %s\n", __FUNCTION__, hostname.c_str(), ret.c_str());
259 addr = this->GetSetting(
"BackendServerIP", hostname);
260 if (addr && !addr->value.empty())
262 std::string& ret = m_namedCache[hostname];
263 ret.assign(addr->value);
264 DBG(DBG_DEBUG,
"%s: resolving hostname %s as %s\n", __FUNCTION__, hostname.c_str(), ret.c_str());
267 DBG(DBG_ERROR,
"%s: unknown host (%s)\n", __FUNCTION__, hostname.c_str());
268 return std::string();
276 SettingPtr WSAPI::GetSetting2_0(
const std::string& key,
const std::string& hostname)
281 WSRequest req = WSRequest(m_server, m_port);
282 req.RequestAccept(CT_JSON);
283 req.RequestService(
"/Myth/GetSetting");
284 req.SetContentParam(
"HostName", hostname);
285 req.SetContentParam(
"Key", key);
286 WSResponse resp(req);
287 if (!resp.IsSuccessful())
289 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
292 const JSON::Document json(resp);
293 const JSON::Node& root = json.GetRoot();
294 if (!json.IsValid() || !root.IsObject())
296 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
299 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
302 const JSON::Node& slist = root.GetObjectValue(
"SettingList");
304 const JSON::Node& sts = slist.GetObjectValue(
"Settings");
309 const JSON::Node& val = sts.GetObjectValue(static_cast<size_t>(0));
313 ret->key = sts.GetObjectKey(0);
314 ret->value = val.GetStringValue();
321 SettingPtr WSAPI::GetSetting5_0(
const std::string& key,
const std::string& hostname)
326 WSRequest req = WSRequest(m_server, m_port);
327 req.RequestAccept(CT_JSON);
328 req.RequestService(
"/Myth/GetSetting");
329 req.SetContentParam(
"HostName", hostname);
330 req.SetContentParam(
"Key", key);
331 WSResponse resp(req);
332 if (!resp.IsSuccessful())
334 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
337 const JSON::Document json(resp);
338 const JSON::Node& root = json.GetRoot();
339 if (!json.IsValid() || !root.IsObject())
341 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
344 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
347 const JSON::Node& val = root.GetObjectValue(
"String");
352 ret->value = val.GetStringValue();
359 std::string hostname;
361 hostname = TcpSocket::GetMyHostName();
362 return GetSetting(key, hostname);
365 SettingMapPtr WSAPI::GetSettings2_0(
const std::string& hostname)
367 SettingMapPtr ret(
new SettingMap);
370 WSRequest req = WSRequest(m_server, m_port);
371 req.RequestAccept(CT_JSON);
372 req.RequestService(
"/Myth/GetSetting");
373 req.SetContentParam(
"HostName", hostname);
374 WSResponse resp(req);
375 if (!resp.IsSuccessful())
377 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
380 const JSON::Document json(resp);
381 const JSON::Node& root = json.GetRoot();
382 if (!json.IsValid() || !root.IsObject())
384 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
387 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
390 const JSON::Node& slist = root.GetObjectValue(
"SettingList");
392 const JSON::Node& sts = slist.GetObjectValue(
"Settings");
395 size_t s = sts.Size();
396 for (
size_t i = 0; i < s; ++i)
398 const JSON::Node& val = sts.GetObjectValue(i);
401 SettingPtr setting(
new Setting());
402 setting->key = sts.GetObjectKey(i);
403 setting->value = val.GetStringValue();
404 ret->insert(SettingMap::value_type(setting->key, setting));
411 SettingMapPtr WSAPI::GetSettings5_0(
const std::string& hostname)
413 SettingMapPtr ret(
new SettingMap);
416 WSRequest req = WSRequest(m_server, m_port);
417 req.RequestAccept(CT_JSON);
418 req.RequestService(
"/Myth/GetSettingList");
419 req.SetContentParam(
"HostName", hostname);
420 WSResponse resp(req);
421 if (!resp.IsSuccessful())
423 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
426 const JSON::Document json(resp);
427 const JSON::Node& root = json.GetRoot();
428 if (!json.IsValid() || !root.IsObject())
430 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
433 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
436 const JSON::Node& slist = root.GetObjectValue(
"SettingList");
438 const JSON::Node& sts = slist.GetObjectValue(
"Settings");
441 size_t s = sts.Size();
442 for (
size_t i = 0; i < s; ++i)
444 const JSON::Node& val = sts.GetObjectValue(i);
447 SettingPtr setting(
new Setting());
448 setting->key = sts.GetObjectKey(i);
449 setting->value = val.GetStringValue();
450 ret->insert(SettingMap::value_type(setting->key, setting));
459 std::string hostname;
461 hostname = TcpSocket::GetMyHostName();
462 return GetSettings(hostname);
465 bool WSAPI::PutSetting2_0(
const std::string& key,
const std::string& value,
bool myhost)
468 WSRequest req = WSRequest(m_server, m_port);
469 req.RequestAccept(CT_JSON);
470 req.RequestService(
"/Myth/PutSetting", HRM_POST);
471 std::string hostname;
473 hostname = TcpSocket::GetMyHostName();
474 req.SetContentParam(
"HostName", hostname);
475 req.SetContentParam(
"Key", key);
476 req.SetContentParam(
"Value", value);
477 WSResponse resp(req);
478 if (!resp.IsSuccessful())
480 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
483 const JSON::Document json(resp);
484 const JSON::Node& root = json.GetRoot();
485 if (!json.IsValid() || !root.IsObject())
487 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
490 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
492 const JSON::Node& field = root.GetObjectValue(
"bool");
493 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
502 CaptureCardListPtr WSAPI::GetCaptureCardList1_4()
504 CaptureCardListPtr ret(
new CaptureCardList);
505 unsigned proto = (unsigned)m_version.protocol;
511 WSRequest req = WSRequest(m_server, m_port);
512 req.RequestAccept(CT_JSON);
513 req.RequestService(
"/Capture/GetCaptureCardList");
514 req.SetContentParam(
"HostName", m_serverHostName.c_str());
515 WSResponse resp(req);
516 if (!resp.IsSuccessful())
518 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
521 const JSON::Document json(resp);
522 const JSON::Node& root = json.GetRoot();
523 if (!json.IsValid() || !root.IsObject())
525 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
528 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
531 const JSON::Node& clist = root.GetObjectValue(
"CaptureCardList");
533 const JSON::Node& cards = clist.GetObjectValue(
"CaptureCards");
535 size_t cs = cards.Size();
536 for (
size_t ci = 0; ci < cs; ++ci)
538 const JSON::Node& card = cards.GetArrayElement(ci);
541 JSON::BindObject(card, captureCard.get(), bindcard);
542 ret->push_back(captureCard);
551 VideoSourceListPtr WSAPI::GetVideoSourceList1_2()
553 VideoSourceListPtr ret(
new VideoSourceList);
554 unsigned proto = (unsigned)m_version.protocol;
560 WSRequest req = WSRequest(m_server, m_port);
561 req.RequestAccept(CT_JSON);
562 req.RequestService(
"/Channel/GetVideoSourceList");
563 WSResponse resp(req);
564 if (!resp.IsSuccessful())
566 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
569 const JSON::Document json(resp);
570 const JSON::Node& root = json.GetRoot();
571 if (!json.IsValid() || !root.IsObject())
573 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
576 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
579 const JSON::Node& slist = root.GetObjectValue(
"VideoSourceList");
581 const JSON::Node& vsrcs = slist.GetObjectValue(
"VideoSources");
583 size_t vs = vsrcs.Size();
584 for (
size_t vi = 0; vi < vs; ++vi)
586 const JSON::Node& vsrc = vsrcs.GetArrayElement(vi);
589 JSON::BindObject(vsrc, videoSource.get(), bindvsrc);
590 ret->push_back(videoSource);
595 ChannelListPtr WSAPI::GetChannelList1_2(uint32_t sourceid,
bool onlyVisible)
597 ChannelListPtr ret(
new ChannelList);
599 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
600 unsigned proto = (unsigned)m_version.protocol;
607 WSRequest req = WSRequest(m_server, m_port);
608 req.RequestAccept(CT_JSON);
609 req.RequestService(
"/Channel/GetChannelInfoList");
614 uint32_to_string(sourceid, buf);
615 req.SetContentParam(
"SourceID", buf);
616 int32_to_string(req_index, buf);
617 req.SetContentParam(
"StartIndex", buf);
618 int32_to_string(req_count, buf);
619 req.SetContentParam(
"Count", buf);
621 DBG(DBG_DEBUG,
"%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
622 WSResponse resp(req);
623 if (!resp.IsSuccessful())
625 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
628 const JSON::Document json(resp);
629 const JSON::Node& root = json.GetRoot();
630 if (!json.IsValid() || !root.IsObject())
632 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
635 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
638 const JSON::Node& clist = root.GetObjectValue(
"ChannelInfoList");
640 JSON::BindObject(clist, &list, bindlist);
642 if (list.protoVer != proto)
649 const JSON::Node& chans = clist.GetObjectValue(
"ChannelInfos");
651 size_t cs = chans.Size();
652 for (
size_t ci = 0; ci < cs; ++ci)
655 const JSON::Node& chan = chans.GetArrayElement(ci);
656 ChannelPtr channel(
new Channel());
658 JSON::BindObject(chan, channel.get(), bindchan);
659 if (channel->chanId && (!onlyVisible || channel->visible))
660 ret->push_back(channel);
662 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
665 while (count == req_count);
670 ChannelListPtr WSAPI::GetChannelList1_5(uint32_t sourceid,
bool onlyVisible)
672 ChannelListPtr ret(
new ChannelList);
674 int32_t req_index = 0, count = 0;
675 unsigned proto = (unsigned)m_version.protocol;
682 WSRequest req = WSRequest(m_server, m_port);
683 req.RequestAccept(CT_JSON);
684 req.RequestService(
"/Channel/GetChannelInfoList");
689 req.SetContentParam(
"Details",
"true");
690 req.SetContentParam(
"OnlyVisible", BOOLSTR(onlyVisible));
691 uint32_to_string(sourceid, buf);
692 req.SetContentParam(
"SourceID", buf);
700 WSResponse resp(req);
701 if (!resp.IsSuccessful())
703 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
706 const JSON::Document json(resp);
707 const JSON::Node& root = json.GetRoot();
708 if (!json.IsValid() || !root.IsObject())
710 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
713 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
716 const JSON::Node& clist = root.GetObjectValue(
"ChannelInfoList");
718 JSON::BindObject(clist, &list, bindlist);
720 if (list.protoVer != proto)
727 const JSON::Node& chans = clist.GetObjectValue(
"ChannelInfos");
729 size_t cs = chans.Size();
730 for (
size_t ci = 0; ci < cs; ++ci)
733 const JSON::Node& chan = chans.GetArrayElement(ci);
734 ChannelPtr channel(
new Channel());
736 JSON::BindObject(chan, channel.get(), bindchan);
738 ret->push_back(channel);
740 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
749 ChannelPtr WSAPI::GetChannel1_2(uint32_t chanid)
753 unsigned proto = (unsigned)m_version.protocol;
759 WSRequest req = WSRequest(m_server, m_port);
760 req.RequestAccept(CT_JSON);
761 req.RequestService(
"/Channel/GetChannelInfo");
762 uint32_to_string(chanid, buf);
763 req.SetContentParam(
"ChanID", buf);
765 WSResponse resp(req);
766 if (!resp.IsSuccessful())
768 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
771 const JSON::Document json(resp);
772 const JSON::Node& root = json.GetRoot();
773 if (!json.IsValid() || !root.IsObject())
775 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
778 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
781 const JSON::Node& chan = root.GetObjectValue(
"ChannelInfo");
782 ChannelPtr channel(
new Channel());
784 JSON::BindObject(chan, channel.get(), bindchan);
785 if (channel->chanId == chanid)
794 std::map<uint32_t, ProgramMapPtr> WSAPI::GetProgramGuide1_0(time_t starttime, time_t endtime)
796 std::map<uint32_t, ProgramMapPtr> ret;
799 unsigned proto = (unsigned)m_version.protocol;
807 WSRequest req = WSRequest(m_server, m_port);
808 req.RequestAccept(CT_JSON);
809 req.RequestService(
"/Guide/GetProgramGuide");
810 req.SetContentParam(
"StartChanId",
"0");
811 req.SetContentParam(
"NumChannels",
"0");
812 time_to_iso8601utc(starttime, buf);
813 req.SetContentParam(
"StartTime", buf);
814 time_to_iso8601utc(endtime, buf);
815 req.SetContentParam(
"EndTime", buf);
816 req.SetContentParam(
"Details",
"true");
818 WSResponse resp(req);
819 if (!resp.IsSuccessful())
821 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
824 const JSON::Document json(resp);
825 const JSON::Node& root = json.GetRoot();
826 if (!json.IsValid() || !root.IsObject())
828 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
831 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
834 const JSON::Node& glist = root.GetObjectValue(
"ProgramGuide");
836 JSON::BindObject(glist, &list, bindlist);
838 if (list.protoVer != proto)
844 const JSON::Node& chans = glist.GetObjectValue(
"Channels");
846 size_t cs = chans.Size();
847 for (
size_t ci = 0; ci < cs; ++ci)
849 const JSON::Node& chan = chans.GetArrayElement(ci);
851 JSON::BindObject(chan, &channel, bindchan);
852 ProgramMapPtr pmap(
new ProgramMap);
853 ret.insert(std::make_pair(channel.chanId, pmap));
855 const JSON::Node& progs = chan.GetObjectValue(
"Programs");
857 size_t ps = progs.Size();
858 for (
size_t pi = 0; pi < ps; ++pi)
861 const JSON::Node& prog = progs.GetArrayElement(pi);
862 ProgramPtr program(
new Program());
864 JSON::BindObject(prog, program.get(), bindprog);
865 program->channel = channel;
866 pmap->insert(std::make_pair(program->startTime, program));
869 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
874 ProgramMapPtr WSAPI::GetProgramGuide1_0(uint32_t chanid, time_t starttime, time_t endtime)
876 ProgramMapPtr ret(
new ProgramMap);
879 unsigned proto = (unsigned)m_version.protocol;
887 WSRequest req = WSRequest(m_server, m_port);
888 req.RequestAccept(CT_JSON);
889 req.RequestService(
"/Guide/GetProgramGuide");
890 uint32_to_string(chanid, buf);
891 req.SetContentParam(
"StartChanId", buf);
892 req.SetContentParam(
"NumChannels",
"1");
893 time_to_iso8601utc(starttime, buf);
894 req.SetContentParam(
"StartTime", buf);
895 time_to_iso8601utc(endtime, buf);
896 req.SetContentParam(
"EndTime", buf);
897 req.SetContentParam(
"Details",
"true");
899 WSResponse resp(req);
900 if (!resp.IsSuccessful())
902 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
905 const JSON::Document json(resp);
906 const JSON::Node& root = json.GetRoot();
907 if (!json.IsValid() || !root.IsObject())
909 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
912 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
915 const JSON::Node& glist = root.GetObjectValue(
"ProgramGuide");
917 JSON::BindObject(glist, &list, bindlist);
919 if (list.protoVer != proto)
925 const JSON::Node& chans = glist.GetObjectValue(
"Channels");
927 size_t cs = chans.Size();
928 for (
size_t ci = 0; ci < cs; ++ci)
930 const JSON::Node& chan = chans.GetArrayElement(ci);
932 JSON::BindObject(chan, &channel, bindchan);
933 if (channel.chanId != chanid)
936 const JSON::Node& progs = chan.GetObjectValue(
"Programs");
938 size_t ps = progs.Size();
939 for (
size_t pi = 0; pi < ps; ++pi)
942 const JSON::Node& prog = progs.GetArrayElement(pi);
943 ProgramPtr program(
new Program());
945 JSON::BindObject(prog, program.get(), bindprog);
946 program->channel = channel;
947 ret->insert(std::make_pair(program->startTime, program));
951 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
956 std::map<uint32_t, ProgramMapPtr> WSAPI::GetProgramGuide2_2(time_t starttime, time_t endtime)
958 std::map<uint32_t, ProgramMapPtr> ret;
960 uint32_t req_index = 0, req_count = FETCHSIZE, count = 0, total = 0;
961 unsigned proto = (unsigned)m_version.protocol;
964 double d = difftime(endtime, starttime);
966 req_count = FETCHSIZE / (int)(1.0 + d / (3 * 86400));
974 WSRequest req = WSRequest(m_server, m_port);
975 req.RequestAccept(CT_JSON);
976 req.RequestService(
"/Guide/GetProgramGuide");
981 uint32_to_string(req_index, buf);
982 req.SetContentParam(
"StartIndex", buf);
983 uint32_to_string(req_count, buf);
984 req.SetContentParam(
"Count", buf);
985 time_to_iso8601utc(starttime, buf);
986 req.SetContentParam(
"StartTime", buf);
987 time_to_iso8601utc(endtime, buf);
988 req.SetContentParam(
"EndTime", buf);
989 req.SetContentParam(
"Details",
"true");
991 DBG(DBG_DEBUG,
"%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
992 WSResponse resp(req);
993 if (!resp.IsSuccessful())
995 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
998 const JSON::Document json(resp);
999 const JSON::Node& root = json.GetRoot();
1000 if (!json.IsValid() || !root.IsObject())
1002 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1005 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1008 const JSON::Node& glist = root.GetObjectValue(
"ProgramGuide");
1010 JSON::BindObject(glist, &list, bindlist);
1012 if (list.protoVer != proto)
1014 InvalidateService();
1019 const JSON::Node& chans = glist.GetObjectValue(
"Channels");
1021 size_t cs = chans.Size();
1022 for (
size_t ci = 0; ci < cs; ++ci)
1025 const JSON::Node& chan = chans.GetArrayElement(ci);
1027 JSON::BindObject(chan, &channel, bindchan);
1028 ProgramMapPtr pmap(
new ProgramMap);
1029 ret.insert(std::make_pair(channel.chanId, pmap));
1031 const JSON::Node& progs = chan.GetObjectValue(
"Programs");
1033 size_t ps = progs.Size();
1034 for (
size_t pi = 0; pi < ps; ++pi)
1036 const JSON::Node& prog = progs.GetArrayElement(pi);
1037 ProgramPtr program(
new Program());
1039 JSON::BindObject(prog, program.get(), bindprog);
1040 program->channel = channel;
1041 pmap->insert(std::make_pair(program->startTime, program));
1045 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
1048 while (count == req_count);
1053 ProgramMapPtr WSAPI::GetProgramList2_2(uint32_t chanid, time_t starttime, time_t endtime)
1055 ProgramMapPtr ret(
new ProgramMap);
1057 uint32_t req_index = 0, req_count = FETCHSIZE_L, count = 0, total = 0;
1058 unsigned proto = (unsigned)m_version.protocol;
1066 WSRequest req = WSRequest(m_server, m_port);
1067 req.RequestAccept(CT_JSON);
1068 req.RequestService(
"/Guide/GetProgramList");
1073 uint32_to_string(req_index, buf);
1074 req.SetContentParam(
"StartIndex", buf);
1075 uint32_to_string(req_count, buf);
1076 req.SetContentParam(
"Count", buf);
1077 uint32_to_string(chanid, buf);
1078 req.SetContentParam(
"ChanId", buf);
1079 time_to_iso8601utc(starttime, buf);
1080 req.SetContentParam(
"StartTime", buf);
1081 time_to_iso8601utc(endtime, buf);
1082 req.SetContentParam(
"EndTime", buf);
1083 req.SetContentParam(
"Details",
"true");
1085 DBG(DBG_DEBUG,
"%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
1086 WSResponse resp(req);
1087 if (!resp.IsSuccessful())
1089 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1092 const JSON::Document json(resp);
1093 const JSON::Node& root = json.GetRoot();
1094 if (!json.IsValid() || !root.IsObject())
1096 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1099 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1102 const JSON::Node& plist = root.GetObjectValue(
"ProgramList");
1104 JSON::BindObject(plist, &list, bindlist);
1106 if (list.protoVer != proto)
1108 InvalidateService();
1113 const JSON::Node& progs = plist.GetObjectValue(
"Programs");
1115 size_t ps = progs.Size();
1116 for (
size_t pi = 0; pi < ps; ++pi)
1119 const JSON::Node& prog = progs.GetArrayElement(pi);
1120 ProgramPtr program(
new Program());
1122 JSON::BindObject(prog, program.get(), bindprog);
1124 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
1125 JSON::BindObject(chan, &(program->channel), bindchan);
1126 ret->insert(std::make_pair(program->startTime, program));
1129 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
1132 while (count == req_count);
1141 ProgramListPtr WSAPI::GetRecordedList1_5(
unsigned n,
bool descending)
1143 ProgramListPtr ret(
new ProgramList);
1145 uint32_t req_index = 0, req_count = FETCHSIZE, count = 0, total = 0;
1146 unsigned proto = (unsigned)m_version.protocol;
1156 WSRequest req = WSRequest(m_server, m_port);
1157 req.RequestAccept(CT_JSON);
1158 req.RequestService(
"/Dvr/GetRecordedList");
1163 if (n && req_count > (n - total))
1164 req_count = (n - total);
1167 uint32_to_string(req_index, buf);
1168 req.SetContentParam(
"StartIndex", buf);
1169 uint32_to_string(req_count, buf);
1170 req.SetContentParam(
"Count", buf);
1171 req.SetContentParam(
"Descending", BOOLSTR(descending));
1173 DBG(DBG_DEBUG,
"%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
1174 WSResponse resp(req);
1175 if (!resp.IsSuccessful())
1177 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1180 const JSON::Document json(resp);
1181 const JSON::Node& root = json.GetRoot();
1182 if (!json.IsValid() || !root.IsObject())
1184 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1187 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1190 const JSON::Node& plist = root.GetObjectValue(
"ProgramList");
1192 JSON::BindObject(plist, &list, bindlist);
1194 if (list.protoVer != proto)
1196 InvalidateService();
1201 const JSON::Node& progs = plist.GetObjectValue(
"Programs");
1203 size_t ps = progs.Size();
1204 for (
size_t pi = 0; pi < ps; ++pi)
1207 const JSON::Node& prog = progs.GetArrayElement(pi);
1208 ProgramPtr program(
new Program());
1210 JSON::BindObject(prog, program.get(), bindprog);
1212 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
1213 JSON::BindObject(chan, &(program->channel), bindchan);
1215 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
1216 JSON::BindObject(reco, &(program->recording), bindreco);
1218 const JSON::Node& arts = prog.GetObjectValue(
"Artwork").GetObjectValue(
"ArtworkInfos");
1219 size_t as = arts.Size();
1220 for (
size_t pa = 0; pa < as; ++pa)
1222 const JSON::Node& artw = arts.GetArrayElement(pa);
1224 JSON::BindObject(artw, &artwork, bindartw);
1225 program->artwork.push_back(artwork);
1227 ret->push_back(program);
1230 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
1233 while (count == req_count && (!n || n > total));
1238 ProgramPtr WSAPI::GetRecorded1_5(uint32_t chanid, time_t recstartts)
1242 unsigned proto = (unsigned)m_version.protocol;
1250 WSRequest req = WSRequest(m_server, m_port);
1251 req.RequestAccept(CT_JSON);
1252 req.RequestService(
"/Dvr/GetRecorded");
1253 uint32_to_string(chanid, buf);
1254 req.SetContentParam(
"ChanId", buf);
1255 time_to_iso8601utc(recstartts, buf);
1256 req.SetContentParam(
"StartTime", buf);
1257 WSResponse resp(req);
1258 if (!resp.IsSuccessful())
1260 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1263 const JSON::Document json(resp);
1264 const JSON::Node& root = json.GetRoot();
1265 if (!json.IsValid() || !root.IsObject())
1267 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1270 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1272 const JSON::Node& prog = root.GetObjectValue(
"Program");
1273 ProgramPtr program(
new Program());
1275 JSON::BindObject(prog, program.get(), bindprog);
1277 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
1278 JSON::BindObject(chan, &(program->channel), bindchan);
1280 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
1281 JSON::BindObject(reco, &(program->recording), bindreco);
1283 const JSON::Node& arts = prog.GetObjectValue(
"Artwork").GetObjectValue(
"ArtworkInfos");
1284 size_t as = arts.Size();
1285 for (
size_t pa = 0; pa < as; ++pa)
1287 const JSON::Node& artw = arts.GetArrayElement(pa);
1289 JSON::BindObject(artw, &artwork, bindartw);
1290 program->artwork.push_back(artwork);
1293 if (program->recording.startTs != INVALID_TIME)
1298 ProgramPtr WSAPI::GetRecorded6_0(uint32_t recordedid)
1302 unsigned proto = (unsigned)m_version.protocol;
1310 WSRequest req = WSRequest(m_server, m_port);
1311 req.RequestAccept(CT_JSON);
1312 req.RequestService(
"/Dvr/GetRecorded");
1313 uint32_to_string(recordedid, buf);
1314 req.SetContentParam(
"RecordedId", buf);
1315 WSResponse resp(req);
1316 if (!resp.IsSuccessful())
1318 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1321 const JSON::Document json(resp);
1322 const JSON::Node& root = json.GetRoot();
1323 if (!json.IsValid() || !root.IsObject())
1325 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1328 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1330 const JSON::Node& prog = root.GetObjectValue(
"Program");
1331 ProgramPtr program(
new Program());
1333 JSON::BindObject(prog, program.get(), bindprog);
1335 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
1336 JSON::BindObject(chan, &(program->channel), bindchan);
1338 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
1339 JSON::BindObject(reco, &(program->recording), bindreco);
1341 const JSON::Node& arts = prog.GetObjectValue(
"Artwork").GetObjectValue(
"ArtworkInfos");
1342 size_t as = arts.Size();
1343 for (
size_t pa = 0; pa < as; ++pa)
1345 const JSON::Node& artw = arts.GetArrayElement(pa);
1347 JSON::BindObject(artw, &artwork, bindartw);
1348 program->artwork.push_back(artwork);
1351 if (program->recording.startTs != INVALID_TIME)
1356 bool WSAPI::DeleteRecording2_1(uint32_t chanid, time_t recstartts,
bool forceDelete,
bool allowRerecord)
1361 WSRequest req = WSRequest(m_server, m_port);
1362 req.RequestAccept(CT_JSON);
1363 req.RequestService(
"/Dvr/DeleteRecording", HRM_POST);
1364 uint32_to_string(chanid, buf);
1365 req.SetContentParam(
"ChanId", buf);
1366 time_to_iso8601utc(recstartts, buf);
1367 req.SetContentParam(
"StartTime", buf);
1368 req.SetContentParam(
"ForceDelete", BOOLSTR(forceDelete));
1369 req.SetContentParam(
"AllowRerecord", BOOLSTR(allowRerecord));
1370 WSResponse resp(req);
1371 if (!resp.IsSuccessful())
1373 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1376 const JSON::Document json(resp);
1377 const JSON::Node& root = json.GetRoot();
1378 if (!json.IsValid() || !root.IsObject())
1380 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1383 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1385 const JSON::Node& field = root.GetObjectValue(
"bool");
1386 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
1391 bool WSAPI::DeleteRecording6_0(uint32_t recordedid,
bool forceDelete,
bool allowRerecord)
1396 WSRequest req = WSRequest(m_server, m_port);
1397 req.RequestAccept(CT_JSON);
1398 req.RequestService(
"/Dvr/DeleteRecording", HRM_POST);
1399 uint32_to_string(recordedid, buf);
1400 req.SetContentParam(
"RecordedId", buf);
1401 req.SetContentParam(
"ForceDelete", BOOLSTR(forceDelete));
1402 req.SetContentParam(
"AllowRerecord", BOOLSTR(allowRerecord));
1403 WSResponse resp(req);
1404 if (!resp.IsSuccessful())
1406 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1409 const JSON::Document json(resp);
1410 const JSON::Node& root = json.GetRoot();
1411 if (!json.IsValid() || !root.IsObject())
1413 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1416 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1418 const JSON::Node& field = root.GetObjectValue(
"bool");
1419 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
1424 bool WSAPI::UnDeleteRecording2_1(uint32_t chanid, time_t recstartts)
1429 WSRequest req = WSRequest(m_server, m_port);
1430 req.RequestAccept(CT_JSON);
1431 req.RequestService(
"/Dvr/UnDeleteRecording", HRM_POST);
1432 uint32_to_string(chanid, buf);
1433 req.SetContentParam(
"ChanId", buf);
1434 time_to_iso8601utc(recstartts, buf);
1435 req.SetContentParam(
"StartTime", buf);
1436 WSResponse resp(req);
1437 if (!resp.IsSuccessful())
1439 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1442 const JSON::Document json(resp);
1443 const JSON::Node& root = json.GetRoot();
1444 if (!json.IsValid() || !root.IsObject())
1446 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1449 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1451 const JSON::Node& field = root.GetObjectValue(
"bool");
1452 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
1457 bool WSAPI::UnDeleteRecording6_0(uint32_t recordedid)
1462 WSRequest req = WSRequest(m_server, m_port);
1463 req.RequestAccept(CT_JSON);
1464 req.RequestService(
"/Dvr/UnDeleteRecording", HRM_POST);
1465 uint32_to_string(recordedid, buf);
1466 req.SetContentParam(
"RecordedId", buf);
1467 WSResponse resp(req);
1468 if (!resp.IsSuccessful())
1470 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1473 const JSON::Document json(resp);
1474 const JSON::Node& root = json.GetRoot();
1475 if (!json.IsValid() || !root.IsObject())
1477 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1480 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1482 const JSON::Node& field = root.GetObjectValue(
"bool");
1483 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
1488 bool WSAPI::UpdateRecordedWatchedStatus4_5(uint32_t chanid, time_t recstartts,
bool watched)
1493 WSRequest req = WSRequest(m_server, m_port);
1494 req.RequestAccept(CT_JSON);
1495 req.RequestService(
"/Dvr/UpdateRecordedWatchedStatus", HRM_POST);
1496 uint32_to_string(chanid, buf);
1497 req.SetContentParam(
"ChanId", buf);
1498 time_to_iso8601utc(recstartts, buf);
1499 req.SetContentParam(
"StartTime", buf);
1500 req.SetContentParam(
"Watched", BOOLSTR(watched));
1501 WSResponse resp(req);
1502 if (!resp.IsSuccessful())
1504 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1507 const JSON::Document json(resp);
1508 const JSON::Node& root = json.GetRoot();
1509 if (!json.IsValid() || !root.IsObject())
1511 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1514 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1516 const JSON::Node& field = root.GetObjectValue(
"bool");
1517 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
1522 bool WSAPI::UpdateRecordedWatchedStatus6_0(uint32_t recordedid,
bool watched)
1527 WSRequest req = WSRequest(m_server, m_port);
1528 req.RequestAccept(CT_JSON);
1529 req.RequestService(
"/Dvr/UpdateRecordedWatchedStatus", HRM_POST);
1530 uint32_to_string(recordedid, buf);
1531 req.SetContentParam(
"RecordedId", buf);
1532 req.SetContentParam(
"Watched", BOOLSTR(watched));
1533 WSResponse resp(req);
1534 if (!resp.IsSuccessful())
1536 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1539 const JSON::Document json(resp);
1540 const JSON::Node& root = json.GetRoot();
1541 if (!json.IsValid() || !root.IsObject())
1543 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1546 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1548 const JSON::Node& field = root.GetObjectValue(
"bool");
1549 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
1554 MarkListPtr WSAPI::GetRecordedCommBreak6_1(uint32_t recordedid,
int unit)
1557 MarkListPtr ret(
new MarkList);
1558 unsigned proto = (unsigned)m_version.protocol;
1564 WSRequest req = WSRequest(m_server, m_port);
1565 req.RequestAccept(CT_JSON);
1566 req.RequestService(
"/Dvr/GetRecordedCommBreak");
1567 uint32_to_string(recordedid, buf);
1568 req.SetContentParam(
"RecordedId", buf);
1570 req.SetContentParam(
"OffsetType",
"Position");
1572 req.SetContentParam(
"OffsetType",
"Duration");
1573 WSResponse resp(req);
1574 if (!resp.IsSuccessful())
1576 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1579 const JSON::Document json(resp);
1580 const JSON::Node& root = json.GetRoot();
1581 if (!json.IsValid() || !root.IsObject())
1583 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1586 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1589 const JSON::Node& slist = root.GetObjectValue(
"CutList");
1591 const JSON::Node& vcuts = slist.GetObjectValue(
"Cuttings");
1593 size_t vs = vcuts.Size();
1594 for (
size_t vi = 0; vi < vs; ++vi)
1596 const JSON::Node& vcut = vcuts.GetArrayElement(vi);
1597 MarkPtr mark(
new Mark());
1599 JSON::BindObject(vcut, mark.get(), bindcut);
1600 ret->push_back(mark);
1605 MarkListPtr WSAPI::GetRecordedCutList6_1(uint32_t recordedid,
int unit)
1608 MarkListPtr ret(
new MarkList);
1609 unsigned proto = (unsigned)m_version.protocol;
1615 WSRequest req = WSRequest(m_server, m_port);
1616 req.RequestAccept(CT_JSON);
1617 req.RequestService(
"/Dvr/GetRecordedCutList");
1618 uint32_to_string(recordedid, buf);
1619 req.SetContentParam(
"RecordedId", buf);
1621 req.SetContentParam(
"OffsetType",
"Position");
1623 req.SetContentParam(
"OffsetType",
"Duration");
1624 WSResponse resp(req);
1625 if (!resp.IsSuccessful())
1627 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1630 const JSON::Document json(resp);
1631 const JSON::Node& root = json.GetRoot();
1632 if (!json.IsValid() || !root.IsObject())
1634 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1637 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1640 const JSON::Node& slist = root.GetObjectValue(
"CutList");
1642 const JSON::Node& vcuts = slist.GetObjectValue(
"Cuttings");
1644 size_t vs = vcuts.Size();
1645 for (
size_t vi = 0; vi < vs; ++vi)
1647 const JSON::Node& vcut = vcuts.GetArrayElement(vi);
1648 MarkPtr mark(
new Mark());
1650 JSON::BindObject(vcut, mark.get(), bindcut);
1651 ret->push_back(mark);
1656 bool WSAPI::SetSavedBookmark6_2(uint32_t recordedid,
int unit, int64_t value)
1661 WSRequest req = WSRequest(m_server, m_port);
1662 req.RequestAccept(CT_JSON);
1663 req.RequestService(
"/Dvr/SetSavedBookmark", HRM_POST);
1664 uint32_to_string(recordedid, buf);
1665 req.SetContentParam(
"RecordedId", buf);
1667 req.SetContentParam(
"OffsetType",
"Duration");
1669 req.SetContentParam(
"OffsetType",
"Position");
1670 int64_to_string(value, buf);
1671 req.SetContentParam(
"Offset", buf);
1672 WSResponse resp(req);
1673 if (!resp.IsSuccessful())
1675 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1678 const JSON::Document json(resp);
1679 const JSON::Node& root = json.GetRoot();
1680 if (!json.IsValid() || !root.IsObject())
1682 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1685 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1687 const JSON::Node& field = root.GetObjectValue(
"bool");
1688 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
1693 int64_t WSAPI::GetSavedBookmark6_2(uint32_t recordedid,
int unit)
1698 WSRequest req = WSRequest(m_server, m_port);
1699 req.RequestAccept(CT_JSON);
1700 req.RequestService(
"/Dvr/GetSavedBookmark", HRM_POST);
1701 uint32_to_string(recordedid, buf);
1702 req.SetContentParam(
"RecordedId", buf);
1704 req.SetContentParam(
"OffsetType",
"Duration");
1706 req.SetContentParam(
"OffsetType",
"Position");
1707 WSResponse resp(req);
1708 if (!resp.IsSuccessful())
1710 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1713 const JSON::Document json(resp);
1714 const JSON::Node& root = json.GetRoot();
1715 if (!json.IsValid() || !root.IsObject())
1717 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1720 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1723 const JSON::Node& field = root.GetObjectValue(
"long");
1724 if (!field.IsString() || string_to_int64(field.GetStringValue().c_str(), &value))
1729 static void ProcessRecordIN(
unsigned proto,
RecordSchedule& record)
1732 record.type_t = RuleTypeFromString(proto, record.type);
1733 record.searchType_t = SearchTypeFromString(proto, record.searchType);
1734 record.dupMethod_t = DupMethodFromString(proto, record.dupMethod);
1735 record.dupIn_t = DupInFromString(proto, record.dupIn);
1738 RecordScheduleListPtr WSAPI::GetRecordScheduleList1_5()
1740 RecordScheduleListPtr ret(
new RecordScheduleList);
1742 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
1743 unsigned proto = (unsigned)m_version.protocol;
1750 WSRequest req = WSRequest(m_server, m_port);
1751 req.RequestAccept(CT_JSON);
1752 req.RequestService(
"/Dvr/GetRecordScheduleList");
1757 int32_to_string(req_index, buf);
1758 req.SetContentParam(
"StartIndex", buf);
1759 int32_to_string(req_count, buf);
1760 req.SetContentParam(
"Count", buf);
1762 DBG(DBG_DEBUG,
"%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
1763 WSResponse resp(req);
1764 if (!resp.IsSuccessful())
1766 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1769 const JSON::Document json(resp);
1770 const JSON::Node& root = json.GetRoot();
1771 if (!json.IsValid() || !root.IsObject())
1773 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1776 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1779 const JSON::Node& rlist = root.GetObjectValue(
"RecRuleList");
1781 JSON::BindObject(rlist, &list, bindlist);
1783 if (list.protoVer != proto)
1785 InvalidateService();
1790 const JSON::Node& recs = rlist.GetObjectValue(
"RecRules");
1792 size_t rs = recs.Size();
1793 for (
size_t ri = 0; ri < rs; ++ri)
1796 const JSON::Node& rec = recs.GetArrayElement(ri);
1799 JSON::BindObject(rec, record.get(), bindrec);
1800 ProcessRecordIN(proto, *record);
1801 ret->push_back(record);
1803 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
1806 while (count == req_count);
1811 RecordSchedulePtr WSAPI::GetRecordSchedule1_5(uint32_t recordid)
1813 RecordSchedulePtr ret;
1815 unsigned proto = (unsigned)m_version.protocol;
1820 WSRequest req = WSRequest(m_server, m_port);
1821 req.RequestAccept(CT_JSON);
1822 req.RequestService(
"/Dvr/GetRecordSchedule");
1823 uint32_to_string(recordid, buf);
1824 req.SetContentParam(
"RecordId", buf);
1825 WSResponse resp(req);
1826 if (!resp.IsSuccessful())
1828 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1831 const JSON::Document json(resp);
1832 const JSON::Node& root = json.GetRoot();
1833 if (!json.IsValid() || !root.IsObject())
1835 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1838 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1840 const JSON::Node& rec = root.GetObjectValue(
"RecRule");
1843 JSON::BindObject(rec, record.get(), bindrec);
1845 if (record->recordId > 0)
1847 ProcessRecordIN(proto, *record);
1853 static void ProcessRecordOUT(
unsigned proto,
RecordSchedule& record)
1857 time_t st = record.startTime;
1858 localtime_r(&st, &stm);
1860 sprintf(buf,
"%.2d:%.2d:%.2d", stm.tm_hour, stm.tm_min, stm.tm_sec);
1861 record.findTime = buf;
1862 record.findDay = (stm.tm_wday + 1) % 7;
1864 record.type = RuleTypeToString(proto, record.type_t);
1865 record.searchType = SearchTypeToString(proto, record.searchType_t);
1866 record.dupMethod = DupMethodToString(proto, record.dupMethod_t);
1867 record.dupIn = DupInToString(proto, record.dupIn_t);
1874 unsigned proto = (unsigned)m_version.protocol;
1876 ProcessRecordOUT(proto, record);
1879 WSRequest req = WSRequest(m_server, m_port);
1880 req.RequestAccept(CT_JSON);
1881 req.RequestService(
"/Dvr/AddRecordSchedule", HRM_POST);
1883 req.SetContentParam(
"Title", record.title);
1884 req.SetContentParam(
"Subtitle", record.subtitle);
1885 req.SetContentParam(
"Description", record.description);
1886 req.SetContentParam(
"Category", record.category);
1887 time_to_iso8601utc(record.startTime, buf);
1888 req.SetContentParam(
"StartTime", buf);
1889 time_to_iso8601utc(record.endTime, buf);
1890 req.SetContentParam(
"EndTime", buf);
1891 req.SetContentParam(
"SeriesId", record.seriesId);
1892 req.SetContentParam(
"ProgramId", record.programId);
1893 uint32_to_string(record.chanId, buf);
1894 req.SetContentParam(
"ChanId", buf);
1895 uint32_to_string(record.parentId, buf);
1896 req.SetContentParam(
"ParentId", buf);
1897 req.SetContentParam(
"Inactive", BOOLSTR(record.inactive));
1898 uint16_to_string(record.season, buf);
1899 req.SetContentParam(
"Season", buf);
1900 uint16_to_string(record.episode, buf);
1901 req.SetContentParam(
"Episode", buf);
1902 req.SetContentParam(
"Inetref", record.inetref);
1903 req.SetContentParam(
"Type", record.type);
1904 req.SetContentParam(
"SearchType", record.searchType);
1905 int8_to_string(record.recPriority, buf);
1906 req.SetContentParam(
"RecPriority", buf);
1907 uint32_to_string(record.preferredInput, buf);
1908 req.SetContentParam(
"PreferredInput", buf);
1909 uint8_to_string(record.startOffset, buf);
1910 req.SetContentParam(
"StartOffset", buf);
1911 uint8_to_string(record.endOffset, buf);
1912 req.SetContentParam(
"EndOffset", buf);
1913 req.SetContentParam(
"DupMethod", record.dupMethod);
1914 req.SetContentParam(
"DupIn", record.dupIn);
1915 uint32_to_string(record.filter, buf);
1916 req.SetContentParam(
"Filter", buf);
1917 req.SetContentParam(
"RecProfile", record.recProfile);
1918 req.SetContentParam(
"RecGroup", record.recGroup);
1919 req.SetContentParam(
"StorageGroup", record.storageGroup);
1920 req.SetContentParam(
"PlayGroup", record.playGroup);
1921 req.SetContentParam(
"AutoExpire", BOOLSTR(record.autoExpire));
1922 uint32_to_string(record.maxEpisodes, buf);
1923 req.SetContentParam(
"MaxEpisodes", buf);
1924 req.SetContentParam(
"MaxNewest", BOOLSTR(record.maxNewest));
1925 req.SetContentParam(
"AutoCommflag", BOOLSTR(record.autoCommflag));
1926 req.SetContentParam(
"AutoTranscode", BOOLSTR(record.autoTranscode));
1927 req.SetContentParam(
"AutoMetaLookup", BOOLSTR(record.autoMetaLookup));
1928 req.SetContentParam(
"AutoUserJob1", BOOLSTR(record.autoUserJob1));
1929 req.SetContentParam(
"AutoUserJob2", BOOLSTR(record.autoUserJob2));
1930 req.SetContentParam(
"AutoUserJob3", BOOLSTR(record.autoUserJob3));
1931 req.SetContentParam(
"AutoUserJob4", BOOLSTR(record.autoUserJob4));
1932 uint32_to_string(record.transcoder, buf);
1933 req.SetContentParam(
"Transcoder", buf);
1935 WSResponse resp(req);
1936 if (!resp.IsSuccessful())
1938 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
1941 const JSON::Document json(resp);
1942 const JSON::Node& root = json.GetRoot();
1943 if (!json.IsValid() || !root.IsObject())
1945 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
1948 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
1950 const JSON::Node& field = root.GetObjectValue(
"int");
1951 if (!field.IsString() || string_to_uint32(field.GetStringValue().c_str(), &recordid))
1953 record.recordId = recordid;
1961 unsigned proto = (unsigned)m_version.protocol;
1963 ProcessRecordOUT(proto, record);
1966 WSRequest req = WSRequest(m_server, m_port);
1967 req.RequestAccept(CT_JSON);
1968 req.RequestService(
"/Dvr/AddRecordSchedule", HRM_POST);
1970 req.SetContentParam(
"Title", record.title);
1971 req.SetContentParam(
"Subtitle", record.subtitle);
1972 req.SetContentParam(
"Description", record.description);
1973 req.SetContentParam(
"Category", record.category);
1974 time_to_iso8601utc(record.startTime, buf);
1975 req.SetContentParam(
"StartTime", buf);
1976 time_to_iso8601utc(record.endTime, buf);
1977 req.SetContentParam(
"EndTime", buf);
1978 req.SetContentParam(
"SeriesId", record.seriesId);
1979 req.SetContentParam(
"ProgramId", record.programId);
1980 uint32_to_string(record.chanId, buf);
1981 req.SetContentParam(
"ChanId", buf);
1982 req.SetContentParam(
"Station", record.callSign);
1983 int8_to_string(record.findDay, buf);
1984 req.SetContentParam(
"FindDay", buf);
1985 req.SetContentParam(
"FindTime", record.findTime);
1986 uint32_to_string(record.parentId, buf);
1987 req.SetContentParam(
"ParentId", buf);
1988 req.SetContentParam(
"Inactive", BOOLSTR(record.inactive));
1989 uint16_to_string(record.season, buf);
1990 req.SetContentParam(
"Season", buf);
1991 uint16_to_string(record.episode, buf);
1992 req.SetContentParam(
"Episode", buf);
1993 req.SetContentParam(
"Inetref", record.inetref);
1994 req.SetContentParam(
"Type", record.type);
1995 req.SetContentParam(
"SearchType", record.searchType);
1996 int8_to_string(record.recPriority, buf);
1997 req.SetContentParam(
"RecPriority", buf);
1998 uint32_to_string(record.preferredInput, buf);
1999 req.SetContentParam(
"PreferredInput", buf);
2000 uint8_to_string(record.startOffset, buf);
2001 req.SetContentParam(
"StartOffset", buf);
2002 uint8_to_string(record.endOffset, buf);
2003 req.SetContentParam(
"EndOffset", buf);
2004 req.SetContentParam(
"DupMethod", record.dupMethod);
2005 req.SetContentParam(
"DupIn", record.dupIn);
2006 uint32_to_string(record.filter, buf);
2007 req.SetContentParam(
"Filter", buf);
2008 req.SetContentParam(
"RecProfile", record.recProfile);
2009 req.SetContentParam(
"RecGroup", record.recGroup);
2010 req.SetContentParam(
"StorageGroup", record.storageGroup);
2011 req.SetContentParam(
"PlayGroup", record.playGroup);
2012 req.SetContentParam(
"AutoExpire", BOOLSTR(record.autoExpire));
2013 uint32_to_string(record.maxEpisodes, buf);
2014 req.SetContentParam(
"MaxEpisodes", buf);
2015 req.SetContentParam(
"MaxNewest", BOOLSTR(record.maxNewest));
2016 req.SetContentParam(
"AutoCommflag", BOOLSTR(record.autoCommflag));
2017 req.SetContentParam(
"AutoTranscode", BOOLSTR(record.autoTranscode));
2018 req.SetContentParam(
"AutoMetaLookup", BOOLSTR(record.autoMetaLookup));
2019 req.SetContentParam(
"AutoUserJob1", BOOLSTR(record.autoUserJob1));
2020 req.SetContentParam(
"AutoUserJob2", BOOLSTR(record.autoUserJob2));
2021 req.SetContentParam(
"AutoUserJob3", BOOLSTR(record.autoUserJob3));
2022 req.SetContentParam(
"AutoUserJob4", BOOLSTR(record.autoUserJob4));
2023 uint32_to_string(record.transcoder, buf);
2024 req.SetContentParam(
"Transcoder", buf);
2026 WSResponse resp(req);
2027 if (!resp.IsSuccessful())
2029 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2032 const JSON::Document json(resp);
2033 const JSON::Node& root = json.GetRoot();
2034 if (!json.IsValid() || !root.IsObject())
2036 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2039 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2041 const JSON::Node& field = root.GetObjectValue(
"uint");
2042 if (!field.IsString() || string_to_uint32(field.GetStringValue().c_str(), &recordid))
2044 record.recordId = recordid;
2051 unsigned proto = (unsigned)m_version.protocol;
2053 ProcessRecordOUT(proto, record);
2056 WSRequest req = WSRequest(m_server, m_port);
2057 req.RequestAccept(CT_JSON);
2058 req.RequestService(
"/Dvr/UpdateRecordSchedule", HRM_POST);
2060 uint32_to_string(record.recordId, buf);
2061 req.SetContentParam(
"RecordId", buf);
2062 req.SetContentParam(
"Title", record.title);
2063 req.SetContentParam(
"Subtitle", record.subtitle);
2064 req.SetContentParam(
"Description", record.description);
2065 req.SetContentParam(
"Category", record.category);
2066 time_to_iso8601utc(record.startTime, buf);
2067 req.SetContentParam(
"StartTime", buf);
2068 time_to_iso8601utc(record.endTime, buf);
2069 req.SetContentParam(
"EndTime", buf);
2070 req.SetContentParam(
"SeriesId", record.seriesId);
2071 req.SetContentParam(
"ProgramId", record.programId);
2072 uint32_to_string(record.chanId, buf);
2073 req.SetContentParam(
"ChanId", buf);
2074 req.SetContentParam(
"Station", record.callSign);
2075 int8_to_string(record.findDay, buf);
2076 req.SetContentParam(
"FindDay", buf);
2077 req.SetContentParam(
"FindTime", record.findTime);
2078 uint32_to_string(record.parentId, buf);
2079 req.SetContentParam(
"ParentId", buf);
2080 req.SetContentParam(
"Inactive", BOOLSTR(record.inactive));
2081 uint16_to_string(record.season, buf);
2082 req.SetContentParam(
"Season", buf);
2083 uint16_to_string(record.episode, buf);
2084 req.SetContentParam(
"Episode", buf);
2085 req.SetContentParam(
"Inetref", record.inetref);
2086 req.SetContentParam(
"Type", record.type);
2087 req.SetContentParam(
"SearchType", record.searchType);
2088 int8_to_string(record.recPriority, buf);
2089 req.SetContentParam(
"RecPriority", buf);
2090 uint32_to_string(record.preferredInput, buf);
2091 req.SetContentParam(
"PreferredInput", buf);
2092 uint8_to_string(record.startOffset, buf);
2093 req.SetContentParam(
"StartOffset", buf);
2094 uint8_to_string(record.endOffset, buf);
2095 req.SetContentParam(
"EndOffset", buf);
2096 req.SetContentParam(
"DupMethod", record.dupMethod);
2097 req.SetContentParam(
"DupIn", record.dupIn);
2098 uint32_to_string(record.filter, buf);
2099 req.SetContentParam(
"Filter", buf);
2100 req.SetContentParam(
"RecProfile", record.recProfile);
2101 req.SetContentParam(
"RecGroup", record.recGroup);
2102 req.SetContentParam(
"StorageGroup", record.storageGroup);
2103 req.SetContentParam(
"PlayGroup", record.playGroup);
2104 req.SetContentParam(
"AutoExpire", BOOLSTR(record.autoExpire));
2105 uint32_to_string(record.maxEpisodes, buf);
2106 req.SetContentParam(
"MaxEpisodes", buf);
2107 req.SetContentParam(
"MaxNewest", BOOLSTR(record.maxNewest));
2108 req.SetContentParam(
"AutoCommflag", BOOLSTR(record.autoCommflag));
2109 req.SetContentParam(
"AutoTranscode", BOOLSTR(record.autoTranscode));
2110 req.SetContentParam(
"AutoMetaLookup", BOOLSTR(record.autoMetaLookup));
2111 req.SetContentParam(
"AutoUserJob1", BOOLSTR(record.autoUserJob1));
2112 req.SetContentParam(
"AutoUserJob2", BOOLSTR(record.autoUserJob2));
2113 req.SetContentParam(
"AutoUserJob3", BOOLSTR(record.autoUserJob3));
2114 req.SetContentParam(
"AutoUserJob4", BOOLSTR(record.autoUserJob4));
2115 uint32_to_string(record.transcoder, buf);
2116 req.SetContentParam(
"Transcoder", buf);
2118 WSResponse resp(req);
2119 if (!resp.IsSuccessful())
2121 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2124 const JSON::Document json(resp);
2125 const JSON::Node& root = json.GetRoot();
2126 if (!json.IsValid() || !root.IsObject())
2128 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2131 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2133 const JSON::Node& field = root.GetObjectValue(
"bool");
2134 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
2139 bool WSAPI::DisableRecordSchedule1_5(uint32_t recordid)
2144 WSRequest req = WSRequest(m_server, m_port);
2145 req.RequestAccept(CT_JSON);
2146 req.RequestService(
"/Dvr/DisableRecordSchedule", HRM_POST);
2148 uint32_to_string(recordid, buf);
2149 req.SetContentParam(
"RecordId", buf);
2151 WSResponse resp(req);
2152 if (!resp.IsSuccessful())
2154 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2157 const JSON::Document json(resp);
2158 const JSON::Node& root = json.GetRoot();
2159 if (!json.IsValid() || !root.IsObject())
2161 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2164 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2166 const JSON::Node& field = root.GetObjectValue(
"bool");
2167 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
2172 bool WSAPI::EnableRecordSchedule1_5(uint32_t recordid)
2177 WSRequest req = WSRequest(m_server, m_port);
2178 req.RequestAccept(CT_JSON);
2179 req.RequestService(
"/Dvr/EnableRecordSchedule", HRM_POST);
2181 uint32_to_string(recordid, buf);
2182 req.SetContentParam(
"RecordId", buf);
2184 WSResponse resp(req);
2185 if (!resp.IsSuccessful())
2187 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2190 const JSON::Document json(resp);
2191 const JSON::Node& root = json.GetRoot();
2192 if (!json.IsValid() || !root.IsObject())
2194 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2197 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2199 const JSON::Node& field = root.GetObjectValue(
"bool");
2200 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
2205 bool WSAPI::RemoveRecordSchedule1_5(uint32_t recordid)
2210 WSRequest req = WSRequest(m_server, m_port);
2211 req.RequestAccept(CT_JSON);
2212 req.RequestService(
"/Dvr/RemoveRecordSchedule", HRM_POST);
2214 uint32_to_string(recordid, buf);
2215 req.SetContentParam(
"RecordId", buf);
2217 WSResponse resp(req);
2218 if (!resp.IsSuccessful())
2220 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2223 const JSON::Document json(resp);
2224 const JSON::Node& root = json.GetRoot();
2225 if (!json.IsValid() || !root.IsObject())
2227 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2230 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2232 const JSON::Node& field = root.GetObjectValue(
"bool");
2233 if (!field.IsString() || strcmp(field.GetStringValue().c_str(),
"true"))
2238 ProgramListPtr WSAPI::GetUpcomingList1_5()
2241 ProgramListPtr ret = GetUpcomingList2_2();
2243 ProgramListPtr recordings = GetRecordedList(20,
true);
2244 for (Myth::ProgramList::iterator it = recordings->begin(); it != recordings->end(); ++it)
2246 if ((*it)->recording.status == RS_RECORDING)
2247 ret->push_back(*it);
2252 ProgramListPtr WSAPI::GetUpcomingList2_2()
2254 ProgramListPtr ret(
new ProgramList);
2256 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
2257 unsigned proto = (unsigned)m_version.protocol;
2266 WSRequest req = WSRequest(m_server, m_port);
2267 req.RequestAccept(CT_JSON);
2268 req.RequestService(
"/Dvr/GetUpcomingList");
2273 int32_to_string(req_index, buf);
2274 req.SetContentParam(
"StartIndex", buf);
2275 int32_to_string(req_count, buf);
2276 req.SetContentParam(
"Count", buf);
2277 req.SetContentParam(
"ShowAll",
"true");
2279 DBG(DBG_DEBUG,
"%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
2280 WSResponse resp(req);
2281 if (!resp.IsSuccessful())
2283 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2286 const JSON::Document json(resp);
2287 const JSON::Node& root = json.GetRoot();
2288 if (!json.IsValid() || !root.IsObject())
2290 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2293 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2296 const JSON::Node& plist = root.GetObjectValue(
"ProgramList");
2298 JSON::BindObject(plist, &list, bindlist);
2300 if (list.protoVer != proto)
2302 InvalidateService();
2307 const JSON::Node& progs = plist.GetObjectValue(
"Programs");
2309 size_t ps = progs.Size();
2310 for (
size_t pi = 0; pi < ps; ++pi)
2313 const JSON::Node& prog = progs.GetArrayElement(pi);
2314 ProgramPtr program(
new Program());
2316 JSON::BindObject(prog, program.get(), bindprog);
2318 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
2319 JSON::BindObject(chan, &(program->channel), bindchan);
2321 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
2322 JSON::BindObject(reco, &(program->recording), bindreco);
2323 ret->push_back(program);
2325 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
2328 while (count == req_count);
2333 ProgramListPtr WSAPI::GetConflictList1_5()
2335 ProgramListPtr ret(
new ProgramList);
2337 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
2338 unsigned proto = (unsigned)m_version.protocol;
2347 WSRequest req = WSRequest(m_server, m_port);
2348 req.RequestAccept(CT_JSON);
2349 req.RequestService(
"/Dvr/GetConflictList");
2354 int32_to_string(req_index, buf);
2355 req.SetContentParam(
"StartIndex", buf);
2356 int32_to_string(req_count, buf);
2357 req.SetContentParam(
"Count", buf);
2359 DBG(DBG_DEBUG,
"%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
2360 WSResponse resp(req);
2361 if (!resp.IsSuccessful())
2363 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2366 const JSON::Document json(resp);
2367 const JSON::Node& root = json.GetRoot();
2368 if (!json.IsValid() || !root.IsObject())
2370 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2373 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2376 const JSON::Node& plist = root.GetObjectValue(
"ProgramList");
2378 JSON::BindObject(plist, &list, bindlist);
2380 if (list.protoVer != proto)
2382 InvalidateService();
2387 const JSON::Node& progs = plist.GetObjectValue(
"Programs");
2389 size_t ps = progs.Size();
2390 for (
size_t pi = 0; pi < ps; ++pi)
2393 const JSON::Node& prog = progs.GetArrayElement(pi);
2394 ProgramPtr program(
new Program());
2396 JSON::BindObject(prog, program.get(), bindprog);
2398 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
2399 JSON::BindObject(chan, &(program->channel), bindchan);
2401 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
2402 JSON::BindObject(reco, &(program->recording), bindreco);
2403 ret->push_back(program);
2405 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
2408 while (count == req_count);
2413 ProgramListPtr WSAPI::GetExpiringList1_5()
2415 ProgramListPtr ret(
new ProgramList);
2417 int32_t req_index = 0, req_count = FETCHSIZE, count = 0;
2418 unsigned proto = (unsigned)m_version.protocol;
2427 WSRequest req = WSRequest(m_server, m_port);
2428 req.RequestAccept(CT_JSON);
2429 req.RequestService(
"/Dvr/GetExpiringList");
2434 int32_to_string(req_index, buf);
2435 req.SetContentParam(
"StartIndex", buf);
2436 int32_to_string(req_count, buf);
2437 req.SetContentParam(
"Count", buf);
2439 DBG(DBG_DEBUG,
"%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count);
2440 WSResponse resp(req);
2441 if (!resp.IsSuccessful())
2443 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2446 const JSON::Document json(resp);
2447 const JSON::Node& root = json.GetRoot();
2448 if (!json.IsValid() || !root.IsObject())
2450 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2453 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2456 const JSON::Node& plist = root.GetObjectValue(
"ProgramList");
2458 JSON::BindObject(plist, &list, bindlist);
2460 if (list.protoVer != proto)
2462 InvalidateService();
2467 const JSON::Node& progs = plist.GetObjectValue(
"Programs");
2469 size_t ps = progs.Size();
2470 for (
size_t pi = 0; pi < ps; ++pi)
2473 const JSON::Node& prog = progs.GetArrayElement(pi);
2474 ProgramPtr program(
new Program());
2476 JSON::BindObject(prog, program.get(), bindprog);
2478 const JSON::Node& chan = prog.GetObjectValue(
"Channel");
2479 JSON::BindObject(chan, &(program->channel), bindchan);
2481 const JSON::Node& reco = prog.GetObjectValue(
"Recording");
2482 JSON::BindObject(reco, &(program->recording), bindreco);
2483 ret->push_back(program);
2485 DBG(DBG_DEBUG,
"%s: received count(%d)\n", __FUNCTION__, count);
2488 while (count == req_count);
2493 StringListPtr WSAPI::GetRecGroupList1_5()
2495 StringListPtr ret(
new StringList);
2498 WSRequest req = WSRequest(m_server, m_port);
2499 req.RequestAccept(CT_JSON);
2500 req.RequestService(
"/Dvr/GetRecGroupList");
2501 WSResponse resp(req);
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& list = root.GetObjectValue(
"StringList");
2520 size_t s = list.Size();
2521 for (
size_t i = 0; i < s; ++i)
2523 const JSON::Node& val = list.GetArrayElement(i);
2526 ret->push_back(val.GetStringValue());
2537 WSStreamPtr WSAPI::GetFile1_32(
const std::string& filename,
const std::string& sgname)
2542 WSRequest req = WSRequest(m_server, m_port);
2543 req.RequestService(
"/Content/GetFile");
2544 req.SetContentParam(
"StorageGroup", sgname);
2545 req.SetContentParam(
"FileName", filename);
2546 WSResponse *resp =
new WSResponse(req);
2548 if (resp->GetStatusCode() == 301 && !resp->Redirection().empty())
2550 URIParser uri(resp->Redirection());
2551 WSRequest rreq(ResolveHostName(uri.Host()), uri.Port());
2552 rreq.RequestService(std::string(
"/").append(uri.Path()));
2554 resp =
new WSResponse(rreq);
2556 if (!resp->IsSuccessful())
2558 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2566 WSStreamPtr WSAPI::GetChannelIcon1_32(uint32_t chanid,
unsigned width,
unsigned height)
2572 WSRequest req = WSRequest(m_server, m_port);
2573 req.RequestService(
"/Guide/GetChannelIcon");
2574 uint32_to_string(chanid, buf);
2575 req.SetContentParam(
"ChanId", buf);
2578 uint32_to_string(width, buf);
2579 req.SetContentParam(
"Width", buf);
2583 uint32_to_string(height, buf);
2584 req.SetContentParam(
"Height", buf);
2586 WSResponse *resp =
new WSResponse(req);
2588 if (resp->GetStatusCode() == 301 && !resp->Redirection().empty())
2590 URIParser uri(resp->Redirection());
2591 WSRequest rreq(ResolveHostName(uri.Host()), uri.Port());
2592 rreq.RequestService(std::string(
"/").append(uri.Path()));
2594 resp =
new WSResponse(rreq);
2596 if (!resp->IsSuccessful())
2598 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2606 std::string WSAPI::GetChannelIconUrl1_32(uint32_t chanid,
unsigned width,
unsigned height)
2611 uri.append(
"http://").append(m_server);
2614 uint32_to_string(m_port, buf);
2615 uri.append(
":").append(buf);
2617 uri.append(
"/Guide/GetChannelIcon");
2618 uint32_to_string(chanid, buf);
2619 uri.append(
"?ChanId=").append(buf);
2622 uint32_to_string(width, buf);
2623 uri.append(
"&Width=").append(buf);
2627 uint32_to_string(height, buf);
2628 uri.append(
"&Height=").append(buf);
2633 WSStreamPtr WSAPI::GetPreviewImage1_32(uint32_t chanid, time_t recstartts,
unsigned width,
unsigned height)
2639 WSRequest req = WSRequest(m_server, m_port);
2640 req.RequestService(
"/Content/GetPreviewImage");
2641 uint32_to_string(chanid, buf);
2642 req.SetContentParam(
"ChanId", buf);
2643 time_to_iso8601utc(recstartts, buf);
2644 req.SetContentParam(
"StartTime", buf);
2647 uint32_to_string(width, buf);
2648 req.SetContentParam(
"Width", buf);
2652 uint32_to_string(height, buf);
2653 req.SetContentParam(
"Height", buf);
2655 WSResponse *resp =
new WSResponse(req);
2657 if (resp->GetStatusCode() == 301 && !resp->Redirection().empty())
2659 URIParser uri(resp->Redirection());
2660 WSRequest rreq(ResolveHostName(uri.Host()), uri.Port());
2661 rreq.RequestService(std::string(
"/").append(uri.Path()));
2663 resp =
new WSResponse(rreq);
2665 if (!resp->IsSuccessful())
2667 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2675 std::string WSAPI::GetPreviewImageUrl1_32(uint32_t chanid, time_t recstartts,
unsigned width,
unsigned height)
2680 uri.append(
"http://").append(m_server);
2683 uint32_to_string(m_port, buf);
2684 uri.append(
":").append(buf);
2686 uri.append(
"/Content/GetPreviewImage");
2687 uint32_to_string(chanid, buf);
2688 uri.append(
"?ChanId=").append(buf);
2689 time_to_iso8601utc(recstartts, buf);
2690 uri.append(
"&StartTime=").append(encodeParam(buf));
2693 uint32_to_string(width, buf);
2694 uri.append(
"&Width=").append(buf);
2698 uint32_to_string(height, buf);
2699 uri.append(
"&Height=").append(buf);
2704 WSStreamPtr WSAPI::GetRecordingArtwork1_32(
const std::string& type,
const std::string& inetref, uint16_t season,
unsigned width,
unsigned height)
2710 WSRequest req = WSRequest(m_server, m_port);
2711 req.RequestService(
"/Content/GetRecordingArtwork");
2712 req.SetContentParam(
"Type", type.c_str());
2713 req.SetContentParam(
"Inetref", inetref.c_str());
2714 uint16_to_string(season, buf);
2715 req.SetContentParam(
"Season", buf);
2718 uint32_to_string(width, buf);
2719 req.SetContentParam(
"Width", buf);
2723 uint32_to_string(height, buf);
2724 req.SetContentParam(
"Height", buf);
2726 WSResponse *resp =
new WSResponse(req);
2728 if (resp->GetStatusCode() == 301 && !resp->Redirection().empty())
2730 URIParser uri(resp->Redirection());
2731 WSRequest rreq(ResolveHostName(uri.Host()), uri.Port());
2732 rreq.RequestService(std::string(
"/").append(uri.Path()));
2734 resp =
new WSResponse(rreq);
2736 if (!resp->IsSuccessful())
2738 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2746 std::string WSAPI::GetRecordingArtworkUrl1_32(
const std::string& type,
const std::string& inetref, uint16_t season,
unsigned width,
unsigned height)
2751 uri.append(
"http://").append(m_server);
2754 uint32_to_string(m_port, buf);
2755 uri.append(
":").append(buf);
2757 uri.append(
"/Content/GetRecordingArtwork");
2758 uri.append(
"?Type=").append(encodeParam(type));
2759 uri.append(
"&Inetref=").append(encodeParam(inetref));
2760 uint16_to_string(season, buf);
2761 uri.append(
"&Season=").append(buf);
2764 uint32_to_string(width, buf);
2765 uri.append(
"&Width=").append(buf);
2769 uint32_to_string(height, buf);
2770 uri.append(
"&Height=").append(buf);
2775 ArtworkListPtr WSAPI::GetRecordingArtworkList1_32(uint32_t chanid, time_t recstartts)
2777 ArtworkListPtr ret(
new ArtworkList);
2779 unsigned proto = (unsigned)m_version.protocol;
2784 WSRequest req = WSRequest(m_server, m_port);
2785 req.RequestAccept(CT_JSON);
2786 req.RequestService(
"/Content/GetRecordingArtworkList");
2787 uint32_to_string(chanid, buf);
2788 req.SetContentParam(
"ChanId", buf);
2789 time_to_iso8601utc(recstartts, buf);
2790 req.SetContentParam(
"StartTime", buf);
2791 WSResponse resp(req);
2792 if (!resp.IsSuccessful())
2794 DBG(DBG_ERROR,
"%s: invalid response\n", __FUNCTION__);
2797 const JSON::Document json(resp);
2798 const JSON::Node& root = json.GetRoot();
2799 if (!json.IsValid() || !root.IsObject())
2801 DBG(DBG_ERROR,
"%s: unexpected content\n", __FUNCTION__);
2804 DBG(DBG_DEBUG,
"%s: content parsed\n", __FUNCTION__);
2806 const JSON::Node& list = root.GetObjectValue(
"ArtworkInfoList");
2808 const JSON::Node& arts = list.GetObjectValue(
"ArtworkInfos");
2809 size_t as = arts.Size();
2810 for (
size_t pa = 0; pa < as; ++pa)
2812 const JSON::Node& artw = arts.GetArrayElement(pa);
2813 ArtworkPtr artwork(
new Artwork());
2814 JSON::BindObject(artw, artwork.get(), bindartw);
2815 ret->push_back(artwork);
2821 #include "private/urlencoder.h" 2823 static std::string encodeParam(
const std::string& str)
2825 return urlencode(str);
const bindings_t * getRecordingBindArray(unsigned proto)
Returns bindings for Myth::Recording.
SettingMapPtr GetSettings(const std::string &hostname)
GET Myth/GetSetting.
const bindings_t * getProgramBindArray(unsigned proto)
Returns bindings for Myth::Program.
const bindings_t * getListBindArray(unsigned proto)
Returns bindings for Myth::List.
const bindings_t * getCuttingBindArray(unsigned proto)
Returns bindings for Myth::Mark.
const bindings_t * getArtworkBindArray(unsigned proto)
Returns bindings for Myth::Artwork.
Brings together all attribute bindings of an object.
bool GetServiceVersion(WSServiceId_t id, WSServiceVersion_t &version)
const bindings_t * getChannelBindArray(unsigned proto)
Returns bindings for Myth::Channel.
const bindings_t * getCaptureCardBindArray(unsigned proto)
Returns bindings for Myth::CaptureCard.
const bindings_t * getVideoSourceBindArray(unsigned proto)
Returns bindings for Myth::VideoSource.
This is the main namespace that encloses all public classes.
const bindings_t * getVersionBindArray(unsigned ranking)
Returns bindings for Myth::Version.
SettingPtr GetSetting(const std::string &key, const std::string &hostname)
GET Myth/GetSetting.
const bindings_t * getRecordScheduleBindArray(unsigned proto)
Returns bindings for Myth::RecordSchedule.