mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
- Added new entries to 'ca.conf'. - Fixed closing unused PID handles (thanks to Stefan Schluenss for reporting this one). - Added more examples to 'diseqc.conf' (thanks to Oliver Endriss). - Fixed disabling multiple recordings on a single DVB card (comment out the definition of the macros DO_REC_AND_PLAY_ON_PRIMARY_DEVICE and DO_MULTIPLE_RECORDINGS in dvbdevice.c). - Plugins can now have their very own OSD setup in the object they return from a call to cPlugin::MainMenuAction(). In order to implement this, the return type of cPlugin::MainMenuAction() had to be changed from (cOsdMenu *) to (cOsdObject *). So in case you are compiling an existing plugin with this version of VDR and you get an error message, simply change cOsdMenu to cOsdObject in the plugin's source for the MainMenuAction() function. Plugin authors who have so far (ab)used the cControl mechanism to implement their own raw OSD should take a look at the new demo plugin 'osddemo'. It implements a very primitive game that shows how a plugin can have its own raw OSD. Especially look into cLineGame and see how it implements the Show() function. See also the chapter on "User interaction" in PLUGINS.html. - Added three new fields to the lines in 'channels.conf': NID, TID and RID. NID and TID are the Network and Transport Stream IDs, respectively. RID is an additional ID that can be used to tell apart channels that would otherwise be indistinguishable. This is typically the case with radio channels, which may have the same NID, TID and SID, but different "radio IDs". This new field is therefore called RID ("radio ID"). Currently NID and TID are not yet used by VDR and should always be 0. The RID is actually used when building the "unique channel ID", so if you have channels in your 'channels.conf' file that cause error messages when loading, you can set the RIDs of these channels to different values. When reading an old 'channels.conf' these new fields will be automatically initialized to 0 and once the file is written back to disk they will be appended to the channel definitions. Thanks to Régis Bossut for pointing out that with some providers the channels can only be distinguished through the RID. - The "unique channel ID" now contains an optional 5th part (the RID). See man vdr(5). - Updated 'channels.conf.cable' and made some channels unique using the new RID (thanks to Andreas Kool for pointing out the problems). - Made some channels unique in 'channels.conf.terr' using the new RID. - Extended the '-l' option to allow logging to LOG_LOCALn (n=0..7) by writing, for instance, '-l 3.7' (suggested by Jürgen Schmidt). - Now deleting stale lock files if they have a time stamp that is outside the window 'now +/- LOCKFILESTALETIME'. This improves things in cases where the system time makes far jumps, so that a lock file might end up with a time stamp that lies in the distant future (thanks to Oliver Endriss).
655 lines
15 KiB
C
655 lines
15 KiB
C
/*
|
|
* osd.c: Abstract On Screen Display layer
|
|
*
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
* how to reach the author.
|
|
*
|
|
* $Id: osd.c 1.38 2002/11/16 14:20:26 kls Exp $
|
|
*/
|
|
|
|
#include "osd.h"
|
|
#include <string.h>
|
|
#include "device.h"
|
|
#include "i18n.h"
|
|
#include "status.h"
|
|
|
|
// --- cOsd ------------------------------------------------------------------
|
|
|
|
#ifdef DEBUG_OSD
|
|
WINDOW *cOsd::window = NULL;
|
|
int cOsd::colorPairs[MaxColorPairs] = { 0 };
|
|
#else
|
|
cOsdBase *cOsd::osd = NULL;
|
|
#endif
|
|
int cOsd::cols = 0;
|
|
int cOsd::rows = 0;
|
|
|
|
void cOsd::Initialize(void)
|
|
{
|
|
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
|
|
initscr();
|
|
keypad(stdscr, true);
|
|
nonl();
|
|
cbreak();
|
|
noecho();
|
|
timeout(10);
|
|
#endif
|
|
#if defined(DEBUG_OSD)
|
|
start_color();
|
|
leaveok(stdscr, true);
|
|
#endif
|
|
}
|
|
|
|
void cOsd::Shutdown(void)
|
|
{
|
|
Close();
|
|
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
|
|
endwin();
|
|
#endif
|
|
}
|
|
|
|
#ifdef DEBUG_OSD
|
|
void cOsd::SetColor(eDvbColor colorFg, eDvbColor colorBg)
|
|
{
|
|
int color = (colorBg << 16) | colorFg | 0x80000000;
|
|
for (int i = 0; i < MaxColorPairs; i++) {
|
|
if (!colorPairs[i]) {
|
|
colorPairs[i] = color;
|
|
init_pair(i + 1, colorFg, colorBg);
|
|
wattrset(window, COLOR_PAIR(i + 1));
|
|
break;
|
|
}
|
|
else if (color == colorPairs[i]) {
|
|
wattrset(window, COLOR_PAIR(i + 1));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
cOsdBase *cOsd::OpenRaw(int x, int y)
|
|
{
|
|
#ifdef DEBUG_OSD
|
|
return NULL;
|
|
#else
|
|
return osd ? NULL : cDevice::PrimaryDevice()->NewOsd(x, y);
|
|
#endif
|
|
}
|
|
|
|
void cOsd::Open(int w, int h)
|
|
{
|
|
int d = (h < 0) ? Setup.OSDheight + h : 0;
|
|
h = abs(h);
|
|
cols = w;
|
|
rows = h;
|
|
#ifdef DEBUG_OSD
|
|
window = subwin(stdscr, h, w, d, (Setup.OSDwidth - w) / 2);
|
|
syncok(window, true);
|
|
#define B2C(b) (((b) * 1000) / 255)
|
|
#define SETCOLOR(n, r, g, b, o) init_color(n, B2C(r), B2C(g), B2C(b))
|
|
//XXX
|
|
SETCOLOR(clrBackground, 0x00, 0x00, 0x00, 127); // background 50% gray
|
|
SETCOLOR(clrBlack, 0x00, 0x00, 0x00, 255);
|
|
SETCOLOR(clrRed, 0xFC, 0x14, 0x14, 255);
|
|
SETCOLOR(clrGreen, 0x24, 0xFC, 0x24, 255);
|
|
SETCOLOR(clrYellow, 0xFC, 0xC0, 0x24, 255);
|
|
SETCOLOR(clrBlue, 0x00, 0x00, 0xFC, 255);
|
|
SETCOLOR(clrCyan, 0x00, 0xFC, 0xFC, 255);
|
|
SETCOLOR(clrMagenta, 0xB0, 0x00, 0xFC, 255);
|
|
SETCOLOR(clrWhite, 0xFC, 0xFC, 0xFC, 255);
|
|
#else
|
|
w *= charWidth;
|
|
h *= lineHeight;
|
|
d *= lineHeight;
|
|
int x = (720 - w + charWidth) / 2; //TODO PAL vs. NTSC???
|
|
int y = (576 - Setup.OSDheight * lineHeight) / 2 + d;
|
|
//XXX
|
|
osd = OpenRaw(x, y);
|
|
//XXX TODO this should be transferred to the places where the individual windows are requested (there's too much detailed knowledge here!)
|
|
if (h / lineHeight == 5) { //XXX channel display
|
|
osd->Create(0, 0, w, h, 4);
|
|
}
|
|
else if (h / lineHeight == 1) { //XXX info display
|
|
osd->Create(0, 0, w, h, 4);
|
|
}
|
|
else if (d == 0) { //XXX full menu
|
|
osd->Create(0, 0, w, lineHeight, 2);
|
|
osd->Create(0, lineHeight, w, (Setup.OSDheight - 3) * lineHeight, 2);
|
|
osd->AddColor(clrBackground);
|
|
osd->AddColor(clrCyan);
|
|
osd->AddColor(clrWhite);
|
|
osd->AddColor(clrBlack);
|
|
osd->Create(0, (Setup.OSDheight - 2) * lineHeight, w, 2 * lineHeight, 4);
|
|
}
|
|
else { //XXX progress display
|
|
/*XXX
|
|
osd->Create(0, 0, w, lineHeight, 1);
|
|
osd->Create(0, lineHeight, w, lineHeight, 2, false);
|
|
osd->Create(0, 2 * lineHeight, w, lineHeight, 1);
|
|
XXX*///XXX some pixels are not drawn correctly with lower bpp values
|
|
osd->Create(0, 0, w, h, 4);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void cOsd::Close(void)
|
|
{
|
|
#ifdef DEBUG_OSD
|
|
if (window) {
|
|
delwin(window);
|
|
window = 0;
|
|
}
|
|
#else
|
|
delete osd;
|
|
osd = NULL;
|
|
#endif
|
|
}
|
|
|
|
void cOsd::Clear(void)
|
|
{
|
|
#ifdef DEBUG_OSD
|
|
SetColor(clrBackground, clrBackground);
|
|
Fill(0, 0, cols, rows, clrBackground);
|
|
#else
|
|
osd->Clear();
|
|
#endif
|
|
}
|
|
|
|
void cOsd::Fill(int x, int y, int w, int h, eDvbColor color)
|
|
{
|
|
if (x < 0) x = cols + x;
|
|
if (y < 0) y = rows + y;
|
|
#ifdef DEBUG_OSD
|
|
SetColor(color, color);
|
|
for (int r = 0; r < h; r++) {
|
|
wmove(window, y + r, x); // ncurses wants 'y' before 'x'!
|
|
whline(window, ' ', w);
|
|
}
|
|
wsyncup(window); // shouldn't be necessary because of 'syncok()', but w/o it doesn't work
|
|
#else
|
|
osd->Fill(x * charWidth, y * lineHeight, (x + w) * charWidth - 1, (y + h) * lineHeight - 1, color);
|
|
#endif
|
|
}
|
|
|
|
void cOsd::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
|
{
|
|
#ifndef DEBUG_OSD
|
|
osd->SetBitmap(x, y, Bitmap);
|
|
#endif
|
|
}
|
|
|
|
void cOsd::ClrEol(int x, int y, eDvbColor color)
|
|
{
|
|
Fill(x, y, cols - x, 1, color);
|
|
}
|
|
|
|
int cOsd::CellWidth(void)
|
|
{
|
|
#ifdef DEBUG_OSD
|
|
return 1;
|
|
#else
|
|
return charWidth;
|
|
#endif
|
|
}
|
|
|
|
int cOsd::LineHeight(void)
|
|
{
|
|
#ifdef DEBUG_OSD
|
|
return 1;
|
|
#else
|
|
return lineHeight;
|
|
#endif
|
|
}
|
|
|
|
int cOsd::Width(unsigned char c)
|
|
{
|
|
#ifdef DEBUG_OSD
|
|
return 1;
|
|
#else
|
|
return osd->Width(c);
|
|
#endif
|
|
}
|
|
|
|
int cOsd::WidthInCells(const char *s)
|
|
{
|
|
#ifdef DEBUG_OSD
|
|
return strlen(s);
|
|
#else
|
|
return (osd->Width(s) + charWidth - 1) / charWidth;
|
|
#endif
|
|
}
|
|
|
|
eDvbFont cOsd::SetFont(eDvbFont Font)
|
|
{
|
|
#ifdef DEBUG_OSD
|
|
return Font;
|
|
#else
|
|
return osd->SetFont(Font);
|
|
#endif
|
|
}
|
|
|
|
void cOsd::Text(int x, int y, const char *s, eDvbColor colorFg, eDvbColor colorBg)
|
|
{
|
|
if (x < 0) x = cols + x;
|
|
if (y < 0) y = rows + y;
|
|
#ifdef DEBUG_OSD
|
|
SetColor(colorFg, colorBg);
|
|
wmove(window, y, x); // ncurses wants 'y' before 'x'!
|
|
waddnstr(window, s, cols - x);
|
|
#else
|
|
osd->Text(x * charWidth, y * lineHeight, s, colorFg, colorBg);
|
|
#endif
|
|
}
|
|
|
|
void cOsd::Flush(void)
|
|
{
|
|
#ifdef DEBUG_OSD
|
|
refresh();
|
|
#else
|
|
if (osd)
|
|
osd->Flush();
|
|
#endif
|
|
}
|
|
|
|
// --- cOsdItem --------------------------------------------------------------
|
|
|
|
cOsdItem::cOsdItem(eOSState State)
|
|
{
|
|
text = NULL;
|
|
offset = -1;
|
|
state = State;
|
|
fresh = false;
|
|
userColor = false;
|
|
fgColor = clrWhite;
|
|
bgColor = clrBackground;
|
|
}
|
|
|
|
cOsdItem::cOsdItem(const char *Text, eOSState State)
|
|
{
|
|
text = NULL;
|
|
offset = -1;
|
|
state = State;
|
|
fresh = false;
|
|
userColor = false;
|
|
fgColor = clrWhite;
|
|
bgColor = clrBackground;
|
|
SetText(Text);
|
|
}
|
|
|
|
cOsdItem::~cOsdItem()
|
|
{
|
|
free(text);
|
|
}
|
|
|
|
void cOsdItem::SetText(const char *Text, bool Copy)
|
|
{
|
|
free(text);
|
|
text = Copy ? strdup(Text) : (char *)Text; // text assumes ownership!
|
|
}
|
|
|
|
void cOsdItem::SetColor(eDvbColor FgColor, eDvbColor BgColor)
|
|
{
|
|
userColor = true;
|
|
fgColor = FgColor;
|
|
bgColor = BgColor;
|
|
}
|
|
|
|
void cOsdItem::Display(int Offset, eDvbColor FgColor, eDvbColor BgColor)
|
|
{
|
|
if (Offset < 0) {
|
|
FgColor = clrBlack;
|
|
BgColor = clrCyan;
|
|
}
|
|
fresh |= Offset >= 0;
|
|
if (Offset >= 0)
|
|
offset = Offset;
|
|
if (offset >= 0)
|
|
Interface->WriteText(0, offset + 2, text, userColor ? fgColor : FgColor, userColor ? bgColor : BgColor);
|
|
}
|
|
|
|
eOSState cOsdItem::ProcessKey(eKeys Key)
|
|
{
|
|
return Key == kOk ? state : osUnknown;
|
|
}
|
|
|
|
// --- cOsdMenu --------------------------------------------------------------
|
|
|
|
cOsdMenu::cOsdMenu(const char *Title, int c0, int c1, int c2, int c3, int c4)
|
|
{
|
|
isMenu = true;
|
|
digit = 0;
|
|
hasHotkeys = false;
|
|
visible = false;
|
|
title = NULL;
|
|
SetTitle(Title);
|
|
cols[0] = c0;
|
|
cols[1] = c1;
|
|
cols[2] = c2;
|
|
cols[3] = c3;
|
|
cols[4] = c4;
|
|
first = 0;
|
|
current = marked = -1;
|
|
subMenu = NULL;
|
|
helpRed = helpGreen = helpYellow = helpBlue = NULL;
|
|
status = NULL;
|
|
Interface->Open();
|
|
}
|
|
|
|
cOsdMenu::~cOsdMenu()
|
|
{
|
|
free(title);
|
|
delete subMenu;
|
|
free(status);
|
|
Interface->Clear();
|
|
Interface->Close();
|
|
}
|
|
|
|
const char *cOsdMenu::hk(const char *s)
|
|
{
|
|
static char buffer[64];
|
|
if (s && hasHotkeys) {
|
|
if (digit == 0 && '1' <= *s && *s <= '9' && *(s + 1) == ' ')
|
|
digit = -1; // prevents automatic hotkeys - input already has them
|
|
if (digit >= 0) {
|
|
digit++;
|
|
snprintf(buffer, sizeof(buffer), " %c %s", (digit < 10) ? '0' + digit : ' ' , s);
|
|
s = buffer;
|
|
}
|
|
}
|
|
return s;
|
|
}
|
|
|
|
void cOsdMenu::SetHasHotkeys(void)
|
|
{
|
|
hasHotkeys = true;
|
|
digit = 0;
|
|
}
|
|
|
|
void cOsdMenu::SetStatus(const char *s)
|
|
{
|
|
free(status);
|
|
status = s ? strdup(s) : NULL;
|
|
if (visible)
|
|
Interface->Status(status);
|
|
}
|
|
|
|
void cOsdMenu::SetTitle(const char *Title, bool ShowDate)
|
|
{
|
|
free(title);
|
|
if (ShowDate)
|
|
asprintf(&title, "%s\t%s", Title, DayDateTime(time(NULL)));
|
|
else
|
|
title = strdup(Title);
|
|
}
|
|
|
|
void cOsdMenu::SetHelp(const char *Red, const char *Green, const char *Yellow, const char *Blue)
|
|
{
|
|
// strings are NOT copied - must be constants!!!
|
|
helpRed = Red;
|
|
helpGreen = Green;
|
|
helpYellow = Yellow;
|
|
helpBlue = Blue;
|
|
if (visible)
|
|
Interface->Help(helpRed, helpGreen, helpYellow, helpBlue);
|
|
}
|
|
|
|
void cOsdMenu::Del(int Index)
|
|
{
|
|
cList<cOsdItem>::Del(Get(Index));
|
|
if (current == Count())
|
|
current--;
|
|
if (Index == first && first > 0)
|
|
first--;
|
|
}
|
|
|
|
void cOsdMenu::Add(cOsdItem *Item, bool Current, cOsdItem *After)
|
|
{
|
|
cList<cOsdItem>::Add(Item, After);
|
|
if (Current)
|
|
current = Item->Index();
|
|
}
|
|
|
|
void cOsdMenu::Ins(cOsdItem *Item, bool Current, cOsdItem *Before)
|
|
{
|
|
cList<cOsdItem>::Ins(Item, Before);
|
|
if (Current)
|
|
current = Item->Index();
|
|
}
|
|
|
|
void cOsdMenu::Display(void)
|
|
{
|
|
if (subMenu) {
|
|
subMenu->Display();
|
|
return;
|
|
}
|
|
visible = true;
|
|
Interface->Clear();
|
|
Interface->SetCols(cols);
|
|
Interface->Title(title);
|
|
Interface->Help(helpRed, helpGreen, helpYellow, helpBlue);
|
|
int count = Count();
|
|
if (count > 0) {
|
|
if (current < 0)
|
|
current = 0; // just for safety - there HAS to be a current item!
|
|
int n = 0;
|
|
if (current - first >= MAXOSDITEMS) {
|
|
first = current - MAXOSDITEMS / 2;
|
|
if (first + MAXOSDITEMS > count)
|
|
first = count - MAXOSDITEMS;
|
|
if (first < 0)
|
|
first = 0;
|
|
}
|
|
for (int i = first; i < count; i++) {
|
|
cOsdItem *item = Get(i);
|
|
if (item) {
|
|
item->Display(i - first, i == current ? clrBlack : clrWhite, i == current ? clrCyan : clrBackground);
|
|
if (i == current)
|
|
cStatus::MsgOsdCurrentItem(item->Text());
|
|
}
|
|
if (++n == MAXOSDITEMS) //TODO get this from Interface!!!
|
|
break;
|
|
}
|
|
}
|
|
if (!isempty(status))
|
|
Interface->Status(status);
|
|
}
|
|
|
|
void cOsdMenu::SetCurrent(cOsdItem *Item)
|
|
{
|
|
current = Item ? Item->Index() : -1;
|
|
}
|
|
|
|
void cOsdMenu::RefreshCurrent(void)
|
|
{
|
|
cOsdItem *item = Get(current);
|
|
if (item)
|
|
item->Set();
|
|
}
|
|
|
|
void cOsdMenu::DisplayCurrent(bool Current)
|
|
{
|
|
cOsdItem *item = Get(current);
|
|
if (item) {
|
|
item->Display(current - first, Current ? clrBlack : clrWhite, Current ? clrCyan : clrBackground);
|
|
if (Current)
|
|
cStatus::MsgOsdCurrentItem(item->Text());
|
|
}
|
|
}
|
|
|
|
void cOsdMenu::Clear(void)
|
|
{
|
|
first = 0;
|
|
current = marked = -1;
|
|
cList<cOsdItem>::Clear();
|
|
}
|
|
|
|
bool cOsdMenu::SpecialItem(int idx)
|
|
{
|
|
cOsdItem *item = Get(idx);
|
|
return item && item->HasUserColor();
|
|
}
|
|
|
|
void cOsdMenu::CursorUp(void)
|
|
{
|
|
if (current > 0) {
|
|
int tmpCurrent = current;
|
|
while (--tmpCurrent >= 0 && SpecialItem(tmpCurrent));
|
|
if (tmpCurrent < 0)
|
|
return;
|
|
if (tmpCurrent >= first)
|
|
DisplayCurrent(false);
|
|
current = tmpCurrent;
|
|
if (current < first) {
|
|
first = first > MAXOSDITEMS - 1 ? first - (MAXOSDITEMS - 1) : 0;
|
|
if (Setup.MenuScrollPage)
|
|
current = SpecialItem(first) ? first + 1 : first;
|
|
Display();
|
|
}
|
|
else
|
|
DisplayCurrent(true);
|
|
}
|
|
}
|
|
|
|
void cOsdMenu::CursorDown(void)
|
|
{
|
|
int last = Count() - 1;
|
|
int lastOnScreen = first + MAXOSDITEMS - 1;
|
|
|
|
if (current < last) {
|
|
int tmpCurrent = current;
|
|
while (++tmpCurrent <= last && SpecialItem(tmpCurrent));
|
|
if (tmpCurrent > last)
|
|
return;
|
|
if (tmpCurrent <= lastOnScreen)
|
|
DisplayCurrent(false);
|
|
current = tmpCurrent;
|
|
if (current > lastOnScreen) {
|
|
first += MAXOSDITEMS - 1;
|
|
lastOnScreen = first + MAXOSDITEMS - 1;
|
|
if (lastOnScreen > last) {
|
|
first = last - (MAXOSDITEMS - 1);
|
|
lastOnScreen = last;
|
|
}
|
|
if (Setup.MenuScrollPage)
|
|
current = SpecialItem(lastOnScreen) ? lastOnScreen - 1 : lastOnScreen;
|
|
Display();
|
|
}
|
|
else
|
|
DisplayCurrent(true);
|
|
}
|
|
}
|
|
|
|
void cOsdMenu::PageUp(void)
|
|
{
|
|
if (Count() <= MAXOSDITEMS)
|
|
return;
|
|
current -= MAXOSDITEMS;
|
|
first -= MAXOSDITEMS;
|
|
if (first < 0)
|
|
first = current = 0;
|
|
if (SpecialItem(current)) {
|
|
current -= (current > 0) ? 1 : -1;
|
|
first = min(first, current - 1);
|
|
}
|
|
Display();
|
|
DisplayCurrent(true);
|
|
}
|
|
|
|
void cOsdMenu::PageDown(void)
|
|
{
|
|
if (Count() <= MAXOSDITEMS)
|
|
return;
|
|
current += MAXOSDITEMS;
|
|
first += MAXOSDITEMS;
|
|
if (current > Count() - 1) {
|
|
current = Count() - 1;
|
|
first = Count() - MAXOSDITEMS;
|
|
}
|
|
if (SpecialItem(current)) {
|
|
current += (current < Count() - 1) ? 1 : -1;
|
|
first = max(first, current - MAXOSDITEMS);
|
|
}
|
|
Display();
|
|
DisplayCurrent(true);
|
|
}
|
|
|
|
void cOsdMenu::Mark(void)
|
|
{
|
|
if (Count() && marked < 0) {
|
|
marked = current;
|
|
SetStatus(tr("Up/Dn for new location - OK to move"));
|
|
}
|
|
}
|
|
|
|
eOSState cOsdMenu::HotKey(eKeys Key)
|
|
{
|
|
for (cOsdItem *item = First(); item; item = Next(item)) {
|
|
const char *s = item->Text();
|
|
if (s && (s = skipspace(s)) != NULL) {
|
|
if (*s == Key - k1 + '1') {
|
|
current = item->Index();
|
|
return ProcessKey(kOk);
|
|
}
|
|
}
|
|
}
|
|
return osContinue;
|
|
}
|
|
|
|
eOSState cOsdMenu::AddSubMenu(cOsdMenu *SubMenu)
|
|
{
|
|
delete subMenu;
|
|
subMenu = SubMenu;
|
|
subMenu->Display();
|
|
return osContinue; // convenience return value
|
|
}
|
|
|
|
eOSState cOsdMenu::CloseSubMenu()
|
|
{
|
|
delete subMenu;
|
|
subMenu = NULL;
|
|
RefreshCurrent();
|
|
Display();
|
|
return osContinue; // convenience return value
|
|
}
|
|
|
|
eOSState cOsdMenu::ProcessKey(eKeys Key)
|
|
{
|
|
if (subMenu) {
|
|
eOSState state = subMenu->ProcessKey(Key);
|
|
if (state == osBack)
|
|
return CloseSubMenu();
|
|
return state;
|
|
}
|
|
|
|
cOsdItem *item = Get(current);
|
|
if (marked < 0 && item) {
|
|
eOSState state = item->ProcessKey(Key);
|
|
if (state != osUnknown)
|
|
return state;
|
|
}
|
|
switch (Key) {
|
|
case k1...k9: return hasHotkeys ? HotKey(Key) : osUnknown;
|
|
case kUp|k_Repeat:
|
|
case kUp: CursorUp(); break;
|
|
case kDown|k_Repeat:
|
|
case kDown: CursorDown(); break;
|
|
case kLeft|k_Repeat:
|
|
case kLeft: PageUp(); break;
|
|
case kRight|k_Repeat:
|
|
case kRight: PageDown(); break;
|
|
case kBack: return osBack;
|
|
case kOk: if (marked >= 0) {
|
|
SetStatus(NULL);
|
|
if (marked != current)
|
|
Move(marked, current);
|
|
marked = -1;
|
|
break;
|
|
}
|
|
// else run into default
|
|
default: if (marked < 0)
|
|
return osUnknown;
|
|
}
|
|
return osContinue;
|
|
}
|
|
|