menu.c
author nathan
Tue, 03 Feb 2009 20:33:04 +0800
branchtrunk
changeset 22 93aaf15c145a
parent 0 474a1293c3c0
child 29 640ce9201139
permissions -rw-r--r--
remove compatibility for VDR < 1.4.5
     1 /*
     2  * MP3/MPlayer plugin to VDR (C++)
     3  *
     4  * (C) 2001-2009 Stefan Huelswitt <s.huelswitt@gmx.de>
     5  *
     6  * This code is free software; you can redistribute it and/or
     7  * modify it under the terms of the GNU General Public License
     8  * as published by the Free Software Foundation; either version 2
     9  * of the License, or (at your option) any later version.
    10  *
    11  * This code is distributed in the hope that it will be useful,
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  * GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License
    17  * along with this program; if not, write to the Free Software
    18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    19  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
    20  */
    21 
    22 #include <ctype.h>
    23 #include <dirent.h>
    24 #include <stdlib.h>
    25 #include <stdio.h>
    26 #include <errno.h>
    27 #include <sys/stat.h>
    28 #include <sys/ioctl.h>
    29 #include <sys/types.h>
    30 #include <unistd.h>
    31 
    32 #include "common.h"
    33 #include "menu.h"
    34 #include "data.h"
    35 #include "data-src.h"
    36 #include "i18n.h"
    37 
    38 // -----------------------------------------------------------------------------
    39 
    40 void Status(const char *text)
    41 {
    42   Skins.Message(mtStatus,text);
    43 }
    44 
    45 void Error(const char *text)
    46 {
    47   Skins.Message(mtError,text);
    48 }
    49 
    50 void Info(const char *text)
    51 {
    52   Skins.Message(mtInfo,text);
    53 }
    54 
    55 // --- cMenuBrowseItem ---------------------------------------------------------
    56 
    57 class cMenuBrowseItem : public cOsdItem {
    58   private:
    59   cFileObj *item;
    60   virtual void Set(void);
    61 public:
    62   cMenuBrowseItem(cFileObj *Item);
    63   cFileObj *Item(void) { return item; }
    64   };
    65 
    66 cMenuBrowseItem::cMenuBrowseItem(cFileObj *Item)
    67 {
    68   item = Item;
    69   Set();
    70 }
    71 
    72 void cMenuBrowseItem::Set(void)
    73 {
    74   char *buffer=0;
    75   asprintf(&buffer,item->Type()==otFile?"%s":"[%s]",item->Name());
    76   SetText(buffer,false);
    77 }
    78 
    79 // --- cMenuBrowse ------------------------------------------------------
    80 
    81 cFileObj *cMenuBrowse::lastselect=0;
    82 
    83 cMenuBrowse::cMenuBrowse(cFileSource *Source, bool Dirselect, bool WithID3, const char *title, const char * const *Excl)
    84 :cOsdMenu(title)
    85 {
    86   currentdir=parent=0;
    87   delete lastselect; lastselect=0;
    88   list=new cDirList;
    89 
    90   dirselectable=Dirselect;
    91   withID3=WithID3;
    92   excl=Excl;
    93 
    94   SetSource(Source); 
    95   NewDir(currentdir);
    96 }
    97 
    98 cMenuBrowse::~cMenuBrowse()
    99 {
   100   free(parent);
   101   free(currentdir);
   102   delete list;
   103 }
   104 
   105 cFileObj *cMenuBrowse::CurrentItem(void)
   106 {
   107   cMenuBrowseItem *item = (cMenuBrowseItem *)Get(Current());
   108   return item ? item->Item():0;
   109 }
   110 
   111 void cMenuBrowse::SetButtons(void)
   112 {
   113   SetHelp(tr("Select"), currentdir?tr("Parent"):0, 0, withID3?tr("ID3 info"):0);
   114   Display();
   115 }
   116 
   117 void cMenuBrowse::SetSource(cFileSource *Source)
   118 {
   119   source=Source;
   120   free(currentdir); currentdir=0;
   121   free(parent); parent=0;
   122   source->GetRemember(currentdir,parent);
   123 }
   124 
   125 bool cMenuBrowse::LoadDir(const char *dir)
   126 {
   127   Clear();
   128   Status(tr("Scanning directory..."));
   129   bool res=list->Load(source,dir,excl);
   130   if(res) {
   131     cFileObj *item=list->First();
   132     while(item) {
   133       Add(new cMenuBrowseItem(item),(parent && !strcmp(item->Name(),parent)));
   134       item=list->Next(item);
   135       }
   136     }
   137   Status(0);
   138   return res;
   139 }
   140 
   141 bool cMenuBrowse::NewDir(const char *dir)
   142 {
   143   char *ncur=dir ? strdup(dir):0;
   144   bool r=LoadDir(ncur);
   145   if(!r && ncur) {
   146     free(ncur); ncur=0;
   147     r=LoadDir(ncur);
   148     }
   149   if(r) {
   150     free(currentdir); currentdir=ncur;
   151 
   152     cFileObj *item=CurrentItem();
   153     source->SetRemember(currentdir,item?item->Name():0);
   154 
   155     SetButtons();
   156     return true;
   157     }
   158   free(ncur);
   159   Error(tr("Error scanning directory!"));
   160   return false;
   161 }
   162 
   163 eOSState cMenuBrowse::Parent(void)
   164 {
   165   eOSState res=osContinue;
   166 
   167   if(currentdir) {
   168     free(parent);
   169     char *ss=strrchr(currentdir,'/');
   170     if(ss) {
   171       *ss++=0;
   172       parent=strdup(ss);
   173       ss=currentdir;
   174       }
   175     else parent=strdup(currentdir);
   176 
   177     if(!NewDir(ss)) res=osEnd;
   178     }
   179   return res;
   180 }
   181 
   182 eOSState cMenuBrowse::Select(bool isred)
   183 {
   184   eOSState res=osContinue;
   185   cFileObj *item;
   186 
   187   if((item=CurrentItem())) {
   188     switch(item->Type()) {
   189       case otParent:
   190         if(!isred || !dirselectable)
   191           res=Parent();
   192         break;
   193       case otDir:
   194         if(!isred || !dirselectable) {
   195           if(!NewDir(item->Path())) res=osEnd;
   196           break;
   197           }
   198         // fall through to otFile
   199       case otFile:
   200         lastselect=new cFileObj(item);
   201         res=osBack;
   202         break;
   203       default:
   204         break;
   205       }
   206     } 
   207   return res;
   208 }
   209 
   210 eOSState cMenuBrowse::ID3Info(void)
   211 {
   212   return osContinue;
   213 }
   214 
   215 eOSState cMenuBrowse::ProcessStdKey(eKeys Key, eOSState state)
   216 {
   217   if(state==osUnknown) {
   218     switch (Key) {
   219       case kOk:     state=Select(false); break;
   220       case kRed:    state=Select(true); break;
   221       case kGreen:  state=Parent(); break;
   222       case kBlue:   if(withID3) state=ID3Info();
   223                     break;
   224       //case kMenu:   state=osEnd; break;
   225       default: break;
   226       }
   227     }
   228   if(state==osEnd || state==osBack) {
   229     cFileObj *item=CurrentItem();
   230     if(item) source->SetRemember(currentdir,item->Name());
   231     }
   232   return state;
   233 }
   234 
   235 // --- cMenuSourceItem ----------------------------------------------------------
   236 
   237 class cMenuSourceItem : public cOsdItem {
   238   private:
   239   cFileSource *source;
   240   virtual void Set(void);
   241 public:
   242   cMenuSourceItem(cFileSource *Source);
   243   cFileSource *Source(void) { return source; }
   244   };
   245 
   246 cMenuSourceItem::cMenuSourceItem(cFileSource *Source)
   247 {
   248   source=Source;
   249   Set();
   250 }
   251 
   252 void cMenuSourceItem::Set(void)
   253 {
   254   char *buffer=0;
   255   asprintf(&buffer, "%s\t%s\t%s", source->NeedsMount()?(source->Status()?"*":">"):"", source->Description(), source->BaseDir());
   256   SetText(buffer,false);
   257 }
   258 
   259 // --- cMenuSource --------------------------------------------------
   260 
   261 cFileSource *cMenuSource::selected=0;
   262 
   263 cMenuSource::cMenuSource(cFileSources *Sources, const char *title)
   264 :cOsdMenu(title,2,20)
   265 {
   266   selected=0;
   267   current=Sources->GetSource();
   268   cFileSource *source=Sources->First();
   269   while(source) {
   270     cOsdMenu::Add(new cMenuSourceItem(source),source==current);
   271     source=Sources->Next(source);
   272     }
   273 
   274   SetHelp(tr("Select"), tr("Mount"), tr("Unmount"), tr("Eject"));
   275   Display();
   276 }
   277 
   278 bool cMenuSource::DoMount(cFileSource *src)
   279 {
   280   bool res=src->Mount();
   281   RefreshCurrent();
   282   DisplayCurrent(true);
   283   return res;
   284 }
   285 
   286 bool cMenuSource::CheckMount(void)
   287 {
   288   cFileSource *src=selected ? selected:current;
   289   if(src->NeedsMount() && !src->Status()) {
   290     Error(tr("Selected source is not mounted!"));
   291     return false;
   292     }
   293   return true;
   294 }
   295 
   296 eOSState cMenuSource::Select(void)
   297 {
   298   if(HasSubMenu() || Count() == 0) return osContinue;
   299 
   300   cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   301   if(src->NeedsMount() && !src->Status()) {
   302     if(!DoMount(src)) Error(tr("Mount failed!"));
   303     }
   304   if(!src->NeedsMount() || src->Status()) {
   305     selected=src;
   306     return osBack;
   307     }
   308   return osContinue;
   309 }
   310 
   311 eOSState cMenuSource::Mount(void)
   312 {
   313   if(HasSubMenu() || Count() == 0) return osContinue;
   314 
   315   cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   316   if(src->NeedsMount() && !src->Status()) {
   317     if(DoMount(src)) Info(tr("Mount succeeded"));
   318     else Error(tr("Mount failed!"));
   319     }
   320   return osContinue;
   321 }
   322 
   323 eOSState cMenuSource::Unmount(void)
   324 {
   325   if(HasSubMenu() || Count() == 0) return osContinue;
   326 
   327   cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   328   if(src->NeedsMount() && src->Status()) {
   329     bool res=src->Unmount();
   330     RefreshCurrent();
   331     DisplayCurrent(true);
   332     if(res) Info(tr("Unmount succeeded"));
   333     else Error(tr("Unmount failed!"));
   334     }
   335   return osContinue;
   336 }
   337 
   338 eOSState cMenuSource::Eject(void)
   339 {
   340   if(HasSubMenu() || Count() == 0) return osContinue;
   341 
   342   cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   343   if(src->NeedsMount()) {
   344     bool res=src->Eject();
   345     RefreshCurrent();
   346     DisplayCurrent(true);
   347     if(!res) Error(tr("Eject failed!"));
   348     }
   349   return osContinue;
   350 }
   351 
   352 eOSState cMenuSource::ProcessKey(eKeys Key)
   353 {
   354   eOSState state = cOsdMenu::ProcessKey(Key);
   355 
   356   if(state==osBack && !CheckMount()) state=osContinue;
   357   if(state==osUnknown) {
   358      switch(Key) {
   359        case kOk:     
   360        case kRed:    return Select();
   361        case kGreen:  return Mount();
   362        case kYellow: return Unmount();
   363        case kBlue:   return Eject();
   364        case kMenu:   CheckMount(); return osEnd;
   365        default: break;
   366        }
   367      }
   368   return state;
   369 }
   370 
   371 // --- cProgressBar ------------------------------------------------------------
   372 
   373 cProgressBar::cProgressBar(int Width, int Height, int Current, int Total)
   374 :cBitmap(Width, Height, 2)
   375 {
   376   if(Total > 0) {
   377     int p = Current * Width / Total;;
   378     DrawRectangle(0, 0, p, Height - 1, clrGreen);
   379     DrawRectangle(p + 1, 0, Width - 1, Height - 1, clrWhite);
   380     }
   381 }
   382