From 656e5ebef7461f82d120fc59bfc7917ea41eef4d Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Thu, 23 Feb 2006 19:07:04 +0000 Subject: [PATCH] Multiple options pages --- Makefile | 2 +- defines.h | 3 + message.h | 1 + thread.h | 2 - vdr.cc | 14 ++++ vdr.h | 10 +++ vepg.cc | 2 + view.cc | 2 +- view.h | 2 +- voptions.cc | 215 ++++++++++++++++++++++++++------------------------ voptions.h | 42 +++------- vwelcome.cc | 18 ++++- vwelcome.h | 7 +- wbutton.cc | 11 +++ wbutton.h | 3 + woptionbox.cc | 50 +++++++++--- woptionbox.h | 12 ++- 17 files changed, 241 insertions(+), 155 deletions(-) diff --git a/Makefile b/Makefile index 557dbaa..b2c3dc6 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ CROSSLIBS = ../jpeg-6b/libjpeg.a OBJECTS = main.o command.o log.o remote.o led.o mtd.o video.o audio.o tcp.o directory.o thread.o event.o \ player.o demuxer.o stream.o vfeed.o afeed.o afeedr.o osd.o surface.o viewman.o vdr.o dsock.o box.o \ - recording.o channel.o message.o playervideo.o messagequeue.o rectimer.o vtimeredit.o \ + recording.o channel.o message.o playervideo.o messagequeue.o rectimer.o vtimeredit.o voptionsmenu.o \ view.o vinfo.o vwallpaper.o vvolume.o vrecordinglist.o vlivebanner.o vmute.o vtimerlist.o \ vrecordingmenu.o vquestion.o vchannellist.o vwelcome.o vvideolive.o vvideorec.o \ vchannelselect.o vserverselect.o colour.o vconnect.o voptions.o vepg.o region.o \ diff --git a/defines.h b/defines.h index 0d6f880..638943c 100644 --- a/defines.h +++ b/defines.h @@ -27,6 +27,9 @@ typedef unsigned int UINT; typedef unsigned long ULONG; typedef unsigned long long ULLONG; +#define OPTIONTYPE_TEXT 1 +#define OPTIONTYPE_INT 2 + //#define SCREENWIDTH 720 //#define SCREENHEIGHT 576 //#define SCREENHEIGHT 480 diff --git a/message.h b/message.h index 3fe32a2..3508883 100644 --- a/message.h +++ b/message.h @@ -60,6 +60,7 @@ class Message const static ULONG TIMER = 15; const static ULONG EPG = 16; const static ULONG EPG_CLOSE = 17; + const static ULONG CHANGED_OPTIONS = 18; }; #endif diff --git a/thread.h b/thread.h index 965228e..544d345 100644 --- a/thread.h +++ b/thread.h @@ -24,8 +24,6 @@ #include #include -#include // temp - class Thread { protected: diff --git a/vdr.cc b/vdr.cc index 7d7a550..1b3b7aa 100644 --- a/vdr.cc +++ b/vdr.cc @@ -359,6 +359,20 @@ Directory* VDR::getRecordingsList() freePacket(); pthread_mutex_unlock(&mutex); + // Sort the directory order + sort(recDir->dirList.begin(), recDir->dirList.end(), DirectorySorter()); + + // Sort all the sub lists + + Directory* sortDir; + DirectoryList::iterator i; + for (i = recDir->dirList.begin(); i != recDir->dirList.end(); i++) + { + sortDir = *i; + sort(sortDir->recList.begin(), sortDir->recList.end(), RecordingSorter()); + } + + // Sort the root level list sort(recDir->recList.begin(), recDir->recList.end(), RecordingSorter()); return recDir; diff --git a/vdr.h b/vdr.h index 22ae2c1..4e36245 100644 --- a/vdr.h +++ b/vdr.h @@ -80,6 +80,16 @@ struct RecordingSorter } }; +struct DirectorySorter +{ + bool operator() (const Directory* a, const Directory* b) + { + int c = strcmp(b->name, a->name); + if (c > 0) return true; + return false; + } +}; + class VDR { diff --git a/vepg.cc b/vepg.cc index 2559fee..e00bc3f 100644 --- a/vepg.cc +++ b/vepg.cc @@ -341,6 +341,8 @@ int VEpg::handleCommand(int command) } case Remote::RECORD: { + Log::getInstance()->log("VEPG", Log::DEBUG, "ID %lu TIME %lu DURATION %lu TITLE %s\n", thisEvent.id, thisEvent.time, thisEvent.duration, thisEvent.title); + //TODO FIXME return 2; } diff --git a/view.cc b/view.cc index b589910..efeb07b 100644 --- a/view.cc +++ b/view.cc @@ -54,7 +54,7 @@ bool View::create(UINT w, UINT h) return surface->create(area.w, area.h); } -void View::setTitleText(char* takeText) +void View::setTitleText(const char* takeText) { int length = strlen(takeText); titleText = new char[length + 1]; diff --git a/view.h b/view.h index 1a9d710..34bdca6 100644 --- a/view.h +++ b/view.h @@ -42,7 +42,7 @@ class View : public Box void setBorderOn(UCHAR on); void setTitleBarOn(UCHAR on); - void setTitleText(char* title); + void setTitleText(const char* title); void setBackgroundColour(Colour& colour); void setTitleBarColour(Colour& colour); diff --git a/voptions.cc b/voptions.cc index caf5b2f..0d03d2a 100644 --- a/voptions.cc +++ b/voptions.cc @@ -20,76 +20,107 @@ #include "voptions.h" -VOptions::VOptions(VWelcome* tvwelcome) +VOptions::VOptions(View* tparent, const char* title, const OPTIONDATA* toptionData, const int tnumOptions) { - vwelcome = tvwelcome; viewman = ViewMan::getInstance(); - create(530, 85+(NUM_OPTIONS*30)); - if (Video::getInstance()->getFormat() == Video::PAL) - { - setScreenPos(104, 130); - } - else - { - setScreenPos(94, 70); - } + parent = tparent; + optionData = toptionData; + numOptions = tnumOptions; + + create(530, 85 + (numOptions * 30)); setBackgroundColour(Colour::VIEWBACKGROUND); setTitleBarOn(1); setTitleBarColour(Colour::TITLEBARBACKGROUND); - setTitleText(tr("Options")); + setTitleText(title); int fontHeight = surface->getFontHeight(); - UINT i; - for (i = 0; i < numOptions; i++) - { - optionBox[i].setSurface(surface); - optionBox[i].setSurfaceOffset(346, 45 + (i * 30)); - optionBox[i].setDimensions(150, fontHeight); - for (UINT j = 0; j < optionData[i].optionCount; j++) - { - Log::getInstance()->log("Options", Log::DEBUG, "Add option: %s", optionData[i].options[j]); - optionBox[i].addOption(tr((char*)optionData[i].options[j])); - } - } + optionBoxes = new WOptionBox[numOptions]; + UINT i, j; char* config; vdr = VDR::getInstance(); + // After setup, save all current indexes + optionsAtStart = new int[numOptions]; for (i = 0; i < numOptions; i++) { - optionBox[i].setSelected(tr((char*)optionData[i].options[optionData[i].defaultOption])); + optionBoxes[i].setSurface(surface); + optionBoxes[i].setSurfaceOffset(346, 45 + (i * 30)); + optionBoxes[i].setDimensions(150, fontHeight); + + if (optionData[i].optionType == OPTIONTYPE_TEXT) + { + for (j = 0; j < optionData[i].optionCount; j++) + { + Log::getInstance()->log("Options", Log::DEBUG, "Add option: %s", optionData[i].options[j]); + optionBoxes[i].addOption(tr((char*)optionData[i].options[j])); + } + + // Set the built in default + optionBoxes[i].setSelected(tr((char*)optionData[i].options[optionData[i].defaultOption])); + } + else + { + // int mode + optionBoxes[i].setIntMode(optionData[i].startInt, optionData[i].optionCount); + optionBoxes[i].setSelected(optionData[i].defaultOption); + } + + // Now see if there is a config option for it config = vdr->configLoad(optionData[i].configSection, optionData[i].configParam); if (config) { - for (UINT j = 0; j < optionData[i].optionCount; j++) + if (optionData[i].optionType == OPTIONTYPE_TEXT) { - if (!strcasecmp(config, optionData[i].options[j])) + for (j = 0; j < optionData[i].optionCount; j++) { - optionBox[i].setSelected(tr((char*)optionData[i].options[j])); + if (!strcasecmp(config, optionData[i].options[j])) + { + optionBoxes[i].setSelected(tr((char*)optionData[i].options[j])); + } } } + else + { + optionBoxes[i].setSelected(atoi(config)); + } delete[] config; } + + // After setup, save initial option + optionsAtStart[i] = optionBoxes[i].getSelectedIndex(); } - // After setup, save all current indexes - optionsAtStart = new int[numOptions]; + selectedOption = 0; + optionBoxes[0].setActive(1); - for (i = 0; i < numOptions; i++) + int voff = 0; + if ((numOptions < 8) && (numOptions >= 4)) + { + voff = (8 - numOptions) * 10; + } + else if (numOptions < 4) { - optionsAtStart[i] = optionBox[i].getSelectedIndex(); + voff = 40; //(4 * 10) } - selectedOption = 0; - optionBox[0].setActive(1); + if (Video::getInstance()->getFormat() == Video::PAL) + { + setScreenPos(104, 130 + voff); + } + else + { + setScreenPos(94, 70 + voff); + } } VOptions::~VOptions() { delete[] optionsAtStart; + delete[] optionBoxes; } void VOptions::draw() @@ -118,7 +149,7 @@ void VOptions::draw() wsy.nextSymbol = WSymbol::RIGHTARROW; wsy.setSurfaceOffset(498, 47 + (i * 30)); wsy.draw(); - optionBox[i].draw(); + optionBoxes[i].draw(); } } @@ -131,9 +162,9 @@ int VOptions::handleCommand(int command) { if (selectedOption > 0) { - optionBox[selectedOption].setActive(0); + optionBoxes[selectedOption].setActive(0); --selectedOption; - optionBox[selectedOption].setActive(1); + optionBoxes[selectedOption].setActive(1); draw(); viewman->updateView(this); } @@ -144,9 +175,9 @@ int VOptions::handleCommand(int command) { if (selectedOption < (numOptions - 1)) { - optionBox[selectedOption].setActive(0); + optionBoxes[selectedOption].setActive(0); ++selectedOption; - optionBox[selectedOption].setActive(1); + optionBoxes[selectedOption].setActive(1); draw(); viewman->updateView(this); } @@ -155,7 +186,7 @@ int VOptions::handleCommand(int command) case Remote::DF_LEFT: case Remote::LEFT: { - optionBox[selectedOption].left(); + optionBoxes[selectedOption].left(); draw(); viewman->updateView(this); return 2; @@ -163,7 +194,7 @@ int VOptions::handleCommand(int command) case Remote::DF_RIGHT: case Remote::RIGHT: { - optionBox[selectedOption].right(); + optionBoxes[selectedOption].right(); draw(); viewman->updateView(this); return 2; @@ -171,11 +202,23 @@ int VOptions::handleCommand(int command) case Remote::BACK: { doSave(); - return 4; + + // Instead of returning 4 here which would delete this view + // before the doSave message is processed, let the message queue + // do the doSave then this close message. That will make the options menu + // disappear before this view + + Message* m = new Message(); + m->message = Message::CLOSE_ME; + m->from = this; + m->to = viewman; + viewman->postMessage(m); + + return 2; } case Remote::OK: { - optionBox[selectedOption].cycle(); + optionBoxes[selectedOption].cycle(); draw(); viewman->updateView(this); } @@ -186,84 +229,50 @@ int VOptions::handleCommand(int command) void VOptions::doSave() { + UINT i; int result[numOptions]; - for (UINT i = 0; i < numOptions; i++) + for (i = 0; i < numOptions; i++) { - result[i] = optionBox[i].getSelectedIndex(); + result[i] = optionBoxes[i].getSelectedIndex(); if (result[i] != optionsAtStart[i]) { Log::getInstance()->log("Options", Log::DEBUG, "Option %i has changed", i); - vdr->configSave(optionData[i].configSection, optionData[i].configParam, - optionData[i].options[result[i]]); + if (optionData[i].optionType == OPTIONTYPE_TEXT) + { + vdr->configSave(optionData[i].configSection, optionData[i].configParam, + optionData[i].options[result[i]]); + } + else + { + char buffer[20]; + sprintf(buffer, "%i", result[i]); + vdr->configSave(optionData[i].configSection, optionData[i].configParam, + buffer); + } } } - // Apply changes - Video* video = Video::getInstance(); - - if (result[0] != optionsAtStart[0]) - { - if (result[0] == 1) - { - Log::getInstance()->log("Options", Log::DEBUG, "Setting New Remote"); - Remote::getInstance()->setRemoteType(Remote::NEWREMOTE); - } - else - { - Log::getInstance()->log("Options", Log::DEBUG, "Setting Old Remote"); - Remote::getInstance()->setRemoteType(Remote::OLDREMOTE); - } - } + // Save a vector of option IDs that have changed - if (result[1] != optionsAtStart[1]) - { - I18n::initialize(); - vwelcome->redrawLang(); - } + map* optionChanges = new map; - if (result[2] != optionsAtStart[2]) + for (i = 0; i < numOptions; i++) { - if (result[2] == 1) - { - Log::getInstance()->log("Options", Log::DEBUG, "Setting S-Video"); - video->setConnection(Video::SVIDEO); - } - else + if (result[i] != optionsAtStart[i]) { - Log::getInstance()->log("Options", Log::DEBUG, "Setting RGB/Composite"); - video->setConnection(Video::COMPOSITERGB); + (*optionChanges)[optionData[i].id] = result[i]; } } - if (result[3] != optionsAtStart[3]) - { - if (result[3] == 1) - { - Log::getInstance()->log("Options", Log::DEBUG, "Setting 16:9 TV"); - video->setTVsize(Video::ASPECT16X9); - } - else - { - Log::getInstance()->log("Options", Log::DEBUG, "Setting 4:3 TV"); - video->setTVsize(Video::ASPECT4X3); - } - } + // Send it to parent for changes to be applied + Message* m = new Message(); + m->message = Message::CHANGED_OPTIONS; + m->to = parent; + m->parameter = (ULONG)optionChanges; + viewman->postMessage(m); - if (result[4] != optionsAtStart[4]) - { - if (result[4] == 1) - { - Log::getInstance()->log("Options", Log::DEBUG, "Setting letterbox"); - video->setMode(Video::LETTERBOX); - } - else - { - Log::getInstance()->log("Options", Log::DEBUG, "Setting chop-sides"); - video->setMode(Video::NORMAL); - } - } } diff --git a/voptions.h b/voptions.h index 790ac38..0d1481c 100644 --- a/voptions.h +++ b/voptions.h @@ -21,8 +21,8 @@ #ifndef VOPTIONS_H #define VOPTIONS_H +#include #include "view.h" -#include "remote.h" #include "viewman.h" #include "vdr.h" #include "colour.h" @@ -30,45 +30,24 @@ #include "woptionbox.h" #include "wsymbol.h" #include "i18n.h" -#include "vwelcome.h" -#define NUM_OPTIONS 8 typedef struct { + UINT id; // Used for working out what has changed at the end char *title; // Name of the option char *configSection; // Which section of the config file char *configParam; // Parameter name in the config file + UINT optionType; // 1 for text, 2 for int UINT optionCount; // How many choices? - UINT defaultOption; // Serial of the default choice (base 0) - const char * const * options; // Text for the options + UINT defaultOption; // Serial of the default choice (base 0), or actual option in int mode + int startInt; // Starting int for int mode + const char * const * options; // Text for the options (null for int mode) } OPTIONDATA; -static const char* options0[] = {"Old", "New"}; -static const char* options1[] = {"RGB+composite", "S-Video"}; -static const char* options2[] = {"4:3", "16:9"}; -static const char* options3[] = {"Chop sides", "Letterbox"}; -static const char* options4[] = {"On", "Off", "Last state"}; -static const char* options5[] = {"All", "FTA only"}; -static const char* options6[] = {"0", "5", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55", "60", "65", "70", "75", "80", "85", "90", "95", "99"}; - -const static OPTIONDATA optionData[NUM_OPTIONS] = -{ - {"Remote control type", "General", "Remote type", 2, 0, options0 }, - {"Language", "General", "Language", I18n::NumLanguages, 0, I18n::Languages }, - {"TV connection type", "TV", "Connection", 2, 0, options1 }, - {"TV aspect ratio", "TV", "Aspect", 2, 0, options2 }, - {"16:9 on 4:3 display mode", "TV", "Widemode", 2, 0, options3 }, - {"Power state after bootup", "General", "Power After Boot", 3, 0, options4 }, - {"Display channels", "General", "Channels", 2, 0, options5 }, - {"VDR-Pri 0=OK !See forums!","General", "Live priority", 21, 0, options6 } -}; - -class VWelcome; - class VOptions : public View { public: - VOptions(VWelcome* tvwelcome); + VOptions(View* tparent, const char* title, const OPTIONDATA* toptionData, const int tnumOptions); ~VOptions(); int handleCommand(int command); @@ -77,13 +56,14 @@ class VOptions : public View private: void doSave(); - const static UINT numOptions = NUM_OPTIONS; + const OPTIONDATA* optionData; + UINT numOptions; UINT selectedOption; - WOptionBox optionBox[numOptions]; + WOptionBox* optionBoxes; VDR* vdr; int* optionsAtStart; ViewMan* viewman; - VWelcome* vwelcome; + View* parent; }; #endif diff --git a/vwelcome.cc b/vwelcome.cc index cf2e745..b495bae 100644 --- a/vwelcome.cc +++ b/vwelcome.cc @@ -20,8 +20,12 @@ #include "vwelcome.h" +VWelcome* VWelcome::instance = NULL; + VWelcome::VWelcome() { + instance = this; + viewman = ViewMan::getInstance(); clockRegion.x = 400; @@ -55,9 +59,15 @@ VWelcome::VWelcome() VWelcome::~VWelcome() { + instance = NULL; Timers::getInstance()->cancelTimer(this, 1); } +VWelcome* VWelcome::getInstance() +{ + return instance; +} + void VWelcome::setup() { sl.clear(); @@ -279,10 +289,10 @@ void VWelcome::doTimersList() void VWelcome::doOptions() { - VOptions* voptions = new VOptions(this); - voptions->draw(); - viewman->add(voptions); - viewman->updateView(voptions); + VOptionsMenu* voptionsmenu = new VOptionsMenu(); + voptionsmenu->draw(); + viewman->add(voptionsmenu); + viewman->updateView(voptionsmenu); } void VWelcome::redrawLang() diff --git a/vwelcome.h b/vwelcome.h index 4993ba5..59ac71b 100644 --- a/vwelcome.h +++ b/vwelcome.h @@ -38,15 +38,18 @@ #include "message.h" #include "colour.h" #include "video.h" -#include "voptions.h" +#include "voptionsmenu.h" #include "i18n.h" #include "timers.h" +// FIXME - take out singleton when broadcast messages exist + class VWelcome : public View, public TimerReceiver { public: VWelcome(); ~VWelcome(); + static VWelcome* getInstance(); void setup(); int handleCommand(int command); @@ -55,6 +58,8 @@ class VWelcome : public View, public TimerReceiver void redrawLang(); private: + static VWelcome* instance; + WSelectList sl; WJpeg jpeg; diff --git a/wbutton.cc b/wbutton.cc index 194d49e..5e7c69c 100644 --- a/wbutton.cc +++ b/wbutton.cc @@ -27,6 +27,7 @@ WButton::WButton() mytext = NULL; active = 0; + tag = 0; } WButton::~WButton() @@ -59,3 +60,13 @@ void WButton::draw() drawText(mytext, 0, 0, Colour::LIGHTTEXT); } } + +void WButton::setTag(int newTag) +{ + tag = newTag; +} + +int WButton::getTag() +{ + return tag; +} diff --git a/wbutton.h b/wbutton.h index cbe1cbd..a76f77e 100644 --- a/wbutton.h +++ b/wbutton.h @@ -36,11 +36,14 @@ class WButton : public Widget void setText(char* text); void setActive(UCHAR tactive); void draw(); + void setTag(int tag); + int getTag(); private: UCHAR active; char* mytext; + int tag; }; #endif diff --git a/woptionbox.cc b/woptionbox.cc index 70efeb8..65c3b4f 100644 --- a/woptionbox.cc +++ b/woptionbox.cc @@ -26,6 +26,8 @@ WOptionBox::WOptionBox() options = NULL; active = 0; currentOption = 0; + + mode = MODE_TEXT; } WOptionBox::~WOptionBox() @@ -41,14 +43,8 @@ void WOptionBox::addOption(const char* takeText) int length = strlen(takeText); char* newOption = new char[length + 1]; strcpy(newOption, takeText); - - Log::getInstance()->log("Temp", Log::DEBUG, "About to realloc, num Options=%i, current options = %p, new text = %s", numOptions, options, newOption); - options = (char**)realloc(options, (numOptions+1) * sizeof(char*)); - Log::getInstance()->log("Temp", Log::DEBUG, ""); - options[numOptions] = newOption; - numOptions++; } @@ -108,12 +104,46 @@ void WOptionBox::setSelected(const char* toSelect) currentOption = 0; } -char* WOptionBox::getSelected() +//char* WOptionBox::getSelected() +//{ +// return options[currentOption]; +//} + +int WOptionBox::getSelectedIndex() { - return options[currentOption]; + if (mode == MODE_TEXT) + { + return currentOption; + } + else + { + return atoi(options[currentOption]); + } } -int WOptionBox::getSelectedIndex() +void WOptionBox::setIntMode(int startInt, int setNumOptions) +{ + mode = MODE_INT; + + int cInt; + char buffer[20]; + + for (cInt = startInt; cInt < (startInt + setNumOptions); cInt++) + { + sprintf(buffer, "%i", cInt); + addOption(buffer); + } +} + +void WOptionBox::setSelected(int toSelect) { - return currentOption; + for(UINT i = 0; i < numOptions; i++) + { + if (atoi(options[i]) == toSelect) + { + currentOption = i; + return; + } + } + currentOption = 0; } diff --git a/woptionbox.h b/woptionbox.h index 433a7f6..6ef0514 100644 --- a/woptionbox.h +++ b/woptionbox.h @@ -32,9 +32,14 @@ class WOptionBox : public Widget public: WOptionBox(); ~WOptionBox(); + + // Int mode stuff + void setIntMode(int start, int numOptions); + void setSelected(int newSelection); + void addOption(const char* newOption); void setSelected(const char* selectedOption); - char* getSelected(); +// char* getSelected(); void setActive(UCHAR tactive); void left(); void right(); @@ -42,11 +47,16 @@ class WOptionBox : public Widget void draw(); int getSelectedIndex(); + const static int MODE_TEXT = 1; + const static int MODE_INT = 2; + private: UCHAR active; UINT numOptions; char** options; UINT currentOption; + + int mode; }; #endif -- 2.39.5