diff options
-rw-r--r-- | css/styles.css | 50 | ||||
-rw-r--r-- | live/css/siteprefs.css | 1 | ||||
-rw-r--r-- | timers.cpp | 484 | ||||
-rw-r--r-- | timers.h | 96 | ||||
-rw-r--r-- | tools.cpp | 392 | ||||
-rw-r--r-- | tools.h | 127 |
6 files changed, 586 insertions, 564 deletions
diff --git a/css/styles.css b/css/styles.css index 8e208a1..ae09f78 100644 --- a/css/styles.css +++ b/css/styles.css @@ -1069,27 +1069,27 @@ table.login tr td { /* ############################## - # Infowin support styles for EPG-Boxes + # Styles for EPG-Boxes ############################## */ -.info-win div.caption { +div.caption { padding: 2px 0px 0px 5px; } -.info-win div.epg_content { +div.epg_content { padding: 0px 0px 7px 0px; margin: 0px 0px 0px 0px; background: transparent url(img/bg_tools.png) top left repeat-y; - border: 0px; + border: 1px solid black; overflow: hidden; } -.info-win div.epg_content div { +div.epg_content div { margin-left: 35px; } -.info-win div.epg_content div.epg_tools { +div.epg_content div.epg_tools { float: left; width: 26px; margin: 0; @@ -1100,59 +1100,65 @@ table.login tr td { vertical-align: top; } -.info-win div.epg_content div div { - margin-left: 0px; -} - -/* -.info-win div.epg_content div div.progress div { +div.epg_content div div { margin-left: 0px; } -*/ -.info-win div.epg_content div.epg_tools img { +div.epg_content div.epg_tools img { margin: 2px 5px; } -.info-win span.epg_images img.epg_image { +span.epg_images img.epg_image { width: 100%; } +/* some adaptions when shown in info-win subwindow */ + +/* +.info-win div.epg_content div div.progress div { + margin-left: 0px; +} +*/ + .info-win div.boxheader { display: none; } +.info-win div.epg_content { + border: 0px; +} + /* ############################## - # About box + # Style adaptions for About box ############################## */ -.info-win div.epg_content div.about_left { +div.epg_content div.about_left { text-align: right; float: left; width: 175px; } -.info-win div.epg_content div.about_right { +div.epg_content div.about_right { padding-left: 200px; } -.info-win div.epg_content div.about_line { +div.epg_content div.about_line { padding-left: 0px; } -.info-win div.epg_content div.about_head { +div.epg_content div.about_head { font-weight: bold; margin-left: -9px; padding-top: 6px; } -.info-win div.epg_content div.about_head div { +div.epg_content div.about_head div { padding-bottom: 6px; margin-left: 0px; } -.info-win div.epg_content div.about_head div div { +div.epg_content div.about_head div div { padding: 2px 0px 2px 10px; background: #E9EFFF; border-top: 1px solid #C0C1DA; diff --git a/live/css/siteprefs.css b/live/css/siteprefs.css index 5e16262..66ddb29 100644 --- a/live/css/siteprefs.css +++ b/live/css/siteprefs.css @@ -25,4 +25,3 @@ table { } - @@ -13,308 +13,308 @@ static bool operator<( cTimer const& left, cTimer const& right ) namespace vdrlive { -using namespace std; -using namespace vdrlive; + using namespace std; + using namespace vdrlive; -static char const* const TIMER_DELETE = "DELETE"; -static char const* const TIMER_TOGGLE = "TOGGLE"; + static char const* const TIMER_DELETE = "DELETE"; + static char const* const TIMER_TOGGLE = "TOGGLE"; -SortedTimers::SortedTimers(): + SortedTimers::SortedTimers(): m_state( 0 ) -{ - ReloadTimers( true ); -} - -string SortedTimers::GetTimerId( cTimer const& timer ) -{ - ostringstream builder; - builder << timer.Channel()->GetChannelID() << ":" << timer.WeekDays() << ":" - << timer.Day() << ":" << timer.Start() << ":" << timer.Stop(); - return builder.str(); -} - -cTimer* SortedTimers::GetByTimerId( string const& timerid ) -{ - vector< string > parts = StringSplit( timerid, ':' ); - if ( parts.size() < 5 ) { - esyslog("GetByTimerId: invalid format %s", timerid.c_str() ); - return 0; + { + ReloadTimers( true ); } - cChannel* channel = Channels.GetByChannelID( tChannelID::FromString( parts[0].c_str() ) ); - if ( channel == 0 ) { - esyslog("GetByTimerId: no channel %s", parts[0].c_str() ); - return 0; + string SortedTimers::GetTimerId( cTimer const& timer ) + { + ostringstream builder; + builder << timer.Channel()->GetChannelID() << ":" << timer.WeekDays() << ":" + << timer.Day() << ":" << timer.Start() << ":" << timer.Stop(); + return builder.str(); } - try { - int weekdays = lexical_cast< int >( parts[1] ); - time_t day = lexical_cast< time_t >( parts[2] ); - int start = lexical_cast< int >( parts[3] ); - int stop = lexical_cast< int >( parts[4] ); - - for ( SortedTimers::iterator timer = begin(); timer != end(); ++timer ) { - if ( timer->Channel() == channel && - ( ( weekdays != 0 && timer->WeekDays() == weekdays ) || ( weekdays == 0 && timer->Day() == day ) ) && - timer->Start() == start && timer->Stop() == stop ) - return &*timer; + cTimer* SortedTimers::GetByTimerId( string const& timerid ) + { + vector< string > parts = StringSplit( timerid, ':' ); + if ( parts.size() < 5 ) { + esyslog("GetByTimerId: invalid format %s", timerid.c_str() ); + return 0; + } + + cChannel* channel = Channels.GetByChannelID( tChannelID::FromString( parts[0].c_str() ) ); + if ( channel == 0 ) { + esyslog("GetByTimerId: no channel %s", parts[0].c_str() ); + return 0; + } + + try { + int weekdays = lexical_cast< int >( parts[1] ); + time_t day = lexical_cast< time_t >( parts[2] ); + int start = lexical_cast< int >( parts[3] ); + int stop = lexical_cast< int >( parts[4] ); + + for ( SortedTimers::iterator timer = begin(); timer != end(); ++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("GetByTimer: bad cast"); } - } catch ( bad_lexical_cast const& ex ) { - esyslog("GetByTimer: bad cast"); + return 0; } - return 0; -} -void SortedTimers::ReloadTimers( bool initial ) -{ - dsyslog("live reloading timers"); + void SortedTimers::ReloadTimers( bool initial ) + { + dsyslog("live reloading timers"); - clear(); - for ( cTimer* timer = Timers.First(); timer != 0; timer = Timers.Next( timer ) ) { - push_back( *timer ); + clear(); + for ( cTimer* timer = Timers.First(); timer != 0; timer = Timers.Next( timer ) ) { + push_back( *timer ); + } + sort(); } - sort(); -} -string SortedTimers::GetTimerDays(cTimer const& timer) -{ - string currentDay = timer.WeekDays() > 0 ? + string SortedTimers::GetTimerDays(cTimer const& timer) + { + string currentDay = timer.WeekDays() > 0 ? #if VDRVERSNUM < 10503 - *cTimer::PrintDay(0, timer.WeekDays()) : + *cTimer::PrintDay(0, timer.WeekDays()) : #else - *cTimer::PrintDay(0, timer.WeekDays(), true) : + *cTimer::PrintDay(0, timer.WeekDays(), true) : #endif - FormatDateTime(tr("%A, %x"), timer.Day()); - return currentDay; -} - -string SortedTimers::GetTimerInfo(cTimer const& timer) -{ - ostringstream info; - info << trVDR("Priority") << ": " << timer.Priority() << endl; - info << trVDR("Lifetime") << ": " << timer.Lifetime() << endl; - info << trVDR("VPS") << ": " << (timer.HasFlags(tfVps)?trVDR("yes"):trVDR("no")) << endl; + FormatDateTime(tr("%A, %x"), timer.Day()); + return currentDay; + } - if (timer.Aux()) + string SortedTimers::GetTimerInfo(cTimer const& timer) { - string epgsearchinfo = GetXMLValue(timer.Aux(), "epgsearch"); - if (!epgsearchinfo.empty()) + ostringstream info; + info << trVDR("Priority") << ": " << timer.Priority() << endl; + info << trVDR("Lifetime") << ": " << timer.Lifetime() << endl; + info << trVDR("VPS") << ": " << (timer.HasFlags(tfVps)?trVDR("yes"):trVDR("no")) << endl; + + if (timer.Aux()) { - string searchtimer = GetXMLValue(epgsearchinfo, "searchtimer"); - if (!searchtimer.empty()) - info << tr("Searchtimer") << ": " << searchtimer << endl; - } + string epgsearchinfo = GetXMLValue(timer.Aux(), "epgsearch"); + if (!epgsearchinfo.empty()) + { + string searchtimer = GetXMLValue(epgsearchinfo, "searchtimer"); + if (!searchtimer.empty()) + info << tr("Searchtimer") << ": " << searchtimer << endl; + } + } + return info.str(); } - return info.str(); -} -TimerManager::TimerManager() -{ -} + TimerManager::TimerManager() + { + } -void TimerManager::UpdateTimer( cTimer* timer, int flags, tChannelID& channel, string const& weekdays, string const& day, - int start, int stop, int priority, int lifetime, string const& title, string const& aux ) -{ - cMutexLock lock( this ); + void TimerManager::UpdateTimer( cTimer* timer, int flags, tChannelID& channel, string const& weekdays, string const& day, + int start, int stop, int priority, int lifetime, string const& title, string const& aux ) + { + cMutexLock lock( this ); - ostringstream builder; - builder << flags << ":" << channel << ":" << ( weekdays != "-------" ? weekdays : "" ) - << ( weekdays == "-------" || day.empty() ? "" : "@" ) << day << ":" << start << ":" << stop << ":" - << priority << ":" << lifetime << ":" << title << ":" << aux; - dsyslog("%s", builder.str().c_str()); + ostringstream builder; + builder << flags << ":" << channel << ":" << ( weekdays != "-------" ? weekdays : "" ) + << ( weekdays == "-------" || day.empty() ? "" : "@" ) << day << ":" << start << ":" << stop << ":" + << priority << ":" << lifetime << ":" << title << ":" << aux; + dsyslog("%s", builder.str().c_str()); - TimerPair timerData( timer, builder.str() ); + TimerPair timerData( timer, builder.str() ); - dsyslog("SV: in UpdateTimer"); - m_updateTimers.push_back( timerData ); - dsyslog("SV: wait for update"); - m_updateWait.Wait( *this ); - dsyslog("SV: update done"); + dsyslog("SV: in UpdateTimer"); + m_updateTimers.push_back( timerData ); + dsyslog("SV: wait for update"); + m_updateWait.Wait( *this ); + dsyslog("SV: update done"); - string error = GetError( timerData ); - if ( !error.empty() ) - throw HtmlError( error ); -} + string error = GetError( timerData ); + if ( !error.empty() ) + throw HtmlError( error ); + } -void TimerManager::DelTimer( cTimer* timer ) -{ - cMutexLock lock( this ); + void TimerManager::DelTimer( cTimer* timer ) + { + cMutexLock lock( this ); - TimerPair timerData( timer, TIMER_DELETE ); + TimerPair timerData( timer, TIMER_DELETE ); - m_updateTimers.push_back( timerData ); - m_updateWait.Wait( *this ); + m_updateTimers.push_back( timerData ); + m_updateWait.Wait( *this ); - string error = GetError( timerData ); - if ( !error.empty() ) - throw HtmlError( error ); -} + string error = GetError( timerData ); + if ( !error.empty() ) + throw HtmlError( error ); + } -void TimerManager::ToggleTimerActive( cTimer* timer) -{ - cMutexLock lock( this ); + void TimerManager::ToggleTimerActive( cTimer* timer) + { + cMutexLock lock( this ); - TimerPair timerData( timer, TIMER_TOGGLE ); + TimerPair timerData( timer, TIMER_TOGGLE ); - m_updateTimers.push_back( timerData ); - m_updateWait.Wait( *this ); + m_updateTimers.push_back( timerData ); + m_updateWait.Wait( *this ); - string error = GetError( timerData ); - if ( !error.empty() ) - throw HtmlError( error ); -} + string error = GetError( timerData ); + if ( !error.empty() ) + throw HtmlError( error ); + } -void TimerManager::DoPendingWork() -{ - if ( m_updateTimers.size() == 0 && !m_timers.Modified() ) - return; + void TimerManager::DoPendingWork() + { + if ( m_updateTimers.size() == 0 && !m_timers.Modified() ) + return; - cMutexLock lock( this ); - if ( m_updateTimers.size() > 0 ) { - DoUpdateTimers(); + cMutexLock lock( this ); + if ( m_updateTimers.size() > 0 ) { + DoUpdateTimers(); + } + DoReloadTimers(); + dsyslog("SV: signalling waiters"); + m_updateWait.Broadcast(); } - DoReloadTimers(); - dsyslog("SV: signalling waiters"); - m_updateWait.Broadcast(); -} -void TimerManager::DoUpdateTimers() -{ - dsyslog("SV: updating timers"); - for ( TimerList::iterator timer = m_updateTimers.begin(); timer != m_updateTimers.end(); ++timer ) { - if ( timer->first == 0 ) // new timer - DoInsertTimer( *timer ); - else if ( timer->second == TIMER_DELETE ) // delete timer - DoDeleteTimer( *timer ); - else if ( timer->second == TIMER_TOGGLE ) // toggle timer - DoToggleTimer( *timer ); - else // update timer - DoUpdateTimer( *timer ); + void TimerManager::DoUpdateTimers() + { + dsyslog("SV: updating timers"); + for ( TimerList::iterator timer = m_updateTimers.begin(); timer != m_updateTimers.end(); ++timer ) { + if ( timer->first == 0 ) // new timer + DoInsertTimer( *timer ); + else if ( timer->second == TIMER_DELETE ) // delete timer + DoDeleteTimer( *timer ); + else if ( timer->second == TIMER_TOGGLE ) // toggle timer + DoToggleTimer( *timer ); + else // update timer + DoUpdateTimer( *timer ); + } + m_updateTimers.clear(); } - m_updateTimers.clear(); -} -void TimerManager::DoInsertTimer( TimerPair& timerData ) -{ - auto_ptr< cTimer > newTimer( new cTimer ); - if ( !newTimer->Parse( timerData.second.c_str() ) ) { - StoreError( timerData, tr("Error in timer settings") ); - return; - } + void TimerManager::DoInsertTimer( TimerPair& timerData ) + { + auto_ptr< cTimer > newTimer( new cTimer ); + if ( !newTimer->Parse( timerData.second.c_str() ) ) { + StoreError( timerData, tr("Error in timer settings") ); + return; + } + + cTimer* checkTimer = Timers.GetTimer( newTimer.get() ); + if ( checkTimer != 0 ) { + StoreError( timerData, tr("Timer already defined") ); + return; + } - cTimer* checkTimer = Timers.GetTimer( newTimer.get() ); - if ( checkTimer != 0 ) { - StoreError( timerData, tr("Timer already defined") ); - return; + Timers.Add( newTimer.get() ); + Timers.SetModified(); + isyslog( "live timer %s added", *newTimer->ToDescr() ); + newTimer.release(); } - Timers.Add( newTimer.get() ); - Timers.SetModified(); - isyslog( "live timer %s added", *newTimer->ToDescr() ); - newTimer.release(); -} + void TimerManager::DoUpdateTimer( TimerPair& timerData ) + { + if ( Timers.BeingEdited() ) { + StoreError( timerData, tr("Timers are being edited - try again later") ); + return; + } -void TimerManager::DoUpdateTimer( TimerPair& timerData ) -{ - if ( Timers.BeingEdited() ) { - StoreError( timerData, tr("Timers are being edited - try again later") ); - return; - } + cTimer* oldTimer = Timers.GetTimer( timerData.first ); + if ( oldTimer == 0 ) { + StoreError( timerData, tr("Timer not defined") ); + return; + } - cTimer* oldTimer = Timers.GetTimer( timerData.first ); - if ( oldTimer == 0 ) { - StoreError( timerData, tr("Timer not defined") ); - return; - } + cTimer copy = *oldTimer; + if ( !copy.Parse( timerData.second.c_str() ) ) { + StoreError( timerData, tr("Error in timer settings") ); + return; + } - cTimer copy = *oldTimer; - if ( !copy.Parse( timerData.second.c_str() ) ) { - StoreError( timerData, tr("Error in timer settings") ); - return; + *oldTimer = copy; + Timers.SetModified(); + isyslog("live timer %s modified (%s)", *oldTimer->ToDescr(), oldTimer->HasFlags(tfActive) ? "active" : "inactive"); } - *oldTimer = copy; - Timers.SetModified(); - isyslog("live timer %s modified (%s)", *oldTimer->ToDescr(), oldTimer->HasFlags(tfActive) ? "active" : "inactive"); -} + void TimerManager::DoDeleteTimer( TimerPair& timerData ) + { + if ( Timers.BeingEdited() ) { + StoreError( timerData, tr("Timers are being edited - try again later") ); + return; + } -void TimerManager::DoDeleteTimer( TimerPair& timerData ) -{ - if ( Timers.BeingEdited() ) { - StoreError( timerData, tr("Timers are being edited - try again later") ); - return; - } + cTimer* oldTimer = Timers.GetTimer( timerData.first ); + if ( oldTimer == 0 ) { + StoreError( timerData, tr("Timer not defined") ); + return; + } - cTimer* oldTimer = Timers.GetTimer( timerData.first ); - if ( oldTimer == 0 ) { - StoreError( timerData, tr("Timer not defined") ); - return; + cTimer copy = *oldTimer; + if ( oldTimer->Recording() ) { + oldTimer->Skip(); + cRecordControls::Process( time( 0 ) ); + } + Timers.Del( oldTimer ); + Timers.SetModified(); + isyslog("live timer %s deleted", *copy.ToDescr()); } - cTimer copy = *oldTimer; - if ( oldTimer->Recording() ) { - oldTimer->Skip(); - cRecordControls::Process( time( 0 ) ); - } - Timers.Del( oldTimer ); - Timers.SetModified(); - isyslog("live timer %s deleted", *copy.ToDescr()); -} + void TimerManager::DoToggleTimer( TimerPair& timerData ) + { + if ( Timers.BeingEdited() ) { + StoreError( timerData, tr("Timers are being edited - try again later") ); + return; + } -void TimerManager::DoToggleTimer( TimerPair& timerData ) -{ - if ( Timers.BeingEdited() ) { - StoreError( timerData, tr("Timers are being edited - try again later") ); - return; - } + cTimer* toggleTimer = Timers.GetTimer( timerData.first ); + if ( toggleTimer == 0 ) { + StoreError( timerData, tr("Timer not defined") ); + return; + } - cTimer* toggleTimer = Timers.GetTimer( timerData.first ); - if ( toggleTimer == 0 ) { - StoreError( timerData, tr("Timer not defined") ); - return; + toggleTimer->OnOff(); + Timers.SetModified(); + isyslog("live timer %s toggled %s", *toggleTimer->ToDescr(), toggleTimer->HasFlags(tfActive) ? "on" : "off"); } - toggleTimer->OnOff(); - Timers.SetModified(); - isyslog("live timer %s toggled %s", *toggleTimer->ToDescr(), toggleTimer->HasFlags(tfActive) ? "on" : "off"); -} - -void TimerManager::StoreError( TimerPair const& timerData, std::string const& error ) -{ - m_failedUpdates.push_back( ErrorPair( timerData, error ) ); -} + void TimerManager::StoreError( TimerPair const& timerData, std::string const& error ) + { + m_failedUpdates.push_back( ErrorPair( timerData, error ) ); + } -string TimerManager::GetError( TimerPair const& timerData ) -{ - for ( ErrorList::iterator error = m_failedUpdates.begin(); error != m_failedUpdates.end(); ++error ) { - if ( error->first == timerData ) { - string message = error->second; - m_failedUpdates.erase( error ); - return message; + string TimerManager::GetError( TimerPair const& timerData ) + { + for ( ErrorList::iterator error = m_failedUpdates.begin(); error != m_failedUpdates.end(); ++error ) { + if ( error->first == timerData ) { + string message = error->second; + m_failedUpdates.erase( error ); + return message; + } } + return ""; } - return ""; -} -const cTimer* TimerManager::GetTimer(tEventID eventid, tChannelID channelid) -{ - cMutexLock timersLock( &LiveTimerManager() ); - SortedTimers& timers = LiveTimerManager().GetTimers(); + const cTimer* TimerManager::GetTimer(tEventID eventid, tChannelID channelid) + { + cMutexLock timersLock( &LiveTimerManager() ); + SortedTimers& timers = LiveTimerManager().GetTimers(); + + for ( SortedTimers::iterator timer = timers.begin(); timer != timers.end(); ++timer ) + if (timer->Channel() && timer->Channel()->GetChannelID() == channelid) + { + if (!timer->Event()) timer->SetEventFromSchedule(); + if (timer->Event() && timer->Event()->EventID() == eventid) + return &*timer; + } + return NULL; + } - for ( SortedTimers::iterator timer = timers.begin(); timer != timers.end(); ++timer ) - if (timer->Channel() && timer->Channel()->GetChannelID() == channelid) - { - if (!timer->Event()) timer->SetEventFromSchedule(); - if (timer->Event() && timer->Event()->EventID() == eventid) - return &*timer; - } - return NULL; -} - -TimerManager& LiveTimerManager() -{ - static TimerManager instance; - return instance; -} + TimerManager& LiveTimerManager() + { + static TimerManager instance; + return instance; + } } // namespace vdrlive @@ -11,69 +11,69 @@ namespace vdrlive { -class SortedTimers: public std::list< cTimer > -{ - friend class TimerManager; + class SortedTimers: public std::list< cTimer > + { + friend class TimerManager; -public: - std::string GetTimerId( cTimer const& timer ); - cTimer* GetByTimerId( std::string const& timerid ); + public: + std::string GetTimerId( cTimer const& timer ); + cTimer* GetByTimerId( std::string const& timerid ); - bool Modified() { return Timers.Modified( m_state ); } - static std::string GetTimerDays(cTimer const& timer); - static std::string GetTimerInfo(cTimer const& timer); + bool Modified() { return Timers.Modified( m_state ); } + static std::string GetTimerDays(cTimer const& timer); + static std::string GetTimerInfo(cTimer const& timer); -private: - SortedTimers(); - SortedTimers( SortedTimers const& ); + private: + SortedTimers(); + SortedTimers( SortedTimers const& ); - int m_state; + int m_state; - void ReloadTimers( bool initial = false ); -}; + void ReloadTimers( bool initial = false ); + }; -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( cTimer* timer, int flags, 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( cTimer* timer, int flags, 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( cTimer* timer); - void ToggleTimerActive( cTimer* timer); - // may only be called from Plugin::MainThreadHook - void DoPendingWork(); - void DoReloadTimers() { m_timers.ReloadTimers(); } - const cTimer* GetTimer(tEventID eventid, tChannelID channelid); + void DelTimer( cTimer* timer); + void ToggleTimerActive( cTimer* timer); + // may only be called from Plugin::MainThreadHook + void DoPendingWork(); + void DoReloadTimers() { m_timers.ReloadTimers(); } + const cTimer* GetTimer(tEventID eventid, tChannelID channelid); -private: - typedef std::pair< cTimer*, std::string > TimerPair; - typedef std::pair< TimerPair, std::string > ErrorPair; - typedef std::list< TimerPair > TimerList; - typedef std::list< ErrorPair > ErrorList; + private: + typedef std::pair< cTimer*, std::string > TimerPair; + typedef std::pair< TimerPair, std::string > ErrorPair; + typedef std::list< TimerPair > TimerList; + typedef std::list< ErrorPair > ErrorList; - TimerManager(); - TimerManager( TimerManager const& ); + TimerManager(); + TimerManager( TimerManager const& ); - SortedTimers m_timers; - TimerList m_updateTimers; - ErrorList m_failedUpdates; - cCondVar m_updateWait; + SortedTimers m_timers; + TimerList m_updateTimers; + ErrorList m_failedUpdates; + cCondVar m_updateWait; - void DoUpdateTimers(); - void DoInsertTimer( TimerPair& timerData ); - void DoUpdateTimer( TimerPair& timerData ); - void DoDeleteTimer( TimerPair& timerData ); - void DoToggleTimer( TimerPair& timerData ); + void DoUpdateTimers(); + void DoInsertTimer( TimerPair& timerData ); + void DoUpdateTimer( TimerPair& timerData ); + void DoDeleteTimer( TimerPair& timerData ); + void DoToggleTimer( TimerPair& timerData ); - void StoreError( TimerPair const& timerData, std::string const& error ); - std::string GetError( TimerPair const& timerData ); -}; + void StoreError( TimerPair const& timerData, std::string const& error ); + std::string GetError( TimerPair const& timerData ); + }; -TimerManager& LiveTimerManager(); + TimerManager& LiveTimerManager(); } // namespace vdrlive @@ -50,119 +50,119 @@ istream& operator>>( istream& is, tChannelID& ret ) namespace vdrlive { -string FormatDateTime( char const* format, time_t time ) -{ - struct tm tm_r; - if ( localtime_r( &time, &tm_r ) == 0 ) { - ostringstream builder; - builder << "cannot represent timestamp " << time << " as local time"; - throw runtime_error( builder.str() ); + string FormatDateTime( char const* format, time_t time ) + { + struct tm tm_r; + if ( localtime_r( &time, &tm_r ) == 0 ) { + ostringstream builder; + builder << "cannot represent timestamp " << time << " as local time"; + throw runtime_error( builder.str() ); + } + + char result[ 256 ]; + if ( strftime( result, sizeof( result ), format, &tm_r ) == 0 ) { + ostringstream builder; + builder << "representation of timestamp " << time << " exceeds " << sizeof( result ) << " bytes"; + throw runtime_error( builder.str() ); + } + return result; } - char result[ 256 ]; - if ( strftime( result, sizeof( result ), format, &tm_r ) == 0 ) { - ostringstream builder; - builder << "representation of timestamp " << time << " exceeds " << sizeof( result ) << " bytes"; - throw runtime_error( builder.str() ); + string StringReplace( string const& text, string const& substring, string const& replacement ) + { + string result = text; + string::size_type pos = 0; + while ( ( pos = result.find( substring, pos ) ) != string::npos ) { + result.replace( pos, substring.length(), replacement ); + pos += replacement.length(); + } + return result; } - return result; -} -string StringReplace( string const& text, string const& substring, string const& replacement ) -{ - string result = text; - string::size_type pos = 0; - while ( ( pos = result.find( substring, pos ) ) != string::npos ) { - result.replace( pos, substring.length(), replacement ); - pos += replacement.length(); + vector< string > StringSplit( string const& text, char delimiter ) + { + vector< string > result; + string::size_type last = 0, pos; + while ( ( pos = text.find( delimiter, last ) ) != string::npos ) { + result.push_back( text.substr( last, pos - last ) ); + last = pos + 1; + } + if ( last < text.length() ) + result.push_back( text.substr( last ) ); + return result; } - return result; -} -vector< string > StringSplit( string const& text, char delimiter ) -{ - vector< string > result; - string::size_type last = 0, pos; - while ( ( pos = text.find( delimiter, last ) ) != string::npos ) { - result.push_back( text.substr( last, pos - last ) ); - last = pos + 1; + int StringToInt( std::string const& string, int base ) + { + char* end; + int result = strtol( string.c_str(), &end, base ); + if ( *end == '\0' ) + return result; + return 0; } - if ( last < text.length() ) - result.push_back( text.substr( last ) ); - return result; -} -int StringToInt( std::string const& string, int base ) -{ - char* end; - int result = strtol( string.c_str(), &end, base ); - if ( *end == '\0' ) + string StringRepeat(int times, const string& input) + { + string result; + for (int i = 0; i < times; i++) { + result += input; + } return result; - return 0; -} - -string StringRepeat(int times, const string& input) -{ - string result; - for (int i = 0; i < times; i++) { - result += input; } - return result; -} -string StringWordTruncate(const string& input, size_t maxLen, bool& truncated) -{ - if (input.length() <= maxLen) + string StringWordTruncate(const string& input, size_t maxLen, bool& truncated) { - return input; + if (input.length() <= maxLen) + { + return input; + } + truncated = true; + string result = input.substr(0, maxLen); + size_t pos = result.find_last_of(" \t,;:.\n?!'\"/\\()[]{}*+-"); + return result.substr(0, pos); } - truncated = true; - string result = input.substr(0, maxLen); - size_t pos = result.find_last_of(" \t,;:.\n?!'\"/\\()[]{}*+-"); - return result.substr(0, pos); -} -string StringFormatBreak(string const& input) -{ - return StringReplace( input, "\n", "<br/>" ); -} + string StringFormatBreak(string const& input) + { + return StringReplace( input, "\n", "<br/>" ); + } -string StringEscapeAndBreak( string const& input ) -{ - stringstream plainBuilder; - HtmlEscOstream builder( plainBuilder ); - builder << input; - return StringReplace( plainBuilder.str(), "\n", "<br/>" ); -} + string StringEscapeAndBreak( string const& input ) + { + stringstream plainBuilder; + HtmlEscOstream builder( plainBuilder ); + builder << input; + return StringReplace( plainBuilder.str(), "\n", "<br/>" ); + } -string StringTrim(string const& str) -{ - string res = str; - string::size_type pos = res.find_last_not_of(' '); - if(pos != string::npos) { - res.erase(pos + 1); - pos = res.find_first_not_of(' '); - if(pos != string::npos) res.erase(0, pos); - } - else res.erase(res.begin(), res.end()); - return res; -} + string StringTrim(string const& str) + { + string res = str; + string::size_type pos = res.find_last_not_of(' '); + if(pos != string::npos) { + res.erase(pos + 1); + pos = res.find_first_not_of(' '); + if(pos != string::npos) res.erase(0, pos); + } + else res.erase(res.begin(), res.end()); + return res; + } -string ZeroPad(int number) -{ - ostringstream os; - os << setw(2) << setfill('0') << number; - return os.str(); -} + string ZeroPad(int number) + { + ostringstream os; + os << setw(2) << setfill('0') << number; + return os.str(); + } -std::string MD5Hash(std::string const& str) -{ - char* szInput = strdup(str.c_str()); - if (!szInput) return ""; - char* szRes = MD5String(szInput); - string res = szRes; - free(szRes); - return res; + std::string MD5Hash(std::string const& str) + { + char* szInput = strdup(str.c_str()); + if (!szInput) return ""; + char* szRes = MD5String(szInput); + string res = szRes; + free(szRes); + return res; /* unsigned char md5[MD5_DIGEST_LENGTH]; MD5(reinterpret_cast<const unsigned char*>(str.c_str()), str.size(), md5); @@ -170,128 +170,128 @@ std::string MD5Hash(std::string const& str) ostringstream hashStr; hashStr << hex; for (size_t i = 0; i < MD5_DIGEST_LENGTH; i++) - hashStr << (0 + md5[i]); + hashStr << (0 + md5[i]); return hashStr.str(); */ -} + } #define HOURS(x) ((x)/100) #define MINUTES(x) ((x)%100) -std::string ExpandTimeString(std::string timestring) -{ - string::size_type colonpos = timestring.find(":"); - if (colonpos == string::npos) + std::string ExpandTimeString(std::string timestring) { - if (timestring.size() == 1) - timestring = "0" + timestring + ":00"; - else if (timestring.size() == 2) - timestring = timestring + ":00"; - else if (timestring.size() == 3) - timestring = "0" + string(timestring.begin(), timestring.begin() + 1) + ":" + string(timestring.begin() + 1, timestring.end()); + string::size_type colonpos = timestring.find(":"); + if (colonpos == 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" + string(timestring.begin(), timestring.begin() + 1) + ":" + string(timestring.begin() + 1, timestring.end()); + else + timestring = string(timestring.begin(), timestring.begin() + 2) + ":" + string(timestring.begin() + 2, timestring.end()); + } else - timestring = string(timestring.begin(), timestring.begin() + 2) + ":" + string(timestring.begin() + 2, timestring.end()); + { + string hours = string(timestring.begin(), timestring.begin() + colonpos); + string mins = string(timestring.begin() + colonpos + 1, timestring.end()); + hours = string(std::max(0,(int)(2 - hours.size())), '0') + hours; + mins = string(std::max(0,(int)(2 - mins.size())), '0') + mins; + timestring = hours + ":" + mins; + } + return timestring; } - else + + time_t GetTimeT(std::string timestring) // timestring in HH:MM { - string hours = string(timestring.begin(), timestring.begin() + colonpos); - string mins = string(timestring.begin() + colonpos + 1, timestring.end()); - hours = string(std::max(0,(int)(2 - hours.size())), '0') + hours; - mins = string(std::max(0,(int)(2 - mins.size())), '0') + mins; - timestring = hours + ":" + mins; + timestring = StringReplace(timestring, ":", ""); + int iTime = lexical_cast< 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); } - return timestring; -} - -time_t GetTimeT(std::string timestring) // timestring in HH:MM -{ - timestring = StringReplace(timestring, ":", ""); - int iTime = lexical_cast< 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 -{ - ostream& ostr_; - urlencoder( ostream& ostr ): ostr_( ostr ) {} - - void operator()( char ch ) + struct urlencoder { - static const char allowedChars[] = { - // 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 - '_', 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 - '_', 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 - // everything above 127 (for signed char, below zero) is replaced with '_' - }; - - if ( ch == ' ' ) - ostr_ << '+'; - else if ( static_cast< signed char >( ch ) < 0 || allowedChars[ size_t( ch ) ] == '_' ) - ostr_ << '%' << setw( 2 ) << setfill( '0' ) << hex << int( static_cast< unsigned char >( ch ) ); - else - ostr_ << ch; + ostream& ostr_; + + urlencoder( 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 + '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', 0x2D,0x2E,0x2F, //20 + 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 + '_', 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 + // everything above 127 (for signed char, below zero) is replaced with '_' + }; + + if ( ch == ' ' ) + ostr_ << '+'; + else if ( static_cast< signed char >( ch ) < 0 || allowedChars[ size_t( ch ) ] == '_' ) + ostr_ << '%' << setw( 2 ) << setfill( '0' ) << hex << int( static_cast< unsigned char >( ch ) ); + else + ostr_ << ch; + } + }; + + string StringUrlEncode( string const& input ) + { + ostringstream ostr; + for_each( input.begin(), input.end(), urlencoder( ostr ) ); + return ostr.str(); } -}; - -string StringUrlEncode( string const& input ) -{ - ostringstream ostr; - for_each( input.begin(), input.end(), urlencoder( ostr ) ); - return ostr.str(); -} // returns the content of <element>...</element> -string GetXMLValue( std::string const& xml, std::string const& element ) -{ - string start = "<" + element + ">"; - string end = "</" + element + ">"; - string::size_type startPos = xml.find(start); - if (startPos == string::npos) return ""; - string::size_type endPos = xml.find(end); - if (endPos == string::npos) return ""; - return xml.substr(startPos + start.size(), endPos - startPos - start.size()); -} + string GetXMLValue( std::string const& xml, std::string const& element ) + { + string start = "<" + element + ">"; + string end = "</" + element + ">"; + string::size_type startPos = xml.find(start); + if (startPos == string::npos) return ""; + string::size_type endPos = xml.find(end); + if (endPos == string::npos) return ""; + return xml.substr(startPos + start.size(), endPos - startPos - start.size()); + } // return the time value as time_t from <datestring> formatted with <format> -time_t GetDateFromDatePicker(std::string const& datestring, std::string const& format) -{ - if (datestring.empty()) - return 0; - int year = lexical_cast< int >(datestring.substr(format.find("yyyy"), 4)); - int month = lexical_cast< int >(datestring.substr(format.find("mm"), 2)); - int day = lexical_cast< 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(std::string const& datestring, std::string const& format) + { + if (datestring.empty()) + return 0; + int year = lexical_cast< int >(datestring.substr(format.find("yyyy"), 4)); + int month = lexical_cast< int >(datestring.substr(format.find("mm"), 2)); + int day = lexical_cast< 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, std::string const& 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 FormatDateTime(cformat.c_str(), date); -} + std::string DatePickerToC(time_t date, std::string const& 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 FormatDateTime(cformat.c_str(), date); + } } // namespace vdrlive @@ -14,7 +14,7 @@ std::istream& operator>>( std::istream& is, tChannelID& ret ); -inline +inline std::ostream& operator<<( std::ostream& os, tChannelID const& id ) { return os << *id.ToString(); @@ -22,66 +22,83 @@ std::ostream& operator<<( std::ostream& os, tChannelID const& id ) namespace vdrlive { -std::string FormatDateTime( char const* format, time_t time ); -std::string StringReplace( std::string const& text, std::string const& substring, std::string const& replacement ); -std::vector< std::string > StringSplit( std::string const& text, char delimiter ); -int StringToInt( std::string const& string, int base = 10 ); -std::string StringRepeat(int times, const std::string& input); -std::string StringWordTruncate(const std::string& input, size_t maxLen, bool& truncated); -inline std::string StringWordTruncate(const std::string& input, size_t maxLen) { bool dummy; return StringWordTruncate(input, maxLen, dummy); } -std::string StringEscapeAndBreak( std::string const& input ); -std::string StringFormatBreak(std::string const& input); -std::string StringTrim(const std::string& str); -std::string ZeroPad(int number); -std::string MD5Hash(std::string const& str); -time_t GetTimeT(std::string timestring); -std::string ExpandTimeString(std::string timestring); -std::string StringUrlEncode( std::string const& input ); -std::string GetXMLValue( std::string const& xml, std::string const& element ); -time_t GetDateFromDatePicker(std::string const& datestring, std::string const& format); - std::string DatePickerToC(time_t date, std::string const& format); - -struct bad_lexical_cast: std::runtime_error -{ - bad_lexical_cast(): std::runtime_error( "bad lexical cast" ) {} -}; + std::string FormatDateTime( char const* format, time_t time ); -template< typename To, typename From > -To lexical_cast( From const& from ) -{ - std::stringstream parser; - parser << from; - To result; - parser >> result; - if ( !parser ) - throw bad_lexical_cast(); - return result; -} + std::string StringReplace( std::string const& text, std::string const& substring, std::string const& replacement ); -template< typename From > -std::string ConvertToString( From const& from, std::locale const& loc = std::locale() ) -{ - std::ostringstream parser; - parser.imbue( loc ); - parser << from; - return parser.str(); -} + std::vector< std::string > StringSplit( std::string const& text, char delimiter ); -class ReadLock -{ -public: - ReadLock( cRwLock& lock, int timeout = 100 ): m_lock( lock ), m_locked( false ) { if ( m_lock.Lock( false, timeout ) ) m_locked = true; } - ~ReadLock() { if ( m_locked ) m_lock.Unlock(); } + int StringToInt( std::string const& string, int base = 10 ); + + std::string StringRepeat(int times, const std::string& input); + + std::string StringWordTruncate(const std::string& input, size_t maxLen, bool& truncated); + + inline std::string StringWordTruncate(const std::string& input, size_t maxLen) { bool dummy; return StringWordTruncate(input, maxLen, dummy); } + + std::string StringEscapeAndBreak( std::string const& input ); + + std::string StringFormatBreak(std::string const& input); + + std::string StringTrim(const std::string& str); + + std::string ZeroPad(int number); + + std::string MD5Hash(std::string const& str); + + time_t GetTimeT(std::string timestring); + + std::string ExpandTimeString(std::string timestring); + + std::string StringUrlEncode( std::string const& input ); + + std::string GetXMLValue( std::string const& xml, std::string const& element ); + + time_t GetDateFromDatePicker(std::string const& datestring, std::string const& format); + + std::string DatePickerToC(time_t date, std::string const& format); + + struct bad_lexical_cast: std::runtime_error + { + bad_lexical_cast(): std::runtime_error( "bad lexical cast" ) {} + }; + + template< typename To, typename From > + To lexical_cast( From const& from ) + { + std::stringstream parser; + parser << from; + To result; + parser >> result; + if ( !parser ) + throw bad_lexical_cast(); + return result; + } + + template< typename From > + std::string ConvertToString( From const& from, std::locale const& loc = std::locale() ) + { + std::ostringstream parser; + parser.imbue( loc ); + parser << from; + return parser.str(); + } + + class ReadLock + { + public: + ReadLock( cRwLock& lock, int timeout = 100 ): m_lock( lock ), m_locked( false ) { if ( m_lock.Lock( false, timeout ) ) m_locked = true; } + ~ReadLock() { if ( m_locked ) m_lock.Unlock(); } - operator bool() { return m_locked; } - bool operator!() { return !m_locked; } + operator bool() { return m_locked; } + bool operator!() { return !m_locked; } -private: - ReadLock( ReadLock const& ); + private: + ReadLock( ReadLock const& ); - cRwLock& m_lock; - bool m_locked; -}; + cRwLock& m_lock; + bool m_locked; + }; } // namespace vdrlive |