diff options
Diffstat (limited to 'frontend.c')
-rw-r--r-- | frontend.c | 868 |
1 files changed, 0 insertions, 868 deletions
diff --git a/frontend.c b/frontend.c deleted file mode 100644 index 9c8da413..00000000 --- a/frontend.c +++ /dev/null @@ -1,868 +0,0 @@ -/* - * frontend.c: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: frontend.c,v 1.76 2009-09-05 21:27:25 rofafor Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#define __STDC_CONSTANT_MACROS -#include <inttypes.h> - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <time.h> -#include <pthread.h> -#include <arpa/inet.h> -#include <netinet/in.h> -#include <netdb.h> -#include <sys/ioctl.h> -#include <sys/socket.h> - -#include <vdr/config.h> -#include <vdr/tools.h> -#include <vdr/plugin.h> - -#include "logdefs.h" -#include "config.h" -#include "frontend.h" -#include "device.h" - -#include "tools/pes.h" -#include "tools/mpeg.h" -#include "tools/h264.h" -#include "tools/general_remote.h" -#include "tools/iso639.h" - -//#define LOG_CONTROL_MESSAGES -//#define XINELIBOUTPUT_LOG_KEYS - -#ifndef STARTUP_IMAGE_FILE -# define STARTUP_IMAGE_FILE "/usr/share/vdr/xineliboutput/logo.mpv" -#endif -#ifndef STARTUP_MAX_SIZE -# define STARTUP_MAX_SIZE (256*1024) -#endif - -//----------------------------- cXinelibThread -------------------------------- - -// -// keyboard control handler -// - -/*static*/ -void cXinelibThread::KeypressHandler(const char *keymap, const char *key, - bool repeat, bool release) -{ -#ifdef XINELIBOUTPUT_LOG_KEYS - static FILE *flog = fopen("/video/keys.log","w"); - if (flog) { - fprintf(flog,"KEY %s %s %d %d\n",keymap,key,repeat,release); fflush(flog); - } -#endif - - TRACE("keypress_handler: " << (keymap?keymap:"") << " " << key); - - if(!key) - return; - - if(keymap) { - cRemote *item = Remotes.First(); - while(item) { - if(!strcmp(item->Name(), keymap)) { - // dirty... but only way to support learning ... - ((cGeneralRemote*)item)->Put(key, repeat, release); - return; - } - item = Remotes.Next(item); - } - cGeneralRemote *r = new cGeneralRemote(keymap); - if(*key) - r->Put(key, repeat, release); - } else { - cRemote::Put(cKey::FromString(key)); - } -} - -#include <vdr/status.h> -class cFrontendStatusMonitor : public cStatus { - private: - bool& m_SpuLangAuto; - public: - cFrontendStatusMonitor(bool& SpuLangAuto) : m_SpuLangAuto(SpuLangAuto) {}; - virtual void SetSubtitleTrack(int /*Index*/, const char * const */*Tracks*/) { m_SpuLangAuto = false; } -}; - -void cXinelibThread::InfoHandler(const char *info) -{ - char *pmap = strdup(info), *map = pmap, *pt; - - if(NULL != (pt=strchr(map, '\r'))) - *pt = 0; - - if(!strncmp(info, "TRACKMAP SPU", 12)) { - int CurrentTrack = ttXSubtitleAuto; - map += 12; - while(*map) { - bool Current = false; - while(*map == ' ') map++; - if(*map == '*') { - Current = true; - map++; - if (*map == '-') { - CurrentTrack = atoi(map); - while (*map && *map != ' ') map++; - continue; - } - } - if(*map >= '0' && *map <= '9') { - int id = atoi(map); - while(*map && *map != ':') map++; - if(*map == ':') map++; - char *lang = map; - while(*map && *map != ' ') map++; - if(*map == ' ') { *map = 0; map++; }; - cXinelibDevice::Instance().SetAvailableTrack(ttSubtitle, id, id+1, iso639_2_to_iso639_1(lang) ?: *cString::sprintf("%03d", id+1)); - if (Current) - CurrentTrack = id; - } - } - if (CurrentTrack == ttXSubtitleAuto) - cXinelibDevice::Instance().EnsureSubtitleTrack(); - else if (CurrentTrack == ttXSubtitleNone) - cXinelibDevice::Instance().SetCurrentSubtitleTrack(ttNone, true); - else - cXinelibDevice::Instance().SetCurrentSubtitleTrack(eTrackType(CurrentTrack+ttSubtitleFirst), true); - } - - else if(!strncmp(info, "TRACKMAP AUDIO", 14)) { - map += 14; - cXinelibDevice::Instance().ClrAvailableTracks(); - while(*map) { - bool Current = false; - while(*map == ' ') map++; - if(*map == '*') { - Current = true; - map++; - } - int id = atoi(map); - while(*map && *map != ':') map++; - if(*map == ':') map++; - char *lang = map; - while(*map && *map != ' ') map++; - if(*map == ' ') { *map = 0; map++; }; - cXinelibDevice::Instance().SetAvailableTrack(ttDolby, id, ttDolby+id, iso639_2_to_iso639_1(lang) ?: *cString::sprintf("%03d", id+1)); - if(Current) - cXinelibDevice::Instance().SetCurrentAudioTrack((eTrackType)(ttDolby+id)); - } - } - - else if(!strncmp(info, "METAINFO", 8)) { - map += 8; - while(*map) { - while(*map == ' ') map++; - char *next = strstr(map, "=@"); - if(!next) - break; - *next = 0; - next += 2; - char *end = strstr(next, "@"); - if(!end) - break; - *end = 0; - - if(!strcmp(map, "title")) - cXinelibDevice::Instance().SetMetaInfo(miTitle, next); - if(!strcmp(map, "tracknumber")) - cXinelibDevice::Instance().SetMetaInfo(miTracknumber, next); - if(!strcmp(map, "album")) - cXinelibDevice::Instance().SetMetaInfo(miAlbum, next); - if(!strcmp(map, "artist")) - cXinelibDevice::Instance().SetMetaInfo(miArtist, next); - map = end+1; - } - } - - else if(!strncmp(info, "DVDBUTTONS ", 11)) { - map += 11; - while(*map == ' ') map++; - cXinelibDevice::Instance().SetMetaInfo(miDvdButtons, map); - } - - else if(!strncmp(info, "TITLE ", 6)) { - map += 6; - while(*map == ' ') map++; - cXinelibDevice::Instance().SetMetaInfo(miTitle, map); - } - - else if(!strncmp(info, "DVDTITLE ", 9)) { - map += 9; - while(*map == ' ') map++; - cXinelibDevice::Instance().SetMetaInfo(miDvdTitleNo, map); - if (*map == '0') // DVD Menu, set spu track to 0 - cXinelibDevice::Instance().SetCurrentSubtitleTrack(ttSubtitleFirst); - } - - else if (!strncmp(info, "WINDOW ", 7)) { - int w, h; - map += 7; - while(*map == ' ') map++; - if (2 == sscanf(map, "%dx%d", &w, &h)) { - xc.osd_width_auto = w; - xc.osd_height_auto = h; - } - } - - free(pmap); -} - -cXinelibThread::cXinelibThread(const char *Description) : cThread(Description) -{ - TRACEF("cXinelibThread::cXinelibThread"); - - m_Volume = 255; - m_bReady = false; - m_bNoVideo = true; - m_bLiveMode = true; /* can't be replaying when there is no output device */ - m_StreamPos = 0; - m_LastClearPos = 0; - m_Frames = 0; - m_bEndOfStreamReached = false; - m_bPlayingFile = false; - m_StatusMonitor = NULL; -} - -cXinelibThread::~cXinelibThread() -{ - TRACEF("cXinelibThread::~cXinelibThread"); - - Cancel(3); - - if (m_StatusMonitor) - DELETENULL(m_StatusMonitor); -} - -// -// Thread control -// - -bool cXinelibThread::IsReady(void) -{ - LOCK_THREAD; - return m_bReady; -} - -// -// Playback control -// - -void cXinelibThread::SetVolume(int NewVolume) -{ - m_Volume = NewVolume; - cString str = cString::sprintf("VOLUME %d%s", NewVolume * 100 / 255, - xc.sw_volume_control ? " SW" : ""); - Xine_Control(str); -} - -void cXinelibThread::TrickSpeed(int Speed) -{ - TRACEF("cXinelibThread::TrickSpeed"); - - Xine_Control("TRICKSPEED", Speed); -} - -void cXinelibThread::SetLiveMode(bool LiveModeOn) -{ - TRACEF("cXinelibThread::SetLiveMode"); - - Lock(); - if(m_bLiveMode == LiveModeOn) { - Unlock(); - return; - } - m_bLiveMode = LiveModeOn; - Unlock(); - - Xine_Control("LIVE", m_bLiveMode ? 1 : 0); -} - -void cXinelibThread::SetStillMode(bool StillModeOn) -{ - TRACEF("cXinelibThread::SetStillMode"); - Xine_Control("STILL", StillModeOn ? 1 : 0); -} - -void cXinelibThread::SetNoVideo(bool bVal) -{ - TRACEF("cXinelibThread::SetNoVideo"); - - Lock(); - if(m_bNoVideo == bVal) { - Unlock(); - return; - } - m_bNoVideo = bVal; - Unlock(); - - Xine_Control("NOVIDEO", m_bNoVideo ? 1 : 0); - - char *opts = NULL; - if(xc.audio_vis_goom_opts[0] && !strcmp(xc.audio_visualization, "goom")) - opts = xc.audio_vis_goom_opts; - - if(m_bNoVideo && strcmp(xc.audio_visualization, "none")) { - ConfigurePostprocessing(xc.audio_visualization, true, opts); - } else { - ConfigurePostprocessing("AudioVisualization", false, NULL); - } -} - -void cXinelibThread::AudioStreamChanged(bool ac3, int StreamId) -{ - TRACEF("cXinelibThread::AudioStreamChanged"); - if(ac3) - Xine_Control("AUDIOSTREAM AC3", StreamId); - else - Xine_Control("AUDIOSTREAM", StreamId); -} - -void cXinelibThread::SetSubtitleTrack(eTrackType Track) -{ - TRACEF("cXinelibThread::SetSubtitleTrack"); - cString buf = cString::sprintf("SPUSTREAM %d%s", - Track==ttNone ? ttXSubtitleNone : (Track - ttSubtitleFirst), - m_SpuLangAuto ? " auto" : ""); - Xine_Control(buf); -} - -void cXinelibThread::Clear(void) -{ - TRACEF("cXinelibThread::Clear"); - - char buf[128]; - - { - LOCK_THREAD; - - if (m_StreamPos == m_LastClearPos) { - //LOGDBG("cXinelibThread::Clear(): double Clear() ignored"); - return; - } - m_LastClearPos = m_StreamPos; - - snprintf(buf, sizeof(buf), "DISCARD %" PRId64 " %d", m_StreamPos, m_Frames); - } - - /* Send to control stream and data stream. If message is sent only to - * control stream, and it is delayed, engine flush will be skipped. - */ - Xine_Control(buf); - Xine_Control_Sync(buf); -} - -bool cXinelibThread::Flush(int TimeoutMs) -{ - TRACEF("cXinelibThread::Flush"); - - return Xine_Control("FLUSH", TimeoutMs) <= 0; -} - -int cXinelibThread::Poll(cPoller& Poller, int TimeoutMs) -{ - TRACEF("cXinelibThread::Poll"); - - if(!m_bReady) { - if(TimeoutMs>0) - cCondWait::SleepMs(TimeoutMs); - if(!m_bReady) - return 0; - } - - int n = Xine_Control("POLL", TimeoutMs); - - return max(n, 0); -} - -// -// Data transfer -// - -int cXinelibThread::Play_PES(const uchar *data, int len) -{ - Lock(); - m_StreamPos += len; - m_Frames++; - /*m_bEndOfStreamReached = false;*/ - Unlock(); - return len; -} - -// -// Stream conversions -// - -// Convert MPEG1 PES headers to MPEG2 PES headers - -int cXinelibThread::Play_Mpeg1_PES(const uchar *data1, int len) -{ - if(!data1[0] && !data1[1] && data1[2] == 0x01 && len>7 && /* header sync bytes */ - ( IS_VIDEO_PACKET(data1) || IS_AUDIO_PACKET(data1)) && /* video / audio / ps1 stream */ - ((data1[6] & 0xC0) != 0x80) && /* really mpeg1 pes */ - (len == ((data1[4]<<8) | data1[5]) + 6)) { /* whole PES packet and nothing else */ - uchar *data2 = new uchar[len+64]; - int i1=0, i2=0, r=0; - - data2[i2++]=data1[i1++]; // 00 (sync) - data2[i2++]=data1[i1++]; // 00 (sync) - data2[i2++]=data1[i1++]; // 01 (sync) - data2[i2++]=data1[i1++]; // stream ID - data2[i2++]=data1[i1++]; // len hi - data2[i2++]=data1[i1++]; // len lo - - // skip stuffing - while ((data1[i1] & 0x80) == 0x80) - i1++; - - if ((data1[i1] & 0xc0) == 0x40) { - // skip STD_buffer_scale, STD_buffer_size - i1 += 2; - } - - if(len<i1+5) return len; - - data2[i2++] = 0x80; - - if ((data1[i1] & 0xf0) == 0x20) { - /* PTS */ - data2[i2++] = 0x80; - data2[i2++] = 5; - data2[i2++] = data1[i1++] & 0x0E; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - } - else if ((data1[i1] & 0xf0) == 0x30) { - /* PTS & DTS */ - data2[i2++] = 0x80|0x40; - data2[i2++] = 10; - data2[i2++] = data1[i1++] & 0x0E; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - - data2[i2++] = data1[i1++] & 0x0E; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - } else { - i1++; - data2[i2++] = 0; /* no pts, no dts */ - data2[i2++] = 0; /* header len */ - } - - int newlen = ((data1[4]<<8) | data1[5]) + (i2-i1), loops=0; - data2[4] = ((newlen)&0xff00)>>8; - data2[5] = ((newlen)&0xff); - if(len-i1 > 0) { - memcpy(data2+i2, data1+i1, len-i1); - cPoller p; - while(!Poll(p,100) && loops++ < 10) { - LOGDBG("Play_Mpeg1_PES: poll failed"); - } - r = Play_PES(data2,newlen+6); - } - - delete data2; - return r==newlen+6 ? ((data1[4]<<8)|data1[5])+6 : 0; - } - return len; // nothing useful found ... -} - -// Pack elementary MPEG stream to PES - -bool cXinelibThread::Play_Mpeg2_ES(const uchar *data, int len, int streamID) -{ - static uchar hdr_vid[] = {0x00,0x00,0x01,0xe0, 0x00,0x00,0x80,0x00,0x00}; /* mpeg2 */ - static uchar hdr_pts[] = {0x00,0x00,0x01,0xe0, 0x00,0x08,0x80,0x80, - 0x05,0x00,0x00,0x00, 0x00,0x00}; /* mpeg2 */ - static uchar seq_end[] = {0x00,0x00,0x01,0xe0, 0x00,0x07,0x80,0x00, - 0x00, - 0x00,0x00,0x01,0xB7}; /* mpeg2 */ - int todo = len, done = 0, hdrlen = 9/*sizeof(hdr)*/; - uchar *frame = new uchar[PES_CHUNK_SIZE+32]; - cPoller p; - bool h264 = IS_NAL_AUD(data); - - hdr_pts[3] = (uchar)streamID; - Poll(p, 100); - Play_PES(hdr_pts, sizeof(hdr_pts)); - - hdr_vid[3] = (uchar)streamID; - while(todo) { - int blocklen = todo; - if(blocklen > ((PES_CHUNK_SIZE - hdrlen) & 0xfffc)) - blocklen = (PES_CHUNK_SIZE - hdrlen) & 0xfffc; - hdr_vid[4] = ((blocklen+3)&0xff00)>>8; - hdr_vid[5] = ((blocklen+3)&0xff); - - memcpy(frame, hdr_vid, hdrlen); - memcpy(frame+hdrlen, data+done, blocklen); - - done += blocklen; - todo -= blocklen; - - Poll(p, 100); - - if(blocklen+hdrlen != Play_PES(frame,blocklen+hdrlen)) { - delete frame; - return false; - } - } - - // append sequence end code to video - if((streamID & 0xF0) == 0xE0) { - seq_end[3] = (uchar)streamID; - seq_end[12] = h264 ? NAL_END_SEQ : 0xB7; - Poll(p, 100); - Play_PES(seq_end, sizeof(seq_end)); - } - - delete[] frame; - return true; -} - -// -// Built-in still images -// - -bool cXinelibThread::QueueBlankDisplay(void) -{ - TRACEF("cXinelibThread::BlankDisplay"); - Xine_Control_Sync("BLANK"); - return true; -} - -bool cXinelibThread::BlankDisplay(void) -{ - TRACEF("cXinelibThread::BlankDisplay"); - - bool r = QueueBlankDisplay(); - for(int i=0; i<5 && !Flush(100); i++) - ; - return r; -} - -bool cXinelibThread::LogoDisplay(void) -{ - TRACEF("cXinelibThread::LogoDisplay"); - - cString Path; - int fd = -1; - - if(Setup.FileName()) { - cString SetupPath = Setup.FileName(); - const char *end = strrchr(SetupPath, '/'); - if(end) { - SetupPath.Truncate(end - (const char *)SetupPath); - fd = open(Path=cString::sprintf("%s/plugins/xineliboutput/logo.mpv", *SetupPath), O_RDONLY); - } - } - - if(fd<0) - fd = open(Path=STARTUP_IMAGE_FILE, O_RDONLY); - - if(fd >= 0) { - uint8_t *data = (uint8_t*)malloc(STARTUP_MAX_SIZE); - int datalen = read(fd, data, STARTUP_MAX_SIZE); - if(datalen == STARTUP_MAX_SIZE) { - LOGMSG("WARNING: custom startup image %s too large", *Path); - } else if(datalen<=0) { - LOGERR("error reading custom startup image %s", *Path); - } else { - LOGMSG("using custom startup image %s", *Path); - bool r = Play_Mpeg2_ES(data, datalen, VIDEO_STREAM); - free(data); - for(int i=0; i<5 && !Flush(100); i++) - ; - return r; - } - free(data); - close(fd); - } - - /* use default image */ - extern const unsigned char v_mpg_vdrlogo[]; // vdrlogo_720x576.c - extern const int v_mpg_vdrlogo_length; - - bool r = Play_Mpeg2_ES(v_mpg_vdrlogo, v_mpg_vdrlogo_length, VIDEO_STREAM); - for(int i=0; i<5 && !Flush(100); i++) - ; - return r; -} - -bool cXinelibThread::NoSignalDisplay(void) -{ - TRACEF("cXinelibThread::NoSignalDisplay"); - - extern const unsigned char v_mpg_nosignal[]; // nosignal_720x576.c - extern const int v_mpg_nosignal_length; - - bool r = Play_Mpeg2_ES(v_mpg_nosignal, v_mpg_nosignal_length, VIDEO_STREAM); - for(int i=0; i<5 && !Flush(100); i++) - ; - return r; -} - -// -// Xine Control -// - -int cXinelibThread::Xine_Control(const char *cmd, int p1) -{ - char buf[128]; - if(snprintf(buf, sizeof(buf), "%s %d", cmd, p1) >= (int)sizeof(buf)) { - LOGMSG("Xine_Control %s: message too long !", cmd); - return 0; - } - //buf[sizeof(buf)-1] = 0; - return Xine_Control(buf); -} - -int cXinelibThread::Xine_Control(const char *cmd, int64_t p1) -{ - char buf[128]; - if(snprintf(buf, sizeof(buf), "%s %" PRId64, cmd, p1) >= (int)sizeof(buf)) { - LOGMSG("Xine_Control %s: message too long !", cmd); - return 0; - } - //buf[sizeof(buf)-1] = 0; - return Xine_Control(buf); -} - -int cXinelibThread::Xine_Control(const char *cmd, const char *p1) -{ - char buf[1024]; - if(snprintf(buf, sizeof(buf), "%s %s", cmd, p1) >= (int)sizeof(buf)) { - LOGMSG("Xine_Control %s: message too long !", cmd); - return 0; - } - //buf[sizeof(buf)-1] = 0; - return Xine_Control(buf); -} - -bool cXinelibThread::PlayFile(const char *FileName, int Position, - bool LoopPlay, ePlayMode PlayMode, - int TimeoutMs) -{ - TRACEF("cXinelibThread::PlayFile"); - - char vis[256]; - - switch(PlayMode) { - case pmVideoOnly: - LOGDBG("cXinelibThread::PlayFile: Video from file, audio from VDR"); - strcpy(vis, "Video"); - break; - case pmAudioOnly: - LOGDBG("cXinelibThread::PlayFile: Audio from file, video from VDR"); - strcpy(vis, "Audio"); - break; - case pmAudioOnlyBlack: - //LOGDBG("cXinelibThread::PlayFile: Audio from file, no video"); - strcpy(vis, "none"); - break; - case pmAudioVideo: - default: - if(xc.audio_vis_goom_opts[0] && !strcmp(xc.audio_visualization, "goom")) - snprintf(vis, sizeof(vis), "%s:%s", xc.audio_visualization, xc.audio_vis_goom_opts); - else - strn0cpy(vis, xc.audio_visualization, sizeof(vis)); - vis[sizeof(vis)-1] = 0; - break; - } - - char buf[4096]; - m_bEndOfStreamReached = false; - if(snprintf(buf, sizeof(buf), "PLAYFILE %s %d %s %s", - LoopPlay ? "Loop" : "", Position, vis, FileName ? FileName : "") - >= 4096) { - LOGMSG("PlayFile: message too long !"); - return 0; - } - - if(FileName) { - Lock(); - m_FileName = FileName; - m_bPlayingFile = true; - m_SpuLangAuto = true; - if (m_StatusMonitor) - DELETENULL(m_StatusMonitor); - m_StatusMonitor = new cFrontendStatusMonitor(m_SpuLangAuto); - Unlock(); - } - - int result = PlayFileCtrl(buf, TimeoutMs); - - if(!FileName || result != 0) { - Lock(); - m_bPlayingFile = false; - m_FileName = NULL; - if (m_StatusMonitor) - DELETENULL(m_StatusMonitor); - Unlock(); - } else { - if(xc.extsub_size >= 0) - Xine_Control("EXTSUBSIZE", xc.extsub_size); - - // set preferred subtitle language - if (Setup.DisplaySubtitles) { - const char *langs = I18nLanguageCode(Setup.SubtitleLanguages[0]); - if (langs) { - char lang1[5]; - strn0cpy(lang1, langs, 4); /* truncate */ - const char *spu_lang = iso639_1_to_iso639_2(lang1); - LOGMSG("Preferred SPU language: %s (%s)", lang1, spu_lang); - if (spu_lang && spu_lang[0] && spu_lang[1] && !spu_lang[2]) - Xine_Control(cString::sprintf("SPUSTREAM %s", spu_lang)); - } - } else { - LOGMSG("Preferred SPU language: (none)"); - Xine_Control(cString::sprintf("SPUSTREAM %d", ttXSubtitleNone)); - } - } - - return Running() && !result; -} - - -// -// Configuration -// - -void cXinelibThread::Configure(void) -{ - ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, - xc.audio_compression, xc.audio_equalizer, - xc.audio_surround, xc.speaker_type); - ConfigureVideo(xc.hue, xc.saturation, xc.brightness, xc.sharpness, xc.noise_reduction, xc.contrast, xc.overscan, xc.vo_aspect_ratio); - ConfigurePostprocessing("upmix", xc.audio_upmix ? true : false, NULL); - ConfigurePostprocessing("autocrop", xc.autocrop ? true : false, - xc.AutocropOptions()); - ConfigurePostprocessing("swscale", xc.swscale ? true : false, - xc.SwScaleOptions()); - ConfigurePostprocessing("pp", xc.ffmpeg_pp ? true : false, - xc.FfmpegPpOptions()); - ConfigurePostprocessing("unsharp",xc.unsharp ? true : false, - xc.UnsharpOptions()); - ConfigurePostprocessing("denoise3d",xc.denoise3d ? true : false, - xc.Denoise3dOptions()); - -#ifdef ENABLE_TEST_POSTPLUGINS - ConfigurePostprocessing("headphone", xc.headphone ? true : false, NULL); -#endif - - Xine_Control(cString::sprintf("SCR %s %d", - xc.live_mode_sync ? "Sync" : "NoSync", - xc.scr_tuning ? xc.scr_hz : 90000)); -} - -int cXinelibThread::ConfigurePostprocessing(const char *deinterlace_method, - int audio_delay, - int audio_compression, - const int *audio_equalizer, - int audio_surround, - int speaker_type) -{ - char buf[1024]; - int r = true; - - if(strcmp(deinterlace_method, "tvtime")) - r = ConfigurePostprocessing("tvtime", false, NULL) && r; - - r = Xine_Control("DEINTERLACE", deinterlace_method) && r; - r = Xine_Control("AUDIODELAY", audio_delay) && r; - r = Xine_Control("AUDIOCOMPRESSION", audio_compression) && r; - r = Xine_Control("AUDIOSURROUND", audio_surround) && r; - r = Xine_Control("SPEAKERS", speaker_type) && r; - sprintf(buf,"EQUALIZER %d %d %d %d %d %d %d %d %d %d", - audio_equalizer[0],audio_equalizer[1], - audio_equalizer[2],audio_equalizer[3], - audio_equalizer[4],audio_equalizer[5], - audio_equalizer[6],audio_equalizer[7], - audio_equalizer[8],audio_equalizer[9]); - r = Xine_Control(buf) && r; - - if(m_bNoVideo && strcmp(xc.audio_visualization, "none")) { - char *opts = NULL; - if(xc.audio_vis_goom_opts[0] && !strcmp(xc.audio_visualization, "goom")) - opts = xc.audio_vis_goom_opts; - //fe->post_open(fe, xc.audio_visualization, NULL); - r = ConfigurePostprocessing(xc.audio_visualization, true, opts) && r; - } else { - //fe->post_close(fe, NULL, 0); - r = ConfigurePostprocessing("AudioVisualization", false, NULL) && r; - } - - if(!strcmp(deinterlace_method, "tvtime")) - r = ConfigurePostprocessing("tvtime", true, xc.deinterlace_opts) && r; - - return r; -} - -int cXinelibThread::ConfigurePostprocessing(const char *name, bool on, const char *args) -{ - char buf[1024]; - int l; - - if(on) - l = snprintf(buf, sizeof(buf), "POST %s On %s", (name&&*name)?name:"0", args?args:""); - else - // 0 - audio vis. - // 1 - audio post - // 2 - video post - //return fe->post_close(fe, name, -1); - l = snprintf(buf, sizeof(buf), "POST %s Off", (name&&*name)?name:"0"); - - if(l >= (int)sizeof(buf)) { - LOGMSG("ConfigurePostprocessing %s: message too long !", name); - return 0; - } - //buf[sizeof(buf)-1] = 0; - - return Xine_Control(buf); -} - -int cXinelibThread::ConfigureVideo(int hue, int saturation, - int brightness, int sharpness, - int noise_reduction, int contrast, - int overscan, int vo_aspect_ratio) -{ - char cmd[128]; - Xine_Control("OVERSCAN", overscan); - snprintf(cmd, sizeof(cmd), - "VIDEO_PROPERTIES %d %d %d %d %d %d %d", - hue, saturation, brightness, sharpness, noise_reduction, contrast, vo_aspect_ratio); - return Xine_Control(cmd); -} - -// -// Playback files -// - -bool cXinelibThread::EndOfStreamReached(void) -{ - LOCK_THREAD; - bool r = m_bEndOfStreamReached; - return r; -} - - |