#include #include #include #include "tools.h" #include "recman.h" #include "epg_events.h" #include "setup.h" using namespace std; namespace vdrlive { /* * ------------------------------------------------------------------------- * EpgInfo * ------------------------------------------------------------------------- */ EpgInfo::EpgInfo(const std::string& id, const std::string& caption) : m_eventId(id), m_caption(caption) { } EpgInfo::~EpgInfo() { } const string EpgInfo::CurrentTime(const char* format) const { return FormatDateTime(format, time(0)); } const string EpgInfo::StartTime(const char* format) const { time_t start = GetStartTime(); return start ? FormatDateTime(format, start) : ""; } const string EpgInfo::EndTime(const char* format) const { time_t end = GetEndTime(); return end ? FormatDateTime(format, end) : ""; } int EpgInfo::Elapsed() const { return EpgEvents::ElapsedTime(GetStartTime(), GetEndTime()); } int EpgInfo::Duration() const { return EpgEvents::Duration(GetStartTime(), GetEndTime()); } /* * ------------------------------------------------------------------------- * EpgEvent * ------------------------------------------------------------------------- */ EpgEvent::EpgEvent(const std::string& id, const cEvent* event, const char* channelName) : EpgInfo(id, channelName), m_event(event) { } EpgEvent::~EpgEvent() { } /* * ------------------------------------------------------------------------- * EpgString * ------------------------------------------------------------------------- */ EpgString::EpgString(const string& id, const string& caption, const string& info) : EpgInfo(id, caption), m_info(info) { } EpgString::~EpgString() { } const string EpgString::Title() const { return m_info; } const string EpgString::ShortDescr() const { return ""; } const string EpgString::LongDescr() const { return ""; } // virtual const std::string Archived() const { return std::string(); } time_t EpgString::GetStartTime() const { return time(0); } time_t EpgString::GetEndTime() const { return time(0); } /* * ------------------------------------------------------------------------- * EpgRecording * ------------------------------------------------------------------------- */ EpgRecording::EpgRecording(const string& recid, const cRecording* recording, const char* caption) : EpgInfo(recid, (caption != 0) ? caption : ""), m_recording(recording), m_ownCaption(caption != 0), m_checkedArchived(false), m_archived() { } EpgRecording::~EpgRecording() { m_recording = 0; } const string EpgRecording::Caption() const { if (m_ownCaption) { return EpgInfo::Caption(); } if (!m_recording) { return ""; } return Name(); } const string EpgRecording::Title() const { if (!m_recording) { return ""; } const cRecordingInfo* info = m_recording->Info(); return (info && info->Title()) ? info->Title() : Name(); } const string EpgRecording::ShortDescr() const { const cRecordingInfo* info = m_recording ? m_recording->Info() : 0; return (info && info->ShortText()) ? info->ShortText() : ""; } const string EpgRecording::LongDescr() const { const cRecordingInfo* info = m_recording ? m_recording->Info() : 0; return (info && info->Description()) ? info->Description() : ""; } const string EpgRecording::Archived() const { if (!m_checkedArchived) { if (m_recording) { m_archived = RecordingsManager::GetArchiveDescr(m_recording); m_checkedArchived = true; } } return m_archived; } time_t EpgRecording::GetStartTime() const { return m_recording ? m_recording->start : 0; } time_t EpgRecording::GetEndTime() const { return m_recording ? m_recording->start : 0; } const string EpgRecording::Name() const { string name(m_recording->Name()); size_t index = name.find_last_of('~'); if (index != string::npos) { name = name.substr(index+1); } return name; } /* * ------------------------------------------------------------------------- * EmptyEvent * ------------------------------------------------------------------------- */ EmptyEvent::EmptyEvent(std::string const &id, tChannelID const &channelID, const char* channelName) : EpgInfo(id, channelName), m_channelID(channelID) { } EmptyEvent::~EmptyEvent() { } /* * ------------------------------------------------------------------------- * EpgEvents * ------------------------------------------------------------------------- */ namespace EpgEvents { string EncodeDomId(tChannelID const &chanId, tEventID const &eId) { string channelId(chanId.ToString()); string eventId("event_"); channelId = vdrlive::EncodeDomId(channelId, ".-", "pm"); eventId += channelId; eventId += '_'; eventId += lexical_cast(eId); return eventId; } void DecodeDomId(string const &epgid, tChannelID& channelId, tEventID& eventId) { string const eventStr("event_"); size_t delimPos = epgid.find_last_of('_'); string cIdStr = epgid.substr(eventStr.length(), delimPos - eventStr.length()); cIdStr = vdrlive::DecodeDomId(cIdStr, "mp", "-."); string const eIdStr = epgid.substr(delimPos+1); channelId = tChannelID::FromString(cIdStr.c_str()); eventId = lexical_cast(eIdStr); } EpgInfoPtr CreateEpgInfo(string const &epgid, cSchedules const *schedules) { string const errorInfo(tr("Epg error")); cSchedulesLock schedulesLock; tEventID eventId = tEventID(); tChannelID channelId = tChannelID(); DecodeDomId(epgid, channelId, eventId); cChannel const *channel = Channels.GetByChannelID(channelId); if (!channel) { return CreateEpgInfo(epgid, errorInfo, tr("Wrong channel id")); } cSchedule const *schedule = schedules->GetSchedule(channel); if (!schedule) { return CreateEpgInfo(epgid, errorInfo, tr("Channel has no schedule")); } cEvent const *event = schedule->GetEvent(eventId); if (!event) { return CreateEpgInfo(epgid, errorInfo, tr("Wrong event id")); } return CreateEpgInfo(channel, event, epgid.c_str()); } EpgInfoPtr CreateEpgInfo(cChannel const *chan, cEvent const *event, char const *idOverride) { if (event) { string domId(idOverride ? idOverride : EncodeDomId(chan->GetChannelID(), event->EventID())); return EpgInfoPtr(new EpgEvent(domId, event, chan->Name())); } if (LiveSetup().GetShowChannelsWithoutEPG()) { string domId(idOverride ? idOverride : EncodeDomId(chan->GetChannelID(), 0)); return EpgInfoPtr(new EmptyEvent(domId, chan->GetChannelID(), chan->Name())); } return EpgInfoPtr(); } EpgInfoPtr CreateEpgInfo(string const &recid, cRecording const *recording, char const *caption) { return EpgInfoPtr(new EpgRecording(recid, recording, caption)); } EpgInfoPtr CreateEpgInfo(string const &id, string const &caption, string const &info) { return EpgInfoPtr(new EpgString(id, caption, info)); } bool ScanForEpgImages(string const & imageId, list & images) { bool found = false; const string filemask(LiveSetup().GetEpgImageDir() + "/" + imageId + "*.*"); glob_t globbuf; globbuf.gl_offs = 0; if (!LiveSetup().GetEpgImageDir().empty() && glob(filemask.c_str(), GLOB_DOOFFS, NULL, &globbuf) == 0) { for(int i=0; i<(int)globbuf.gl_pathc; i++) { const string imagefile(globbuf.gl_pathv[i]); size_t delimPos = imagefile.find_last_of('/'); images.push_back(imagefile.substr(delimPos+1)); found = true; } globfree(&globbuf); } return found; } list EpgImages(string const &epgid) { size_t delimPos = epgid.find_last_of('_'); string imageId = epgid.substr(delimPos+1); list images; if (! ScanForEpgImages(imageId, images)) { // if we didn't get images try to work arround a bug // in tvm2vdr. tvm2vdr seems always to use one digit // less, which leads in some rare cases to the bug in // LIVE, that unrelated and to many images are // displayed. But without this 'fix' no images would // be visible at all. The bug should be fixed in // tvm2vdr.pl (Perl version of tvm2vdr). There exists // a plugin - also called tvm2vdr - which might not // have that bug. imageId = imageId.substr(0, imageId.size()-1); ScanForEpgImages(imageId, images); } return images; } int ElapsedTime(time_t const startTime, time_t const endTime) { // Elapsed time is only meaningful when there is a non zero // duration (e.g. startTime != endTime and endTime > startTime) int duration = Duration(startTime, endTime); if (duration > 0) { time_t now = time(0); if ((startTime <= now) && (now <= endTime)) { return 100 * (now - startTime) / duration; } } return -1; } int Duration(time_t const startTime, time_t const endTime) { return endTime - startTime; } } // namespace EpgEvents }; // namespace vdrlive