diff --git a/COPYING b/COPYING index f90922e..fe40b44 100644 --- a/COPYING +++ b/COPYING @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -56,7 +56,7 @@ patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - GNU GENERAL PUBLIC LICENSE + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS + END OF TERMS AND CONDITIONS - How to Apply These Terms to Your New Programs + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it diff --git a/README b/README index d1fda8f..cc14eb3 100644 --- a/README +++ b/README @@ -37,9 +37,9 @@ Requirements: VDR >= 2.4.0 gcc >= v8, must support -std=c++17 -PCRE2 >= 10.38 - https://github.com/PhilipHazel/pcre2/releases -Tntnet >= 2.2.1 - http://www.tntnet.org/download.hms // https://web.archive.org/web/20160314183814/http://www.tntnet.org/download.html -Cxxtools >= 2.2.1 - http://www.tntnet.org/download.hms // https://web.archive.org/web/20160314183814/http://www.tntnet.org/download.html +PCRE2 >= 10.38 - https://github.com/PhilipHazel/pcre2/releases +Tntnet >= 2.2.1 - http://www.tntnet.org/download.hms // https://web.archive.org/web/20160314183814/http://www.tntnet.org/download.html +Cxxtools >= 2.2.1 - http://www.tntnet.org/download.hms // https://web.archive.org/web/20160314183814/http://www.tntnet.org/download.html Tntnet provides basic Web server functions for live and needs cxxtools. Boost provides some data structures we need. While currently relying on the @@ -52,7 +52,7 @@ If you optionally want to regenerate the i18n-generated.h header file for backward compatible i18n (VDR version prior to 1.5.7) you also need: (See also the Internationalization section below) -Locale::PO - Perl module from CPAN www.cpan.org +Locale::PO - Perl module from CPAN www.cpan.org The default i18n-generated.h header contains all translations from GIT. Users that just want to stay on bleeding development @@ -91,7 +91,7 @@ Setup: Live provides a username/password protection, so that it can be used from the internet. The default username and password are: - admin/live + admin/live The default port is 8008. @@ -108,10 +108,10 @@ for SSL connections" section below on hints how to setup SSL. To display images or channel logos, you can use: - -e <...> --epgimages=/path/to/epgimages use EPG images created by plugins like tvm2vdr - -t <...> --tvscraperimages=/path/to/tvscraperimages use images created by tvscraper DEPRECATED! - -f <...> --ffmpegconf=conf-filename use filename to acquire FFMPEG commands - --chanlogos=/path/to/channellogos use channel logos (PNG only, case sensitive) + -e <...> --epgimages=/path/to/epgimages use EPG images created by plugins like tvm2vdr + -t <...> --tvscraperimages=/path/to/tvscraperimages use images created by tvscraper DEPRECATED! + -f <...> --ffmpegconf=conf-filename use filename to acquire FFMPEG commands + --chanlogos=/path/to/channellogos use channel logos (PNG only, case sensitive) Example: --tvscraperimages=/var/cache/vdr/plugins/tvscraper DEPRECATED! Note: tvscraperimages is not required any more, live uses the internal service interface "GetEnvironment" for plugins to get this information from tvscraper/scraper2vdr @@ -135,7 +135,7 @@ How to make LIVE listen for SSL connections: To make LIVE listen for incoming SSL connections you`ll have to use a Tntnet version > 1.6.0.6. By default it will listen on port 8443. - * Example: https://localhost:8443 + * Example: https://localhost:8443 In order to start the SslListener LIVE requires a SSL certificate. If no SSL certificate is specified via command-line option, LIVE will try @@ -162,9 +162,9 @@ SSL Command-line options: (default: 8443) use PORT 0 to disable incoming SSL connections -c CERT, --cert=CERT path to a custom SSL certificate file - (default: $CONFIGDIR/live.pem) + (default: $CONFIGDIR/live.pem) -k KEY, --cert=CERT path to a custom SSL certificate key file - (default: $CONFIGDIR/live-key.pem) + (default: $CONFIGDIR/live-key.pem) Creating a self-signed SSL server certificate: diff --git a/cache.h b/cache.h index 29a52f2..d5a63b5 100644 --- a/cache.h +++ b/cache.h @@ -20,76 +20,76 @@ template> class cache { public: - typedef TKey key_type; - typedef TValue mapped_type; - typedef std::shared_ptr ptr_type; + typedef TKey key_type; + typedef TValue mapped_type; + typedef std::shared_ptr ptr_type; private: - typedef std::pair value_type; + typedef std::pair value_type; - typedef std::list ValueList; - typedef std::map KeyMap; + typedef std::list ValueList; + typedef std::map KeyMap; public: - cache( size_t maxWeight ) - : m_maxWeight( maxWeight ) - , m_currentWeight( 0 ) {} - - size_t weight() const { return m_currentWeight; } - size_t count() const { return m_values.size(); } - - ptr_type get( key_type const& key ) - { - assert( m_lookup.size() == m_values.size() ); - - typename KeyMap::iterator it = m_lookup.find( key ); - ptr_type result = it != m_lookup.end() ? it->second->second : ptr_type( new mapped_type( key ) ); - - if ( it != m_lookup.end() ) { - if ( result->is_current() ) { - if ( it->second != m_values.begin() ) { - m_values.erase( it->second ); - it->second = m_values.insert( m_values.begin(), std::make_pair( key, result ) ); - } - return result; - } - - m_currentWeight -= result->weight(); - m_values.erase( it->second ); - } - - if ( !result->load() ) { - if ( it != m_lookup.end() ) - m_lookup.erase( it ); - return ptr_type(); - } - - // put new object into cache - if ( result->weight() < m_maxWeight ) { - m_currentWeight += result->weight(); - - typename ValueList::iterator element = m_values.insert( m_values.begin(), std::make_pair( key, result ) ); - if ( it != m_lookup.end() ) - it->second = element; - else - m_lookup.insert( std::make_pair( key, element ) ); - - while ( m_currentWeight > m_maxWeight ) { - value_type& value = m_values.back(); - m_currentWeight -= value.second->weight(); - m_lookup.erase( m_lookup.find( value.first ) ); - m_values.pop_back(); - } - } - - return result; - } + cache( size_t maxWeight ) + : m_maxWeight( maxWeight ) + , m_currentWeight( 0 ) {} + + size_t weight() const { return m_currentWeight; } + size_t count() const { return m_values.size(); } + + ptr_type get( key_type const& key ) + { + assert( m_lookup.size() == m_values.size() ); + + typename KeyMap::iterator it = m_lookup.find( key ); + ptr_type result = it != m_lookup.end() ? it->second->second : ptr_type( new mapped_type( key ) ); + + if ( it != m_lookup.end() ) { + if ( result->is_current() ) { + if ( it->second != m_values.begin() ) { + m_values.erase( it->second ); + it->second = m_values.insert( m_values.begin(), std::make_pair( key, result ) ); + } + return result; + } + + m_currentWeight -= result->weight(); + m_values.erase( it->second ); + } + + if ( !result->load() ) { + if ( it != m_lookup.end() ) + m_lookup.erase( it ); + return ptr_type(); + } + + // put new object into cache + if ( result->weight() < m_maxWeight ) { + m_currentWeight += result->weight(); + + typename ValueList::iterator element = m_values.insert( m_values.begin(), std::make_pair( key, result ) ); + if ( it != m_lookup.end() ) + it->second = element; + else + m_lookup.insert( std::make_pair( key, element ) ); + + while ( m_currentWeight > m_maxWeight ) { + value_type& value = m_values.back(); + m_currentWeight -= value.second->weight(); + m_lookup.erase( m_lookup.find( value.first ) ); + m_values.pop_back(); + } + } + + return result; + } private: - std::size_t m_maxWeight; - std::size_t m_currentWeight; - ValueList m_values; - KeyMap m_lookup; + std::size_t m_maxWeight; + std::size_t m_currentWeight; + ValueList m_values; + KeyMap m_lookup; }; } // namespace vgstools diff --git a/epg_events.cpp b/epg_events.cpp index a9f6d0a..091de0e 100644 --- a/epg_events.cpp +++ b/epg_events.cpp @@ -20,278 +20,278 @@ namespace vdrlive { - /* - * ------------------------------------------------------------------------- - * EpgInfo - * ------------------------------------------------------------------------- - */ - - EpgInfo::EpgInfo(cSv id, cSv caption): - m_eventId(id), - m_caption(caption) - { } - - EpgInfo::~EpgInfo() { } - - cSv EpgInfo::ChannelName() const - { const cChannel* channel = Channel(); - return channel ? channel->Name() : cSv(); - } - - const std::string EpgInfo::CurrentTime(const char* format) const - { - return std::string(cToSvDateTime(format, time(0))); - } - - const std::string EpgInfo::StartTime(const char* format) const - { - time_t start = GetStartTime(); - return start ? std::string(cToSvDateTime(format, start)) : ""; - } - - const std::string EpgInfo::EndTime(const char* format) const - { - time_t end = GetEndTime(); - return end ? std::string(cToSvDateTime(format, end)) : ""; - } - - int EpgInfo::Elapsed() const - { - return EpgEvents::ElapsedTime(GetStartTime(), GetEndTime()); - } - - int EpgInfo::Duration() const - { - return EpgEvents::Duration(GetStartTime(), GetEndTime()); - } - - /* - * ------------------------------------------------------------------------- - * EpgEvent - * ------------------------------------------------------------------------- - */ - - EpgEvent::EpgEvent(cSv id, const cEvent* event, const char* channelName) : - EpgInfo(id, channelName), - m_event(event) - { } - - EpgEvent::~EpgEvent() { } - - /* - * ------------------------------------------------------------------------- - * EpgString - * ------------------------------------------------------------------------- - */ - - EpgString::EpgString(cSv id, cSv caption, cSv info) : - EpgInfo(id, caption), - m_info(info) - { } - - EpgString::~EpgString() { } - - cSv EpgString::Title() const - { - return m_info; - } - - cSv EpgString::ShortDescr() const - { - return cSv(); - } - - cSv EpgString::LongDescr() const - { - return cSv(); - } - - time_t EpgString::GetStartTime() const - { - return time(0); - } - - time_t EpgString::GetEndTime() const - { - return time(0); - } - - /* - * ------------------------------------------------------------------------- - * EpgRecording - * ------------------------------------------------------------------------- - */ - - EpgRecording::EpgRecording(cSv recid, const cRecording* recording, const char* caption) : - EpgInfo(recid, caption), - m_recording(recording), - m_ownCaption(caption != 0), - m_checkedArchived(false), - m_archived() - { } - - EpgRecording::~EpgRecording() - { - m_recording = 0; - } - - cSv EpgRecording::Caption() const - { - if (m_ownCaption) { - return EpgInfo::Caption(); - } - if (!m_recording) { - return cSv(); - } - - return Name(); - } - - cSv EpgRecording::Title() const - { - if (!m_recording) { - return cSv(); - } - - const cRecordingInfo* info = m_recording->Info(); - return (info && info->Title()) ? info->Title() : Name(); - } - - cSv EpgRecording::ShortDescr() const - { - const cRecordingInfo* info = m_recording ? m_recording->Info() : 0; - return (info && info->ShortText()) ? info->ShortText() : cSv(); - } - - cSv EpgRecording::LongDescr() const - { - const cRecordingInfo* info = m_recording ? m_recording->Info() : 0; - return (info && info->Description()) ? info->Description() : cSv(); - } - - cSv EpgRecording::ChannelName() const - { - const cRecordingInfo* info = m_recording ? m_recording->Info() : 0; - return info && info->ChannelName() ? info->ChannelName(): cSv(); - } - - cSv EpgRecording::Archived() const - { - if (!m_checkedArchived && m_recording) { - m_archived = RecordingsManager::GetArchiveDescr(m_recording); - m_checkedArchived = true; - } - return m_archived; - } - - cSv EpgRecording::FileName() const - { - return m_recording->FileName(); - } - - time_t EpgRecording::GetStartTime() const - { - return m_recording ? m_recording->Start() : 0; - } - - time_t EpgRecording::GetEndTime() const - { - time_t endTime = 0; - if (m_recording) - { - time_t startTime = m_recording->Start(); - int length = m_recording->LengthInSeconds(); - - endTime = (length < 0) ? startTime : startTime + length; - } - return endTime; - } - int EpgRecording::EventDuration() const - { - const cRecordingInfo* info = m_recording ? m_recording->Info() : 0; + /* + * ------------------------------------------------------------------------- + * EpgInfo + * ------------------------------------------------------------------------- + */ + + EpgInfo::EpgInfo(cSv id, cSv caption): + m_eventId(id), + m_caption(caption) + { } + + EpgInfo::~EpgInfo() { } + + cSv EpgInfo::ChannelName() const + { const cChannel* channel = Channel(); + return channel ? channel->Name() : cSv(); + } + + const std::string EpgInfo::CurrentTime(const char* format) const + { + return std::string(cToSvDateTime(format, time(0))); + } + + const std::string EpgInfo::StartTime(const char* format) const + { + time_t start = GetStartTime(); + return start ? std::string(cToSvDateTime(format, start)) : ""; + } + + const std::string EpgInfo::EndTime(const char* format) const + { + time_t end = GetEndTime(); + return end ? std::string(cToSvDateTime(format, end)) : ""; + } + + int EpgInfo::Elapsed() const + { + return EpgEvents::ElapsedTime(GetStartTime(), GetEndTime()); + } + + int EpgInfo::Duration() const + { + return EpgEvents::Duration(GetStartTime(), GetEndTime()); + } + + /* + * ------------------------------------------------------------------------- + * EpgEvent + * ------------------------------------------------------------------------- + */ + + EpgEvent::EpgEvent(cSv id, const cEvent* event, const char* channelName) : + EpgInfo(id, channelName), + m_event(event) + { } + + EpgEvent::~EpgEvent() { } + + /* + * ------------------------------------------------------------------------- + * EpgString + * ------------------------------------------------------------------------- + */ + + EpgString::EpgString(cSv id, cSv caption, cSv info) : + EpgInfo(id, caption), + m_info(info) + { } + + EpgString::~EpgString() { } + + cSv EpgString::Title() const + { + return m_info; + } + + cSv EpgString::ShortDescr() const + { + return cSv(); + } + + cSv EpgString::LongDescr() const + { + return cSv(); + } + + time_t EpgString::GetStartTime() const + { + return time(0); + } + + time_t EpgString::GetEndTime() const + { + return time(0); + } + + /* + * ------------------------------------------------------------------------- + * EpgRecording + * ------------------------------------------------------------------------- + */ + + EpgRecording::EpgRecording(cSv recid, const cRecording* recording, const char* caption) : + EpgInfo(recid, caption), + m_recording(recording), + m_ownCaption(caption != 0), + m_checkedArchived(false), + m_archived() + { } + + EpgRecording::~EpgRecording() + { + m_recording = 0; + } + + cSv EpgRecording::Caption() const + { + if (m_ownCaption) { + return EpgInfo::Caption(); + } + if (!m_recording) { + return cSv(); + } + + return Name(); + } + + cSv EpgRecording::Title() const + { + if (!m_recording) { + return cSv(); + } + + const cRecordingInfo* info = m_recording->Info(); + return (info && info->Title()) ? info->Title() : Name(); + } + + cSv EpgRecording::ShortDescr() const + { + const cRecordingInfo* info = m_recording ? m_recording->Info() : 0; + return (info && info->ShortText()) ? info->ShortText() : cSv(); + } + + cSv EpgRecording::LongDescr() const + { + const cRecordingInfo* info = m_recording ? m_recording->Info() : 0; + return (info && info->Description()) ? info->Description() : cSv(); + } + + cSv EpgRecording::ChannelName() const + { + const cRecordingInfo* info = m_recording ? m_recording->Info() : 0; + return info && info->ChannelName() ? info->ChannelName(): cSv(); + } + + cSv EpgRecording::Archived() const + { + if (!m_checkedArchived && m_recording) { + m_archived = RecordingsManager::GetArchiveDescr(m_recording); + m_checkedArchived = true; + } + return m_archived; + } + + cSv EpgRecording::FileName() const + { + return m_recording->FileName(); + } + + time_t EpgRecording::GetStartTime() const + { + return m_recording ? m_recording->Start() : 0; + } + + time_t EpgRecording::GetEndTime() const + { + time_t endTime = 0; + if (m_recording) + { + time_t startTime = m_recording->Start(); + int length = m_recording->LengthInSeconds(); + + endTime = (length < 0) ? startTime : startTime + length; + } + return endTime; + } + int EpgRecording::EventDuration() const + { + const cRecordingInfo* info = m_recording ? m_recording->Info() : 0; if (!info || !info->GetEvent() ) return 0; - return info->GetEvent()->Duration(); - } - - int EpgRecording::Elapsed() const - { - if (!m_recording) - return -1; - int current, total; - // try currently playing recording if any + return info->GetEvent()->Duration(); + } + + int EpgRecording::Elapsed() const + { + if (!m_recording) + return -1; + int current, total; + // try currently playing recording if any #if APIVERSNUM >= 20402 - cMutexLock mutexLock; - cControl* pControl = cControl::Control(mutexLock); + cMutexLock mutexLock; + cControl* pControl = cControl::Control(mutexLock); #else - cControl* pControl = cControl::Control(); + cControl* pControl = cControl::Control(); #endif - if (pControl) - { - const cRecording* playing = pControl->GetRecording(); - if (playing && playing->Id() == m_recording->Id() - && pControl->GetIndex(current,total) && total) - return (100 * current) / total; - } - // Check for resume position next - current = m_recording->GetResume(); - total= m_recording->NumFrames(); - if (current > 0 && total > 0) - return (100 * current) / total; - return -1; - } - - cSv EpgRecording::Name() const - { - cSv name(m_recording->Name()); - size_t index = name.find_last_of('~'); - if (index != std::string::npos) { - name = name.substr(index+1); - } - return name; - } - - /* - * ------------------------------------------------------------------------- - * EmptyEvent - * ------------------------------------------------------------------------- - */ - - EmptyEvent::EmptyEvent(cSv id, tChannelID const &channelID, const char* channelName) : - EpgInfo(id, channelName), - m_channelID(channelID) - { } - - EmptyEvent::~EmptyEvent() { } - - /* - * ------------------------------------------------------------------------- - * EpgEvents - * ------------------------------------------------------------------------- - */ - namespace EpgEvents { - std::string EncodeDomId(tChannelID const &chanId, tEventID const &eId) - { - std::string eventId("event_"); - - eventId += vdrlive::EncodeDomId(cToSvConcat(chanId), ".-", "pm"); - eventId += '_'; - eventId += cSv(cToSvInt(eId)); - return eventId; - } - - void DecodeDomId(cSv epgid, tChannelID& channelId, tEventID& eventId) - { - cSv eventStr("event_"); - - size_t delimPos = epgid.find_last_of('_'); - cSv cIdStr_enc = epgid.substr(eventStr.length(), delimPos - eventStr.length()); - - std::string cIdStr = vdrlive::DecodeDomId(cIdStr_enc, "mp", "-."); - cSv eIdStr = epgid.substr(delimPos+1); - - channelId = tChannelID::FromString(cIdStr.c_str()); - eventId = parse_int(eIdStr); - } + if (pControl) + { + const cRecording* playing = pControl->GetRecording(); + if (playing && playing->Id() == m_recording->Id() + && pControl->GetIndex(current,total) && total) + return (100 * current) / total; + } + // Check for resume position next + current = m_recording->GetResume(); + total= m_recording->NumFrames(); + if (current > 0 && total > 0) + return (100 * current) / total; + return -1; + } + + cSv EpgRecording::Name() const + { + cSv name(m_recording->Name()); + size_t index = name.find_last_of('~'); + if (index != std::string::npos) { + name = name.substr(index+1); + } + return name; + } + + /* + * ------------------------------------------------------------------------- + * EmptyEvent + * ------------------------------------------------------------------------- + */ + + EmptyEvent::EmptyEvent(cSv id, tChannelID const &channelID, const char* channelName) : + EpgInfo(id, channelName), + m_channelID(channelID) + { } + + EmptyEvent::~EmptyEvent() { } + + /* + * ------------------------------------------------------------------------- + * EpgEvents + * ------------------------------------------------------------------------- + */ + namespace EpgEvents { + std::string EncodeDomId(tChannelID const &chanId, tEventID const &eId) + { + std::string eventId("event_"); + + eventId += vdrlive::EncodeDomId(cToSvConcat(chanId), ".-", "pm"); + eventId += '_'; + eventId += cSv(cToSvInt(eId)); + return eventId; + } + + void DecodeDomId(cSv epgid, tChannelID& channelId, tEventID& eventId) + { + cSv eventStr("event_"); + + size_t delimPos = epgid.find_last_of('_'); + cSv cIdStr_enc = epgid.substr(eventStr.length(), delimPos - eventStr.length()); + + std::string cIdStr = vdrlive::DecodeDomId(cIdStr_enc, "mp", "-."); + cSv eIdStr = epgid.substr(delimPos+1); + + channelId = tChannelID::FromString(cIdStr.c_str()); + eventId = parse_int(eIdStr); + } const cEvent *GetEventByEpgid(cSv epgid) { tChannelID channelid = tChannelID(); @@ -308,123 +308,123 @@ namespace vdrlive #endif } - EpgInfoPtr CreateEpgInfo(cSv epgid, cSchedules const *schedules) - { - tEventID eventId = tEventID(); - tChannelID channelId = tChannelID(); - - DecodeDomId(epgid, channelId, eventId); - LOCK_CHANNELS_READ; - cChannel const *channel = Channels->GetByChannelID(channelId); - if (!channel) { - return CreateEpgInfo(epgid, tr("Epg error"), tr("Wrong channel id")); - } - cSchedule const *schedule = schedules->GetSchedule(channel); - if (!schedule) { - return CreateEpgInfo(epgid, tr("Epg error"), tr("Channel has no schedule")); - } + EpgInfoPtr CreateEpgInfo(cSv epgid, cSchedules const *schedules) + { + tEventID eventId = tEventID(); + tChannelID channelId = tChannelID(); + + DecodeDomId(epgid, channelId, eventId); + LOCK_CHANNELS_READ; + cChannel const *channel = Channels->GetByChannelID(channelId); + if (!channel) { + return CreateEpgInfo(epgid, tr("Epg error"), tr("Wrong channel id")); + } + cSchedule const *schedule = schedules->GetSchedule(channel); + if (!schedule) { + return CreateEpgInfo(epgid, tr("Epg error"), tr("Channel has no schedule")); + } #if APIVERSNUM >= 20502 - cEvent const *event = schedule->GetEventById(eventId); + cEvent const *event = schedule->GetEventById(eventId); #else - cEvent const *event = schedule->GetEvent(eventId); + cEvent const *event = schedule->GetEvent(eventId); #endif - if (!event) { - return CreateEpgInfo(epgid, tr("Epg error"), tr("Wrong event id")); - } - return CreateEpgInfo(channel, event, epgid); - } + if (!event) { + return CreateEpgInfo(epgid, tr("Epg error"), tr("Wrong event id")); + } + return CreateEpgInfo(channel, event, epgid); + } - EpgInfoPtr CreateEpgInfo(cChannel const *chan, cEvent const *event, cSv idOverride) - { - assert(chan); + EpgInfoPtr CreateEpgInfo(cChannel const *chan, cEvent const *event, cSv idOverride) + { + assert(chan); - if (event) { + if (event) { if (idOverride.empty()) return std::make_shared(EncodeDomId(chan->GetChannelID(), event->EventID()), event, chan->Name()); return std::make_shared(idOverride, event, chan->Name()); - } - if (LiveSetup().GetShowChannelsWithoutEPG()) { - std::string domId(!idOverride.empty() ? idOverride : EncodeDomId(chan->GetChannelID(), 0)); - return std::make_shared(domId, chan->GetChannelID(), chan->Name()); - } - return EpgInfoPtr(); - } - - EpgInfoPtr CreateEpgInfo(cSv recid, cRecording const *recording, char const *caption) - { - return std::make_shared(recid, recording, caption); - } - - EpgInfoPtr CreateEpgInfo(cSv id, cSv caption, cSv info) - { - return std::make_shared(id, caption, info); - } - - - bool ScanForEpgImages(cSv imageId, cSv wildcard, std::list & images) - { - bool found = false; - const std::string filemask = concat(LiveSetup().GetEpgImageDir(), "/", imageId, wildcard); - glob_t globbuf; - globbuf.gl_offs = 0; - if (!LiveSetup().GetEpgImageDir().empty() && glob(filemask.c_str(), GLOB_DOOFFS, NULL, &globbuf) == 0) { - for(size_t i = 0; i < globbuf.gl_pathc; i++) { - const std::string_view imagefile(globbuf.gl_pathv[i]); - size_t delimPos = imagefile.find_last_of('/'); - images.push_back(std::move(std::string(imagefile.substr(delimPos+1)))); - found = true; - } - globfree(&globbuf); - } - return found; - } - bool ScanForEpgImages(cSv channelId, cSv eventId, cSv wildcard, std::list & images) - { + } + if (LiveSetup().GetShowChannelsWithoutEPG()) { + std::string domId(!idOverride.empty() ? idOverride : EncodeDomId(chan->GetChannelID(), 0)); + return std::make_shared(domId, chan->GetChannelID(), chan->Name()); + } + return EpgInfoPtr(); + } + + EpgInfoPtr CreateEpgInfo(cSv recid, cRecording const *recording, char const *caption) + { + return std::make_shared(recid, recording, caption); + } + + EpgInfoPtr CreateEpgInfo(cSv id, cSv caption, cSv info) + { + return std::make_shared(id, caption, info); + } + + + bool ScanForEpgImages(cSv imageId, cSv wildcard, std::list & images) + { + bool found = false; + const std::string filemask = concat(LiveSetup().GetEpgImageDir(), "/", imageId, wildcard); + glob_t globbuf; + globbuf.gl_offs = 0; + if (!LiveSetup().GetEpgImageDir().empty() && glob(filemask.c_str(), GLOB_DOOFFS, NULL, &globbuf) == 0) { + for(size_t i = 0; i < globbuf.gl_pathc; i++) { + const std::string_view imagefile(globbuf.gl_pathv[i]); + size_t delimPos = imagefile.find_last_of('/'); + images.push_back(std::move(std::string(imagefile.substr(delimPos+1)))); + found = true; + } + globfree(&globbuf); + } + return found; + } + bool ScanForEpgImages(cSv channelId, cSv eventId, cSv wildcard, std::list & images) + { if (LiveSetup().GetEpgImageDir().empty() ) return false; - if (ScanForEpgImages(cToSvConcat(channelId, "_", eventId), wildcard, images)) return true; - return ScanForEpgImages(eventId, wildcard, images); + if (ScanForEpgImages(cToSvConcat(channelId, "_", eventId), wildcard, images)) return true; + return ScanForEpgImages(eventId, wildcard, images); } - bool ScanForRecImages(cSv imageId, cSv recfolder , std::list & images) - { + bool ScanForRecImages(cSv imageId, cSv recfolder , std::list & images) + { // format of imageId: - if (recfolder.empty()) return false; - - bool found = false; - const std::string filetypes[] = {"png", "jpg", "webp", "PNG", "JPG"}; - int size = sizeof(filetypes)/sizeof(filetypes[0]); - - for (int j = 0; j < size; j++) - { - const std::string filemask = concat(recfolder, "/*.", filetypes[j]); - glob_t globbuf; - globbuf.gl_offs = 0; - if (glob(filemask.c_str(), GLOB_DOOFFS, NULL, &globbuf) == 0) { - for(size_t i = 0; i < globbuf.gl_pathc; i++) { - const std::string_view imagefile(globbuf.gl_pathv[i]); - size_t delimPos = imagefile.find_last_of('/'); - const std::string_view imagename(imagefile.substr(delimPos+1)); - images.push_back(std::move(std::string(imagename))); - - // create a temporary symlink of the image in /tmp - cToSvConcat tmpfile("/tmp/", imageId, "_", imagename); + if (recfolder.empty()) return false; + + bool found = false; + const std::string filetypes[] = {"png", "jpg", "webp", "PNG", "JPG"}; + int size = sizeof(filetypes)/sizeof(filetypes[0]); + + for (int j = 0; j < size; j++) + { + const std::string filemask = concat(recfolder, "/*.", filetypes[j]); + glob_t globbuf; + globbuf.gl_offs = 0; + if (glob(filemask.c_str(), GLOB_DOOFFS, NULL, &globbuf) == 0) { + for(size_t i = 0; i < globbuf.gl_pathc; i++) { + const std::string_view imagefile(globbuf.gl_pathv[i]); + size_t delimPos = imagefile.find_last_of('/'); + const std::string_view imagename(imagefile.substr(delimPos+1)); + images.push_back(std::move(std::string(imagename))); + + // create a temporary symlink of the image in /tmp + cToSvConcat tmpfile("/tmp/", imageId, "_", imagename); cToSvConcat cmdBuff("ln -s \"", imagefile, "\" \"", tmpfile, "\""); - int s = system(cmdBuff.c_str() ); - if (s < 0) - esyslog("live: ERROR: Couldn't execute command %s", cmdBuff.c_str() ); - found = true; - } - globfree(&globbuf); - } - } - return found; - } - - bool PosterTvscraper(cTvMedia &media, const cEvent *event, const cRecording *recording) - { + int s = system(cmdBuff.c_str() ); + if (s < 0) + esyslog("live: ERROR: Couldn't execute command %s", cmdBuff.c_str() ); + found = true; + } + globfree(&globbuf); + } + } + return found; + } + + bool PosterTvscraper(cTvMedia &media, const cEvent *event, const cRecording *recording) + { media.path = ""; media.width = media.height = 0; - if (LiveSetup().GetTvscraperImageDir().empty() ) return false; + if (LiveSetup().GetTvscraperImageDir().empty() ) return false; ScraperGetPoster call; call.event = event; call.recording = recording; @@ -434,95 +434,95 @@ namespace vdrlive media.height = call.poster.height; return true; } - return false; + return false; } - std::list EpgImages(cSv epgid) - { + std::list EpgImages(cSv epgid) + { // format of epgid: event__ - size_t delimPosFirst = epgid.find_first_of('_'); - size_t delimPosLast = epgid.find_last_of('_'); - cSv channelIdStr_enc = epgid.substr(delimPosFirst+1, delimPosLast-delimPosFirst-1); - std::string channelId = vdrlive::DecodeDomId(channelIdStr_enc, "mp", "-."); - cSv eventId = epgid.substr(delimPosLast+1); - - - std::list images; - - // Initially we scan for images that follow the scheme - // '__.*' where distinction is - // any character sequence. Usually distinction will be used - // to assign more than one image to an epg event. Thus it - // will be a digit or number. The sorting of the images - // will depend on the 'distinction' lexical sorting - // (similar to what ls does). - // Example: - // S19.2E-1-2222-33333_112123_0.jpg first epg image for event id 112123 - // S19.2E-1-2222-33333_112123_1.png second epg image for event id 112123 - // If no image is found with channelId it will be searched - // with the eventId only following the scheme: - // '_.*' - // Example: - // 112123_0.jpg first epg image for event id 112123 - // 112123_1.png second epg image for event id 112123 - if (! ScanForEpgImages(channelId, eventId, "_*.*", images)) - { - // if we didn't find images that follow the scheme - // above we try to find images that contain only the - // event id as file name without extension: - if (! ScanForEpgImages(channelId, eventId, ".*", images)) - { + size_t delimPosFirst = epgid.find_first_of('_'); + size_t delimPosLast = epgid.find_last_of('_'); + cSv channelIdStr_enc = epgid.substr(delimPosFirst+1, delimPosLast-delimPosFirst-1); + std::string channelId = vdrlive::DecodeDomId(channelIdStr_enc, "mp", "-."); + cSv eventId = epgid.substr(delimPosLast+1); + + + std::list images; + + // Initially we scan for images that follow the scheme + // '__.*' where distinction is + // any character sequence. Usually distinction will be used + // to assign more than one image to an epg event. Thus it + // will be a digit or number. The sorting of the images + // will depend on the 'distinction' lexical sorting + // (similar to what ls does). + // Example: + // S19.2E-1-2222-33333_112123_0.jpg first epg image for event id 112123 + // S19.2E-1-2222-33333_112123_1.png second epg image for event id 112123 + // If no image is found with channelId it will be searched + // with the eventId only following the scheme: + // '_.*' + // Example: + // 112123_0.jpg first epg image for event id 112123 + // 112123_1.png second epg image for event id 112123 + if (! ScanForEpgImages(channelId, eventId, "_*.*", images)) + { + // if we didn't find images that follow the scheme + // above we try to find images that contain only the + // event id as file name without extension: + if (! ScanForEpgImages(channelId, eventId, ".*", images)) + { #if TVM2VDR_PL_WORKAROUND - // if we didn't get images try to work around 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 does not have that bug. - eventId = eventId.substr(0, eventId.size()-1); - ScanForEpgImages(channelId, eventId, "*.*", images); + // if we didn't get images try to work around 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 does not have that bug. + eventId = eventId.substr(0, eventId.size()-1); + ScanForEpgImages(channelId, eventId, "*.*", images); #endif - } - } - return images; - } + } + } + return images; + } - std::list RecImages(cSv epgid, cSv recfolder) - { + std::list RecImages(cSv epgid, cSv recfolder) + { // format of epgid: recording_ - size_t delimPos = epgid.find_last_of('_'); - cSv imageId = epgid.substr(delimPos+1); - - std::list images; - // Scan for all images in recording directory - ScanForRecImages(imageId, recfolder, 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 + size_t delimPos = epgid.find_last_of('_'); + cSv imageId = epgid.substr(delimPos+1); + + std::list images; + // Scan for all images in recording directory + ScanForRecImages(imageId, recfolder, 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 void AppendScraperData(cToSvConcat<0> &target, cScraperVideo *scraperVideo) { cTvMedia s_image; diff --git a/epg_events.h b/epg_events.h index 1f596d1..2c6e8fe 100644 --- a/epg_events.h +++ b/epg_events.h @@ -20,241 +20,241 @@ namespace vdrlive { - class EpgInfo; + class EpgInfo; - typedef std::shared_ptr EpgInfoPtr; + typedef std::shared_ptr EpgInfoPtr; - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - namespace EpgEvents { + namespace EpgEvents { - std::string EncodeDomId(tChannelID const &chanId, tEventID const &eventId); - void DecodeDomId(cSv epgid, tChannelID &chanId, tEventID &eventId); + std::string EncodeDomId(tChannelID const &chanId, tEventID const &eventId); + void DecodeDomId(cSv epgid, tChannelID &chanId, tEventID &eventId); const cEvent *GetEventByEpgid(cSv epgid); - /** - * Allocate and initialize an epgEvent instance with the - * passed channel and event information. - * Never call this function with a NULL chan pointer - */ - EpgInfoPtr CreateEpgInfo(cChannel const *chan, cEvent const *event, cSv idOverride = cSv()); - - /** - * This is the inverse creator for epgInfos to the creator above. - */ - EpgInfoPtr CreateEpgInfo(cSv epgid, cSchedules const *schedules); - - /** - * Allocate and initialize an epgEvent instance with the - * passed recording information. - */ - EpgInfoPtr CreateEpgInfo(cSv recid, cRecording const *recording, char const *caption = 0); - - /** - * Allocate and initialize an epgEvent instance with the - * passed string informations - */ - EpgInfoPtr CreateEpgInfo(cSv id, cSv caption, cSv info); - - /** - * Return a list of EpgImage paths for a given epgid. - */ + /** + * Allocate and initialize an epgEvent instance with the + * passed channel and event information. + * Never call this function with a NULL chan pointer + */ + EpgInfoPtr CreateEpgInfo(cChannel const *chan, cEvent const *event, cSv idOverride = cSv()); + + /** + * This is the inverse creator for epgInfos to the creator above. + */ + EpgInfoPtr CreateEpgInfo(cSv epgid, cSchedules const *schedules); + + /** + * Allocate and initialize an epgEvent instance with the + * passed recording information. + */ + EpgInfoPtr CreateEpgInfo(cSv recid, cRecording const *recording, char const *caption = 0); + + /** + * Allocate and initialize an epgEvent instance with the + * passed string informations + */ + EpgInfoPtr CreateEpgInfo(cSv id, cSv caption, cSv info); + + /** + * Return a list of EpgImage paths for a given epgid. + */ bool PosterTvscraper(cTvMedia &media, const cEvent *event, const cRecording *recording); - std::list EpgImages(cSv epgid); + std::list EpgImages(cSv epgid); - /** - * Return a list of RecImages in the given folder. - */ - std::list RecImages(cSv epgid, cSv recfolder); + /** + * Return a list of RecImages in the given folder. + */ + std::list RecImages(cSv epgid, cSv recfolder); - /** - * Calculate the duration. A duration can be zero or - * negative. Negative durations are considered invalid by - * LIVE. - */ - int Duration(time_t const startTime, time_t const endTime); + /** + * Calculate the duration. A duration can be zero or + * negative. Negative durations are considered invalid by + * LIVE. + */ + int Duration(time_t const startTime, time_t const endTime); - /** - * Calculate the elapsed time of a positive duration. This - * takes into account the startTime and the current time. If - * the current time is not in the interval startTime <= - * currTime <= endTime the return value is -1. - */ - int ElapsedTime(time_t const startTime, time_t const endTime); + /** + * Calculate the elapsed time of a positive duration. This + * takes into account the startTime and the current time. If + * the current time is not in the interval startTime <= + * currTime <= endTime the return value is -1. + */ + int ElapsedTime(time_t const startTime, time_t const endTime); - } // namespace EpgEvents + } // namespace EpgEvents - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - class EpgInfo - { - public: - EpgInfo(cSv id, cSv caption); - virtual ~EpgInfo(); + class EpgInfo + { + public: + EpgInfo(cSv id, cSv caption); + virtual ~EpgInfo(); - virtual cSv Id() const { return m_eventId; } + virtual cSv Id() const { return m_eventId; } - virtual cSv Caption() const { return m_caption; } + virtual cSv Caption() const { return m_caption; } - virtual cSv Title() const = 0; + virtual cSv Title() const = 0; - virtual cSv ShortDescr() const = 0; + virtual cSv ShortDescr() const = 0; - virtual cSv LongDescr() const = 0; + virtual cSv LongDescr() const = 0; - virtual cChannel const * Channel() const { return 0; } + virtual cChannel const * Channel() const { return 0; } - virtual cSv ChannelName() const; + virtual cSv ChannelName() const; - virtual cSv Archived() const { return cSv(); } + virtual cSv Archived() const { return cSv(); } - virtual cSv FileName() const { return cSv(); } + virtual cSv FileName() const { return cSv(); } - virtual std::string const StartTime(const char* format) const; + virtual std::string const StartTime(const char* format) const; - virtual std::string const EndTime(const char* format) const; + virtual std::string const EndTime(const char* format) const; - virtual std::string const CurrentTime(const char* format) const; + virtual std::string const CurrentTime(const char* format) const; - virtual int Duration() const; // for recordings, this is the length of the recording - virtual int EventDuration() const { return -1; }; // this is always the event duration + virtual int Duration() const; // for recordings, this is the length of the recording + virtual int EventDuration() const { return -1; }; // this is always the event duration - virtual int Elapsed() const; + virtual int Elapsed() const; - virtual time_t GetStartTime() const = 0; + virtual time_t GetStartTime() const = 0; - virtual time_t GetEndTime() const = 0; + virtual time_t GetEndTime() const = 0; - virtual cEvent const *Event() const { return NULL; } - private: - std::string m_eventId; - std::string m_caption; - }; + virtual cEvent const *Event() const { return NULL; } + private: + std::string m_eventId; + std::string m_caption; + }; - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - class EpgString : public EpgInfo - { - friend EpgInfoPtr EpgEvents::CreateEpgInfo(cSv, cSv, cSv); + class EpgString : public EpgInfo + { + friend EpgInfoPtr EpgEvents::CreateEpgInfo(cSv, cSv, cSv); - public: - EpgString(cSv id, cSv caption, cSv info); - virtual ~EpgString(); + public: + EpgString(cSv id, cSv caption, cSv info); + virtual ~EpgString(); - virtual cSv Title() const; + virtual cSv Title() const; - virtual cSv ShortDescr() const; + virtual cSv ShortDescr() const; - virtual cSv LongDescr() const; + virtual cSv LongDescr() const; - virtual time_t GetStartTime() const; + virtual time_t GetStartTime() const; - virtual time_t GetEndTime() const; + virtual time_t GetEndTime() const; - virtual cSv FileName() const { return cSv(); } + virtual cSv FileName() const { return cSv(); } - private: - const std::string m_info; - }; + private: + const std::string m_info; + }; - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - class EpgEvent : public EpgInfo - { - friend EpgInfoPtr EpgEvents::CreateEpgInfo(cChannel const *, cEvent const *, cSv); + class EpgEvent : public EpgInfo + { + friend EpgInfoPtr EpgEvents::CreateEpgInfo(cChannel const *, cEvent const *, cSv); - public: - EpgEvent(cSv id, cEvent const *event, char const *channelName); - virtual ~EpgEvent(); + public: + EpgEvent(cSv id, cEvent const *event, char const *channelName); + virtual ~EpgEvent(); - virtual cSv Title() const { return m_event->Title(); } + virtual cSv Title() const { return m_event->Title(); } - virtual cSv ShortDescr() const { return m_event->ShortText(); } + virtual cSv ShortDescr() const { return m_event->ShortText(); } - virtual cSv LongDescr() const { return m_event->Description(); } + virtual cSv LongDescr() const { return m_event->Description(); } - virtual time_t GetStartTime() const { return m_event->StartTime(); } + virtual time_t GetStartTime() const { return m_event->StartTime(); } - virtual time_t GetEndTime() const { return m_event->EndTime(); } + virtual time_t GetEndTime() const { return m_event->EndTime(); } - virtual cChannel const * Channel() const { LOCK_CHANNELS_READ; return Channels->GetByChannelID(m_event->ChannelID());} + virtual cChannel const * Channel() const { LOCK_CHANNELS_READ; return Channels->GetByChannelID(m_event->ChannelID());} - virtual cSv FileName() const { return cSv(); } + virtual cSv FileName() const { return cSv(); } - virtual cEvent const *Event() const { return m_event; } - private: - cEvent const * m_event; - }; + virtual cEvent const *Event() const { return m_event; } + private: + cEvent const * m_event; + }; - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - class EmptyEvent : public EpgInfo - { - friend EpgInfoPtr EpgEvents::CreateEpgInfo(cChannel const *, cEvent const *, cSv); + class EmptyEvent : public EpgInfo + { + friend EpgInfoPtr EpgEvents::CreateEpgInfo(cChannel const *, cEvent const *, cSv); - public: - EmptyEvent(cSv id, tChannelID const &channelID, const char* channelName); - virtual ~EmptyEvent(); + public: + EmptyEvent(cSv id, tChannelID const &channelID, const char* channelName); + virtual ~EmptyEvent(); - virtual cSv Title() const { return tr("No EPG information available"); } + virtual cSv Title() const { return tr("No EPG information available"); } - virtual cSv ShortDescr() const { return cSv(); } + virtual cSv ShortDescr() const { return cSv(); } - virtual cSv LongDescr() const { return cSv(); } + virtual cSv LongDescr() const { return cSv(); } - virtual time_t GetStartTime() const { return 0; } + virtual time_t GetStartTime() const { return 0; } - virtual time_t GetEndTime() const { return 0; } + virtual time_t GetEndTime() const { return 0; } - virtual cChannel const * Channel() const { LOCK_CHANNELS_READ; return Channels->GetByChannelID(m_channelID);} + virtual cChannel const * Channel() const { LOCK_CHANNELS_READ; return Channels->GetByChannelID(m_channelID);} - virtual cSv FileName() const { return cSv(); } + virtual cSv FileName() const { return cSv(); } - private: - tChannelID m_channelID; - }; + private: + tChannelID m_channelID; + }; - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- - class EpgRecording : public EpgInfo - { - friend EpgInfoPtr EpgEvents::CreateEpgInfo(cSv, cRecording const *, const char *); + class EpgRecording : public EpgInfo + { + friend EpgInfoPtr EpgEvents::CreateEpgInfo(cSv, cRecording const *, const char *); - protected: - cSv Name() const; + protected: + cSv Name() const; - public: - EpgRecording(cSv recid, cRecording const *recording, char const *caption); - virtual ~EpgRecording(); + public: + EpgRecording(cSv recid, cRecording const *recording, char const *caption); + virtual ~EpgRecording(); - virtual cSv Caption() const; + virtual cSv Caption() const; - virtual cSv Title() const; + virtual cSv Title() const; - virtual cSv ShortDescr() const; + virtual cSv ShortDescr() const; - virtual cSv LongDescr() const; + virtual cSv LongDescr() const; - virtual cSv ChannelName() const; + virtual cSv ChannelName() const; - virtual cSv Archived() const; + virtual cSv Archived() const; - virtual cSv FileName() const; + virtual cSv FileName() const; - virtual time_t GetStartTime() const; + virtual time_t GetStartTime() const; - virtual time_t GetEndTime() const; - virtual int EventDuration() const; // this is always the event duration + virtual time_t GetEndTime() const; + virtual int EventDuration() const; // this is always the event duration - virtual int Elapsed() const; + virtual int Elapsed() const; - private: - const cRecording* m_recording; - bool m_ownCaption; - mutable bool m_checkedArchived; - mutable std::string m_archived; - }; + private: + const cRecording* m_recording; + bool m_ownCaption; + mutable bool m_checkedArchived; + mutable std::string m_archived; + }; bool appendEpgItem(cToSvConcat<0> &epg_item, RecordingsItemRecPtr &recItem, const cEvent *Event, const cChannel *Channel, bool withChannel); }; // namespace vdrlive diff --git a/epgsearch.cpp b/epgsearch.cpp index 22dd35e..b013a30 100644 --- a/epgsearch.cpp +++ b/epgsearch.cpp @@ -23,14 +23,14 @@ bool operator<( SearchTimer const& left, SearchTimer const& right ) bool CheckEpgsearchVersion() { - /* @winni: Falls Du an der Versionsnummer Anpassungen vornehmen willst, mach das bitte in livefeatures.h ganz unten. Danke */ - const Features& f = LiveFeatures(); - if ( f.Loaded() ) { - if ( !f.Recent() ) - throw HtmlError( tr("Required minimum version of epgsearch: ") + std::string( f.MinVersion() )); - return true; - } - return false; + /* @winni: Falls Du an der Versionsnummer Anpassungen vornehmen willst, mach das bitte in livefeatures.h ganz unten. Danke */ + const Features& f = LiveFeatures(); + if ( f.Loaded() ) { + if ( !f.Recent() ) + throw HtmlError( tr("Required minimum version of epgsearch: ") + std::string( f.MinVersion() )); + return true; + } + return false; } SearchTimer::SearchTimer() @@ -40,51 +40,51 @@ SearchTimer::SearchTimer() void SearchTimer::Init() { - m_id = -1; - m_useTime = false; - m_startTime = 0; - m_stopTime = 0; - m_useChannel = NoChannel; - m_useCase = false; - m_mode = 0; - m_useTitle = true; - m_useSubtitle = true; - m_useDescription = true; - m_useDuration = false; - m_minDuration = 0; - m_maxDuration = 0; - m_useDayOfWeek = false; - m_dayOfWeek = 0; - m_useEpisode = false; - m_priority = parse_int(EPGSearchSetupValues::ReadValue("DefPriority")); - m_lifetime = parse_int(EPGSearchSetupValues::ReadValue("DefLifetime")); - m_fuzzytolerance = 1; - m_useInFavorites = false; - m_useAsSearchtimer = 0; - m_action = 0; - m_delAfterDays = 0; - m_recordingsKeep = 0; - m_pauseOnNrRecordings = 0; - m_switchMinBefore = 1; - m_useExtEPGInfo = false; - m_useVPS = false; - m_marginstart = parse_int(EPGSearchSetupValues::ReadValue("DefMarginStart")); - m_marginstop = parse_int(EPGSearchSetupValues::ReadValue("DefMarginStop")); - m_avoidrepeats = false; - m_allowedrepeats = 0; - m_compareTitle = false; - m_compareSubtitle = 0; - m_compareSummary = false; - m_repeatsWithinDays = 0; - m_blacklistmode = 0; - m_menuTemplate = 0; - m_delMode = 0; - m_delAfterCountRecs = 0; - m_delAfterDaysOfFirstRec = 0; - m_useAsSearchTimerFrom = 0; - m_useAsSearchTimerTil = 0; - m_catvaluesAvoidRepeat = 0; - m_ignoreMissingEPGCats = false; + m_id = -1; + m_useTime = false; + m_startTime = 0; + m_stopTime = 0; + m_useChannel = NoChannel; + m_useCase = false; + m_mode = 0; + m_useTitle = true; + m_useSubtitle = true; + m_useDescription = true; + m_useDuration = false; + m_minDuration = 0; + m_maxDuration = 0; + m_useDayOfWeek = false; + m_dayOfWeek = 0; + m_useEpisode = false; + m_priority = parse_int(EPGSearchSetupValues::ReadValue("DefPriority")); + m_lifetime = parse_int(EPGSearchSetupValues::ReadValue("DefLifetime")); + m_fuzzytolerance = 1; + m_useInFavorites = false; + m_useAsSearchtimer = 0; + m_action = 0; + m_delAfterDays = 0; + m_recordingsKeep = 0; + m_pauseOnNrRecordings = 0; + m_switchMinBefore = 1; + m_useExtEPGInfo = false; + m_useVPS = false; + m_marginstart = parse_int(EPGSearchSetupValues::ReadValue("DefMarginStart")); + m_marginstop = parse_int(EPGSearchSetupValues::ReadValue("DefMarginStop")); + m_avoidrepeats = false; + m_allowedrepeats = 0; + m_compareTitle = false; + m_compareSubtitle = 0; + m_compareSummary = false; + m_repeatsWithinDays = 0; + m_blacklistmode = 0; + m_menuTemplate = 0; + m_delMode = 0; + m_delAfterCountRecs = 0; + m_delAfterDaysOfFirstRec = 0; + m_useAsSearchTimerFrom = 0; + m_useAsSearchTimerTil = 0; + m_catvaluesAvoidRepeat = 0; + m_ignoreMissingEPGCats = false; } SearchTimer::SearchTimer( std::string const& data ) @@ -94,61 +94,61 @@ SearchTimer::SearchTimer( std::string const& data ) try { std::vector::const_iterator part = parts.begin(); for ( int i = 0; part != parts.end(); ++i, ++part ) { - switch ( i ) { - case 0: m_id = parse_int( *part ); break; - case 1: m_search = StringReplace( StringReplace( *part, "|", ":" ), "!^pipe^!", "|" ); break; - case 2: m_useTime = lexical_cast( *part ); break; - case 3: if ( m_useTime ) m_startTime = parse_int( *part ); break; - case 4: if ( m_useTime ) m_stopTime = parse_int( *part ); break; - case 5: m_useChannel = parse_int( *part ); break; - case 6: ParseChannel( *part ); break; - case 7: m_useCase = parse_int( *part ); break; - case 8: m_mode = parse_int( *part ); break; - case 9: m_useTitle = lexical_cast( *part ); break; - case 10: m_useSubtitle = lexical_cast( *part ); break; - case 11: m_useDescription = lexical_cast( *part ); break; - case 12: m_useDuration = lexical_cast( *part ); break; - case 13: if ( m_useDuration ) m_minDuration = parse_int( *part ); break; - case 14: if ( m_useDuration ) m_maxDuration = parse_int( *part ); break; - case 15: m_useAsSearchtimer = parse_int( *part ); break; - case 16: m_useDayOfWeek = lexical_cast( *part ); break; - case 17: m_dayOfWeek = parse_int( *part ); break; - case 18: m_useEpisode = lexical_cast( *part ); break; - case 19: m_directory = StringReplace( StringReplace( *part, "|", ":" ), "!^pipe^!", "|" ); break; - case 20: m_priority = parse_int( *part ); break; - case 21: m_lifetime = parse_int( *part ); break; - case 22: m_marginstart = parse_int( *part ); break; - case 23: m_marginstop = parse_int( *part ); break; - case 24: m_useVPS = lexical_cast( *part ); break; - case 25: m_action = parse_int( *part ); break; - case 26: m_useExtEPGInfo = lexical_cast( *part ); break; - case 27: ParseExtEPGInfo( *part ); break; - case 28: m_avoidrepeats = lexical_cast( *part ); break; - case 29: m_allowedrepeats = parse_int( *part ); break; - case 30: m_compareTitle = lexical_cast( *part ); break; - case 31: m_compareSubtitle = parse_int( *part ); break; - case 32: m_compareSummary = lexical_cast( *part ); break; - case 33: m_catvaluesAvoidRepeat = parse_int< unsigned long >( *part ); break; - case 34: m_repeatsWithinDays = parse_int( *part ); break; - case 35: m_delAfterDays = parse_int( *part ); break; - case 36: m_recordingsKeep = parse_int( *part ); break; - case 37: m_switchMinBefore = parse_int( *part ); break; - case 38: m_pauseOnNrRecordings = parse_int( *part ); break; - case 39: m_blacklistmode = parse_int( *part ); break; - case 40: ParseBlacklist( *part ); break; - case 41: m_fuzzytolerance = parse_int( *part ); break; - case 42: m_useInFavorites = lexical_cast( *part ); break; - case 43: m_menuTemplate = parse_int( *part ); break; - case 44: m_delMode = parse_int( *part ); break; - case 45: m_delAfterCountRecs = parse_int( *part ); break; - case 46: m_delAfterDaysOfFirstRec = parse_int( *part ); break; - case 47: m_useAsSearchTimerFrom = parse_int( *part ); break; - case 48: m_useAsSearchTimerTil = parse_int( *part ); break; - case 49: m_ignoreMissingEPGCats = lexical_cast( *part ); break; - } - } - } catch ( bad_lexical_cast const& ex ) { - } + switch ( i ) { + case 0: m_id = parse_int( *part ); break; + case 1: m_search = StringReplace( StringReplace( *part, "|", ":" ), "!^pipe^!", "|" ); break; + case 2: m_useTime = lexical_cast( *part ); break; + case 3: if ( m_useTime ) m_startTime = parse_int( *part ); break; + case 4: if ( m_useTime ) m_stopTime = parse_int( *part ); break; + case 5: m_useChannel = parse_int( *part ); break; + case 6: ParseChannel( *part ); break; + case 7: m_useCase = parse_int( *part ); break; + case 8: m_mode = parse_int( *part ); break; + case 9: m_useTitle = lexical_cast( *part ); break; + case 10: m_useSubtitle = lexical_cast( *part ); break; + case 11: m_useDescription = lexical_cast( *part ); break; + case 12: m_useDuration = lexical_cast( *part ); break; + case 13: if ( m_useDuration ) m_minDuration = parse_int( *part ); break; + case 14: if ( m_useDuration ) m_maxDuration = parse_int( *part ); break; + case 15: m_useAsSearchtimer = parse_int( *part ); break; + case 16: m_useDayOfWeek = lexical_cast( *part ); break; + case 17: m_dayOfWeek = parse_int( *part ); break; + case 18: m_useEpisode = lexical_cast( *part ); break; + case 19: m_directory = StringReplace( StringReplace( *part, "|", ":" ), "!^pipe^!", "|" ); break; + case 20: m_priority = parse_int( *part ); break; + case 21: m_lifetime = parse_int( *part ); break; + case 22: m_marginstart = parse_int( *part ); break; + case 23: m_marginstop = parse_int( *part ); break; + case 24: m_useVPS = lexical_cast( *part ); break; + case 25: m_action = parse_int( *part ); break; + case 26: m_useExtEPGInfo = lexical_cast( *part ); break; + case 27: ParseExtEPGInfo( *part ); break; + case 28: m_avoidrepeats = lexical_cast( *part ); break; + case 29: m_allowedrepeats = parse_int( *part ); break; + case 30: m_compareTitle = lexical_cast( *part ); break; + case 31: m_compareSubtitle = parse_int( *part ); break; + case 32: m_compareSummary = lexical_cast( *part ); break; + case 33: m_catvaluesAvoidRepeat = parse_int< unsigned long >( *part ); break; + case 34: m_repeatsWithinDays = parse_int( *part ); break; + case 35: m_delAfterDays = parse_int( *part ); break; + case 36: m_recordingsKeep = parse_int( *part ); break; + case 37: m_switchMinBefore = parse_int( *part ); break; + case 38: m_pauseOnNrRecordings = parse_int( *part ); break; + case 39: m_blacklistmode = parse_int( *part ); break; + case 40: ParseBlacklist( *part ); break; + case 41: m_fuzzytolerance = parse_int( *part ); break; + case 42: m_useInFavorites = lexical_cast( *part ); break; + case 43: m_menuTemplate = parse_int( *part ); break; + case 44: m_delMode = parse_int( *part ); break; + case 45: m_delAfterCountRecs = parse_int( *part ); break; + case 46: m_delAfterDaysOfFirstRec = parse_int( *part ); break; + case 47: m_useAsSearchTimerFrom = parse_int( *part ); break; + case 48: m_useAsSearchTimerTil = parse_int( *part ); break; + case 49: m_ignoreMissingEPGCats = lexical_cast( *part ); break; + } + } + } catch ( bad_lexical_cast const& ex ) { + } } std::string SearchTimer::ToText() @@ -274,32 +274,32 @@ std::string SearchTimer::ToText() void SearchTimer::ParseChannel( std::string const& data ) { - switch ( m_useChannel ) { + switch ( m_useChannel ) { case NoChannel: m_channels = tr("All"); break; case Interval: ParseChannelIDs( data ); break; case Group: m_channels = data; break; case FTAOnly: m_channels = tr("FTA"); break; - } + } } void SearchTimer::ParseChannelIDs( std::string const& data ) { - std::vector parts = StringSplit( data, '|' ); - m_channelMin = tChannelID::FromString( parts[ 0 ].c_str() ); + std::vector parts = StringSplit( data, '|' ); + m_channelMin = tChannelID::FromString( parts[ 0 ].c_str() ); - LOCK_CHANNELS_READ; - cChannel const* channel = Channels->GetByChannelID( m_channelMin ); - if ( channel != 0 ) - m_channels = channel->Name(); + LOCK_CHANNELS_READ; + cChannel const* channel = Channels->GetByChannelID( m_channelMin ); + if ( channel != 0 ) + m_channels = channel->Name(); - if ( parts.size() < 2 ) - return; + if ( parts.size() < 2 ) + return; - m_channelMax = tChannelID::FromString( parts[ 1 ].c_str() ); + m_channelMax = tChannelID::FromString( parts[ 1 ].c_str() ); - channel = Channels->GetByChannelID( m_channelMax ); - if ( channel != 0 ) - m_channels += std::string( " - " ) + channel->Name(); + channel = Channels->GetByChannelID( m_channelMax ); + if ( channel != 0 ) + m_channels += std::string( " - " ) + channel->Name(); } void SearchTimer::ParseExtEPGInfo( std::string const& data ) @@ -314,81 +314,81 @@ void SearchTimer::ParseBlacklist( std::string const& data ) std::string SearchTimer::StartTimeFormatted() { - time_t start = cTimer::SetTime(time(NULL), (((StartTime() / 100 ) % 100) * 60 * 60) + (StartTime() % 100 * 60)); - return std::string(cToSvDateTime(tr("%I:%M %p"), start)); + time_t start = cTimer::SetTime(time(NULL), (((StartTime() / 100 ) % 100) * 60 * 60) + (StartTime() % 100 * 60)); + return std::string(cToSvDateTime(tr("%I:%M %p"), start)); } std::string SearchTimer::StopTimeFormatted() { - time_t stop = cTimer::SetTime(time(NULL), (((StopTime() / 100 ) % 100) * 60 * 60) + (StopTime() % 100 * 60)); - return std::string(cToSvDateTime(tr("%I:%M %p"), stop)); + time_t stop = cTimer::SetTime(time(NULL), (((StopTime() / 100 ) % 100) * 60 * 60) + (StopTime() % 100 * 60)); + return std::string(cToSvDateTime(tr("%I:%M %p"), stop)); } std::string SearchTimer::UseAsSearchTimerFrom(std::string const& format) { - return DatePickerToC(m_useAsSearchTimerFrom, format); + return DatePickerToC(m_useAsSearchTimerFrom, format); } std::string SearchTimer::UseAsSearchTimerTil(std::string const& format) { - return DatePickerToC(m_useAsSearchTimerTil, format); + return DatePickerToC(m_useAsSearchTimerTil, format); } void SearchTimer::SetUseAsSearchTimerFrom(std::string const& datestring, std::string const& format) { - m_useAsSearchTimerFrom = GetDateFromDatePicker(datestring, format); + m_useAsSearchTimerFrom = GetDateFromDatePicker(datestring, format); } void SearchTimer::SetUseAsSearchTimerTil(std::string const& datestring, std::string const& format) { - m_useAsSearchTimerTil = GetDateFromDatePicker(datestring, format); + m_useAsSearchTimerTil = GetDateFromDatePicker(datestring, format); } SearchTimers::SearchTimers() { - Reload(); + Reload(); } bool SearchTimers::Reload() { - Epgsearch_services_v1_0 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_0 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); #if VDRVERSNUM >= 20301 - LOCK_CHANNELS_READ; + LOCK_CHANNELS_READ; #else - ReadLock channelsLock( Channels, 0 ); + ReadLock channelsLock( Channels, 0 ); #endif - std::list timers = service.handler->SearchTimerList(); - m_timers.assign( timers.begin(), timers.end() ); - m_timers.sort(); - return true; + std::list timers = service.handler->SearchTimerList(); + m_timers.assign( timers.begin(), timers.end() ); + m_timers.sort(); + return true; } bool SearchTimers::Save(SearchTimer* searchtimer) { - Epgsearch_services_v1_0 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_0 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - if (!searchtimer) return false; + if (!searchtimer) return false; #if VDRVERSNUM >= 20301 - LOCK_CHANNELS_READ; + LOCK_CHANNELS_READ; #else - ReadLock channelsLock( Channels, 0 ); + ReadLock channelsLock( Channels, 0 ); #endif - if (searchtimer->Id() >= 0) - return service.handler->ModSearchTimer(searchtimer->ToText()); - else - { - searchtimer->SetId(0); - int id = service.handler->AddSearchTimer(searchtimer->ToText()); - if (id >= 0) - searchtimer->SetId(id); - return (id >= 0); - } + if (searchtimer->Id() >= 0) + return service.handler->ModSearchTimer(searchtimer->ToText()); + else + { + searchtimer->SetId(0); + int id = service.handler->AddSearchTimer(searchtimer->ToText()); + if (id >= 0) + searchtimer->SetId(id); + return (id >= 0); + } } SearchTimer* SearchTimers::GetByTimerId( std::string const& id ) @@ -400,32 +400,32 @@ SearchTimer* SearchTimers::GetByTimerId( std::string const& id ) bool SearchTimers::ToggleActive(std::string const& id) { - SearchTimer* search = GetByTimerId( id ); - if (!search) return false; - search->SetUseAsSearchTimer(search->UseAsSearchTimer()==1?0:1); - return Save(search); + SearchTimer* search = GetByTimerId( id ); + if (!search) return false; + search->SetUseAsSearchTimer(search->UseAsSearchTimer()==1?0:1); + return Save(search); } bool SearchTimers::Delete(std::string const& id) { - SearchTimer* search = GetByTimerId( id ); - if (!search) return false; + SearchTimer* search = GetByTimerId( id ); + if (!search) return false; - Epgsearch_services_v1_0 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_0 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - if (service.handler->DelSearchTimer(parse_int( id ))) - return Reload(); - return false; + if (service.handler->DelSearchTimer(parse_int( id ))) + return Reload(); + return false; } void SearchTimers::TriggerUpdate() { - Epgsearch_updatesearchtimers_v1_0 service; - service.showMessage = true; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService("Epgsearch-updatesearchtimers-v1.0", &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_updatesearchtimers_v1_0 service; + service.showMessage = true; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService("Epgsearch-updatesearchtimers-v1.0", &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); } bool SearchTimer::BlacklistSelected(int id) const @@ -477,12 +477,12 @@ bool ExtEPGInfo::Selected(unsigned int index, std::string const& values) ExtEPGInfos::ExtEPGInfos() { - Epgsearch_services_v1_0 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_0 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - std::list infos = service.handler->ExtEPGInfoList(); - m_infos.assign( infos.begin(), infos.end() ); + std::list infos = service.handler->ExtEPGInfoList(); + m_infos.assign( infos.begin(), infos.end() ); } ChannelGroup::ChannelGroup( std::string const& data ) @@ -492,7 +492,7 @@ ChannelGroup::ChannelGroup( std::string const& data ) std::vector::const_iterator part = parts.begin(); for ( int i = 0; part != parts.end(); ++i, ++part ) { switch ( i ) { - case 0: m_name = *part; break; + case 0: m_name = *part; break; } } } catch ( bad_lexical_cast const& ex ) { @@ -501,12 +501,12 @@ ChannelGroup::ChannelGroup( std::string const& data ) ChannelGroups::ChannelGroups() { - Epgsearch_services_v1_0 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_0 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - std::list list = service.handler->ChanGrpList(); - m_list.assign( list.begin(), list.end() ); + std::list list = service.handler->ChanGrpList(); + m_list.assign( list.begin(), list.end() ); } Blacklist::Blacklist( std::string const& data ) @@ -515,69 +515,69 @@ Blacklist::Blacklist( std::string const& data ) try { std::vector::const_iterator part = parts.begin(); for ( int i = 0; part != parts.end(); ++i, ++part ) { - switch ( i ) { - case 0: m_id = parse_int( *part ); break; - case 1: m_search = StringReplace( StringReplace( *part, "|", ":" ), "!^pipe^!", "|" ); break; - } - } - } catch ( bad_lexical_cast const& ex ) { - } + switch ( i ) { + case 0: m_id = parse_int( *part ); break; + case 1: m_search = StringReplace( StringReplace( *part, "|", ":" ), "!^pipe^!", "|" ); break; + } + } + } catch ( bad_lexical_cast const& ex ) { + } } Blacklists::Blacklists() { - Epgsearch_services_v1_0 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_0 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - std::list list = service.handler->BlackList(); - m_list.assign( list.begin(), list.end() ); + std::list list = service.handler->BlackList(); + m_list.assign( list.begin(), list.end() ); m_list.sort(); } SearchResult::SearchResult( std::string const& data ) { - std::vector parts = StringSplit( data, ':' ); - try { - std::vector::const_iterator part = parts.begin(); - for ( int i = 0; part != parts.end(); ++i, ++part ) { - switch ( i ) { - case 0: m_searchId = parse_int( *part ); break; - case 1: m_eventId = parse_int( *part ); break; - case 2: m_title = StringReplace( *part, "|", ":" ); break; - case 3: m_shorttext = StringReplace( *part, "|", ":" ); break; - case 4: m_description = StringReplace( *part, "|", ":" ); break; - case 5: m_starttime = parse_int( *part ); break; - case 6: m_stoptime = parse_int( *part ); break; - case 7: m_channel = tChannelID::FromString( part->c_str() ); break; - case 8: m_timerstart = parse_int( *part ); break; - case 9: m_timerstop = parse_int( *part ); break; - case 10: m_file = *part; break; - case 11: m_timerMode = parse_int( *part ); break; - } - } - } catch ( bad_lexical_cast const& ex ) { - } + std::vector parts = StringSplit( data, ':' ); + try { + std::vector::const_iterator part = parts.begin(); + for ( int i = 0; part != parts.end(); ++i, ++part ) { + switch ( i ) { + case 0: m_searchId = parse_int( *part ); break; + case 1: m_eventId = parse_int( *part ); break; + case 2: m_title = StringReplace( *part, "|", ":" ); break; + case 3: m_shorttext = StringReplace( *part, "|", ":" ); break; + case 4: m_description = StringReplace( *part, "|", ":" ); break; + case 5: m_starttime = parse_int( *part ); break; + case 6: m_stoptime = parse_int( *part ); break; + case 7: m_channel = tChannelID::FromString( part->c_str() ); break; + case 8: m_timerstart = parse_int( *part ); break; + case 9: m_timerstop = parse_int( *part ); break; + case 10: m_file = *part; break; + case 11: m_timerMode = parse_int( *part ); break; + } + } + } catch ( bad_lexical_cast const& ex ) { + } } const cEvent* SearchResult::GetEvent(const cChannel* Channel) { - if (!Channel) return NULL; + if (!Channel) return NULL; #if VDRVERSNUM >= 20301 - LOCK_SCHEDULES_READ; + LOCK_SCHEDULES_READ; #else - cSchedulesLock schedulesLock; - const cSchedules* Schedules = cSchedules::Schedules(schedulesLock); - if (!Schedules) return NULL; + cSchedulesLock schedulesLock; + const cSchedules* Schedules = cSchedules::Schedules(schedulesLock); + if (!Schedules) return NULL; #endif - const cSchedule *Schedule = Schedules->GetSchedule(Channel); - if (!Schedule) return NULL; + const cSchedule *Schedule = Schedules->GetSchedule(Channel); + if (!Schedule) return NULL; #if APIVERSNUM >= 20502 - return Schedule->GetEventById(m_eventId); + return Schedule->GetEventById(m_eventId); #else - return Schedule->GetEvent(m_eventId); + return Schedule->GetEvent(m_eventId); #endif } @@ -585,40 +585,40 @@ std::vector SearchResults::queryList; void SearchResults::GetByID(int id) { - Epgsearch_services_v1_0 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_0 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - std::list list = service.handler->QuerySearchTimer(id); - m_list.assign( list.begin(), list.end() ); - m_list.sort(); + std::list list = service.handler->QuerySearchTimer(id); + m_list.assign( list.begin(), list.end() ); + m_list.sort(); } void SearchResults::GetByQuery(std::string const& query) { - Epgsearch_services_v1_0 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_0 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - std::list list = service.handler->QuerySearch(query); - m_list.assign( list.begin(), list.end() ); - m_list.sort(); + std::list list = service.handler->QuerySearch(query); + m_list.assign( list.begin(), list.end() ); + m_list.sort(); } std::string SearchResults::AddQuery(cSv query) { for (auto it = queryList.begin(); it != queryList.end(); ++it) if (it->Value() == query) { it->Used(); - return std::string(cToSvXxHash128(query)); + return std::string(cToSvXxHash128(query)); } - queryList.emplace_back(query); - return std::string(cToSvXxHash128(query)); + queryList.emplace_back(query); + return std::string(cToSvXxHash128(query)); } std::string SearchResults::GetQuery(cSv md5) { - if (md5.empty()) return std::string(); - std::string query; + if (md5.empty()) return std::string(); + std::string query; for (auto it = queryList.begin(); it != queryList.end(); ++it) { if(md5 == cSv(cToSvXxHash128(it->Value() ))) @@ -628,7 +628,7 @@ std::string SearchResults::GetQuery(cSv md5) break; } } - return query; + return query; } void SearchResults::CleanQuery() { @@ -651,49 +651,49 @@ void SearchResults::CleanQuery() { RecordingDirs::RecordingDirs(bool shortList) { - if (shortList) + if (shortList) { - Epgsearch_services_v1_2 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_2 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - m_set = service.handler->ShortDirectoryList(); + m_set = service.handler->ShortDirectoryList(); } - else + else { - Epgsearch_services_v1_0 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_0 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - m_set = service.handler->DirectoryList(); + m_set = service.handler->DirectoryList(); } } std::string EPGSearchSetupValues::ReadValue(const std::string& entry) { - Epgsearch_services_v1_0 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_0 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - return service.handler->ReadSetupValue(entry); + return service.handler->ReadSetupValue(entry); } bool EPGSearchSetupValues::WriteValue(const std::string& entry, const std::string& value) { - Epgsearch_services_v1_0 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_0 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - return service.handler->WriteSetupValue(entry, value); + return service.handler->WriteSetupValue(entry, value); } std::string EPGSearchExpr::EvaluateExpr(const std::string& expr, const cEvent* event) { - Epgsearch_services_v1_2 service; - if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) - throw HtmlError( tr("EPGSearch version outdated! Please update.") ); + Epgsearch_services_v1_2 service; + if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 ) + throw HtmlError( tr("EPGSearch version outdated! Please update.") ); - return service.handler->Evaluate(expr, event); + return service.handler->Evaluate(expr, event); } diff --git a/epgsearch.h b/epgsearch.h index 16ed7ba..1423e59 100644 --- a/epgsearch.h +++ b/epgsearch.h @@ -25,352 +25,352 @@ bool operator<( SearchTimer const& left, SearchTimer const& right ); class SearchTimer { public: - enum eUseChannel - { - NoChannel = 0, - Interval = 1, - Group = 2, - FTAOnly = 3 - }; - - SearchTimer(); - SearchTimer( std::string const& data ); - void Init(); - std::string ToText(); - friend bool operator<( SearchTimer const& left, SearchTimer const& right ); - - int Id() const { return m_id; } - void SetId(int id) { m_id = id; } - std::string const& Search() const { return m_search; } - void SetSearch(std::string const& search) { m_search = search; } - int SearchMode() { return m_mode; } - void SetSearchMode(int mode) { m_mode = mode; } - int Tolerance() const { return m_fuzzytolerance; } - void SetTolerance(int tolerance) { m_fuzzytolerance = tolerance; } - bool MatchCase() const { return m_useCase; } - void SetMatchCase(bool useCase) { m_useCase = useCase; } - bool UseTime() const { return m_useTime; } - void SetUseTime(bool useTime) { m_useTime = useTime; } - bool UseTitle() const { return m_useTitle; } - void SetUseTitle(bool useTitle) { m_useTitle = useTitle; } - bool UseSubtitle() const { return m_useSubtitle; } - void SetUseSubtitle(bool useSubtitle) { m_useSubtitle = useSubtitle; } - bool UseDescription() const { return m_useDescription; } - void SetUseDescription(bool useDescription) { m_useDescription = useDescription; } - int StartTime() const { return m_startTime; } - std::string StartTimeFormatted(); - void SetStartTime(int startTime) { m_startTime = startTime; } - int StopTime() const { return m_stopTime; } - std::string StopTimeFormatted(); - void SetStopTime(int stopTime) { m_stopTime = stopTime; } - eUseChannel UseChannel() const { return static_cast( m_useChannel ); } - void SetUseChannel(eUseChannel useChannel) { m_useChannel = useChannel; } - tChannelID ChannelMin() const { return m_channelMin; } - void SetChannelMin(tChannelID channelMin) { m_channelMin = channelMin; } - tChannelID ChannelMax() const { return m_channelMax; } - void SetChannelMax(tChannelID channelMax) { m_channelMax = channelMax; } - std::string ChannelText() const { return m_channels; } - void SetChannelText(const std::string& channels) { m_channels = channels; } - int UseAsSearchTimer() const { return m_useAsSearchtimer; } - void SetUseAsSearchTimer(int useAsSearchtimer) { m_useAsSearchtimer = useAsSearchtimer; } - bool UseDuration() const { return m_useDuration; } - void SetUseDuration(bool useDuration) { m_useDuration = useDuration; } - int MinDuration() const { return m_minDuration; } - void SetMinDuration(int minDuration) { m_minDuration = minDuration; } - int MaxDuration() const { return m_maxDuration; } - void SetMaxDuration(int maxDuration) { m_maxDuration = maxDuration; } - bool UseDayOfWeek() const { return m_useDayOfWeek; } - void SetUseDayOfWeek(bool useDayOfWeek) { m_useDayOfWeek = useDayOfWeek; } - int DayOfWeek() const { return m_dayOfWeek; } - void SetDayOfWeek(int dayOfWeek) { m_dayOfWeek = dayOfWeek; } - bool UseInFavorites() const { return m_useInFavorites; } - void SetUseInFavorites(bool useInFavorites) { m_useInFavorites = useInFavorites; } - int SearchTimerAction() const { return m_action; } - void SetSearchTimerAction(int action) { m_action = action; } - bool UseSeriesRecording() const { return m_useEpisode; } - void SetUseSeriesRecording(bool useEpisode) { m_useEpisode = useEpisode; } - std::string const& Directory() const { return m_directory; } - void SetDirectory(std::string const& directory) { m_directory = directory; } - int DelRecsAfterDays() const { return m_delAfterDays; } - void SetDelRecsAfterDays(int delAfterDays) { m_delAfterDays = delAfterDays; } - int KeepRecs() const { return m_recordingsKeep; } - void SetKeepRecs(int recordingsKeep) { m_recordingsKeep = recordingsKeep; } - int PauseOnRecs() const {return m_pauseOnNrRecordings; } - void SetPauseOnRecs(int pauseOnNrRecordings) { m_pauseOnNrRecordings = pauseOnNrRecordings; } - int BlacklistMode() const {return m_blacklistmode; } - void SetBlacklistMode(int blacklistmode) { m_blacklistmode = blacklistmode; } - bool BlacklistSelected(int id) const; - void ParseBlacklist( std::string const& data ); - int SwitchMinBefore() const { return m_switchMinBefore; } - void SetSwitchMinBefore(int switchMinBefore) { m_switchMinBefore = switchMinBefore; } - bool UseExtEPGInfo() const { return m_useExtEPGInfo; } - void SetUseExtEPGInfo(bool useExtEPGInfo) { m_useExtEPGInfo = useExtEPGInfo; } - std::vector ExtEPGInfo() const { return m_ExtEPGInfo; } - void SetExtEPGInfo(const std::vector& ExtEPGInfo) { m_ExtEPGInfo = ExtEPGInfo; } - bool AvoidRepeats() const { return m_avoidrepeats; } - void SetAvoidRepeats(bool avoidrepeats) { m_avoidrepeats = avoidrepeats; } - int AllowedRepeats() const { return m_allowedrepeats; } - void SetAllowedRepeats(int allowedrepeats) { m_allowedrepeats = allowedrepeats; } - int RepeatsWithinDays() const { return m_repeatsWithinDays; } - void SetRepeatsWithinDays(int repeatsWithinDays) { m_repeatsWithinDays = repeatsWithinDays; } - bool CompareTitle() const { return m_compareTitle; } - void SetCompareTitle(bool compareTitle) { m_compareTitle = compareTitle; } - int CompareSubtitle() const { return m_compareSubtitle; } - void SetCompareSubtitle(int compareSubtitle) { m_compareSubtitle = compareSubtitle; } - bool CompareSummary() const { return m_compareSummary; } - void SetCompareSummary(bool compareSummary) { m_compareSummary = compareSummary; } - unsigned long CompareCategories() const { return m_catvaluesAvoidRepeat; } - void SetCompareCategories(unsigned long compareCategories) { m_catvaluesAvoidRepeat = compareCategories; } - int Priority() const { return m_priority; } - void SetPriority(int priority) { m_priority = priority; } - int Lifetime() const { return m_lifetime; } - void SetLifetime(int lifetime) { m_lifetime = lifetime; } - int MarginStart() const { return m_marginstart; } - void SetMarginStart(int marginstart) { m_marginstart = marginstart; } - int MarginStop() const { return m_marginstop; } - void SetMarginStop(int marginstop) { m_marginstop = marginstop; } - bool UseVPS() const { return m_useVPS; } - void SetUseVPS(bool useVPS) { m_useVPS = useVPS; } - int DelMode() const { return m_delMode; } - void SetDelMode(int delMode) { m_delMode = delMode; } - int DelAfterCountRecs() const { return m_delAfterCountRecs; } - void SetDelAfterCountRecs(int delAfterCountRecs) { m_delAfterCountRecs = delAfterCountRecs; } - int DelAfterDaysOfFirstRec() const { return m_delAfterDaysOfFirstRec; } - void SetDelAfterDaysOfFirstRec(int delAfterDaysOfFirstRec) { m_delAfterDaysOfFirstRec = delAfterDaysOfFirstRec; } - std::string UseAsSearchTimerFrom(std::string const& format); - void SetUseAsSearchTimerFrom(std::string const& datestring, std::string const& format); - std::string UseAsSearchTimerTil(std::string const& format); - void SetUseAsSearchTimerTil(std::string const& datestring, std::string const& format); - bool IgnoreMissingEPGCats() const { return m_ignoreMissingEPGCats; } - void SetIgnoreMissingEPGCats(bool ignoreMissingEPGCats) { m_ignoreMissingEPGCats = ignoreMissingEPGCats; } + enum eUseChannel + { + NoChannel = 0, + Interval = 1, + Group = 2, + FTAOnly = 3 + }; + + SearchTimer(); + SearchTimer( std::string const& data ); + void Init(); + std::string ToText(); + friend bool operator<( SearchTimer const& left, SearchTimer const& right ); + + int Id() const { return m_id; } + void SetId(int id) { m_id = id; } + std::string const& Search() const { return m_search; } + void SetSearch(std::string const& search) { m_search = search; } + int SearchMode() { return m_mode; } + void SetSearchMode(int mode) { m_mode = mode; } + int Tolerance() const { return m_fuzzytolerance; } + void SetTolerance(int tolerance) { m_fuzzytolerance = tolerance; } + bool MatchCase() const { return m_useCase; } + void SetMatchCase(bool useCase) { m_useCase = useCase; } + bool UseTime() const { return m_useTime; } + void SetUseTime(bool useTime) { m_useTime = useTime; } + bool UseTitle() const { return m_useTitle; } + void SetUseTitle(bool useTitle) { m_useTitle = useTitle; } + bool UseSubtitle() const { return m_useSubtitle; } + void SetUseSubtitle(bool useSubtitle) { m_useSubtitle = useSubtitle; } + bool UseDescription() const { return m_useDescription; } + void SetUseDescription(bool useDescription) { m_useDescription = useDescription; } + int StartTime() const { return m_startTime; } + std::string StartTimeFormatted(); + void SetStartTime(int startTime) { m_startTime = startTime; } + int StopTime() const { return m_stopTime; } + std::string StopTimeFormatted(); + void SetStopTime(int stopTime) { m_stopTime = stopTime; } + eUseChannel UseChannel() const { return static_cast( m_useChannel ); } + void SetUseChannel(eUseChannel useChannel) { m_useChannel = useChannel; } + tChannelID ChannelMin() const { return m_channelMin; } + void SetChannelMin(tChannelID channelMin) { m_channelMin = channelMin; } + tChannelID ChannelMax() const { return m_channelMax; } + void SetChannelMax(tChannelID channelMax) { m_channelMax = channelMax; } + std::string ChannelText() const { return m_channels; } + void SetChannelText(const std::string& channels) { m_channels = channels; } + int UseAsSearchTimer() const { return m_useAsSearchtimer; } + void SetUseAsSearchTimer(int useAsSearchtimer) { m_useAsSearchtimer = useAsSearchtimer; } + bool UseDuration() const { return m_useDuration; } + void SetUseDuration(bool useDuration) { m_useDuration = useDuration; } + int MinDuration() const { return m_minDuration; } + void SetMinDuration(int minDuration) { m_minDuration = minDuration; } + int MaxDuration() const { return m_maxDuration; } + void SetMaxDuration(int maxDuration) { m_maxDuration = maxDuration; } + bool UseDayOfWeek() const { return m_useDayOfWeek; } + void SetUseDayOfWeek(bool useDayOfWeek) { m_useDayOfWeek = useDayOfWeek; } + int DayOfWeek() const { return m_dayOfWeek; } + void SetDayOfWeek(int dayOfWeek) { m_dayOfWeek = dayOfWeek; } + bool UseInFavorites() const { return m_useInFavorites; } + void SetUseInFavorites(bool useInFavorites) { m_useInFavorites = useInFavorites; } + int SearchTimerAction() const { return m_action; } + void SetSearchTimerAction(int action) { m_action = action; } + bool UseSeriesRecording() const { return m_useEpisode; } + void SetUseSeriesRecording(bool useEpisode) { m_useEpisode = useEpisode; } + std::string const& Directory() const { return m_directory; } + void SetDirectory(std::string const& directory) { m_directory = directory; } + int DelRecsAfterDays() const { return m_delAfterDays; } + void SetDelRecsAfterDays(int delAfterDays) { m_delAfterDays = delAfterDays; } + int KeepRecs() const { return m_recordingsKeep; } + void SetKeepRecs(int recordingsKeep) { m_recordingsKeep = recordingsKeep; } + int PauseOnRecs() const {return m_pauseOnNrRecordings; } + void SetPauseOnRecs(int pauseOnNrRecordings) { m_pauseOnNrRecordings = pauseOnNrRecordings; } + int BlacklistMode() const {return m_blacklistmode; } + void SetBlacklistMode(int blacklistmode) { m_blacklistmode = blacklistmode; } + bool BlacklistSelected(int id) const; + void ParseBlacklist( std::string const& data ); + int SwitchMinBefore() const { return m_switchMinBefore; } + void SetSwitchMinBefore(int switchMinBefore) { m_switchMinBefore = switchMinBefore; } + bool UseExtEPGInfo() const { return m_useExtEPGInfo; } + void SetUseExtEPGInfo(bool useExtEPGInfo) { m_useExtEPGInfo = useExtEPGInfo; } + std::vector ExtEPGInfo() const { return m_ExtEPGInfo; } + void SetExtEPGInfo(const std::vector& ExtEPGInfo) { m_ExtEPGInfo = ExtEPGInfo; } + bool AvoidRepeats() const { return m_avoidrepeats; } + void SetAvoidRepeats(bool avoidrepeats) { m_avoidrepeats = avoidrepeats; } + int AllowedRepeats() const { return m_allowedrepeats; } + void SetAllowedRepeats(int allowedrepeats) { m_allowedrepeats = allowedrepeats; } + int RepeatsWithinDays() const { return m_repeatsWithinDays; } + void SetRepeatsWithinDays(int repeatsWithinDays) { m_repeatsWithinDays = repeatsWithinDays; } + bool CompareTitle() const { return m_compareTitle; } + void SetCompareTitle(bool compareTitle) { m_compareTitle = compareTitle; } + int CompareSubtitle() const { return m_compareSubtitle; } + void SetCompareSubtitle(int compareSubtitle) { m_compareSubtitle = compareSubtitle; } + bool CompareSummary() const { return m_compareSummary; } + void SetCompareSummary(bool compareSummary) { m_compareSummary = compareSummary; } + unsigned long CompareCategories() const { return m_catvaluesAvoidRepeat; } + void SetCompareCategories(unsigned long compareCategories) { m_catvaluesAvoidRepeat = compareCategories; } + int Priority() const { return m_priority; } + void SetPriority(int priority) { m_priority = priority; } + int Lifetime() const { return m_lifetime; } + void SetLifetime(int lifetime) { m_lifetime = lifetime; } + int MarginStart() const { return m_marginstart; } + void SetMarginStart(int marginstart) { m_marginstart = marginstart; } + int MarginStop() const { return m_marginstop; } + void SetMarginStop(int marginstop) { m_marginstop = marginstop; } + bool UseVPS() const { return m_useVPS; } + void SetUseVPS(bool useVPS) { m_useVPS = useVPS; } + int DelMode() const { return m_delMode; } + void SetDelMode(int delMode) { m_delMode = delMode; } + int DelAfterCountRecs() const { return m_delAfterCountRecs; } + void SetDelAfterCountRecs(int delAfterCountRecs) { m_delAfterCountRecs = delAfterCountRecs; } + int DelAfterDaysOfFirstRec() const { return m_delAfterDaysOfFirstRec; } + void SetDelAfterDaysOfFirstRec(int delAfterDaysOfFirstRec) { m_delAfterDaysOfFirstRec = delAfterDaysOfFirstRec; } + std::string UseAsSearchTimerFrom(std::string const& format); + void SetUseAsSearchTimerFrom(std::string const& datestring, std::string const& format); + std::string UseAsSearchTimerTil(std::string const& format); + void SetUseAsSearchTimerTil(std::string const& datestring, std::string const& format); + bool IgnoreMissingEPGCats() const { return m_ignoreMissingEPGCats; } + void SetIgnoreMissingEPGCats(bool ignoreMissingEPGCats) { m_ignoreMissingEPGCats = ignoreMissingEPGCats; } private: - int m_id; - std::string m_search; - bool m_useTime; - int m_startTime; - int m_stopTime; - int m_useChannel; - tChannelID m_channelMin; - tChannelID m_channelMax; - std::string m_channels; - bool m_useCase; - int m_mode; - bool m_useTitle; - bool m_useSubtitle; - bool m_useDescription; - bool m_useDuration; - int m_minDuration; - int m_maxDuration; - bool m_useDayOfWeek; - int m_dayOfWeek; - bool m_useEpisode; - int m_priority; - int m_lifetime; - int m_fuzzytolerance; - bool m_useInFavorites; - int m_useAsSearchtimer; - int m_action; - std::string m_directory; - int m_delAfterDays; - int m_recordingsKeep; - int m_pauseOnNrRecordings; - int m_switchMinBefore; - int m_marginstart; - int m_marginstop; - bool m_useVPS; - bool m_useExtEPGInfo; - std::vector m_ExtEPGInfo; - bool m_avoidrepeats; - int m_allowedrepeats; - bool m_compareTitle; - int m_compareSubtitle; - bool m_compareSummary; - int m_repeatsWithinDays; - int m_blacklistmode; - std::vector m_blacklistIDs; - int m_menuTemplate; - unsigned long m_catvaluesAvoidRepeat; - int m_delMode; - int m_delAfterCountRecs; - int m_delAfterDaysOfFirstRec; - time_t m_useAsSearchTimerFrom; - time_t m_useAsSearchTimerTil; - bool m_ignoreMissingEPGCats; - - void ParseChannel( std::string const& data ); - void ParseChannelIDs( std::string const& data ); - void ParseExtEPGInfo( std::string const& data ); + int m_id; + std::string m_search; + bool m_useTime; + int m_startTime; + int m_stopTime; + int m_useChannel; + tChannelID m_channelMin; + tChannelID m_channelMax; + std::string m_channels; + bool m_useCase; + int m_mode; + bool m_useTitle; + bool m_useSubtitle; + bool m_useDescription; + bool m_useDuration; + int m_minDuration; + int m_maxDuration; + bool m_useDayOfWeek; + int m_dayOfWeek; + bool m_useEpisode; + int m_priority; + int m_lifetime; + int m_fuzzytolerance; + bool m_useInFavorites; + int m_useAsSearchtimer; + int m_action; + std::string m_directory; + int m_delAfterDays; + int m_recordingsKeep; + int m_pauseOnNrRecordings; + int m_switchMinBefore; + int m_marginstart; + int m_marginstop; + bool m_useVPS; + bool m_useExtEPGInfo; + std::vector m_ExtEPGInfo; + bool m_avoidrepeats; + int m_allowedrepeats; + bool m_compareTitle; + int m_compareSubtitle; + bool m_compareSummary; + int m_repeatsWithinDays; + int m_blacklistmode; + std::vector m_blacklistIDs; + int m_menuTemplate; + unsigned long m_catvaluesAvoidRepeat; + int m_delMode; + int m_delAfterCountRecs; + int m_delAfterDaysOfFirstRec; + time_t m_useAsSearchTimerFrom; + time_t m_useAsSearchTimerTil; + bool m_ignoreMissingEPGCats; + + void ParseChannel( std::string const& data ); + void ParseChannelIDs( std::string const& data ); + void ParseExtEPGInfo( std::string const& data ); }; class ExtEPGInfo { public: - ExtEPGInfo(std::string const& data ); - int Id() const { return m_id; } - std::string Name() const { return m_menuname; } - std::vector Values() const { return m_values; } - bool Selected(unsigned int index, std::string const& values); + ExtEPGInfo(std::string const& data ); + int Id() const { return m_id; } + std::string Name() const { return m_menuname; } + std::vector Values() const { return m_values; } + bool Selected(unsigned int index, std::string const& values); private: - int m_id; - std::string m_name; - std::string m_menuname; - std::vector m_values; - int m_searchmode; + int m_id; + std::string m_name; + std::string m_menuname; + std::vector m_values; + int m_searchmode; - void ParseValues( std::string const& data ); + void ParseValues( std::string const& data ); }; class ExtEPGInfos { public: - typedef std::list ExtEPGInfoList; - typedef ExtEPGInfoList::size_type size_type; - typedef ExtEPGInfoList::iterator iterator; - typedef ExtEPGInfoList::const_iterator const_iterator; + typedef std::list ExtEPGInfoList; + typedef ExtEPGInfoList::size_type size_type; + typedef ExtEPGInfoList::iterator iterator; + typedef ExtEPGInfoList::const_iterator const_iterator; - ExtEPGInfos(); + ExtEPGInfos(); - size_type size() const { return m_infos.size(); } + size_type size() const { return m_infos.size(); } - iterator begin() { return m_infos.begin(); } - const_iterator begin() const { return m_infos.begin(); } - iterator end() { return m_infos.end(); } - const_iterator end() const { return m_infos.end(); } + iterator begin() { return m_infos.begin(); } + const_iterator begin() const { return m_infos.begin(); } + iterator end() { return m_infos.end(); } + const_iterator end() const { return m_infos.end(); } private: - ExtEPGInfoList m_infos; + ExtEPGInfoList m_infos; }; class ChannelGroup { public: - ChannelGroup(std::string const& data ); - std::string Name() { return m_name; } + ChannelGroup(std::string const& data ); + std::string Name() { return m_name; } private: - std::string m_name; + std::string m_name; }; class ChannelGroups { public: - typedef std::list ChannelGroupList; - typedef ChannelGroupList::size_type size_type; - typedef ChannelGroupList::iterator iterator; - typedef ChannelGroupList::const_iterator const_iterator; + typedef std::list ChannelGroupList; + typedef ChannelGroupList::size_type size_type; + typedef ChannelGroupList::iterator iterator; + typedef ChannelGroupList::const_iterator const_iterator; - ChannelGroups(); + ChannelGroups(); - size_type size() const { return m_list.size(); } + size_type size() const { return m_list.size(); } - iterator begin() { return m_list.begin(); } - const_iterator begin() const { return m_list.begin(); } - iterator end() { return m_list.end(); } - const_iterator end() const { return m_list.end(); } + iterator begin() { return m_list.begin(); } + const_iterator begin() const { return m_list.begin(); } + iterator end() { return m_list.end(); } + const_iterator end() const { return m_list.end(); } private: - ChannelGroupList m_list; + ChannelGroupList m_list; }; class SearchTimers { public: - typedef std::list TimerList; - typedef TimerList::size_type size_type; - typedef TimerList::iterator iterator; - typedef TimerList::const_iterator const_iterator; - - SearchTimers(); - bool Save(SearchTimer* searchtimer); - bool Reload(); - - size_type size() const { return m_timers.size(); } - - iterator begin() { return m_timers.begin(); } - const_iterator begin() const { return m_timers.begin(); } - iterator end() { return m_timers.end(); } - const_iterator end() const { return m_timers.end(); } - SearchTimer* GetByTimerId( std::string const& id ); - bool ToggleActive(std::string const& id); - bool Delete(std::string const& id); - void TriggerUpdate(); + typedef std::list TimerList; + typedef TimerList::size_type size_type; + typedef TimerList::iterator iterator; + typedef TimerList::const_iterator const_iterator; + + SearchTimers(); + bool Save(SearchTimer* searchtimer); + bool Reload(); + + size_type size() const { return m_timers.size(); } + + iterator begin() { return m_timers.begin(); } + const_iterator begin() const { return m_timers.begin(); } + iterator end() { return m_timers.end(); } + const_iterator end() const { return m_timers.end(); } + SearchTimer* GetByTimerId( std::string const& id ); + bool ToggleActive(std::string const& id); + bool Delete(std::string const& id); + void TriggerUpdate(); private: - TimerList m_timers; + TimerList m_timers; }; class Blacklist { public: - Blacklist( std::string const& data ); + Blacklist( std::string const& data ); - std::string const& Search() const { return m_search; } - int Id() const { return m_id; } - bool operator<( Blacklist const& other ) const { return Search() < other.Search(); } + std::string const& Search() const { return m_search; } + int Id() const { return m_id; } + bool operator<( Blacklist const& other ) const { return Search() < other.Search(); } private: - int m_id; - std::string m_search; + int m_id; + std::string m_search; }; class Blacklists { public: - typedef std::list blacklist; - typedef blacklist::size_type size_type; - typedef blacklist::iterator iterator; - typedef blacklist::const_iterator const_iterator; + typedef std::list blacklist; + typedef blacklist::size_type size_type; + typedef blacklist::iterator iterator; + typedef blacklist::const_iterator const_iterator; - Blacklists(); + Blacklists(); - size_type size() const { return m_list.size(); } + size_type size() const { return m_list.size(); } - iterator begin() { return m_list.begin(); } - const_iterator begin() const { return m_list.begin(); } - iterator end() { return m_list.end(); } - const_iterator end() const { return m_list.end(); } + iterator begin() { return m_list.begin(); } + const_iterator begin() const { return m_list.begin(); } + iterator end() { return m_list.end(); } + const_iterator end() const { return m_list.end(); } private: - blacklist m_list; + blacklist m_list; }; class SearchResult { public: - SearchResult( std::string const& data ); - - int SearchId() const { return m_searchId; } - tEventID EventId() const { return m_eventId; } - std::string const& Title() const { return m_title; } - std::string const& ShortText() const { return m_shorttext; } - std::string const& Description() const { return m_description; } - time_t StartTime() const { return m_starttime; } - time_t StopTime() const { return m_stoptime; } - tChannelID Channel() const { return m_channel; } - time_t TimerStartTime() const { return m_timerstart; } - time_t TimerStopTime() const { return m_timerstop; } - int TimerMode() const { return m_timerMode; } - bool operator<( SearchResult const& other ) const { return m_starttime < other.m_starttime; } - const cEvent* GetEvent(const cChannel* Channel); + SearchResult( std::string const& data ); + + int SearchId() const { return m_searchId; } + tEventID EventId() const { return m_eventId; } + std::string const& Title() const { return m_title; } + std::string const& ShortText() const { return m_shorttext; } + std::string const& Description() const { return m_description; } + time_t StartTime() const { return m_starttime; } + time_t StopTime() const { return m_stoptime; } + tChannelID Channel() const { return m_channel; } + time_t TimerStartTime() const { return m_timerstart; } + time_t TimerStopTime() const { return m_timerstop; } + int TimerMode() const { return m_timerMode; } + bool operator<( SearchResult const& other ) const { return m_starttime < other.m_starttime; } + const cEvent* GetEvent(const cChannel* Channel); #if VDRVERSNUM >= 20301 - /* Be careful when calling this function concerning the lock order: - * Timers, Channels, Recordings Schedules - */ - const cChannel* GetChannel() { LOCK_CHANNELS_READ; return Channels->GetByChannelID(m_channel); } + /* Be careful when calling this function concerning the lock order: + * Timers, Channels, Recordings Schedules + */ + const cChannel* GetChannel() { LOCK_CHANNELS_READ; return Channels->GetByChannelID(m_channel); } #else - const cChannel* GetChannel() { return Channels.GetByChannelID(m_channel); } + const cChannel* GetChannel() { return Channels.GetByChannelID(m_channel); } #endif private: - int m_searchId; - tEventID m_eventId; - std::string m_title; - std::string m_shorttext; - std::string m_description; - time_t m_starttime; - time_t m_stoptime; - tChannelID m_channel; - time_t m_timerstart; - time_t m_timerstop; - std::string m_file; - int m_timerMode; + int m_searchId; + tEventID m_eventId; + std::string m_title; + std::string m_shorttext; + std::string m_description; + time_t m_starttime; + time_t m_stoptime; + tChannelID m_channel; + time_t m_timerstart; + time_t m_timerstop; + std::string m_file; + int m_timerMode; }; #define QUERYLIFETIME 60*20 // seconds. If a query is not used in this timeframe, it is deleted @@ -387,56 +387,56 @@ class cQueryEntry { }; class SearchResults { - static std::vector queryList; + static std::vector queryList; public: - typedef std::list searchresults; - typedef searchresults::size_type size_type; - typedef searchresults::iterator iterator; - typedef searchresults::const_iterator const_iterator; + typedef std::list searchresults; + typedef searchresults::size_type size_type; + typedef searchresults::iterator iterator; + typedef searchresults::const_iterator const_iterator; - SearchResults() {} - void GetByID(int id); - void GetByQuery(std::string const& query); + SearchResults() {} + void GetByID(int id); + void GetByQuery(std::string const& query); - size_type size() const { return m_list.size(); } + size_type size() const { return m_list.size(); } - iterator begin() { return m_list.begin(); } - const_iterator begin() const { return m_list.begin(); } - iterator end() { return m_list.end(); } - const_iterator end() const { return m_list.end(); } + iterator begin() { return m_list.begin(); } + const_iterator begin() const { return m_list.begin(); } + iterator end() { return m_list.end(); } + const_iterator end() const { return m_list.end(); } - void merge(SearchResults& r) {m_list.merge(r.m_list); m_list.sort();} - static std::string AddQuery(cSv query); - static std::string GetQuery(cSv md5); + void merge(SearchResults& r) {m_list.merge(r.m_list); m_list.sort();} + static std::string AddQuery(cSv query); + static std::string GetQuery(cSv md5); static void CleanQuery(); private: - searchresults m_list; + searchresults m_list; }; class RecordingDirs { public: - typedef std::set recordingdirs; - typedef recordingdirs::size_type size_type; - typedef recordingdirs::iterator iterator; - typedef recordingdirs::const_iterator const_iterator; + typedef std::set recordingdirs; + typedef recordingdirs::size_type size_type; + typedef recordingdirs::iterator iterator; + typedef recordingdirs::const_iterator const_iterator; - RecordingDirs(bool shortList=false); + RecordingDirs(bool shortList=false); - iterator begin() { return m_set.begin(); } - const_iterator begin() const { return m_set.begin(); } - iterator end() { return m_set.end(); } - const_iterator end() const { return m_set.end(); } + iterator begin() { return m_set.begin(); } + const_iterator begin() const { return m_set.begin(); } + iterator end() { return m_set.end(); } + const_iterator end() const { return m_set.end(); } private: - recordingdirs m_set; + recordingdirs m_set; }; class EPGSearchSetupValues { public: - static std::string ReadValue(const std::string& entry); - static bool WriteValue(const std::string& entry, const std::string& value); + static std::string ReadValue(const std::string& entry); + static bool WriteValue(const std::string& entry, const std::string& value); }; class EPGSearchExpr diff --git a/exception.h b/exception.h index b49906a..0e052a7 100644 --- a/exception.h +++ b/exception.h @@ -8,8 +8,8 @@ namespace vdrlive { class HtmlError: public std::runtime_error { public: - explicit HtmlError( std::string const& message ): std::runtime_error( message ) {} - virtual ~HtmlError() throw() {} + explicit HtmlError( std::string const& message ): std::runtime_error( message ) {} + virtual ~HtmlError() throw() {} }; } // namespace vdrlive diff --git a/ffmpeg.cpp b/ffmpeg.cpp index 071276e..13e32a5 100644 --- a/ffmpeg.cpp +++ b/ffmpeg.cpp @@ -14,147 +14,147 @@ namespace vdrlive { FFmpegThread::FFmpegThread() - :cThread("stream utility handler") + :cThread("stream utility handler") { - dsyslog("Live: FFmpegTread() created"); + dsyslog("Live: FFmpegTread() created"); } FFmpegThread::~FFmpegThread() { - Stop(); - dsyslog("Live: FFmpegTread() destructed"); + Stop(); + dsyslog("Live: FFmpegTread() destructed"); } void FFmpegThread::StartFFmpeg(std::string s, std::string url, std::string tag) { - if ( targetUrl.compare(url) || targetTag.compare(tag)) { - dsyslog("Live: FFmpegTread::StartFFmpeg() change %s [%s] -> %s [%s]", targetUrl.c_str(), targetTag.c_str(), url.c_str(), tag.c_str()); - if ( Active() ) Stop(); - targetUrl = url; - targetTag = tag; - } - session = s; - Start(); - dsyslog("Live: FFmpegTread::StartFFmpeg() completed"); + if ( targetUrl.compare(url) || targetTag.compare(tag)) { + dsyslog("Live: FFmpegTread::StartFFmpeg() change %s [%s] -> %s [%s]", targetUrl.c_str(), targetTag.c_str(), url.c_str(), tag.c_str()); + if ( Active() ) Stop(); + targetUrl = url; + targetTag = tag; + } + session = s; + Start(); + dsyslog("Live: FFmpegTread::StartFFmpeg() completed"); } void FFmpegThread::Stop() { - cw.Signal(); - dsyslog("Live: FFmpegTread::Stop() try stopping"); - if ( Active() ) Cancel( 5 ); - dsyslog("Live: FFmpegTread::Stop() stopped"); + cw.Signal(); + dsyslog("Live: FFmpegTread::Stop() try stopping"); + if ( Active() ) Cancel( 5 ); + dsyslog("Live: FFmpegTread::Stop() stopped"); } void FFmpegThread::Touch() { - touch = true; + touch = true; } void FFmpegThread::Action() { - dsyslog("Live: FFmpegTread::Action() started url = %s [%s]", targetUrl.c_str(), targetTag.c_str()); - - // read command for tag from FFMPG configuration file - std::string line; - std::string packerCmd; - static const char *ws = "\t "; // whitespace separators between tags and commands - try { - std::ifstream config(LiveSetup().GetFFmpegConf()); - while (std::getline(config, line)) { - size_t tag = line.find_first_not_of(ws); - if (tag == std::string::npos) continue; // empty - if (line[tag] == '#') continue; // comment - if (line.compare(tag, targetTag.length(), targetTag)) continue; // wrong tag prefix - size_t sep = line.find_first_of(ws, tag + targetTag.length()); - if (sep == std::string::npos) continue; // unterminated tag - size_t cmd = line.find_first_not_of(ws, sep); - if (cmd == std::string::npos) continue; // no command - packerCmd = line.substr(cmd); - break; - } - config.close(); - } - catch (std::exception const& ex) { - esyslog("ERROR: live reading file \"%s\": %s", LiveSetup().GetFFmpegConf().c_str(), ex.what()); - } - - if (packerCmd.empty()) { - esyslog("ERROR: live could not find FFMPEG command for tag \"%s\"", targetTag.c_str()); - } else { - - std::stringstream ss; - ss.str(""); - ss << "\"http://localhost:" << LiveSetup().GetStreamdevPort() << "/" << targetUrl << "\""; - packerCmd.replace(packerCmd.find(""), 7, ss.str()); - dsyslog("Live: FFmpegTread::Action packetizer cmd: %s", packerCmd.c_str()); - - try { - cPipe2 pp; - int retry = 0; - int count = 0; - do { - ss.str(""); - ss << "mkdir -p /tmp/live-hls-buffer/" << session << " && " - "cd /tmp/live-hls-buffer/" << session << " && rm -rf * && " - "exec " << packerCmd << " " - "-f hls -hls_time 1 -hls_start_number_source datetime -hls_flags delete_segments " - "-master_pl_name master_"; - ss << targetUrl; - ss << ".m3u8 ffmpeg_"; - ss << targetUrl; - ss << "_data.m3u8"; - bool ret = pp.Open(ss.str().c_str(), "w"); // start ffmpeg - - dsyslog("Live: FFmpegTread::Action::Open(%d) ffmpeg started", ret); - - ss.str(""); - ss << "/tmp/live-hls-buffer/" << session << "/master_"; - ss << targetUrl; - ss << ".m3u8"; - - count = 0; - do { - cw.Wait(1000); - std::ifstream f(ss.str().c_str()); - if (f.good()) break; // check if ffmpeg starts to generate output - dsyslog("Live: FFmpegTread::Action() ffmpeg starting... %d", count); - } while (Running() && pp.Check() == 0 && ++count < 6); - if (pp.Check() < 0) continue; - - if (count < 6) { - dsyslog("Live: FFmpegTread::Action() ffmpeg running %d", count); - break; - } - else { // ffmpeg did not start properly - fwrite("q", 1, 1, pp); fflush(pp); // send quit commmand to ffmpeg - usleep(200e3); - int r = pp.Close(); - dsyslog("Live: FFmpegTread::Action::Close(%d) disabled ffmpeg", r); - usleep(500e3); - } - } while (retry++ < 2 && Running()); - if (retry > 1) return; - - touch = false; - count = 0; - while (Running() && pp.Check() == 0 && count++ < 60) { - if (touch) { - touch = false; - count = 0; - } - cw.Wait(1000); - } - fwrite("q", 1, 1, pp); fflush(pp); // send quit commmand to ffmpeg - usleep(500e3); - int r = pp.Close(); - dsyslog("Live: FFmpegTread::Action::Close(%d) disabled ffmpeg", r); - - } catch (std::exception const& ex) { - esyslog("ERROR: live FFmpegTread::Action() failed: %s", ex.what()); - } - } - dsyslog("Live: FFmpegTread::Action() finished"); + dsyslog("Live: FFmpegTread::Action() started url = %s [%s]", targetUrl.c_str(), targetTag.c_str()); + + // read command for tag from FFMPG configuration file + std::string line; + std::string packerCmd; + static const char *ws = "\t "; // whitespace separators between tags and commands + try { + std::ifstream config(LiveSetup().GetFFmpegConf()); + while (std::getline(config, line)) { + size_t tag = line.find_first_not_of(ws); + if (tag == std::string::npos) continue; // empty + if (line[tag] == '#') continue; // comment + if (line.compare(tag, targetTag.length(), targetTag)) continue; // wrong tag prefix + size_t sep = line.find_first_of(ws, tag + targetTag.length()); + if (sep == std::string::npos) continue; // unterminated tag + size_t cmd = line.find_first_not_of(ws, sep); + if (cmd == std::string::npos) continue; // no command + packerCmd = line.substr(cmd); + break; + } + config.close(); + } + catch (std::exception const& ex) { + esyslog("ERROR: live reading file \"%s\": %s", LiveSetup().GetFFmpegConf().c_str(), ex.what()); + } + + if (packerCmd.empty()) { + esyslog("ERROR: live could not find FFMPEG command for tag \"%s\"", targetTag.c_str()); + } else { + + std::stringstream ss; + ss.str(""); + ss << "\"http://localhost:" << LiveSetup().GetStreamdevPort() << "/" << targetUrl << "\""; + packerCmd.replace(packerCmd.find(""), 7, ss.str()); + dsyslog("Live: FFmpegTread::Action packetizer cmd: %s", packerCmd.c_str()); + + try { + cPipe2 pp; + int retry = 0; + int count = 0; + do { + ss.str(""); + ss << "mkdir -p /tmp/live-hls-buffer/" << session << " && " + "cd /tmp/live-hls-buffer/" << session << " && rm -rf * && " + "exec " << packerCmd << " " + "-f hls -hls_time 1 -hls_start_number_source datetime -hls_flags delete_segments " + "-master_pl_name master_"; + ss << targetUrl; + ss << ".m3u8 ffmpeg_"; + ss << targetUrl; + ss << "_data.m3u8"; + bool ret = pp.Open(ss.str().c_str(), "w"); // start ffmpeg + + dsyslog("Live: FFmpegTread::Action::Open(%d) ffmpeg started", ret); + + ss.str(""); + ss << "/tmp/live-hls-buffer/" << session << "/master_"; + ss << targetUrl; + ss << ".m3u8"; + + count = 0; + do { + cw.Wait(1000); + std::ifstream f(ss.str().c_str()); + if (f.good()) break; // check if ffmpeg starts to generate output + dsyslog("Live: FFmpegTread::Action() ffmpeg starting... %d", count); + } while (Running() && pp.Check() == 0 && ++count < 6); + if (pp.Check() < 0) continue; + + if (count < 6) { + dsyslog("Live: FFmpegTread::Action() ffmpeg running %d", count); + break; + } + else { // ffmpeg did not start properly + fwrite("q", 1, 1, pp); fflush(pp); // send quit commmand to ffmpeg + usleep(200e3); + int r = pp.Close(); + dsyslog("Live: FFmpegTread::Action::Close(%d) disabled ffmpeg", r); + usleep(500e3); + } + } while (retry++ < 2 && Running()); + if (retry > 1) return; + + touch = false; + count = 0; + while (Running() && pp.Check() == 0 && count++ < 60) { + if (touch) { + touch = false; + count = 0; + } + cw.Wait(1000); + } + fwrite("q", 1, 1, pp); fflush(pp); // send quit commmand to ffmpeg + usleep(500e3); + int r = pp.Close(); + dsyslog("Live: FFmpegTread::Action::Close(%d) disabled ffmpeg", r); + + } catch (std::exception const& ex) { + esyslog("ERROR: live FFmpegTread::Action() failed: %s", ex.what()); + } + } + dsyslog("Live: FFmpegTread::Action() finished"); } // --- cPipe2 ----------------------------------------------------------------- @@ -164,132 +164,132 @@ void FFmpegThread::Action() cPipe2::cPipe2(void) { - pid = -1; - f = NULL; + pid = -1; + f = NULL; } cPipe2::~cPipe2() { - Close(); + Close(); } bool cPipe2::Open(const char *Command, const char *Mode) { - int fd[2]; - - if (pipe(fd) < 0) { - LOG_ERROR; - return false; - } - if ((pid = fork()) < 0) { // fork failed - LOG_ERROR; - close(fd[0]); - close(fd[1]); - return false; - } - - const char *mode = "w"; - int iopipe = 0; - - if (pid > 0) { // parent process - terminated = false; - if (strcmp(Mode, "r") == 0) { - mode = "r"; - iopipe = 1; - } - close(fd[iopipe]); - if ((f = fdopen(fd[1 - iopipe], mode)) == NULL) { - LOG_ERROR; - close(fd[1 - iopipe]); - } - return f != NULL; - } - else { // child process - int iofd = STDOUT_FILENO; - if (strcmp(Mode, "w") == 0) { - iopipe = 1; - iofd = STDIN_FILENO; - } - close(fd[iopipe]); - if (dup2(fd[1 - iopipe], iofd) == -1) { // now redirect - LOG_ERROR; - close(fd[1 - iopipe]); - _exit(-1); - } - else { - int MaxPossibleFileDescriptors = getdtablesize(); - for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++) - close(i); //close all dup'ed filedescriptors - if (execl("/bin/sh", "sh", "-c", Command, NULL) == -1) { - LOG_ERROR_STR(Command); - close(fd[1 - iopipe]); - _exit(-1); - } - } - _exit(0); - } + int fd[2]; + + if (pipe(fd) < 0) { + LOG_ERROR; + return false; + } + if ((pid = fork()) < 0) { // fork failed + LOG_ERROR; + close(fd[0]); + close(fd[1]); + return false; + } + + const char *mode = "w"; + int iopipe = 0; + + if (pid > 0) { // parent process + terminated = false; + if (strcmp(Mode, "r") == 0) { + mode = "r"; + iopipe = 1; + } + close(fd[iopipe]); + if ((f = fdopen(fd[1 - iopipe], mode)) == NULL) { + LOG_ERROR; + close(fd[1 - iopipe]); + } + return f != NULL; + } + else { // child process + int iofd = STDOUT_FILENO; + if (strcmp(Mode, "w") == 0) { + iopipe = 1; + iofd = STDIN_FILENO; + } + close(fd[iopipe]); + if (dup2(fd[1 - iopipe], iofd) == -1) { // now redirect + LOG_ERROR; + close(fd[1 - iopipe]); + _exit(-1); + } + else { + int MaxPossibleFileDescriptors = getdtablesize(); + for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++) + close(i); //close all dup'ed filedescriptors + if (execl("/bin/sh", "sh", "-c", Command, NULL) == -1) { + LOG_ERROR_STR(Command); + close(fd[1 - iopipe]); + _exit(-1); + } + } + _exit(0); + } } int cPipe2::Check(void) { - int ret = -1; - - if (terminated) return -1; - if (pid > 0) { - int status = 0; - ret = waitpid(pid, &status, WNOHANG);; - if (ret < 0) { - if (errno != EINTR && errno != ECHILD) { - LOG_ERROR; - return ret; - } - } - if (ret > 0) terminated = true; - - } - - return ret; + int ret = -1; + + if (terminated) return -1; + if (pid > 0) { + int status = 0; + ret = waitpid(pid, &status, WNOHANG);; + if (ret < 0) { + if (errno != EINTR && errno != ECHILD) { + LOG_ERROR; + return ret; + } + } + if (ret > 0) terminated = true; + + } + + return ret; } int cPipe2::Close(void) { - int ret = -1; - - if (f) { - fclose(f); - f = NULL; - } - - if (pid > 0) { - int status = 0; - int i = 5; - while (i > 0) { - ret = waitpid(pid, &status, WNOHANG); - if (ret < 0) { - if (errno != EINTR && errno != ECHILD) { - LOG_ERROR; - break; - } - } - else if (ret == pid) - break; - i--; - cCondWait::SleepMs(100); - } - if (!i) { - kill(pid, SIGINT); - cCondWait::SleepMs(100); - ret = waitpid(pid, &status, WNOHANG); - kill(pid, SIGKILL); - cCondWait::SleepMs(100); - ret = waitpid(pid, &status, WNOHANG); - } - else if (ret == -1 || !WIFEXITED(status)) - ret = -1; - pid = -1; - } - - return ret; + int ret = -1; + + if (f) { + fclose(f); + f = NULL; + } + + if (pid > 0) { + int status = 0; + int i = 5; + while (i > 0) { + ret = waitpid(pid, &status, WNOHANG); + if (ret < 0) { + if (errno != EINTR && errno != ECHILD) { + LOG_ERROR; + break; + } + } + else if (ret == pid) + break; + i--; + cCondWait::SleepMs(100); + } + if (!i) { + kill(pid, SIGINT); + cCondWait::SleepMs(100); + ret = waitpid(pid, &status, WNOHANG); + kill(pid, SIGKILL); + cCondWait::SleepMs(100); + ret = waitpid(pid, &status, WNOHANG); + } + else if (ret == -1 || !WIFEXITED(status)) + ret = -1; + pid = -1; + } + + return ret; } } // namespace vdrlive diff --git a/ffmpeg.h b/ffmpeg.h index 64b3244..80d0e33 100644 --- a/ffmpeg.h +++ b/ffmpeg.h @@ -8,22 +8,22 @@ namespace vdrlive { class FFmpegThread : public cThread { public: - FFmpegThread(); - ~FFmpegThread(); + FFmpegThread(); + ~FFmpegThread(); - void StartFFmpeg(std::string s, std::string url, std::string tag); - void Stop(); - void Touch(); + void StartFFmpeg(std::string s, std::string url, std::string tag); + void Stop(); + void Touch(); protected: - void Action(); + void Action(); private: - cCondWait cw; - bool touch = false; - std::string targetUrl; - std::string targetTag; - std::string session; + cCondWait cw; + bool touch = false; + std::string targetUrl; + std::string targetTag; + std::string session; }; // cPipe2 implements a pipe that closes all unnecessary file descriptors in @@ -31,16 +31,16 @@ class FFmpegThread : public cThread { class cPipe2 { private: - pid_t pid; - bool terminated = false; - FILE *f; + pid_t pid; + bool terminated = false; + FILE *f; public: - cPipe2(void); - ~cPipe2(); - operator FILE* () { return f; } - bool Open(const char *Command, const char *Mode); - int Check(void); - int Close(void); + cPipe2(void); + ~cPipe2(); + operator FILE* () { return f; } + bool Open(const char *Command, const char *Mode); + int Check(void); + int Close(void); }; } // namespace vdrlive diff --git a/filecache.cpp b/filecache.cpp index 9f6a9e1..9206cb4 100644 --- a/filecache.cpp +++ b/filecache.cpp @@ -10,35 +10,35 @@ namespace vdrlive { std::time_t FileObject::get_filetime( std::string const& path ) { - struct stat sbuf; - if ( stat( path.c_str(), &sbuf ) < 0 ) - return 0; - return sbuf.st_ctime; + struct stat sbuf; + if ( stat( path.c_str(), &sbuf ) < 0 ) + return 0; + return sbuf.st_ctime; } bool FileObject::load() { - std::ifstream ifs( m_path.c_str(), std::ios::in | std::ios::binary | std::ios::ate ); - if ( !ifs ) - return false; + std::ifstream ifs( m_path.c_str(), std::ios::in | std::ios::binary | std::ios::ate ); + if ( !ifs ) + return false; - std::streamsize size = ifs.tellg(); - ifs.seekg( 0, std::ios::beg ); + std::streamsize size = ifs.tellg(); + ifs.seekg( 0, std::ios::beg ); - std::vector data( size ); - data.resize( size ); - ifs.read( &data[0], size ); - ifs.close(); + std::vector data( size ); + data.resize( size ); + ifs.read( &data[0], size ); + ifs.close(); - m_ctime = get_filetime( m_path ); - m_data.swap( data ); - return true; + m_ctime = get_filetime( m_path ); + m_data.swap( data ); + return true; } FileCache& LiveFileCache() { - static FileCache instance( 1000000 ); - return instance; + static FileCache instance( 1000000 ); + return instance; } } // namespace vdrlive @@ -48,6 +48,6 @@ using namespace vdrlive; int main() { - FileCache::ptr_type f = LiveFileCache().get("/tmp/live/active.png"); + FileCache::ptr_type f = LiveFileCache().get("/tmp/live/active.png"); } #endif diff --git a/filecache.h b/filecache.h index c2f0007..900a7ee 100644 --- a/filecache.h +++ b/filecache.h @@ -16,45 +16,45 @@ namespace vdrlive { class FileObject { public: - FileObject( std::string const& path ) - : m_ctime( std::numeric_limits::max() ) - , m_path( path ) {} + FileObject( std::string const& path ) + : m_ctime( std::numeric_limits::max() ) + , m_path( path ) {} - std::size_t size() const { return m_data.size(); } - std::size_t weight() const { return size(); } - bool is_current() const { return m_ctime == get_filetime( m_path ); } - bool load(); - char const* data() const { return &m_data[0]; } - std::time_t ctime() const { return m_ctime; } + std::size_t size() const { return m_data.size(); } + std::size_t weight() const { return size(); } + bool is_current() const { return m_ctime == get_filetime( m_path ); } + bool load(); + char const* data() const { return &m_data[0]; } + std::time_t ctime() const { return m_ctime; } private: - static std::time_t get_filetime( std::string const& path ); + static std::time_t get_filetime( std::string const& path ); - mutable std::time_t m_ctime; - std::string m_path; - std::vector m_data; + mutable std::time_t m_ctime; + std::string m_path; + std::vector m_data; }; class FileCache: public vgstools::cache { - typedef vgstools::cache base_type; + typedef vgstools::cache base_type; public: - FileCache( size_t maxWeight ): base_type( maxWeight ) {} + FileCache( size_t maxWeight ): base_type( maxWeight ) {} - ptr_type get( key_type const& key ) - { - cMutexLock lock( &m_mutex ); - // dsyslog( "vdrlive::FileCache::get( %s )", key.c_str() ); - // dsyslog( "vdrlive::FileCache had %u entries (weight: %u)", count(), weight() ); - ptr_type result = base_type::get( key ); - // dsyslog( "vdrlive::FileCache now has %u entries (weight: %u)", count(), weight() ); - // dsyslog( "vdrlive::FileCache::get( %s ) = %p", key.c_str(), result.get() ); - return result; - } + ptr_type get( key_type const& key ) + { + cMutexLock lock( &m_mutex ); + // dsyslog( "vdrlive::FileCache::get( %s )", key.c_str() ); + // dsyslog( "vdrlive::FileCache had %u entries (weight: %u)", count(), weight() ); + ptr_type result = base_type::get( key ); + // dsyslog( "vdrlive::FileCache now has %u entries (weight: %u)", count(), weight() ); + // dsyslog( "vdrlive::FileCache::get( %s ) = %p", key.c_str(), result.get() ); + return result; + } private: - cMutex m_mutex; + cMutex m_mutex; }; //typedef vgstools::cache FileCache; diff --git a/grab.cpp b/grab.cpp index 7299dbc..2d63ab1 100644 --- a/grab.cpp +++ b/grab.cpp @@ -13,98 +13,98 @@ const unsigned int GrabPauseIntervalMs = GrabMinIntervalMs * 20; class GrabImageTask: public StickyTask { public: - explicit GrabImageTask( int quality = 80, int width = 729, int height = 480 ) - : m_firstTime( 0 ) - , m_lastTime( 0 ) - , m_quality( quality ) - , m_width( width ) - , m_height( height ) - {} + explicit GrabImageTask( int quality = 80, int width = 729, int height = 480 ) + : m_firstTime( 0 ) + , m_lastTime( 0 ) + , m_quality( quality ) + , m_width( width ) + , m_height( height ) + {} - void Activate() { m_firstTime = 0; } - bool IsActive(); + void Activate() { m_firstTime = 0; } + bool IsActive(); private: - uint64_t m_firstTime; - uint64_t m_lastTime; - int m_quality; - int m_width; - int m_height; - - bool GrabImage(); - - virtual void Action(); + uint64_t m_firstTime; + uint64_t m_lastTime; + int m_quality; + int m_width; + int m_height; + + bool GrabImage(); + + virtual void Action(); }; bool GrabImageTask::IsActive() { - cMutexLock lock( &LiveTaskManager() ); - return GrabImage(); + cMutexLock lock( &LiveTaskManager() ); + return GrabImage(); } bool GrabImageTask::GrabImage() { - cDevice* device = cDevice::PrimaryDevice(); - if ( device == 0 ) { - SetError( tr("Couldn't acquire primary device") ); - return false; - } - - int size = 0; - uchar* image = device->GrabImage( size, true, m_quality, m_width, m_height ); - if ( image == 0 ) { - SetError( tr("Couldn't grab image from primary device") ); - return false; - } - - LiveGrabImageManager().PutImage( reinterpret_cast( image ), size ); - return true; + cDevice* device = cDevice::PrimaryDevice(); + if ( device == 0 ) { + SetError( tr("Couldn't acquire primary device") ); + return false; + } + + int size = 0; + uchar* image = device->GrabImage( size, true, m_quality, m_width, m_height ); + if ( image == 0 ) { + SetError( tr("Couldn't grab image from primary device") ); + return false; + } + + LiveGrabImageManager().PutImage( reinterpret_cast( image ), size ); + return true; } void GrabImageTask::Action() { - uint64_t now = cTimeMs::Now(); + uint64_t now = cTimeMs::Now(); - if ( m_firstTime == 0 ) - m_firstTime = now; + if ( m_firstTime == 0 ) + m_firstTime = now; - if ( now - m_lastTime < GrabMinIntervalMs || now - m_firstTime > GrabPauseIntervalMs ) - return; + if ( now - m_lastTime < GrabMinIntervalMs || now - m_firstTime > GrabPauseIntervalMs ) + return; - if ( !GrabImage() ) - return; + if ( !GrabImage() ) + return; - m_lastTime = now; + m_lastTime = now; } GrabImageManager::GrabImageManager() - : m_task( new GrabImageTask ) - , m_size( 0 ) + : m_task( new GrabImageTask ) + , m_size( 0 ) { } GrabImageInfo GrabImageManager::GetImage() const { - cMutexLock lock( &LiveTaskManager() ); - m_task->Activate(); - return std::make_pair( m_image, m_size ); + cMutexLock lock( &LiveTaskManager() ); + m_task->Activate(); + return std::make_pair( m_image, m_size ); } bool GrabImageManager::CanGrab() const { - return m_task->IsActive(); + return m_task->IsActive(); } void GrabImageManager::PutImage( char* image, int size ) { - m_image.reset( image, &free ); - m_size = size; + m_image.reset( image, &free ); + m_size = size; } GrabImageManager& LiveGrabImageManager() { - static GrabImageManager instance; - return instance; + static GrabImageManager instance; + return instance; } } // namespace vdrlive diff --git a/grab.h b/grab.h index 06c4176..894f01f 100644 --- a/grab.h +++ b/grab.h @@ -14,24 +14,24 @@ class GrabImageTask; class GrabImageManager { - friend GrabImageManager& LiveGrabImageManager(); - friend class GrabImageTask; + friend GrabImageManager& LiveGrabImageManager(); + friend class GrabImageTask; public: - bool CanGrab() const; - GrabImageInfo GetImage() const; + bool CanGrab() const; + GrabImageInfo GetImage() const; private: - GrabImageManager(); - GrabImageManager( GrabImageManager const& ); + GrabImageManager(); + GrabImageManager( GrabImageManager const& ); - GrabImageManager& operator=( GrabImageManager const& ); + GrabImageManager& operator=( GrabImageManager const& ); - void PutImage( char* image, int size ); + void PutImage( char* image, int size ); - std::unique_ptr m_task; - GrabImagePtr m_image; - int m_size; + std::unique_ptr m_task; + GrabImagePtr m_image; + int m_size; }; GrabImageManager& LiveGrabImageManager(); diff --git a/i18n.cpp b/i18n.cpp index 57db521..7d2c682 100644 --- a/i18n.cpp +++ b/i18n.cpp @@ -1,6 +1,6 @@ /* - This file has some own functionality and is used as backward - compatibility for vdr prior to version 1.5.7 language support. + This file has some own functionality and is used as backward + compatibility for vdr prior to version 1.5.7 language support. Backward compatibility to old language support has been dropped on Feb 13, 2015. */ @@ -12,23 +12,23 @@ namespace vdrlive { - I18n& LiveI18n() - { - static I18n instance; - return instance; - } + I18n& LiveI18n() + { + static I18n instance; + return instance; + } - I18n::I18n() - : m_encoding(cCharSetConv::SystemCharacterTable() ? cCharSetConv::SystemCharacterTable() : "UTF-8") - { - // fix encoding spelling for HTML standard. - std::string const iso("iso"); - if (m_encoding.find(iso) != std::string::npos) { - if (iso.length() == m_encoding.find_first_of("0123456789")) { - m_encoding.insert(iso.length(), "-"); - } - } - } + I18n::I18n() + : m_encoding(cCharSetConv::SystemCharacterTable() ? cCharSetConv::SystemCharacterTable() : "UTF-8") + { + // fix encoding spelling for HTML standard. + std::string const iso("iso"); + if (m_encoding.find(iso) != std::string::npos) { + if (iso.length() == m_encoding.find_first_of("0123456789")) { + m_encoding.insert(iso.length(), "-"); + } + } + } } // namespace vdrlive diff --git a/i18n.h b/i18n.h index 7e8cba9..1825c69 100644 --- a/i18n.h +++ b/i18n.h @@ -7,16 +7,16 @@ namespace vdrlive { class I18n { - friend I18n& LiveI18n(); + friend I18n& LiveI18n(); - private: - std::string m_encoding; + private: + std::string m_encoding; - I18n( I18n const& ); // don't copy - I18n(); + I18n( I18n const& ); // don't copy + I18n(); - public: - std::string const& CharacterEncoding() const { return m_encoding; } + public: + std::string const& CharacterEncoding() const { return m_encoding; } }; I18n& LiveI18n(); diff --git a/live.cpp b/live.cpp index c7ff57e..9ab9800 100644 --- a/live.cpp +++ b/live.cpp @@ -35,48 +35,48 @@ Plugin::Plugin(void) const char *Plugin::CommandLineHelp(void) { - return LiveSetup().CommandLineHelp(); + return LiveSetup().CommandLineHelp(); } bool Plugin::ProcessArgs(int argc, char *argv[]) { - return LiveSetup().ParseCommandLine( argc, argv ); + return LiveSetup().ParseCommandLine( argc, argv ); } bool Plugin::Initialize(void) { - m_configDirectory = canonicalize_file_name(cPlugin::ConfigDirectory( PLUGIN_NAME_I18N )); - m_resourceDirectory = canonicalize_file_name(cPlugin::ResourceDirectory( PLUGIN_NAME_I18N )); + m_configDirectory = canonicalize_file_name(cPlugin::ConfigDirectory( PLUGIN_NAME_I18N )); + m_resourceDirectory = canonicalize_file_name(cPlugin::ResourceDirectory( PLUGIN_NAME_I18N )); - return LiveSetup().Initialize(); + return LiveSetup().Initialize(); } bool Plugin::Start(void) { - // force status monitor startup - LiveStatusMonitor(); + // force status monitor startup + LiveStatusMonitor(); - // preload files into file Cache - PreLoadFileCache(m_resourceDirectory); + // preload files into file Cache + PreLoadFileCache(m_resourceDirectory); - // load users - Users.Load(AddDirectory(m_configDirectory.c_str(), "users.conf"), true); + // load users + Users.Load(AddDirectory(m_configDirectory.c_str(), "users.conf"), true); - // XXX error handling - m_thread.reset( new ServerThread ); - m_thread->Start(); - return true; + // XXX error handling + m_thread.reset( new ServerThread ); + m_thread->Start(); + return true; } void Plugin::Stop(void) { - m_thread->Stop(); + m_thread->Stop(); } void Plugin::MainThreadHook(void) { - LiveTimerManager().DoPendingWork(); - LiveTaskManager().DoScheduledTasks(); + LiveTimerManager().DoPendingWork(); + LiveTaskManager().DoScheduledTasks(); } void Plugin::Housekeeping(void) { @@ -85,17 +85,17 @@ void Plugin::Housekeeping(void) { cString Plugin::Active(void) { - return NULL; + return NULL; } cMenuSetupPage *Plugin::SetupMenu(void) { - return new cMenuSetupLive(); + return new cMenuSetupLive(); } bool Plugin::SetupParse(const char *Name, const char *Value) { - return LiveSetup().ParseSetupEntry( Name, Value ); + return LiveSetup().ParseSetupEntry( Name, Value ); } class cLiveImageProviderImp: public cLiveImageProvider { diff --git a/live.h b/live.h index 4ad4a9f..a537629 100644 --- a/live.h +++ b/live.h @@ -20,32 +20,32 @@ namespace vdrlive { class Plugin : public cPlugin { public: - Plugin(void); - virtual const char *Version(void) { return VERSION; } - virtual const char *Description(void) { return tr(DESCRIPTION); } - virtual const char *CommandLineHelp(void); - virtual bool ProcessArgs(int argc, char *argv[]); - virtual bool Start(void); - virtual bool Initialize(void); - virtual void Stop(void); - virtual void MainThreadHook(void); - virtual void Housekeeping(void); - virtual cString Active(void); - virtual cMenuSetupPage *SetupMenu(void); - virtual bool SetupParse(const char *Name, const char *Value); + Plugin(void); + virtual const char *Version(void) { return VERSION; } + virtual const char *Description(void) { return tr(DESCRIPTION); } + virtual const char *CommandLineHelp(void); + virtual bool ProcessArgs(int argc, char *argv[]); + virtual bool Start(void); + virtual bool Initialize(void); + virtual void Stop(void); + virtual void MainThreadHook(void); + virtual void Housekeeping(void); + virtual cString Active(void); + virtual cMenuSetupPage *SetupMenu(void); + virtual bool SetupParse(const char *Name, const char *Value); virtual bool Service(const char *Id, void *Data = NULL); - static std::string const& GetConfigDirectory() { return m_configDirectory; } - static std::string const& GetResourceDirectory() { return m_resourceDirectory; } + static std::string const& GetConfigDirectory() { return m_configDirectory; } + static std::string const& GetResourceDirectory() { return m_resourceDirectory; } private: - static const char *VERSION; - static const char *DESCRIPTION; + static const char *VERSION; + static const char *DESCRIPTION; - static std::string m_configDirectory; - static std::string m_resourceDirectory; + static std::string m_configDirectory; + static std::string m_resourceDirectory; - std::unique_ptr m_thread; + std::unique_ptr m_thread; }; } // namespace vdrlive diff --git a/live/css/siteprefs.css b/live/css/siteprefs.css index bab3a8b..fd84985 100644 --- a/live/css/siteprefs.css +++ b/live/css/siteprefs.css @@ -12,7 +12,7 @@ */ /* table { - width: 100%; + width: 100%; } */ @@ -22,6 +22,6 @@ table { */ /* .info-win span.epg_images { - width: 120px; + width: 120px; } */ diff --git a/live/css/styles.css b/live/css/styles.css index 607e0d3..bac4a7f 100644 --- a/live/css/styles.css +++ b/live/css/styles.css @@ -4,67 +4,67 @@ */ html, body { - color: black; - background-color: white; + color: black; + background-color: white; } body { - margin: 0px; - padding: 0px; - font-size: 11px; - font-family: Verdana, Arial, Helvetica, sans-serif; + margin: 0px; + padding: 0px; + font-size: 11px; + font-family: Verdana, Arial, Helvetica, sans-serif; } table { - font-size: 11px; - font-family: Verdana, Arial, Helvetica, sans-serif; - margin: 0px; + font-size: 11px; + font-family: Verdana, Arial, Helvetica, sans-serif; + margin: 0px; } tr, td { - padding-top: 0px; - padding-bottom: 0px; + padding-top: 0px; + padding-bottom: 0px; } form { - margin: 0; - padding: 0; + margin: 0; + padding: 0; } input, textarea { - border: 1px solid #6D96A9; - font-size: 11px; - font-family: Verdana, Arial, Helvetica, sans-serif; - background: #FEFEFE; - margin: 0; + border: 1px solid #6D96A9; + font-size: 11px; + font-family: Verdana, Arial, Helvetica, sans-serif; + background: #FEFEFE; + margin: 0; } input.width99, textarea.width99 { - width: 99%; + width: 99%; } select { - border: 1px solid #6D96A9; - font-size: 11px; - font-family: Verdana, Arial, Helvetica, sans-serif; + border: 1px solid #6D96A9; + font-size: 11px; + font-family: Verdana, Arial, Helvetica, sans-serif; } img { - border: 0; + border: 0; } img.icon { - margin: 2px; + margin: 2px; } a { - text-decoration: none; + text-decoration: none; } a:hover { - text-decoration: underline; + text-decoration: underline; } a:active { - text-decoration: underline; + text-decoration: underline; } @@ -74,57 +74,57 @@ a:active { */ .bold { - font-weight: bold; + font-weight: bold; } .dotted { - border: 1px dotted #bbbbbb; - padding: 3px; - margin: 2px; - float: left; - background-color: #f3f3f3; + border: 1px dotted #bbbbbb; + padding: 3px; + margin: 2px; + float: left; + background-color: #f3f3f3; } .title { - font-weight: bold; + font-weight: bold; } .short { - font-weight: normal; + font-weight: normal; } .normal-font { - font-weight: normal; + font-weight: normal; } .bold-font { - font-weight: bold; + font-weight: bold; } .margin-bottom { - margin-bottom: 5px; + margin-bottom: 5px; } .more { - font-weight: bold; - cursor: pointer; + font-weight: bold; + cursor: pointer; } .withmargin { - margin: 5px; + margin: 5px; } .nomargin { - margin: 0px; + margin: 0px; } .notpresent { - display: none; + display: none; } .nowrap { - white-space: nowrap; + white-space: nowrap; } .scraper_list { - margin-top: 4px; - margin-bottom: 4px; + margin-top: 4px; + margin-bottom: 4px; } @@ -134,54 +134,54 @@ a:active { */ .hint-tip { - margin: 0px auto; - max-width: 480px; /* depends on the tip background image width */ - color: #fff; + margin: 0px auto; + max-width: 480px; /* depends on the tip background image width */ + color: #fff; } .hint-tip .hint-tip-top .hint-tip-c, .hint-tip .hint-tip-bot .hint-tip-c { - font-size: 1px; /* ensure minimum height */ - height: 17px; + font-size: 1px; /* ensure minimum height */ + height: 17px; } .hint-tip .hint-tip-top { - background: transparent url(../img/rounded-box-blue-tl.png) no-repeat 0px 0px; - margin-right: 17px; /* space for right corner */ + background: transparent url(../img/rounded-box-blue-tl.png) no-repeat 0px 0px; + margin-right: 17px; /* space for right corner */ } .hint-tip .hint-tip-top .hint-tip-c { - background: transparent url(../img/rounded-box-blue-tr.png) no-repeat right 0px; - margin-right: -17px; /* pull right corner back over "empty" space (from above margin) */ + background: transparent url(../img/rounded-box-blue-tr.png) no-repeat right 0px; + margin-right: -17px; /* pull right corner back over "empty" space (from above margin) */ } .hint-tip .hint-tip-bdy { - background: transparent url(../img/rounded-box-blue-ml.png) repeat-y 0px 0px; - margin-right: 17px; + background: transparent url(../img/rounded-box-blue-ml.png) repeat-y 0px 0px; + margin-right: 17px; } .hint-tip .hint-tip-bdy .hint-tip-c { - background: transparent url(../img/rounded-box-blue-mr.png) repeat-y right 0px; - margin-right: -17px; + background: transparent url(../img/rounded-box-blue-mr.png) repeat-y right 0px; + margin-right: -17px; } .hint-tip .hint-tip-bdy .hint-tip-c .hint-tip-s { /* optional gradient overlay */ - /* background: transparent url(../img/rounded-box-blue-ms.jpg) repeat-x 0px 0px; */ - padding: 0px 17px 0px 17px; + /* background: transparent url(../img/rounded-box-blue-ms.jpg) repeat-x 0px 0px; */ + padding: 0px 17px 0px 17px; } .hint-tip .hint-tip-bot { - background: transparent url(../img/rounded-box-blue-bl.png) no-repeat 0px 0px; - margin-right: 17px; + background: transparent url(../img/rounded-box-blue-bl.png) no-repeat 0px 0px; + margin-right: 17px; } .hint-tip .hint-tip-bot .hint-tip-c { - background: transparent url(../img/rounded-box-blue-br.png) no-repeat right 0px; - margin-right: -17px; + background: transparent url(../img/rounded-box-blue-br.png) no-repeat right 0px; + margin-right: -17px; } .hint-title { - display: none; + display: none; } @@ -191,50 +191,50 @@ a:active { */ .ok-info { - margin: 0px auto; - max-width: 480px; /* depends on the tip background image width */ - color: #fff; + margin: 0px auto; + max-width: 480px; /* depends on the tip background image width */ + color: #fff; } .ok-info .ok-info-top .ok-info-c, .ok-info .ok-info-bot .ok-info-c { - font-size: 1px; /* ensure minimum height */ - height: 17px; + font-size: 1px; /* ensure minimum height */ + height: 17px; } .ok-info .ok-info-top { - background: transparent url(../img/rounded-box-green-tl.png) no-repeat 0px 0px; - margin-right: 17px; /* space for right corner */ + background: transparent url(../img/rounded-box-green-tl.png) no-repeat 0px 0px; + margin-right: 17px; /* space for right corner */ } .ok-info .ok-info-top .ok-info-c { - background: transparent url(../img/rounded-box-green-tr.png) no-repeat right 0px; - margin-right: -17px; /* pull right corner back over "empty" space (from above margin) */ + background: transparent url(../img/rounded-box-green-tr.png) no-repeat right 0px; + margin-right: -17px; /* pull right corner back over "empty" space (from above margin) */ } .ok-info .ok-info-body { - background: transparent url(../img/rounded-box-green-ml.png) repeat-y 0px 0px; - margin-right: 17px; + background: transparent url(../img/rounded-box-green-ml.png) repeat-y 0px 0px; + margin-right: 17px; } .ok-info .ok-info-body .ok-info-c { - background: transparent url(../img/rounded-box-green-mr.png) repeat-y right 0px; - margin-right: -17px; + background: transparent url(../img/rounded-box-green-mr.png) repeat-y right 0px; + margin-right: -17px; } .ok-info .ok-info-body .ok-info-c .ok-info-s { /* optional gradient overlay */ - /* background: transparent url(../img/rounded-box-green-ms.jpg) repeat-x 0px 0px; */ - padding: 0px 17px 0px 17px; + /* background: transparent url(../img/rounded-box-green-ms.jpg) repeat-x 0px 0px; */ + padding: 0px 17px 0px 17px; } .ok-info .ok-info-bot { - background: transparent url(../img/rounded-box-green-bl.png) no-repeat 0px 0px; - margin-right: 17px; + background: transparent url(../img/rounded-box-green-bl.png) no-repeat 0px 0px; + margin-right: 17px; } .ok-info .ok-info-bot .ok-info-c { - background: transparent url(../img/rounded-box-green-br.png) no-repeat right 0px; - margin-right: -17px; + background: transparent url(../img/rounded-box-green-br.png) no-repeat right 0px; + margin-right: -17px; } @@ -244,50 +244,50 @@ a:active { */ .err-info { - margin: 0px auto; - max-width: 480px; /* depends on the tip background image width */ - color: #fff; + margin: 0px auto; + max-width: 480px; /* depends on the tip background image width */ + color: #fff; } .err-info .err-info-top .err-info-c, .err-info .err-info-bot .err-info-c { - font-size: 1px; /* ensure minimum height */ - height: 17px; + font-size: 1px; /* ensure minimum height */ + height: 17px; } .err-info .err-info-top { - background: transparent url(../img/rounded-box-redwine-tl.png) no-repeat 0px 0px; - margin-right: 17px; /* space for right corner */ + background: transparent url(../img/rounded-box-redwine-tl.png) no-repeat 0px 0px; + margin-right: 17px; /* space for right corner */ } .err-info .err-info-top .err-info-c { - background: transparent url(../img/rounded-box-redwine-tr.png) no-repeat right 0px; - margin-right: -17px; /* pull right corner back over "empty" space (from above margin) */ + background: transparent url(../img/rounded-box-redwine-tr.png) no-repeat right 0px; + margin-right: -17px; /* pull right corner back over "empty" space (from above margin) */ } .err-info .err-info-body { - background: transparent url(../img/rounded-box-redwine-ml.png) repeat-y 0px 0px; - margin-right: 17px; + background: transparent url(../img/rounded-box-redwine-ml.png) repeat-y 0px 0px; + margin-right: 17px; } .err-info .err-info-body .err-info-c { - background: transparent url(../img/rounded-box-redwine-mr.png) repeat-y right 0px; - margin-right: -17px; + background: transparent url(../img/rounded-box-redwine-mr.png) repeat-y right 0px; + margin-right: -17px; } .err-info .err-info-body .err-info-c .err-info-s { /* optional gradient overlay */ - /* background: transparent url(../img/rounded-box-redwine-ms.jpg) repeat-x 0px 0px; */ - padding: 0px 17px 0px 17px; + /* background: transparent url(../img/rounded-box-redwine-ms.jpg) repeat-x 0px 0px; */ + padding: 0px 17px 0px 17px; } .err-info .err-info-bot { - background: transparent url(../img/rounded-box-redwine-bl.png) no-repeat 0px 0px; - margin-right: 17px; + background: transparent url(../img/rounded-box-redwine-bl.png) no-repeat 0px 0px; + margin-right: 17px; } .err-info .err-info-bot .err-info-c { - background: transparent url(../img/rounded-box-redwine-br.png) no-repeat right 0px; - margin-right: -17px; + background: transparent url(../img/rounded-box-redwine-br.png) no-repeat right 0px; + margin-right: -17px; } @@ -297,24 +297,24 @@ a:active { */ div.epg_content { - border: 1px solid black; + border: 1px solid black; } span.epg_images { - float: right; + float: right; margin-left: 5px; - width: 240px; + width: 240px; } img.actor { - width: 118px; + width: 118px; } img.artwork { - width: 480px + width: 480px } img.channel_logo { - max-height:32px; max-width:120px; vertical-align:middle; - background-color: #E9EFFF00; + max-height:32px; max-width:120px; vertical-align:middle; + background-color: #E9EFFF00; } @@ -324,92 +324,92 @@ img.channel_logo { */ div.info-win { - width: 560px; - max-width: 2048px; - border: none; - margin: 0px auto; + width: 560px; + max-width: 2048px; + border: none; + margin: 0px auto; } div.info-win img.actor { - width: 118px; + width: 118px; } div.info-win img.artwork { - width: 480px; + width: 480px; } .info-win .info-win-top .info-win-c { - /*font-size: 1px;*/ /* ensure minimum height */ - height: 37px; + /*font-size: 1px;*/ /* ensure minimum height */ + height: 37px; } .info-win .info-win-bot .info-win-c { - font-size: 1px; /* ensure minimum height */ - height: 21px; + font-size: 1px; /* ensure minimum height */ + height: 21px; } .info-win .info-win-top { - background: transparent url(../img/info-win-t-l.png) no-repeat 0px 0px; - margin-right: 26px; /* space for right corner */ + background: transparent url(../img/info-win-t-l.png) no-repeat 0px 0px; + margin-right: 26px; /* space for right corner */ } .info-win .info-win-top .info-win-c { - background: transparent url(../img/info-win-t-r.png) no-repeat right 0px; - margin-right: -26px; /* pull right corner back over "empty" space (from above margin) */ - overflow: hidden; + background: transparent url(../img/info-win-t-r.png) no-repeat right 0px; + margin-right: -26px; /* pull right corner back over "empty" space (from above margin) */ + overflow: hidden; } .info-win .info-win-top .info-win-c .info-win-t { - color: #FFF; - font-weight: bold; - margin-top: 14px; - margin-left: 15px; - float: left; + color: #FFF; + font-weight: bold; + margin-top: 14px; + margin-left: 15px; + float: left; max-width: 490px; } .info-win .info-win-top .info-win-c .info-win-b { - margin-top: 17px; - margin-right: 26px; - float: right; + margin-top: 17px; + margin-right: 26px; + float: right; } .info-win .info-win-top .info-win-c .info-win-b .close { - width: 16px; - height: 16px; - background: transparent url(../img/close.png) no-repeat top right; + width: 16px; + height: 16px; + background: transparent url(../img/close.png) no-repeat top right; } .info-win .info-win-top .info-win-c .info-win-b .close:hover { - width: 16px; - height: 16px; - background: transparent url(../img/close_red.png) no-repeat top right; + width: 16px; + height: 16px; + background: transparent url(../img/close_red.png) no-repeat top right; } .info-win .info-win-body { - background: transparent url(../img/info-win-m-l.png) repeat-y 0px 0px; - margin-right: 26px; + background: transparent url(../img/info-win-m-l.png) repeat-y 0px 0px; + margin-right: 26px; } .info-win .info-win-body .info-win-c { - background: transparent url(../img/info-win-m-r.png) repeat-y right 0px; - margin-right: -26px; + background: transparent url(../img/info-win-m-r.png) repeat-y right 0px; + margin-right: -26px; } .info-win .info-win-body .info-win-c .info-win-s { - padding: 0px 26px 0px 14px; + padding: 0px 26px 0px 14px; } .info-win .info-win-bot { - background: transparent url(../img/info-win-b-l.png) no-repeat 0px 0px; - margin-right: 26px; + background: transparent url(../img/info-win-b-l.png) no-repeat 0px 0px; + margin-right: 26px; } .info-win .info-win-bot .info-win-c { - background: transparent url(../img/info-win-b-r.png) no-repeat right 0px; - margin-right: -26px; + background: transparent url(../img/info-win-b-r.png) no-repeat right 0px; + margin-right: -26px; } .hint-title { - display: none; + display: none; } @@ -419,38 +419,38 @@ div.info-win img.artwork { */ div.menu { - background: #000057 url(../img/menu_line_bg.png) repeat-x; - min-height: 27px; - margin: 0; - padding: 0 0 0 10px; - line-height: 20px; - vertical-align: middle; - border-top: 1px solid black; - border-bottom: 1px solid black; - color: #6D96A9; + background: #000057 url(../img/menu_line_bg.png) repeat-x; + min-height: 27px; + margin: 0; + padding: 0 0 0 10px; + line-height: 20px; + vertical-align: middle; + border-top: 1px solid black; + border-bottom: 1px solid black; + color: #6D96A9; } div.menu a { - color: white; - font-weight: bold; + color: white; + font-weight: bold; } a#login { - color: #F5FF2D; + color: #F5FF2D; } div.menu a.active { - color: #FFDB88; - font-weight: bold; + color: #FFDB88; + font-weight: bold; } div.menu form { - display: inline; + display: inline; } div.inhalt { - overflow: auto; - padding: 10px; + overflow: auto; + padding: 10px; } @@ -460,56 +460,56 @@ div.inhalt { */ div#pagemenu { - margin-top: 2px; - padding-top: 6px; - background: #FFFFFF url(../img/bg_line.png) top repeat-x; + margin-top: 2px; + padding-top: 6px; + background: #FFFFFF url(../img/bg_line.png) top repeat-x; } div#pagemenu div { - padding-bottom: 6px; - background: #FFFFFF url(../img/bg_line_top.png) bottom repeat-x; + padding-bottom: 6px; + background: #FFFFFF url(../img/bg_line_top.png) bottom repeat-x; } div#pagemenu div div { - padding: 2px 0px 2px 10px; - background: #E9EFFF; - border-top: 1px solid #C0C1DA; - border-bottom: 1px solid #C0C1DA; + padding: 2px 0px 2px 10px; + background: #E9EFFF; + border-top: 1px solid #C0C1DA; + border-bottom: 1px solid #C0C1DA; } div#pagemenu div div div { - border: 0; - padding: 0; - margin: 0; + border: 0; + padding: 0; + margin: 0; } div#pagemenu form { - display: inline; + display: inline; } div#pagemenu form#remote input { - margin-left: 1em; + margin-left: 1em; } div#pagemenu a { - color: black; - font-weight: bold; + color: black; + font-weight: bold; } div#pagemenu a.active { - color: blue; - font-weight: bold; + color: blue; + font-weight: bold; } div#pagemenu form a { - /* - margin-left: 1em; - */ + /* + margin-left: 1em; + */ } div#pagemenu form a img { - vertical-align: middle; - margin-top: -5px; + vertical-align: middle; + margin-top: -5px; } @@ -519,45 +519,45 @@ div#pagemenu form a img { */ div#messagebar { - margin-top: 8px; - margin-bottom: 2px; - line-height: 20px; + margin-top: 8px; + margin-bottom: 2px; + line-height: 20px; min-height: 27px; - vertical-align: middle; - background: #7CAD3F url(../img/msgbar_line_bg.png) top repeat-x; - border-top: 1px solid #2B6B00; - border-bottom: 1px solid #2B6B00; + vertical-align: middle; + background: #7CAD3F url(../img/msgbar_line_bg.png) top repeat-x; + border-top: 1px solid #2B6B00; + border-bottom: 1px solid #2B6B00; } div#messagebar div { - color: black; + color: black; } div#messagebar div div { - padding-left: 10px; - background: transparent; + padding-left: 10px; + background: transparent; } div#messagebar div div div { - border: 0; - padding: 0; - margin: 0; + border: 0; + padding: 0; + margin: 0; } div#messagebar a { - color: black; - font-weight: bold; + color: black; + font-weight: bold; } div#messagebar a.active { - color: blue; - font-weight: bold; + color: blue; + font-weight: bold; } div#messagebar span#mbmessage { - padding: 0em 1em 0em 1em; - color: #A14040; - font-weight: bold; + padding: 0em 1em 0em 1em; + color: #A14040; + font-weight: bold; } @@ -567,66 +567,66 @@ div#messagebar span#mbmessage { */ img.logo { - float: left; - margin-top: 5px; - margin-left: 5px; - margin-right: 25px; + float: left; + margin-top: 5px; + margin-left: 5px; + margin-right: 25px; } div#infobox { - float: left; - border: 1px solid #C0C1DA; - margin: 5px; - min-width: 320px; + float: left; + border: 1px solid #C0C1DA; + margin: 5px; + min-width: 320px; } div#infobox div.st_header { - overflow: hidden; - padding: 1px 4px; - background: #E9EFFF; - border-bottom: 1px solid #C0C1DA; + overflow: hidden; + padding: 1px 4px; + background: #E9EFFF; + border-bottom: 1px solid #C0C1DA; } div#infobox div.st_header div.now { - float: right; + float: right; } div#infobox div.st_header div.caption { - float: left; - overflow: hidden; - font-weight: bold; - padding: 0px; + float: left; + overflow: hidden; + font-weight: bold; + padding: 0px; } div#infobox div.st_content { - overflow: hidden; - padding: 4px; - background: white url(../img/bg_line_top.png) top left repeat-x; + overflow: hidden; + padding: 4px; + background: white url(../img/bg_line_top.png) top left repeat-x; } div#infobox div.st_content div.duration { - float: right; - padding-left: 2em; + float: right; + padding-left: 2em; } div#infobox div.st_content div.name { - float: left; - overflow: hidden; - font-weight: bold; + float: left; + overflow: hidden; + font-weight: bold; } div#infobox div.st_controls { - overflow: hidden; - padding: 4px; + overflow: hidden; + padding: 4px; } div#infobox div.st_controls div.st_pbar { - padding-top: 4px; - float: right; + padding-top: 4px; + float: right; } div#infobox div.st_controls div { - float: left; + float: left; } div#infobox div.st_controls div.st_update { @@ -649,31 +649,31 @@ div#infobox div.st_controls div#infobox_channel_buttons { */ button { - width: 100px; - height: 20px; - color: #FFFFFF; - font-size: 11px; - border: 0px; - vertical-align: middle; - text-align: center; - cursor: pointer; - padding-bottom: 3px; + width: 100px; + height: 20px; + color: #FFFFFF; + font-size: 11px; + border: 0px; + vertical-align: middle; + text-align: center; + cursor: pointer; + padding-bottom: 3px; } button.green { - background-image: url(../img/button_green.png); + background-image: url(../img/button_green.png); } button.red { - background-image: url(../img/button_red.png); + background-image: url(../img/button_red.png); } button.blue { - background-image: url(../img/button_blue.png); + background-image: url(../img/button_blue.png); } button.yellow { - background-image: url(../img/button_yellow.png); + background-image: url(../img/button_yellow.png); } @@ -683,7 +683,7 @@ button.yellow { */ table td.buttonpanel { - text-align: right; + text-align: right; } table td.toprow { @@ -693,27 +693,27 @@ table th.toprow { } table td.bottomrow { - border-bottom: 1px solid black !important; + border-bottom: 1px solid black !important; } table td.leftcol { - border-left: 1px solid black; + border-left: 1px solid black; } table td.rightcol { - border-right: 1px solid black; + border-right: 1px solid black; } table td.topaligned { - vertical-align: top; + vertical-align: top; } table td.padded { - padding: 3px 7px 3px 3px; + padding: 3px 7px 3px 3px; } table td.cast_role { - text-align: left; - font-weight: bold; + text-align: left; + font-weight: bold; } @@ -723,118 +723,118 @@ table td.cast_role { */ div.event { - width: 255px; - height: 255px; - padding: 0; - margin-right: 5px; - float: left; + width: 255px; + height: 255px; + padding: 0; + margin-right: 5px; + float: left; } div.event div.station { - margin: 0; - padding: 0; - width: 255px; + margin: 0; + padding: 0; + width: 255px; } div.event div.title a { - color: black; + color: black; } div.station div { - margin: 0; - padding: 0; - background: url(../img/bg_box_l.png) top left no-repeat; - height: 23px; + margin: 0; + padding: 0; + background: url(../img/bg_box_l.png) top left no-repeat; + height: 23px; } div.station div div { - background: url(../img/bg_box_r.png) top right no-repeat; + background: url(../img/bg_box_r.png) top right no-repeat; } div.station div div div { - background: url(../img/bg_box_h.png) repeat-x; - line-height: 20px; - vertical-align: middle; - text-align: left; - margin-right: 3px; - margin-left: 3px; - padding-left: 5px; - padding-top: 2px; - font-weight: bold; - border-bottom: none; + background: url(../img/bg_box_h.png) repeat-x; + line-height: 20px; + vertical-align: middle; + text-align: left; + margin-right: 3px; + margin-left: 3px; + padding-left: 5px; + padding-top: 2px; + font-weight: bold; + border-bottom: none; } div.station div div div a { - color: #ffffff; - font-weight: bold; + color: #ffffff; + font-weight: bold; } td div.station { - vertical-align: middle; + vertical-align: middle; } td div.station a { - color: black; - font-weight: bold; + color: black; + font-weight: bold; } div.content { - width: 253px; - height: 220px; - padding: 0; - margin: 0; - overflow: hidden; + width: 253px; + height: 220px; + padding: 0; + margin: 0; + overflow: hidden; - background: white url(../img/bg_tools.png) top left repeat-y; - border-left: 1px solid #000000; - border-right: 1px solid #000000; - border-bottom: 1px solid #000000; + background: white url(../img/bg_tools.png) top left repeat-y; + border-left: 1px solid #000000; + border-right: 1px solid #000000; + border-bottom: 1px solid #000000; } div.content div.tools { - float: left; - width: 26px; - height: 220px; - margin: 0; - padding: 0; - padding-top: 3px; - text-align: center; - vertical-align: top; + float: left; + width: 26px; + height: 220px; + margin: 0; + padding: 0; + padding-top: 3px; + text-align: center; + vertical-align: top; } div.content div.whatson_info { - margin-left: 31px; + margin-left: 31px; } div.content div.tools img { - margin: 2px 5px; + margin: 2px 5px; } div.description { - margin: 5px 5px 0px 5px; - overflow: hidden; + margin: 5px 5px 0px 5px; + overflow: hidden; } div.title { - margin: 5px; + margin: 5px; } div.short { - margin: 5px; + margin: 5px; } div.info { - margin: 5px 5px 0px 5px; - overflow: hidden; + margin: 5px 5px 0px 5px; + overflow: hidden; } div.info div.duration { - float: right; - margin: 0px 5px 0px 5px; + float: right; + margin: 0px 5px 0px 5px; } div.info div.time { - margin: 0px 5px 0px 5px; + margin: 0px 5px 0px 5px; } .margin_right { @@ -842,39 +842,39 @@ div.info div.time { } div.info div.date { - float: left; + float: left; padding: 0px; } div.progress { - overflow: hidden; - padding: 2px 0px; - margin: 0px 5px 0px 0px; + overflow: hidden; + padding: 2px 0px; + margin: 0px 5px 0px 0px; } div.progress div { - float: right; - padding: 0px; + float: right; + padding: 0px; } div.__progress { - overflow: hidden; - width: 100px; - height: 8px; - border: 1px solid #C0C1DA; + overflow: hidden; + width: 100px; + height: 8px; + border: 1px solid #C0C1DA; } div.__progress_invisible { - overflow: hidden; - width: 100px; - height: 10px; - border: 0px none transparent; + overflow: hidden; + width: 100px; + height: 10px; + border: 0px none transparent; } div.__progress div.__elapsed { - float: left; - height: 8px; - background-color: #E9EFFF; + float: left; + height: 8px; + background-color: #E9EFFF; } @@ -885,21 +885,21 @@ div.__progress div.__elapsed { */ table.listing { - padding: 0px; - margin: 0px; + padding: 0px; + margin: 0px; } table.listing>tbody>tr>td { - background: transparent url(../img/bg_line.png) bottom repeat-x; - border-bottom: 1px solid #C0C1DA; + background: transparent url(../img/bg_line.png) bottom repeat-x; + border-bottom: 1px solid #C0C1DA; } table.listing tbody tr td.action { - padding-left: 3px; - padding-right: 5px; + padding-left: 3px; + padding-right: 5px; } .action-rightcol { - padding-right: 4px; + padding-right: 4px; float: right; } .noborder { @@ -909,12 +909,12 @@ table.listing tbody tr td.action { } table.listing tr td.leftcol { - padding-left: 7px; - padding-right: 5px; + padding-left: 7px; + padding-right: 5px; } table.listing tr td.current { - color: blue; + color: blue; } table.listing tr td.noborder { @@ -923,27 +923,27 @@ table.listing tr td.noborder { } table.listing>tbody>tr.head>td { - color: white; - font-weight: bold; - margin: 0px; - padding: 0px; - border-bottom: 1px solid black; + color: white; + font-weight: bold; + margin: 0px; + padding: 0px; + border-bottom: 1px solid black; } table.listing tr.description td { - font-weight: bold; - background: #E9EFFF; + font-weight: bold; + background: #E9EFFF; } table.listing tr.spacer td { - height: 10px; - background: transparent; - border-bottom: 0px; + height: 10px; + background: transparent; + border-bottom: 0px; } table.listing a { - color: black; - font-weight: bold; + color: black; + font-weight: bold; } @@ -954,65 +954,65 @@ table.listing a { */ div.player-container { - width: 100%; - padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */ - position: relative; /* for the player inside of it */ - text-align: center; + width: 100%; + padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */ + position: relative; /* for the player inside of it */ + text-align: center; } div.player { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; } table.streaming { - width: 100%; - max-width: 1280px; - margin-top: 2ex; - margin-left: auto; - margin-right: auto; - text-align: center; + width: 100%; + max-width: 1280px; + margin-top: 2ex; + margin-left: auto; + margin-right: auto; + text-align: center; } table.streaming>tbody>tr>td { - width: auto; - vertical-align: top; - white-space: nowrap; - border: 0px none black; - padding: 0px 5px 0px 5px; + width: auto; + vertical-align: top; + white-space: nowrap; + border: 0px none black; + padding: 0px 5px 0px 5px; } table.streaming>tbody>tr>td .short { - white-space: normal; + white-space: normal; } table.streaming>tbody>tr>td.action { - border-left: 1px none black; + border-left: 1px none black; } table.streaming>tbody>tr>td:first-child { - width: auto; - border-left: 1px none black; + width: auto; + border-left: 1px none black; } table.streaming>tbody>tr>td:last-child { - width: 100%; + width: 100%; } table.streaming>tbody>tr>td { - background: inherit; - border-left: 1px solid black; + background: inherit; + border-left: 1px solid black; } table.streaming .withmargin { - margin: 0px; + margin: 0px; } table.streaming .progress { - margin: 0px; + margin: 0px; } @@ -1023,8 +1023,8 @@ table.streaming .progress { */ table.mschedule { - padding: 0px; - margin: 0px; + padding: 0px; + margin: 0px; } table.mschedule tr { @@ -1032,14 +1032,14 @@ table.mschedule tr { } table.mschedule td.time { - vertical-align: top; - padding: 5px; + vertical-align: top; + padding: 5px; } table.mschedule tr td.event { - vertical-align: top; - background: transparent url(../img/bg_line.png) bottom repeat-x; - border-bottom: 1px solid #C0C1DA; + vertical-align: top; + background: transparent url(../img/bg_line.png) bottom repeat-x; + border-bottom: 1px solid #C0C1DA; } table.mschedule tr td.has_timer { @@ -1099,14 +1099,14 @@ table.mschedule tr td div.description { } table.mschedule a { - /* + /* color: black; - font-weight: bold; + font-weight: bold; */ } table.mschedule a>img { - vertical-align: text-bottom; + vertical-align: text-bottom; } @@ -1115,31 +1115,31 @@ table.mschedule a>img { ############################# */ -div.boxheader { - margin: 0px; - padding: 0px; - background: url(../img/bg_box_l.png) top left no-repeat; +div.boxheader { + margin: 0px; + padding: 0px; + background: url(../img/bg_box_l.png) top left no-repeat; } div.boxheader > div { - margin: 0px; - background: url(../img/bg_box_r.png) top right no-repeat; + margin: 0px; + background: url(../img/bg_box_r.png) top right no-repeat; } div.boxheader > div > div { - background: url(../img/bg_box_h.png) repeat-x; - vertical-align: middle; - text-align: left; - margin-right: 3px; - margin-left: 3px; - padding-left: 5px; - padding-right: 5px; - padding-top: 2px; - color: white; - font-weight: bold; - height: 21px; - line-height: 20px; - white-space: nowrap; + background: url(../img/bg_box_h.png) repeat-x; + vertical-align: middle; + text-align: left; + margin-right: 3px; + margin-left: 3px; + padding-left: 5px; + padding-right: 5px; + padding-top: 2px; + color: white; + font-weight: bold; + height: 21px; + line-height: 20px; + white-space: nowrap; } @@ -1149,82 +1149,82 @@ div.boxheader > div > div { */ table.recordings { - border-spacing: 0px; - border: 0px; - border-collapse: collapse; + border-spacing: 0px; + border: 0px; + border-collapse: collapse; } table.recordings a { color: black; } div.recordings { - border: 1px solid black; + border: 1px solid black; } .recordings ul { - list-style-type: none; - padding: 0px; - margin: 0px; + list-style-type: none; + padding: 0px; + margin: 0px; } div.recording_item { - overflow: hidden; - background: url(../img/bg_line.png) bottom repeat-x; - border-bottom: 1px solid #C0C1DA; + overflow: hidden; + background: url(../img/bg_line.png) bottom repeat-x; + border-bottom: 1px solid #C0C1DA; } tr.recording_item { - overflow: hidden; - background: url(../img/bg_line.png) bottom repeat-x; - border-bottom: 1px solid #C0C1DA; + overflow: hidden; + background: url(../img/bg_line.png) bottom repeat-x; + border-bottom: 1px solid #C0C1DA; } tr.recording_item:last-child { - border-bottom: 2px solid #C0C1DA; + border-bottom: 2px solid #C0C1DA; } .recording_item > div { - float: left; + float: left; } .recording_item div.recording_imgs { - margin: 2px; + margin: 2px; } .recording_item .recording_folder_name { - font-weight: bold; - cursor: pointer; + font-weight: bold; + cursor: pointer; } .recording_item .recording_folder_name_new { - font-weight: bold; - color: orangered; - cursor: pointer; + font-weight: bold; + color: orangered; + cursor: pointer; } .recording_item div.recording_name_new { - color: orangered; + color: orangered; } .recording_item div.recording_name_new a { - color: orangered; + color: orangered; } .recording_item div.recording_errors { - width: 26px; + width: 26px; } .recording_item div.recording_sd_hd { - width: 35px; + width: 35px; } .recording_item div.recording_arch { - float: right; - padding-top: 0.5ex; - padding-left: 0.5em; - padding-right: 0.5em; + float: right; + padding-top: 0.5ex; + padding-left: 0.5em; + padding-right: 0.5em; } .recording_item div.recording_actions { - float: right; - padding-left: 0.5em; - padding-right: 0.5em; + float: right; + padding-left: 0.5em; + padding-right: 0.5em; } @@ -1234,18 +1234,18 @@ tr.recording_item:last-child { */ div.screenshot { - background-image: url(../img/tv.jpg); - background-repeat: no-repeat; - height: 320px; - width: 569px; - float: left; - padding: 20px 20px 98px 21px; - margin-right: 20px; + background-image: url(../img/tv.jpg); + background-repeat: no-repeat; + height: 320px; + width: 569px; + float: left; + padding: 20px 20px 98px 21px; + margin-right: 20px; } div.screenshot img { - width: 569px; - height: 320px; + width: 569px; + height: 320px; } @@ -1255,55 +1255,55 @@ div.screenshot img { */ #osd { - background-color:black; - color:white; - height: 320px; - width: 569px; + background-color:black; + color:white; + height: 320px; + width: 569px; } .osd { - padding: 5px 0px 5px 10px; - position:relative; + padding: 5px 0px 5px 10px; + position:relative; } .osd div { - margin:0px; - tab-size:4; - font-family: "Courier New", Courier, monospace; + margin:0px; + tab-size:4; + font-family: "Courier New", Courier, monospace; } .osdMessage { - position:absolute; + position:absolute; overflow:auto; - top:250px; - max-height: 100px; - min-height:20px; - width: 510px; + top:250px; + max-height: 100px; + min-height:20px; + width: 510px; background-color:yellow; color:black; padding:10px; border:2px solid red; } .osdText, .osdItems { - overflow:auto; - overflow-x:hidden; - height: 267px; - width: 555px; - margin:5px 0px !important; + overflow:auto; + overflow-x:hidden; + height: 267px; + width: 555px; + margin:5px 0px !important; } .osdItem, .osdTitle { - cursor:pointer; - white-space: nowrap; + cursor:pointer; + white-space: nowrap; } .osdItem.selected { - background-color:#cccccc; - color:#000000; + background-color:#cccccc; + color:#000000; } .osdButtons {} .osdButtons div { - float:left; - margin-right:5px; - padding:2px; - width:130px; - text-align: center; - cursor:pointer; + float:left; + margin-right:5px; + padding:2px; + width:130px; + text-align: center; + cursor:pointer; } .osdButtonGreen {background-color:green} @@ -1318,27 +1318,27 @@ div.screenshot img { */ table.error { - border: 1px solid #E9360D; - margin: 2px; - padding: 0px; + border: 1px solid #E9360D; + margin: 2px; + padding: 0px; } table.error tr td.message { - padding: 5px; + padding: 5px; } table.error tr td.title { - background: #E9360D; - color: white; - font-weight: bold; - margin: 0; - padding: 3px 3px 3px 10px; + background: #E9360D; + color: white; + font-weight: bold; + margin: 0; + padding: 3px 3px 3px 10px; } table.error td.border { - padding: 0; - margin: 0; - width: 1px; + padding: 0; + margin: 0; + width: 1px; } @@ -1349,14 +1349,14 @@ table.error td.border { */ table.formular { - margin-top: 10px; + margin-top: 10px; } table.formular tr td { - vertical-align: top; - vertical-align: middle; - background: url(../img/bg_line.png) bottom repeat-x; - border-bottom: 1px solid #C0C1DA; + vertical-align: top; + vertical-align: middle; + background: url(../img/bg_line.png) bottom repeat-x; + border-bottom: 1px solid #C0C1DA; } table.formular tr td input { @@ -1369,43 +1369,43 @@ table.formular tr td .dotted input { } table.formular tr td.leftcol { - padding-left: 2px; + padding-left: 2px; } table.formular tr td.rightcol { - padding-right: 7px; + padding-right: 7px; } table.formular tr td.label { - font-weight: bold; - vertical-align: top; + font-weight: bold; + vertical-align: top; } table.formular tr.head td { - color: white; - font-weight: bold; - margin: 0; - padding: 0; - border: none; + color: white; + font-weight: bold; + margin: 0; + padding: 0; + border: none; } table.dependent { - background-color: #FFFFFF; - margin-top: 3px; - margin-bottom: 5px; + background-color: #FFFFFF; + margin-top: 3px; + margin-bottom: 5px; } table.dependent tr:last-child td { - border-bottom: 1px none red; + border-bottom: 1px none red; } table.dependent tr td { - background: transparent; - vertical-align: middle; + background: transparent; + vertical-align: middle; } table.dependent tr td.label .withmargin { - margin-left: 0px; + margin-left: 0px; } @@ -1415,12 +1415,12 @@ table.dependent tr td.label .withmargin { */ table.login { - margin: 0 auto; + margin: 0 auto; } table.login tr td { - padding: 3px 5px; - text-align: right; + padding: 3px 5px; + text-align: right; } @@ -1430,39 +1430,39 @@ table.login tr td { */ div.caption { - padding: 2px 0px 0px 5px; + padding: 2px 0px 0px 5px; } div.epg_content { - padding: 0px 0px 7px 0px; - margin: 0px 0px 0px 0px; + padding: 0px 0px 7px 0px; + margin: 0px 0px 0px 0px; background: transparent url(../img/bg_tools.png) top left repeat-y; border: 1px solid black; - overflow: hidden; + overflow: hidden; } div.epg_content div.epg_tools { - float: left; - width: 26px; - margin: 0 5px 0 0; - margin: 0 5px 0 0; - padding: 0; - padding-top: 3px; - text-align: center; - vertical-align: top; + float: left; + width: 26px; + margin: 0 5px 0 0; + margin: 0 5px 0 0; + padding: 0; + padding-top: 3px; + text-align: center; + vertical-align: top; } div.epg_content div.epg_tools img { - margin: 2px 5px; + margin: 2px 5px; } span.epg_images img.epg_image { - width: 100%; + width: 100%; } /* some adaptions when shown in info-win subwindow */ .info-win div.boxheader { - display: none; + display: none; } .info-win div.epg_content { @@ -1476,35 +1476,35 @@ span.epg_images img.epg_image { */ div.epg_content div.about_left { - text-align: right; - float: left; - width: 175px; + text-align: right; + float: left; + width: 175px; } div.epg_content div.about_right { - padding-left: 200px; + padding-left: 200px; } div.epg_content div.about_line { - padding-left: 30px; + padding-left: 30px; } div.epg_content div.about_head { - font-weight: bold; - margin-left: -9px; - padding-top: 6px; + font-weight: bold; + margin-left: -9px; + padding-top: 6px; } div.epg_content div.about_head div { - padding-bottom: 6px; - margin-left: 0px; + padding-bottom: 6px; + margin-left: 0px; } div.epg_content div.about_head div div { - padding: 2px 0px 2px 10px; - background: #E9EFFF; - border-top: 1px solid #C0C1DA; - border-bottom: 1px solid #C0C1DA; + padding: 2px 0px 2px 10px; + background: #E9EFFF; + border-top: 1px solid #C0C1DA; + border-bottom: 1px solid #C0C1DA; } div.thumb { @@ -1565,31 +1565,31 @@ td.enlarge-image img.thumbpt { width: 100px; } span.epg_images { - width: 150px; + width: 150px; } div.info-win { - width: 410px; + width: 410px; } div.info-win img.artwork { /* info-win - 95 */ - width: 315px + width: 315px } img.artwork { - width: 315px + width: 315px } div.info-win img.actor { /* artwork/4 - 4 */ - width: 73px; + width: 73px; } img.actor { - width: 73px; + width: 73px; } .hint-tip { - max-width: 200px; /* depends on the tip background image width */ + max-width: 200px; /* depends on the tip background image width */ } img.channel_logo { - max-height:32px; max-width:90px; + max-height:32px; max-width:90px; } } diff --git a/live/js/live/browserwin.js b/live/js/live/browserwin.js index 39f6cf8..7de7188 100644 --- a/live/js/live/browserwin.js +++ b/live/js/live/browserwin.js @@ -10,7 +10,7 @@ /* Class: BrowserWin - Create and browswer window pointing at an specific URL. + Create and browswer window pointing at an specific URL. Arguments: @@ -19,83 +19,83 @@ Options: Note: */ var BrowserWin = new Class({ - options: { - size: { width: 720, height: 640 }, - toolbar: false, - location: false, - directories: false, - statusbar: false, - menubar: false, - scrollbar: false, - resizable: true, - wm: false // override default window manager. - }, + options: { + size: { width: 720, height: 640 }, + toolbar: false, + location: false, + directories: false, + statusbar: false, + menubar: false, + scrollbar: false, + resizable: true, + wm: false // override default window manager. + }, - initialize: function(id, url, options){ - this.setOptions(options); - this.id = id; - this.wm = this.options.wm || BrowserWin.$wm; - this.wm.register(this, url); - }, + initialize: function(id, url, options){ + this.setOptions(options); + this.id = id; + this.wm = this.options.wm || BrowserWin.$wm; + this.wm.register(this, url); + }, - create: function(url){ - winOpts = "height=" + this.options.size.height; - winOpts += ",width=" + this.options.size.width; - winOpts += ",toolbar=" + this.options.toolbar; - winOpts += ",location=" + this.options.toolbar; - winOpts += ",directories=" + this.options.directories; - winOpts += ",statusbar=" + this.options.statusbar; - winOpts += ",menubar=" + this.options.menubar; - winOpts += ",scrollbars=" + this.options.scrollbars; - winOpts += ",resizable=" + this.options.resizable; - if ($defined(this.options.top)) { - winOpts += ",top=" + this.options.top; - } - if ($defined(this.options.left)) { - winOpts += ",left=" + this.options.left; - } - this.$winRef = window.open(url, this.id, winOpts); - }, + create: function(url){ + winOpts = "height=" + this.options.size.height; + winOpts += ",width=" + this.options.size.width; + winOpts += ",toolbar=" + this.options.toolbar; + winOpts += ",location=" + this.options.toolbar; + winOpts += ",directories=" + this.options.directories; + winOpts += ",statusbar=" + this.options.statusbar; + winOpts += ",menubar=" + this.options.menubar; + winOpts += ",scrollbars=" + this.options.scrollbars; + winOpts += ",resizable=" + this.options.resizable; + if ($defined(this.options.top)) { + winOpts += ",top=" + this.options.top; + } + if ($defined(this.options.left)) { + winOpts += ",left=" + this.options.left; + } + this.$winRef = window.open(url, this.id, winOpts); + }, - close: function(){ - this.wm.unregister(this); - } - }); + close: function(){ + this.wm.unregister(this); + } + }); BrowserWin.implement(new Events, new Options); BrowserWin.Manager = new Class({ - options: { - onRegister: Class.empty, - onUnregister: Class.empty - }, + options: { + onRegister: Class.empty, + onUnregister: Class.empty + }, - initialize: function(options){ - this.setOptions(options); - this.hashTab = new Hash(); - }, + initialize: function(options){ + this.setOptions(options); + this.hashTab = new Hash(); + }, - register: function(browserWin, url){ - this.unregister(browserWin); + register: function(browserWin, url){ + this.unregister(browserWin); - browserWin.create(url); - this.hashTab.set(browserWin.id, browserWin); - this.fireEvent('onRegister', [browserWin]); - }, + browserWin.create(url); + this.hashTab.set(browserWin.id, browserWin); + this.fireEvent('onRegister', [browserWin]); + }, - unregister: function(browserWin){ - if (this.hashTab.hasKey(browserWin.id)) { - winRef = this.hashTab.get(browserWin.id); - winRef.$winRef.close(); - this.fireEvent('onUnregister', [winRef]); - this.hashTab.remove(browserWin.id); - } - } - }); + unregister: function(browserWin){ + if (this.hashTab.hasKey(browserWin.id)) { + winRef = this.hashTab.get(browserWin.id); + winRef.$winRef.close(); + this.fireEvent('onUnregister', [winRef]); + this.hashTab.remove(browserWin.id); + } + } + }); BrowserWin.Manager.implement(new Events, new Options); BrowserWin.$wm = null; window.addEvent('domready', function(){ - BrowserWin.$wm = new BrowserWin.Manager(); - }); + BrowserWin.$wm = new BrowserWin.Manager(); + }); diff --git a/live/js/live/header.js b/live/js/live/header.js index 85fc7ef..66223f5 100644 --- a/live/js/live/header.js +++ b/live/js/live/header.js @@ -4,22 +4,22 @@ function adjustHeader() { - // exchange body top margin by equally-sized header-padding element - var padding = document.getElementById( "padding" ); - if( padding.style.height == "" ) - { - var bodyStyles = ( window.getComputedStyle )? getComputedStyle( document.body, null ) : document.body.currentStyle; - padding.style.height = bodyStyles.marginTop; - padding.style.backgroundColor = ( window.bgColor )? window.bgColor : "white"; - padding.style.display = ""; - document.body.style.marginTop = "0px"; - } - // expand underlay to header's height - var header = document.getElementById( "header" ); - var underlay = document.getElementById( "underlay" ); - underlay.style.height = header.offsetHeight+ "px"; - underlay.style.display = ""; - header.style.position = "fixed"; - return; + // exchange body top margin by equally-sized header-padding element + var padding = document.getElementById( "padding" ); + if( padding.style.height == "" ) + { + var bodyStyles = ( window.getComputedStyle )? getComputedStyle( document.body, null ) : document.body.currentStyle; + padding.style.height = bodyStyles.marginTop; + padding.style.backgroundColor = ( window.bgColor )? window.bgColor : "white"; + padding.style.display = ""; + document.body.style.marginTop = "0px"; + } + // expand underlay to header's height + var header = document.getElementById( "header" ); + var underlay = document.getElementById( "underlay" ); + underlay.style.height = header.offsetHeight+ "px"; + underlay.style.display = ""; + header.style.position = "fixed"; + return; } diff --git a/live/js/live/hinttips.js b/live/js/live/hinttips.js index 14ebf61..88ad8d7 100644 --- a/live/js/live/hinttips.js +++ b/live/js/live/hinttips.js @@ -8,20 +8,20 @@ */ var HintTips = Tips.extend({ - initialize: function(elements, options){ - this.parent(elements, options); - this.toolTip.empty(); - /* top border of tip */ - var hd = new Element('div', {'class': this.options.className + '-tip-top'}).inject(this.toolTip); - hd = new Element('div', {'class': this.options.className + '-tip-c'}).inject(hd); + initialize: function(elements, options){ + this.parent(elements, options); + this.toolTip.empty(); + /* top border of tip */ + var hd = new Element('div', {'class': this.options.className + '-tip-top'}).inject(this.toolTip); + hd = new Element('div', {'class': this.options.className + '-tip-c'}).inject(hd); - /* body of tip: some helper divs and content */ - this.wrapper = new Element('div', {'class': this.options.className + '-tip-bdy'}).inject(this.toolTip); - this.wrapper = new Element('div', {'class': this.options.className + '-tip-c'}).inject(this.wrapper); - this.wrapper = new Element('div', {'class': this.options.className + '-tip-s'}).inject(this.wrapper); + /* body of tip: some helper divs and content */ + this.wrapper = new Element('div', {'class': this.options.className + '-tip-bdy'}).inject(this.toolTip); + this.wrapper = new Element('div', {'class': this.options.className + '-tip-c'}).inject(this.wrapper); + this.wrapper = new Element('div', {'class': this.options.className + '-tip-s'}).inject(this.wrapper); - /* bottom border of tip */ - var bt = new Element('div', {'class': this.options.className + '-tip-bot'}).inject(this.toolTip); - bt = new Element('div', {'class': this.options.className + '-tip-c'}).inject(bt); - } - }); + /* bottom border of tip */ + var bt = new Element('div', {'class': this.options.className + '-tip-bot'}).inject(this.toolTip); + bt = new Element('div', {'class': this.options.className + '-tip-c'}).inject(bt); + } + }); diff --git a/live/js/live/infowin.js b/live/js/live/infowin.js index 58e8142..889d085 100644 --- a/live/js/live/infowin.js +++ b/live/js/live/infowin.js @@ -11,161 +11,161 @@ /* Class: InfoWin - Create an information window as overlay to current page. + Create an information window as overlay to current page. Arguments: Options: Note: - A window consists of a frame-element. This is the overall - containing element used to control the display and size of the - window. It is accessible through the 'winFrame' property. - - The InfoWin class provides the following properties to fill the - window with content: - - titleBox: the element meant to place the title of the window into. - - buttonBox: here the default window buttons are created. You might - clear this and create your own kind of window controls. - - winBody: this is where your window contents goes. + A window consists of a frame-element. This is the overall + containing element used to control the display and size of the + window. It is accessible through the 'winFrame' property. + + The InfoWin class provides the following properties to fill the + window with content: + - titleBox: the element meant to place the title of the window into. + - buttonBox: here the default window buttons are created. You might + clear this and create your own kind of window controls. + - winBody: this is where your window contents goes. */ var InfoWin = new Class({ - options: { - timeout: 0, - onShow: Class.empty, - onHide: Class.empty, - onDomExtend: Class.empty, - destroyOnHide: false, - className: 'info', - wm: false, // override default window manager. - draggable: true, - resizable: true, - buttonimg: 'transparent.png', - bodyselect: 'div.content', - titleselect: 'div.caption', - classSuffix: '-win', - idSuffix: '-id', - offsets: {'x': -16, 'y': -16} - }, - - initialize: function(id, options){ - this.setOptions(options); - this.wm = this.options.wm || InfoWin.$wm; - this.winFrame = $(id + this.options.classSuffix + this.options.idSuffix); - if (!$defined(this.winFrame)){ - this.buildFrame(id); - this.build(id); - this.wm.register(this); - } - }, - - // internal: build new window element. - // - // build sets up a frame for a new InfoWin. The parent element - // of the window frame has the id '-win-id'. The function - // must return true if the body of the InfoWin has been filled - // with the user data, false otherwise. - build: function(id){ - // header of window: upper shadows, corners title and controls - var top = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-top' - }).inject(this.winFrame); - if (this.options.draggable) this.winFrame.makeDraggable({'handle': top}); - top = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-c' - }).inject(top); - this.titleBox = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-t' - }).inject(top); - - this.buttonBox = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-b' - }).inject(top); - var cls = new Element('div', { - 'class': 'close' - }).inject(this.buttonBox); - cls.addEvent('click', function(event){ - var event = new Event(event); - event.stop(); - return this.hide(); - }.bind(this)); - cls = new Element('img', { - 'src': this.options.buttonimg, - 'alt': 'close', - 'width': '16px', - 'height': '16px' - }).inject(cls); - - // body of window: user content. - var bdy = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-body' - }).inject(this.winFrame); - bdy = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-c' - }).inject(bdy); - this.winBody = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-s' - }).inject(bdy); - - // bottom border of window: lower shadows and corners, optional - // resize handle. - var bot = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-bot' - }).inject(this.winFrame); - bot = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-c' - }).inject(bot); - - if (this.options.resizable) { - this.winFrame.makeResizable({'handle': bot}); - } - - if (!this.fillTitle(id)) { - // todo: add generic title - } - return this.fillBody(id); - }, - - buildFrame: function(id){ - this.winFrame = new Element('div', { - 'id': id + this.options.classSuffix + this.options.idSuffix, - 'class': this.options.className + this.options.classSuffix, - 'styles': { - 'position': 'absolute', - 'top': '0', - 'left': '0' - } - }); - }, - - show: function(event){ - this.position(event); - this.fireEvent('onShow', [this.winFrame]); - this.wm.raise(this); - if (this.options.timeout) - this.timer = this.hide.delay(this.options.timeout, this); - return false; - }, - - hide: function(){ - this.fireEvent('onHide', [this.winFrame]); - if (this.options.destroyOnHide) { - this.wm.unregister(this); - for (var z in this) this[z] = null; - this.destroyed = true; - } - else { - this.wm.bury(this); - } - return false; - }, - - fillBody: function(id){ - var bodyElems = $$('#'+ id + ' ' + this.options.bodyselect); - if ($defined(bodyElems) && bodyElems.length > 0) { - this.winBody.empty(); - this.fireEvent('onDomExtend', [id, bodyElems]); - this.winBody.adopt(bodyElems); + options: { + timeout: 0, + onShow: Class.empty, + onHide: Class.empty, + onDomExtend: Class.empty, + destroyOnHide: false, + className: 'info', + wm: false, // override default window manager. + draggable: true, + resizable: true, + buttonimg: 'transparent.png', + bodyselect: 'div.content', + titleselect: 'div.caption', + classSuffix: '-win', + idSuffix: '-id', + offsets: {'x': -16, 'y': -16} + }, + + initialize: function(id, options){ + this.setOptions(options); + this.wm = this.options.wm || InfoWin.$wm; + this.winFrame = $(id + this.options.classSuffix + this.options.idSuffix); + if (!$defined(this.winFrame)){ + this.buildFrame(id); + this.build(id); + this.wm.register(this); + } + }, + + // internal: build new window element. + // + // build sets up a frame for a new InfoWin. The parent element + // of the window frame has the id '-win-id'. The function + // must return true if the body of the InfoWin has been filled + // with the user data, false otherwise. + build: function(id){ + // header of window: upper shadows, corners title and controls + var top = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-top' + }).inject(this.winFrame); + if (this.options.draggable) this.winFrame.makeDraggable({'handle': top}); + top = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-c' + }).inject(top); + this.titleBox = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-t' + }).inject(top); + + this.buttonBox = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-b' + }).inject(top); + var cls = new Element('div', { + 'class': 'close' + }).inject(this.buttonBox); + cls.addEvent('click', function(event){ + var event = new Event(event); + event.stop(); + return this.hide(); + }.bind(this)); + cls = new Element('img', { + 'src': this.options.buttonimg, + 'alt': 'close', + 'width': '16px', + 'height': '16px' + }).inject(cls); + + // body of window: user content. + var bdy = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-body' + }).inject(this.winFrame); + bdy = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-c' + }).inject(bdy); + this.winBody = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-s' + }).inject(bdy); + + // bottom border of window: lower shadows and corners, optional + // resize handle. + var bot = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-bot' + }).inject(this.winFrame); + bot = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-c' + }).inject(bot); + + if (this.options.resizable) { + this.winFrame.makeResizable({'handle': bot}); + } + + if (!this.fillTitle(id)) { + // todo: add generic title + } + return this.fillBody(id); + }, + + buildFrame: function(id){ + this.winFrame = new Element('div', { + 'id': id + this.options.classSuffix + this.options.idSuffix, + 'class': this.options.className + this.options.classSuffix, + 'styles': { + 'position': 'absolute', + 'top': '0', + 'left': '0' + } + }); + }, + + show: function(event){ + this.position(event); + this.fireEvent('onShow', [this.winFrame]); + this.wm.raise(this); + if (this.options.timeout) + this.timer = this.hide.delay(this.options.timeout, this); + return false; + }, + + hide: function(){ + this.fireEvent('onHide', [this.winFrame]); + if (this.options.destroyOnHide) { + this.wm.unregister(this); + for (var z in this) this[z] = null; + this.destroyed = true; + } + else { + this.wm.bury(this); + } + return false; + }, + + fillBody: function(id){ + var bodyElems = $$('#'+ id + ' ' + this.options.bodyselect); + if ($defined(bodyElems) && bodyElems.length > 0) { + this.winBody.empty(); + this.fireEvent('onDomExtend', [id, bodyElems]); + this.winBody.adopt(bodyElems); var history_num_back = 0; var history_back = this.winBody.getElementById('history_' + id); if (history_back) { @@ -200,20 +200,20 @@ var InfoWin = new Class({ } return true; } - return false; - }, - - fillTitle: function(id){ - var titleElems = $$('#' + id + ' ' + this.options.titleselect); - if ($defined(titleElems) && titleElems.length > 0) { - this.titleBox.empty().adopt(titleElems); - return true; - } - return false; - }, - - position: function(event){ - var prop = {'x': 'left', 'y': 'top'}; + return false; + }, + + fillTitle: function(id){ + var titleElems = $$('#' + id + ' ' + this.options.titleselect); + if ($defined(titleElems) && titleElems.length > 0) { + this.titleBox.empty().adopt(titleElems); + return true; + } + return false; + }, + + position: function(event){ + var prop = {'x': 'left', 'y': 'top'}; var pos = event.page['y'] + this.options.offsets['y']; this.winFrame.setStyle(prop['y'], pos); pos = event.page['x'] + this.options.offsets['x']; @@ -221,81 +221,81 @@ var InfoWin = new Class({ if (pos < 1) pos = 1; this.winFrame.setStyle(prop['x'], pos); } - }); + }); InfoWin.implement(new Events, new Options); /* Class: InfoWin.Manager - Provide an container and events for the created info win - instances. Closed info-wins are preserved in a hidden DOM element - and used again if a window with a closed id is opened again. + Provide an container and events for the created info win + instances. Closed info-wins are preserved in a hidden DOM element + and used again if a window with a closed id is opened again. */ InfoWin.Manager = new Class({ - options: { - closedContainer: 'infowin-closed', - openedContainer: 'infowin-opened', - onRegister: Class.empty, - onUnregister: Class.empty, - onRaise: Class.empty, - onBury: Class.empty - }, - - initialize: function(options){ - this.setOptions(options); - // initialize properties this.closedWins and this.openedWins: - ['closed', 'opened'].each(function(kind){ - var wins = kind + 'Wins'; - var opts = this.options[kind + 'Container']; - this[wins] = $(opts); - if (!$defined(this[wins])){ - this[wins] = new Element('div', { - 'id': opts, - 'styles' : { - 'display' : (kind == 'closed') ? 'none' : 'block' - } - }); - this[wins].inject(document.body); - } - }, this); - }, - - register: function(infoWin){ - this.fireEvent('onRegister', [infoWin]); - infoWin.winFrame.addEvent('click', function(){ - this.raise(infoWin); - }.bind(this)); - infoWin.winFrame.inject(this.closedWins); - }, - - unregister: function(infoWin){ - this.fireEvent('onUnregister', [infoWin]); - infoWin.winFrame.remove(); - }, - - raise: function(infoWin){ - this.fireEvent('onRaise', [infoWin]); - infoWin.winFrame.inject(this.openedWins); - }, - - bury: function(infoWin){ - this.fireEvent('onBury', [infoWin]); - infoWin.winFrame.inject(this.closedWins); - } - }); + options: { + closedContainer: 'infowin-closed', + openedContainer: 'infowin-opened', + onRegister: Class.empty, + onUnregister: Class.empty, + onRaise: Class.empty, + onBury: Class.empty + }, + + initialize: function(options){ + this.setOptions(options); + // initialize properties this.closedWins and this.openedWins: + ['closed', 'opened'].each(function(kind){ + var wins = kind + 'Wins'; + var opts = this.options[kind + 'Container']; + this[wins] = $(opts); + if (!$defined(this[wins])){ + this[wins] = new Element('div', { + 'id': opts, + 'styles' : { + 'display' : (kind == 'closed') ? 'none' : 'block' + } + }); + this[wins].inject(document.body); + } + }, this); + }, + + register: function(infoWin){ + this.fireEvent('onRegister', [infoWin]); + infoWin.winFrame.addEvent('click', function(){ + this.raise(infoWin); + }.bind(this)); + infoWin.winFrame.inject(this.closedWins); + }, + + unregister: function(infoWin){ + this.fireEvent('onUnregister', [infoWin]); + infoWin.winFrame.remove(); + }, + + raise: function(infoWin){ + this.fireEvent('onRaise', [infoWin]); + infoWin.winFrame.inject(this.openedWins); + }, + + bury: function(infoWin){ + this.fireEvent('onBury', [infoWin]); + infoWin.winFrame.inject(this.closedWins); + } + }); InfoWin.Manager.implement(new Events, new Options); InfoWin.$wm = null; window.addEvent('domready', function(){ - InfoWin.$wm = new InfoWin.Manager(); - }); + InfoWin.$wm = new InfoWin.Manager(); + }); /* Class: InfoWin.Ajax - Use an instance of mootools Ajax class to asynchronously request - the content of an info win. + Use an instance of mootools Ajax class to asynchronously request + the content of an info win. */ function is_digit(c){ if (c >= '0' && c <= '9') { @@ -316,113 +316,113 @@ function decrease_history_num_back(url) { } InfoWin.Ajax = InfoWin.extend({ - options: { - loadingMsg: 'loading', - errorMsg: 'an error occurred!', - onError: Class.empty - }, + options: { + loadingMsg: 'loading', + errorMsg: 'an error occurred!', + onError: Class.empty + }, - initialize: function(id, url_in, options){ + initialize: function(id, url_in, options){ var url = decrease_history_num_back(url_in); - this.parent(id, options); - if ($defined(this.ajaxResponse)) { - this.addEvent('onError', function(){ - this.hide.delay(1000, this); - }.bind(this)); - var ajax = new Ajax(url, { - update: this.ajaxResponse, - onComplete: function(text, xmldoc){ - this.fillTitle(id); - this.fillBody(id); - this.ajaxResponse.remove(); - }.bind(this), - onFailure: function(transport){ - this.titleBox.setHTML(this.options.errorMsg); - this.fireEvent('onError', [id, url]); - }.bind(this) - }).request('async=1'); - } - }, - - // this function gets called when no previous instance for 'id' - // created a DOM subtree for an infowin. - build: function(id){ - if (!this.parent(id)) { - this.titleBox.setHTML(this.options.loadingMsg); - this.ajaxResponse = new Element('div', { - 'styles' : { - 'display': 'none' - } - }).inject(this.winFrame); - } - } - }); + this.parent(id, options); + if ($defined(this.ajaxResponse)) { + this.addEvent('onError', function(){ + this.hide.delay(1000, this); + }.bind(this)); + var ajax = new Ajax(url, { + update: this.ajaxResponse, + onComplete: function(text, xmldoc){ + this.fillTitle(id); + this.fillBody(id); + this.ajaxResponse.remove(); + }.bind(this), + onFailure: function(transport){ + this.titleBox.setHTML(this.options.errorMsg); + this.fireEvent('onError', [id, url]); + }.bind(this) + }).request('async=1'); + } + }, + + // this function gets called when no previous instance for 'id' + // created a DOM subtree for an infowin. + build: function(id){ + if (!this.parent(id)) { + this.titleBox.setHTML(this.options.loadingMsg); + this.ajaxResponse = new Element('div', { + 'styles' : { + 'display': 'none' + } + }).inject(this.winFrame); + } + } + }); /* Class: Infowin.Notifier - Creates a notification popup that disappears automatically. - Useful for a confirmation message after a AJAX action request. + Creates a notification popup that disappears automatically. + Useful for a confirmation message after a AJAX action request. */ InfoWin.Notifier = InfoWin.extend({ - options: { - timeout: 2500, - destroyOnHide: true, - className: 'ok', - classSuffix: '-info', - message: '', - offsets: {'x': 16, 'y': 16} - }, - - initialize: function(id, options){ - this.parent(id, options); - }, - - build: function(id){ - /* top border of hint */ - var top = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-top' - }).inject(this.winFrame); - top = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-c' - }).inject(top); - - /* body of tip: some helper divs and content */ - var bdy = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-body' - }).inject(this.winFrame); - bdy = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-c' - }).inject(bdy); - this.winBody = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-s' - }).inject(bdy); - - /* bottom border of tip */ - var bot = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-bot' - }).inject(this.winFrame); - bot = new Element('div', { - 'class': this.options.className + this.options.classSuffix + '-c' - }).inject(bot); - - return this.fillBody(id); - }, - - fillBody: function(id){ - this.winFrame.setStyle('position', 'fixed'); - this.winBody.empty().setHTML(this.options.message); - return true; - }, - - position: function(event){ - var prop = {'x': 'left', 'y': 'top'}; - for (var z in prop) { - var pos = this.options.offsets[z]; - this.winFrame.setStyle(prop[z], pos); - } - } - }); + options: { + timeout: 2500, + destroyOnHide: true, + className: 'ok', + classSuffix: '-info', + message: '', + offsets: {'x': 16, 'y': 16} + }, + + initialize: function(id, options){ + this.parent(id, options); + }, + + build: function(id){ + /* top border of hint */ + var top = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-top' + }).inject(this.winFrame); + top = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-c' + }).inject(top); + + /* body of tip: some helper divs and content */ + var bdy = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-body' + }).inject(this.winFrame); + bdy = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-c' + }).inject(bdy); + this.winBody = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-s' + }).inject(bdy); + + /* bottom border of tip */ + var bot = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-bot' + }).inject(this.winFrame); + bot = new Element('div', { + 'class': this.options.className + this.options.classSuffix + '-c' + }).inject(bot); + + return this.fillBody(id); + }, + + fillBody: function(id){ + this.winFrame.setStyle('position', 'fixed'); + this.winBody.empty().setHTML(this.options.message); + return true; + }, + + position: function(event){ + var prop = {'x': 'left', 'y': 'top'}; + for (var z in prop) { + var pos = this.options.offsets[z]; + this.winFrame.setStyle(prop[z], pos); + } + } + }); diff --git a/live/js/live/liveajax.js b/live/js/live/liveajax.js index fc8f8f9..488648b 100644 --- a/live/js/live/liveajax.js +++ b/live/js/live/liveajax.js @@ -7,7 +7,7 @@ function LiveSimpleAjaxRequest(url, param, value) { - var req = new Ajax(url, { - method : 'post' - }).request(param + '=' + value + '&async=1'); + var req = new Ajax(url, { + method : 'post' + }).request(param + '=' + value + '&async=1'); }; diff --git a/live/js/live/pageenhance.js b/live/js/live/pageenhance.js index 6e65132..9c72a67 100644 --- a/live/js/live/pageenhance.js +++ b/live/js/live/pageenhance.js @@ -9,152 +9,152 @@ */ var PageEnhance = new Class({ - options: { - epgLinkSelector: 'a[href^="epginfo.html?epgid"]', - actionLinkSelector: 'a[href^="vdr_request/"]', - editTimerSelector: 'a[href^="edit_timer.html?timerid"]', - hintTipSelector: '*[title]', - hintClassName: 'hint', - infoWinOptions: { - bodyselect: 'div.epg_content', - loadingMsg: 'loading', - errorMsg: 'an error occurred!' - }, - notifyIdPrefix: 'notify', - notifyStrings: { - successMsg: ' Success!', - errorMsg: ' failed!' - } - }, + options: { + epgLinkSelector: 'a[href^="epginfo.html?epgid"]', + actionLinkSelector: 'a[href^="vdr_request/"]', + editTimerSelector: 'a[href^="edit_timer.html?timerid"]', + hintTipSelector: '*[title]', + hintClassName: 'hint', + infoWinOptions: { + bodyselect: 'div.epg_content', + loadingMsg: 'loading', + errorMsg: 'an error occurred!' + }, + notifyIdPrefix: 'notify', + notifyStrings: { + successMsg: ' Success!', + errorMsg: ' failed!' + } + }, - initialize: function(options){ - this.setOptions(options); - this.$notifyCount = 0; - window.addEvent('domready', this.domReadySetup.bind(this)); - window.addEvent('mousedown', this.mouseDownSetup.bind(this)); - }, + initialize: function(options){ + this.setOptions(options); + this.$notifyCount = 0; + window.addEvent('domready', this.domReadySetup.bind(this)); + window.addEvent('mousedown', this.mouseDownSetup.bind(this)); + }, - // actions applied on domready to the page. - domReadySetup: function(){ - $$(this.options.epgLinkSelector).each(this.epgPopup.bind(this)); - this.addHintTips($$(this.options.hintTipSelector)); - $$(this.options.actionLinkSelector).each(this.vdrRequest.bind(this)); - // the following line activates timer editing in popup window. - // but it does not yet work like expected. So we leave it deactivated currently. - // $$(this.options.editTimerSelector).each(this.editTimer.bind(this)); - }, + // actions applied on domready to the page. + domReadySetup: function(){ + $$(this.options.epgLinkSelector).each(this.epgPopup.bind(this)); + this.addHintTips($$(this.options.hintTipSelector)); + $$(this.options.actionLinkSelector).each(this.vdrRequest.bind(this)); + // the following line activates timer editing in popup window. + // but it does not yet work like expected. So we leave it deactivated currently. + // $$(this.options.editTimerSelector).each(this.editTimer.bind(this)); + }, - // actions applied on mouse down. - mouseDownSetup: function(){ - $$('.' + this.options.hintClassName + '-tip').setStyle('visibility', 'hidden'); - }, + // actions applied on mouse down. + mouseDownSetup: function(){ + $$('.' + this.options.hintClassName + '-tip').setStyle('visibility', 'hidden'); + }, - // registered as 'onDomExtend' event for InfoWin. Takes care to - // enhance the new DOM elements, too. - domExtend: function(id, elems){ - var sel = '#' + id + ' ' + this.options.hintTipSelector; - elems = $$(sel); - this.addHintTips(elems); - $$('#' + id + ' ' + this.options.actionLinkSelector).each(this.vdrRequest.bind(this)); - }, + // registered as 'onDomExtend' event for InfoWin. Takes care to + // enhance the new DOM elements, too. + domExtend: function(id, elems){ + var sel = '#' + id + ' ' + this.options.hintTipSelector; + elems = $$(sel); + this.addHintTips(elems); + $$('#' + id + ' ' + this.options.actionLinkSelector).each(this.vdrRequest.bind(this)); + }, - // EPG popup function. Apply to all elements that should - // pop up an EPG InfowWin window. - epgPopup: function(el){ - var href = el.href; - var epgid = $pick(href, ""); - if (epgid != "") { - var extractId = /epgid=(\w+)/; - var found = extractId.exec(epgid); - if ($defined(found) && found.length > 1) { - epgid = found[1]; - el.addEvent('click', function(event){ - if (window.matchMedia("(max-width: 600px)").matches) { + // EPG popup function. Apply to all elements that should + // pop up an EPG InfowWin window. + epgPopup: function(el){ + var href = el.href; + var epgid = $pick(href, ""); + if (epgid != "") { + var extractId = /epgid=(\w+)/; + var found = extractId.exec(epgid); + if ($defined(found) && found.length > 1) { + epgid = found[1]; + el.addEvent('click', function(event){ + if (window.matchMedia("(max-width: 600px)").matches) { location.replace(href); return true; - } - var event = new Event(event); - new InfoWin.Ajax(epgid, href, $merge(this.options.infoWinOptions, { - onDomExtend: this.domExtend.bind(this) - })).show(event); - event.stop(); - return false; - }.bind(this)); - } - } - }, + } + var event = new Event(event); + new InfoWin.Ajax(epgid, href, $merge(this.options.infoWinOptions, { + onDomExtend: this.domExtend.bind(this) + })).show(event); + event.stop(); + return false; + }.bind(this)); + } + } + }, - // Edit Timer Popup function. Apply to all elements that should - // pop up a timer edit windows based on InfoWin window. - editTimer: function(el){ - var href = el.href; - var timerid = $pick(href, ""); - if (timerid != "") { - var extractId = /timerid=(.+)/; - var found = extractId.exec(timerid); - if ($defined(found) && found.length > 1) { - timerid = found[1]; - el.addEvent('click', function(event){ - var event = new Event(event); - new InfoWin.Ajax(timerid, href, $merge(this.options.infoWinOptions, { - bodyselect: '', - modal: true, - onDomExtend: this.domExtend.bind(this) - })).show(event); - event.stop(); - return false; - }.bind(this)); - } - } - }, + // Edit Timer Popup function. Apply to all elements that should + // pop up a timer edit windows based on InfoWin window. + editTimer: function(el){ + var href = el.href; + var timerid = $pick(href, ""); + if (timerid != "") { + var extractId = /timerid=(.+)/; + var found = extractId.exec(timerid); + if ($defined(found) && found.length > 1) { + timerid = found[1]; + el.addEvent('click', function(event){ + var event = new Event(event); + new InfoWin.Ajax(timerid, href, $merge(this.options.infoWinOptions, { + bodyselect: '', + modal: true, + onDomExtend: this.domExtend.bind(this) + })).show(event); + event.stop(); + return false; + }.bind(this)); + } + } + }, - // function that requests an action from the server VDR. - vdrRequest: function(el){ - el.addEvent('click', function(event, element){ - var href = $pick(element.href, ""); - if (href != "") { - this.$notifyCount++; - var req = new Ajax(href, { - method: 'post', - onComplete: function(text, xmldoc) { - try { - var success = xmldoc.getElementsByTagName('response').item(0).firstChild.nodeValue; - new InfoWin.Notifier(this.options.notifyIdPrefix + this.$notifyCount, { - className: success == '1' ? 'ok' : 'err', - message: success == '1' ? this.options.notifyStrings.successMsg : this.options.notifyStrings.errorMsg - }).show(event); - } catch(e) { - } - }.bind(this) - }); - req.request('async=1'); - event.stop(); - return false; - } - return true; - }.bindWithEvent(this, el)); - }, + // function that requests an action from the server VDR. + vdrRequest: function(el){ + el.addEvent('click', function(event, element){ + var href = $pick(element.href, ""); + if (href != "") { + this.$notifyCount++; + var req = new Ajax(href, { + method: 'post', + onComplete: function(text, xmldoc) { + try { + var success = xmldoc.getElementsByTagName('response').item(0).firstChild.nodeValue; + new InfoWin.Notifier(this.options.notifyIdPrefix + this.$notifyCount, { + className: success == '1' ? 'ok' : 'err', + message: success == '1' ? this.options.notifyStrings.successMsg : this.options.notifyStrings.errorMsg + }).show(event); + } catch(e) { + } + }.bind(this) + }); + req.request('async=1'); + event.stop(); + return false; + } + return true; + }.bindWithEvent(this, el)); + }, - // change normal 'title'-Attributes into enhanced hinttips - // used by domExtend and domReadySetup functions. - addHintTips: function(elems) { - if (window.matchMedia("(hover: none)").matches) { - elems_use = elems.filter( - function(item, index){ return !item.hasClass('apopup'); } - ); - } else { - elems_use = elems; - } - if (!$defined(this.tips)) { - this.tips = new HintTips(elems_use, { - maxTitleChars: 100, - className: this.options.hintClassName - }); - } - else { - $$(elems_use).each(this.tips.build, this.tips); - } - } - }); + // change normal 'title'-Attributes into enhanced hinttips + // used by domExtend and domReadySetup functions. + addHintTips: function(elems) { + if (window.matchMedia("(hover: none)").matches) { + elems_use = elems.filter( + function(item, index){ return !item.hasClass('apopup'); } + ); + } else { + elems_use = elems; + } + if (!$defined(this.tips)) { + this.tips = new HintTips(elems_use, { + maxTitleChars: 100, + className: this.options.hintClassName + }); + } + else { + $$(elems_use).each(this.tips.build, this.tips); + } + } + }); PageEnhance.implement(new Events, new Options); diff --git a/live/js/live/treeview.js b/live/js/live/treeview.js index f24d2f9..1228f55 100644 --- a/live/js/live/treeview.js +++ b/live/js/live/treeview.js @@ -10,23 +10,23 @@ function findSibling(node, name) { - while ((node.nextSibling.nodeType != Node.ELEMENT_NODE) - || (node.nextSibling.nodeName != name)) { - node = node.nextSibling; - } - if (node.nextSibling.nodeName == name) - return node.nextSibling; + while ((node.nextSibling.nodeType != Node.ELEMENT_NODE) + || (node.nextSibling.nodeName != name)) { + node = node.nextSibling; + } + if (node.nextSibling.nodeName == name) + return node.nextSibling; - return null; + return null; } function findChildNode(node, className) { - for (idx = 0; idx < node.childNodes.length; idx++) { - n = node.childNodes.item(idx); - if (n.classList.contains(className)) return n; - } - return null; + for (idx = 0; idx < node.childNodes.length; idx++) { + n = node.childNodes.item(idx); + if (n.classList.contains(className)) return n; + } + return null; } function setImages(node, expand, folder) @@ -191,36 +191,36 @@ var cookieNameRec = "VDR-Live-Recordings-Tree-Open-Nodes"; document.addEventListener("DOMContentLoaded", function() { - openNodesOnPageLoad(); + openNodesOnPageLoad(); }); //The following cookie functions are taken from http://www.quirksmode.org/js/cookies.html function createCookie(name,value,days) { - if (value.length > 1000) return; // too large cookies result in too large http headers - if (days) { - var date = new Date(); - date.setTime(date.getTime()+(days*24*60*60*1000)); - var expires = "; expires="+date.toGMTString(); - } - else var expires = ""; - document.cookie = name+"="+value+expires+";SameSite=Lax; path=/"; + if (value.length > 1000) return; // too large cookies result in too large http headers + if (days) { + var date = new Date(); + date.setTime(date.getTime()+(days*24*60*60*1000)); + var expires = "; expires="+date.toGMTString(); + } + else var expires = ""; + document.cookie = name+"="+value+expires+";SameSite=Lax; path=/"; } function readCookie(name) { - var nameEQ = name + "="; - var ca = document.cookie.split(';'); - for(var i=0;i < ca.length;i++) { - var c = ca[i]; - while (c.charAt(0)==' ') c = c.substring(1,c.length); - if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); - } - return null; + var nameEQ = name + "="; + var ca = document.cookie.split(';'); + for(var i=0;i < ca.length;i++) { + var c = ca[i]; + while (c.charAt(0)==' ') c = c.substring(1,c.length); + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); + } + return null; } function eraseCookie(name) { - createCookie(name,"",-1); + createCookie(name,"",-1); } diff --git a/live/js/live/vdr_status.js b/live/js/live/vdr_status.js index b0de0c1..fe1b61e 100644 --- a/live/js/live/vdr_status.js +++ b/live/js/live/vdr_status.js @@ -7,217 +7,217 @@ var LiveVdrInfo = Ajax.extend({ - options: { - autoCancel: true - }, - - initialize: function(url, boxId) - { - this.parent(url, null); - this.addEvent('onComplete', this.showInfo); - this.addEvent('onFailure', this.reportError); - - this.boxId = boxId; - this.reload = true; - this.timer = null; - }, - - request: function(update) - { - this.parent({update: update ? "1" : "0"}); - }, - - showInfo: function(text, xmldoc) - { - try { - this.selectInfoElems(xmldoc); - - this.setEpgInfo(xmldoc); - - this.setInfoMessage(xmldoc); - - this.setUpdate(xmldoc); - } - catch (e) { - this.reportError(null); - } - }, - - reportError: function(transport) - { - this.setTextContent('caption', 'ERROR'); - var message; - if (transport != null) { - message = $("__infobox_request_err").firstChild.nodeValue; - } - else { - message = $("__infobox_update_err").firstChild.nodeValue; - } - this.setTextContent('name', message); - }, - - // private function to switch visibility of controls. - selectInfoElems: function(xmldoc) - { - var infoType = xmldoc.getElementsByTagName('type').item(0); - - var channel = $(this.boxId + '_channel_buttons'); - var playback = $(this.boxId + '_recording_buttons'); - - if (infoType.firstChild.nodeValue != "channel") { - channel.style.display = 'none'; - playback.style.display = 'block'; - this.setTextContent('pause', infoType.firstChild.nodeValue); - this.setTextContent('play', infoType.firstChild.nodeValue); - this.setTextContent('rwd', infoType.firstChild.nodeValue); - this.setTextContent('ffw', infoType.firstChild.nodeValue); - this.setTextContent('stop', infoType.firstChild.nodeValue); - } - else { - playback.style.display = 'none'; - channel.style.display = 'block'; - } - }, - - // private function to activate the info message display if the - // corresponding element is found in the current page. - setInfoMessage: function(xmldoc) - { - var info = xmldoc.getElementsByTagName('info').item(0); - if (! $defined(info)) - return; - - var messagebar = $('messagebar'); - if (! $defined(messagebar)) - return; - - var message = xmldoc.getElementsByTagName('message').item(0); - var url = xmldoc.getElementsByTagName('url').item(0); - - if (message.firstChild.nodeValue != "") { - $('mbmessage').setText(message.firstChild.nodeValue); - if ($defined(url.firstChild)) { - $('mbdelimiter').removeClass('notpresent'); - $('mbreact').setProperty('href', url.firstChild.nodeValue); - } - else { - $('mbdelimiter').addClass('notpresent'); - $('mbreact').addClass('notpresent'); - } - messagebar.removeClass('notpresent'); - } - }, - - // private function to display information from EPG info. - setEpgInfo: function(xmldoc) - { - var epgInfo = xmldoc.getElementsByTagName('epginfo').item(0); - - for (var i = 0; i < epgInfo.childNodes.length; i++) { - var node = epgInfo.childNodes.item(i); - if (node.nodeType == 1) { - var textContent = ""; - if (node.firstChild != null) - textContent = node.firstChild.nodeValue; - this.setTextContent(node.nodeName, textContent); - } - } - }, - - // private function to update text contents. - setTextContent: function(nodeName, textContent) - { - var docNode = $(this.boxId + '_' + nodeName); - if (docNode != null) { - switch (nodeName) { - case "caption": - case "timenow": - case "name": - case "duration": - { - if (docNode.innerHTML != textContent) - docNode.innerHTML = textContent; - break; - } - case "elapsed": - { - var width = textContent + "%"; - if (docNode.style.width != width) - docNode.style.width = width; - break; - } - case "nextchan": - case "prevchan": - { - if (textContent != "") { - // docNode.href = "javascript:LiveSimpleAjaxRequest('switch_channel.xml', 'param', '" + textContent + "');"; - docNode.href = "vdr_request/switch_channel?param=" + textContent; - docNode.style.visibility = "visible"; - } - else { - docNode.style.visibility = "hidden"; - } - break; - } - case "pause": - case "play": - case "rwd": - case "ffw": - case "stop": - { - if (textContent != "") { - // docNode.href = "javascript:LiveSimpleAjaxRequest('" + nodeName + "_recording.xml', 'param', '" + textContent + "');"; - docNode.href = "vdr_request/" + nodeName + "_recording?param=" + textContent; - docNode.style.visibility = "visible"; - } - else { - docNode.style.visibility = "hidden"; - } - break; - } - default: - break; - } - } - }, - - // private function to determine update status and to trigger - // the next update. - setUpdate: function(xmldoc) - { - /* check if we still need to update the status */ - var upd = xmldoc.getElementsByTagName('update').item(0); - var rel = (upd.firstChild.nodeValue == "1"); - - if (rel != this.reload) { - this.reload = rel; - var img = $('statusReloadBtn'); - if (img != null) { - // change image according to state. - img.src = this.reload ? 'img/stop_update.png' : 'img/reload.png'; - } - } - if (this.reload) - this.timer = this.request.delay(1000, this, true); - }, - - toggleUpdate: function() - { - if (this.reload) { - if (this.timer != null) { - this.timer = $clear(this.timer); - } - } - this.request(!this.reload); - }, - - pageFinished: function() - { - if (this.reload) { - if (this.timer != null) { - this.timer = $clear(this.timer); - } - } - this.cancel(); - } + options: { + autoCancel: true + }, + + initialize: function(url, boxId) + { + this.parent(url, null); + this.addEvent('onComplete', this.showInfo); + this.addEvent('onFailure', this.reportError); + + this.boxId = boxId; + this.reload = true; + this.timer = null; + }, + + request: function(update) + { + this.parent({update: update ? "1" : "0"}); + }, + + showInfo: function(text, xmldoc) + { + try { + this.selectInfoElems(xmldoc); + + this.setEpgInfo(xmldoc); + + this.setInfoMessage(xmldoc); + + this.setUpdate(xmldoc); + } + catch (e) { + this.reportError(null); + } + }, + + reportError: function(transport) + { + this.setTextContent('caption', 'ERROR'); + var message; + if (transport != null) { + message = $("__infobox_request_err").firstChild.nodeValue; + } + else { + message = $("__infobox_update_err").firstChild.nodeValue; + } + this.setTextContent('name', message); + }, + + // private function to switch visibility of controls. + selectInfoElems: function(xmldoc) + { + var infoType = xmldoc.getElementsByTagName('type').item(0); + + var channel = $(this.boxId + '_channel_buttons'); + var playback = $(this.boxId + '_recording_buttons'); + + if (infoType.firstChild.nodeValue != "channel") { + channel.style.display = 'none'; + playback.style.display = 'block'; + this.setTextContent('pause', infoType.firstChild.nodeValue); + this.setTextContent('play', infoType.firstChild.nodeValue); + this.setTextContent('rwd', infoType.firstChild.nodeValue); + this.setTextContent('ffw', infoType.firstChild.nodeValue); + this.setTextContent('stop', infoType.firstChild.nodeValue); + } + else { + playback.style.display = 'none'; + channel.style.display = 'block'; + } + }, + + // private function to activate the info message display if the + // corresponding element is found in the current page. + setInfoMessage: function(xmldoc) + { + var info = xmldoc.getElementsByTagName('info').item(0); + if (! $defined(info)) + return; + + var messagebar = $('messagebar'); + if (! $defined(messagebar)) + return; + + var message = xmldoc.getElementsByTagName('message').item(0); + var url = xmldoc.getElementsByTagName('url').item(0); + + if (message.firstChild.nodeValue != "") { + $('mbmessage').setText(message.firstChild.nodeValue); + if ($defined(url.firstChild)) { + $('mbdelimiter').removeClass('notpresent'); + $('mbreact').setProperty('href', url.firstChild.nodeValue); + } + else { + $('mbdelimiter').addClass('notpresent'); + $('mbreact').addClass('notpresent'); + } + messagebar.removeClass('notpresent'); + } + }, + + // private function to display information from EPG info. + setEpgInfo: function(xmldoc) + { + var epgInfo = xmldoc.getElementsByTagName('epginfo').item(0); + + for (var i = 0; i < epgInfo.childNodes.length; i++) { + var node = epgInfo.childNodes.item(i); + if (node.nodeType == 1) { + var textContent = ""; + if (node.firstChild != null) + textContent = node.firstChild.nodeValue; + this.setTextContent(node.nodeName, textContent); + } + } + }, + + // private function to update text contents. + setTextContent: function(nodeName, textContent) + { + var docNode = $(this.boxId + '_' + nodeName); + if (docNode != null) { + switch (nodeName) { + case "caption": + case "timenow": + case "name": + case "duration": + { + if (docNode.innerHTML != textContent) + docNode.innerHTML = textContent; + break; + } + case "elapsed": + { + var width = textContent + "%"; + if (docNode.style.width != width) + docNode.style.width = width; + break; + } + case "nextchan": + case "prevchan": + { + if (textContent != "") { + // docNode.href = "javascript:LiveSimpleAjaxRequest('switch_channel.xml', 'param', '" + textContent + "');"; + docNode.href = "vdr_request/switch_channel?param=" + textContent; + docNode.style.visibility = "visible"; + } + else { + docNode.style.visibility = "hidden"; + } + break; + } + case "pause": + case "play": + case "rwd": + case "ffw": + case "stop": + { + if (textContent != "") { + // docNode.href = "javascript:LiveSimpleAjaxRequest('" + nodeName + "_recording.xml', 'param', '" + textContent + "');"; + docNode.href = "vdr_request/" + nodeName + "_recording?param=" + textContent; + docNode.style.visibility = "visible"; + } + else { + docNode.style.visibility = "hidden"; + } + break; + } + default: + break; + } + } + }, + + // private function to determine update status and to trigger + // the next update. + setUpdate: function(xmldoc) + { + /* check if we still need to update the status */ + var upd = xmldoc.getElementsByTagName('update').item(0); + var rel = (upd.firstChild.nodeValue == "1"); + + if (rel != this.reload) { + this.reload = rel; + var img = $('statusReloadBtn'); + if (img != null) { + // change image according to state. + img.src = this.reload ? 'img/stop_update.png' : 'img/reload.png'; + } + } + if (this.reload) + this.timer = this.request.delay(1000, this, true); + }, + + toggleUpdate: function() + { + if (this.reload) { + if (this.timer != null) { + this.timer = $clear(this.timer); + } + } + this.request(!this.reload); + }, + + pageFinished: function() + { + if (this.reload) { + if (this.timer != null) { + this.timer = $clear(this.timer); + } + } + this.cancel(); + } }); diff --git a/live/themes/orange-blue/css/theme.css b/live/themes/orange-blue/css/theme.css index afcb5e3..9a1aae7 100644 --- a/live/themes/orange-blue/css/theme.css +++ b/live/themes/orange-blue/css/theme.css @@ -4,26 +4,26 @@ */ html, body { - background-color: #081966; - color: white; + background-color: #081966; + color: white; } table { - background-color: #263480; + background-color: #263480; } input { - border: 1px solid #081966; + border: 1px solid #081966; background: #DDDDFF; } select { - border: 1px solid #081966; + border: 1px solid #081966; background: #DDDDFF; } a { - color: #F5EE74; + color: #F5EE74; } @@ -33,31 +33,31 @@ a { */ .hint-tip { - color: black; + color: black; } .hint-tip .hint-tip-top { - background: transparent url(/img/rounded-box-orange-tl.png) no-repeat 0px 0px; + background: transparent url(/img/rounded-box-orange-tl.png) no-repeat 0px 0px; } .hint-tip .hint-tip-top .hint-tip-c { - background: transparent url(/img/rounded-box-orange-tr.png) no-repeat right 0px; + background: transparent url(/img/rounded-box-orange-tr.png) no-repeat right 0px; } .hint-tip .hint-tip-bdy { - background: transparent url(/img/rounded-box-orange-ml.png) repeat-y 0px 0px; + background: transparent url(/img/rounded-box-orange-ml.png) repeat-y 0px 0px; } .hint-tip .hint-tip-bdy .hint-tip-c { - background: transparent url(/img/rounded-box-orange-mr.png) repeat-y right 0px; + background: transparent url(/img/rounded-box-orange-mr.png) repeat-y right 0px; } .hint-tip .hint-tip-bot { - background: transparent url(/img/rounded-box-orange-bl.png) no-repeat 0px 0px; + background: transparent url(/img/rounded-box-orange-bl.png) no-repeat 0px 0px; } .hint-tip .hint-tip-bot .hint-tip-c { - background: transparent url(/img/rounded-box-orange-br.png) no-repeat right 0px; + background: transparent url(/img/rounded-box-orange-br.png) no-repeat right 0px; } @@ -67,30 +67,30 @@ a { */ .info-win .info-win-top { - background: transparent url(../img/info-win-t-l.png) no-repeat 0px 0px; + background: transparent url(../img/info-win-t-l.png) no-repeat 0px 0px; } .info-win .info-win-top .info-win-c { - background: transparent url(../img/info-win-t-r.png) no-repeat right 0px; + background: transparent url(../img/info-win-t-r.png) no-repeat right 0px; } .info-win .info-win-top .info-win-c .info-win-t { - color: #000; + color: #000; } .info-win .info-win-body { - background: transparent url(../img/info-win-m-l.png) repeat-y 0px 0px; + background: transparent url(../img/info-win-m-l.png) repeat-y 0px 0px; } .info-win .info-win-body .info-win-c { - background: transparent url(../img/info-win-m-r.png) repeat-y right 0px; + background: transparent url(../img/info-win-m-r.png) repeat-y right 0px; } .info-win .info-win-bot { - background: transparent url(../img/info-win-b-l.png) no-repeat 0px 0px; + background: transparent url(../img/info-win-b-l.png) no-repeat 0px 0px; } .info-win .info-win-bot .info-win-c { - background: transparent url(../img/info-win-b-r.png) no-repeat right 0px; + background: transparent url(../img/info-win-b-r.png) no-repeat right 0px; } @@ -100,52 +100,52 @@ a { */ div.menu { - background: #FCBC40 url(../img/menu_line_bg.png) repeat-x; - border-top: 1px solid #FFFDDD; - border-bottom: 1px solid #FFFDDD; - color: #122DBA; + background: #FCBC40 url(../img/menu_line_bg.png) repeat-x; + border-top: 1px solid #FFFDDD; + border-bottom: 1px solid #FFFDDD; + color: #122DBA; } div.menu a { - color: black; + color: black; } a#login { - color: red; + color: red; } div.menu a.active { - color: #122DBA; + color: #122DBA; } div#pagemenu { - background: #FFFFFF url(../img/bg_line.png) top repeat-x; + background: #FFFFFF url(../img/bg_line.png) top repeat-x; } div#pagemenu div { - background: #FFFFFF url(../img/bg_line_top.png) bottom repeat-x; + background: #FFFFFF url(../img/bg_line_top.png) bottom repeat-x; } div#pagemenu div div { - background: #122DBA; - border-top: 1px solid #C0C0FF; - border-bottom: 1px solid #C0C0FF; + background: #122DBA; + border-top: 1px solid #C0C0FF; + border-bottom: 1px solid #C0C0FF; } div#pagemenu a { - color: #FCBC40; + color: #FCBC40; } div#pagemenu a.active { - color: #FFFDDD; + color: #FFFDDD; } div#pagemenu span { - color: #FCBC40; + color: #FCBC40; } div#pagemenu span.sep { - color: #FCBC40; + color: #FCBC40; } @@ -155,16 +155,16 @@ div#pagemenu span.sep { */ div#infobox { - border: 1px solid #FCBC40; + border: 1px solid #FCBC40; } div#infobox div.st_header { - background: #122DBA; - border-bottom: 1px solid #C0C0FF; + background: #122DBA; + border-bottom: 1px solid #C0C0FF; } div#infobox div.st_content { - background: #081966 url(../img/bg_line_top.png) top left repeat-x; + background: #081966 url(../img/bg_line_top.png) top left repeat-x; } div#infobox div.st_controls div.st_update { @@ -178,15 +178,15 @@ div#infobox div.st_controls div.st_update { */ table td.bottomrow { - border-bottom: 1px solid #FFFDDD !important; + border-bottom: 1px solid #FFFDDD !important; } table td.leftcol { - border-left: 1px solid #FFFDDD; + border-left: 1px solid #FFFDDD; } table td.rightcol { - border-right: 1px solid #FFFDDD; + border-right: 1px solid #FFFDDD; } @@ -196,19 +196,19 @@ table td.rightcol { */ table.mschedule tr td.even { - background-color: #081999; + background-color: #081999; } table.mschedule tr td.odd { - background-color: #081966; + background-color: #081966; } table.mschedule tr td.current_row { - background-color: #FCB840; + background-color: #FCB840; } table.mschedule a { - color: inherit; + color: inherit; } @@ -218,41 +218,41 @@ table.mschedule a { */ div.station div { - background: url(../img/bg_box_l.png) top left no-repeat; + background: url(../img/bg_box_l.png) top left no-repeat; } div.station div div { - background: url(../img/bg_box_r.png) top right no-repeat; + background: url(../img/bg_box_r.png) top right no-repeat; } div.station div div div { - background: url(../img/bg_box_h.png) repeat-x; + background: url(../img/bg_box_h.png) repeat-x; } div.station div div div a { - color: #000000; + color: #000000; } td div.station a { - color: #FCBC40; + color: #FCBC40; } div.content { - background: #263480 url(../img/bg_tools.png) top left repeat-y; - border-left: 1px solid #FFFDDD; - border-right: 1px solid #FFFDDD; - border-bottom: 1px solid #FFFDDD; + background: #263480 url(../img/bg_tools.png) top left repeat-y; + border-left: 1px solid #FFFDDD; + border-right: 1px solid #FFFDDD; + border-bottom: 1px solid #FFFDDD; } div.__progress { - border: 1px solid #C0C0FF; + border: 1px solid #C0C0FF; } div.__progress div.__elapsed { - background-color: #FCB840; + background-color: #FCB840; } img.channel_logo { - background-color: #FCB84000; + background-color: #FCB84000; } @@ -262,25 +262,25 @@ img.channel_logo { */ table.listing tr td { - /* background: url(../img/bg_line.png) bottom repeat-x; */ + /* background: url(../img/bg_line.png) bottom repeat-x; */ background: transparent; - border-bottom: 1px solid #FCBC40; + border-bottom: 1px solid #FCBC40; } table.listing tr.description td { - background: #122DBA; + background: #122DBA; } table.listing tr td.current { - color: #FCBC40; + color: #FCBC40; } table.listing tr.spacer td { - background-color: #081966; + background-color: #081966; } table.listing a { - color: #FCBC40; + color: #FCBC40; } @@ -289,17 +289,17 @@ table.listing a { ############################# */ -div.boxheader { - background: url(../img/bg_box_l.png) top left no-repeat; +div.boxheader { + background: url(../img/bg_box_l.png) top left no-repeat; } div.boxheader div { - background: url(../img/bg_box_r.png) top right no-repeat; + background: url(../img/bg_box_r.png) top right no-repeat; } div.boxheader div div { - background: url(../img/bg_box_h.png) repeat-x; - color: black; + background: url(../img/bg_box_h.png) repeat-x; + color: black; } @@ -309,14 +309,14 @@ div.boxheader div div { */ div.recordings { - border: 1px solid #FFFDDD; - background-color: #263480; + border: 1px solid #FFFDDD; + background-color: #263480; } div.recording_item { - /* background: url(../img/bg_line.png) bottom repeat-x; */ + /* background: url(../img/bg_line.png) bottom repeat-x; */ background: transparent; - border-bottom: 1px solid #FCBC40; + border-bottom: 1px solid #FCBC40; } @@ -326,7 +326,7 @@ div.recording_item { */ div.screenshot { - background-image: url(../img/tv.jpg); + background-image: url(../img/tv.jpg); } @@ -336,11 +336,11 @@ div.screenshot { */ div.dotted { - border: 1px dotted #bbbbbb; - padding: 3px; - margin: 2px; - float: left; - background-color: #122dBA; + border: 1px dotted #bbbbbb; + padding: 3px; + margin: 2px; + float: left; + background-color: #122dBA; } @@ -350,13 +350,13 @@ div.dotted { */ table.formular tr td { - /* background: url(../img/bg_line.png) bottom repeat-x; */ - background: transparent; - border-bottom: 1px solid #FCBC40; + /* background: url(../img/bg_line.png) bottom repeat-x; */ + background: transparent; + border-bottom: 1px solid #FCBC40; } table.dependent { - background-color: #263480; + background-color: #263480; } @@ -376,7 +376,7 @@ table.dependent { */ .info-win div.epg_content div.about_head div div { - background: #122DBA; - border-top: 1px solid #C0C1DA; - border-bottom: 1px solid #C0C1DA; + background: #122DBA; + border-top: 1px solid #C0C1DA; + border-bottom: 1px solid #C0C1DA; } diff --git a/live/themes/redwine/css/theme.css b/live/themes/redwine/css/theme.css index c379dff..5507ce4 100644 --- a/live/themes/redwine/css/theme.css +++ b/live/themes/redwine/css/theme.css @@ -4,11 +4,11 @@ */ input { - border: 1px solid #963B5F; + border: 1px solid #963B5F; } select { - border: 1px solid #963B5F; + border: 1px solid #963B5F; } @@ -18,31 +18,31 @@ select { */ .hint-tip { - color: white; + color: white; } .hint-tip .hint-tip-top { - background: transparent url(/img/rounded-box-redwine-tl.png) no-repeat 0px 0px; + background: transparent url(/img/rounded-box-redwine-tl.png) no-repeat 0px 0px; } .hint-tip .hint-tip-top .hint-tip-c { - background: transparent url(/img/rounded-box-redwine-tr.png) no-repeat right 0px; + background: transparent url(/img/rounded-box-redwine-tr.png) no-repeat right 0px; } .hint-tip .hint-tip-bdy { - background: transparent url(/img/rounded-box-redwine-ml.png) repeat-y 0px 0px; + background: transparent url(/img/rounded-box-redwine-ml.png) repeat-y 0px 0px; } .hint-tip .hint-tip-bdy .hint-tip-c { - background: transparent url(/img/rounded-box-redwine-mr.png) repeat-y right 0px; + background: transparent url(/img/rounded-box-redwine-mr.png) repeat-y right 0px; } .hint-tip .hint-tip-bot { - background: transparent url(/img/rounded-box-redwine-bl.png) no-repeat 0px 0px; + background: transparent url(/img/rounded-box-redwine-bl.png) no-repeat 0px 0px; } .hint-tip .hint-tip-bot .hint-tip-c { - background: transparent url(/img/rounded-box-redwine-br.png) no-repeat right 0px; + background: transparent url(/img/rounded-box-redwine-br.png) no-repeat right 0px; } @@ -62,34 +62,34 @@ select { */ div.menu { - background: #000057 url(../img/menu_line_bg.png) repeat-x; - color: #FFE9FA; + background: #000057 url(../img/menu_line_bg.png) repeat-x; + color: #FFE9FA; } div#pagemenu { - background: #FFFFFF url(../img/bg_line.png) top repeat-x; + background: #FFFFFF url(../img/bg_line.png) top repeat-x; } div#pagemenu div { - background: #FFFFFF url(../img/bg_line_top.png) bottom repeat-x; + background: #FFFFFF url(../img/bg_line_top.png) bottom repeat-x; } div#pagemenu div div { - background: #FFE9FA; - border-top: 1px solid #DA8DA8; - border-bottom: 1px solid #DA8DA8; + background: #FFE9FA; + border-top: 1px solid #DA8DA8; + border-bottom: 1px solid #DA8DA8; } div#pagemenu a.active { - color: #984E79; + color: #984E79; } div#pagemenu span.sep { - color: #DA8DA8; + color: #DA8DA8; } div#pagemenu span.active { - color: #984E79; + color: #984E79; } @@ -99,16 +99,16 @@ div#pagemenu span.active { */ div#infobox { - border: 1px solid #DA8DA8; + border: 1px solid #DA8DA8; } div#infobox div.st_header { - background: #FFE9FA; - border-bottom: 1px solid #DA8DA8; + background: #FFE9FA; + border-bottom: 1px solid #DA8DA8; } div#infobox div.st_content { - background: white url(../img/bg_line_top.png) top left repeat-x; + background: white url(../img/bg_line_top.png) top left repeat-x; } div#infobox div.st_controls div.st_update { @@ -122,31 +122,31 @@ div#infobox div.st_controls div.st_update { */ div.head_box_l { - background-image: url(../img/bg_header_l.png); + background-image: url(../img/bg_header_l.png); } div.head_box_m { - background-image: url(../img/bg_header_h.png); + background-image: url(../img/bg_header_h.png); } div.head_box_r { - background-image: url(../img/bg_header_r.png); + background-image: url(../img/bg_header_r.png); } button.smallbutton { - background-image: url(../img/button_blue.png); + background-image: url(../img/button_blue.png); } button.green { - background-image: url(../img/button_green.png); + background-image: url(../img/button_green.png); } button.red { - background-image: url(../img/button_red.png); + background-image: url(../img/button_red.png); } button.blue { - background-image: url(../img/button_blue.png); + background-image: url(../img/button_blue.png); } @@ -156,30 +156,30 @@ button.blue { */ div.station div { - background: url(../img/bg_box_l.png) top left no-repeat; + background: url(../img/bg_box_l.png) top left no-repeat; } div.station div div { - background: url(../img/bg_box_r.png) top right no-repeat; + background: url(../img/bg_box_r.png) top right no-repeat; } div.station div div div { - background: url(../img/bg_box_h.png) repeat-x; + background: url(../img/bg_box_h.png) repeat-x; } div.content { - background: white url(../img/bg_tools.png) top left repeat-y; + background: white url(../img/bg_tools.png) top left repeat-y; } div.__progress { - border: 1px solid #DA8DA8; + border: 1px solid #DA8DA8; } div.__progress div.__elapsed { - background-color: #FFE9FA; + background-color: #FFE9FA; } img.channel_logo { - background-color: #FFE9FA00; + background-color: #FFE9FA00; } @@ -188,16 +188,16 @@ img.channel_logo { ############################# */ -div.boxheader { - background: url(../img/bg_box_l.png) top left no-repeat; +div.boxheader { + background: url(../img/bg_box_l.png) top left no-repeat; } div.boxheader div { - background: url(../img/bg_box_r.png) top right no-repeat; + background: url(../img/bg_box_r.png) top right no-repeat; } div.boxheader div div { - background: url(../img/bg_box_h.png) repeat-x; + background: url(../img/bg_box_h.png) repeat-x; } @@ -207,8 +207,8 @@ div.boxheader div div { */ div.recording_item { - background: url(../img/bg_line.png) bottom repeat-x; - border-bottom: 1px solid #DA8DA8; + background: url(../img/bg_line.png) bottom repeat-x; + border-bottom: 1px solid #DA8DA8; } @@ -218,7 +218,7 @@ div.recording_item { */ div.screenshot { - background-image: url(../img/tv.jpg); + background-image: url(../img/tv.jpg); } @@ -228,8 +228,8 @@ div.screenshot { */ table.formular tr td { - background: url(../img/bg_line.png) bottom repeat-x; - border-bottom: 1px solid #DA8DA8; + background: url(../img/bg_line.png) bottom repeat-x; + border-bottom: 1px solid #DA8DA8; } @@ -239,11 +239,11 @@ table.formular tr td { */ table.listing tr td.head { - background: #963B5F; + background: #963B5F; } table.listing tr td { - background: url(../img/bg_line.png) bottom repeat-x; + background: url(../img/bg_line.png) bottom repeat-x; border-bottom: 1px solid #DA8DA8; } @@ -254,15 +254,15 @@ table.listing tr td { */ .about_box div.about_content div.about_head { - background: #FFFFFF url(../img/bg_line.png) top repeat-x; + background: #FFFFFF url(../img/bg_line.png) top repeat-x; } .about_box div.about_content div.about_head div { - background: #FFFFFF url(../img/bg_line_top.png) bottom repeat-x; + background: #FFFFFF url(../img/bg_line_top.png) bottom repeat-x; } .about_box div.about_content div.about_head div div { - background: #FFE9FA; - border-top: 1px solid #DA8DA8; - border-bottom: 1px solid #DA8DA8; + background: #FFE9FA; + border-top: 1px solid #DA8DA8; + border-bottom: 1px solid #DA8DA8; } diff --git a/live/themes/veltliner/css/theme.css b/live/themes/veltliner/css/theme.css index 2abfd34..76caad4 100644 --- a/live/themes/veltliner/css/theme.css +++ b/live/themes/veltliner/css/theme.css @@ -4,11 +4,11 @@ */ input { - border: 1px solid #004F00; + border: 1px solid #004F00; } select { - border: 1px solid #E0F000; + border: 1px solid #E0F000; } @@ -18,31 +18,31 @@ select { */ .hint-tip { - color: white; + color: white; } .hint-tip .hint-tip-top { - background: transparent url(/img/rounded-box-green-tl.png) no-repeat 0px 0px; + background: transparent url(/img/rounded-box-green-tl.png) no-repeat 0px 0px; } .hint-tip .hint-tip-top .hint-tip-c { - background: transparent url(/img/rounded-box-green-tr.png) no-repeat right 0px; + background: transparent url(/img/rounded-box-green-tr.png) no-repeat right 0px; } .hint-tip .hint-tip-bdy { - background: transparent url(/img/rounded-box-green-ml.png) repeat-y 0px 0px; + background: transparent url(/img/rounded-box-green-ml.png) repeat-y 0px 0px; } .hint-tip .hint-tip-bdy .hint-tip-c { - background: transparent url(/img/rounded-box-green-mr.png) repeat-y right 0px; + background: transparent url(/img/rounded-box-green-mr.png) repeat-y right 0px; } .hint-tip .hint-tip-bot { - background: transparent url(/img/rounded-box-green-bl.png) no-repeat 0px 0px; + background: transparent url(/img/rounded-box-green-bl.png) no-repeat 0px 0px; } .hint-tip .hint-tip-bot .hint-tip-c { - background: transparent url(/img/rounded-box-green-br.png) no-repeat right 0px; + background: transparent url(/img/rounded-box-green-br.png) no-repeat right 0px; } @@ -52,18 +52,18 @@ select { */ .info-win .info-win-top { - background: transparent url(../img/info-win-t-l.png) no-repeat 0px 0px; + background: transparent url(../img/info-win-t-l.png) no-repeat 0px 0px; } .info-win .info-win-top .info-win-c { - background: transparent url(../img/info-win-t-r.png) no-repeat right 0px; + background: transparent url(../img/info-win-t-r.png) no-repeat right 0px; } .info-win .info-win-top { - color: white; + color: white; } .info-win-c .info-win-t { - color: #000; + color: #000; } @@ -73,34 +73,34 @@ select { */ div.menu { - background: #000020 url(../img/menu_line_bg.png) repeat-x; - color: #005E00; + background: #000020 url(../img/menu_line_bg.png) repeat-x; + color: #005E00; } div#pagemenu { - background: #00F0F0 url(../img/bg_line.png) top repeat-x; + background: #00F0F0 url(../img/bg_line.png) top repeat-x; } div#pagemenu div { - background: #00F0F0 url(../img/bg_line_top.png) bottom repeat-x; + background: #00F0F0 url(../img/bg_line_top.png) bottom repeat-x; } div#pagemenu div div { - background: #00AE00; - border-top: 1px solid #006300; - border-bottom: 1px solid #005E00; + background: #00AE00; + border-top: 1px solid #006300; + border-bottom: 1px solid #005E00; } div#pagemenu a.active { - color: #E03000; + color: #E03000; } div#pagemenu span.sep { - color: #001E00; + color: #001E00; } div#pagemenu span.active { - color: #E03000; + color: #E03000; } @@ -110,16 +110,16 @@ div#pagemenu span.active { */ div#infobox { - border: 1px solid #005F00; + border: 1px solid #005F00; } div#infobox div.st_header { - background: #00AE00; - border-bottom: 1px solid #006300; + background: #00AE00; + border-bottom: 1px solid #006300; } div#infobox div.st_content { - background: white url(../img/bg_line_top.png) top left repeat-x; + background: white url(../img/bg_line_top.png) top left repeat-x; } div#infobox div.st_controls div.st_update { @@ -133,31 +133,31 @@ div#infobox div.st_controls div.st_update { */ div.head_box_l { - background-image: url(../img/bg_header_l.png); + background-image: url(../img/bg_header_l.png); } div.head_box_m { - background-image: url(../img/bg_header_h.png); + background-image: url(../img/bg_header_h.png); } div.head_box_r { - background-image: url(../img/bg_header_r.png); + background-image: url(../img/bg_header_r.png); } button.smallbutton { - background-image: url(../img/button_blue.png); + background-image: url(../img/button_blue.png); } button.green { - background-image: url(../img/button_green.png); + background-image: url(../img/button_green.png); } button.red { - background-image: url(../img/button_red.png); + background-image: url(../img/button_red.png); } button.blue { - background-image: url(../img/button_blue.png); + background-image: url(../img/button_blue.png); } @@ -167,30 +167,30 @@ button.blue { */ div.station div { - background: url(../img/bg_box_l.png) top left no-repeat; + background: url(../img/bg_box_l.png) top left no-repeat; } div.station div div { - background: url(../img/bg_box_r.png) top right no-repeat; + background: url(../img/bg_box_r.png) top right no-repeat; } div.station div div div { - background: url(../img/bg_box_h.png) repeat-x; + background: url(../img/bg_box_h.png) repeat-x; } div.content { - background: white url(../img/bg_tools.png) top left repeat-y; + background: white url(../img/bg_tools.png) top left repeat-y; } div.__progress { - border: 1px solid #006E00; + border: 1px solid #006E00; } div.__progress div.__elapsed { - background-color: #FFCC00; + background-color: #FFCC00; } img.channel_logo { - background-color: #FFCC0000; + background-color: #FFCC0000; } @@ -200,12 +200,12 @@ img.channel_logo { */ table.timers tr td { - background: url(../img/bg_line.png) bottom repeat-x; - border-bottom: 1px solid #006E00; + background: url(../img/bg_line.png) bottom repeat-x; + border-bottom: 1px solid #006E00; } table.timers tr.description td { - background: #00AE00; + background: #00AE00; } @@ -215,11 +215,11 @@ table.timers tr.description td { */ table.schedule tr td.head { - background: #00AE00; + background: #00AE00; } table.schedule tr td { - background: url(../img/bg_line.png) bottom repeat-x; + background: url(../img/bg_line.png) bottom repeat-x; border-bottom: 1px solid #006E00; } @@ -229,16 +229,16 @@ table.schedule tr td { ############################# */ -div.boxheader { - background: url(../img/bg_box_l.png) top left no-repeat; +div.boxheader { + background: url(../img/bg_box_l.png) top left no-repeat; } div.boxheader div { - background: url(../img/bg_box_r.png) top right no-repeat; + background: url(../img/bg_box_r.png) top right no-repeat; } div.boxheader div div { - background: url(../img/bg_box_h.png) repeat-x; + background: url(../img/bg_box_h.png) repeat-x; } @@ -248,8 +248,8 @@ div.boxheader div div { */ div.recording_item { - background: url(../img/bg_line.png) bottom repeat-x; - border-bottom: 1px solid #006E00; + background: url(../img/bg_line.png) bottom repeat-x; + border-bottom: 1px solid #006E00; } @@ -259,7 +259,7 @@ div.recording_item { */ div.screenshot { - background-image: url(../img/tv.jpg); + background-image: url(../img/tv.jpg); } @@ -269,8 +269,8 @@ div.screenshot { */ table.edit tr td { - background: url(../img/bg_line.png) bottom repeat-x; - border-bottom: 1px solid #006E00; + background: url(../img/bg_line.png) bottom repeat-x; + border-bottom: 1px solid #006E00; } @@ -280,11 +280,11 @@ table.edit tr td { */ table.searchresults tr td.head { - background: #00AE00; + background: #00AE00; } table.searchresults tr td { - background: url(../img/bg_line.png) bottom repeat-x; + background: url(../img/bg_line.png) bottom repeat-x; border-bottom: 1px solid #006E00; } @@ -305,15 +305,15 @@ table.searchresults tr td { */ .about_box div.about_content div.about_head { - background: #F0F0F0 url(../img/bg_line.png) top repeat-x; + background: #F0F0F0 url(../img/bg_line.png) top repeat-x; } .about_box div.about_content div.about_head div { - background: #F0F0F0 url(../img/bg_line_top.png) bottom repeat-x; + background: #F0F0F0 url(../img/bg_line_top.png) bottom repeat-x; } .about_box div.about_content div.about_head div div { - background: #009900; - border-top: 1px solid #006E00; - border-bottom: 1px solid #006E00; + background: #009900; + border-top: 1px solid #006E00; + border-bottom: 1px solid #006E00; } diff --git a/livefeatures.cpp b/livefeatures.cpp index eaaddc9..6958355 100644 --- a/livefeatures.cpp +++ b/livefeatures.cpp @@ -6,30 +6,30 @@ namespace vdrlive { SplitVersion::SplitVersion( std::string version ) - : m_version( 0 ) + : m_version( 0 ) { - static const int factors[] = { 100000000, 1000000, 1000, 1 }; + static const int factors[] = { 100000000, 1000000, 1000, 1 }; - size_t pos = version.find('-'); - if ( pos != std::string::npos ) { - m_suffix = version.substr( pos + 1 ); - version.erase( pos ); - } - std::vector parts = StringSplit( version, '.' ); - for ( size_t i = 0; i < parts.size() && i < sizeof(factors)/sizeof(factors[0]); ++i ) { - m_version += atoi( parts[ i ].c_str() ) * factors[ i ]; - } + size_t pos = version.find('-'); + if ( pos != std::string::npos ) { + m_suffix = version.substr( pos + 1 ); + version.erase( pos ); + } + std::vector parts = StringSplit( version, '.' ); + for ( size_t i = 0; i < parts.size() && i < sizeof(factors)/sizeof(factors[0]); ++i ) { + m_version += atoi( parts[ i ].c_str() ) * factors[ i ]; + } } bool SplitVersion::operator<( const SplitVersion& right ) const { - if ( m_version == right.m_version ) { - if (right.m_suffix.empty()) { - return false; - } - return m_suffix < right.m_suffix; - } - return m_version < right.m_version; + if ( m_version == right.m_version ) { + if (right.m_suffix.empty()) { + return false; + } + return m_suffix < right.m_suffix; + } + return m_version < right.m_version; } } // namespace vdrlive diff --git a/livefeatures.h b/livefeatures.h index e0f1ebe..353c215 100644 --- a/livefeatures.h +++ b/livefeatures.h @@ -15,13 +15,13 @@ namespace vdrlive { class SplitVersion { public: - explicit SplitVersion( std::string version ); + explicit SplitVersion( std::string version ); - bool operator<( const SplitVersion& right ) const; + bool operator<( const SplitVersion& right ) const; private: - int m_version; - std::string m_suffix; + int m_version; + std::string m_suffix; }; template @@ -33,51 +33,51 @@ Features& LiveFeatures(); template class Features { - friend Features& LiveFeatures<>(); + friend Features& LiveFeatures<>(); public: - bool Loaded() const { return m_plugin != 0; } - bool Recent() const { return !(m_version < m_minVersion); } - char const* Version() const { return m_plugin ? m_plugin->Version() : ""; } - char const* MinVersion() const { return Feat::MinVersion(); } + bool Loaded() const { return m_plugin != 0; } + bool Recent() const { return !(m_version < m_minVersion); } + char const* Version() const { return m_plugin ? m_plugin->Version() : ""; } + char const* MinVersion() const { return Feat::MinVersion(); } private: - cPlugin* m_plugin; - SplitVersion m_version; - SplitVersion m_minVersion; - - Features() - : m_plugin( cPluginManager::GetPlugin( Feat::Plugin() ) ) - , m_version( Version() ) - , m_minVersion( Feat::MinVersion() ) {} + cPlugin* m_plugin; + SplitVersion m_version; + SplitVersion m_minVersion; + + Features() + : m_plugin( cPluginManager::GetPlugin( Feat::Plugin() ) ) + , m_version( Version() ) + , m_minVersion( Feat::MinVersion() ) {} }; template Features& LiveFeatures() { - static Features instance; - return instance; + static Features instance; + return instance; } namespace features { - struct epgsearch - { - static const char* Plugin() { return "epgsearch"; } - static const char* MinVersion() { return "0.9.25.beta6"; } - }; - - struct streamdev_server - { - static const char* Plugin() { return "streamdev-server"; } - static const char* MinVersion() { return "?"; } - }; - - struct tvscraper - { - static const char* Plugin() { return "tvscraper"; } - static const char* MinVersion() { return "1.1.9"; } - }; + struct epgsearch + { + static const char* Plugin() { return "epgsearch"; } + static const char* MinVersion() { return "0.9.25.beta6"; } + }; + + struct streamdev_server + { + static const char* Plugin() { return "streamdev-server"; } + static const char* MinVersion() { return "?"; } + }; + + struct tvscraper + { + static const char* Plugin() { return "tvscraper"; } + static const char* MinVersion() { return "1.1.9"; } + }; } // namespace features } // namespace vdrlive diff --git a/md5.cpp b/md5.cpp index 7d6bcd0..8d4b099 100644 --- a/md5.cpp +++ b/md5.cpp @@ -67,36 +67,36 @@ static unsigned char PADDING[64] = // PrintMD5: Converts a completed md5 digest into a char* string. char* PrintMD5(uchar md5Digest[16]) { - char chBuffer[256]; - char chEach[10]; - int nCount; - - memset(chBuffer,0,256); - memset(chEach, 0, 10); - - for (nCount = 0; nCount < 16; nCount++) - { - sprintf(chEach, "%02x", md5Digest[nCount]); -// strncat(chBuffer, chEach, sizeof(chEach)); // compiler warning with gcc V9 - strncat(chBuffer, chEach, sizeof(chBuffer)-strlen(chBuffer)-1); // no need to limit to the size of chEach, - // because it will only append up to the 0 byte of chEach, - // but don't overflow chBuffer and let room the terminating 0 - } - - return strdup(chBuffer); + char chBuffer[256]; + char chEach[10]; + int nCount; + + memset(chBuffer,0,256); + memset(chEach, 0, 10); + + for (nCount = 0; nCount < 16; nCount++) + { + sprintf(chEach, "%02x", md5Digest[nCount]); +// strncat(chBuffer, chEach, sizeof(chEach)); // compiler warning with gcc V9 + strncat(chBuffer, chEach, sizeof(chBuffer)-strlen(chBuffer)-1); // no need to limit to the size of chEach, + // because it will only append up to the 0 byte of chEach, + // but don't overflow chBuffer and let room the terminating 0 + } + + return strdup(chBuffer); } // MD5String: Performs the MD5 algorithm on a char* string, returning // the results as a char*. char* MD5String(char* szString) { - int nLen = strlen(szString); - md5 alg; + int nLen = strlen(szString); + md5 alg; - alg.Update((unsigned char*)szString, (unsigned int)nLen); - alg.Finalize(); + alg.Update((unsigned char*)szString, (unsigned int)nLen); + alg.Finalize(); - return PrintMD5(alg.Digest()); + return PrintMD5(alg.Digest()); } @@ -104,12 +104,12 @@ char* MD5String(char* szString) // Initializes a new context. void md5::Init() { - memset(m_Count, 0, 2 * sizeof(uint4)); + memset(m_Count, 0, 2 * sizeof(uint4)); - m_State[0] = 0x67452301; - m_State[1] = 0xefcdab89; - m_State[2] = 0x98badcfe; - m_State[3] = 0x10325476; + m_State[0] = 0x67452301; + m_State[1] = 0xefcdab89; + m_State[2] = 0x98badcfe; + m_State[3] = 0x10325476; } // md5::Update @@ -118,32 +118,32 @@ void md5::Init() // context. void md5::Update(uchar* chInput, uint4 nInputLen) { - uint4 i, index, partLen; + uint4 i, index, partLen; - // Compute number of bytes mod 64 - index = (unsigned int)((m_Count[0] >> 3) & 0x3F); + // Compute number of bytes mod 64 + index = (unsigned int)((m_Count[0] >> 3) & 0x3F); - // Update number of bits - if ((m_Count[0] += (nInputLen << 3)) < (nInputLen << 3)) - m_Count[1]++; + // Update number of bits + if ((m_Count[0] += (nInputLen << 3)) < (nInputLen << 3)) + m_Count[1]++; - m_Count[1] += (nInputLen >> 29); + m_Count[1] += (nInputLen >> 29); - partLen = 64 - index; + partLen = 64 - index; - // Transform as many times as possible. - if (nInputLen >= partLen) - { - memcpy( &m_Buffer[index], chInput, partLen ); - Transform(m_Buffer); + // Transform as many times as possible. + if (nInputLen >= partLen) + { + memcpy( &m_Buffer[index], chInput, partLen ); + Transform(m_Buffer); - for (i = partLen; i + 63 < nInputLen; i += 64) - Transform(&chInput[i]); + for (i = partLen; i + 63 < nInputLen; i += 64) + Transform(&chInput[i]); - index = 0; - } - else - i = 0; + index = 0; + } + else + i = 0; // Buffer remaining input memcpy( &m_Buffer[index], &chInput[i], nInputLen-i ); @@ -154,26 +154,26 @@ void md5::Update(uchar* chInput, uint4 nInputLen) // the message digest and zeroizing the context. void md5::Finalize() { - uchar bits[8]; - uint4 index, padLen; + uchar bits[8]; + uint4 index, padLen; - // Save number of bits - Encode (bits, m_Count, 8); + // Save number of bits + Encode (bits, m_Count, 8); - // Pad out to 56 mod 64 - index = (unsigned int)((m_Count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - Update(PADDING, padLen); + // Pad out to 56 mod 64 + index = (unsigned int)((m_Count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + Update(PADDING, padLen); - // Append length (before padding) - Update (bits, 8); + // Append length (before padding) + Update (bits, 8); - // Store state in digest - Encode (m_Digest, m_State, 16); + // Store state in digest + Encode (m_Digest, m_State, 16); - memset(m_Count, 0, 2 * sizeof(uint4)); - memset(m_State, 0, 4 * sizeof(uint4)); - memset(m_Buffer,0, 64 * sizeof(uchar)); + memset(m_Count, 0, 2 * sizeof(uint4)); + memset(m_State, 0, 4 * sizeof(uint4)); + memset(m_Buffer,0, 64 * sizeof(uchar)); } // md5::Transform @@ -269,17 +269,17 @@ void md5::Transform (uchar* block) // a multiple of 4. void md5::Encode(uchar* dest, uint4* src, uint4 nLength) { - uint4 i, j; + uint4 i, j; - assert(nLength % 4 == 0); + assert(nLength % 4 == 0); - for (i = 0, j = 0; j < nLength; i++, j += 4) - { - dest[j] = (uchar)(src[i] & 0xff); - dest[j+1] = (uchar)((src[i] >> 8) & 0xff); - dest[j+2] = (uchar)((src[i] >> 16) & 0xff); - dest[j+3] = (uchar)((src[i] >> 24) & 0xff); - } + for (i = 0, j = 0; j < nLength; i++, j += 4) + { + dest[j] = (uchar)(src[i] & 0xff); + dest[j+1] = (uchar)((src[i] >> 8) & 0xff); + dest[j+2] = (uchar)((src[i] >> 16) & 0xff); + dest[j+3] = (uchar)((src[i] >> 24) & 0xff); + } } // md5::Decode @@ -287,13 +287,13 @@ void md5::Encode(uchar* dest, uint4* src, uint4 nLength) // a multiple of 4. void md5::Decode(uint4* dest, uchar* src, uint4 nLength) { - uint4 i, j; + uint4 i, j; - assert(nLength % 4 == 0); + assert(nLength % 4 == 0); - for (i = 0, j = 0; j < nLength; i++, j += 4) - { - dest[i] = ((uint4)src[j]) | (((uint4)src[j+1])<<8) | - (((uint4)src[j+2])<<16) | (((uint4)src[j+3])<<24); - } + for (i = 0, j = 0; j < nLength; i++, j += 4) + { + dest[i] = ((uint4)src[j]) | (((uint4)src[j+1])<<8) | + (((uint4)src[j+2])<<16) | (((uint4)src[j+3])<<24); + } } diff --git a/md5.h b/md5.h index 1d42561..86bf3f8 100644 --- a/md5.h +++ b/md5.h @@ -44,52 +44,52 @@ class md5 { // Methods public: - md5() { Init(); } - void Init(); - void Update(uchar* chInput, uint4 nInputLen); - void Finalize(); - uchar* Digest() { return m_Digest; } + md5() { Init(); } + void Init(); + void Update(uchar* chInput, uint4 nInputLen); + void Finalize(); + uchar* Digest() { return m_Digest; } private: - void Transform(uchar* block); - void Encode(uchar* dest, uint4* src, uint4 nLength); - void Decode(uint4* dest, uchar* src, uint4 nLength); + void Transform(uchar* block); + void Encode(uchar* dest, uint4* src, uint4 nLength); + void Decode(uint4* dest, uchar* src, uint4 nLength); - inline uint4 rotate_left(uint4 x, uint4 n) - { return ((x << n) | (x >> (32-n))); } + inline uint4 rotate_left(uint4 x, uint4 n) + { return ((x << n) | (x >> (32-n))); } - inline uint4 F(uint4 x, uint4 y, uint4 z) - { return ((x & y) | (~x & z)); } + inline uint4 F(uint4 x, uint4 y, uint4 z) + { return ((x & y) | (~x & z)); } - inline uint4 G(uint4 x, uint4 y, uint4 z) - { return ((x & z) | (y & ~z)); } + inline uint4 G(uint4 x, uint4 y, uint4 z) + { return ((x & z) | (y & ~z)); } - inline uint4 H(uint4 x, uint4 y, uint4 z) - { return (x ^ y ^ z); } + inline uint4 H(uint4 x, uint4 y, uint4 z) + { return (x ^ y ^ z); } - inline uint4 I(uint4 x, uint4 y, uint4 z) - { return (y ^ (x | ~z)); } + inline uint4 I(uint4 x, uint4 y, uint4 z) + { return (y ^ (x | ~z)); } - inline void FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) - { a += F(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } + inline void FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) + { a += F(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } - inline void GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) + inline void GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { a += G(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } - inline void HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) + inline void HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { a += H(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } - inline void II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) + inline void II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { a += I(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } // Data private: - uint4 m_State[4]; - uint4 m_Count[2]; - uchar m_Buffer[64] = {0}; - uchar m_Digest[16] = {0}; - uchar m_Finalized = 0; + uint4 m_State[4]; + uint4 m_Count[2]; + uchar m_Buffer[64] = {0}; + uchar m_Digest[16] = {0}; + uchar m_Finalized = 0; }; diff --git a/osd_status.cpp b/osd_status.cpp index e8c4249..60addbf 100644 --- a/osd_status.cpp +++ b/osd_status.cpp @@ -6,106 +6,106 @@ namespace vdrlive { OsdStatusMonitor::OsdStatusMonitor():title(),message(),red(),green(),yellow(),blue(),text(),selected(-1),lastUpdate(0){ - memset(&tabs, 0, sizeof(tabs)); + memset(&tabs, 0, sizeof(tabs)); } OsdStatusMonitor::~OsdStatusMonitor() { - OsdClear(); -} + OsdClear(); +} void OsdStatusMonitor::OsdClear() { - title = message = text = ""; - red = green = yellow = blue = ""; - items.Clear(); - selected = -1; - memset(&tabs, 0, sizeof(tabs)); - lastUpdate= clock(); + title = message = text = ""; + red = green = yellow = blue = ""; + items.Clear(); + selected = -1; + memset(&tabs, 0, sizeof(tabs)); + lastUpdate= clock(); } void OsdStatusMonitor::OsdTitle(const char *Title) { - title = Title ? Title : ""; - lastUpdate= clock(); + title = Title ? Title : ""; + lastUpdate= clock(); } void OsdStatusMonitor::OsdStatusMessage(const char *Message) { - message = Message ? Message : ""; - lastUpdate= clock(); + message = Message ? Message : ""; + lastUpdate= clock(); } void OsdStatusMonitor::OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue) { - red = Red ? Red :""; - green = Green ? Green : ""; - yellow = Yellow ? Yellow : ""; - blue = Blue ? Blue : ""; - lastUpdate= clock(); + red = Red ? Red :""; + green = Green ? Green : ""; + yellow = Yellow ? Yellow : ""; + blue = Blue ? Blue : ""; + lastUpdate= clock(); } void OsdStatusMonitor::OsdItem(const char *Text, int Index) { - const char* tab; - const char* colStart = Text; - for (int col = 0; col < MaxTabs && - (tab = strchr(colStart, '\t')); col++) { - int width = tab - colStart + 1; - if (width > tabs[col]) - tabs[col] = width; - colStart = colStart + width; - } - items.Add(new cLiveOsdItem(Text)); - lastUpdate= clock(); + const char* tab; + const char* colStart = Text; + for (int col = 0; col < MaxTabs && + (tab = strchr(colStart, '\t')); col++) { + int width = tab - colStart + 1; + if (width > tabs[col]) + tabs[col] = width; + colStart = colStart + width; + } + items.Add(new cLiveOsdItem(Text)); + lastUpdate= clock(); } void OsdStatusMonitor::OsdCurrentItem(const char *Text) { - int i = -1; - int best = -1; - int dist = items.Count(); - cLiveOsdItem * currentItem = NULL; - cLiveOsdItem *bestItem = NULL; - for (cLiveOsdItem *item = items.First(); item; item = items.Next(item)) { - if (++i == selected) - currentItem = item; - if ( item->Text().compare(Text) == 0) { - if (abs(i - selected) < dist) { - // best match is the one closest to previous position - best = i; - bestItem= item; - dist = abs(i - selected); - } - else if (selected < 0) { - // previous position unknown - take first match - best = i; - bestItem= item; - break; - } - else { - // we already have a better match, so we're done - break; - } - } - } - if (best >= 0) { - // found matching item - selected = best; - bestItem->Select(true); - if (currentItem && currentItem != bestItem){ - currentItem->Select(false); - lastUpdate= clock(); - } - } - else if (currentItem) { - // no match: the same item is still selected but its text changed - currentItem->Update(Text); - lastUpdate= clock(); - } + int i = -1; + int best = -1; + int dist = items.Count(); + cLiveOsdItem * currentItem = NULL; + cLiveOsdItem *bestItem = NULL; + for (cLiveOsdItem *item = items.First(); item; item = items.Next(item)) { + if (++i == selected) + currentItem = item; + if ( item->Text().compare(Text) == 0) { + if (abs(i - selected) < dist) { + // best match is the one closest to previous position + best = i; + bestItem= item; + dist = abs(i - selected); + } + else if (selected < 0) { + // previous position unknown - take first match + best = i; + bestItem= item; + break; + } + else { + // we already have a better match, so we're done + break; + } + } + } + if (best >= 0) { + // found matching item + selected = best; + bestItem->Select(true); + if (currentItem && currentItem != bestItem){ + currentItem->Select(false); + lastUpdate= clock(); + } + } + else if (currentItem) { + // no match: the same item is still selected but its text changed + currentItem->Update(Text); + lastUpdate= clock(); + } } void OsdStatusMonitor::OsdTextItem(const char *Text, bool Scroll) { - if (Text) { - text = Text; - //text= text.replace( text.begin(), text.end(), '\n', '|'); - } - else { - text = ""; - } - lastUpdate= clock(); + if (Text) { + text = Text; + //text= text.replace( text.begin(), text.end(), '\n', '|'); + } + else { + text = ""; + } + lastUpdate= clock(); } std::string const OsdStatusMonitor::GetTitleHtml() {return !title.empty() ? "
" + EncodeHtml(title) + "
" : "";} std::string const OsdStatusMonitor::GetMessageHtml() {return !message.empty() ? "
" + EncodeHtml(message) + "
" : "";} @@ -115,8 +115,8 @@ std::string const OsdStatusMonitor::GetYellowHtml() {return !yellow.empty() ? "< std::string const OsdStatusMonitor::GetBlueHtml() {return !blue.empty() ? "
" + EncodeHtml(blue) + "
" : "";} std::string const OsdStatusMonitor::GetTextHtml() {return !text.empty() ? "
" + EncodeHtml(text) + "
" : "";} std::string const OsdStatusMonitor::GetButtonsHtml() { - std::string buffer= GetRedHtml() + GetGreenHtml() + GetYellowHtml() + GetBlueHtml(); - return !buffer.empty() ? "
" + buffer + "
" : ""; + std::string buffer= GetRedHtml() + GetGreenHtml() + GetYellowHtml() + GetBlueHtml(); + return !buffer.empty() ? "
" + buffer + "
" : ""; } std::string const OsdStatusMonitor::GetItemsHtml(void){ @@ -146,37 +146,37 @@ std::string const OsdStatusMonitor::GetItemsHtml(void){ } std::string const OsdStatusMonitor::GetHtml(){ - std::stringstream ss; - ss << lastUpdate; - return "
" + GetTitleHtml() + GetItemsHtml() + GetTextHtml() + GetMessageHtml() + GetButtonsHtml() + "
"; + std::stringstream ss; + ss << lastUpdate; + return "
" + GetTitleHtml() + GetItemsHtml() + GetTextHtml() + GetMessageHtml() + GetButtonsHtml() + "
"; } std::string const OsdStatusMonitor::EncodeHtml(const std::string& html, bool stopAtTab) { - std::stringstream ss; - std::string::const_iterator i; - for (i = html.begin(); i != html.end(); ++i) { - if (*i == '<') - ss << "<"; - else if (*i == '>') - ss << ">"; - else if (*i == '&') - ss << "&"; - else if (*i == '"') - ss << """; - else if (*i == '\t' && stopAtTab) - break; - else - ss << static_cast(*i); // Copy untranslated - } - return ss.str(); + std::stringstream ss; + std::string::const_iterator i; + for (i = html.begin(); i != html.end(); ++i) { + if (*i == '<') + ss << "<"; + else if (*i == '>') + ss << ">"; + else if (*i == '&') + ss << "&"; + else if (*i == '"') + ss << """; + else if (*i == '\t' && stopAtTab) + break; + else + ss << static_cast(*i); // Copy untranslated + } + return ss.str(); } OsdStatusMonitor& LiveOsdStatusMonitor() { - static OsdStatusMonitor instance; - return instance; + static OsdStatusMonitor instance; + return instance; } } // namespace vdrlive diff --git a/osd_status.h b/osd_status.h index a4c7f0f..4a6a891 100644 --- a/osd_status.h +++ b/osd_status.h @@ -10,73 +10,73 @@ namespace vdrlive { class cLiveOsdItem: public cListObject { - private: - std::string text; - bool selected; - public: - std::string Text() const { return text; } - int isSelected() const {return selected;} - void Select(const bool doSelect) { selected= doSelect; }; - void Update(const char* Text) { text = Text ? Text : ""; }; - explicit cLiveOsdItem(const char* Text):text(),selected(false) { text = Text ? Text : ""; }; - ~cLiveOsdItem() { } + private: + std::string text; + bool selected; + public: + std::string Text() const { return text; } + int isSelected() const {return selected;} + void Select(const bool doSelect) { selected= doSelect; }; + void Update(const char* Text) { text = Text ? Text : ""; }; + explicit cLiveOsdItem(const char* Text):text(),selected(false) { text = Text ? Text : ""; }; + ~cLiveOsdItem() { } }; class OsdStatusMonitor: public cStatus { - friend OsdStatusMonitor& LiveOsdStatusMonitor(); + friend OsdStatusMonitor& LiveOsdStatusMonitor(); public: - enum { MaxTabs = 6 }; + enum { MaxTabs = 6 }; private: - OsdStatusMonitor(); - OsdStatusMonitor( OsdStatusMonitor const& ); - - std::string title; - std::string message; - std::string red; - std::string green; - std::string yellow; - std::string blue; - std::string text; - int selected; - cList items; - unsigned short tabs[MaxTabs]; - clock_t lastUpdate; + OsdStatusMonitor(); + OsdStatusMonitor( OsdStatusMonitor const& ); + + std::string title; + std::string message; + std::string red; + std::string green; + std::string yellow; + std::string blue; + std::string text; + int selected; + cList items; + unsigned short tabs[MaxTabs]; + clock_t lastUpdate; protected: -// static void append(char *&tail, char type, const char *src, int max); -public: - - std::string const GetTitle() const {return title;} - std::string const GetMessage() const {return message;} - std::string const GetRed() const {return red;} - std::string const GetGreen() const {return green;} - std::string const GetYellow() const {return yellow;} - std::string const GetBlue() const {return blue;} - std::string const GetText() const {return text;} - - virtual std::string const GetHtml(); - virtual std::string const GetTitleHtml(); - virtual std::string const GetMessageHtml(); - virtual std::string const GetRedHtml(); - virtual std::string const GetGreenHtml(); - virtual std::string const GetYellowHtml(); - virtual std::string const GetBlueHtml(); - virtual std::string const GetTextHtml(); - virtual std::string const GetButtonsHtml(); - virtual std::string const GetItemsHtml(); - - virtual void OsdClear(); - virtual void OsdTitle(const char *Title); - virtual void OsdStatusMessage(const char *Message); - virtual void OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue); - virtual void OsdTextItem(const char *Text, bool Scroll); - virtual void OsdItem(const char *Text, int Index); - virtual void OsdCurrentItem(const char *Text); - - virtual ~OsdStatusMonitor(); - - std::string const EncodeHtml(const std::string& html, bool stopAtTab = false); +// static void append(char *&tail, char type, const char *src, int max); +public: + + std::string const GetTitle() const {return title;} + std::string const GetMessage() const {return message;} + std::string const GetRed() const {return red;} + std::string const GetGreen() const {return green;} + std::string const GetYellow() const {return yellow;} + std::string const GetBlue() const {return blue;} + std::string const GetText() const {return text;} + + virtual std::string const GetHtml(); + virtual std::string const GetTitleHtml(); + virtual std::string const GetMessageHtml(); + virtual std::string const GetRedHtml(); + virtual std::string const GetGreenHtml(); + virtual std::string const GetYellowHtml(); + virtual std::string const GetBlueHtml(); + virtual std::string const GetTextHtml(); + virtual std::string const GetButtonsHtml(); + virtual std::string const GetItemsHtml(); + + virtual void OsdClear(); + virtual void OsdTitle(const char *Title); + virtual void OsdStatusMessage(const char *Message); + virtual void OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue); + virtual void OsdTextItem(const char *Text, bool Scroll); + virtual void OsdItem(const char *Text, int Index); + virtual void OsdCurrentItem(const char *Text); + + virtual ~OsdStatusMonitor(); + + std::string const EncodeHtml(const std::string& html, bool stopAtTab = false); }; OsdStatusMonitor& LiveOsdStatusMonitor(); diff --git a/pages/channels_widget.ecpp b/pages/channels_widget.ecpp index 1d36c1c..6b5025b 100644 --- a/pages/channels_widget.ecpp +++ b/pages/channels_widget.ecpp @@ -7,10 +7,10 @@ using namespace vdrlive; <%args> - name = "channel"; - selected; - onchange; - bool channelid = false; + name = "channel"; + selected; + onchange; + bool channelid = false; <%session scope="global"> bool logged_in(false); @@ -18,13 +18,13 @@ bool logged_in(false); % if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); diff --git a/pages/content.ecpp b/pages/content.ecpp index 594c1be..6977839 100644 --- a/pages/content.ecpp +++ b/pages/content.ecpp @@ -15,11 +15,11 @@ bool logged_in(false); std::string mime("image/png"); if (request.getArgsCount() > 0) { #if TNT_MAPURL_NAMED_ARGS - mime = request.getArg("mime-type"); + mime = request.getArg("mime-type"); #else - mime = request.getArg(0); + mime = request.getArg(0); #endif - // dsyslog("vdrlive::content found mime arg (%s)", mime.c_str()); + // dsyslog("vdrlive::content found mime arg (%s)", mime.c_str()); } reply.setContentType(mime); // dsyslog("vdrlive::content::mimetype(%s)", mime.c_str()); @@ -30,26 +30,26 @@ std::string const path(request.getPathInfo()); // security checking of path. In order to not allow exploits the // path must be absolute and not contain any upward references (e.g '../') if (path.empty()) { - return HTTP_BAD_REQUEST; + return HTTP_BAD_REQUEST; } if ('/' != path[0]) { - return HTTP_BAD_REQUEST; + return HTTP_BAD_REQUEST; } if (std::string::npos != path.find("../", 1)) { - return HTTP_BAD_REQUEST; + return HTTP_BAD_REQUEST; } FileCache::ptr_type f = LiveFileCache().get(path); if (f.get() == 0) { - // dsyslog("vdrlive::content: DECLINED"); - return DECLINED; + // dsyslog("vdrlive::content: DECLINED"); + return DECLINED; } std::string ctime = tnt::HttpMessage::htdate(f->ctime()); std::string browserTime = request.getHeader(tnt::httpheader::ifModifiedSince); if (browserTime == ctime) { - // dsyslog("vdrlive::content: HTTP_NOT_MODIFIED"); - return HTTP_NOT_MODIFIED; + // dsyslog("vdrlive::content: HTTP_NOT_MODIFIED"); + return HTTP_NOT_MODIFIED; } // dsyslog("vdrlive::content: send %d bytes of data", f->size()); diff --git a/pages/delete_recording.ecpp b/pages/delete_recording.ecpp index 5455ed6..cae53c0 100644 --- a/pages/delete_recording.ecpp +++ b/pages/delete_recording.ecpp @@ -10,8 +10,8 @@ using namespace vdrlive; <%args> - std::string param; - std::string async; + std::string param; + std::string async; <%cpp> RecordingsManagerPtr recordings = LiveRecordingsManager(); @@ -26,15 +26,15 @@ using namespace vdrlive; throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); } - bool ajaxReq = !async.empty() && (parse_int(async) != 0); - std::string referrer; + bool ajaxReq = !async.empty() && (parse_int(async) != 0); + std::string referrer; - if (ajaxReq) { - reply.setContentType( "application/xml" ); - } - else { - referrer = request.getHeader("Referer:"); - } + if (ajaxReq) { + reply.setContentType( "application/xml" ); + } + else { + referrer = request.getHeader("Referer:"); + } RemoveRecordingTask task(param); LiveTaskManager().Execute(task); @@ -47,10 +47,10 @@ using namespace vdrlive; result = "error"; } - if (!ajaxReq) { - if (!referrer.empty()) { - return reply.redirect(referrer); - } + if (!ajaxReq) { + if (!referrer.empty()) { + return reply.redirect(referrer); + } Normale Seite:
recording: <$ recording->Name() $>
@@ -58,10 +58,10 @@ result: <$ result $>
error: <$ (task.Error()) $>
Seitenende! <%cpp> - } - else { + } + else { <& xmlresponse.ajax name=("delete_recording") pname=("recording") value=(recording->Name()) result=(task.Result()) error=(task.Error()) &> <%cpp> - } + } diff --git a/pages/edit_recording.ecpp b/pages/edit_recording.ecpp index 6c73a6c..08a4e28 100644 --- a/pages/edit_recording.ecpp +++ b/pages/edit_recording.ecpp @@ -10,14 +10,14 @@ using namespace vdrlive; <%args> - // input parameters - std::string recid; - std::string async; + // input parameters + std::string recid; + std::string async; int history_num_back; //number of pages to go back to the recordings page // call with 1 -> chancel will go back one page in history - // form parameters - std::string name = ""; - std::string directory = ""; + // form parameters + std::string name = ""; + std::string directory = ""; std::string newdir = ""; std::string title = ""; std::string shorttext = ""; @@ -38,38 +38,38 @@ const cRecording* recording; <%include>page_init.eh <%cpp> - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - if (!cUser::CurrentUserHasRightTo(UR_EDITRECS)) - throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); + if (!cUser::CurrentUserHasRightTo(UR_EDITRECS)) + throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); - bool ajaxReq = !async.empty() && (parse_int(async) != 0); + bool ajaxReq = !async.empty() && (parse_int(async) != 0); - std::string message; + std::string message; - recording = NULL; - if (!recid.empty()) { - recording = LiveRecordingsManager()->GetByMd5Hash(recid); - if (!recording) - throw HtmlError(tr("Couldn't find recording. Maybe you mistyped your request?")); - } + recording = NULL; + if (!recid.empty()) { + recording = LiveRecordingsManager()->GetByMd5Hash(recid); + if (!recording) + throw HtmlError(tr("Couldn't find recording. Maybe you mistyped your request?")); + } bool returnToReferer = false; - if (request.getMethod() == "POST") { + if (request.getMethod() == "POST") { ++history_num_back; - if (name.empty()) - message = tr("Please set a name for the recording!"); - else if (recording) { - bool copy_only = false; - if (delresume == "delresume") LiveRecordingsManager()->DeleteResume(recording); + if (name.empty()) + message = tr("Please set a name for the recording!"); + else if (recording) { + bool copy_only = false; + if (delresume == "delresume") LiveRecordingsManager()->DeleteResume(recording); if (delmarks == "delmarks") LiveRecordingsManager()->DeleteMarks(recording); if (copy == "copy") copy_only = true; if (newdir != ".") directory = newdir; - if (LiveRecordingsManager()->UpdateRecording(recording, directory, name, copy_only, title, shorttext, description)) + if (LiveRecordingsManager()->UpdateRecording(recording, directory, name, copy_only, title, shorttext, description)) returnToReferer = true; - else - message = tr("Cannot copy, rename or move the recording."); - } + else + message = tr("Cannot copy, rename or move the recording."); + } } if (returnToReferer) { @@ -81,104 +81,104 @@ const cRecording* recording; <%cpp> - } else { + } else { - if (recording) { - const cRecordingInfo *info = recording->Info(); - name = recording->BaseName(); - directory = StringReplace(*recording->Folder(), "~", "/"); - title = cSv(info->Title()); - shorttext = cSv(info->ShortText()); - description = cSv(info->Description()); - } + if (recording) { + const cRecordingInfo *info = recording->Info(); + name = recording->BaseName(); + directory = StringReplace(*recording->Folder(), "~", "/"); + title = cSv(info->Title()); + shorttext = cSv(info->ShortText()); + description = cSv(info->Description()); + } <& pageelems.doc_type &> - + - VDR Live - <$ tr("Edit recording") $> + VDR Live - <$ tr("Edit recording") $> <%cpp> - if (!ajaxReq) { + if (!ajaxReq) { - <& pageelems.stylesheets &> + <& pageelems.stylesheets &> <& pageelems.create_html_js &> - <& pageelems.ajax_js &> + <& pageelems.ajax_js &> <%cpp> - } + } - - + function new_dir() { + var dir = document.getElementById("directory"); + dir.style.display = "none"; + document.getElementById("new_dir_button").style.display = "none"; + var newdir = document.getElementById("newdir"); + newdir.value = dir.value; + newdir.style.display = ""; + } + + + <%cpp> - if (!ajaxReq) { + if (!ajaxReq) { - <& pageelems.logo &> - <& menu active=(active_r) &> + <& pageelems.logo &> + <& menu active=(active_r) &> <%cpp> - } + } -
-
- - - - - - - - - - - - - + + +
<$ tr("Edit recording") $>
<$ tr("Name") $>:
<$ tr("Directory") $>:
- + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + " title="<$tr("Create new directory")$>" onclick="new_dir()" style="vertical-align: middle"> + + + + + + + + + + + + + + + + + + + + + + + + + + + <%cpp> if (recording && recording->Info()->Aux()) { @@ -196,36 +196,36 @@ if (recording && recording->Info()->Aux()) { } if (!aux_data.empty()) { - - - - + + + + <%cpp> } else { - - - - + + + + <%cpp> } } - - - -
<$ tr("Edit recording") $>
<$ tr("Name") $>:
<$ tr("Directory") $>:
+ - " title="<$tr("Create new directory")$>" onclick="new_dir()" style="vertical-align: middle"> - -
<$ tr("Delete resume information") $>:
<$ tr("Delete marks information") $>:
<$ tr("Copy only") $>:
<$ tr("Title") $>:
<$ tr("Short description") $>:
<$ tr("Description") $>:
<$ tr("Delete resume information") $>:
<$ tr("Delete marks information") $>:
<$ tr("Copy only") $>:
<$ tr("Title") $>:
<$ tr("Short description") $>:
<$ tr("Description") $>:
<$ tr("Search timer") $>:
<$ aux_data $>
<$ tr("Search timer") $>:
<$ aux_data $>
<$ tr("Auxiliary info") $>:
<$ recording->Info()->Aux() $>
<$ tr("Auxiliary info") $>:
<$ recording->Info()->Aux() $>
-
- - -
-
- -
- <$ message $> -
- - +
+
+ + +
+
+ +
+ <$ message $> +
+
+ % } <%include>page_exit.eh diff --git a/pages/edit_searchtimer.ecpp b/pages/edit_searchtimer.ecpp index 374aadd..ade47d5 100644 --- a/pages/edit_searchtimer.ecpp +++ b/pages/edit_searchtimer.ecpp @@ -10,71 +10,71 @@ using namespace vdrlive; <%args> - // input parameters - std::string searchtimerid; - std::string test; - - // form parameters - std::string search = ""; - int mode = 0; - bool matchcase = false; - int tolerance = 1; - bool usetitle = false; - bool usesubtitle = false; - bool usedescr = false; - int usechannel = SearchTimer::NoChannel; - - std::string channelfrom_string = ""; - std::string channelto_string = ""; - - std::string changrpsel = ""; - bool usetime = false; - std::string start_s = "00:00"; - std::string stop_s = "00:00"; - bool useduration = false; - int durationmin_h = 0; - int durationmin_m = 0; - int durationmax_h = 1; - int durationmax_m = 30; - bool useweekday = false; - bool wday_mon = false; - bool wday_tue = false; - bool wday_wed = false; - bool wday_thu = false; - bool wday_fri = false; - bool wday_sat = false; - bool wday_sun = false; - bool useinfavorites = false; - int useassearchtimer = 0; - int searchtimeraction = 0; - bool seriesrecording = false; - std::string directory = ""; - int delrecafterdays = 0; - int keeprecs = 0; - int pauseonrecs = 0; - int blacklistmode = 0; - int switchminbefore = 0; - bool useextepginfo = false; - std::string extepgvalues[]; - bool avoidrepeats = false; - int allowedrepeats = 0; - int repeatswithindays = 0; - bool comparetitle = false; - int comparesubtitle = 0; - bool comparesummary = false; - unsigned avoidrepeatscatselected[]; - int priority = 0; - int lifetime = 0; - int marginstart = 0; - int marginstop = 0; - bool usevps = false; - bool delmode = false; - int delaftercountrecs = 0; - int delafterdaysoffirstrec = 0; - std::string blacklistids_internal; - std::string useassearchtimerfrom; - std::string useassearchtimerto; - bool ignoreMissingEPGCats = false; + // input parameters + std::string searchtimerid; + std::string test; + + // form parameters + std::string search = ""; + int mode = 0; + bool matchcase = false; + int tolerance = 1; + bool usetitle = false; + bool usesubtitle = false; + bool usedescr = false; + int usechannel = SearchTimer::NoChannel; + + std::string channelfrom_string = ""; + std::string channelto_string = ""; + + std::string changrpsel = ""; + bool usetime = false; + std::string start_s = "00:00"; + std::string stop_s = "00:00"; + bool useduration = false; + int durationmin_h = 0; + int durationmin_m = 0; + int durationmax_h = 1; + int durationmax_m = 30; + bool useweekday = false; + bool wday_mon = false; + bool wday_tue = false; + bool wday_wed = false; + bool wday_thu = false; + bool wday_fri = false; + bool wday_sat = false; + bool wday_sun = false; + bool useinfavorites = false; + int useassearchtimer = 0; + int searchtimeraction = 0; + bool seriesrecording = false; + std::string directory = ""; + int delrecafterdays = 0; + int keeprecs = 0; + int pauseonrecs = 0; + int blacklistmode = 0; + int switchminbefore = 0; + bool useextepginfo = false; + std::string extepgvalues[]; + bool avoidrepeats = false; + int allowedrepeats = 0; + int repeatswithindays = 0; + bool comparetitle = false; + int comparesubtitle = 0; + bool comparesummary = false; + unsigned avoidrepeatscatselected[]; + int priority = 0; + int lifetime = 0; + int marginstart = 0; + int marginstop = 0; + bool usevps = false; + bool delmode = false; + int delaftercountrecs = 0; + int delafterdaysoffirstrec = 0; + std::string blacklistids_internal; + std::string useassearchtimerfrom; + std::string useassearchtimerto; + bool ignoreMissingEPGCats = false; <%session scope="global"> bool logged_in(false); @@ -92,8 +92,8 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); }> <%cpp> - if (!cUser::CurrentUserHasRightTo(UR_EDITSTIMERS)) - throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); + if (!cUser::CurrentUserHasRightTo(UR_EDITSTIMERS)) + throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); #define SELECTIF(x) reply.out() << ( (x) ? "selected=\"selected\"" : "" ); #define CHECKIF(x) reply.out() << ( (x) ? "checked=\"checked\"" : "" ); @@ -103,122 +103,122 @@ const char *TNT_ARRAY = "[]"; const char *TNT_ARRAY = ""; #endif - SearchTimers searchtimers; - bool testmode = !test.empty(); - editsearchtimer = NULL; + SearchTimers searchtimers; + bool testmode = !test.empty(); + editsearchtimer = NULL; tChannelID channelfrom = tChannelID::FromString(channelfrom_string.c_str()); tChannelID channelto = tChannelID::FromString(channelto_string.c_str()); - if ( request.getMethod() == "POST") { - SearchTimer searchtimer; - if ( !searchtimerid.empty() && !testmode) { - editsearchtimer = searchtimers.GetByTimerId( searchtimerid ); - if ( editsearchtimer == 0 ) - throw HtmlError( tr("Couldn't find search timer. Maybe you mistyped your request?") ); - searchtimer.SetId(editsearchtimer->Id()); - } - - searchtimer.SetSearch(search); - searchtimer.SetSearchMode(mode); - searchtimer.SetTolerance(tolerance); - searchtimer.SetMatchCase(matchcase); - searchtimer.SetUseTitle(usetitle); - searchtimer.SetUseSubtitle(usesubtitle); - searchtimer.SetUseDescription(usedescr); - searchtimer.SetUseExtEPGInfo(useextepginfo); - if (useextepginfo) - { - std::vector infos; - unsigned int i=0; - for (ExtEPGInfos::iterator extinfo = extEPGInfos.begin(); extinfo != extEPGInfos.end(); ++extinfo, i++) - { - std::stringstream os; - os << extinfo->Id() << "#" << (iId()); + } + + searchtimer.SetSearch(search); + searchtimer.SetSearchMode(mode); + searchtimer.SetTolerance(tolerance); + searchtimer.SetMatchCase(matchcase); + searchtimer.SetUseTitle(usetitle); + searchtimer.SetUseSubtitle(usesubtitle); + searchtimer.SetUseDescription(usedescr); + searchtimer.SetUseExtEPGInfo(useextepginfo); + if (useextepginfo) + { + std::vector infos; + unsigned int i=0; + for (ExtEPGInfos::iterator extinfo = extEPGInfos.begin(); extinfo != extEPGInfos.end(); ++extinfo, i++) + { + std::stringstream os; + os << extinfo->Id() << "#" << (i @@ -227,12 +227,12 @@ const char *TNT_ARRAY = ""; <%cpp> -// return reply.redirect("searchtimers.html"); - } - else - { - searchtimer.SetId(0); - std::string md5 = SearchResults::AddQuery(searchtimer.ToText()); +// return reply.redirect("searchtimers.html"); + } + else + { + searchtimer.SetId(0); + std::string md5 = SearchResults::AddQuery(searchtimer.ToText()); @@ -241,683 +241,683 @@ const char *TNT_ARRAY = ""; <%cpp> -// return reply.redirect("searchresults.html?searchtimerquery=" + md5); - } - } - pageTitle = !searchtimerid.empty() ? tr("Edit search timer") : tr("New search timer"); - - if ( !searchtimerid.empty() ) { - SearchTimer* searchtimer = searchtimers.GetByTimerId( searchtimerid ); - if ( searchtimer == 0 ) - throw HtmlError( tr("Couldn't find search timer. Maybe you mistyped your request?") ); - - search = searchtimer->Search(); - mode = searchtimer->SearchMode(); - tolerance = searchtimer->Tolerance(); - matchcase = searchtimer->MatchCase(); - usetitle = searchtimer->UseTitle(); - usesubtitle = searchtimer->UseSubtitle(); - usedescr = searchtimer->UseDescription(); - usechannel = searchtimer->UseChannel(); - channelfrom = searchtimer->ChannelMin(); - channelto = searchtimer->ChannelMax(); - if (!channelto.Valid() && channelfrom.Valid()) - channelto = channelfrom; - if (usechannel == SearchTimer::Group) - changrpsel = searchtimer->ChannelText(); - usetime = searchtimer->UseTime(); +// return reply.redirect("searchresults.html?searchtimerquery=" + md5); + } + } + pageTitle = !searchtimerid.empty() ? tr("Edit search timer") : tr("New search timer"); + + if ( !searchtimerid.empty() ) { + SearchTimer* searchtimer = searchtimers.GetByTimerId( searchtimerid ); + if ( searchtimer == 0 ) + throw HtmlError( tr("Couldn't find search timer. Maybe you mistyped your request?") ); + + search = searchtimer->Search(); + mode = searchtimer->SearchMode(); + tolerance = searchtimer->Tolerance(); + matchcase = searchtimer->MatchCase(); + usetitle = searchtimer->UseTitle(); + usesubtitle = searchtimer->UseSubtitle(); + usedescr = searchtimer->UseDescription(); + usechannel = searchtimer->UseChannel(); + channelfrom = searchtimer->ChannelMin(); + channelto = searchtimer->ChannelMax(); + if (!channelto.Valid() && channelfrom.Valid()) + channelto = channelfrom; + if (usechannel == SearchTimer::Group) + changrpsel = searchtimer->ChannelText(); + usetime = searchtimer->UseTime(); start_s = intToTimeString(searchtimer->StartTime() ); stop_s = intToTimeString(searchtimer->StopTime() ); - useduration = searchtimer->UseDuration(); - if (useduration) - { - durationmin_m = searchtimer->MinDuration() % 100; - durationmin_h = searchtimer->MinDuration() / 100; - durationmax_m = searchtimer->MaxDuration() % 100; - durationmax_h = searchtimer->MaxDuration() / 100; - } - useweekday = searchtimer->UseDayOfWeek(); - if (useweekday) - { - int dayofweek = searchtimer->DayOfWeek(); - if (dayofweek >= 0) - { - wday_sun = (dayofweek == 0); - wday_mon = (dayofweek == 1); - wday_tue = (dayofweek == 2); - wday_wed = (dayofweek == 3); - wday_thu = (dayofweek == 4); - wday_fri = (dayofweek == 5); - wday_sat = (dayofweek == 6); - } - else - { - wday_sun = -dayofweek & 0x01; - wday_mon = -dayofweek & 0x02; - wday_tue = -dayofweek & 0x04; - wday_wed = -dayofweek & 0x08; - wday_thu = -dayofweek & 0x10; - wday_fri = -dayofweek & 0x20; - wday_sat = -dayofweek & 0x40; - } - } - useinfavorites = searchtimer->UseInFavorites(); - useassearchtimer = searchtimer->UseAsSearchTimer(); - if (useassearchtimer == 2) - { - useassearchtimerfrom = searchtimer->UseAsSearchTimerFrom("yyyy-mm-dd"); - useassearchtimerto = searchtimer->UseAsSearchTimerTil("yyyy-mm-dd"); - } - searchtimeraction = searchtimer->SearchTimerAction(); - seriesrecording = searchtimer->UseSeriesRecording(); - directory = searchtimer->Directory(); - delrecafterdays = searchtimer->DelRecsAfterDays(); - keeprecs = searchtimer->KeepRecs(); - pauseonrecs = searchtimer->PauseOnRecs(); - blacklistmode = searchtimer->BlacklistMode(); - switchminbefore = searchtimer->SwitchMinBefore(); - useextepginfo = searchtimer->UseExtEPGInfo(); - std::vector infos = searchtimer->ExtEPGInfo(); - for(unsigned int i=0; i parts = StringSplit( infos[i], '#' ); - extepgvalues.push_back(parts.size() > 1?parts[1]:""); - } - else - extepgvalues.push_back(""); - } - ignoreMissingEPGCats = searchtimer->IgnoreMissingEPGCats(); - avoidrepeats = searchtimer->AvoidRepeats(); - allowedrepeats = searchtimer->AllowedRepeats(); - repeatswithindays = searchtimer->RepeatsWithinDays(); - comparetitle = searchtimer->CompareTitle(); - comparesubtitle = searchtimer->CompareSubtitle(); - comparesummary = searchtimer->CompareSummary(); - for(unsigned int i=0; iCompareCategories() & (1<Priority(); - lifetime = searchtimer->Lifetime(); - marginstart = searchtimer->MarginStart(); - marginstop = searchtimer->MarginStop(); - usevps = searchtimer->UseVPS(); - delmode = searchtimer->DelMode(); - delaftercountrecs = searchtimer->DelAfterCountRecs(); - delafterdaysoffirstrec = searchtimer->DelAfterDaysOfFirstRec(); - - editsearchtimer = searchtimer; - } - else - { - for(unsigned int i=0; i(EPGSearchSetupValues::ReadValue("DefPriority")); - lifetime = parse_int(EPGSearchSetupValues::ReadValue("DefLifetime")); - marginstart = parse_int(EPGSearchSetupValues::ReadValue("DefMarginStart")); - marginstop = parse_int(EPGSearchSetupValues::ReadValue("DefMarginStop")); - } + useduration = searchtimer->UseDuration(); + if (useduration) + { + durationmin_m = searchtimer->MinDuration() % 100; + durationmin_h = searchtimer->MinDuration() / 100; + durationmax_m = searchtimer->MaxDuration() % 100; + durationmax_h = searchtimer->MaxDuration() / 100; + } + useweekday = searchtimer->UseDayOfWeek(); + if (useweekday) + { + int dayofweek = searchtimer->DayOfWeek(); + if (dayofweek >= 0) + { + wday_sun = (dayofweek == 0); + wday_mon = (dayofweek == 1); + wday_tue = (dayofweek == 2); + wday_wed = (dayofweek == 3); + wday_thu = (dayofweek == 4); + wday_fri = (dayofweek == 5); + wday_sat = (dayofweek == 6); + } + else + { + wday_sun = -dayofweek & 0x01; + wday_mon = -dayofweek & 0x02; + wday_tue = -dayofweek & 0x04; + wday_wed = -dayofweek & 0x08; + wday_thu = -dayofweek & 0x10; + wday_fri = -dayofweek & 0x20; + wday_sat = -dayofweek & 0x40; + } + } + useinfavorites = searchtimer->UseInFavorites(); + useassearchtimer = searchtimer->UseAsSearchTimer(); + if (useassearchtimer == 2) + { + useassearchtimerfrom = searchtimer->UseAsSearchTimerFrom("yyyy-mm-dd"); + useassearchtimerto = searchtimer->UseAsSearchTimerTil("yyyy-mm-dd"); + } + searchtimeraction = searchtimer->SearchTimerAction(); + seriesrecording = searchtimer->UseSeriesRecording(); + directory = searchtimer->Directory(); + delrecafterdays = searchtimer->DelRecsAfterDays(); + keeprecs = searchtimer->KeepRecs(); + pauseonrecs = searchtimer->PauseOnRecs(); + blacklistmode = searchtimer->BlacklistMode(); + switchminbefore = searchtimer->SwitchMinBefore(); + useextepginfo = searchtimer->UseExtEPGInfo(); + std::vector infos = searchtimer->ExtEPGInfo(); + for(unsigned int i=0; i parts = StringSplit( infos[i], '#' ); + extepgvalues.push_back(parts.size() > 1?parts[1]:""); + } + else + extepgvalues.push_back(""); + } + ignoreMissingEPGCats = searchtimer->IgnoreMissingEPGCats(); + avoidrepeats = searchtimer->AvoidRepeats(); + allowedrepeats = searchtimer->AllowedRepeats(); + repeatswithindays = searchtimer->RepeatsWithinDays(); + comparetitle = searchtimer->CompareTitle(); + comparesubtitle = searchtimer->CompareSubtitle(); + comparesummary = searchtimer->CompareSummary(); + for(unsigned int i=0; iCompareCategories() & (1<Priority(); + lifetime = searchtimer->Lifetime(); + marginstart = searchtimer->MarginStart(); + marginstop = searchtimer->MarginStop(); + usevps = searchtimer->UseVPS(); + delmode = searchtimer->DelMode(); + delaftercountrecs = searchtimer->DelAfterCountRecs(); + delafterdaysoffirstrec = searchtimer->DelAfterDaysOfFirstRec(); + + editsearchtimer = searchtimer; + } + else + { + for(unsigned int i=0; i(EPGSearchSetupValues::ReadValue("DefPriority")); + lifetime = parse_int(EPGSearchSetupValues::ReadValue("DefLifetime")); + marginstart = parse_int(EPGSearchSetupValues::ReadValue("DefMarginStart")); + marginstop = parse_int(EPGSearchSetupValues::ReadValue("DefMarginStop")); + } <& pageelems.doc_type &> - + - VDR Live - <$ editsearchtimer ? tr("Edit search timer") : tr("New search timer") $> - - <& pageelems.stylesheets &> - <& pageelems.ajax_js &> - - - - - - <& pageelems.logo &> - <& menu active=("searchtimers") &> -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -% if (extEPGInfos.size() > 0) { - - - - + +% } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
<$ editsearchtimer ? tr("Edit search timer") : tr("New search timer") $>
<$ tr("Search term") $>:
<$ tr("Search mode" ) $>:
-
- -
- -
<$ tr("Match case") $>:
id="matchcase"/>
<$ tr("Search in") $>:
-
- /> - -
-
- /> - -
-
- /> - -
-
<$ tr("Use extended EPG info" ) $>:
- onclick="changeduseextepginfo(this)" id="useextepginfo"/> - +
<$ tr("Use channel" ) $>:
+ + + + + +
<$ tr("Use time") $>:
+ onclick="changedusetime(this)" id="usetime" /> + +
<$ tr("Use duration") $>:
+ onclick="changeduseduration(this)" id="useduration" /> + +
<$ tr("Use day of week") $>:
+ onclick="changeduseweekday(this)" id="useweekday" /> + +
<$ tr("Use blacklists" ) $>:
+ + +
<$ tr("Use in favorites menu") $>:
/>
<$ tr("Use as search timer" ) $>:
+
+ +
+ + + + + +
+
+ + + +
+
+ +
+ <%include>page_exit.eh diff --git a/pages/edit_timer.ecpp b/pages/edit_timer.ecpp index 5c95a89..6ae1858 100644 --- a/pages/edit_timer.ecpp +++ b/pages/edit_timer.ecpp @@ -16,30 +16,30 @@ using namespace vdrlive; <%args> - // input parameters - std::string timerid; - std::string epgid; - std::string async; - // form parameters + // input parameters + std::string timerid; + std::string epgid; + std::string async; + // form parameters std::string channel_string = ""; - int active = 1; - std::string title = ""; - std::string remoteServerName = ""; - std::string date = ""; - bool wday_mon = false; - bool wday_tue = false; - bool wday_wed = false; - bool wday_thu = false; - bool wday_fri = false; - bool wday_sat = false; - bool wday_sun = false; + int active = 1; + std::string title = ""; + std::string remoteServerName = ""; + std::string date = ""; + bool wday_mon = false; + bool wday_tue = false; + bool wday_wed = false; + bool wday_thu = false; + bool wday_fri = false; + bool wday_sat = false; + bool wday_sun = false; std::string start_s = "00:00"; std::string stop_s = "00:00"; - bool vps = 0; - int priority = 0; - int lifetime = 0; - std::string aux = ""; - std::string directory = ""; + bool vps = 0; + int priority = 0; + int lifetime = 0; + std::string aux = ""; + std::string directory = ""; int nav_back = 1; <%session scope="global"> @@ -52,38 +52,38 @@ const cTimer* timer; <%include>page_init.eh <%cpp> - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - if (!cUser::CurrentUserHasRightTo(UR_EDITTIMERS)) - throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); + if (!cUser::CurrentUserHasRightTo(UR_EDITTIMERS)) + throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); - bool ajaxReq = !async.empty() && (parse_int(async) != 0); + bool ajaxReq = !async.empty() && (parse_int(async) != 0); tChannelID channel = tChannelID::FromString(channel_string.c_str()); - std::string message; - cMutexLock timersLock( &LiveTimerManager() ); - SortedTimers& timers = LiveTimerManager().GetTimers(); + std::string message; + cMutexLock timersLock( &LiveTimerManager() ); + SortedTimers& timers = LiveTimerManager().GetTimers(); - timer = 0; - int timerId = 0; - if ( !timerid.empty() ) { - std::string tId = SortedTimers::DecodeDomId(timerid); -// dsyslog("live: DEBUG: TIMER: timerid = %s", timerid); -// dsyslog("live: DEBUG: TIMER: tId = %s", tId.c_str()); - timer = timers.GetByTimerId(tId); - if ( timer == 0 ) - throw HtmlError( tr("Couldn't find timer. Maybe you mistyped your request?") ); + timer = 0; + int timerId = 0; + if ( !timerid.empty() ) { + std::string tId = SortedTimers::DecodeDomId(timerid); +// dsyslog("live: DEBUG: TIMER: timerid = %s", timerid); +// dsyslog("live: DEBUG: TIMER: tId = %s", tId.c_str()); + timer = timers.GetByTimerId(tId); + if ( timer == 0 ) + throw HtmlError( tr("Couldn't find timer. Maybe you mistyped your request?") ); else timerId = timer->Id(); - } + } - if ( request.getMethod() == "POST" && title.empty()) { ++nav_back; message = tr("Please set a title for the timer!"); } - if ( request.getMethod() == "POST" && !title.empty()) { - const char* oldRemote = NULL; - if (timer) { - oldRemote = timer->Remote(); -// dsyslog("live: found valid timer on server '%s'", oldRemote); + if ( request.getMethod() == "POST" && title.empty()) { ++nav_back; message = tr("Please set a title for the timer!"); } + if ( request.getMethod() == "POST" && !title.empty()) { + const char* oldRemote = NULL; + if (timer) { + oldRemote = timer->Remote(); +// dsyslog("live: found valid timer on server '%s'", oldRemote); } uint flags = ( active ? tfActive : 0 ) | ( vps ? tfVps : 0 ); @@ -116,7 +116,7 @@ const cTimer* timer; std::string file = directory.empty() ? title : directory + "~" + title; const char* remote = ( remoteServerName == "") ? NULL : remoteServerName.c_str(); -// dsyslog("live: remote '%s'", remote); +// dsyslog("live: remote '%s'", remote); LiveTimerManager().UpdateTimer( timerId, remote, oldRemote, flags, channel, weekdays, date, start, stop, priority, lifetime, file, aux ); timerNotifier.SetTimerModification(); @@ -127,250 +127,250 @@ const cTimer* timer; <%cpp> -// return reply.redirect("html/back.html"); -// return reply.redirect(!edit_timerreferer.empty()?edit_timerreferer:"timers.html"); - } else { +// return reply.redirect("html/back.html"); +// return reply.redirect(!edit_timerreferer.empty()?edit_timerreferer:"timers.html"); + } else { - if (message.empty()) - edit_timerreferer = request.getHeader("Referer:", "timers.html"); + if (message.empty()) + edit_timerreferer = request.getHeader("Referer:", "timers.html"); - std::unique_ptr eventTimer; - if (timer == 0 && !epgid.empty()) { - const cEvent *event = EpgEvents::GetEventByEpgid(epgid); + std::unique_ptr eventTimer; + if (timer == 0 && !epgid.empty()) { + const cEvent *event = EpgEvents::GetEventByEpgid(epgid); if (event) { eventTimer.reset( new cTimer( event ) ); - timer = eventTimer.get(); + timer = eventTimer.get(); } else { esyslog("live: edit timer with epgid %s not valid", epgid.c_str() ); } - } - if (timer == 0) - { - eventTimer.reset( new cTimer() ); - eventTimer->SetFlags( tfActive ); - timer = eventTimer.get(); - } + } + if (timer == 0) + { + eventTimer.reset( new cTimer() ); + eventTimer->SetFlags( tfActive ); + timer = eventTimer.get(); + } - if ( timer != 0 && request.getMethod() == "GET" ) { - active = timer->Flags() & tfActive; - channel = timer->Channel()->GetChannelID(); - title = timer->File() ? timer->File() : ""; - remoteServerName = timer->Remote() ? timer->Remote() : ""; + if ( timer != 0 && request.getMethod() == "GET" ) { + active = timer->Flags() & tfActive; + channel = timer->Channel()->GetChannelID(); + title = timer->File() ? timer->File() : ""; + remoteServerName = timer->Remote() ? timer->Remote() : ""; // dsyslog("live: remoteServerName '%s'", remoteServerName.c_str()); - if ( LiveFeatures().Recent() ) { - std::vector directories = StringSplit( title, '~' ); - if (directories.size() > 1) { - directory = directories[0]; - title = title.substr(directory.size()+1); - } - } - // TRANSLATORS: only adjust the ordering and separators, don't translate the m's, d's and y's - date = timer->Day() ? DatePickerToC(timer->Day(), "yyyy-mm-dd") : ""; - wday_mon = timer->WeekDays() & 0x01; - wday_tue = timer->WeekDays() & 0x02; - wday_wed = timer->WeekDays() & 0x04; - wday_thu = timer->WeekDays() & 0x08; - wday_fri = timer->WeekDays() & 0x10; - wday_sat = timer->WeekDays() & 0x20; - wday_sun = timer->WeekDays() & 0x40; + if ( LiveFeatures().Recent() ) { + std::vector directories = StringSplit( title, '~' ); + if (directories.size() > 1) { + directory = directories[0]; + title = title.substr(directory.size()+1); + } + } + // TRANSLATORS: only adjust the ordering and separators, don't translate the m's, d's and y's + date = timer->Day() ? DatePickerToC(timer->Day(), "yyyy-mm-dd") : ""; + wday_mon = timer->WeekDays() & 0x01; + wday_tue = timer->WeekDays() & 0x02; + wday_wed = timer->WeekDays() & 0x04; + wday_thu = timer->WeekDays() & 0x08; + wday_fri = timer->WeekDays() & 0x10; + wday_sat = timer->WeekDays() & 0x20; + wday_sun = timer->WeekDays() & 0x40; start_s = intToTimeString(timer->Start() ); stop_s = intToTimeString(timer->Stop() ); - vps = timer->Flags() & tfVps; - priority = timer->Priority(); - lifetime = timer->Lifetime(); - aux = timer->Aux() ? timer->Aux() : ""; - } + vps = timer->Flags() & tfVps; + priority = timer->Priority(); + lifetime = timer->Lifetime(); + aux = timer->Aux() ? timer->Aux() : ""; + } <& pageelems.doc_type &> - + - VDR Live - <$ timer ? tr("Edit timer") : tr("New timer") $> + VDR Live - <$ timer ? tr("Edit timer") : tr("New timer") $> <%cpp> - if (!ajaxReq) { + if (!ajaxReq) { - <& pageelems.stylesheets &> - <& pageelems.ajax_js &> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> <%cpp> - } + } - - + + <%cpp> - if (!ajaxReq) { + if (!ajaxReq) { - <& pageelems.logo &> - <& menu active=("timers") &> + <& pageelems.logo &> + <& menu active=("timers") &> <%cpp> - } + } -
-
- - - - - - - - +
+ + + + + +
<$ timer ? tr("Edit timer") : tr("New timer") $>
+ + + - - - - + + + + - - - - + + + + - - - - + + + + <%cpp> - cStringList svdrpServerNames; - if (GetSVDRPServerNames(&svdrpServerNames)) { - svdrpServerNames.Sort(true); + cStringList svdrpServerNames; + if (GetSVDRPServerNames(&svdrpServerNames)) { + svdrpServerNames.Sort(true); - - - + + - + + + <%cpp> - svdrpServerNames.Clear(); - } + svdrpServerNames.Clear(); + } <%cpp> - if ( LiveFeatures().Recent() ) { - RecordingDirs recordingdirs(true); + if ( LiveFeatures().Recent() ) { + RecordingDirs recordingdirs(true); - - - + + - + +% } + + + <%cpp> - } + } - - - - + + + + - - - - + + + + - - - - + + + + - - - + + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - -
<$ timer ? tr("Edit timer") : tr("New timer") $>
<$ trVDR("Active") $>:
-
- type="radio"> - -
-
- type="radio"> - -
-
<$ trVDR("Active") $>:
+
+ type="radio"> + +
+
+ type="radio"> + +
+
<$ trVDR("Channel") $>:
<& channels_widget name=("channel_string") channelid=(true) selected=(channel) &>
<$ trVDR("Channel") $>:
<& channels_widget name=("channel_string") channelid=(true) selected=(channel) &>
<$ tr("Title" ) $>:
<$ tr("Title" ) $>:
<$ tr("Server" ) $>:
<$ tr("Server" ) $>:
-
<$ tr("Directory" ) $>:
<$ tr("Directory" ) $>:
-
<$ trVDR("Day") $>:
<$ trVDR("Day") $>:
<$ tr("Weekday") $>:
-
- /> - -
-
- /> - -
-
- /> - -
-
- /> - -
-
- /> - -
-
- /> - -
-
- /> - -
-
<$ tr("Weekday") $>:
+
+ /> + +
+
+ /> + +
+
+ /> + +
+
+ /> + +
+
+ /> + +
+
+ /> + +
+
+ /> + +
+
<$ trVDR("Start") $>:
<$ trVDR("Start") $>:
<$ trVDR("Stop") $>:
+
<$ trVDR("Stop") $>:
<$ tr("Use VPS") $>:
/>
<$ tr("Use VPS") $>:
/>
<$ trVDR("Priority") $>:
<$ trVDR("Priority") $>:
<$ trVDR("Lifetime") $>:
<$ trVDR("Lifetime") $>:
-
- - -
-
-
-
- <$ message $> -
-
- + + +
+ + +
+ + + + +
+ <$ message $> +
+ + % } <%include>page_exit.eh diff --git a/pages/edit_user.ecpp b/pages/edit_user.ecpp index 01c9d91..5305b7d 100644 --- a/pages/edit_user.ecpp +++ b/pages/edit_user.ecpp @@ -8,21 +8,21 @@ using namespace vdrlive; <%args> - // input parameters - std::string userid; - // form parameters - std::string username; - std::string password; - bool ur_editsetup = false; - bool ur_addtimers = false; - bool ur_deltimers = false; - bool ur_delrecs = false; - bool ur_useremote = false; - bool ur_startreplay = false; - bool ur_switchchnl = false; - bool ur_addstimers = false; - bool ur_delstimers = false; - bool ur_editrecs = false; + // input parameters + std::string userid; + // form parameters + std::string username; + std::string password; + bool ur_editsetup = false; + bool ur_addtimers = false; + bool ur_deltimers = false; + bool ur_delrecs = false; + bool ur_useremote = false; + bool ur_startreplay = false; + bool ur_switchchnl = false; + bool ur_addstimers = false; + bool ur_delstimers = false; + bool ur_editrecs = false; <%session scope="global"> bool logged_in(false); @@ -32,150 +32,150 @@ cUser* editUser; <%include>page_init.eh <%cpp> - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); #define CHECKIF(x) reply.out() << ( (x) ? "checked=\"checked\"" : "" ); - editUser = NULL; + editUser = NULL; - if (request.getMethod() == "POST") { - if (!userid.empty()) { - editUser = Users.GetByUserId( userid ); - if ( editUser == 0 ) - throw HtmlError( tr("Couldn't find user. Maybe you mistyped your request?") ); - editUser->SetName(username); - if (password != std::string(editUser->GetPasswordLength(), '*')) - editUser->SetPassword(password); - } - else - { - if (Users.GetByUserName( username )) - throw HtmlError( tr("This user name is already in use!") ); - editUser = new cUser(Users.GetNewId(), username, password); - Users.Add(editUser); - } - editUser->SetUserrights(0); - if (ur_editsetup) editUser->SetRight(UR_EDITSETUP); - if (ur_addtimers) editUser->SetRight(UR_EDITTIMERS); - if (ur_deltimers) editUser->SetRight(UR_DELTIMERS); - if (ur_delrecs) editUser->SetRight(UR_DELRECS); - if (ur_useremote) editUser->SetRight(UR_USEREMOTE); - if (ur_startreplay) editUser->SetRight(UR_STARTREPLAY); - if (ur_switchchnl) editUser->SetRight(UR_SWITCHCHNL); - if (ur_addstimers) editUser->SetRight(UR_EDITSTIMERS); - if (ur_delstimers) editUser->SetRight(UR_DELSTIMERS); - if (ur_editrecs) editUser->SetRight(UR_EDITRECS); + if (request.getMethod() == "POST") { + if (!userid.empty()) { + editUser = Users.GetByUserId( userid ); + if ( editUser == 0 ) + throw HtmlError( tr("Couldn't find user. Maybe you mistyped your request?") ); + editUser->SetName(username); + if (password != std::string(editUser->GetPasswordLength(), '*')) + editUser->SetPassword(password); + } + else + { + if (Users.GetByUserName( username )) + throw HtmlError( tr("This user name is already in use!") ); + editUser = new cUser(Users.GetNewId(), username, password); + Users.Add(editUser); + } + editUser->SetUserrights(0); + if (ur_editsetup) editUser->SetRight(UR_EDITSETUP); + if (ur_addtimers) editUser->SetRight(UR_EDITTIMERS); + if (ur_deltimers) editUser->SetRight(UR_DELTIMERS); + if (ur_delrecs) editUser->SetRight(UR_DELRECS); + if (ur_useremote) editUser->SetRight(UR_USEREMOTE); + if (ur_startreplay) editUser->SetRight(UR_STARTREPLAY); + if (ur_switchchnl) editUser->SetRight(UR_SWITCHCHNL); + if (ur_addstimers) editUser->SetRight(UR_EDITSTIMERS); + if (ur_delstimers) editUser->SetRight(UR_DELSTIMERS); + if (ur_editrecs) editUser->SetRight(UR_EDITRECS); - Users.Save(); + Users.Save(); - return reply.redirect("users.html"); - } + return reply.redirect("users.html"); + } - pageTitle = !userid.empty() ? tr("Edit user") : tr("New user"); + pageTitle = !userid.empty() ? tr("Edit user") : tr("New user"); - if ( !userid.empty() ) { - cUser* User = Users.GetByUserId( userid ); - if ( User == 0 ) - throw HtmlError( tr("Couldn't find user. Maybe you mistyped your request?") ); + if ( !userid.empty() ) { + cUser* User = Users.GetByUserId( userid ); + if ( User == 0 ) + throw HtmlError( tr("Couldn't find user. Maybe you mistyped your request?") ); - username = User->Name(); - password = std::string(User->GetPasswordLength(), '*'); - ur_editsetup = User->HasRightTo(UR_EDITSETUP); - ur_addtimers = User->HasRightTo(UR_EDITTIMERS); - ur_deltimers = User->HasRightTo(UR_DELTIMERS); - ur_delrecs = User->HasRightTo(UR_DELRECS); - ur_useremote = User->HasRightTo(UR_USEREMOTE); - ur_startreplay = User->HasRightTo(UR_STARTREPLAY); - ur_switchchnl = User->HasRightTo(UR_SWITCHCHNL); - ur_addstimers = User->HasRightTo(UR_EDITSTIMERS); - ur_delstimers = User->HasRightTo(UR_DELSTIMERS); - ur_editrecs = User->HasRightTo(UR_EDITRECS); - editUser = User; - } - else - { - ur_editsetup = true; - ur_addtimers = true; - ur_deltimers = true; - ur_delrecs = true; - ur_useremote = true; - ur_startreplay = true; - ur_switchchnl = true; - ur_addstimers = true; - ur_delstimers = true; - ur_editrecs = true; - } + username = User->Name(); + password = std::string(User->GetPasswordLength(), '*'); + ur_editsetup = User->HasRightTo(UR_EDITSETUP); + ur_addtimers = User->HasRightTo(UR_EDITTIMERS); + ur_deltimers = User->HasRightTo(UR_DELTIMERS); + ur_delrecs = User->HasRightTo(UR_DELRECS); + ur_useremote = User->HasRightTo(UR_USEREMOTE); + ur_startreplay = User->HasRightTo(UR_STARTREPLAY); + ur_switchchnl = User->HasRightTo(UR_SWITCHCHNL); + ur_addstimers = User->HasRightTo(UR_EDITSTIMERS); + ur_delstimers = User->HasRightTo(UR_DELSTIMERS); + ur_editrecs = User->HasRightTo(UR_EDITRECS); + editUser = User; + } + else + { + ur_editsetup = true; + ur_addtimers = true; + ur_deltimers = true; + ur_delrecs = true; + ur_useremote = true; + ur_startreplay = true; + ur_switchchnl = true; + ur_addstimers = true; + ur_delstimers = true; + ur_editrecs = true; + } <& pageelems.doc_type &> - - - VDR Live - <$ pageTitle $> - <& pageelems.stylesheets &> - <& pageelems.ajax_js &> - - - <& pageelems.logo &> - <& menu active=("users") &> -
-
- - - - - + + + VDR Live - <$ pageTitle $> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> + + + <& pageelems.logo &> + <& menu active=("users") &> +
+ + +
<$ pageTitle $>
+ + + - - - - - - - - - - - - + + + + + + + + + + + - - - - -
<$ pageTitle $>
<$ tr("Name" ) $>:
<$ tr("Password" ) $>:
<$ tr("User rights") $>:
- /> -
- /> -
- /> -
- /> -
- /> -
- /> -
- /> -
+
<$ tr("Name" ) $>:
<$ tr("Password" ) $>:
<$ tr("User rights") $>:
+ /> +
+ /> +
+ /> +
+ /> +
+ /> +
+ /> +
+ /> +
<%cpp> - if (LiveFeatures().Recent()) { + if (LiveFeatures().Recent()) { - /> -
- /> -
+ /> +
+ /> +
<%cpp> - } + } - /> -
-
-
- - -
-
-
-
- + /> +
+ + + + +
+ + +
+ + + + + + <%include>page_exit.eh diff --git a/pages/epginfo.ecpp b/pages/epginfo.ecpp index 77f3476..88d7b4a 100644 --- a/pages/epginfo.ecpp +++ b/pages/epginfo.ecpp @@ -11,145 +11,145 @@ using namespace vdrlive; <%args> - std::string epgid; - std::string delete_rec; // to_confirm or confirmed - int history_num_back = 0; - std::string async; - std::string tab; + std::string epgid; + std::string delete_rec; // to_confirm or confirmed + int history_num_back = 0; + std::string async; + std::string tab; std::string sort; std::string filter; std::string flat; <%session scope="global"> - bool logged_in(false); + bool logged_in(false); <%request scope="global"> - EpgInfoPtr epgEvent; - std::string epgImage; + EpgInfoPtr epgEvent; + std::string epgImage; uintptr_t i_event; uintptr_t irecording; <%include>page_init.eh <%cpp> reply.setHeader (tnt::httpheader::cacheControl, "no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate", true); - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - pageTitle = tr("Electronic program guide information"); + pageTitle = tr("Electronic program guide information"); - bool ajaxReq = !async.empty() && (parse_int(async) != 0); + bool ajaxReq = !async.empty() && (parse_int(async) != 0); - bool aboutBox = false; + bool aboutBox = false; if (epgid.compare(0, 4, "del_") == 0) { delete_rec = "to_confirm"; epgid.erase(0, 4); } - bool isEvent = false; - RecordingsManagerPtr recordings; - epgImage.clear(); + bool isEvent = false; + RecordingsManagerPtr recordings; + epgImage.clear(); i_event = 0; irecording = 0; if (!delete_rec.empty()) { - pageTitle = tr("Delete recordings"); + pageTitle = tr("Delete recordings"); } else if (!epgid.empty()) { - const std::string_view recording_s("recording_"); - const std::string_view event_s("event_"); - const std::string_view aboutbox("aboutBox"); + const std::string_view recording_s("recording_"); + const std::string_view event_s("event_"); + const std::string_view aboutbox("aboutBox"); - // check for recording: - if (epgid.compare(0, recording_s.length(), recording_s) == 0) { - recordings = LiveRecordingsManager(); - const cRecording *recording = recordings->GetByMd5Hash(epgid); - if (recording == 0) { - throw HtmlError(tr("Couldn't find recording or no recordings available")); - } - epgEvent = EpgEvents::CreateEpgInfo(epgid, recording); + // check for recording: + if (epgid.compare(0, recording_s.length(), recording_s) == 0) { + recordings = LiveRecordingsManager(); + const cRecording *recording = recordings->GetByMd5Hash(epgid); + if (recording == 0) { + throw HtmlError(tr("Couldn't find recording or no recordings available")); + } + epgEvent = EpgEvents::CreateEpgInfo(epgid, recording); cTvMedia image; - EpgEvents::PosterTvscraper(image, NULL, recording); - epgImage = image.path; + EpgEvents::PosterTvscraper(image, NULL, recording); + epgImage = image.path; irecording = (uintptr_t)recording; - } - // check for event: - else if (epgid.compare(0, event_s.length(), event_s) == 0) { - /* Need to lock here channels also, because CreateEpgInfo will lock - * it also and this will result in a wrong lock order */ - LOCK_CHANNELS_READ; - LOCK_SCHEDULES_READ; - epgEvent = EpgEvents::CreateEpgInfo(epgid, Schedules); - isEvent = true; - const cEvent* event = epgEvent->Event(); + } + // check for event: + else if (epgid.compare(0, event_s.length(), event_s) == 0) { + /* Need to lock here channels also, because CreateEpgInfo will lock + * it also and this will result in a wrong lock order */ + LOCK_CHANNELS_READ; + LOCK_SCHEDULES_READ; + epgEvent = EpgEvents::CreateEpgInfo(epgid, Schedules); + isEvent = true; + const cEvent* event = epgEvent->Event(); cTvMedia image; - EpgEvents::PosterTvscraper(image, event, NULL); - epgImage = image.path; + EpgEvents::PosterTvscraper(image, event, NULL); + epgImage = image.path; i_event = (uintptr_t)event; - } - // check for aboutbox: - else if (epgid.compare(0, aboutbox.length(), aboutbox) == 0) { - aboutBox = true; - } - } + } + // check for aboutbox: + else if (epgid.compare(0, aboutbox.length(), aboutbox) == 0) { + aboutBox = true; + } + } <& pageelems.doc_type &> - - - VDR-Live - <$ pageTitle $> + + + VDR-Live - <$ pageTitle $> <%cpp> - if (!ajaxReq) { + if (!ajaxReq) { - <& pageelems.stylesheets &> + <& pageelems.stylesheets &> <& pageelems.create_html_js &> - <& pageelems.ajax_js &> + <& pageelems.ajax_js &> <%cpp> - } + } - - + + <%cpp> - if (!ajaxReq) { + if (!ajaxReq) { - <& pageelems.logo &> - <& menu &> + <& pageelems.logo &> + <& menu &> <%cpp> - } + } -
+
<%cpp> - if (epgEvent && delete_rec.empty()) { + if (epgEvent && delete_rec.empty()) { uintptr_t i_epgEvent = (uintptr_t)(&epgEvent); - std::string start(epgEvent->StartTime("%a,") + std::string(" ") - + epgEvent->StartTime(tr("%b %d %y")) + std::string(" ") + std::string start(epgEvent->StartTime("%a,") + std::string(" ") + + epgEvent->StartTime(tr("%b %d %y")) + std::string(" ") + epgEvent->StartTime(tr("%I:%M %p")) ); if (epgEvent->EventDuration() < 0) { // epg event, no recording start += std::string(" - ") + epgEvent->EndTime(tr("%I:%M %p")); - start += " "; - AppendDuration(start, tr("(%d:%02d)"), epgEvent->Duration()); + start += " "; + AppendDuration(start, tr("(%d:%02d)"), epgEvent->Duration()); } - std::string tools_component; - if (recordings) { - tools_component = epgEvent->Archived().empty() ? "recordings.rec_tools" : "recordings.archived_disc" ; - } - if (isEvent) - tools_component = "epginfo.epgTools"; + std::string tools_component; + if (recordings) { + tools_component = epgEvent->Archived().empty() ? "recordings.rec_tools" : "recordings.archived_disc" ; + } + if (isEvent) + tools_component = "epginfo.epgTools"; - <& pageelems.epg_tt_box boxId=(epgEvent->Id()) caption=(epgEvent->Caption()) tools_comp=(tools_component) time=(start) title=(epgEvent->Title()) short_descr=(epgEvent->ShortDescr()) long_descr=(epgEvent->LongDescr()) archived=(epgEvent->Archived()) elapsed=(epgEvent->Elapsed()) channel=(epgEvent->ChannelName()) filename=(epgEvent->FileName()) epgImage=(epgImage) irecording=(irecording) ievent=(i_event) iepgEvent=(i_epgEvent) sort=(sort) filter=(filter) flat=(flat) history_num_back=(history_num_back) &> + <& pageelems.epg_tt_box boxId=(epgEvent->Id()) caption=(epgEvent->Caption()) tools_comp=(tools_component) time=(start) title=(epgEvent->Title()) short_descr=(epgEvent->ShortDescr()) long_descr=(epgEvent->LongDescr()) archived=(epgEvent->Archived()) elapsed=(epgEvent->Elapsed()) channel=(epgEvent->ChannelName()) filename=(epgEvent->FileName()) epgImage=(epgImage) irecording=(irecording) ievent=(i_event) iepgEvent=(i_epgEvent) sort=(sort) filter=(filter) flat=(flat) history_num_back=(history_num_back) &> <%cpp> - } - if (aboutBox) { + } + if (aboutBox) { - <& pageelems.about_tt_box &> + <& pageelems.about_tt_box &> <%cpp> - } + } if (!delete_rec.empty() ) { <& recordings.todel todel=(epgid) confirmed=(delete_rec) history_num_back=(history_num_back) &> % } -
- +
+ <%include>page_exit.eh diff --git a/pages/error.ecpp b/pages/error.ecpp index 6ac995a..7bdda16 100644 --- a/pages/error.ecpp +++ b/pages/error.ecpp @@ -6,9 +6,9 @@ using namespace vdrlive; <%args> - pageTitle; - errorTitle = tr("Page error"); - errorMessage; + pageTitle; + errorTitle = tr("Page error"); + errorMessage; <%session scope="global"> bool logged_in(false); @@ -18,26 +18,26 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); }> <& pageelems.doc_type &> - - - VDR-Live - <$ pageTitle $> - <& pageelems.stylesheets &> - - - <& pageelems.logo &> - <& menu &> -
- <& error.error_widget errorTitle=(errorTitle) errorMessage=(errorMessage) &> -
- + + + VDR-Live - <$ pageTitle $> + <& pageelems.stylesheets &> + + + <& pageelems.logo &> + <& menu &> +
+ <& error.error_widget errorTitle=(errorTitle) errorMessage=(errorMessage) &> +
+ <%def error_widget> - <%args> - errorTitle; - errorMessage; - - - - -
<$ errorTitle $>
<$ errorMessage $>
+ <%args> + errorTitle; + errorMessage; + + + + +
<$ errorTitle $>
<$ errorMessage $>
diff --git a/pages/event_widget.ecpp b/pages/event_widget.ecpp index db8538d..ef11b4d 100644 --- a/pages/event_widget.ecpp +++ b/pages/event_widget.ecpp @@ -20,17 +20,17 @@ bool logged_in(false); if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); }> - - - - - - -
<$ channel_name $>
-   - -
<$ start $> - <$ end $>
-
<$ title $>
-
<$ short_description $>
-
<$ description $>
-
+ + + + + + +
<$ channel_name $>
+   + +
<$ start $> - <$ end $>
+
<$ title $>
+
<$ short_description $>
+
<$ description $>
+
diff --git a/pages/ffw_recording.ecpp b/pages/ffw_recording.ecpp index f7711dc..6a4fdc6 100644 --- a/pages/ffw_recording.ecpp +++ b/pages/ffw_recording.ecpp @@ -7,16 +7,16 @@ using namespace vdrlive; <%args> - std::string param; + std::string param; <%session scope="global"> - bool logged_in(false); + bool logged_in(false); <%cpp> - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - reply.setContentType( "application/xml" ); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + reply.setContentType( "application/xml" ); - ForwardRecordingTask task( param ); - LiveTaskManager().Execute( task ); + ForwardRecordingTask task( param ); + LiveTaskManager().Execute( task ); <& xmlresponse.ajax name=("ffw_recording") pname=("recording") value=(param) result=(task.Result()) error=(task.Error()) &> diff --git a/pages/ibox.ecpp b/pages/ibox.ecpp index f7b57e3..2b2242f 100644 --- a/pages/ibox.ecpp +++ b/pages/ibox.ecpp @@ -12,7 +12,7 @@ using namespace vdrlive; <%args> - int update; + int update; <%session scope="global"> bool logged_in(false); @@ -20,125 +20,125 @@ int update_status(1); TimerConflictNotifier timerNotifier(); <%cpp> - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - std::string EMPTY_STR; - tChannelID prev_chan; - tChannelID next_chan; - reply.setContentType( "application/xml" ); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + std::string EMPTY_STR; + tChannelID prev_chan; + tChannelID next_chan; + reply.setContentType( "application/xml" ); - if (update_status != update) { - update_status = update; - } + if (update_status != update) { + update_status = update; + } - std::string infoMsg; - std::string infoUrl; + std::string infoMsg; + std::string infoUrl; - if (timerNotifier.ShouldNotify()) { - infoMsg = timerNotifier.Message(); - infoUrl = "timerconflicts.html"; - } + if (timerNotifier.ShouldNotify()) { + infoMsg = timerNotifier.Message(); + infoUrl = "timerconflicts.html"; + } - const char* NowReplaying = cReplayControl::NowReplaying(); + const char* NowReplaying = cReplayControl::NowReplaying(); - EpgInfoPtr epgEvent; + EpgInfoPtr epgEvent; - if (NowReplaying) { - RecordingsManagerPtr recManager = LiveRecordingsManager(); - // is is OK to lock here, because CreateEpgInfo will *not* lock other lists - LOCK_RECORDINGS_READ; - cRecording *recording = (cRecording *)Recordings->GetByName(NowReplaying); - if (recording) { - epgEvent = EpgEvents::CreateEpgInfo( + if (NowReplaying) { + RecordingsManagerPtr recManager = LiveRecordingsManager(); + // is is OK to lock here, because CreateEpgInfo will *not* lock other lists + LOCK_RECORDINGS_READ; + cRecording *recording = (cRecording *)Recordings->GetByName(NowReplaying); + if (recording) { + epgEvent = EpgEvents::CreateEpgInfo( concat("recording_", cToSvXxHash128(XXH3_128bits(NowReplaying, strlen(NowReplaying))) ), - recording, - tr("playing recording")); - } - } - else { - std::string CHANNEL_STR("channel"); - LOCK_CHANNELS_READ; + recording, + tr("playing recording")); + } + } + else { + std::string CHANNEL_STR("channel"); + LOCK_CHANNELS_READ; - if (cDevice::CurrentChannel()) { - const int SKIP_GAP = 1; - cChannel* Channel = (cChannel *)Channels->GetByNumber(cDevice::CurrentChannel()); + if (cDevice::CurrentChannel()) { + const int SKIP_GAP = 1; + cChannel* Channel = (cChannel *)Channels->GetByNumber(cDevice::CurrentChannel()); - cChannel* tmp = (cChannel *)Channels->GetByNumber(Channels->GetPrevNormal(cDevice::CurrentChannel()), -SKIP_GAP); + cChannel* tmp = (cChannel *)Channels->GetByNumber(Channels->GetPrevNormal(cDevice::CurrentChannel()), -SKIP_GAP); #if VDRVERSNUM >= 20606 - if (tmp) + if (tmp) #else - if (tmp && cDevice::PrimaryDevice() && cDevice::PrimaryDevice()->HasDecoder() ) + if (tmp && cDevice::PrimaryDevice() && cDevice::PrimaryDevice()->HasDecoder() ) #endif - prev_chan = tmp->GetChannelID(); - tmp = (cChannel *)Channels->GetByNumber(Channels->GetNextNormal(cDevice::CurrentChannel()), SKIP_GAP); + prev_chan = tmp->GetChannelID(); + tmp = (cChannel *)Channels->GetByNumber(Channels->GetNextNormal(cDevice::CurrentChannel()), SKIP_GAP); #if VDRVERSNUM >= 20606 - if (tmp) + if (tmp) #else - if (tmp && cDevice::PrimaryDevice() && cDevice::PrimaryDevice()->HasDecoder() ) + if (tmp && cDevice::PrimaryDevice() && cDevice::PrimaryDevice()->HasDecoder() ) #endif - next_chan = tmp->GetChannelID(); + next_chan = tmp->GetChannelID(); - const std::string chanName(Channel->Name()); - LOCK_SCHEDULES_READ; - const cSchedule *Schedule = Schedules->GetSchedule(Channel); + const std::string chanName(Channel->Name()); + LOCK_SCHEDULES_READ; + const cSchedule *Schedule = Schedules->GetSchedule(Channel); - if (Schedule) { - const cEvent *Event = Schedule->GetPresentEvent(); - if (Event) { - epgEvent = EpgEvents::CreateEpgInfo(Channel, - Event, - CHANNEL_STR.c_str()); - } - else { - const std::string noInfo(tr("no epg info for current event!")); - epgEvent = EpgEvents::CreateEpgInfo(CHANNEL_STR, - chanName, - noInfo); - } - } - else { - const std::string noInfo(tr("no epg info for current channel!")); - epgEvent = EpgEvents::CreateEpgInfo(CHANNEL_STR, - Channel->Name(), - noInfo); - } - } - else { - const std::string chanName(tr("no current channel!")); - epgEvent = EpgEvents::CreateEpgInfo(CHANNEL_STR, - chanName, - chanName); - } - } - if (!epgEvent) { - const std::string ERROR_STR("error"); - const std::string noInfo(tr("error retrieving status info!")); - const std::string chanName(tr("no current channel!")); - epgEvent = EpgEvents::CreateEpgInfo(ERROR_STR, - chanName, - noInfo); - } - else { - if (prev_chan.Valid() && next_chan.Valid()) - { + if (Schedule) { + const cEvent *Event = Schedule->GetPresentEvent(); + if (Event) { + epgEvent = EpgEvents::CreateEpgInfo(Channel, + Event, + CHANNEL_STR.c_str()); + } + else { + const std::string noInfo(tr("no epg info for current event!")); + epgEvent = EpgEvents::CreateEpgInfo(CHANNEL_STR, + chanName, + noInfo); + } + } + else { + const std::string noInfo(tr("no epg info for current channel!")); + epgEvent = EpgEvents::CreateEpgInfo(CHANNEL_STR, + Channel->Name(), + noInfo); + } + } + else { + const std::string chanName(tr("no current channel!")); + epgEvent = EpgEvents::CreateEpgInfo(CHANNEL_STR, + chanName, + chanName); + } + } + if (!epgEvent) { + const std::string ERROR_STR("error"); + const std::string noInfo(tr("error retrieving status info!")); + const std::string chanName(tr("no current channel!")); + epgEvent = EpgEvents::CreateEpgInfo(ERROR_STR, + chanName, + noInfo); + } + else { + if (prev_chan.Valid() && next_chan.Valid()) + { <& xmlresponse.ibox update=(update_status) type=(epgEvent->Id()) caption=(epgEvent->Caption()) currentTime=(epgEvent->CurrentTime(tr("%I:%M:%S %p"))) duration=(epgEvent->StartTime(tr("%I:%M %p")) + std::string(" - ") + epgEvent->EndTime(tr("%I:%M %p"))) title=(epgEvent->Title()) elapsed=(epgEvent->Elapsed()) prev_chan=(prev_chan) next_chan=(next_chan) infoMsg=(infoMsg) infoUrl=(infoUrl) &> <%cpp> - } - else if (prev_chan.Valid()) { + } + else if (prev_chan.Valid()) { <& xmlresponse.ibox update=(update_status) type=(epgEvent->Id()) caption=(epgEvent->Caption()) currentTime=(epgEvent->CurrentTime(tr("%I:%M:%S %p"))) duration=(epgEvent->StartTime(tr("%I:%M %p")) + std::string(" - ") + epgEvent->EndTime(tr("%I:%M %p"))) title=(epgEvent->Title()) elapsed=(epgEvent->Elapsed()) prev_chan=(prev_chan) infoMsg=(infoMsg) infoUrl=(infoUrl) &> <%cpp> - } - else if (next_chan.Valid()) { + } + else if (next_chan.Valid()) { <& xmlresponse.ibox update=(update_status) type=(epgEvent->Id()) caption=(epgEvent->Caption()) currentTime=(epgEvent->CurrentTime(tr("%I:%M:%S %p"))) duration=(epgEvent->StartTime(tr("%I:%M %p")) + std::string(" - ") + epgEvent->EndTime(tr("%I:%M %p"))) title=(epgEvent->Title()) elapsed=(epgEvent->Elapsed()) next_chan=(next_chan) infoMsg=(infoMsg) infoUrl=(infoUrl) &> <%cpp> - } - else { + } + else { <& xmlresponse.ibox update=(update_status) type=(epgEvent->Id()) caption=(epgEvent->Caption()) currentTime=(epgEvent->CurrentTime(tr("%I:%M:%S %p"))) duration=(epgEvent->StartTime(tr("%I:%M %p")) + std::string(" - ") + epgEvent->EndTime(tr("%I:%M %p"))) title=(epgEvent->Title()) elapsed=(epgEvent->Elapsed()) infoMsg=(infoMsg) infoUrl=(infoUrl) &> <%cpp> - } - } + } + } diff --git a/pages/keypress.ecpp b/pages/keypress.ecpp index 16ddd4f..a2cbc86 100644 --- a/pages/keypress.ecpp +++ b/pages/keypress.ecpp @@ -8,14 +8,14 @@ using namespace vdrlive; <%args> - int keycode = kNone; + int keycode = kNone; <%session scope="global"> bool logged_in(false); <%cpp> - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - reply.setContentType("application/xml"); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + reply.setContentType("application/xml"); diff --git a/pages/login.ecpp b/pages/login.ecpp index d380066..da7fd79 100644 --- a/pages/login.ecpp +++ b/pages/login.ecpp @@ -19,15 +19,15 @@ bool logged_in(false); std::string message; if (action == "login") { - if (Users.ValidLogin(login, password)) { - logged_in = true; - cUsers::logged_in_user = login; - } else { - message = tr("Wrong username or password"); - } + if (Users.ValidLogin(login, password)) { + logged_in = true; + cUsers::logged_in_user = login; + } else { + message = tr("Wrong username or password"); + } } else if (action == "logout") { - logged_in = false; - cUsers::logged_in_user = ""; + logged_in = false; + cUsers::logged_in_user = ""; } LiveSetup().CheckLocalNet(request.getPeerIp()); @@ -37,36 +37,36 @@ if (logged_in || !LiveSetup().UseAuth()) return reply.redirect(LiveSetup().GetSt }> <& pageelems.doc_type &> - - - VDR-Live - <$ tr("Login") $> - <& pageelems.stylesheets &> - <& pageelems.ajax_js &> - - -
-
<$ tr("VDR Live Login") $>
-
- " alt="VDR Live" /> -
- - - - - - - - - - - - - -
-
- <$ message $> -
-
-
- + + + VDR-Live - <$ tr("Login") $> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> + + +
+
<$ tr("VDR Live Login") $>
+
+ " alt="VDR Live" /> +
+ + + + + + + + + + + + + +
+
+ <$ message $> +
+
+
+ diff --git a/pages/menu.ecpp b/pages/menu.ecpp index 0d21e33..01cac9e 100644 --- a/pages/menu.ecpp +++ b/pages/menu.ecpp @@ -28,7 +28,7 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); set_active = active; if (!component.empty()) { - set_component = component; + set_component = component; } @@ -66,16 +66,16 @@ if (LiveSetup().UseAuth()) { <%cpp> } - | >? + | >?
">
-
- <$ tr("Your attention is required") $>: - <$ timerNotifier.Message() $> - <$ tr("React") $> +
+ <$ tr("Your attention is required") $>: + <$ timerNotifier.Message() $> + <$ tr("React") $> ">| - <$ tr("Dismiss") $> + <$ tr("Dismiss") $>
@@ -85,24 +85,24 @@ if (!component.empty()) { diff --git a/pages/multischedule.ecpp b/pages/multischedule.ecpp index 197d933..877df23 100644 --- a/pages/multischedule.ecpp +++ b/pages/multischedule.ecpp @@ -9,61 +9,61 @@ using namespace vdrlive; enum class tState { - None, - Inactive, - Active, - Recording + None, + Inactive, + Active, + Recording }; struct SchedEntry { - std::string title; - std::string short_description; - std::string description; - std::string description_trunc; - std::string start; - std::string end; - std::string day; - std::string epgid; - bool truncated; - tState timer; - int start_row; - int row_count; + std::string title; + std::string short_description; + std::string description; + std::string description_trunc; + std::string start; + std::string end; + std::string day; + std::string epgid; + bool truncated; + tState timer; + int start_row; + int row_count; - static SchedEntry DummyEntry(int start_row, int row_count) { - SchedEntry en; - en.start_row = start_row; - en.row_count = row_count; - // no title and no start time = dummy event - en.title = ""; - en.start = ""; - return en; - } + static SchedEntry DummyEntry(int start_row, int row_count) { + SchedEntry en; + en.start_row = start_row; + en.row_count = row_count; + // no title and no start time = dummy event + en.title = ""; + en.start = ""; + return en; + } }; -std::string channel_groups_setting; -std::vector channel_groups_names; -std::vector< std::vector > channel_groups_numbers; -std::vector times_names; -std::vector times_start; +std::string channel_groups_setting; +std::vector channel_groups_names; +std::vector< std::vector > channel_groups_numbers; +std::vector times_names; +std::vector times_start; <%args> - int channel = -1; - unsigned int time_para = 0; + int channel = -1; + unsigned int time_para = 0; <%session scope="global"> - bool logged_in(false); + bool logged_in(false); <%request scope="global"> - unsigned int channel_group=0; - unsigned int time_selected=0; - cString prev; - cString next; + unsigned int channel_group=0; + unsigned int time_selected=0; + cString prev; + cString next; <%include>page_init.eh <%cpp> reply.setHeader (tnt::httpheader::cacheControl, "no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate", true); - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - pageTitle = tr("MultiSchedule"); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + pageTitle = tr("MultiSchedule"); #define MAX_CHANNELS 10 #define MAX_DAYS 3 @@ -366,112 +366,112 @@ std::vector times_start; continue; } for (const cEvent *Event = Schedule->Events()->First(); Event; - Event = Schedule->Events()->Next(Event) ) - { - if (Event->EndTime() <= sched_start ) - continue; - if (Event->StartTime() >= sched_end ) - continue; + Event = Schedule->Events()->Next(Event) ) + { + if (Event->EndTime() <= sched_start ) + continue; + if (Event->StartTime() >= sched_end ) + continue; - EpgInfoPtr epgEvent = EpgEvents::CreateEpgInfo(Channel, Event); - if ( prev_row < 0 && Event->StartTime() > sched_start + MINUTES_PER_ROW ) - { - // insert dummy event at start - table[ j ].push_back( SchedEntry() ); - SchedEntry &en=table[ j ].back(); - int event_start_row = (Event->StartTime() - sched_start) / 60 / MINUTES_PER_ROW; - en.start_row = 0; - en.row_count = event_start_row; - if ( en.row_count < 1 ) - en.row_count = 1; - // no title and no start time = dummy event - en.title = ""; - en.start = ""; - prev_row = en.start_row + en.row_count; - } - table[ j ].push_back( SchedEntry() ); - SchedEntry &en=table[j].back(); + EpgInfoPtr epgEvent = EpgEvents::CreateEpgInfo(Channel, Event); + if ( prev_row < 0 && Event->StartTime() > sched_start + MINUTES_PER_ROW ) + { + // insert dummy event at start + table[ j ].push_back( SchedEntry() ); + SchedEntry &en=table[ j ].back(); + int event_start_row = (Event->StartTime() - sched_start) / 60 / MINUTES_PER_ROW; + en.start_row = 0; + en.row_count = event_start_row; + if ( en.row_count < 1 ) + en.row_count = 1; + // no title and no start time = dummy event + en.title = ""; + en.start = ""; + prev_row = en.start_row + en.row_count; + } + table[ j ].push_back( SchedEntry() ); + SchedEntry &en=table[j].back(); - en.title = epgEvent->Title(); - en.short_description = epgEvent->ShortDescr(); - en.description = epgEvent->LongDescr(); - en.start = epgEvent->StartTime(tr("%I:%M %p")); - en.end = epgEvent->EndTime(tr("%I:%M %p")); - en.day = epgEvent->StartTime(tr("%A, %b %d %Y")); - en.epgid = EpgEvents::EncodeDomId(Channel->GetChannelID(), Event->EventID()); - const cTimer* timer = LiveTimerManager().GetTimer(Event->EventID(), Channel->GetChannelID()); - if (!timer) - en.timer = tState::None; - else if (timer->Recording()) - en.timer = tState::Recording; - else if (timer->Flags() & tfActive) - en.timer = tState::Active; - else - en.timer = tState::Inactive; + en.title = epgEvent->Title(); + en.short_description = epgEvent->ShortDescr(); + en.description = epgEvent->LongDescr(); + en.start = epgEvent->StartTime(tr("%I:%M %p")); + en.end = epgEvent->EndTime(tr("%I:%M %p")); + en.day = epgEvent->StartTime(tr("%A, %b %d %Y")); + en.epgid = EpgEvents::EncodeDomId(Channel->GetChannelID(), Event->EventID()); + const cTimer* timer = LiveTimerManager().GetTimer(Event->EventID(), Channel->GetChannelID()); + if (!timer) + en.timer = tState::None; + else if (timer->Recording()) + en.timer = tState::Recording; + else if (timer->Flags() & tfActive) + en.timer = tState::Active; + else + en.timer = tState::Inactive; - en.start_row = prev_row > 0 ? prev_row : 0; - int end_time = Schedule->Events()->Next(Event) ? - Schedule->Events()->Next(Event)->StartTime() : - Event->EndTime(); - if (end_time > sched_end) - end_time = sched_end; - int next_event_start_row = (end_time - sched_start) / 60 / MINUTES_PER_ROW; - en.row_count = next_event_start_row - en.start_row; - if ( en.row_count < 1 ) - en.row_count = 1; - prev_row = en.start_row + en.row_count; + en.start_row = prev_row > 0 ? prev_row : 0; + int end_time = Schedule->Events()->Next(Event) ? + Schedule->Events()->Next(Event)->StartTime() : + Event->EndTime(); + if (end_time > sched_end) + end_time = sched_end; + int next_event_start_row = (end_time - sched_start) / 60 / MINUTES_PER_ROW; + en.row_count = next_event_start_row - en.start_row; + if ( en.row_count < 1 ) + en.row_count = 1; + prev_row = en.start_row + en.row_count; - // truncate description if too long - en.truncated=false; - en.description_trunc=StringWordTruncate( en.description, - CHARACTERS_PER_ROW*(en.row_count-2), - en.truncated ); + // truncate description if too long + en.truncated=false; + en.description_trunc=StringWordTruncate( en.description, + CHARACTERS_PER_ROW*(en.row_count-2), + en.truncated ); - }; - if ( table[ j ].begin() == table[ j ].end() ) - { - // no entries... create a single dummy entry - table[ j ].push_back( SchedEntry() ); - SchedEntry &en=table[ j ].back(); - en.start_row = 0; - en.row_count = sched_end_row; - // no title and no start time = dummy event - en.title = ""; - en.start = ""; - } - } + }; + if ( table[ j ].begin() == table[ j ].end() ) + { + // no entries... create a single dummy entry + table[ j ].push_back( SchedEntry() ); + SchedEntry &en=table[ j ].back(); + en.start_row = 0; + en.row_count = sched_end_row; + // no title and no start time = dummy event + en.title = ""; + en.start = ""; + } + } - +
<%cpp> - - - + + + <%cpp> for ( unsigned int channel = 0; channel< channel_names.size() ; channel++) { - - + <%cpp> } - + <%cpp> bool odd=true; std::list::iterator cur_event[ MAX_CHANNELS ]; for (int i=0;i times_start; row_class += odd ? " odd " : " even "; - - + + <%cpp> for ( unsigned int channel = 0; channel< channel_names.size() ; channel++) { // output spacer column - + <%cpp> if ( cur_event[channel] == table[channel].end() || cur_event[channel]->start_row != row ) - { + { // no new event in this channel, skip it - SchedEntry &en=*(--table[channel].end()); - if ( row == 0 || en.start_row + en.row_count == row) { + SchedEntry &en=*(--table[channel].end()); + if ( row == 0 || en.start_row + en.row_count == row) { - + <%cpp> - } + } continue; - } + } SchedEntry &en=*cur_event[channel]; if (en.title.empty() && en.start.empty() ) { // empty dummy event - <%cpp> - ++cur_event[channel]; + ++cur_event[channel]; continue; } @@ -557,11 +557,11 @@ std::vector times_start; } else { " width="16" height="16"><%cpp> } - if (LiveSetup().GetShowIMDb() ) { + if (LiveSetup().GetShowIMDb() ) { <& pageelems.imdb_info_href title=(en.title) &> - <%cpp> } + <%cpp> }
<$ en.start $>
-
<$ en.title $>
+
<$ en.title $>
<%cpp> if ( en.row_count>2 && !en.short_description.empty() ) { @@ -592,13 +592,13 @@ std::vector times_start; ++cur_event[channel]; } -
+ <%cpp> - } + } -
<$ tr("Time") $>
 
<$ tr("Time") $>
 
<$ channel_names[channel] $> <# reply.sout() automatically escapes special characters to html entities #> +
<$ channel_names[channel] $> <# reply.sout() automatically escapes special characters to html entities #> % if (cDevice::PrimaryDevice() && cDevice::PrimaryDevice()->HasDecoder() ) { <& pageelems.ajax_action_href action="switch_channel" tip=(tr("Switch to this channel.")) param=(channel_IDs[channel]) image="zap.png" alt="" &> % } <& pageelems.hls_channel channelId=(channel_IDs[channel]) &> <& pageelems.m3u_playlist_channel channelId=(channel_IDs[channel]) &>
   
time leftcol rightcol <$ row_class $>"> +
time leftcol rightcol <$ row_class $>"> <%cpp> - if ( minutes < MINUTES_PER_ROW ) - { + if ( minutes < MINUTES_PER_ROW ) + { - <$ cToSvDateTime( tr("%I:%M %p"), sched_start + row * 60 * MINUTES_PER_ROW ) $> + <$ cToSvDateTime( tr("%I:%M %p"), sched_start + row * 60 * MINUTES_PER_ROW ) $> <%cpp> - } - else - { + } + else + { -   +   <%cpp> - } + } -     +
-
event topaligned leftcol rightcol" rowspan="<$ en.row_count $>"> + event topaligned leftcol rightcol" rowspan="<$ en.row_count $>">
-
- + + + <%include>page_exit.eh @@ -607,27 +607,27 @@ std::vector times_start; diff --git a/pages/page_exit.eh b/pages/page_exit.eh index fb83055..c61adf4 100644 --- a/pages/page_exit.eh +++ b/pages/page_exit.eh @@ -3,11 +3,11 @@ #include <%cpp> - spoint.commit(); + spoint.commit(); } catch ( vdrlive::HtmlError const& ex ) { - tnt::QueryParams param = qparam; - param.add( "pageTitle", pageTitle ); - param.add( "errorMessage", ex.what() ); - callComp( "error", request, reply, param ); + tnt::QueryParams param = qparam; + param.add( "pageTitle", pageTitle ); + param.add( "errorMessage", ex.what() ); + callComp( "error", request, reply, param ); } diff --git a/pages/page_init.eh b/pages/page_init.eh index b8311c7..b6cbaf7 100644 --- a/pages/page_init.eh +++ b/pages/page_init.eh @@ -10,6 +10,6 @@ std::string pageTitle; <%cpp> try { - reply.setHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT"); - tnt::Savepoint spoint( reply ); + reply.setHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT"); + tnt::Savepoint spoint( reply ); diff --git a/pages/pageelems.ecpp b/pages/pageelems.ecpp index b73cd43..f08a6d4 100644 --- a/pages/pageelems.ecpp +++ b/pages/pageelems.ecpp @@ -287,22 +287,22 @@ function existingRecordingString(col_span, bottomrow, id, archiveDescr, imdb_id,
<%cpp> - if (LiveSetup().GetShowLogo() || LiveSetup().GetShowInfoBox()) { + if (LiveSetup().GetShowLogo() || LiveSetup().GetShowInfoBox()) {
<%cpp> - } + } @@ -310,7 +310,7 @@ function existingRecordingString(col_span, bottomrow, id, archiveDescr, imdb_id, <%def hide_element> <%args> - int hide = 1; + int hide = 1; <%cpp> if (hide) { style="visibility: hidden"<%cpp> } @@ -319,14 +319,14 @@ function existingRecordingString(col_span, bottomrow, id, archiveDescr, imdb_id, <%def progressbar> <%args> - int progress = 0; - std::string id; - int duration = -1; // invalid duration as default + int progress = 0; + std::string id; + int duration = -1; // invalid duration as default <%cpp> - std::string cls("__progress"); - if ((duration >= 0) && ((progress < 0) || (duration == 0))) - cls +="_invisible"; + std::string cls("__progress"); + if ((duration >= 0) && ((progress < 0) || (duration == 0))) + cls +="_invisible";
if (!id.empty()) { id="<$ id $>" <%cpp> } style="width: <$ progress $>%">
@@ -335,12 +335,12 @@ function existingRecordingString(col_span, bottomrow, id, archiveDescr, imdb_id, <%def ajax_action_href> <%args> - std::string action; - std::string tip; - std::string param; - std::string image; - std::string alt; - std::string id; + std::string action; + std::string tip; + std::string param; + std::string image; + std::string alt; + std::string id; <%cpp> { if (!id.empty()) { id="<$ id $>" <%cpp> } <& hide_element hide=(id.empty()? 0 : 1) &> href="vdr_request/<$ action $>?param=<$ param $>" <%cpp>if (!tip.empty()) { <& tooltip.hint text=(tip) &> <%cpp> } >" alt="<$ alt $>" /> <%cpp> } @@ -349,8 +349,8 @@ function existingRecordingString(col_span, bottomrow, id, archiveDescr, imdb_id, <%def imdb_info_href> <%args> - std::string title; - std::string s_IMDB_ID; + std::string title; + std::string s_IMDB_ID; <%cpp> // if (LiveSetup().GetShowIMDb()) @@ -367,8 +367,8 @@ if (s_IMDB_ID.empty() ) { <%def hls_channel> <%args> - std::string channelId; - std::string class_; + std::string channelId; + std::string class_; <%cpp> if (LiveSetup().GetUseStreamdev() && LiveFeatures().Loaded()) { @@ -383,8 +383,8 @@ if (LiveSetup().GetUseStreamdev() && LiveFeatures(). <%def hls_recording> <%args> - std::string recId; - std::string class_; + std::string recId; + std::string class_; <%cpp> if (LiveSetup().GetUseStreamdev() && LiveFeatures().Loaded()) { @@ -399,8 +399,8 @@ if (LiveSetup().GetUseStreamdev() && LiveFeatures(). <%def m3u_playlist_channel> <%args> - std::string channelId; - std::string class_; + std::string channelId; + std::string class_; <%cpp> if (LiveFeatures().Loaded()) { @@ -415,8 +415,8 @@ if (LiveFeatures().Loaded()) { <%def m3u_playlist_recording> <%args> - std::string recid; - std::string linkText; + std::string recid; + std::string linkText; <%cpp> #if TNT_WATCHDOG_SILENCE @@ -440,8 +440,8 @@ cToSvConcat url("playlist.m3u?recid=", recid); <%def stream_recording> <%args> - std::string recid; - std::string linkText; + std::string recid; + std::string linkText; <%cpp> #if TNT_WATCHDOG_SILENCE @@ -451,8 +451,8 @@ if (!recid.empty()) recording = LiveRecordingsManager()->GetByMd5Hash(recid); cToSvConcat rfid; if (recording) { struct stat st; - if (stat(recording->FileName(), &st) == 0) - rfid.appendFormated("%lu:%llu.rec", (unsigned long) st.st_dev, (unsigned long long) st.st_ino); + if (stat(recording->FileName(), &st) == 0) + rfid.appendFormated("%lu:%llu.rec", (unsigned long) st.st_dev, (unsigned long long) st.st_ino); } if (!rfid.empty() ) { " alt="" <& tooltip.hint text=(tr("Stream this recording.")) &> /> <$ linkText $> @@ -467,23 +467,23 @@ if (!rfid.empty() ) { <%def event_timer> <%args> - std::string epgid; + std::string epgid; <%cpp> - tChannelID channelid; - tEventID eventid; - EpgEvents::DecodeDomId(epgid, channelid, eventid); - const cTimer* timer = LiveTimerManager().GetTimer(eventid, channelid); - if (timer) { + tChannelID channelid; + tEventID eventid; + EpgEvents::DecodeDomId(epgid, channelid, eventid); + const cTimer* timer = LiveTimerManager().GetTimer(eventid, channelid); + if (timer) { - <& pageelems.edit_timer timerId=(LiveTimerManager().GetTimers().GetTimerId(*timer)) imgName=(timer->Recording() ? "recording_timer.gif" : (timer->Flags() & tfActive ? "record_timer.png" : "record_inactive_timer.png")) &> + <& pageelems.edit_timer timerId=(LiveTimerManager().GetTimers().GetTimerId(*timer)) imgName=(timer->Recording() ? "recording_timer.gif" : (timer->Flags() & tfActive ? "record_timer.png" : "record_inactive_timer.png")) &> <%cpp> - } - else { + } + else { - " alt="" <& tooltip.hint text=(tr("Record this")) &> /> + " alt="" <& tooltip.hint text=(tr("Record this")) &> /> <%cpp> - } + } @@ -491,50 +491,50 @@ if (!rfid.empty() ) { <%def edit_timer> <%args> - std::string timerId; - std::string imgName = "edit.png"; + std::string timerId; + std::string imgName = "edit.png"; - " alt="" <& tooltip.hint text=(tr("Edit timer")) &> /> + " alt="" <& tooltip.hint text=(tr("Edit timer")) &> /> <# ---------------------------------------------------------------------- #> <%def ajax_js> - - - - - - - -<%cpp> - if (LiveSetup().GetShowInfoBox()) { - - - -<%cpp> - } + + + + + + + +<%cpp> + if (LiveSetup().GetShowInfoBox()) { + + + +<%cpp> + } @@ -542,39 +542,39 @@ if (!rfid.empty() ) { <%def infobox>
-
-
-
<$ tr("retrieving status ...") $>
-
--:--
-
-
-
-
--:--
-
-
- - -
- <& ajax_action_href action=("switch_channel") id=("infobox_prevchan") image=("one_downarrow.png") tip=(tr("previous channel")) &> - <& ajax_action_href action=("switch_channel") id=("infobox_nextchan") image=("one_uparrow.png") tip=(tr("next channel")) &> -
-
- <& progressbar id=("infobox_elapsed") &> -
-
-
-
- <$ tr("No server response!") $> - <$ tr("Failed to update infobox!") $> -
+
+
+
<$ tr("retrieving status ...") $>
+
--:--
+
+
+
+
--:--
+
+
+ + +
+ <& ajax_action_href action=("switch_channel") id=("infobox_prevchan") image=("one_downarrow.png") tip=(tr("previous channel")) &> + <& ajax_action_href action=("switch_channel") id=("infobox_nextchan") image=("one_uparrow.png") tip=(tr("next channel")) &> +
+
+ <& progressbar id=("infobox_elapsed") &> +
+
+
+
+ <$ tr("No server response!") $> + <$ tr("Failed to update infobox!") $> +
@@ -582,41 +582,41 @@ if (!rfid.empty() ) { <%def epg_tool_box> <%args> - int detail; - std::string epgid; - std::string title; - time_t startTime; - time_t endTime; - int lastCurrentChanel = int(); + int detail; + std::string epgid; + std::string title; + time_t startTime; + time_t endTime; + int lastCurrentChanel = int(); std::string s_IMDB_ID; <%cpp> - int duration = EpgEvents::Duration(startTime, endTime); - int elapsed = EpgEvents::ElapsedTime(startTime, endTime); + int duration = EpgEvents::Duration(startTime, endTime); + int elapsed = EpgEvents::ElapsedTime(startTime, endTime); tEventID eventId = tEventID(); - tChannelID channelId = tChannelID(); + tChannelID channelId = tChannelID(); - EpgEvents::DecodeDomId(epgid, channelId, eventId); - if (detail) { // output for vertical toolbox + EpgEvents::DecodeDomId(epgid, channelId, eventId); + if (detail) { // output for vertical toolbox - <& pageelems.event_timer epgid=(epgid) &> + <& pageelems.event_timer epgid=(epgid) &> <%cpp> if (cDevice::PrimaryDevice() && cDevice::PrimaryDevice()->HasDecoder() ) { - <& pageelems.ajax_action_href action="switch_channel" tip=(tr("Switch to this channel.")) param=(channelId) image="zap.png" alt="" &> + <& pageelems.ajax_action_href action="switch_channel" tip=(tr("Switch to this channel.")) param=(channelId) image="zap.png" alt="" &> <%cpp> - } if (LiveFeatures().Recent() && eventId != 0) { + } if (LiveFeatures().Recent() && eventId != 0) { - " alt="" <& tooltip.hint text=(tr("Search for repeats.")) &> /> + " alt="" <& tooltip.hint text=(tr("Search for repeats.")) &> /> <%cpp> - } - if ((duration == 0) || (elapsed >= 0)) { + } + if ((duration == 0) || (elapsed >= 0)) { - <& pageelems.hls_channel channelId=(channelId) &> - <& pageelems.m3u_playlist_channel channelId=(channelId) &> + <& pageelems.hls_channel channelId=(channelId) &> + <& pageelems.m3u_playlist_channel channelId=(channelId) &> <%cpp> - } - if (eventId != 0) { + } + if (eventId != 0) { /* Need to lock here channels also, because CreateEpgInfo will lock * it also and this will result in a wrong lock order */ LOCK_CHANNELS_READ; @@ -631,21 +631,21 @@ if (!rfid.empty() ) { const char *sdhd = video_SD_HD == 0 ? "sd": video_SD_HD == 1 ? "hd": video_SD_HD == 2 ? "ud" : 0; - <& pageelems.imdb_info_href title=(title) s_IMDB_ID=(s_IMDB_ID) &> + <& pageelems.imdb_info_href title=(title) s_IMDB_ID=(s_IMDB_ID) &> % if (detail > 1) { <%cpp> if (sdhd) { - + <%cpp> - } - } - } - } - } - else { // table output + } + } + } + } + } + else { // table output "><& pageelems.event_timer epgid=(epgid) &> % if (cDevice::PrimaryDevice() && cDevice::PrimaryDevice()->HasDecoder() ) { @@ -681,29 +681,29 @@ if (!rfid.empty() ) { <%def epg_tt_box> <%args> - std::string boxId; - std::string caption; - std::string tools_comp; - std::string time; - std::string channel; - std::string title; - std::string short_descr; - std::string long_descr; - std::string filename; - std::string archived; - std::string epgImage; - uintptr_t ievent; - uintptr_t irecording; - uintptr_t iepgEvent; - int elapsed = -1; + std::string boxId; + std::string caption; + std::string tools_comp; + std::string time; + std::string channel; + std::string title; + std::string short_descr; + std::string long_descr; + std::string filename; + std::string archived; + std::string epgImage; + uintptr_t ievent; + uintptr_t irecording; + uintptr_t iepgEvent; + int elapsed = -1; std::string sort; std::string filter; std::string flat; int history_num_back = 0; -
-
-
+
+
+
<%cpp> @@ -808,28 +808,28 @@ if (scraperMovieOrTv.found) {
-
-
-
- <& (tools_comp) id=(boxId) archived=(archived) detail=(2) title=(title) s_IMDB_ID=(scraperMovieOrTv.IMDB_ID) sort=(sort) filter=(filter) flat=(flat) history_num_back=(history_num_back) &> -
-
-
-
+
+
+
+ <& (tools_comp) id=(boxId) archived=(archived) detail=(2) title=(title) s_IMDB_ID=(scraperMovieOrTv.IMDB_ID) sort=(sort) filter=(filter) flat=(flat) history_num_back=(history_num_back) &> +
+
+
+
<%cpp> if (epgEvent && epgEvent->EventDuration() >= 0) { // recording - "><$ FormatDuration(tr("%d:%02d"), epgEvent->Duration())$> / "><$FormatDuration(tr("%d:%02d"), epgEvent->EventDuration())$> + "><$ FormatDuration(tr("%d:%02d"), epgEvent->Duration())$> / "><$FormatDuration(tr("%d:%02d"), epgEvent->EventDuration())$> <%cpp> } if (elapsed >= 0) { -
<& pageelems.progressbar progress=(elapsed) &>
+
<& pageelems.progressbar progress=(elapsed) &>
<%cpp> } -
-
+
+
% if (!archived.empty()) { <$ (archived + " ") $> % } @@ -837,22 +837,22 @@ if (elapsed >= 0) { % if (!filename.empty() && !channel.empty()) {
<$ (channel) $>
% } -
-
<$ (title) $>
-
<$ (short_descr) $>
-
_description> - +
+
<$ (title) $>
+
<$ (short_descr) $>
+
_description> + <%cpp> - std::list images = EpgEvents::EpgImages(boxId); - for(std::list::iterator it = images.begin(); it != images.end(); ++it ) { + std::list images = EpgEvents::EpgImages(boxId); + for(std::list::iterator it = images.begin(); it != images.end(); ++it ) { - + % } bool scraperImage = false; % if(!epgImage.empty() ) { scraperImage = true; - + % } if (episodeFound && !scraperMovieOrTv.episode.episodeImage.path.empty() ) { scraperImage = true; @@ -860,7 +860,7 @@ if (elapsed >= 0) { <%cpp> } // episodeFound && !scraperMovieOrTv.episode.episodeImage.path.empty() - if (!scraperImage) { + if (!scraperImage) { std::list images1 = EpgEvents::RecImages(boxId, filename); size_t delimPos = boxId.find_last_of('_'); std::string recId = (delimPos)?boxId.substr(delimPos+1):boxId; @@ -868,13 +868,13 @@ if (elapsed >= 0) { for(std::list::iterator it = images1.begin(); it != images1.end(); ++it ) { - + <%cpp> } } - <# id = "<$ boxId $>_epg_image" class="epg_images" #> + <# id = "<$ boxId $>_epg_image" class="epg_images" #> <# ----------------- scraper data ----------------- #> <# ----------------- epg ----------------- #>
- <%cpp> reply.out() << StringEscapeAndBreak(long_descr); + <%cpp> reply.out() << StringEscapeAndBreak(long_descr); const char *br_after_long_desc = "

"; if (long_descr.empty()) br_after_long_desc = ""; const cEvent *event = nullptr; @@ -1155,10 +1155,10 @@ if (event) { } } -
-
-
-
+
+
+
+
@@ -1181,82 +1181,82 @@ for (const cTvMedia &media: *media_v) { <# ---------------------------------------------------------------------- #> <%def about_tt_box> -
-
-
<$ tr(LIVESUMMARY) $>
-
-
-
-
<$ tr("Authors") $>
-
<$ tr("Project Idea") $>:
-
Thomas Keil (Thomas)
-
<$ tr("Webserver") $>:
-
Sascha Volkenandt (LordJaxom)
-
<$ tr("Current Maintainer") $>:
-
Markus Ehrnsperger (MarkusE @ VDR Portal)
-
<$ tr("Previous Maintainer") $>:
-
Jasmin Jessich (jasminj)
-
<$ tr("Project leader") $>:
-
Dieter Hametner (tadi)
-
<$ tr("Content") $>:
-
Christian Wieninger (winni)
-
<$ tr("Graphics") $>:
-
Michael Brückner (skiller2k1)
-
<$ tr("Information") $>
-
<$ tr("LIVE version") $>:
-
<$ LIVEVERSION $><$ VERSION_SUFFIX $>
-
<$ tr("VDR version") $>:
-
<$ VDRVERSION $>
-
<$ tr("Features") $>
-
EPGsearch:
-
-% Features< features::epgsearch >& epgsearch = LiveFeatures< features::epgsearch >(); - "/> -% if ( epgsearch.Recent() ) { - <$ tr("active") $>: <$ epgsearch.Version() $> -% } else { - <$ tr("required") $>: <$ epgsearch.MinVersion() $> -% } - (<$ tr("Homepage") $>)
-
-
Streamdev server:
-
-<%cpp> - Features< features::streamdev_server >& streamdev = LiveFeatures< features::streamdev_server >(); - - "/> -<%cpp> - if ( streamdev.Loaded() ) { - - <$ tr("active") $>: <$ streamdev.Version() $> -<%cpp> - } else { - - <$ tr("required") $>: <$ streamdev.MinVersion() $> -<%cpp> - } - - (<$ tr("Homepage") $>)
-
-
tvscraper:
-
-% Features< features::tvscraper >& tvscraper = LiveFeatures< features::tvscraper >(); - "/> -% if ( tvscraper.Recent() ) { - <$ tr("active") $>: <$ tvscraper.Version() $> -% } else { - <$ tr("required") $>: <$ tvscraper.MinVersion() $> -% } - (<$ tr("Homepage") $>)
-
-
<$ tr("Information providers") $>
-
Movie information provided by TMDB. This product uses the TMDB API but is not endorsed or certified by TMDB.
-
Information provided by TheTVDB.com. Please consider supporting them.
-
<$ tr("Bugs and suggestions") $>
-
<$ tr("If you encounter any bugs or would like to suggest new features, please use our bugtracker") $>:
- https://github.com/MarkusEh/vdr-plugin-live/issues
-
 
-
-
-
+
+
+
<$ tr(LIVESUMMARY) $>
+
+
+
+
<$ tr("Authors") $>
+
<$ tr("Project Idea") $>:
+
Thomas Keil (Thomas)
+
<$ tr("Webserver") $>:
+
Sascha Volkenandt (LordJaxom)
+
<$ tr("Current Maintainer") $>:
+
Markus Ehrnsperger (MarkusE @ VDR Portal)
+
<$ tr("Previous Maintainer") $>:
+
Jasmin Jessich (jasminj)
+
<$ tr("Project leader") $>:
+
Dieter Hametner (tadi)
+
<$ tr("Content") $>:
+
Christian Wieninger (winni)
+
<$ tr("Graphics") $>:
+
Michael Brückner (skiller2k1)
+
<$ tr("Information") $>
+
<$ tr("LIVE version") $>:
+
<$ LIVEVERSION $><$ VERSION_SUFFIX $>
+
<$ tr("VDR version") $>:
+
<$ VDRVERSION $>
+
<$ tr("Features") $>
+
EPGsearch:
+
+% Features< features::epgsearch >& epgsearch = LiveFeatures< features::epgsearch >(); + "/> +% if ( epgsearch.Recent() ) { + <$ tr("active") $>: <$ epgsearch.Version() $> +% } else { + <$ tr("required") $>: <$ epgsearch.MinVersion() $> +% } + (<$ tr("Homepage") $>)
+
+
Streamdev server:
+
+<%cpp> + Features< features::streamdev_server >& streamdev = LiveFeatures< features::streamdev_server >(); + + "/> +<%cpp> + if ( streamdev.Loaded() ) { + + <$ tr("active") $>: <$ streamdev.Version() $> +<%cpp> + } else { + + <$ tr("required") $>: <$ streamdev.MinVersion() $> +<%cpp> + } + + (<$ tr("Homepage") $>)
+
+
tvscraper:
+
+% Features< features::tvscraper >& tvscraper = LiveFeatures< features::tvscraper >(); + "/> +% if ( tvscraper.Recent() ) { + <$ tr("active") $>: <$ tvscraper.Version() $> +% } else { + <$ tr("required") $>: <$ tvscraper.MinVersion() $> +% } + (<$ tr("Homepage") $>)
+
+
<$ tr("Information providers") $>
+
Movie information provided by TMDB. This product uses the TMDB API but is not endorsed or certified by TMDB.
+
Information provided by TheTVDB.com. Please consider supporting them.
+
<$ tr("Bugs and suggestions") $>
+
<$ tr("If you encounter any bugs or would like to suggest new features, please use our bugtracker") $>:
+ https://github.com/MarkusEh/vdr-plugin-live/issues
+
 
+
+
+
diff --git a/pages/pause_recording.ecpp b/pages/pause_recording.ecpp index 1771fa8..9345509 100644 --- a/pages/pause_recording.ecpp +++ b/pages/pause_recording.ecpp @@ -7,16 +7,16 @@ using namespace vdrlive; <%args> - std::string param; + std::string param; <%session scope="global"> - bool logged_in(false); + bool logged_in(false); <%cpp> - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - reply.setContentType( "application/xml" ); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + reply.setContentType( "application/xml" ); - PauseRecordingTask task( param ); - LiveTaskManager().Execute( task ); + PauseRecordingTask task( param ); + LiveTaskManager().Execute( task ); <& xmlresponse.ajax name=("pause_recording") pname=("recording") value=(param) result=(task.Result()) error=(task.Error()) &> diff --git a/pages/play_recording.ecpp b/pages/play_recording.ecpp index 2bb2ddd..4e76f4e 100644 --- a/pages/play_recording.ecpp +++ b/pages/play_recording.ecpp @@ -9,18 +9,18 @@ using namespace vdrlive; <%args> - std::string param; + std::string param; <%session scope="global"> - bool logged_in(false); + bool logged_in(false); <%cpp> - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - if (!cUser::CurrentUserHasRightTo(UR_STARTREPLAY)) - throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); - reply.setContentType( "application/xml" ); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + if (!cUser::CurrentUserHasRightTo(UR_STARTREPLAY)) + throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); + reply.setContentType( "application/xml" ); - PlayRecordingTask task( param ); - LiveTaskManager().Execute( task ); + PlayRecordingTask task( param ); + LiveTaskManager().Execute( task ); <& xmlresponse.ajax name=("play_recording") pname=("recording") value=(param) result=(task.Result()) error=(task.Error()) &> diff --git a/pages/playlist.ecpp b/pages/playlist.ecpp index d69e49f..e29a34d 100644 --- a/pages/playlist.ecpp +++ b/pages/playlist.ecpp @@ -10,40 +10,40 @@ using namespace vdrlive; <%args> - std::string channelid; - std::string recid; + std::string channelid; + std::string recid; <%session scope="global"> - bool logged_in(false); + bool logged_in(false); <%request scope="page"> - cChannel* Channel; + cChannel* Channel; <%include>page_init.eh <%cpp> - tChannelID channel = tChannelID::FromString(channelid.c_str()); + tChannelID channel = tChannelID::FromString(channelid.c_str()); - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - if (!cUser::CurrentUserHasRightTo(UR_STARTREPLAY)) - throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + if (!cUser::CurrentUserHasRightTo(UR_STARTREPLAY)) + throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); // the availabilty of Channel signals that we will do live TV streaming. - Channel = 0; - if (recid.empty()) { - LOCK_CHANNELS_READ; - Channel = (cChannel *)Channels->GetByChannelID(channel); - if (Channel == 0) { - throw HtmlError( tr("Couldn't find channel or no channels available. Maybe you mistyped your request?") ); - } - } - std::string server = request.getHost(); - server = server.substr(0, server.rfind(':')); - std::string videourl; - reply.setContentType("audio/x-mpegurl"); - if (Channel != 0) { - videourl = concat("#EXTM3U\n#EXTINF:-1,", Channel->Name(), "\nhttp://", server, ":", cToSvInt(LiveSetup().GetStreamdevPort()), "/", LiveSetup().GetStreamdevType(), "/", *Channel->GetChannelID().ToString()); - } - else { + Channel = 0; + if (recid.empty()) { + LOCK_CHANNELS_READ; + Channel = (cChannel *)Channels->GetByChannelID(channel); + if (Channel == 0) { + throw HtmlError( tr("Couldn't find channel or no channels available. Maybe you mistyped your request?") ); + } + } + std::string server = request.getHost(); + server = server.substr(0, server.rfind(':')); + std::string videourl; + reply.setContentType("audio/x-mpegurl"); + if (Channel != 0) { + videourl = concat("#EXTM3U\n#EXTINF:-1,", Channel->Name(), "\nhttp://", server, ":", cToSvInt(LiveSetup().GetStreamdevPort()), "/", LiveSetup().GetStreamdevType(), "/", *Channel->GetChannelID().ToString()); + } + else { const cRecording* recording = LiveRecordingsManager()->GetByMd5Hash(recid); cToSvConcat rfid; if (LiveFeatures().Loaded()) { @@ -58,14 +58,14 @@ using namespace vdrlive; videourl = concat("#EXTM3U\n#EXTINF:-1,", recording?recording->Name():"recording not found", "\nhttp://", server, ":", cToSvInt(LiveSetup().GetServerPort()), "/recstream.html?recid=", recid); else videourl = concat("#EXTM3U\n#EXTINF:-1,", recording?recording->Name():"recording not found", "\nhttp://", server, ":", cToSvInt(LiveSetup().GetStreamdevPort()), "/", LiveSetup().GetStreamdevType(), "/", rfid, ".ts"); - } + } <& playlist.m3u videourl=(videourl) &> <%include>page_exit.eh <%def m3u> <%args> - std::string videourl; + std::string videourl; <$ videourl $> diff --git a/pages/recordings.ecpp b/pages/recordings.ecpp index 5a3f7a1..0af6352 100644 --- a/pages/recordings.ecpp +++ b/pages/recordings.ecpp @@ -23,24 +23,24 @@ using namespace vdrlive; <%args> - std::string sort; - std::string todel; - std::string diskinfo; - std::string filter; - std::string deletions[]; - std::string flat; + std::string sort; + std::string todel; + std::string diskinfo; + std::string filter; + std::string deletions[]; + std::string flat; int history_num_back = 0; <%session scope="global"> - bool logged_in(false); + bool logged_in(false); <# scope="page" should be enough but does not work with tntnet 3.0 #> <%request scope="global"> - std::string currentSort; - std::string deleteResult; - std::string currentFilter; - std::string currentFlat; + std::string currentSort; + std::string deleteResult; + std::string currentFilter; + std::string currentFlat; <%include>page_init.eh @@ -334,10 +334,10 @@ if (!deleteResult.empty()) { <& recordings.recordings_item iRecItem=(iRecItemRoot) irecording_item=(irecording_item) iRecordingsTree=(iRecordingsTree) iOpenTreeNodes=(iOpenTreeNodes) iAvailable_recs=(iAvailable_recs) &>
- - - - + + + + + diff --git a/pages/searchtimers.ecpp b/pages/searchtimers.ecpp index 9a10895..b85a363 100644 --- a/pages/searchtimers.ecpp +++ b/pages/searchtimers.ecpp @@ -8,9 +8,9 @@ using namespace vdrlive; <%args> - // input parameters - std::string searchtimerid; - std::string action; + // input parameters + std::string searchtimerid; + std::string action; <%session scope="global"> bool logged_in(false); @@ -20,49 +20,49 @@ bool logged_in(false); if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); <%cpp> - pageTitle = tr("Search timers"); - SearchTimers timers; - if ( !searchtimerid.empty() ) { - if (action == "toggle") - timers.ToggleActive(searchtimerid); - if (action == "delete") { - if (!cUser::CurrentUserHasRightTo(UR_DELSTIMERS)) - throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); - timers.Delete(searchtimerid); - } - } - if (action == "update") - timers.TriggerUpdate(); + pageTitle = tr("Search timers"); + SearchTimers timers; + if ( !searchtimerid.empty() ) { + if (action == "toggle") + timers.ToggleActive(searchtimerid); + if (action == "delete") { + if (!cUser::CurrentUserHasRightTo(UR_DELSTIMERS)) + throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); + timers.Delete(searchtimerid); + } + } + if (action == "update") + timers.TriggerUpdate(); <& pageelems.doc_type &> - + - VDR-Live - <$ pageTitle $> - <& pageelems.stylesheets &> - <& pageelems.ajax_js &> - - - <& pageelems.logo &> - <& menu active=("searchtimers") component=("searchtimers.searchtimer_actions")> -
- - - - - - - - - - + VDR-Live - <$ pageTitle $> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> + + + <& pageelems.logo &> + <& menu active=("searchtimers") component=("searchtimers.searchtimer_actions")> +
+
-
<$ pageTitle $>
-
<$ tr("Expression") $>
<$ tr("Channel") $>
<$ tr("Starts between") $>
-
+ + + + + + + + + <%cpp> - for (SearchTimers::iterator timer = timers.begin(); timer != timers.end(); ++timer) { - SearchTimers::iterator nextTimer = timer; ++nextTimer; - bool bottom = (nextTimer == timers.end()); + for (SearchTimers::iterator timer = timers.begin(); timer != timers.end(); ++timer) { + SearchTimers::iterator nextTimer = timer; ++nextTimer; + bool bottom = (nextTimer == timers.end()); int i = std::abs(timer->Id() ); char timerID_b[21]; // unsigned int 64: max. 20. (18446744073709551615) signed int64: max. 19 (+ sign) char *timerID = timerID_b+20; @@ -71,25 +71,25 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); else for (; i; i /= 10) *(--timerID) = '0' + (i%10); - - - - - - - - - - + + + + + + + + + + <%cpp> - } + } - - -
+
<$ pageTitle $>
+
<$ tr("Expression") $>
<$ tr("Channel") $>
<$ tr("Starts between") $>
+
"><%cpp> if(timer->UseAsSearchTimer()) { " alt="" /><%cpp> } ">
<$ timer->Search() $>
">
<$ timer->ChannelText() $>
">
UseTime() ? timer->StartTimeFormatted()+" - "+timer->StopTimeFormatted() ?>
">UseAsSearchTimer() ? "active.png" : "inactive.png") $>" alt="<$ tr("Toggle search timer actions (in)active") $>" <& tooltip.hint text=(tr("Toggle search timer actions (in)active")) &> />">" alt="<$ tr("Browse search timer results") $>" <& tooltip.hint text=(tr("Browse search timer results")) &> />">" alt="<$ tr("Edit search timer") $>" <& tooltip.hint text=(tr("Edit search timer")) &> />">')">" alt="<$ tr("Delete search timer") $>" <& tooltip.hint text=(tr("Delete search timer")) &> />
"><%cpp> if(timer->UseAsSearchTimer()) { " alt="" /><%cpp> } ">
<$ timer->Search() $>
">
<$ timer->ChannelText() $>
">
UseTime() ? timer->StartTimeFormatted()+" - "+timer->StopTimeFormatted() ?>
">UseAsSearchTimer() ? "active.png" : "inactive.png") $>" alt="<$ tr("Toggle search timer actions (in)active") $>" <& tooltip.hint text=(tr("Toggle search timer actions (in)active")) &> />">" alt="<$ tr("Browse search timer results") $>" <& tooltip.hint text=(tr("Browse search timer results")) &> />">" alt="<$ tr("Edit search timer") $>" <& tooltip.hint text=(tr("Edit search timer")) &> />">')">" alt="<$ tr("Delete search timer") $>" <& tooltip.hint text=(tr("Delete search timer")) &> />
-
-
- + + + + +
+ <%include>page_exit.eh diff --git a/pages/setup.ecpp b/pages/setup.ecpp index 1440094..bfa09aa 100644 --- a/pages/setup.ecpp +++ b/pages/setup.ecpp @@ -11,194 +11,194 @@ using namespace vdrlive; <%args> - std::string lastchannel; - bool useauth = false; - std::string login; - std::string pass; - std::string times; - std::string channelGroups; - std::string scheduleDuration; - std::string startscreen; - std::string theme; - std::string localnetmask; - std::string showLogo; - std::string showInfoBox; - std::string useStreamdev; - std::string markNewRec; - std::string showIMDb; - std::string showPlayMediaplayer; - std::string showChannelsWithoutEPG; - std::string streamdevport; - std::string streamdevtype; - int authchanged = 0; + std::string lastchannel; + bool useauth = false; + std::string login; + std::string pass; + std::string times; + std::string channelGroups; + std::string scheduleDuration; + std::string startscreen; + std::string theme; + std::string localnetmask; + std::string showLogo; + std::string showInfoBox; + std::string useStreamdev; + std::string markNewRec; + std::string showIMDb; + std::string showPlayMediaplayer; + std::string showChannelsWithoutEPG; + std::string streamdevport; + std::string streamdevtype; + int authchanged = 0; <%session scope="global"> - bool logged_in(false); + bool logged_in(false); <%include>page_init.eh <%cpp> if (!logged_in && LiveSetup().UseAuth() ) return reply.redirect("login.html"); if (!cUser::CurrentUserHasRightTo(UR_EDITSETUP)) - throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); + throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); #define SELECTIF(x) reply.out() << ( (x) ? "selected=\"selected\"" : "" ); #define CHECKIF(x) reply.out() << ( (x) ? " checked=\"checked\"" : "" ); - std::string message; + std::string message; - if ( request.getMethod() == "POST") { - if (authchanged && useauth && (login.empty() || pass.empty())) - message = tr("Please set login and password!"); - else - { - LiveSetup().SetLastChannel(lastchannel != "" ? parse_int(lastchannel):0); - LiveSetup().SetUseAuth(useauth); - if (useauth) { - LiveSetup().SetAdminLogin(login); - if (pass != "") - LiveSetup().SetAdminPassword(pass); - LiveSetup().SetLocalNetMask(localnetmask); - LiveSetup().CheckLocalNet(request.getPeerIp()); - } - LiveSetup().SetTimes(times); - LiveSetup().SetChannelGroups(channelGroups); - LiveSetup().SetScheduleDuration(scheduleDuration); - LiveSetup().SetStartScreen(startscreen); - LiveSetup().SetTheme(theme); - LiveSetup().SetShowLogo(!showLogo.empty()); - LiveSetup().SetShowInfoBox(!showInfoBox.empty()); - LiveSetup().SetUseStreamdev(!useStreamdev.empty()); - LiveSetup().SetStreamdevPort(streamdevport.empty() ? 3000 : parse_int(streamdevport)); - LiveSetup().SetStreamdevType(streamdevtype.empty() ? "PES" : streamdevtype); - LiveSetup().SetMarkNewRec(!markNewRec.empty()); + if ( request.getMethod() == "POST") { + if (authchanged && useauth && (login.empty() || pass.empty())) + message = tr("Please set login and password!"); + else + { + LiveSetup().SetLastChannel(lastchannel != "" ? parse_int(lastchannel):0); + LiveSetup().SetUseAuth(useauth); + if (useauth) { + LiveSetup().SetAdminLogin(login); + if (pass != "") + LiveSetup().SetAdminPassword(pass); + LiveSetup().SetLocalNetMask(localnetmask); + LiveSetup().CheckLocalNet(request.getPeerIp()); + } + LiveSetup().SetTimes(times); + LiveSetup().SetChannelGroups(channelGroups); + LiveSetup().SetScheduleDuration(scheduleDuration); + LiveSetup().SetStartScreen(startscreen); + LiveSetup().SetTheme(theme); + LiveSetup().SetShowLogo(!showLogo.empty()); + LiveSetup().SetShowInfoBox(!showInfoBox.empty()); + LiveSetup().SetUseStreamdev(!useStreamdev.empty()); + LiveSetup().SetStreamdevPort(streamdevport.empty() ? 3000 : parse_int(streamdevport)); + LiveSetup().SetStreamdevType(streamdevtype.empty() ? "PES" : streamdevtype); + LiveSetup().SetMarkNewRec(!markNewRec.empty()); - LiveSetup().SetShowIMDb(!showIMDb.empty()); - LiveSetup().SetShowPlayMediaplayer(!showPlayMediaplayer.empty()); - LiveSetup().SetShowChannelsWithoutEPG(!showChannelsWithoutEPG.empty()); - LiveSetup().SaveSetup(); + LiveSetup().SetShowIMDb(!showIMDb.empty()); + LiveSetup().SetShowPlayMediaplayer(!showPlayMediaplayer.empty()); + LiveSetup().SetShowChannelsWithoutEPG(!showChannelsWithoutEPG.empty()); + LiveSetup().SaveSetup(); - message = tr("Setup saved."); - } - } - pageTitle = tr("Setup"); - int ilastchannel = LiveSetup().GetLastChannel(); - if (ilastchannel == std::numeric_limits< int >::max()) - lastchannel = ""; - else - lastchannel = std::string(cToSvInt(ilastchannel)); + message = tr("Setup saved."); + } + } + pageTitle = tr("Setup"); + int ilastchannel = LiveSetup().GetLastChannel(); + if (ilastchannel == std::numeric_limits< int >::max()) + lastchannel = ""; + else + lastchannel = std::string(cToSvInt(ilastchannel)); - login = LiveSetup().GetAdminLogin(); - useauth = LiveSetup().GetUseAuth(); - times = LiveSetup().GetTimes(); - channelGroups = LiveSetup().GetChannelGroups(); - scheduleDuration = LiveSetup().GetScheduleDuration(); - startscreen = LiveSetup().GetStartScreen(); - theme = LiveSetup().GetTheme(); - localnetmask = LiveSetup().GetLocalNetMask(); - showLogo = LiveSetup().GetShowLogo() ? "1" : ""; - showInfoBox = LiveSetup().GetShowInfoBox() ? "1" : ""; - useStreamdev = LiveSetup().GetUseStreamdev() ? "1" : ""; - streamdevport = std::string(cToSvInt(LiveSetup().GetStreamdevPort())); - streamdevtype = LiveSetup().GetStreamdevType(); - markNewRec = LiveSetup().GetMarkNewRec() ? "1" : ""; - showIMDb = LiveSetup().GetShowIMDb() ? "1" : ""; - showPlayMediaplayer = LiveSetup().GetShowPlayMediaplayer() ? "1" : ""; - showChannelsWithoutEPG = LiveSetup().GetShowChannelsWithoutEPG() ? "1" : ""; + login = LiveSetup().GetAdminLogin(); + useauth = LiveSetup().GetUseAuth(); + times = LiveSetup().GetTimes(); + channelGroups = LiveSetup().GetChannelGroups(); + scheduleDuration = LiveSetup().GetScheduleDuration(); + startscreen = LiveSetup().GetStartScreen(); + theme = LiveSetup().GetTheme(); + localnetmask = LiveSetup().GetLocalNetMask(); + showLogo = LiveSetup().GetShowLogo() ? "1" : ""; + showInfoBox = LiveSetup().GetShowInfoBox() ? "1" : ""; + useStreamdev = LiveSetup().GetUseStreamdev() ? "1" : ""; + streamdevport = std::string(cToSvInt(LiveSetup().GetStreamdevPort())); + streamdevtype = LiveSetup().GetStreamdevType(); + markNewRec = LiveSetup().GetMarkNewRec() ? "1" : ""; + showIMDb = LiveSetup().GetShowIMDb() ? "1" : ""; + showPlayMediaplayer = LiveSetup().GetShowPlayMediaplayer() ? "1" : ""; + showChannelsWithoutEPG = LiveSetup().GetShowChannelsWithoutEPG() ? "1" : ""; <& pageelems.doc_type &> - + - VDR-Live - <$ pageTitle $> - <& pageelems.stylesheets &> - <& pageelems.ajax_js &> - - - - <& pageelems.logo &> - <& menu active=("setup") &> -
-
- - - - - - - - - - - - - - - + VDR-Live - <$ pageTitle $> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> + + + + <& pageelems.logo &> + <& menu active=("setup") &> +
+ + + +
<$ tr("Setup") $>
<$ tr("Use authentication") $>:
- onclick="changeduseauth(this)"/> - -
<$ tr("Show live logo image") $>:
- CHECKIF(!showLogo.empty()); /> -
+ + + + + + + + + + + + - - + + % if (LiveFeatures().Loaded()) { - - - - - - - - - - - - + + + + + + + + + + + + % } // endif LiveFeatures().Loaded() @@ -206,100 +206,100 @@ if (!cUser::CurrentUserHasRightTo(UR_EDITSETUP)) CHECKIF(!markNewRec.empty()); /> - - - - + + + + <# - - - - + + + + #> - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + - - - - -
<$ tr("Setup") $>
<$ tr("Use authentication") $>:
+ onclick="changeduseauth(this)"/> + +
<$ tr("Show live logo image") $>:
+ CHECKIF(!showLogo.empty()); /> +
<$ tr("Show dynamic VDR information box") $>:
+ CHECKIF(!showInfoBox.empty()); /> -
<$ tr("Allow video streaming") $>:
- onclick="changedusestreamdev(this)"/> -
<$ tr("Streamdev server port") $>:
<$ tr("Streamdev stream type") $>:
<$ tr("Allow video streaming") $>:
+ onclick="changedusestreamdev(this)"/> +
<$ tr("Streamdev server port") $>:
<$ tr("Streamdev stream type") $>:
<$ tr("Mark new recordings") $>:
<$ tr("Show link to IMDb in list views") $>:
- CHECKIF(!showIMDb.empty()); /> -
<$ tr("Show link to IMDb in list views") $>:
+ CHECKIF(!showIMDb.empty()); /> +
<$ tr("Show \"Play in Mediaplayer\" in list views") $>:
- CHECKIF(!showPlayMediaplayer.empty()); /> -
<$ tr("Show \"Play in Mediaplayer\" in list views") $>:
+ CHECKIF(!showPlayMediaplayer.empty()); /> +
<$ tr("Last channel to display") $>:
<$ tr("Additional fixed times in 'What's on?'") $>:
- <& tooltip.help text=(tr("Format is HH:MM. Separate multiple times with a semicolon")) &>
<$ tr("Channel groups for MultiSchedule") $>:
- <& tooltip.help text=(tr("Separate channels with a comma ',', separate groups with a semi-colon ';'")) &>
<$ tr("Duration of MultiSchedule in hours") $>:
-
<$ tr("Show channels without EPG") $>:
- CHECKIF(!showChannelsWithoutEPG.empty()); /> -
<$ tr("Last channel to display") $>:
<$ tr("Additional fixed times in 'What's on?'") $>:
+ <& tooltip.help text=(tr("Format is HH:MM. Separate multiple times with a semicolon")) &>
<$ tr("Channel groups for MultiSchedule") $>:
+ <& tooltip.help text=(tr("Separate channels with a comma ',', separate groups with a semi-colon ';'")) &>
<$ tr("Duration of MultiSchedule in hours") $>:
+
<$ tr("Show channels without EPG") $>:
+ CHECKIF(!showChannelsWithoutEPG.empty()); /> +
<$ tr("Start page") $>:
<$ tr("Theme") $>:
<$ tr("Start page") $>:
<$ tr("Theme") $>:
-
- -
-
-
-
- + + + + +
+ +
+ + + + +
+ <%include>page_exit.eh diff --git a/pages/stop_recording.ecpp b/pages/stop_recording.ecpp index 3647cff..52217c4 100644 --- a/pages/stop_recording.ecpp +++ b/pages/stop_recording.ecpp @@ -7,16 +7,16 @@ using namespace vdrlive; <%args> - std::string param; + std::string param; <%session scope="global"> - bool logged_in(false); + bool logged_in(false); <%cpp> - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - reply.setContentType( "application/xml" ); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + reply.setContentType( "application/xml" ); - StopRecordingTask task( param ); - LiveTaskManager().Execute( task ); + StopRecordingTask task( param ); + LiveTaskManager().Execute( task ); <& xmlresponse.ajax name=("stop_recording") pname=("recording") value=(param) result=(task.Result()) error=(task.Error()) &> diff --git a/pages/stream.ecpp b/pages/stream.ecpp index decb6ea..19cf93c 100644 --- a/pages/stream.ecpp +++ b/pages/stream.ecpp @@ -11,135 +11,135 @@ using namespace vdrlive; <%args> - int channel = 1; - std::string channelid; - std::string recid; + int channel = 1; + std::string channelid; + std::string recid; <%session scope="global"> - bool logged_in(false); - std::string prev_recording; - std::string next_recording; - FFmpegThread *f_worker = nullptr; + bool logged_in(false); + std::string prev_recording; + std::string next_recording; + FFmpegThread *f_worker = nullptr; <%request scope="global"> - const cChannel* Channel; - std::string RecId; + const cChannel* Channel; + std::string RecId; <%include>page_init.eh <%cpp> - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - pageTitle = trVDR("Stream"); + pageTitle = trVDR("Stream"); - // check for session cookie. - std::string session; - if (request.hasCookie("tntnet")) { - session = request.getCookie("tntnet"); - dsyslog("vdrlive::stream::session(%s)", session.c_str()); - } - else { - esyslog("vdrlive::stream: no session cookie found"); - return reply.redirect(""); - } + // check for session cookie. + std::string session; + if (request.hasCookie("tntnet")) { + session = request.getCookie("tntnet"); + dsyslog("vdrlive::stream::session(%s)", session.c_str()); + } + else { + esyslog("vdrlive::stream: no session cookie found"); + return reply.redirect(""); + } - Channel = nullptr; - std::string url; - if ( qparam.has("recid") ) { - RecId = recid.substr( 0, 10 ).compare( "recording_" ) == 0 ? recid.substr( 10 ) : recid; - const cRecording* Recording = LiveRecordingsManager()->GetByMd5Hash( recid ); - if ( Recording ) { - struct stat st; - const char* filename = Recording->FileName(); - if ( filename && stat( filename, &st ) == 0 ) { - char buffer[50]; // suitable for accommodating url with 2x ULLONG_MAX - int length = snprintf( buffer, sizeof( buffer ), "%lu:%llu.rec", ( unsigned long )st.st_dev, ( unsigned long long )st.st_ino ); - if ( 0 < length && length < ( int )sizeof( buffer ) ) { - url += buffer; - LOCK_CHANNELS_READ; - tChannelID cid = Recording->Info()->ChannelID(); - Channel = Channels->GetByChannelID( cid ); - } - } - } - if ( !Channel ) - throw HtmlError( tr("Couldn't find recording or no recordings available. Maybe you mistyped your request?") ); - } else if ( qparam.has("channelid") ) { - LOCK_CHANNELS_READ; - tChannelID cid = cid.FromString(channelid.c_str()); - Channel = Channels->GetByChannelID( cid ); - url = channelid; - } else if ( channel > 0 ) { - LOCK_CHANNELS_READ; - Channel = Channels->GetByNumber( channel ); - url += Channel->GetChannelID().ToString(); - } - if ( !Channel ) - throw HtmlError( tr("Couldn't find channel or no channels available. Maybe you mistyped your request?") ); + Channel = nullptr; + std::string url; + if ( qparam.has("recid") ) { + RecId = recid.substr( 0, 10 ).compare( "recording_" ) == 0 ? recid.substr( 10 ) : recid; + const cRecording* Recording = LiveRecordingsManager()->GetByMd5Hash( recid ); + if ( Recording ) { + struct stat st; + const char* filename = Recording->FileName(); + if ( filename && stat( filename, &st ) == 0 ) { + char buffer[50]; // suitable for accommodating url with 2x ULLONG_MAX + int length = snprintf( buffer, sizeof( buffer ), "%lu:%llu.rec", ( unsigned long )st.st_dev, ( unsigned long long )st.st_ino ); + if ( 0 < length && length < ( int )sizeof( buffer ) ) { + url += buffer; + LOCK_CHANNELS_READ; + tChannelID cid = Recording->Info()->ChannelID(); + Channel = Channels->GetByChannelID( cid ); + } + } + } + if ( !Channel ) + throw HtmlError( tr("Couldn't find recording or no recordings available. Maybe you mistyped your request?") ); + } else if ( qparam.has("channelid") ) { + LOCK_CHANNELS_READ; + tChannelID cid = cid.FromString(channelid.c_str()); + Channel = Channels->GetByChannelID( cid ); + url = channelid; + } else if ( channel > 0 ) { + LOCK_CHANNELS_READ; + Channel = Channels->GetByNumber( channel ); + url += Channel->GetChannelID().ToString(); + } + if ( !Channel ) + throw HtmlError( tr("Couldn't find channel or no channels available. Maybe you mistyped your request?") ); - url += "."; - for ( auto c : LiveSetup().GetStreamdevType() ) - url += std::tolower( c ); - dsyslog("vdrlive::stream::vtype(%d)", Channel->Vtype()); - dsyslog("vdrlive::stream::f_worker(%p)", f_worker); - if ( !f_worker) { - f_worker = new FFmpegThread(); - dsyslog("vdrlive::stream: new FFmpegThread created"); - } + url += "."; + for ( auto c : LiveSetup().GetStreamdevType() ) + url += std::tolower( c ); + dsyslog("vdrlive::stream::vtype(%d)", Channel->Vtype()); + dsyslog("vdrlive::stream::f_worker(%p)", f_worker); + if ( !f_worker) { + f_worker = new FFmpegThread(); + dsyslog("vdrlive::stream: new FFmpegThread created"); + } - switch( Channel->Vtype() ) { - case 27: // h264 - f_worker->StartFFmpeg(session, url, qparam.has("recid") ? tagRecordingH264 : tagChannelH264); - break; - case 36: // h265 - f_worker->StartFFmpeg(session, url, qparam.has("recid") ? tagRecordingHVEC : tagChannelHVEC); - break; - case 2: // mpeg2 - f_worker->StartFFmpeg(session, url, qparam.has("recid") ? tagRecordingMPG2 : tagChannelMPG2); - break; - default: // others - f_worker->StartFFmpeg(session, url, qparam.has("recid") ? tagRecordingDFLT : tagChannelDFLT); - } - dsyslog("vdrlive::stream::StartFFmpeg(%s)", url.c_str()); + switch( Channel->Vtype() ) { + case 27: // h264 + f_worker->StartFFmpeg(session, url, qparam.has("recid") ? tagRecordingH264 : tagChannelH264); + break; + case 36: // h265 + f_worker->StartFFmpeg(session, url, qparam.has("recid") ? tagRecordingHVEC : tagChannelHVEC); + break; + case 2: // mpeg2 + f_worker->StartFFmpeg(session, url, qparam.has("recid") ? tagRecordingMPG2 : tagChannelMPG2); + break; + default: // others + f_worker->StartFFmpeg(session, url, qparam.has("recid") ? tagRecordingDFLT : tagChannelDFLT); + } + dsyslog("vdrlive::stream::StartFFmpeg(%s)", url.c_str()); <# <& pageelems.doc_type &> #> - - - VDR Live - <$ pageTitle $> - <& pageelems.stylesheets &> - <& pageelems.ajax_js &> - <& pageelems.create_html_js &> - - - - <& pageelems.logo &> -% if ( qparam.has("recid") ) { - <& menu active=("stream") component=("stream.recording_selection") &> -% } else { - <& menu active=("stream") component=("stream.channel_selection") &> -% } -
-
-
+ + + VDR Live - <$ pageTitle $> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> + <& pageelems.create_html_js &> + + + + <& pageelems.logo &> +% if ( qparam.has("recid") ) { + <& menu active=("stream") component=("stream.recording_selection") &> +% } else { + <& menu active=("stream") component=("stream.channel_selection") &> +% } +
+
+
- - -
-
+ + +
+
<%cpp> if (qparam.has("recid")) { dsyslog("vdrlive::stream: generating recording info"); @@ -147,81 +147,81 @@ RecordingsItemRecPtr rPtr = LiveRecordingsManager()->GetByIdHash( recid ); cToSvConcat<0> recording_item; rPtr->AppendAsJSArray(recording_item); - - - - -
+ + + + +
<%cpp> } else { dsyslog("vdrlive::stream: generating EPG info"); const cSchedule *Schedule = NULL; { - LOCK_SCHEDULES_READ; - Schedule = Schedules->GetSchedule(Channel); + LOCK_SCHEDULES_READ; + Schedule = Schedules->GetSchedule(Channel); } const cEvent *Event = NULL; if (Schedule) - Event = Schedule->GetPresentEvent(); + Event = Schedule->GetPresentEvent(); EpgInfoPtr epgEvent; if (Event) { - epgEvent = EpgEvents::CreateEpgInfo(Channel, Event); + epgEvent = EpgEvents::CreateEpgInfo(Channel, Event); - tChannelID chanId; - tEventID eventId; - EpgEvents::DecodeDomId(epgEvent->Id(), chanId, eventId); - char const * timeFormat = tr("%I:%M %p"); - char const * dateFormat = tr("%A, %x"); - std::string headTime = std::string(cToSvDateTime(timeFormat, time(0))); - std::string headDate = std::string(cToSvDateTime(dateFormat, time(0))); - std::string startTime(epgEvent->StartTime(tr("%I:%M %p"))); - std::string endTime(epgEvent->EndTime(tr("%I:%M %p"))); - std::string startDate(epgEvent->StartTime(tr("%a, %x"))); + tChannelID chanId; + tEventID eventId; + EpgEvents::DecodeDomId(epgEvent->Id(), chanId, eventId); + char const * timeFormat = tr("%I:%M %p"); + char const * dateFormat = tr("%A, %x"); + std::string headTime = std::string(cToSvDateTime(timeFormat, time(0))); + std::string headDate = std::string(cToSvDateTime(dateFormat, time(0))); + std::string startTime(epgEvent->StartTime(tr("%I:%M %p"))); + std::string endTime(epgEvent->EndTime(tr("%I:%M %p"))); + std::string startDate(epgEvent->StartTime(tr("%a, %x"))); - std::string timeSpan(startTime + " - " + endTime); + std::string timeSpan(startTime + " - " + endTime); - if (startTime.empty() && endTime.empty()) { - timeSpan = headTime; - startDate = headDate; - } + if (startTime.empty() && endTime.empty()) { + timeSpan = headTime; + startDate = headDate; + } std::string longDescription = concat( StringEscapeAndBreak(StringWordTruncate(epgEvent->LongDescr(), LiveSetup().GetMaxTooltipChars())), - "

", + "

", tr("Click to view details.")); - - - - <& pageelems.epg_tool_box detail=(0) epgid=(epgEvent->Id()) title=(epgEvent->Title()) startTime=(epgEvent->GetStartTime()) endTime=(epgEvent->GetEndTime()) lastCurrentChanel=(0) &> - - - - -
-
-
<$ (timeSpan) $>
-
<& pageelems.progressbar progress=(epgEvent->Elapsed()) duration=(epgEvent->Duration()) &>
-
-
-
-% if (eventId != 0) { - <& tooltip.display domId=(epgEvent->Id()) &> -% } - ><$ (epgEvent->Title()) $>
<$ (epgEvent->ShortDescr()) $>
-% } else { - <$ (epgEvent->Title()) $> -% } -
-
-
+ + + + <& pageelems.epg_tool_box detail=(0) epgid=(epgEvent->Id()) title=(epgEvent->Title()) startTime=(epgEvent->GetStartTime()) endTime=(epgEvent->GetEndTime()) lastCurrentChanel=(0) &> + + + + +
+
+
<$ (timeSpan) $>
+
<& pageelems.progressbar progress=(epgEvent->Elapsed()) duration=(epgEvent->Duration()) &>
+
+
+
+% if (eventId != 0) { + <& tooltip.display domId=(epgEvent->Id()) &> +% } + ><$ (epgEvent->Title()) $>
<$ (epgEvent->ShortDescr()) $>
+% } else { + <$ (epgEvent->Title()) $> +% } +
+
+
%} // if (Event) %} // if ( qparam.has("recid") -
- +
+ <%include>page_exit.eh diff --git a/pages/stream_data.ecpp b/pages/stream_data.ecpp index e549fee..2ea9cd8 100644 --- a/pages/stream_data.ecpp +++ b/pages/stream_data.ecpp @@ -31,13 +31,13 @@ reply.setContentType(mime); // check for session cookie. TODO: handle secure cookie for ssl std::string session; if (request.hasCookie("tntnet")) { - session = request.getCookie("tntnet"); + session = request.getCookie("tntnet"); } // forge target path from requested path. std::string path(request.getPathInfo()); if (path.substr(0, 7) == "/media/") { - path.replace(0, 7, "/tmp/live-hls-buffer/"); + path.replace(0, 7, "/tmp/live-hls-buffer/"); } else return DECLINED; @@ -47,33 +47,33 @@ if (path.rfind(".m3u8") != std::string::npos && path.find("master_") != std::str else retry = 5; std::ifstream f; do { - f.open ( path.c_str(), std::ios::binary ); - if (!f.is_open()) { - usleep(200e3); - } + f.open ( path.c_str(), std::ios::binary ); + if (!f.is_open()) { + usleep(200e3); + } } while (!f.is_open() && --retry); // fail if file did not appear if (!f.is_open()) { - dsyslog("vdrlive::stream_data: %s - DECLINED", path.c_str()); - return DECLINED; + dsyslog("vdrlive::stream_data: %s - DECLINED", path.c_str()); + return DECLINED; } // wait until TARGETDURATION in playlist is != 0 if (path.rfind(".m3u8") != std::string::npos && path.find("ffmpeg_") != std::string::npos) { - std::string line; - int count = 20; - while(getline(f, line) && count) { - if (line.find("#EXT-X-TARGETDURATION:") != std::string::npos) { - if (! (atoi(line.erase(0, 22).c_str()))) { - count--; - f.close(); - usleep(100e3); - f.open( path.c_str(), std::ios::binary ); - } - } - } - f.clear(); // unset eof flag + std::string line; + int count = 20; + while(getline(f, line) && count) { + if (line.find("#EXT-X-TARGETDURATION:") != std::string::npos) { + if (! (atoi(line.erase(0, 22).c_str()))) { + count--; + f.close(); + usleep(100e3); + f.open( path.c_str(), std::ios::binary ); + } + } + } + f.clear(); // unset eof flag } usleep(100e3); @@ -85,30 +85,30 @@ unsigned httpReturn = HTTP_OK; std::string range = request.getHeader(tnt::httpheader::range); off_t offset = 0, stop = size-1; if (!range.empty()) { - range.erase(0,6); - std::stringstream ss(range); - char tmp; - ss >> offset >> tmp >> stop; - dsyslog("vdrlive::stream_data::range(%jd to %jd)", (intmax_t)offset, (intmax_t)stop); - if (offset > size) return HTTP_RANGE_NOT_SATISFIABLE; - if ((stop+1) > size) stop = size - 1; - httpReturn = HTTP_PARTIAL_CONTENT; - std::stringstream contentRange; - contentRange << offset << ('-') << stop << ('/') << size; - reply.setHeader(tnt::httpheader::contentRange, contentRange.str()); - f.seekg( offset, std::ios::beg ); + range.erase(0,6); + std::stringstream ss(range); + char tmp; + ss >> offset >> tmp >> stop; + dsyslog("vdrlive::stream_data::range(%jd to %jd)", (intmax_t)offset, (intmax_t)stop); + if (offset > size) return HTTP_RANGE_NOT_SATISFIABLE; + if ((stop+1) > size) stop = size - 1; + httpReturn = HTTP_PARTIAL_CONTENT; + std::stringstream contentRange; + contentRange << offset << ('-') << stop << ('/') << size; + reply.setHeader(tnt::httpheader::contentRange, contentRange.str()); + f.seekg( offset, std::ios::beg ); } char buffer[KILOBYTE(64)]; size_t r, c = stop - offset+ 1; while (r = f.readsome(buffer, (c < (long int) sizeof(buffer))?c:sizeof(buffer))) { - reply.out().write(buffer, r); - c -= r; - if (!reply.out()) { - return HTTP_GONE; - } + reply.out().write(buffer, r); + c -= r; + if (!reply.out()) { + return HTTP_GONE; + } #if TNT_WATCHDOG_SILENCE - request.touch(); // retrigger the watchdog. + request.touch(); // retrigger the watchdog. #endif } diff --git a/pages/switch_channel.ecpp b/pages/switch_channel.ecpp index fc95e65..24fd0d5 100644 --- a/pages/switch_channel.ecpp +++ b/pages/switch_channel.ecpp @@ -9,31 +9,31 @@ using namespace vdrlive; <%args> - std::string param; - std::string async; + std::string param; + std::string async; <%cpp> - tChannelID paramID = tChannelID::FromString(param.c_str()); - bool ajaxReq = !async.empty() && (parse_int(async) != 0); - std::string referrer; + tChannelID paramID = tChannelID::FromString(param.c_str()); + bool ajaxReq = !async.empty() && (parse_int(async) != 0); + std::string referrer; - if (!cUser::CurrentUserHasRightTo(UR_SWITCHCHNL)) - throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); + if (!cUser::CurrentUserHasRightTo(UR_SWITCHCHNL)) + throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); - if (ajaxReq) { - reply.setContentType( "application/xml" ); - } - else { - referrer = request.getHeader("Referer:"); - } + if (ajaxReq) { + reply.setContentType( "application/xml" ); + } + else { + referrer = request.getHeader("Referer:"); + } - SwitchChannelTask task( paramID ); - LiveTaskManager().Execute( task ); + SwitchChannelTask task( paramID ); + LiveTaskManager().Execute( task ); - if (!ajaxReq) { - if (!referrer.empty()) { - return reply.redirect(referrer); - } + if (!ajaxReq) { + if (!referrer.empty()) { + return reply.redirect(referrer); + } Normale Seite:
channel: <$ paramID $>
@@ -41,10 +41,10 @@ result: <$ (task.Result()) $>
error: <$ (task.Error()) $>
Seitenende! <%cpp> - } - else { + } + else { <& xmlresponse.ajax name=("switch_channel") pname=("channel") value=(paramID) result=(task.Result()) error=(task.Error()) &> <%cpp> - } + } diff --git a/pages/timerconflicts.ecpp b/pages/timerconflicts.ecpp index b2b5607..4308637 100644 --- a/pages/timerconflicts.ecpp +++ b/pages/timerconflicts.ecpp @@ -10,7 +10,7 @@ using namespace vdrlive; <%args> - // input parameters + // input parameters <%session scope="global"> bool logged_in(false); @@ -21,89 +21,89 @@ reply.setHeader (tnt::httpheader::cacheControl, "no-store, no-cache, max-age=0, if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); <%cpp> - pageTitle = tr("Timer conflicts"); - TimerConflicts timerConflicts; - cMutexLock timersLock( &LiveTimerManager() ); - SortedTimers& timers = LiveTimerManager().GetTimers(); + pageTitle = tr("Timer conflicts"); + TimerConflicts timerConflicts; + cMutexLock timersLock( &LiveTimerManager() ); + SortedTimers& timers = LiveTimerManager().GetTimers(); <& pageelems.doc_type &> - - - VDR-Live - <$ pageTitle $> - <& pageelems.stylesheets &> - <& pageelems.ajax_js &> + + + VDR-Live - <$ pageTitle $> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> <& pageelems.create_html_js &> - - - <& pageelems.logo &> - <& menu active=("timersconflicts")> -
-% if (timerConflicts.size() == 0) { - <$ tr("No timer conflicts") $> -% } else { - + + + <& pageelems.logo &> + <& menu active=("timersconflicts")> +
+% if (timerConflicts.size() == 0) { + <$ tr("No timer conflicts") $> +% } else { +
<%cpp> - for (TimerConflicts::iterator conflict = timerConflicts.begin(); conflict != timerConflicts.end(); ++conflict) { - const std::list< TimerInConflict >& conflTimers = conflict->ConflictingTimers(); - for (std::list< TimerInConflict >::const_iterator confltimer = conflTimers.begin(); confltimer != conflTimers.end(); ++confltimer) { + for (TimerConflicts::iterator conflict = timerConflicts.begin(); conflict != timerConflicts.end(); ++conflict) { + const std::list< TimerInConflict >& conflTimers = conflict->ConflictingTimers(); + for (std::list< TimerInConflict >::const_iterator confltimer = conflTimers.begin(); confltimer != conflTimers.end(); ++confltimer) { - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + <%cpp> - for (std::list::const_iterator timerIndex = confltimer->concurrentTimerIndices.begin(); timerIndex != confltimer->concurrentTimerIndices.end(); ++timerIndex) { - LOCK_TIMERS_READ; - cTimer* timer = (cTimer *)Timers->GetById(*timerIndex, (confltimer->remote == "") ? NULL : confltimer->remote.c_str()); - if (!timer) continue; + for (std::list::const_iterator timerIndex = confltimer->concurrentTimerIndices.begin(); timerIndex != confltimer->concurrentTimerIndices.end(); ++timerIndex) { + LOCK_TIMERS_READ; + cTimer* timer = (cTimer *)Timers->GetById(*timerIndex, (confltimer->remote == "") ? NULL : confltimer->remote.c_str()); + if (!timer) continue; - std::list< int >::const_iterator nexttimerIndex = timerIndex; - ++nexttimerIndex; - bool bottom = (nexttimerIndex == confltimer->concurrentTimerIndices.end()); + std::list< int >::const_iterator nexttimerIndex = timerIndex; + ++nexttimerIndex; + bool bottom = (nexttimerIndex == confltimer->concurrentTimerIndices.end()); - std::string timerStateImg = "transparent.png"; - std::string timerStateHint; - if (timer->Id() == confltimer->timerIndex) { - timerStateImg = "timerconflict.gif"; - timerStateHint = tr("Timer has a conflict."); - } - else if (timer->Flags() & tfActive) { - timerStateImg = "arrow.png"; - timerStateHint = tr("Timer is active."); - } + std::string timerStateImg = "transparent.png"; + std::string timerStateHint; + if (timer->Id() == confltimer->timerIndex) { + timerStateImg = "timerconflict.gif"; + timerStateHint = tr("Timer has a conflict."); + } + else if (timer->Flags() & tfActive) { + timerStateImg = "arrow.png"; + timerStateHint = tr("Timer is active."); + } - EpgInfoPtr epgEvent; - std::string longDescription; - std::string searchTimName; - std::string searchTimId; + EpgInfoPtr epgEvent; + std::string longDescription; + std::string searchTimName; + std::string searchTimId; std::string recID; std::string recName; - std::string title; + std::string title; longDescription = StringEscapeAndBreak(SortedTimers::GetTimerInfo(*timer)); - if (!timer->Event()) { - LOCK_SCHEDULES_READ; - timer->SetEventFromSchedule(Schedules); - } - if (timer->Event()) { - epgEvent = EpgEvents::CreateEpgInfo(timer->Channel(), timer->Event()); + if (!timer->Event()) { + LOCK_SCHEDULES_READ; + timer->SetEventFromSchedule(Schedules); + } + if (timer->Event()) { + epgEvent = EpgEvents::CreateEpgInfo(timer->Channel(), timer->Event()); bool truncated = false; if (epgEvent->LongDescr().length()) longDescription += "
"; longDescription += StringEscapeAndBreak(StringWordTruncate(epgEvent->LongDescr(), LiveSetup().GetMaxTooltipChars(), truncated)); @@ -116,60 +116,60 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); std::string timerFile; AppendHtmlEscapedAndCorrectNonUTF8(timerFile, timer->File()); -
- - + + - - - - - + + + + - - - - - + + + - -% } + +% } - - + + <%cpp> - } - } + } + } -
-
<$ concat(cToSvDateTime(tr("%A, %x"), conflict->ConflictTime()), " ", cToSvDateTime(tr("%I:%M %p"), conflict->ConflictTime()), " - ", cToSvInt(confltimer->percentage), "%") $><$ tr("Server")$>: <$ (confltimer->remote == "" ) ? tr("local") : confltimer->remote $>
-
<$ trVDR("Channel") $>
<$ trVDR("File") $>
<$ tr("Search timer") $>
+
<$ concat(cToSvDateTime(tr("%A, %x"), conflict->ConflictTime()), " ", cToSvDateTime(tr("%I:%M %p"), conflict->ConflictTime()), " - ", cToSvInt(confltimer->percentage), "%") $><$ tr("Server")$>: <$ (confltimer->remote == "" ) ? tr("local") : confltimer->remote $>
+
<$ trVDR("Channel") $>
<$ trVDR("File") $>
<$ tr("Search timer") $>
">" alt="" <%cpp> if (!timerStateHint.empty()) { <& tooltip.hint text=(timerStateHint) &><%cpp> } / >">
+
">" alt="" <%cpp> if (!timerStateHint.empty()) { <& tooltip.hint text=(timerStateHint) &><%cpp> } / >">
<$ cToSvDateTime(tr("%I:%M %p"), timer->StartTime()) $> - <$ cToSvDateTime(tr("%I:%M %p"), timer->StopTime()) $>
: <$*cSource::ToString(timer->Channel()->Source() )$>-<$cToSvConcat(timer->Channel()->Frequency())$>-<$timer->Channel()->Parameters()$>"><$ timer->Channel()->Name() $>
"><$ timer->Priority() $>
td-hidden-xs"> td-hidden-xs"> td-hidden-xs"> td-hidden-xs">">
+
td-hidden-xs"> td-hidden-xs"> td-hidden-xs"> td-hidden-xs">">">
-% if ( !timer->Local() || searchTimId.empty() ) { +
">
+% if ( !timer->Local() || searchTimId.empty() ) { <# not created by epgsearch, check tvscraper autotimer #> - <$$ StringReplace(searchTimName, "~", "~") $> + <$$ StringReplace(searchTimName, "~", "~") $> % if (!recID.empty() ) { <$$ StringReplace(recName, "~", "~") $> % } -% } else { - <$$ StringReplace(searchTimName, "~", "~") $> -% } +% } else { + <$$ StringReplace(searchTimName, "~", "~") $> +% }
td-hidden-xs"> td-hidden-xs"> td-hidden-xs">"> + td-hidden-xs"> td-hidden-xs"> td-hidden-xs">"> " alt="" <& tooltip.hint text=(tr("Search for repeats.")) &> /> Flags() & tfActive) ? "active.png" : "inactive.png") $>" alt="" <& tooltip.hint text=(tr("Toggle timer active/inactive")) &> />
<& pageelems.edit_timer timerId=(timers.GetTimerId(*timer)) &>
" alt="" <& tooltip.hint text=(tr("Delete timer")) &> />
-
+
-% } -
- + +% } +
+ <%include>page_exit.eh diff --git a/pages/timers.ecpp b/pages/timers.ecpp index b8137c2..5ec8049 100644 --- a/pages/timers.ecpp +++ b/pages/timers.ecpp @@ -12,47 +12,47 @@ using namespace vdrlive; <%args> - // input parameters - std::string timerid; - std::string action; + // input parameters + std::string timerid; + std::string action; <%session scope="global"> - bool logged_in(false); + bool logged_in(false); <%request scope="page"> - const cTimer* timer; - TimerConflictNotifier timerNotifier; + const cTimer* timer; + TimerConflictNotifier timerNotifier; <%include>page_init.eh <%cpp> reply.setHeader (tnt::httpheader::cacheControl, "no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate", true); - if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); - pageTitle = trVDR("Timers"); + pageTitle = trVDR("Timers"); - cMutexLock timersLock( &LiveTimerManager() ); - SortedTimers& timers = LiveTimerManager().GetTimers(); - TimerConflicts timerConflicts; + cMutexLock timersLock( &LiveTimerManager() ); + SortedTimers& timers = LiveTimerManager().GetTimers(); + TimerConflicts timerConflicts; - timer = 0; - if ( !timerid.empty() && !action.empty() ) { - std::string tId = SortedTimers::DecodeDomId(timerid); -// dsyslog("live: DEBUG: TIMER: tId = %s", tId.c_str()); - timer = timers.GetByTimerId(tId); - if ( timer == 0 ) - throw HtmlError( tr("Couldn't find timer. Maybe you mistyped your request?") ); - if (action == "delete") { - if (!cUser::CurrentUserHasRightTo(UR_DELTIMERS)) - throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); + timer = 0; + if ( !timerid.empty() && !action.empty() ) { + std::string tId = SortedTimers::DecodeDomId(timerid); +// dsyslog("live: DEBUG: TIMER: tId = %s", tId.c_str()); + timer = timers.GetByTimerId(tId); + if ( timer == 0 ) + throw HtmlError( tr("Couldn't find timer. Maybe you mistyped your request?") ); + if (action == "delete") { + if (!cUser::CurrentUserHasRightTo(UR_DELTIMERS)) + throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") ); // dsyslog("live: timers.ecpp timer->Id() %d", timer->Id()); // dsyslog("live: timers.ecpp timer->Remote() %s", timer->Remote()); - LiveTimerManager().DelTimer(timer->Id(), timer->Remote()); - timerNotifier.SetTimerModification(); - } - if (action == "toggle") { - LiveTimerManager().ToggleTimerActive(timer->Id(), timer->Remote()); - timerNotifier.SetTimerModification(); - } + LiveTimerManager().DelTimer(timer->Id(), timer->Remote()); + timerNotifier.SetTimerModification(); + } + if (action == "toggle") { + LiveTimerManager().ToggleTimerActive(timer->Id(), timer->Remote()); + timerNotifier.SetTimerModification(); + } @@ -61,135 +61,135 @@ using namespace vdrlive; <%cpp> - } else { + } else { - std::string previousDay = ""; + std::string previousDay = ""; <& pageelems.doc_type &> - - - VDR-Live - <$ pageTitle $> - <& pageelems.stylesheets &> - <& pageelems.ajax_js &> + + + VDR-Live - <$ pageTitle $> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> <& pageelems.create_html_js &> - - - <& pageelems.logo &> - <& menu active=("timers") component=("timers.timer_actions")> -
+ + + <& pageelems.logo &> + <& menu active=("timers") component=("timers.timer_actions")> +
<%cpp> - #ifdef DEBUG_LOCK + #ifdef DEBUG_LOCK dsyslog("live: pages/timers.ecpp LOCK_TIMERS_READ"); #endif - LOCK_TIMERS_READ; + LOCK_TIMERS_READ; cSortedTimers sortedTimers(Timers); - if (sortedTimers.Size() == 0) { + if (sortedTimers.Size() == 0) { - <$ tr("No timer defined") $> -% } else { - + <$ tr("No timer defined") $> +% } else { +
<%cpp> - // check for remote timers: - bool noRemoteTimers = true; - for (int i = 0; noRemoteTimers && i < sortedTimers.Size(); i++) { - noRemoteTimers &= sortedTimers[i]->Local(); - } - // check for search timers or tvscraper autotimer: - bool noSearchTimers = true; - for (int i = 0; noSearchTimers && i < sortedTimers.Size(); i++) { - std::string recID; - std::string recName; - timer = sortedTimers[i]; - noSearchTimers &= timer->Local() && SortedTimers::SearchTimerInfo(*timer, "s-id").empty() && SortedTimers::TvScraperTimerInfo(*timer, recID, recName).empty(); - } - // output of the timer list: + // check for remote timers: + bool noRemoteTimers = true; + for (int i = 0; noRemoteTimers && i < sortedTimers.Size(); i++) { + noRemoteTimers &= sortedTimers[i]->Local(); + } + // check for search timers or tvscraper autotimer: + bool noSearchTimers = true; + for (int i = 0; noSearchTimers && i < sortedTimers.Size(); i++) { + std::string recID; + std::string recName; + timer = sortedTimers[i]; + noSearchTimers &= timer->Local() && SortedTimers::SearchTimerInfo(*timer, "s-id").empty() && SortedTimers::TvScraperTimerInfo(*timer, recID, recName).empty(); + } + // output of the timer list: for (int i = 0; i < sortedTimers.Size(); i++) { const cTimer *timer = sortedTimers[i]; - EpgInfoPtr epgEvent = 0; - std::string longDescription; - std::string searchTimName; - std::string searchTimId; - std::string recID; - std::string recName; + EpgInfoPtr epgEvent = 0; + std::string longDescription; + std::string searchTimName; + std::string searchTimId; + std::string recID; + std::string recName; longDescription = StringEscapeAndBreak(SortedTimers::GetTimerInfo(*timer)); - if (timer->Event()) - { + if (timer->Event()) + { epgEvent = EpgEvents::CreateEpgInfo(timer->Channel(), timer->Event()); bool truncated = false; if (epgEvent->LongDescr().length()) longDescription += "
"; - longDescription += StringEscapeAndBreak(StringWordTruncate(epgEvent->LongDescr(), LiveSetup().GetMaxTooltipChars(), truncated)); - if (truncated) longDescription += " ..."; + longDescription += StringEscapeAndBreak(StringWordTruncate(epgEvent->LongDescr(), LiveSetup().GetMaxTooltipChars(), truncated)); + if (truncated) longDescription += " ..."; } AppendHtmlEscapedAndCorrectNonUTF8(searchTimName, SortedTimers::SearchTimerInfo(*timer, "searchtimer")); searchTimId = SortedTimers::SearchTimerInfo(*timer, "s-id"); if (searchTimName.empty() && searchTimId.empty() ) AppendHtmlEscapedAndCorrectNonUTF8(searchTimName, SortedTimers::TvScraperTimerInfo(*timer, recID, recName) ); - std::string currentDay = SortedTimers::GetTimerDays(timer); + std::string currentDay = SortedTimers::GetTimerDays(timer); const cTimer *nextTimer = NULL; if (i < (sortedTimers.Size() - 1)) nextTimer = sortedTimers[i + 1]; - bool bottom = false; - if (i == sortedTimers.Size() - 1) bottom = true; - else { - std::string nextDay = SortedTimers::GetTimerDays(nextTimer); - bottom = (currentDay != nextDay); - } - if (previousDay != currentDay) { - if (!previousDay.empty()) { + bool bottom = false; + if (i == sortedTimers.Size() - 1) bottom = true; + else { + std::string nextDay = SortedTimers::GetTimerDays(nextTimer); + bottom = (currentDay != nextDay); + } + if (previousDay != currentDay) { + if (!previousDay.empty()) { - - + + <%cpp> - } - previousDay = currentDay; + } + previousDay = currentDay; - - - - - - + + + + + + - - - + + + - + <%cpp> - } - std::string timerStateImg = "transparent.png"; - std::string timerStateHint; - if (timer->Recording()) { - timerStateImg = "arrow_rec.gif"; - timerStateHint = tr("Timer is recording."); - } - else if (timer->Flags() & tfActive) { - if (timerConflicts.HasConflict(timer->Id() )) { - timerStateImg = "timerconflict.gif"; - timerStateHint = tr("Timer has a conflict."); - } - else { - timerStateImg = "arrow.png"; - timerStateHint = tr("Timer is active."); - } - } + } + std::string timerStateImg = "transparent.png"; + std::string timerStateHint; + if (timer->Recording()) { + timerStateImg = "arrow_rec.gif"; + timerStateHint = tr("Timer is recording."); + } + else if (timer->Flags() & tfActive) { + if (timerConflicts.HasConflict(timer->Id() )) { + timerStateImg = "timerconflict.gif"; + timerStateHint = tr("Timer has a conflict."); + } + else { + timerStateImg = "arrow.png"; + timerStateHint = tr("Timer is active."); + } + } std::string timerFile; AppendHtmlEscapedAndCorrectNonUTF8(timerFile, timer->File()); - + - +
-
+
-
- <$ currentDay $> -
-
<$ trVDR("Channel") $>
+
+ <$ currentDay $> +
+
<$ trVDR("Channel") $>
<$ trVDR("File") $>
">">
<$ tr("Search timer") $>
<$ trVDR("File") $>
">">
<$ tr("Search timer") $>
">" alt="" <%cpp> if (!timerStateHint.empty()) { <& tooltip.hint text=(timerStateHint) &> <%cpp> } />">" alt="" <%cpp> if (!timerStateHint.empty()) { <& tooltip.hint text=(timerStateHint) &> <%cpp> } /> ">
@@ -200,44 +200,44 @@ using namespace vdrlive; - - + + + - - + <%cpp> - } - } + } + } -
<$ cToSvDateTime(tr("%I:%M %p"), timer->StartTime()) $> - <$ cToSvDateTime(tr("%I:%M %p"), timer->StopTime()) $>
: <$*cSource::ToString(timer->Channel()->Source() )$>-<$cToSvConcat(timer->Channel()->Frequency())$>-<$timer->Channel()->Parameters()$>"><$ timer->Channel()->Name() $>
td-hidden-xs"> td-hidden-xs"> td-hidden-xs">">
+
"> - td-hidden-xs">
<$ timer->Local()?trVDR(" "):timer->Remote() $>
td-hidden-xs">
<$ timer->Local()?trVDR(" "):timer->Remote() $>
">
-% if ( !timer->Local() || searchTimId.empty() ) { +% if ( !timer->Local() || searchTimId.empty() ) { <# not created by epgsearch, check tvscraper autotimer #> <$$ StringReplace(searchTimName, "~", "~") $> % if (!recID.empty() ) { - <$$ StringReplace(recName, "~", "~") $> + <$$ StringReplace(recName, "~", "~") $> % } -% } else { - <$$ StringReplace(searchTimName, "~", "~") $> -% } +% } else { + <$$ StringReplace(searchTimName, "~", "~") $> +% }
td-hidden-xs"> td-hidden-xs">"> + "> Flags() & tfActive) ? "active.png" : "inactive.png") $>" alt="" <& tooltip.hint text=(tr("Toggle timer active/inactive")) &> />
<& pageelems.edit_timer timerId=(timers.GetTimerId(*timer)) &>
" alt="" <& tooltip.hint text=(tr("Delete timer")) &> />
-
- +
+
+ % } <%include>page_exit.eh diff --git a/pages/users.ecpp b/pages/users.ecpp index 605539a..b307f45 100644 --- a/pages/users.ecpp +++ b/pages/users.ecpp @@ -7,9 +7,9 @@ using namespace vdrlive; <%args> - // input parameters - std::string userid; - std::string action; + // input parameters + std::string userid; + std::string action; <%session scope="global"> bool logged_in(false); @@ -19,58 +19,58 @@ bool logged_in(false); if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); <%cpp> - pageTitle = tr("Users"); - if ( !userid.empty() ) { - if (action == "delete") - { - Users.Del(Users.GetByUserId( userid )); - Users.Save(); - } - } + pageTitle = tr("Users"); + if ( !userid.empty() ) { + if (action == "delete") + { + Users.Del(Users.GetByUserId( userid )); + Users.Save(); + } + } <& pageelems.doc_type &> - - - VDR-Live - <$ pageTitle $> - <& pageelems.stylesheets &> - <& pageelems.ajax_js &> - - - <& pageelems.logo &> - <& menu active=("users") component=("users.user_actions")> -
- - - - - - - + + + VDR-Live - <$ pageTitle $> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> + + + <& pageelems.logo &> + <& menu active=("users") component=("users.user_actions")> +
+
-
<$ pageTitle $>
-
<$ tr("Name") $>
-
+ + + + + + <%cpp> - cUser* user = Users.First(); - while (user) - { - bool bottom = (Users.Next(user) == NULL); - if (user) - { + cUser* user = Users.First(); + while (user) + { + bool bottom = (Users.Next(user) == NULL); + if (user) + { - - - - - + + + + + <%cpp> - } - user = Users.Next(user); - } + } + user = Users.Next(user); + } -
+
<$ pageTitle $>
+
<$ tr("Name") $>
+
">
<$ user->Name() $>
">" alt="" <& tooltip.hint text=(tr("Edit user")) &> />">" alt="" <& tooltip.hint text=(tr("Delete user")) &> />
">
<$ user->Name() $>
">" alt="" <& tooltip.hint text=(tr("Edit user")) &> />">" alt="" <& tooltip.hint text=(tr("Delete user")) &> />
-
- + +
+ <%include>page_exit.eh diff --git a/pages/whats_on.ecpp b/pages/whats_on.ecpp index abf8095..328da61 100644 --- a/pages/whats_on.ecpp +++ b/pages/whats_on.ecpp @@ -43,9 +43,9 @@ std::string headTime; std::string headDate; if (mode.empty()) - mode = LiveSetup().GetLastWhatsOnListMode(); + mode = LiveSetup().GetLastWhatsOnListMode(); else - LiveSetup().SetLastWhatsOnListMode(mode); + LiveSetup().SetLastWhatsOnListMode(mode); current_type = type; current_mode = mode; @@ -55,230 +55,230 @@ current_fixtime = fixtime; char const * timeFormat = tr("%I:%M %p"); char const * dateFormat = tr("%A, %x"); if (mode == "detail") { - dateFormat = tr("%a, %x"); + dateFormat = tr("%a, %x"); } if (type == "now") { - headTime = std::string(cToSvDateTime(timeFormat, time(0))); - headDate = std::string(cToSvDateTime(dateFormat, time(0))); - head = std::string(tr("What's running on")) + " " + headDate + " " + tr("at") + " " + headTime; + headTime = std::string(cToSvDateTime(timeFormat, time(0))); + headDate = std::string(cToSvDateTime(dateFormat, time(0))); + head = std::string(tr("What's running on")) + " " + headDate + " " + tr("at") + " " + headTime; } else if (type == "next") { - headTime = std::string(cToSvDateTime(timeFormat, time(0) + 3600)); - headDate = std::string(cToSvDateTime(dateFormat, time(0) + 3600)); - head = tr("What's on next?"); + headTime = std::string(cToSvDateTime(timeFormat, time(0) + 3600)); + headDate = std::string(cToSvDateTime(dateFormat, time(0) + 3600)); + head = tr("What's on next?"); } else if (type == "at") { - if (attime != "") - displaytime = ExpandTimeString(attime); - else if (fixtime != "") - displaytime = ExpandTimeString(fixtime); - current_displaytime = displaytime; + if (attime != "") + displaytime = ExpandTimeString(attime); + else if (fixtime != "") + displaytime = ExpandTimeString(fixtime); + current_displaytime = displaytime; - seektime = GetTimeT(displaytime); - if (seektime - time(0) + 3600 < 0) // if wanted time is past more then 1h, then use tomorrow - seektime += SECSINDAY; - headTime = std::string(cToSvDateTime(timeFormat, seektime)); - headDate = std::string(cToSvDateTime(dateFormat, seektime)); - head = std::string(tr("What's running on")) + " " + headDate + " " + tr("at") + std::string(" ") + headTime; + seektime = GetTimeT(displaytime); + if (seektime - time(0) + 3600 < 0) // if wanted time is past more then 1h, then use tomorrow + seektime += SECSINDAY; + headTime = std::string(cToSvDateTime(timeFormat, seektime)); + headDate = std::string(cToSvDateTime(dateFormat, seektime)); + head = std::string(tr("What's running on")) + " " + headDate + " " + tr("at") + std::string(" ") + headTime; } else if (type == "favs") { - head = tr("Favorites"); + head = tr("Favorites"); } <& pageelems.doc_type &> - + - VDR-Live - <$ head $> - <& pageelems.stylesheets &> - <& pageelems.ajax_js &> + VDR-Live - <$ head $> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> <& pageelems.create_html_js &> - - - - <& pageelems.logo &> - <& menu active=("whats_on") component=("whats_on.whats_on_actions")> -
-% if (mode == "list") { - - - - -% } + + + + <& pageelems.logo &> + <& menu active=("whats_on") component=("whats_on.whats_on_actions")> +
+% if (mode == "list") { +
<$ head $>
+ + + +% } <%cpp> - std::list eventList; + std::list eventList; - // collect the broadcasts - if (type != "favs") - { - LOCK_CHANNELS_READ; - { - for (cChannel *Channel = (cChannel *)Channels->First(); Channel && Channel->Number() <= LiveSetup().GetLastChannel(); Channel = (cChannel *)Channels->Next(Channel)) { - if (Channel->GroupSep()) { - continue; - } - const cSchedule *Schedule; - { - LOCK_SCHEDULES_READ; - Schedule = Schedules->GetSchedule(Channel); - } - if (!Schedule) { - continue; - } - const cEvent *Event = NULL; - if (type == "now") - Event = Schedule->GetPresentEvent(); - else if (type == "next") - Event = Schedule->GetFollowingEvent(); - else if (type == "at") - Event = Schedule->GetEventAround(seektime); + // collect the broadcasts + if (type != "favs") + { + LOCK_CHANNELS_READ; + { + for (cChannel *Channel = (cChannel *)Channels->First(); Channel && Channel->Number() <= LiveSetup().GetLastChannel(); Channel = (cChannel *)Channels->Next(Channel)) { + if (Channel->GroupSep()) { + continue; + } + const cSchedule *Schedule; + { + LOCK_SCHEDULES_READ; + Schedule = Schedules->GetSchedule(Channel); + } + if (!Schedule) { + continue; + } + const cEvent *Event = NULL; + if (type == "now") + Event = Schedule->GetPresentEvent(); + else if (type == "next") + Event = Schedule->GetFollowingEvent(); + else if (type == "at") + Event = Schedule->GetEventAround(seektime); - if (!Event && !LiveSetup().GetShowChannelsWithoutEPG()) continue; + if (!Event && !LiveSetup().GetShowChannelsWithoutEPG()) continue; - EpgInfoPtr epgEvent = EpgEvents::CreateEpgInfo(Channel, Event); - eventList.push_back(epgEvent); - } - } - } - else // get favorite broadcasts from epgsearch - { - SearchResults results; - SearchTimers timers; - for (SearchTimers::iterator timer = timers.begin(); timer != timers.end(); ++timer) { - if (!timer->UseInFavorites()) continue; - SearchResults curresults; - curresults.GetByID(timer->Id()); - results.merge(curresults); - } - time_t now = time(NULL); - for (SearchResults::iterator result = results.begin(); result != results.end(); ++result) { - long diff = result->StartTime() - now; - if (labs(diff) >= 24*60*60) continue; // skip broadcasts more than a day away - const cChannel* Channel = result->GetChannel(); - if (!Channel) continue; - EpgInfoPtr epgEvent = EpgEvents::CreateEpgInfo(Channel, result->GetEvent(Channel)); - eventList.push_back(epgEvent); - } - } + EpgInfoPtr epgEvent = EpgEvents::CreateEpgInfo(Channel, Event); + eventList.push_back(epgEvent); + } + } + } + else // get favorite broadcasts from epgsearch + { + SearchResults results; + SearchTimers timers; + for (SearchTimers::iterator timer = timers.begin(); timer != timers.end(); ++timer) { + if (!timer->UseInFavorites()) continue; + SearchResults curresults; + curresults.GetByID(timer->Id()); + results.merge(curresults); + } + time_t now = time(NULL); + for (SearchResults::iterator result = results.begin(); result != results.end(); ++result) { + long diff = result->StartTime() - now; + if (labs(diff) >= 24*60*60) continue; // skip broadcasts more than a day away + const cChannel* Channel = result->GetChannel(); + if (!Channel) continue; + EpgInfoPtr epgEvent = EpgEvents::CreateEpgInfo(Channel, result->GetEvent(Channel)); + eventList.push_back(epgEvent); + } + } - // display broadcasts - for(std::list::iterator i = eventList.begin(); i != eventList.end(); ++i ) { - EpgInfoPtr epgEvent = *i; + // display broadcasts + for(std::list::iterator i = eventList.begin(); i != eventList.end(); ++i ) { + EpgInfoPtr epgEvent = *i; - bool truncated = false; - std::string truncDescription(StringWordTruncate(epgEvent->LongDescr(), maximumTruncDescriptionLength, truncated)); - std::string longDescription = StringEscapeAndBreak(StringWordTruncate(epgEvent->LongDescr(), LiveSetup().GetMaxTooltipChars())) - + "

" + tr("Click to view details."); - const cChannel* Channel = epgEvent->Channel(); - if (!Channel) continue; - int chNumber = Channel->Number(); + bool truncated = false; + std::string truncDescription(StringWordTruncate(epgEvent->LongDescr(), maximumTruncDescriptionLength, truncated)); + std::string longDescription = StringEscapeAndBreak(StringWordTruncate(epgEvent->LongDescr(), LiveSetup().GetMaxTooltipChars())) + + "

" + tr("Click to view details."); + const cChannel* Channel = epgEvent->Channel(); + if (!Channel) continue; + int chNumber = Channel->Number(); - std::string startTime(epgEvent->StartTime(tr("%I:%M %p"))); - std::string endTime(epgEvent->EndTime(tr("%I:%M %p"))); - std::string startDate(epgEvent->StartTime(tr("%a, %x"))); + std::string startTime(epgEvent->StartTime(tr("%I:%M %p"))); + std::string endTime(epgEvent->EndTime(tr("%I:%M %p"))); + std::string startDate(epgEvent->StartTime(tr("%a, %x"))); - std::string timeSpan(startTime + " - " + endTime); + std::string timeSpan(startTime + " - " + endTime); - if (startTime.empty() && endTime.empty()) { - timeSpan = mode=="detail" ? headTime : std::string(); - startDate = headDate; - } - if (mode == "detail") { + if (startTime.empty() && endTime.empty()) { + timeSpan = mode=="detail" ? headTime : std::string(); + startDate = headDate; + } + if (mode == "detail") { -
- -
-
- <& pageelems.epg_tool_box detail=(1) epgid=(epgEvent->Id()) title=(epgEvent->Title()) startTime=(epgEvent->GetStartTime()) endTime=(epgEvent->GetEndTime()) &> -
-
-
<$ (startDate) $>
<$ (timeSpan) $>
-
<& pageelems.progressbar progress=(epgEvent->Elapsed()) duration=(epgEvent->Duration()) &>
-
<$ (epgEvent->Title()) $>
-
<$ (epgEvent->ShortDescr()) $>
-
<$ truncDescription $> -% if (truncated) { - ...
-
-
-
+
+ +
+
+ <& pageelems.epg_tool_box detail=(1) epgid=(epgEvent->Id()) title=(epgEvent->Title()) startTime=(epgEvent->GetStartTime()) endTime=(epgEvent->GetEndTime()) &> +
+
+
<$ (startDate) $>
<$ (timeSpan) $>
+
<& pageelems.progressbar progress=(epgEvent->Elapsed()) duration=(epgEvent->Duration()) &>
+
<$ (epgEvent->Title()) $>
+
<$ (epgEvent->ShortDescr()) $>
+
<$ truncDescription $> +% if (truncated) { + ...
+
+
+
<%cpp> - } else { // mode == "list" - std::list::iterator last = i; - bool lastCurrentChanel = (++last == eventList.end()); - tChannelID chanId; - tEventID eventId; - EpgEvents::DecodeDomId(epgEvent->Id(), chanId, eventId); + } else { // mode == "list" + std::list::iterator last = i; + bool lastCurrentChanel = (++last == eventList.end()); + tChannelID chanId; + tEventID eventId; + EpgEvents::DecodeDomId(epgEvent->Id(), chanId, eventId); - // Searching for channel logos - std::string chanlogoimg; - if (!LiveSetup().GetChanLogoDir().empty() ) { - std::string chanlogofile = StringReplace(epgEvent->Caption(), "/", "_") + ".png"; - std::string chanlogopath = LiveSetup().GetChanLogoDir() + chanlogofile; - struct stat chanfilebuf; + // Searching for channel logos + std::string chanlogoimg; + if (!LiveSetup().GetChanLogoDir().empty() ) { + std::string chanlogofile = StringReplace(epgEvent->Caption(), "/", "_") + ".png"; + std::string chanlogopath = LiveSetup().GetChanLogoDir() + chanlogofile; + struct stat chanfilebuf; bool logo_available = stat (chanlogopath.c_str(), &chanfilebuf) == 0; if (!logo_available) { chanlogofile = std::string(cToSvToLower(chanlogofile, g_locale)); chanlogopath = LiveSetup().GetChanLogoDir() + chanlogofile; logo_available = stat (chanlogopath.c_str(), &chanfilebuf) == 0; } - if (logo_available) { - chanlogoimg = "\"");Caption()); chanlogoimg.append("\" loading=\"lazy\" class=\"channel_logo\">"); - } + } } -
- <& pageelems.epg_tool_box detail=(0) epgid=(epgEvent->Id()) title=(epgEvent->Title()) startTime=(epgEvent->GetStartTime()) endTime=(epgEvent->GetEndTime()) lastCurrentChanel=(lastCurrentChanel ? 1 : 0) &> - - - - -% } + + <& pageelems.epg_tool_box detail=(0) epgid=(epgEvent->Id()) title=(epgEvent->Title()) startTime=(epgEvent->GetStartTime()) endTime=(epgEvent->GetEndTime()) lastCurrentChanel=(lastCurrentChanel ? 1 : 0) &> + + + + +% } <%cpp> - } + } -% if (mode == "list") { -
<$ head $>
"> -
-
<$ (timeSpan) $>
-
<& pageelems.progressbar progress=(epgEvent->Elapsed()) duration=(epgEvent->Duration()) &>
-
-
"> -% if (eventId != 0) { - "> -
"> +
+
<$ (timeSpan) $>
+
<& pageelems.progressbar progress=(epgEvent->Elapsed()) duration=(epgEvent->Duration()) &>
+
+
"> +% if (eventId != 0) { + "> +
+% if (mode == "list") { + % } -
- + + <%include>page_exit.eh @@ -291,15 +291,15 @@ if (type == "now") { | "><$ tr("What's on") $> | diff --git a/pages/xmlresponse.ecpp b/pages/xmlresponse.ecpp index 046a96e..de071ea 100644 --- a/pages/xmlresponse.ecpp +++ b/pages/xmlresponse.ecpp @@ -12,11 +12,11 @@ std::string const XMLHEADER = " <%args> - std::string name; - std::string pname; - std::string value; - bool result; - std::string error; + std::string name; + std::string pname; + std::string value; + bool result; + std::string error; <$$ XMLHEADER $> @@ -32,43 +32,43 @@ std::string const XMLHEADER = " <%args> - int update; - std::string type; - std::string currentTime; - std::string caption; - std::string title; - std::string duration; - int elapsed; - std::string prev_chan; - std::string next_chan; - std::string infoMsg; - std::string infoUrl; + int update; + std::string type; + std::string currentTime; + std::string caption; + std::string title; + std::string duration; + int elapsed; + std::string prev_chan; + std::string next_chan; + std::string infoMsg; + std::string infoUrl; <$$ XMLHEADER $> - <$ update $> + <$ update $> 1 - <$ update $> - - <$ type $> - <$ caption $> - <$ currentTime $> - <$ title $> - <$ duration $> - <$ elapsed $> - <$ next_chan $> - <$ prev_chan $> - + <$ update $> + + <$ type $> + <$ caption $> + <$ currentTime $> + <$ title $> + <$ duration $> + <$ elapsed $> + <$ next_chan $> + <$ prev_chan $> + <%cpp> if (!infoMsg.empty()) { - <$ infoMsg $> + <$ infoMsg $> <$ infoUrl $> <%cpp> diff --git a/preload.cpp b/preload.cpp index 7e02c1b..17c3f67 100644 --- a/preload.cpp +++ b/preload.cpp @@ -12,118 +12,118 @@ namespace vdrlive { // (cd live; find * -type f ! -wholename '*CVS*' ! -wholename '*themes*' ! -name '*~' ! -name '.*') | awk '{print "\"" $1 "\","}' // and clean out unneeded entries. - void PreLoadFileCache(std::string const& configDir) - { - static char const * const preloadFiles[] = { - "css/siteprefs.css", - "css/styles.css", - "img/rounded-box-blue-bl.png", - "img/rounded-box-blue-br.png", - "img/rounded-box-blue-ml.png", - "img/rounded-box-blue-mr.png", - "img/rounded-box-blue-tr.png", - "img/rounded-box-green-bl.png", - "img/rounded-box-blue-tl.png", - "img/rounded-box-green-br.png", - "img/rounded-box-green-ml.png", - "img/rounded-box-green-mr.png", - "img/del.png", - "img/info-win-t-r.png", - "img/info-win-m-l.png", - "img/info-win-m-r.png", - "img/info-win-b-l.png", - "img/info-win-b-r.png", - "img/close_red.png", - "img/info-win-t-l.png", - "img/rounded-box-green-tl.png", - "img/rounded-box-green-tr.png", - "img/rounded-box-orange-bl.png", - "img/rounded-box-orange-br.png", - "img/rounded-box-orange-ml.png", - "img/rounded-box-orange-mr.png", - "img/rounded-box-orange-tl.png", - "img/rounded-box-orange-tr.png", - "img/active.png", - "img/arrow.png", - "img/bg_box_h.png", - "img/bg_box_l.png", - "img/bg_box_r.png", - "img/bg_header_h.png", - "img/bg_header_l.png", - "img/bg_header_r.png", - "img/bg_line.png", - "img/bg_line_top.png", - "img/bg_tools.png", - "img/button_blue.png", - "img/button_green.png", - "img/button_new.png", - "img/button_red.png", - "img/button_yellow.png", - "img/close.png", - "img/edit.png", - "img/ffw.png", - "img/file.png", - "img/folder_closed.png", - "img/folder_open.png", - "img/help.png", - "img/imdb.png", - "img/inactive.png", - "img/logo_login.png", - "img/logo.png", - "img/menu_line_bg.png", - "img/minus.png", - "img/movie.png", - "img/on_dvd.png", - "img/one_downarrow.png", - "img/one_uparrow.png", - "img/pause.png", - "img/play.png", - "img/plus.png", - "img/record.png", - "img/record_timer.png", - "img/recording_timer.gif", - "img/reload.png", - "img/rwd.png", - "img/search.png", - "img/stop.png", - "img/stop_update.png", - "img/transparent.png", - "img/zap.png", - "img/remotecontrol.jpg", - "img/tv.jpg", - "img/arrow_rec.gif", - "img/favicon.ico", - "img/playlist.png", - "img/sd.png", - "img/hd.png", - "img/rd.png", - "img/RecordingErrors.png", - "img/NoRecordingErrors.png", - "img/NotCheckedForRecordingErrors.png", - "js/live/browserwin.js", - "js/live/vdr_status.js", - "js/live/infowin.js", - "js/live/header.js", - "js/live/liveajax.js", - "js/live/hinttips.js", - "js/live/pageenhance.js", - "js/live/createHtml.js", - "js/live/epg_tt_box.js", - "js/live/treeview.js", - "js/mootools/mootools.v1.11.js", - "html/back.html", - 0 - }; + void PreLoadFileCache(std::string const& configDir) + { + static char const * const preloadFiles[] = { + "css/siteprefs.css", + "css/styles.css", + "img/rounded-box-blue-bl.png", + "img/rounded-box-blue-br.png", + "img/rounded-box-blue-ml.png", + "img/rounded-box-blue-mr.png", + "img/rounded-box-blue-tr.png", + "img/rounded-box-green-bl.png", + "img/rounded-box-blue-tl.png", + "img/rounded-box-green-br.png", + "img/rounded-box-green-ml.png", + "img/rounded-box-green-mr.png", + "img/del.png", + "img/info-win-t-r.png", + "img/info-win-m-l.png", + "img/info-win-m-r.png", + "img/info-win-b-l.png", + "img/info-win-b-r.png", + "img/close_red.png", + "img/info-win-t-l.png", + "img/rounded-box-green-tl.png", + "img/rounded-box-green-tr.png", + "img/rounded-box-orange-bl.png", + "img/rounded-box-orange-br.png", + "img/rounded-box-orange-ml.png", + "img/rounded-box-orange-mr.png", + "img/rounded-box-orange-tl.png", + "img/rounded-box-orange-tr.png", + "img/active.png", + "img/arrow.png", + "img/bg_box_h.png", + "img/bg_box_l.png", + "img/bg_box_r.png", + "img/bg_header_h.png", + "img/bg_header_l.png", + "img/bg_header_r.png", + "img/bg_line.png", + "img/bg_line_top.png", + "img/bg_tools.png", + "img/button_blue.png", + "img/button_green.png", + "img/button_new.png", + "img/button_red.png", + "img/button_yellow.png", + "img/close.png", + "img/edit.png", + "img/ffw.png", + "img/file.png", + "img/folder_closed.png", + "img/folder_open.png", + "img/help.png", + "img/imdb.png", + "img/inactive.png", + "img/logo_login.png", + "img/logo.png", + "img/menu_line_bg.png", + "img/minus.png", + "img/movie.png", + "img/on_dvd.png", + "img/one_downarrow.png", + "img/one_uparrow.png", + "img/pause.png", + "img/play.png", + "img/plus.png", + "img/record.png", + "img/record_timer.png", + "img/recording_timer.gif", + "img/reload.png", + "img/rwd.png", + "img/search.png", + "img/stop.png", + "img/stop_update.png", + "img/transparent.png", + "img/zap.png", + "img/remotecontrol.jpg", + "img/tv.jpg", + "img/arrow_rec.gif", + "img/favicon.ico", + "img/playlist.png", + "img/sd.png", + "img/hd.png", + "img/rd.png", + "img/RecordingErrors.png", + "img/NoRecordingErrors.png", + "img/NotCheckedForRecordingErrors.png", + "js/live/browserwin.js", + "js/live/vdr_status.js", + "js/live/infowin.js", + "js/live/header.js", + "js/live/liveajax.js", + "js/live/hinttips.js", + "js/live/pageenhance.js", + "js/live/createHtml.js", + "js/live/epg_tt_box.js", + "js/live/treeview.js", + "js/mootools/mootools.v1.11.js", + "html/back.html", + 0 + }; - FileCache& fc = LiveFileCache(); - size_t i = 0; - while (preloadFiles[i]) { - FileCache::ptr_type f = fc.get(configDir + "/" + preloadFiles[i]); - if (0 == f.get()) { - isyslog("live: can't preload %s/%s! Generated pages might be degraded!", configDir.c_str(), preloadFiles[i]); - } - i++; - } - isyslog("live: initial file cache has %zu entries and needs %zu bytes of data!", fc.count(), fc.weight()); - } + FileCache& fc = LiveFileCache(); + size_t i = 0; + while (preloadFiles[i]) { + FileCache::ptr_type f = fc.get(configDir + "/" + preloadFiles[i]); + if (0 == f.get()) { + isyslog("live: can't preload %s/%s! Generated pages might be degraded!", configDir.c_str(), preloadFiles[i]); + } + i++; + } + isyslog("live: initial file cache has %zu entries and needs %zu bytes of data!", fc.count(), fc.weight()); + } } diff --git a/preload.h b/preload.h index b408072..f19f7f9 100644 --- a/preload.h +++ b/preload.h @@ -5,7 +5,7 @@ namespace vdrlive { - void PreLoadFileCache(std::string const& configDir); + void PreLoadFileCache(std::string const& configDir); }; #endif // VDR_LIVE_PRELOAD_H diff --git a/recman.cpp b/recman.cpp index 70b7d24..9c02eac 100644 --- a/recman.cpp +++ b/recman.cpp @@ -51,46 +51,46 @@ template void StringAppendFrameParams(std::string &s, const cRecord template void StringAppendFrameParams>(cToSvConcat<0> &s, const cRecording *rec); template void StringAppendFrameParams>(cToSvConcat<255> &s, const cRecording *rec); - /** - * Implementation of class RecordingsManager: - */ - std::weak_ptr RecordingsManager::m_recMan; - std::shared_ptr RecordingsManager::m_recTree; - cStateKey RecordingsManager::m_recordingsStateKey; + /** + * Implementation of class RecordingsManager: + */ + std::weak_ptr RecordingsManager::m_recMan; + std::shared_ptr RecordingsManager::m_recTree; + cStateKey RecordingsManager::m_recordingsStateKey; time_t scraperLastRecordingsUpdate; - // The RecordingsManager holds a VDR lock on the - // Recordings. Additionally the singleton instance of - // RecordingsManager is held in a weak pointer. If it is not in - // use any longer, it will be freed automatically, which leads to a - // release of the VDR recordings lock. Upon requesting access to - // the RecordingsManager via LiveRecordingsManger function, first - // the weak ptr is locked (obtaining a std::shared_ptr from an possible - // existing instance) and if not successful a new instance is - // created, which again locks the VDR Recordings. - // - // RecordingsManager provides factory methods to obtain other - // recordings data structures. The data structures returned keep if - // needed the instance of RecordingsManager alive until destructed - // themselves. This way the use of LIVE::recordings is straight - // forward and does hide the locking needs from the user. - - RecordingsManager::RecordingsManager() - { - } - - RecordingsTreePtr RecordingsManager::GetRecordingsTree() const - { - RecordingsManagerPtr recMan = EnsureValidData(); - if (! recMan) { + // The RecordingsManager holds a VDR lock on the + // Recordings. Additionally the singleton instance of + // RecordingsManager is held in a weak pointer. If it is not in + // use any longer, it will be freed automatically, which leads to a + // release of the VDR recordings lock. Upon requesting access to + // the RecordingsManager via LiveRecordingsManger function, first + // the weak ptr is locked (obtaining a std::shared_ptr from an possible + // existing instance) and if not successful a new instance is + // created, which again locks the VDR Recordings. + // + // RecordingsManager provides factory methods to obtain other + // recordings data structures. The data structures returned keep if + // needed the instance of RecordingsManager alive until destructed + // themselves. This way the use of LIVE::recordings is straight + // forward and does hide the locking needs from the user. + + RecordingsManager::RecordingsManager() + { + } + + RecordingsTreePtr RecordingsManager::GetRecordingsTree() const + { + RecordingsManagerPtr recMan = EnsureValidData(); + if (! recMan) { esyslog("live, ERROR, recMan == nullptr after call to EnsureValidData"); - return RecordingsTreePtr(recMan, std::shared_ptr()); - } - return RecordingsTreePtr(recMan, m_recTree); - } + return RecordingsTreePtr(recMan, std::shared_ptr()); + } + return RecordingsTreePtr(recMan, m_recTree); + } - cRecording const * RecordingsManager::GetByMd5Hash(cSv hash) const - { + cRecording const * RecordingsManager::GetByMd5Hash(cSv hash) const + { if (hash.length() != 42) return 0; if (hash.compare(0, 10, "recording_") != 0) return 0; XXH128_hash_t xxh = parse_hex_128(hash.substr(10)); @@ -99,11 +99,11 @@ template void StringAppendFrameParams>(cToSvConcat<255> &s, con XXH128_hash_t xxh_rec = XXH3_128bits(rec->FileName(), strlen(rec->FileName())); if (xxh_rec.high64 == xxh.high64 && xxh_rec.low64 == xxh.low64) return rec; } - return 0; - } + return 0; + } - RecordingsItemRecPtr const RecordingsManager::GetByIdHash(cSv hash) const - { + RecordingsItemRecPtr const RecordingsManager::GetByIdHash(cSv hash) const + { if (hash.length() != 42) return 0; if (hash.compare(0, 10, "recording_") != 0) return 0; XXH128_hash_t xxh = parse_hex_128(hash.substr(10)); @@ -111,97 +111,97 @@ template void StringAppendFrameParams>(cToSvConcat<255> &s, con XXH128_hash_t xxh_rec = recItem->IdHash(); if (xxh_rec.high64 == xxh.high64 && xxh_rec.low64 == xxh.low64) return recItem; } - return 0; - } - - bool RecordingsManager::UpdateRecording(cRecording const * recording, cSv directory, cSv name, bool copy, cSv title, cSv shorttext, cSv description) const - { - if (!recording) - return false; - - std::string oldname = recording->FileName(); - size_t found = oldname.find_last_of("/"); - - if (found == std::string::npos) - return false; - - std::string filename = FileSystemExchangeChars(directory.empty() ? name : (StringReplace(directory, "/", "~") + "~").append(name), true); - - // Check for injections that try to escape from the video dir. - if (filename.compare(0, 3, "..~") == 0 || filename.find("~..") != std::string::npos) { - esyslog("live: renaming failed: new name invalid \"%.*s\"", (int)filename.length(), filename.data()); - return false; - } - - std::string newname = concat(cVideoDirectory::Name(), "/", filename, cSv(oldname).substr(found)); - - if (!MoveDirectory(oldname, newname, copy)) { - esyslog("live: renaming failed from '%.*s' to '%s'", (int)oldname.length(), oldname.data(), newname.c_str()); - return false; - } - - LOCK_RECORDINGS_WRITE; - if (!copy) - Recordings->DelByName(oldname.c_str()); - Recordings->AddByName(newname.c_str()); - recording = Recordings->GetByName(newname.c_str()); // old pointer to recording invalid after DelByName/AddByName - cRecordingUserCommand::InvokeCommand(*cString::sprintf("rename \"%s\"", *strescape(oldname.c_str(), "\\\"$'")), newname.c_str()); - - // update texts - // need null terminated strings for VDR API - std::string desc(description); - desc.erase(std::remove(desc.begin(), desc.end(), '\r'), desc.end()); // remove \r from HTML - - cRecordingInfo* info = recording->Info(); - if (title != cSv(info->Title()) || shorttext != cSv(info->ShortText()) || desc != cSv(info->Description())) - { - info->SetData(title.empty() ? nullptr : std::string(title).c_str(), shorttext.empty() ? nullptr : std::string(shorttext).c_str(), desc.empty() ? nullptr : desc.c_str()); - info->Write(); - } - - return true; - } - - void RecordingsManager::DeleteResume(cRecording const * recording) const - { - if (!recording) - return; - - cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording()); - ResumeFile.Delete(); - } - - void RecordingsManager::DeleteMarks(cRecording const * recording) const - { - if (!recording) - return; - - cMarks marks; - marks.Load(recording->FileName()); - if (marks.Count()) { - cMark *mark = marks.First(); - while (mark) { - cMark *nextmark = marks.Next(mark); - marks.Del(mark); - mark = nextmark; - } - marks.Save(); - } - } - - void RecordingsManager::DeleteRecording(cRecording const * recording) const - { - if (!recording) - return; - - std::string name(recording->FileName()); - const_cast(recording)->Delete(); - LOCK_RECORDINGS_WRITE; - Recordings->DelByName(name.c_str()); - } - - int RecordingsManager::GetArchiveType(cRecording const * recording) - { + return 0; + } + + bool RecordingsManager::UpdateRecording(cRecording const * recording, cSv directory, cSv name, bool copy, cSv title, cSv shorttext, cSv description) const + { + if (!recording) + return false; + + std::string oldname = recording->FileName(); + size_t found = oldname.find_last_of("/"); + + if (found == std::string::npos) + return false; + + std::string filename = FileSystemExchangeChars(directory.empty() ? name : (StringReplace(directory, "/", "~") + "~").append(name), true); + + // Check for injections that try to escape from the video dir. + if (filename.compare(0, 3, "..~") == 0 || filename.find("~..") != std::string::npos) { + esyslog("live: renaming failed: new name invalid \"%.*s\"", (int)filename.length(), filename.data()); + return false; + } + + std::string newname = concat(cVideoDirectory::Name(), "/", filename, cSv(oldname).substr(found)); + + if (!MoveDirectory(oldname, newname, copy)) { + esyslog("live: renaming failed from '%.*s' to '%s'", (int)oldname.length(), oldname.data(), newname.c_str()); + return false; + } + + LOCK_RECORDINGS_WRITE; + if (!copy) + Recordings->DelByName(oldname.c_str()); + Recordings->AddByName(newname.c_str()); + recording = Recordings->GetByName(newname.c_str()); // old pointer to recording invalid after DelByName/AddByName + cRecordingUserCommand::InvokeCommand(*cString::sprintf("rename \"%s\"", *strescape(oldname.c_str(), "\\\"$'")), newname.c_str()); + + // update texts + // need null terminated strings for VDR API + std::string desc(description); + desc.erase(std::remove(desc.begin(), desc.end(), '\r'), desc.end()); // remove \r from HTML + + cRecordingInfo* info = recording->Info(); + if (title != cSv(info->Title()) || shorttext != cSv(info->ShortText()) || desc != cSv(info->Description())) + { + info->SetData(title.empty() ? nullptr : std::string(title).c_str(), shorttext.empty() ? nullptr : std::string(shorttext).c_str(), desc.empty() ? nullptr : desc.c_str()); + info->Write(); + } + + return true; + } + + void RecordingsManager::DeleteResume(cRecording const * recording) const + { + if (!recording) + return; + + cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording()); + ResumeFile.Delete(); + } + + void RecordingsManager::DeleteMarks(cRecording const * recording) const + { + if (!recording) + return; + + cMarks marks; + marks.Load(recording->FileName()); + if (marks.Count()) { + cMark *mark = marks.First(); + while (mark) { + cMark *nextmark = marks.Next(mark); + marks.Del(mark); + mark = nextmark; + } + marks.Save(); + } + } + + void RecordingsManager::DeleteRecording(cRecording const * recording) const + { + if (!recording) + return; + + std::string name(recording->FileName()); + const_cast(recording)->Delete(); + LOCK_RECORDINGS_WRITE; + Recordings->DelByName(name.c_str()); + } + + int RecordingsManager::GetArchiveType(cRecording const * recording) + { // 1: on DVD // 2: on HDD // 0: "normal" VDR recording @@ -218,90 +218,90 @@ template void StringAppendFrameParams>(cToSvConcat<255> &s, con if (stat (file, &buffer) == 0) return 2; // stat is 10% faster than access on my system. On others, there is a larger difference // see https://stackoverflow.com/questions/12774207/fastest-way-to-check-if-a-file-exists-using-standard-c-c11-14-17-c - return 0; - } - - std::string const RecordingsManager::GetArchiveId(cRecording const * recording, int archiveType) - { - std::string filename = recording->FileName(); - - if (archiveType==1) { - std::string dvdFile = filename + "/dvd.vdr"; - std::ifstream dvd(dvdFile); - - if (dvd) { - std::string archiveDisc; - std::string videoDisc; - dvd >> archiveDisc; - if ("0000" == archiveDisc) { - dvd >> videoDisc; - return videoDisc; - } - return archiveDisc; - } - } else if(archiveType==2) { - std::string hddFile = filename + "/hdd.vdr"; - std::ifstream hdd(hddFile); - - if (hdd) { - std::string archiveDisc; - hdd >> archiveDisc; - return archiveDisc; - } - } - return ""; - } - - std::string const RecordingsManager::GetArchiveDescr(cRecording const * recording) - { - int archiveType; - std::string archived; - archiveType = GetArchiveType(recording); - if (archiveType==1) { - archived += " ["; - archived += tr("On archive DVD No."); - archived += ": "; - archived += GetArchiveId(recording, archiveType); - archived += "]"; - } else if (archiveType==2) { - archived += " ["; - archived += tr("On archive HDD No."); - archived += ": "; - archived += GetArchiveId(recording, archiveType); - archived += "]"; - } - return archived; - } - - bool RecordingsManager::StateChanged () - { - bool result = false; - - // will return true only, if the Recordings List has been changed since last read - if (cRecordings::GetRecordingsRead(m_recordingsStateKey)) { - result = true; - m_recordingsStateKey.Remove(); - } - - return result; - } - - RecordingsManagerPtr RecordingsManager::EnsureValidData() - { - // Get singleton instance of RecordingsManager. 'this' is not - // an instance of std::shared_ptr of the singleton - // RecordingsManager, so we obtain it in the overall - // recommended way. - RecordingsManagerPtr recMan = LiveRecordingsManager(); - if (! recMan) { - // theoretically this code is never reached ... - esyslog("live: lost RecordingsManager instance while using it!"); - recMan = RecordingsManagerPtr(); - } - - // StateChanged must be executed every time, so not part of - // the short cut evaluation in the if statement below. - bool stateChanged = StateChanged(); + return 0; + } + + std::string const RecordingsManager::GetArchiveId(cRecording const * recording, int archiveType) + { + std::string filename = recording->FileName(); + + if (archiveType==1) { + std::string dvdFile = filename + "/dvd.vdr"; + std::ifstream dvd(dvdFile); + + if (dvd) { + std::string archiveDisc; + std::string videoDisc; + dvd >> archiveDisc; + if ("0000" == archiveDisc) { + dvd >> videoDisc; + return videoDisc; + } + return archiveDisc; + } + } else if(archiveType==2) { + std::string hddFile = filename + "/hdd.vdr"; + std::ifstream hdd(hddFile); + + if (hdd) { + std::string archiveDisc; + hdd >> archiveDisc; + return archiveDisc; + } + } + return ""; + } + + std::string const RecordingsManager::GetArchiveDescr(cRecording const * recording) + { + int archiveType; + std::string archived; + archiveType = GetArchiveType(recording); + if (archiveType==1) { + archived += " ["; + archived += tr("On archive DVD No."); + archived += ": "; + archived += GetArchiveId(recording, archiveType); + archived += "]"; + } else if (archiveType==2) { + archived += " ["; + archived += tr("On archive HDD No."); + archived += ": "; + archived += GetArchiveId(recording, archiveType); + archived += "]"; + } + return archived; + } + + bool RecordingsManager::StateChanged () + { + bool result = false; + + // will return true only, if the Recordings List has been changed since last read + if (cRecordings::GetRecordingsRead(m_recordingsStateKey)) { + result = true; + m_recordingsStateKey.Remove(); + } + + return result; + } + + RecordingsManagerPtr RecordingsManager::EnsureValidData() + { + // Get singleton instance of RecordingsManager. 'this' is not + // an instance of std::shared_ptr of the singleton + // RecordingsManager, so we obtain it in the overall + // recommended way. + RecordingsManagerPtr recMan = LiveRecordingsManager(); + if (! recMan) { + // theoretically this code is never reached ... + esyslog("live: lost RecordingsManager instance while using it!"); + recMan = RecordingsManagerPtr(); + } + + // StateChanged must be executed every time, so not part of + // the short cut evaluation in the if statement below. + bool stateChanged = StateChanged(); // check: changes on scraper data? cGetScraperUpdateTimes scraperUpdateTimes; if (scraperUpdateTimes.call(LiveSetup().GetPluginScraper()) ) { @@ -310,21 +310,21 @@ template void StringAppendFrameParams>(cToSvConcat<255> &s, con stateChanged = true; } } - if (stateChanged || (!m_recTree) ) { - if (stateChanged) { - m_recTree.reset(); - } - if (stateChanged || !m_recTree) { + if (stateChanged || (!m_recTree) ) { + if (stateChanged) { + m_recTree.reset(); + } + if (stateChanged || !m_recTree) { m_recTree = std::shared_ptr(new RecordingsTree(recMan)); - } - if (!m_recTree) { - esyslog("live: creation of recordings tree failed!"); - return RecordingsManagerPtr(); - } + } + if (!m_recTree) { + esyslog("live: creation of recordings tree failed!"); + return RecordingsManagerPtr(); + } - } - return recMan; - } + } + return recMan; + } ShortTextDescription::ShortTextDescription(const char * ShortText, const char * Description): m_short_text(ShortText), @@ -339,9 +339,9 @@ template void StringAppendFrameParams>(cToSvConcat<255> &s, con return std::tolower(result, g_locale); } - /** - * Implementation of class RecordingsItemPtrCompare - */ + /** + * Implementation of class RecordingsItemPtrCompare + */ int RecordingsItemPtrCompare::FindBestMatch(RecordingsItemRecPtr & BestMatch, const std::vector::const_iterator & First, const std::vector::const_iterator & Last, const RecordingsItemRecPtr & EPG_Entry) { // d: length of movie in minutes, without commercial breaks @@ -372,25 +372,25 @@ template void StringAppendFrameParams>(cToSvConcat<255> &s, con return numRecordings; } - bool RecordingsItemPtrCompare::ByAscendingDate(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) - { - return (first->StartTime() < second->StartTime()); - } + bool RecordingsItemPtrCompare::ByAscendingDate(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) + { + return (first->StartTime() < second->StartTime()); + } - bool RecordingsItemPtrCompare::ByDuplicatesName(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) // return first < second - { + bool RecordingsItemPtrCompare::ByDuplicatesName(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) // return first < second + { return first->orderDuplicates(second, false); - } + } - bool RecordingsItemPtrCompare::ByDuplicates(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) // return first < second - { + bool RecordingsItemPtrCompare::ByDuplicates(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) // return first < second + { return first->orderDuplicates(second, true); - } + } - bool RecordingsItemPtrCompare::ByDuplicatesLanguage(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) // return first < second - { + bool RecordingsItemPtrCompare::ByDuplicatesLanguage(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) // return first < second + { return first->orderDuplicates(second, true, true); - } + } size_t firstNonPunct(cSv s) { // returns first non-punct char in s @@ -427,29 +427,29 @@ template void StringAppendFrameParams>(cToSvConcat<255> &s, con } bool RecordingsItemPtrCompare::ByDescendingDurationDeviation(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) { return first->DurationDeviation() > second->DurationDeviation(); - } + } - bool RecordingsItemPtrCompare::ByEpisode(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) { - return first->scraperEpisodeNumber() < second->scraperEpisodeNumber(); - } + bool RecordingsItemPtrCompare::ByEpisode(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) { + return first->scraperEpisodeNumber() < second->scraperEpisodeNumber(); + } - bool RecordingsItemPtrCompare::BySeason(const RecordingsItemDirPtr & first, const RecordingsItemDirPtr & second) { - return first->scraperSeasonNumber() < second->scraperSeasonNumber(); - } + bool RecordingsItemPtrCompare::BySeason(const RecordingsItemDirPtr & first, const RecordingsItemDirPtr & second) { + return first->scraperSeasonNumber() < second->scraperSeasonNumber(); + } - bool RecordingsItemPtrCompare::ByReleaseDate(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) { - return first->scraperReleaseDate() < second->scraperReleaseDate(); - } + bool RecordingsItemPtrCompare::ByReleaseDate(const RecordingsItemRecPtr & first, const RecordingsItemRecPtr & second) { + return first->scraperReleaseDate() < second->scraperReleaseDate(); + } tCompRec RecordingsItemPtrCompare::getComp(eSortOrder sortOrder) { - switch (sortOrder) { - case eSortOrder::name: return &RecordingsItemPtrCompare::ByAscendingNameDescSort; - case eSortOrder::date: return &RecordingsItemPtrCompare::ByAscendingDate; - case eSortOrder::errors: return &RecordingsItemPtrCompare::ByDescendingRecordingErrors; - case eSortOrder::durationDeviation: return &RecordingsItemPtrCompare::ByDescendingDurationDeviation; - case eSortOrder::duplicatesLanguage: return &RecordingsItemPtrCompare::ByDuplicatesLanguage; - } - esyslog("live: ERROR, RecordingsItemPtrCompare::getComp, sortOrder %d unknown", (int)sortOrder); + switch (sortOrder) { + case eSortOrder::name: return &RecordingsItemPtrCompare::ByAscendingNameDescSort; + case eSortOrder::date: return &RecordingsItemPtrCompare::ByAscendingDate; + case eSortOrder::errors: return &RecordingsItemPtrCompare::ByDescendingRecordingErrors; + case eSortOrder::durationDeviation: return &RecordingsItemPtrCompare::ByDescendingDurationDeviation; + case eSortOrder::duplicatesLanguage: return &RecordingsItemPtrCompare::ByDuplicatesLanguage; + } + esyslog("live: ERROR, RecordingsItemPtrCompare::getComp, sortOrder %d unknown", (int)sortOrder); return &RecordingsItemPtrCompare::ByAscendingNameDescSort; } @@ -501,97 +501,97 @@ bool searchNameDesc(RecordingsItemRecPtr &RecItem, const std::vectornumberOfRecordings(); - return result; + for (const auto &item: m_subdirs) result += item->numberOfRecordings(); + return result; } - void RecordingsItemDir::finishRecordingsTree() { - for (auto &item: m_subdirs) item->finishRecordingsTree(); - if (m_cmp_rec) std::sort(m_entries.begin(), m_entries.end(), m_cmp_rec); - if (m_cmp_dir) std::sort(m_subdirs.begin(), m_subdirs.end(), m_cmp_dir); - else std::sort(m_subdirs.begin(), m_subdirs.end(), RecordingsItemPtrCompare::ByAscendingNameSort); - m_entries.shrink_to_fit(); - m_subdirs.shrink_to_fit(); + void RecordingsItemDir::finishRecordingsTree() { + for (auto &item: m_subdirs) item->finishRecordingsTree(); + if (m_cmp_rec) std::sort(m_entries.begin(), m_entries.end(), m_cmp_rec); + if (m_cmp_dir) std::sort(m_subdirs.begin(), m_subdirs.end(), m_cmp_dir); + else std::sort(m_subdirs.begin(), m_subdirs.end(), RecordingsItemPtrCompare::ByAscendingNameSort); + m_entries.shrink_to_fit(); + m_subdirs.shrink_to_fit(); } RecordingsItemDirPtr RecordingsItemDir::addDirIfNotExists(cSv dirName) { std::vector::iterator iter = std::lower_bound(m_subdirs.begin(), m_subdirs.end(), dirName); if (iter != m_subdirs.end() && !(dirName < *iter) ) return *iter; RecordingsItemDirPtr dirPtr = std::make_shared(dirName, Level() + 1); - m_subdirs.insert(iter, dirPtr); + m_subdirs.insert(iter, dirPtr); return dirPtr; - } + } RecordingsItemDirPtr RecordingsItemDir::addDirCollectionIfNotExists(int collectionId, const RecordingsItemRecPtr &rPtr) { std::vector::iterator iter = std::lower_bound(m_subdirs.begin(), m_subdirs.end(), collectionId); if (iter != m_subdirs.end() && !(collectionId < *iter) ) return *iter; - RecordingsItemDirPtr dirPtr2 = std::make_shared(Level() + 1, rPtr); - m_subdirs.insert(iter, dirPtr2); + RecordingsItemDirPtr dirPtr2 = std::make_shared(Level() + 1, rPtr); + m_subdirs.insert(iter, dirPtr2); return dirPtr2; - } + } RecordingsItemDirPtr RecordingsItemDir::addDirSeasonIfNotExists(int seasonNumber, const RecordingsItemRecPtr &rPtr) { std::vector::iterator iter = std::lower_bound(m_subdirs.begin(), m_subdirs.end(), seasonNumber); if (iter != m_subdirs.end() && !(seasonNumber < *iter) ) return *iter; - RecordingsItemDirPtr dirPtr2 = std::make_shared(Level() + 1, rPtr); - m_subdirs.insert(iter, dirPtr2); + RecordingsItemDirPtr dirPtr2 = std::make_shared(Level() + 1, rPtr); + m_subdirs.insert(iter, dirPtr2); return dirPtr2; - } + } - const std::vector *RecordingsItemDir::getRecordings(eSortOrder sortOrder) - { - if (m_cmp_rec) return &m_entries; - if (sortOrder == eSortOrder::name) { + const std::vector *RecordingsItemDir::getRecordings(eSortOrder sortOrder) + { + if (m_cmp_rec) return &m_entries; + if (sortOrder == eSortOrder::name) { if (!m_entriesSorted) { - std::sort(m_entries.begin(), m_entries.end(), RecordingsItemPtrCompare::getComp(eSortOrder::name)); + std::sort(m_entries.begin(), m_entries.end(), RecordingsItemPtrCompare::getComp(eSortOrder::name)); m_entriesSorted = true; - } - return &m_entries; - } - if (m_sortOrder == sortOrder) return &m_entries_other_sort; + } + return &m_entries; + } + if (m_sortOrder == sortOrder) return &m_entries_other_sort; if (m_entries_other_sort.empty() ) m_entries_other_sort = m_entries; - std::sort(m_entries_other_sort.begin(), m_entries_other_sort.end(), RecordingsItemPtrCompare::getComp(sortOrder)); - m_sortOrder = sortOrder; - return &m_entries_other_sort; - } + std::sort(m_entries_other_sort.begin(), m_entries_other_sort.end(), RecordingsItemPtrCompare::getComp(sortOrder)); + m_sortOrder = sortOrder; + return &m_entries_other_sort; + } bool RecordingsItemDir::checkNew() const{ - for (const auto &rec:m_entries) if (rec->checkNew()) return true; - for (const auto &subdir:m_subdirs) if (subdir->checkNew() ) return true; - return false; - } + for (const auto &rec:m_entries) if (rec->checkNew()) return true; + for (const auto &subdir:m_subdirs) if (subdir->checkNew() ) return true; + return false; + } void RecordingsItemDir::addDirList(std::vector &dirs, cSv basePath) const - { + { std::string basePath0(basePath); if (basePath.empty() ) dirs.push_back(""); else basePath0.append("/"); size_t basePath0_len = basePath0.length(); - for (const auto &subdir: m_subdirs) { + for (const auto &subdir: m_subdirs) { basePath0.erase(basePath0_len); basePath0.append(subdir->m_name); dirs.push_back(basePath0); subdir->addDirList(dirs, basePath0); } - } + } - void RecordingsItemDir::setTvShow(const RecordingsItemRecPtr &rPtr) { + void RecordingsItemDir::setTvShow(const RecordingsItemRecPtr &rPtr) { if (m_cmp_dir) return; m_cmp_dir = RecordingsItemPtrCompare::BySeason; m_imageLevels = cImageLevels(eImageLevel::tvShowCollection, eImageLevel::anySeasonCollection); m_rec_item = rPtr; m_s_season_number = m_rec_item->scraperSeasonNumber(); - } + } const cTvMedia &RecordingsItemDir::scraperImage() const { if (!m_s_image_requested) { @@ -602,34 +602,34 @@ bool searchNameDesc(RecordingsItemRecPtr &RecItem, const std::vectorm_s_collection_id; m_rec_item->m_scraperVideo->getOverview(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &m_name); - } + } - RecordingsItemDirCollection::~RecordingsItemDirCollection() { } + RecordingsItemDirCollection::~RecordingsItemDirCollection() { } - /** - * Implementation of class RecordingsItemDirSeason: - */ - RecordingsItemDirSeason::RecordingsItemDirSeason(int level, const RecordingsItemRecPtr &rPtr): - RecordingsItemDir(cToSvInt(rPtr->m_s_season_number), level) - { + /** + * Implementation of class RecordingsItemDirSeason: + */ + RecordingsItemDirSeason::RecordingsItemDirSeason(int level, const RecordingsItemRecPtr &rPtr): + RecordingsItemDir(cToSvInt(rPtr->m_s_season_number), level) + { m_cmp_rec = RecordingsItemPtrCompare::ByEpisode; // m_imageLevels = cImageLevels(eImageLevel::seasonMovie, eImageLevel::tvShowCollection, eImageLevel::anySeasonCollection); m_imageLevels = cImageLevels(eImageLevel::seasonMovie); m_rec_item = rPtr; m_s_season_number = m_rec_item->m_s_season_number; - } - RecordingsItemDirSeason::~RecordingsItemDirSeason() { } + } + RecordingsItemDirSeason::~RecordingsItemDirSeason() { } int GetNumberOfTsFiles(const cRecording* recording) { // find our number of ts files @@ -646,17 +646,17 @@ bool searchNameDesc(RecordingsItemRecPtr &RecItem, const std::vectorId()), - m_recording(recording), + m_recording(recording), m_hash(XXH3_128bits(recording->FileName(), strlen(recording->FileName()) )), - m_isArchived(RecordingsManager::GetArchiveType(m_recording) ) - { + m_isArchived(RecordingsManager::GetArchiveType(m_recording) ) + { // dsyslog("live: REC: C: rec %s -> %s", name.c_str(), parent->Name().c_str()); timeItemRec->start(); m_timeIdentify = timeIdentify; @@ -669,15 +669,15 @@ bool searchNameDesc(RecordingsItemRecPtr &RecItem, const std::vectorstop(); - } + } - RecordingsItemRec::~RecordingsItemRec() - { - // dsyslog("live: REC: D: rec %s", Name().c_str()); - } + RecordingsItemRec::~RecordingsItemRec() + { + // dsyslog("live: REC: D: rec %s", Name().c_str()); + } std::string RecordingsItemRec::GetNameForSearch(cSv name) - { + { std::string result; result.reserve(name.length()); const char *name_c = name.data(); @@ -687,7 +687,7 @@ bool searchNameDesc(RecordingsItemRecPtr &RecItem, const std::vector(codepoint, g_locale) ) stringAppendUtfCodepoint(result, std::tolower(codepoint, g_locale)); } return result; - } + } bool RecordingsItemRec::matchesFilter(cSv filter) const { if (filter.empty() ) return true; @@ -700,7 +700,7 @@ bool searchNameDesc(RecordingsItemRecPtr &RecItem, const std::vectorstart(); cGetScraperVideo getScraperVideo(NULL, m_recording); if (m_timeIdentify) m_timeIdentify->start(); @@ -726,7 +726,7 @@ bool searchNameDesc(RecordingsItemRecPtr &RecItem, const std::vectorstop(); - } + } const cTvMedia &RecordingsItemRec::scraperImage() const { if (!m_s_image_requested) { m_s_image_requested = true; @@ -738,10 +738,10 @@ bool searchNameDesc(RecordingsItemRecPtr &RecItem, const std::vectorNameForSearch() ); if(i != 0) return i; @@ -1027,9 +1027,9 @@ void AppendScraperData(cToSvConcat<0> &target, cSv s_IMDB_ID, const cTvMedia &s_ } } - /** - * Implementation of class RecordingsItemDummy - */ + /** + * Implementation of class RecordingsItemDummy + */ RecordingsItemDummy::RecordingsItemDummy(const cEvent *event, cScraperVideo *scraperVideo): RecordingsItemRec(event->Title() ), m_event(event) @@ -1052,13 +1052,13 @@ void AppendScraperData(cToSvConcat<0> &target, cSv s_IMDB_ID, const cTvMedia &s_ bool operator< (int a, const RecordingsItemDirPtr &b) { return *b > a; } bool operator< (const RecordingsItemDirPtr &a, int b) { return *a < b; } - /** - * Implementation of class RecordingsTree: - */ - RecordingsTree::RecordingsTree(RecordingsManagerPtr recMan) : - m_maxLevel(0), - m_root(std::make_shared("", 0)) - { + /** + * Implementation of class RecordingsTree: + */ + RecordingsTree::RecordingsTree(RecordingsManagerPtr recMan) : + m_maxLevel(0), + m_root(std::make_shared("", 0)) + { // esyslog("live: DH: ****** RecordingsTree::RecordingsTree() ********"); cMeasureTime timeRecs, timeIdentify, timeOverview, timeImage, timeDurationDeviation, timeNumTsFiles, timeItemRec; @@ -1066,7 +1066,7 @@ void AppendScraperData(cToSvConcat<0> &target, cSv s_IMDB_ID, const cTvMedia &s_ // check availability of scraper data m_creation_timestamp = time(0); cGetScraperVideo getScraperVideo; - bool scraperDataAvailable = getScraperVideo.call(LiveSetup().GetPluginScraper()); + bool scraperDataAvailable = getScraperVideo.call(LiveSetup().GetPluginScraper()); RecordingsItemDirPtr recPtrTvShows = std::make_shared(tr("TV shows"), 1); RecordingsItemDirPtr recPtrMovieCollections = std::make_shared(tr("Movie collections"), 1); // create "base" folders @@ -1083,10 +1083,10 @@ void AppendScraperData(cToSvConcat<0> &target, cSv s_IMDB_ID, const cTvMedia &s_ m_root->m_subdirs.push_back(recPtrOthers); } else { m_rootFileSystem = m_root; - } + } // add all recordings - LOCK_RECORDINGS_READ; - for (cRecording* recording = (cRecording *)Recordings->First(); recording; recording = (cRecording *)Recordings->Next(recording)) { + LOCK_RECORDINGS_READ; + for (cRecording* recording = (cRecording *)Recordings->First(); recording; recording = (cRecording *)Recordings->Next(recording)) { if (scraperDataAvailable) m_maxLevel = std::max(m_maxLevel, recording->HierarchyLevels() + 1); else m_maxLevel = std::max(m_maxLevel, recording->HierarchyLevels() ); @@ -1132,7 +1132,7 @@ void AppendScraperData(cToSvConcat<0> &target, cSv s_IMDB_ID, const cTvMedia &s_ } } } while (pos != std::string::npos); - } + } if (scraperDataAvailable) { for (auto it = recPtrTvShows->m_subdirs.begin(); it != recPtrTvShows->m_subdirs.end(); ) { if ((*it)->numberOfRecordings() < 2) it = recPtrTvShows->m_subdirs.erase(it); @@ -1142,8 +1142,8 @@ void AppendScraperData(cToSvConcat<0> &target, cSv s_IMDB_ID, const cTvMedia &s_ if ((*it)->numberOfRecordings() < 2) it = recPtrMovieCollections->m_subdirs.erase(it); else ++it; } - } - m_root->finishRecordingsTree(); + } + m_root->finishRecordingsTree(); std::chrono::duration timeNeeded = std::chrono::high_resolution_clock::now() - begin; dsyslog("live: DH: ------ RecordingsTree::RecordingsTree() --------, required time: %9.5f", timeNeeded.count() ); /* @@ -1155,61 +1155,61 @@ void AppendScraperData(cToSvConcat<0> &target, cSv s_IMDB_ID, const cTvMedia &s_ timeDurationDeviation.print("live: Scraper "); timeNumTsFiles.print("live: NumTsFiles"); */ - } - - RecordingsTree::~RecordingsTree() - { - // esyslog("live: DH: ****** RecordingsTree::~RecordingsTree() ********"); - } - const std::vector *RecordingsTree::allRecordings(eSortOrder sortOrder) { - if (sortOrder == m_sortOrder) return &m_allRecordings_other_sort; - if (sortOrder == eSortOrder::name) { - if (!m_allRecordingsSorted) { - std::sort(m_allRecordings.begin(), m_allRecordings.end(), RecordingsItemPtrCompare::getComp(eSortOrder::name)); - m_allRecordingsSorted = true; - } - return &m_allRecordings; + } + + RecordingsTree::~RecordingsTree() + { + // esyslog("live: DH: ****** RecordingsTree::~RecordingsTree() ********"); + } + const std::vector *RecordingsTree::allRecordings(eSortOrder sortOrder) { + if (sortOrder == m_sortOrder) return &m_allRecordings_other_sort; + if (sortOrder == eSortOrder::name) { + if (!m_allRecordingsSorted) { + std::sort(m_allRecordings.begin(), m_allRecordings.end(), RecordingsItemPtrCompare::getComp(eSortOrder::name)); + m_allRecordingsSorted = true; + } + return &m_allRecordings; } if (m_allRecordings_other_sort.empty() ) m_allRecordings_other_sort = m_allRecordings; - std::sort(m_allRecordings_other_sort.begin(), m_allRecordings_other_sort.end(), RecordingsItemPtrCompare::getComp(sortOrder)); + std::sort(m_allRecordings_other_sort.begin(), m_allRecordings_other_sort.end(), RecordingsItemPtrCompare::getComp(sortOrder)); m_sortOrder = sortOrder; - return &m_allRecordings_other_sort; - } - - /** - * Implementation of class RecordingsTreePtr: - */ - RecordingsTreePtr::RecordingsTreePtr() : - std::shared_ptr(), - m_recManPtr() - { - } - - RecordingsTreePtr::RecordingsTreePtr(RecordingsManagerPtr recManPtr, std::shared_ptr recTree) : - std::shared_ptr(recTree), - m_recManPtr(recManPtr) - { - } - - RecordingsTreePtr::~RecordingsTreePtr() - { - } - - /** - * Implementation of function LiveRecordingsManager: - */ - RecordingsManagerPtr LiveRecordingsManager() - { - RecordingsManagerPtr r = RecordingsManager::m_recMan.lock(); - if (r) { - return r; - } - else { + return &m_allRecordings_other_sort; + } + + /** + * Implementation of class RecordingsTreePtr: + */ + RecordingsTreePtr::RecordingsTreePtr() : + std::shared_ptr(), + m_recManPtr() + { + } + + RecordingsTreePtr::RecordingsTreePtr(RecordingsManagerPtr recManPtr, std::shared_ptr recTree) : + std::shared_ptr(recTree), + m_recManPtr(recManPtr) + { + } + + RecordingsTreePtr::~RecordingsTreePtr() + { + } + + /** + * Implementation of function LiveRecordingsManager: + */ + RecordingsManagerPtr LiveRecordingsManager() + { + RecordingsManagerPtr r = RecordingsManager::m_recMan.lock(); + if (r) { + return r; + } + else { RecordingsManagerPtr n(new RecordingsManager); - RecordingsManager::m_recMan = n; - return n; - } - } + RecordingsManager::m_recMan = n; + return n; + } + } // icon with recording errors and tooltip std::string recordingErrorsHtml(int recordingErrors) { diff --git a/recman.h b/recman.h index 32eae3f..fc0268c 100644 --- a/recman.h +++ b/recman.h @@ -113,15 +113,15 @@ template void DeleteRecording(cRecording const * recording) const; /** - * Determine whether the recording has been archived on - * removable media (e.g. DVD-ROM) + * Determine whether the recording has been archived on + * removable media (e.g. DVD-ROM) */ static int GetArchiveType(cRecording const * recording); /** - * Provide an identification of the removable media - * (e.g. DVD-ROM Number or Name) where the recording has - * been archived. + * Provide an identification of the removable media + * (e.g. DVD-ROM Number or Name) where the recording has + * been archived. */ static std::string const GetArchiveId(cRecording const * recording, int archiveType); @@ -193,7 +193,7 @@ template cSv Name() const { return m_name; } int Level() const { return m_level; } - void finishRecordingsTree(); // sort recursively, Order: m_cmp_rec (if defined. Otherwise: no sort) + void finishRecordingsTree(); // sort recursively, Order: m_cmp_rec (if defined. Otherwise: no sort) // dirs: Order: m_cmp_dir (if defined. Otherwise: m_name_for_sort) virtual bool operator< (const RecordingsItemDirPtr &sec) const { return m_name < sec->m_name; } virtual bool operator< (cSv sec) const { return m_name < sec; } @@ -202,31 +202,31 @@ template virtual bool operator> (int sec) const { return false; } int numberOfRecordings() const; RecordingsItemDirPtr addDirIfNotExists(cSv dirName); - RecordingsItemDirPtr addDirCollectionIfNotExists(int collectionId, const RecordingsItemRecPtr &rPtr); - RecordingsItemDirPtr addDirSeasonIfNotExists(int seasonNumber, const RecordingsItemRecPtr &rPtr); - const std::vector *getRecordings(eSortOrder sortOrder); - const std::vector *getDirs() { return &m_subdirs; } - bool checkNew() const; - void addDirList(std::vector &dirs, cSv basePath) const; + RecordingsItemDirPtr addDirCollectionIfNotExists(int collectionId, const RecordingsItemRecPtr &rPtr); + RecordingsItemDirPtr addDirSeasonIfNotExists(int seasonNumber, const RecordingsItemRecPtr &rPtr); + const std::vector *getRecordings(eSortOrder sortOrder); + const std::vector *getDirs() { return &m_subdirs; } + bool checkNew() const; + void addDirList(std::vector &dirs, cSv basePath) const; void setTvShow(const RecordingsItemRecPtr &rPtr); int scraperCollectionId() const { return m_s_collection_id; } int scraperSeasonNumber() const { return m_s_season_number; } const cTvMedia &scraperImage() const; - bool recEntriesSorted() const { return m_cmp_rec != NULL; } - bool dirEntriesSorted() const { return m_cmp_dir != NULL; } + bool recEntriesSorted() const { return m_cmp_rec != NULL; } + bool dirEntriesSorted() const { return m_cmp_dir != NULL; } protected: std::string m_name; int m_level; std::vector m_subdirs; std::vector m_entries; - bool m_entriesSorted = false; + bool m_entriesSorted = false; std::vector m_entries_other_sort; - eSortOrder m_sortOrder = (eSortOrder)-1; - bool (*m_cmp_dir)(const RecordingsItemDirPtr &itemPtr1, const RecordingsItemDirPtr &itemPtr2) = NULL; - bool (*m_cmp_rec)(const RecordingsItemRecPtr &itemPtr1, const RecordingsItemRecPtr &itemPtr2) = NULL; + eSortOrder m_sortOrder = (eSortOrder)-1; + bool (*m_cmp_dir)(const RecordingsItemDirPtr &itemPtr1, const RecordingsItemDirPtr &itemPtr2) = NULL; + bool (*m_cmp_rec)(const RecordingsItemRecPtr &itemPtr1, const RecordingsItemRecPtr &itemPtr2) = NULL; // scraper data RecordingsItemRecPtr m_rec_item; // in this rec item (if available), there are the relevant scraper data // for dirs (collection), it points to a rec item with relevant data for the collection @@ -300,7 +300,7 @@ template virtual const int IsArchived() const { return m_isArchived; } virtual const std::string ArchiveDescr() const { return RecordingsManager::GetArchiveDescr(m_recording) ; } virtual const char *NewR() const { return LiveSetup().GetMarkNewRec() && Recording()->IsNew() ? "_new" : "" ; } - virtual bool checkNew() const { return m_recording->IsNew(); } // for recursive checks on dirs, here we don't check LiveSetup + virtual bool checkNew() const { return m_recording->IsNew(); } // for recursive checks on dirs, here we don't check LiveSetup #if VDRVERSNUM >= 20505 virtual const int RecordingErrors() const { return RecInfo()->Errors(); } #else @@ -310,7 +310,7 @@ template if (m_number_ts_files == -2) m_number_ts_files = GetNumberOfTsFiles(m_recording); return m_number_ts_files; } - virtual void getScraperData(std::string *collectionName = NULL); + virtual void getScraperData(std::string *collectionName = NULL); bool scraperDataAvailable() const { return m_s_videoType == tMovie || m_s_videoType == tSeries; } tvType scraperVideoType() const { return m_s_videoType; } int scraperCollectionId() const { return m_s_collection_id; } @@ -339,7 +339,7 @@ template const std::string m_name; std::string GetNameForSearch(cSv name); const std::string m_name_for_search; - const int m_idI = -1; + const int m_idI = -1; const cRecording *m_recording = nullptr; const XXH128_hash_t m_hash; const int m_isArchived = 0; @@ -387,13 +387,13 @@ template virtual const cRecording* Recording() const { return nullptr; } virtual const cRecordingInfo* RecInfo() const { return nullptr; } - virtual bool checkNew() const { return false; } + virtual bool checkNew() const { return false; } virtual const int IsArchived() const { return 0 ; } virtual const std::string ArchiveDescr() const { return std::string(); } virtual const char *NewR() const { return ""; } virtual const int RecordingErrors() const { return -1; } virtual int NumberTsFiles() const { return 0 ; } - virtual void getScraperData(std::string *collectionName = NULL) {} + virtual void getScraperData(std::string *collectionName = NULL) {} const cTvMedia &scraperImage() const { return m_s_image; } virtual int SD_HD() const { return 0; } @@ -460,7 +460,7 @@ template * This ensures that after last use of the RecordingsManager it is * deleted. After deletion of the original RecordingsManager a repeated * call to this function creates a new RecordingsManager which is again - * kept alive as long references to it exist. + * kept alive as long references to it exist. */ RecordingsManagerPtr LiveRecordingsManager(); diff --git a/services.h b/services.h index add1ad9..fc66803 100644 --- a/services.h +++ b/services.h @@ -66,19 +66,19 @@ class cEpisode { // Data structure for service "GetEventType" class ScraperGetEventType { public: - ScraperGetEventType(void) { - event = NULL; - recording = NULL; - type = tNone; - movieId = 0; - seriesId = 0; - episodeId = 0; - }; + ScraperGetEventType(void) { + event = NULL; + recording = NULL; + type = tNone; + movieId = 0; + seriesId = 0; + episodeId = 0; + }; // in const cEvent *event; // check type for this event const cRecording *recording; // or for this recording //out - tvType type; //tSeries or tMovie or tNone + tvType type; //tSeries or tMovie or tNone int movieId; int seriesId; int episodeId; diff --git a/setup.cpp b/setup.cpp index d81bc2d..9a793ad 100644 --- a/setup.cpp +++ b/setup.cpp @@ -23,91 +23,91 @@ namespace vdrlive { Setup::Setup(): - m_serverPort( 8008 ), - m_serverSslPort( 8443 ), - m_serverSslCert(), - m_serverSslKey(), - m_lastChannel( 0 ), - m_screenshotInterval( 1000 ), - m_useAuth( 1 ), - m_adminLogin("admin"), - m_channelGroups( "" ), - m_scheduleDuration( "8" ), - m_theme("marine"), + m_serverPort( 8008 ), + m_serverSslPort( 8443 ), + m_serverSslCert(), + m_serverSslKey(), + m_lastChannel( 0 ), + m_screenshotInterval( 1000 ), + m_useAuth( 1 ), + m_adminLogin("admin"), + m_channelGroups( "" ), + m_scheduleDuration( "8" ), + m_theme("marine"), m_themedLinkPrefix("themes/" + m_theme + "/"), m_themedLinkPrefixImg("themes/marine/img/"), - m_lastwhatsonlistmode("detail"), - m_lastsortingmode("nameasc"), - m_tntnetloglevel("WARN"), - m_showLogo(1), - m_showInfoBox(1), - m_useStreamdev(1), - m_streamdevPort(3000), - m_streamdevType("TS"), - m_markNewRec(1), - - m_streamVopt0(cmdChannelH264), - m_streamVopt1(cmdChannelHVEC), - m_streamVopt2(cmdChannelMPG2), - m_streamVopt3(cmdChannelDFLT), - - m_showIMDb(1), - m_showPlayMediaplayer(1), - m_showChannelsWithoutEPG(0) + m_lastwhatsonlistmode("detail"), + m_lastsortingmode("nameasc"), + m_tntnetloglevel("WARN"), + m_showLogo(1), + m_showInfoBox(1), + m_useStreamdev(1), + m_streamdevPort(3000), + m_streamdevType("TS"), + m_markNewRec(1), + + m_streamVopt0(cmdChannelH264), + m_streamVopt1(cmdChannelHVEC), + m_streamVopt2(cmdChannelMPG2), + m_streamVopt3(cmdChannelDFLT), + + m_showIMDb(1), + m_showPlayMediaplayer(1), + m_showChannelsWithoutEPG(0) { - m_adminPasswordMD5 = "4:" + MD5Hash("live"); - liveplugin = cPluginManager::GetPlugin("live"); + m_adminPasswordMD5 = "4:" + MD5Hash("live"); + liveplugin = cPluginManager::GetPlugin("live"); m_vdr_start = time(0); } bool Setup::ParseCommandLine( int argc, char* argv[] ) { - static struct option opts[] = { - { "url", required_argument, NULL, 'u' }, - { "port", required_argument, NULL, 'p' }, - { "ip", required_argument, NULL, 'i' }, - { "log", required_argument, NULL, 'l' }, - { "epgimages", required_argument, NULL, 'e' }, - { "tvscraperimages", required_argument, NULL, 't' }, - { "sslport", required_argument, NULL, 's' }, - { "cert", required_argument, NULL, 'c' }, - { "key", required_argument, NULL, 'k' }, - { "ffmpegconf", required_argument, NULL, 'f' }, - { "chanlogos", required_argument, NULL, '1' }, - { 0 } - }; + static struct option opts[] = { + { "url", required_argument, NULL, 'u' }, + { "port", required_argument, NULL, 'p' }, + { "ip", required_argument, NULL, 'i' }, + { "log", required_argument, NULL, 'l' }, + { "epgimages", required_argument, NULL, 'e' }, + { "tvscraperimages", required_argument, NULL, 't' }, + { "sslport", required_argument, NULL, 's' }, + { "cert", required_argument, NULL, 'c' }, + { "key", required_argument, NULL, 'k' }, + { "ffmpegconf", required_argument, NULL, 'f' }, + { "chanlogos", required_argument, NULL, '1' }, + { 0 } + }; m_serverUrl = ""; - int optchar, optind = 0; - while ( ( optchar = getopt_long( argc, argv, "p:i:l:e:s:c:", opts, &optind ) ) != -1 ) { - switch ( optchar ) { - case 'u': m_serverUrl = optarg; break; - case 'p': m_serverPort = atoi( optarg ); break; - case 'i': m_serverIps.push_back( optarg ); break; - case 'l': m_tntnetloglevel = optarg; break; - case 'e': m_epgimagedir = optarg; break; - case 't': m_tvscraperimagedir = optarg; - if(!m_tvscraperimagedir.empty() && m_tvscraperimagedir[m_tvscraperimagedir.length()-1] != '/') m_tvscraperimagedir += "/"; - break; - case 's': m_serverSslPort = atoi( optarg ); break; - case 'c': m_serverSslCert = optarg; break; - case 'k': m_serverSslKey = optarg; break; - case 'f': m_ffmpegFile = optarg; break; - case '1': m_chanlogodir = optarg; - if(!m_chanlogodir.empty() && m_chanlogodir[m_chanlogodir.length()-1] != '/') m_chanlogodir += "/"; - break; - default: return false; - } - } + int optchar, optind = 0; + while ( ( optchar = getopt_long( argc, argv, "p:i:l:e:s:c:", opts, &optind ) ) != -1 ) { + switch ( optchar ) { + case 'u': m_serverUrl = optarg; break; + case 'p': m_serverPort = atoi( optarg ); break; + case 'i': m_serverIps.push_back( optarg ); break; + case 'l': m_tntnetloglevel = optarg; break; + case 'e': m_epgimagedir = optarg; break; + case 't': m_tvscraperimagedir = optarg; + if(!m_tvscraperimagedir.empty() && m_tvscraperimagedir[m_tvscraperimagedir.length()-1] != '/') m_tvscraperimagedir += "/"; + break; + case 's': m_serverSslPort = atoi( optarg ); break; + case 'c': m_serverSslCert = optarg; break; + case 'k': m_serverSslKey = optarg; break; + case 'f': m_ffmpegFile = optarg; break; + case '1': m_chanlogodir = optarg; + if(!m_chanlogodir.empty() && m_chanlogodir[m_chanlogodir.length()-1] != '/') m_chanlogodir += "/"; + break; + default: return false; + } + } if (!m_serverUrl.empty() ) { m_serverUrlImages = m_serverUrl + ":"; m_serverUrlImages += cSv(cToSvInt(m_serverPort)); m_serverUrlImages += "/tvscraper/"; } else m_serverUrlImages = ""; - return CheckServerPort() && - CheckServerSslPort() && - CheckServerIps(); + return CheckServerPort() && + CheckServerSslPort() && + CheckServerIps(); } bool Setup::Initialize( void ) @@ -180,180 +180,180 @@ bool Setup::Initialize( void ) char const* Setup::CommandLineHelp() const { - if ( m_helpString.empty() ) { - std::stringstream builder; - builder << " -p PORT, --port=PORT use PORT to listen for incoming connections\n" - " (default: " << m_serverPort << ")\n" - << " -i IP, --ip=IP bind server only to specified IP, may appear\n" - " multiple times\n" - " (default: 0.0.0.0)\n" - << " -s PORT, --sslport=PORT use PORT to listen for incoming SSL connections\n" - " (default: " << m_serverSslPort << ")\n" - << " -u URL, --url=URL URL to this live server, e.g. http://rpi.fritz.box\n" - " only required if live is used as image server, e.g. for vnsi\n" - << " -c CERT, --cert=CERT full path to a custom SSL certificate file\n" - << " -k KEY, --key=KEY full path to a custom SSL certificate key file\n" - << " -l level, --log=level log level for Tntnet (values: WARN, ERROR, INFO, DEBUG, TRACE)\n" - << " -e , --epgimages= directory for EPG images\n" - << " -t , --tvscraperimages= directory for Tvscraper images\n" - << " -f , --ffmpegconf= filename of FFMPEG configuration file\n" - << " --chanlogos= directory for channel logos (PNG)\n"; - m_helpString = builder.str(); - } - return m_helpString.c_str(); + if ( m_helpString.empty() ) { + std::stringstream builder; + builder << " -p PORT, --port=PORT use PORT to listen for incoming connections\n" + " (default: " << m_serverPort << ")\n" + << " -i IP, --ip=IP bind server only to specified IP, may appear\n" + " multiple times\n" + " (default: 0.0.0.0)\n" + << " -s PORT, --sslport=PORT use PORT to listen for incoming SSL connections\n" + " (default: " << m_serverSslPort << ")\n" + << " -u URL, --url=URL URL to this live server, e.g. http://rpi.fritz.box\n" + " only required if live is used as image server, e.g. for vnsi\n" + << " -c CERT, --cert=CERT full path to a custom SSL certificate file\n" + << " -k KEY, --key=KEY full path to a custom SSL certificate key file\n" + << " -l level, --log=level log level for Tntnet (values: WARN, ERROR, INFO, DEBUG, TRACE)\n" + << " -e , --epgimages= directory for EPG images\n" + << " -t , --tvscraperimages= directory for Tvscraper images\n" + << " -f , --ffmpegconf= filename of FFMPEG configuration file\n" + << " --chanlogos= directory for channel logos (PNG)\n"; + m_helpString = builder.str(); + } + return m_helpString.c_str(); } bool Setup::ParseSetupEntry( char const* name, char const* value ) { - if ( strcmp( name, "LastChannel" ) == 0 ) m_lastChannel = atoi( value ); - else if ( strcmp( name, "ScreenshotInterval" ) == 0 ) m_screenshotInterval = atoi( value ); - else if ( strcmp( name, "UseAuth" ) == 0 ) m_useAuth = atoi( value ); - else if ( strcmp( name, "AdminLogin" ) == 0 ) m_adminLogin = value; - else if ( strcmp( name, "AdminPasswordMD5" ) == 0 ) m_adminPasswordMD5 = value; - else if ( strcmp( name, "UserdefTimes" ) == 0 ) m_times = value; - else if ( strcmp( name, "ChannelGroups" ) == 0 ) m_channelGroups = value; - else if ( strcmp( name, "ScheduleDuration" ) == 0 ) m_scheduleDuration = value; - else if ( strcmp( name, "StartPage" ) == 0 ) m_startscreen = value; - else if ( strcmp( name, "Theme" ) == 0 ) SetTheme(value); - else if ( strcmp( name, "LocalNetMask" ) == 0 ) { m_localnetmask = value; } - else if ( strcmp( name, "LastWhatsOnListMode" ) == 0 ) { m_lastwhatsonlistmode = value; } - else if ( strcmp( name, "LastSortingMode" ) == 0 ) { m_lastsortingmode = value; } - else if ( strcmp( name, "ShowLogo" ) == 0 ) { m_showLogo = atoi(value); } - else if ( strcmp( name, "ShowInfoBox" ) == 0 ) { m_showInfoBox = atoi(value); } - else if ( strcmp( name, "UseStreamdev" ) == 0 ) { m_useStreamdev = atoi(value); } - else if ( strcmp( name, "StreamdevPort" ) == 0 ) { m_streamdevPort = atoi(value); } - else if ( strcmp( name, "StreamdevType" ) == 0 ) { m_streamdevType = value; } - else if ( strcmp( name, "StreamVideoOpt0" ) == 0 ) { m_streamVopt0 = value; } - else if ( strcmp( name, "StreamVideoOpt1" ) == 0 ) { m_streamVopt1 = value; } - else if ( strcmp( name, "StreamVideoOpt2" ) == 0 ) { m_streamVopt2 = value; } - else if ( strcmp( name, "StreamVideoOpt3" ) == 0 ) { m_streamVopt3 = value; } - else if ( strcmp( name, "ScreenShotInterval" ) == 0 ) { m_screenshotInterval = atoi(value); } - else if ( strcmp( name, "MarkNewRec" ) == 0 ) { m_markNewRec = atoi(value); } - else if ( strcmp( name, "ShowIMDb" ) == 0 ) { m_showIMDb = atoi(value); } - else if ( strcmp( name, "ShowPlayMediaplayer" ) == 0 ) { m_showPlayMediaplayer = atoi(value); } - else if ( strcmp( name, "ShowChannelsWithoutEPG" ) == 0 ) { m_showChannelsWithoutEPG = atoi(value); } - else return false; - return true; + if ( strcmp( name, "LastChannel" ) == 0 ) m_lastChannel = atoi( value ); + else if ( strcmp( name, "ScreenshotInterval" ) == 0 ) m_screenshotInterval = atoi( value ); + else if ( strcmp( name, "UseAuth" ) == 0 ) m_useAuth = atoi( value ); + else if ( strcmp( name, "AdminLogin" ) == 0 ) m_adminLogin = value; + else if ( strcmp( name, "AdminPasswordMD5" ) == 0 ) m_adminPasswordMD5 = value; + else if ( strcmp( name, "UserdefTimes" ) == 0 ) m_times = value; + else if ( strcmp( name, "ChannelGroups" ) == 0 ) m_channelGroups = value; + else if ( strcmp( name, "ScheduleDuration" ) == 0 ) m_scheduleDuration = value; + else if ( strcmp( name, "StartPage" ) == 0 ) m_startscreen = value; + else if ( strcmp( name, "Theme" ) == 0 ) SetTheme(value); + else if ( strcmp( name, "LocalNetMask" ) == 0 ) { m_localnetmask = value; } + else if ( strcmp( name, "LastWhatsOnListMode" ) == 0 ) { m_lastwhatsonlistmode = value; } + else if ( strcmp( name, "LastSortingMode" ) == 0 ) { m_lastsortingmode = value; } + else if ( strcmp( name, "ShowLogo" ) == 0 ) { m_showLogo = atoi(value); } + else if ( strcmp( name, "ShowInfoBox" ) == 0 ) { m_showInfoBox = atoi(value); } + else if ( strcmp( name, "UseStreamdev" ) == 0 ) { m_useStreamdev = atoi(value); } + else if ( strcmp( name, "StreamdevPort" ) == 0 ) { m_streamdevPort = atoi(value); } + else if ( strcmp( name, "StreamdevType" ) == 0 ) { m_streamdevType = value; } + else if ( strcmp( name, "StreamVideoOpt0" ) == 0 ) { m_streamVopt0 = value; } + else if ( strcmp( name, "StreamVideoOpt1" ) == 0 ) { m_streamVopt1 = value; } + else if ( strcmp( name, "StreamVideoOpt2" ) == 0 ) { m_streamVopt2 = value; } + else if ( strcmp( name, "StreamVideoOpt3" ) == 0 ) { m_streamVopt3 = value; } + else if ( strcmp( name, "ScreenShotInterval" ) == 0 ) { m_screenshotInterval = atoi(value); } + else if ( strcmp( name, "MarkNewRec" ) == 0 ) { m_markNewRec = atoi(value); } + else if ( strcmp( name, "ShowIMDb" ) == 0 ) { m_showIMDb = atoi(value); } + else if ( strcmp( name, "ShowPlayMediaplayer" ) == 0 ) { m_showPlayMediaplayer = atoi(value); } + else if ( strcmp( name, "ShowChannelsWithoutEPG" ) == 0 ) { m_showChannelsWithoutEPG = atoi(value); } + else return false; + return true; } bool Setup::CheckServerPort() { - if ( m_serverPort <= 0 || m_serverPort > std::numeric_limits::max() ) { - esyslog( "live: ERROR: server port %d is not a valid port number", m_serverPort ); - std::cerr << "ERROR: live server port " << m_serverPort << " is not a valid port number" << std::endl; - return false; - } - return true; + if ( m_serverPort <= 0 || m_serverPort > std::numeric_limits::max() ) { + esyslog( "live: ERROR: server port %d is not a valid port number", m_serverPort ); + std::cerr << "ERROR: live server port " << m_serverPort << " is not a valid port number" << std::endl; + return false; + } + return true; } bool Setup::CheckServerSslPort() { - if ( m_serverSslPort < 0 || m_serverSslPort > std::numeric_limits::max() ) { - esyslog( "live: ERROR: server SSL port %d is not a valid port number", m_serverSslPort ); - std::cerr << "ERROR: live server SSL port " << m_serverSslPort << " is not a valid port number" << std::endl; - return false; - } - return true; + if ( m_serverSslPort < 0 || m_serverSslPort > std::numeric_limits::max() ) { + esyslog( "live: ERROR: server SSL port %d is not a valid port number", m_serverSslPort ); + std::cerr << "ERROR: live server SSL port " << m_serverSslPort << " is not a valid port number" << std::endl; + return false; + } + return true; } namespace { - struct IpValidator - { - bool operator() (std::string const & ip) - { - struct in6_addr buf; - struct in_addr buf4; - - esyslog( "live: INFO: validating server IP '%s'", ip.c_str()); - std::cerr << "INFO: validating live server IP '" << ip << "'" << std::endl; - bool valid = inet_aton(ip.c_str(), &buf4) || inet_pton(AF_INET6, ip.c_str(), &buf); - - if (!valid) { - esyslog( "live: ERROR: server IP %s is not a valid IP address", ip.c_str()); - std::cerr << "ERROR: live server IP '" << ip << "' is not a valid IP address" << std::endl; - } - return valid; - } - }; + struct IpValidator + { + bool operator() (std::string const & ip) + { + struct in6_addr buf; + struct in_addr buf4; + + esyslog( "live: INFO: validating server IP '%s'", ip.c_str()); + std::cerr << "INFO: validating live server IP '" << ip << "'" << std::endl; + bool valid = inet_aton(ip.c_str(), &buf4) || inet_pton(AF_INET6, ip.c_str(), &buf); + + if (!valid) { + esyslog( "live: ERROR: server IP %s is not a valid IP address", ip.c_str()); + std::cerr << "ERROR: live server IP '" << ip << "' is not a valid IP address" << std::endl; + } + return valid; + } + }; } bool Setup::CheckServerIps() { - if ( m_serverIps.empty() ) { + if ( m_serverIps.empty() ) { #if TNT_IPV6_V6ONLY - m_serverIps.push_back(""); - return true; + m_serverIps.push_back(""); + return true; #else - FILE* f = fopen("/proc/sys/net/ipv6/bindv6only", "r"); - if (f) { - bool bindv6only = false; - int c = fgetc(f); - if (c != EOF) { - bindv6only = ((c - '0') != 0); - } - fclose(f); - f = NULL; - esyslog( "live: INFO: bindv6only=%d", bindv6only); - // add a default IPv6 listener address - m_serverIps.push_back("::"); - // skip the default IPv4 listener address if the IPv6 one will be bound also to v4 - if (!bindv6only) - return true; - } - // add a default IPv4 listener address - m_serverIps.push_back("0.0.0.0"); - // we assume these are OK :) - return true; + FILE* f = fopen("/proc/sys/net/ipv6/bindv6only", "r"); + if (f) { + bool bindv6only = false; + int c = fgetc(f); + if (c != EOF) { + bindv6only = ((c - '0') != 0); + } + fclose(f); + f = NULL; + esyslog( "live: INFO: bindv6only=%d", bindv6only); + // add a default IPv6 listener address + m_serverIps.push_back("::"); + // skip the default IPv4 listener address if the IPv6 one will be bound also to v4 + if (!bindv6only) + return true; + } + // add a default IPv4 listener address + m_serverIps.push_back("0.0.0.0"); + // we assume these are OK :) + return true; #endif // TNT_IPV6_V6ONLY - } + } - IpList::iterator i = partition(m_serverIps.begin(), m_serverIps.end(), IpValidator()); - m_serverIps.erase(i, m_serverIps.end()); + IpList::iterator i = partition(m_serverIps.begin(), m_serverIps.end(), IpValidator()); + m_serverIps.erase(i, m_serverIps.end()); - return !m_serverIps.empty(); + return !m_serverIps.empty(); } std::string const Setup::GetMD5HashAdminPassword() const { - // format is : - std::vector parts = StringSplit( m_adminPasswordMD5, ':' ); - return (parts.size() > 1) ? parts[1] : ""; + // format is : + std::vector parts = StringSplit( m_adminPasswordMD5, ':' ); + return (parts.size() > 1) ? parts[1] : ""; } int Setup::GetAdminPasswordLength() const { - // format is : - std::vector parts = StringSplit( m_adminPasswordMD5, ':' ); - return (parts.size() > 0) ? parse_int( parts[0] ) : 0; + // format is : + std::vector parts = StringSplit( m_adminPasswordMD5, ':' ); + return (parts.size() > 0) ? parse_int( parts[0] ) : 0; } std::string Setup::SetAdminPassword(std::string password) { - std::stringstream passwordStr; - passwordStr << password.size() << ":" << MD5Hash(password); - m_adminPasswordMD5 = passwordStr.str(); - return m_adminPasswordMD5; + std::stringstream passwordStr; + passwordStr << password.size() << ":" << MD5Hash(password); + m_adminPasswordMD5 = passwordStr.str(); + return m_adminPasswordMD5; } std::string const Setup::GetStartScreenLink() const { - if (m_startscreen == "whatsonnext") - return "whats_on.html?type=next"; - else if (m_startscreen == "schedule") - return "schedule.html"; - else if (m_startscreen == "multischedule") - return "multischedule.html"; - else if (m_startscreen == "timers") - return "timers.html"; - else if (m_startscreen == "recordings") - return "recordings.html"; - else - return "whats_on.html?type=now"; + if (m_startscreen == "whatsonnext") + return "whats_on.html?type=next"; + else if (m_startscreen == "schedule") + return "schedule.html"; + else if (m_startscreen == "multischedule") + return "multischedule.html"; + else if (m_startscreen == "timers") + return "timers.html"; + else if (m_startscreen == "recordings") + return "recordings.html"; + else + return "whats_on.html?type=now"; } bool Setup::UseAuth() const { - return m_useAuth && !GetIsLocalNet(); + return m_useAuth && !GetIsLocalNet(); } void Setup::SetTvscraperImageDir(const std::string &dir) { @@ -367,164 +367,164 @@ void Setup::SetTvscraperImageDir(const std::string &dir) { bool Setup::CheckLocalNet(const std::string& ip) { - // split local net mask in net and range - std::vector parts = StringSplit( m_localnetmask, '/' ); - if (parts.size() != 2) return false; - std::string net = parts[0]; - - int range = parse_int(parts[1]); - // split net and IP address in its 4 subcomponents - std::vector netparts = StringSplit( net, '.' ); - std::vector addrparts = StringSplit( ip, '.' ); - if (netparts.size() != 4 || addrparts.size() != 4) return false; - - // to binary representation - std::stringstream bin_netstream; - bin_netstream << std::bitset<8>(parse_int(netparts[0])) - << std::bitset<8>(parse_int(netparts[1])) - << std::bitset<8>(parse_int(netparts[2])) - << std::bitset<8>(parse_int(netparts[3])); - - std::stringstream bin_addrstream; - bin_addrstream << std::bitset<8>(parse_int(addrparts[0])) - << std::bitset<8>(parse_int(addrparts[1])) - << std::bitset<8>(parse_int(addrparts[2])) - << std::bitset<8>(parse_int(addrparts[3])); - - // compare range - std::string bin_net = bin_netstream.str(); - std::string bin_addr = bin_addrstream.str(); - std::string bin_net_range(bin_net.begin(), bin_net.begin() + range); - std::string addr_net_range(bin_addr.begin(), bin_addr.begin() + range); - m_islocalnet = (bin_net_range == addr_net_range); - - return m_islocalnet; + // split local net mask in net and range + std::vector parts = StringSplit( m_localnetmask, '/' ); + if (parts.size() != 2) return false; + std::string net = parts[0]; + + int range = parse_int(parts[1]); + // split net and IP address in its 4 subcomponents + std::vector netparts = StringSplit( net, '.' ); + std::vector addrparts = StringSplit( ip, '.' ); + if (netparts.size() != 4 || addrparts.size() != 4) return false; + + // to binary representation + std::stringstream bin_netstream; + bin_netstream << std::bitset<8>(parse_int(netparts[0])) + << std::bitset<8>(parse_int(netparts[1])) + << std::bitset<8>(parse_int(netparts[2])) + << std::bitset<8>(parse_int(netparts[3])); + + std::stringstream bin_addrstream; + bin_addrstream << std::bitset<8>(parse_int(addrparts[0])) + << std::bitset<8>(parse_int(addrparts[1])) + << std::bitset<8>(parse_int(addrparts[2])) + << std::bitset<8>(parse_int(addrparts[3])); + + // compare range + std::string bin_net = bin_netstream.str(); + std::string bin_addr = bin_addrstream.str(); + std::string bin_net_range(bin_net.begin(), bin_net.begin() + range); + std::string addr_net_range(bin_addr.begin(), bin_addr.begin() + range); + m_islocalnet = (bin_net_range == addr_net_range); + + return m_islocalnet; } bool Setup::SaveSetup() { - if (!liveplugin) return false; - liveplugin->SetupStore("LastChannel", m_lastChannel); - liveplugin->SetupStore("UseAuth", m_useAuth); - if (m_useAuth) - { - liveplugin->SetupStore("AdminLogin", m_adminLogin.c_str()); - liveplugin->SetupStore("AdminPasswordMD5", m_adminPasswordMD5.c_str()); - liveplugin->SetupStore("LocalNetMask", m_localnetmask.c_str()); - } - liveplugin->SetupStore("UserdefTimes", m_times.c_str()); - liveplugin->SetupStore("ChannelGroups", m_channelGroups.c_str()); - liveplugin->SetupStore("ScheduleDuration", m_scheduleDuration.c_str()); - liveplugin->SetupStore("StartPage", m_startscreen.c_str()); - liveplugin->SetupStore("Theme", m_theme.c_str()); - liveplugin->SetupStore("LastWhatsOnListMode", m_lastwhatsonlistmode.c_str()); - liveplugin->SetupStore("LastSortingMode", m_lastsortingmode.c_str()); - liveplugin->SetupStore("ShowLogo", m_showLogo); - liveplugin->SetupStore("ShowInfoBox", m_showInfoBox); - liveplugin->SetupStore("UseStreamdev", m_useStreamdev); - liveplugin->SetupStore("StreamdevPort", m_streamdevPort); - liveplugin->SetupStore("StreamdevType", m_streamdevType.c_str()); - liveplugin->SetupStore("ScreenShotInterval", m_screenshotInterval); - liveplugin->SetupStore("MarkNewRec", m_markNewRec); - liveplugin->SetupStore("ShowIMDb", m_showIMDb); - liveplugin->SetupStore("ShowPlayMediaplayer", m_showPlayMediaplayer); - liveplugin->SetupStore("ShowChannelsWithoutEPG", m_showChannelsWithoutEPG); - - return true; + if (!liveplugin) return false; + liveplugin->SetupStore("LastChannel", m_lastChannel); + liveplugin->SetupStore("UseAuth", m_useAuth); + if (m_useAuth) + { + liveplugin->SetupStore("AdminLogin", m_adminLogin.c_str()); + liveplugin->SetupStore("AdminPasswordMD5", m_adminPasswordMD5.c_str()); + liveplugin->SetupStore("LocalNetMask", m_localnetmask.c_str()); + } + liveplugin->SetupStore("UserdefTimes", m_times.c_str()); + liveplugin->SetupStore("ChannelGroups", m_channelGroups.c_str()); + liveplugin->SetupStore("ScheduleDuration", m_scheduleDuration.c_str()); + liveplugin->SetupStore("StartPage", m_startscreen.c_str()); + liveplugin->SetupStore("Theme", m_theme.c_str()); + liveplugin->SetupStore("LastWhatsOnListMode", m_lastwhatsonlistmode.c_str()); + liveplugin->SetupStore("LastSortingMode", m_lastsortingmode.c_str()); + liveplugin->SetupStore("ShowLogo", m_showLogo); + liveplugin->SetupStore("ShowInfoBox", m_showInfoBox); + liveplugin->SetupStore("UseStreamdev", m_useStreamdev); + liveplugin->SetupStore("StreamdevPort", m_streamdevPort); + liveplugin->SetupStore("StreamdevType", m_streamdevType.c_str()); + liveplugin->SetupStore("ScreenShotInterval", m_screenshotInterval); + liveplugin->SetupStore("MarkNewRec", m_markNewRec); + liveplugin->SetupStore("ShowIMDb", m_showIMDb); + liveplugin->SetupStore("ShowPlayMediaplayer", m_showPlayMediaplayer); + liveplugin->SetupStore("ShowChannelsWithoutEPG", m_showChannelsWithoutEPG); + + return true; } Setup& LiveSetup() { - static Setup instance; - return instance; + static Setup instance; + return instance; } cMenuSetupLive::cMenuSetupLive(): - cMenuSetupPage() + cMenuSetupPage() { - m_lastChannel = vdrlive::LiveSetup().GetLastChannel(); - m_useAuth = vdrlive::LiveSetup().UseAuth(); - strcpy(m_adminLogin, vdrlive::LiveSetup().GetAdminLogin().c_str()); + m_lastChannel = vdrlive::LiveSetup().GetLastChannel(); + m_useAuth = vdrlive::LiveSetup().UseAuth(); + strcpy(m_adminLogin, vdrlive::LiveSetup().GetAdminLogin().c_str()); - m_oldpasswordMD5 = m_newpasswordMD5 = vdrlive::LiveSetup().GetMD5HashAdminPassword(); + m_oldpasswordMD5 = m_newpasswordMD5 = vdrlive::LiveSetup().GetMD5HashAdminPassword(); - std::string strHidden(vdrlive::LiveSetup().GetAdminPasswordLength(), '*'); - strn0cpy(m_tmpPassword, strHidden.c_str(), sizeof(m_tmpPassword)); - strcpy(m_adminPassword, ""); - Set(); + std::string strHidden(vdrlive::LiveSetup().GetAdminPasswordLength(), '*'); + strn0cpy(m_tmpPassword, strHidden.c_str(), sizeof(m_tmpPassword)); + strcpy(m_adminPassword, ""); + Set(); } void cMenuSetupLive::Set(void) { - int current = Current(); - Clear(); - //Add(new cMenuEditIntItem(tr("Last channel to display"), &m_lastChannel, 0, 65536)); - Add(new cMenuEditChanItem(tr("Last channel to display"), &m_lastChannel, tr("No limit"))); - //Add(new cMenuEditIntItem(tr("Screenshot interval"), &m_lastChannel, 0, 65536)); - Add(new cMenuEditBoolItem(tr("Use authentication"), &m_useAuth, tr("No"), tr("Yes"))); - Add(new cMenuEditStrItem( tr("Admin login"), m_adminLogin, sizeof(m_adminLogin), tr(FileNameChars))); - Add(new cMenuEditStrItem( tr("Admin password"), m_tmpPassword, sizeof(m_tmpPassword), tr(FileNameChars))); - SetCurrent(Get(current)); - Display(); + int current = Current(); + Clear(); + //Add(new cMenuEditIntItem(tr("Last channel to display"), &m_lastChannel, 0, 65536)); + Add(new cMenuEditChanItem(tr("Last channel to display"), &m_lastChannel, tr("No limit"))); + //Add(new cMenuEditIntItem(tr("Screenshot interval"), &m_lastChannel, 0, 65536)); + Add(new cMenuEditBoolItem(tr("Use authentication"), &m_useAuth, tr("No"), tr("Yes"))); + Add(new cMenuEditStrItem( tr("Admin login"), m_adminLogin, sizeof(m_adminLogin), tr(FileNameChars))); + Add(new cMenuEditStrItem( tr("Admin password"), m_tmpPassword, sizeof(m_tmpPassword), tr(FileNameChars))); + SetCurrent(Get(current)); + Display(); } void cMenuSetupLive::Store(void) { - vdrlive::LiveSetup().SetLastChannel(m_lastChannel); - vdrlive::LiveSetup().SetUseAuth(m_useAuth); - vdrlive::LiveSetup().SetAdminLogin(m_adminLogin); - if (m_oldpasswordMD5 != m_newpasswordMD5) // only save the password if needed - vdrlive::LiveSetup().SetAdminPassword(m_adminPassword); - LiveSetup().SaveSetup(); + vdrlive::LiveSetup().SetLastChannel(m_lastChannel); + vdrlive::LiveSetup().SetUseAuth(m_useAuth); + vdrlive::LiveSetup().SetAdminLogin(m_adminLogin); + if (m_oldpasswordMD5 != m_newpasswordMD5) // only save the password if needed + vdrlive::LiveSetup().SetAdminPassword(m_adminPassword); + LiveSetup().SaveSetup(); } bool cMenuSetupLive::InEditMode(const char* ItemText, const char* ItemName, const char* ItemValue) { - bool bEditMode = true; - // ugly solution to detect, if in edit mode - char* value = strdup(ItemText); - strreplace(value, ItemName, ""); - strreplace(value, ":\t", ""); - // for bigpatch - strreplace(value, "\t", ""); - if (strlen(value) == strlen(ItemValue)) - bEditMode = false; - free(value); - return bEditMode; + bool bEditMode = true; + // ugly solution to detect, if in edit mode + char* value = strdup(ItemText); + strreplace(value, ItemName, ""); + strreplace(value, ":\t", ""); + // for bigpatch + strreplace(value, "\t", ""); + if (strlen(value) == strlen(ItemValue)) + bEditMode = false; + free(value); + return bEditMode; } eOSState cMenuSetupLive::ProcessKey(eKeys Key) { - const char* ItemText = Get(Current())->Text(); - bool bPassWasInEditMode = false; - if (ItemText && strlen(ItemText) > 0 && strstr(ItemText, tr("Admin password")) == ItemText) - bPassWasInEditMode = InEditMode(ItemText, tr("Admin password"), m_tmpPassword); - - eOSState state = cMenuSetupPage::ProcessKey(Key); - - ItemText = Get(Current())->Text(); - bool bPassIsInEditMode = false; - if (ItemText && strlen(ItemText) > 0 && strstr(ItemText, tr("Admin password")) == ItemText) - bPassIsInEditMode = InEditMode(ItemText, tr("Admin password"), m_tmpPassword); - - if (bPassWasInEditMode && !bPassIsInEditMode) - { - strcpy(m_adminPassword, m_tmpPassword); - m_newpasswordMD5 = MD5Hash(m_tmpPassword); - std::string strHidden(strlen(m_adminPassword), '*'); - strcpy(m_tmpPassword, strHidden.c_str()); - Set(); - Display(); - } - if (!bPassWasInEditMode && bPassIsInEditMode) - { - strcpy(m_tmpPassword, ""); - Set(); - Display(); - state = cMenuSetupPage::ProcessKey(Key); - } - - return state; + const char* ItemText = Get(Current())->Text(); + bool bPassWasInEditMode = false; + if (ItemText && strlen(ItemText) > 0 && strstr(ItemText, tr("Admin password")) == ItemText) + bPassWasInEditMode = InEditMode(ItemText, tr("Admin password"), m_tmpPassword); + + eOSState state = cMenuSetupPage::ProcessKey(Key); + + ItemText = Get(Current())->Text(); + bool bPassIsInEditMode = false; + if (ItemText && strlen(ItemText) > 0 && strstr(ItemText, tr("Admin password")) == ItemText) + bPassIsInEditMode = InEditMode(ItemText, tr("Admin password"), m_tmpPassword); + + if (bPassWasInEditMode && !bPassIsInEditMode) + { + strcpy(m_adminPassword, m_tmpPassword); + m_newpasswordMD5 = MD5Hash(m_tmpPassword); + std::string strHidden(strlen(m_adminPassword), '*'); + strcpy(m_tmpPassword, strHidden.c_str()); + Set(); + Display(); + } + if (!bPassWasInEditMode && bPassIsInEditMode) + { + strcpy(m_tmpPassword, ""); + Set(); + Display(); + state = cMenuSetupPage::ProcessKey(Key); + } + + return state; } } // namespace vdrlive diff --git a/setup.h b/setup.h index 766ff9d..aec6b04 100644 --- a/setup.h +++ b/setup.h @@ -6,7 +6,7 @@ #include #include #if TNTVERSION >= 30000 - #include // must be loaded before any VDR include because of duplicate macros (LOG_ERROR, LOG_DEBUG, LOG_INFO) + #include // must be loaded before any VDR include because of duplicate macros (LOG_ERROR, LOG_DEBUG, LOG_INFO) #endif #include @@ -56,165 +56,165 @@ class cMenuSetupLive; class Setup { - friend Setup& LiveSetup(); - friend class cMenuSetupLive; // friend declaration is not forward - // declaration, although GCC 3.3 claims so - - public: - typedef std::list IpList; - - // command line - int GetServerPort() const { return m_serverPort; } - int GetServerSslPort() const { return m_serverSslPort; } - std::string GetServerSslCert() const { return m_serverSslCert; } - std::string GetServerSslKey() const { return m_serverSslKey; } - const std::string &GetServerUrl() const { return m_serverUrl; } - const std::string &GetServerUrlImages() const { return m_serverUrlImages; } - IpList const& GetServerIps() const { return m_serverIps; } - // VDR setup - int GetLastChannel() const { return m_lastChannel == 0 ? std::numeric_limits::max() : m_lastChannel; } - int GetScreenshotInterval() const { return m_screenshotInterval; } - std::string const GetAdminLogin() const { return m_adminLogin; } - std::string const GetMD5HashAdminPassword() const; - int GetAdminPasswordLength() const; - bool GetUseAuth() const { return m_useAuth; } - bool UseAuth() const; - std::string const GetTimes() const { return m_times; } - std::string const GetChannelGroups() const { return m_channelGroups; } - std::string const GetScheduleDuration() const { return m_scheduleDuration; } - std::string const GetStartScreen() const { return m_startscreen; } - std::string const GetStartScreenLink() const; - std::string const GetTheme() const { return m_theme; } - std::string const GetThemedLink(std::string const & type, const std::string& name) const { return GetThemedLinkPrefix() + type + "/" + name; } + friend Setup& LiveSetup(); + friend class cMenuSetupLive; // friend declaration is not forward + // declaration, although GCC 3.3 claims so + + public: + typedef std::list IpList; + + // command line + int GetServerPort() const { return m_serverPort; } + int GetServerSslPort() const { return m_serverSslPort; } + std::string GetServerSslCert() const { return m_serverSslCert; } + std::string GetServerSslKey() const { return m_serverSslKey; } + const std::string &GetServerUrl() const { return m_serverUrl; } + const std::string &GetServerUrlImages() const { return m_serverUrlImages; } + IpList const& GetServerIps() const { return m_serverIps; } + // VDR setup + int GetLastChannel() const { return m_lastChannel == 0 ? std::numeric_limits::max() : m_lastChannel; } + int GetScreenshotInterval() const { return m_screenshotInterval; } + std::string const GetAdminLogin() const { return m_adminLogin; } + std::string const GetMD5HashAdminPassword() const; + int GetAdminPasswordLength() const; + bool GetUseAuth() const { return m_useAuth; } + bool UseAuth() const; + std::string const GetTimes() const { return m_times; } + std::string const GetChannelGroups() const { return m_channelGroups; } + std::string const GetScheduleDuration() const { return m_scheduleDuration; } + std::string const GetStartScreen() const { return m_startscreen; } + std::string const GetStartScreenLink() const; + std::string const GetTheme() const { return m_theme; } + std::string const GetThemedLink(std::string const & type, const std::string& name) const { return GetThemedLinkPrefix() + type + "/" + name; } std::string const GetThemedLinkPrefix() const { return m_themedLinkPrefix ; } std::string const GetThemedLinkPrefixImg() const { return m_themedLinkPrefixImg ; } - std::string const GetLocalNetMask() const { return m_localnetmask; }; - bool GetIsLocalNet() const { return m_islocalnet; }; - std::string const GetLastWhatsOnListMode() const { return m_lastwhatsonlistmode; } - std::string const GetLastSortingMode() const { return m_lastsortingmode; } - std::string const GetTntnetLogLevel() const { return m_tntnetloglevel; } - bool GetShowLogo() const { return m_showLogo != 0; } - bool GetUseArchive() const { return false; } - bool GetShowInfoBox() const { return m_showInfoBox != 0; } - bool GetUseStreamdev() const { return m_useStreamdev != 0; } - int GetStreamdevPort() const { return m_streamdevPort; } - std::string const GetStreamdevType() const { return m_streamdevType; } - bool GetMarkNewRec() const { return m_markNewRec != 0; } - std::string const GetFFmpegConf() const { return m_ffmpegConf; } - std::string const GetStreamVideoOpt0() const { return m_streamVopt0; } - std::string const GetStreamVideoOpt1() const { return m_streamVopt1; } - std::string const GetStreamVideoOpt2() const { return m_streamVopt2; } - std::string const GetStreamVideoOpt3() const { return m_streamVopt3; } - bool GetShowIMDb() const { return m_showIMDb != 0; } -// bool GetShowPlayMediaplayer() const { return m_showPlayMediaplayer != 0; } - bool GetShowPlayMediaplayer() const { return false; } - std::string const GetEpgImageDir() { return m_epgimagedir; } - const std::string &GetTvscraperImageDir() const { return m_tvscraperimagedir; } - cPlugin *GetPluginTvscraper() { return m_p_tvscraper; } // tvscraper - cPlugin *GetPluginScraper() { return m_p_scraper; } // tvscraper. Or, if not available, scraper2vdr - void SetTvscraperImageDir(const std::string &dir); - const std::string &GetChanLogoDir() const { return m_chanlogodir; } - bool GetShowChannelsWithoutEPG() const { return m_showChannelsWithoutEPG != 0; } - int GetMaxTooltipChars() const { return m_maxTooltipChars; } - - void SetLastChannel(int lastChannel) { m_lastChannel = lastChannel; } - void SetAdminLogin(std::string const & login) { m_adminLogin = login; } - std::string SetAdminPassword(std::string password); - void SetUseAuth(int auth) { m_useAuth = auth; } - void SetScreenshotInterval(int interval) { m_screenshotInterval = interval; } - void SetTimes(std::string const & times) { m_times = times; } - void SetChannelGroups(std::string const & channelGroups) { m_channelGroups = channelGroups; } - void SetScheduleDuration(std::string const & scheduleDuration) { m_scheduleDuration = scheduleDuration; } - void SetStartScreen(std::string const & startscreen) { m_startscreen = startscreen; } - void SetTheme(std::string const & theme) { m_theme = theme; m_themedLinkPrefix = "themes/" + theme + "/"; m_themedLinkPrefixImg = m_themedLinkPrefix + "img/"; } - void SetLocalNetMask(std::string const & localnetmask) { m_localnetmask = localnetmask; } - void SetIsLocalNet(bool islocalnet) { m_islocalnet = islocalnet; } - void SetLastWhatsOnListMode(std::string const & mode) { m_lastwhatsonlistmode = mode; SaveSetup(); } - void SetLastSortingMode(std::string const & mode) { m_lastsortingmode = mode; SaveSetup(); } - void SetShowLogo(bool show) { m_showLogo = show ? 1 : 0; } - void SetShowInfoBox(bool show) { m_showInfoBox = show ? 1 : 0; } - void SetUseStreamdev(bool use) { m_useStreamdev = use ? 1 : 0; } - void SetStreamdevPort(int port) { m_streamdevPort = port; } - void SetStreamdevType(std::string const & type) { m_streamdevType = type; } - void SetMarkNewRec(bool show) { m_markNewRec = show ? 1 : 0; } - void SetShowIMDb(bool show) { m_showIMDb = show ? 1 : 0; } - void SetShowPlayMediaplayer(bool show) { m_showPlayMediaplayer = show ? 1 : 0; } - void SetShowChannelsWithoutEPG(bool show) { m_showChannelsWithoutEPG = show ? 1 : 0; } - - bool SaveSetup(); - - bool ParseCommandLine( int argc, char* argv[] ); - bool Initialize( void ); - char const* CommandLineHelp() const; - - bool ParseSetupEntry( char const* name, char const* value ); - - bool CheckLocalNet(std::string const & ip); + std::string const GetLocalNetMask() const { return m_localnetmask; }; + bool GetIsLocalNet() const { return m_islocalnet; }; + std::string const GetLastWhatsOnListMode() const { return m_lastwhatsonlistmode; } + std::string const GetLastSortingMode() const { return m_lastsortingmode; } + std::string const GetTntnetLogLevel() const { return m_tntnetloglevel; } + bool GetShowLogo() const { return m_showLogo != 0; } + bool GetUseArchive() const { return false; } + bool GetShowInfoBox() const { return m_showInfoBox != 0; } + bool GetUseStreamdev() const { return m_useStreamdev != 0; } + int GetStreamdevPort() const { return m_streamdevPort; } + std::string const GetStreamdevType() const { return m_streamdevType; } + bool GetMarkNewRec() const { return m_markNewRec != 0; } + std::string const GetFFmpegConf() const { return m_ffmpegConf; } + std::string const GetStreamVideoOpt0() const { return m_streamVopt0; } + std::string const GetStreamVideoOpt1() const { return m_streamVopt1; } + std::string const GetStreamVideoOpt2() const { return m_streamVopt2; } + std::string const GetStreamVideoOpt3() const { return m_streamVopt3; } + bool GetShowIMDb() const { return m_showIMDb != 0; } +// bool GetShowPlayMediaplayer() const { return m_showPlayMediaplayer != 0; } + bool GetShowPlayMediaplayer() const { return false; } + std::string const GetEpgImageDir() { return m_epgimagedir; } + const std::string &GetTvscraperImageDir() const { return m_tvscraperimagedir; } + cPlugin *GetPluginTvscraper() { return m_p_tvscraper; } // tvscraper + cPlugin *GetPluginScraper() { return m_p_scraper; } // tvscraper. Or, if not available, scraper2vdr + void SetTvscraperImageDir(const std::string &dir); + const std::string &GetChanLogoDir() const { return m_chanlogodir; } + bool GetShowChannelsWithoutEPG() const { return m_showChannelsWithoutEPG != 0; } + int GetMaxTooltipChars() const { return m_maxTooltipChars; } + + void SetLastChannel(int lastChannel) { m_lastChannel = lastChannel; } + void SetAdminLogin(std::string const & login) { m_adminLogin = login; } + std::string SetAdminPassword(std::string password); + void SetUseAuth(int auth) { m_useAuth = auth; } + void SetScreenshotInterval(int interval) { m_screenshotInterval = interval; } + void SetTimes(std::string const & times) { m_times = times; } + void SetChannelGroups(std::string const & channelGroups) { m_channelGroups = channelGroups; } + void SetScheduleDuration(std::string const & scheduleDuration) { m_scheduleDuration = scheduleDuration; } + void SetStartScreen(std::string const & startscreen) { m_startscreen = startscreen; } + void SetTheme(std::string const & theme) { m_theme = theme; m_themedLinkPrefix = "themes/" + theme + "/"; m_themedLinkPrefixImg = m_themedLinkPrefix + "img/"; } + void SetLocalNetMask(std::string const & localnetmask) { m_localnetmask = localnetmask; } + void SetIsLocalNet(bool islocalnet) { m_islocalnet = islocalnet; } + void SetLastWhatsOnListMode(std::string const & mode) { m_lastwhatsonlistmode = mode; SaveSetup(); } + void SetLastSortingMode(std::string const & mode) { m_lastsortingmode = mode; SaveSetup(); } + void SetShowLogo(bool show) { m_showLogo = show ? 1 : 0; } + void SetShowInfoBox(bool show) { m_showInfoBox = show ? 1 : 0; } + void SetUseStreamdev(bool use) { m_useStreamdev = use ? 1 : 0; } + void SetStreamdevPort(int port) { m_streamdevPort = port; } + void SetStreamdevType(std::string const & type) { m_streamdevType = type; } + void SetMarkNewRec(bool show) { m_markNewRec = show ? 1 : 0; } + void SetShowIMDb(bool show) { m_showIMDb = show ? 1 : 0; } + void SetShowPlayMediaplayer(bool show) { m_showPlayMediaplayer = show ? 1 : 0; } + void SetShowChannelsWithoutEPG(bool show) { m_showChannelsWithoutEPG = show ? 1 : 0; } + + bool SaveSetup(); + + bool ParseCommandLine( int argc, char* argv[] ); + bool Initialize( void ); + char const* CommandLineHelp() const; + + bool ParseSetupEntry( char const* name, char const* value ); + + bool CheckLocalNet(std::string const & ip); time_t GetVdrStart() { return m_vdr_start; } - private: - Setup(); - Setup( Setup const& ); - - // me - cPlugin* liveplugin; - - mutable std::string m_helpString; - // command-line options - int m_serverPort; - int m_serverSslPort; - std::string m_serverSslCert; - std::string m_serverSslKey; - std::string m_serverUrl; - std::string m_serverUrlImages; - static std::string m_configDirectory; - IpList m_serverIps; - std::string m_epgimagedir; - std::string m_tvscraperimagedir; + private: + Setup(); + Setup( Setup const& ); + + // me + cPlugin* liveplugin; + + mutable std::string m_helpString; + // command-line options + int m_serverPort; + int m_serverSslPort; + std::string m_serverSslCert; + std::string m_serverSslKey; + std::string m_serverUrl; + std::string m_serverUrlImages; + static std::string m_configDirectory; + IpList m_serverIps; + std::string m_epgimagedir; + std::string m_tvscraperimagedir; cPlugin *m_p_tvscraper; cPlugin *m_p_scraper; - std::string m_chanlogodir; - - // setup options - int m_lastChannel; - int m_screenshotInterval; - - int m_useAuth; - std::string m_adminLogin; - std::string m_adminPasswordMD5; - std::string m_times; - std::string m_channelGroups; - std::string m_scheduleDuration; - std::string m_startscreen; - std::string m_theme; + std::string m_chanlogodir; + + // setup options + int m_lastChannel; + int m_screenshotInterval; + + int m_useAuth; + std::string m_adminLogin; + std::string m_adminPasswordMD5; + std::string m_times; + std::string m_channelGroups; + std::string m_scheduleDuration; + std::string m_startscreen; + std::string m_theme; std::string m_themedLinkPrefix; std::string m_themedLinkPrefixImg; - std::string m_localnetmask; - bool m_islocalnet; - std::string m_lastwhatsonlistmode; - std::string m_lastsortingmode; - std::string m_tntnetloglevel; - int m_showLogo; - int m_showInfoBox; - int m_useStreamdev; - int m_streamdevPort; - std::string m_streamdevType; - int m_markNewRec; - std::string m_ffmpegFile; - std::string m_ffmpegConf; - std::string m_streamVopt0; - std::string m_streamVopt1; - std::string m_streamVopt2; - std::string m_streamVopt3; - int m_showIMDb; - int m_showPlayMediaplayer; - int m_showChannelsWithoutEPG; + std::string m_localnetmask; + bool m_islocalnet; + std::string m_lastwhatsonlistmode; + std::string m_lastsortingmode; + std::string m_tntnetloglevel; + int m_showLogo; + int m_showInfoBox; + int m_useStreamdev; + int m_streamdevPort; + std::string m_streamdevType; + int m_markNewRec; + std::string m_ffmpegFile; + std::string m_ffmpegConf; + std::string m_streamVopt0; + std::string m_streamVopt1; + std::string m_streamVopt2; + std::string m_streamVopt3; + int m_showIMDb; + int m_showPlayMediaplayer; + int m_showChannelsWithoutEPG; const int m_maxTooltipChars = 300; // maximum number of characters to be displayed in tooltips - bool CheckServerPort(); - bool CheckServerIps(); - bool CheckServerSslPort(); + bool CheckServerPort(); + bool CheckServerIps(); + bool CheckServerSslPort(); time_t m_vdr_start = 0; }; @@ -222,25 +222,25 @@ Setup& LiveSetup(); class cMenuSetupLive : public cMenuSetupPage { - protected: - virtual void Store(void); - virtual eOSState ProcessKey(eKeys Key); - public: - cMenuSetupLive(); - - private: - int m_lastChannel; - int m_screenshotInterval; - - int m_useAuth; - char m_adminLogin[20]; - char m_adminPassword[20]; - char m_tmpPassword[20]; - std::string m_oldpasswordMD5; - std::string m_newpasswordMD5; - - void Set(void); - bool InEditMode(const char* ItemText, const char* ItemName, const char* ItemValue); + protected: + virtual void Store(void); + virtual eOSState ProcessKey(eKeys Key); + public: + cMenuSetupLive(); + + private: + int m_lastChannel; + int m_screenshotInterval; + + int m_useAuth; + char m_adminLogin[20]; + char m_adminPassword[20]; + char m_tmpPassword[20]; + std::string m_oldpasswordMD5; + std::string m_newpasswordMD5; + + void Set(void); + bool InEditMode(const char* ItemText, const char* ItemName, const char* ItemValue); }; } // namespace vdrlive diff --git a/status.cpp b/status.cpp index 8c8d3b2..3df6c17 100644 --- a/status.cpp +++ b/status.cpp @@ -11,18 +11,18 @@ StatusMonitor::StatusMonitor() void StatusMonitor::TimerChange(const cTimer *Timer, eTimerChange Change) { - LiveTimerManager().SetReloadTimers(); + LiveTimerManager().SetReloadTimers(); } void StatusMonitor::Recording( cDevice const*, char const*, char const*, bool ) { - LiveTimerManager().SetReloadTimers(); + LiveTimerManager().SetReloadTimers(); } StatusMonitor& LiveStatusMonitor() { - static StatusMonitor instance; - return instance; + static StatusMonitor instance; + return instance; } } // namespace vdrlive diff --git a/status.h b/status.h index 2f2f383..1fcdc9a 100644 --- a/status.h +++ b/status.h @@ -11,14 +11,14 @@ namespace vdrlive { class StatusMonitor: public cStatus { - friend StatusMonitor& LiveStatusMonitor(); + friend StatusMonitor& LiveStatusMonitor(); private: - StatusMonitor(); - StatusMonitor( StatusMonitor const& ); + StatusMonitor(); + StatusMonitor( StatusMonitor const& ); - virtual void TimerChange(const cTimer *Timer, eTimerChange Change); - virtual void Recording( cDevice const* Device, char const* Name, char const* FileName, bool On ); + virtual void TimerChange(const cTimer *Timer, eTimerChange Change); + virtual void Recording( cDevice const* Device, char const* Name, char const* FileName, bool On ); }; StatusMonitor& LiveStatusMonitor(); diff --git a/tasks.cpp b/tasks.cpp index 9138206..d2576d6 100644 --- a/tasks.cpp +++ b/tasks.cpp @@ -18,208 +18,208 @@ namespace vdrlive { const char* NowReplaying() { - return cReplayControl::NowReplaying(); + return cReplayControl::NowReplaying(); } StickyTask::StickyTask() { - LiveTaskManager().AddStickyTask( *this ); + LiveTaskManager().AddStickyTask( *this ); } StickyTask::~StickyTask() { - LiveTaskManager().RemoveStickyTask( *this ); + LiveTaskManager().RemoveStickyTask( *this ); } void SwitchChannelTask::Action() { - LOCK_CHANNELS_READ; - cChannel* channel = (cChannel *)Channels->GetByChannelID( m_channel ); - if ( channel == 0 ) { - SetError( tr("Couldn't find channel or no channels available.") ); - return; - } - - if ( !Channels->SwitchTo( channel->Number() ) ) - SetError( tr("Couldn't switch to channel.") ); + LOCK_CHANNELS_READ; + cChannel* channel = (cChannel *)Channels->GetByChannelID( m_channel ); + if ( channel == 0 ) { + SetError( tr("Couldn't find channel or no channels available.") ); + return; + } + + if ( !Channels->SwitchTo( channel->Number() ) ) + SetError( tr("Couldn't switch to channel.") ); } void PlayRecordingTask::Action() { - RecordingsManagerPtr recordings = LiveRecordingsManager(); - cRecording const* recording = recordings->GetByMd5Hash( m_recording ); - if ( recording == 0 ) { - SetError( tr("Couldn't find recording or no recordings available.") ); - return; - } - - const char *current = NowReplaying(); - if (!current || (0 != strcmp(current, recording->FileName()))) { - cReplayControl::SetRecording( 0 ); - cControl::Shutdown(); - cReplayControl::SetRecording( recording->FileName() ); - cControl::Launch( new cReplayControl ); - cControl::Attach(); - } - else { + RecordingsManagerPtr recordings = LiveRecordingsManager(); + cRecording const* recording = recordings->GetByMd5Hash( m_recording ); + if ( recording == 0 ) { + SetError( tr("Couldn't find recording or no recordings available.") ); + return; + } + + const char *current = NowReplaying(); + if (!current || (0 != strcmp(current, recording->FileName()))) { + cReplayControl::SetRecording( 0 ); + cControl::Shutdown(); + cReplayControl::SetRecording( recording->FileName() ); + cControl::Launch( new cReplayControl ); + cControl::Attach(); + } + else { #if APIVERSNUM >= 20402 - cMutexLock mutexLock; - cReplayControl* replayControl = reinterpret_cast(cControl::Control(mutexLock)); + cMutexLock mutexLock; + cReplayControl* replayControl = reinterpret_cast(cControl::Control(mutexLock)); #else - cReplayControl* replayControl = reinterpret_cast(cControl::Control()); + cReplayControl* replayControl = reinterpret_cast(cControl::Control()); #endif - if (! replayControl) { - SetError(tr("Cannot control playback!")); - return; - } + if (! replayControl) { + SetError(tr("Cannot control playback!")); + return; + } - replayControl->Play(); - } + replayControl->Play(); + } } void PauseRecordingTask::Action() { - RecordingsManagerPtr recordings = LiveRecordingsManager(); - cRecording const* recording = recordings->GetByMd5Hash( m_recording ); - if ( recording == 0 ) { - SetError( tr("Couldn't find recording or no recordings available.") ); - return; - } - - const char *current = NowReplaying(); - if (!current) { - SetError(tr("Not playing a recording.")); - return; - } - - if (0 != strcmp(current, recording->FileName())) { - // not replaying same recording like in request - SetError(tr("Not playing the same recording as from request.")); - return; - } + RecordingsManagerPtr recordings = LiveRecordingsManager(); + cRecording const* recording = recordings->GetByMd5Hash( m_recording ); + if ( recording == 0 ) { + SetError( tr("Couldn't find recording or no recordings available.") ); + return; + } + + const char *current = NowReplaying(); + if (!current) { + SetError(tr("Not playing a recording.")); + return; + } + + if (0 != strcmp(current, recording->FileName())) { + // not replaying same recording like in request + SetError(tr("Not playing the same recording as from request.")); + return; + } #if APIVERSNUM >= 20402 - cMutexLock mutexLock; - cReplayControl* replayControl = reinterpret_cast(cControl::Control(mutexLock)); + cMutexLock mutexLock; + cReplayControl* replayControl = reinterpret_cast(cControl::Control(mutexLock)); #else - cReplayControl* replayControl = reinterpret_cast(cControl::Control()); + cReplayControl* replayControl = reinterpret_cast(cControl::Control()); #endif - if (! replayControl) { - SetError(tr("Cannot control playback!")); - return; - } + if (! replayControl) { + SetError(tr("Cannot control playback!")); + return; + } - replayControl->Pause(); + replayControl->Pause(); } void StopRecordingTask::Action() { - RecordingsManagerPtr recordings = LiveRecordingsManager(); - cRecording const* recording = recordings->GetByMd5Hash( m_recording ); - if ( recording == 0 ) { - SetError( tr("Couldn't find recording or no recordings available.") ); - return; - } - - const char *current = NowReplaying(); - if (!current) { - SetError(tr("Not playing a recording.")); - return; - } - - cReplayControl::SetRecording( 0 ); - cControl::Shutdown(); + RecordingsManagerPtr recordings = LiveRecordingsManager(); + cRecording const* recording = recordings->GetByMd5Hash( m_recording ); + if ( recording == 0 ) { + SetError( tr("Couldn't find recording or no recordings available.") ); + return; + } + + const char *current = NowReplaying(); + if (!current) { + SetError(tr("Not playing a recording.")); + return; + } + + cReplayControl::SetRecording( 0 ); + cControl::Shutdown(); } void ForwardRecordingTask::Action() { - RecordingsManagerPtr recordings = LiveRecordingsManager(); - cRecording const* recording = recordings->GetByMd5Hash( m_recording ); - if ( recording == 0 ) { - SetError( tr("Couldn't find recording or no recordings available.") ); - return; - } - - const char *current = NowReplaying(); - if (!current) { - SetError(tr("Not playing a recording.")); - return; - } - - if (0 != strcmp(current, recording->FileName())) { - // not replaying same recording like in request - SetError(tr("Not playing the same recording as from request.")); - return; - } + RecordingsManagerPtr recordings = LiveRecordingsManager(); + cRecording const* recording = recordings->GetByMd5Hash( m_recording ); + if ( recording == 0 ) { + SetError( tr("Couldn't find recording or no recordings available.") ); + return; + } + + const char *current = NowReplaying(); + if (!current) { + SetError(tr("Not playing a recording.")); + return; + } + + if (0 != strcmp(current, recording->FileName())) { + // not replaying same recording like in request + SetError(tr("Not playing the same recording as from request.")); + return; + } #if APIVERSNUM >= 20402 - cMutexLock mutexLock; - cReplayControl* replayControl = reinterpret_cast(cControl::Control(mutexLock)); + cMutexLock mutexLock; + cReplayControl* replayControl = reinterpret_cast(cControl::Control(mutexLock)); #else - cReplayControl* replayControl = reinterpret_cast(cControl::Control()); + cReplayControl* replayControl = reinterpret_cast(cControl::Control()); #endif - if (! replayControl) { - SetError(tr("Cannot control playback!")); - return; - } + if (! replayControl) { + SetError(tr("Cannot control playback!")); + return; + } - replayControl->Forward(); + replayControl->Forward(); } void BackwardRecordingTask::Action() { - RecordingsManagerPtr recordings = LiveRecordingsManager(); - cRecording const* recording = recordings->GetByMd5Hash( m_recording ); - if ( recording == 0 ) { - SetError(tr("Couldn't find recording or no recordings available.")); - return; - } - - const char *current = NowReplaying(); - if (!current) { - SetError(tr("Not playing a recording.")); - return; - } - - if (0 != strcmp(current, recording->FileName())) { - // not replaying same recording like in request - SetError(tr("Not playing the same recording as from request.")); - return; - } + RecordingsManagerPtr recordings = LiveRecordingsManager(); + cRecording const* recording = recordings->GetByMd5Hash( m_recording ); + if ( recording == 0 ) { + SetError(tr("Couldn't find recording or no recordings available.")); + return; + } + + const char *current = NowReplaying(); + if (!current) { + SetError(tr("Not playing a recording.")); + return; + } + + if (0 != strcmp(current, recording->FileName())) { + // not replaying same recording like in request + SetError(tr("Not playing the same recording as from request.")); + return; + } #if APIVERSNUM >= 20402 - cMutexLock mutexLock; - cReplayControl* replayControl = reinterpret_cast(cControl::Control(mutexLock)); + cMutexLock mutexLock; + cReplayControl* replayControl = reinterpret_cast(cControl::Control(mutexLock)); #else - cReplayControl* replayControl = reinterpret_cast(cControl::Control()); + cReplayControl* replayControl = reinterpret_cast(cControl::Control()); #endif - if (! replayControl) { - SetError(tr("Cannot control playback!")); - return; - } + if (! replayControl) { + SetError(tr("Cannot control playback!")); + return; + } - replayControl->Backward(); + replayControl->Backward(); } void RemoveRecordingTask::Action() { - RecordingsManagerPtr recordings = LiveRecordingsManager(); - cRecording const * recording = recordings->GetByMd5Hash( m_recording ); - if ( recording == 0 ) { - SetError( tr("Couldn't find recording or no recordings available.") ); - return; - } - - m_recName = recording->Name(); - - const char *current = NowReplaying(); - if (current && (0 == strcmp(current, recording->FileName()))) { - SetError(tr("Attempt to delete recording currently in playback.")); - return; - } - - recordings->DeleteRecording(recording); + RecordingsManagerPtr recordings = LiveRecordingsManager(); + cRecording const * recording = recordings->GetByMd5Hash( m_recording ); + if ( recording == 0 ) { + SetError( tr("Couldn't find recording or no recordings available.") ); + return; + } + + m_recName = recording->Name(); + + const char *current = NowReplaying(); + if (current && (0 == strcmp(current, recording->FileName()))) { + SetError(tr("Attempt to delete recording currently in playback.")); + return; + } + + recordings->DeleteRecording(recording); } TaskManager::TaskManager() @@ -228,45 +228,45 @@ TaskManager::TaskManager() void TaskManager::AddStickyTask( Task& task ) { - cMutexLock lock( this ); - m_stickyTasks.push_back( &task ); + cMutexLock lock( this ); + m_stickyTasks.push_back( &task ); } void TaskManager::RemoveStickyTask( Task& task ) { - cMutexLock lock( this ); - m_stickyTasks.erase( find( m_stickyTasks.begin(), m_stickyTasks.end(), &task ) ); + cMutexLock lock( this ); + m_stickyTasks.erase( find( m_stickyTasks.begin(), m_stickyTasks.end(), &task ) ); } bool TaskManager::Execute( Task& task ) { - cMutexLock lock( this ); + cMutexLock lock( this ); - m_taskQueue.push_back( &task ); - m_scheduleWait.Wait( *this ); - return task.Result(); + m_taskQueue.push_back( &task ); + m_scheduleWait.Wait( *this ); + return task.Result(); } void TaskManager::DoScheduledTasks() { - if ( m_taskQueue.empty() && m_stickyTasks.empty() ) - return; + if ( m_taskQueue.empty() && m_stickyTasks.empty() ) + return; using std::for_each; using std::bind; using namespace std::placeholders; - cMutexLock lock( this ); - for_each( m_taskQueue.begin(), m_taskQueue.end(), bind( &Task::Action, _1 ) ); - for_each( m_stickyTasks.begin(), m_stickyTasks.end(), bind( &Task::Action, _1 ) ); - m_taskQueue.clear(); - m_scheduleWait.Broadcast(); + cMutexLock lock( this ); + for_each( m_taskQueue.begin(), m_taskQueue.end(), bind( &Task::Action, _1 ) ); + for_each( m_stickyTasks.begin(), m_stickyTasks.end(), bind( &Task::Action, _1 ) ); + m_taskQueue.clear(); + m_scheduleWait.Broadcast(); } TaskManager& LiveTaskManager() { - static TaskManager instance; - return instance; + static TaskManager instance; + return instance; } } // namespace vdrlive diff --git a/tasks.h b/tasks.h index 5700f11..5d63ea8 100644 --- a/tasks.h +++ b/tasks.h @@ -18,145 +18,145 @@ class Task; class TaskManager: public cMutex { - friend TaskManager& LiveTaskManager(); - friend class StickyTask; + friend TaskManager& LiveTaskManager(); + friend class StickyTask; - typedef std::vector TaskList; + typedef std::vector TaskList; public: - bool Execute( Task& task ); + bool Execute( Task& task ); - // may only be called from Plugin::MainThreadHook - void DoScheduledTasks(); + // may only be called from Plugin::MainThreadHook + void DoScheduledTasks(); private: - TaskManager(); - TaskManager( TaskManager const& ); + TaskManager(); + TaskManager( TaskManager const& ); - void AddStickyTask( Task& task ); - void RemoveStickyTask( Task& task ); + void AddStickyTask( Task& task ); + void RemoveStickyTask( Task& task ); - TaskList m_taskQueue; - TaskList m_stickyTasks; - cCondVar m_scheduleWait; + TaskList m_taskQueue; + TaskList m_stickyTasks; + cCondVar m_scheduleWait; }; class Task { - friend void TaskManager::DoScheduledTasks(); + friend void TaskManager::DoScheduledTasks(); public: - virtual ~Task() {} + virtual ~Task() {} - bool Result() const { return m_result; } - std::string const& Error() const { return m_error; } + bool Result() const { return m_result; } + std::string const& Error() const { return m_error; } protected: - explicit Task() - : m_result( true ) - {} - Task( Task const& ); + explicit Task() + : m_result( true ) + {} + Task( Task const& ); - void SetError( std::string const& error ) { m_result = false; m_error = error; } + void SetError( std::string const& error ) { m_result = false; m_error = error; } private: - bool m_result; - std::string m_error; + bool m_result; + std::string m_error; - virtual void Action() = 0; + virtual void Action() = 0; }; class StickyTask: public Task { protected: - explicit StickyTask(); - virtual ~StickyTask(); + explicit StickyTask(); + virtual ~StickyTask(); }; class SwitchChannelTask: public Task { public: - explicit SwitchChannelTask( tChannelID channel ): m_channel( channel ) {} + explicit SwitchChannelTask( tChannelID channel ): m_channel( channel ) {} private: - tChannelID m_channel; + tChannelID m_channel; - virtual void Action() override; + virtual void Action() override; }; class RecordingTask: public Task { protected: - explicit RecordingTask(std::string const& recording) - : m_recording(recording) - {} + explicit RecordingTask(std::string const& recording) + : m_recording(recording) + {} - std::string m_recording; + std::string m_recording; }; class PlayRecordingTask: public RecordingTask { public: - explicit PlayRecordingTask( std::string const& recording ) - : RecordingTask(recording) - {} + explicit PlayRecordingTask( std::string const& recording ) + : RecordingTask(recording) + {} - virtual void Action() override; + virtual void Action() override; }; class PauseRecordingTask: public RecordingTask { public: - explicit PauseRecordingTask( std::string const& recording ) - : RecordingTask(recording) - {} + explicit PauseRecordingTask( std::string const& recording ) + : RecordingTask(recording) + {} - virtual void Action() override; + virtual void Action() override; }; class StopRecordingTask: public RecordingTask { public: - explicit StopRecordingTask( std::string const& recording ) - : RecordingTask(recording) - {} + explicit StopRecordingTask( std::string const& recording ) + : RecordingTask(recording) + {} - virtual void Action() override; + virtual void Action() override; }; class ForwardRecordingTask: public RecordingTask { public: - explicit ForwardRecordingTask( std::string const& recording ) - : RecordingTask(recording) - {} + explicit ForwardRecordingTask( std::string const& recording ) + : RecordingTask(recording) + {} - virtual void Action() override; + virtual void Action() override; }; class BackwardRecordingTask: public RecordingTask { public: - explicit BackwardRecordingTask( std::string const& recording ) - : RecordingTask(recording) - {} + explicit BackwardRecordingTask( std::string const& recording ) + : RecordingTask(recording) + {} - virtual void Action() override; + virtual void Action() override; }; class RemoveRecordingTask: public RecordingTask { public: - explicit RemoveRecordingTask( std::string const& recording ) - : RecordingTask(recording) - {} + explicit RemoveRecordingTask( std::string const& recording ) + : RecordingTask(recording) + {} - virtual void Action() override; + virtual void Action() override; - std::string const & RecName() const { return m_recName; } + std::string const & RecName() const { return m_recName; } private: - std::string m_recName; + std::string m_recName; }; diff --git a/thread.cpp b/thread.cpp index 2366e3f..3090882 100644 --- a/thread.cpp +++ b/thread.cpp @@ -16,30 +16,30 @@ ServerThread::ServerThread() ServerThread::~ServerThread() { - Stop(); + Stop(); } void ServerThread::Stop() { - if ( Active() ) { - m_server->shutdown(); - Cancel( 5 ); - } + if ( Active() ) { + m_server->shutdown(); + Cancel( 5 ); + } } void ServerThread::Action() { - try { - m_server.reset(new Tntnet()); - TntConfig::Get().Configure(*m_server); - m_server->run(); - m_server.reset(0); - } catch (std::exception const& ex) { - // XXX move initial error handling to live.cpp - esyslog("live: ERROR: live httpd server crashed: %s", ex.what()); - std::cerr << "HTTPD FATAL ERROR: " << ex.what() << std::endl; - //cThread::EmergencyExit(true); - } + try { + m_server.reset(new Tntnet()); + TntConfig::Get().Configure(*m_server); + m_server->run(); + m_server.reset(0); + } catch (std::exception const& ex) { + // XXX move initial error handling to live.cpp + esyslog("live: ERROR: live httpd server crashed: %s", ex.what()); + std::cerr << "HTTPD FATAL ERROR: " << ex.what() << std::endl; + //cThread::EmergencyExit(true); + } } } // namespace vdrlive diff --git a/thread.h b/thread.h index 8e90cd2..e0da8a3 100644 --- a/thread.h +++ b/thread.h @@ -11,16 +11,16 @@ namespace vdrlive { class ServerThread : public cThread { public: - ServerThread(); - virtual ~ServerThread(); + ServerThread(); + virtual ~ServerThread(); - void Stop(); + void Stop(); protected: - virtual void Action(); + virtual void Action(); private: - std::unique_ptr m_server; + std::unique_ptr m_server; }; } // namespace vdrlive diff --git a/timerconflict.cpp b/timerconflict.cpp index 66d5411..b4f491a 100644 --- a/timerconflict.cpp +++ b/timerconflict.cpp @@ -13,104 +13,104 @@ namespace vdrlive { - bool CheckEpgsearchVersion(); - - static char ServiceInterface[] = "Epgsearch-services-v1.1"; - - bool operator<( TimerConflict const& left, TimerConflict const& right ) - { - return left.conflictTime < right.conflictTime; - } - - TimerConflict::TimerConflict() - { - Init(); - } - - void TimerConflict::Init() - { - conflictTime = 0; - } - - TimerConflict::TimerConflict( std::string const& data ) - { - Init(); -// dsyslog("live: TimerConflict() data '%s'", data.c_str()); - std::vector parts = StringSplit( data, ':' ); - try { - std::vector::const_iterator part = parts.begin(); - if (parts.size() > 0) { - conflictTime = parse_int( *part++ ); - for ( int i = 1; part != parts.end(); ++i, ++part ) { - std::vector timerparts = StringSplit( *part, '|' ); - std::vector::const_iterator timerpart = timerparts.begin(); - TimerInConflict timer; - for ( int j = 0; timerpart != timerparts.end(); ++j, ++timerpart ) { - switch (j) { - case 0: timer.timerIndex = parse_int( *timerpart ); break; - case 1: timer.percentage = parse_int( *timerpart ); break; - case 2: { - std::vector conctimerparts = StringSplit( *timerpart, '#' ); - std::vector::const_iterator conctimerpart = conctimerparts.begin(); - for ( int k = 0; conctimerpart != conctimerparts.end(); ++k, ++conctimerpart ) - timer.concurrentTimerIndices.push_back(parse_int( *conctimerpart )); - break; - } - case 3: { - timer.remote = *timerpart; - break; - } - } - } - conflictingTimers.push_back(timer); - } - } - } - catch ( bad_lexical_cast const& ex ) { - } - } - - TimerConflicts::TimerConflicts() - { - Epgsearch_services_v1_1 service; - if ( CheckEpgsearchVersion() && cPluginManager::CallFirstService(ServiceInterface, &service)) - { - cServiceHandler_v1_1* handler = dynamic_cast(service.handler.get()); - if (handler) - { - std::list conflicts = service.handler->TimerConflictList(); -// for(std::list::const_iterator i = conflicts.begin(); i != conflicts.end(); ++i) { -// dsyslog("live: TimerConflicts::TimerConflicts() conflicts '%s'",i->c_str()); -// } - GetRemote(conflicts); // add remote VDR conflicts - m_conflicts.assign( conflicts.begin(), conflicts.end() ); - m_conflicts.sort(); - } - } -// for (TimerConflicts::iterator conflict=m_conflicts.begin(); conflict!=m_conflicts.end(); conflict++) { -// const std::list& conflTimers = conflict->ConflictingTimers(); -// for (std::list::const_iterator confltimer = conflTimers.begin(); confltimer != conflTimers.end(); ++confltimer) { -// dsyslog("live: TimerConflicts::TimerConflictsi() Timer ID with conflict '%d'", confltimer->timerIndex ); -// dsyslog("live: TimerConflicts::TimerConflictsi() conflict on server '%s'", confltimer->remote.c_str() ); -// for (std::list::const_iterator timerIndex = confltimer->concurrentTimerIndices.begin(); timerIndex != confltimer->concurrentTimerIndices.end(); ++timerIndex) { -// dsyslog("live: TimerConflicts::TimerConflicts() concurrent Timer IDs '%d'", *timerIndex); -// } -// } -// } - } - - - void TimerConflicts::GetRemote(std::list & conflicts ) - { - cStringList svdrpServerNames; - - if (GetSVDRPServerNames(&svdrpServerNames)) { - svdrpServerNames.Sort(true); - } - for (int i = 0; i < svdrpServerNames.Size(); i++) { - std::string remoteServer = svdrpServerNames[i]; -// dsyslog("live: TimerConflicts::GetRemote() found remote server '%s'", remoteServer.c_str()); - cStringList response; + bool CheckEpgsearchVersion(); + + static char ServiceInterface[] = "Epgsearch-services-v1.1"; + + bool operator<( TimerConflict const& left, TimerConflict const& right ) + { + return left.conflictTime < right.conflictTime; + } + + TimerConflict::TimerConflict() + { + Init(); + } + + void TimerConflict::Init() + { + conflictTime = 0; + } + + TimerConflict::TimerConflict( std::string const& data ) + { + Init(); +// dsyslog("live: TimerConflict() data '%s'", data.c_str()); + std::vector parts = StringSplit( data, ':' ); + try { + std::vector::const_iterator part = parts.begin(); + if (parts.size() > 0) { + conflictTime = parse_int( *part++ ); + for ( int i = 1; part != parts.end(); ++i, ++part ) { + std::vector timerparts = StringSplit( *part, '|' ); + std::vector::const_iterator timerpart = timerparts.begin(); + TimerInConflict timer; + for ( int j = 0; timerpart != timerparts.end(); ++j, ++timerpart ) { + switch (j) { + case 0: timer.timerIndex = parse_int( *timerpart ); break; + case 1: timer.percentage = parse_int( *timerpart ); break; + case 2: { + std::vector conctimerparts = StringSplit( *timerpart, '#' ); + std::vector::const_iterator conctimerpart = conctimerparts.begin(); + for ( int k = 0; conctimerpart != conctimerparts.end(); ++k, ++conctimerpart ) + timer.concurrentTimerIndices.push_back(parse_int( *conctimerpart )); + break; + } + case 3: { + timer.remote = *timerpart; + break; + } + } + } + conflictingTimers.push_back(timer); + } + } + } + catch ( bad_lexical_cast const& ex ) { + } + } + + TimerConflicts::TimerConflicts() + { + Epgsearch_services_v1_1 service; + if ( CheckEpgsearchVersion() && cPluginManager::CallFirstService(ServiceInterface, &service)) + { + cServiceHandler_v1_1* handler = dynamic_cast(service.handler.get()); + if (handler) + { + std::list conflicts = service.handler->TimerConflictList(); +// for(std::list::const_iterator i = conflicts.begin(); i != conflicts.end(); ++i) { +// dsyslog("live: TimerConflicts::TimerConflicts() conflicts '%s'",i->c_str()); +// } + GetRemote(conflicts); // add remote VDR conflicts + m_conflicts.assign( conflicts.begin(), conflicts.end() ); + m_conflicts.sort(); + } + } +// for (TimerConflicts::iterator conflict=m_conflicts.begin(); conflict!=m_conflicts.end(); conflict++) { +// const std::list& conflTimers = conflict->ConflictingTimers(); +// for (std::list::const_iterator confltimer = conflTimers.begin(); confltimer != conflTimers.end(); ++confltimer) { +// dsyslog("live: TimerConflicts::TimerConflictsi() Timer ID with conflict '%d'", confltimer->timerIndex ); +// dsyslog("live: TimerConflicts::TimerConflictsi() conflict on server '%s'", confltimer->remote.c_str() ); +// for (std::list::const_iterator timerIndex = confltimer->concurrentTimerIndices.begin(); timerIndex != confltimer->concurrentTimerIndices.end(); ++timerIndex) { +// dsyslog("live: TimerConflicts::TimerConflicts() concurrent Timer IDs '%d'", *timerIndex); +// } +// } +// } + } + + + void TimerConflicts::GetRemote(std::list & conflicts ) + { + cStringList svdrpServerNames; + + if (GetSVDRPServerNames(&svdrpServerNames)) { + svdrpServerNames.Sort(true); + } + for (int i = 0; i < svdrpServerNames.Size(); i++) { + std::string remoteServer = svdrpServerNames[i]; +// dsyslog("live: TimerConflicts::GetRemote() found remote server '%s'", remoteServer.c_str()); + cStringList response; std::string command = "PLUG epgsearch lscc"; bool svdrpOK = ExecSVDRPCommand(remoteServer.c_str(), command.c_str(), &response); if ( !svdrpOK ) { @@ -119,108 +119,108 @@ namespace vdrlive { else { for (int i = 0; i < response.Size(); i++) { int code = SVDRPCode(response[i]); -// dsyslog("live: GetRemote() response[i] '%s'", response[i]); - switch ( code ) { - case 900: { - std::string rConflict = response[i]; - std::string remConflict = rConflict.substr(4); - remConflict.append("|"); - remConflict.append(remoteServer); -// dsyslog("live: TimerConflicts::GetRemote() found remote conflict '%s' ", remConflict.c_str()); - conflicts.push_back(remConflict); - break; - } - case 901: break; // no conflict found - default: { - esyslog("live: TimerConflicts::GetRemote() svdrp command '%s' failed, respone: %s", command.c_str(), response[i]); - svdrpOK = false; - break; - } - } - } +// dsyslog("live: GetRemote() response[i] '%s'", response[i]); + switch ( code ) { + case 900: { + std::string rConflict = response[i]; + std::string remConflict = rConflict.substr(4); + remConflict.append("|"); + remConflict.append(remoteServer); +// dsyslog("live: TimerConflicts::GetRemote() found remote conflict '%s' ", remConflict.c_str()); + conflicts.push_back(remConflict); + break; + } + case 901: break; // no conflict found + default: { + esyslog("live: TimerConflicts::GetRemote() svdrp command '%s' failed, respone: %s", command.c_str(), response[i]); + svdrpOK = false; + break; + } + } + } if ( svdrpOK ) { -// dsyslog("live: TimerConflicts::GetRemote() on server '%s' successful", remoteServer.c_str()); - } +// dsyslog("live: TimerConflicts::GetRemote() on server '%s' successful", remoteServer.c_str()); + } else { - esyslog("live: TimerConflicts::GetRemote() on server '%s' failed", remoteServer.c_str()); - } - } - response.Clear(); - } - svdrpServerNames.Clear(); - } - - bool TimerConflicts::HasConflict(int timerId) - { - for (const auto& conflict : *this) - for (const auto& tic : conflict.ConflictingTimers()) - if (tic.timerIndex == timerId) - return true; - return false; - } - - bool TimerConflicts::CheckAdvised() - { - Epgsearch_services_v1_1 service; - if (CheckEpgsearchVersion() && cPluginManager::CallFirstService(ServiceInterface, &service)) - { - cServiceHandler_v1_1* handler = dynamic_cast(service.handler.get()); - if (!handler) - return false; - else - return handler->IsConflictCheckAdvised(); - } - else - return false; - } - - TimerConflictNotifier::TimerConflictNotifier() - : lastCheck(0) - , lastTimerModification(0) - , conflicts() - { - } - - TimerConflictNotifier::~TimerConflictNotifier() - { - } - - bool TimerConflictNotifier::ShouldNotify() - { - time_t now = time(0); - bool reCheckAdvised((now - lastCheck) > CHECKINTERVAL); - bool recentTimerChange((now - lastTimerModification) <= CHECKINTERVAL); - - if (recentTimerChange || (reCheckAdvised && TimerConflicts::CheckAdvised())) { - lastCheck = now; - conflicts.reset(new TimerConflicts()); - return conflicts->size() > 0; - } - return false; - } - - void TimerConflictNotifier::SetTimerModification() - { - lastTimerModification = time(0); - } - - std::string TimerConflictNotifier::Message() const - { - int count = conflicts ? conflicts->size() : 0; - std::string msg = tr("Timer conflict check detected "); - msg += ConvertToString(count) + " "; - if (count == 1) - msg += tr("conflict"); - else - msg += tr("conflicts"); - - return count > 0 ? msg + "!" : ""; - } - - std::string TimerConflictNotifier::Url() const - { - return "timerconflicts.html"; - } + esyslog("live: TimerConflicts::GetRemote() on server '%s' failed", remoteServer.c_str()); + } + } + response.Clear(); + } + svdrpServerNames.Clear(); + } + + bool TimerConflicts::HasConflict(int timerId) + { + for (const auto& conflict : *this) + for (const auto& tic : conflict.ConflictingTimers()) + if (tic.timerIndex == timerId) + return true; + return false; + } + + bool TimerConflicts::CheckAdvised() + { + Epgsearch_services_v1_1 service; + if (CheckEpgsearchVersion() && cPluginManager::CallFirstService(ServiceInterface, &service)) + { + cServiceHandler_v1_1* handler = dynamic_cast(service.handler.get()); + if (!handler) + return false; + else + return handler->IsConflictCheckAdvised(); + } + else + return false; + } + + TimerConflictNotifier::TimerConflictNotifier() + : lastCheck(0) + , lastTimerModification(0) + , conflicts() + { + } + + TimerConflictNotifier::~TimerConflictNotifier() + { + } + + bool TimerConflictNotifier::ShouldNotify() + { + time_t now = time(0); + bool reCheckAdvised((now - lastCheck) > CHECKINTERVAL); + bool recentTimerChange((now - lastTimerModification) <= CHECKINTERVAL); + + if (recentTimerChange || (reCheckAdvised && TimerConflicts::CheckAdvised())) { + lastCheck = now; + conflicts.reset(new TimerConflicts()); + return conflicts->size() > 0; + } + return false; + } + + void TimerConflictNotifier::SetTimerModification() + { + lastTimerModification = time(0); + } + + std::string TimerConflictNotifier::Message() const + { + int count = conflicts ? conflicts->size() : 0; + std::string msg = tr("Timer conflict check detected "); + msg += ConvertToString(count) + " "; + if (count == 1) + msg += tr("conflict"); + else + msg += tr("conflicts"); + + return count > 0 ? msg + "!" : ""; + } + + std::string TimerConflictNotifier::Url() const + { + return "timerconflicts.html"; + } } // namespace vdrlive diff --git a/timerconflict.h b/timerconflict.h index c8647cb..377fb13 100644 --- a/timerconflict.h +++ b/timerconflict.h @@ -14,85 +14,85 @@ namespace vdrlive { // classes for timer conflict interface // conflicting timer - class TimerInConflict - { - public: - int timerIndex; // it's index in VDR - std::string remote = ""; - int percentage; // percentage of recording - std::list concurrentTimerIndices; // concurrent timer indices + class TimerInConflict + { + public: + int timerIndex; // it's index in VDR + std::string remote = ""; + int percentage; // percentage of recording + std::list concurrentTimerIndices; // concurrent timer indices - TimerInConflict(int TimerIndex=-1, int Percentage=0) : timerIndex(TimerIndex), percentage(Percentage) {} - }; + TimerInConflict(int TimerIndex=-1, int Percentage=0) : timerIndex(TimerIndex), percentage(Percentage) {} + }; - class TimerConflict; + class TimerConflict; - bool operator<( TimerConflict const& left, TimerConflict const& right ); + bool operator<( TimerConflict const& left, TimerConflict const& right ); // one timer conflict time - class TimerConflict - { - time_t conflictTime; // time of conflict - std::list conflictingTimers; // conflicting timers at this time + class TimerConflict + { + time_t conflictTime; // time of conflict + std::list conflictingTimers; // conflicting timers at this time - friend bool operator<( TimerConflict const& left, TimerConflict const& right ); + friend bool operator<( TimerConflict const& left, TimerConflict const& right ); - public: - TimerConflict( std::string const& data ); - TimerConflict(); - void Init(); + public: + TimerConflict( std::string const& data ); + TimerConflict(); + void Init(); - time_t ConflictTime() { return conflictTime; } - const std::list& ConflictingTimers() const { return conflictingTimers; } - }; + time_t ConflictTime() { return conflictTime; } + const std::list& ConflictingTimers() const { return conflictingTimers; } + }; - class TimerConflicts - { - public: - typedef std::list ConflictList; - typedef ConflictList::size_type size_type; - typedef ConflictList::iterator iterator; - typedef ConflictList::const_iterator const_iterator; + class TimerConflicts + { + public: + typedef std::list ConflictList; + typedef ConflictList::size_type size_type; + typedef ConflictList::iterator iterator; + typedef ConflictList::const_iterator const_iterator; - TimerConflicts(); + TimerConflicts(); - size_type size() const { return m_conflicts.size(); } - iterator begin() { return m_conflicts.begin(); } - const_iterator begin() const { return m_conflicts.begin(); } - iterator end() { return m_conflicts.end(); } - const_iterator end() const { return m_conflicts.end(); } + size_type size() const { return m_conflicts.size(); } + iterator begin() { return m_conflicts.begin(); } + const_iterator begin() const { return m_conflicts.begin(); } + iterator end() { return m_conflicts.end(); } + const_iterator end() const { return m_conflicts.end(); } - bool HasConflict(int timerId); - static bool CheckAdvised(); - private: - void GetRemote(std::list & conflicts); - ConflictList m_conflicts; - }; + bool HasConflict(int timerId); + static bool CheckAdvised(); + private: + void GetRemote(std::list & conflicts); + ConflictList m_conflicts; + }; - class TimerConflictNotifier - { - public: - typedef std::shared_ptr TimerConflictsPtr; + class TimerConflictNotifier + { + public: + typedef std::shared_ptr TimerConflictsPtr; - TimerConflictNotifier(); - virtual ~TimerConflictNotifier(); + TimerConflictNotifier(); + virtual ~TimerConflictNotifier(); - bool ShouldNotify(); + bool ShouldNotify(); - void SetTimerModification(); + void SetTimerModification(); - std::string Message() const; - std::string Url() const; + std::string Message() const; + std::string Url() const; - TimerConflictsPtr const CurrentConflicts() const { return conflicts; } + TimerConflictsPtr const CurrentConflicts() const { return conflicts; } - static int const CHECKINTERVAL = 5; // recheck value in seconds. + static int const CHECKINTERVAL = 5; // recheck value in seconds. - private: - time_t lastCheck; - time_t lastTimerModification; - TimerConflictsPtr conflicts; - }; // class TimerConflictNotifier + private: + time_t lastCheck; + time_t lastTimerModification; + TimerConflictsPtr conflicts; + }; // class TimerConflictNotifier } // namespace vdrlive diff --git a/timers.cpp b/timers.cpp index 20afceb..4fe16ef 100644 --- a/timers.cpp +++ b/timers.cpp @@ -15,110 +15,110 @@ namespace vdrlive { - static char const* const TIMER_DELETE = "DELETE"; - static char const* const TIMER_TOGGLE = "TOGGLE"; - - SortedTimers::SortedTimers() { } - - std::string SortedTimers::GetTimerId( cTimer const& timer ) - { - std::stringstream builder; - builder << cSv(cToSvConcat(timer.Channel()->GetChannelID())) << ":" << timer.WeekDays() << ":" - << timer.Day() << ":" << timer.Start() << ":" << timer.Stop(); - return builder.str(); - } - - const cTimer* SortedTimers::GetByTimerId( std::string const& timerid ) - { - std::vector parts = StringSplit( timerid, ':' ); - if ( parts.size() < 5 ) { - esyslog("live: GetByTimerId: invalid format %s", timerid.c_str() ); - return 0; - } + static char const* const TIMER_DELETE = "DELETE"; + static char const* const TIMER_TOGGLE = "TOGGLE"; + + SortedTimers::SortedTimers() { } + + std::string SortedTimers::GetTimerId( cTimer const& timer ) + { + std::stringstream builder; + builder << cSv(cToSvConcat(timer.Channel()->GetChannelID())) << ":" << timer.WeekDays() << ":" + << timer.Day() << ":" << timer.Start() << ":" << timer.Stop(); + return builder.str(); + } + + const cTimer* SortedTimers::GetByTimerId( std::string const& timerid ) + { + std::vector parts = StringSplit( timerid, ':' ); + if ( parts.size() < 5 ) { + esyslog("live: GetByTimerId: invalid format %s", timerid.c_str() ); + return 0; + } #ifdef DEBUG_LOCK - dsyslog("live: timers.cpp SortedTimers::GetByTimerId() LOCK_TIMERS_READ"); - dsyslog("live: timers.cpp SortedTimers::GetByTimerId() LOCK_CHANNELS_READ"); + dsyslog("live: timers.cpp SortedTimers::GetByTimerId() LOCK_TIMERS_READ"); + dsyslog("live: timers.cpp SortedTimers::GetByTimerId() LOCK_CHANNELS_READ"); #endif - LOCK_TIMERS_READ - LOCK_CHANNELS_READ; - cChannel* channel = (cChannel *)Channels->GetByChannelID( tChannelID::FromString( parts[0].c_str() ) ); - if ( channel == 0 ) { - esyslog("live: GetByTimerId: no channel %s", parts[0].c_str() ); - return 0; - } - - try { - int weekdays = parse_int( parts[1] ); - time_t day = parse_int( parts[2] ); - int start = parse_int( parts[3] ); - int stop = parse_int( parts[4] ); - - cMutexLock MutexLock(&m_mutex); - - for (cTimer* timer = (cTimer *)Timers->First(); timer; timer = (cTimer *)Timers->Next(timer)) { - if ( timer->Channel() == channel && - ( ( weekdays != 0 && timer->WeekDays() == weekdays ) || ( weekdays == 0 && timer->Day() == day ) ) && - timer->Start() == start && timer->Stop() == stop ) - return &*timer; - } - } catch ( bad_lexical_cast const& ex ) { - esyslog("live: GetByTimer: bad cast"); - } - return 0; - } - - std::string SortedTimers::EncodeDomId(std::string const& timerid) - { - std::string tId("timer_"); - tId += vdrlive::EncodeDomId(timerid, ".-:", "pmc"); - return tId; - } - - std::string SortedTimers::DecodeDomId(std::string const &timerDomId) - { - std::string const timerStr("timer_"); - - std::string tId = timerDomId.substr(timerStr.length()); - - return vdrlive::DecodeDomId(tId, "pmc", ".-:"); - } - - - std::string SortedTimers::GetTimerDays(cTimer const *timer) - { - if (!timer) return ""; - std::string currentDay = timer->WeekDays() > 0 ? - *cTimer::PrintDay(0, timer->WeekDays(), true) : - std::string(cToSvDateTime(tr("%A, %x"), timer->Day())); - return currentDay; - } - - std::string SortedTimers::GetTimerInfo(cTimer const& timer) - { - std::stringstream info; - info << trVDR("Priority") << ": " << timer.Priority() << std::endl; - info << trVDR("Lifetime") << ": " << timer.Lifetime() << std::endl; - info << trVDR("VPS") << ": " << (timer.HasFlags(tfVps)?trVDR("yes"):trVDR("no")) << std::endl; - - if (timer.Aux()) - { - cSv epgsearchinfo = partInXmlTag(timer.Aux(), "epgsearch"); - if (!epgsearchinfo.empty()) - { - cSv searchtimer = partInXmlTag(epgsearchinfo, "searchtimer"); - if (!searchtimer.empty()) - info << tr("Search timer") << ": " << searchtimer << std::endl; - } - } + LOCK_TIMERS_READ + LOCK_CHANNELS_READ; + cChannel* channel = (cChannel *)Channels->GetByChannelID( tChannelID::FromString( parts[0].c_str() ) ); + if ( channel == 0 ) { + esyslog("live: GetByTimerId: no channel %s", parts[0].c_str() ); + return 0; + } + + try { + int weekdays = parse_int( parts[1] ); + time_t day = parse_int( parts[2] ); + int start = parse_int( parts[3] ); + int stop = parse_int( parts[4] ); + + cMutexLock MutexLock(&m_mutex); + + for (cTimer* timer = (cTimer *)Timers->First(); timer; timer = (cTimer *)Timers->Next(timer)) { + if ( timer->Channel() == channel && + ( ( weekdays != 0 && timer->WeekDays() == weekdays ) || ( weekdays == 0 && timer->Day() == day ) ) && + timer->Start() == start && timer->Stop() == stop ) + return &*timer; + } + } catch ( bad_lexical_cast const& ex ) { + esyslog("live: GetByTimer: bad cast"); + } + return 0; + } + + std::string SortedTimers::EncodeDomId(std::string const& timerid) + { + std::string tId("timer_"); + tId += vdrlive::EncodeDomId(timerid, ".-:", "pmc"); + return tId; + } + + std::string SortedTimers::DecodeDomId(std::string const &timerDomId) + { + std::string const timerStr("timer_"); + + std::string tId = timerDomId.substr(timerStr.length()); + + return vdrlive::DecodeDomId(tId, "pmc", ".-:"); + } + + + std::string SortedTimers::GetTimerDays(cTimer const *timer) + { + if (!timer) return ""; + std::string currentDay = timer->WeekDays() > 0 ? + *cTimer::PrintDay(0, timer->WeekDays(), true) : + std::string(cToSvDateTime(tr("%A, %x"), timer->Day())); + return currentDay; + } + + std::string SortedTimers::GetTimerInfo(cTimer const& timer) + { + std::stringstream info; + info << trVDR("Priority") << ": " << timer.Priority() << std::endl; + info << trVDR("Lifetime") << ": " << timer.Lifetime() << std::endl; + info << trVDR("VPS") << ": " << (timer.HasFlags(tfVps)?trVDR("yes"):trVDR("no")) << std::endl; + + if (timer.Aux()) + { + cSv epgsearchinfo = partInXmlTag(timer.Aux(), "epgsearch"); + if (!epgsearchinfo.empty()) + { + cSv searchtimer = partInXmlTag(epgsearchinfo, "searchtimer"); + if (!searchtimer.empty()) + info << tr("Search timer") << ": " << searchtimer << std::endl; + } + } if (!timer.Local()) { info << trVDR("Record on") << ": " << timer.Remote() << std::endl; } - return info.str(); - } + return info.str(); + } - std::string SortedTimers::TvScraperTimerInfo(cTimer const& timer, std::string &recID, std::string &recName) { - if (!timer.Aux()) return ""; + std::string SortedTimers::TvScraperTimerInfo(cTimer const& timer, std::string &recID, std::string &recName) { + if (!timer.Aux()) return ""; cGetAutoTimerReason getAutoTimerReason; getAutoTimerReason.timer = &timer; getAutoTimerReason.requestRecording = true; @@ -137,473 +137,473 @@ namespace vdrlive { cSv data = partInXmlTag(tvScraperInfo, "reason"); if (data.empty() ) return ""; return concat(data, " ", partInXmlTag(tvScraperInfo, "causedBy")); - } - - bool SortedTimers::Modified() - { - bool modified = false; - - // will return != 0 only, if the Timers List has been changed since last read - if (cTimers::GetTimersRead(m_TimersStateKey)) { - modified = true; - m_TimersStateKey.Remove(); - } - - return modified; - } - - TimerManager::TimerManager() - : m_reloadTimers(true) - { - } - - void TimerManager::UpdateTimer( int timerId, const char* remote, const char* oldRemote, int flags, const tChannelID& channel, std::string const& weekdays, - std::string const& day, int start, int stop, int priority, int lifetime, std::string const& title, std::string const& aux ) - { - cMutexLock lock( this ); - - std::stringstream builder; - builder << flags << ":" - << cSv(cToSvConcat(channel)) << ":" - << ( weekdays != "-------" ? weekdays : "" ) - << ( weekdays == "-------" || day.empty() ? "" : "@" ) << day << ":" - << start << ":" - << stop << ":" - << priority << ":" - << lifetime << ":" - << StringReplace(title, ":", "|" ) << ":" - << StringReplace(aux, ":", "|" ); - // Use StringReplace here because if ':' are characters in the - // title or aux string it breaks parsing of timer definition - // in VDRs cTimer::Parse method. The '|' will be replaced - // back to ':' by the cTimer::Parse() method. - - // Fix was submitted by rofafor: see - // http://www.vdr-portal.de/board/thread.php?threadid=100398 - - dsyslog("live: UpdateTimer() timerId '%d'", timerId); - dsyslog("live: UpdateTimer() remote '%s'", remote); - dsyslog("live: UpdateTimer() oldRemote '%s'", oldRemote); - dsyslog("live: UpdateTimer() channel '%s'", *(channel.ToString())); - dsyslog("live: UpdateTimer() channel '%s'", cToSvConcat(channel).c_str() ); - dsyslog("live: UpdateTimer() builder '%s'", builder.str().c_str()); + } + + bool SortedTimers::Modified() + { + bool modified = false; + + // will return != 0 only, if the Timers List has been changed since last read + if (cTimers::GetTimersRead(m_TimersStateKey)) { + modified = true; + m_TimersStateKey.Remove(); + } + + return modified; + } + + TimerManager::TimerManager() + : m_reloadTimers(true) + { + } + + void TimerManager::UpdateTimer( int timerId, const char* remote, const char* oldRemote, int flags, const tChannelID& channel, std::string const& weekdays, + std::string const& day, int start, int stop, int priority, int lifetime, std::string const& title, std::string const& aux ) + { + cMutexLock lock( this ); + + std::stringstream builder; + builder << flags << ":" + << cSv(cToSvConcat(channel)) << ":" + << ( weekdays != "-------" ? weekdays : "" ) + << ( weekdays == "-------" || day.empty() ? "" : "@" ) << day << ":" + << start << ":" + << stop << ":" + << priority << ":" + << lifetime << ":" + << StringReplace(title, ":", "|" ) << ":" + << StringReplace(aux, ":", "|" ); + // Use StringReplace here because if ':' are characters in the + // title or aux string it breaks parsing of timer definition + // in VDRs cTimer::Parse method. The '|' will be replaced + // back to ':' by the cTimer::Parse() method. + + // Fix was submitted by rofafor: see + // http://www.vdr-portal.de/board/thread.php?threadid=100398 + + dsyslog("live: UpdateTimer() timerId '%d'", timerId); + dsyslog("live: UpdateTimer() remote '%s'", remote); + dsyslog("live: UpdateTimer() oldRemote '%s'", oldRemote); + dsyslog("live: UpdateTimer() channel '%s'", *(channel.ToString())); + dsyslog("live: UpdateTimer() channel '%s'", cToSvConcat(channel).c_str() ); + dsyslog("live: UpdateTimer() builder '%s'", builder.str().c_str()); timerStruct timerData = { .id = timerId, .remote=remote, .oldRemote=oldRemote, .builder=builder.str() }; - // dsyslog("live: SV: in UpdateTimer"); - m_updateTimers.push_back( timerData ); - // dsyslog("live: SV: wait for update"); - m_updateWait.Wait( *this ); - // dsyslog("live: SV: update done"); - - std::string error = GetError( timerData ); - if ( !error.empty() ) - throw HtmlError( error ); - } - - void TimerManager::DelTimer( int timerId, const char* remote ) - { - cMutexLock lock( this ); - - dsyslog("live: DelTimer() timerId '%d'", timerId); - dsyslog("live: DelTimer() remote '%s'", remote); - - timerStruct timerData{ .id=timerId, .remote=remote, .oldRemote=remote, .builder=TIMER_DELETE }; - - m_updateTimers.push_back( timerData ); - m_updateWait.Wait( *this ); - - std::string error = GetError( timerData ); - if ( !error.empty() ) - throw HtmlError( error ); - } - - void TimerManager::ToggleTimerActive( int timerId, const char* remote) - { - cMutexLock lock( this ); - - timerStruct timerData{ .id=timerId, .remote=remote, .oldRemote=remote, .builder=TIMER_TOGGLE }; - - m_updateTimers.push_back( timerData ); - m_updateWait.Wait( *this ); - - std::string error = GetError( timerData ); - if ( !error.empty() ) - throw HtmlError( error ); - } - - void TimerManager::DoPendingWork() - { - if ( m_updateTimers.size() == 0 && !m_timers.Modified() && !m_reloadTimers ) - return; - - cMutexLock lock( this ); - if ( m_updateTimers.size() > 0 ) { - DoUpdateTimers(); - } - // dsyslog("live: SV: signaling waiters"); - m_updateWait.Broadcast(); - } - - void TimerManager::DoUpdateTimers() - { - // dsyslog("live: SV: updating timers"); - for ( TimerList::iterator timer = m_updateTimers.begin(); timer != m_updateTimers.end(); ++timer ) { -// dsyslog("live: DoUpdateTimers() timerid '%d'", timer->id ); -// dsyslog("live: DoUpdateTimers() remote '%s'", timer->remote ); -// dsyslog("live: DoUpdateTimers() builder '%s'", timer->builder.c_str() ); - if ( timer->id == 0 ) // new timer - DoInsertTimer( *timer ); - else if ( timer->builder == TIMER_DELETE ) // delete timer - DoDeleteTimer( *timer ); - else if ( timer->builder == TIMER_TOGGLE ) // toggle timer - DoToggleTimer( *timer ); - else // update timer - DoUpdateTimer( *timer ); - } - m_updateTimers.clear(); - } - - void TimerManager::DoInsertTimer( timerStruct& timerData ) - { - if ( timerData.remote ) { // add remote timer via svdrpsend - dsyslog("live: DoInsertTimer() add remote timer on server '%s'", timerData.remote); - cStringList response; - std::string command = "NEWT "; - command.append(timerData.builder); - dsyslog("live: DoInsertTimer() svdrp command '%s'", command.c_str()); - bool svdrpOK = ExecSVDRPCommand(timerData.remote, command.c_str(), &response); - if ( !svdrpOK ) { - esyslog("live: svdrp command on remote server %s failed", timerData.remote); - } + // dsyslog("live: SV: in UpdateTimer"); + m_updateTimers.push_back( timerData ); + // dsyslog("live: SV: wait for update"); + m_updateWait.Wait( *this ); + // dsyslog("live: SV: update done"); + + std::string error = GetError( timerData ); + if ( !error.empty() ) + throw HtmlError( error ); + } + + void TimerManager::DelTimer( int timerId, const char* remote ) + { + cMutexLock lock( this ); + + dsyslog("live: DelTimer() timerId '%d'", timerId); + dsyslog("live: DelTimer() remote '%s'", remote); + + timerStruct timerData{ .id=timerId, .remote=remote, .oldRemote=remote, .builder=TIMER_DELETE }; + + m_updateTimers.push_back( timerData ); + m_updateWait.Wait( *this ); + + std::string error = GetError( timerData ); + if ( !error.empty() ) + throw HtmlError( error ); + } + + void TimerManager::ToggleTimerActive( int timerId, const char* remote) + { + cMutexLock lock( this ); + + timerStruct timerData{ .id=timerId, .remote=remote, .oldRemote=remote, .builder=TIMER_TOGGLE }; + + m_updateTimers.push_back( timerData ); + m_updateWait.Wait( *this ); + + std::string error = GetError( timerData ); + if ( !error.empty() ) + throw HtmlError( error ); + } + + void TimerManager::DoPendingWork() + { + if ( m_updateTimers.size() == 0 && !m_timers.Modified() && !m_reloadTimers ) + return; + + cMutexLock lock( this ); + if ( m_updateTimers.size() > 0 ) { + DoUpdateTimers(); + } + // dsyslog("live: SV: signaling waiters"); + m_updateWait.Broadcast(); + } + + void TimerManager::DoUpdateTimers() + { + // dsyslog("live: SV: updating timers"); + for ( TimerList::iterator timer = m_updateTimers.begin(); timer != m_updateTimers.end(); ++timer ) { +// dsyslog("live: DoUpdateTimers() timerid '%d'", timer->id ); +// dsyslog("live: DoUpdateTimers() remote '%s'", timer->remote ); +// dsyslog("live: DoUpdateTimers() builder '%s'", timer->builder.c_str() ); + if ( timer->id == 0 ) // new timer + DoInsertTimer( *timer ); + else if ( timer->builder == TIMER_DELETE ) // delete timer + DoDeleteTimer( *timer ); + else if ( timer->builder == TIMER_TOGGLE ) // toggle timer + DoToggleTimer( *timer ); + else // update timer + DoUpdateTimer( *timer ); + } + m_updateTimers.clear(); + } + + void TimerManager::DoInsertTimer( timerStruct& timerData ) + { + if ( timerData.remote ) { // add remote timer via svdrpsend + dsyslog("live: DoInsertTimer() add remote timer on server '%s'", timerData.remote); + cStringList response; + std::string command = "NEWT "; + command.append(timerData.builder); + dsyslog("live: DoInsertTimer() svdrp command '%s'", command.c_str()); + bool svdrpOK = ExecSVDRPCommand(timerData.remote, command.c_str(), &response); + if ( !svdrpOK ) { + esyslog("live: svdrp command on remote server %s failed", timerData.remote); + } else { - for (int i = 0; i < response.Size(); i++) { + for (int i = 0; i < response.Size(); i++) { int code = SVDRPCode(response[i]); - if (code != 250) { - esyslog("live: DoInsertTimer() svdrp failed, response: %s", response[i]); - svdrpOK = false; - } - } - if ( svdrpOK ) { - isyslog("live: remote timer '%s' on server '%s' added", timerData.builder.c_str(), timerData.remote); - } - else { - dsyslog("live: TimerManager::DoInsertTimer(): error in settings for remote timer"); - StoreError(timerData, tr("Error in timer settings")); - } + if (code != 250) { + esyslog("live: DoInsertTimer() svdrp failed, response: %s", response[i]); + svdrpOK = false; + } + } + if ( svdrpOK ) { + isyslog("live: remote timer '%s' on server '%s' added", timerData.builder.c_str(), timerData.remote); + } + else { + dsyslog("live: TimerManager::DoInsertTimer(): error in settings for remote timer"); + StoreError(timerData, tr("Error in timer settings")); + } } response.Clear(); } - else { // add local timer - std::unique_ptr newTimer( new cTimer ); - if ( !newTimer->Parse( timerData.builder.c_str() ) ) { - dsyslog("live: TimerManager::DoInsertTimer(): error in settings for local timer"); - StoreError( timerData, tr("Error in timer settings") ); + else { // add local timer + std::unique_ptr newTimer( new cTimer ); + if ( !newTimer->Parse( timerData.builder.c_str() ) ) { + dsyslog("live: TimerManager::DoInsertTimer(): error in settings for local timer"); + StoreError( timerData, tr("Error in timer settings") ); return; } - dsyslog("live: DoInsertTimer() add local timer"); + dsyslog("live: DoInsertTimer() add local timer"); #ifdef DEBUG_LOCK dsyslog("live: timers.cpp TimerManager::DoInsertTimer() LOCK_TIMERS_WRITE"); #endif - LOCK_TIMERS_WRITE; - Timers->SetExplicitModify(); - const cTimer *checkTimer = Timers->GetTimer( newTimer.get() ); - if ( checkTimer ) { - StoreError( timerData, tr("Timer already defined") ); - return; - } - Timers->Add( newTimer.get() ); - Timers->SetModified(); - isyslog( "live: local timer %s added", *newTimer->ToDescr() ); - newTimer.release(); - } - } - - void TimerManager::DoUpdateTimer( timerStruct& timerData ) - { - dsyslog("live: DoUpdateTimer() timerid '%d'", timerData.id ); - dsyslog("live: DoUpdateTimer() remote '%s'", timerData.remote ); - dsyslog("live: DoUpdateTimer() oldRemote '%s'", timerData.oldRemote ); - dsyslog("live: DoUpdateTimer() builder '%s'", timerData.builder.c_str() ); - - if ( timerData.remote && timerData.oldRemote ) { // old and new are remote - if ( timerData.remote == timerData.oldRemote ) { // timer stays on the same remote server - dsyslog("live: DoUptimer() update timer on remote server '%s'", timerData.remote); - cStringList response; - std::string command = "MODT "; - command.append(cToSvInt(timerData.id)); - command.append(" "); - command.append(timerData.builder); - dsyslog("live: DoUpdateTimer() svdrp command '%s'", command.c_str()); - bool svdrpOK = ExecSVDRPCommand(timerData.remote, command.c_str(), &response); - if ( !svdrpOK ) { - esyslog("live: svdr command on remote server %s failed", timerData.remote); - } - else { - bool responseOK = true; - for (int i = 0; i < response.Size(); i++) { - int code = SVDRPCode(response[i]); - if (code != 250) { - esyslog("live: DoInsertTimer() svdrp response: %s", response[i]); - responseOK = false; - } - } - if ( responseOK ) { - isyslog("live: remote timer '%s' on server '%s' updated", command.c_str(), timerData.remote); - } - else { - StoreError(timerData, tr("Error in timer settings")); - } - } - response.Clear(); - } - else { // timer moves from one remote server to another - isyslog("live: DoUptimer() move timer from remote server '%s' to remote server '%s'", timerData.oldRemote, timerData.remote); - timerStruct timerDataMove = { .id = timerData.id, .remote=timerData.oldRemote, .oldRemote=timerData.oldRemote, .builder=timerData.builder}; - DoDeleteTimer( timerDataMove ); - timerDataMove = { .id = timerData.id, .remote=timerData.remote, .oldRemote=timerData.remote, .builder=timerData.builder}; - DoInsertTimer( timerDataMove ); - } - - } - else if ( timerData.remote && !timerData.oldRemote ) { // move timer from local to remote - dsyslog("live: DoUpdateTimer() move timer from local to remote server"); - timerStruct timerDataMove = { .id = timerData.id, .remote=NULL, .oldRemote=NULL, .builder=timerData.builder}; - DoDeleteTimer( timerDataMove ); - timerDataMove = { .id = timerData.id, .remote=timerData.remote, .oldRemote=timerData.remote, .builder=timerData.builder}; - DoInsertTimer( timerDataMove ); - } - else if ( !timerData.remote && timerData.oldRemote ) { // move timer from remote to local - dsyslog("live: DoUpdateTimer() move timer from remote server to local"); - timerStruct timerDataMove = { .id = timerData.id, .remote=timerData.oldRemote, .oldRemote=timerData.oldRemote, .builder=timerData.builder}; - DoDeleteTimer( timerDataMove ); - timerDataMove = { .id = timerData.id, .remote=NULL, .oldRemote=NULL, .builder=timerData.builder}; - DoInsertTimer( timerDataMove ); - } - else { // old and new are local - dsyslog("live: DoUpdateTimer() old and new timer are local"); + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + const cTimer *checkTimer = Timers->GetTimer( newTimer.get() ); + if ( checkTimer ) { + StoreError( timerData, tr("Timer already defined") ); + return; + } + Timers->Add( newTimer.get() ); + Timers->SetModified(); + isyslog( "live: local timer %s added", *newTimer->ToDescr() ); + newTimer.release(); + } + } + + void TimerManager::DoUpdateTimer( timerStruct& timerData ) + { + dsyslog("live: DoUpdateTimer() timerid '%d'", timerData.id ); + dsyslog("live: DoUpdateTimer() remote '%s'", timerData.remote ); + dsyslog("live: DoUpdateTimer() oldRemote '%s'", timerData.oldRemote ); + dsyslog("live: DoUpdateTimer() builder '%s'", timerData.builder.c_str() ); + + if ( timerData.remote && timerData.oldRemote ) { // old and new are remote + if ( timerData.remote == timerData.oldRemote ) { // timer stays on the same remote server + dsyslog("live: DoUptimer() update timer on remote server '%s'", timerData.remote); + cStringList response; + std::string command = "MODT "; + command.append(cToSvInt(timerData.id)); + command.append(" "); + command.append(timerData.builder); + dsyslog("live: DoUpdateTimer() svdrp command '%s'", command.c_str()); + bool svdrpOK = ExecSVDRPCommand(timerData.remote, command.c_str(), &response); + if ( !svdrpOK ) { + esyslog("live: svdr command on remote server %s failed", timerData.remote); + } + else { + bool responseOK = true; + for (int i = 0; i < response.Size(); i++) { + int code = SVDRPCode(response[i]); + if (code != 250) { + esyslog("live: DoInsertTimer() svdrp response: %s", response[i]); + responseOK = false; + } + } + if ( responseOK ) { + isyslog("live: remote timer '%s' on server '%s' updated", command.c_str(), timerData.remote); + } + else { + StoreError(timerData, tr("Error in timer settings")); + } + } + response.Clear(); + } + else { // timer moves from one remote server to another + isyslog("live: DoUptimer() move timer from remote server '%s' to remote server '%s'", timerData.oldRemote, timerData.remote); + timerStruct timerDataMove = { .id = timerData.id, .remote=timerData.oldRemote, .oldRemote=timerData.oldRemote, .builder=timerData.builder}; + DoDeleteTimer( timerDataMove ); + timerDataMove = { .id = timerData.id, .remote=timerData.remote, .oldRemote=timerData.remote, .builder=timerData.builder}; + DoInsertTimer( timerDataMove ); + } + + } + else if ( timerData.remote && !timerData.oldRemote ) { // move timer from local to remote + dsyslog("live: DoUpdateTimer() move timer from local to remote server"); + timerStruct timerDataMove = { .id = timerData.id, .remote=NULL, .oldRemote=NULL, .builder=timerData.builder}; + DoDeleteTimer( timerDataMove ); + timerDataMove = { .id = timerData.id, .remote=timerData.remote, .oldRemote=timerData.remote, .builder=timerData.builder}; + DoInsertTimer( timerDataMove ); + } + else if ( !timerData.remote && timerData.oldRemote ) { // move timer from remote to local + dsyslog("live: DoUpdateTimer() move timer from remote server to local"); + timerStruct timerDataMove = { .id = timerData.id, .remote=timerData.oldRemote, .oldRemote=timerData.oldRemote, .builder=timerData.builder}; + DoDeleteTimer( timerDataMove ); + timerDataMove = { .id = timerData.id, .remote=NULL, .oldRemote=NULL, .builder=timerData.builder}; + DoInsertTimer( timerDataMove ); + } + else { // old and new are local + dsyslog("live: DoUpdateTimer() old and new timer are local"); #ifdef DEBUG_LOCK dsyslog("live: timers.cpp TimerManager::DoUpdateTimer() LOCK_TIMERS_WRITE"); #endif - LOCK_TIMERS_WRITE; - Timers->SetExplicitModify(); - cTimer* oldTimer = Timers->GetById( timerData.id, timerData.oldRemote ); - dsyslog("live: DoUpdateTimer() change local timer '%s'", *oldTimer->ToDescr()); - if ( oldTimer == 0 ) { - StoreError( timerData, tr("Timer not defined") ); - return; - } - - cTimer copy = *oldTimer; - dsyslog("live: old timer flags: %u", copy.Flags()); - if ( !copy.Parse( timerData.builder.c_str() ) ) { - StoreError( timerData, tr("Error in timer settings") ); - return; - } - if (oldTimer->HasFlags(tfRecording)) copy.SetFlags(tfRecording); // changed a running recording, restore flag "tfRecording" + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + cTimer* oldTimer = Timers->GetById( timerData.id, timerData.oldRemote ); + dsyslog("live: DoUpdateTimer() change local timer '%s'", *oldTimer->ToDescr()); + if ( oldTimer == 0 ) { + StoreError( timerData, tr("Timer not defined") ); + return; + } + + cTimer copy = *oldTimer; + dsyslog("live: old timer flags: %u", copy.Flags()); + if ( !copy.Parse( timerData.builder.c_str() ) ) { + StoreError( timerData, tr("Error in timer settings") ); + return; + } + if (oldTimer->HasFlags(tfRecording)) copy.SetFlags(tfRecording); // changed a running recording, restore flag "tfRecording" #ifdef TFEVENT - if (oldTimer->HasFlags(tfEvent) && oldTimer->Start() == copy.Start() && oldTimer->Stop() == copy.Stop() ) copy.SetFlags(tfEvent); + if (oldTimer->HasFlags(tfEvent) && oldTimer->Start() == copy.Start() && oldTimer->Stop() == copy.Stop() ) copy.SetFlags(tfEvent); #endif - dsyslog("live: new timer flags: %u", copy.Flags()); - *oldTimer = copy; - - Timers->SetModified(); - isyslog("live: local timer %s modified (%s)", *oldTimer->ToDescr(), oldTimer->HasFlags(tfActive) ? "active" : "inactive"); - } - } - - void TimerManager::DoDeleteTimer( timerStruct& timerData ) - { - dsyslog("live: DoDeleteTimer() timerid '%d'", timerData.id ); - dsyslog("live: DoDeleteTimer() remote '%s'", timerData.remote ); - dsyslog("live: DoDeleteTimer() builder '%s'", timerData.builder.c_str() ); - - if ( timerData.remote ) { // delete remote timer via svdrpsend - dsyslog("live: DoDeleteTimer() delete remote timer id '%d' from server '%s'", timerData.id, timerData.remote); - cStringList response; - std::string command = "DELT "; - command.append(cToSvInt(timerData.id)); - bool svdrpOK = ExecSVDRPCommand(timerData.remote, command.c_str(), &response); - if ( !svdrpOK ) { - esyslog( "live: delete remote timer id %d failed", timerData.id); - } - else { - for (int i = 0; i < response.Size(); i++) { - int code = SVDRPCode(response[i]); - if (code != 250) { - esyslog("live: DoDeleteTimer() svdrp failed, response: %s", response[i]); - svdrpOK = false; - } - } - if ( svdrpOK ) { - isyslog("live: remote timer '%s' on server '%s' deleted", command.c_str(), timerData.remote); - } - else { - StoreError(timerData, tr("Error in timer settings")); - } - } - response.Clear(); - } - else { // delete local timer - dsyslog("live: DoDeleteTimer() delete local timer id '%d'", timerData.id); + dsyslog("live: new timer flags: %u", copy.Flags()); + *oldTimer = copy; + + Timers->SetModified(); + isyslog("live: local timer %s modified (%s)", *oldTimer->ToDescr(), oldTimer->HasFlags(tfActive) ? "active" : "inactive"); + } + } + + void TimerManager::DoDeleteTimer( timerStruct& timerData ) + { + dsyslog("live: DoDeleteTimer() timerid '%d'", timerData.id ); + dsyslog("live: DoDeleteTimer() remote '%s'", timerData.remote ); + dsyslog("live: DoDeleteTimer() builder '%s'", timerData.builder.c_str() ); + + if ( timerData.remote ) { // delete remote timer via svdrpsend + dsyslog("live: DoDeleteTimer() delete remote timer id '%d' from server '%s'", timerData.id, timerData.remote); + cStringList response; + std::string command = "DELT "; + command.append(cToSvInt(timerData.id)); + bool svdrpOK = ExecSVDRPCommand(timerData.remote, command.c_str(), &response); + if ( !svdrpOK ) { + esyslog( "live: delete remote timer id %d failed", timerData.id); + } + else { + for (int i = 0; i < response.Size(); i++) { + int code = SVDRPCode(response[i]); + if (code != 250) { + esyslog("live: DoDeleteTimer() svdrp failed, response: %s", response[i]); + svdrpOK = false; + } + } + if ( svdrpOK ) { + isyslog("live: remote timer '%s' on server '%s' deleted", command.c_str(), timerData.remote); + } + else { + StoreError(timerData, tr("Error in timer settings")); + } + } + response.Clear(); + } + else { // delete local timer + dsyslog("live: DoDeleteTimer() delete local timer id '%d'", timerData.id); #if VDRVERSNUM < 20301 - if ( Timers.BeingEdited() ) { - StoreError( timerData, tr("Timers are being edited - try again later") ); - return; - } + if ( Timers.BeingEdited() ) { + StoreError( timerData, tr("Timers are being edited - try again later") ); + return; + } #endif #if VDRVERSNUM >= 20301 - #ifdef DEBUG_LOCK + #ifdef DEBUG_LOCK dsyslog("live: timers.cpp TimerManager::DoDeleteTimer() LOCK_TIMERS_WRITE"); #endif - LOCK_TIMERS_WRITE; - Timers->SetExplicitModify(); - cTimer* oldTimer = Timers->GetById( timerData.id, timerData.remote ); + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + cTimer* oldTimer = Timers->GetById( timerData.id, timerData.remote ); #else - cTimer* oldTimer = Timers.GetTimer( const_cast(timerData.first) ); + cTimer* oldTimer = Timers.GetTimer( const_cast(timerData.first) ); #endif - if ( oldTimer == 0 ) { - StoreError( timerData, tr("Timer not defined") ); - return; - } - cTimer copy = *oldTimer; - if ( oldTimer->Recording() ) { - oldTimer->Skip(); + if ( oldTimer == 0 ) { + StoreError( timerData, tr("Timer not defined") ); + return; + } + cTimer copy = *oldTimer; + if ( oldTimer->Recording() ) { + oldTimer->Skip(); #if VDRVERSNUM >= 20301 - cRecordControls::Process( Timers, time( 0 ) ); + cRecordControls::Process( Timers, time( 0 ) ); #else - cRecordControls::Process( time( 0 ) ); + cRecordControls::Process( time( 0 ) ); #endif - } + } #if VDRVERSNUM >= 20301 - Timers->Del( oldTimer ); - Timers->SetModified(); + Timers->Del( oldTimer ); + Timers->SetModified(); #else - Timers.Del( oldTimer ); - Timers.SetModified(); + Timers.Del( oldTimer ); + Timers.SetModified(); #endif - isyslog("live: local timer %s deleted", *copy.ToDescr()); - } - } - - void TimerManager::DoToggleTimer( timerStruct& timerData ) - { - if ( timerData.remote ) { // toggle remote timer via svdrpsend - #ifdef DEBUG_LOCK + isyslog("live: local timer %s deleted", *copy.ToDescr()); + } + } + + void TimerManager::DoToggleTimer( timerStruct& timerData ) + { + if ( timerData.remote ) { // toggle remote timer via svdrpsend + #ifdef DEBUG_LOCK dsyslog("live: timers.cpp TimerManager::DoToggleTimer() LOCK_TIMERS_READ"); #endif - LOCK_TIMERS_READ; - const cTimer* toggleTimer = Timers->GetById( timerData.id, timerData.remote ); - std::string command = "MODT "; - command.append(cToSvInt(timerData.id)); - if (toggleTimer->HasFlags(tfActive)) { - dsyslog("live: DoToggleTimer() timer is active"); - command.append(" off"); - } - else { - dsyslog("live: DoToggleTimer() timer is not active"); - command.append(" on"); - } - cStringList response; - dsyslog("live: DoToggleTimer svdrp command '%s'", command.c_str()); - bool svdrpOK = ExecSVDRPCommand(timerData.remote, command.c_str(), &response); - if ( !svdrpOK ) { - esyslog("live: svdr command on remote server %s failed", timerData.remote); - } - else { - for (int i = 0; i < response.Size(); i++) { + LOCK_TIMERS_READ; + const cTimer* toggleTimer = Timers->GetById( timerData.id, timerData.remote ); + std::string command = "MODT "; + command.append(cToSvInt(timerData.id)); + if (toggleTimer->HasFlags(tfActive)) { + dsyslog("live: DoToggleTimer() timer is active"); + command.append(" off"); + } + else { + dsyslog("live: DoToggleTimer() timer is not active"); + command.append(" on"); + } + cStringList response; + dsyslog("live: DoToggleTimer svdrp command '%s'", command.c_str()); + bool svdrpOK = ExecSVDRPCommand(timerData.remote, command.c_str(), &response); + if ( !svdrpOK ) { + esyslog("live: svdr command on remote server %s failed", timerData.remote); + } + else { + for (int i = 0; i < response.Size(); i++) { int code = SVDRPCode(response[i]); - if (code != 250) { - esyslog("live: DoToggleTimer() svdrp failed, response: %s", response[i]); - svdrpOK = false; - } - } - if ( svdrpOK ) { - isyslog("live: remote timer '%s' on server '%s' toggled", command.c_str(), timerData.remote); - } - else { - StoreError(timerData, tr("Error in timer settings")); - } - } - response.Clear(); - } - else { // toggle local timer + if (code != 250) { + esyslog("live: DoToggleTimer() svdrp failed, response: %s", response[i]); + svdrpOK = false; + } + } + if ( svdrpOK ) { + isyslog("live: remote timer '%s' on server '%s' toggled", command.c_str(), timerData.remote); + } + else { + StoreError(timerData, tr("Error in timer settings")); + } + } + response.Clear(); + } + else { // toggle local timer #if VDRVERSNUM < 20301 - if ( Timers.BeingEdited() ) { - StoreError( timerData, tr("Timers are being edited - try again later") ); - return; - } + if ( Timers.BeingEdited() ) { + StoreError( timerData, tr("Timers are being edited - try again later") ); + return; + } #endif #if VDRVERSNUM >= 20301 - #ifdef DEBUG_LOCK + #ifdef DEBUG_LOCK dsyslog("live: timers.cpp TimerManager::DoToggleTimer() LOCK_TIMERS_WRITE"); - #endif - LOCK_TIMERS_WRITE; - Timers->SetExplicitModify(); - cTimer* toggleTimer = Timers->GetById( timerData.id, timerData.remote ); + #endif + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + cTimer* toggleTimer = Timers->GetById( timerData.id, timerData.remote ); #else - cTimer* toggleTimer = Timers.GetTimer( const_cast(timerData.first) ); + cTimer* toggleTimer = Timers.GetTimer( const_cast(timerData.first) ); #endif - if ( toggleTimer == 0 ) { - StoreError( timerData, tr("Timer not defined") ); - return; - } + if ( toggleTimer == 0 ) { + StoreError( timerData, tr("Timer not defined") ); + return; + } #if VDRVERSNUM >= 20301 - toggleTimer->OnOff(); - Timers->SetModified(); + toggleTimer->OnOff(); + Timers->SetModified(); #else - toggleTimer->OnOff(); - Timers.SetModified(); + toggleTimer->OnOff(); + Timers.SetModified(); #endif - isyslog("live: timer %s toggled %s", *toggleTimer->ToDescr(), toggleTimer->HasFlags(tfActive) ? "on" : "off"); - } - } - - void TimerManager::StoreError( timerStruct const& timerData, std::string const& error ) - { - m_failedUpdates.push_back( ErrorPair( timerData, error ) ); - } - - std::string TimerManager::GetError( timerStruct const& timerData ) - { - for ( ErrorList::iterator error = m_failedUpdates.begin(); error != m_failedUpdates.end(); ++error ) { - if ( error->first.id == timerData.id && - error->first.remote == timerData.remote && - error->first.oldRemote == timerData.oldRemote && - error->first.builder == timerData.builder ) { - std::string message = error->second; - m_failedUpdates.erase( error ); - return message; - } - } - return ""; - } - - const cTimer* TimerManager::GetTimer(tEventID eventid, tChannelID channelid) - { - cMutexLock timersLock( &LiveTimerManager() ); - - #ifdef DEBUG_LOCK + isyslog("live: timer %s toggled %s", *toggleTimer->ToDescr(), toggleTimer->HasFlags(tfActive) ? "on" : "off"); + } + } + + void TimerManager::StoreError( timerStruct const& timerData, std::string const& error ) + { + m_failedUpdates.push_back( ErrorPair( timerData, error ) ); + } + + std::string TimerManager::GetError( timerStruct const& timerData ) + { + for ( ErrorList::iterator error = m_failedUpdates.begin(); error != m_failedUpdates.end(); ++error ) { + if ( error->first.id == timerData.id && + error->first.remote == timerData.remote && + error->first.oldRemote == timerData.oldRemote && + error->first.builder == timerData.builder ) { + std::string message = error->second; + m_failedUpdates.erase( error ); + return message; + } + } + return ""; + } + + const cTimer* TimerManager::GetTimer(tEventID eventid, tChannelID channelid) + { + cMutexLock timersLock( &LiveTimerManager() ); + + #ifdef DEBUG_LOCK dsyslog("live: timers.cpp TimerManager::GetTimer() LOCK_TIMERS_READ"); - #endif + #endif LOCK_TIMERS_READ; - for (cTimer* timer = (cTimer *)Timers->First(); timer; timer = (cTimer *)Timers->Next(timer)) { - if (timer->Channel() && timer->Channel()->GetChannelID() == channelid) - { - if (timer->Event() && timer->Event()->EventID() == eventid) - return &*timer; - } - } - return NULL; - } - - TimerManager& LiveTimerManager() - { - static TimerManager instance; - return instance; - } + for (cTimer* timer = (cTimer *)Timers->First(); timer; timer = (cTimer *)Timers->Next(timer)) { + if (timer->Channel() && timer->Channel()->GetChannelID() == channelid) + { + if (timer->Event() && timer->Event()->EventID() == eventid) + return &*timer; + } + } + return NULL; + } + + TimerManager& LiveTimerManager() + { + static TimerManager instance; + return instance; + } } // namespace vdrlive diff --git a/timers.h b/timers.h index 3a1bdc4..869615f 100644 --- a/timers.h +++ b/timers.h @@ -14,86 +14,86 @@ namespace vdrlive { - class SortedTimers: public std::list - { - friend class TimerManager; + class SortedTimers: public std::list + { + friend class TimerManager; - public: - static std::string GetTimerId(cTimer const& timer); - const cTimer* GetByTimerId(std::string const& timerid); + public: + static std::string GetTimerId(cTimer const& timer); + const cTimer* GetByTimerId(std::string const& timerid); - // en- or decodes a timer into an id usable for DOM Ids. - static std::string EncodeDomId(std::string const& timerid); - static std::string DecodeDomId(std::string const &timerDomId); + // en- or decodes a timer into an id usable for DOM Ids. + static std::string EncodeDomId(std::string const& timerid); + static std::string DecodeDomId(std::string const &timerDomId); - bool Modified(); + bool Modified(); - static std::string GetTimerDays(cTimer const *timer); - static std::string GetTimerInfo(cTimer const& timer); + static std::string GetTimerDays(cTimer const *timer); + static std::string GetTimerInfo(cTimer const& timer); template - static cSv SearchTimerInfo(cTimer const& timer, const char (&value)[N] ) { + static cSv SearchTimerInfo(cTimer const& timer, const char (&value)[N] ) { return partInXmlTag(partInXmlTag(timer.Aux(), "epgsearch"), value); } - static std::string TvScraperTimerInfo(cTimer const& timer, std::string &recID, std::string &recName); + static std::string TvScraperTimerInfo(cTimer const& timer, std::string &recID, std::string &recName); - private: - SortedTimers(); - SortedTimers( SortedTimers const& ); + private: + SortedTimers(); + SortedTimers( SortedTimers const& ); - cMutex m_mutex; - cStateKey m_TimersStateKey; - }; + cMutex m_mutex; + cStateKey m_TimersStateKey; + }; - class TimerManager: public cMutex - { - friend TimerManager& LiveTimerManager(); + class TimerManager: public cMutex + { + friend TimerManager& LiveTimerManager(); - public: - SortedTimers& GetTimers() { return m_timers; } + public: + SortedTimers& GetTimers() { return m_timers; } - void UpdateTimer( int timerId, const char* remote, const char* oldRemote, int flags, const tChannelID& channel, std::string const& weekdays, - std::string const& day, int start, int stop, int priority, int lifetime, std::string const& title, std::string const& aux ); + void UpdateTimer( int timerId, const char* remote, const char* oldRemote, int flags, const tChannelID& channel, std::string const& weekdays, + std::string const& day, int start, int stop, int priority, int lifetime, std::string const& title, std::string const& aux ); - void DelTimer( int timerId, const char* remote); - void ToggleTimerActive( int timerId, const char* remote); - // may only be called from Plugin::MainThreadHook - void DoPendingWork(); - const cTimer* GetTimer(tEventID eventid, tChannelID channelid); - void SetReloadTimers() { m_reloadTimers = true; } + void DelTimer( int timerId, const char* remote); + void ToggleTimerActive( int timerId, const char* remote); + // may only be called from Plugin::MainThreadHook + void DoPendingWork(); + const cTimer* GetTimer(tEventID eventid, tChannelID channelid); + void SetReloadTimers() { m_reloadTimers = true; } - private: - typedef struct + private: + typedef struct { int id; const char* remote; const char* oldRemote; - std::string builder; + std::string builder; } timerStruct; - typedef std::pair ErrorPair; - typedef std::list TimerList; - typedef std::list ErrorList; + typedef std::pair ErrorPair; + typedef std::list TimerList; + typedef std::list ErrorList; - TimerManager(); - TimerManager( TimerManager const& ); + TimerManager(); + TimerManager( TimerManager const& ); - SortedTimers m_timers; - TimerList m_updateTimers; - ErrorList m_failedUpdates; - cCondVar m_updateWait; - bool m_reloadTimers = false; + SortedTimers m_timers; + TimerList m_updateTimers; + ErrorList m_failedUpdates; + cCondVar m_updateWait; + bool m_reloadTimers = false; - void DoUpdateTimers(); - void DoInsertTimer( timerStruct& timerData ); - void DoUpdateTimer( timerStruct& timerData ); - void DoDeleteTimer( timerStruct& timerData ); - void DoToggleTimer( timerStruct& timerData ); + void DoUpdateTimers(); + void DoInsertTimer( timerStruct& timerData ); + void DoUpdateTimer( timerStruct& timerData ); + void DoDeleteTimer( timerStruct& timerData ); + void DoToggleTimer( timerStruct& timerData ); - void StoreError( timerStruct const& timerData, std::string const& error ); - std::string GetError( timerStruct const& timerData ); - }; + void StoreError( timerStruct const& timerData, std::string const& error ); + std::string GetError( timerStruct const& timerData ); + }; - TimerManager& LiveTimerManager(); + TimerManager& LiveTimerManager(); } // namespace vdrlive diff --git a/tntconfig.cpp b/tntconfig.cpp index b4831e0..a5bd447 100644 --- a/tntconfig.cpp +++ b/tntconfig.cpp @@ -19,396 +19,396 @@ namespace vdrlive { - TntConfig::TntConfig() - { - } - - namespace { - std::string GetResourcePath() - { - std::string resourceDir(Plugin::GetResourceDirectory()); - return resourceDir; - } - - void MapUrl(tnt::Tntnet & app, const char *rule, const char * component, std::string const & instPath, const char * pathInfo, const char * mime_type) - { + TntConfig::TntConfig() + { + } + + namespace { + std::string GetResourcePath() + { + std::string resourceDir(Plugin::GetResourceDirectory()); + return resourceDir; + } + + void MapUrl(tnt::Tntnet & app, const char *rule, const char * component, std::string const & instPath, const char * pathInfo, const char * mime_type) + { #if TNT_MAPURL_NAMED_ARGS - tnt::Mapping::args_type argMap; - argMap.insert(std::make_pair("mime-type", mime_type)); + tnt::Mapping::args_type argMap; + argMap.insert(std::make_pair("mime-type", mime_type)); #endif - app.mapUrl(rule, component) - .setPathInfo(instPath + pathInfo) + app.mapUrl(rule, component) + .setPathInfo(instPath + pathInfo) #if TNT_MAPURL_NAMED_ARGS - .setArgs(argMap); + .setArgs(argMap); #else - .pushArg(mime_type); + .pushArg(mime_type); #endif - } - } + } + } - void TntConfig::ConfigureTvscraper(tnt::Tntnet& app, const std::string &tvscraperImageDir) const + void TntConfig::ConfigureTvscraper(tnt::Tntnet& app, const std::string &tvscraperImageDir) const { // make the Tvscraper images available in the web server - // Images from Tvscraper TheMovieDb: Movies - MapUrl(app, - "^/tvscraper/movies/([^/]*)\\.([^./]+)", - "content", - tvscraperImageDir + "movies", - "/$1.$2", - "image/$2"); - // Images from Tvscraper TheMovieDb: Collections - MapUrl(app, - "^/tvscraper/movies/collections/([^/]*)\\.([^./]+)", - "content", - tvscraperImageDir + "movies/collections", - "/$1.$2", - "image/$2"); - // Images from Tvscraper TheMovieDb: Actors - MapUrl(app, - "^/tvscraper/movies/actors/([^/]*)\\.([^./]+)", - "content", - tvscraperImageDir + "movies/actors", - "/$1.$2", - "image/$2"); - // Images from Tvscraper TheMovieDb: TV shows - MapUrl(app, - "^/tvscraper/movies/tv/([^/]*)/([^/]*)\\.([^./]+)", - "content", - tvscraperImageDir + "movies/tv", - "/$1/$2.$3", - "image/$3"); - // Images from Tvscraper TheMovieDb: TV shows, season - MapUrl(app, - "^/tvscraper/movies/tv/([^/]*)/([^/]*)/([^/]*)\\.([^./]+)", - "content", - tvscraperImageDir + "movies/tv", - "/$1/$2/$3.$4", - "image/$4"); - // Images from Tvscraper TheMovieDb: TV shows, episode - MapUrl(app, - "^/tvscraper/movies/tv/([^/]*)/([^/]*)/([^/]*)/([^/]*)\\.([^./]+)", - "content", - tvscraperImageDir + "movies/tv", - "/$1/$2/$3/$4.$5", - "image/$5"); - // Images from Tvscraper TheTvDb: TV shows - MapUrl(app, - "^/tvscraper/series/([^/]*)/([^/]*)\\.([^./]+)", - "content", - tvscraperImageDir + "series", - "/$1/$2.$3", - "image/$3"); - // Images from Tvscraper TheTvDb: TV shows, episode images - MapUrl(app, - "^/tvscraper/series/([^/]*)/([^/]*)/([^/]*)\\.([^./]+)", - "content", - LiveSetup().GetTvscraperImageDir() + "series", - "/$1/$2/$3.$4", - "image/$4"); - // Images from Tvscraper, from external EPG provider (start time, channel, image) - MapUrl(app, - "^/tvscraper/epg/([^/]*)/([^/]*)/([^/]*)\\.([^./]+)", - "content", - LiveSetup().GetTvscraperImageDir() + "epg", - "/$1/$2/$3.$4", - "image/$4"); - // Images from Tvscraper, from external EPG provider, in recordings (start time, channel, image) - MapUrl(app, - "^/tvscraper/recordings/([^/]*)\\.([^./]+)", - "content", - LiveSetup().GetTvscraperImageDir() + "recordings", - "/$1.$2", - "image/$2"); + // Images from Tvscraper TheMovieDb: Movies + MapUrl(app, + "^/tvscraper/movies/([^/]*)\\.([^./]+)", + "content", + tvscraperImageDir + "movies", + "/$1.$2", + "image/$2"); + // Images from Tvscraper TheMovieDb: Collections + MapUrl(app, + "^/tvscraper/movies/collections/([^/]*)\\.([^./]+)", + "content", + tvscraperImageDir + "movies/collections", + "/$1.$2", + "image/$2"); + // Images from Tvscraper TheMovieDb: Actors + MapUrl(app, + "^/tvscraper/movies/actors/([^/]*)\\.([^./]+)", + "content", + tvscraperImageDir + "movies/actors", + "/$1.$2", + "image/$2"); + // Images from Tvscraper TheMovieDb: TV shows + MapUrl(app, + "^/tvscraper/movies/tv/([^/]*)/([^/]*)\\.([^./]+)", + "content", + tvscraperImageDir + "movies/tv", + "/$1/$2.$3", + "image/$3"); + // Images from Tvscraper TheMovieDb: TV shows, season + MapUrl(app, + "^/tvscraper/movies/tv/([^/]*)/([^/]*)/([^/]*)\\.([^./]+)", + "content", + tvscraperImageDir + "movies/tv", + "/$1/$2/$3.$4", + "image/$4"); + // Images from Tvscraper TheMovieDb: TV shows, episode + MapUrl(app, + "^/tvscraper/movies/tv/([^/]*)/([^/]*)/([^/]*)/([^/]*)\\.([^./]+)", + "content", + tvscraperImageDir + "movies/tv", + "/$1/$2/$3/$4.$5", + "image/$5"); + // Images from Tvscraper TheTvDb: TV shows + MapUrl(app, + "^/tvscraper/series/([^/]*)/([^/]*)\\.([^./]+)", + "content", + tvscraperImageDir + "series", + "/$1/$2.$3", + "image/$3"); + // Images from Tvscraper TheTvDb: TV shows, episode images + MapUrl(app, + "^/tvscraper/series/([^/]*)/([^/]*)/([^/]*)\\.([^./]+)", + "content", + LiveSetup().GetTvscraperImageDir() + "series", + "/$1/$2/$3.$4", + "image/$4"); + // Images from Tvscraper, from external EPG provider (start time, channel, image) + MapUrl(app, + "^/tvscraper/epg/([^/]*)/([^/]*)/([^/]*)\\.([^./]+)", + "content", + LiveSetup().GetTvscraperImageDir() + "epg", + "/$1/$2/$3.$4", + "image/$4"); + // Images from Tvscraper, from external EPG provider, in recordings (start time, channel, image) + MapUrl(app, + "^/tvscraper/recordings/([^/]*)\\.([^./]+)", + "content", + LiveSetup().GetTvscraperImageDir() + "recordings", + "/$1.$2", + "image/$2"); } - void TntConfig::Configure(tnt::Tntnet& app) const - { - std::string const configDir(Plugin::GetConfigDirectory()); + void TntConfig::Configure(tnt::Tntnet& app) const + { + std::string const configDir(Plugin::GetConfigDirectory()); #if TNT_LOG_SERINFO - cxxtools::SerializationInfo si; - std::istringstream logXmlConf( - "\n" - " " + LiveSetup().GetTntnetLogLevel() + "\n" - " \n" - " \n" - " cxxtools\n" - " " + LiveSetup().GetTntnetLogLevel() + "\n" - " \n" - " \n" - " tntnet\n" - " " + LiveSetup().GetTntnetLogLevel() + "\n" - " \n" - " \n" - "\n" - ); - cxxtools::xml::XmlDeserializer d(logXmlConf); - d.deserialize(si); - log_init(si); + cxxtools::SerializationInfo si; + std::istringstream logXmlConf( + "\n" + " " + LiveSetup().GetTntnetLogLevel() + "\n" + " \n" + " \n" + " cxxtools\n" + " " + LiveSetup().GetTntnetLogLevel() + "\n" + " \n" + " \n" + " tntnet\n" + " " + LiveSetup().GetTntnetLogLevel() + "\n" + " \n" + " \n" + "\n" + ); + cxxtools::xml::XmlDeserializer d(logXmlConf); + d.deserialize(si); + log_init(si); #else - std::istringstream logConf( - "rootLogger=" + LiveSetup().GetTntnetLogLevel() + "\n" - "logger.tntnet=" + LiveSetup().GetTntnetLogLevel() + "\n" - "logger.cxxtools=" + LiveSetup().GetTntnetLogLevel() + "\n" - ); + std::istringstream logConf( + "rootLogger=" + LiveSetup().GetTntnetLogLevel() + "\n" + "logger.tntnet=" + LiveSetup().GetTntnetLogLevel() + "\n" + "logger.cxxtools=" + LiveSetup().GetTntnetLogLevel() + "\n" + ); - log_init(logConf); + log_init(logConf); #endif - // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ - // ------------------------------------------------------------------------ - // These mapUrl statements are very security sensitive! - // A wrong mapping to content may allow retrieval of arbitrary files - // from your VDR system via live. - // Two measures are taken against this in our implementation: - // 1. The MapUrls need to be checked regularly against possible exploits - // One tool to do this can be found here: - // http://www.lumadis.be/regex/test_regex.php - // Newly inserted MapUrls should be marked with author and confirmed - // by a second party. (use source code comments for this) - // 2. content.ecpp checks the given path to be - // a. an absolute path starting at / - // b. not containing ../ paths components - // In order to do so, the MapUrl statements must create absolute - // path arguments to content@ - // ------------------------------------------------------------------------ - // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ - - app.mapUrl("^/$", "login"); - - // the following redirects vdr_request URL to the component - // specified by the action parameter. - // inserted by 'tadi' -- verified with above, but not counterchecked yet! - app.mapUrl("^/vdr_request/([^.]+)", "$1"); - - // the following redirects play_video URL to the content component. - // inserted by 'tadi' -- not verified, not counterchecked yet! - //app.mapUrl("^/vlc/(.+)", "static@tntnet") - // .setPathInfo("/$1") - // .pushArg(string("DocumentRoot=") + VideoDirectory); - - // the following selects the theme specific 'theme.css' file - // inserted by 'tadi' -- verified with above, but not counterchecked yet! - MapUrl(app, - "^/themes/([^/]*)/css.*/(.+\\.css)", - "content", - GetResourcePath(), - "/themes/$1/css/$2", - "text/css"); - - // the following rules enable SVG file support, which require the special - // content type "image/svg+xml" for inline display in browsers - // inserted by 'flell' -- verified with above, but not counterchecked yet! - MapUrl(app, - "^/themes/([^/]*)/img.*/(.+)\\.svg", - "content", - GetResourcePath(), - "/themes/$1/img/$2.svg", - "image/svg+xml"); - - MapUrl(app, - "^/themes/([^/]*)/img.*/(.+)\\.svg", - "content", - GetResourcePath(), - "/img/$2.svg", - "image/svg+xml"); - - MapUrl(app, - "^/img.*/(.+)\\.svg", - "content", - GetResourcePath(), - "/img/$1.svg", - "image/svg+xml"); - - // the following rule enables channel logo support - // inserted by 'flell' -- verified with above, but not counterchecked yet! - if (!LiveSetup().GetChanLogoDir().empty() ) { - MapUrl(app, - "^/chanlogos/(.+)\\.png", - "content", - LiveSetup().GetChanLogoDir(), - "/$1.png", - "image/png"); - } - - // the following rules provide a search scheme for images. The first - // rule where a image is found, terminates the search. - // 1. /themes//img/. - // 2. /img/. - // deprecated: 3. . (builtin images) - // inserted by 'tadi' -- verified with above, but not counterchecked yet! - MapUrl(app, - "^/themes/([^/]*)/img.*/(.+)\\.(.+)", - "content", - GetResourcePath(), - "/themes/$1/img/$2.$3", - "image/$3"); - - MapUrl(app, - "^/themes/([^/]*)/img.*/(.+)\\.(.+)", - "content", - GetResourcePath(), - "/img/$2.$3", - "image/$3"); + // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ + // ------------------------------------------------------------------------ + // These mapUrl statements are very security sensitive! + // A wrong mapping to content may allow retrieval of arbitrary files + // from your VDR system via live. + // Two measures are taken against this in our implementation: + // 1. The MapUrls need to be checked regularly against possible exploits + // One tool to do this can be found here: + // http://www.lumadis.be/regex/test_regex.php + // Newly inserted MapUrls should be marked with author and confirmed + // by a second party. (use source code comments for this) + // 2. content.ecpp checks the given path to be + // a. an absolute path starting at / + // b. not containing ../ paths components + // In order to do so, the MapUrl statements must create absolute + // path arguments to content@ + // ------------------------------------------------------------------------ + // +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ CAUTION +++ + + app.mapUrl("^/$", "login"); + + // the following redirects vdr_request URL to the component + // specified by the action parameter. + // inserted by 'tadi' -- verified with above, but not counterchecked yet! + app.mapUrl("^/vdr_request/([^.]+)", "$1"); + + // the following redirects play_video URL to the content component. + // inserted by 'tadi' -- not verified, not counterchecked yet! + //app.mapUrl("^/vlc/(.+)", "static@tntnet") + // .setPathInfo("/$1") + // .pushArg(string("DocumentRoot=") + VideoDirectory); + + // the following selects the theme specific 'theme.css' file + // inserted by 'tadi' -- verified with above, but not counterchecked yet! + MapUrl(app, + "^/themes/([^/]*)/css.*/(.+\\.css)", + "content", + GetResourcePath(), + "/themes/$1/css/$2", + "text/css"); + + // the following rules enable SVG file support, which require the special + // content type "image/svg+xml" for inline display in browsers + // inserted by 'flell' -- verified with above, but not counterchecked yet! + MapUrl(app, + "^/themes/([^/]*)/img.*/(.+)\\.svg", + "content", + GetResourcePath(), + "/themes/$1/img/$2.svg", + "image/svg+xml"); + + MapUrl(app, + "^/themes/([^/]*)/img.*/(.+)\\.svg", + "content", + GetResourcePath(), + "/img/$2.svg", + "image/svg+xml"); + + MapUrl(app, + "^/img.*/(.+)\\.svg", + "content", + GetResourcePath(), + "/img/$1.svg", + "image/svg+xml"); + + // the following rule enables channel logo support + // inserted by 'flell' -- verified with above, but not counterchecked yet! + if (!LiveSetup().GetChanLogoDir().empty() ) { + MapUrl(app, + "^/chanlogos/(.+)\\.png", + "content", + LiveSetup().GetChanLogoDir(), + "/$1.png", + "image/png"); + } + + // the following rules provide a search scheme for images. The first + // rule where a image is found, terminates the search. + // 1. /themes//img/. + // 2. /img/. + // deprecated: 3. . (builtin images) + // inserted by 'tadi' -- verified with above, but not counterchecked yet! + MapUrl(app, + "^/themes/([^/]*)/img.*/(.+)\\.(.+)", + "content", + GetResourcePath(), + "/themes/$1/img/$2.$3", + "image/$3"); + + MapUrl(app, + "^/themes/([^/]*)/img.*/(.+)\\.(.+)", + "content", + GetResourcePath(), + "/img/$2.$3", + "image/$3"); // get image dir from plugin Tvscraper - static cPlugin *pScraper = LiveSetup().GetPluginTvscraper(); - if (pScraper) { + static cPlugin *pScraper = LiveSetup().GetPluginTvscraper(); + if (pScraper) { // plugin Tvscraper is available // first try cEnvironment, which is also available in scraper2vdr cEnvironment environment; if (pScraper->Service("GetEnvironment", &environment) ) { // plugin Tvscraper/scraper2vdr supports the service interface cEnvironment - esyslog("live: INFO: set image dir from GetEnvironment to '%s'", environment.basePath.c_str()); + esyslog("live: INFO: set image dir from GetEnvironment to '%s'", environment.basePath.c_str()); LiveSetup().SetTvscraperImageDir(environment.basePath); } else { cGetScraperImageDir getScraperImageDir; if (getScraperImageDir.call(pScraper) ) { // plugin Tvscraper supports the service interface GetScraperImageDir (version 1.05 or newer) - esyslog("live: WARNING: set image dir from deprecated GetScraperImageDir to '%s'", getScraperImageDir.scraperImageDir.c_str()); + esyslog("live: WARNING: set image dir from deprecated GetScraperImageDir to '%s'", getScraperImageDir.scraperImageDir.c_str()); LiveSetup().SetTvscraperImageDir(getScraperImageDir.scraperImageDir); } } - } - if (!LiveSetup().GetTvscraperImageDir().empty()) { - ConfigureTvscraper(app, LiveSetup().GetTvscraperImageDir()); - } - - // EPG images - std::string const epgImgPath(LiveSetup().GetEpgImageDir()); - if (!epgImgPath.empty()) { - // inserted by 'tadi' -- verified with above, but not counterchecked yet! - MapUrl(app, - "^/epgimages/([^/]*)\\.([^./]+)", - "content", - epgImgPath, - "/$1.$2", - "image/$2"); - } - - // recording images - MapUrl(app, - "^/recimages/([^/]*)/([^/]*)\\.([^./]+)", - "content", - "", - "/tmp/$1_$2.$3", - "image/$3"); - - // select additional (not build in) javascript. - // WARNING: no path components with '.' in the name are allowed. Only - // the basename may contain dots and must end with '.js' - // inserted by 'tadi' -- verified with above, but not counterchecked yet! - MapUrl(app, - "^/js(/[^.]*)([^/]*\\.js)", - "content", - GetResourcePath(), - "/js$1$2", - "text/javascript"); - - // map to 'css/basename(uri)' - // inserted by 'tadi' -- verified with above, but not counterchecked yet! - MapUrl(app, - "^/css.*/(.+)", - "content", - GetResourcePath(), - "/css/$1", - "text/css"); - - // map to 'img/basename(uri)' - // inserted by 'tadi' -- verified with above, but not counterchecked yet! - MapUrl(app, - "^/img.*/(.+)\\.([^.]+)", - "content", - GetResourcePath(), - "/img/$1.$2", - "image/$2"); - - // map to 'html/basename(uri)' - // inserted by 'MarkusE' -- verified with above, but not counterchecked yet! - MapUrl(app, - "^/html.*/(.+)", - "content", - GetResourcePath(), - "/html/$1", - "text/html"); - - // Map favicon.ico into img directory - MapUrl(app, - "^/favicon.ico$", - "content", - GetResourcePath(), - "/img/favicon.ico", - "image/x-icon"); - - // Map HLS streaming data folder. Module stream_data.ecpp is used to serve content. - app.mapUrl("^/media/(.+)", "stream_data"); - - // takes first path components without 'extension' when it does not - // contain '.' - // modified by 'tadi' -- verified with above, but not counterchecked yet! - app.mapUrl("^/([^./]+)(.*)?", "$1"); + } + if (!LiveSetup().GetTvscraperImageDir().empty()) { + ConfigureTvscraper(app, LiveSetup().GetTvscraperImageDir()); + } + + // EPG images + std::string const epgImgPath(LiveSetup().GetEpgImageDir()); + if (!epgImgPath.empty()) { + // inserted by 'tadi' -- verified with above, but not counterchecked yet! + MapUrl(app, + "^/epgimages/([^/]*)\\.([^./]+)", + "content", + epgImgPath, + "/$1.$2", + "image/$2"); + } + + // recording images + MapUrl(app, + "^/recimages/([^/]*)/([^/]*)\\.([^./]+)", + "content", + "", + "/tmp/$1_$2.$3", + "image/$3"); + + // select additional (not build in) javascript. + // WARNING: no path components with '.' in the name are allowed. Only + // the basename may contain dots and must end with '.js' + // inserted by 'tadi' -- verified with above, but not counterchecked yet! + MapUrl(app, + "^/js(/[^.]*)([^/]*\\.js)", + "content", + GetResourcePath(), + "/js$1$2", + "text/javascript"); + + // map to 'css/basename(uri)' + // inserted by 'tadi' -- verified with above, but not counterchecked yet! + MapUrl(app, + "^/css.*/(.+)", + "content", + GetResourcePath(), + "/css/$1", + "text/css"); + + // map to 'img/basename(uri)' + // inserted by 'tadi' -- verified with above, but not counterchecked yet! + MapUrl(app, + "^/img.*/(.+)\\.([^.]+)", + "content", + GetResourcePath(), + "/img/$1.$2", + "image/$2"); + + // map to 'html/basename(uri)' + // inserted by 'MarkusE' -- verified with above, but not counterchecked yet! + MapUrl(app, + "^/html.*/(.+)", + "content", + GetResourcePath(), + "/html/$1", + "text/html"); + + // Map favicon.ico into img directory + MapUrl(app, + "^/favicon.ico$", + "content", + GetResourcePath(), + "/img/favicon.ico", + "image/x-icon"); + + // Map HLS streaming data folder. Module stream_data.ecpp is used to serve content. + app.mapUrl("^/media/(.+)", "stream_data"); + + // takes first path components without 'extension' when it does not + // contain '.' + // modified by 'tadi' -- verified with above, but not counterchecked yet! + app.mapUrl("^/([^./]+)(.*)?", "$1"); #if TNT_GLOBAL_TNTCONFIG - tnt::TntConfig::it().sessionTimeout = 86400; - tnt::TntConfig::it().defaultContentType = std::string("text/html; charset=") + LiveI18n().CharacterEncoding(); + tnt::TntConfig::it().sessionTimeout = 86400; + tnt::TntConfig::it().defaultContentType = std::string("text/html; charset=") + LiveI18n().CharacterEncoding(); #else - tnt::Sessionscope::setDefaultTimeout(86400); - tnt::HttpReply::setDefaultContentType(std::string("text/html; charset=") + LiveI18n().CharacterEncoding()); + tnt::Sessionscope::setDefaultTimeout(86400); + tnt::HttpReply::setDefaultContentType(std::string("text/html; charset=") + LiveI18n().CharacterEncoding()); #endif - Setup::IpList const& ips = LiveSetup().GetServerIps(); - int port = LiveSetup().GetServerPort(); - size_t listenFailures = 0; - for (Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip) { - try { - esyslog("live: INFO: attempt to listen on ip = '%s'", ip->c_str()); - app.listen(*ip, port); - } - catch (std::exception const & ex) { - esyslog("live: ERROR: ip = %s is invalid: exception = %s", ip->c_str(), ex.what()); - if (++listenFailures == ips.size()) { - // if no listener was initialized we throw at - // least the last exception to the next layer. - throw; - } - } - } - - int s_port = LiveSetup().GetServerSslPort(); - if (s_port > 0) { - std::string s_cert = LiveSetup().GetServerSslCert(); - std::string s_key = LiveSetup().GetServerSslKey(); - - if (s_cert.empty()) { - s_cert = configDir + "/live.pem"; - } - - if (s_key.empty()) { - s_key = configDir + "/live-key.pem"; - } - - if (std::ifstream( s_cert.c_str() ) && std::ifstream( s_key.c_str() ) ) { - for ( Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip ) { + Setup::IpList const& ips = LiveSetup().GetServerIps(); + int port = LiveSetup().GetServerPort(); + size_t listenFailures = 0; + for (Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip) { + try { + esyslog("live: INFO: attempt to listen on ip = '%s'", ip->c_str()); + app.listen(*ip, port); + } + catch (std::exception const & ex) { + esyslog("live: ERROR: ip = %s is invalid: exception = %s", ip->c_str(), ex.what()); + if (++listenFailures == ips.size()) { + // if no listener was initialized we throw at + // least the last exception to the next layer. + throw; + } + } + } + + int s_port = LiveSetup().GetServerSslPort(); + if (s_port > 0) { + std::string s_cert = LiveSetup().GetServerSslCert(); + std::string s_key = LiveSetup().GetServerSslKey(); + + if (s_cert.empty()) { + s_cert = configDir + "/live.pem"; + } + + if (s_key.empty()) { + s_key = configDir + "/live-key.pem"; + } + + if (std::ifstream( s_cert.c_str() ) && std::ifstream( s_key.c_str() ) ) { + for ( Setup::IpList::const_iterator ip = ips.begin(); ip != ips.end(); ++ip ) { #if TNTVERSION < 31000 - app.sslListen(s_cert, s_key, *ip, s_port); + app.sslListen(s_cert, s_key, *ip, s_port); #else - cxxtools::SslCtx sslCtx; - sslCtx.loadCertificateFile(s_cert, s_key); - app.listen(*ip, s_port, sslCtx); + cxxtools::SslCtx sslCtx; + sslCtx.loadCertificateFile(s_cert, s_key); + app.listen(*ip, s_port, sslCtx); #endif - } - } - else { - esyslog( "live: ERROR: Unable to load cert/key (%s / %s): %s", s_cert.c_str(), s_key.c_str(), strerror( errno ) ); - } - } - else { - isyslog( "live: INFO: SSL port %d specified, no SSL Web server will be started", s_port); - } - } - - TntConfig const& TntConfig::Get() - { - static TntConfig instance; - return instance; - } + } + } + else { + esyslog( "live: ERROR: Unable to load cert/key (%s / %s): %s", s_cert.c_str(), s_key.c_str(), strerror( errno ) ); + } + } + else { + isyslog( "live: INFO: SSL port %d specified, no SSL Web server will be started", s_port); + } + } + + TntConfig const& TntConfig::Get() + { + static TntConfig instance; + return instance; + } } // namespace vdrlive diff --git a/tntconfig.h b/tntconfig.h index dae0681..07dc24f 100644 --- a/tntconfig.h +++ b/tntconfig.h @@ -2,7 +2,7 @@ #define VDR_LIVE_TNTCONFIG_H #if TNTVERSION >= 30000 - #include + #include #endif #include "tntfeatures.h" @@ -11,18 +11,18 @@ namespace vdrlive { - class TntConfig - { - public: - static TntConfig const& Get(); + class TntConfig + { + public: + static TntConfig const& Get(); void ConfigureTvscraper(tnt::Tntnet& app, const std::string &tvscraperImageDir) const; - void Configure(tnt::Tntnet& app) const; + void Configure(tnt::Tntnet& app) const; - private: - TntConfig(); - TntConfig( TntConfig const& ); - }; + private: + TntConfig(); + TntConfig( TntConfig const& ); + }; } // namespace vdrlive diff --git a/tntfeatures.h b/tntfeatures.h index bae63a5..13fc491 100644 --- a/tntfeatures.h +++ b/tntfeatures.h @@ -11,18 +11,18 @@ #define TNT_QUERYPARAMS_NO_BOOL (TNTVERSION >= 22000) // new version of TNTNET allow the request watchdog to be silenced. -#define TNT_WATCHDOG_SILENCE (TNTVERSION >= 16900) +#define TNT_WATCHDOG_SILENCE (TNTVERSION >= 16900) // version of TNTNET that binds ipv6 addresses with IPV6_V6ONLY flag set to true -#define TNT_IPV6_V6ONLY (CXXTOOLVER >= 21000) +#define TNT_IPV6_V6ONLY (CXXTOOLVER >= 21000) // version of TNTNET with properties deserializer for logger configuration args. -#define TNT_LOG_SERINFO (CXXTOOLVER >= 22000) +#define TNT_LOG_SERINFO (CXXTOOLVER >= 22000) // version of Tntnet wich expects name, value mappings for URL-Mapper arguments. -#define TNT_MAPURL_NAMED_ARGS (TNTVERSION >= 22000) +#define TNT_MAPURL_NAMED_ARGS (TNTVERSION >= 22000) // version of TNTNET where configuration is global -#define TNT_GLOBAL_TNTCONFIG (TNTVERSION >= 22000) +#define TNT_GLOBAL_TNTCONFIG (TNTVERSION >= 22000) #endif // VDR_LIVE_TNTFEATURES_H diff --git a/tools.cpp b/tools.cpp index f5c3c52..2768da8 100644 --- a/tools.cpp +++ b/tools.cpp @@ -84,76 +84,76 @@ template void AppendHtmlEscapedAndCorrectNonUTF8(std::string &targe template void AppendHtmlEscapedAndCorrectNonUTF8>(cToSvConcat<0> &target, const char* s, const char *end, bool tooltip); template - void AppendDuration(T &target, char const* format, int duration) - { - int minutes = (duration + 30) / 60; - int hours = minutes / 60; - minutes %= 60; + void AppendDuration(T &target, char const* format, int duration) + { + int minutes = (duration + 30) / 60; + int hours = minutes / 60; + minutes %= 60; stringAppendFormated(target, format, hours, minutes); - } + } template void AppendDuration(std::string &target, char const* format, int duration); template void AppendDuration>(cToSvConcat<0> &target, char const* format, int duration); - std::string FormatDuration(char const* format, int duration) - { - std::string result; - AppendDuration(result, format, duration); - return result; - } - - std::string StringReplace(cSv text, cSv substring, cSv replacement) - { - std::string result(text); - size_t pos = 0; - while ( ( pos = result.find( substring, pos ) ) != std::string::npos ) { - result.replace( pos, substring.length(), replacement ); - pos += replacement.length(); - } - return result; - } - - std::vector StringSplit(cSv text, char delimiter ) - { - std::vector result; - size_t last = 0, pos; - while ( ( pos = text.find( delimiter, last ) ) != std::string::npos ) { - result.emplace_back( text.substr( last, pos - last ) ); - last = pos + 1; - } - if ( last < text.length() ) - result.emplace_back( text.substr( last ) ); - return result; - } - - cSv StringWordTruncate(cSv input, size_t maxLen, bool& truncated) - { - if (input.length() <= maxLen) - { + std::string FormatDuration(char const* format, int duration) + { + std::string result; + AppendDuration(result, format, duration); + return result; + } + + std::string StringReplace(cSv text, cSv substring, cSv replacement) + { + std::string result(text); + size_t pos = 0; + while ( ( pos = result.find( substring, pos ) ) != std::string::npos ) { + result.replace( pos, substring.length(), replacement ); + pos += replacement.length(); + } + return result; + } + + std::vector StringSplit(cSv text, char delimiter ) + { + std::vector result; + size_t last = 0, pos; + while ( ( pos = text.find( delimiter, last ) ) != std::string::npos ) { + result.emplace_back( text.substr( last, pos - last ) ); + last = pos + 1; + } + if ( last < text.length() ) + result.emplace_back( text.substr( last ) ); + return result; + } + + cSv StringWordTruncate(cSv input, size_t maxLen, bool& truncated) + { + if (input.length() <= maxLen) + { truncated = false; - return input; - } - truncated = true; - cSv result = input.substr(0, maxLen); - size_t pos = result.find_last_of(" \t,;:.\n?!'\"/\\()[]{}*+-"); - return result.substr(0, pos); - } - - std::string StringFormatBreak(cSv input) - { - return StringReplace(input, "\n", "
" ); - } - - std::string StringEscapeAndBreak(cSv input, const char* nl) - { - std::stringstream plainBuilder; - HtmlEscOstream builder(plainBuilder); // see https://web.archive.org/web/20151208133551/http://www.tntnet.org/apidoc_master/html/classtnt_1_1HtmlEscOstream.html - builder << input; - return StringReplace(plainBuilder.str(), "\n", nl); - } - - cSv StringTrim(cSv str) - { - size_t pos = str.find_last_not_of(' '); + return input; + } + truncated = true; + cSv result = input.substr(0, maxLen); + size_t pos = result.find_last_of(" \t,;:.\n?!'\"/\\()[]{}*+-"); + return result.substr(0, pos); + } + + std::string StringFormatBreak(cSv input) + { + return StringReplace(input, "\n", "
" ); + } + + std::string StringEscapeAndBreak(cSv input, const char* nl) + { + std::stringstream plainBuilder; + HtmlEscOstream builder(plainBuilder); // see https://web.archive.org/web/20151208133551/http://www.tntnet.org/apidoc_master/html/classtnt_1_1HtmlEscOstream.html + builder << input; + return StringReplace(plainBuilder.str(), "\n", nl); + } + + cSv StringTrim(cSv str) + { + size_t pos = str.find_last_not_of(' '); if (pos == std::string::npos) return cSv(); cSv trailBlankRemoved = str.substr(0, pos+1); pos = trailBlankRemoved.find_first_not_of(' '); @@ -202,22 +202,22 @@ template template void AppendTextTruncateOnWord(std::string &target, const char *text, int max_len, bool tooltip); template void AppendTextTruncateOnWord>(cToSvConcat<0> &target, const char *text, int max_len, bool tooltip); - std::string MD5Hash(std::string const& str) - { - char* szInput = strdup(str.c_str()); - if (!szInput) return ""; - char* szRes = MD5String(szInput); - std::string res = szRes; - free(szRes); - return res; - } - - std::string xxHash32(cSv str) - { - char res[8]; + std::string MD5Hash(std::string const& str) + { + char* szInput = strdup(str.c_str()); + if (!szInput) return ""; + char* szRes = MD5String(szInput); + std::string res = szRes; + free(szRes); + return res; + } + + std::string xxHash32(cSv str) + { + char res[8]; stringhelpers_internal::addCharsHex(res, 8, XXH32(str.data(), str.length(), 20) ); return std::string(res, 8); - } + } XXH64_hash_t parse_hex_64(cSv str) { if (str.length() != 16) { @@ -252,60 +252,60 @@ template void AppendTextTruncateOnWord>(cToSvConcat<0> &target, c #define HOURS(x) ((x)/100) #define MINUTES(x) ((x)%100) - std::string ExpandTimeString(std::string timestring) - { - size_t colonpos = timestring.find(":"); - if (colonpos == std::string::npos) - { - if (timestring.size() == 1) - timestring = "0" + timestring + ":00"; - else if (timestring.size() == 2) - timestring = timestring + ":00"; - else if (timestring.size() == 3) - timestring = "0" + std::string(timestring.begin(), timestring.begin() + 1) + ":" + std::string(timestring.begin() + 1, timestring.end()); - else - timestring = std::string(timestring.begin(), timestring.begin() + 2) + ":" + std::string(timestring.begin() + 2, timestring.end()); - } - else - { - std::string hours = std::string(timestring.begin(), timestring.begin() + colonpos); - std::string mins = std::string(timestring.begin() + colonpos + 1, timestring.end()); - hours = std::string(std::max(0,(int)(2 - hours.size())), '0') + hours; - mins = std::string(std::max(0,(int)(2 - mins.size())), '0') + mins; - timestring = hours + ":" + mins; - } - return timestring; - } - - time_t GetTimeT(std::string timestring) // timestring in HH:MM - { - timestring = StringReplace(timestring, ":", ""); - int iTime = parse_int( timestring ); - struct tm tm_r; - time_t t = time(NULL); - tm* tmnow = localtime_r(&t, &tm_r); - tmnow->tm_hour = HOURS(iTime); - tmnow->tm_min = MINUTES(iTime); - return mktime(tmnow); - } - - struct urlencoder - { + std::string ExpandTimeString(std::string timestring) + { + size_t colonpos = timestring.find(":"); + if (colonpos == std::string::npos) + { + if (timestring.size() == 1) + timestring = "0" + timestring + ":00"; + else if (timestring.size() == 2) + timestring = timestring + ":00"; + else if (timestring.size() == 3) + timestring = "0" + std::string(timestring.begin(), timestring.begin() + 1) + ":" + std::string(timestring.begin() + 1, timestring.end()); + else + timestring = std::string(timestring.begin(), timestring.begin() + 2) + ":" + std::string(timestring.begin() + 2, timestring.end()); + } + else + { + std::string hours = std::string(timestring.begin(), timestring.begin() + colonpos); + std::string mins = std::string(timestring.begin() + colonpos + 1, timestring.end()); + hours = std::string(std::max(0,(int)(2 - hours.size())), '0') + hours; + mins = std::string(std::max(0,(int)(2 - mins.size())), '0') + mins; + timestring = hours + ":" + mins; + } + return timestring; + } + + time_t GetTimeT(std::string timestring) // timestring in HH:MM + { + timestring = StringReplace(timestring, ":", ""); + int iTime = parse_int( timestring ); + struct tm tm_r; + time_t t = time(NULL); + tm* tmnow = localtime_r(&t, &tm_r); + tmnow->tm_hour = HOURS(iTime); + tmnow->tm_min = MINUTES(iTime); + return mktime(tmnow); + } + + struct urlencoder + { std::ostream& ostr_; explicit urlencoder( std::ostream& ostr ): ostr_( ostr ) {} void operator()( char ch ) { static const char allowedChars[] = { - // 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , A , B , C , D , E , F , - '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', //00 - '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', //10 + // 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , A , B , C , D , E , F , + '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', //00 + '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', //10 '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 0x2D,0x2E,0x2F,//20 - 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,'_', '_', '_', '_', '_', '_', //30 + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,'_', '_', '_', '_', '_', '_', //30 '_', 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,//40 - 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,'_', '_', '_', '_', '_', //50 + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,'_', '_', '_', '_', '_', //50 '_', 0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,//60 - 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,'_', '_', '_', '_', '_' //70 + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,'_', '_', '_', '_', '_' //70 // everything above 127 (for signed char, below zero) is replaced with '_' }; @@ -316,42 +316,42 @@ template void AppendTextTruncateOnWord>(cToSvConcat<0> &target, c else ostr_ << ch; } - }; + }; - std::string StringUrlEncode(cSv input) - { - std::stringstream ostr; - std::for_each (input.begin(), input.end(), urlencoder( ostr ) ); - return ostr.str(); - } + std::string StringUrlEncode(cSv input) + { + std::stringstream ostr; + std::for_each (input.begin(), input.end(), urlencoder( ostr ) ); + return ostr.str(); + } // return the time value as time_t from formatted with - time_t GetDateFromDatePicker(cSv datestring, cSv format) - { - if (datestring.empty()) - return 0; - int year = parse_int(datestring.substr(format.find("yyyy"), 4)); - int month = parse_int(datestring.substr(format.find("mm"), 2)); - int day = parse_int(datestring.substr(format.find("dd"), 2)); - struct tm tm_r; - tm_r.tm_year = year - 1900; - tm_r.tm_mon = month -1; - tm_r.tm_mday = day; - tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0; - tm_r.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting - return mktime(&tm_r); - } + time_t GetDateFromDatePicker(cSv datestring, cSv format) + { + if (datestring.empty()) + return 0; + int year = parse_int(datestring.substr(format.find("yyyy"), 4)); + int month = parse_int(datestring.substr(format.find("mm"), 2)); + int day = parse_int(datestring.substr(format.find("dd"), 2)); + struct tm tm_r; + tm_r.tm_year = year - 1900; + tm_r.tm_mon = month -1; + tm_r.tm_mday = day; + tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0; + tm_r.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting + return mktime(&tm_r); + } // format is in datepicker format ('mm' for month, 'dd' for day, 'yyyy' for year) - std::string DatePickerToC(time_t date, cSv format) - { - if (date == 0) return ""; - std::string cformat(format); - cformat = StringReplace(cformat, "mm", "%m"); - cformat = StringReplace(cformat, "dd", "%d"); - cformat = StringReplace(cformat, "yyyy", "%Y"); - return std::string(cToSvDateTime(cformat.c_str(), date)); - } + std::string DatePickerToC(time_t date, cSv format) + { + if (date == 0) return ""; + std::string cformat(format); + cformat = StringReplace(cformat, "mm", "%m"); + cformat = StringReplace(cformat, "dd", "%d"); + cformat = StringReplace(cformat, "yyyy", "%Y"); + return std::string(cToSvDateTime(cformat.c_str(), date)); + } int timeStringToInt(const char *t) { // input: t in xx:xx format // output: time in epgsearch format (int, 100*h + min) @@ -377,26 +377,26 @@ template void AppendTextTruncateOnWord>(cToSvConcat<0> &target, c return t; } - std::string EncodeDomId(cSv toEncode, char const * from, char const * to) - { - std::string encoded(toEncode); - for (; *from && *to; from++, to++) { - replace(encoded.begin(), encoded.end(), *from, *to); - } - return encoded; - } - - std::string DecodeDomId(cSv toDecode, char const * from, char const * to) - { - std::string decoded(toDecode); - for (; *from && *to; from++, to++) { - replace(decoded.begin(), decoded.end(), *from, *to); - } - return decoded; - } - - std::string FileSystemExchangeChars(cSv s, bool ToFileSystem) - { + std::string EncodeDomId(cSv toEncode, char const * from, char const * to) + { + std::string encoded(toEncode); + for (; *from && *to; from++, to++) { + replace(encoded.begin(), encoded.end(), *from, *to); + } + return encoded; + } + + std::string DecodeDomId(cSv toDecode, char const * from, char const * to) + { + std::string decoded(toDecode); + for (; *from && *to; from++, to++) { + replace(decoded.begin(), decoded.end(), *from, *to); + } + return decoded; + } + + std::string FileSystemExchangeChars(cSv s, bool ToFileSystem) + { if (s.empty()) return std::string(); char *str = reinterpret_cast(std::malloc(s.length() + 1)); // VDR ExchangeChars needs a pointer to data allocated with malloc if (!str) { @@ -405,173 +405,173 @@ template void AppendTextTruncateOnWord>(cToSvConcat<0> &target, c } std::memcpy(str, s.data(), s.length()); str[s.length()] = 0; - str = ExchangeChars(str, ToFileSystem); - std::string data = str; - std::free(str); - return data; - } - - bool MoveDirectory(cSv sourceDir, cSv targetDir, bool copy) - { - const char* delim = "/"; - std::string source(sourceDir); - std::string target(targetDir); - - // add missing directory delimiters - if (source.compare(source.size() - 1, 1, delim) != 0) { - source += "/"; - } - if (target.compare(target.size() - 1, 1, delim) != 0) { - target += "/"; - } - - if (source != target) { - // validate target directory - if (target.find(source) != std::string::npos) { - esyslog("live: cannot move under sub-directory\n"); - return false; - } - if (!MakeDirs(target.c_str(), true)) { - esyslog("live: cannot create directory %s", target.c_str()); - return false; - } - - struct stat st1, st2; - if (stat(source.c_str(), &st1) != 0) { + str = ExchangeChars(str, ToFileSystem); + std::string data = str; + std::free(str); + return data; + } + + bool MoveDirectory(cSv sourceDir, cSv targetDir, bool copy) + { + const char* delim = "/"; + std::string source(sourceDir); + std::string target(targetDir); + + // add missing directory delimiters + if (source.compare(source.size() - 1, 1, delim) != 0) { + source += "/"; + } + if (target.compare(target.size() - 1, 1, delim) != 0) { + target += "/"; + } + + if (source != target) { + // validate target directory + if (target.find(source) != std::string::npos) { + esyslog("live: cannot move under sub-directory\n"); + return false; + } + if (!MakeDirs(target.c_str(), true)) { + esyslog("live: cannot create directory %s", target.c_str()); + return false; + } + + struct stat st1, st2; + if (stat(source.c_str(), &st1) != 0) { esyslog("live: rename. Source %s does not exist", source.c_str()); return false; } - stat(target.c_str(), &st2); - if (!copy && (st1.st_dev == st2.st_dev)) { - if (!cVideoDirectory::RenameVideoFile(source.c_str(), target.c_str())) { - esyslog("live: rename failed from %s to %s", source.c_str(), target.c_str()); - return false; - } - } - else { - int required = DirSizeMB(source.c_str()); - int available = FreeDiskSpaceMB(target.c_str()); - - // validate free space - if (required < available) { - cReadDir d(source.c_str()); - struct dirent *e; - bool success = true; - - // allocate copying buffer - const int len = 1024 * 1024; - char *buffer = MALLOC(char, len); - if (!buffer) { - esyslog("live: cannot allocate renaming buffer"); - return false; - } - - // loop through all files, but skip all subdirectories - while ((e = d.Next()) != NULL) { - // skip generic entries - if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..") && strcmp(e->d_name, "lost+found")) { - std::string sourceFile = source + e->d_name; - std::string targetFile = target + e->d_name; - - // copy only regular files - if (!stat(sourceFile.c_str(), &st1) && S_ISREG(st1.st_mode)) { - int r = -1, w = -1; - cUnbufferedFile *inputFile = cUnbufferedFile::Create(sourceFile.c_str(), O_RDONLY | O_LARGEFILE); - cUnbufferedFile *outputFile = cUnbufferedFile::Create(targetFile.c_str(), O_RDWR | O_CREAT | O_LARGEFILE); - - // validate files - if (!inputFile || !outputFile) { - esyslog("live: cannot open file %s or %s", sourceFile.c_str(), targetFile.c_str()); - success = false; - break; - } - - // do actual copy - dsyslog("live: copying %s to %s", sourceFile.c_str(), targetFile.c_str()); - do { - r = inputFile->Read(buffer, len); - if (r > 0) - w = outputFile->Write(buffer, r); - else - w = 0; - } while (r > 0 && w > 0); - DELETENULL(inputFile); - DELETENULL(outputFile); - - // validate result - if (r < 0 || w < 0) { - success = false; - break; - } - } - } - } - - // release allocated buffer - free(buffer); - - // delete all created target files and directories - if (!success) { - size_t found = target.find_last_of(delim); - if (found != std::string::npos) { - target = target.substr(0, found); - } - if (!RemoveFileOrDir(target.c_str(), true)) { - esyslog("live: cannot remove target %s", target.c_str()); - } - found = target.find_last_of(delim); - if (found != std::string::npos) { - target = target.substr(0, found); - } - if (!RemoveEmptyDirectories(target.c_str(), true)) { - esyslog("live: cannot remove target directory %s", target.c_str()); - } - esyslog("live: copying failed"); - return false; - } - else if (!copy && !RemoveFileOrDir(source.c_str(), true)) { // delete source files - esyslog("live: cannot remove source directory %s", source.c_str()); - return false; - } - - // delete all empty source directories - if (!copy) { - size_t found = source.find_last_of(delim); - if (found != std::string::npos) { - source = source.substr(0, found); - while (source != cVideoDirectory::Name()) { - found = source.find_last_of(delim); - if (found == std::string::npos) - break; - source = source.substr(0, found); - if (!RemoveEmptyDirectories(source.c_str(), true)) - break; - } - } - } - } - else { - esyslog("live: %s requires %dMB - only %dMB available", copy ? "moving" : "copying", required, available); - // delete all created empty target directories - size_t found = target.find_last_of(delim); - if (found != std::string::npos) { - target = target.substr(0, found); - while (target != cVideoDirectory::Name()) { - found = target.find_last_of(delim); - if (found == std::string::npos) - break; - target = target.substr(0, found); - if (!RemoveEmptyDirectories(target.c_str(), true)) - break; - } - } - return false; - } - } - } - - return true; - } + stat(target.c_str(), &st2); + if (!copy && (st1.st_dev == st2.st_dev)) { + if (!cVideoDirectory::RenameVideoFile(source.c_str(), target.c_str())) { + esyslog("live: rename failed from %s to %s", source.c_str(), target.c_str()); + return false; + } + } + else { + int required = DirSizeMB(source.c_str()); + int available = FreeDiskSpaceMB(target.c_str()); + + // validate free space + if (required < available) { + cReadDir d(source.c_str()); + struct dirent *e; + bool success = true; + + // allocate copying buffer + const int len = 1024 * 1024; + char *buffer = MALLOC(char, len); + if (!buffer) { + esyslog("live: cannot allocate renaming buffer"); + return false; + } + + // loop through all files, but skip all subdirectories + while ((e = d.Next()) != NULL) { + // skip generic entries + if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..") && strcmp(e->d_name, "lost+found")) { + std::string sourceFile = source + e->d_name; + std::string targetFile = target + e->d_name; + + // copy only regular files + if (!stat(sourceFile.c_str(), &st1) && S_ISREG(st1.st_mode)) { + int r = -1, w = -1; + cUnbufferedFile *inputFile = cUnbufferedFile::Create(sourceFile.c_str(), O_RDONLY | O_LARGEFILE); + cUnbufferedFile *outputFile = cUnbufferedFile::Create(targetFile.c_str(), O_RDWR | O_CREAT | O_LARGEFILE); + + // validate files + if (!inputFile || !outputFile) { + esyslog("live: cannot open file %s or %s", sourceFile.c_str(), targetFile.c_str()); + success = false; + break; + } + + // do actual copy + dsyslog("live: copying %s to %s", sourceFile.c_str(), targetFile.c_str()); + do { + r = inputFile->Read(buffer, len); + if (r > 0) + w = outputFile->Write(buffer, r); + else + w = 0; + } while (r > 0 && w > 0); + DELETENULL(inputFile); + DELETENULL(outputFile); + + // validate result + if (r < 0 || w < 0) { + success = false; + break; + } + } + } + } + + // release allocated buffer + free(buffer); + + // delete all created target files and directories + if (!success) { + size_t found = target.find_last_of(delim); + if (found != std::string::npos) { + target = target.substr(0, found); + } + if (!RemoveFileOrDir(target.c_str(), true)) { + esyslog("live: cannot remove target %s", target.c_str()); + } + found = target.find_last_of(delim); + if (found != std::string::npos) { + target = target.substr(0, found); + } + if (!RemoveEmptyDirectories(target.c_str(), true)) { + esyslog("live: cannot remove target directory %s", target.c_str()); + } + esyslog("live: copying failed"); + return false; + } + else if (!copy && !RemoveFileOrDir(source.c_str(), true)) { // delete source files + esyslog("live: cannot remove source directory %s", source.c_str()); + return false; + } + + // delete all empty source directories + if (!copy) { + size_t found = source.find_last_of(delim); + if (found != std::string::npos) { + source = source.substr(0, found); + while (source != cVideoDirectory::Name()) { + found = source.find_last_of(delim); + if (found == std::string::npos) + break; + source = source.substr(0, found); + if (!RemoveEmptyDirectories(source.c_str(), true)) + break; + } + } + } + } + else { + esyslog("live: %s requires %dMB - only %dMB available", copy ? "moving" : "copying", required, available); + // delete all created empty target directories + size_t found = target.find_last_of(delim); + if (found != std::string::npos) { + target = target.substr(0, found); + while (target != cVideoDirectory::Name()) { + found = target.find_last_of(delim); + if (found == std::string::npos) + break; + target = target.substr(0, found); + if (!RemoveEmptyDirectories(target.c_str(), true)) + break; + } + } + return false; + } + } + } + + return true; + } cSv ScraperImagePath2Live(cSv path) { int tvscraperImageDirLength = LiveSetup().GetTvscraperImageDir().length(); diff --git a/tools.h b/tools.h index 7d57936..725446c 100644 --- a/tools.h +++ b/tools.h @@ -28,7 +28,7 @@ std::istream& operator>>( std::istream& is, tChannelID& ret ); inline std::ostream& operator<<( std::ostream& os, tChannelID const& id ) { - return os << cToSvConcat(id); + return os << cToSvConcat(id); } template void stringAppendFormated(cToSvConcat<0> &target, const char *format, Args&&... args) { @@ -36,8 +36,8 @@ template void stringAppendFormated(cToSvConcat<0> &target, con } namespace vdrlive { - extern const std::locale g_locale; - extern const std::collate& g_collate_char; + extern const std::locale g_locale; + extern const std::collate& g_collate_char; template void AppendHtmlEscapedAndCorrectNonUTF8(T &target, const char* s, const char *end = NULL, bool tooltip = false); @@ -47,27 +47,27 @@ template } template - void AppendTextTruncateOnWord(T &target, const char *text, int max_len, bool tooltip = false); + void AppendTextTruncateOnWord(T &target, const char *text, int max_len, bool tooltip = false); template void AppendDuration(T &target, char const* format, int duration); - std::string FormatDuration( char const* format, int duration ); + std::string FormatDuration( char const* format, int duration ); - std::string StringReplace(cSv text, cSv substring, cSv replacement ); + std::string StringReplace(cSv text, cSv substring, cSv replacement ); - std::vector StringSplit(cSv text, char delimiter ); + std::vector StringSplit(cSv text, char delimiter ); - cSv StringWordTruncate(cSv input, size_t maxLen, bool& truncated); - inline cSv StringWordTruncate(cSv input, size_t maxLen) { bool dummy; return StringWordTruncate(input, maxLen, dummy); } + cSv StringWordTruncate(cSv input, size_t maxLen, bool& truncated); + inline cSv StringWordTruncate(cSv input, size_t maxLen) { bool dummy; return StringWordTruncate(input, maxLen, dummy); } std::string StringEscapeAndBreak(cSv input, const char* nl = "
"); - std::string StringFormatBreak(cSv input); - cSv StringTrim(cSv str); + std::string StringFormatBreak(cSv input); + cSv StringTrim(cSv str); template void AppendTextMaxLen(T &target, const char *text); std::string MD5Hash(std::string const& str); - std::string xxHash32(cSv str); + std::string xxHash32(cSv str); class cToSvXxHash32: public cToSvHex<8> { public: @@ -93,56 +93,56 @@ template } }; - time_t GetTimeT(std::string timestring); // timestring in HH:MM - std::string ExpandTimeString(std::string timestring); - - std::string StringUrlEncode(cSv input); - - time_t GetDateFromDatePicker(cSv datestring, cSv format); - std::string DatePickerToC(time_t date, cSv format); - std::string intToTimeString(int tm); - int timeStringToInt(const char *t); - int timeStringToInt(const std::string &t); - - std::string EncodeDomId(cSv toEncode, char const * from = ".-:", char const * to = "pmc"); - std::string DecodeDomId(cSv toDecode, char const * from = "pmc", char const * to = ".-:"); - - std::string FileSystemExchangeChars(cSv s, bool ToFileSystem); - - bool MoveDirectory(cSv sourceDir, cSv targetDir, bool copy = false); - - struct bad_lexical_cast: std::runtime_error - { - bad_lexical_cast(): std::runtime_error( "bad lexical cast" ) {} - }; - - template - To lexical_cast( From const& from ) - { - std::stringstream parser; - parser << from; - To result; - parser >> result; - if ( !parser ) - throw bad_lexical_cast(); - return result; - } - - template - std::string ConvertToString( From const& from, std::locale const& loc = g_locale ) - { - std::ostringstream parser; - parser.imbue( loc ); - parser << from; - return parser.str(); - } - - class ReadLock - { - private: - typedef void (ReadLock::*safe_bool)() const; - - public: + time_t GetTimeT(std::string timestring); // timestring in HH:MM + std::string ExpandTimeString(std::string timestring); + + std::string StringUrlEncode(cSv input); + + time_t GetDateFromDatePicker(cSv datestring, cSv format); + std::string DatePickerToC(time_t date, cSv format); + std::string intToTimeString(int tm); + int timeStringToInt(const char *t); + int timeStringToInt(const std::string &t); + + std::string EncodeDomId(cSv toEncode, char const * from = ".-:", char const * to = "pmc"); + std::string DecodeDomId(cSv toDecode, char const * from = "pmc", char const * to = ".-:"); + + std::string FileSystemExchangeChars(cSv s, bool ToFileSystem); + + bool MoveDirectory(cSv sourceDir, cSv targetDir, bool copy = false); + + struct bad_lexical_cast: std::runtime_error + { + bad_lexical_cast(): std::runtime_error( "bad lexical cast" ) {} + }; + + template + To lexical_cast( From const& from ) + { + std::stringstream parser; + parser << from; + To result; + parser >> result; + if ( !parser ) + throw bad_lexical_cast(); + return result; + } + + template + std::string ConvertToString( From const& from, std::locale const& loc = g_locale ) + { + std::ostringstream parser; + parser.imbue( loc ); + parser << from; + return parser.str(); + } + + class ReadLock + { + private: + typedef void (ReadLock::*safe_bool)() const; + + public: explicit ReadLock(cRwLock& lock, int timeout = 100) : m_lock(lock) , m_locked(false) @@ -151,25 +151,25 @@ template m_locked = true; } - ~ReadLock() - { - if (m_locked) - m_lock.Unlock(); - } + ~ReadLock() + { + if (m_locked) + m_lock.Unlock(); + } - operator safe_bool() const - { - return m_locked ? &ReadLock::safe_bool_idiom : 0; - } + operator safe_bool() const + { + return m_locked ? &ReadLock::safe_bool_idiom : 0; + } - private: - ReadLock(ReadLock const&); + private: + ReadLock(ReadLock const&); - cRwLock& m_lock; - bool m_locked; + cRwLock& m_lock; + bool m_locked; - void safe_bool_idiom() const {} - }; + void safe_bool_idiom() const {} + }; // methods for scraper ************************************** diff --git a/users.cpp b/users.cpp index 718e1b0..fe0cdd7 100644 --- a/users.cpp +++ b/users.cpp @@ -19,28 +19,28 @@ std::string cUsers::logged_in_user; cUser::cUser(int ID, const std::string& Name, const std::string& Password) : m_ID(ID), m_Name(Name) { - SetPassword(Password); + SetPassword(Password); } void cUser::SetPassword(const std::string& Password) { - std::stringstream passwordStr; - passwordStr << Password.size() << "|" << MD5Hash(Password); - m_PasswordMD5 = passwordStr.str(); + std::stringstream passwordStr; + passwordStr << Password.size() << "|" << MD5Hash(Password); + m_PasswordMD5 = passwordStr.str(); } int cUser::GetPasswordLength() const { - // format is : - std::vector parts = StringSplit( m_PasswordMD5, '|' ); - return (parts.size() > 0) ? parse_int( parts[0] ) : 0; + // format is : + std::vector parts = StringSplit( m_PasswordMD5, '|' ); + return (parts.size() > 0) ? parse_int( parts[0] ) : 0; } std::string const cUser::GetMD5HashPassword() const { - // format is : - std::vector parts = StringSplit( m_PasswordMD5, '|' ); - return (parts.size() > 1) ? parts[1] : ""; + // format is : + std::vector parts = StringSplit( m_PasswordMD5, '|' ); + return (parts.size() > 1) ? parts[1] : ""; } bool cUser::Parse(const char *s) @@ -66,25 +66,25 @@ bool cUser::Parse(const char *s) pos_next = pos + strlen(pos); valuelen = pos_next - pos + 1; if (valuelen > MAXVALUELEN) - { - esyslog("live: entry '%s' is too long. Will be truncated!", pos); - valuelen = MAXVALUELEN; - } + { + esyslog("live: entry '%s' is too long. Will be truncated!", pos); + valuelen = MAXVALUELEN; + } strn0cpy(value, pos, valuelen); pos = pos_next; - switch (parameter) { - case 1: m_ID = parse_int(value); - break; - case 2: m_Name = value; - break; - case 3: m_PasswordMD5 = value; - break; - case 4: - m_Userrights = parse_int(value); - break; - default: - break; + switch (parameter) { + case 1: m_ID = parse_int(value); + break; + case 2: m_Name = value; + break; + case 3: m_PasswordMD5 = value; + break; + case 4: + m_Userrights = parse_int(value); + break; + default: + break; } //switch } parameter++; @@ -111,21 +111,21 @@ bool cUser::Save(FILE *f) bool cUser::HasRightTo(eUserRights right) { - return ((m_Userrights & (1 << (right-1))) != 0); + return ((m_Userrights & (1 << (right-1))) != 0); } bool cUser::CurrentUserHasRightTo(eUserRights right) { - if (!LiveSetup().UseAuth()) return true; - cUser* user = cUsers::GetByUserName(cUsers::logged_in_user); - return (cUsers::logged_in_user == LiveSetup().GetAdminLogin() || (user && (user->m_Userrights & (1 << (right-1))) != 0)); + if (!LiveSetup().UseAuth()) return true; + cUser* user = cUsers::GetByUserName(cUsers::logged_in_user); + return (cUsers::logged_in_user == LiveSetup().GetAdminLogin() || (user && (user->m_Userrights & (1 << (right-1))) != 0)); } void cUser::SetRight(eUserRights right) { - isyslog("live: set right '%d' in '%d'", right, m_Userrights); - m_Userrights |= (1 << (right-1)); - isyslog("live: now rights are '%d'", m_Userrights); + isyslog("live: set right '%d' in '%d'", right, m_Userrights); + m_Userrights |= (1 << (right-1)); + isyslog("live: now rights are '%d'", m_Userrights); } bool cUsers::Delete(const std::string& Name) @@ -134,11 +134,11 @@ bool cUsers::Delete(const std::string& Name) while (user) { if (user->Name() == Name) - { - Users.Del(user); - Users.Save(); - return true; - } + { + Users.Del(user); + Users.Save(); + return true; + } user = Users.Next(user); } return false; @@ -146,53 +146,53 @@ bool cUsers::Delete(const std::string& Name) cUser* cUsers::GetByUserId(const std::string& Id) { - cUser* user = Users.First(); - while (user) - { - if (user->Id() == atoi(Id.c_str())) - return user; - user = Users.Next(user); + cUser* user = Users.First(); + while (user) + { + if (user->Id() == atoi(Id.c_str())) + return user; + user = Users.Next(user); } - return NULL; + return NULL; } cUser* cUsers::GetByUserName(const std::string& Name) { - cUser* user = Users.First(); - while (user) - { - if (user->Name() == Name) - return user; - user = Users.Next(user); + cUser* user = Users.First(); + while (user) + { + if (user->Name() == Name) + return user; + user = Users.Next(user); } - return NULL; + return NULL; } int cUsers::GetNewId() { - int iMaxId = -1; - cUser* user = Users.First(); - while (user) - { - if (iMaxId < user->Id()) - iMaxId = user->Id(); - user = Users.Next(user); + int iMaxId = -1; + cUser* user = Users.First(); + while (user) + { + if (iMaxId < user->Id()) + iMaxId = user->Id(); + user = Users.Next(user); } - return iMaxId + 1; + return iMaxId + 1; } bool cUsers::ValidUserLogin(const std::string& login, const std::string& password) { - cUser* user = GetByUserName(login); - if (user && MD5Hash(password) == user->GetMD5HashPassword()) - return true; - return false; + cUser* user = GetByUserName(login); + if (user && MD5Hash(password) == user->GetMD5HashPassword()) + return true; + return false; } bool cUsers::ValidLogin(const std::string& login, const std::string& password) { - return ((login == LiveSetup().GetAdminLogin() && MD5Hash(password) == LiveSetup().GetMD5HashAdminPassword()) || - ValidUserLogin(login, password)); + return ((login == LiveSetup().GetAdminLogin() && MD5Hash(password) == LiveSetup().GetMD5HashAdminPassword()) || + ValidUserLogin(login, password)); } } diff --git a/users.h b/users.h index 9afc833..9d8d687 100644 --- a/users.h +++ b/users.h @@ -15,56 +15,56 @@ namespace vdrlive { enum eUserRights { - UR_EDITSETUP=1, - UR_EDITTIMERS, - UR_DELTIMERS, - UR_DELRECS, - UR_USEREMOTE, - UR_STARTREPLAY, - UR_SWITCHCHNL, - UR_EDITSTIMERS, - UR_DELSTIMERS, - UR_EDITRECS + UR_EDITSETUP=1, + UR_EDITTIMERS, + UR_DELTIMERS, + UR_DELRECS, + UR_USEREMOTE, + UR_STARTREPLAY, + UR_SWITCHCHNL, + UR_EDITSTIMERS, + UR_DELSTIMERS, + UR_EDITRECS }; // --- cUser -------------------------------------------------------- class cUser : public cListObject { - int m_ID; + int m_ID; std::string m_Name; std::string m_PasswordMD5; - int m_Userrights; + int m_Userrights; public: - cUser() : m_ID(-1), m_Userrights(0) {} - cUser(int ID, const std::string& Name, const std::string& Password); - int Id() const { return m_ID; } - std::string Name() const { return m_Name; } - std::string PasswordMD5() const { return m_PasswordMD5; } - int Userrights() const { return m_Userrights; } - int GetPasswordLength() const; - std::string const GetMD5HashPassword() const; - void SetId(int Id) { m_ID = Id; } - void SetName(const std::string& Name) { m_Name = Name; } - void SetPassword(const std::string& Password); - void SetUserrights(int Userrights) { m_Userrights = Userrights; } - bool HasRightTo(eUserRights right); - static bool CurrentUserHasRightTo(eUserRights right); - void SetRight(eUserRights right); - bool Parse(const char *s); - const char *ToText(void); - bool Save(FILE *f); + cUser() : m_ID(-1), m_Userrights(0) {} + cUser(int ID, const std::string& Name, const std::string& Password); + int Id() const { return m_ID; } + std::string Name() const { return m_Name; } + std::string PasswordMD5() const { return m_PasswordMD5; } + int Userrights() const { return m_Userrights; } + int GetPasswordLength() const; + std::string const GetMD5HashPassword() const; + void SetId(int Id) { m_ID = Id; } + void SetName(const std::string& Name) { m_Name = Name; } + void SetPassword(const std::string& Password); + void SetUserrights(int Userrights) { m_Userrights = Userrights; } + bool HasRightTo(eUserRights right); + static bool CurrentUserHasRightTo(eUserRights right); + void SetRight(eUserRights right); + bool Parse(const char *s); + const char *ToText(void); + bool Save(FILE *f); }; // --- cUsers -------------------------------------------------------- class cUsers : public cConfig { public: - bool ValidUserLogin(const std::string& login, const std::string& password); - bool ValidLogin(const std::string& login, const std::string& password); + bool ValidUserLogin(const std::string& login, const std::string& password); + bool ValidLogin(const std::string& login, const std::string& password); bool Delete(const std::string& Name); - static cUser* GetByUserId(const std::string& Id); - static cUser* GetByUserName(const std::string& Name); - int GetNewId(); + static cUser* GetByUserId(const std::string& Id); + static cUser* GetByUserName(const std::string& Name); + int GetNewId(); - static std::string logged_in_user; + static std::string logged_in_user; }; extern cUsers Users;