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