summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pages/multischedule.ecpp217
-rw-r--r--pages/setup.ecpp17
-rw-r--r--setup.cpp8
-rw-r--r--setup.h6
4 files changed, 204 insertions, 44 deletions
diff --git a/pages/multischedule.ecpp b/pages/multischedule.ecpp
index bf05fa6..9005932 100644
--- a/pages/multischedule.ecpp
+++ b/pages/multischedule.ecpp
@@ -32,11 +32,12 @@ struct SchedEntry {
};
std::vector<std::string> channel_groups_names;
+ std::vector< std::vector<int> > channel_groups_numbers;
std::vector<std::string> times_names;
std::vector<time_t> times_start;
</%pre>
<%args>
- unsigned int channel = 0;
+ int channel = -1;
unsigned int time_para = 0;
</%args>
<%session scope="global">
@@ -55,39 +56,112 @@ pageTitle = trVDR("Schedule");
if ( !channelsLock )
throw HtmlError( tr("Couldn't aquire access to channels, please try again later.") );
-#define MAX_CHANNELS 5
+#define MAX_CHANNELS 10
#define MAX_DAYS 3
#define MAX_HOURS 8
#define MINUTES_PER_ROW 5
#define CHARACTERS_PER_ROW 30
+ if ( channel_groups_numbers.size() == 0 )
+ {
// build the groups of channels to display
- std::vector< std::vector<int> > channel_groups_numbers;
- channel_groups_names.clear();
- int cur_group_count=0;
- for ( cChannel *listChannel = Channels.First(); listChannel; listChannel = Channels.Next( listChannel ) )
+ std::string channelGroups=LiveSetup().GetChannelGroups();
+ if ( channelGroups.empty() )
+ {
+ // setup default channel groups
+ int lastChannel = LiveSetup().GetLastChannel();
+ if ( lastChannel == 0 )
+ lastChannel = Channels.MaxNumber();
+ std::stringstream groups;
+ for ( int i = 1; i<= lastChannel; i++)
+ {
+ groups << i;
+ if ( (i % 5) == 0 )
+ groups << ";";
+ else
+ groups << ",";
+ }
+ channelGroups = groups.str();
+ LiveSetup().SetChannelGroups( channelGroups );
+ }
+ size_t groupSep;
+ std::string thisGroup = "";
+ while ( ! channelGroups.empty() )
{
- if ( listChannel->GroupSep() || *listChannel->Name() == '\0' )
- continue;
+ groupSep = channelGroups.find(';');
+ thisGroup = channelGroups.substr(0, groupSep );
+ if ( groupSep != channelGroups.npos )
+ channelGroups.erase(0, groupSep+1 );
+ else
+ channelGroups="";
- if ( cur_group_count==0 )
+ int cur_group_count=0;
+ channel_groups_names.push_back( std::string() );
+ channel_groups_numbers.push_back( std::vector<int>() );
+ while ( !thisGroup.empty() )
+ {
+ std::string thisChannel;
+ try {
+ if ( cur_group_count != 0 )
+ channel_groups_names.back() += std::string( " - " );
+ size_t channelSep = thisGroup.find(',');
+ thisChannel = thisGroup.substr(0, channelSep );
+ if ( channelSep != thisGroup.npos )
+ thisGroup.erase( 0, channelSep+1 );
+ else
+ thisGroup = "";
+ int channel_no = lexical_cast< int > (thisChannel);
+ cChannel* Channel = Channels.GetByNumber( channel_no );
+ if ( !Channel )
+ {
+ esyslog("Live: could not find channel no '%s'.", thisChannel.c_str() );
+ continue;
+ }
+ channel_groups_names.back() += std::string( Channel->Name() );
+ channel_groups_numbers.back().push_back( Channel->Number() );
+ cur_group_count++;
+ if ( cur_group_count>=MAX_CHANNELS )
+ {
+ // start new group if group gets too large
+ cur_group_count=0;
+ channel_groups_names.push_back( std::string() );
+ channel_groups_numbers.push_back( std::vector<int>() );
+ }
+ }
+ catch ( const bad_lexical_cast & )
{
- // first entry in this group
- channel_groups_names.push_back( std::string() );
- channel_groups_numbers.push_back( std::vector<int>( MAX_CHANNELS) );
+ esyslog("Live: could not convert '%s' into a channel number", thisChannel.c_str());
+ continue;
}
- else channel_groups_names.back() += " - ";
-
- channel_groups_names.back() += std::string( listChannel->Name() );
- channel_groups_numbers.back()[ cur_group_count ] = listChannel->Number();
-
- cur_group_count++;
- if ( cur_group_count >= MAX_CHANNELS )
- // we need a new group next round
- cur_group_count = 0;
+ }
+ }
+ }
+ if ( channel < 0 ) {
+ if (cDevice::CurrentChannel()) {
+ // find group corresponding to current channel
+ int curGroup =0;
+ int curChannel = cDevice::CurrentChannel();
+ for ( std::vector< std::vector<int> >::iterator grIt = channel_groups_numbers.begin();
+ grIt != channel_groups_numbers.end() && channel < 0; ++grIt, ++curGroup )
+ {
+ for ( std::vector<int>::iterator chIt = (*grIt).begin();
+ chIt != (*grIt).end() && channel < 0; ++ chIt )
+ {
+ if ( *chIt == curChannel )
+ channel_group = channel = curGroup;
+ }
+ }
+ // if nothing is found, fall back to group 0
+ if ( channel < 0 )
+ channel = 0;
+ }
+ else {
+ channel_group = channel;
+ }
}
+
if ( channel >= channel_groups_numbers.size() )
- channel = channel_groups_numbers.size()-1;
+ channel = 0;
channel_group = channel;
{
// build time list
@@ -95,7 +169,7 @@ pageTitle = trVDR("Schedule");
times_start.clear();
// calculate time of midnight (localtime) and convert back to GMT
- time_t now = time(NULL);
+ time_t now = (time(NULL)/3600)*3600;
time_t now_local = time(NULL);
struct tm tm_r;
if ( localtime_r( &now_local, &tm_r ) == 0 ) {
@@ -108,22 +182,58 @@ pageTitle = trVDR("Schedule");
tm_r.tm_sec=0;
time_t midnight = mktime( &tm_r );
- // default is now rounded to full hour
- times_names.push_back( tr("Now") );
- times_start.push_back( 3600 * ( now /3600 ) );
-
- int i =0;
- // skip allready passed times
- while ( now>midnight+MAX_HOURS*3600*i)
- i++;
-
- for (; i<4*MAX_DAYS ; i++ )
+ // add four 8h steps per day to the time list
+ for (int i=0; i<4*MAX_DAYS ; i++ )
{
- times_names.push_back(FormatDateTime( tr("%A, %x"), midnight + MAX_HOURS*3600*i)
- +std::string(" ")+ FormatDateTime( tr("%I:%M %p"), midnight + MAX_HOURS*3600*i) );
- //times_names.push_back("today 0:00");
times_start.push_back( midnight + MAX_HOURS*3600*i );
}
+ vector< string > parts = StringSplit( LiveSetup().GetTimes(), ';' );
+ vector< time_t > offsets;
+ vector< string >::const_iterator part = parts.begin();
+ for ( ; part != parts.end(); ++part )
+ {
+ try {
+ unsigned int sep = (*part).find(':');
+ std::string hour = (*part).substr(0, sep );
+ if ( sep == (*part).npos )
+ {
+ esyslog("Live: Error parsing time '%s'", (*part).c_str() );
+ continue;
+ }
+ std::string min = (*part).substr(sep+1, (*part).npos );
+ offsets.push_back( lexical_cast<time_t>( hour )*60*60 + lexical_cast<time_t>( min ) *60 );
+ }
+ catch ( const bad_lexical_cast & ) {
+ esyslog("Live: Error parsing time '%s'", part->c_str() );
+ };
+ };
+ // add the time of the farourites to the time list
+ for (int i=0; i< MAX_DAYS ; i++ )
+ {
+ vector< time_t >::const_iterator offset = offsets.begin();
+ for ( ; offset != offsets.end(); ++offset )
+ {
+ times_start.push_back( midnight + 24*3600*i + *offset );
+ }
+ }
+ // add now
+ times_start.push_back( now );
+ // sort the times
+ std::sort( times_start.begin(), times_start.end() );
+ // delete every time which has already passed
+ while ( *times_start.begin()< now )
+ times_start.erase(times_start.begin() );
+
+ // build the corresponding names
+ for ( vector< time_t >::const_iterator start = times_start.begin();
+ start != times_start.end(); ++start )
+ {
+ times_names.push_back(FormatDateTime( tr("%A, %x"), *start)
+ +std::string(" ")+ FormatDateTime( tr("%I:%M %p"), *start) );
+ }
+ // the first time is now
+ times_names[0]=tr("Now");
+
if ( time_para >= times_names.size() )
time_para = times_names.size()-1;
time_selected=time_para;
@@ -147,15 +257,28 @@ pageTitle = trVDR("Schedule");
time_t now = time(NULL);
if ( time_para >= times_start.size() )
time_para = times_start.size()-1;
- time_t sched_start = times_start[ time_para ];
- time_t sched_end = sched_start + 60 * 60 * MAX_HOURS;
+ time_t sched_start = (times_start[ time_para ]/300)*300;
+ time_t max_hours;
+ try {
+ max_hours = lexical_cast<time_t>( LiveSetup().GetScheduleDuration() );
+ }
+ catch ( const bad_lexical_cast & )
+ {
+ esyslog("Live: could not convert '%s' into a schedule duration", LiveSetup().GetScheduleDuration().c_str());
+ max_hours = 8;
+ };
+ if (max_hours > 48)
+ max_hours = 48;
+
+ time_t sched_end = sched_start + 60 * 60 * max_hours;
int sched_end_row = ( sched_end - sched_start ) / 60 / MINUTES_PER_ROW;
std::list<SchedEntry> table[MAX_CHANNELS];
- string channel_names[ MAX_CHANNELS];
+ std::vector<std::string> channel_names(channel_groups_numbers[ channel ].size() );
+ std::vector<tChannelID> channel_IDs(channel_groups_numbers[ channel ].size() );
if ( channel >= channel_groups_numbers.size() )
channel = channel_groups_numbers.size()-1;
//for ( int chan = 0; chan<MAX_CHANNELS; chan++)
- for ( int j = 0; j<MAX_CHANNELS; j++)
+ for ( unsigned int j = 0; j<channel_groups_numbers[ channel ].size(); j++)
{
int prev_row = -1;
@@ -168,6 +291,7 @@ pageTitle = trVDR("Schedule");
if ( Channel->GroupSep() || Channel->Name() == '\0' )
continue;
channel_names[ j ] = Channel->Name();
+ channel_IDs[ j ] = Channel->GetChannelID();
cSchedule const* Schedule = schedules->GetSchedule( Channel );
if ( ! Schedule )
@@ -210,6 +334,8 @@ pageTitle = trVDR("Schedule");
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 )
@@ -245,10 +371,13 @@ pageTitle = trVDR("Schedule");
<td > <div class="boxheader"> <div><div><$ tr("Time") $></div></div> </div></td>
<td class="time spacer"> &nbsp; </td>
<%cpp>
- for ( int channel = 0; channel< MAX_CHANNELS ; channel++)
+ for ( unsigned int channel = 0; channel< channel_names.size() ; channel++)
{
</%cpp>
- <td> <div class="boxheader"> <div> <div><$ StringEscapeAndBreak(channel_names[channel]) $> </div></div> </div></td>
+ <td> <div class="boxheader"> <div> <div><$ StringEscapeAndBreak(channel_names[channel]) $>
+ <& pageelems.ajax_action_href action="switch_channel" tip=(tr("Switch to this channel.")) param=(channel_IDs[channel]) image="zap.png" alt="" &>
+ <& pageelems.vlc_stream_channel channelId=(channel_IDs[channel]) &>
+ </div></div> </div></td>
<td class="time spacer"> &nbsp; </td>
<%cpp>
}
@@ -263,7 +392,7 @@ pageTitle = trVDR("Schedule");
{
int minutes= ( (sched_start + row * 60 * MINUTES_PER_ROW ) % 3600 ) / 60;
string row_class;
- if ( minutes == 0 )
+ if ( minutes < MINUTES_PER_ROW )
{
// full hour, swap odd/even
odd = !odd;
@@ -279,7 +408,7 @@ pageTitle = trVDR("Schedule");
<tr class=" <$ row_class $>">
<td class=" time leftcol ">
<%cpp>
- if ( minutes == 0 )
+ if ( minutes < MINUTES_PER_ROW )
{
</%cpp>
<$ FormatDateTime( tr("%I:%M %p"), sched_start + row * 60 * MINUTES_PER_ROW ) $>
diff --git a/pages/setup.ecpp b/pages/setup.ecpp
index 8956c83..7279ad0 100644
--- a/pages/setup.ecpp
+++ b/pages/setup.ecpp
@@ -16,6 +16,8 @@ using namespace std;
string login;
string pass;
string times;
+ string channelGroups;
+ string scheduleDuration;
string startscreen;
string theme;
string localnetmask;
@@ -58,6 +60,8 @@ if (!cUser::CurrentUserHasRightTo(UR_EDITSETUP))
LiveSetup().CheckLocalNet(request.getPeerIp());
}
LiveSetup().SetTimes(times);
+ LiveSetup().SetChannelGroups(channelGroups);
+ LiveSetup().SetScheduleDuration(scheduleDuration);
LiveSetup().SetStartScreen(startscreen);
LiveSetup().SetTheme(theme);
LiveSetup().SetShowLogo(!showLogo.empty());
@@ -85,6 +89,8 @@ if (!cUser::CurrentUserHasRightTo(UR_EDITSETUP))
login = LiveSetup().GetAdminLogin();
useauth = LiveSetup().GetUseAuth();
times = LiveSetup().GetTimes();
+ channelGroups = LiveSetup().GetChannelGroups();
+ scheduleDuration = LiveSetup().GetScheduleDuration();
startscreen = LiveSetup().GetStartScreen();
theme = LiveSetup().GetTheme();
localnetmask = LiveSetup().GetLocalNetMask();
@@ -227,6 +233,16 @@ if (!cUser::CurrentUserHasRightTo(UR_EDITSETUP))
<& tooltip.help text=(tr("Format is HH:MM. Separate multiple times with a semicolon")) &></td>
</tr>
<tr>
+ <td class="label leftcol"><div class="withmargin"><$ tr("Channel groups for MultiSchedule") $>:</div></td>
+ <td class="rightcol"><input type="text" name="channelGroups" value="<$ channelGroups $>" id="channelGroups" />
+ <& tooltip.help text=(tr("Separate channels with a comma ',', separate groups with a semi-colon ';'")) &></td>
+ </tr>
+ <tr>
+ <td class="label leftcol"><div class="withmargin"><$ tr("Duration of MultiSchedule in hours") $>:</div></td>
+ <td class="rightcol"><input type="text" name="scheduleDuration" value="<$ scheduleDuration $>" id="scheduleDuration" />
+ </td>
+ </tr>
+ <tr>
<td class="label leftcol"><div class="withmargin"><$ tr("Show channels without EPG") $>:</div></td>
<td class="rightcol">
<input type="checkbox" name="showChannelsWithoutEPG" id="showChannelsWithoutEPG" value="1" <%cpp> CHECKIF(!showChannelsWithoutEPG.empty()); </%cpp>/>
@@ -239,6 +255,7 @@ if (!cUser::CurrentUserHasRightTo(UR_EDITSETUP))
<option value="whatsonnow" <%cpp> SELECTIF(startscreen == "whatsonnow") </%cpp>><$ trVDR("What's on now?") $></option>
<option value="whatsonnext" <%cpp> SELECTIF(startscreen == "whatsonnext") </%cpp>><$ trVDR("What's on next?") $></option>
<option value="schedule" <%cpp> SELECTIF(startscreen == "schedule") </%cpp>><$ trVDR("Schedule") $></option>
+ <option value="multischedule" <%cpp> SELECTIF(startscreen == "multischedule") </%cpp>><$ trVDR("MultiSchedule") $></option>
<option value="recordings" <%cpp> SELECTIF(startscreen == "recordings") </%cpp>><$ trVDR("Recordings") $></option>
<option value="timers" <%cpp> SELECTIF(startscreen == "timers") </%cpp>><$ trVDR("Timers") $></option>
</select></td>
diff --git a/setup.cpp b/setup.cpp
index 11ee6c5..5737378 100644
--- a/setup.cpp
+++ b/setup.cpp
@@ -36,6 +36,8 @@ Setup::Setup():
m_screenshotInterval( 1000 ),
m_useAuth( 1 ),
m_adminLogin("admin"),
+ m_channelGroups( "" ),
+ m_scheduleDuration( "8" ),
m_theme("marine"),
m_lastwhatsonlistmode("detail"),
m_tntnetloglevel("WARN"),
@@ -120,6 +122,8 @@ bool Setup::ParseSetupEntry( char const* name, char const* 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 ) m_theme = value;
else if ( strcmp( name, "LocalNetMask" ) == 0 ) { m_localnetmask = value; }
@@ -223,6 +227,8 @@ std::string const Setup::GetStartScreenLink() const
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")
@@ -284,6 +290,8 @@ bool Setup::SaveSetup()
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());
diff --git a/setup.h b/setup.h
index 498540e..a22051e 100644
--- a/setup.h
+++ b/setup.h
@@ -44,6 +44,8 @@ class Setup
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; }
@@ -68,6 +70,8 @@ class Setup
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; }
void SetLocalNetMask(std::string const & localnetmask) { m_localnetmask = localnetmask; }
@@ -119,6 +123,8 @@ class Setup
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_localnetmask;