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