diff options
Diffstat (limited to 'menu.c')
-rw-r--r-- | menu.c | 745 |
1 files changed, 745 insertions, 0 deletions
@@ -0,0 +1,745 @@ +/* + * menu.c: The actual menu implementations + * + * See the main source file 'osm.c' for copyright information and + * how to reach the author. + * + * $Id: menu.c 1.1 2000/02/19 13:36:48 kls Exp $ + */ + +#include "menu.h" +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include "config.h" +#include "dvbapi.h" + +const char *FileNameChars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789/-.# ";//TODO more? + +// --- cMenuEditItem --------------------------------------------------------- + +class cMenuEditItem : public cOsdItem { +private: + const char *name; + const char *value; +public: + cMenuEditItem(const char *Name); + ~cMenuEditItem(); + void SetValue(const char *Value); + }; + +cMenuEditItem::cMenuEditItem(const char *Name) +{ + name = strdup(Name); + value = NULL; +} + +cMenuEditItem::~cMenuEditItem() +{ + delete name; + delete value; +} + +void cMenuEditItem::SetValue(const char *Value) +{ + delete value; + value = strdup(Value); + char *buffer = NULL; + asprintf(&buffer, "%s:\t%s", name, value); + SetText(buffer, false); + Display(); +} + +// --- cMenuEditIntItem ------------------------------------------------------ + +class cMenuEditIntItem : public cMenuEditItem { +protected: + int *value; + int min, max; + virtual void Set(void); +public: + cMenuEditIntItem(const char *Name, int *Value, int Min = 0, int Max = INT_MAX); + virtual eOSStatus ProcessKey(eKeys Key); + }; + +cMenuEditIntItem::cMenuEditIntItem(const char *Name, int *Value, int Min, int Max) +:cMenuEditItem(Name) +{ + value = Value; + min = Min; + max = Max; + Set(); +} + +void cMenuEditIntItem::Set(void) +{ + char buf[16]; + snprintf(buf, sizeof(buf), "%d", *value); + SetValue(buf); +} + +eOSStatus cMenuEditIntItem::ProcessKey(eKeys Key) +{ + eOSStatus status = cMenuEditItem::ProcessKey(Key); + + if (status == osUnknown) { + int newValue; + if (k0 <= Key && Key <= k9) { + if (fresh) { + *value = 0; + fresh = false; + } + newValue = *value * 10 + (Key - k0); + } + else if (Key == kLeft) { // TODO might want to increase the delta if repeated quickly? + newValue = *value - 1; + fresh = true; + } + else if (Key == kRight) { + newValue = *value + 1; + fresh = true; + } + else + return status; + if ((!fresh || min <= newValue) && newValue <= max) { + *value = newValue; + Set(); + } + status = osContinue; + } + return status; +} + +// --- cMenuEditBoolItem ----------------------------------------------------- + +class cMenuEditBoolItem : public cMenuEditIntItem { +protected: + virtual void Set(void); +public: + cMenuEditBoolItem(const char *Name, int *Value); + }; + +cMenuEditBoolItem::cMenuEditBoolItem(const char *Name, int *Value) +:cMenuEditIntItem(Name, Value, 0, 1) +{ + Set(); +} + +void cMenuEditBoolItem::Set(void) +{ + char buf[16]; + snprintf(buf, sizeof(buf), "%s", *value ? "yes" : "no"); + SetValue(buf); +} + +// --- cMenuEditChanItem ----------------------------------------------------- + +class cMenuEditChanItem : public cMenuEditIntItem { +protected: + virtual void Set(void); +public: + cMenuEditChanItem(const char *Name, int *Value); + }; + +cMenuEditChanItem::cMenuEditChanItem(const char *Name, int *Value) +:cMenuEditIntItem(Name, Value, 1, Channels.Count()) +{ + Set(); +} + +void cMenuEditChanItem::Set(void) +{ + char buf[255]; + cChannel *channel = Channels.Get(*value - 1); + if (channel) + snprintf(buf, sizeof(buf), "%d %s", *value, channel->name); + else + *buf = 0; + SetValue(buf); +} + +// --- cMenuEditDayItem ------------------------------------------------------ + +class cMenuEditDayItem : public cMenuEditIntItem { +protected: + static int days[]; + int d; + virtual void Set(void); +public: + cMenuEditDayItem(const char *Name, int *Value); + virtual eOSStatus ProcessKey(eKeys Key); + }; + +int cMenuEditDayItem::days[] ={ cTimer::ParseDay("M------"), + cTimer::ParseDay("-T-----"), + cTimer::ParseDay("--W----"), + cTimer::ParseDay("---T---"), + cTimer::ParseDay("----F--"), + cTimer::ParseDay("-----S-"), + cTimer::ParseDay("------S"), + cTimer::ParseDay("MTWTF--"), + cTimer::ParseDay("MTWTFS-"), + cTimer::ParseDay("MTWTFSS"), + cTimer::ParseDay("-----SS"), + 0 }; + +cMenuEditDayItem::cMenuEditDayItem(const char *Name, int *Value) +:cMenuEditIntItem(Name, Value, -INT_MAX, 31) +{ + d = -1; + if (*value < 0) { + int n = 0; + while (days[n]) { + if (days[n] == *value) { + d = n; + break; + } + n++; + } + } + Set(); +} + +void cMenuEditDayItem::Set(void) +{ + SetValue(cTimer::PrintDay(*value)); +} + +eOSStatus cMenuEditDayItem::ProcessKey(eKeys Key) +{ + switch (Key) { + case kLeft: if (d > 0) + *value = days[--d]; + else if (d == 0) { + *value = 31; + d = -1; + } + else if (*value == 1) { + d = sizeof(days) / sizeof(int) - 2; + *value = days[d]; + } + else + return cMenuEditIntItem::ProcessKey(Key); + Set(); + break; + case kRight: if (d >= 0) { + *value = days[++d]; + if (*value == 0) { + *value = 1; + d = -1; + } + } + else if (*value == 31) { + d = 0; + *value = days[d]; + } + else + return cMenuEditIntItem::ProcessKey(Key); + Set(); + break; + default : return cMenuEditIntItem::ProcessKey(Key); + } + return osContinue; +} + +// --- cMenuEditTimeItem ----------------------------------------------------- + +class cMenuEditTimeItem : public cMenuEditItem { +protected: + int *value; + int hh, mm; + int pos; + virtual void Set(void); +public: + cMenuEditTimeItem(const char *Name, int *Value); + virtual eOSStatus ProcessKey(eKeys Key); + }; + +cMenuEditTimeItem::cMenuEditTimeItem(const char *Name, int *Value) +:cMenuEditItem(Name) +{ + value = Value; + hh = *value / 100; + mm = *value % 100; + pos = 0; + Set(); +} + +void cMenuEditTimeItem::Set(void) +{ + char buf[10]; + snprintf(buf, sizeof(buf), "%02d:%02d", hh, mm); + SetValue(buf); +} + +eOSStatus cMenuEditTimeItem::ProcessKey(eKeys Key) +{ + eOSStatus status = cMenuEditItem::ProcessKey(Key); + + if (status == osUnknown) { + if (k0 <= Key && Key <= k9) { + if (fresh || pos > 3) { + pos = 0; + fresh = false; + } + int n = Key - k0; + switch (pos) { + case 0: if (n <= 2) { + hh = n * 10; + mm = 0; + pos++; + } + break; + case 1: if (hh + n <= 23) { + hh += n; + pos++; + } + break; + case 2: if (n <= 5) { + mm += n * 10; + pos++; + } + break; + case 3: if (mm + n <= 59) { + mm += n; + pos++; + } + break; + } + } + else if (Key == kLeft) { // TODO might want to increase the delta if repeated quickly? + if (--mm < 0) { + mm = 59; + if (--hh < 0) + hh = 23; + } + fresh = true; + } + else if (Key == kRight) { + if (++mm > 59) { + mm = 0; + if (++hh > 23) + hh = 0; + } + fresh = true; + } + else + return status; + *value = hh * 100 + mm; + Set(); + status = osContinue; + } + return status; +} + +// --- cMenuEditChrItem ------------------------------------------------------ + +class cMenuEditChrItem : public cMenuEditItem { +private: + char *value; + const char *allowed; + const char *current; + virtual void Set(void); +public: + cMenuEditChrItem(const char *Name, char *Value, const char *Allowed); + ~cMenuEditChrItem(); + virtual eOSStatus ProcessKey(eKeys Key); + }; + +cMenuEditChrItem::cMenuEditChrItem(const char *Name, char *Value, const char *Allowed) +:cMenuEditItem(Name) +{ + value = Value; + allowed = strdup(Allowed); + current = strchr(allowed, *Value); + if (!current) + current = allowed; + Set(); +} + +cMenuEditChrItem::~cMenuEditChrItem() +{ + delete allowed; +} + +void cMenuEditChrItem::Set(void) +{ + char buf[2]; + snprintf(buf, sizeof(buf), "%c", *value); + SetValue(buf); +} + +eOSStatus cMenuEditChrItem::ProcessKey(eKeys Key) +{ + eOSStatus status = cMenuEditItem::ProcessKey(Key); + + if (status == osUnknown) { + if (Key == kLeft) { + if (current > allowed) + current--; + } + else if (Key == kRight) { + if (*(current + 1)) + current++; + } + else + return status; + *value = *current; + Set(); + status = osContinue; + } + return status; +} + +// --- cMenuEditStrItem ------------------------------------------------------ + +class cMenuEditStrItem : public cMenuEditItem { +private: + char *value; + int length; + const char *allowed; + int pos; + virtual void Set(void); + char Inc(char c, bool Up); +public: + cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed); + ~cMenuEditStrItem(); + virtual eOSStatus ProcessKey(eKeys Key); + }; + +cMenuEditStrItem::cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed) +:cMenuEditItem(Name) +{ + value = Value; + length = Length; + allowed = strdup(Allowed); + pos = -1; + Set(); +} + +cMenuEditStrItem::~cMenuEditStrItem() +{ + delete allowed; +} + +void cMenuEditStrItem::Set(void) +{ + char buf[1000]; + if (pos >= 0) { + strncpy(buf, value, pos); + char *s = value[pos] != ' ' ? value + pos + 1 : ""; + snprintf(buf + pos, sizeof(buf) - pos - 2, "[%c]%s", *(value + pos), s); + SetValue(buf); + } + else + SetValue(value); +} + +char cMenuEditStrItem::Inc(char c, bool Up) +{ + const char *p = strchr(allowed, c); + if (!p) + p = allowed; + if (Up) { + if (!*++p) + p = allowed; + } + else if (--p < allowed) + p = allowed + strlen(allowed) - 1; + return *p; +} + +eOSStatus cMenuEditStrItem::ProcessKey(eKeys Key) +{ + switch (Key) { + case kLeft: if (pos > 0) { + if (value[pos] == ' ') + value[pos] = 0; + pos--; + } + break; + case kRight: if (pos < length && value[pos] != ' ') { + if (++pos >= int(strlen(value))) { + value[pos] = ' '; + value[pos + 1] = 0; + } + } + break; + case kUp: + case kDown: if (pos >= 0) + value[pos] = Inc(value[pos], Key == kUp); + else + return cMenuEditItem::ProcessKey(Key); + break; + case kOk: if (pos >= 0) { + if (value[pos] == ' ') + value[pos] = 0; + pos = -1; + break; + } + // run into default + default: return cMenuEditItem::ProcessKey(Key); + } + Set(); + return osContinue; +} + +// --- cMenuEditChannel ------------------------------------------------------ + +class cMenuEditChannel : public cOsdMenu { +private: + cChannel *channel; + cChannel data; +public: + cMenuEditChannel(int Index); + virtual eOSStatus ProcessKey(eKeys Key); + }; + +cMenuEditChannel::cMenuEditChannel(int Index) +:cOsdMenu("Edit channel", 14) +{ + channel = Channels.Get(Index); + if (channel) { + data = *channel; + Add(new cMenuEditStrItem("Name", data.name, sizeof(data.name), FileNameChars)); + Add(new cMenuEditIntItem("Frequency", &data.frequency, 10000, 13000)); //TODO exact limits??? + Add(new cMenuEditChrItem("Polarization", &data.polarization, "hv")); + Add(new cMenuEditIntItem("Diseqc", &data.diseqc, 0, 10)); //TODO exact limits??? + Add(new cMenuEditIntItem("Srate", &data.srate, 22000, 27500)); //TODO exact limits - toggle??? + Add(new cMenuEditIntItem("Vpid", &data.vpid, 0, 10000)); //TODO exact limits??? + Add(new cMenuEditIntItem("Apid", &data.apid, 0, 10000)); //TODO exact limits??? + } +} + +eOSStatus cMenuEditChannel::ProcessKey(eKeys Key) +{ + eOSStatus status = cOsdMenu::ProcessKey(Key); + + if (status == osUnknown) { + if (Key == kOk) { + if (channel) + *channel = data; + Channels.Save(); + status = osBack; + } + } + return status; +} + +// --- cMenuChannelItem ------------------------------------------------------ + +class cMenuChannelItem : public cOsdItem { +private: + int index; + cChannel *channel; +public: + cMenuChannelItem(int Index, cChannel *Channel); + virtual void Set(void); + }; + +cMenuChannelItem::cMenuChannelItem(int Index, cChannel *Channel) +{ + index = Index; + channel = Channel; + Set(); +} + +void cMenuChannelItem::Set(void) +{ + char *buffer = NULL; + asprintf(&buffer, "%d\t%s", index + 1, channel->name); // user visible channel numbers start with '1' + SetText(buffer, false); +} + +// --- cMenuChannels --------------------------------------------------------- + +class cMenuChannels : public cOsdMenu { +public: + cMenuChannels(void); + virtual eOSStatus ProcessKey(eKeys Key); + }; + +cMenuChannels::cMenuChannels(void) +:cOsdMenu("Channels", 4) +{ + //TODO + int i = 0; + cChannel *channel; + + while ((channel = Channels.Get(i)) != NULL) { + Add(new cMenuChannelItem(i, channel), i == CurrentChannel); + i++; + } +} + +eOSStatus cMenuChannels::ProcessKey(eKeys Key) +{ + eOSStatus status = cOsdMenu::ProcessKey(Key); + + if (status == osUnknown) { + switch (Key) { + //TODO need to block this if we are already editing a channel! + case kRight: return AddSubMenu(new cMenuEditChannel(Current())); + case kOk: { + cChannel *ch = Channels.Get(Current()); + if (ch) + ch->Switch(); + return osEnd; + } + default: break; + } + } + return status; +} + +// --- cMenuEditTimer -------------------------------------------------------- + +class cMenuEditTimer : public cOsdMenu { +private: + cTimer *timer; + cTimer data; +public: + cMenuEditTimer(int Index); + virtual eOSStatus ProcessKey(eKeys Key); + }; + +cMenuEditTimer::cMenuEditTimer(int Index) +:cOsdMenu("Edit timer", 10) +{ + timer = Timers.Get(Index); + if (timer) { + data = *timer; + Add(new cMenuEditBoolItem("Active", &data.active)); + Add(new cMenuEditChanItem("Channel", &data.channel)); + Add(new cMenuEditDayItem( "Day", &data.day)); + Add(new cMenuEditTimeItem("Start", &data.start)); + Add(new cMenuEditTimeItem("Stop", &data.stop)); +//TODO VPS??? + Add(new cMenuEditChrItem( "Quality", &data.quality, DvbQuality)); + Add(new cMenuEditIntItem( "Priority", &data.priority, 0, 99)); + Add(new cMenuEditIntItem( "Lifetime", &data.lifetime, 0, 99)); + Add(new cMenuEditStrItem( "File", data.file, sizeof(data.file), FileNameChars)); + } +} + +eOSStatus cMenuEditTimer::ProcessKey(eKeys Key) +{ + eOSStatus status = cOsdMenu::ProcessKey(Key); + + if (status == osUnknown) { + if (Key == kOk) { + if (timer && memcmp(timer, &data, sizeof(data)) != 0) { + *timer = data; + Timers.Save(); + isyslog(LOG_INFO, "timer %d modified (%s)", timer->Index() + 1, timer->active ? "active" : "inactive"); + } + status = osBack; + } + } + return status; +} + +// --- cMenuTimerItem -------------------------------------------------------- + +class cMenuTimerItem : public cOsdItem { +private: + int index; + cTimer *timer; +public: + cMenuTimerItem(int Index, cTimer *Timer); + virtual void Set(void); + }; + +cMenuTimerItem::cMenuTimerItem(int Index, cTimer *Timer) +{ + index = Index; + timer = Timer; + Set(); +} + +void cMenuTimerItem::Set(void) +{ + char *buffer = NULL; + asprintf(&buffer, "%d\t%c\t%d\t%s\t%02d:%02d\t%02d:%02d", index + 1, + timer->active ? '>' : ' ', + timer->channel, + timer->PrintDay(timer->day), + timer->start / 100, + timer->start % 100, + timer->stop / 100, + timer->stop % 100); // user visible timer numbers start with '1' + SetText(buffer, false); +} + +// --- cMenuTimer ------------------------------------------------------------ + +class cMenuTimer : public cOsdMenu { +public: + cMenuTimer(void); + virtual eOSStatus ProcessKey(eKeys Key); + }; + +cMenuTimer::cMenuTimer(void) +:cOsdMenu("Timer", 3, 2, 4, 10, 6) +{ + int i = 0; + cTimer *timer; + + while ((timer = Timers.Get(i)) != NULL) { + Add(new cMenuTimerItem(i, timer)); + i++; + } +} + +eOSStatus cMenuTimer::ProcessKey(eKeys Key) +{ + eOSStatus status = cOsdMenu::ProcessKey(Key); + + if (status == osUnknown) { + switch (Key) { + //TODO need to block this if we are already editing a channel! + case kOk: return AddSubMenu(new cMenuEditTimer(Current())); + //TODO new timer + //TODO delete timer + case kLeft: + case kRight: + { + cTimer *timer = Timers.Get(Current()); + if (timer) { + timer->active = (Key == kRight); + isyslog(LOG_INFO, "timer %d %sactivated", timer->Index() + 1, timer->active ? "" : "de"); + RefreshCurrent(); + DisplayCurrent(true); + Timers.Save(); + } + } + default: break; + } + } + return status; +} + +// --- cMenuMain ------------------------------------------------------------- + +cMenuMain::cMenuMain(void) +:cOsdMenu("Main") +{ + //TODO + Add(new cOsdItem("Channels", osChannels)); + Add(new cOsdItem("Timer", osTimer)); + Add(new cOsdItem("Recordings", osRecordings)); +} + +eOSStatus cMenuMain::ProcessKey(eKeys Key) +{ + eOSStatus status = cOsdMenu::ProcessKey(Key); + + switch (status) { + case osChannels: return AddSubMenu(new cMenuChannels); + case osTimer: return AddSubMenu(new cMenuTimer); + //TODO Replay + default: break; + } + return status; +} + |