2011-12-07 14:37:51 +01:00
|
|
|
///
|
|
|
|
/// @file softhddevice.cpp @brief A software HD device plugin for VDR.
|
|
|
|
///
|
2012-01-02 19:31:08 +01:00
|
|
|
/// Copyright (c) 2011, 2012 by Johns. All Rights Reserved.
|
2011-12-07 14:37:51 +01:00
|
|
|
///
|
|
|
|
/// Contributor(s):
|
|
|
|
///
|
|
|
|
/// License: AGPLv3
|
|
|
|
///
|
|
|
|
/// This program is free software: you can redistribute it and/or modify
|
|
|
|
/// it under the terms of the GNU Affero General Public License as
|
|
|
|
/// published by the Free Software Foundation, either version 3 of the
|
|
|
|
/// License.
|
|
|
|
///
|
|
|
|
/// This program is distributed in the hope that it will be useful,
|
|
|
|
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
/// GNU Affero General Public License for more details.
|
|
|
|
///
|
|
|
|
/// $Id$
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include <vdr/interface.h>
|
|
|
|
#include <vdr/plugin.h>
|
|
|
|
#include <vdr/player.h>
|
|
|
|
#include <vdr/osd.h>
|
|
|
|
#include <vdr/dvbspu.h>
|
|
|
|
#include <vdr/shutdown.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "softhddev.h"
|
|
|
|
#include "softhddevice.h"
|
2012-01-06 15:39:32 +01:00
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
#include "video.h"
|
2012-01-03 21:31:03 +01:00
|
|
|
extern void AudioPoller(void);
|
2012-01-07 03:05:43 +01:00
|
|
|
extern void CodecSetAudioPassthrough(int);
|
2012-02-21 22:24:28 +01:00
|
|
|
extern void CodecSetAudioDownmix(int);
|
2011-12-12 17:06:05 +01:00
|
|
|
}
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-02-23 23:33:00 +01:00
|
|
|
static const char *const VERSION = "0.4.9"
|
|
|
|
#ifdef GIT_REV
|
|
|
|
"-GIT" GIT_REV
|
|
|
|
#endif
|
|
|
|
;
|
2011-12-07 14:37:51 +01:00
|
|
|
static const char *const DESCRIPTION =
|
|
|
|
trNOOP("A software and GPU emulated HD device");
|
|
|
|
|
2012-02-19 19:22:03 +01:00
|
|
|
static const char *MAINMENUENTRY = trNOOP("SoftHdDevice");
|
2011-12-07 14:37:51 +01:00
|
|
|
static class cSoftHdDevice *MyDevice;
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-01-09 17:03:04 +01:00
|
|
|
#define RESOLUTIONS 4 ///< number of resolutions
|
|
|
|
|
2012-01-18 15:15:37 +01:00
|
|
|
/// resolutions names
|
2012-01-09 17:03:04 +01:00
|
|
|
static const char *const Resolution[RESOLUTIONS] = {
|
|
|
|
"576i", "720p", "1080i_fake", "1080i"
|
|
|
|
};
|
|
|
|
|
2012-01-05 17:20:44 +01:00
|
|
|
static char ConfigMakePrimary; ///< config primary wanted
|
2012-01-10 15:52:07 +01:00
|
|
|
static char ConfigHideMainMenuEntry; ///< config hide main menu entry
|
2012-01-09 17:03:04 +01:00
|
|
|
|
2012-02-02 16:00:26 +01:00
|
|
|
static int ConfigVideoSkipLines; ///< config skip lines top/bottom
|
2012-02-13 14:13:24 +01:00
|
|
|
static int ConfigVideoStudioLevels; ///< config use studio levels
|
2012-02-22 15:06:05 +01:00
|
|
|
static int ConfigVideo60HzMode; ///< config use 60Hz display mode
|
2012-02-02 16:00:26 +01:00
|
|
|
|
2012-01-09 17:03:04 +01:00
|
|
|
/// config deinterlace
|
|
|
|
static int ConfigVideoDeinterlace[RESOLUTIONS];
|
|
|
|
|
|
|
|
/// config skip chroma
|
|
|
|
static int ConfigVideoSkipChromaDeinterlace[RESOLUTIONS];
|
|
|
|
|
2012-02-14 22:29:17 +01:00
|
|
|
/// config inverse telecine
|
|
|
|
static int ConfigVideoInverseTelecine[RESOLUTIONS];
|
|
|
|
|
2012-01-09 17:03:04 +01:00
|
|
|
/// config denoise
|
|
|
|
static int ConfigVideoDenoise[RESOLUTIONS];
|
|
|
|
|
|
|
|
/// config sharpen
|
|
|
|
static int ConfigVideoSharpen[RESOLUTIONS];
|
|
|
|
|
|
|
|
/// config scaling
|
|
|
|
static int ConfigVideoScaling[RESOLUTIONS];
|
|
|
|
|
2012-01-05 17:20:44 +01:00
|
|
|
static int ConfigVideoAudioDelay; ///< config audio delay
|
2012-01-07 03:05:43 +01:00
|
|
|
static int ConfigAudioPassthrough; ///< config audio pass-through
|
2012-02-21 22:24:28 +01:00
|
|
|
static int ConfigAudioDownmix; ///< config audio downmix
|
2012-01-09 17:03:04 +01:00
|
|
|
|
2012-01-20 15:33:37 +01:00
|
|
|
static int ConfigAutoCropInterval; ///< auto crop detection interval
|
|
|
|
static int ConfigAutoCropDelay; ///< auto crop detection delay
|
2012-01-27 23:49:05 +01:00
|
|
|
static int ConfigAutoCropTolerance; ///< auto crop detection tolerance
|
2012-01-20 15:33:37 +01:00
|
|
|
|
2012-01-26 15:00:49 +01:00
|
|
|
static char ConfigSuspendClose; ///< suspend should close devices
|
|
|
|
static char ConfigSuspendX11; ///< suspend should stop x11
|
|
|
|
|
2012-01-06 15:39:32 +01:00
|
|
|
static volatile char DoMakePrimary; ///< flag switch primary
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// C Callbacks
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
class cSoftRemote:public cRemote
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
cSoftRemote(const char *name):cRemote(name)
|
|
|
|
{
|
2011-12-14 18:01:03 +01:00
|
|
|
}
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
bool Put(const char *code, bool repeat = false, bool release = false) {
|
|
|
|
return cRemote::Put(code, repeat, release);
|
2011-12-14 18:01:03 +01:00
|
|
|
}
|
2011-12-07 14:37:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
|
|
|
|
int release)
|
|
|
|
{
|
|
|
|
cRemote *remote;
|
|
|
|
cSoftRemote *csoft;
|
|
|
|
|
|
|
|
if (!keymap || !key) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// find remote
|
|
|
|
for (remote = Remotes.First(); remote; remote = Remotes.Next(remote)) {
|
|
|
|
if (!strcmp(remote->Name(), keymap)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (remote) {
|
|
|
|
csoft = (cSoftRemote *) remote;
|
|
|
|
} else {
|
|
|
|
dsyslog("[softhddev]%s: remote '%s' not found\n", __FUNCTION__,
|
|
|
|
keymap);
|
|
|
|
csoft = new cSoftRemote(keymap);
|
|
|
|
}
|
|
|
|
|
2012-01-20 21:46:22 +01:00
|
|
|
//dsyslog("[softhddev]%s %s, %s\n", __FUNCTION__, keymap, key);
|
2012-02-17 16:37:38 +01:00
|
|
|
if (key[1]) { // no single character
|
|
|
|
csoft->Put(key, repeat, release);
|
|
|
|
} else if (!csoft->Put(key, repeat, release)) {
|
|
|
|
cRemote::Put(KBDKEY(key[0])); // feed it for edit mode
|
|
|
|
}
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// OSD
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-02-16 15:31:53 +01:00
|
|
|
/**
|
|
|
|
** Soft device plugin OSD class.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
class cSoftOsd:public cOsd
|
|
|
|
{
|
2012-02-16 15:31:53 +01:00
|
|
|
//int Level; ///< level: subtitle
|
2012-01-12 18:55:07 +01:00
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
public:
|
2012-02-16 15:31:53 +01:00
|
|
|
cSoftOsd(int, int, uint);
|
2011-12-07 14:37:51 +01:00
|
|
|
virtual ~ cSoftOsd(void);
|
|
|
|
virtual void Flush(void);
|
2012-02-06 20:54:20 +01:00
|
|
|
virtual void SetActive(bool);
|
2011-12-07 14:37:51 +01:00
|
|
|
};
|
|
|
|
|
2012-02-06 20:54:20 +01:00
|
|
|
static volatile char OsdDirty; ///< flag force redraw everything
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Sets this OSD to be the active one.
|
|
|
|
**
|
|
|
|
** @param on true on, false off
|
|
|
|
**
|
|
|
|
** @note only needed as workaround for text2skin plugin with
|
|
|
|
** undrawn areas.
|
|
|
|
*/
|
|
|
|
void cSoftOsd::SetActive(bool on)
|
|
|
|
{
|
2012-02-16 15:31:53 +01:00
|
|
|
//dsyslog("[softhddev]%s: %d\n", __FUNCTION__, on);
|
2012-02-06 20:54:20 +01:00
|
|
|
|
|
|
|
if (Active() == on) {
|
|
|
|
return; // already active, no action
|
|
|
|
}
|
|
|
|
cOsd::SetActive(on);
|
|
|
|
if (on) {
|
|
|
|
OsdDirty = 1;
|
|
|
|
} else {
|
|
|
|
OsdClose();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
cSoftOsd::cSoftOsd(int left, int top, uint level)
|
|
|
|
:cOsd(left, top, level)
|
|
|
|
{
|
2012-01-21 15:56:45 +01:00
|
|
|
/* FIXME: OsdWidth/OsdHeight not correct!
|
|
|
|
dsyslog("[softhddev]%s: %dx%d+%d+%d, %d\n", __FUNCTION__, OsdWidth(),
|
|
|
|
OsdHeight(), left, top, level);
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
|
2012-02-16 15:31:53 +01:00
|
|
|
//this->Level = level;
|
2012-01-21 15:56:45 +01:00
|
|
|
SetActive(true);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
cSoftOsd::~cSoftOsd(void)
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
SetActive(false);
|
2012-02-06 20:54:20 +01:00
|
|
|
// done by SetActive: OsdClose();
|
2011-12-07 14:37:51 +01:00
|
|
|
|
2012-01-07 23:47:07 +01:00
|
|
|
#ifdef USE_YAEPG
|
2012-01-18 15:15:37 +01:00
|
|
|
// support yaepghd, video window
|
|
|
|
if (vidWin.bpp) { // restore fullsized video
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
double video_aspect;
|
|
|
|
|
|
|
|
::GetOsdSize(&width, &height, &video_aspect);
|
|
|
|
// works osd relative
|
|
|
|
VideoSetOutputPosition(0, 0, width, height);
|
2012-01-07 22:36:06 +01:00
|
|
|
}
|
2012-01-07 23:47:07 +01:00
|
|
|
#endif
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-02-06 20:54:20 +01:00
|
|
|
/**
|
|
|
|
** Actually commits all data to the OSD hardware.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
void cSoftOsd::Flush(void)
|
|
|
|
{
|
|
|
|
cPixmapMemory *pm;
|
|
|
|
|
|
|
|
if (!Active()) {
|
|
|
|
return;
|
|
|
|
}
|
2012-01-07 23:47:07 +01:00
|
|
|
#ifdef USE_YAEPG
|
2012-01-18 15:15:37 +01:00
|
|
|
// support yaepghd, video window
|
2012-01-07 22:36:06 +01:00
|
|
|
if (vidWin.bpp) {
|
2012-01-09 17:03:04 +01:00
|
|
|
dsyslog("[softhddev]%s: %dx%d+%d+%d\n", __FUNCTION__, vidWin.Width(),
|
|
|
|
vidWin.Height(), vidWin.x1, vidWin.y2);
|
2012-01-07 22:36:06 +01:00
|
|
|
|
|
|
|
// FIXME: vidWin is OSD relative not video window.
|
|
|
|
VideoSetOutputPosition(Left() + vidWin.x1, Top() + vidWin.y1,
|
|
|
|
vidWin.Width(), vidWin.Height());
|
|
|
|
}
|
2012-01-07 23:47:07 +01:00
|
|
|
#endif
|
2012-01-07 22:36:06 +01:00
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
if (!IsTrueColor()) {
|
|
|
|
static char warned;
|
|
|
|
cBitmap *bitmap;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!warned) {
|
|
|
|
dsyslog("[softhddev]%s: FIXME: should be truecolor\n",
|
|
|
|
__FUNCTION__);
|
|
|
|
warned = 1;
|
|
|
|
}
|
|
|
|
// draw all bitmaps
|
|
|
|
for (i = 0; (bitmap = GetBitmap(i)); ++i) {
|
|
|
|
uint8_t *argb;
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int w;
|
|
|
|
int h;
|
|
|
|
int x1;
|
|
|
|
int y1;
|
|
|
|
int x2;
|
|
|
|
int y2;
|
|
|
|
|
|
|
|
// get dirty bounding box
|
2012-02-06 20:54:20 +01:00
|
|
|
if (OsdDirty) { // forced complete update
|
|
|
|
x1 = 0;
|
|
|
|
y1 = 0;
|
|
|
|
x2 = bitmap->Width() - 1;
|
|
|
|
y2 = bitmap->Height() - 1;
|
|
|
|
} else if (!bitmap->Dirty(x1, y1, x2, y2)) {
|
2011-12-07 14:37:51 +01:00
|
|
|
continue; // nothing dirty continue
|
|
|
|
}
|
2012-01-18 15:15:37 +01:00
|
|
|
// convert and upload only dirty areas
|
|
|
|
w = x2 - x1 + 1;
|
|
|
|
h = y2 - y1 + 1;
|
2012-02-06 20:54:20 +01:00
|
|
|
if (1) { // just for the case it makes trouble
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
double video_aspect;
|
|
|
|
|
|
|
|
::GetOsdSize(&width, &height, &video_aspect);
|
|
|
|
if (w > width) {
|
|
|
|
w = width;
|
|
|
|
x2 = x1 + width - 1;
|
|
|
|
}
|
|
|
|
if (h > height) {
|
|
|
|
h = height;
|
|
|
|
y2 = y1 + height - 1;
|
|
|
|
}
|
|
|
|
}
|
2012-01-18 15:15:37 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
if (w > bitmap->Width() || h > bitmap->Height()) {
|
2012-02-23 15:32:43 +01:00
|
|
|
esyslog(tr("[softhddev]: dirty area too big\n"));
|
2012-01-18 15:15:37 +01:00
|
|
|
abort();
|
2012-01-12 18:55:07 +01:00
|
|
|
}
|
2012-01-18 15:15:37 +01:00
|
|
|
#endif
|
|
|
|
argb = (uint8_t *) malloc(w * h * sizeof(uint32_t));
|
|
|
|
for (y = y1; y <= y2; ++y) {
|
|
|
|
for (x = x1; x <= x2; ++x) {
|
|
|
|
((uint32_t *) argb)[x - x1 + (y - y1) * w] =
|
|
|
|
bitmap->GetColor(x, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OsdDrawARGB(Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1,
|
|
|
|
w, h, argb);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
bitmap->Clean();
|
2012-02-06 20:54:20 +01:00
|
|
|
// FIXME: reuse argb
|
2011-12-07 14:37:51 +01:00
|
|
|
free(argb);
|
|
|
|
}
|
2012-02-06 20:54:20 +01:00
|
|
|
OsdDirty = 0;
|
2011-12-07 14:37:51 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCK_PIXMAPS;
|
|
|
|
while ((pm = RenderPixmaps())) {
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int w;
|
|
|
|
int h;
|
|
|
|
|
|
|
|
x = Left() + pm->ViewPort().X();
|
|
|
|
y = Top() + pm->ViewPort().Y();
|
|
|
|
w = pm->ViewPort().Width();
|
|
|
|
h = pm->ViewPort().Height();
|
|
|
|
|
2012-01-06 15:39:32 +01:00
|
|
|
/*
|
2012-01-20 21:46:22 +01:00
|
|
|
dsyslog("[softhddev]%s: draw %dx%d+%d+%d %p\n", __FUNCTION__, w, h,
|
|
|
|
x, y, pm->Data());
|
2012-01-06 15:39:32 +01:00
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
OsdDrawARGB(x, y, w, h, pm->Data());
|
|
|
|
|
|
|
|
delete pm;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// OSD provider
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-02-16 15:31:53 +01:00
|
|
|
/**
|
|
|
|
** Soft device plugin OSD provider class.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
class cSoftOsdProvider:public cOsdProvider
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
static cOsd *Osd;
|
|
|
|
public:
|
|
|
|
virtual cOsd * CreateOsd(int, int, uint);
|
|
|
|
virtual bool ProvidesTrueColor(void);
|
|
|
|
cSoftOsdProvider(void);
|
|
|
|
};
|
|
|
|
|
2012-01-05 17:20:44 +01:00
|
|
|
cOsd *cSoftOsdProvider::Osd; ///< single osd
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
** Create a new OSD.
|
2012-02-06 20:54:20 +01:00
|
|
|
**
|
|
|
|
** @param left x-coordinate of OSD
|
|
|
|
** @param top y-coordinate of OSD
|
|
|
|
** @param level layer level of OSD
|
2011-12-07 14:37:51 +01:00
|
|
|
*/
|
|
|
|
cOsd *cSoftOsdProvider::CreateOsd(int left, int top, uint level)
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s: %d, %d, %d\n", __FUNCTION__, left, top, level);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
2012-02-16 15:31:53 +01:00
|
|
|
return Osd = new cSoftOsd(left, top, level);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2012-02-16 15:31:53 +01:00
|
|
|
** Check if this OSD provider is able to handle a true color OSD.
|
|
|
|
**
|
|
|
|
** @returns true we are able to handle a true color OSD.
|
2011-12-07 14:37:51 +01:00
|
|
|
*/
|
|
|
|
bool cSoftOsdProvider::ProvidesTrueColor(void)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-01-07 22:36:06 +01:00
|
|
|
/**
|
|
|
|
** Create cOsdProvider class.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
cSoftOsdProvider::cSoftOsdProvider(void)
|
|
|
|
: cOsdProvider()
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// cMenuSetupPage
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-02-19 19:22:03 +01:00
|
|
|
/**
|
|
|
|
** Soft device plugin menu setup page class.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
class cMenuSetupSoft:public cMenuSetupPage
|
|
|
|
{
|
|
|
|
protected:
|
2012-02-19 19:22:03 +01:00
|
|
|
///
|
|
|
|
/// local copies of global setup variables:
|
|
|
|
/// @{
|
2011-12-07 14:37:51 +01:00
|
|
|
int MakePrimary;
|
2012-01-10 15:52:07 +01:00
|
|
|
int HideMainMenuEntry;
|
2012-02-02 16:00:26 +01:00
|
|
|
int SkipLines;
|
2012-02-13 14:13:24 +01:00
|
|
|
int StudioLevels;
|
2012-01-09 17:03:04 +01:00
|
|
|
int Scaling[RESOLUTIONS];
|
|
|
|
int Deinterlace[RESOLUTIONS];
|
|
|
|
int SkipChromaDeinterlace[RESOLUTIONS];
|
2012-02-14 22:29:17 +01:00
|
|
|
int InverseTelecine[RESOLUTIONS];
|
2012-01-09 17:03:04 +01:00
|
|
|
int Denoise[RESOLUTIONS];
|
|
|
|
int Sharpen[RESOLUTIONS];
|
2011-12-19 17:03:40 +01:00
|
|
|
int AudioDelay;
|
2012-01-07 03:05:43 +01:00
|
|
|
int AudioPassthrough;
|
2012-02-21 22:24:28 +01:00
|
|
|
int AudioDownmix;
|
2012-01-20 15:33:37 +01:00
|
|
|
int AutoCropInterval;
|
|
|
|
int AutoCropDelay;
|
2012-01-27 23:49:05 +01:00
|
|
|
int AutoCropTolerance;
|
2012-01-22 20:49:43 +01:00
|
|
|
int SuspendClose;
|
|
|
|
int SuspendX11;
|
2012-02-19 19:22:03 +01:00
|
|
|
/// @}
|
2011-12-07 14:37:51 +01:00
|
|
|
protected:
|
|
|
|
virtual void Store(void);
|
|
|
|
public:
|
|
|
|
cMenuSetupSoft(void);
|
|
|
|
};
|
|
|
|
|
2012-01-09 17:03:04 +01:00
|
|
|
/**
|
|
|
|
** Create a seperator item.
|
2012-01-20 15:33:37 +01:00
|
|
|
**
|
|
|
|
** @param label text inside separator
|
2012-01-09 17:03:04 +01:00
|
|
|
*/
|
|
|
|
static inline cOsdItem *SeparatorItem(const char *label)
|
|
|
|
{
|
|
|
|
cOsdItem *item;
|
|
|
|
|
|
|
|
item = new cOsdItem(cString::sprintf("* %s: ", label));
|
|
|
|
item->SetSelectable(false);
|
|
|
|
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
/**
|
|
|
|
** Constructor setup menu.
|
|
|
|
*/
|
|
|
|
cMenuSetupSoft::cMenuSetupSoft(void)
|
|
|
|
{
|
2012-01-05 17:20:44 +01:00
|
|
|
static const char *const deinterlace[] = {
|
2012-02-09 21:22:42 +01:00
|
|
|
"Bob", "Weave/None", "Temporal", "TemporalSpatial", "Software Bob",
|
|
|
|
"Software Spatial",
|
2012-01-05 17:20:44 +01:00
|
|
|
};
|
|
|
|
static const char *const scaling[] = {
|
|
|
|
"Normal", "Fast", "HQ", "Anamorphic"
|
|
|
|
};
|
2012-01-07 03:05:43 +01:00
|
|
|
static const char *const passthrough[] = {
|
|
|
|
"None", "AC-3"
|
|
|
|
};
|
2012-01-09 17:03:04 +01:00
|
|
|
static const char *const resolution[RESOLUTIONS] = {
|
|
|
|
"576i", "720p", "fake 1080i", "1080i"
|
|
|
|
};
|
|
|
|
int i;
|
2011-12-12 17:06:05 +01:00
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
// cMenuEditBoolItem cMenuEditBitItem cMenuEditNumItem
|
|
|
|
// cMenuEditStrItem cMenuEditStraItem cMenuEditIntItem
|
2011-12-15 16:02:32 +01:00
|
|
|
MakePrimary = ConfigMakePrimary;
|
2011-12-07 14:37:51 +01:00
|
|
|
Add(new cMenuEditBoolItem(tr("Make primary device"), &MakePrimary,
|
2012-01-19 00:16:15 +01:00
|
|
|
trVDR("no"), trVDR("yes")));
|
2012-01-10 15:52:07 +01:00
|
|
|
HideMainMenuEntry = ConfigHideMainMenuEntry;
|
|
|
|
Add(new cMenuEditBoolItem(tr("Hide main menu entry"), &HideMainMenuEntry,
|
2012-01-19 00:16:15 +01:00
|
|
|
trVDR("no"), trVDR("yes")));
|
2012-01-09 17:03:04 +01:00
|
|
|
//
|
|
|
|
// video
|
|
|
|
//
|
|
|
|
Add(SeparatorItem(tr("Video")));
|
2012-02-02 16:00:26 +01:00
|
|
|
|
|
|
|
SkipLines = ConfigVideoSkipLines;
|
|
|
|
Add(new cMenuEditIntItem(tr("Skip lines top+bot (pixel)"), &SkipLines, 0,
|
|
|
|
64));
|
2012-02-13 14:13:24 +01:00
|
|
|
StudioLevels = ConfigVideoStudioLevels;
|
|
|
|
Add(new cMenuEditBoolItem(tr("Use studio levels (vdpau only)"),
|
|
|
|
&StudioLevels, trVDR("no"), trVDR("yes")));
|
2012-02-02 16:00:26 +01:00
|
|
|
|
2012-01-09 17:03:04 +01:00
|
|
|
for (i = 0; i < RESOLUTIONS; ++i) {
|
|
|
|
Add(SeparatorItem(resolution[i]));
|
|
|
|
Scaling[i] = ConfigVideoScaling[i];
|
|
|
|
Add(new cMenuEditStraItem(tr("Scaling"), &Scaling[i], 4, scaling));
|
|
|
|
Deinterlace[i] = ConfigVideoDeinterlace[i];
|
2012-02-09 21:22:42 +01:00
|
|
|
Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace[i], 6,
|
2012-01-09 17:03:04 +01:00
|
|
|
deinterlace));
|
|
|
|
SkipChromaDeinterlace[i] = ConfigVideoSkipChromaDeinterlace[i];
|
|
|
|
Add(new cMenuEditBoolItem(tr("SkipChromaDeinterlace (vdpau)"),
|
2012-01-19 00:16:15 +01:00
|
|
|
&SkipChromaDeinterlace[i], trVDR("no"), trVDR("yes")));
|
2012-02-14 22:29:17 +01:00
|
|
|
InverseTelecine[i] = ConfigVideoInverseTelecine[i];
|
|
|
|
Add(new cMenuEditBoolItem(tr("Inverse Telecine (vdpau)"),
|
|
|
|
&InverseTelecine[i], trVDR("no"), trVDR("yes")));
|
2012-01-09 17:03:04 +01:00
|
|
|
Denoise[i] = ConfigVideoDenoise[i];
|
|
|
|
Add(new cMenuEditIntItem(tr("Denoise (0..1000) (vdpau)"), &Denoise[i],
|
|
|
|
0, 1000));
|
|
|
|
Sharpen[i] = ConfigVideoSharpen[i];
|
|
|
|
Add(new cMenuEditIntItem(tr("Sharpen (-1000..1000) (vdpau)"),
|
|
|
|
&Sharpen[i], -1000, 1000));
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// audio
|
|
|
|
//
|
|
|
|
Add(SeparatorItem(tr("Audio")));
|
2011-12-19 17:03:40 +01:00
|
|
|
AudioDelay = ConfigVideoAudioDelay;
|
2012-01-05 17:20:44 +01:00
|
|
|
Add(new cMenuEditIntItem(tr("Audio delay (ms)"), &AudioDelay, -1000,
|
|
|
|
1000));
|
2012-01-07 03:05:43 +01:00
|
|
|
AudioPassthrough = ConfigAudioPassthrough;
|
|
|
|
Add(new cMenuEditStraItem(tr("Audio pass-through"), &AudioPassthrough, 2,
|
|
|
|
passthrough));
|
2012-02-21 22:24:28 +01:00
|
|
|
AudioDownmix = ConfigAudioDownmix;
|
|
|
|
Add(new cMenuEditBoolItem(tr("Enable AC-3 downmix"), &AudioDownmix,
|
|
|
|
trVDR("no"), trVDR("yes")));
|
2012-01-20 15:33:37 +01:00
|
|
|
//
|
|
|
|
// auto-crop
|
|
|
|
//
|
|
|
|
Add(SeparatorItem(tr("Auto-crop")));
|
|
|
|
AutoCropInterval = ConfigAutoCropInterval;
|
|
|
|
Add(new cMenuEditIntItem(tr("autocrop interval (frames)"),
|
|
|
|
&AutoCropInterval, 0, 200));
|
|
|
|
AutoCropDelay = ConfigAutoCropDelay;
|
|
|
|
Add(new cMenuEditIntItem(tr("autocrop delay (n * interval)"),
|
|
|
|
&AutoCropDelay, 0, 200));
|
2012-01-27 23:49:05 +01:00
|
|
|
AutoCropTolerance = ConfigAutoCropTolerance;
|
|
|
|
Add(new cMenuEditIntItem(tr("autocrop tolerance (pixel)"),
|
|
|
|
&AutoCropTolerance, 0, 32));
|
2012-01-22 20:49:43 +01:00
|
|
|
//
|
|
|
|
// suspend
|
|
|
|
//
|
|
|
|
Add(SeparatorItem(tr("Suspend")));
|
|
|
|
SuspendClose = ConfigSuspendClose;
|
|
|
|
Add(new cMenuEditBoolItem(tr("suspend closes video+audio"), &SuspendClose,
|
|
|
|
trVDR("no"), trVDR("yes")));
|
|
|
|
SuspendX11 = ConfigSuspendX11;
|
|
|
|
Add(new cMenuEditBoolItem(tr("suspend stops x11"), &SuspendX11,
|
|
|
|
trVDR("no"), trVDR("yes")));
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Store setup.
|
|
|
|
*/
|
|
|
|
void cMenuSetupSoft::Store(void)
|
|
|
|
{
|
2012-01-09 17:03:04 +01:00
|
|
|
int i;
|
|
|
|
|
2011-12-17 19:25:08 +01:00
|
|
|
SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary);
|
2012-01-10 15:52:07 +01:00
|
|
|
SetupStore("HideMainMenuEntry", ConfigHideMainMenuEntry =
|
|
|
|
HideMainMenuEntry);
|
2012-01-09 17:03:04 +01:00
|
|
|
|
2012-02-02 16:00:26 +01:00
|
|
|
SetupStore("SkipLines", ConfigVideoSkipLines = SkipLines);
|
|
|
|
VideoSetSkipLines(ConfigVideoSkipLines);
|
2012-02-13 14:13:24 +01:00
|
|
|
SetupStore("StudioLevels", ConfigVideoStudioLevels = StudioLevels);
|
|
|
|
VideoSetStudioLevels(ConfigVideoStudioLevels);
|
2012-02-02 16:00:26 +01:00
|
|
|
|
2012-01-09 17:03:04 +01:00
|
|
|
for (i = 0; i < RESOLUTIONS; ++i) {
|
|
|
|
char buf[128];
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling");
|
|
|
|
SetupStore(buf, ConfigVideoScaling[i] = Scaling[i]);
|
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Deinterlace");
|
|
|
|
SetupStore(buf, ConfigVideoDeinterlace[i] = Deinterlace[i]);
|
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i],
|
|
|
|
"SkipChromaDeinterlace");
|
|
|
|
SetupStore(buf, ConfigVideoSkipChromaDeinterlace[i] =
|
|
|
|
SkipChromaDeinterlace[i]);
|
2012-02-14 22:29:17 +01:00
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "InverseTelecine");
|
|
|
|
SetupStore(buf, ConfigVideoInverseTelecine[i] = InverseTelecine[i]);
|
2012-01-09 17:03:04 +01:00
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Denoise");
|
|
|
|
SetupStore(buf, ConfigVideoDenoise[i] = Denoise[i]);
|
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Sharpen");
|
|
|
|
SetupStore(buf, ConfigVideoSharpen[i] = Sharpen[i]);
|
|
|
|
}
|
|
|
|
VideoSetScaling(ConfigVideoScaling);
|
2011-12-17 19:25:08 +01:00
|
|
|
VideoSetDeinterlace(ConfigVideoDeinterlace);
|
2012-01-05 17:20:44 +01:00
|
|
|
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace);
|
2012-02-14 22:29:17 +01:00
|
|
|
VideoSetInverseTelecine(ConfigVideoInverseTelecine);
|
2012-01-05 17:20:44 +01:00
|
|
|
VideoSetDenoise(ConfigVideoDenoise);
|
|
|
|
VideoSetSharpen(ConfigVideoSharpen);
|
2012-01-09 17:03:04 +01:00
|
|
|
|
2011-12-19 17:03:40 +01:00
|
|
|
SetupStore("AudioDelay", ConfigVideoAudioDelay = AudioDelay);
|
|
|
|
VideoSetAudioDelay(ConfigVideoAudioDelay);
|
2012-01-07 03:05:43 +01:00
|
|
|
SetupStore("AudioPassthrough", ConfigAudioPassthrough = AudioPassthrough);
|
|
|
|
CodecSetAudioPassthrough(ConfigAudioPassthrough);
|
2012-02-21 22:24:28 +01:00
|
|
|
SetupStore("AudioDownmix", ConfigAudioDownmix = AudioDownmix);
|
|
|
|
CodecSetAudioDownmix(ConfigAudioDownmix);
|
2012-01-20 15:33:37 +01:00
|
|
|
|
|
|
|
SetupStore("AutoCrop.Interval", ConfigAutoCropInterval = AutoCropInterval);
|
|
|
|
SetupStore("AutoCrop.Delay", ConfigAutoCropDelay = AutoCropDelay);
|
2012-02-02 16:00:26 +01:00
|
|
|
SetupStore("AutoCrop.Tolerance", ConfigAutoCropTolerance =
|
|
|
|
AutoCropTolerance);
|
|
|
|
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay,
|
|
|
|
ConfigAutoCropTolerance);
|
2012-01-22 20:49:43 +01:00
|
|
|
|
|
|
|
SetupStore("Suspend.Close", ConfigSuspendClose = SuspendClose);
|
|
|
|
SetupStore("Suspend.X11", ConfigSuspendX11 = SuspendX11);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-01-22 11:12:57 +01:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// cPlayer
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Dummy player for suspend mode.
|
|
|
|
*/
|
|
|
|
class cSoftHdPlayer:public cPlayer
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
cSoftHdPlayer(void);
|
|
|
|
virtual ~ cSoftHdPlayer();
|
|
|
|
};
|
|
|
|
|
|
|
|
cSoftHdPlayer::cSoftHdPlayer(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
cSoftHdPlayer::~cSoftHdPlayer()
|
|
|
|
{
|
|
|
|
Detach();
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// cControl
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Dummy control for suspend mode.
|
|
|
|
*/
|
|
|
|
class cSoftHdControl:public cControl
|
|
|
|
{
|
|
|
|
public:
|
2012-02-08 23:26:49 +01:00
|
|
|
static cSoftHdPlayer *Player; ///< dummy player
|
2012-01-22 11:12:57 +01:00
|
|
|
virtual void Hide(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
virtual eOSState ProcessKey(eKeys);
|
|
|
|
|
|
|
|
cSoftHdControl(void);
|
|
|
|
|
|
|
|
virtual ~ cSoftHdControl();
|
|
|
|
};
|
|
|
|
|
2012-02-08 23:26:49 +01:00
|
|
|
cSoftHdPlayer *cSoftHdControl::Player;
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Handle a key event.
|
|
|
|
**
|
|
|
|
** @param key key pressed
|
|
|
|
*/
|
2012-01-22 11:12:57 +01:00
|
|
|
eOSState cSoftHdControl::ProcessKey(eKeys key)
|
|
|
|
{
|
|
|
|
if (!ISMODELESSKEY(key) || key == kBack || key == kStop) {
|
|
|
|
if (Player) {
|
|
|
|
delete Player;
|
|
|
|
|
|
|
|
Player = NULL;
|
|
|
|
}
|
2012-02-08 23:26:49 +01:00
|
|
|
Resume();
|
2012-01-22 11:12:57 +01:00
|
|
|
return osEnd;
|
|
|
|
}
|
|
|
|
return osContinue;
|
|
|
|
}
|
|
|
|
|
2012-02-19 19:22:03 +01:00
|
|
|
/**
|
|
|
|
** Player control constructor.
|
|
|
|
*/
|
2012-01-22 11:12:57 +01:00
|
|
|
cSoftHdControl::cSoftHdControl(void)
|
|
|
|
: cControl(Player = new cSoftHdPlayer)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-02-19 19:22:03 +01:00
|
|
|
/**
|
|
|
|
** Player control destructor.
|
|
|
|
*/
|
2012-01-22 11:12:57 +01:00
|
|
|
cSoftHdControl::~cSoftHdControl()
|
|
|
|
{
|
|
|
|
if (Player) {
|
|
|
|
delete Player;
|
|
|
|
|
|
|
|
Player = NULL;
|
|
|
|
}
|
|
|
|
Resume();
|
|
|
|
}
|
|
|
|
|
2012-02-19 19:22:03 +01:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// cOsdMenu
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Soft device plugin menu class.
|
|
|
|
*/
|
|
|
|
class cSoftHdMenu:public cOsdMenu
|
|
|
|
{
|
|
|
|
int HotkeyState; ///< current hot-key state
|
|
|
|
int HotkeyCode; ///< current hot-key code
|
|
|
|
public:
|
|
|
|
cSoftHdMenu(const char *, int = 0, int = 0, int = 0, int = 0, int = 0);
|
|
|
|
virtual ~ cSoftHdMenu();
|
|
|
|
virtual eOSState ProcessKey(eKeys);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Soft device menu constructor.
|
|
|
|
*/
|
|
|
|
cSoftHdMenu::cSoftHdMenu(const char *title, int c0, int c1, int c2, int c3,
|
|
|
|
int c4)
|
|
|
|
:cOsdMenu(title, c0, c1, c2, c3, c4)
|
|
|
|
{
|
|
|
|
HotkeyState = 0;
|
|
|
|
|
|
|
|
SetHasHotkeys();
|
|
|
|
Add(new cOsdItem(hk(tr("Suspend SoftHdDevice")), osUser1));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Soft device menu destructor.
|
|
|
|
*/
|
|
|
|
cSoftHdMenu::~cSoftHdMenu()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Handle hot key commands.
|
|
|
|
*/
|
|
|
|
static void HandleHotkey(int code)
|
|
|
|
{
|
|
|
|
switch (code) {
|
|
|
|
case 10: // disable pass-through
|
|
|
|
CodecSetAudioPassthrough(ConfigAudioPassthrough = 0);
|
|
|
|
break;
|
|
|
|
case 11: // enable pass-through
|
|
|
|
CodecSetAudioPassthrough(ConfigAudioPassthrough = 1);
|
|
|
|
break;
|
|
|
|
case 12: // toggle pass-through
|
|
|
|
CodecSetAudioPassthrough(ConfigAudioPassthrough ^= 1);
|
|
|
|
break;
|
|
|
|
default:
|
2012-02-23 15:32:43 +01:00
|
|
|
esyslog(tr("[softhddev]: hot key %d is not supported\n"), code);
|
2012-02-19 19:22:03 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Handle key event.
|
|
|
|
**
|
|
|
|
** @param key key event
|
|
|
|
*/
|
|
|
|
eOSState cSoftHdMenu::ProcessKey(eKeys key)
|
|
|
|
{
|
|
|
|
eOSState state;
|
|
|
|
|
|
|
|
//dsyslog("[softhddev]%s: %x\n", __FUNCTION__, key);
|
|
|
|
|
|
|
|
switch (HotkeyState) {
|
|
|
|
case 0: // initial state, waiting for hot key
|
|
|
|
if (key == kBlue) {
|
|
|
|
HotkeyState = 1;
|
|
|
|
return osContinue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (k0 <= key && key <= k9) {
|
|
|
|
HotkeyCode = key - k0;
|
|
|
|
HotkeyState = 2;
|
|
|
|
return osContinue;
|
|
|
|
}
|
|
|
|
HotkeyState = 0;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (k0 <= key && key <= k9) {
|
|
|
|
HotkeyCode *= 10;
|
|
|
|
HotkeyCode += key - k0;
|
|
|
|
HotkeyState = 0;
|
|
|
|
dsyslog("[softhddev]%s: hot-key %d\n", __FUNCTION__,
|
|
|
|
HotkeyCode);
|
|
|
|
HandleHotkey(HotkeyCode);
|
|
|
|
return osEnd;
|
|
|
|
}
|
|
|
|
if (key == kOk) {
|
|
|
|
HotkeyState = 0;
|
|
|
|
dsyslog("[softhddev]%s: hot-key %d\n", __FUNCTION__,
|
|
|
|
HotkeyCode);
|
|
|
|
HandleHotkey(HotkeyCode);
|
|
|
|
return osEnd;
|
|
|
|
}
|
|
|
|
HotkeyState = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// call standard function
|
|
|
|
state = cOsdMenu::ProcessKey(key);
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case osUser1:
|
|
|
|
if (!cSoftHdControl::Player) { // not already suspended
|
|
|
|
cControl::Launch(new cSoftHdControl);
|
|
|
|
cControl::Attach();
|
|
|
|
Suspend(ConfigSuspendClose, ConfigSuspendClose,
|
|
|
|
ConfigSuspendX11);
|
|
|
|
if (ShutdownHandler.GetUserInactiveTime()) {
|
|
|
|
dsyslog("[softhddev]%s: set user inactive\n",
|
|
|
|
__FUNCTION__);
|
|
|
|
ShutdownHandler.SetUserInactive();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return osEnd;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// cDevice
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
class cSoftHdDevice:public cDevice
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
cSoftHdDevice(void);
|
2012-02-19 19:22:03 +01:00
|
|
|
virtual ~ cSoftHdDevice(void);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
virtual bool HasDecoder(void) const;
|
|
|
|
virtual bool CanReplay(void) const;
|
|
|
|
virtual bool SetPlayMode(ePlayMode);
|
|
|
|
virtual void TrickSpeed(int);
|
|
|
|
virtual void Clear(void);
|
|
|
|
virtual void Play(void);
|
|
|
|
virtual void Freeze(void);
|
|
|
|
virtual void Mute(void);
|
|
|
|
virtual void StillPicture(const uchar *, int);
|
|
|
|
virtual bool Poll(cPoller &, int = 0);
|
|
|
|
virtual bool Flush(int = 0);
|
|
|
|
virtual int64_t GetSTC(void);
|
2012-02-01 16:50:48 +01:00
|
|
|
virtual void SetVideoDisplayFormat(eVideoDisplayFormat);
|
2012-02-17 15:10:24 +01:00
|
|
|
virtual void SetVideoFormat(bool);
|
2012-01-18 15:15:37 +01:00
|
|
|
virtual void GetVideoSize(int &, int &, double &);
|
2011-12-07 14:37:51 +01:00
|
|
|
virtual void GetOsdSize(int &, int &, double &);
|
|
|
|
virtual int PlayVideo(const uchar *, int);
|
2012-02-21 20:55:28 +01:00
|
|
|
#ifndef xxUSE_TS_AUDIO
|
|
|
|
virtual int PlayAudio(const uchar *, int, uchar);
|
|
|
|
#endif
|
2011-12-07 14:37:51 +01:00
|
|
|
//virtual int PlayTsVideo(const uchar *, int);
|
2012-02-21 20:55:28 +01:00
|
|
|
#if !defined(USE_AUDIO_THREAD) || defined(USE_TS_AUDIO)
|
2012-01-03 21:31:03 +01:00
|
|
|
virtual int PlayTsAudio(const uchar *, int);
|
|
|
|
#endif
|
2011-12-07 14:37:51 +01:00
|
|
|
virtual void SetAudioChannelDevice(int);
|
|
|
|
virtual int GetAudioChannelDevice(void);
|
|
|
|
virtual void SetDigitalAudioDevice(bool);
|
|
|
|
virtual void SetAudioTrackDevice(eTrackType);
|
2012-02-12 20:14:43 +01:00
|
|
|
virtual void SetVolumeDevice(int);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
// Image Grab facilities
|
|
|
|
|
|
|
|
virtual uchar *GrabImage(int &, bool, int, int, int);
|
|
|
|
|
2012-01-12 18:55:07 +01:00
|
|
|
#if 0
|
2011-12-07 14:37:51 +01:00
|
|
|
// SPU facilities
|
|
|
|
private:
|
2012-02-19 19:22:03 +01:00
|
|
|
cDvbSpuDecoder * spuDecoder;
|
2011-12-07 14:37:51 +01:00
|
|
|
public:
|
2012-02-19 19:22:03 +01:00
|
|
|
virtual cSpuDecoder * GetSpuDecoder(void);
|
2012-01-12 18:55:07 +01:00
|
|
|
#endif
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
protected:
|
2012-02-19 19:22:03 +01:00
|
|
|
virtual void MakePrimaryDevice(bool);
|
2011-12-07 14:37:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
cSoftHdDevice::cSoftHdDevice(void)
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s\n", __FUNCTION__);
|
2011-12-08 20:50:32 +01:00
|
|
|
|
2012-01-12 18:55:07 +01:00
|
|
|
#if 0
|
2011-12-08 20:50:32 +01:00
|
|
|
spuDecoder = NULL;
|
2012-01-12 18:55:07 +01:00
|
|
|
#endif
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
cSoftHdDevice::~cSoftHdDevice(void)
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-01-19 00:16:15 +01:00
|
|
|
/**
|
|
|
|
** Informs a device that it will be the primary device.
|
|
|
|
**
|
|
|
|
** @param on flag if becoming or loosing primary
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
void cSoftHdDevice::MakePrimaryDevice(bool on)
|
|
|
|
{
|
|
|
|
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, on);
|
|
|
|
|
|
|
|
cDevice::MakePrimaryDevice(on);
|
|
|
|
if (on) {
|
|
|
|
new cSoftOsdProvider();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-12 18:55:07 +01:00
|
|
|
#if 0
|
|
|
|
|
2012-01-18 15:15:37 +01:00
|
|
|
cSpuDecoder *cSoftHdDevice::GetSpuDecoder(void)
|
2011-12-07 14:37:51 +01:00
|
|
|
{
|
|
|
|
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
|
|
|
|
|
|
|
if (IsPrimaryDevice() && !spuDecoder) {
|
|
|
|
spuDecoder = new cDvbSpuDecoder();
|
|
|
|
}
|
|
|
|
return spuDecoder;
|
2011-12-14 18:01:03 +01:00
|
|
|
}
|
2011-12-07 14:37:51 +01:00
|
|
|
|
2012-01-12 18:55:07 +01:00
|
|
|
#endif
|
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
bool cSoftHdDevice::HasDecoder(void) const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-01-22 11:12:57 +01:00
|
|
|
/**
|
|
|
|
** Returns true if this device can currently start a replay session.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
bool cSoftHdDevice::CanReplay(void) const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-01-22 11:12:57 +01:00
|
|
|
/**
|
|
|
|
** Sets the device into the given play mode.
|
|
|
|
*/
|
|
|
|
bool cSoftHdDevice::SetPlayMode(ePlayMode play_mode)
|
2011-12-07 14:37:51 +01:00
|
|
|
{
|
2012-01-22 11:12:57 +01:00
|
|
|
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, play_mode);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
2012-01-22 11:12:57 +01:00
|
|
|
switch (play_mode) {
|
2011-12-07 14:37:51 +01:00
|
|
|
case pmAudioVideo:
|
|
|
|
break;
|
|
|
|
case pmAudioOnly:
|
|
|
|
case pmAudioOnlyBlack:
|
|
|
|
break;
|
|
|
|
case pmVideoOnly:
|
|
|
|
break;
|
|
|
|
case pmNone:
|
2012-01-11 18:01:18 +01:00
|
|
|
return true;
|
2011-12-07 14:37:51 +01:00
|
|
|
case pmExtern_THIS_SHOULD_BE_AVOIDED:
|
2012-01-22 20:49:43 +01:00
|
|
|
dsyslog("[softhddev] play mode external\n");
|
2012-01-26 15:00:49 +01:00
|
|
|
Suspend(1, 1, 0);
|
|
|
|
return true;
|
2011-12-07 14:37:51 +01:00
|
|
|
default:
|
2012-02-22 15:06:05 +01:00
|
|
|
dsyslog("[softhddev] playmode not implemented... %d\n", play_mode);
|
2011-12-07 14:37:51 +01:00
|
|
|
break;
|
|
|
|
}
|
2012-02-23 15:32:43 +01:00
|
|
|
|
2012-02-23 23:33:00 +01:00
|
|
|
return::SetPlayMode(play_mode);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-01-30 15:58:21 +01:00
|
|
|
/**
|
|
|
|
** Gets the current System Time Counter, which can be used to
|
|
|
|
** synchronize audio, video and subtitles.
|
|
|
|
*/
|
2011-12-14 18:01:03 +01:00
|
|
|
int64_t cSoftHdDevice::GetSTC(void)
|
|
|
|
{
|
2012-01-22 17:07:08 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-14 18:01:03 +01:00
|
|
|
|
2012-01-05 17:20:44 +01:00
|
|
|
return::VideoGetClock();
|
2011-12-14 18:01:03 +01:00
|
|
|
}
|
|
|
|
|
2012-01-08 21:46:00 +01:00
|
|
|
/**
|
|
|
|
** Set trick play speed.
|
|
|
|
**
|
2012-02-16 15:31:53 +01:00
|
|
|
** Every single frame shall then be displayed the given number of
|
|
|
|
** times.
|
|
|
|
**
|
2012-01-08 21:46:00 +01:00
|
|
|
** @param speed trick speed
|
|
|
|
*/
|
|
|
|
void cSoftHdDevice::TrickSpeed(int speed)
|
2011-12-07 14:37:51 +01:00
|
|
|
{
|
2012-01-08 21:46:00 +01:00
|
|
|
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, speed);
|
2012-02-16 15:31:53 +01:00
|
|
|
|
|
|
|
::TrickSpeed(speed);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-02-16 15:31:53 +01:00
|
|
|
/**
|
|
|
|
** Clears all video and audio data from the device.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
void cSoftHdDevice::Clear(void)
|
|
|
|
{
|
|
|
|
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-14 18:01:03 +01:00
|
|
|
|
|
|
|
cDevice::Clear();
|
|
|
|
::Clear();
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-02-16 15:31:53 +01:00
|
|
|
/**
|
|
|
|
** Sets the device into play mode (after a previous trick mode)
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
void cSoftHdDevice::Play(void)
|
|
|
|
{
|
|
|
|
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-14 18:01:03 +01:00
|
|
|
|
|
|
|
cDevice::Play();
|
|
|
|
::Play();
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-01-10 15:52:07 +01:00
|
|
|
/**
|
|
|
|
** Puts the device into "freeze frame" mode.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
void cSoftHdDevice::Freeze(void)
|
|
|
|
{
|
|
|
|
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-14 18:01:03 +01:00
|
|
|
|
|
|
|
cDevice::Freeze();
|
|
|
|
::Freeze();
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-02-12 20:14:43 +01:00
|
|
|
/**
|
|
|
|
** Turns off audio while replaying.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
void cSoftHdDevice::Mute(void)
|
|
|
|
{
|
|
|
|
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
|
|
|
|
|
|
|
cDevice::Mute();
|
|
|
|
::Mute();
|
|
|
|
}
|
|
|
|
|
2012-01-08 21:46:00 +01:00
|
|
|
/**
|
|
|
|
** Display the given I-frame as a still picture.
|
|
|
|
*/
|
|
|
|
void cSoftHdDevice::StillPicture(const uchar * data, int length)
|
2011-12-07 14:37:51 +01:00
|
|
|
{
|
2012-01-24 16:37:11 +01:00
|
|
|
dsyslog("[softhddev]%s: %s %p %d\n", __FUNCTION__,
|
|
|
|
data[0] == 0x47 ? "ts" : "pes", data, length);
|
2012-01-08 21:46:00 +01:00
|
|
|
|
2012-01-09 17:03:04 +01:00
|
|
|
if (data[0] == 0x47) { // ts sync
|
2012-01-08 21:46:00 +01:00
|
|
|
cDevice::StillPicture(data, length);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
::StillPicture(data, length);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-01-08 21:46:00 +01:00
|
|
|
/**
|
|
|
|
** Check if the device is ready for further action.
|
|
|
|
**
|
|
|
|
** @param poller file handles (unused)
|
|
|
|
** @param timeout_ms timeout in ms to become ready
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
bool cSoftHdDevice::Poll(
|
2011-12-12 17:06:05 +01:00
|
|
|
__attribute__ ((unused)) cPoller & poller, int timeout_ms)
|
2011-12-07 14:37:51 +01:00
|
|
|
{
|
2012-01-22 17:07:08 +01:00
|
|
|
//dsyslog("[softhddev]%s: %d\n", __FUNCTION__, timeout_ms);
|
2011-12-12 17:06:05 +01:00
|
|
|
|
2012-01-05 17:20:44 +01:00
|
|
|
return::Poll(timeout_ms);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-01-08 21:46:00 +01:00
|
|
|
/**
|
|
|
|
** Flush the device output buffers.
|
|
|
|
**
|
|
|
|
** @param timeout_ms timeout in ms to become ready
|
|
|
|
*/
|
2011-12-14 18:01:03 +01:00
|
|
|
bool cSoftHdDevice::Flush(int timeout_ms)
|
2011-12-07 14:37:51 +01:00
|
|
|
{
|
2011-12-14 18:01:03 +01:00
|
|
|
dsyslog("[softhddev]%s: %d ms\n", __FUNCTION__, timeout_ms);
|
|
|
|
|
2012-01-08 21:46:00 +01:00
|
|
|
return::Flush(timeout_ms);
|
2011-12-14 18:01:03 +01:00
|
|
|
}
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2012-02-01 16:50:48 +01:00
|
|
|
/**
|
|
|
|
** Sets the video display format to the given one (only useful if this
|
|
|
|
** device has an MPEG decoder).
|
|
|
|
*/
|
2012-02-23 23:33:00 +01:00
|
|
|
void cSoftHdDevice::
|
|
|
|
SetVideoDisplayFormat(eVideoDisplayFormat video_display_format)
|
2012-02-01 16:50:48 +01:00
|
|
|
{
|
|
|
|
static int last = -1;
|
|
|
|
|
|
|
|
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, video_display_format);
|
|
|
|
|
2012-02-12 20:30:50 +01:00
|
|
|
cDevice::SetVideoDisplayFormat(video_display_format);
|
|
|
|
|
2012-02-01 16:50:48 +01:00
|
|
|
// called on every channel switch, no need to kill osd...
|
|
|
|
if (last != video_display_format) {
|
|
|
|
last = video_display_format;
|
2012-02-06 20:54:20 +01:00
|
|
|
|
2012-02-01 16:50:48 +01:00
|
|
|
::VideoSetDisplayFormat(video_display_format);
|
2012-02-06 20:54:20 +01:00
|
|
|
OsdDirty = 1;
|
2012-02-01 16:50:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-17 15:10:24 +01:00
|
|
|
/**
|
|
|
|
** Sets the output video format to either 16:9 or 4:3 (only useful
|
|
|
|
** if this device has an MPEG decoder).
|
|
|
|
**
|
|
|
|
** Should call SetVideoDisplayFormat.
|
|
|
|
**
|
|
|
|
** @param video_format16_9 flag true 16:9.
|
|
|
|
*/
|
|
|
|
void cSoftHdDevice::SetVideoFormat(bool video_format16_9)
|
|
|
|
{
|
|
|
|
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, video_format16_9);
|
|
|
|
|
|
|
|
// FIXME: 4:3 / 16:9 video format not supported.
|
|
|
|
|
|
|
|
SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat));
|
|
|
|
}
|
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
/**
|
2012-01-18 15:15:37 +01:00
|
|
|
** Returns the width, height and video_aspect ratio of the currently
|
|
|
|
** displayed video material.
|
|
|
|
**
|
|
|
|
** @note the size is used to scale the subtitle.
|
|
|
|
*/
|
|
|
|
void cSoftHdDevice::GetVideoSize(int &width, int &height, double &video_aspect)
|
|
|
|
{
|
|
|
|
::GetOsdSize(&width, &height, &video_aspect);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Returns the width, height and pixel_aspect ratio the OSD.
|
2011-12-07 14:37:51 +01:00
|
|
|
**
|
|
|
|
** FIXME: Called every second, for nothing (no OSD displayed)?
|
|
|
|
*/
|
|
|
|
void cSoftHdDevice::GetOsdSize(int &width, int &height, double &pixel_aspect)
|
|
|
|
{
|
|
|
|
::GetOsdSize(&width, &height, &pixel_aspect);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2012-02-21 20:55:28 +01:00
|
|
|
#ifndef xxUSE_TS_AUDIO
|
|
|
|
|
2012-01-08 21:46:00 +01:00
|
|
|
/**
|
|
|
|
** Play a audio packet.
|
2012-02-21 20:55:28 +01:00
|
|
|
**
|
|
|
|
** @param data exactly one complete PES packet (which is incomplete)
|
|
|
|
** @param length length of PES packet
|
|
|
|
** @param id type of audio data this packet holds
|
2012-01-08 21:46:00 +01:00
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
int cSoftHdDevice::PlayAudio(const uchar * data, int length, uchar id)
|
|
|
|
{
|
|
|
|
//dsyslog("[softhddev]%s: %p %p %d %d\n", __FUNCTION__, this, data, length, id);
|
|
|
|
|
2012-01-08 21:46:00 +01:00
|
|
|
return::PlayAudio(data, length, id);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-02-21 20:55:28 +01:00
|
|
|
#endif
|
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
void cSoftHdDevice::SetAudioTrackDevice(
|
|
|
|
__attribute__ ((unused)) eTrackType type)
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-01-06 15:39:32 +01:00
|
|
|
void cSoftHdDevice::SetDigitalAudioDevice( __attribute__ ((unused)) bool on)
|
2011-12-07 14:37:51 +01:00
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s: %s\n", __FUNCTION__, on ? "true" : "false");
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-01-06 15:39:32 +01:00
|
|
|
void cSoftHdDevice::SetAudioChannelDevice( __attribute__ ((unused))
|
|
|
|
int audio_channel)
|
2011-12-07 14:37:51 +01:00
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s: %d\n", __FUNCTION__, audio_channel);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int cSoftHdDevice::GetAudioChannelDevice(void)
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-02-12 20:14:43 +01:00
|
|
|
/**
|
|
|
|
** Sets the audio volume on this device (Volume = 0...255).
|
|
|
|
**
|
|
|
|
** @param volume device volume
|
|
|
|
*/
|
|
|
|
void cSoftHdDevice::SetVolumeDevice(int volume)
|
|
|
|
{
|
|
|
|
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, volume);
|
|
|
|
|
|
|
|
::SetVolumeDevice(volume);
|
|
|
|
}
|
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2012-02-06 20:54:20 +01:00
|
|
|
/**
|
|
|
|
** Play a video packet.
|
2012-02-21 20:55:28 +01:00
|
|
|
**
|
|
|
|
** @param data exactly one complete PES packet (which is incomplete)
|
|
|
|
** @param length length of PES packet
|
2012-02-06 20:54:20 +01:00
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
int cSoftHdDevice::PlayVideo(const uchar * data, int length)
|
|
|
|
{
|
|
|
|
//dsyslog("[softhddev]%s: %p %d\n", __FUNCTION__, data, length);
|
|
|
|
|
2012-01-05 17:20:44 +01:00
|
|
|
return::PlayVideo(data, length);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
///
|
|
|
|
/// Play a TS video packet.
|
|
|
|
///
|
2012-01-19 00:16:15 +01:00
|
|
|
int cSoftHdDevice::PlayTsVideo(const uchar * data, int length)
|
2011-12-07 14:37:51 +01:00
|
|
|
{
|
|
|
|
// many code to repeat
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-02-19 19:22:03 +01:00
|
|
|
#if !defined(USE_AUDIO_THREAD) || defined(USE_TS_AUDIO)
|
2012-01-19 00:16:15 +01:00
|
|
|
|
2012-01-03 21:31:03 +01:00
|
|
|
///
|
|
|
|
/// Play a TS audio packet.
|
|
|
|
///
|
|
|
|
/// misuse this function as audio poller
|
|
|
|
///
|
2012-01-19 00:16:15 +01:00
|
|
|
/// @param data ts data buffer
|
|
|
|
/// @param length ts packet length
|
|
|
|
///
|
2012-01-03 21:31:03 +01:00
|
|
|
int cSoftHdDevice::PlayTsAudio(const uchar * data, int length)
|
|
|
|
{
|
2012-02-19 19:22:03 +01:00
|
|
|
#ifdef USE_TS_AUDIO
|
|
|
|
return::PlayTsAudio(data, length);
|
|
|
|
#else
|
2012-01-03 21:31:03 +01:00
|
|
|
AudioPoller();
|
|
|
|
|
2012-01-05 17:20:44 +01:00
|
|
|
return cDevice::PlayTsAudio(data, length);
|
2012-02-19 19:22:03 +01:00
|
|
|
#endif
|
2012-01-03 21:31:03 +01:00
|
|
|
}
|
2012-01-19 00:16:15 +01:00
|
|
|
|
2012-01-03 21:31:03 +01:00
|
|
|
#endif
|
|
|
|
|
2012-01-20 21:46:22 +01:00
|
|
|
/**
|
|
|
|
** Grabs the currently visible screen image.
|
|
|
|
**
|
|
|
|
** @param size size of the returned data
|
|
|
|
** @param jpeg flag true, create JPEG data
|
|
|
|
** @param quality JPEG quality
|
|
|
|
** @param width number of horizontal pixels in the frame
|
|
|
|
** @param height number of vertical pixels in the frame
|
|
|
|
*/
|
|
|
|
uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width,
|
|
|
|
int height)
|
2011-12-07 14:37:51 +01:00
|
|
|
{
|
|
|
|
dsyslog("[softhddev]%s: %d, %d, %d, %dx%d\n", __FUNCTION__, size, jpeg,
|
2012-01-20 21:46:22 +01:00
|
|
|
quality, width, height);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
2012-01-21 15:56:45 +01:00
|
|
|
return::GrabImage(&size, jpeg, quality, width, height);
|
2011-12-14 18:01:03 +01:00
|
|
|
}
|
2011-12-07 14:37:51 +01:00
|
|
|
|
2012-02-12 20:30:50 +01:00
|
|
|
/**
|
|
|
|
** Call rgb to jpeg for C Plugin.
|
|
|
|
*/
|
|
|
|
extern "C" uint8_t * CreateJpeg(uint8_t * image, int *size, int quality,
|
|
|
|
int width, int height)
|
|
|
|
{
|
|
|
|
return (uint8_t *) RgbToJpeg((uchar *) image, width, height, *size,
|
|
|
|
quality);
|
|
|
|
}
|
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// cPlugin
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
class cPluginSoftHdDevice:public cPlugin
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
cPluginSoftHdDevice(void);
|
|
|
|
virtual ~ cPluginSoftHdDevice(void);
|
|
|
|
virtual const char *Version(void);
|
|
|
|
virtual const char *Description(void);
|
|
|
|
virtual const char *CommandLineHelp(void);
|
|
|
|
virtual bool ProcessArgs(int, char *[]);
|
|
|
|
virtual bool Initialize(void);
|
|
|
|
virtual bool Start(void);
|
|
|
|
virtual void Stop(void);
|
2012-01-22 11:12:57 +01:00
|
|
|
// virtual void Housekeeping(void);
|
2011-12-07 14:37:51 +01:00
|
|
|
virtual void MainThreadHook(void);
|
2012-01-10 15:52:07 +01:00
|
|
|
virtual const char *MainMenuEntry(void);
|
|
|
|
virtual cOsdObject *MainMenuAction(void);
|
2011-12-07 14:37:51 +01:00
|
|
|
virtual cMenuSetupPage *SetupMenu(void);
|
|
|
|
virtual bool SetupParse(const char *, const char *);
|
2012-01-12 15:20:01 +01:00
|
|
|
// virtual bool Service(const char *, void * = NULL);
|
|
|
|
virtual const char **SVDRPHelpPages(void);
|
|
|
|
virtual cString SVDRPCommand(const char *, const char *, int &);
|
2011-12-07 14:37:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
cPluginSoftHdDevice::cPluginSoftHdDevice(void)
|
|
|
|
{
|
|
|
|
// Initialize any member variables here.
|
|
|
|
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
|
|
|
|
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
cPluginSoftHdDevice::~cPluginSoftHdDevice(void)
|
|
|
|
{
|
|
|
|
// Clean up after yourself!
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-08 20:50:32 +01:00
|
|
|
|
|
|
|
::SoftHdDeviceExit();
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-02-23 23:33:00 +01:00
|
|
|
/**
|
|
|
|
** Return plugin version number.
|
|
|
|
**
|
|
|
|
** @returns version number as constant string.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
const char *cPluginSoftHdDevice::Version(void)
|
|
|
|
{
|
|
|
|
return VERSION;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *cPluginSoftHdDevice::Description(void)
|
|
|
|
{
|
|
|
|
return tr(DESCRIPTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Return a string that describes all known command line options.
|
|
|
|
*/
|
|
|
|
const char *cPluginSoftHdDevice::CommandLineHelp(void)
|
|
|
|
{
|
|
|
|
return::CommandLineHelp();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Process the command line arguments.
|
|
|
|
*/
|
|
|
|
bool cPluginSoftHdDevice::ProcessArgs(int argc, char *argv[])
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
return::ProcessArgs(argc, argv);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cPluginSoftHdDevice::Initialize(void)
|
|
|
|
{
|
|
|
|
// Start any background activities the plugin shall perform.
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
MyDevice = new cSoftHdDevice();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-01-11 18:01:18 +01:00
|
|
|
/**
|
|
|
|
** Start any background activities the plugin shall perform.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
bool cPluginSoftHdDevice::Start(void)
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
2012-01-11 18:01:18 +01:00
|
|
|
if (!MyDevice->IsPrimaryDevice()) {
|
2011-12-07 14:37:51 +01:00
|
|
|
isyslog("[softhddev] softhddevice is not the primary device!");
|
|
|
|
if (ConfigMakePrimary) {
|
|
|
|
// Must be done in the main thread
|
|
|
|
dsyslog("[softhddev] makeing softhddevice %d the primary device!",
|
|
|
|
MyDevice->DeviceNumber());
|
|
|
|
DoMakePrimary = 1;
|
|
|
|
} else {
|
|
|
|
isyslog("[softhddev] softhddevice %d is not the primary device!",
|
|
|
|
MyDevice->DeviceNumber());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
::Start();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cPluginSoftHdDevice::Stop(void)
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
::Stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
2012-01-22 11:12:57 +01:00
|
|
|
/**
|
|
|
|
** Perform any cleanup or other regular tasks.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
void cPluginSoftHdDevice::Housekeeping(void)
|
|
|
|
{
|
2012-01-22 11:12:57 +01:00
|
|
|
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
|
|
|
|
|
|
|
// ::Housekeeping();
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-01-10 15:52:07 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Create main menu entry.
|
|
|
|
*/
|
2011-12-07 14:37:51 +01:00
|
|
|
const char *cPluginSoftHdDevice::MainMenuEntry(void)
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2012-01-10 15:52:07 +01:00
|
|
|
|
|
|
|
return ConfigHideMainMenuEntry ? NULL : tr(MAINMENUENTRY);
|
2011-12-07 14:37:51 +01:00
|
|
|
}
|
|
|
|
|
2012-01-10 15:52:07 +01:00
|
|
|
/**
|
|
|
|
** Perform the action when selected from the main VDR menu.
|
|
|
|
*/
|
|
|
|
cOsdObject *cPluginSoftHdDevice::MainMenuAction(void)
|
|
|
|
{
|
2012-01-22 17:07:08 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2012-01-10 15:52:07 +01:00
|
|
|
|
2012-02-19 19:22:03 +01:00
|
|
|
#if 0
|
2012-01-22 11:12:57 +01:00
|
|
|
//MyDevice->StopReplay();
|
2012-02-08 23:26:49 +01:00
|
|
|
if (!cSoftHdControl::Player) { // not already suspended
|
|
|
|
cControl::Launch(new cSoftHdControl);
|
|
|
|
cControl::Attach();
|
|
|
|
Suspend(ConfigSuspendClose, ConfigSuspendClose, ConfigSuspendX11);
|
|
|
|
if (ShutdownHandler.GetUserInactiveTime()) {
|
|
|
|
dsyslog("[softhddev]%s: set user inactive\n", __FUNCTION__);
|
|
|
|
ShutdownHandler.SetUserInactive();
|
|
|
|
}
|
2012-01-19 00:16:15 +01:00
|
|
|
}
|
2012-01-10 15:52:07 +01:00
|
|
|
|
|
|
|
return NULL;
|
2012-02-19 19:22:03 +01:00
|
|
|
#endif
|
|
|
|
return new cSoftHdMenu("SoftHdDevice");
|
2012-01-10 15:52:07 +01:00
|
|
|
}
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
** Called for every plugin once during every cycle of VDR's main program
|
|
|
|
** loop.
|
|
|
|
*/
|
|
|
|
void cPluginSoftHdDevice::MainThreadHook(void)
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
if (DoMakePrimary && MyDevice) {
|
|
|
|
dsyslog("[softhddev]%s: switching primary device\n", __FUNCTION__);
|
|
|
|
cDevice::SetPrimaryDevice(MyDevice->DeviceNumber() + 1);
|
|
|
|
DoMakePrimary = 0;
|
|
|
|
}
|
2012-01-11 18:01:18 +01:00
|
|
|
// check if user is inactive, automatic enter suspend mode
|
|
|
|
if (ShutdownHandler.IsUserInactive()) {
|
|
|
|
// this is regular called, but guarded against double calls
|
2012-01-26 15:00:49 +01:00
|
|
|
Suspend(ConfigSuspendClose, ConfigSuspendClose, ConfigSuspendX11);
|
2012-01-11 18:01:18 +01:00
|
|
|
}
|
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
::MainThreadHook();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Return our setup menu.
|
|
|
|
*/
|
|
|
|
cMenuSetupPage *cPluginSoftHdDevice::SetupMenu(void)
|
|
|
|
{
|
2012-01-06 15:39:32 +01:00
|
|
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
|
|
|
return new cMenuSetupSoft;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Parse setup parameters
|
2012-01-20 15:33:37 +01:00
|
|
|
**
|
|
|
|
** @param name paramter name (case sensetive)
|
|
|
|
** @param value value as string
|
|
|
|
**
|
|
|
|
** @returns true if the parameter is supported.
|
2011-12-07 14:37:51 +01:00
|
|
|
*/
|
|
|
|
bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
|
|
|
{
|
2012-01-09 17:03:04 +01:00
|
|
|
int i;
|
|
|
|
|
2012-01-10 15:52:07 +01:00
|
|
|
//dsyslog("[softhddev]%s: '%s' = '%s'\n", __FUNCTION__, name, value);
|
2011-12-07 14:37:51 +01:00
|
|
|
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "MakePrimary")) {
|
2011-12-07 14:37:51 +01:00
|
|
|
ConfigMakePrimary = atoi(value);
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "HideMainMenuEntry")) {
|
2012-01-10 15:52:07 +01:00
|
|
|
ConfigHideMainMenuEntry = atoi(value);
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "SkipLines")) {
|
2012-02-02 16:00:26 +01:00
|
|
|
VideoSetSkipLines(ConfigVideoSkipLines = atoi(value));
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "StudioLevels")) {
|
2012-02-13 14:13:24 +01:00
|
|
|
VideoSetStudioLevels(ConfigVideoStudioLevels = atoi(value));
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "60HzMode")) {
|
|
|
|
VideoSet60HzMode(ConfigVideo60HzMode = atoi(value));
|
|
|
|
return true;
|
|
|
|
}
|
2012-01-09 17:03:04 +01:00
|
|
|
for (i = 0; i < RESOLUTIONS; ++i) {
|
2012-01-20 15:33:37 +01:00
|
|
|
char buf[128];
|
|
|
|
|
2012-01-09 17:03:04 +01:00
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling");
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, buf)) {
|
2012-01-09 17:03:04 +01:00
|
|
|
ConfigVideoScaling[i] = atoi(value);
|
|
|
|
VideoSetScaling(ConfigVideoScaling);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Deinterlace");
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, buf)) {
|
2012-01-09 17:03:04 +01:00
|
|
|
ConfigVideoDeinterlace[i] = atoi(value);
|
|
|
|
VideoSetDeinterlace(ConfigVideoDeinterlace);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i],
|
|
|
|
"SkipChromaDeinterlace");
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, buf)) {
|
2012-01-09 17:03:04 +01:00
|
|
|
ConfigVideoSkipChromaDeinterlace[i] = atoi(value);
|
|
|
|
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace);
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-14 22:29:17 +01:00
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "InverseTelecine");
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, buf)) {
|
2012-02-14 22:29:17 +01:00
|
|
|
ConfigVideoInverseTelecine[i] = atoi(value);
|
|
|
|
VideoSetInverseTelecine(ConfigVideoInverseTelecine);
|
|
|
|
return true;
|
|
|
|
}
|
2012-01-09 17:03:04 +01:00
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Denoise");
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, buf)) {
|
2012-01-09 17:03:04 +01:00
|
|
|
ConfigVideoDenoise[i] = atoi(value);
|
|
|
|
VideoSetDenoise(ConfigVideoDenoise);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Sharpen");
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, buf)) {
|
2012-01-09 17:03:04 +01:00
|
|
|
ConfigVideoSharpen[i] = atoi(value);
|
|
|
|
VideoSetSharpen(ConfigVideoSharpen);
|
|
|
|
return true;
|
|
|
|
}
|
2011-12-12 17:06:05 +01:00
|
|
|
}
|
2012-01-20 15:33:37 +01:00
|
|
|
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "AudioDelay")) {
|
2011-12-19 17:03:40 +01:00
|
|
|
VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value));
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "AudioPassthrough")) {
|
2012-01-07 03:05:43 +01:00
|
|
|
CodecSetAudioPassthrough(ConfigAudioPassthrough = atoi(value));
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "AudioDownmix")) {
|
2012-02-21 22:24:28 +01:00
|
|
|
CodecSetAudioDownmix(ConfigAudioDownmix = atoi(value));
|
|
|
|
return true;
|
|
|
|
}
|
2011-12-07 14:37:51 +01:00
|
|
|
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "AutoCrop.Interval")) {
|
2012-01-20 15:33:37 +01:00
|
|
|
VideoSetAutoCrop(ConfigAutoCropInterval =
|
2012-01-27 23:49:05 +01:00
|
|
|
atoi(value), ConfigAutoCropDelay, ConfigAutoCropTolerance);
|
2012-01-20 15:33:37 +01:00
|
|
|
return true;
|
|
|
|
}
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "AutoCrop.Delay")) {
|
2012-01-20 15:33:37 +01:00
|
|
|
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay =
|
2012-01-27 23:49:05 +01:00
|
|
|
atoi(value), ConfigAutoCropTolerance);
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "AutoCrop.Tolerance")) {
|
2012-02-02 16:00:26 +01:00
|
|
|
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay,
|
|
|
|
ConfigAutoCropTolerance = atoi(value));
|
2012-01-20 15:33:37 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "Suspend.Close")) {
|
2012-01-22 20:49:43 +01:00
|
|
|
ConfigSuspendClose = atoi(value);
|
|
|
|
return true;
|
|
|
|
}
|
2012-02-22 15:06:05 +01:00
|
|
|
if (!strcasecmp(name, "Suspend.X11")) {
|
2012-01-22 20:49:43 +01:00
|
|
|
ConfigSuspendX11 = atoi(value);
|
|
|
|
return true;
|
|
|
|
}
|
2011-12-07 14:37:51 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-01-10 15:52:07 +01:00
|
|
|
#if 0
|
|
|
|
|
|
|
|
bool cPluginSoftHdDevice::Service(const char *Id, void *Data)
|
|
|
|
{
|
|
|
|
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2012-01-12 15:20:01 +01:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// cPlugin SVDRP
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Return SVDRP commands help pages.
|
|
|
|
**
|
|
|
|
** return a pointer to a list of help strings for all of the plugin's
|
|
|
|
** SVDRP commands.
|
|
|
|
*/
|
|
|
|
const char **cPluginSoftHdDevice::SVDRPHelpPages(void)
|
|
|
|
{
|
|
|
|
// FIXME: translation?
|
|
|
|
static const char *text[] = {
|
2012-02-02 16:00:26 +01:00
|
|
|
"SUSP\n" " Suspend plugin.\n",
|
|
|
|
"RESU\n" " Resume plugin.\n",
|
2012-01-12 15:20:01 +01:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
** Handle SVDRP commands.
|
|
|
|
*/
|
|
|
|
cString cPluginSoftHdDevice::SVDRPCommand(const char *command,
|
2012-01-12 18:55:07 +01:00
|
|
|
__attribute__ ((unused)) const char *option,
|
|
|
|
__attribute__ ((unused)) int &reply_code)
|
2012-01-12 15:20:01 +01:00
|
|
|
{
|
|
|
|
if (!strcasecmp(command, "SUSP")) {
|
2012-02-08 23:26:49 +01:00
|
|
|
if (cSoftHdControl::Player) { // already suspended
|
|
|
|
return "SoftHdDevice already suspended";
|
|
|
|
}
|
|
|
|
// should be after suspend, but SetPlayMode resumes
|
2012-01-22 11:12:57 +01:00
|
|
|
cControl::Launch(new cSoftHdControl);
|
|
|
|
cControl::Attach();
|
2012-01-26 15:00:49 +01:00
|
|
|
Suspend(ConfigSuspendClose, ConfigSuspendClose, ConfigSuspendX11);
|
2012-01-12 15:20:01 +01:00
|
|
|
return "SoftHdDevice is suspended";
|
|
|
|
}
|
2012-01-22 11:12:57 +01:00
|
|
|
if (!strcasecmp(command, "RESU")) {
|
2012-01-22 20:49:43 +01:00
|
|
|
if (ShutdownHandler.GetUserInactiveTime()) {
|
|
|
|
ShutdownHandler.SetUserInactiveTimeout();
|
|
|
|
}
|
2012-02-08 23:26:49 +01:00
|
|
|
if (cSoftHdControl::Player) { // suspended
|
|
|
|
cControl::Shutdown(); // not need, if not suspended
|
|
|
|
}
|
2012-01-22 11:12:57 +01:00
|
|
|
Resume();
|
|
|
|
return "SoftHdDevice is resumed";
|
|
|
|
}
|
2012-01-12 15:20:01 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-12-07 14:37:51 +01:00
|
|
|
VDRPLUGINCREATOR(cPluginSoftHdDevice); // Don't touch this!
|