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