diff options
author | Martin Schirrmacher <root@suffball.ath.cx> | 2013-04-11 13:25:51 +0200 |
---|---|---|
committer | Martin Schirrmacher <root@suffball.ath.cx> | 2013-04-11 13:25:51 +0200 |
commit | 4762c54a64e6390559dc12cc590d7095fac79795 (patch) | |
tree | 18460287e79628eb303f45f69971ab84d0c1c238 /osdmenu.c | |
download | vdr-plugin-neutrinoepg-4762c54a64e6390559dc12cc590d7095fac79795.tar.gz vdr-plugin-neutrinoepg-4762c54a64e6390559dc12cc590d7095fac79795.tar.bz2 |
initial commit
Diffstat (limited to 'osdmenu.c')
-rw-r--r-- | osdmenu.c | 718 |
1 files changed, 718 insertions, 0 deletions
diff --git a/osdmenu.c b/osdmenu.c new file mode 100644 index 0000000..ece1cdd --- /dev/null +++ b/osdmenu.c @@ -0,0 +1,718 @@ +#include "osdmenu.h" +#include "osditem.h" +#include "menuevent.h" + +time_t t; + +int MaxGroup; +int *CurrentGroupChannel; +int *FirstGroupChannel; +int *LastGroupChannel; + +int ChannelsShown; +int ChannelsBefore; +int ChannelsAfter; + +myOsdMenu::myOsdMenu() : cOsdMenu("") +{ + jumpto = false; + + if( Setup.UseSmallFont == 2 ) + { + if(showchannelnumbers) + cOsdMenu::SetCols(1, CHNUMWIDTH + 1, ChannelNameWidth, 5); + else + cOsdMenu::SetCols(1, ChannelNameWidth, 5); + } + else + { + if(showchannelnumbers) + cOsdMenu::SetCols(1, CHNUMWIDTH + 1, ChannelNameWidth, 6); + else + cOsdMenu::SetCols(1, ChannelNameWidth, 6); + } + + t = time(NULL); + next = false; + + // test how many OsdItems shown on display + // add 50 items, make a PageDown and look what item is the current + ChannelsShown = 0; + char buf[20]=""; + for(int i = 0; i < 50; i++) + { + strcpy(buf, (const char *)itoa(i)); + if( i == 0 ) + Add(new cOsdItem(buf), true); + else + Add(new cOsdItem(buf), false); + } + Display(); + + PageDown(); + cOsdItem *tItem = Get(Current()); + ChannelsShown = atoi((const char *)tItem->Text()); + Clear(); + + // how many items are before and after the middle item + if( (ChannelsShown % 2) != 0 ) + { + ChannelsBefore = (ChannelsShown / 2); + ChannelsAfter = (ChannelsShown / 2); + } + else + { + ChannelsBefore = (ChannelsShown / 2); + ChannelsAfter = (ChannelsShown / 2)-1; + } + + // what is the current watching channel? + int CurrentChannelNr = cDevice::CurrentChannel(); + cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr); + // what is the current channel & group? + CurrentGroup = GetGroupFromChannel( CurrentChannel->Index() ); + CurrentGroupChannel[CurrentGroup] = CurrentChannel->Index(); + + for( int Group = 0; Group < MaxGroup; Group++) + { + if( CurrentGroupChannel[Group] == -1 ) + { + CurrentGroupChannel[Group] = GetFirstChannelOfGroup(Group); + syslog(LOG_ERR, "neutrinoepg: Group: %d CurrentGroupChannel: %d", Group, CurrentGroupChannel[Group]); + } + if( FirstGroupChannel[Group] == -1 ) + { + FirstGroupChannel[Group] = GetFirstChannelOfGroup(Group); + syslog(LOG_ERR, "neutrinoepg: Group: %d FirstGroupChannel: %d", Group, FirstGroupChannel[Group]); + } + if( LastGroupChannel[Group] == -1 ) + { + LastGroupChannel[Group] = GetLastChannelOfGroup(Group); + syslog(LOG_ERR, "neutrinoepg: Group: %d LastGroupChannel: %d", Group, LastGroupChannel[Group]); + } + } + + LoadSchedules(0); +} + +myOsdMenu::~myOsdMenu() +{ +} + +int myOsdMenu::GetGroupIndex(int Group) +{ + if( FirstChannelsHasGroup() == false && Group == 0) + return -1; + + if( FirstChannelsHasGroup() == false ) + Group--; + + int GroupIndex = -1; + GroupIndex = GetFirstGroupIndex(); + while( Group-- ) + GroupIndex = Channels.GetNextGroup(GroupIndex); + + return GroupIndex; +} +int myOsdMenu::GetGroupByGroupIndex(int GroupIndex) +{ + if( ChannelsHasGroup() == false || GroupIndex == -1 ) + return 0; + + int GroupIndexSearch = GetFirstGroupIndex(); + + int Group = 0; + for(; GroupIndexSearch != GroupIndex && GroupIndexSearch != -1; Group++) + GroupIndexSearch = Channels.GetNextGroup(GroupIndexSearch); + if( FirstChannelsHasGroup() == false ) + return Group+1; + return Group; +} +int myOsdMenu::GetGroupFromChannel(int ChanIndex) +{ + int GroupIndex = Channels.GetPrevGroup(ChanIndex); + if( GroupIndex == -1 ) + return 0; + return GetGroupByGroupIndex( GroupIndex ); +} + +int myOsdMenu::GetLastGroupIndex(void) +{ + cChannel *Channel = Channels.Last(); + return Channels.GetPrevGroup( Channel->Index() ); +} + +int myOsdMenu::GetFirstGroupIndex(void) +{ + cChannel *Channel = Channels.First(); + if( Channel->GroupSep() ) + return Channel->Index(); + return Channels.GetNextGroup( Channel->Index() ); +} + +int myOsdMenu::GetFirstChannelOfGroup(int Group) +{ + if( ChannelsHasGroup() == false ) + return Channels.First()->Index(); + + return GetNextChannel( GetGroupIndex(Group) ); +} + +int myOsdMenu::GetLastChannelOfGroup(int Group) +{ + int NextGroup = Channels.GetNextGroup( GetGroupIndex(Group) ); + // next group -> get prev channel of next group + if( NextGroup != -1 ) + return GetPrevChannel(NextGroup); + else // no next group -> get last channel + return Channels.Last()->Index(); +} + +int myOsdMenu::GetNextChannel(int ChanIndex) +{ + cChannel *Channel; + Channel = Channels.Get( Channels.GetNextNormal(ChanIndex) ); + if( Channel == NULL ) + return -1; + do + { + bool isRadio = ( (!Channel->Vpid()) && (Channel->Apid(0)) ) ? true : false; + if( !(isRadio && hideradiochannels) && !(Channel->Ca() && hideencryptedchannels) ) + break; + } while( (Channel = Channels.Get( Channels.GetNextNormal( Channel->Index() ))) != NULL ); + + if( Channel == NULL ) + return -1; + + return Channel->Index(); +} +int myOsdMenu::GetPrevChannel(int ChanIndex) +{ + cChannel *Channel; + Channel = Channels.Get( Channels.GetPrevNormal(ChanIndex) ); + if( Channel == NULL ) + return -1; + do + { + bool isRadio = ( (!Channel->Vpid()) && (Channel->Apid(0)) ) ? true : false; + if( !(isRadio && hideradiochannels) && !(Channel->Ca() && hideencryptedchannels) ) + break; + } while( (Channel = Channels.Get( Channels.GetPrevNormal( Channel->Index() ))) != NULL ); + + if( Channel == NULL ) + return -1; + + return Channel->Index(); +} + +bool myOsdMenu::isChannelInGroup(int ChanIndex, int Group) +{ + if( ChannelsHasGroup() == false ) + return true; + + int ChanGroup = GetGroupFromChannel(ChanIndex); + return Group == ChanGroup ? true : false; +} + +bool myOsdMenu::ChannelsHasGroup(void) +{ + cChannel *Channel = Channels.First(); + if( Channel->GroupSep() ) + return true; + int Group = Channels.GetNextGroup(Channel->Index()); + return Group != -1 ? true : false; +} + +bool myOsdMenu::FirstChannelsHasGroup(void) +{ + cChannel *Channel = Channels.First(); + if( Channel->GroupSep() ) + return true; + return false; +} + +void myOsdMenu::LoadSchedules(int shift) +{ + t += shift * Step * 60; + + // clar all items + Clear(); + + schedules = cSchedules::Schedules(schedulesLock); + for( cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel) ) + { + // is filtered by config? + bool isRadio = ( (!Channel->Vpid()) && (Channel->Apid(0)) ) ? true : false; + if( (isRadio && hideradiochannels) || (Channel->Ca() && hideencryptedchannels) ) + continue; + + // only channels! + if( Channel->GroupSep() ) + continue; + + // only channels of the current Group + if( !isChannelInGroup( Channel->Index(), CurrentGroup ) ) + continue; + + // Hack to show the current channel in the middle of the screen + // so do not show channels before + // do it only if the settings middlemenuentry is set + + // only if channels in group > channels shown on display + if( (LastGroupChannel[CurrentGroup] - FirstGroupChannel[CurrentGroup]) > ChannelsShown && middlemenuentry) + { + // at the beginning + if( (CurrentGroupChannel[CurrentGroup] - FirstGroupChannel[CurrentGroup]) < ChannelsBefore ) + { + if( (Channel->Index() - FirstGroupChannel[CurrentGroup]) >= ChannelsShown ) + continue; + } + else + { + // in the middle + // don't show channels from the beginning + if( Channel->Index() < CurrentGroupChannel[CurrentGroup] ) + { + if( (CurrentGroupChannel[CurrentGroup] - Channel->Index()) > ChannelsBefore ) + continue; + } + // don't show channels from the end + if( Channel->Index() > CurrentGroupChannel[CurrentGroup] ) + { + if( (Channel->Index() - CurrentGroupChannel[CurrentGroup]) > ChannelsAfter ) + continue; + } + } + if( (LastGroupChannel[CurrentGroup] - CurrentGroupChannel[CurrentGroup]) < ChannelsAfter && + (Channel->Index() - LastGroupChannel[CurrentGroup]) >= ChannelsShown ) + continue; + } + + const cSchedule *Schedule = schedules->GetSchedule( Channel->GetChannelID() ); + if(Schedule) + { + // event from now or any other date (next) + const cEvent *Event = next ? Schedule->GetEventAround(t) : Schedule->GetPresentEvent(); + Add(new myOsdItem(Event, Channel, next), Channel->Index() == CurrentGroupChannel[CurrentGroup] ); + } + else + Add(new myOsdItem(NULL, Channel, next), Channel->Index() == CurrentGroupChannel[CurrentGroup] ); + } + + sprintf(tmp, "%d:%d", bookmark / 100, bookmark % 100); + + SetMyTitle(); + +// if( switchwithok ) +// SetHelp(next ? trVDR("Button$Now") : NULL, "<<", ">>", trVDR("Button$Info") ); +// else + + if( next ) + SetHelp(trVDR("Button$Now"), "<<", ">>", switchwithok ? trVDR("Button$Info") : trVDR("Button$Switch")); + else + SetHelp(bookmark ? tmp : NULL, "<<", ">>", switchwithok ? trVDR("Button$Info") : trVDR("Button$Switch")); + + Display(); +} + +void myOsdMenu::SetMyTitle(void) +{ + char *buffer = NULL; + + if( CurrentGroup == 0 && FirstChannelsHasGroup() == false ) + { + if( next ) + asprintf(&buffer, "%d/%d %s - %s", + CurrentGroup + 1, MaxGroup, tr("without group"), *DayDateTime(t)); + else + asprintf(&buffer, "%d/%d %s - %s", + CurrentGroup + 1, MaxGroup, tr("without group"), trVDR("What's on now?")); + } else + { + if( next ) + asprintf(&buffer, "%d/%d %s - %s", + CurrentGroup + 1, MaxGroup, Channels.Get( GetGroupIndex(CurrentGroup) )->Name(), *DayDateTime(t)); + else + asprintf(&buffer, "%d/%d %s - %s", + CurrentGroup + 1, MaxGroup, Channels.Get( GetGroupIndex(CurrentGroup) )->Name(), trVDR("What's on now?")); + } + SetTitle(buffer); + free(buffer); +} +eOSState myOsdMenu::Switch() +{ + myOsdItem *item = (myOsdItem *)Get(Current()); + if(item) + { + const cChannel *channel = item->channel; + if(channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true) ) + return keeposd ? osContinue : osEnd; + } + Skins.Message(mtError, trVDR("Can't switch channel!")); + return osContinue; +} + +void myOsdMenu::GoToDay(int day) +{ + struct tm tm1, tm2; + time_t tmp_t = time(NULL); + + localtime_r(&t, &tm1); + localtime_r(&tmp_t, &tm2); + tm2.tm_hour = tm1.tm_hour; + tm2.tm_min = tm1.tm_min; + tm2.tm_mday += day; + + t = mktime(&tm2); + + next = true; + LoadSchedules(0); +} + +void myOsdMenu::JumpTo(int hour, int min) +{ + struct tm tmp_tm; + localtime_r(&t, &tmp_tm); + + if(tmp_tm.tm_hour > hour || tmp_tm.tm_min > min && tmp_tm.tm_hour >= hour) + tmp_tm.tm_mday++; + + tmp_tm.tm_hour = hour; + tmp_tm.tm_min = min; + + t = mktime(&tmp_tm); + + next = true; + LoadSchedules(0); +} + +eOSState myOsdMenu::ProcessKey(eKeys Key) +{ + eOSState state; + + if(jumpto) + { + switch(Key) + { + case k0...k9: + { + int number = Key-k0; + switch(index) + { + // first digit + case 0: + if(number <= 2) + { + hh = number * 10; + sprintf(tmp,"%s: %d-:--",tr("Jump to"),number); + index++; + } + break; + // second digit + case 1: + if(hh <= 10 || hh == 20 && number <= 3) + { + hh += number; + sprintf(tmp,"%s: %02d:--",tr("Jump to"),hh); + index++; + } + break; + // third digit + case 2: + if(number <= 5) + { + mm = number * 10; + sprintf(tmp,"%s: %02d:%d-",tr("Jump to"),hh,number); + index++; + } + break; + // fourth digit + case 3: + mm += number; + sprintf(tmp,"%s: %02d:%02d",tr("Jump to"),hh,mm); + index++; + break; + default: + break; + } + if(index == 4) + { + JumpTo(hh, mm); + jumpto = 0; + } + else + { + SetTitle(tmp); + Display(); + } + break; + } + case kOk: + JumpTo(hh, mm); + jumpto = 0; + break; + case kBack: + jumpto = 0; + SetMyTitle(); + Display(); + break; + default: + break; + } + state = osContinue; + } + else + { + state = cOsdMenu::ProcessKey(Key); + + if(state == osUnknown) + { + switch(Key) + { + case k1...k7: + GoToDay(Key-k0); + break; + // toggle asking for a time to jump to + case k0: + hh = mm = index =0; + sprintf(tmp, "%s: --:--",tr("Jump to")); + SetTitle(tmp); + Display(); + jumpto = 1; + break; + case kRed: + if( next ) + { + next = false; + t = time(NULL); + LoadSchedules(0); + } else + { + if( bookmark ) + JumpTo(bookmark/100,bookmark%100); + } + break; + case kGreen: + next = true; + LoadSchedules(-1); + break; + case kYellow: + next = true; + LoadSchedules(1); + break; + case kBlue: + if(switchwithok) + { + if( Count() ) + return AddSubMenu(new myMenuEvent((myOsdItem*) Get(Current()))); + } else + { + if( next ) + { + next = false; + t = time(NULL); + LoadSchedules(0); + } + else + return Switch(); + } + break; + case kOk: + if(switchwithok) + { + return Switch(); + } else + { + if(Count()) + return AddSubMenu(new myMenuEvent((myOsdItem*)Get(Current()))); + } + case kNext: + if( isMenuEvent ) + return osContinue; + // if we switch channel groups with next/prev key do it + if( switchgroupkey == 1 ) + { + CurrentGroup++; + if( CurrentGroup >= MaxGroup ) + CurrentGroup = 0; + LoadSchedules(0); + } else // we do a page down + { + if( CurrentGroupChannel[CurrentGroup] == LastGroupChannel[CurrentGroup] ) + { + CurrentGroupChannel[CurrentGroup] = FirstGroupChannel[CurrentGroup]; + } else + { + for(int i = 0; i < ChannelsShown; i++) + { + CurrentGroupChannel[CurrentGroup] = GetNextChannel( CurrentGroupChannel[CurrentGroup] ); + if( CurrentGroupChannel[CurrentGroup] == -1 ) + break; + } + if( CurrentGroupChannel[CurrentGroup] > LastGroupChannel[CurrentGroup] || CurrentGroupChannel[CurrentGroup] == -1 ) + { + CurrentGroupChannel[CurrentGroup] = LastGroupChannel[CurrentGroup]; + } + } + + if( !middlemenuentry ) // if middlemenuentry hack is not set we can use vdr function for page down + PageDown(); + else // otherwise we must do a page down by our own + { + LoadSchedules(0); + } + } + return osContinue; + case kPrev: + if( isMenuEvent ) + return osContinue; + // if we switch channel groups with next/prev key do it + if( switchgroupkey == 1 ) + { + CurrentGroup--; + if( CurrentGroup < 0 ) + CurrentGroup = MaxGroup-1; + LoadSchedules(0); + } else // we do a page up + { + if( CurrentGroupChannel[CurrentGroup] == FirstGroupChannel[CurrentGroup] ) + { + CurrentGroupChannel[CurrentGroup] = LastGroupChannel[CurrentGroup]; + } else + { + for(int i = 0; i < ChannelsShown; i++) + { + CurrentGroupChannel[CurrentGroup] = GetPrevChannel( CurrentGroupChannel[CurrentGroup] ); + } + if( CurrentGroupChannel[CurrentGroup] < FirstGroupChannel[CurrentGroup] ) + { + CurrentGroupChannel[CurrentGroup] = FirstGroupChannel[CurrentGroup]; + } + } + + if( !middlemenuentry ) // if middlemenuentry hack is not set we can use vdr function for page up + PageUp(); + else // otherwise we must do a page down by our own + { + LoadSchedules(0); + } + } + return osContinue; + default: + break; + } + } else + { + switch((int)Key) + { + case kUp|k_Repeat: + case kUp: + { + if( isMenuEvent ) + return osContinue; + + CurrentGroupChannel[CurrentGroup] = GetPrevChannel( CurrentGroupChannel[CurrentGroup] ); + if( CurrentGroupChannel[CurrentGroup] < FirstGroupChannel[CurrentGroup] ) + CurrentGroupChannel[CurrentGroup] = LastGroupChannel[CurrentGroup]; + + if( !middlemenuentry ) // if middlemenuentry hack is not set we can let vdr kUp + return osContinue; + + LoadSchedules(0); + return osContinue; + } + case kDown|k_Repeat: + case kDown: + { + if( isMenuEvent ) + return osContinue; + + CurrentGroupChannel[CurrentGroup] = GetNextChannel( CurrentGroupChannel[CurrentGroup] ); + if( CurrentGroupChannel[CurrentGroup] > LastGroupChannel[CurrentGroup] || CurrentGroupChannel[CurrentGroup] == -1 ) + CurrentGroupChannel[CurrentGroup] = FirstGroupChannel[CurrentGroup]; + + if( !middlemenuentry ) // if middlemenuentry hack is not set we can let vdr kDown + return osContinue; + + LoadSchedules(0); + return osContinue; + } + case kLeft|k_Repeat: + case kLeft: + if( switchgroupkey == 1 ) // if we not switch groups by left/right we let do vdr the rest (page up) + { + if( CurrentGroupChannel[CurrentGroup] == FirstGroupChannel[CurrentGroup] ) + { + CurrentGroupChannel[CurrentGroup] = LastGroupChannel[CurrentGroup]; + } else + { + for(int i = 0; i < ChannelsShown; i++) + { + CurrentGroupChannel[CurrentGroup] = GetPrevChannel( CurrentGroupChannel[CurrentGroup] ); + } + if( CurrentGroupChannel[CurrentGroup] < FirstGroupChannel[CurrentGroup] ) + { + CurrentGroupChannel[CurrentGroup] = FirstGroupChannel[CurrentGroup]; + } + } + + //syslog(LOG_ERR, "neutrinoepg: left after Group: %d Channel: %d", CurrentGroup, CurrentGroupChannel[CurrentGroup]); + + if( middlemenuentry ) // if middlemenuentry hack is set do own page up + { + LoadSchedules(0); + break; + } + + return osContinue; + } + // otherwise we switch the group to the left + CurrentGroup--; + if( CurrentGroup < 0 ) + CurrentGroup = MaxGroup-1; + LoadSchedules(0); + break; + case kRight|k_Repeat: + case kRight: + if( switchgroupkey == 1 ) // if we not switch groups by left/right we let do vdr the rest (page down) + { + if( CurrentGroupChannel[CurrentGroup] == LastGroupChannel[CurrentGroup] ) + { + CurrentGroupChannel[CurrentGroup] = FirstGroupChannel[CurrentGroup]; + } else + { + for(int i = 0; i < ChannelsShown; i++) + { + CurrentGroupChannel[CurrentGroup] = GetNextChannel( CurrentGroupChannel[CurrentGroup] ); + if( CurrentGroupChannel[CurrentGroup] == -1 ) + break; + } + if( CurrentGroupChannel[CurrentGroup] > LastGroupChannel[CurrentGroup] || CurrentGroupChannel[CurrentGroup] == -1 ) + { + CurrentGroupChannel[CurrentGroup] = LastGroupChannel[CurrentGroup]; + } + } + + if( middlemenuentry ) // if middlemenuentry hack is set do manuel page up + { + LoadSchedules(0); + break; + } + + return osContinue; + } + + // otherwise we switch the group to the right + CurrentGroup++; + if( CurrentGroup >= MaxGroup ) + CurrentGroup = 0; + LoadSchedules(0); + break; + default: + break; + } + + } + } + return state; +} |