menu.c
author nathan
Sat, 29 Dec 2007 14:49:09 +0100
branchtrunk
changeset 2 4c1f7b705009
parent 0 474a1293c3c0
child 22 93aaf15c145a
permissions -rw-r--r--
release 0.10.1
     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