diff --git a/HISTORY b/HISTORY index 8ffced2..749b4ed 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,7 @@ VDR Plugin 'streamdev' Revision History --------------------------------------- +- Restructured menuHTTP classes - Added RSS format for HTTP menus - Recordings can now also be selected by struct stat "st_dev:st_ino.rec" - Implemented multi-device support for streamdev client (suggested by johns) diff --git a/server/connectionHTTP.c b/server/connectionHTTP.c index 940517b..a8a8c8f 100644 --- a/server/connectionHTTP.c +++ b/server/connectionHTTP.c @@ -25,7 +25,7 @@ cConnectionHTTP::cConnectionHTTP(void): m_StreamType((eStreamType)StreamdevServerSetup.HTTPStreamType), m_Channel(NULL), m_Recording(NULL), - m_ChannelList(NULL) + m_MenuList(NULL) { Dprintf("constructor hsRequest\n"); m_Apid[0] = m_Apid[1] = 0; @@ -169,8 +169,8 @@ bool cConnectionHTTP::ProcessRequest(void) // should never happen esyslog("streamdev-server connectionHTTP: Missing method or pathinfo"); } else if (it_method->second.compare("GET") == 0 && ProcessURI(it_pathinfo->second)) { - if (m_ChannelList) - return Respond("%s", true, m_ChannelList->HttpHeader().c_str()); + if (m_MenuList) + return Respond("%s", true, m_MenuList->HttpHeader().c_str()); else if (m_Channel != NULL) { cDevice *device = NULL; if (ProvidesChannel(m_Channel, StreamdevServerSetup.HTTPPriority)) @@ -217,9 +217,9 @@ bool cConnectionHTTP::ProcessRequest(void) return HttpResponse(404, true); } } else if (it_method->second.compare("HEAD") == 0 && ProcessURI(it_pathinfo->second)) { - if (m_ChannelList) { + if (m_MenuList) { DeferClose(); - return Respond("%s", true, m_ChannelList->HttpHeader().c_str()); + return Respond("%s", true, m_MenuList->HttpHeader().c_str()); } else if (m_Channel != NULL) { if (ProvidesChannel(m_Channel, StreamdevServerSetup.HTTPPriority)) { @@ -363,13 +363,13 @@ void cConnectionHTTP::Flushed(void) if (m_Status != hsBody) return; - if (m_ChannelList) { - if (m_ChannelList->HasNext()) { - if (!Respond("%s", true, m_ChannelList->Next().c_str())) + if (m_MenuList) { + if (m_MenuList->HasNext()) { + if (!Respond("%s", true, m_MenuList->Next().c_str())) DeferClose(); } else { - DELETENULL(m_ChannelList); + DELETENULL(m_MenuList); m_Status = hsFinished; DeferClose(); } @@ -387,28 +387,22 @@ void cConnectionHTTP::Flushed(void) } } -cChannelList* cConnectionHTTP::ChannelListFromString(const std::string& Path, const std::string& Filebase, const std::string& Fileext) const +cMenuList* cConnectionHTTP::MenuListFromString(const std::string& Path, const std::string& Filebase, const std::string& Fileext) const { std::string groupTarget; - cChannelIterator *iterator = NULL; + cItemIterator *iterator = NULL; const static std::string GROUP("group"); if (Filebase.compare("tree") == 0) { - const cChannel* c = NULL; tStrStrMap::const_iterator it = m_Params.find(GROUP); - if (it != m_Params.end()) - c = cChannelList::GetGroup(atoi(it->second.c_str())); - iterator = new cListTree(c); + iterator = new cListTree(it == m_Params.end() ? NULL : it->second.c_str()); groupTarget = Filebase + Fileext; } else if (Filebase.compare("groups") == 0) { iterator = new cListGroups(); groupTarget = (std::string) "group" + Fileext; } else if (Filebase.compare("group") == 0) { - const cChannel* c = NULL; tStrStrMap::const_iterator it = m_Params.find(GROUP); - if (it != m_Params.end()) - c = cChannelList::GetGroup(atoi(it->second.c_str())); - iterator = new cListGroup(c); + iterator = new cListGroup(it == m_Params.end() ? NULL : it->second.c_str()); } else if (Filebase.compare("channels") == 0) { iterator = new cListChannels(); } else if (Filebase.compare("all") == 0 || @@ -436,16 +430,16 @@ cChannelList* cConnectionHTTP::ChannelListFromString(const std::string& Path, co self += '?' + it->second; rss += '?' + it->second; } - return new cHtmlChannelList(iterator, m_StreamType, self.c_str(), rss.c_str(), groupTarget.c_str()); + return new cHtmlMenuList(iterator, m_StreamType, self.c_str(), rss.c_str(), groupTarget.c_str()); } else if (Fileext.compare(".m3u") == 0) { - return new cM3uChannelList(iterator, base.c_str()); + return new cM3uMenuList(iterator, base.c_str()); } else if (Fileext.compare(".rss") == 0) { std::string html = Filebase + ".html"; tStrStrMap::const_iterator it = Headers().find("QUERY_STRING"); if (it != Headers().end() && !it->second.empty()) { html += '?' + it->second; } - return new cRssChannelList(iterator, base.c_str(), html.c_str()); + return new cRssMenuList(iterator, base.c_str(), html.c_str()); } else { delete iterator; } @@ -520,7 +514,7 @@ bool cConnectionHTTP::ProcessURI(const std::string& PathInfo) Dprintf("before channelfromstring: type(%s) filespec(%s) fileext(%s)\n", type.c_str(), filespec.c_str(), fileext.c_str()); - if ((m_ChannelList = ChannelListFromString(PathInfo.substr(1, file_pos), filespec.c_str(), fileext.c_str())) != NULL) { + if ((m_MenuList = MenuListFromString(PathInfo.substr(1, file_pos), filespec.c_str(), fileext.c_str())) != NULL) { Dprintf("Channel list requested\n"); return true; } else if ((m_Recording = RecordingFromString(filespec.c_str(), fileext.c_str())) != NULL) { diff --git a/server/connectionHTTP.h b/server/connectionHTTP.h index 91f4a0e..e946242 100644 --- a/server/connectionHTTP.h +++ b/server/connectionHTTP.h @@ -13,7 +13,7 @@ #include class cChannel; -class cChannelList; +class cMenuList; class cConnectionHTTP: public cServerConnection { private: @@ -36,9 +36,9 @@ private: // job: replay cRecording *m_Recording; // job: listing - cChannelList *m_ChannelList; + cMenuList *m_MenuList; - cChannelList* ChannelListFromString(const std::string &PathInfo, const std::string &Filebase, const std::string &Fileext) const; + cMenuList* MenuListFromString(const std::string &PathInfo, const std::string &Filebase, const std::string &Fileext) const; cRecording* RecordingFromString(const char* FileBase, const char* FileExt) const; bool ProcessURI(const std::string &PathInfo); diff --git a/server/menuHTTP.c b/server/menuHTTP.c index 7839527..ca44579 100644 --- a/server/menuHTTP.c +++ b/server/menuHTTP.c @@ -2,16 +2,60 @@ #include "server/menuHTTP.h" //**************************** cChannelIterator ************** -cChannelIterator::cChannelIterator(const cChannel *First): channel(First) -{} +cChannelIterator::cChannelIterator(const cChannel *First) +{ + first = First; + current = NULL; +} -const cChannel* cChannelIterator::Next() +bool cChannelIterator::Next() { - const cChannel *current = channel; - channel = NextChannel(channel); + if (first) + { + current = first; + first = NULL; + } + else + current = NextChannel(current); return current; } +const cString cChannelIterator::ItemId() const +{ + if (current) + { + if (current->GroupSep()) + { + int index = 0; + for (int curr = Channels.GetNextGroup(-1); curr >= 0; curr = Channels.GetNextGroup(curr)) + { + if (Channels.Get(curr) == current) + return itoa(index); + index++; + } + } + else + { + return itoa(current->Number()); + } + } + return cString("-1"); +} + +const cChannel* cChannelIterator::GetGroup(const char* GroupId) +{ + int group = -1; + if (GroupId) + { + int Index = atoi(GroupId); + group = Channels.GetNextGroup(-1); + while (Index-- && group >= 0) + group = Channels.GetNextGroup(group); + } + return group >= 0 ? Channels.Get(group) : NULL; +} + + //**************************** cListAll ************** cListAll::cListAll(): cChannelIterator(Channels.First()) {} @@ -46,7 +90,7 @@ const cChannel* cListGroups::NextChannel(const cChannel *Channel) } // // ********************* cListGroup **************** -cListGroup::cListGroup(const cChannel *Group): cChannelIterator(GetNextChannelInGroup(Group)) +cListGroup::cListGroup(const char *GroupId): cChannelIterator(GetNextChannelInGroup(GetGroup(GroupId))) {} const cChannel* cListGroup::GetNextChannelInGroup(const cChannel *Channel) @@ -62,9 +106,9 @@ const cChannel* cListGroup::NextChannel(const cChannel *Channel) } // // ********************* cListTree **************** -cListTree::cListTree(const cChannel *SelectedGroup): cChannelIterator(Channels.Get(Channels.GetNextGroup(-1))) +cListTree::cListTree(const char *SelectedGroupId): cChannelIterator(Channels.Get(Channels.GetNextGroup(-1))) { - selectedGroup = SelectedGroup; + selectedGroup = GetGroup(SelectedGroupId); currentGroup = Channels.Get(Channels.GetNextGroup(-1)); } @@ -86,43 +130,23 @@ const cChannel* cListTree::NextChannel(const cChannel *Channel) return Channel; } -// ******************** cChannelList ****************** -cChannelList::cChannelList(cChannelIterator *Iterator) : iterator(Iterator) +// ******************** cMenuList ****************** +cMenuList::cMenuList(cItemIterator *Iterator) : iterator(Iterator) {} -cChannelList::~cChannelList() +cMenuList::~cMenuList() { delete iterator; } -int cChannelList::GetGroupIndex(const cChannel *Group) -{ - int index = 0; - for (int curr = Channels.GetNextGroup(-1); curr >= 0; curr = Channels.GetNextGroup(curr)) - { - if (Channels.Get(curr) == Group) - return index; - index++; - } - return -1; -} - -const cChannel* cChannelList::GetGroup(int Index) -{ - int group = Channels.GetNextGroup(-1); - while (Index-- && group >= 0) - group = Channels.GetNextGroup(group); - return group >= 0 ? Channels.Get(group) : NULL; -} - -// ******************** cHtmlChannelList ****************** -const char* cHtmlChannelList::menu = +// ******************** cHtmlMenuList ****************** +const char* cHtmlMenuList::menu = "[Home (no script)] " "[Tree View] " "[Groups (Playlist | RSS)] " "[Channels (Playlist | RSS)] "; -const char* cHtmlChannelList::css = +const char* cHtmlMenuList::css = ""; -const char* cHtmlChannelList::js = +const char* cHtmlMenuList::js = ""; -std::string cHtmlChannelList::StreamTypeMenu() +std::string cHtmlMenuList::StreamTypeMenu() { std::string typeMenu; typeMenu += (streamType == stTS ? (std::string) "[TS] " : @@ -215,29 +239,29 @@ std::string cHtmlChannelList::StreamTypeMenu() return typeMenu; } -cHtmlChannelList::cHtmlChannelList(cChannelIterator *Iterator, eStreamType StreamType, const char *Self, const char *Rss, const char *GroupTarget): cChannelList(Iterator) +cHtmlMenuList::cHtmlMenuList(cItemIterator *Iterator, eStreamType StreamType, const char *Self, const char *Rss, const char *GroupTarget): cMenuList(Iterator) { streamType = StreamType; self = strdup(Self); rss = strdup(Rss); groupTarget = (GroupTarget && *GroupTarget) ? strdup(GroupTarget) : NULL; htmlState = hsRoot; - current = NULL; + onItem = true; } -cHtmlChannelList::~cHtmlChannelList() +cHtmlMenuList::~cHtmlMenuList() { free((void *) self); free((void *) rss); free((void *) groupTarget); } -bool cHtmlChannelList::HasNext() +bool cHtmlMenuList::HasNext() { return htmlState != hsPageBottom; } -std::string cHtmlChannelList::Next() +std::string cHtmlMenuList::Next() { switch (htmlState) { @@ -254,39 +278,39 @@ std::string cHtmlChannelList::Next() htmlState = hsPageTop; break; case hsPageTop: - current = NextChannel(); - htmlState = current ? (current->GroupSep() ? hsGroupTop : hsPlainTop) : hsPageBottom; + onItem = NextItem(); + htmlState = onItem ? (IsGroup() ? hsGroupTop : hsPlainTop) : hsPageBottom; break; case hsPlainTop: htmlState = hsPlainItem; break; case hsPlainItem: - current = NextChannel(); - htmlState = current && !current->GroupSep() ? hsPlainItem : hsPlainBottom; + onItem = NextItem(); + htmlState = onItem && !IsGroup() ? hsPlainItem : hsPlainBottom; break; case hsPlainBottom: - htmlState = current ? hsGroupTop : hsPageBottom; + htmlState = onItem ? hsGroupTop : hsPageBottom; break; case hsGroupTop: - current = NextChannel(); - htmlState = current && !current->GroupSep() ? hsItemsTop : hsGroupBottom; + onItem = NextItem(); + htmlState = onItem && !IsGroup() ? hsItemsTop : hsGroupBottom; break; case hsItemsTop: htmlState = hsItem; break; case hsItem: - current = NextChannel(); - htmlState = current && !current->GroupSep() ? hsItem : hsItemsBottom; + onItem = NextItem(); + htmlState = onItem && !IsGroup() ? hsItem : hsItemsBottom; break; case hsItemsBottom: htmlState = hsGroupBottom; break; case hsGroupBottom: - htmlState = current ? hsGroupTop : hsPageBottom; + htmlState = onItem ? hsGroupTop : hsPageBottom; break; case hsPageBottom: default: - esyslog("streamdev-server cHtmlChannelList: invalid call to Next()"); + esyslog("streamdev-server cHtmlMenuList: invalid call to Next()"); break; } switch (htmlState) @@ -311,36 +335,35 @@ std::string cHtmlChannelList::Next() } } -std::string cHtmlChannelList::HtmlHead() +std::string cHtmlMenuList::HtmlHead() { return (std::string) ""; } -std::string cHtmlChannelList::PageTop() +std::string cHtmlMenuList::PageTop() { return (std::string) "
" + menu + "
" + StreamTypeMenu() + "
"; } -std::string cHtmlChannelList::PageBottom() +std::string cHtmlMenuList::PageBottom() { return (std::string) ""; } -std::string cHtmlChannelList::GroupTitle() +std::string cHtmlMenuList::GroupTitle() { if (groupTarget) { - return (std::string) "" + current->Name() + ""; + return (std::string) "" + + ItemTitle() + ""; } else { - return (std::string) current->Name(); + return (std::string) ItemTitle(); } } -std::string cHtmlChannelList::ItemText() +std::string cHtmlMenuList::ItemText() { std::string line; std::string suffix; @@ -352,58 +375,58 @@ std::string cHtmlChannelList::ItemText() case stPES: suffix = (std::string) ".vdr"; break; default: suffix = ""; } - line += (std::string) "
  • Number()) + "\">"; - line += (std::string) "GetChannelID().ToString() + suffix + "\""; + line += (std::string) "
  • "; + line += (std::string) "Number() < 1000) - line += (std::string) " tvid=\"" + (const char*) itoa(current->Number()) + "\""; + if (strlen(ItemId()) < 4) + line += (std::string) " tvid=\"" + (const char*) ItemId() + "\""; - line += (std::string) ">" + current->Name() + ""; + line += (std::string) ">" + ItemTitle() + ""; - int count = 0; - for (int i = 0; current->Apid(i) != 0; ++i, ++count) - ; - for (int i = 0; current->Dpid(i) != 0; ++i, ++count) - ; - - if (count > 1) + // TS always streams all PIDs + if (streamType != stTS) { int index = 1; - for (int i = 0; current->Apid(i) != 0; ++i, ++index) { - line += (std::string) " GetChannelID().ToString() + - "+" + (const char*)itoa(index) + suffix + "\" class=\"apid\" vod>" + current->Alang(i) + ""; - } - for (int i = 0; current->Dpid(i) != 0; ++i, ++index) { - line += (std::string) " GetChannelID().ToString() + - "+" + (const char*)itoa(index) + suffix + "\" class=\"dpid\" vod>" + current->Dlang(i) + ""; - } + const char* lang; + std::string pids; + for (int i = 0; (lang = Alang(i)) != NULL; ++i, ++index) { + pids += (std::string) " " + (const char*) lang + ""; + } + for (int i = 0; (lang = Dlang(i)) != NULL; ++i, ++index) { + pids += (std::string) " " + (const char*) lang + ""; + } + // always show audio PIDs for stES to select audio only + if (index > 2 || streamType == stES) + line += pids; } line += "
  • "; return line; } -// ******************** cM3uChannelList ****************** -cM3uChannelList::cM3uChannelList(cChannelIterator *Iterator, const char* Base) -: cChannelList(Iterator), +// ******************** cM3uMenuList ****************** +cM3uMenuList::cM3uMenuList(cItemIterator *Iterator, const char* Base) +: cMenuList(Iterator), m_IConv(cCharSetConv::SystemCharacterTable(), "UTF-8") { base = strdup(Base); m3uState = msFirst; } -cM3uChannelList::~cM3uChannelList() +cM3uMenuList::~cM3uMenuList() { free(base); } -bool cM3uChannelList::HasNext() +bool cM3uMenuList::HasNext() { return m3uState != msLast; } -std::string cM3uChannelList::Next() +std::string cM3uMenuList::Next() { if (m3uState == msFirst) { @@ -411,32 +434,30 @@ std::string cM3uChannelList::Next() return "#EXTM3U"; } - const cChannel *channel = NextChannel(); - if (!channel) + if (!NextItem()) { m3uState = msLast; return ""; } - std::string name = (std::string) m_IConv.Convert(channel->Name()); + std::string name = (std::string) m_IConv.Convert(ItemTitle()); - if (channel->GroupSep()) + if (IsGroup()) { return (std::string) "#EXTINF:-1," + name + "\r\n" + - base + "group.m3u?group=" + - (const char*) itoa(cChannelList::GetGroupIndex(channel)); + base + "group.m3u?group=" + (const char*) ItemId(); } else { return (std::string) "#EXTINF:-1," + - (const char*) itoa(channel->Number()) + " " + name + "\r\n" + - base + (std::string) channel->GetChannelID().ToString(); + (const char*) ItemId() + " " + name + "\r\n" + + base + (const char*) ItemRessource(); } } -// ******************** cRssChannelList ****************** -cRssChannelList::cRssChannelList(cChannelIterator *Iterator, const char *Base, const char *Html) -: cChannelList(Iterator), +// ******************** cRssMenuList ****************** +cRssMenuList::cRssMenuList(cItemIterator *Iterator, const char *Base, const char *Html) +: cMenuList(Iterator), m_IConv(cCharSetConv::SystemCharacterTable(), "UTF-8") { base = strdup(Base); @@ -444,18 +465,18 @@ cRssChannelList::cRssChannelList(cChannelIterator *Iterator, const char *Base, c rssState = msFirst; } -cRssChannelList::~cRssChannelList() +cRssMenuList::~cRssMenuList() { free(base); free(html); } -bool cRssChannelList::HasNext() +bool cRssMenuList::HasNext() { return rssState != msLast; } -std::string cRssChannelList::Next() +std::string cRssMenuList::Next() { std::string type_ext; @@ -469,27 +490,26 @@ std::string cRssChannelList::Next() ; } - const cChannel *channel = NextChannel(); - if (!channel) + if (!NextItem()) { rssState = msLast; return "\t\n\n"; } - std::string name = (std::string) m_IConv.Convert(channel->Name()); + std::string name = (std::string) m_IConv.Convert(ItemTitle()); - if (channel->GroupSep()) + if (IsGroup()) { return (std::string) "\t\t\n\t\t\t" + name + "\n\t\t\t" + - base + "group.rss?group=" + (const char*) itoa(cChannelList::GetGroupIndex(channel)) + "\n\t\t\n"; + base + "group.rss?group=" + (const char*) ItemId() + "\n\t\t\n"; } else { return (std::string) "\t\t\n\t\t\t" + - (const char*) itoa(channel->Number()) + " " + name + "\n\t\t\t" + - base + (std::string) channel->GetChannelID().ToString() + "\n\t\t\tGetChannelID().ToString() + "\" type=\"video/mpeg\" />\n\t\t\n"; + (const char*) ItemId() + " " + name + "\n\t\t\t" + + base + (const char*) ItemRessource() + "\n\t\t\t\n\t\t\n"; } } diff --git a/server/menuHTTP.h b/server/menuHTTP.h index b025598..ec759e9 100644 --- a/server/menuHTTP.h +++ b/server/menuHTTP.h @@ -6,16 +6,38 @@ class cChannel; -// ******************** cChannelIterator ****************** -class cChannelIterator +// ******************** cItemIterator ****************** +class cItemIterator +{ + public: + virtual bool Next() = 0; + virtual bool IsGroup() const = 0; + virtual const cString ItemId() const = 0; + virtual const char* ItemTitle() const = 0; + virtual const cString ItemRessource() const = 0; + virtual const char* Alang(int i) const = 0; + virtual const char* Dlang(int i) const = 0; +}; + +class cChannelIterator: public cItemIterator { private: - const cChannel *channel; + const cChannel *first; + const cChannel *current; protected: virtual const cChannel* NextChannel(const cChannel *Channel) = 0; static inline const cChannel* SkipFakeGroups(const cChannel *Channel); + // Helper which returns the group by its index + static const cChannel* GetGroup(const char* GroupId); public: - const cChannel* Next(); + + virtual bool Next(); + virtual bool IsGroup() const { return current && current->GroupSep(); } + virtual const cString ItemId() const; + virtual const char* ItemTitle() const { return current ? current->Name() : ""; } + virtual const cString ItemRessource() const { return (current ? current->GetChannelID() : tChannelID::InvalidID).ToString(); } + virtual const char* Alang(int i) const { return current && current->Apid(i) ? current->Alang(i) : NULL; } + virtual const char* Dlang(int i) const { return current && current->Dpid(i) ? current->Dlang(i) : NULL; } cChannelIterator(const cChannel *First); virtual ~cChannelIterator() {}; }; @@ -54,7 +76,7 @@ class cListGroup: public cChannelIterator protected: virtual const cChannel* NextChannel(const cChannel *Channel); public: - cListGroup(const cChannel *Group); + cListGroup(const char *GroupId); virtual ~cListGroup() {}; }; @@ -66,31 +88,32 @@ class cListTree: public cChannelIterator protected: virtual const cChannel* NextChannel(const cChannel *Channel); public: - cListTree(const cChannel *SelectedGroup); + cListTree(const char *SelectedGroupId); virtual ~cListTree() {}; }; -// ******************** cChannelList ****************** -class cChannelList +// ******************** cMenuList ****************** +class cMenuList { private: - cChannelIterator *iterator; + cItemIterator *iterator; protected: - const cChannel* NextChannel() { return iterator->Next(); } + bool NextItem() { return iterator->Next(); } + bool IsGroup() { return iterator->IsGroup(); } + const cString ItemId() { return iterator->ItemId(); } + const char* ItemTitle() { return iterator->ItemTitle(); } + const cString ItemRessource() { return iterator->ItemRessource(); } + const char* Alang(int i) { return iterator->Alang(i); } + const char* Dlang(int i) { return iterator->Dlang(i); } public: - // Helper which returns the group index - static int GetGroupIndex(const cChannel* Group); - // Helper which returns the group by its index - static const cChannel* GetGroup(int Index); - virtual std::string HttpHeader() { return "HTTP/1.0 200 OK\r\n"; }; virtual bool HasNext() = 0; virtual std::string Next() = 0; - cChannelList(cChannelIterator *Iterator); - virtual ~cChannelList(); + cMenuList(cItemIterator *Iterator); + virtual ~cMenuList(); }; -class cHtmlChannelList: public cChannelList +class cHtmlMenuList: public cMenuList { private: static const char* menu; @@ -104,7 +127,7 @@ class cHtmlChannelList: public cChannelList hsItemsTop, hsItem, hsItemsBottom }; eHtmlState htmlState; - const cChannel *current; + bool onItem; eStreamType streamType; const char* self; const char* rss; @@ -118,18 +141,18 @@ class cHtmlChannelList: public cChannelList std::string PageBottom(); public: virtual std::string HttpHeader() { - return cChannelList::HttpHeader() + return cMenuList::HttpHeader() + "Content-type: text/html; charset=" + (cCharSetConv::SystemCharacterTable() ? cCharSetConv::SystemCharacterTable() : "UTF-8") + "\r\n"; } virtual bool HasNext(); virtual std::string Next(); - cHtmlChannelList(cChannelIterator *Iterator, eStreamType StreamType, const char *Self, const char *Rss, const char *GroupTarget); - virtual ~cHtmlChannelList(); + cHtmlMenuList(cItemIterator *Iterator, eStreamType StreamType, const char *Self, const char *Rss, const char *GroupTarget); + virtual ~cHtmlMenuList(); }; -class cM3uChannelList: public cChannelList +class cM3uMenuList: public cMenuList { private: char *base; @@ -137,14 +160,14 @@ class cM3uChannelList: public cChannelList eM3uState m3uState; cCharSetConv m_IConv; public: - virtual std::string HttpHeader() { return cChannelList::HttpHeader() + "Content-type: audio/x-mpegurl; charset=UTF-8\r\n"; }; + virtual std::string HttpHeader() { return cMenuList::HttpHeader() + "Content-type: audio/x-mpegurl; charset=UTF-8\r\n"; }; virtual bool HasNext(); virtual std::string Next(); - cM3uChannelList(cChannelIterator *Iterator, const char* Base); - virtual ~cM3uChannelList(); + cM3uMenuList(cItemIterator *Iterator, const char* Base); + virtual ~cM3uMenuList(); }; -class cRssChannelList: public cChannelList +class cRssMenuList: public cMenuList { private: char *base; @@ -153,12 +176,12 @@ class cRssChannelList: public cChannelList eRssState rssState; cCharSetConv m_IConv; public: - virtual std::string HttpHeader() { return cChannelList::HttpHeader() + "Content-type: application/rss+xml\r\n"; }; + virtual std::string HttpHeader() { return cMenuList::HttpHeader() + "Content-type: application/rss+xml\r\n"; }; virtual bool HasNext(); virtual std::string Next(); - cRssChannelList(cChannelIterator *Iterator, const char *Base, const char *Html); - virtual ~cRssChannelList(); + cRssMenuList(cItemIterator *Iterator, const char *Base, const char *Html); + virtual ~cRssMenuList(); }; inline const cChannel* cChannelIterator::SkipFakeGroups(const cChannel* Group)