mplayer.c
author nathan
Sat, 29 Dec 2007 14:47:40 +0100
branchtrunk
changeset 0 474a1293c3c0
child 2 4c1f7b705009
permissions -rw-r--r--
release 0.10.0
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 <getopt.h>
nathan@0
    23
#include <malloc.h>
nathan@0
    24
#include <stdlib.h>
nathan@0
    25
#include <ctype.h>
nathan@0
    26
nathan@0
    27
#include "common.h"
nathan@0
    28
nathan@0
    29
#include <vdr/plugin.h>
nathan@0
    30
#include <vdr/player.h>
nathan@0
    31
#include <vdr/status.h>
nathan@0
    32
#include <vdr/font.h>
nathan@0
    33
#include <vdr/osdbase.h>
nathan@0
    34
#include <vdr/menuitems.h>
nathan@0
    35
#ifdef HAVE_BEAUTYPATCH
nathan@0
    36
#include <vdr/fontsym.h>
nathan@0
    37
#endif
nathan@0
    38
#if APIVERSNUM >= 10307
nathan@0
    39
#include <vdr/skins.h>
nathan@0
    40
#endif
nathan@0
    41
#if APIVERSNUM >= 10332
nathan@0
    42
#include <vdr/remote.h>
nathan@0
    43
#endif
nathan@0
    44
nathan@0
    45
#if APIVERSNUM > 10307
nathan@0
    46
#include <vdr/menu.h>
nathan@0
    47
#elif APIVERSNUM == 10307
nathan@0
    48
class cMenuText : public cOsdMenu {
nathan@0
    49
private:
nathan@0
    50
  char *text;
nathan@0
    51
public:
nathan@0
    52
  cMenuText(const char *Title, const char *Text, eDvbFont Font = fontOsd);
nathan@0
    53
  virtual ~cMenuText();
nathan@0
    54
  void SetText(const char *Text);
nathan@0
    55
  virtual void Display(void);
nathan@0
    56
  virtual eOSState ProcessKey(eKeys Key);
nathan@0
    57
  };
nathan@0
    58
#else
nathan@0
    59
class cMenuText : public cOsdMenu {
nathan@0
    60
public:
nathan@0
    61
  cMenuText(const char *Title, const char *Text, eDvbFont Font = fontOsd);
nathan@0
    62
  virtual eOSState ProcessKey(eKeys Key);
nathan@0
    63
  };
nathan@0
    64
#endif
nathan@0
    65
nathan@0
    66
#include "setup.h"
nathan@0
    67
#include "setup-mplayer.h"
nathan@0
    68
#include "menu.h"
nathan@0
    69
#include "player-mplayer.h"
nathan@0
    70
#include "data.h"
nathan@0
    71
#include "data-src.h"
nathan@0
    72
#include "i18n.h"
nathan@0
    73
#include "version.h"
nathan@0
    74
#include "service.h"
nathan@0
    75
nathan@0
    76
const char *sourcesSub=0;
nathan@0
    77
cFileSources MPlaySources;
nathan@0
    78
nathan@0
    79
// --- cMenuSetupMPlayer --------------------------------------------------------
nathan@0
    80
nathan@0
    81
class cMenuSetupMPlayer : public cMenuSetupPage {
nathan@0
    82
private:
nathan@0
    83
  cMPlayerSetup data;
nathan@0
    84
  const char *res[3];
nathan@0
    85
protected:
nathan@0
    86
  virtual void Store(void);
nathan@0
    87
public:
nathan@0
    88
  cMenuSetupMPlayer(void);
nathan@0
    89
  };
nathan@0
    90
nathan@0
    91
cMenuSetupMPlayer::cMenuSetupMPlayer(void)
nathan@0
    92
{
nathan@0
    93
  data=MPlayerSetup;
nathan@0
    94
  SetSection(tr("MPlayer"));
nathan@0
    95
  Add(new cMenuEditBoolItem(tr("Setup.MPlayer$Control mode"),  &data.SlaveMode, tr("Traditional"), tr("Slave")));
nathan@0
    96
#if APIVERSNUM < 10307
nathan@0
    97
  Add(new cMenuEditIntItem( tr("Setup.MPlayer$OSD position"),  &data.OsdPos, 0, 6));
nathan@0
    98
#endif
nathan@0
    99
  res[0]=tr("disabled");
nathan@0
   100
  res[1]=tr("global only");
nathan@0
   101
  res[2]=tr("local first");
nathan@0
   102
  Add(new cMenuEditStraItem(tr("Setup.MPlayer$Resume mode"),   &data.ResumeMode, 3, res));
nathan@0
   103
  Add(new cMenuEditBoolItem(tr("Hide mainmenu entry"),         &data.HideMainMenu));
nathan@0
   104
  for(int i=0; i<10; i++) {
nathan@0
   105
    char name[32];
nathan@0
   106
    snprintf(name,sizeof(name),"%s %d",tr("Setup.MPlayer$Slave command key"),i);
nathan@0
   107
    static const char allowed[] = { "abcdefghijklmnopqrstuvwxyz0123456789!\"§$%&/()=?{}[]\\+*~#',;.:-_<>|@´`^°" };
nathan@0
   108
    Add(new cMenuEditStrItem(name, data.KeyCmd[i],MAX_KEYCMD,allowed));
nathan@0
   109
    }
nathan@0
   110
}
nathan@0
   111
nathan@0
   112
void cMenuSetupMPlayer::Store(void)
nathan@0
   113
{
nathan@0
   114
  MPlayerSetup=data;
nathan@0
   115
  SetupStore("ControlMode", MPlayerSetup.SlaveMode);
nathan@0
   116
  SetupStore("HideMainMenu",MPlayerSetup.HideMainMenu);
nathan@0
   117
  SetupStore("ResumeMode",  MPlayerSetup.ResumeMode);
nathan@0
   118
#if APIVERSNUM < 10307
nathan@0
   119
  SetupStore("OsdPos",      MPlayerSetup.OsdPos);
nathan@0
   120
#endif
nathan@0
   121
  for(int i=0; i<10; i++) {
nathan@0
   122
    char name[16];
nathan@0
   123
    snprintf(name,sizeof(name),"KeyCmd%d",i);
nathan@0
   124
    SetupStore(name,MPlayerSetup.KeyCmd[i]);
nathan@0
   125
    }
nathan@0
   126
}
nathan@0
   127
nathan@0
   128
// --- cMPlayerControl ---------------------------------------------------------
nathan@0
   129
nathan@0
   130
class cMPlayerControl : public cControl {
nathan@0
   131
private:
nathan@0
   132
  static cFileObj *file;
nathan@0
   133
  static bool rewind;
nathan@0
   134
  cMPlayerPlayer *player;
nathan@0
   135
#if APIVERSNUM >= 10307
nathan@0
   136
  cSkinDisplayReplay *display;
nathan@0
   137
#endif
nathan@0
   138
  bool visible, modeOnly, haveBeauty;
nathan@0
   139
  time_t timeoutShow;
nathan@0
   140
  int lastCurrent, lastTotal;
nathan@0
   141
  char *lastReplayMsg;
nathan@0
   142
  //
nathan@0
   143
  bool jumpactive, jumphide, jumpmode;
nathan@0
   144
  int jumpval;
nathan@0
   145
  //
nathan@0
   146
  void Stop(void);
nathan@0
   147
  void ShowTimed(int Seconds=0);
nathan@0
   148
  void DisplayAtBottom(const char *s);
nathan@0
   149
  void ShowProgress(void);
nathan@0
   150
  void ShowMode(void);
nathan@0
   151
  void ShowTitle(void);
nathan@0
   152
  void Jump(void);
nathan@0
   153
  void JumpProcess(eKeys Key);
nathan@0
   154
  void JumpDisplay(void);
nathan@0
   155
public:
nathan@0
   156
  cMPlayerControl(void);
nathan@0
   157
  virtual ~cMPlayerControl();
nathan@0
   158
  virtual eOSState ProcessKey(eKeys Key);
nathan@0
   159
  virtual void Show(void) { ShowTimed(); }
nathan@0
   160
  virtual void Hide(void);
nathan@0
   161
  static void SetFile(const cFileObj *File, bool Rewind);
nathan@0
   162
  };
nathan@0
   163
nathan@0
   164
cFileObj *cMPlayerControl::file=0;
nathan@0
   165
bool cMPlayerControl::rewind=false;
nathan@0
   166
nathan@0
   167
cMPlayerControl::cMPlayerControl(void)
nathan@0
   168
:cControl(player=new cMPlayerPlayer(file,rewind))
nathan@0
   169
{
nathan@0
   170
  visible=modeOnly=jumpactive=haveBeauty=false;
nathan@0
   171
  lastReplayMsg=0;
nathan@0
   172
#if APIVERSNUM >= 10307
nathan@0
   173
  display=0;
nathan@0
   174
#else
nathan@0
   175
#ifdef HAVE_BEAUTYPATCH
nathan@0
   176
#if APIVERSNUM >= 10300
nathan@0
   177
  const cFont *sym=cFont::GetFont(fontSym);
nathan@0
   178
  const cFont *osd=cFont::GetFont(fontOsd);
nathan@0
   179
  const cFont::tCharData *symD=sym->CharData(32);
nathan@0
   180
  const cFont::tCharData *osdD=osd->CharData(32);
nathan@0
   181
#else //APIVERSNUM >= 10300
nathan@0
   182
  cFont *sym=new cFont(fontSym);
nathan@0
   183
  cFont *osd=new cFont(fontOsd);
nathan@0
   184
  const cFont::tCharData *symD=sym->CharData(32);
nathan@0
   185
  const cFont::tCharData *osdD=osd->CharData(32);
nathan@0
   186
  delete sym;
nathan@0
   187
  delete osd;
nathan@0
   188
#endif //APIVERSNUM >= 10300
nathan@0
   189
  if(symD != osdD) haveBeauty=true;
nathan@0
   190
  d(printf("mplayer: beauty patch %sdetected\n",haveBeauty?"":"NOT "))
nathan@0
   191
#endif //HAVE_BEAUTYPATCH
nathan@0
   192
#endif //APIVERSNUM >= 10307
nathan@0
   193
  ShowTitle();
nathan@0
   194
}
nathan@0
   195
nathan@0
   196
cMPlayerControl::~cMPlayerControl()
nathan@0
   197
{
nathan@0
   198
  Stop();
nathan@0
   199
#if APIVERSNUM >= 10338
nathan@0
   200
  cStatus::MsgReplaying(this,0,0,false);
nathan@0
   201
#else
nathan@0
   202
  cStatus::MsgReplaying(this, NULL);
nathan@0
   203
#endif
nathan@0
   204
  free(lastReplayMsg);
nathan@0
   205
}
nathan@0
   206
nathan@0
   207
void cMPlayerControl::SetFile(const cFileObj *File, bool Rewind)
nathan@0
   208
{
nathan@0
   209
  delete file;
nathan@0
   210
  file=File ? new cFileObj(File) : 0;
nathan@0
   211
  rewind=Rewind;
nathan@0
   212
}
nathan@0
   213
nathan@0
   214
void cMPlayerControl::Stop(void)
nathan@0
   215
{
nathan@0
   216
  delete player; player=0;
nathan@0
   217
}
nathan@0
   218
nathan@0
   219
void cMPlayerControl::ShowTimed(int Seconds)
nathan@0
   220
{
nathan@0
   221
  if(modeOnly) Hide();
nathan@0
   222
  if(!visible) {
nathan@0
   223
    ShowProgress();
nathan@0
   224
    timeoutShow = Seconds>0 ? time(0)+Seconds : 0;
nathan@0
   225
    }
nathan@0
   226
}
nathan@0
   227
nathan@0
   228
void cMPlayerControl::Hide(void)
nathan@0
   229
{
nathan@0
   230
  if(visible) {
nathan@0
   231
#if APIVERSNUM >= 10307
nathan@0
   232
    delete display; display=0;
nathan@0
   233
#else
nathan@0
   234
    Interface->Close();
nathan@0
   235
#endif
nathan@0
   236
    visible=modeOnly=false;
nathan@0
   237
#if APIVERSNUM >= 10500
nathan@0
   238
    SetNeedsFastResponse(false);
nathan@0
   239
#else
nathan@0
   240
    needsFastResponse=false;
nathan@0
   241
#endif
nathan@0
   242
    }
nathan@0
   243
}
nathan@0
   244
nathan@0
   245
void cMPlayerControl::DisplayAtBottom(const char *s)
nathan@0
   246
{
nathan@0
   247
#if APIVERSNUM < 10307
nathan@0
   248
  const int p=modeOnly ? 0 : 2;
nathan@0
   249
  if(s) {
nathan@0
   250
    const int d=max(Width()-cOsd::WidthInCells(s),0) / 2;
nathan@0
   251
    if(modeOnly) Interface->Fill(0, p, Interface->Width(), 1, clrTransparent);
nathan@0
   252
    Interface->Write(d, p, s);
nathan@0
   253
    }
nathan@0
   254
  else
nathan@0
   255
    Interface->Fill(12, p, Width() - 22, 1, clrBackground);
nathan@0
   256
#endif
nathan@0
   257
}
nathan@0
   258
nathan@0
   259
void cMPlayerControl::ShowTitle(void)
nathan@0
   260
{
nathan@0
   261
  const char *path=0;
nathan@0
   262
  bool release=true;
nathan@0
   263
  if(player) path=player->GetCurrentName();
nathan@0
   264
  if(!path) {
nathan@0
   265
    path=file->FullPath();
nathan@0
   266
    release=false;
nathan@0
   267
    }
nathan@0
   268
  if(path) {
nathan@0
   269
    const char *name=rindex(path,'/');
nathan@0
   270
    if(name) name++; else name=path;
nathan@0
   271
    if(!lastReplayMsg || strcmp(lastReplayMsg,path)) {
nathan@0
   272
#if APIVERSNUM >= 10338
nathan@0
   273
      cStatus::MsgReplaying(this,name,path,true);
nathan@0
   274
#else
nathan@0
   275
      cStatus::MsgReplaying(this,path);
nathan@0
   276
#endif
nathan@0
   277
      free(lastReplayMsg);
nathan@0
   278
      lastReplayMsg=strdup(path);
nathan@0
   279
      }
nathan@0
   280
    if(visible) {
nathan@0
   281
#if APIVERSNUM >= 10307
nathan@0
   282
      if(display) display->SetTitle(name);
nathan@0
   283
#else
nathan@0
   284
      int n=strlen(name);
nathan@0
   285
      if(n>Width()) {
nathan@0
   286
        n=n-Width()+4; if(n<0) n=0;
nathan@0
   287
        char str[72];
nathan@0
   288
        snprintf(str,sizeof(str),"... %s",name+n);
nathan@0
   289
        Interface->Write(0,0,str);
nathan@0
   290
        }
nathan@0
   291
      else Interface->Write(0,0,name);
nathan@0
   292
#endif
nathan@0
   293
      }
nathan@0
   294
    }
nathan@0
   295
  if(release) free((void *)path);
nathan@0
   296
}
nathan@0
   297
nathan@0
   298
void cMPlayerControl::ShowProgress(void)
nathan@0
   299
{
nathan@0
   300
  int Current, Total;
nathan@0
   301
nathan@0
   302
  if(GetIndex(Current,Total) && Total>0) {
nathan@0
   303
    bool flush=false;
nathan@0
   304
    if(!visible) {
nathan@0
   305
#if APIVERSNUM >= 10307
nathan@0
   306
      display=Skins.Current()->DisplayReplay(false);
nathan@0
   307
#else
nathan@0
   308
      Interface->Open(Setup.OSDwidth,-MPlayerSetup.OsdPos-3);
nathan@0
   309
      Interface->Clear();
nathan@0
   310
      if(MPlayerSetup.OsdPos>0) Interface->Fill(0,3,Interface->Width(),MPlayerSetup.OsdPos,clrTransparent);
nathan@0
   311
#endif
nathan@0
   312
      visible=true; modeOnly=false;
nathan@0
   313
#if APIVERSNUM >= 10500
nathan@0
   314
      SetNeedsFastResponse(true);
nathan@0
   315
#else
nathan@0
   316
      needsFastResponse=true;
nathan@0
   317
#endif
nathan@0
   318
      lastCurrent=lastTotal=-1;
nathan@0
   319
      flush=true;
nathan@0
   320
      }
nathan@0
   321
nathan@0
   322
    if(abs(Current-lastCurrent)>12) {
nathan@0
   323
#if APIVERSNUM >= 10307
nathan@0
   324
      if(Total>0) display->SetProgress(Current, Total);
nathan@0
   325
      display->SetCurrent(IndexToHMSF(Current));
nathan@0
   326
      display->SetTotal(IndexToHMSF(Total));
nathan@0
   327
      bool Play, Forward;
nathan@0
   328
      int Speed;
nathan@0
   329
      if(GetReplayMode(Play,Forward,Speed)) 
nathan@0
   330
        display->SetMode(Play, Forward, Speed);
nathan@0
   331
#else
nathan@0
   332
      cProgressBar ProgressBar(Width() * cOsd::CellWidth(), cOsd::LineHeight(), Current, Total);
nathan@0
   333
      Interface->SetBitmap(0, cOsd::LineHeight(), ProgressBar);
nathan@0
   334
      Interface->Write(0,2,IndexToHMSF(Current));
nathan@0
   335
      Interface->Write(-7,2,IndexToHMSF(Total));
nathan@0
   336
#endif
nathan@0
   337
      ShowTitle();
nathan@0
   338
      flush=true;
nathan@0
   339
      lastCurrent=Current; lastTotal=Total;
nathan@0
   340
      }
nathan@0
   341
    if(flush) 
nathan@0
   342
#if APIVERSNUM >= 10307
nathan@0
   343
      Skins.Flush();
nathan@0
   344
#else
nathan@0
   345
      Interface->Flush();
nathan@0
   346
#endif
nathan@0
   347
    ShowMode();
nathan@0
   348
    }
nathan@0
   349
}
nathan@0
   350
nathan@0
   351
#if APIVERSNUM < 10307
nathan@0
   352
#ifdef HAVE_BEAUTYPATCH
nathan@0
   353
int forwSym[] = { FSYM_FORW,FSYM_FORW1,FSYM_FORW2,FSYM_FORW3 };
nathan@0
   354
int backSym[] = { FSYM_BACK,FSYM_BACK1,FSYM_BACK2,FSYM_BACK3 };
nathan@0
   355
#endif
nathan@0
   356
#endif
nathan@0
   357
nathan@0
   358
void cMPlayerControl::ShowMode(void)
nathan@0
   359
{
nathan@0
   360
  if(Setup.ShowReplayMode && !jumpactive) {
nathan@0
   361
    bool Play, Forward;
nathan@0
   362
    int Speed;
nathan@0
   363
    if(GetReplayMode(Play, Forward, Speed)) {
nathan@0
   364
       bool NormalPlay = (Play && Speed == -1);
nathan@0
   365
nathan@0
   366
       if(!visible) {
nathan@0
   367
         if(NormalPlay) return;
nathan@0
   368
#if APIVERSNUM >= 10307
nathan@0
   369
         display = Skins.Current()->DisplayReplay(true);
nathan@0
   370
#else
nathan@0
   371
         Interface->Open(0,-MPlayerSetup.OsdPos-1);
nathan@0
   372
#endif
nathan@0
   373
         visible=modeOnly=true;
nathan@0
   374
         }
nathan@0
   375
nathan@0
   376
       if(modeOnly && !timeoutShow && NormalPlay) timeoutShow=time(0)+SELECTHIDE_TIMEOUT;
nathan@0
   377
nathan@0
   378
#if APIVERSNUM >= 10307
nathan@0
   379
       display->SetMode(Play, Forward, Speed);
nathan@0
   380
#else
nathan@0
   381
       char buf[16];
nathan@0
   382
       eDvbFont OldFont;
nathan@0
   383
#ifdef HAVE_BEAUTYPATCH
nathan@0
   384
       if(haveBeauty) {
nathan@0
   385
         int i=0;
nathan@0
   386
         if(!(Width()&1)) buf[i++]=' ';
nathan@0
   387
         buf[i]=FSYM_EMPTY; if(Speed>=0 && !Forward) buf[i]=backSym[Speed];
nathan@0
   388
         i++;
nathan@0
   389
         buf[i++]=Play?(Speed==-1?FSYM_PLAY:FSYM_EMPTY):FSYM_PAUSE;
nathan@0
   390
         buf[i]=FSYM_EMPTY; if(Speed>=0 && Forward) buf[i]=forwSym[Speed];
nathan@0
   391
         i++;
nathan@0
   392
         if(!(Width()&1)) buf[i++]=' ';
nathan@0
   393
         buf[i]=0;
nathan@0
   394
         OldFont = Interface->SetFont(fontSym);
nathan@0
   395
         }
nathan@0
   396
       else {
nathan@0
   397
#endif //HAVE_BEAUTYPATCH
nathan@0
   398
         const char *Mode;
nathan@0
   399
         if (Speed == -1) Mode = Play    ? "  >  " : " ||  ";
nathan@0
   400
         else if (Play)   Mode = Forward ? " X>> " : " <<X ";
nathan@0
   401
         else             Mode = Forward ? " X|> " : " <|X ";
nathan@0
   402
         strn0cpy(buf, Mode, sizeof(buf));
nathan@0
   403
         char *p = strchr(buf, 'X');
nathan@0
   404
         if(p) *p = Speed > 0 ? '1' + Speed - 1 : ' ';
nathan@0
   405
         OldFont = Interface->SetFont(fontFix);
nathan@0
   406
#ifdef HAVE_BEAUTYPATCH
nathan@0
   407
         }
nathan@0
   408
#endif //HAVE_BEAUTYPATCH
nathan@0
   409
       DisplayAtBottom(buf);
nathan@0
   410
       Interface->SetFont(OldFont);
nathan@0
   411
#endif //APIVERSNUM >= 10307
nathan@0
   412
       }
nathan@0
   413
    }
nathan@0
   414
}
nathan@0
   415
nathan@0
   416
void cMPlayerControl::JumpDisplay(void)
nathan@0
   417
{
nathan@0
   418
  char buf[64];
nathan@0
   419
  const char *j=tr("Jump: "), u=jumpmode?'%':'m';
nathan@0
   420
  if(!jumpval) sprintf(buf,"%s- %c",  j,u);
nathan@0
   421
  else         sprintf(buf,"%s%d- %c",j,jumpval,u);
nathan@0
   422
#if APIVERSNUM >= 10307
nathan@0
   423
  display->SetJump(buf);
nathan@0
   424
#else
nathan@0
   425
  DisplayAtBottom(buf);
nathan@0
   426
#endif
nathan@0
   427
}
nathan@0
   428
nathan@0
   429
void cMPlayerControl::JumpProcess(eKeys Key)
nathan@0
   430
{
nathan@0
   431
  const int n=Key-k0;
nathan@0
   432
  switch (Key) {
nathan@0
   433
    case k0 ... k9:
nathan@0
   434
      {
nathan@0
   435
      const int max=jumpmode?100:lastTotal;
nathan@0
   436
      if(jumpval*10+n <= max) jumpval=jumpval*10+n;
nathan@0
   437
      JumpDisplay();
nathan@0
   438
      }
nathan@0
   439
      break;
nathan@0
   440
    case kBlue:
nathan@0
   441
      jumpmode=!jumpmode; jumpval=0;
nathan@0
   442
      DisplayAtBottom(0); JumpDisplay();
nathan@0
   443
      break;
nathan@0
   444
    case kPlay:
nathan@0
   445
    case kUp:
nathan@0
   446
      player->Goto(jumpval*(jumpmode?1:60),jumpmode,false);
nathan@0
   447
      jumpactive=false;
nathan@0
   448
      break;
nathan@0
   449
    case kFastRew:
nathan@0
   450
    case kFastFwd:
nathan@0
   451
    case kLeft:
nathan@0
   452
    case kRight:
nathan@0
   453
      if(!jumpmode) {
nathan@0
   454
        player->SkipSeconds(jumpval*60 * ((Key==kLeft || Key==kFastRew) ? -1:1));
nathan@0
   455
        jumpactive=false;
nathan@0
   456
        }
nathan@0
   457
      break;
nathan@0
   458
    default:
nathan@0
   459
      jumpactive=false;
nathan@0
   460
      break;
nathan@0
   461
    }
nathan@0
   462
nathan@0
   463
  if(!jumpactive) {
nathan@0
   464
    if(jumphide) Hide();
nathan@0
   465
    else 
nathan@0
   466
#if APIVERSNUM >= 10307
nathan@0
   467
      display->SetJump(0);
nathan@0
   468
#else
nathan@0
   469
      DisplayAtBottom(0);
nathan@0
   470
#endif
nathan@0
   471
    }
nathan@0
   472
}
nathan@0
   473
nathan@0
   474
void cMPlayerControl::Jump(void)
nathan@0
   475
{
nathan@0
   476
  jumpval=0; jumphide=jumpmode=false;
nathan@0
   477
  if(!visible) {
nathan@0
   478
    ShowTimed(); if(!visible) return;
nathan@0
   479
    jumphide=true;
nathan@0
   480
    }
nathan@0
   481
  JumpDisplay();
nathan@0
   482
  jumpactive=true;
nathan@0
   483
}
nathan@0
   484
nathan@0
   485
eOSState cMPlayerControl::ProcessKey(eKeys Key)
nathan@0
   486
{
nathan@0
   487
  if(!player->Active()) { Hide(); Stop(); return osEnd; }
nathan@0
   488
nathan@0
   489
  if(!player->SlaveMode()) {
nathan@0
   490
    if(Key==kBlue) { Hide(); Stop(); return osEnd; }
nathan@0
   491
    }
nathan@0
   492
  else {
nathan@0
   493
    if(visible) {
nathan@0
   494
      if(timeoutShow && time(0)>timeoutShow) {
nathan@0
   495
        Hide(); ShowMode();
nathan@0
   496
        timeoutShow = 0;
nathan@0
   497
        }
nathan@0
   498
      else {
nathan@0
   499
        if(modeOnly) ShowMode();
nathan@0
   500
        else ShowProgress();
nathan@0
   501
        }
nathan@0
   502
      }
nathan@0
   503
    else ShowTitle();
nathan@0
   504
nathan@0
   505
    if(jumpactive && Key != kNone) {
nathan@0
   506
      JumpProcess(Key);
nathan@0
   507
      return osContinue;
nathan@0
   508
      }
nathan@0
   509
nathan@0
   510
    bool DoShowMode = true;
nathan@0
   511
    switch (Key) {
nathan@0
   512
      case kPlay:
nathan@0
   513
      case kUp:      player->Play(); break;
nathan@0
   514
nathan@0
   515
      case kPause:
nathan@0
   516
      case kDown:    player->Pause(); break;
nathan@0
   517
nathan@0
   518
      case kFastRew|k_Repeat:
nathan@0
   519
      case kFastRew:
nathan@0
   520
      case kLeft|k_Repeat:
nathan@0
   521
      case kLeft:    player->SkipSeconds(-10); break;
nathan@0
   522
nathan@0
   523
      case kFastFwd|k_Repeat:
nathan@0
   524
      case kFastFwd:
nathan@0
   525
      case kRight|k_Repeat:
nathan@0
   526
      case kRight:   player->SkipSeconds(10); break;
nathan@0
   527
nathan@0
   528
      case kRed:     Jump(); break;
nathan@0
   529
nathan@0
   530
      case kGreen|k_Repeat:                      // temporary use
nathan@0
   531
      case kGreen:   player->SkipSeconds(-60); break;
nathan@0
   532
      case kYellow|k_Repeat:
nathan@0
   533
      case kYellow:  player->SkipSeconds(60); break;
nathan@0
   534
  //    case kGreen|k_Repeat:                      // reserved for future use
nathan@0
   535
  //    case kGreen:   player->SkipPrev(); break;
nathan@0
   536
  //    case kYellow|k_Repeat:
nathan@0
   537
  //    case kYellow:  player->SkipNext(); break;
nathan@0
   538
nathan@0
   539
      case kBack:
nathan@0
   540
#if APIVERSNUM >= 10332
nathan@0
   541
                     Hide();
nathan@0
   542
                     cRemote::CallPlugin(i18n_name);
nathan@0
   543
                     return osBack;
nathan@0
   544
#endif
nathan@0
   545
      case kStop:
nathan@0
   546
      case kBlue:    Hide(); Stop(); return osEnd;
nathan@0
   547
nathan@0
   548
      default:
nathan@0
   549
        DoShowMode = false;
nathan@0
   550
        switch(Key) {
nathan@0
   551
          case kOk: if(visible && !modeOnly) { Hide(); DoShowMode=true; }
nathan@0
   552
                    else ShowTimed();
nathan@0
   553
                    break;
nathan@0
   554
          case k0:
nathan@0
   555
          case k1:
nathan@0
   556
          case k2:
nathan@0
   557
          case k3:
nathan@0
   558
          case k4:
nathan@0
   559
          case k5:
nathan@0
   560
          case k6:
nathan@0
   561
          case k7:
nathan@0
   562
          case k8:
nathan@0
   563
          case k9:  {
nathan@0
   564
                    const char *cmd=MPlayerSetup.KeyCmd[Key-k0];
nathan@0
   565
                    if(cmd[0]) player->KeyCmd(cmd);
nathan@0
   566
                    }
nathan@0
   567
                    break;
nathan@0
   568
          default:  break;
nathan@0
   569
          }
nathan@0
   570
        break;
nathan@0
   571
      }
nathan@0
   572
nathan@0
   573
    if(DoShowMode) ShowMode();
nathan@0
   574
    }
nathan@0
   575
  return osContinue;
nathan@0
   576
}
nathan@0
   577
nathan@0
   578
// --- cMenuMPlayAid -----------------------------------------------------------
nathan@0
   579
nathan@0
   580
class cMenuMPlayAid : public cOsdMenu {
nathan@0
   581
public:
nathan@0
   582
  cMenuMPlayAid(void);
nathan@0
   583
  virtual eOSState ProcessKey(eKeys Key);
nathan@0
   584
  };
nathan@0
   585
nathan@0
   586
cMenuMPlayAid::cMenuMPlayAid(void)
nathan@0
   587
:cOsdMenu(tr("MPlayer Audio ID"),20)
nathan@0
   588
{
nathan@0
   589
  Add(new cMenuEditIntItem(tr("Audiostream ID"),&MPlayerAid,-1,255));
nathan@0
   590
  Display();
nathan@0
   591
}
nathan@0
   592
nathan@0
   593
eOSState cMenuMPlayAid::ProcessKey(eKeys Key)
nathan@0
   594
{
nathan@0
   595
  eOSState state=cOsdMenu::ProcessKey(Key);
nathan@0
   596
  if(state==osUnknown) {
nathan@0
   597
    switch(Key) {
nathan@0
   598
      case kOk: state=osBack; break;
nathan@0
   599
      default:  break;
nathan@0
   600
      }
nathan@0
   601
    }
nathan@0
   602
  return state;
nathan@0
   603
}
nathan@0
   604
nathan@0
   605
// --- cMenuMPlayBrowse ---------------------------------------------------------
nathan@0
   606
nathan@0
   607
class cMenuMPlayBrowse : public cMenuBrowse {
nathan@0
   608
private:
nathan@0
   609
  bool sourcing, aidedit;
nathan@0
   610
  eOSState Source(bool second);
nathan@0
   611
  eOSState Summary(void);
nathan@0
   612
protected:
nathan@0
   613
  virtual void SetButtons(void);
nathan@0
   614
public:
nathan@0
   615
  cMenuMPlayBrowse(void);
nathan@0
   616
  virtual eOSState ProcessKey(eKeys Key);
nathan@0
   617
  };
nathan@0
   618
nathan@0
   619
static const char *excl_sum[] = { ".*","*.summary","*.txt","*.nfo",0 };
nathan@0
   620
nathan@0
   621
cMenuMPlayBrowse::cMenuMPlayBrowse(void)
nathan@0
   622
:cMenuBrowse(MPlaySources.GetSource(),false,false,tr("MPlayer browser"),excl_sum)
nathan@0
   623
{
nathan@0
   624
  sourcing=aidedit=false;
nathan@0
   625
  SetButtons();
nathan@0
   626
}
nathan@0
   627
nathan@0
   628
void cMenuMPlayBrowse::SetButtons(void)
nathan@0
   629
{
nathan@0
   630
  static char blue[12];
nathan@0
   631
  snprintf(blue,sizeof(blue),MPlayerAid>=0 ? "AID:%d" : "AID:def",MPlayerAid);
nathan@0
   632
  SetHelp(tr(BUTTON"Play"), MPlayerSetup.ResumeMode ? tr(BUTTON"Rewind"):0, tr("Source"), blue);
nathan@0
   633
  Display();
nathan@0
   634
}
nathan@0
   635
nathan@0
   636
eOSState cMenuMPlayBrowse::Source(bool second)
nathan@0
   637
{
nathan@0
   638
  if(HasSubMenu()) return osContinue;
nathan@0
   639
nathan@0
   640
  if(!second) {
nathan@0
   641
    sourcing=true;
nathan@0
   642
    return AddSubMenu(new cMenuSource(&MPlaySources,tr("MPlayer source")));
nathan@0
   643
    }
nathan@0
   644
  sourcing=false;
nathan@0
   645
  cFileSource *src=cMenuSource::GetSelected();
nathan@0
   646
  if(src) {
nathan@0
   647
    MPlaySources.SetSource(src);
nathan@0
   648
    SetSource(src);
nathan@0
   649
    NewDir(0);
nathan@0
   650
    }
nathan@0
   651
  return osContinue;
nathan@0
   652
}
nathan@0
   653
nathan@0
   654
eOSState cMenuMPlayBrowse::Summary(void)
nathan@0
   655
{
nathan@0
   656
  cFileObj *item=CurrentItem();
nathan@0
   657
  if(item && item->Type()==otFile) {
nathan@0
   658
    static const char *exts[] = { ".summary",".txt",".nfo",0 };
nathan@0
   659
    for(int i=0; exts[i]; i++) {
nathan@0
   660
      char buff[4096];
nathan@0
   661
      strn0cpy(buff,item->FullPath(),sizeof(buff)-20);
nathan@0
   662
      char *e=&buff[strlen(buff)];
nathan@0
   663
      strn0cpy(e,exts[i],20);
nathan@0
   664
      int fd=open(buff,O_RDONLY);
nathan@0
   665
      *e=0;
nathan@0
   666
      if(fd<0 && (e=rindex(buff,'.'))) {
nathan@0
   667
        strn0cpy(e,exts[i],20);
nathan@0
   668
        fd=open(buff,O_RDONLY);
nathan@0
   669
        }
nathan@0
   670
      if(fd>=0) {
nathan@0
   671
        int r=read(fd,buff,sizeof(buff)-1);
nathan@0
   672
        close(fd);
nathan@0
   673
        if(r>0) {
nathan@0
   674
          buff[r]=0;
nathan@0
   675
          return AddSubMenu(new cMenuText(tr("Summary"),buff));
nathan@0
   676
          }
nathan@0
   677
        }
nathan@0
   678
      }
nathan@0
   679
    }
nathan@0
   680
  return osContinue;
nathan@0
   681
}
nathan@0
   682
nathan@0
   683
eOSState cMenuMPlayBrowse::ProcessKey(eKeys Key)
nathan@0
   684
{
nathan@0
   685
  eOSState state=cOsdMenu::ProcessKey(Key);
nathan@0
   686
  if(state==osContinue && !HasSubMenu()) {
nathan@0
   687
    if(sourcing) return Source(true);
nathan@0
   688
    if(aidedit) { aidedit=false; SetButtons(); }
nathan@0
   689
    }
nathan@0
   690
  bool rew=false;
nathan@0
   691
  if(state==osUnknown) {
nathan@0
   692
    switch(Key) {
nathan@0
   693
      case kGreen:
nathan@0
   694
        {
nathan@0
   695
        cFileObj *item=CurrentItem();
nathan@0
   696
        if(item && item->Type()==otFile) {
nathan@0
   697
          lastselect=new cFileObj(item);
nathan@0
   698
          state=osBack;
nathan@0
   699
          rew=true;
nathan@0
   700
          } 
nathan@0
   701
        else state=osContinue;
nathan@0
   702
        break;
nathan@0
   703
        }
nathan@0
   704
      case kYellow:
nathan@0
   705
        state=Source(false);
nathan@0
   706
        break;
nathan@0
   707
      case kBlue:
nathan@0
   708
        aidedit=true;
nathan@0
   709
        state=AddSubMenu(new cMenuMPlayAid);
nathan@0
   710
        break;
nathan@0
   711
      case k0:
nathan@0
   712
        state=Summary();
nathan@0
   713
        break;
nathan@0
   714
      default:
nathan@0
   715
        break;
nathan@0
   716
      }
nathan@0
   717
    }
nathan@0
   718
  if(state==osUnknown) state=cMenuBrowse::ProcessStdKey(Key,state);
nathan@0
   719
  if(state==osBack && lastselect) {
nathan@0
   720
    cMPlayerControl::SetFile(lastselect,rew);
nathan@0
   721
    cControl::Launch(new cMPlayerControl);
nathan@0
   722
    return osEnd;
nathan@0
   723
    }
nathan@0
   724
  return state;
nathan@0
   725
}
nathan@0
   726
nathan@0
   727
// --- cPluginMPlayer ----------------------------------------------------------
nathan@0
   728
nathan@0
   729
static const char *VERSION        = PLUGIN_VERSION;
nathan@0
   730
static const char *DESCRIPTION    = "Media replay via MPlayer";
nathan@0
   731
static const char *MAINMENUENTRY  = "MPlayer";
nathan@0
   732
nathan@0
   733
class cPluginMPlayer : public cPlugin {
nathan@0
   734
private:
nathan@0
   735
#if APIVERSNUM >= 10330
nathan@0
   736
  bool ExternalPlay(const char *path, bool test);
nathan@0
   737
#endif
nathan@0
   738
public:
nathan@0
   739
  cPluginMPlayer(void);
nathan@0
   740
  virtual ~cPluginMPlayer();
nathan@0
   741
  virtual const char *Version(void) { return VERSION; }
nathan@0
   742
  virtual const char *Description(void) { return tr(DESCRIPTION); }
nathan@0
   743
  virtual const char *CommandLineHelp(void);
nathan@0
   744
  virtual bool ProcessArgs(int argc, char *argv[]);
nathan@0
   745
#if APIVERSNUM >= 10131
nathan@0
   746
  virtual bool Initialize(void);
nathan@0
   747
#else
nathan@0
   748
  virtual bool Start(void);
nathan@0
   749
#endif
nathan@0
   750
  virtual const char *MainMenuEntry(void);
nathan@0
   751
  virtual cOsdMenu *MainMenuAction(void);
nathan@0
   752
  virtual cMenuSetupPage *SetupMenu(void);
nathan@0
   753
  virtual bool SetupParse(const char *Name, const char *Value);
nathan@0
   754
#if APIVERSNUM >= 10330
nathan@0
   755
  virtual bool Service(const char *Id, void *Data);
nathan@0
   756
#if APIVERSNUM >= 10331
nathan@0
   757
  virtual const char **SVDRPHelpPages(void);
nathan@0
   758
  virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode);
nathan@0
   759
#endif
nathan@0
   760
#endif
nathan@0
   761
  };
nathan@0
   762
nathan@0
   763
cPluginMPlayer::cPluginMPlayer(void)
nathan@0
   764
{
nathan@0
   765
  // Initialize any member variables here.
nathan@0
   766
  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
nathan@0
   767
  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
nathan@0
   768
  status=0;
nathan@0
   769
}
nathan@0
   770
nathan@0
   771
cPluginMPlayer::~cPluginMPlayer()
nathan@0
   772
{
nathan@0
   773
  delete status;
nathan@0
   774
}
nathan@0
   775
nathan@0
   776
const char *cPluginMPlayer::CommandLineHelp(void)
nathan@0
   777
{
nathan@0
   778
  static char *help_str=0;
nathan@0
   779
  
nathan@0
   780
  free(help_str);    //                                     for easier orientation, this is column 80|
nathan@0
   781
  asprintf(&help_str,"  -m CMD,   --mount=CMD    use CMD to mount/unmount/eject mp3 sources\n"
nathan@0
   782
                     "                           (default: %s)\n"
nathan@0
   783
                     "  -M CMD,   --mplayer=CMD  use CMD when calling MPlayer\n"
nathan@0
   784
                     "                           (default: %s)\n"
nathan@0
   785
                     "  -S SUB,   --sources=SUB  search sources config in SUB subdirectory\n"
nathan@0
   786
                     "                           (default: %s)\n"
nathan@0
   787
                     "  -R DIR,   --resume=DIR   store global resume file in DIR\n"
nathan@0
   788
                     "                           (default: %s)\n",
nathan@0
   789
                     mountscript,
nathan@0
   790
                     MPlayerCmd,
nathan@0
   791
                     sourcesSub ? sourcesSub:"none",
nathan@0
   792
                     globalResumeDir ? globalResumeDir:"video dir"
nathan@0
   793
                     );
nathan@0
   794
  return help_str;
nathan@0
   795
}
nathan@0
   796
nathan@0
   797
bool cPluginMPlayer::ProcessArgs(int argc, char *argv[])
nathan@0
   798
{
nathan@0
   799
  static struct option long_options[] = {
nathan@0
   800
      { "mount",    required_argument, NULL, 'm' },
nathan@0
   801
      { "mplayer",  required_argument, NULL, 'M' },
nathan@0
   802
      { "sources",  required_argument, NULL, 'S' },
nathan@0
   803
      { "resume",   required_argument, NULL, 'R' },
nathan@0
   804
      { NULL }
nathan@0
   805
    };
nathan@0
   806
nathan@0
   807
  int c, option_index = 0;
nathan@0
   808
  while((c=getopt_long(argc,argv,"m:M:S:R:",long_options,&option_index))!=-1) {
nathan@0
   809
    switch (c) {
nathan@0
   810
      case 'm': mountscript=optarg; break;
nathan@0
   811
      case 'M': MPlayerCmd=optarg; break;
nathan@0
   812
      case 'S': sourcesSub=optarg; break;
nathan@0
   813
      case 'R': globalResumeDir=optarg; break;
nathan@0
   814
      default:  return false;
nathan@0
   815
      }
nathan@0
   816
    }
nathan@0
   817
  return true;
nathan@0
   818
}
nathan@0
   819
nathan@0
   820
#if APIVERSNUM >= 10131
nathan@0
   821
bool cPluginMPlayer::Initialize(void)
nathan@0
   822
#else
nathan@0
   823
bool cPluginMPlayer::Start(void)
nathan@0
   824
#endif
nathan@0
   825
{
nathan@0
   826
  if(!CheckVDRVersion(1,1,16,"mplayer")) return false;
nathan@0
   827
  i18n_name=Name();
nathan@0
   828
  MPlaySources.Load(AddDirectory(ConfigDirectory(sourcesSub),"mplayersources.conf"));
nathan@0
   829
  if(MPlaySources.Count()<1) {
nathan@0
   830
    esyslog("ERROR: you must have defined at least one source in mplayersources.conf");
nathan@0
   831
    fprintf(stderr,"No source(s) defined in mplayersources.conf\n");
nathan@0
   832
    return false;
nathan@0
   833
    }
nathan@0
   834
  RegisterI18n(Phrases);
nathan@0
   835
  if(!(status=new cMPlayerStatus)) return false;
nathan@0
   836
  return true;
nathan@0
   837
}
nathan@0
   838
nathan@0
   839
const char *cPluginMPlayer::MainMenuEntry(void)
nathan@0
   840
{
nathan@0
   841
  return MPlayerSetup.HideMainMenu ? 0 : tr(MAINMENUENTRY);
nathan@0
   842
}
nathan@0
   843
nathan@0
   844
cOsdMenu *cPluginMPlayer::MainMenuAction(void)
nathan@0
   845
{
nathan@0
   846
  return new cMenuMPlayBrowse;
nathan@0
   847
}
nathan@0
   848
nathan@0
   849
cMenuSetupPage *cPluginMPlayer::SetupMenu(void)
nathan@0
   850
{
nathan@0
   851
  return new cMenuSetupMPlayer;
nathan@0
   852
}
nathan@0
   853
nathan@0
   854
bool cPluginMPlayer::SetupParse(const char *Name, const char *Value)
nathan@0
   855
{
nathan@0
   856
  if(      !strcasecmp(Name, "ControlMode"))  MPlayerSetup.SlaveMode    = atoi(Value);
nathan@0
   857
  else if (!strcasecmp(Name, "HideMainMenu")) MPlayerSetup.HideMainMenu = atoi(Value);
nathan@0
   858
  else if (!strcasecmp(Name, "ResumeMode"))   MPlayerSetup.ResumeMode   = atoi(Value);
nathan@0
   859
  else if (!strcasecmp(Name, "OsdPos"))       MPlayerSetup.OsdPos       = atoi(Value);
nathan@0
   860
  else if (!strncasecmp(Name,"KeyCmd", 6) && strlen(Name)==7 && isdigit(Name[6]))
nathan@0
   861
    strn0cpy(MPlayerSetup.KeyCmd[Name[6]-'0'],Value,sizeof(MPlayerSetup.KeyCmd[0]));
nathan@0
   862
  else return false;
nathan@0
   863
  return true;
nathan@0
   864
}
nathan@0
   865
nathan@0
   866
#if APIVERSNUM >= 10330
nathan@0
   867
nathan@0
   868
bool cPluginMPlayer::ExternalPlay(const char *path, bool test)
nathan@0
   869
{
nathan@0
   870
  char real[PATH_MAX+1];
nathan@0
   871
  if(realpath(path,real)) {
nathan@0
   872
    cFileSource *src=MPlaySources.FindSource(real);
nathan@0
   873
    if(src) {
nathan@0
   874
      cFileObj *item=new cFileObj(src,0,0,otFile);
nathan@0
   875
      if(item) {
nathan@0
   876
        item->SplitAndSet(real);
nathan@0
   877
        if(item->GuessType()) {
nathan@0
   878
          if(item->Exists()) {
nathan@0
   879
            if(!test) {
nathan@0
   880
              cMPlayerControl::SetFile(item,true);
nathan@0
   881
              cControl::Launch(new cMPlayerControl);
nathan@0
   882
              cControl::Attach();
nathan@0
   883
              }
nathan@0
   884
            delete item;
nathan@0
   885
            return true;
nathan@0
   886
            }
nathan@0
   887
          else dsyslog("MPlayer service: cannot play '%s'",path);
nathan@0
   888
          }
nathan@0
   889
        else dsyslog("MPlayer service: GuessType() failed for '%s'",path);
nathan@0
   890
        delete item;
nathan@0
   891
        }
nathan@0
   892
      }
nathan@0
   893
    else dsyslog("MPlayer service: cannot find source for '%s', real '%s'",path,real);
nathan@0
   894
    }
nathan@0
   895
  else if(errno!=ENOENT && errno!=ENOTDIR)
nathan@0
   896
    esyslog("ERROR: realpath: %s: %s",path,strerror(errno));
nathan@0
   897
  return false;
nathan@0
   898
}
nathan@0
   899
nathan@0
   900
bool cPluginMPlayer::Service(const char *Id, void *Data)
nathan@0
   901
{
nathan@0
   902
  if(!strcasecmp(Id,"MPlayer-Play-v1")) {
nathan@0
   903
    if(Data) {
nathan@0
   904
      struct MPlayerServiceData *msd=(struct MPlayerServiceData *)Data;
nathan@0
   905
      msd->result=ExternalPlay(msd->data.filename,false);
nathan@0
   906
      }
nathan@0
   907
    return true;
nathan@0
   908
    }
nathan@0
   909
  else if(!strcasecmp(Id,"MPlayer-Test-v1")) {
nathan@0
   910
    if(Data) {
nathan@0
   911
      struct MPlayerServiceData *msd=(struct MPlayerServiceData *)Data;
nathan@0
   912
      msd->result=ExternalPlay(msd->data.filename,true);
nathan@0
   913
      }
nathan@0
   914
    return true;
nathan@0
   915
    }
nathan@0
   916
  return false;
nathan@0
   917
}
nathan@0
   918
nathan@0
   919
#if APIVERSNUM >= 10331
nathan@0
   920
nathan@0
   921
const char **cPluginMPlayer::SVDRPHelpPages(void)
nathan@0
   922
{
nathan@0
   923
  static const char *HelpPages[] = {
nathan@0
   924
    "PLAY <filename>\n"
nathan@0
   925
    "    Triggers playback of file 'filename'.",
nathan@0
   926
    "TEST <filename>\n"
nathan@0
   927
    "    Tests is playback of file 'filename' is possible.",
nathan@0
   928
    NULL
nathan@0
   929
    };
nathan@0
   930
  return HelpPages;
nathan@0
   931
}
nathan@0
   932
nathan@0
   933
cString cPluginMPlayer::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode)
nathan@0
   934
{
nathan@0
   935
  if(!strcasecmp(Command,"PLAY")) {
nathan@0
   936
    if(*Option) {
nathan@0
   937
      if(ExternalPlay(Option,false)) return "Playback triggered";
nathan@0
   938
      else { ReplyCode=550; return "Playback failed"; }
nathan@0
   939
      }
nathan@0
   940
    else { ReplyCode=501; return "Missing filename"; }
nathan@0
   941
    }
nathan@0
   942
  else if(!strcasecmp(Command,"TEST")) {
nathan@0
   943
    if(*Option) {
nathan@0
   944
      if(ExternalPlay(Option,true)) return "Playback possible";
nathan@0
   945
      else { ReplyCode=550; return "Playback not possible"; }
nathan@0
   946
      }
nathan@0
   947
    else { ReplyCode=501; return "Missing filename"; }
nathan@0
   948
    }
nathan@0
   949
  return NULL;
nathan@0
   950
}
nathan@0
   951
nathan@0
   952
#endif // 1.3.31
nathan@0
   953
#endif // 1.3.30
nathan@0
   954
nathan@0
   955
VDRPLUGINCREATOR(cPluginMPlayer); // Don't touch this!