diff options
author | austriancoder <austriancoder> | 2005-08-15 17:28:49 +0000 |
---|---|---|
committer | austriancoder <austriancoder> | 2005-08-15 17:28:49 +0000 |
commit | 290038f3de13b728cab6d3db7729078482903844 (patch) | |
tree | b83287be6ad0602f7f73a91c11b36074e5062be0 /dxr3interface.c | |
parent | 8955b4dfa419698ecb853bb8f1cdc1fe96d206d6 (diff) | |
download | vdr-plugin-dxr3-290038f3de13b728cab6d3db7729078482903844.tar.gz vdr-plugin-dxr3-290038f3de13b728cab6d3db7729078482903844.tar.bz2 |
HEAD = 0.2.3 release, because i want to start my coding with this codebase
Diffstat (limited to 'dxr3interface.c')
-rw-r--r-- | dxr3interface.c | 1205 |
1 files changed, 1205 insertions, 0 deletions
diff --git a/dxr3interface.c b/dxr3interface.c new file mode 100644 index 0000000..9f735fa --- /dev/null +++ b/dxr3interface.c @@ -0,0 +1,1205 @@ +/* + * dxr3interface.c + * + * Copyright (C) 2002-2004 Kai Möller + * Copyright (C) 2004 Christian Gmeiner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <assert.h> +#include <math.h> +#include <sys/soundcard.h> +#include <linux/dvb/audio.h> + +#include "dxr3interface.h" +#include "dxr3syncbuffer.h" +#include "dxr3osd.h" + +// ================================== +const int LPCM_HEADER_LENGTH = 7; +const int ZEROBUFFER_SIZE = 4096; +uint8_t zerobuffer[ZEROBUFFER_SIZE] = {0}; +const uint32_t UNKNOWN_AUDIO_MODE = 9; // default, unused value + +// ================================== +//! helper function to generate name +static const char *Dxr3Name(const char *Name, int n) +{ + static char buffer[PATH_MAX]; + snprintf(buffer, sizeof(buffer), "/dev/em8300%s-%d", Name, n); + return buffer; +} + +// ================================== +//! helper function to open card #n +static int Dxr3Open(const char *Name, int n, int Mode) +{ + const char *FileName = Dxr3Name(Name, n); + int fd = open(FileName, Mode); + + if (fd < 0) + { + esyslog("dxr3: unable to open %s: %m", FileName); + } + return fd; +} + +// ================================== +//! constructor +cDxr3Interface::cDxr3Interface() : + m_fdControl(-1), m_fdVideo(-1), m_fdAudio(-1), m_fdSpu(-1) +{ + // open control stream + m_fdControl = Dxr3Open("", cDxr3ConfigData::Instance().GetDxr3Card(), + O_WRONLY | O_SYNC); + if (m_fdControl < 0) + { + esyslog("dxr3: please verify that the em8300 modules are loaded"); + exit(1); + } + + // upload microcode to dxr3 + UploadMicroCode(); + + ///< open multimedia streams + m_fdVideo = Dxr3Open("_mv", cDxr3ConfigData::Instance().GetDxr3Card(), + O_WRONLY | O_SYNC); + m_fdAudio = Dxr3Open("_ma", cDxr3ConfigData::Instance().GetDxr3Card(), + O_WRONLY | O_SYNC); + m_fdSpu = Dxr3Open("_sp", cDxr3ConfigData::Instance().GetDxr3Card(), + O_WRONLY | O_SYNC); + + // everything ok? + if (m_fdVideo < 0 || m_fdAudio < 0 || m_fdSpu < 0) + { + + esyslog("dxr3: fatal: unable to open some em8300 devices"); + exit(1); + } + + // create clock + m_pClock = new cDxr3SysClock(m_fdControl, m_fdVideo, m_fdSpu); + + // everything ok? + if (!m_pClock) + { + esyslog("dxr3: fatal: unable to allocate memory for em8300 clock"); + exit(1); + } + + // set default values + m_AudioActive = false; + m_VideoActive = false; + m_OverlayActive = false; + m_ExternalReleased = false; + m_volume = 255; + m_audioChannel = AUDIO_STEREO; + m_horizontal = 720; + m_vertical = 576; + m_audioChannelCount = UNKNOWN_CHANNEL_COUNT; + m_audioDataRate = 0; + m_audioSampleSize = 0; + + m_audioMode = UNKNOWN_AUDIO_MODE; + m_aspectRatio = UNKNOWN_ASPECT_RATIO; + m_spuMode = EM8300_SPUMODE_OFF; + + // configure device based on settings + ConfigureDevice(); + + // get bcs values from driver + if (ioctl(m_fdControl, EM8300_IOCTL_GETBCS, &m_bcs) < 0) + { + esyslog("dxr3: failed to get brightness/contrast/saturation: %m"); + } + else + { + dsyslog("dxr3: intf: brightness=%d,contrast=%d,saturation=%d at init", + m_bcs.brightness, m_bcs.contrast, m_bcs.saturation); + } + + PlayBlackFrame(); + SetChannelCount(1); +} + +// ================================== +//! destructor +cDxr3Interface::~cDxr3Interface() +{ + // close filehandles + if (m_fdControl > -1) + { + close(m_fdControl); + } + if (m_fdVideo > -1) + { + close(m_fdVideo); + } + if (m_fdSpu > -1) + { + close(m_fdSpu); + } + if (m_fdAudio > -1) + { + close(m_fdAudio); + } + + // free some memory + if (m_pClock) + { + delete m_pClock; + } +} + +// main +// ================================== +void cDxr3Interface::Start() +{ +} + +// ================================== +void cDxr3Interface::Stop() +{ +} + +// audio +// ================================== +//! set audio output to analog +void cDxr3Interface::SetAudioAnalog() +{ + int ioval = 0; + Lock(); + + if (!m_ExternalReleased && m_audioMode != EM8300_AUDIOMODE_ANALOG) + { + int prevMode = m_audioMode; + m_audioMode = ioval = EM8300_AUDIOMODE_ANALOG; + if (ioctl(m_fdControl, EM8300_IOCTL_SET_AUDIOMODE, &ioval) < 0) + { + esyslog("dxr3: unable to set analog audio mode: %m"); + } + if (prevMode == EM8300_AUDIOMODE_DIGITALAC3) + { + ReOpenAudio(); + } + } + + Unlock(); +} + +// ================================== +//! set audio output to digital pcm +void cDxr3Interface::SetAudioDigitalPCM() +{ + int ioval = 0; + Lock(); + + if (!m_ExternalReleased && m_audioMode != EM8300_AUDIOMODE_DIGITALPCM) + { + int prevMode = m_audioMode; + m_audioMode = ioval = EM8300_AUDIOMODE_DIGITALPCM; + + if (ioctl(m_fdControl, EM8300_IOCTL_SET_AUDIOMODE, &ioval) < 0) + { + esyslog("dxr3: unable to set digital PCM audio mode: %m"); + } + if (prevMode == EM8300_AUDIOMODE_DIGITALAC3) + { + ReOpenAudio(); + } + } + + Unlock(); +} + +// ================================== +//! set audio output to digital ac3 +void cDxr3Interface::SetAudioDigitalAC3() +{ + if (m_audioMode != EM8300_AUDIOMODE_DIGITALAC3) + { + int ioval = 0; + Lock(); + + if (!m_ExternalReleased && m_audioMode != EM8300_AUDIOMODE_DIGITALAC3) + { + m_audioMode = ioval = EM8300_AUDIOMODE_DIGITALAC3; + if (ioctl(m_fdControl, EM8300_IOCTL_SET_AUDIOMODE, &ioval) < 0) + { + esyslog("dxr3: unable to set AC3 audio mode: %m"); + } + ReOpenAudio(); + } + + Unlock(); + } +} + +// ================================== +//! set audio speed +void cDxr3Interface::SetAudioSpeed(uint32_t speed) +{ + if (m_audioDataRate != speed && speed != UNKNOWN_DATA_RATE) + { + if (!m_ExternalReleased) + { + if (m_audioMode != EM8300_AUDIOMODE_DIGITALAC3) + { + if (ioctl(m_fdAudio, SNDCTL_DSP_SPEED, &speed) < 0) + { + esyslog("dxr3: unable to set DSP speed to %d: %m", speed); + } + } + } + m_audioDataRate = speed; + } +} + +// ================================== +//! set number of channels +void cDxr3Interface::SetChannelCount(uint32_t count) +{ + if (m_audioChannelCount != count && count != UNKNOWN_CHANNEL_COUNT) + { + if (!m_ExternalReleased) + { + if (m_audioMode != EM8300_AUDIOMODE_DIGITALAC3) + { + if (ioctl(m_fdAudio, SNDCTL_DSP_STEREO, &count) < 0) + { + esyslog("dxr3: unable to set channel count to %d: %m", + count); + } + } + } + m_audioChannelCount = count; + } +} + +// ================================== +//! set audio sample size +void cDxr3Interface::SetAudioSampleSize(uint32_t sampleSize) +{ + if (!m_ExternalReleased) + { + if (ioctl(m_fdAudio, SNDCTL_DSP_SAMPLESIZE, sampleSize) < 0) + { + esyslog("dxr3: unable to set audio sample size to %d: %m", + sampleSize); + } + } + m_audioSampleSize = sampleSize; +} + +// clock +// ================================== +void cDxr3Interface::SetSysClock(uint32_t scr) +{ + if (!m_ExternalReleased) + { + m_pClock->SetSysClock(scr); + } +} + +// ================================== +uint32_t cDxr3Interface::GetSysClock() const +{ + uint32_t ret = 0; + if (!m_ExternalReleased) + { + ret = m_pClock->GetSysClock(); + } + return ret; +} + +// ================================== +int64_t cDxr3Interface::GetPts() +{ + return m_lastSeenPts << 1; +} + +// ================================== +void cDxr3Interface::SetPts(uint32_t pts) +{ + if (!m_ExternalReleased) + { + m_pClock->SetPts(pts); + } +} + +// ================================== +void cDxr3Interface::SetSpuPts(uint32_t pts) +{ + pts = pts >> 1; + if (!m_ExternalReleased) + { + if (pts > m_pClock->GetSysClock() && + pts - m_pClock->GetSysClock() < 100000) + { + m_pClock->SetSpuPts(pts); + } + } +} + +// state changes +// ================================== +//! enable subpicture processing of the dxr3 +void cDxr3Interface::EnableSPU() +{ + int ioval = 0; + Lock(); + + if (!m_ExternalReleased && m_spuMode != EM8300_SPUMODE_ON) + { + m_spuMode = ioval = EM8300_SPUMODE_ON; + if (ioctl(m_fdControl, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) + { + esyslog("dxr3: unable to enable subpicture mode: %m"); + } + } + + Unlock(); +} + +// ================================== +//! disable subpicture proeccesing of the dxr3 +void cDxr3Interface::DisableSPU() +{ + int ioval = 0; + Lock(); + + if (!m_ExternalReleased && m_spuMode != EM8300_SPUMODE_OFF) + { + m_spuMode = ioval = EM8300_SPUMODE_OFF; + if (ioctl(m_fdControl, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) + { + esyslog("dxr3: unable to disable subpicture mode: %m"); + } + } + + Unlock(); +} + +// ================================== +//! disable audio output of dxr3 +void cDxr3Interface::DisableAudio() +{ + m_AudioActive = false; + + // we write zero buffers to dxr3 + if (!m_ExternalReleased) + { + if (write(m_fdAudio, zerobuffer, ZEROBUFFER_SIZE) < 0) Resuscitation(); + if (write(m_fdAudio, zerobuffer, ZEROBUFFER_SIZE) < 0) Resuscitation(); + if (write(m_fdAudio, zerobuffer, ZEROBUFFER_SIZE) < 0) Resuscitation(); + if (write(m_fdAudio, zerobuffer, ZEROBUFFER_SIZE) < 0) Resuscitation(); + } +} + +// ================================== +//! enable overlay mode of the dxr3 +void cDxr3Interface::EnableOverlay() +{ + // first check if it is enabled already + if (m_OverlayActive) + { + return; + } + + /* +#define EM8300_OVERLAY_SIGNAL_ONLY 1 +#define EM8300_OVERLAY_SIGNAL_WITH_VGA 2 +#define EM8300_OVERLAY_VGA_ONLY 3 + */ + + int ioval = EM8300_OVERLAY_SIGNAL_WITH_VGA; + // set overlay signal mode + if (ioctl(m_fdControl, EM8300_IOCTL_OVERLAY_SIGNALMODE, &ioval) < 0) + { + //###### + esyslog("dxr3: unable to set overlay signal mode: %m"); + return; + } + + // setup overlay screen + em8300_overlay_screen_t scr; + scr.xsize = 1024; + scr.ysize = 768; + + if (ioctl(m_fdControl, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr) < 0) + { + //###### + esyslog("dxr3: unable to set up overlay screen: %m"); + return; + } + + // setup overlay window + em8300_overlay_window_t win; + win.xpos = 0; + win.ypos = 0; + win.width = 1024; + win.height = 768; + + if (ioctl(m_fdControl, EM8300_IOCTL_OVERLAY_SETWINDOW, &win) < 0) + { + //###### + esyslog("dxr3: unable to set up overlay window: %m"); + return; + } + + m_OverlayActive = true; +} + +// ================================== +//! disable overlay mode of the dxr3 +void cDxr3Interface::DisanleOverlay() +{ + // is it already disabled + if (!m_OverlayActive) + { + return; + } +} + +// set/get functions +// ================================== +//! get aspect ratio +uint32_t cDxr3Interface::GetAspectRatio() const +{ + int ioval = 0; + Lock(); + + if (!m_ExternalReleased) + { + if (ioctl(m_fdControl, EM8300_IOCTL_GET_ASPECTRATIO, &ioval) < 0) + { + esyslog("dxr3: unable to get aspect ratio: %m"); + } + } + + Unlock(); + return ioval; +} + +// ================================== +//! set aspect ratio +void cDxr3Interface::SetAspectRatio(uint32_t ratio) +{ + static int requestCounter = 0; + + Lock(); + + if (cDxr3ConfigData::Instance().GetForceLetterBox()) + ratio = EM8300_ASPECTRATIO_16_9; + if (Setup.VideoFormat) + ratio = EM8300_ASPECTRATIO_4_3; + + if (!m_ExternalReleased && ratio != UNKNOWN_ASPECT_RATIO) + { + if (ratio != m_aspectRatio && requestCounter > 50) + { + requestCounter = 0; + if (ioctl(m_fdControl, EM8300_IOCTL_SET_ASPECTRATIO, &ratio) < 0) + { + esyslog("dxr3: unable to set aspect ratio: %m"); + } + else + { + m_aspectRatio = ratio; + } + } + else + { + if (ratio != m_aspectRatio) + { + ++requestCounter; + } + else + { + requestCounter = 0; + } + } + } + + Unlock(); +} + +// play functions +// ================================== +//! set playing mode and start sync engine +void cDxr3Interface::SetPlayMode() +{ + em8300_register_t reg; + int ioval; + + Lock(); + + if (!m_ExternalReleased) + { + ioval = EM8300_SUBDEVICE_AUDIO; + ioctl(m_fdControl, EM8300_IOCTL_FLUSH, &ioval); + fsync(m_fdVideo); + + + ioval = EM8300_PLAYMODE_PLAY; + if (ioctl(m_fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) + { + esyslog("dxr3: unable to set play mode: %m"); + } + reg.microcode_register = 1; + reg.reg = 0; + reg.val = MVCOMMAND_SYNC; + + if (ioctl(m_fdControl, EM8300_IOCTL_WRITEREG, ®) < 0) + { + esyslog("dxr3: unable to start em8300 sync engine: %m"); + } + } + + Unlock(); +} + +// ================================== +void cDxr3Interface::Pause() +{ + int ioval = EM8300_PLAYMODE_PAUSED; + Lock(); + + if (!m_ExternalReleased) + { + if (ioctl(m_fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) + { + esyslog("dxr3: unable to set pause mode: %m"); + } + } + + Unlock(); +} +// ================================== +void cDxr3Interface::SingleStep() +{ + int ioval = EM8300_PLAYMODE_SINGLESTEP; + Lock(); + + if (!m_ExternalReleased) + { + if (ioctl(m_fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) + { + esyslog("dxr3: unable to set single-step mode: %m"); + } + } + + Unlock(); +} + +// ================================== +void cDxr3Interface::PlayVideoFrame(cFixedLengthFrame* pFrame, int times) +{ + int written = 0; + int count = 0; + + if (m_VideoActive) + { + Lock(); + + if (!m_ExternalReleased) + { + for (int i = 0; i < times; i++) + { + if (times > 1) + { + dsyslog("dxr3: playvideoframe: times=%d", times); + } + + while (written < pFrame->GetCount() && count >= 0) + { + if ((count = write(m_fdVideo, pFrame->GetData() + written, pFrame->GetCount() - written)) < 0) + { + // an error occured + Resuscitation(); + } + written += count; + } + + // reset + written = 0; + } + } + + Unlock(); + + SetAspectRatio(pFrame->GetAspectRatio()); + uint32_t pts = pFrame->GetPts(); + if (pts > 0) m_lastSeenPts = pts; + } +} + +// ================================== +void cDxr3Interface::PlayVideoFrame(const uint8_t* pBuf, int length, int times) +{ + Lock(); + + if (!m_ExternalReleased) + { + for (int i = 0; i < times; i++) + { + if (write(m_fdVideo, pBuf, length) < 0) Resuscitation(); + } + } + + Unlock(); +} + +// ================================== +void cDxr3Interface::PlayAudioFrame(cFixedLengthFrame* pFrame) +{ + // XXX: Call this only with we are not in external mode? + int written = 0; + + if (m_AudioActive) + { + Lock(); + + SetAudioSpeed(pFrame->GetDataRate()); + SetChannelCount(pFrame->GetChannelCount()); + + if (!m_ExternalReleased) + { + if (!cDxr3ConfigData::Instance().GetAc3OutPut()) + ResampleVolume((short*)pFrame->GetData(), pFrame->GetCount()); + + written = write(m_fdAudio, pFrame->GetData(), pFrame->GetCount()); + if (written < 0) + { + esyslog("dxr3: unable to play audio frame: %m"); + // TODO: Resuscitation() ? + } + else if (written != pFrame->GetCount()) + { + esyslog("dxr3: unable to play whole audio frame, skipped" + " %d bytes", pFrame->GetCount() - written); + } + } + + Unlock(); + } +} + +// ================================== +void cDxr3Interface::PlayAudioFrame(uint8_t* pBuf, int length) +{ + int written = 0; + Lock(); + + if (!m_ExternalReleased) + { + if (!cDxr3ConfigData::Instance().GetAc3OutPut()) + ResampleVolume((short*)pBuf, length); + + if ((written = write(m_fdAudio, pBuf, length)) < 0) + { + esyslog("dxr3: unable to play audio frame: %m"); + Resuscitation(); + } + else if (written != length) + { + esyslog("dxr3: unable to play whole audio frame, skipped %d bytes", + length - written); + } + } + + Unlock(); +} + +// ================================== +void cDxr3Interface::PlayAudioLpcmFrame(uint8_t* pBuf, int length) +{ + if (length > (LPCM_HEADER_LENGTH + 2)) + { + uint8_t* pFrame = new uint8_t[length - LPCM_HEADER_LENGTH]; + // only even number of bytes are allowed + assert(!((length - LPCM_HEADER_LENGTH) % 2)); + + for (int i = LPCM_HEADER_LENGTH; i < length; i += 2) + { + pFrame[i - LPCM_HEADER_LENGTH] = pBuf[i + 1]; + pFrame[i - LPCM_HEADER_LENGTH + 1] = pBuf[i]; + } + + int codedSpeed = (pBuf[5] >> 4) & 0x03; + int speed = 0; + + switch (codedSpeed) + { + case 1: + speed = 96000; + break; + + case 2: + speed = 44100; + break; + + case 3: + speed = 32000; + break; + + default: + speed = 48000; + break; + } + + SetAudioSpeed(speed); + PlayAudioFrame(pFrame, length - LPCM_HEADER_LENGTH); + delete[] pFrame; + } +} + +// external device access +// ================================== +//! release devices, so mplayer-plugin, for instance, +//! can access the dxr3 +void cDxr3Interface::ExternalReleaseDevices() +{ + Lock(); + + if (!m_ExternalReleased) + { + if (m_fdControl > -1) close(m_fdControl); + if (m_fdVideo > -1) close(m_fdVideo); + if (m_fdSpu > -1) close(m_fdSpu); + if (m_fdAudio > -1) close(m_fdAudio); + m_fdControl = m_fdVideo = m_fdSpu = m_fdAudio = -1; + m_aspectRatio = UNKNOWN_ASPECT_RATIO; + m_audioMode = UNKNOWN_AUDIO_MODE; + + m_ExternalReleased = true; + + delete m_pClock; + m_pClock = 0; + } + + Unlock(); +} + +// ================================== +//! reopen devices for using in the dxr3 plugin +void cDxr3Interface::ExternalReopenDevices() +{ + Lock(); + + if (m_ExternalReleased) + { + // open control stream + m_fdControl = Dxr3Open("", cDxr3ConfigData::Instance().GetDxr3Card(), + O_WRONLY | O_SYNC); + + // open 'multimedia' streams + m_fdVideo = Dxr3Open("_mv", cDxr3ConfigData::Instance().GetDxr3Card(), + O_WRONLY | O_SYNC); + m_fdAudio = Dxr3Open("_ma", cDxr3ConfigData::Instance().GetDxr3Card(), + O_WRONLY | O_SYNC); + m_fdSpu = Dxr3Open("_sp", cDxr3ConfigData::Instance().GetDxr3Card(), + O_WRONLY | O_SYNC); + + if (m_fdControl < 0 || m_fdVideo < 0 || m_fdAudio < 0 || m_fdSpu <0) + { + ExternalReleaseDevices(); + } + else + { + m_pClock = new cDxr3SysClock(m_fdControl, m_fdVideo, m_fdSpu); + if (!m_pClock) + { + esyslog("dxr3: fatal: failed to allocate memory for em8300" + " system clock in reopen"); + exit(1); + } + + SetChannelCount(1); + m_ExternalReleased = false; + } + + Resuscitation(); + } + + Unlock(); +} + + +// tools +// ================================== +//! play black frame on tv +void cDxr3Interface::PlayBlackFrame() +{ + extern char blackframe[]; + extern int blackframeLength; + + Lock(); + + if (!m_ExternalReleased) + { + if (write(m_fdVideo, blackframe, blackframeLength) < 0) + Resuscitation(); + if (write(m_fdVideo, blackframe, blackframeLength) < 0) + Resuscitation(); + if (write(m_fdVideo, blackframe, blackframeLength) < 0) + Resuscitation(); + } + m_horizontal = 720; + m_vertical = 576; + + Unlock(); +} + +// ================================== +void cDxr3Interface::ReOpenAudio() +{ + Lock(); + + if (!m_ExternalReleased) + { + if (m_fdAudio > -1) + { + int bufsize = 0; + ioctl(m_fdAudio, SNDCTL_DSP_GETODELAY, &bufsize); + usleep(bufsize / 192 * 1000); + + delete m_pClock; + close(m_fdAudio); + + m_fdAudio = Dxr3Open("_ma", + cDxr3ConfigData::Instance().GetDxr3Card(), + O_WRONLY | O_SYNC); + + uint32_t tmpAudioDataRate = m_audioDataRate; + uint32_t tmpAudioChannelCount = m_audioChannelCount; + m_audioDataRate = m_audioChannelCount = 0; + m_pClock = new cDxr3SysClock(m_fdControl, m_fdVideo, m_fdSpu); + SetAudioSpeed(tmpAudioDataRate); + SetChannelCount(tmpAudioChannelCount); + } + } + + Unlock(); +} + +// ================================== +//! uploadroutine for microcode +void cDxr3Interface::UploadMicroCode() +{ + em8300_microcode_t em8300_microcode; + struct stat s; + + // 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: %m", + MICROCODE); + exit(1); + } + + if (fstat(UCODE, &s ) <0) + { + esyslog("dxr3: fatal: unable to fstat microcode file %s: %m", + MICROCODE); + exit(1); + } + + // read 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: %m", + 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(m_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; +} + +// ================================== +//! config and setup device via ioctl calls +void cDxr3Interface::ConfigureDevice() +{ + uint32_t videomode = 0; + + // set video mode + if (cDxr3ConfigData::Instance().GetVideoMode() == PAL) + { + dsyslog("dxr3: configure: video mode: PAL"); + videomode = EM8300_VIDEOMODE_PAL; + } + else if (cDxr3ConfigData::Instance().GetVideoMode() == PAL60) + { + dsyslog("dxr3: configure: video mode: PAL60"); + videomode = EM8300_VIDEOMODE_PAL60; + } + else + { + dsyslog("dxr3: configure: video mode: NTSC"); + videomode = EM8300_VIDEOMODE_NTSC; + } + + // make ioctl + if (ioctl(m_fdControl, EM8300_IOCTL_SET_VIDEOMODE, &videomode) == -1) + { + esyslog("dxr3: fatal: unable to set video mode: %m"); + exit(1); + } + + // set audio mode + if (!cDxr3ConfigData::Instance().GetUseDigitalOut()) + { + dsyslog("dxr3: configure: audio mode: analog"); + SetAudioAnalog(); + } +} + +// ================================== +//! reset whole hardware +void cDxr3Interface::Resuscitation() +{ + time_t startt = time(&startt); + time_t endt = 0; + m_ExternalReleased = true; + + dsyslog("dxr3: resuscitation: device failure or user initiated reset"); + + UploadMicroCode(); + + //NonBlockingCloseOpen(); + m_ExternalReleased = false; + + endt = time(&endt); + + if (endt - startt > 4) + { + esyslog("dxr3: fatal: reopening devices took too long"); + exit(1); + } + dsyslog("dxr3: resuscitation: reopening devices took %ld seconds", + endt - startt); + + ConfigureDevice(); +} + +// ================================== +//! pcm resampling function +void cDxr3Interface::ResampleVolume(short* pcmbuf, int size) +{ + if (m_volume == 0) + { + memset(pcmbuf, 0, size); + } + if (m_volume < 255 || m_audioChannel != AUDIO_STEREO) + { + int factor = (int)pow (2.0, (double)m_volume/32 + 8.0) - 1; + //int factor = (int)pow (2.0, (double)m_volume/16) - 1; + for (int i = 0; i < size / (int)sizeof(short); i++) + { + if (m_audioChannel == AUDIO_MONO_RIGHT && !(i & 0x1)) + { + pcmbuf[i] = pcmbuf[i+1]; + } + if (m_audioChannel == AUDIO_MONO_LEFT && (i & 0x1)) + { + pcmbuf[i] = pcmbuf[i-1]; + } + else if (m_volume < 255) + { + pcmbuf[i] = (((int)pcmbuf[i]) * factor) / 65536; + } + } + } +} + +// ================================== +void cDxr3Interface::ClearOsd() +{ + encodedata ed; + int controlstart= 0; + int x1 = 0; + int& i = ed.count = 0; + + // display duration... + ed.data[i++]= 0x00; + ed.data[i++]= 0x00; //durration before turn on command occurs + //in 90000/1024 units + // x1 + ed.data[i++]= x1 >> 8; //since this is the last command block, this + ed.data[i++]= x1 & 0xff; //points back to itself + + + // 0x01: start displaying + ed.data[i++]= 0x02; + + // 0xFF: end sequence + ed.data[i++]= 0xFF; + if (!i&1) + { + ed.data[i++]= 0xff; + } + + // x0 + ed.data[2]= (controlstart) >> 8; + ed.data[3]= (controlstart) & 0xff; + + // packet size + ed.data[0]= i >> 8; + ed.data[1]= i & 0xff; + + if (!m_ExternalReleased) + { + WriteSpu((const uint8_t*) &ed, (int) ed.count); + ClearButton(); + } +} + +// ================================== +void cDxr3Interface::WriteSpu(const uint8_t* pBuf, int length) +{ + Lock(); + + if (!m_ExternalReleased) + { + if (write(m_fdSpu, pBuf, length) < 0) Resuscitation(); + } + + Unlock(); +} + +// ================================== +void cDxr3Interface::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; + + ioctl(m_fdSpu, EM8300_IOCTL_SPU_BUTTON, &button); +} + +// ================================== +void cDxr3Interface::ClearButton() +{ + em8300_button_t button; + + button.color = 0; + button.contrast = 0; + button.top = 1; + button.bottom = 2; + button.left = 1; + button.right = 2; + + ioctl(m_fdSpu, EM8300_IOCTL_SPU_BUTTON, &button); +} + +// ================================== +void cDxr3Interface::SetPalette(unsigned int *pal) +{ + ioctl(m_fdSpu, EM8300_IOCTL_SPU_SETPALETTE, (uint8_t*)pal); +} + +// helper functions for dxr3 main osd screen +// ================================== +//! reset dxr3 card +void cDxr3Interface::ResetHardware() +{ + Lock(); + + isyslog("dxr3: hardware reset requested"); + Resuscitation(); + + Unlock(); +} + +// set brightness/contrast/saturation +// ================================== +//! set brightness +void cDxr3Interface::SetBrightness(int value) +{ + m_bcs.brightness = value; + + if (ioctl(m_fdControl, EM8300_IOCTL_SETBCS, &m_bcs) < 0) + { + esyslog("dxr3: unable to set brightness to %d: %m", value); + } +} + +// ================================== +//! set contrast +void cDxr3Interface::SetContrast(int value) +{ + m_bcs.contrast = value; + + if (ioctl(m_fdControl, EM8300_IOCTL_SETBCS, &m_bcs) < 0) + { + esyslog("dxr3: unable to set contrast to %d: %m", value); + } +} + +// ================================== +//! set saturation +void cDxr3Interface::SetSaturation(int value) +{ + m_bcs.saturation = value; + + if (ioctl(m_fdControl, EM8300_IOCTL_SETBCS, &m_bcs) < 0) + { + esyslog("dxr3: unable to set saturation to %d: %m", value); + } +} + +// ================================== +cMutex* cDxr3Interface::m_pMutex = new cMutex; + +// Local variables: +// mode: c++ +// c-file-style: "stroustrup" +// c-file-offsets: ((inline-open . 0)) +// indent-tabs-mode: t +// End: |