summaryrefslogtreecommitdiff
path: root/menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'menu.c')
-rw-r--r--menu.c402
1 files changed, 402 insertions, 0 deletions
diff --git a/menu.c b/menu.c
new file mode 100644
index 0000000..96c1a12
--- /dev/null
+++ b/menu.c
@@ -0,0 +1,402 @@
+/*
+ * image plugin to VDR (C++)
+ *
+ * (C) 2004 "Interpohl" <interpohl@vdr-portal.de>
+ * (C) 2004 A.Brachold <vdr04-at-deltab.de>
+ * (C) 2004 O.Kreuzinger <Onno@Kreuzinger.biz>
+ * (C) 2003 Kai Tobias Burwieck <kai@burwieck.net>
+ * (C) 2001,2002 Stefan Huelswitt <huels@iname.com>
+ *
+ * This code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <ctype.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "menu.h"
+#include "i18n.h"
+
+// --- cMenuBrowseItem ----------------------------------------------------------
+
+class cMenuBrowseItem:public cOsdItem {
+private:
+ cDirItem * item;
+ virtual void Set(void);
+public:
+ cMenuBrowseItem(cDirItem * Item);
+ cDirItem *Item(void) { return item; }
+};
+
+cMenuBrowseItem::cMenuBrowseItem(cDirItem * Item)
+{
+ item = Item;
+ Set();
+}
+
+void cMenuBrowseItem::Set(void)
+{
+ char *buffer = 0;
+ asprintf(&buffer, item->Type == itFile ? "%s" : "[%s]", item->Name);
+ SetText(buffer, false);
+}
+
+// --- cMenuBrowse ------------------------------------------------------
+
+cDirItem *cMenuBrowse::lastselect = 0;
+
+cMenuBrowse::cMenuBrowse(cFileSource * Source, bool Dirselect,const char *title)
+: cOsdMenu(title)
+{
+ currentdir = parent = 0;
+ delete lastselect;
+ lastselect = 0;
+ list = new cDirList;
+
+ dirselectable = Dirselect;
+
+ SetSource(Source);
+ LoadDir(currentdir);
+ SetButtons();
+}
+
+cMenuBrowse::~cMenuBrowse()
+{
+ free(parent);
+ free(currentdir);
+ delete list;
+}
+
+cDirItem *cMenuBrowse::CurrentItem(void)
+{
+ cMenuBrowseItem *item = (cMenuBrowseItem *) Get(Current());
+ return item ? item->Item() : 0;
+}
+
+void cMenuBrowse::SetButtons(void)
+{
+ SetHelp(tr("Select"), 0, 0, currentdir ? tr("Parent") : 0);
+ Display();
+}
+
+void cMenuBrowse::SetSource(cFileSource * Source)
+{
+ source = Source;
+ free(currentdir);
+ currentdir = 0;
+ free(parent);
+ parent = 0;
+ source->GetRemember(currentdir, parent);
+}
+
+bool cMenuBrowse::LoadDir(const char *dir)
+{
+ Clear();
+
+ //FIXME use a nonblocking way
+ //OSD_InfoMsg(tr("Scanning directory..."));
+
+ if(!list->Load(source, dir))
+ return false;
+
+ cDirItem *item = list->First();
+ while(item)
+ {
+ Add(new cMenuBrowseItem(item),
+ (parent && !strcmp(item->Name, parent)));
+ item = list->Next(item);
+ }
+ return true;
+}
+
+bool cMenuBrowse::NewDir(const char *dir)
+{
+ if(LoadDir(dir))
+ {
+ char *ncur = dir ? strdup(dir) : 0; // don't free currentdir first, as (new)dir may
+ free(currentdir);
+ currentdir = ncur; // be a reference to somewhere inside currentdir as well
+
+ cDirItem *item = CurrentItem();
+ source->SetRemember(currentdir, item ? item->Name : 0);
+
+ SetButtons();
+ return true;
+ }
+ OSD_ErrorMsg(tr("Error scanning directory!"));
+ return false;
+}
+
+eOSState cMenuBrowse::Parent(void)
+{
+ eOSState res = osContinue;
+
+ if(currentdir)
+ {
+ free(parent);
+ char *ss = strrchr(currentdir, '/');
+ if(ss)
+ {
+ *ss++ = 0;
+ parent = strdup(ss);
+ ss = currentdir;
+ }
+ else
+ parent = strdup(currentdir);
+
+ if(!NewDir(ss))
+ res = osEnd;
+ }
+ return res;
+}
+
+eOSState cMenuBrowse::Select(bool isred)
+{
+ eOSState res = osContinue;
+ cDirItem *item;
+
+ if((item = CurrentItem()))
+ {
+ switch (item->Type)
+ {
+ case itParent:
+ if(!isred || !dirselectable)
+ res = Parent();
+ break;
+ case itDir:
+ if(!isred || !dirselectable)
+ {
+ char *d = item->Path();
+ if(!NewDir(d))
+ res = osEnd;
+ free(d);
+ break;
+ }
+ // fall through to itFile
+ case itFile:
+ lastselect =
+ new cDirItem(source, currentdir, item->Name,
+ item->Type);
+ res = osBack;
+ break;
+ default:
+ break;
+ }
+ }
+ return res;
+}
+
+eOSState cMenuBrowse::ProcessKey(eKeys Key)
+{
+ eOSState state = cOsdMenu::ProcessKey(Key);
+
+ if(state == osUnknown)
+ {
+ switch (Key)
+ {
+ case kOk:
+ state = Select(false);
+ break;
+ case kRed:
+ state = Select(true);
+ break;
+ case kBlue:
+ state = Parent();
+ break;
+ case kMenu:
+ state = osEnd;
+ break;
+ default:
+ break;
+ }
+ }
+ if(state == osEnd || state == osBack)
+ {
+ cDirItem *item = CurrentItem();
+ if(item)
+ source->SetRemember(currentdir, item->Name);
+ }
+ return state;
+}
+
+// --- cMenuSourceItem ----------------------------------------------------------
+
+class cMenuSourceItem:public cOsdItem {
+ private:
+ cFileSource * source;
+ virtual void Set(void);
+ public:
+ cMenuSourceItem(cFileSource * Source);
+ cFileSource *Source(void) { return source; }
+};
+
+cMenuSourceItem::cMenuSourceItem(cFileSource * Source)
+{
+ source = Source;
+ Set();
+}
+
+void cMenuSourceItem::Set(void)
+{
+ char *buffer = 0;
+ asprintf(&buffer, "%s\t%s\t%s",
+ source->NeedsMount()? (source->Status()? "*" : ">") : "",
+ source->Description(), source->BaseDir());
+ SetText(buffer, false);
+}
+
+// --- cMenuSource --------------------------------------------------
+
+cFileSource *cMenuSource::selected = 0;
+
+cMenuSource::cMenuSource(cFileSources * Sources,
+ const char *title):cOsdMenu(title, 2, 20)
+{
+ selected = 0;
+ current = Sources->GetSource();
+ cFileSource *source = Sources->First();
+ while(source) {
+ cOsdMenu::Add(new cMenuSourceItem(source), source == current);
+ source = Sources->Next(source);
+ }
+
+ SetHelp(tr("Select"), tr("Mount"), tr("Unmount"), tr("Eject"));
+ Display();
+}
+
+bool cMenuSource::DoMount(cFileSource * src)
+{
+ bool res = src->Mount();
+ RefreshCurrent();
+ DisplayCurrent(true);
+ return res;
+}
+
+bool cMenuSource::CheckMount(void)
+{
+ cFileSource *src = selected ? selected : current;
+ if(src->NeedsMount() && !src->Status()) {
+ OSD_ErrorMsg(tr("Selected source is not mounted!"));
+ return false;
+ }
+ return true;
+}
+
+eOSState cMenuSource::Select(void)
+{
+ if(HasSubMenu() || Count() == 0)
+ return osContinue;
+
+ cFileSource *src = ((cMenuSourceItem *) Get(Current()))->Source();
+ if(src->NeedsMount() && !src->Status())
+ {
+ if(!DoMount(src))
+ OSD_ErrorMsg(tr("Mount failed!"));
+ }
+ if(!src->NeedsMount() || src->Status())
+ {
+ selected = src;
+ return osBack;
+ }
+ return osContinue;
+}
+
+eOSState cMenuSource::Mount(void)
+{
+ if(HasSubMenu() || Count() == 0)
+ return osContinue;
+
+ cFileSource *src = ((cMenuSourceItem *) Get(Current()))->Source();
+ if(src->NeedsMount() && !src->Status())
+ {
+ if(DoMount(src))
+ OSD_InfoMsg(tr("Mount succeeded"));
+ else
+ OSD_ErrorMsg(tr("Mount failed!"));
+ }
+ return osContinue;
+}
+
+eOSState cMenuSource::Unmount(void)
+{
+ if(HasSubMenu() || Count() == 0)
+ return osContinue;
+
+ cFileSource *src = ((cMenuSourceItem *) Get(Current()))->Source();
+ if(src->NeedsMount() && src->Status())
+ {
+ bool res = src->Unmount();
+ RefreshCurrent();
+ DisplayCurrent(true);
+ if(res)
+ OSD_InfoMsg(tr("Unmount succeeded"));
+ else
+ OSD_ErrorMsg(tr("Unmount failed!"));
+ }
+ return osContinue;
+}
+
+eOSState cMenuSource::Eject(void)
+{
+ if(HasSubMenu() || Count() == 0)
+ return osContinue;
+
+ cFileSource *src = ((cMenuSourceItem *) Get(Current()))->Source();
+ if(src->NeedsMount())
+ {
+ bool res = src->Eject();
+ RefreshCurrent();
+ DisplayCurrent(true);
+ if(!res)
+ OSD_ErrorMsg(tr("Eject failed!"));
+ }
+ return osContinue;
+}
+
+eOSState cMenuSource::ProcessKey(eKeys Key)
+{
+ eOSState state = cOsdMenu::ProcessKey(Key);
+
+ if(state == osBack && !CheckMount())
+ state = osContinue;
+ if(state == osUnknown)
+ {
+ switch (Key)
+ {
+ case kOk:
+ case kRed:
+ return Select();
+ case kGreen:
+ return Mount();
+ case kYellow:
+ return Unmount();
+ case kBlue:
+ return Eject();
+ case kMenu:
+ CheckMount();
+ return osEnd;
+ default:
+ break;
+ }
+ }
+ return state;
+}