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