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