summaryrefslogtreecommitdiff
path: root/dxr3device.c
diff options
context:
space:
mode:
authorChristian Gmeiner <christian.gmeiner@gmail.com>2010-02-03 11:34:01 +0100
committerChristian Gmeiner <christian.gmeiner@gmail.com>2010-02-03 11:34:01 +0100
commit1c564f1da32e294606bb815b23109e5a08d2e87b (patch)
tree69748b49cb3d4734beac87ab9b533695ffc48ce8 /dxr3device.c
parentf69bf5ba73f56008514e4899cc9fef630ea9e044 (diff)
downloadvdr-plugin-dxr3-1c564f1da32e294606bb815b23109e5a08d2e87b.tar.gz
vdr-plugin-dxr3-1c564f1da32e294606bb815b23109e5a08d2e87b.tar.bz2
merge dxr3interface into dxr3device
Diffstat (limited to 'dxr3device.c')
-rw-r--r--dxr3device.c332
1 files changed, 270 insertions, 62 deletions
diff --git a/dxr3device.c b/dxr3device.c
index 72853d2..8177bec 100644
--- a/dxr3device.c
+++ b/dxr3device.c
@@ -20,20 +20,26 @@
*
*/
+#include <sys/ioctl.h>
+
#include "dxr3device.h"
-#include "dxr3interface.h"
#include "dxr3tools.h"
#include "dxr3osd.h"
#include "dxr3audio-oss.h"
#include "dxr3audio-alsa.h"
#include "dxr3pesframe.h"
+#include "settings.h"
+
+static const char *DEV_DXR3_OSD = "_sp";
+static const char *DEV_DXR3_VIDEO = "_mv";
+static const char *DEV_DXR3_CONT = "";
-// ==================================
-//! constructor
-cDxr3Device::cDxr3Device() : pluginOn(true), vPts(0), scrSet(false)
+cDxr3Device::cDxr3Device() : pluginOn(true), vPts(0), scrSet(false), playCount(0)
{
m_spuDecoder = NULL;
+ claimDevices();
+
// TODO: this will be later the place,
// where we will decide what kind of
// audio output system we will use.
@@ -44,18 +50,29 @@ cDxr3Device::cDxr3Device() : pluginOn(true), vPts(0), scrSet(false)
aDecoder = new cDxr3AudioDecoder();
}
-// ==================================
cDxr3Device::~cDxr3Device()
{
audioOut->releaseDevice();
delete audioOut;
delete aDecoder;
+ releaseDevices();
+
if (m_spuDecoder)
delete m_spuDecoder;
}
-// ==================================
+int cDxr3Device::Dxr3Open(const char *name, int mode, bool report_error)
+{
+ const char *filename = *cDxr3Name(name, cSettings::instance()->card());
+ int fd = open(filename, mode);
+
+ if (report_error && (fd < 0)) {
+ LOG_ERROR_STR(filename);
+ }
+ return fd;
+}
+
void cDxr3Device::MakePrimaryDevice(bool On)
{
#if VDRVERSNUM >= 10711
@@ -67,31 +84,30 @@ void cDxr3Device::MakePrimaryDevice(bool On)
}
}
-// replaying
-// ==================================
-//! do we have an mpeg2 decoder?
bool cDxr3Device::HasDecoder() const
{
- // sure we have one ;)
return true;
}
-// ==================================
-//! can we replay vdr recordings?
bool cDxr3Device::CanReplay() const
{
- // also sure...
return true;
}
-// ==================================
bool cDxr3Device::SetPlayMode(ePlayMode PlayMode)
{
dsyslog("[dxr3-device] setting playmode %d", PlayMode);
+ uint32_t ioval = EM8300_PLAYMODE_PAUSED;
+
switch (PlayMode) {
case pmNone:
audioOut->setEnabled(false);
+ CHECK(ioctl(fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval));
+ ioval = 0;
+ CHECK(ioctl(fdControl, EM8300_IOCTL_SCR_SET, &ioval));
+ scrSet = false;
+ playCount = 0;
break;
case pmAudioVideo:
@@ -106,49 +122,45 @@ bool cDxr3Device::SetPlayMode(ePlayMode PlayMode)
return true;
}
-// ==================================
int64_t cDxr3Device::GetSTC()
{
return (vPts << 1);
}
-// ==================================
void cDxr3Device::TrickSpeed(int Speed)
{
dsyslog("dxr3: device: tricspeed: %d", Speed);
}
-// ==================================
-//! clear our demux buffer
void cDxr3Device::Clear()
{
dsyslog("[dxr3-device] clear");
+
+ uint32_t ioval = EM8300_SUBDEVICE_VIDEO;
+ CHECK(ioctl(fdControl, EM8300_IOCTL_FLUSH, &ioval));
+
+ ioval = EM8300_SUBDEVICE_AUDIO;
+ CHECK(ioctl(fdControl, EM8300_IOCTL_FLUSH, &ioval));
+
cDevice::Clear();
}
-// ==================================
-//! play a recording
void cDxr3Device::Play()
{
dsyslog("[dxr3-device] play");
}
-// ==================================
-//! puts the device into "freeze frame" mode
void cDxr3Device::Freeze()
{
dsyslog("[dxr3-device] freeze");
}
-// ==================================
void cDxr3Device::Mute()
{
audioOut->mute();
cDevice::Mute();
}
-// ==================================
-//! displays the given I-frame as a still picture.
void cDxr3Device::StillPicture(const uchar *Data, int Length)
{
dsyslog("[dxr3-device] stillpciture");
@@ -168,26 +180,13 @@ void cDxr3Device::StillPicture(const uchar *Data, int Length)
}
}
-// ==================================
bool cDxr3Device::Poll(cPoller &Poller, int TimeoutMs)
{
- /*
- if ((m_DemuxDevice.GetDemuxMode() == DXR3_DEMUX_TRICK_MODE &&
- m_DemuxDevice.GetTrickState() == DXR3_FREEZE)) {
- cCondWait::SleepMs(TimeoutMs);
- return false;
- }
- return m_DemuxDevice.Poll(TimeoutMs); // Poller.Poll(TimeoutMs);
- */
return true;
}
-// ==================================
-//! actually plays the given data block as video
int cDxr3Device::PlayVideo(const uchar *Data, int Length)
{
- static int i = 0;
-
cDxr3PesFrame frame;
frame.parse(Data, Length);
uint32_t pts = frame.GetPts();
@@ -199,24 +198,23 @@ int cDxr3Device::PlayVideo(const uchar *Data, int Length)
}
if (!scrSet && vPts != 0) {
- cDxr3Interface::instance()->SetSysClock(vPts);
+ CHECK(ioctl(fdControl, EM8300_IOCTL_SCR_SET, &vPts));
scrSet = true;
}
- cDxr3Interface::instance()->PlayVideoFrame(&frame, vPts);
+ playVideoFrame(&frame, vPts);
- if (i < 7) {
- i++;
+ if (playCount < 7) {
+ playCount++;
}
- if (i == 7) {
- cDxr3Interface::instance()->SetPlayMode();
- i = 8;
+ if (playCount == 7) {
+ //cDxr3Interface::instance()->SetPlayMode();
+ setPlayMode();
+ playCount = 8;
}
return Length;
}
-// ==================================
-// plays additional audio streams, like Dolby Digital
int cDxr3Device::PlayAudio(const uchar *Data, int Length, uchar Id)
{
cDxr3PesFrame frame;
@@ -230,35 +228,61 @@ int cDxr3Device::PlayAudio(const uchar *Data, int Length, uchar Id)
#if VDRVERSNUM >= 10710
void cDxr3Device::GetVideoSize(int &Width, int &Height, double &VideoAspect)
{
- cDxr3Interface::instance()->dimension((uint32_t&)Width, (uint32_t&)Height);
- uint32_t aspect = cDxr3Interface::instance()->GetAspectRatio();
+ uint32_t aspect;
+ CHECK(ioctl(fdControl, EM8300_IOCTL_GET_ASPECTRATIO, &aspect));
if (aspect == EM8300_ASPECTRATIO_4_3) {
VideoAspect = 4.0 / 3.0;
} else {
VideoAspect = 16.0 / 9.0;
}
+
+ Width = horizontal;
+ Height = vertical;
}
#endif
-// additional functions
-
-// ==================================
void cDxr3Device::SetVideoFormat(bool VideoFormat16_9)
{
- cDxr3Interface::instance()->SetAspectRatio(
- VideoFormat16_9 ? EM8300_ASPECTRATIO_16_9 : EM8300_ASPECTRATIO_4_3);
+ int ratio = EM8300_ASPECTRATIO_4_3;
+ if (VideoFormat16_9) {
+ ratio = EM8300_ASPECTRATIO_16_9;
+ }
+
+ int aspect;
+
+ if (cSettings::instance()->forceLetterBox()) {
+ ratio = EM8300_ASPECTRATIO_16_9;
+ }
+
+ if (Setup.VideoFormat) {
+ aspect = EM8300_ASPECTRATIO_4_3;
+#ifdef EM8300_IOCTL_SET_WSS
+ if (cSettings::Instance().GetUseWSS()) {
+ int wssmode;
+ if (ratio == EM8300_ASPECTRATIO_16_9) {
+ wssmode = EM8300_WSS_16_9;
+ } else {
+ wssmode = EM8300_WSS_OFF;
+ }
+
+ CHECK(ioctl(fdControl, EM8300_IOCTL_SET_WSS, &wssmode);
+ }
+#endif
+ } else {
+ aspect = ratio;
+ }
+
+ CHECK(ioctl(fdControl, EM8300_IOCTL_SET_ASPECTRATIO, &aspect));
+
+ SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat));
}
-// ==================================
-//! sets volume for audio output
void cDxr3Device::SetVolumeDevice(int Volume)
{
audioOut->setVolume(Volume);
}
-// ==================================
-//! sets audio channel for audio output (stereo, mono left, mono right)
void cDxr3Device::SetAudioChannelDevice(int AudioChannel)
{
audioOut->setAudioChannel(AudioChannel);
@@ -274,8 +298,6 @@ void cDxr3Device::SetDigitalAudioDevice(bool on)
audioOut->setDigitalAudio(on);
}
-// ==================================
-// get spudecoder
cSpuDecoder *cDxr3Device::GetSpuDecoder()
{
if (!m_spuDecoder && IsPrimaryDevice()) {
@@ -302,7 +324,7 @@ void cDxr3Device::turnPlugin(bool on)
}
// get full control over device
- cDxr3Interface::instance()->ClaimDevices();
+ claimDevices();
audioOut->openDevice();
// enable pes packet processing
@@ -319,7 +341,7 @@ void cDxr3Device::turnPlugin(bool on)
// release device and give control to somebody else
Tools::WriteInfoToOsd(tr("DXR3: releasing devices"));
- cDxr3Interface::instance()->ReleaseDevices();
+ releaseDevices();
audioOut->releaseDevice();
// disable pes packet processing
@@ -327,6 +349,192 @@ void cDxr3Device::turnPlugin(bool on)
}
}
+void cDxr3Device::dimension(uint32_t &hor, uint32_t &ver)
+{
+ hor = horizontal;
+ ver = vertical;
+}
+
+void cDxr3Device::setPalette(uint8_t *pal)
+{
+ CHECK(ioctl(fdSpu, EM8300_IOCTL_SPU_SETPALETTE, pal));
+}
+
+void cDxr3Device::writeSpu(const uint8_t* data, int length)
+{
+ WriteAllOrNothing(fdSpu, data, length, 1000, 10);
+}
+
+void cDxr3Device::setButton(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t palette)
+{
+ em8300_button_t button;
+
+ button.color = palette >> 16;
+ button.contrast = palette & 0xFFFF;
+ button.top = sy;
+ button.bottom = ey;
+ button.left = sx;
+ button.right = ex;
+
+ CHECK(ioctl(fdSpu, EM8300_IOCTL_SPU_BUTTON, &button));
+}
+
+void cDxr3Device::clearButton()
+{
+ em8300_button_t button;
+
+ // todo: why are there 1s and 2s - memset 0
+ button.color = 0;
+ button.contrast = 0;
+ button.top = 1;
+ button.bottom = 2;
+ button.left = 1;
+ button.right = 2;
+
+ CHECK(ioctl(fdSpu, EM8300_IOCTL_SPU_BUTTON, &button))
+}
+
+int cDxr3Device::ossSetPlayMode(uint32_t mode)
+{
+ return ioctl(fdControl, EM8300_IOCTL_SET_AUDIOMODE, &mode);
+}
+
+void cDxr3Device::claimDevices()
+{
+ // open control stream
+ fdControl = Dxr3Open(DEV_DXR3_CONT, O_WRONLY | O_SYNC);
+ if (fdControl < 0) {
+ esyslog("dxr3: please verify that the em8300 modules are loaded");
+ exit(1);
+ }
+
+ uploadFirmware();
+
+ ///< open multimedia streams
+ fdVideo = Dxr3Open(DEV_DXR3_VIDEO, O_WRONLY | O_SYNC);
+ fdSpu = Dxr3Open(DEV_DXR3_OSD, O_WRONLY | O_SYNC);
+
+ // everything ok?
+ if (fdVideo < 0 || fdSpu < 0) {
+ esyslog("dxr3: fatal: unable to open some em8300 devices");
+ exit(1);
+ }
+
+ // configure device based on settings
+ //ConfigureDevice();
+
+ // get bcs values from driver
+ CHECK(ioctl(fdControl, EM8300_IOCTL_GETBCS, &bcs));
+
+ playBlackFrame();
+}
+
+void cDxr3Device::releaseDevices()
+{
+ close(fdControl);
+ close(fdVideo);
+ close(fdSpu);
+
+ fdControl = fdVideo = fdSpu = -1;
+}
+
+void cDxr3Device::uploadFirmware()
+{
+ if (!cSettings::instance()->loadFirmware()) {
+ return;
+ }
+
+ dsyslog("[dxr3-interface] loading firmware");
+
+ // try to open it
+ // MICROCODE comes from makefile
+ int UCODE = open(MICROCODE, O_RDONLY);
+
+ if (UCODE < 0) {
+ esyslog("dxr3: fatal: unable to open microcode file %s", MICROCODE);
+ exit(1);
+ }
+
+ struct stat s;
+ if (fstat(UCODE, &s ) <0) {
+ esyslog("dxr3: fatal: unable to fstat microcode file %s", MICROCODE);
+ exit(1);
+ }
+
+ // read microcode
+ em8300_microcode_t em8300_microcode;
+ em8300_microcode.ucode = new char[s.st_size];
+ if (em8300_microcode.ucode == NULL) {
+ esyslog("dxr3: fatal: unable to malloc() space for microcode");
+ exit(1);
+ }
+
+ if (read(UCODE,em8300_microcode.ucode,s.st_size) < 1) {
+ esyslog("dxr3: fatal: unable to read microcode file %s", MICROCODE);
+ // free memory to avoid memory leak
+ delete[] (char*) em8300_microcode.ucode;
+ exit(1);
+ }
+
+ close(UCODE);
+ em8300_microcode.ucode_size = s.st_size;
+
+ // upload it
+ if( ioctl(fdControl, EM8300_IOCTL_INIT, &em8300_microcode) == -1) {
+ esyslog("dxr3: fatal: microcode upload failed: %m");
+ // free memory to avoid memory leak
+ delete [] (char*) em8300_microcode.ucode;
+ exit(1);
+ }
+
+ // free memory to avoid memory leak
+ delete [] (char*) em8300_microcode.ucode;
+}
+
+void cDxr3Device::setPlayMode()
+{
+ em8300_register_t reg;
+ int ioval;
+
+ ioval = EM8300_SUBDEVICE_AUDIO;
+ ioctl(fdControl, EM8300_IOCTL_FLUSH, &ioval);
+ fsync(fdVideo);
+
+ ioval = EM8300_PLAYMODE_PLAY;
+ CHECK(ioctl(fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval));
+ reg.microcode_register = 1;
+ reg.reg = 0;
+ reg.val = MVCOMMAND_SYNC;
+
+ CHECK(ioctl(fdControl, EM8300_IOCTL_WRITEREG, &reg));
+}
+
+void cDxr3Device::playVideoFrame(cDxr3PesFrame *frame, uint32_t pts)
+{
+ if (pts > 0) {
+ pts += 45000;
+ CHECK(ioctl(fdVideo, EM8300_IOCTL_VIDEO_SETPTS, &pts));
+ }
+
+ const uint8_t *data = frame->GetPayload();
+ uint32_t len = frame->GetPayloadLength();
+
+ WriteAllOrNothing(fdVideo, data, len, 1000, 10);
+}
+
+void cDxr3Device::playBlackFrame()
+{
+ extern char blackframe[];
+ extern int blackframeLength;
+
+ for (int i = 0; i < 3; i++) {
+ WriteAllOrNothing(fdVideo, (const uchar*)blackframe, blackframeLength, 1000, 10);
+ }
+
+ horizontal = 720;
+ vertical = 576;
+}
+
// Local variables:
// mode: c++
// c-file-style: "stroustrup"