mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 19:16:51 +02:00
Missing files
This commit is contained in:
parent
b66bf7a698
commit
57923c656e
420
server/menuHTTP.c
Normal file
420
server/menuHTTP.c
Normal file
@ -0,0 +1,420 @@
|
||||
#include <vdr/channels.h>
|
||||
#include "server/menuHTTP.h"
|
||||
|
||||
//**************************** cChannelIterator **************
|
||||
cChannelIterator::cChannelIterator(cChannel *First): channel(First)
|
||||
{}
|
||||
|
||||
const cChannel* cChannelIterator::Next()
|
||||
{
|
||||
const cChannel *current = channel;
|
||||
channel = NextChannel(channel);
|
||||
return current;
|
||||
}
|
||||
|
||||
//**************************** cListAll **************
|
||||
cListAll::cListAll(): cChannelIterator(Channels.First())
|
||||
{}
|
||||
|
||||
const cChannel* cListAll::NextChannel(const cChannel *Channel)
|
||||
{
|
||||
if (Channel)
|
||||
Channel = Channels.Next(Channel);
|
||||
return Channel;
|
||||
}
|
||||
|
||||
//**************************** cListChannels **************
|
||||
cListChannels::cListChannels(): cChannelIterator(Channels.Get(Channels.GetNextNormal(-1)))
|
||||
{}
|
||||
|
||||
const cChannel* cListChannels::NextChannel(const cChannel *Channel)
|
||||
{
|
||||
if (Channel)
|
||||
Channel = Channels.Get(Channels.GetNextNormal(Channel->Index()));
|
||||
return Channel;
|
||||
}
|
||||
|
||||
// ********************* cListGroups ****************
|
||||
cListGroups::cListGroups(): cChannelIterator(Channels.Get(Channels.GetNextGroup(-1)))
|
||||
{}
|
||||
|
||||
const cChannel* cListGroups::NextChannel(const cChannel *Channel)
|
||||
{
|
||||
if (Channel)
|
||||
Channel = Channels.Get(Channels.GetNextGroup(Channel->Index()));
|
||||
return Channel;
|
||||
}
|
||||
//
|
||||
// ********************* cListGroup ****************
|
||||
cListGroup::cListGroup(const cChannel *Group): cChannelIterator((Group && Group->GroupSep() && Channels.Next(Group) && !Channels.Next(Group)->GroupSep()) ? Channels.Next(Group) : NULL)
|
||||
{}
|
||||
|
||||
const cChannel* cListGroup::NextChannel(const cChannel *Channel)
|
||||
{
|
||||
if (Channel)
|
||||
Channel = Channels.Next(Channel);
|
||||
return (Channel && !Channel->GroupSep()) ? Channel : NULL;
|
||||
}
|
||||
//
|
||||
// ********************* cListTree ****************
|
||||
cListTree::cListTree(const cChannel *SelectedGroup): cChannelIterator(Channels.Get(Channels.GetNextGroup(-1)))
|
||||
{
|
||||
selectedGroup = SelectedGroup;
|
||||
currentGroup = Channels.Get(Channels.GetNextGroup(-1));
|
||||
}
|
||||
|
||||
const cChannel* cListTree::NextChannel(const cChannel *Channel)
|
||||
{
|
||||
if (currentGroup == selectedGroup)
|
||||
{
|
||||
if (Channel)
|
||||
Channel = Channels.Next(Channel);
|
||||
if (Channel && Channel->GroupSep())
|
||||
currentGroup = Channel;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Channel)
|
||||
Channel = Channels.Get(Channels.GetNextGroup(Channel->Index()));
|
||||
currentGroup = Channel;
|
||||
}
|
||||
return Channel;
|
||||
}
|
||||
|
||||
// ******************** cChannelList ******************
|
||||
cChannelList::cChannelList(cChannelIterator *Iterator) : iterator(Iterator)
|
||||
{}
|
||||
|
||||
cChannelList::~cChannelList()
|
||||
{
|
||||
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 =
|
||||
"[<a href=\"/\">Home</a> (<a href=\"all.html\">no script</a>)] "
|
||||
"[<a href=\"tree.html\">Tree View</a>] "
|
||||
"[<a href=\"groups.html\">Groups</a> (<a href=\"groups.m3u\">Playlist</a>)] "
|
||||
"[<a href=\"channels.html\">Channels</a> (<a href=\"channels.m3u\">Playlist</a>)] ";
|
||||
|
||||
const char* cHtmlChannelList::css =
|
||||
"<style type=\"text/css\">\n"
|
||||
"<!--\n"
|
||||
"a:link, a:visited, a:hover, a:active, a:focus { color:#333399; }\n"
|
||||
"body { font:100% Verdana, Arial, Helvetica, sans-serif; background-color:#9999FF; margin:1em; }\n"
|
||||
".menu { position:fixed; top:0px; left:1em; right:1em; height:3em; text-align:center; background-color:white; border:inset 2px #9999ff; }\n"
|
||||
"h2 { font-size:150%; margin:0em; padding:0em 1.5em; }\n"
|
||||
".contents { margin-top:5em; background-color:white; }\n"
|
||||
".group { background:url(data:image/gif;base64,R0lGODdhAQAeAIQeAJub/5yc/6Cf/6Oj/6am/6qq/66u/7Gx/7S0/7i4/7u8/7+//8LD/8bG/8nK/83N/9HQ/9TU/9fX/9va/97e/+Lh/+Xl/+no/+3t//Dw//Pz//b3//v7//7+/////////ywAAAAAAQAeAAAFGCAQCANRGAeSKAvTOA8USRNVWReWaRvXhQA7) repeat-x; border:inset 2px #9999ff; }\n"
|
||||
".items { border-top:dashed 1px; margin-top:0px; margin-bottom:0px; padding:0.7em 5em; }\n"
|
||||
".apid { padding-left:28px; margin:0.5em; background:url(data:image/gif;base64,R0lGODlhGwASAKEBAAAAAP///////////yH5BAEKAAEALAAAAAAbABIAAAJAjI+pywj5WgPxVAmpNRcHqnGb94FPhE7m+okts7JvusSmSys2iLv6TstldjMfhhUkcXi+zjFUVFo6TiVVij0UAAA7) no-repeat; }\n"
|
||||
".dpid { padding-left:28px; margin:0.5em; background:url(data:image/gif;base64,R0lGODlhGwASAKEBAAAAAP///////////yH5BAEKAAEALAAAAAAbABIAAAJFjI+py+0BopwAUoqivRvr83UaZ4RWMnVoBbLZaJbuqcCLGcv0+t5Vvgu2hLrh6pfDzVSpnlGEbAZhnIutZaVmH9yuV1EAADs=) no-repeat; }\n"
|
||||
"button { width:2em; margin:0.2em 0.5em; vertical-align:top; }\n"
|
||||
"-->\n"
|
||||
"</style>";
|
||||
|
||||
const char* cHtmlChannelList::js =
|
||||
"<script language=\"JavaScript\">\n"
|
||||
"<!--\n"
|
||||
|
||||
"function eventTarget(evt) {\n"
|
||||
" if (!evt) evt = window.event;\n"
|
||||
" if (evt.target) return evt.target;\n"
|
||||
" else if (evt.srcElement) return evt.srcElement;\n"
|
||||
" else return null;\n"
|
||||
"}\n"
|
||||
|
||||
// toggle visibility of a group
|
||||
"function clickHandler(evt) {\n"
|
||||
" var button = eventTarget(evt);\n"
|
||||
" if (button) {\n"
|
||||
" var group = document.getElementById('c' + button.id);\n"
|
||||
" if (group) {\n"
|
||||
" button.removeChild(button.firstChild);\n"
|
||||
" if (group.style.display == 'block') {\n"
|
||||
" button.appendChild(document.createTextNode(\"+\"));\n"
|
||||
" group.style.display = 'none';\n"
|
||||
" } else {\n"
|
||||
" button.appendChild(document.createTextNode(\"-\"));\n"
|
||||
" group.style.display = 'block';\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
|
||||
// insert a click button infront of each h2 and an id to the corresponding list
|
||||
"function init() {\n"
|
||||
" var titles = document.getElementsByTagName('h2');\n"
|
||||
" for (var i = 0; i < titles.length; i++) {\n"
|
||||
" var button = document.createElement('button');\n"
|
||||
" button.id = 'g' + i;\n"
|
||||
" button.onclick = clickHandler;\n"
|
||||
" button.appendChild(document.createTextNode('+'));\n"
|
||||
" titles[i].insertBefore(button, titles[i].firstChild);\n"
|
||||
" var group = titles[i].nextSibling;\n"
|
||||
" while (group) {\n"
|
||||
" if (group.className && group.className == 'items') {\n"
|
||||
" group.id = 'cg' + i;\n"
|
||||
" break;\n"
|
||||
" }\n"
|
||||
" group = group.nextSibling;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
|
||||
"window.onload = init;\n"
|
||||
|
||||
// hide lists before the browser renders it
|
||||
"if (document.styleSheets[0].insertRule)\n"
|
||||
" document.styleSheets[0].insertRule('.items { display:none }', 0);\n"
|
||||
"else if (document.styleSheets[0].addRule)\n"
|
||||
" document.styleSheets[0].addRule('.items', 'display:none');\n"
|
||||
|
||||
"//-->\n"
|
||||
"</script>";
|
||||
|
||||
|
||||
std::string cHtmlChannelList::StreamTypeMenu()
|
||||
{
|
||||
std::string typeMenu;
|
||||
typeMenu += (streamType == stTS ? (std::string) "[TS] " :
|
||||
(std::string) "[<a href=\"/TS/" + self + "\">TS</a>] ");
|
||||
typeMenu += (streamType == stPS ? (std::string) "[PS] " :
|
||||
(std::string) "[<a href=\"/PS/" + self + "\">PS</a>] ");
|
||||
typeMenu += (streamType == stPES ? (std::string) "[PES] " :
|
||||
(std::string) "[<a href=\"/PES/" + self + "\">PES</a>] ");
|
||||
typeMenu += (streamType == stES ? (std::string) "[ES] " :
|
||||
(std::string) "[<a href=\"/ES/" + self + "\">ES</a>] ");
|
||||
typeMenu += (streamType == stExtern ? (std::string) "[Extern] " :
|
||||
(std::string) "[<a href=\"/Extern/" + self + "\">Extern</a>] ");
|
||||
return typeMenu;
|
||||
}
|
||||
|
||||
cHtmlChannelList::cHtmlChannelList(cChannelIterator *Iterator, eStreamType StreamType, const char *Self, const char *GroupTarget): cChannelList(Iterator)
|
||||
{
|
||||
streamType = StreamType;
|
||||
self = strdup(Self);
|
||||
groupTarget = (GroupTarget && *GroupTarget) ? strdup(GroupTarget) : NULL;
|
||||
htmlState = hsRoot;
|
||||
current = NULL;
|
||||
}
|
||||
|
||||
cHtmlChannelList::~cHtmlChannelList()
|
||||
{
|
||||
free((void *) self);
|
||||
free((void *) groupTarget);
|
||||
}
|
||||
|
||||
bool cHtmlChannelList::HasNext()
|
||||
{
|
||||
return htmlState != hsPageBottom;
|
||||
}
|
||||
|
||||
std::string cHtmlChannelList::Next()
|
||||
{
|
||||
switch (htmlState)
|
||||
{
|
||||
case hsRoot:
|
||||
htmlState = hsHtmlHead;
|
||||
break;
|
||||
case hsHtmlHead:
|
||||
htmlState = hsCss;
|
||||
break;
|
||||
case hsCss:
|
||||
htmlState = *self ? hsPageTop : hsJs;
|
||||
break;
|
||||
case hsJs:
|
||||
htmlState = hsPageTop;
|
||||
break;
|
||||
case hsPageTop:
|
||||
current = NextChannel();
|
||||
htmlState = current ? (current->GroupSep() ? hsGroupTop : hsPlainTop) : hsPageBottom;
|
||||
break;
|
||||
case hsPlainTop:
|
||||
htmlState = hsPlainItem;
|
||||
break;
|
||||
case hsPlainItem:
|
||||
current = NextChannel();
|
||||
htmlState = current && !current->GroupSep() ? hsPlainItem : hsPlainBottom;
|
||||
break;
|
||||
case hsPlainBottom:
|
||||
htmlState = current ? hsGroupTop : hsPageBottom;
|
||||
break;
|
||||
case hsGroupTop:
|
||||
current = NextChannel();
|
||||
htmlState = current && !current->GroupSep() ? hsItemsTop : hsGroupBottom;
|
||||
break;
|
||||
case hsItemsTop:
|
||||
htmlState = hsItem;
|
||||
break;
|
||||
case hsItem:
|
||||
current = NextChannel();
|
||||
htmlState = current && !current->GroupSep() ? hsItem : hsItemsBottom;
|
||||
break;
|
||||
case hsItemsBottom:
|
||||
htmlState = hsGroupBottom;
|
||||
break;
|
||||
case hsGroupBottom:
|
||||
htmlState = current ? hsGroupTop : hsPageBottom;
|
||||
break;
|
||||
case hsPageBottom:
|
||||
default:
|
||||
esyslog("streamdev-server cHtmlChannelList: invalid call to Next()");
|
||||
break;
|
||||
}
|
||||
switch (htmlState)
|
||||
{
|
||||
// NOTE: JavaScript requirements:
|
||||
// Group title is identified by <h2> tag
|
||||
// Channel list must be a sibling of <h2> with class "items"
|
||||
case hsHtmlHead: return "<html><head>" + HtmlHead();
|
||||
case hsCss: return css;
|
||||
case hsJs: return js;
|
||||
case hsPageTop: return "</head><body>" + PageTop() + "<div class=\"contents\">";
|
||||
case hsGroupTop: return "<div class=\"group\"><h2>" + GroupTitle() + "</h2>";
|
||||
case hsItemsTop:
|
||||
case hsPlainTop: return "<ol class=\"items\">";
|
||||
case hsItem:
|
||||
case hsPlainItem: return ItemText();
|
||||
case hsItemsBottom:
|
||||
case hsPlainBottom: return "</ol>";
|
||||
case hsGroupBottom: return "</div>";
|
||||
case hsPageBottom: return "</div>" + PageBottom() + "</body></html>";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string cHtmlChannelList::HtmlHead()
|
||||
{
|
||||
return (std::string) "";
|
||||
}
|
||||
|
||||
std::string cHtmlChannelList::PageTop()
|
||||
{
|
||||
return (std::string) "<div class=\"menu\"><div>" + menu + "</div><div>" + StreamTypeMenu() + "</div></div>";
|
||||
}
|
||||
|
||||
std::string cHtmlChannelList::PageBottom()
|
||||
{
|
||||
return (std::string) "";
|
||||
}
|
||||
|
||||
std::string cHtmlChannelList::GroupTitle()
|
||||
{
|
||||
if (groupTarget)
|
||||
{
|
||||
return (std::string) "<a href=\"" + groupTarget + "?group=" +
|
||||
(const char*) itoa(cChannelList::GetGroupIndex(current)) +
|
||||
"\">" + current->Name() + "</a>";
|
||||
}
|
||||
else
|
||||
{
|
||||
return (std::string) current->Name();
|
||||
}
|
||||
}
|
||||
|
||||
std::string cHtmlChannelList::ItemText()
|
||||
{
|
||||
std::string line;
|
||||
line += (std::string) "<li value=\"" + (const char*) itoa(current->Number()) + "\">";
|
||||
line += (std::string) "<a href=\"" + (std::string) current->GetChannelID().ToString() + "\">" +
|
||||
current->Name() + "</a>";
|
||||
|
||||
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)
|
||||
{
|
||||
int index = 1;
|
||||
for (int i = 0; current->Apid(i) != 0; ++i, ++index) {
|
||||
line += (std::string) " <a href=\"" + (std::string) current->GetChannelID().ToString() +
|
||||
"+" + (const char*)itoa(index) + "\" class=\"apid\">" + current->Alang(i) + "</a>";
|
||||
}
|
||||
for (int i = 0; current->Dpid(i) != 0; ++i, ++index) {
|
||||
line += (std::string) " <a href=\"" + (std::string) current->GetChannelID().ToString() +
|
||||
"+" + (const char*)itoa(index) + "\" class=\"dpid\">" + current->Dlang(i) + "</a>";
|
||||
}
|
||||
}
|
||||
line += "</li>";
|
||||
return line;
|
||||
}
|
||||
|
||||
// ******************** cM3uChannelList ******************
|
||||
cM3uChannelList::cM3uChannelList(cChannelIterator *Iterator, const char* Base)
|
||||
: cChannelList(Iterator)
|
||||
#if defined(APIVERSNUM) && APIVERSNUM >= 10503
|
||||
, m_IConv(cCharSetConv::SystemCharacterTable(), "UTF-8")
|
||||
#endif
|
||||
{
|
||||
base = strdup(Base);
|
||||
m3uState = msFirst;
|
||||
}
|
||||
|
||||
cM3uChannelList::~cM3uChannelList()
|
||||
{
|
||||
free(base);
|
||||
}
|
||||
|
||||
bool cM3uChannelList::HasNext()
|
||||
{
|
||||
return m3uState != msLast;
|
||||
}
|
||||
|
||||
std::string cM3uChannelList::Next()
|
||||
{
|
||||
if (m3uState == msFirst)
|
||||
{
|
||||
m3uState = msContinue;
|
||||
return "#EXTM3U";
|
||||
}
|
||||
|
||||
const cChannel *channel = NextChannel();
|
||||
if (!channel)
|
||||
{
|
||||
m3uState = msLast;
|
||||
return "";
|
||||
}
|
||||
|
||||
#if defined(APIVERSNUM) && APIVERSNUM >= 10503
|
||||
std::string name = (std::string) m_IConv.Convert(channel->Name());
|
||||
#else
|
||||
std::string name = channel->Name();
|
||||
#endif
|
||||
|
||||
if (channel->GroupSep())
|
||||
{
|
||||
return (std::string) "#EXTINF:0," + name + "\r\n" +
|
||||
base + "group.m3u?group=" +
|
||||
(const char*) itoa(cChannelList::GetGroupIndex(channel));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (std::string) "#EXTINF:0," +
|
||||
(const char*) itoa(channel->Number()) + " " + name + "\r\n" +
|
||||
base + (std::string) channel->GetChannelID().ToString();
|
||||
}
|
||||
}
|
||||
|
140
server/menuHTTP.h
Normal file
140
server/menuHTTP.h
Normal file
@ -0,0 +1,140 @@
|
||||
#ifndef VDR_STREAMDEV_SERVERS_MENUHTTP_H
|
||||
#define VDR_STREAMDEV_SERVERS_MENUHTTP_H
|
||||
|
||||
#include <string>
|
||||
#include "../common.h"
|
||||
|
||||
class cChannel;
|
||||
|
||||
// ******************** cChannelIterator ******************
|
||||
class cChannelIterator
|
||||
{
|
||||
private:
|
||||
const cChannel *channel;
|
||||
protected:
|
||||
virtual const cChannel* NextChannel(const cChannel *Channel) = 0;
|
||||
public:
|
||||
const cChannel* Next();
|
||||
cChannelIterator(cChannel *First);
|
||||
virtual ~cChannelIterator() {};
|
||||
};
|
||||
|
||||
class cListAll: public cChannelIterator
|
||||
{
|
||||
protected:
|
||||
virtual const cChannel* NextChannel(const cChannel *Channel);
|
||||
public:
|
||||
cListAll();
|
||||
virtual ~cListAll() {};
|
||||
};
|
||||
|
||||
class cListChannels: public cChannelIterator
|
||||
{
|
||||
protected:
|
||||
virtual const cChannel* NextChannel(const cChannel *Channel);
|
||||
public:
|
||||
cListChannels();
|
||||
virtual ~cListChannels() {};
|
||||
};
|
||||
|
||||
class cListGroups: public cChannelIterator
|
||||
{
|
||||
protected:
|
||||
virtual const cChannel* NextChannel(const cChannel *Channel);
|
||||
public:
|
||||
cListGroups();
|
||||
virtual ~cListGroups() {};
|
||||
};
|
||||
|
||||
class cListGroup: public cChannelIterator
|
||||
{
|
||||
protected:
|
||||
virtual const cChannel* NextChannel(const cChannel *Channel);
|
||||
public:
|
||||
cListGroup(const cChannel *Group);
|
||||
virtual ~cListGroup() {};
|
||||
};
|
||||
|
||||
class cListTree: public cChannelIterator
|
||||
{
|
||||
private:
|
||||
const cChannel* selectedGroup;
|
||||
const cChannel* currentGroup;
|
||||
protected:
|
||||
virtual const cChannel* NextChannel(const cChannel *Channel);
|
||||
public:
|
||||
cListTree(const cChannel *SelectedGroup);
|
||||
virtual ~cListTree() {};
|
||||
};
|
||||
|
||||
// ******************** cChannelList ******************
|
||||
class cChannelList
|
||||
{
|
||||
private:
|
||||
cChannelIterator *iterator;
|
||||
protected:
|
||||
const cChannel* NextChannel() { return iterator->Next(); }
|
||||
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();
|
||||
};
|
||||
|
||||
class cHtmlChannelList: public cChannelList
|
||||
{
|
||||
private:
|
||||
static const char* menu;
|
||||
static const char* css;
|
||||
static const char* js;
|
||||
|
||||
enum eHtmlState {
|
||||
hsRoot, hsHtmlHead, hsCss, hsJs, hsPageTop, hsPageBottom,
|
||||
hsGroupTop, hsGroupBottom,
|
||||
hsPlainTop, hsPlainItem, hsPlainBottom,
|
||||
hsItemsTop, hsItem, hsItemsBottom
|
||||
};
|
||||
eHtmlState htmlState;
|
||||
const cChannel *current;
|
||||
eStreamType streamType;
|
||||
const char* self;
|
||||
const char* groupTarget;
|
||||
|
||||
std::string StreamTypeMenu();
|
||||
std::string HtmlHead();
|
||||
std::string PageTop();
|
||||
std::string GroupTitle();
|
||||
std::string ItemText();
|
||||
std::string PageBottom();
|
||||
public:
|
||||
virtual std::string HttpHeader() { return cChannelList::HttpHeader() + "Content-type: text/html\r\n\r\n"; }
|
||||
virtual bool HasNext();
|
||||
virtual std::string Next();
|
||||
cHtmlChannelList(cChannelIterator *Iterator, eStreamType StreamType, const char *Self, const char *GroupTarget);
|
||||
virtual ~cHtmlChannelList();
|
||||
};
|
||||
|
||||
class cM3uChannelList: public cChannelList
|
||||
{
|
||||
private:
|
||||
char *base;
|
||||
enum eM3uState { msFirst, msContinue, msLast };
|
||||
eM3uState m3uState;
|
||||
#if defined(APIVERSNUM) && APIVERSNUM >= 10503
|
||||
cCharSetConv m_IConv;
|
||||
#endif
|
||||
public:
|
||||
virtual std::string HttpHeader() { return cChannelList::HttpHeader() + "Content-type: audio/x-mpegurl\r\n"; };
|
||||
virtual bool HasNext();
|
||||
virtual std::string Next();
|
||||
cM3uChannelList(cChannelIterator *Iterator, const char* Base);
|
||||
virtual ~cM3uChannelList();
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user