menu.c
author nathan
Sun, 06 Dec 2009 08:48:57 +0800
branchtrunk
changeset 34 afc13760179b
parent 29 640ce9201139
permissions -rw-r--r--
fixed gcc 4.4.1 const errors
     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=aprintf(item->Type()==otFile?"%s":"[%s]",item->Name());
    75   SetText(buffer,false);
    76 }
    77 
    78 // --- cMenuBrowse ------------------------------------------------------
    79 
    80 cFileObj *cMenuBrowse::lastselect=0;
    81 
    82 cMenuBrowse::cMenuBrowse(cFileSource *Source, bool Dirselect, bool WithID3, const char *title, const char * const *Excl)
    83 :cOsdMenu(title)
    84 {
    85   currentdir=parent=0;
    86   delete lastselect; lastselect=0;
    87   list=new cDirList;
    88 
    89   dirselectable=Dirselect;
    90   withID3=WithID3;
    91   excl=Excl;
    92 
    93   SetSource(Source); 
    94   NewDir(currentdir);
    95 }
    96 
    97 cMenuBrowse::~cMenuBrowse()
    98 {
    99   free(parent);
   100   free(currentdir);
   101   delete list;
   102 }
   103 
   104 cFileObj *cMenuBrowse::CurrentItem(void)
   105 {
   106   cMenuBrowseItem *item = (cMenuBrowseItem *)Get(Current());
   107   return item ? item->Item():0;
   108 }
   109 
   110 void cMenuBrowse::SetButtons(void)
   111 {
   112   SetHelp(tr("Select"), currentdir?tr("Parent"):0, 0, withID3?tr("ID3 info"):0);
   113   Display();
   114 }
   115 
   116 void cMenuBrowse::SetSource(cFileSource *Source)
   117 {
   118   source=Source;
   119   free(currentdir); currentdir=0;
   120   free(parent); parent=0;
   121   source->GetRemember(currentdir,parent);
   122 }
   123 
   124 bool cMenuBrowse::LoadDir(const char *dir)
   125 {
   126   Clear();
   127   Status(tr("Scanning directory..."));
   128   bool res=list->Load(source,dir,excl);
   129   if(res) {
   130     cFileObj *item=list->First();
   131     while(item) {
   132       Add(new cMenuBrowseItem(item),(parent && !strcmp(item->Name(),parent)));
   133       item=list->Next(item);
   134       }
   135     }
   136   Status(0);
   137   return res;
   138 }
   139 
   140 bool cMenuBrowse::NewDir(const char *dir)
   141 {
   142   char *ncur=dir ? strdup(dir):0;
   143   bool r=LoadDir(ncur);
   144   if(!r && ncur) {
   145     free(ncur); ncur=0;
   146     r=LoadDir(ncur);
   147     }
   148   if(r) {
   149     free(currentdir); currentdir=ncur;
   150 
   151     cFileObj *item=CurrentItem();
   152     source->SetRemember(currentdir,item?item->Name():0);
   153 
   154     SetButtons();
   155     return true;
   156     }
   157   free(ncur);
   158   Error(tr("Error scanning directory!"));
   159   return false;
   160 }
   161 
   162 eOSState cMenuBrowse::Parent(void)
   163 {
   164   eOSState res=osContinue;
   165 
   166   if(currentdir) {
   167     free(parent);
   168     char *ss=strrchr(currentdir,'/');
   169     if(ss) {
   170       *ss++=0;
   171       parent=strdup(ss);
   172       ss=currentdir;
   173       }
   174     else parent=strdup(currentdir);
   175 
   176     if(!NewDir(ss)) res=osEnd;
   177     }
   178   return res;
   179 }
   180 
   181 eOSState cMenuBrowse::Select(bool isred)
   182 {
   183   eOSState res=osContinue;
   184   cFileObj *item;
   185 
   186   if((item=CurrentItem())) {
   187     switch(item->Type()) {
   188       case otParent:
   189         if(!isred || !dirselectable)
   190           res=Parent();
   191         break;
   192       case otDir:
   193         if(!isred || !dirselectable) {
   194           if(!NewDir(item->Path())) res=osEnd;
   195           break;
   196           }
   197         // fall through to otFile
   198       case otFile:
   199         lastselect=new cFileObj(item);
   200         res=osBack;
   201         break;
   202       default:
   203         break;
   204       }
   205     } 
   206   return res;
   207 }
   208 
   209 eOSState cMenuBrowse::ID3Info(void)
   210 {
   211   return osContinue;
   212 }
   213 
   214 eOSState cMenuBrowse::ProcessStdKey(eKeys Key, eOSState state)
   215 {
   216   if(state==osUnknown) {
   217     switch (Key) {
   218       case kOk:     state=Select(false); break;
   219       case kRed:    state=Select(true); break;
   220       case kGreen:  state=Parent(); break;
   221       case kBlue:   if(withID3) state=ID3Info();
   222                     break;
   223       //case kMenu:   state=osEnd; break;
   224       default: break;
   225       }
   226     }
   227   if(state==osEnd || state==osBack) {
   228     cFileObj *item=CurrentItem();
   229     if(item) source->SetRemember(currentdir,item->Name());
   230     }
   231   return state;
   232 }
   233 
   234 // --- cMenuSourceItem ----------------------------------------------------------
   235 
   236 class cMenuSourceItem : public cOsdItem {
   237   private:
   238   cFileSource *source;
   239   virtual void Set(void);
   240 public:
   241   cMenuSourceItem(cFileSource *Source);
   242   cFileSource *Source(void) { return source; }
   243   };
   244 
   245 cMenuSourceItem::cMenuSourceItem(cFileSource *Source)
   246 {
   247   source=Source;
   248   Set();
   249 }
   250 
   251 void cMenuSourceItem::Set(void)
   252 {
   253   char *buffer=aprintf("%s\t%s\t%s", source->NeedsMount()?(source->Status()?"*":">"):"", source->Description(), source->BaseDir());
   254   SetText(buffer,false);
   255 }
   256 
   257 // --- cMenuSource --------------------------------------------------
   258 
   259 cFileSource *cMenuSource::selected=0;
   260 
   261 cMenuSource::cMenuSource(cFileSources *Sources, const char *title)
   262 :cOsdMenu(title,2,20)
   263 {
   264   selected=0;
   265   current=Sources->GetSource();
   266   cFileSource *source=Sources->First();
   267   while(source) {
   268     cOsdMenu::Add(new cMenuSourceItem(source),source==current);
   269     source=Sources->Next(source);
   270     }
   271 
   272   SetHelp(tr("Select"), tr("Mount"), tr("Unmount"), tr("Eject"));
   273   Display();
   274 }
   275 
   276 bool cMenuSource::DoMount(cFileSource *src)
   277 {
   278   bool res=src->Mount();
   279   RefreshCurrent();
   280   DisplayCurrent(true);
   281   return res;
   282 }
   283 
   284 bool cMenuSource::CheckMount(void)
   285 {
   286   cFileSource *src=selected ? selected:current;
   287   if(src->NeedsMount() && !src->Status()) {
   288     Error(tr("Selected source is not mounted!"));
   289     return false;
   290     }
   291   return true;
   292 }
   293 
   294 eOSState cMenuSource::Select(void)
   295 {
   296   if(HasSubMenu() || Count() == 0) return osContinue;
   297 
   298   cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   299   if(src->NeedsMount() && !src->Status()) {
   300     if(!DoMount(src)) Error(tr("Mount failed!"));
   301     }
   302   if(!src->NeedsMount() || src->Status()) {
   303     selected=src;
   304     return osBack;
   305     }
   306   return osContinue;
   307 }
   308 
   309 eOSState cMenuSource::Mount(void)
   310 {
   311   if(HasSubMenu() || Count() == 0) return osContinue;
   312 
   313   cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   314   if(src->NeedsMount() && !src->Status()) {
   315     if(DoMount(src)) Info(tr("Mount succeeded"));
   316     else Error(tr("Mount failed!"));
   317     }
   318   return osContinue;
   319 }
   320 
   321 eOSState cMenuSource::Unmount(void)
   322 {
   323   if(HasSubMenu() || Count() == 0) return osContinue;
   324 
   325   cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   326   if(src->NeedsMount() && src->Status()) {
   327     bool res=src->Unmount();
   328     RefreshCurrent();
   329     DisplayCurrent(true);
   330     if(res) Info(tr("Unmount succeeded"));
   331     else Error(tr("Unmount failed!"));
   332     }
   333   return osContinue;
   334 }
   335 
   336 eOSState cMenuSource::Eject(void)
   337 {
   338   if(HasSubMenu() || Count() == 0) return osContinue;
   339 
   340   cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   341   if(src->NeedsMount()) {
   342     bool res=src->Eject();
   343     RefreshCurrent();
   344     DisplayCurrent(true);
   345     if(!res) Error(tr("Eject failed!"));
   346     }
   347   return osContinue;
   348 }
   349 
   350 eOSState cMenuSource::ProcessKey(eKeys Key)
   351 {
   352   eOSState state = cOsdMenu::ProcessKey(Key);
   353 
   354   if(state==osBack && !CheckMount()) state=osContinue;
   355   if(state==osUnknown) {
   356      switch(Key) {
   357        case kOk:     
   358        case kRed:    return Select();
   359        case kGreen:  return Mount();
   360        case kYellow: return Unmount();
   361        case kBlue:   return Eject();
   362        case kMenu:   CheckMount(); return osEnd;
   363        default: break;
   364        }
   365      }
   366   return state;
   367 }
   368 
   369 // --- cProgressBar ------------------------------------------------------------
   370 
   371 cProgressBar::cProgressBar(int Width, int Height, int Current, int Total)
   372 :cBitmap(Width, Height, 2)
   373 {
   374   if(Total > 0) {
   375     int p = Current * Width / Total;;
   376     DrawRectangle(0, 0, p, Height - 1, clrGreen);
   377     DrawRectangle(p + 1, 0, Width - 1, Height - 1, clrWhite);
   378     }
   379 }
   380