menu.c
branchtrunk
changeset 0 474a1293c3c0
child 22 93aaf15c145a
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/menu.c	Sat Dec 29 14:47:40 2007 +0100
     1.3 @@ -0,0 +1,402 @@
     1.4 +/*
     1.5 + * MP3/MPlayer plugin to VDR (C++)
     1.6 + *
     1.7 + * (C) 2001-2007 Stefan Huelswitt <s.huelswitt@gmx.de>
     1.8 + *
     1.9 + * This code is free software; you can redistribute it and/or
    1.10 + * modify it under the terms of the GNU General Public License
    1.11 + * as published by the Free Software Foundation; either version 2
    1.12 + * of the License, or (at your option) any later version.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful,
    1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.17 + * GNU General Public License for more details.
    1.18 + *
    1.19 + * You should have received a copy of the GNU General Public License
    1.20 + * along with this program; if not, write to the Free Software
    1.21 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    1.22 + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
    1.23 + */
    1.24 +
    1.25 +#include <ctype.h>
    1.26 +#include <dirent.h>
    1.27 +#include <stdlib.h>
    1.28 +#include <stdio.h>
    1.29 +#include <errno.h>
    1.30 +#include <sys/stat.h>
    1.31 +#include <sys/ioctl.h>
    1.32 +#include <sys/types.h>
    1.33 +#include <unistd.h>
    1.34 +
    1.35 +#include "common.h"
    1.36 +#include "menu.h"
    1.37 +#include "data.h"
    1.38 +#include "data-src.h"
    1.39 +#include "i18n.h"
    1.40 +
    1.41 +// -----------------------------------------------------------------------------
    1.42 +
    1.43 +void Status(const char *text)
    1.44 +{
    1.45 +#if APIVERSNUM >= 10307
    1.46 +  Skins.Message(mtStatus,text);
    1.47 +#else
    1.48 +  if(text) {
    1.49 +    Interface->Status(text);
    1.50 +    Interface->Flush();
    1.51 +    }
    1.52 +#endif
    1.53 +}
    1.54 +
    1.55 +void Error(const char *text)
    1.56 +{
    1.57 +#if APIVERSNUM >= 10307
    1.58 +  Skins.Message(mtError,text);
    1.59 +#else
    1.60 +  Interface->Error(text);
    1.61 +#endif
    1.62 +}
    1.63 +
    1.64 +void Info(const char *text)
    1.65 +{
    1.66 +#if APIVERSNUM >= 10307
    1.67 +  Skins.Message(mtInfo,text);
    1.68 +#else
    1.69 +  Interface->Info(text);
    1.70 +#endif
    1.71 +}
    1.72 +
    1.73 +// --- cMenuBrowseItem ---------------------------------------------------------
    1.74 +
    1.75 +class cMenuBrowseItem : public cOsdItem {
    1.76 +  private:
    1.77 +  cFileObj *item;
    1.78 +  virtual void Set(void);
    1.79 +public:
    1.80 +  cMenuBrowseItem(cFileObj *Item);
    1.81 +  cFileObj *Item(void) { return item; }
    1.82 +  };
    1.83 +
    1.84 +cMenuBrowseItem::cMenuBrowseItem(cFileObj *Item)
    1.85 +{
    1.86 +  item = Item;
    1.87 +  Set();
    1.88 +}
    1.89 +
    1.90 +void cMenuBrowseItem::Set(void)
    1.91 +{
    1.92 +  char *buffer=0;
    1.93 +  asprintf(&buffer,item->Type()==otFile?"%s":"[%s]",item->Name());
    1.94 +  SetText(buffer,false);
    1.95 +}
    1.96 +
    1.97 +// --- cMenuBrowse ------------------------------------------------------
    1.98 +
    1.99 +cFileObj *cMenuBrowse::lastselect=0;
   1.100 +
   1.101 +cMenuBrowse::cMenuBrowse(cFileSource *Source, bool Dirselect, bool WithID3, const char *title, const char * const *Excl)
   1.102 +:cOsdMenu(title)
   1.103 +{
   1.104 +  currentdir=parent=0;
   1.105 +  delete lastselect; lastselect=0;
   1.106 +  list=new cDirList;
   1.107 +
   1.108 +  dirselectable=Dirselect;
   1.109 +  withID3=WithID3;
   1.110 +  excl=Excl;
   1.111 +
   1.112 +  SetSource(Source); 
   1.113 +  NewDir(currentdir);
   1.114 +}
   1.115 +
   1.116 +cMenuBrowse::~cMenuBrowse()
   1.117 +{
   1.118 +  free(parent);
   1.119 +  free(currentdir);
   1.120 +  delete list;
   1.121 +}
   1.122 +
   1.123 +cFileObj *cMenuBrowse::CurrentItem(void)
   1.124 +{
   1.125 +  cMenuBrowseItem *item = (cMenuBrowseItem *)Get(Current());
   1.126 +  return item ? item->Item():0;
   1.127 +}
   1.128 +
   1.129 +void cMenuBrowse::SetButtons(void)
   1.130 +{
   1.131 +  SetHelp(tr("Select"), currentdir?tr("Parent"):0, 0, withID3?tr("ID3 info"):0);
   1.132 +  Display();
   1.133 +}
   1.134 +
   1.135 +void cMenuBrowse::SetSource(cFileSource *Source)
   1.136 +{
   1.137 +  source=Source;
   1.138 +  free(currentdir); currentdir=0;
   1.139 +  free(parent); parent=0;
   1.140 +  source->GetRemember(currentdir,parent);
   1.141 +}
   1.142 +
   1.143 +bool cMenuBrowse::LoadDir(const char *dir)
   1.144 +{
   1.145 +  Clear();
   1.146 +  Status(tr("Scanning directory..."));
   1.147 +  bool res=list->Load(source,dir,excl);
   1.148 +  if(res) {
   1.149 +    cFileObj *item=list->First();
   1.150 +    while(item) {
   1.151 +      Add(new cMenuBrowseItem(item),(parent && !strcmp(item->Name(),parent)));
   1.152 +      item=list->Next(item);
   1.153 +      }
   1.154 +    }
   1.155 +  Status(0);
   1.156 +  return res;
   1.157 +}
   1.158 +
   1.159 +bool cMenuBrowse::NewDir(const char *dir)
   1.160 +{
   1.161 +  char *ncur=dir ? strdup(dir):0;
   1.162 +  bool r=LoadDir(ncur);
   1.163 +  if(!r && ncur) {
   1.164 +    free(ncur); ncur=0;
   1.165 +    r=LoadDir(ncur);
   1.166 +    }
   1.167 +  if(r) {
   1.168 +    free(currentdir); currentdir=ncur;
   1.169 +
   1.170 +    cFileObj *item=CurrentItem();
   1.171 +    source->SetRemember(currentdir,item?item->Name():0);
   1.172 +
   1.173 +    SetButtons();
   1.174 +    return true;
   1.175 +    }
   1.176 +  free(ncur);
   1.177 +  Error(tr("Error scanning directory!"));
   1.178 +  return false;
   1.179 +}
   1.180 +
   1.181 +eOSState cMenuBrowse::Parent(void)
   1.182 +{
   1.183 +  eOSState res=osContinue;
   1.184 +
   1.185 +  if(currentdir) {
   1.186 +    free(parent);
   1.187 +    char *ss=strrchr(currentdir,'/');
   1.188 +    if(ss) {
   1.189 +      *ss++=0;
   1.190 +      parent=strdup(ss);
   1.191 +      ss=currentdir;
   1.192 +      }
   1.193 +    else parent=strdup(currentdir);
   1.194 +
   1.195 +    if(!NewDir(ss)) res=osEnd;
   1.196 +    }
   1.197 +  return res;
   1.198 +}
   1.199 +
   1.200 +eOSState cMenuBrowse::Select(bool isred)
   1.201 +{
   1.202 +  eOSState res=osContinue;
   1.203 +  cFileObj *item;
   1.204 +
   1.205 +  if((item=CurrentItem())) {
   1.206 +    switch(item->Type()) {
   1.207 +      case otParent:
   1.208 +        if(!isred || !dirselectable)
   1.209 +          res=Parent();
   1.210 +        break;
   1.211 +      case otDir:
   1.212 +        if(!isred || !dirselectable) {
   1.213 +          if(!NewDir(item->Path())) res=osEnd;
   1.214 +          break;
   1.215 +          }
   1.216 +        // fall through to otFile
   1.217 +      case otFile:
   1.218 +        lastselect=new cFileObj(item);
   1.219 +        res=osBack;
   1.220 +        break;
   1.221 +      default:
   1.222 +        break;
   1.223 +      }
   1.224 +    } 
   1.225 +  return res;
   1.226 +}
   1.227 +
   1.228 +eOSState cMenuBrowse::ID3Info(void)
   1.229 +{
   1.230 +  return osContinue;
   1.231 +}
   1.232 +
   1.233 +eOSState cMenuBrowse::ProcessStdKey(eKeys Key, eOSState state)
   1.234 +{
   1.235 +  if(state==osUnknown) {
   1.236 +    switch (Key) {
   1.237 +      case kOk:     state=Select(false); break;
   1.238 +      case kRed:    state=Select(true); break;
   1.239 +      case kGreen:  state=Parent(); break;
   1.240 +      case kBlue:   if(withID3) state=ID3Info();
   1.241 +                    break;
   1.242 +      //case kMenu:   state=osEnd; break;
   1.243 +      default: break;
   1.244 +      }
   1.245 +    }
   1.246 +  if(state==osEnd || state==osBack) {
   1.247 +    cFileObj *item=CurrentItem();
   1.248 +    if(item) source->SetRemember(currentdir,item->Name());
   1.249 +    }
   1.250 +  return state;
   1.251 +}
   1.252 +
   1.253 +// --- cMenuSourceItem ----------------------------------------------------------
   1.254 +
   1.255 +class cMenuSourceItem : public cOsdItem {
   1.256 +  private:
   1.257 +  cFileSource *source;
   1.258 +  virtual void Set(void);
   1.259 +public:
   1.260 +  cMenuSourceItem(cFileSource *Source);
   1.261 +  cFileSource *Source(void) { return source; }
   1.262 +  };
   1.263 +
   1.264 +cMenuSourceItem::cMenuSourceItem(cFileSource *Source)
   1.265 +{
   1.266 +  source=Source;
   1.267 +  Set();
   1.268 +}
   1.269 +
   1.270 +void cMenuSourceItem::Set(void)
   1.271 +{
   1.272 +  char *buffer=0;
   1.273 +  asprintf(&buffer, "%s\t%s\t%s", source->NeedsMount()?(source->Status()?"*":">"):"", source->Description(), source->BaseDir());
   1.274 +  SetText(buffer,false);
   1.275 +}
   1.276 +
   1.277 +// --- cMenuSource --------------------------------------------------
   1.278 +
   1.279 +cFileSource *cMenuSource::selected=0;
   1.280 +
   1.281 +cMenuSource::cMenuSource(cFileSources *Sources, const char *title)
   1.282 +:cOsdMenu(title,2,20)
   1.283 +{
   1.284 +  selected=0;
   1.285 +  current=Sources->GetSource();
   1.286 +  cFileSource *source=Sources->First();
   1.287 +  while(source) {
   1.288 +    cOsdMenu::Add(new cMenuSourceItem(source),source==current);
   1.289 +    source=Sources->Next(source);
   1.290 +    }
   1.291 +
   1.292 +  SetHelp(tr("Select"), tr("Mount"), tr("Unmount"), tr("Eject"));
   1.293 +  Display();
   1.294 +}
   1.295 +
   1.296 +bool cMenuSource::DoMount(cFileSource *src)
   1.297 +{
   1.298 +  bool res=src->Mount();
   1.299 +  RefreshCurrent();
   1.300 +  DisplayCurrent(true);
   1.301 +  return res;
   1.302 +}
   1.303 +
   1.304 +bool cMenuSource::CheckMount(void)
   1.305 +{
   1.306 +  cFileSource *src=selected ? selected:current;
   1.307 +  if(src->NeedsMount() && !src->Status()) {
   1.308 +    Error(tr("Selected source is not mounted!"));
   1.309 +    return false;
   1.310 +    }
   1.311 +  return true;
   1.312 +}
   1.313 +
   1.314 +eOSState cMenuSource::Select(void)
   1.315 +{
   1.316 +  if(HasSubMenu() || Count() == 0) return osContinue;
   1.317 +
   1.318 +  cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   1.319 +  if(src->NeedsMount() && !src->Status()) {
   1.320 +    if(!DoMount(src)) Error(tr("Mount failed!"));
   1.321 +    }
   1.322 +  if(!src->NeedsMount() || src->Status()) {
   1.323 +    selected=src;
   1.324 +    return osBack;
   1.325 +    }
   1.326 +  return osContinue;
   1.327 +}
   1.328 +
   1.329 +eOSState cMenuSource::Mount(void)
   1.330 +{
   1.331 +  if(HasSubMenu() || Count() == 0) return osContinue;
   1.332 +
   1.333 +  cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   1.334 +  if(src->NeedsMount() && !src->Status()) {
   1.335 +    if(DoMount(src)) Info(tr("Mount succeeded"));
   1.336 +    else Error(tr("Mount failed!"));
   1.337 +    }
   1.338 +  return osContinue;
   1.339 +}
   1.340 +
   1.341 +eOSState cMenuSource::Unmount(void)
   1.342 +{
   1.343 +  if(HasSubMenu() || Count() == 0) return osContinue;
   1.344 +
   1.345 +  cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   1.346 +  if(src->NeedsMount() && src->Status()) {
   1.347 +    bool res=src->Unmount();
   1.348 +    RefreshCurrent();
   1.349 +    DisplayCurrent(true);
   1.350 +    if(res) Info(tr("Unmount succeeded"));
   1.351 +    else Error(tr("Unmount failed!"));
   1.352 +    }
   1.353 +  return osContinue;
   1.354 +}
   1.355 +
   1.356 +eOSState cMenuSource::Eject(void)
   1.357 +{
   1.358 +  if(HasSubMenu() || Count() == 0) return osContinue;
   1.359 +
   1.360 +  cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
   1.361 +  if(src->NeedsMount()) {
   1.362 +    bool res=src->Eject();
   1.363 +    RefreshCurrent();
   1.364 +    DisplayCurrent(true);
   1.365 +    if(!res) Error(tr("Eject failed!"));
   1.366 +    }
   1.367 +  return osContinue;
   1.368 +}
   1.369 +
   1.370 +eOSState cMenuSource::ProcessKey(eKeys Key)
   1.371 +{
   1.372 +  eOSState state = cOsdMenu::ProcessKey(Key);
   1.373 +
   1.374 +  if(state==osBack && !CheckMount()) state=osContinue;
   1.375 +  if(state==osUnknown) {
   1.376 +     switch(Key) {
   1.377 +       case kOk:     
   1.378 +       case kRed:    return Select();
   1.379 +       case kGreen:  return Mount();
   1.380 +       case kYellow: return Unmount();
   1.381 +       case kBlue:   return Eject();
   1.382 +       case kMenu:   CheckMount(); return osEnd;
   1.383 +       default: break;
   1.384 +       }
   1.385 +     }
   1.386 +  return state;
   1.387 +}
   1.388 +
   1.389 +// --- cProgressBar ------------------------------------------------------------
   1.390 +
   1.391 +cProgressBar::cProgressBar(int Width, int Height, int Current, int Total)
   1.392 +:cBitmap(Width, Height, 2)
   1.393 +{
   1.394 +  if(Total > 0) {
   1.395 +    int p = Current * Width / Total;;
   1.396 +#if APIVERSNUM >= 10307
   1.397 +    DrawRectangle(0, 0, p, Height - 1, clrGreen);
   1.398 +    DrawRectangle(p + 1, 0, Width - 1, Height - 1, clrWhite);
   1.399 +#else
   1.400 +    Fill(0, 0, p, Height - 1, clrGreen);
   1.401 +    Fill(p + 1, 0, Width - 1, Height - 1, clrWhite);
   1.402 +#endif
   1.403 +    }
   1.404 +}
   1.405 +