mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 19:16:51 +02:00
Added RSS format for HTTP menus
This commit is contained in:
parent
176df8341d
commit
9bbb74b7fd
1
HISTORY
1
HISTORY
@ -1,6 +1,7 @@
|
||||
VDR Plugin 'streamdev' Revision History
|
||||
---------------------------------------
|
||||
|
||||
- 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)
|
||||
- Basic support for HTTP streaming of recordings
|
||||
|
@ -417,13 +417,7 @@ cChannelList* cConnectionHTTP::ChannelListFromString(const std::string& Path, co
|
||||
}
|
||||
|
||||
if (iterator) {
|
||||
if (Filebase.empty() || Fileext.compare(".htm") == 0 || Fileext.compare(".html") == 0) {
|
||||
std::string self = Filebase + Fileext;
|
||||
tStrStrMap::const_iterator it = Headers().find("QUERY_STRING");
|
||||
if (it != Headers().end() && !it->second.empty())
|
||||
self += '?' + it->second;
|
||||
return new cHtmlChannelList(iterator, m_StreamType, self.c_str(), groupTarget.c_str());
|
||||
} else if (Fileext.compare(".m3u") == 0) {
|
||||
// assemble base url: http://host/path/
|
||||
std::string base;
|
||||
const static std::string HOST("HTTP_HOST");
|
||||
tStrStrMap::const_iterator it = Headers().find(HOST);
|
||||
@ -433,7 +427,25 @@ cChannelList* cConnectionHTTP::ChannelListFromString(const std::string& Path, co
|
||||
base = (std::string) "http://" + LocalIp() + ":" +
|
||||
(const char*) itoa(StreamdevServerSetup.HTTPServerPort) + "/";
|
||||
base += Path;
|
||||
|
||||
if (Filebase.empty() || Fileext.compare(".htm") == 0 || Fileext.compare(".html") == 0) {
|
||||
std::string self = Filebase + Fileext;
|
||||
std::string rss = Filebase + ".rss";
|
||||
tStrStrMap::const_iterator it = Headers().find("QUERY_STRING");
|
||||
if (it != Headers().end() && !it->second.empty()) {
|
||||
self += '?' + it->second;
|
||||
rss += '?' + it->second;
|
||||
}
|
||||
return new cHtmlChannelList(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());
|
||||
} 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());
|
||||
} else {
|
||||
delete iterator;
|
||||
}
|
||||
|
@ -119,8 +119,8 @@ const cChannel* cChannelList::GetGroup(int Index)
|
||||
const char* cHtmlChannelList::menu =
|
||||
"[<a href=\"/\">Home</a> (<a href=\"all.html\" tvid=\"RED\">no script</a>)] "
|
||||
"[<a href=\"tree.html\" tvid=\"GREEN\">Tree View</a>] "
|
||||
"[<a href=\"groups.html\" tvid=\"YELLOW\">Groups</a> (<a href=\"groups.m3u\">Playlist</a>)] "
|
||||
"[<a href=\"channels.html\" tvid=\"BLUE\">Channels</a> (<a href=\"channels.m3u\">Playlist</a>)] ";
|
||||
"[<a href=\"groups.html\" tvid=\"YELLOW\">Groups</a> (<a href=\"groups.m3u\">Playlist</a> | <a href=\"groups.rss\">RSS</a>)] "
|
||||
"[<a href=\"channels.html\" tvid=\"BLUE\">Channels</a> (<a href=\"channels.m3u\">Playlist</a> | <a href=\"channels.rss\">RSS</a>)] ";
|
||||
|
||||
const char* cHtmlChannelList::css =
|
||||
"<style type=\"text/css\">\n"
|
||||
@ -215,10 +215,11 @@ std::string cHtmlChannelList::StreamTypeMenu()
|
||||
return typeMenu;
|
||||
}
|
||||
|
||||
cHtmlChannelList::cHtmlChannelList(cChannelIterator *Iterator, eStreamType StreamType, const char *Self, const char *GroupTarget): cChannelList(Iterator)
|
||||
cHtmlChannelList::cHtmlChannelList(cChannelIterator *Iterator, eStreamType StreamType, const char *Self, const char *Rss, const char *GroupTarget): cChannelList(Iterator)
|
||||
{
|
||||
streamType = StreamType;
|
||||
self = strdup(Self);
|
||||
rss = strdup(Rss);
|
||||
groupTarget = (GroupTarget && *GroupTarget) ? strdup(GroupTarget) : NULL;
|
||||
htmlState = hsRoot;
|
||||
current = NULL;
|
||||
@ -227,6 +228,7 @@ cHtmlChannelList::cHtmlChannelList(cChannelIterator *Iterator, eStreamType Strea
|
||||
cHtmlChannelList::~cHtmlChannelList()
|
||||
{
|
||||
free((void *) self);
|
||||
free((void *) rss);
|
||||
free((void *) groupTarget);
|
||||
}
|
||||
|
||||
@ -311,7 +313,7 @@ std::string cHtmlChannelList::Next()
|
||||
|
||||
std::string cHtmlChannelList::HtmlHead()
|
||||
{
|
||||
return (std::string) "";
|
||||
return (std::string) "<link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS\" href=\"" + rss + "\"/>";
|
||||
}
|
||||
|
||||
std::string cHtmlChannelList::PageTop()
|
||||
@ -432,3 +434,63 @@ std::string cM3uChannelList::Next()
|
||||
}
|
||||
}
|
||||
|
||||
// ******************** cRssChannelList ******************
|
||||
cRssChannelList::cRssChannelList(cChannelIterator *Iterator, const char *Base, const char *Html)
|
||||
: cChannelList(Iterator),
|
||||
m_IConv(cCharSetConv::SystemCharacterTable(), "UTF-8")
|
||||
{
|
||||
base = strdup(Base);
|
||||
html = strdup(Html);
|
||||
rssState = msFirst;
|
||||
}
|
||||
|
||||
cRssChannelList::~cRssChannelList()
|
||||
{
|
||||
free(base);
|
||||
free(html);
|
||||
}
|
||||
|
||||
bool cRssChannelList::HasNext()
|
||||
{
|
||||
return rssState != msLast;
|
||||
}
|
||||
|
||||
std::string cRssChannelList::Next()
|
||||
{
|
||||
std::string type_ext;
|
||||
|
||||
if (rssState == msFirst)
|
||||
{
|
||||
rssState = msContinue;
|
||||
return (std::string) "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<rss version=\"2.0\">\n\t<channel>\n"
|
||||
"\t\t<title>VDR</title>\n"
|
||||
"\t\t<link>" + base + html + "</link>\n"
|
||||
"\t\t<description>VDR channel list</description>\n"
|
||||
;
|
||||
}
|
||||
|
||||
const cChannel *channel = NextChannel();
|
||||
if (!channel)
|
||||
{
|
||||
rssState = msLast;
|
||||
return "\t</channel>\n</rss>\n";
|
||||
}
|
||||
|
||||
std::string name = (std::string) m_IConv.Convert(channel->Name());
|
||||
|
||||
if (channel->GroupSep())
|
||||
{
|
||||
return (std::string) "\t\t<item>\n\t\t\t<title>" +
|
||||
name + "</title>\n\t\t\t<link>" +
|
||||
base + "group.rss?group=" + (const char*) itoa(cChannelList::GetGroupIndex(channel)) + "</link>\n\t\t</item>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
return (std::string) "\t\t<item>\n\t\t\t<title>" +
|
||||
(const char*) itoa(channel->Number()) + " " + name + "</title>\n\t\t\t<link>" +
|
||||
base + (std::string) channel->GetChannelID().ToString() + "</link>\n\t\t\t<enclosure url=\"" +
|
||||
base + (std::string) channel->GetChannelID().ToString() + "\" type=\"video/mpeg\" />\n\t\t</item>\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -107,6 +107,7 @@ class cHtmlChannelList: public cChannelList
|
||||
const cChannel *current;
|
||||
eStreamType streamType;
|
||||
const char* self;
|
||||
const char* rss;
|
||||
const char* groupTarget;
|
||||
|
||||
std::string StreamTypeMenu();
|
||||
@ -124,7 +125,7 @@ class cHtmlChannelList: public cChannelList
|
||||
}
|
||||
virtual bool HasNext();
|
||||
virtual std::string Next();
|
||||
cHtmlChannelList(cChannelIterator *Iterator, eStreamType StreamType, const char *Self, const char *GroupTarget);
|
||||
cHtmlChannelList(cChannelIterator *Iterator, eStreamType StreamType, const char *Self, const char *Rss, const char *GroupTarget);
|
||||
virtual ~cHtmlChannelList();
|
||||
};
|
||||
|
||||
@ -143,6 +144,23 @@ class cM3uChannelList: public cChannelList
|
||||
virtual ~cM3uChannelList();
|
||||
};
|
||||
|
||||
class cRssChannelList: public cChannelList
|
||||
{
|
||||
private:
|
||||
char *base;
|
||||
char *html;
|
||||
enum eRssState { msFirst, msContinue, msLast };
|
||||
eRssState rssState;
|
||||
cCharSetConv m_IConv;
|
||||
public:
|
||||
virtual std::string HttpHeader() { return cChannelList::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();
|
||||
};
|
||||
|
||||
inline const cChannel* cChannelIterator::SkipFakeGroups(const cChannel* Group)
|
||||
{
|
||||
while (Group && Group->GroupSep() && !*Group->Name())
|
||||
|
Loading…
Reference in New Issue
Block a user