From fe224ebecb006afd6dcbc1c3ccf9de823607a8d6 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 30 Sep 2014 16:41:38 +0200 Subject: [PATCH] projects/RPi/patches/xbmc: add FM support patch from 4.0.7 back Signed-off-by: Stephan Raue --- ...bmc-995.01-fernetmenta-fixes-b3b79dd.patch | 11169 ++++++++++++++++ ...02-dont-set-_NET_WM_STATE_FULLSCREEN.patch | 29 + .../RPi/patches/xbmc/xbmc-995.03-keymap.patch | 13 + .../xbmc/xbmc-gotham_rbp_backports.patch | 675 - 4 files changed, 11211 insertions(+), 675 deletions(-) create mode 100644 projects/RPi/patches/xbmc/xbmc-995.01-fernetmenta-fixes-b3b79dd.patch create mode 100644 projects/RPi/patches/xbmc/xbmc-995.02-dont-set-_NET_WM_STATE_FULLSCREEN.patch create mode 100644 projects/RPi/patches/xbmc/xbmc-995.03-keymap.patch diff --git a/projects/RPi/patches/xbmc/xbmc-995.01-fernetmenta-fixes-b3b79dd.patch b/projects/RPi/patches/xbmc/xbmc-995.01-fernetmenta-fixes-b3b79dd.patch new file mode 100644 index 0000000000..ea1528d955 --- /dev/null +++ b/projects/RPi/patches/xbmc/xbmc-995.01-fernetmenta-fixes-b3b79dd.patch @@ -0,0 +1,11169 @@ +From cd390c16efd020e7b02296bcdac9d700ce088e5c Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 28 May 2012 10:34:39 +0200 +Subject: [PATCH 01/96] videoplayer: adapt lateness detection and dropping to + buffering + +--- + xbmc/cores/VideoRenderers/RenderManager.cpp | 16 +- + xbmc/cores/VideoRenderers/RenderManager.h | 12 +- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 15 +- + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 31 ++++ + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 7 + + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 194 +++++++++++++++++---- + xbmc/cores/dvdplayer/DVDPlayerVideo.h | 23 +++ + 7 files changed, 260 insertions(+), 38 deletions(-) + +diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp +index a33591d..9e2c055 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.cpp ++++ b/xbmc/cores/VideoRenderers/RenderManager.cpp +@@ -284,6 +284,8 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi + m_bIsStarted = true; + m_bReconfigured = true; + m_presentstep = PRESENT_IDLE; ++ m_presentpts = DVD_NOPTS_VALUE; ++ m_sleeptime = 1.0; + m_presentevent.notifyAll(); + + m_firstFlipPage = false; // tempfix +@@ -627,7 +629,7 @@ void CXBMCRenderManager::SetViewMode(int iViewMode) + m_pRenderer->SetViewMode(iViewMode); + } + +-void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) ++void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, double pts /* = 0 */, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) + { + { CSharedLock lock(m_sharedSection); + +@@ -695,6 +697,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L + m.timestamp = timestamp; + m.presentfield = sync; + m.presentmethod = presentmethod; ++ m.pts = pts; + requeue(m_queued, m_free); + + /* signal to any waiters to check state */ +@@ -1063,6 +1066,8 @@ void CXBMCRenderManager::PrepareNextRender() + m_discard.push_back(m_presentsource); + m_presentsource = idx; + m_queued.pop_front(); ++ m_sleeptime = m_Queue[idx].timestamp - clocktime; ++ m_presentpts = m_Queue[idx].pts; + m_presentevent.notifyAll(); + } + } +@@ -1079,3 +1084,12 @@ void CXBMCRenderManager::DiscardBuffer() + m_presentstep = PRESENT_IDLE; + m_presentevent.notifyAll(); + } ++ ++bool CXBMCRenderManager::GetStats(double &sleeptime, double &pts, int &bufferLevel) ++{ ++ CSingleLock lock(m_presentlock); ++ sleeptime = m_sleeptime; ++ pts = m_presentpts; ++ bufferLevel = m_queued.size() + m_discard.size(); ++ return true; ++} +diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h +index c469795..949c652 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.h ++++ b/xbmc/cores/VideoRenderers/RenderManager.h +@@ -98,10 +98,11 @@ public: + * + * @param bStop reference to stop flag of calling thread + * @param timestamp of frame delivered with AddVideoPicture ++ * @param pts used for lateness detection + * @param source depreciated + * @param sync signals frame, top, or bottom field + */ +- void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE); ++ void FlipPage(volatile bool& bStop, double timestamp = 0.0, double pts = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE); + unsigned int PreInit(); + void UnInit(); + bool Flush(); +@@ -176,6 +177,12 @@ public: + int WaitForBuffer(volatile bool& bStop, int timeout = 100); + + /** ++ * Can be called by player for lateness detection. This is done best by ++ * looking at the end of the queue. ++ */ ++ bool GetStats(double &sleeptime, double &pts, int &bufferLevel); ++ ++ /** + * Video player call this on flush in oder to discard any queued frames + */ + void DiscardBuffer(); +@@ -222,6 +229,7 @@ protected: + + struct SPresent + { ++ double pts; + double timestamp; + EFIELDSYNC presentfield; + EPRESENTMETHOD presentmethod; +@@ -233,6 +241,8 @@ protected: + + ERenderFormat m_format; + ++ double m_sleeptime; ++ double m_presentpts; + double m_presentcorr; + double m_presenterr; + double m_errorbuff[ERRORBUFFSIZE]; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +index f6751f4..fb34463 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +@@ -132,6 +132,10 @@ struct DVDVideoUserData + #define DVP_FLAG_NOSKIP 0x00000010 // indicate this picture should never be dropped + #define DVP_FLAG_DROPPED 0x00000020 // indicate that this picture has been dropped in decoder stage, will have no data + ++#define DVP_FLAG_DROPDEINT 0x00000040 // indicate that this picture was requested to have been dropped in deint stage ++#define DVP_FLAG_NO_POSTPROC 0x00000100 ++#define DVP_FLAG_DRAIN 0x00000200 ++ + // DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2! + + #define DVP_QSCALE_UNKNOWN 0 +@@ -149,6 +153,9 @@ class CDVDCodecOptions; + #define VC_PICTURE 0x00000004 // the decoder got a picture, call Decode(NULL, 0) again to parse the rest of the data + #define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data + #define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again ++#define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped ++#define VC_HURRY 0x00000040 ++ + class CDVDVideoCodec + { + public: +@@ -266,7 +273,6 @@ public: + return 0; + } + +- + /** + * Number of references to old pictures that are allowed to + * be retained when calling decode on the next demux packet +@@ -283,4 +289,11 @@ public: + * Interact with user settings so that user disabled codecs are disabled + */ + static bool IsCodecDisabled(DVDCodecAvailableType* map, unsigned int size, AVCodecID id); ++ ++ virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) ++ { ++ return false; ++ } ++ ++ virtual void SetCodecControl(int flags) {} + }; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index 9b6a34d..413151d 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -164,6 +164,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec() + m_iLastKeyframe = 0; + m_dts = DVD_NOPTS_VALUE; + m_started = false; ++ m_decoderPts = DVD_NOPTS_VALUE; + } + + CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg() +@@ -355,6 +356,14 @@ void CDVDVideoCodecFFmpeg::SetDropState(bool bDrop) + { + if( m_pCodecContext ) + { ++ if (bDrop && m_pHardware && m_pHardware->CanSkipDeint()) ++ { ++ m_requestSkipDeint = true; ++ bDrop = false; ++ } ++ else ++ m_requestSkipDeint = false; ++ + // i don't know exactly how high this should be set + // couldn't find any good docs on it. think it varies + // from codec to codec on what it does +@@ -556,6 +565,7 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + void CDVDVideoCodecFFmpeg::Reset() + { + m_started = false; ++ m_decoderPts = DVD_NOPTS_VALUE; + m_iLastKeyframe = m_pCodecContext->has_b_frames; + m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext); + +@@ -665,6 +675,22 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + else + pDvdVideoPicture->pts = DVD_NOPTS_VALUE; + ++ if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE) ++ m_decoderPts = pDvdVideoPicture->pts; ++ else ++ m_decoderPts = m_dts; ++ ++ if (m_requestSkipDeint) ++ { ++ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPDEINT; ++ m_skippedDeint = 1; ++ } ++ else ++ m_skippedDeint = 0; ++ ++ m_requestSkipDeint = false; ++ pDvdVideoPicture->iFlags |= m_codecControlFlags; ++ + if(!m_started) + pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; + +@@ -924,3 +950,8 @@ unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences() + else + return 0; + } ++ ++void CDVDVideoCodecFFmpeg::SetCodecControl(int flags) ++{ ++ m_codecControlFlags = flags; ++} +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +index 2287031..8376f72 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +@@ -45,6 +45,7 @@ public: + virtual int Check (AVCodecContext* avctx) = 0; + virtual void Reset () {} + virtual unsigned GetAllowedReferences() { return 0; } ++ virtual bool CanSkipDeint() {return false; } + virtual const std::string Name() = 0; + virtual CCriticalSection* Section() { return NULL; } + }; +@@ -62,6 +63,8 @@ public: + virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open + virtual unsigned GetConvergeCount(); + virtual unsigned GetAllowedReferences(); ++ virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) {pts=m_decoderPts; skippedDeint=m_skippedDeint; if (m_pFrame) interlaced = m_pFrame->interlaced_frame; return true;} ++ virtual void SetCodecControl(int flags); + + bool IsHardwareAllowed() { return !m_bSoftware; } + IHardwareDecoder * GetHardware() { return m_pHardware; }; +@@ -127,4 +130,8 @@ protected: + double m_dts; + bool m_started; + std::vector m_formats; ++ double m_decoderPts, m_decoderInterval; ++ int m_skippedDeint; ++ bool m_requestSkipDeint; ++ int m_codecControlFlags; + }; +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 99b3155..4fad1a3 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -38,6 +38,7 @@ + #include "DVDCodecs/DVDCodecs.h" + #include "DVDCodecs/Overlay/DVDOverlayCodecCC.h" + #include "DVDCodecs/Overlay/DVDOverlaySSA.h" ++#include "guilib/GraphicContext.h" + #include + #include + #include +@@ -320,8 +321,10 @@ void CDVDPlayerVideo::Process() + + int iDropped = 0; //frames dropped in a row + bool bRequestDrop = false; ++ int iDropDirective; + + m_videoStats.Start(); ++ m_droppingStats.Reset(); + + while (!m_bStop) + { +@@ -431,6 +434,7 @@ void CDVDPlayerVideo::Process() + picture.iFlags &= ~DVP_FLAG_ALLOCATED; + m_packets.clear(); + m_started = false; ++ m_droppingStats.Reset(); + } + else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush()) + { +@@ -443,6 +447,7 @@ void CDVDPlayerVideo::Process() + //we need to recalculate the framerate + //TODO: this needs to be set on a streamchange instead + ResetFrameRateCalc(); ++ m_droppingStats.Reset(); + + m_stalled = true; + m_started = false; +@@ -460,8 +465,10 @@ void CDVDPlayerVideo::Process() + m_speed = static_cast(pMsg)->m_value; + if(m_speed == DVD_PLAYSPEED_PAUSE) + m_iNrOfPicturesNotToSkip = 0; ++ + if (m_pVideoCodec) + m_pVideoCodec->SetSpeed(m_speed); ++ m_droppingStats.Reset(); + } + else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED)) + { +@@ -507,6 +514,28 @@ void CDVDPlayerVideo::Process() + m_iNrOfPicturesNotToSkip = 1; + } + ++ bRequestDrop = false; ++ iDropDirective = CalcDropRequirement(pts); ++ if (iDropDirective & EOS_VERYLATE) ++ { ++ if (m_bAllowDrop) ++ { ++ m_pullupCorrection.Flush(); ++ bRequestDrop = true; ++ } ++ } ++ int codecControl = 0; ++ if (iDropDirective & EOS_BUFFER_LEVEL) ++ codecControl |= DVP_FLAG_DRAIN; ++ if (m_speed > DVD_PLAYSPEED_NORMAL) ++ codecControl |= DVP_FLAG_NO_POSTPROC; ++ m_pVideoCodec->SetCodecControl(codecControl); ++ if (iDropDirective & EOS_DROPPED) ++ { ++ m_iDroppedFrames++; ++ iDropped++; ++ } ++ + if (m_messageQueue.GetDataSize() == 0 + || m_speed < 0) + { +@@ -559,15 +588,7 @@ void CDVDPlayerVideo::Process() + } + + m_videoStats.AddSampleBytes(pPacket->iSize); +- // assume decoder dropped a picture if it didn't give us any +- // picture from a demux packet, this should be reasonable +- // for libavformat as a demuxer as it normally packetizes +- // pictures when they come from demuxer +- if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE)) +- { +- m_iDroppedFrames++; +- iDropped++; +- } ++ + // reset the request, the following while loop may break before + // setting the flag to a new value + bRequestDrop = false; +@@ -1176,33 +1197,12 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) + m_FlipTimeStamp += max(0.0, iSleepTime); + m_FlipTimeStamp += iFrameDuration; + +- if (iSleepTime <= 0 && m_speed) +- m_iLateFrames++; +- else +- m_iLateFrames = 0; +- +- // ask decoder to drop frames next round, as we are very late +- if(m_iLateFrames > 10) ++ if ((pPicture->iFlags & DVP_FLAG_DROPPED)) + { +- if (!(pPicture->iFlags & DVP_FLAG_NOSKIP)) +- { +- //if we're calculating the framerate, +- //don't drop frames until we've calculated a stable framerate +- if (m_bAllowDrop || m_speed != DVD_PLAYSPEED_NORMAL) +- { +- result |= EOS_VERYLATE; +- m_pullupCorrection.Flush(); //dropped frames mess up the pattern, so just flush it +- } +- m_iDroppedRequest++; +- } +- } +- else +- { +- m_iDroppedRequest = 0; +- } +- +- if( (pPicture->iFlags & DVP_FLAG_DROPPED) ) ++ m_droppingStats.AddOutputDropGain(pts, 1/m_fFrameRate); ++ CLog::Log(LOGDEBUG,"%s - dropped in output", __FUNCTION__); + return result | EOS_DROPPED; ++ } + + // set fieldsync if picture is interlaced + EFIELDSYNC mDisplayField = FS_NONE; +@@ -1235,7 +1235,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) + if (index < 0) + return EOS_DROPPED; + +- g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField); ++ g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, pts, -1, mDisplayField); + + return result; + #else +@@ -1535,3 +1535,127 @@ void CDVDPlayerVideo::CalcFrameRate() + m_iFrameRateCount = 0; + } + } ++ ++int CDVDPlayerVideo::CalcDropRequirement(double pts) ++{ ++ int result = 0; ++ double iSleepTime; ++ double iDecoderPts, iRenderPts; ++ double iInterval; ++ int interlaced; ++ double iGain; ++ double iLateness; ++ bool bNewFrame; ++ int iSkippedDeint = 0; ++ int iBufferLevel; ++ ++ // get decoder stats ++ if (!m_pVideoCodec->GetPts(iDecoderPts, iSkippedDeint, interlaced)) ++ iDecoderPts = pts; ++ if (iDecoderPts == DVD_NOPTS_VALUE) ++ iDecoderPts = pts; ++ ++ // get render stats ++ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel); ++ ++ if (iBufferLevel < 0) ++ result |= EOS_BUFFER_LEVEL; ++ else if (iBufferLevel < 2) ++ { ++ result |= EOS_BUFFER_LEVEL; ++ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - hurry: %d", iBufferLevel); ++ } ++ ++ bNewFrame = iDecoderPts != m_droppingStats.m_lastDecoderPts; ++ ++ if (interlaced) ++ iInterval = 2/m_fFrameRate*(double)DVD_TIME_BASE; ++ else ++ iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE; ++ ++ if (m_droppingStats.m_lastDecoderPts > 0 ++ && bNewFrame ++ && m_bAllowDrop ++ && m_droppingStats.m_dropRequests > 0) ++ { ++ iGain = (iDecoderPts - m_droppingStats.m_lastDecoderPts - iInterval)/(double)DVD_TIME_BASE; ++ if (iSkippedDeint) ++ { ++ CDroppingStats::CGain gain; ++ gain.gain = 1/m_fFrameRate; ++ gain.pts = iDecoderPts; ++ m_droppingStats.m_gain.push_back(gain); ++ m_droppingStats.m_totalGain += gain.gain; ++ result |= EOS_DROPPED; ++ m_droppingStats.m_dropRequests = 0; ++ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped de-interlacing cycle, Sleeptime: %f, Bufferlevel: %d", iSleepTime, iBufferLevel); ++ } ++ else if (iGain > 1/m_fFrameRate) ++ { ++ CDroppingStats::CGain gain; ++ gain.gain = iGain; ++ gain.pts = iDecoderPts; ++ m_droppingStats.m_gain.push_back(gain); ++ m_droppingStats.m_totalGain += iGain; ++ result |= EOS_DROPPED; ++ m_droppingStats.m_dropRequests = 0; ++ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped in decoder, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain); ++ } ++ } ++ m_droppingStats.m_lastDecoderPts = iDecoderPts; ++ ++ // subtract gains ++ while (!m_droppingStats.m_gain.empty() && ++ iRenderPts >= m_droppingStats.m_gain.front().pts) ++ { ++ m_droppingStats.m_totalGain -= m_droppingStats.m_gain.front().gain; ++ m_droppingStats.m_gain.pop_front(); ++ } ++ ++ // calculate lateness ++ iLateness = iSleepTime + m_droppingStats.m_totalGain; ++ if (iLateness < 0 && m_speed) ++ { ++ if (bNewFrame) ++ m_droppingStats.m_lateFrames++; ++ ++ // if lateness is smaller than frametime, we observe this state ++ // for 10 cycles ++ if (m_droppingStats.m_lateFrames > 10 || iLateness < -2/m_fFrameRate) ++ { ++ // is frame allowed to skip ++ if (m_iNrOfPicturesNotToSkip <= 0) ++ { ++ result |= EOS_VERYLATE; ++ if (bNewFrame) ++ m_droppingStats.m_dropRequests++; ++ } ++ } ++ } ++ else ++ { ++ m_droppingStats.m_dropRequests = 0; ++ m_droppingStats.m_lateFrames = 0; ++ } ++ m_droppingStats.m_lastRenderPts = iRenderPts; ++ return result; ++} ++ ++void CDroppingStats::Reset() ++{ ++ m_gain.clear(); ++ m_totalGain = 0; ++ m_lastDecoderPts = 0; ++ m_lastRenderPts = 0; ++ m_lateFrames = 0; ++ m_dropRequests = 0; ++} ++ ++void CDroppingStats::AddOutputDropGain(double pts, double frametime) ++{ ++ CDroppingStats::CGain gain; ++ gain.gain = frametime; ++ gain.pts = pts; ++ m_gain.push_back(gain); ++ m_totalGain += frametime; ++} +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +index f8ad541..186e271 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +@@ -36,6 +36,25 @@ class CDVDOverlayCodecCC; + + #define VIDEO_PICTURE_QUEUE_SIZE 1 + ++class CDroppingStats ++{ ++public: ++ void Reset(); ++ void AddOutputDropGain(double pts, double frametime); ++ struct CGain ++ { ++ double gain; ++ double pts; ++ }; ++ std::deque m_gain; ++ double m_totalGain; ++ double m_lastDecoderPts; ++ double m_lastRenderPts; ++ unsigned int m_lateFrames; ++ unsigned int m_dropRequests; ++}; ++ ++ + class CDVDPlayerVideo : public CThread + { + public: +@@ -104,6 +123,7 @@ protected: + #define EOS_ABORT 1 + #define EOS_DROPPED 2 + #define EOS_VERYLATE 4 ++#define EOS_BUFFER_LEVEL 8 + + void AutoCrop(DVDVideoPicture* pPicture); + void AutoCrop(DVDVideoPicture *pPicture, RECT &crop); +@@ -129,6 +149,7 @@ protected: + + void ResetFrameRateCalc(); + void CalcFrameRate(); ++ int CalcDropRequirement(double pts); + + double m_fFrameRate; //framerate of the video currently playing + bool m_bCalcFrameRate; //if we should calculate the framerate from the timestamps +@@ -182,5 +203,7 @@ protected: + CPullupCorrection m_pullupCorrection; + + std::list m_packets; ++ ++ CDroppingStats m_droppingStats; + }; + +-- +1.9.1 + + +From 3b8554f9ad09aaed840ae6e00f5073c6e0015721 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sun, 2 Sep 2012 16:05:21 +0200 +Subject: [PATCH 02/96] video player: present correct pts to user for a/v sync + (after buffering in renderer) + +--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 25 +++++++++++++++++++++++++ + xbmc/cores/dvdplayer/DVDPlayerVideo.h | 2 +- + 2 files changed, 26 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 4fad1a3..1d29b6f 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -1455,6 +1455,22 @@ void CDVDPlayerVideo::ResetFrameRateCalc() + g_advancedSettings.m_videoFpsDetect == 0; + } + ++double CDVDPlayerVideo::GetCurrentPts() ++{ ++ double iSleepTime, iRenderPts; ++ int iBufferLevel; ++ ++ // get render stats ++ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel); ++ ++ if( m_stalled ) ++ iRenderPts = DVD_NOPTS_VALUE; ++ else ++ iRenderPts = iRenderPts - max(0.0, iSleepTime); ++ ++ return iRenderPts; ++} ++ + #define MAXFRAMERATEDIFF 0.01 + #define MAXFRAMESERR 1000 + +@@ -1573,6 +1589,15 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) + else + iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE; + ++ ++ m_FlipTimeStamp = m_pClock->GetAbsoluteClock() + max(0.0, iSleepTime) + iInterval; ++ ++ if( m_stalled ) ++ m_iCurrentPts = DVD_NOPTS_VALUE; ++ else ++ m_iCurrentPts = iRenderPts - max(0.0, iSleepTime); ++ ++ + if (m_droppingStats.m_lastDecoderPts > 0 + && bNewFrame + && m_bAllowDrop +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +index 186e271..59c7f09 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +@@ -100,7 +100,7 @@ public: + + bool InitializedOutputDevice(); + +- double GetCurrentPts() { return m_iCurrentPts; } ++ double GetCurrentPts(); + int GetPullupCorrection() { return m_pullupCorrection.GetPatternLength(); } + + double GetOutputDelay(); /* returns the expected delay, from that a packet is put in queue */ +-- +1.9.1 + + +From 1b02662cd1ad58a5421f4dccb61cef38fea3de4e Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sat, 16 Feb 2013 18:25:53 +0100 +Subject: [PATCH 03/96] videoplayer: some rework and documentation + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 28 ++++++++++++++++++++-- + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 11 +++++++++ + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 2 +- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 +- + 4 files changed, 39 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +index fb34463..ecd325c 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +@@ -154,7 +154,6 @@ class CDVDCodecOptions; + #define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data + #define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again + #define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped +-#define VC_HURRY 0x00000040 + + class CDVDVideoCodec + { +@@ -290,10 +289,35 @@ public: + */ + static bool IsCodecDisabled(DVDCodecAvailableType* map, unsigned int size, AVCodecID id); + +- virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) ++ /* For calculation of dropping requirements player asks for some information. ++ * ++ * - pts : right after decoder, used to detect gaps (dropped frames in decoder) ++ * - skippedDeint : indicates if decoder has just skipped a deinterlacing cycle ++ * instead of dropping a full frame ++ * - interlaced : when detecting gaps in pts, player needs to know whether ++ * it's interlaced or not ++ * ++ * If codec does not implement this method, pts of decoded frame at input ++ * video player is used. In case coded does post-proc and de-interlacing there ++ * may be quite some frames queued up between exit decoder and entry player. ++ */ ++ virtual bool GetCodecStats(double &pts, int &skippedDeint, int &interlaced) + { + return false; + } + ++ /** ++ * Codec can be informed by player with the following flags: ++ * ++ * DVP_FLAG_NO_POSTPROC : if speed is not normal the codec can switch off ++ * postprocessing and de-interlacing ++ * ++ * DVP_FLAG_DRAIN : codecs may do postprocessing and de-interlacing. ++ * If video buffers in RenderManager are about to run dry, ++ * this is signaled to codec. Codec can wait for post-proc ++ * to be finished instead of returning empty and getting another ++ * packet. ++ * ++ */ + virtual void SetCodecControl(int flags) {} + }; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index 413151d..b59c1ee 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -951,6 +951,17 @@ unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences() + return 0; + } + ++bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &skippedDeint, int &interlaced) ++{ ++ pts = m_decoderPts; ++ skippedDeint = m_skippedDeint; ++ if (m_pFrame) ++ interlaced = m_pFrame->interlaced_frame; ++ else ++ interlaced = 0; ++ return true; ++} ++ + void CDVDVideoCodecFFmpeg::SetCodecControl(int flags) + { + m_codecControlFlags = flags; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +index 8376f72..c0ce198 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +@@ -63,7 +63,7 @@ public: + virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open + virtual unsigned GetConvergeCount(); + virtual unsigned GetAllowedReferences(); +- virtual bool GetPts(double &pts, int &skippedDeint, int &interlaced) {pts=m_decoderPts; skippedDeint=m_skippedDeint; if (m_pFrame) interlaced = m_pFrame->interlaced_frame; return true;} ++ virtual bool GetCodecStats(double &pts, int &skippedDeint, int &interlaced); + virtual void SetCodecControl(int flags); + + bool IsHardwareAllowed() { return !m_bSoftware; } +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 1d29b6f..ee07f30 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -1566,7 +1566,7 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) + int iBufferLevel; + + // get decoder stats +- if (!m_pVideoCodec->GetPts(iDecoderPts, iSkippedDeint, interlaced)) ++ if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iSkippedDeint, interlaced)) + iDecoderPts = pts; + if (iDecoderPts == DVD_NOPTS_VALUE) + iDecoderPts = pts; +-- +1.9.1 + + +From 79a3a5317beae2966b118a77a25b60b8b3a88c22 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sat, 1 Jun 2013 11:21:19 +0200 +Subject: [PATCH 04/96] renderer: bump buffers to 5 + +--- + xbmc/cores/VideoRenderers/BaseRenderer.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h +index dc2712a..9edfbd4 100644 +--- a/xbmc/cores/VideoRenderers/BaseRenderer.h ++++ b/xbmc/cores/VideoRenderers/BaseRenderer.h +@@ -29,7 +29,7 @@ + + #define MAX_PLANES 3 + #define MAX_FIELDS 3 +-#define NUM_BUFFERS 3 ++#define NUM_BUFFERS 5 + + class CSetting; + +-- +1.9.1 + + +From 307a65669e2b2936d77ec1f06cb60ff45fa5ffa9 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 28 May 2012 10:41:31 +0200 +Subject: [PATCH 05/96] videoplayer: update frametime, it might change due to + fps detection + +--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index ee07f30..b3175cd 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -708,6 +708,8 @@ void CDVDPlayerVideo::Process() + + int iResult = OutputPicture(&picture, pts); + ++ frametime = (double)DVD_TIME_BASE/m_fFrameRate; ++ + if(m_started == false) + { + m_codecname = m_pVideoCodec->GetName(); +-- +1.9.1 + + +From 0c8b92541bac2a40e3cad9f7da8fd6ce028a27ae Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 28 May 2012 10:43:06 +0200 +Subject: [PATCH 06/96] videoplayer: give streams with invalid fps a chance for + fps detection + +--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index b3175cd..9c36bdb 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -1497,7 +1497,7 @@ void CDVDPlayerVideo::CalcFrameRate() + double frameduration = m_pullupCorrection.GetFrameDuration(); + + if (frameduration == DVD_NOPTS_VALUE || +- (g_advancedSettings.m_videoFpsDetect == 1 && m_pullupCorrection.GetPatternLength() > 1)) ++ (g_advancedSettings.m_videoFpsDetect == 1 && (m_pullupCorrection.GetPatternLength() > 1 && !m_bFpsInvalid))) + { + //reset the stored framerates if no good framerate was detected + m_fStableFrameRate = 0.0; +-- +1.9.1 + + +From 08385386346bd04b66867a679271e8e6ad99ff6c Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 28 May 2012 10:49:05 +0200 +Subject: [PATCH 07/96] dvdplayer: allow rewinding at end of stream, do a seek + after rewind + +--- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 3a37dee..15e490c 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -1633,7 +1633,7 @@ void CDVDPlayer::HandlePlaySpeed() + + } + else if (m_CurrentVideo.id >= 0 +- && m_CurrentVideo.inited == true ++ && (m_CurrentVideo.inited == true || GetPlaySpeed() < 0) // allow rewind at end of file + && m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts() + && m_SpeedState.lasttime != GetTime()) + { +@@ -2294,6 +2294,12 @@ void CDVDPlayer::HandleMessages() + pvrinputstream->Pause( speed == 0 ); + } + ++ // do a seek after rewind, clock is not in sync with current pts ++ if (m_playSpeed < 0 && speed >= 0) ++ { ++ m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), true, true, true)); ++ } ++ + // if playspeed is different then DVD_PLAYSPEED_NORMAL or DVD_PLAYSPEED_PAUSE + // audioplayer, stops outputing audio to audiorendere, but still tries to + // sleep an correct amount for each packet +-- +1.9.1 + + +From 79e223a725462b9e0ce94c5d9f820a92e782a197 Mon Sep 17 00:00:00 2001 +From: FernetMenta +Date: Thu, 5 Jul 2012 15:22:05 +0200 +Subject: [PATCH 08/96] X11: ditch SDL for video and window events + +--- + xbmc/Application.cpp | 2 +- + xbmc/system.h | 5 + + xbmc/windowing/Makefile.in | 1 + + xbmc/windowing/WinEvents.cpp | 4 + + xbmc/windowing/WinEventsX11.cpp | 784 ++++++++++++++++++++++++++++++++++++ + xbmc/windowing/WinEventsX11.h | 65 +++ + xbmc/windowing/X11/WinSystemX11.cpp | 386 ++++++++++++------ + xbmc/windowing/X11/WinSystemX11.h | 10 +- + 8 files changed, 1129 insertions(+), 128 deletions(-) + create mode 100644 xbmc/windowing/WinEventsX11.cpp + create mode 100644 xbmc/windowing/WinEventsX11.h + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 5e31453..5a24ffb 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -917,7 +917,7 @@ bool CApplication::CreateGUI() + + uint32_t sdlFlags = 0; + +-#if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2) ++#if (defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)) && !defined(HAS_GLX) + sdlFlags |= SDL_INIT_VIDEO; + #endif + +diff --git a/xbmc/system.h b/xbmc/system.h +index 1f4e15f..075e44a 100644 +--- a/xbmc/system.h ++++ b/xbmc/system.h +@@ -171,16 +171,21 @@ + #define HAS_GL + #ifdef HAVE_X11 + #define HAS_GLX ++#define HAS_X11_WIN_EVENTS + #endif + #ifdef HAVE_SDL + #define HAS_SDL + #ifndef HAS_SDL_OPENGL + #define HAS_SDL_OPENGL + #endif ++#ifndef HAVE_X11 + #define HAS_SDL_WIN_EVENTS ++#endif + #else ++#ifndef HAVE_X11 + #define HAS_LINUX_EVENTS + #endif ++#endif + #define HAS_LINUX_NETWORK + #define HAS_LIRC + #ifdef HAVE_LIBPULSE +diff --git a/xbmc/windowing/Makefile.in b/xbmc/windowing/Makefile.in +index 6704967..4b41723 100644 +--- a/xbmc/windowing/Makefile.in ++++ b/xbmc/windowing/Makefile.in +@@ -1,6 +1,7 @@ + SRCS=WinEventsSDL.cpp \ + WinEventsLinux.cpp \ + WinEventsWayland.cpp \ ++ WinEventsX11.cpp \ + WinSystem.cpp \ + WinEvents.cpp + +diff --git a/xbmc/windowing/WinEvents.cpp b/xbmc/windowing/WinEvents.cpp +index 1022ad2..8e64497 100644 +--- a/xbmc/windowing/WinEvents.cpp ++++ b/xbmc/windowing/WinEvents.cpp +@@ -42,6 +42,10 @@ + #include "WinEventsSDL.h" + #define WinEventsType CWinEventsSDL + ++#elif (defined(TARGET_FREEBSD) || defined(TARGET_LINUX)) && defined(HAS_X11_WIN_EVENTS) ++#include "WinEventsX11.h" ++#define WinEventsType CWinEventsX11 ++ + #elif defined(HAVE_WAYLAND) + #include "WinEventsWayland.h" + #define WinEventsType CWinEventsWayland +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +new file mode 100644 +index 0000000..ad58aad +--- /dev/null ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -0,0 +1,784 @@ ++/* ++* Copyright (C) 2005-2012 Team XBMC ++* http://www.xbmc.org ++* ++* This Program is free software; you can redistribute it and/or modify ++* it under the terms of the GNU General Public License as published by ++* the Free Software Foundation; either version 2, 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 General Public License ++* along with XBMC; see the file COPYING. If not, write to ++* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++* http://www.gnu.org/copyleft/gpl.html ++* ++*/ ++ ++#include "system.h" ++ ++#ifdef HAS_X11_WIN_EVENTS ++ ++#include "WinEvents.h" ++#include "WinEventsX11.h" ++#include "Application.h" ++#include "ApplicationMessenger.h" ++#include ++#include "X11/WinSystemX11GL.h" ++#include "X11/keysymdef.h" ++#include "X11/XF86keysym.h" ++#include "utils/log.h" ++#include "guilib/GUIWindowManager.h" ++#include "input/MouseStat.h" ++ ++CWinEventsX11Imp* CWinEventsX11Imp::WinEvents = 0; ++ ++static uint32_t SymMappingsX11[][2] = ++{ ++ {XK_BackSpace, XBMCK_BACKSPACE} ++, {XK_Tab, XBMCK_TAB} ++, {XK_Clear, XBMCK_CLEAR} ++, {XK_Return, XBMCK_RETURN} ++, {XK_Pause, XBMCK_PAUSE} ++, {XK_Escape, XBMCK_ESCAPE} ++, {XK_Delete, XBMCK_DELETE} ++// multi-media keys ++, {XF86XK_Back, XBMCK_BROWSER_BACK} ++, {XF86XK_Forward, XBMCK_BROWSER_FORWARD} ++, {XF86XK_Refresh, XBMCK_BROWSER_REFRESH} ++, {XF86XK_Stop, XBMCK_BROWSER_STOP} ++, {XF86XK_Search, XBMCK_BROWSER_SEARCH} ++, {XF86XK_Favorites, XBMCK_BROWSER_FAVORITES} ++, {XF86XK_HomePage, XBMCK_BROWSER_HOME} ++, {XF86XK_AudioMute, XBMCK_VOLUME_MUTE} ++, {XF86XK_AudioLowerVolume, XBMCK_VOLUME_DOWN} ++, {XF86XK_AudioRaiseVolume, XBMCK_VOLUME_UP} ++, {XF86XK_AudioNext, XBMCK_MEDIA_NEXT_TRACK} ++, {XF86XK_AudioPrev, XBMCK_MEDIA_PREV_TRACK} ++, {XF86XK_AudioStop, XBMCK_MEDIA_STOP} ++, {XF86XK_AudioPause, XBMCK_MEDIA_PLAY_PAUSE} ++, {XF86XK_Mail, XBMCK_LAUNCH_MAIL} ++, {XF86XK_Select, XBMCK_LAUNCH_MEDIA_SELECT} ++, {XF86XK_Launch0, XBMCK_LAUNCH_APP1} ++, {XF86XK_Launch1, XBMCK_LAUNCH_APP2} ++, {XF86XK_WWW, XBMCK_LAUNCH_FILE_BROWSER} ++, {XF86XK_AudioMedia, XBMCK_LAUNCH_MEDIA_CENTER } ++ // Numeric keypad ++, {XK_KP_0, XBMCK_KP0} ++, {XK_KP_1, XBMCK_KP1} ++, {XK_KP_2, XBMCK_KP2} ++, {XK_KP_3, XBMCK_KP3} ++, {XK_KP_4, XBMCK_KP4} ++, {XK_KP_5, XBMCK_KP5} ++, {XK_KP_6, XBMCK_KP6} ++, {XK_KP_7, XBMCK_KP7} ++, {XK_KP_8, XBMCK_KP8} ++, {XK_KP_9, XBMCK_KP9} ++, {XK_KP_Separator, XBMCK_KP_PERIOD} ++, {XK_KP_Divide, XBMCK_KP_DIVIDE} ++, {XK_KP_Multiply, XBMCK_KP_MULTIPLY} ++, {XK_KP_Subtract, XBMCK_KP_MINUS} ++, {XK_KP_Add, XBMCK_KP_PLUS} ++, {XK_KP_Enter, XBMCK_KP_ENTER} ++, {XK_KP_Equal, XBMCK_KP_EQUALS} ++ // Arrows + Home/End pad ++, {XK_Up, XBMCK_UP} ++, {XK_Down, XBMCK_DOWN} ++, {XK_Right, XBMCK_RIGHT} ++, {XK_Left, XBMCK_LEFT} ++, {XK_Insert, XBMCK_INSERT} ++, {XK_Home, XBMCK_HOME} ++, {XK_End, XBMCK_END} ++, {XK_Page_Up, XBMCK_PAGEUP} ++, {XK_Page_Down, XBMCK_PAGEDOWN} ++ // Function keys ++, {XK_F1, XBMCK_F1} ++, {XK_F2, XBMCK_F2} ++, {XK_F3, XBMCK_F3} ++, {XK_F4, XBMCK_F4} ++, {XK_F5, XBMCK_F5} ++, {XK_F6, XBMCK_F6} ++, {XK_F7, XBMCK_F7} ++, {XK_F8, XBMCK_F8} ++, {XK_F9, XBMCK_F9} ++, {XK_F10, XBMCK_F10} ++, {XK_F11, XBMCK_F11} ++, {XK_F12, XBMCK_F12} ++, {XK_F13, XBMCK_F13} ++, {XK_F14, XBMCK_F14} ++, {XK_F15, XBMCK_F15} ++ // Key state modifier keys ++, {XK_Num_Lock, XBMCK_NUMLOCK} ++, {XK_Caps_Lock, XBMCK_CAPSLOCK} ++, {XK_Scroll_Lock, XBMCK_SCROLLOCK} ++, {XK_Shift_R, XBMCK_RSHIFT} ++, {XK_Shift_L, XBMCK_LSHIFT} ++, {XK_Control_R, XBMCK_RCTRL} ++, {XK_Control_L, XBMCK_LCTRL} ++, {XK_Alt_R, XBMCK_RALT} ++, {XK_Alt_L, XBMCK_LALT} ++, {XK_Meta_R, XBMCK_RMETA} ++, {XK_Meta_L, XBMCK_LMETA} ++, {XK_Super_L, XBMCK_LSUPER} ++, {XK_Super_R, XBMCK_RSUPER} ++, {XK_Mode_switch, XBMCK_MODE} ++, {XK_Multi_key, XBMCK_COMPOSE} ++ // Miscellaneous function keys ++, {XK_Help, XBMCK_HELP} ++, {XK_Print, XBMCK_PRINT} ++//, {0, XBMCK_SYSREQ} ++, {XK_Break, XBMCK_BREAK} ++, {XK_Menu, XBMCK_MENU} ++, {XF86XK_PowerOff, XBMCK_POWER} ++, {XK_EcuSign, XBMCK_EURO} ++, {XK_Undo, XBMCK_UNDO} ++ /* Media keys */ ++, {XF86XK_Eject, XBMCK_EJECT} ++, {XF86XK_Stop, XBMCK_STOP} ++, {XF86XK_AudioRecord, XBMCK_RECORD} ++, {XF86XK_AudioRewind, XBMCK_REWIND} ++, {XF86XK_Phone, XBMCK_PHONE} ++, {XF86XK_AudioPlay, XBMCK_PLAY} ++, {XF86XK_AudioRandomPlay, XBMCK_SHUFFLE} ++, {XF86XK_AudioForward, XBMCK_FASTFORWARD} ++}; ++ ++bool CWinEventsX11::MessagePump() ++{ ++ return CWinEventsX11Imp::MessagePump(); ++} ++ ++size_t CWinEventsX11::GetQueueSize() ++{ ++ return CWinEventsX11Imp::GetQueueSize(); ++} ++ ++CWinEventsX11Imp::CWinEventsX11Imp() ++{ ++ m_display = 0; ++ m_window = 0; ++ m_keybuf = 0; ++ m_utf16buf = 0; ++} ++ ++CWinEventsX11Imp::~CWinEventsX11Imp() ++{ ++ if (m_keybuf); ++ { ++ free(m_keybuf); ++ m_keybuf = 0; ++ } ++ ++ if (m_utf16buf) ++ { ++ free(m_utf16buf); ++ m_utf16buf = 0; ++ } ++ ++ if (m_xic) ++ { ++ XUnsetICFocus(m_xic); ++ XDestroyIC(m_xic); ++ m_xic = 0; ++ } ++ ++ if (m_xim) ++ { ++ XCloseIM(m_xim); ++ m_xim = 0; ++ } ++ ++ m_symLookupTable.clear(); ++} ++ ++bool CWinEventsX11Imp::Init(Display *dpy, Window win) ++{ ++ if (WinEvents) ++ return true; ++ ++ WinEvents = new CWinEventsX11Imp(); ++ WinEvents->m_display = dpy; ++ WinEvents->m_window = win; ++ WinEvents->m_keybuf = (char*)malloc(32*sizeof(char)); ++ WinEvents->m_utf16buf = (uint16_t*)malloc(32*sizeof(uint16_t)); ++ WinEvents->m_keymodState = 0; ++ WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); ++ WinEvents->m_structureChanged = false; ++ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); ++ ++ // open input method ++ char *old_locale = NULL, *old_modifiers = NULL; ++ char res_name[8]; ++ const char *p; ++ size_t n; ++ ++ // set resource name to xbmc, not used ++ strcpy(res_name, "xbmc"); ++ ++ // save current locale, this should be "C" ++ p = setlocale(LC_ALL, NULL); ++ if (p) ++ { ++ old_locale = (char*)malloc(strlen(p) +1); ++ strcpy(old_locale, p); ++ } ++ p = XSetLocaleModifiers(NULL); ++ if (p) ++ { ++ old_modifiers = (char*)malloc(strlen(p) +1); ++ strcpy(old_modifiers, p); ++ } ++ ++ // set users preferences and open input method ++ p = setlocale(LC_ALL, ""); ++ XSetLocaleModifiers(""); ++ WinEvents->m_xim = XOpenIM(WinEvents->m_display, NULL, res_name, res_name); ++ ++ // restore old locale ++ if (old_locale) ++ { ++ setlocale(LC_ALL, old_locale); ++ free(old_locale); ++ } ++ if (old_modifiers) ++ { ++ XSetLocaleModifiers(old_modifiers); ++ free(old_modifiers); ++ } ++ ++ WinEvents->m_xic = NULL; ++ if (WinEvents->m_xim) ++ { ++ WinEvents->m_xic = XCreateIC(WinEvents->m_xim, ++ XNClientWindow, WinEvents->m_window, ++ XNFocusWindow, WinEvents->m_window, ++ XNInputStyle, XIMPreeditNothing | XIMStatusNothing, ++ XNResourceName, res_name, ++ XNResourceClass, res_name, ++ NULL); ++ } ++ ++ if (!WinEvents->m_xic) ++ CLog::Log(LOGWARNING,"CWinEventsX11::Init - no input method found"); ++ ++ // build Keysym lookup table ++ for (unsigned int i = 0; i < sizeof(SymMappingsX11)/(2*sizeof(uint32_t)); ++i) ++ { ++ WinEvents->m_symLookupTable[SymMappingsX11[i][0]] = SymMappingsX11[i][1]; ++ } ++ ++ return true; ++} ++ ++void CWinEventsX11Imp::Quit() ++{ ++ if (!WinEvents) ++ return; ++ ++ delete WinEvents; ++ WinEvents = 0; ++} ++ ++bool CWinEventsX11Imp::HasStructureChanged() ++{ ++ if (!WinEvents) ++ return false; ++ ++ bool ret = WinEvents->m_structureChanged; ++ WinEvents->m_structureChanged = false; ++ return ret; ++} ++ ++bool CWinEventsX11Imp::MessagePump() ++{ ++ if (!WinEvents) ++ return false; ++ ++ bool ret = false; ++ XEvent xevent; ++ unsigned long serial = 0; ++ ++ while (WinEvents && XPending(WinEvents->m_display)) ++ { ++ memset(&xevent, 0, sizeof (XEvent)); ++ XNextEvent(WinEvents->m_display, &xevent); ++ ++ // ignore events generated by auto-repeat ++ if (xevent.type == KeyRelease && XPending(WinEvents->m_display)) ++ { ++ XEvent peekevent; ++ XPeekEvent(WinEvents->m_display, &peekevent); ++ if ((peekevent.type == KeyPress) && ++ (peekevent.xkey.keycode == xevent.xkey.keycode) && ++ ((peekevent.xkey.time - xevent.xkey.time) < 2)) ++ { ++ XNextEvent(WinEvents->m_display, &peekevent); ++ continue; ++ } ++ } ++ ++ if (XFilterEvent(&xevent, None)) ++ continue; ++ ++ switch (xevent.type) ++ { ++ case MapNotify: ++ { ++ g_application.SetRenderGUI(true); ++ break; ++ } ++ ++ case UnmapNotify: ++ { ++ g_application.SetRenderGUI(false); ++ break; ++ } ++ ++ case FocusIn: ++ { ++ if (WinEvents->m_xic) ++ XSetICFocus(WinEvents->m_xic); ++ g_application.m_AppFocused = true; ++ if (serial == xevent.xfocus.serial) ++ break; ++ g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); ++ break; ++ } ++ ++ case FocusOut: ++ { ++ if (WinEvents->m_xic) ++ XUnsetICFocus(WinEvents->m_xic); ++ g_application.m_AppFocused = false; ++ g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); ++ serial = xevent.xfocus.serial; ++ break; ++ } ++ ++ case Expose: ++ { ++ g_windowManager.MarkDirty(); ++ break; ++ } ++ ++ case ConfigureNotify: ++ { ++ if (xevent.xconfigure.window != WinEvents->m_window) ++ break; ++ ++ WinEvents->m_structureChanged = true; ++ XBMC_Event newEvent; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_VIDEORESIZE; ++ newEvent.resize.w = xevent.xconfigure.width; ++ newEvent.resize.h = xevent.xconfigure.height; ++ ret |= g_application.OnEvent(newEvent); ++ g_windowManager.MarkDirty(); ++ break; ++ } ++ ++ case ClientMessage: ++ { ++ if (xevent.xclient.data.l[0] == WinEvents->m_wmDeleteMessage) ++ if (!g_application.m_bStop) CApplicationMessenger::Get().Quit(); ++ break; ++ } ++ ++ case KeyPress: ++ { ++ XBMC_Event newEvent; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_KEYDOWN; ++ KeySym xkeysym; ++ ++ // fallback if we have no IM ++ if (!WinEvents->m_xic) ++ { ++ static XComposeStatus state; ++ char keybuf[32]; ++ xkeysym = XLookupKeysym(&xevent.xkey, 0); ++ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); ++ newEvent.key.keysym.scancode = xevent.xkey.keycode; ++ newEvent.key.state = xevent.xkey.state; ++ newEvent.key.type = xevent.xkey.type; ++ if (XLookupString(&xevent.xkey, keybuf, sizeof(keybuf), NULL, &state)) ++ { ++ newEvent.key.keysym.unicode = keybuf[0]; ++ } ++ ret |= ProcessKey(newEvent, 500); ++ break; ++ } ++ ++ Status status; ++ int utf16size; ++ int utf16length; ++ int len; ++ len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, ++ WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf), ++ &xkeysym, &status); ++ if (status == XBufferOverflow) ++ { ++ WinEvents->m_keybuf = (char*)realloc(WinEvents->m_keybuf, len*sizeof(char)); ++ len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, ++ WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf), ++ &xkeysym, &status); ++ } ++ switch (status) ++ { ++ case XLookupNone: ++ break; ++ case XLookupChars: ++ case XLookupBoth: ++ { ++ if (len == 0) ++ break; ++ utf16size = len * sizeof(uint16_t); ++ if (utf16size > sizeof(WinEvents->m_utf16buf)) ++ { ++ WinEvents->m_utf16buf = (uint16_t *)realloc(WinEvents->m_utf16buf,utf16size); ++ if (WinEvents->m_utf16buf == NULL) ++ { ++ break; ++ } ++ } ++ utf16length = Utf8ToUnicode(WinEvents->m_keybuf, len, WinEvents->m_utf16buf, utf16size); ++ if (utf16length < 0) ++ { ++ break; ++ } ++ for (unsigned int i = 0; i < utf16length - 1; i++) ++ { ++ newEvent.key.keysym.sym = XBMCK_UNKNOWN; ++ newEvent.key.keysym.unicode = WinEvents->m_utf16buf[i]; ++ newEvent.key.state = xevent.xkey.state; ++ newEvent.key.type = xevent.xkey.type; ++ ret |= ProcessKey(newEvent, 500); ++ } ++ if (utf16length > 0) ++ { ++ newEvent.key.keysym.scancode = xevent.xkey.keycode; ++ xkeysym = XLookupKeysym(&xevent.xkey, 0); ++ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); ++ newEvent.key.keysym.unicode = WinEvents->m_utf16buf[utf16length - 1]; ++ newEvent.key.state = xevent.xkey.state; ++ newEvent.key.type = xevent.xkey.type; ++ ++ ret |= ProcessKey(newEvent, 500); ++ } ++ break; ++ } ++ ++ case XLookupKeySym: ++ { ++ newEvent.key.keysym.scancode = xevent.xkey.keycode; ++ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); ++ newEvent.key.state = xevent.xkey.state; ++ newEvent.key.type = xevent.xkey.type; ++ ret |= ProcessKey(newEvent, 500); ++ break; ++ } ++ ++ }// switch status ++ break; ++ } //KeyPress ++ ++ case KeyRelease: ++ { ++ XBMC_Event newEvent; ++ KeySym xkeysym; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_KEYUP; ++ xkeysym = XLookupKeysym(&xevent.xkey, 0); ++ newEvent.key.keysym.scancode = xevent.xkey.keycode; ++ newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); ++ newEvent.key.state = xevent.xkey.state; ++ newEvent.key.type = xevent.xkey.type; ++ ret |= ProcessKey(newEvent, 0); ++ break; ++ } ++ ++ // lose mouse coverage ++ case LeaveNotify: ++ { ++ g_Mouse.SetActive(false); ++ break; ++ } ++ ++ case MotionNotify: ++ { ++ XBMC_Event newEvent; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_MOUSEMOTION; ++ newEvent.motion.xrel = (int16_t)xevent.xmotion.x_root; ++ newEvent.motion.yrel = (int16_t)xevent.xmotion.y_root; ++ newEvent.motion.x = (int16_t)xevent.xmotion.x; ++ newEvent.motion.y = (int16_t)xevent.xmotion.y; ++ ret |= g_application.OnEvent(newEvent); ++ break; ++ } ++ ++ case ButtonPress: ++ { ++ XBMC_Event newEvent; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_MOUSEBUTTONDOWN; ++ newEvent.button.button = (unsigned char)xevent.xbutton.button; ++ newEvent.button.state = XBMC_PRESSED; ++ newEvent.button.x = (int16_t)xevent.xbutton.x; ++ newEvent.button.y = (int16_t)xevent.xbutton.y; ++ ret |= g_application.OnEvent(newEvent); ++ break; ++ } ++ ++ case ButtonRelease: ++ { ++ XBMC_Event newEvent; ++ memset(&newEvent, 0, sizeof(newEvent)); ++ newEvent.type = XBMC_MOUSEBUTTONUP; ++ newEvent.button.button = (unsigned char)xevent.xbutton.button; ++ newEvent.button.state = XBMC_RELEASED; ++ newEvent.button.x = (int16_t)xevent.xbutton.x; ++ newEvent.button.y = (int16_t)xevent.xbutton.y; ++ ret |= g_application.OnEvent(newEvent); ++ break; ++ } ++ ++ default: ++ { ++ break; ++ } ++ }// switch event.type ++ }// while ++ ++ ret |= ProcessKeyRepeat(); ++ ++ return ret; ++} ++ ++size_t CWinEventsX11Imp::GetQueueSize() ++{ ++ int ret = 0; ++ ++ if (WinEvents) ++ ret = XPending(WinEvents->m_display); ++ ++ return ret; ++} ++ ++bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event, int repeatDelay) ++{ ++ if (event.type == XBMC_KEYDOWN) ++ { ++ // check key modifiers ++ switch(event.key.keysym.sym) ++ { ++ case XBMCK_LSHIFT: ++ WinEvents->m_keymodState |= XBMCKMOD_LSHIFT; ++ break; ++ case XBMCK_RSHIFT: ++ WinEvents->m_keymodState |= XBMCKMOD_RSHIFT; ++ break; ++ case XBMCK_LCTRL: ++ WinEvents->m_keymodState |= XBMCKMOD_LCTRL; ++ break; ++ case XBMCK_RCTRL: ++ WinEvents->m_keymodState |= XBMCKMOD_RCTRL; ++ break; ++ case XBMCK_LALT: ++ WinEvents->m_keymodState |= XBMCKMOD_LALT; ++ break; ++ case XBMCK_RALT: ++ WinEvents->m_keymodState |= XBMCKMOD_RCTRL; ++ break; ++ case XBMCK_LMETA: ++ WinEvents->m_keymodState |= XBMCKMOD_LMETA; ++ break; ++ case XBMCK_RMETA: ++ WinEvents->m_keymodState |= XBMCKMOD_RMETA; ++ break; ++ case XBMCK_MODE: ++ WinEvents->m_keymodState |= XBMCKMOD_MODE; ++ break; ++ default: ++ break; ++ } ++ event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState; ++ memcpy(&(WinEvents->m_lastKey), &event, sizeof(event)); ++ WinEvents->m_repeatKeyTimeout.Set(repeatDelay); ++ ++ bool ret = ProcessShortcuts(event); ++ if (ret) ++ return ret; ++ } ++ else if (event.type == XBMC_KEYUP) ++ { ++ switch(event.key.keysym.sym) ++ { ++ case XBMCK_LSHIFT: ++ WinEvents->m_keymodState &= ~XBMCKMOD_LSHIFT; ++ break; ++ case XBMCK_RSHIFT: ++ WinEvents->m_keymodState &= ~XBMCKMOD_RSHIFT; ++ break; ++ case XBMCK_LCTRL: ++ WinEvents->m_keymodState &= ~XBMCKMOD_LCTRL; ++ break; ++ case XBMCK_RCTRL: ++ WinEvents->m_keymodState &= ~XBMCKMOD_RCTRL; ++ break; ++ case XBMCK_LALT: ++ WinEvents->m_keymodState &= ~XBMCKMOD_LALT; ++ break; ++ case XBMCK_RALT: ++ WinEvents->m_keymodState &= ~XBMCKMOD_RCTRL; ++ break; ++ case XBMCK_LMETA: ++ WinEvents->m_keymodState &= ~XBMCKMOD_LMETA; ++ break; ++ case XBMCK_RMETA: ++ WinEvents->m_keymodState &= ~XBMCKMOD_RMETA; ++ break; ++ case XBMCK_MODE: ++ WinEvents->m_keymodState &= ~XBMCKMOD_MODE; ++ break; ++ default: ++ break; ++ } ++ event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState; ++ memset(&(WinEvents->m_lastKey), 0, sizeof(event)); ++ } ++ ++ return g_application.OnEvent(event); ++} ++ ++bool CWinEventsX11Imp::ProcessShortcuts(XBMC_Event& event) ++{ ++ if (event.key.keysym.mod & XBMCKMOD_ALT) ++ { ++ switch(event.key.keysym.sym) ++ { ++ case XBMCK_TAB: // ALT+TAB to minimize/hide ++ g_application.Minimize(); ++ return true; ++ ++ default: ++ return false; ++ } ++ } ++ return false; ++} ++ ++bool CWinEventsX11Imp::ProcessKeyRepeat() ++{ ++ if (WinEvents && (WinEvents->m_lastKey.type == XBMC_KEYDOWN)) ++ { ++ if (WinEvents->m_repeatKeyTimeout.IsTimePast()) ++ { ++ return ProcessKey(WinEvents->m_lastKey, 10); ++ } ++ } ++ return false; ++} ++ ++int CWinEventsX11Imp::Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength) ++{ ++ // p moves over the output buffer. max_ptr points to the next to the last slot of the buffer. ++ uint16_t *p = utf16; ++ uint16_t const *const maxPtr = utf16 + utf16MaxLength; ++ ++ // end_of_input points to the last byte of input as opposed to the next to the last byte. ++ char const *const endOfInput = utf8 + utf8Length - 1; ++ ++ while (utf8 <= endOfInput) ++ { ++ unsigned char const c = *utf8; ++ if (p >= maxPtr) ++ { ++ //No more output space. ++ return -1; ++ } ++ if (c < 0x80) ++ { ++ //One byte ASCII. ++ *p++ = c; ++ utf8 += 1; ++ } ++ else if (c < 0xC0) ++ { ++ // Follower byte without preceding leader bytes. ++ return -1; ++ } ++ // 11 bits ++ else if (c < 0xE0) ++ { ++ // Two byte sequence. We need one follower byte. ++ if (endOfInput - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0)) ++ { ++ return -1; ++ } ++ *p++ = (uint16_t)(((c & 0x1F) << 6) + (utf8[1] & 0x3F)); ++ utf8 += 2; ++ } ++ // 16 bis ++ else if (c < 0xF0) ++ { ++ // Three byte sequence. We need two follower byte. ++ if (endOfInput - utf8 < 2 || ((utf8[1] ^ 0x80) & 0xC0) || ((utf8[2] ^ 0x80) & 0xC0)) ++ { ++ return -1; ++ } ++ *p++ = (uint16_t)(((c & 0xF) << 12) + ((utf8[1] & 0x3F) << 6) + (utf8[2] & 0x3F)); ++ utf8 += 3; ++ } ++ // 21 bits ++ else if (c < 0xF8) ++ { ++ int plane; ++ // Four byte sequence. We need three follower bytes. ++ if (endOfInput - utf8 < 3 || ((utf8[1] ^ 0x80) & 0xC0) || ++ ((utf8[2] ^ 0x80) & 0xC0) || ((utf8[3] ^ 0x80) & 0xC0)) ++ { ++ return -1; ++ } ++ uint32_t unicode = ((c & 0x7) << 18) + ((utf8[1] & 0x3F) << 12) + ++ ((utf8[2] & 0x3F) << 6) + (utf8[3] & 0x3F); ++ utf8 += 4; ++ CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); ++ } ++ // 26 bits ++ else if (c < 0xFC) ++ { ++ CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); ++ utf8 += 5; ++ } ++ // 31 bit ++ else ++ { ++ CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); ++ utf8 += 6; ++ } ++ } ++ return p - utf16; ++} ++ ++XBMCKey CWinEventsX11Imp::LookupXbmcKeySym(KeySym keysym) ++{ ++ // try direct mapping first ++ std::map::iterator it; ++ it = WinEvents->m_symLookupTable.find(keysym); ++ if (it != WinEvents->m_symLookupTable.end()) ++ { ++ return (XBMCKey)(it->second); ++ } ++ ++ // try ascii mappings ++ if (keysym>>8 == 0x00) ++ return (XBMCKey)(keysym & 0xFF); ++ ++ return (XBMCKey)keysym; ++} ++#endif +diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h +new file mode 100644 +index 0000000..ce57c23 +--- /dev/null ++++ b/xbmc/windowing/WinEventsX11.h +@@ -0,0 +1,65 @@ ++/* ++* Copyright (C) 2005-2012 Team XBMC ++* http://www.xbmc.org ++* ++* This Program is free software; you can redistribute it and/or modify ++* it under the terms of the GNU General Public License as published by ++* the Free Software Foundation; either version 2, 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 General Public License ++* along with XBMC; see the file COPYING. If not, write to ++* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++* http://www.gnu.org/copyleft/gpl.html ++* ++*/ ++#pragma once ++ ++#include "WinEvents.h" ++#include ++#include "threads/SystemClock.h" ++#include ++ ++class CWinEventsX11 : public IWinEvents ++{ ++public: ++ virtual bool MessagePump(); ++ virtual size_t GetQueueSize(); ++}; ++ ++class CWinEventsX11Imp ++{ ++public: ++ CWinEventsX11Imp(); ++ virtual ~CWinEventsX11Imp(); ++ static bool Init(Display *dpy, Window win); ++ static void Quit(); ++ static bool HasStructureChanged(); ++ static bool MessagePump(); ++ static size_t GetQueueSize(); ++ ++protected: ++ static int Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength); ++ static XBMCKey LookupXbmcKeySym(KeySym keysym); ++ static bool ProcessKey(XBMC_Event &event, int repeatDelay); ++ static bool ProcessKeyRepeat(); ++ static bool ProcessShortcuts(XBMC_Event& event); ++ static CWinEventsX11Imp *WinEvents; ++ Display *m_display; ++ Window m_window; ++ Atom m_wmDeleteMessage; ++ char *m_keybuf; ++ uint16_t *m_utf16buf; ++ XIM m_xim; ++ XIC m_xic; ++ XBMC_Event m_lastKey; ++ XbmcThreads::EndTime m_repeatKeyTimeout; ++ std::map m_symLookupTable; ++ int m_keymodState; ++ bool m_structureChanged; ++}; +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 083d1e9..40b8403 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -22,7 +22,6 @@ + + #ifdef HAS_GLX + +-#include + #include "WinSystemX11.h" + #include "settings/DisplaySettings.h" + #include "settings/Settings.h" +@@ -34,7 +33,6 @@ + #include "XRandR.h" + #include + #include "threads/SingleLock.h" +-#include + #include "cores/VideoRenderers/RenderManager.h" + #include "utils/TimeUtils.h" + #include "utils/StringUtils.h" +@@ -43,19 +41,22 @@ + #include + #endif + ++#include "../WinEventsX11.h" ++#include "input/MouseStat.h" ++ + using namespace std; + + CWinSystemX11::CWinSystemX11() : CWinSystemBase() + { + m_eWindowSystem = WINDOW_SYSTEM_X11; + m_glContext = NULL; +- m_SDLSurface = NULL; + m_dpy = NULL; + m_glWindow = 0; +- m_wmWindow = 0; + m_bWasFullScreenBeforeMinimize = false; + m_minimized = false; ++ m_bIgnoreNextFocusMessage = false; + m_dpyLostTime = 0; ++ m_invisibleCursor = 0; + + XSetErrorHandler(XErrorHandler); + } +@@ -68,18 +69,6 @@ bool CWinSystemX11::InitWindowSystem() + { + if ((m_dpy = XOpenDisplay(NULL))) + { +- +- SDL_EnableUNICODE(1); +- // set repeat to 10ms to ensure repeat time < frame time +- // so that hold times can be reliably detected +- SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, 10); +- +- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); +- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); +- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); +- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); +- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); +- + return CWinSystemBase::InitWindowSystem(); + } + else +@@ -117,45 +106,37 @@ bool CWinSystemX11::DestroyWindowSystem() + + bool CWinSystemX11::CreateNewWindow(const CStdString& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction) + { +- RESOLUTION_INFO& desktop = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP); +- +- if (fullScreen && +- (res.iWidth != desktop.iWidth || res.iHeight != desktop.iHeight || +- res.fRefreshRate != desktop.fRefreshRate || res.iScreen != desktop.iScreen)) +- { +- //on the first call to SDL_SetVideoMode, SDL stores the current displaymode +- //SDL restores the displaymode on SDL_QUIT(), if we change the displaymode +- //before the first call to SDL_SetVideoMode, SDL changes the displaymode back +- //to the wrong mode on exit +- +- CLog::Log(LOGINFO, "CWinSystemX11::CreateNewWindow initializing to desktop resolution first"); +- if (!SetFullScreen(true, desktop, false)) +- return false; +- } +- + if(!SetFullScreen(fullScreen, res, false)) + return false; + +- CBaseTexture* iconTexture = CTexture::LoadFromFile("special://xbmc/media/icon256x256.png"); +- +- if (iconTexture) +- SDL_WM_SetIcon(SDL_CreateRGBSurfaceFrom(iconTexture->GetPixels(), iconTexture->GetWidth(), iconTexture->GetHeight(), 32, iconTexture->GetPitch(), 0xff0000, 0x00ff00, 0x0000ff, 0xff000000L), NULL); +- SDL_WM_SetCaption("XBMC Media Center", NULL); +- delete iconTexture; +- +- // register XRandR Events +-#if defined(HAS_XRANDR) +- int iReturn; +- XRRQueryExtension(m_dpy, &m_RREventBase, &iReturn); +- XRRSelectInput(m_dpy, m_wmWindow, RRScreenChangeNotifyMask); +-#endif +- + m_bWindowCreated = true; + return true; + } + + bool CWinSystemX11::DestroyWindow() + { ++ if (!m_glWindow) ++ return true; ++ ++ if (m_glContext) ++ glXMakeCurrent(m_dpy, None, NULL); ++ ++ if (m_invisibleCursor) ++ { ++ XUndefineCursor(m_dpy, m_glWindow); ++ XFreeCursor(m_dpy, m_invisibleCursor); ++ m_invisibleCursor = 0; ++ } ++ ++ CWinEventsX11Imp::Quit(); ++ ++ XUnmapWindow(m_dpy, m_glWindow); ++ XSync(m_dpy,TRUE); ++ XUngrabKeyboard(m_dpy, CurrentTime); ++ XUngrabPointer(m_dpy, CurrentTime); ++ XDestroyWindow(m_dpy, m_glWindow); ++ m_glWindow = 0; ++ + return true; + } + +@@ -165,67 +146,105 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n + && m_nHeight == newHeight) + return true; + ++ if (!SetWindow(newWidth, newHeight, false)) ++ { ++ return false; ++ } ++ ++ RefreshGlxContext(); + m_nWidth = newWidth; + m_nHeight = newHeight; ++ m_bFullScreen = false; + +- int options = SDL_OPENGL; +- if (m_bFullScreen) +- options |= SDL_FULLSCREEN; +- else +- options |= SDL_RESIZABLE; ++ return false; ++} + +- if ((m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, options))) ++void CWinSystemX11::RefreshWindow() ++{ ++ g_xrandr.Query(true); ++ XOutput out = g_xrandr.GetCurrentOutput(); ++ XMode mode = g_xrandr.GetCurrentMode(out.name); ++ ++ // only overwrite desktop resolution, if we are not in fullscreen mode ++ if (!g_graphicsContext.IsFullScreenVideo()) + { +- SetGrabMode(); +- RefreshGlxContext(); +- return true; ++ CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshWindow - store desktop resolution, width: %d, height: %d, hz: %2.2f", mode.w, mode.h, mode.hz); ++ UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz); ++ g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id; ++ g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name; + } + +- return false; ++ RESOLUTION_INFO res; ++ unsigned int i; ++ bool found(false); ++ for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i) ++ { ++ if (g_settings.m_ResInfo[i].strId == mode.id) ++ { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution"); ++ return; ++ } ++ ++ if (g_graphicsContext.IsFullScreenRoot()) ++ g_graphicsContext.SetVideoResolution((RESOLUTION)i, true); ++ else ++ g_graphicsContext.SetVideoResolution(RES_WINDOW, true); + } + + bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) + { +- m_nWidth = res.iWidth; +- m_nHeight = res.iHeight; +- m_bFullScreen = fullScreen; + + #if defined(HAS_XRANDR) + XOutput out; + XMode mode; +- out.name = res.strOutput; +- mode.w = res.iWidth; +- mode.h = res.iHeight; +- mode.hz = res.fRefreshRate; +- mode.id = res.strId; ++ ++ if (fullScreen) ++ { ++ out.name = res.strOutput; ++ mode.w = res.iWidth; ++ mode.h = res.iHeight; ++ mode.hz = res.fRefreshRate; ++ mode.id = res.strId; ++ } ++ else ++ { ++ out.name = g_settings.m_ResInfo[RES_DESKTOP].strOutput; ++ mode.w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; ++ mode.h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; ++ mode.hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; ++ mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId; ++ } + +- if(m_bFullScreen) ++ XOutput currout = g_xrandr.GetCurrentOutput(); ++ XMode currmode = g_xrandr.GetCurrentMode(currout.name); ++ ++ // only call xrandr if mode changes ++ if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h || ++ currmode.hz != mode.hz || currmode.id != mode.id) + { ++ CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr"); + OnLostDevice(); + g_xrandr.SetMode(out, mode); + } +- else +- g_xrandr.RestoreState(); + #endif + +- int options = SDL_OPENGL; +- if (m_bFullScreen) +- options |= SDL_FULLSCREEN; +- else +- options |= SDL_RESIZABLE; +- +- if ((m_SDLSurface = SDL_SetVideoMode(m_nWidth, m_nHeight, 0, options))) +- { +- if ((m_SDLSurface->flags & SDL_OPENGL) != SDL_OPENGL) +- CLog::Log(LOGERROR, "CWinSystemX11::SetFullScreen SDL_OPENGL not set, SDL_GetError:%s", SDL_GetError()); ++ if (!SetWindow(res.iWidth, res.iHeight, fullScreen)) ++ return false; + +- SetGrabMode(); +- RefreshGlxContext(); ++ RefreshGlxContext(); + +- return true; +- } ++ m_nWidth = res.iWidth; ++ m_nHeight = res.iHeight; ++ m_bFullScreen = fullScreen; + +- return false; ++ return true; + } + + void CWinSystemX11::UpdateResolutions() +@@ -327,17 +346,10 @@ bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) + bool CWinSystemX11::RefreshGlxContext() + { + bool retVal = false; +- SDL_SysWMinfo info; +- SDL_VERSION(&info.version); +- if (SDL_GetWMInfo(&info) <= 0) +- { +- CLog::Log(LOGERROR, "Failed to get window manager info from SDL"); +- return false; +- } + +- if(m_glWindow == info.info.x11.window && m_glContext) ++ if (m_glContext) + { +- CLog::Log(LOGERROR, "GLX: Same window as before, refreshing context"); ++ CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context"); + glXMakeCurrent(m_dpy, None, NULL); + glXMakeCurrent(m_dpy, m_glWindow, m_glContext); + return true; +@@ -349,8 +361,6 @@ bool CWinSystemX11::RefreshGlxContext() + int availableVisuals = 0; + vMask.screen = DefaultScreen(m_dpy); + XWindowAttributes winAttr; +- m_glWindow = info.info.x11.window; +- m_wmWindow = info.info.x11.wmwindow; + + /* Assume a depth of 24 in case the below calls to XGetWindowAttributes() + or XGetVisualInfo() fail. That shouldn't happen unless something is +@@ -421,7 +431,10 @@ bool CWinSystemX11::RefreshGlxContext() + + void CWinSystemX11::ShowOSMouse(bool show) + { +- SDL_ShowCursor(show ? 1 : 0); ++ if (show) ++ XUndefineCursor(m_dpy,m_glWindow); ++ else if (m_invisibleCursor) ++ XDefineCursor(m_dpy,m_glWindow, m_invisibleCursor); + } + + void CWinSystemX11::ResetOSScreensaver() +@@ -435,8 +448,6 @@ void CWinSystemX11::ResetOSScreensaver() + { + m_screensaverReset.StartZero(); + XResetScreenSaver(m_dpy); +- //need to flush the output buffer, since we don't check for events on m_dpy +- XFlush(m_dpy); + } + } + else +@@ -452,13 +463,27 @@ void CWinSystemX11::NotifyAppActiveChange(bool bActivated) + + m_minimized = !bActivated; + } ++ ++void CWinSystemX11::NotifyAppFocusChange(bool bGaining) ++{ ++ if (bGaining && m_bWasFullScreenBeforeMinimize && !m_bIgnoreNextFocusMessage && ++ !g_graphicsContext.IsFullScreenRoot()) ++ g_graphicsContext.ToggleFullScreenRoot(); ++ if (!bGaining) ++ m_bIgnoreNextFocusMessage = false; ++} ++ + bool CWinSystemX11::Minimize() + { + m_bWasFullScreenBeforeMinimize = g_graphicsContext.IsFullScreenRoot(); + if (m_bWasFullScreenBeforeMinimize) ++ { ++ m_bIgnoreNextFocusMessage = true; + g_graphicsContext.ToggleFullScreenRoot(); ++ } ++ ++ XIconifyWindow(m_dpy, m_glWindow, DefaultScreen(m_dpy)); + +- SDL_WM_IconifyWindow(); + m_minimized = true; + return true; + } +@@ -468,13 +493,13 @@ bool CWinSystemX11::Restore() + } + bool CWinSystemX11::Hide() + { +- XUnmapWindow(m_dpy, m_wmWindow); ++ XUnmapWindow(m_dpy, m_glWindow); + XSync(m_dpy, False); + return true; + } + bool CWinSystemX11::Show(bool raise) + { +- XMapWindow(m_dpy, m_wmWindow); ++ XMapWindow(m_dpy, m_glWindow); + XSync(m_dpy, False); + m_minimized = false; + return true; +@@ -506,6 +531,7 @@ void CWinSystemX11::CheckDisplayEvents() + if (bGotEvent || bTimeout) + { + CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); ++ RefreshWindow(); + + CSingleLock lock(m_resourceSection); + +@@ -564,37 +590,151 @@ bool CWinSystemX11::EnableFrameLimiter() + return m_minimized; + } + +-void CWinSystemX11::SetGrabMode(const CSetting *setting /*= NULL*/) ++bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) + { +- bool enabled; +- if (setting) +- enabled = ((CSettingBool*)setting)->GetValue(); +- else +- enabled = CSettings::Get().GetBool("input.enablesystemkeys"); +- +- if (m_SDLSurface && m_SDLSurface->flags & SDL_FULLSCREEN) ++ bool changeWindow = false; ++ bool changeSize = false; ++ bool mouseActive = false; ++ float mouseX, mouseY; ++ ++ if (m_glWindow && (m_bFullScreen != fullscreen)) + { +- if (enabled) ++ mouseActive = g_Mouse.IsActive(); ++ if (mouseActive) + { +- //SDL will always call XGrabPointer and XGrabKeyboard when in fullscreen +- //so temporarily zero the SDL_FULLSCREEN flag, then turn off SDL grab mode +- //this will make SDL call XUnGrabPointer and XUnGrabKeyboard +- m_SDLSurface->flags &= ~SDL_FULLSCREEN; +- SDL_WM_GrabInput(SDL_GRAB_OFF); +- m_SDLSurface->flags |= SDL_FULLSCREEN; ++ Window root_return, child_return; ++ int root_x_return, root_y_return; ++ int win_x_return, win_y_return; ++ unsigned int mask_return; ++ bool isInWin = XQueryPointer(m_dpy, m_glWindow, &root_return, &child_return, ++ &root_x_return, &root_y_return, ++ &win_x_return, &win_y_return, ++ &mask_return); ++ if (isInWin) ++ { ++ mouseX = (float)win_x_return/m_nWidth; ++ mouseY = (float)win_y_return/m_nHeight; ++ g_Mouse.SetActive(false); ++ } ++ else ++ mouseActive = false; + } +- else ++ DestroyWindow(); ++ } ++ ++ // create main window ++ if (!m_glWindow) ++ { ++ GLint att[] = + { +- //turn off key grabbing, which will actually make SDL turn it on when in fullscreen +- SDL_WM_GrabInput(SDL_GRAB_OFF); +- } ++ GLX_RGBA, ++ GLX_RED_SIZE, 8, ++ GLX_GREEN_SIZE, 8, ++ GLX_BLUE_SIZE, 8, ++ GLX_ALPHA_SIZE, 8, ++ GLX_DEPTH_SIZE, 24, ++ GLX_DOUBLEBUFFER, ++ None ++ }; ++ Colormap cmap; ++ XSetWindowAttributes swa; ++ XVisualInfo *vi; ++ ++ vi = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), att); ++ cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone); ++ ++ int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen)); ++ swa.override_redirect = fullscreen ? True : False; ++ swa.border_pixel = fullscreen ? 0 : 5; ++ swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; ++ swa.colormap = cmap; ++ swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; ++ swa.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask | ++ ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ++ PropertyChangeMask | StructureNotifyMask | KeymapStateMask | ++ EnterWindowMask | LeaveWindowMask | ExposureMask; ++ unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask; ++ ++ m_glWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen), ++ 0, 0, width, height, 0, vi->depth, ++ InputOutput, vi->visual, ++ mask, &swa); ++ ++ // define invisible cursor ++ Pixmap bitmapNoData; ++ XColor black; ++ static char noData[] = { 0,0,0,0,0,0,0,0 }; ++ black.red = black.green = black.blue = 0; ++ ++ bitmapNoData = XCreateBitmapFromData(m_dpy, m_glWindow, noData, 8, 8); ++ m_invisibleCursor = XCreatePixmapCursor(m_dpy, bitmapNoData, bitmapNoData, ++ &black, &black, 0, 0); ++ XFreePixmap(m_dpy, bitmapNoData); ++ XDefineCursor(m_dpy,m_glWindow, m_invisibleCursor); ++ ++ //init X11 events ++ CWinEventsX11Imp::Init(m_dpy, m_glWindow); ++ ++ changeWindow = true; ++ changeSize = true; + } +-} + +-void CWinSystemX11::OnSettingChanged(const CSetting *setting) +-{ +- if (setting->GetId() == "input.enablesystemkeys") +- SetGrabMode(setting); ++ if (!CWinEventsX11Imp::HasStructureChanged() && ((width != m_nWidth) || (height != m_nHeight))) ++ { ++ changeSize = true; ++ } ++ ++ if (changeSize || changeWindow) ++ { ++ XResizeWindow(m_dpy, m_glWindow, width, height); ++ } ++ ++ if (changeWindow) ++ { ++ if (!fullscreen) ++ { ++ XWMHints wm_hints; ++ XClassHint class_hints; ++ XTextProperty windowName, iconName; ++ std::string titleString = "XBMC Media Center"; ++ char *title = (char*)titleString.c_str(); ++ ++ XStringListToTextProperty(&title, 1, &windowName); ++ XStringListToTextProperty(&title, 1, &iconName); ++ wm_hints.initial_state = NormalState; ++ wm_hints.input = True; ++ wm_hints.icon_pixmap = None; ++ wm_hints.flags = StateHint | IconPixmapHint | InputHint; ++ ++ XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName, ++ NULL, 0, NULL, &wm_hints, ++ NULL); ++ ++ // register interest in the delete window message ++ Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False); ++ XSetWMProtocols(m_dpy, m_glWindow, &wmDeleteMessage, 1); ++ } ++ XMapRaised(m_dpy, m_glWindow); ++ XSync(m_dpy,TRUE); ++ ++ if (changeWindow && mouseActive) ++ { ++ XWarpPointer(m_dpy, None, m_glWindow, 0, 0, 0, 0, mouseX*width, mouseY*height); ++ } ++ ++ if (fullscreen) ++ { ++ int result = -1; ++ while (result != GrabSuccess) ++ { ++ result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, m_glWindow, None, CurrentTime); ++ XbmcThreads::ThreadSleep(100); ++ } ++ XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); ++ ++ } ++ } ++ return true; + } + + #endif +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index b1464d0..34b912f 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -54,6 +54,7 @@ public: + virtual bool EnableFrameLimiter(); + + virtual void NotifyAppActiveChange(bool bActivated); ++ virtual void NotifyAppFocusChange(bool bGaining); + + virtual bool Minimize(); + virtual bool Restore() ; +@@ -66,20 +67,21 @@ public: + Display* GetDisplay() { return m_dpy; } + GLXWindow GetWindow() { return m_glWindow; } + GLXContext GetGlxContext() { return m_glContext; } +- virtual void OnSettingChanged(const CSetting *setting); ++ void RefreshWindow(); + + protected: + bool RefreshGlxContext(); + void CheckDisplayEvents(); + void OnLostDevice(); ++ bool SetWindow(int width, int height, bool fullscreen); + +- SDL_Surface* m_SDLSurface; ++ Window m_glWindow; + GLXContext m_glContext; +- GLXWindow m_glWindow; +- Window m_wmWindow; + Display* m_dpy; ++ Cursor m_invisibleCursor; + bool m_bWasFullScreenBeforeMinimize; + bool m_minimized; ++ bool m_bIgnoreNextFocusMessage; + int m_RREventBase; + CCriticalSection m_resourceSection; + std::vector m_resources; +-- +1.9.1 + + +From df8808f316b757da4e760ee8669326901191a6e5 Mon Sep 17 00:00:00 2001 +From: FernetMenta +Date: Thu, 5 Jul 2012 15:24:22 +0200 +Subject: [PATCH 09/96] X11: Add xbmc icon + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 126 +++++++++++++++++++++++++++++++++++- + xbmc/windowing/X11/WinSystemX11.h | 3 +- + 2 files changed, 127 insertions(+), 2 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 40b8403..858ea5e 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -137,6 +137,9 @@ bool CWinSystemX11::DestroyWindow() + XDestroyWindow(m_dpy, m_glWindow); + m_glWindow = 0; + ++ if (m_icon) ++ XFreePixmap(m_dpy, m_icon); ++ + return true; + } + +@@ -691,8 +694,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) + + if (changeWindow) + { ++ m_icon = None; + if (!fullscreen) + { ++ CreateIconPixmap(); + XWMHints wm_hints; + XClassHint class_hints; + XTextProperty windowName, iconName; +@@ -703,7 +708,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) + XStringListToTextProperty(&title, 1, &iconName); + wm_hints.initial_state = NormalState; + wm_hints.input = True; +- wm_hints.icon_pixmap = None; ++ wm_hints.icon_pixmap = m_icon; + wm_hints.flags = StateHint | IconPixmapHint | InputHint; + + XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName, +@@ -737,4 +742,123 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) + return true; + } + ++bool CWinSystemX11::CreateIconPixmap() ++{ ++ int depth; ++ XImage *img = NULL; ++ Visual *vis; ++ XWindowAttributes wndattribs; ++ XVisualInfo visInfo; ++ double rRatio; ++ double gRatio; ++ double bRatio; ++ int outIndex = 0; ++ int i,j; ++ int numBufBytes; ++ unsigned char *buf; ++ uint32_t *newBuf = 0; ++ size_t numNewBufBytes; ++ ++ // Get visual Info ++ XGetWindowAttributes(m_dpy, m_glWindow, &wndattribs); ++ visInfo.visualid = wndattribs.visual->visualid; ++ int nvisuals = 0; ++ XVisualInfo* visuals = XGetVisualInfo(m_dpy, VisualIDMask, &visInfo, &nvisuals); ++ if (nvisuals != 1) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - could not find visual"); ++ return false; ++ } ++ visInfo = visuals[0]; ++ XFree(visuals); ++ ++ depth = visInfo.depth; ++ vis = visInfo.visual; ++ ++ if (depth < 15) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - no suitable depth"); ++ return false; ++ } ++ ++ rRatio = vis->red_mask / 255.0; ++ gRatio = vis->green_mask / 255.0; ++ bRatio = vis->blue_mask / 255.0; ++ ++ CTexture iconTexture; ++ iconTexture.LoadFromFile("special://xbmc/media/icon256x256.png"); ++ buf = iconTexture.GetPixels(); ++ ++ numBufBytes = iconTexture.GetWidth() * iconTexture.GetHeight() * 4; ++ ++ if (depth>=24) ++ numNewBufBytes = (4 * (iconTexture.GetWidth() * iconTexture.GetHeight())); ++ else ++ numNewBufBytes = (2 * (iconTexture.GetWidth() * iconTexture.GetHeight())); ++ ++ newBuf = (uint32_t*)malloc(numNewBufBytes); ++ if (!newBuf) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - malloc failed"); ++ return false; ++ } ++ ++ for (i=0; ired_mask; ++ g &= vis->green_mask; ++ b &= vis->blue_mask; ++ newBuf[outIndex] = r | g | b; ++ ++outIndex; ++ } ++ } ++ img = XCreateImage(m_dpy, vis, depth,ZPixmap, 0, (char *)newBuf, ++ iconTexture.GetWidth(), iconTexture.GetHeight(), ++ (depth>=24)?32:16, 0); ++ if (!img) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - could not create image"); ++ free(newBuf); ++ return false; ++ } ++ if (!XInitImage(img)) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::CreateIconPixmap - init image failed"); ++ XDestroyImage(img); ++ return false; ++ } ++ ++ // set byte order ++ union ++ { ++ char c[sizeof(short)]; ++ short s; ++ } order; ++ order.s = 1; ++ if ((1 == order.c[0])) ++ { ++ img->byte_order = LSBFirst; ++ } ++ else ++ { ++ img->byte_order = MSBFirst; ++ } ++ ++ // create icon pixmap from image ++ m_icon = XCreatePixmap(m_dpy, m_glWindow, img->width, img->height, depth); ++ GC gc = XCreateGC(m_dpy, m_glWindow, 0, NULL); ++ XPutImage(m_dpy, m_icon, gc, img, 0, 0, 0, 0, img->width, img->height); ++ XFreeGC(m_dpy, gc); ++ XDestroyImage(img); // this also frees newBuf ++ ++ return true; ++} ++ + #endif +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 34b912f..352e90e 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -79,6 +79,7 @@ protected: + GLXContext m_glContext; + Display* m_dpy; + Cursor m_invisibleCursor; ++ Pixmap m_icon; + bool m_bWasFullScreenBeforeMinimize; + bool m_minimized; + bool m_bIgnoreNextFocusMessage; +@@ -90,7 +91,7 @@ protected: + private: + bool IsSuitableVisual(XVisualInfo *vInfo); + static int XErrorHandler(Display* dpy, XErrorEvent* error); +- void SetGrabMode(const CSetting *setting = NULL); ++ bool CreateIconPixmap(); + + CStopWatch m_screensaverReset; + }; +-- +1.9.1 + + +From 66e95a677c6705dcbf031610fa2f3dbf5d15efbe Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sun, 20 May 2012 14:11:26 +0200 +Subject: [PATCH 10/96] X11: add SDL joystick until we have a better solution + +--- + xbmc/windowing/WinEventsX11.cpp | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index ad58aad..6f57a87 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -35,6 +35,10 @@ + #include "guilib/GUIWindowManager.h" + #include "input/MouseStat.h" + ++#ifdef HAS_SDL_JOYSTICK ++#include "input/SDLJoystick.h" ++#endif ++ + CWinEventsX11Imp* CWinEventsX11Imp::WinEvents = 0; + + static uint32_t SymMappingsX11[][2] = +@@ -556,6 +560,28 @@ bool CWinEventsX11Imp::MessagePump() + + ret |= ProcessKeyRepeat(); + ++#ifdef HAS_SDL_JOYSTICK ++ SDL_Event event; ++ while (SDL_PollEvent(&event)) ++ { ++ switch(event.type) ++ { ++ case SDL_JOYBUTTONUP: ++ case SDL_JOYBUTTONDOWN: ++ case SDL_JOYAXISMOTION: ++ case SDL_JOYBALLMOTION: ++ case SDL_JOYHATMOTION: ++ g_Joystick.Update(event); ++ ret = true; ++ break; ++ ++ default: ++ break; ++ } ++ memset(&event, 0, sizeof(SDL_Event)); ++ } ++#endif ++ + return ret; + } + +-- +1.9.1 + + +From 3f976cfab6a42dd7232464c7a366f4e6fa43b19f Mon Sep 17 00:00:00 2001 +From: Joakim Plate +Date: Thu, 5 Jul 2012 12:35:55 +0200 +Subject: [PATCH 11/96] X11: factor out code handling device reset notification + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 22 ++++++++++++++-------- + xbmc/windowing/X11/WinSystemX11.h | 1 + + 2 files changed, 15 insertions(+), 8 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 858ea5e..304dac8 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -533,14 +533,7 @@ void CWinSystemX11::CheckDisplayEvents() + + if (bGotEvent || bTimeout) + { +- CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); +- RefreshWindow(); +- +- CSingleLock lock(m_resourceSection); +- +- // tell any shared resources +- for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) +- (*i)->OnResetDevice(); ++ NotifyXRREvent(); + + // reset fail safe timer + m_dpyLostTime = 0; +@@ -548,6 +541,19 @@ void CWinSystemX11::CheckDisplayEvents() + #endif + } + ++void CWinSystemX11::NotifyXRREvent() ++{ ++ CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); ++ RefreshWindow(); ++ ++ CSingleLock lock(m_resourceSection); ++ ++ // tell any shared resources ++ for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) ++ (*i)->OnResetDevice(); ++ ++} ++ + void CWinSystemX11::OnLostDevice() + { + CLog::Log(LOGDEBUG, "%s - notify display change event", __FUNCTION__); +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 352e90e..3f91b9b 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -68,6 +68,7 @@ public: + GLXWindow GetWindow() { return m_glWindow; } + GLXContext GetGlxContext() { return m_glContext; } + void RefreshWindow(); ++ void NotifyXRREvent(); + + protected: + bool RefreshGlxContext(); +-- +1.9.1 + + +From ff1ddbc3986fb6e541d9850c4e51321fed42dab8 Mon Sep 17 00:00:00 2001 +From: FernetMenta +Date: Thu, 5 Jul 2012 15:02:00 +0200 +Subject: [PATCH 12/96] X11: move xrandr events to WinEventsX11 + +--- + xbmc/windowing/WinEventsX11.cpp | 42 +++++++++++++++++++++++++++++++++++++ + xbmc/windowing/WinEventsX11.h | 5 +++++ + xbmc/windowing/X11/WinSystemX11.cpp | 6 +++++- + 3 files changed, 52 insertions(+), 1 deletion(-) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index 6f57a87..d77cb2a 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -35,6 +35,10 @@ + #include "guilib/GUIWindowManager.h" + #include "input/MouseStat.h" + ++#if defined(HAS_XRANDR) ++#include ++#endif ++ + #ifdef HAS_SDL_JOYSTICK + #include "input/SDLJoystick.h" + #endif +@@ -212,6 +216,7 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win) + WinEvents->m_keymodState = 0; + WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + WinEvents->m_structureChanged = false; ++ WinEvents->m_xrrEventPending = false; + memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); + + // open input method +@@ -275,6 +280,13 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win) + WinEvents->m_symLookupTable[SymMappingsX11[i][0]] = SymMappingsX11[i][1]; + } + ++ // register for xrandr events ++#if defined(HAS_XRANDR) ++ int iReturn; ++ XRRQueryExtension(WinEvents->m_display, &WinEvents->m_RREventBase, &iReturn); ++ XRRSelectInput(WinEvents->m_display, WinEvents->m_window, RRScreenChangeNotifyMask); ++#endif ++ + return true; + } + +@@ -297,6 +309,15 @@ bool CWinEventsX11Imp::HasStructureChanged() + return ret; + } + ++void CWinEventsX11Imp::SetXRRFailSafeTimer(int millis) ++{ ++ if (!WinEvents) ++ return; ++ ++ WinEvents->m_xrrFailSafeTimer.Set(millis); ++ WinEvents->m_xrrEventPending = true; ++} ++ + bool CWinEventsX11Imp::MessagePump() + { + if (!WinEvents) +@@ -556,10 +577,31 @@ bool CWinEventsX11Imp::MessagePump() + break; + } + }// switch event.type ++ ++#if defined(HAS_XRANDR) ++ if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRScreenChangeNotify)) ++ { ++ XRRUpdateConfiguration(&xevent); ++ if (xevent.xgeneric.serial != serial) ++ g_Windowing.NotifyXRREvent(); ++ WinEvents->m_xrrEventPending = false; ++ serial = xevent.xgeneric.serial; ++ } ++#endif ++ + }// while + + ret |= ProcessKeyRepeat(); + ++#if defined(HAS_XRANDR) ++ if (WinEvents && WinEvents->m_xrrEventPending && WinEvents->m_xrrFailSafeTimer.IsTimePast()) ++ { ++ CLog::Log(LOGERROR,"CWinEventsX11::MessagePump - missed XRR Events"); ++ g_Windowing.NotifyXRREvent(); ++ WinEvents->m_xrrEventPending = false; ++ } ++#endif ++ + #ifdef HAS_SDL_JOYSTICK + SDL_Event event; + while (SDL_PollEvent(&event)) +diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h +index ce57c23..a412f32 100644 +--- a/xbmc/windowing/WinEventsX11.h ++++ b/xbmc/windowing/WinEventsX11.h +@@ -40,6 +40,8 @@ public: + static bool Init(Display *dpy, Window win); + static void Quit(); + static bool HasStructureChanged(); ++ static void PendingResize(int width, int height); ++ static void SetXRRFailSafeTimer(int millis); + static bool MessagePump(); + static size_t GetQueueSize(); + +@@ -62,4 +64,7 @@ protected: + std::map m_symLookupTable; + int m_keymodState; + bool m_structureChanged; ++ int m_RREventBase; ++ XbmcThreads::EndTime m_xrrFailSafeTimer; ++ bool m_xrrEventPending; + }; +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 304dac8..16b13aa 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -510,7 +510,7 @@ bool CWinSystemX11::Show(bool raise) + + void CWinSystemX11::CheckDisplayEvents() + { +-#if defined(HAS_XRANDR) ++#if defined(HAS_XRANDR) && defined(HAS_SDL_VIDEO_X11) + bool bGotEvent(false); + bool bTimeout(false); + XEvent Event; +@@ -566,8 +566,12 @@ void CWinSystemX11::OnLostDevice() + (*i)->OnLostDevice(); + } + ++#if defined(HAS_SDL_VIDEO_X11) + // fail safe timer + m_dpyLostTime = CurrentHostCounter(); ++#else ++ CWinEventsX11Imp::SetXRRFailSafeTimer(3000); ++#endif + } + + void CWinSystemX11::Register(IDispResource *resource) +-- +1.9.1 + + +From 3a1d2d126d78b438efa6da902b41fb4f65866dd0 Mon Sep 17 00:00:00 2001 +From: FernetMenta +Date: Thu, 12 Apr 2012 15:43:56 +0200 +Subject: [PATCH 13/96] xrandr: remove method RestoreState + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 13 +++++++++++-- + xbmc/windowing/X11/XRandR.cpp | 19 ------------------- + xbmc/windowing/X11/XRandR.h | 1 - + 3 files changed, 11 insertions(+), 22 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 16b13aa..f61d425 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -80,9 +80,18 @@ bool CWinSystemX11::InitWindowSystem() + bool CWinSystemX11::DestroyWindowSystem() + { + #if defined(HAS_XRANDR) +- //restore videomode on exit ++ //restore desktop resolution on exit + if (m_bFullScreen) +- g_xrandr.RestoreState(); ++ { ++ XOutput out; ++ XMode mode; ++ out.name = g_settings.m_ResInfo[RES_DESKTOP].strOutput; ++ mode.w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; ++ mode.h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; ++ mode.hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; ++ mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId; ++ g_xrandr.SetMode(out, mode); ++ } + #endif + + if (m_dpy) +diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp +index 0ac17ab..7e06655 100644 +--- a/xbmc/windowing/X11/XRandR.cpp ++++ b/xbmc/windowing/X11/XRandR.cpp +@@ -139,25 +139,6 @@ void CXRandR::SaveState() + Query(true); + } + +-void CXRandR::RestoreState() +-{ +- vector::iterator outiter; +- for (outiter=m_current.begin() ; outiter!=m_current.end() ; outiter++) +- { +- vector modes = (*outiter).modes; +- vector::iterator modeiter; +- for (modeiter=modes.begin() ; modeiter!=modes.end() ; modeiter++) +- { +- XMode mode = *modeiter; +- if (mode.isCurrent) +- { +- SetMode(*outiter, mode); +- return; +- } +- } +- } +-} +- + bool CXRandR::SetMode(XOutput output, XMode mode) + { + if ((output.name == m_currentOutput && mode.id == m_currentMode) || (output.name == "" && mode.id == "")) +diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h +index 0aec487..00b49dc 100644 +--- a/xbmc/windowing/X11/XRandR.h ++++ b/xbmc/windowing/X11/XRandR.h +@@ -99,7 +99,6 @@ public: + bool SetMode(XOutput output, XMode mode); + void LoadCustomModeLinesToAllOutputs(void); + void SaveState(); +- void RestoreState(); + //bool Has1080i(); + //bool Has1080p(); + //bool Has720p(); +-- +1.9.1 + + +From 17b89c5e0ee97f7a162ba8c0f46c6efeb11fdd24 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sun, 20 May 2012 13:17:10 +0200 +Subject: [PATCH 14/96] xrandr: observe orientation + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 89 ++++++++++++++++++++++++++++++------- + xbmc/windowing/X11/WinSystemX11.h | 2 + + xbmc/windowing/X11/XRandR.cpp | 7 +++ + xbmc/windowing/X11/XRandR.h | 1 + + 4 files changed, 82 insertions(+), 17 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index f61d425..4257aeb 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -85,11 +85,11 @@ bool CWinSystemX11::DestroyWindowSystem() + { + XOutput out; + XMode mode; +- out.name = g_settings.m_ResInfo[RES_DESKTOP].strOutput; +- mode.w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; +- mode.h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; +- mode.hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; +- mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId; ++ out.name = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput; ++ mode.w = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).iWidth; ++ mode.h = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).iHeight; ++ mode.hz = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).fRefreshRate; ++ mode.id = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId; + g_xrandr.SetMode(out, mode); + } + #endif +@@ -173,25 +173,34 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n + + void CWinSystemX11::RefreshWindow() + { +- g_xrandr.Query(true); ++ if (!g_xrandr.Query(true)) ++ { ++ CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); ++ return; ++ } + XOutput out = g_xrandr.GetCurrentOutput(); + XMode mode = g_xrandr.GetCurrentMode(out.name); + ++ RotateResolutions(); ++ + // only overwrite desktop resolution, if we are not in fullscreen mode + if (!g_graphicsContext.IsFullScreenVideo()) + { + CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshWindow - store desktop resolution, width: %d, height: %d, hz: %2.2f", mode.w, mode.h, mode.hz); +- UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, mode.w, mode.h, mode.hz); +- g_settings.m_ResInfo[RES_DESKTOP].strId = mode.id; +- g_settings.m_ResInfo[RES_DESKTOP].strOutput = out.name; ++ if (!out.isRotated) ++ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz); ++ else ++ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz); ++ CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id; ++ CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = out.name; + } + + RESOLUTION_INFO res; + unsigned int i; + bool found(false); +- for (i = RES_DESKTOP; i < g_settings.m_ResInfo.size(); ++i) ++ for (i = RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); ++i) + { +- if (g_settings.m_ResInfo[i].strId == mode.id) ++ if (CDisplaySettings::Get().GetResolutionInfo(i).strId == mode.id) + { + found = true; + break; +@@ -227,16 +236,24 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + } + else + { +- out.name = g_settings.m_ResInfo[RES_DESKTOP].strOutput; +- mode.w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; +- mode.h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; +- mode.hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; +- mode.id = g_settings.m_ResInfo[RES_DESKTOP].strId; ++ out.name = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput; ++ mode.w = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).iWidth; ++ mode.h = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).iHeight; ++ mode.hz = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).fRefreshRate; ++ mode.id = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId; + } + + XOutput currout = g_xrandr.GetCurrentOutput(); + XMode currmode = g_xrandr.GetCurrentMode(currout.name); + ++ // flip h/w when rotated ++ if (m_bIsRotated) ++ { ++ int w = mode.w; ++ mode.w = mode.h; ++ mode.h = w; ++ } ++ + // only call xrandr if mode changes + if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h || + currmode.hz != mode.hz || currmode.id != mode.id) +@@ -269,7 +286,11 @@ void CWinSystemX11::UpdateResolutions() + { + XOutput out = g_xrandr.GetCurrentOutput(); + XMode mode = g_xrandr.GetCurrentMode(out.name); +- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz); ++ m_bIsRotated = out.isRotated; ++ if (!m_bIsRotated) ++ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz); ++ else ++ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz); + CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id; + CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = out.name; + } +@@ -308,6 +329,16 @@ void CWinSystemX11::UpdateResolutions() + res.iHeight = mode.h; + res.iScreenWidth = mode.w; + res.iScreenHeight = mode.h; ++ if (!m_bIsRotated) ++ { ++ res.iWidth = mode.w; ++ res.iHeight = mode.h; ++ } ++ else ++ { ++ res.iWidth = mode.h; ++ res.iHeight = mode.w; ++ } + if (mode.h>0 && mode.w>0 && out.hmm>0 && out.wmm>0) + res.fPixelRatio = ((float)out.wmm/(float)mode.w) / (((float)out.hmm/(float)mode.h)); + else +@@ -335,6 +366,30 @@ void CWinSystemX11::UpdateResolutions() + + } + ++void CWinSystemX11::RotateResolutions() ++{ ++#if defined(HAS_XRANDR) ++ XOutput out = g_xrandr.GetCurrentOutput(); ++ if (out.isRotated == m_bIsRotated) ++ return; ++ ++ for (unsigned int i = 0; i < CDisplaySettings::Get().ResolutionInfoSize(); ++i) ++ { ++ int width = CDisplaySettings::Get().GetResolutionInfo(i).iWidth; ++ CDisplaySettings::Get().GetResolutionInfo(i).iWidth = CDisplaySettings::Get().GetResolutionInfo(i).iHeight; ++ CDisplaySettings::Get().GetResolutionInfo(i).iHeight = width; ++ } ++ // update desktop resolution ++// int h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; ++// int w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; ++// float hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; ++// UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, hz); ++ ++ m_bIsRotated = out.isRotated; ++ ++#endif ++} ++ + bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) + { + int value; +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 3f91b9b..4175aab 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -75,12 +75,14 @@ protected: + void CheckDisplayEvents(); + void OnLostDevice(); + bool SetWindow(int width, int height, bool fullscreen); ++ void RotateResolutions(); + + Window m_glWindow; + GLXContext m_glContext; + Display* m_dpy; + Cursor m_invisibleCursor; + Pixmap m_icon; ++ bool m_bIsRotated; + bool m_bWasFullScreenBeforeMinimize; + bool m_minimized; + bool m_bIgnoreNextFocusMessage; +diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp +index 7e06655..330e945 100644 +--- a/xbmc/windowing/X11/XRandR.cpp ++++ b/xbmc/windowing/X11/XRandR.cpp +@@ -98,6 +98,13 @@ bool CXRandR::Query(bool force) + xoutput.y = (output->Attribute("y") != NULL ? atoi(output->Attribute("y")) : 0); + xoutput.wmm = (output->Attribute("wmm") != NULL ? atoi(output->Attribute("wmm")) : 0); + xoutput.hmm = (output->Attribute("hmm") != NULL ? atoi(output->Attribute("hmm")) : 0); ++ if (output->Attribute("rotation") != NULL ++ && (strcasecmp(output->Attribute("rotation"), "left") == 0 || strcasecmp(output->Attribute("rotation"), "right") == 0)) ++ { ++ xoutput.isRotated = true; ++ } ++ else ++ xoutput.isRotated = false; + + if (!xoutput.isConnected) + continue; +diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h +index 00b49dc..508604d 100644 +--- a/xbmc/windowing/X11/XRandR.h ++++ b/xbmc/windowing/X11/XRandR.h +@@ -86,6 +86,7 @@ public: + int wmm; + int hmm; + std::vector modes; ++ bool isRotated; + }; + + class CXRandR +-- +1.9.1 + + +From 50b8649389095c3b80ed2d698630eaf95fc9218e Mon Sep 17 00:00:00 2001 +From: FernetMenta +Date: Thu, 5 Jul 2012 11:54:15 +0200 +Subject: [PATCH 15/96] xrandr: allow getting info for multiple screen's + +Refactored by: Joakim Plate +--- + xbmc/windowing/X11/XRandR.cpp | 65 +++++++++++++++++++++++++++++++++---------- + xbmc/windowing/X11/XRandR.h | 8 ++++-- + 2 files changed, 57 insertions(+), 16 deletions(-) + +diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp +index 330e945..4685413 100644 +--- a/xbmc/windowing/X11/XRandR.cpp ++++ b/xbmc/windowing/X11/XRandR.cpp +@@ -40,6 +40,7 @@ using namespace std; + CXRandR::CXRandR(bool query) + { + m_bInit = false; ++ m_numScreens = 1; + if (query) + Query(); + } +@@ -56,11 +57,21 @@ bool CXRandR::Query(bool force) + return false; + + m_outputs.clear(); +- m_current.clear(); ++ // query all screens ++ for(unsigned int screennum=0; screennumValue(), "screen") != 0) ++ if (strcasecmp(pRootElement->Value(), "screen") != screennum) + { + // TODO ERROR + return false; +@@ -92,6 +103,7 @@ bool CXRandR::Query(bool force) + xoutput.name = output->Attribute("name"); + StringUtils::Trim(xoutput.name); + xoutput.isConnected = (strcasecmp(output->Attribute("connected"), "true") == 0); ++ xoutput.screen = screennum; + xoutput.w = (output->Attribute("w") != NULL ? atoi(output->Attribute("w")) : 0); + xoutput.h = (output->Attribute("h") != NULL ? atoi(output->Attribute("h")) : 0); + xoutput.x = (output->Attribute("x") != NULL ? atoi(output->Attribute("x")) : 0); +@@ -123,7 +135,6 @@ bool CXRandR::Query(bool force) + xoutput.modes.push_back(xmode); + if (xmode.isCurrent) + { +- m_current.push_back(xoutput); + hascurrent = true; + } + } +@@ -247,17 +258,6 @@ bool CXRandR::SetMode(XOutput output, XMode mode) + return true; + } + +-XOutput CXRandR::GetCurrentOutput() +-{ +- Query(); +- for (unsigned int j = 0; j < m_outputs.size(); j++) +- { +- if(m_outputs[j].isConnected) +- return m_outputs[j]; +- } +- XOutput empty; +- return empty; +-} + XMode CXRandR::GetCurrentMode(CStdString outputName) + { + Query(); +@@ -329,6 +329,43 @@ void CXRandR::LoadCustomModeLinesToAllOutputs(void) + } + } + ++void CXRandR::SetNumScreens(unsigned int num) ++{ ++ m_numScreens = num; ++ m_bInit = false; ++} ++ ++bool CXRandR::IsOutputConnected(CStdString name) ++{ ++ bool result = false; ++ Query(); ++ ++ for (unsigned int i = 0; i < m_outputs.size(); ++i) ++ { ++ if (m_outputs[i].name == name) ++ { ++ result = true; ++ break; ++ } ++ } ++ return result; ++} ++ ++XOutput* CXRandR::GetOutput(CStdString outputName) ++{ ++ XOutput *result = 0; ++ Query(); ++ for (unsigned int i = 0; i < m_outputs.size(); ++i) ++ { ++ if (m_outputs[i].name == outputName) ++ { ++ result = &m_outputs[i]; ++ break; ++ } ++ } ++ return result; ++} ++ + CXRandR g_xrandr; + + #endif // HAS_XRANDR +diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h +index 508604d..d37838a 100644 +--- a/xbmc/windowing/X11/XRandR.h ++++ b/xbmc/windowing/X11/XRandR.h +@@ -79,6 +79,7 @@ public: + } + CStdString name; + bool isConnected; ++ int screen; + int w; + int h; + int x; +@@ -94,12 +95,15 @@ class CXRandR + public: + CXRandR(bool query=false); + bool Query(bool force=false); ++ bool Query(bool force, int screennum); + std::vector GetModes(void); +- XOutput GetCurrentOutput(); + XMode GetCurrentMode(CStdString outputName); ++ XOutput *GetOutput(CStdString outputName); + bool SetMode(XOutput output, XMode mode); + void LoadCustomModeLinesToAllOutputs(void); + void SaveState(); ++ void SetNumScreens(unsigned int num); ++ bool IsOutputConnected(CStdString name); + //bool Has1080i(); + //bool Has1080p(); + //bool Has720p(); +@@ -107,10 +111,10 @@ public: + + private: + bool m_bInit; +- std::vector m_current; + std::vector m_outputs; + CStdString m_currentOutput; + CStdString m_currentMode; ++ unsigned int m_numScreens; + }; + + extern CXRandR g_xrandr; +-- +1.9.1 + + +From 1c4250942d2478de4241bfd7f54b627faf476824 Mon Sep 17 00:00:00 2001 +From: FernetMenta +Date: Thu, 5 Jul 2012 11:44:00 +0200 +Subject: [PATCH 16/96] X11: fix multi-head setups + +--- + language/English/strings.po | 4 +- + system/settings/settings.xml | 11 ++ + xbmc/rendering/gl/RenderSystemGL.h | 1 + + xbmc/settings/DisplaySettings.cpp | 44 ++++++- + xbmc/settings/DisplaySettings.h | 2 + + xbmc/settings/Settings.cpp | 6 + + xbmc/windowing/WinEventsX11.cpp | 7 + + xbmc/windowing/X11/WinSystemX11.cpp | 255 +++++++++++++++++++++--------------- + xbmc/windowing/X11/WinSystemX11.h | 10 +- + 9 files changed, 227 insertions(+), 113 deletions(-) + +diff --git a/language/English/strings.po b/language/English/strings.po +index 616a321..685847c 100755 +--- a/language/English/strings.po ++++ b/language/English/strings.po +@@ -1021,7 +1021,9 @@ msgctxt "#245" + msgid "Sizing: (%i,%i)->(%i,%i) (Zoom x%2.2f) AR:%2.2f:1 (Pixels: %2.2f:1) (VShift: %2.2f)" + msgstr "" + +-#empty string with id 246 ++msgctxt "#246" ++msgid "Monitor" ++msgstr "" + + msgctxt "#247" + msgid "Scripts" +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index f92bd59..fba4561 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -2251,6 +2251,15 @@ +
+ + ++ ++ HAS_GLX ++ 0 ++ Default ++ ++ monitors ++ ++ ++ + + 0 + 0 +@@ -2272,6 +2281,7 @@ + -1 + + ++ + + + +@@ -2289,6 +2299,7 @@ + -1 + + ++ + + + +diff --git a/xbmc/rendering/gl/RenderSystemGL.h b/xbmc/rendering/gl/RenderSystemGL.h +index 4bd540b..f1e2c50 100644 +--- a/xbmc/rendering/gl/RenderSystemGL.h ++++ b/xbmc/rendering/gl/RenderSystemGL.h +@@ -44,6 +44,7 @@ public: + virtual bool IsExtSupported(const char* extension); + + virtual void SetVSync(bool vsync); ++ virtual void ResetVSync() { m_bVsyncInit = false; } + + virtual void SetViewPort(CRect& viewPort); + virtual void GetViewPort(CRect& viewPort); +diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp +index daa1b18..db2f667 100644 +--- a/xbmc/settings/DisplaySettings.cpp ++++ b/xbmc/settings/DisplaySettings.cpp +@@ -219,7 +219,8 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting) + + const std::string &settingId = setting->GetId(); + if (settingId == "videoscreen.resolution" || +- settingId == "videoscreen.screen") ++ settingId == "videoscreen.screen" || ++ settingId == "videoscreen.monitor") + { + RESOLUTION newRes = RES_DESKTOP; + if (settingId == "videoscreen.resolution") +@@ -235,6 +236,11 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting) + // get desktop resolution for screen + newRes = GetResolutionForScreen(); + } ++ else if (settingId == "videoscreen.monitor") ++ { ++ g_Windowing.UpdateResolutions(); ++ newRes = GetResolutionForScreen(); ++ } + + string screenmode = GetStringFromResolution(newRes); + CSettings::Get().SetString("videoscreen.screenmode", screenmode); +@@ -245,7 +251,11 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting) + RESOLUTION newRes = GetResolutionFromString(((CSettingString*)setting)->GetValue()); + + SetCurrentResolution(newRes, false); +- g_graphicsContext.SetVideoResolution(newRes); ++ bool outputChanged = false; ++#if defined(HAS_GLX) ++ outputChanged = !g_Windowing.IsCurrentOutput(CSettings::Get().GetString("videoscreen.monitor")); ++#endif ++ g_graphicsContext.SetVideoResolution(newRes, outputChanged); + + // check if the old or the new resolution was/is windowed + // in which case we don't show any prompt to the user +@@ -641,6 +651,10 @@ void CDisplaySettings::SettingOptionsScreensFiller(const CSetting *setting, std: + if (g_advancedSettings.m_canWindowed) + list.push_back(make_pair(g_localizeStrings.Get(242), DM_WINDOWED)); + ++#if defined(HAS_GLX) ++ list.push_back(make_pair(g_localizeStrings.Get(244), 0)); ++#else ++ + for (int idx = 0; idx < g_Windowing.GetNumScreens(); idx++) + { + int screen = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP + idx).iScreen; +@@ -655,6 +669,7 @@ void CDisplaySettings::SettingOptionsScreensFiller(const CSetting *setting, std: + RESOLUTION_INFO resInfo = CDisplaySettings::Get().GetResolutionInfo(res); + current = resInfo.iScreen; + } ++#endif + } + + void CDisplaySettings::SettingOptionsVerticalSyncsFiller(const CSetting *setting, std::vector< std::pair > &list, int ¤t) +@@ -683,3 +698,28 @@ void CDisplaySettings::SettingOptionsPreferredStereoscopicViewModesFiller(const + SettingOptionsStereoscopicModesFiller(setting, list, current); + list.push_back(make_pair(g_localizeStrings.Get(36525), RENDER_STEREO_MODE_AUTO)); // option for autodetect + } ++ ++void CDisplaySettings::SettingOptionsMonitorsFiller(const CSetting *setting, std::vector< std::pair > &list, std::string ¤t) ++{ ++#if defined(HAS_GLX) ++ std::vector monitors; ++ g_Windowing.GetConnectedOutputs(&monitors); ++ for (unsigned int i=0; i RES_CUSTOM) ++ { ++ std::vector::iterator firstCustom = m_resolutions.begin()+RES_CUSTOM; ++ m_resolutions.erase(firstCustom, m_resolutions.end()); ++ } ++} +diff --git a/xbmc/settings/DisplaySettings.h b/xbmc/settings/DisplaySettings.h +index 8ee1be2..bead24b 100644 +--- a/xbmc/settings/DisplaySettings.h ++++ b/xbmc/settings/DisplaySettings.h +@@ -78,6 +78,7 @@ public: + + void ApplyCalibrations(); + void UpdateCalibrations(); ++ void ClearCustomResolutions(); + + float GetZoomAmount() const { return m_zoomAmount; } + void SetZoomAmount(float zoomAmount) { m_zoomAmount = zoomAmount; } +@@ -95,6 +96,7 @@ public: + static void SettingOptionsVerticalSyncsFiller(const CSetting *setting, std::vector< std::pair > &list, int ¤t); + static void SettingOptionsStereoscopicModesFiller(const CSetting *setting, std::vector< std::pair > &list, int ¤t); + static void SettingOptionsPreferredStereoscopicViewModesFiller(const CSetting *setting, std::vector< std::pair > &list, int ¤t); ++ static void SettingOptionsMonitorsFiller(const CSetting *setting, std::vector< std::pair > &list, std::string ¤t); + + protected: + CDisplaySettings(); +diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp +index d8d50ea..013adf9 100644 +--- a/xbmc/settings/Settings.cpp ++++ b/xbmc/settings/Settings.cpp +@@ -406,6 +406,7 @@ void CSettings::Uninitialize() + m_settingsManager->UnregisterSettingOptionsFiller("screens"); + m_settingsManager->UnregisterSettingOptionsFiller("stereoscopicmodes"); + m_settingsManager->UnregisterSettingOptionsFiller("preferedstereoscopicviewmodes"); ++ m_settingsManager->UnregisterSettingOptionsFiller("monitors"); + m_settingsManager->UnregisterSettingOptionsFiller("shutdownstates"); + m_settingsManager->UnregisterSettingOptionsFiller("startupwindows"); + m_settingsManager->UnregisterSettingOptionsFiller("streamlanguages"); +@@ -835,6 +836,7 @@ void CSettings::InitializeOptionFillers() + m_settingsManager->RegisterSettingOptionsFiller("screens", CDisplaySettings::SettingOptionsScreensFiller); + m_settingsManager->RegisterSettingOptionsFiller("stereoscopicmodes", CDisplaySettings::SettingOptionsStereoscopicModesFiller); + m_settingsManager->RegisterSettingOptionsFiller("preferedstereoscopicviewmodes", CDisplaySettings::SettingOptionsPreferredStereoscopicViewModesFiller); ++ m_settingsManager->RegisterSettingOptionsFiller("monitors", CDisplaySettings::SettingOptionsMonitorsFiller); + m_settingsManager->RegisterSettingOptionsFiller("shutdownstates", CPowerManager::SettingOptionsShutdownStatesFiller); + m_settingsManager->RegisterSettingOptionsFiller("startupwindows", ADDON::CSkinInfo::SettingOptionsStartupWindowsFiller); + m_settingsManager->RegisterSettingOptionsFiller("streamlanguages", CLangInfo::SettingOptionsStreamLanguagesFiller); +@@ -868,6 +870,9 @@ void CSettings::InitializeConditions() + #ifdef HAS_GL + m_settingsManager->AddCondition("has_gl"); + #endif ++#ifdef HAS_GLX ++ m_settingsManager->AddCondition("has_glx"); ++#endif + #ifdef HAS_GLES + m_settingsManager->AddCondition("has_gles"); + #endif +@@ -1021,6 +1026,7 @@ void CSettings::InitializeISettingCallbacks() + settingSet.insert("videoscreen.resolution"); + settingSet.insert("videoscreen.screenmode"); + settingSet.insert("videoscreen.vsync"); ++ settingSet.insert("videoscreen.monitor"); + m_settingsManager->RegisterCallback(&CDisplaySettings::Get(), settingSet); + + settingSet.clear(); +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index d77cb2a..d98f12f 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -526,9 +526,16 @@ bool CWinEventsX11Imp::MessagePump() + break; + } + ++ case EnterNotify: ++ { ++ g_Windowing.NotifyMouseCoverage(true); ++ break; ++ } ++ + // lose mouse coverage + case LeaveNotify: + { ++ g_Windowing.NotifyMouseCoverage(false); + g_Mouse.SetActive(false); + break; + } +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 4257aeb..5e86772 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -36,6 +36,8 @@ + #include "cores/VideoRenderers/RenderManager.h" + #include "utils/TimeUtils.h" + #include "utils/StringUtils.h" ++#include "settings/Settings.h" ++#include "windowing/WindowingFactory.h" + + #if defined(HAS_XRANDR) + #include +@@ -57,6 +59,7 @@ CWinSystemX11::CWinSystemX11() : CWinSystemBase() + m_bIgnoreNextFocusMessage = false; + m_dpyLostTime = 0; + m_invisibleCursor = 0; ++ m_bIsInternalXrr = false; + + XSetErrorHandler(XErrorHandler); + } +@@ -69,7 +72,8 @@ bool CWinSystemX11::InitWindowSystem() + { + if ((m_dpy = XOpenDisplay(NULL))) + { +- return CWinSystemBase::InitWindowSystem(); ++ bool ret = CWinSystemBase::InitWindowSystem(); ++ return ret; + } + else + CLog::Log(LOGERROR, "GLX Error: No Display found"); +@@ -106,6 +110,8 @@ bool CWinSystemX11::DestroyWindowSystem() + + //we don't call XCloseDisplay() here, since ati keeps a pointer to our m_dpy + //so instead we just let m_dpy die on exit ++ // i have seen core dumps on ATI if the display is not closed here ++ XCloseDisplay(m_dpy); + } + + // m_SDLSurface is free()'d by SDL_Quit(). +@@ -128,7 +134,10 @@ bool CWinSystemX11::DestroyWindow() + return true; + + if (m_glContext) ++ { ++ glFinish(); + glXMakeCurrent(m_dpy, None, NULL); ++ } + + if (m_invisibleCursor) + { +@@ -158,7 +167,7 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n + && m_nHeight == newHeight) + return true; + +- if (!SetWindow(newWidth, newHeight, false)) ++ if (!SetWindow(newWidth, newHeight, false, CSettings::Get().GetString("videoscreen.monitor"))) + { + return false; + } +@@ -167,58 +176,11 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n + m_nWidth = newWidth; + m_nHeight = newHeight; + m_bFullScreen = false; ++ m_currentOutput = CSettings::Get().GetString("videoscreen.monitor"); + + return false; + } + +-void CWinSystemX11::RefreshWindow() +-{ +- if (!g_xrandr.Query(true)) +- { +- CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); +- return; +- } +- XOutput out = g_xrandr.GetCurrentOutput(); +- XMode mode = g_xrandr.GetCurrentMode(out.name); +- +- RotateResolutions(); +- +- // only overwrite desktop resolution, if we are not in fullscreen mode +- if (!g_graphicsContext.IsFullScreenVideo()) +- { +- CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshWindow - store desktop resolution, width: %d, height: %d, hz: %2.2f", mode.w, mode.h, mode.hz); +- if (!out.isRotated) +- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz); +- else +- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz); +- CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id; +- CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = out.name; +- } +- +- RESOLUTION_INFO res; +- unsigned int i; +- bool found(false); +- for (i = RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); ++i) +- { +- if (CDisplaySettings::Get().GetResolutionInfo(i).strId == mode.id) +- { +- found = true; +- break; +- } +- } +- +- if (!found) +- { +- CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution"); +- return; +- } +- +- if (g_graphicsContext.IsFullScreenRoot()) +- g_graphicsContext.SetVideoResolution((RESOLUTION)i, true); +- else +- g_graphicsContext.SetVideoResolution(RES_WINDOW, true); +-} +- + bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) + { + +@@ -243,8 +205,7 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + mode.id = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId; + } + +- XOutput currout = g_xrandr.GetCurrentOutput(); +- XMode currmode = g_xrandr.GetCurrentMode(currout.name); ++ XMode currmode = g_xrandr.GetCurrentMode(out.name); + + // flip h/w when rotated + if (m_bIsRotated) +@@ -255,16 +216,17 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + } + + // only call xrandr if mode changes +- if (currout.name != out.name || currmode.w != mode.w || currmode.h != mode.h || ++ if (currmode.w != mode.w || currmode.h != mode.h || + currmode.hz != mode.hz || currmode.id != mode.id) + { + CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr"); + OnLostDevice(); ++ m_bIsInternalXrr = true; + g_xrandr.SetMode(out, mode); + } + #endif + +- if (!SetWindow(res.iWidth, res.iHeight, fullScreen)) ++ if (!SetWindow(res.iWidth, res.iHeight, fullScreen, CSettings::Get().GetString("videoscreen.monitor"))) + return false; + + RefreshGlxContext(); +@@ -272,6 +234,7 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + m_nWidth = res.iWidth; + m_nHeight = res.iHeight; + m_bFullScreen = fullScreen; ++ m_currentOutput = CSettings::Get().GetString("videoscreen.monitor"); + + return true; + } +@@ -280,19 +243,30 @@ void CWinSystemX11::UpdateResolutions() + { + CWinSystemBase::UpdateResolutions(); + +- + #if defined(HAS_XRANDR) +- if(g_xrandr.Query()) +- { +- XOutput out = g_xrandr.GetCurrentOutput(); +- XMode mode = g_xrandr.GetCurrentMode(out.name); +- m_bIsRotated = out.isRotated; ++ CStdString currentMonitor; ++ int numScreens = XScreenCount(m_dpy); ++ g_xrandr.SetNumScreens(numScreens); ++ if(g_xrandr.Query(true)) ++ { ++ currentMonitor = CSettings::Get().GetString("videoscreen.monitor"); ++ // check if the monitor is connected ++ XOutput *out = g_xrandr.GetOutput(currentMonitor); ++ if (!out) ++ { ++ // choose first output ++ currentMonitor = g_xrandr.GetModes()[0].name; ++ out = g_xrandr.GetOutput(currentMonitor); ++ CSettings::Get().SetString("videoscreen.monitor", currentMonitor); ++ } ++ XMode mode = g_xrandr.GetCurrentMode(currentMonitor); ++ m_bIsRotated = out->isRotated; + if (!m_bIsRotated) +- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz); ++ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), out->screen, mode.w, mode.h, mode.hz); + else +- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz); ++ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), out->screen, mode.h, mode.w, mode.hz); + CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id; +- CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = out.name; ++ CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = currentMonitor; + } + else + #endif +@@ -303,23 +277,22 @@ void CWinSystemX11::UpdateResolutions() + UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, w, h, 0.0); + } + +- + #if defined(HAS_XRANDR) + ++ // erase previous stored modes ++ CDisplaySettings::Get().ClearCustomResolutions(); ++ + CLog::Log(LOGINFO, "Available videomodes (xrandr):"); +- vector::iterator outiter; +- vector outs; +- outs = g_xrandr.GetModes(); +- CLog::Log(LOGINFO, "Number of connected outputs: %"PRIdS"", outs.size()); ++ ++ XOutput *out = g_xrandr.GetOutput(currentMonitor); + string modename = ""; + +- for (outiter = outs.begin() ; outiter != outs.end() ; outiter++) ++ if (out != NULL) + { +- XOutput out = *outiter; + vector::iterator modeiter; +- CLog::Log(LOGINFO, "Output '%s' has %"PRIdS" modes", out.name.c_str(), out.modes.size()); ++ CLog::Log(LOGINFO, "Output '%s' has %"PRIdS" modes", out->name.c_str(), out->modes.size()); + +- for (modeiter = out.modes.begin() ; modeiter!=out.modes.end() ; modeiter++) ++ for (modeiter = out->modes.begin() ; modeiter!=out->modes.end() ; modeiter++) + { + XMode mode = *modeiter; + CLog::Log(LOGINFO, "ID:%s Name:%s Refresh:%f Width:%d Height:%d", +@@ -339,8 +312,8 @@ void CWinSystemX11::UpdateResolutions() + res.iWidth = mode.h; + res.iHeight = mode.w; + } +- if (mode.h>0 && mode.w>0 && out.hmm>0 && out.wmm>0) +- res.fPixelRatio = ((float)out.wmm/(float)mode.w) / (((float)out.hmm/(float)mode.h)); ++ if (mode.h>0 && mode.w>0 && out->hmm>0 && out->wmm>0) ++ res.fPixelRatio = ((float)out->wmm/(float)mode.w) / (((float)out->hmm/(float)mode.h)); + else + res.fPixelRatio = 1.0f; + +@@ -366,28 +339,19 @@ void CWinSystemX11::UpdateResolutions() + + } + +-void CWinSystemX11::RotateResolutions() ++void CWinSystemX11::GetConnectedOutputs(std::vector *outputs) + { +-#if defined(HAS_XRANDR) +- XOutput out = g_xrandr.GetCurrentOutput(); +- if (out.isRotated == m_bIsRotated) +- return; +- +- for (unsigned int i = 0; i < CDisplaySettings::Get().ResolutionInfoSize(); ++i) ++ vector outs; ++ outs = g_xrandr.GetModes(); ++ for(unsigned int i=0; ipush_back(outs[i].name); + } +- // update desktop resolution +-// int h = g_settings.m_ResInfo[RES_DESKTOP].iHeight; +-// int w = g_settings.m_ResInfo[RES_DESKTOP].iWidth; +-// float hz = g_settings.m_ResInfo[RES_DESKTOP].fRefreshRate; +-// UpdateDesktopResolution(g_settings.m_ResInfo[RES_DESKTOP], 0, w, h, hz); +- +- m_bIsRotated = out.isRotated; ++} + +-#endif ++bool CWinSystemX11::IsCurrentOutput(CStdString output) ++{ ++ return m_currentOutput.Equals(output); + } + + bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) +@@ -417,8 +381,11 @@ bool CWinSystemX11::RefreshGlxContext() + if (m_glContext) + { + CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context"); ++ glFinish(); + glXMakeCurrent(m_dpy, None, NULL); + glXMakeCurrent(m_dpy, m_glWindow, m_glContext); ++ XSync(m_dpy, FALSE); ++ g_Windowing.ResetVSync(); + return true; + } + +@@ -484,6 +451,8 @@ bool CWinSystemX11::RefreshGlxContext() + { + // make this context current + glXMakeCurrent(m_dpy, m_glWindow, m_glContext); ++ g_Windowing.ResetVSync(); ++ XSync(m_dpy, False); + retVal = true; + } + else +@@ -525,24 +494,53 @@ void CWinSystemX11::ResetOSScreensaver() + + void CWinSystemX11::NotifyAppActiveChange(bool bActivated) + { +- if (bActivated && m_bWasFullScreenBeforeMinimize && !g_graphicsContext.IsFullScreenRoot()) ++ if (bActivated && m_bWasFullScreenBeforeMinimize && !m_bFullScreen) ++ { + g_graphicsContext.ToggleFullScreenRoot(); + ++ m_bWasFullScreenBeforeMinimize = false; ++ } + m_minimized = !bActivated; + } + + void CWinSystemX11::NotifyAppFocusChange(bool bGaining) + { + if (bGaining && m_bWasFullScreenBeforeMinimize && !m_bIgnoreNextFocusMessage && +- !g_graphicsContext.IsFullScreenRoot()) ++ !m_bFullScreen) ++ { ++ m_bWasFullScreenBeforeMinimize = false; + g_graphicsContext.ToggleFullScreenRoot(); ++ m_minimized = false; ++ } + if (!bGaining) + m_bIgnoreNextFocusMessage = false; + } + ++void CWinSystemX11::NotifyMouseCoverage(bool covered) ++{ ++ if (!m_bFullScreen) ++ return; ++ ++ if (covered) ++ { ++ int result = -1; ++ while (result != GrabSuccess && result != AlreadyGrabbed) ++ { ++ result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); ++ XbmcThreads::ThreadSleep(100); ++ } ++ XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); ++ } ++ else ++ { ++ XUngrabKeyboard(m_dpy, CurrentTime); ++ XUngrabPointer(m_dpy, CurrentTime); ++ } ++} ++ + bool CWinSystemX11::Minimize() + { +- m_bWasFullScreenBeforeMinimize = g_graphicsContext.IsFullScreenRoot(); ++ m_bWasFullScreenBeforeMinimize = m_bFullScreen; + if (m_bWasFullScreenBeforeMinimize) + { + m_bIgnoreNextFocusMessage = true; +@@ -608,13 +606,46 @@ void CWinSystemX11::CheckDisplayEvents() + void CWinSystemX11::NotifyXRREvent() + { + CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); +- RefreshWindow(); ++ m_windowDirty = true; + +- CSingleLock lock(m_resourceSection); ++ // if external event update resolutions ++ if (!m_bIsInternalXrr) ++ { ++ UpdateResolutions(); ++ } ++ else if (!g_xrandr.Query(true)) ++ { ++ CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); ++ return; ++ } ++ m_bIsInternalXrr = false; + +- // tell any shared resources +- for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) +- (*i)->OnResetDevice(); ++ CStdString currentOutput = CSettings::Get().GetString("videoscreen.monitor"); ++ XOutput *out = g_xrandr.GetOutput(currentOutput); ++ XMode mode = g_xrandr.GetCurrentMode(currentOutput); ++ ++ RESOLUTION_INFO res; ++ unsigned int i; ++ bool found(false); ++ for (i = RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); ++i) ++ { ++ if (CDisplaySettings::Get().GetResolutionInfo(i).strId == mode.id) ++ { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ { ++ CLog::Log(LOGERROR, "CWinSystemX11::RefreshWindow - could not find resolution"); ++ i = RES_DESKTOP; ++ } ++ ++ if (g_graphicsContext.IsFullScreenRoot()) ++ g_graphicsContext.SetVideoResolution((RESOLUTION)i, true); ++ else ++ g_graphicsContext.SetVideoResolution(RES_WINDOW, true); + + } + +@@ -667,14 +698,14 @@ bool CWinSystemX11::EnableFrameLimiter() + return m_minimized; + } + +-bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) ++bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStdString &output) + { + bool changeWindow = false; + bool changeSize = false; + bool mouseActive = false; + float mouseX, mouseY; + +- if (m_glWindow && (m_bFullScreen != fullscreen)) ++ if (m_glWindow && ((m_bFullScreen != fullscreen) || !m_currentOutput.Equals(output) || m_windowDirty)) + { + mouseActive = g_Mouse.IsActive(); + if (mouseActive) +@@ -696,6 +727,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) + else + mouseActive = false; + } ++ OnLostDevice(); + DestroyWindow(); + } + +@@ -717,7 +749,11 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) + XSetWindowAttributes swa; + XVisualInfo *vi; + +- vi = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), att); ++ XOutput *out = g_xrandr.GetOutput(output); ++ if (!out) ++ out = g_xrandr.GetOutput(m_currentOutput); ++ m_nScreen = out->screen; ++ vi = glXChooseVisual(m_dpy, m_nScreen, att); + cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone); + + int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen)); +@@ -733,7 +769,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) + unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask; + + m_glWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen), +- 0, 0, width, height, 0, vi->depth, ++ out->x, out->y, width, height, 0, vi->depth, + InputOutput, vi->visual, + mask, &swa); + +@@ -804,14 +840,19 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen) + if (fullscreen) + { + int result = -1; +- while (result != GrabSuccess) ++ while (result != GrabSuccess && result != AlreadyGrabbed) + { +- result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, m_glWindow, None, CurrentTime); ++ result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + XbmcThreads::ThreadSleep(100); + } + XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); +- + } ++ CSingleLock lock(m_resourceSection); ++ // tell any shared resources ++ for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) ++ (*i)->OnResetDevice(); ++ ++ m_windowDirty = false; + } + return true; + } +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 4175aab..94584ab 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -67,15 +67,16 @@ public: + Display* GetDisplay() { return m_dpy; } + GLXWindow GetWindow() { return m_glWindow; } + GLXContext GetGlxContext() { return m_glContext; } +- void RefreshWindow(); + void NotifyXRREvent(); ++ void GetConnectedOutputs(std::vector *outputs); ++ bool IsCurrentOutput(CStdString output); ++ void NotifyMouseCoverage(bool covered); + + protected: + bool RefreshGlxContext(); + void CheckDisplayEvents(); + void OnLostDevice(); +- bool SetWindow(int width, int height, bool fullscreen); +- void RotateResolutions(); ++ bool SetWindow(int width, int height, bool fullscreen, const CStdString &output); + + Window m_glWindow; + GLXContext m_glContext; +@@ -90,6 +91,9 @@ protected: + CCriticalSection m_resourceSection; + std::vector m_resources; + uint64_t m_dpyLostTime; ++ CStdString m_currentOutput; ++ bool m_windowDirty; ++ bool m_bIsInternalXrr; + + private: + bool IsSuitableVisual(XVisualInfo *vInfo); +-- +1.9.1 + + +From 42b6e1775d61778a57119471091900998ddf6d37 Mon Sep 17 00:00:00 2001 +From: FernetMenta +Date: Thu, 5 Jul 2012 11:36:32 +0200 +Subject: [PATCH 17/96] X11: remove all DefaultScreen and RootWindow macros + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 6 +++--- + xbmc/windowing/X11/WinSystemX11.h | 1 + + xbmc/windowing/X11/WinSystemX11GL.cpp | 2 +- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 5e86772..c4fa17c 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -271,7 +271,7 @@ void CWinSystemX11::UpdateResolutions() + else + #endif + { +- int x11screen = DefaultScreen(m_dpy); ++ int x11screen = m_nScreen; + int w = DisplayWidth(m_dpy, x11screen); + int h = DisplayHeight(m_dpy, x11screen); + UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, w, h, 0.0); +@@ -393,7 +393,7 @@ bool CWinSystemX11::RefreshGlxContext() + XVisualInfo *visuals; + XVisualInfo *vInfo = NULL; + int availableVisuals = 0; +- vMask.screen = DefaultScreen(m_dpy); ++ vMask.screen = m_nScreen; + XWindowAttributes winAttr; + + /* Assume a depth of 24 in case the below calls to XGetWindowAttributes() +@@ -547,7 +547,7 @@ bool CWinSystemX11::Minimize() + g_graphicsContext.ToggleFullScreenRoot(); + } + +- XIconifyWindow(m_dpy, m_glWindow, DefaultScreen(m_dpy)); ++ XIconifyWindow(m_dpy, m_glWindow, m_nScreen); + + m_minimized = true; + return true; +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 94584ab..2bcaf52 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -49,6 +49,7 @@ public: + virtual bool SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays); + virtual void UpdateResolutions(); + virtual int GetNumScreens() { return 1; } ++ virtual int GetCurrentScreen() { return m_nScreen; } + virtual void ShowOSMouse(bool show); + virtual void ResetOSScreensaver(); + virtual bool EnableFrameLimiter(); +diff --git a/xbmc/windowing/X11/WinSystemX11GL.cpp b/xbmc/windowing/X11/WinSystemX11GL.cpp +index 6383754..21e7dc5 100644 +--- a/xbmc/windowing/X11/WinSystemX11GL.cpp ++++ b/xbmc/windowing/X11/WinSystemX11GL.cpp +@@ -167,7 +167,7 @@ bool CWinSystemX11GL::CreateNewWindow(const CStdString& name, bool fullScreen, R + return false; + + m_glxext = " "; +- m_glxext += (const char*)glXQueryExtensionsString(m_dpy, DefaultScreen(m_dpy)); ++ m_glxext += (const char*)glXQueryExtensionsString(m_dpy, m_nScreen); + m_glxext += " "; + + CLog::Log(LOGDEBUG, "GLX_EXTENSIONS:%s", m_glxext.c_str()); +-- +1.9.1 + + +From 227a92bca30d905570f4827cef6102b0ba5f1022 Mon Sep 17 00:00:00 2001 +From: FernetMenta +Date: Thu, 5 Jul 2012 11:45:22 +0200 +Subject: [PATCH 18/96] X11: remove all DefaultScreen and RootWindow macros + (VideoRefClock) + +Note this is on a separate display connection. +--- + xbmc/video/VideoReferenceClock.cpp | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp +index 0b3950a..ca43b5a 100644 +--- a/xbmc/video/VideoReferenceClock.cpp ++++ b/xbmc/video/VideoReferenceClock.cpp +@@ -271,7 +271,7 @@ bool CVideoReferenceClock::SetupGLX() + } + + bool ExtensionFound = false; +- istringstream Extensions(glXQueryExtensionsString(m_Dpy, DefaultScreen(m_Dpy))); ++ istringstream Extensions(glXQueryExtensionsString(m_Dpy, g_Windowing.GetCurrentScreen())); + string ExtensionStr; + + while (!ExtensionFound) +@@ -297,7 +297,7 @@ bool CVideoReferenceClock::SetupGLX() + m_bIsATI = true; + } + +- m_vInfo = glXChooseVisual(m_Dpy, DefaultScreen(m_Dpy), singleBufferAttributes); ++ m_vInfo = glXChooseVisual(m_Dpy, g_Windowing.GetCurrentScreen(), singleBufferAttributes); + if (!m_vInfo) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXChooseVisual returned NULL"); +@@ -308,15 +308,16 @@ bool CVideoReferenceClock::SetupGLX() + { + Swa.border_pixel = 0; + Swa.event_mask = StructureNotifyMask; +- Swa.colormap = XCreateColormap(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), m_vInfo->visual, AllocNone ); ++ Swa.colormap = XCreateColormap(m_Dpy, g_Windowing.GetWindow(), m_vInfo->visual, AllocNone ); + SwaMask = CWBorderPixel | CWColormap | CWEventMask; + +- m_Window = XCreateWindow(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), 0, 0, 256, 256, 0, ++ m_Window = XCreateWindow(m_Dpy, g_Windowing.GetWindow(), 0, 0, 256, 256, 0, + m_vInfo->depth, InputOutput, m_vInfo->visual, SwaMask, &Swa); + } + else + { +- m_pixmap = XCreatePixmap(m_Dpy, DefaultRootWindow(m_Dpy), 256, 256, m_vInfo->depth); ++ Window window = g_Windowing.GetWindow(); ++ m_pixmap = XCreatePixmap(m_Dpy, window, 256, 256, m_vInfo->depth); + if (!m_pixmap) + { + CLog::Log(LOGDEBUG, "CVideoReferenceClock: unable to create pixmap"); +@@ -383,7 +384,7 @@ bool CVideoReferenceClock::SetupGLX() + + //set up receiving of RandR events, we'll get one when the refreshrate changes + XRRQueryExtension(m_Dpy, &m_RREventBase, &ReturnV); +- XRRSelectInput(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen), RRScreenChangeNotifyMask); ++ XRRSelectInput(m_Dpy, g_Windowing.GetWindow(), RRScreenChangeNotifyMask); + + UpdateRefreshrate(true); //forced refreshrate update + m_MissedVblanks = 0; +@@ -518,7 +519,7 @@ int CVideoReferenceClock::GetRandRRate() + int RefreshRate; + XRRScreenConfiguration *CurrInfo; + +- CurrInfo = XRRGetScreenInfo(m_Dpy, RootWindow(m_Dpy, m_vInfo->screen)); ++ CurrInfo = XRRGetScreenInfo(m_Dpy, g_Windowing.GetWindow()); + RefreshRate = XRRConfigCurrentRate(CurrInfo); + XRRFreeScreenConfigInfo(CurrInfo); + +-- +1.9.1 + + +From 9244c0ac286705cc5e8577138b219a25db3bdda3 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Wed, 20 Jun 2012 17:37:11 +0200 +Subject: [PATCH 19/96] X11: recreate gl context after output has changed + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 24 ++++++++++++++---------- + xbmc/windowing/X11/WinSystemX11.h | 1 + + xbmc/windowing/X11/WinSystemX11GL.cpp | 9 +++++++++ + 3 files changed, 24 insertions(+), 10 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index c4fa17c..f2fd18d 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -172,7 +172,6 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n + return false; + } + +- RefreshGlxContext(); + m_nWidth = newWidth; + m_nHeight = newHeight; + m_bFullScreen = false; +@@ -223,14 +222,13 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + OnLostDevice(); + m_bIsInternalXrr = true; + g_xrandr.SetMode(out, mode); ++ return true; + } + #endif + + if (!SetWindow(res.iWidth, res.iHeight, fullScreen, CSettings::Get().GetString("videoscreen.monitor"))) + return false; + +- RefreshGlxContext(); +- + m_nWidth = res.iWidth; + m_nHeight = res.iHeight; + m_bFullScreen = fullScreen; +@@ -381,11 +379,8 @@ bool CWinSystemX11::RefreshGlxContext() + if (m_glContext) + { + CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context"); +- glFinish(); + glXMakeCurrent(m_dpy, None, NULL); + glXMakeCurrent(m_dpy, m_glWindow, m_glContext); +- XSync(m_dpy, FALSE); +- g_Windowing.ResetVSync(); + return true; + } + +@@ -445,14 +440,14 @@ bool CWinSystemX11::RefreshGlxContext() + { + glXMakeCurrent(m_dpy, None, NULL); + glXDestroyContext(m_dpy, m_glContext); ++ XSync(m_dpy, FALSE); ++ m_newGlContext = true; + } + + if ((m_glContext = glXCreateContext(m_dpy, vInfo, NULL, True))) + { + // make this context current + glXMakeCurrent(m_dpy, m_glWindow, m_glContext); +- g_Windowing.ResetVSync(); +- XSync(m_dpy, False); + retVal = true; + } + else +@@ -729,6 +724,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + } + OnLostDevice(); + DestroyWindow(); ++ m_windowDirty = true; + } + + // create main window +@@ -847,13 +843,21 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + } + XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); + } ++ ++ CDirtyRegionList dr; ++ RefreshGlxContext(); ++ XSync(m_dpy, FALSE); ++ g_graphicsContext.Clear(0); ++ g_graphicsContext.Flip(dr); ++ g_Windowing.ResetVSync(); ++ m_windowDirty = false; ++ + CSingleLock lock(m_resourceSection); + // tell any shared resources + for (vector::iterator i = m_resources.begin(); i != m_resources.end(); i++) + (*i)->OnResetDevice(); +- +- m_windowDirty = false; + } ++ + return true; + } + +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 2bcaf52..9666cc3 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -95,6 +95,7 @@ protected: + CStdString m_currentOutput; + bool m_windowDirty; + bool m_bIsInternalXrr; ++ bool m_newGlContext; + + private: + bool IsSuitableVisual(XVisualInfo *vInfo); +diff --git a/xbmc/windowing/X11/WinSystemX11GL.cpp b/xbmc/windowing/X11/WinSystemX11GL.cpp +index 21e7dc5..8e68d5d 100644 +--- a/xbmc/windowing/X11/WinSystemX11GL.cpp ++++ b/xbmc/windowing/X11/WinSystemX11GL.cpp +@@ -24,6 +24,7 @@ + #include "WinSystemX11GL.h" + #include "utils/log.h" + #include "utils/StringUtils.h" ++#include "Application.h" + + CWinSystemX11GL::CWinSystemX11GL() + { +@@ -197,17 +198,25 @@ bool CWinSystemX11GL::CreateNewWindow(const CStdString& name, bool fullScreen, R + + bool CWinSystemX11GL::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) + { ++ m_newGlContext = false; + CWinSystemX11::ResizeWindow(newWidth, newHeight, newLeft, newTop); + CRenderSystemGL::ResetRenderSystem(newWidth, newHeight, false, 0); + ++ if (m_newGlContext) ++ g_application.ReloadSkin(); ++ + return true; + } + + bool CWinSystemX11GL::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays) + { ++ m_newGlContext = false; + CWinSystemX11::SetFullScreen(fullScreen, res, blankOtherDisplays); + CRenderSystemGL::ResetRenderSystem(res.iWidth, res.iHeight, fullScreen, res.fRefreshRate); + ++ if (m_newGlContext) ++ g_application.ReloadSkin(); ++ + return true; + } + +-- +1.9.1 + + +From b3587cc41599e6bd73bd54a58f59118d1edfced4 Mon Sep 17 00:00:00 2001 +From: FernetMenta +Date: Thu, 5 Jul 2012 12:06:25 +0200 +Subject: [PATCH 20/96] X11: hook video reference clock in windowing + +--- + xbmc/video/VideoReferenceClock.cpp | 71 +++++++++++++++++++++++++++----------- + xbmc/video/VideoReferenceClock.h | 13 ++++++- + 2 files changed, 63 insertions(+), 21 deletions(-) + +diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp +index ca43b5a..0ddf102 100644 +--- a/xbmc/video/VideoReferenceClock.cpp ++++ b/xbmc/video/VideoReferenceClock.cpp +@@ -136,12 +136,23 @@ CVideoReferenceClock::CVideoReferenceClock() : CThread("VideoReferenceClock") + m_Context = NULL; + m_pixmap = None; + m_glPixmap = None; +- m_RREventBase = 0; + m_UseNvSettings = true; + m_bIsATI = false; + #endif + } + ++CVideoReferenceClock::~CVideoReferenceClock() ++{ ++#if defined(HAS_GLX) ++ // some ATI voodoo, if we don't close the display, we crash on exit ++ if (m_Dpy) ++ { ++ XCloseDisplay(m_Dpy); ++ m_Dpy = NULL; ++ } ++#endif ++} ++ + void CVideoReferenceClock::Process() + { + bool SetupSuccess = false; +@@ -152,6 +163,10 @@ void CVideoReferenceClock::Process() + m_D3dCallback.Reset(); + g_Windowing.Register(&m_D3dCallback); + #endif ++#if defined(HAS_GLX) && defined(HAS_XRANDR) ++ g_Windowing.Register(this); ++ m_xrrEvent = false; ++#endif + + while(!m_bStop) + { +@@ -212,6 +227,16 @@ void CVideoReferenceClock::Process() + //clean up the vblank clock + #if defined(HAS_GLX) && defined(HAS_XRANDR) + CleanupGLX(); ++ if (m_xrrEvent) ++ { ++ m_releaseEvent.Set(); ++ while (!m_bStop) ++ { ++ if (m_resetEvent.WaitMSec(100)) ++ break; ++ } ++ m_xrrEvent = false; ++ } + #elif defined(TARGET_WINDOWS) && defined(HAS_DX) + CleanupD3D(); + #elif defined(TARGET_DARWIN) +@@ -223,6 +248,9 @@ void CVideoReferenceClock::Process() + #if defined(TARGET_WINDOWS) && defined(HAS_DX) + g_Windowing.Unregister(&m_D3dCallback); + #endif ++#if defined(HAS_GLX) ++ g_Windowing.Unregister(this); ++#endif + } + + bool CVideoReferenceClock::WaitStarted(int MSecs) +@@ -232,6 +260,24 @@ bool CVideoReferenceClock::WaitStarted(int MSecs) + } + + #if defined(HAS_GLX) && defined(HAS_XRANDR) ++ ++void CVideoReferenceClock::OnLostDevice() ++{ ++ if (!m_xrrEvent) ++ { ++ m_releaseEvent.Reset(); ++ m_resetEvent.Reset(); ++ m_xrrEvent = true; ++ m_releaseEvent.Wait(); ++ } ++} ++ ++void CVideoReferenceClock::OnResetDevice() ++{ ++ m_xrrEvent = false; ++ m_resetEvent.Set(); ++} ++ + bool CVideoReferenceClock::SetupGLX() + { + int singleBufferAttributes[] = { +@@ -382,10 +428,6 @@ bool CVideoReferenceClock::SetupGLX() + return false; + } + +- //set up receiving of RandR events, we'll get one when the refreshrate changes +- XRRQueryExtension(m_Dpy, &m_RREventBase, &ReturnV); +- XRRSelectInput(m_Dpy, g_Windowing.GetWindow(), RRScreenChangeNotifyMask); +- + UpdateRefreshrate(true); //forced refreshrate update + m_MissedVblanks = 0; + +@@ -586,6 +628,9 @@ void CVideoReferenceClock::RunGLX() + + while(!m_bStop) + { ++ if (m_xrrEvent) ++ return; ++ + //wait for the next vblank + if (!m_bIsATI) + { +@@ -649,7 +694,6 @@ void CVideoReferenceClock::RunGLX() + UpdateClock((int)(VblankCount - PrevVblankCount), true); + SingleLock.Leave(); + SendVblankSignal(); +- UpdateRefreshrate(); + IsReset = false; + } + else if (!m_bStop) +@@ -1186,23 +1230,10 @@ bool CVideoReferenceClock::UpdateRefreshrate(bool Forced /*= false*/) + + #if defined(HAS_GLX) && defined(HAS_XRANDR) + +- //check for RandR events +- bool GotEvent = Forced || m_RefreshChanged == 2; +- XEvent Event; +- while (XCheckTypedEvent(m_Dpy, m_RREventBase + RRScreenChangeNotify, &Event)) +- { +- if (Event.type == m_RREventBase + RRScreenChangeNotify) +- { +- CLog::Log(LOGDEBUG, "CVideoReferenceClock: Received RandR event %i", Event.type); +- GotEvent = true; +- } +- XRRUpdateConfiguration(&Event); +- } +- + if (!Forced) + m_RefreshChanged = 0; + +- if (!GotEvent) //refreshrate did not change ++ if (!Forced) //refreshrate did not change + return false; + + //the refreshrate can be wrong on nvidia drivers, so read it from nvidia-settings when it's available +diff --git a/xbmc/video/VideoReferenceClock.h b/xbmc/video/VideoReferenceClock.h +index dd65a1b..afd71fc 100644 +--- a/xbmc/video/VideoReferenceClock.h ++++ b/xbmc/video/VideoReferenceClock.h +@@ -30,6 +30,7 @@ + #include + #include + #include ++ #include "guilib/DispResource.h" + #elif defined(TARGET_WINDOWS) && defined(HAS_DX) + #include + #include "guilib/D3DResource.h" +@@ -56,9 +57,13 @@ class CD3DCallback : public ID3DResource + #endif + + class CVideoReferenceClock : public CThread ++#if defined(HAS_GLX) && defined(HAS_XRANDR) ++ ,public IDispResource ++#endif + { + public: + CVideoReferenceClock(); ++ virtual ~CVideoReferenceClock(); + + int64_t GetTime(bool interpolated = true); + int64_t GetFrequency(); +@@ -75,6 +80,11 @@ class CVideoReferenceClock : public CThread + void VblankHandler(int64_t nowtime, double fps); + #endif + ++#if defined(HAS_GLX) && defined(HAS_XRANDR) ++ virtual void OnLostDevice(); ++ virtual void OnResetDevice(); ++#endif ++ + private: + void Process(); + bool UpdateRefreshrate(bool Forced = false); +@@ -121,7 +131,8 @@ class CVideoReferenceClock : public CThread + GLXContext m_Context; + Pixmap m_pixmap; + GLXPixmap m_glPixmap; +- int m_RREventBase; ++ bool m_xrrEvent; ++ CEvent m_releaseEvent, m_resetEvent; + + bool m_UseNvSettings; + bool m_bIsATI; +-- +1.9.1 + + +From e9fe9c2f0dae615075a9173e5c4a0c6ef6700097 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Thu, 21 Jun 2012 17:26:51 +0200 +Subject: [PATCH 21/96] X11: fix video calibrations + +--- + xbmc/windowing/WinSystem.h | 1 + + xbmc/windowing/X11/WinSystemX11.cpp | 36 +++++++++++++++++++++++++++++++++++- + xbmc/windowing/X11/WinSystemX11.h | 1 + + 3 files changed, 37 insertions(+), 1 deletion(-) + +diff --git a/xbmc/windowing/WinSystem.h b/xbmc/windowing/WinSystem.h +index 00a2d24..c0db210 100644 +--- a/xbmc/windowing/WinSystem.h ++++ b/xbmc/windowing/WinSystem.h +@@ -103,6 +103,7 @@ public: + std::vector ScreenResolutions(int screen, float refreshrate); + std::vector RefreshRates(int screen, int width, int height, uint32_t dwFlags); + REFRESHRATE DefaultRefreshRate(int screen, std::vector rates); ++ virtual bool HasCalibration(const RESOLUTION_INFO &resInfo) { return true; }; + + // text input interface + virtual void EnableTextInput(bool bEnable) {} +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index f2fd18d..c4152c8 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -320,7 +320,7 @@ void CWinSystemX11::UpdateResolutions() + res.strMode = StringUtils::Format("%s: %s @ %.2fHz", out.name.c_str(), mode.name.c_str(), mode.hz); + res.strOutput = out.name; + res.strId = mode.id; +- res.iSubtitles = (int)(0.95*mode.h); ++ res.iSubtitles = (int)(0.965*mode.h); + res.fRefreshRate = mode.hz; + res.bFullScreen = true; + +@@ -333,8 +333,42 @@ void CWinSystemX11::UpdateResolutions() + CDisplaySettings::Get().AddResolutionInfo(res); + } + } ++ CDisplaySettings::Get().ApplyCalibrations(); + #endif ++} ++ ++bool CWinSystemX11::HasCalibration(const RESOLUTION_INFO &resInfo) ++{ ++ XOutput *out = g_xrandr.GetOutput(m_currentOutput); ++ ++ // keep calibrations done on a not connected output ++ if (!out->name.Equals(resInfo.strOutput)) ++ return true; ++ ++ // keep calibrations not updated with resolution data ++ if (resInfo.iWidth == 0) ++ return true; ++ ++ float fPixRatio; ++ if (resInfo.iHeight>0 && resInfo.iWidth>0 && out->hmm>0 && out->wmm>0) ++ fPixRatio = ((float)out->wmm/(float)resInfo.iWidth) / (((float)out->hmm/(float)resInfo.iHeight)); ++ else ++ fPixRatio = 1.0f; + ++ if (resInfo.Overscan.left != 0) ++ return true; ++ if (resInfo.Overscan.top != 0) ++ return true; ++ if (resInfo.Overscan.right != resInfo.iWidth) ++ return true; ++ if (resInfo.Overscan.bottom != resInfo.iHeight) ++ return true; ++ if (resInfo.fPixelRatio != fPixRatio) ++ return true; ++ if (resInfo.iSubtitles != (int)(0.965*resInfo.iHeight)) ++ return true; ++ ++ return false; + } + + void CWinSystemX11::GetConnectedOutputs(std::vector *outputs) +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 9666cc3..5b52d6c 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -63,6 +63,7 @@ public: + virtual bool Show(bool raise = true); + virtual void Register(IDispResource *resource); + virtual void Unregister(IDispResource *resource); ++ virtual bool HasCalibration(const RESOLUTION_INFO &resInfo); + + // Local to WinSystemX11 only + Display* GetDisplay() { return m_dpy; } +-- +1.9.1 + + +From 1d80e75563853da38393b91d38c1c3b449db0bd9 Mon Sep 17 00:00:00 2001 +From: FernetMenta +Date: Thu, 5 Jul 2012 12:00:26 +0200 +Subject: [PATCH 22/96] X11: deactivate screen saver on startup + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 29 +++++++++++++++++++++++++++++ + xbmc/windowing/X11/WinSystemX11.h | 1 + + 2 files changed, 30 insertions(+) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index c4152c8..b76b229 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -521,6 +521,33 @@ void CWinSystemX11::ResetOSScreensaver() + } + } + ++void CWinSystemX11::EnableSystemScreenSaver(bool bEnable) ++{ ++ if (!m_dpy) ++ return; ++ ++ if (bEnable) ++ XForceScreenSaver(m_dpy, ScreenSaverActive); ++ else ++ { ++ Window root_return, child_return; ++ int root_x_return, root_y_return; ++ int win_x_return, win_y_return; ++ unsigned int mask_return; ++ bool isInWin = XQueryPointer(m_dpy, RootWindow(m_dpy, m_nScreen), &root_return, &child_return, ++ &root_x_return, &root_y_return, ++ &win_x_return, &win_y_return, ++ &mask_return); ++ ++ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, root_x_return+300, root_y_return+300); ++ XSync(m_dpy, FALSE); ++ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, 0, 0); ++ XSync(m_dpy, FALSE); ++ XWarpPointer(m_dpy, None, RootWindow(m_dpy, m_nScreen), 0, 0, 0, 0, root_x_return, root_y_return); ++ XSync(m_dpy, FALSE); ++ } ++} ++ + void CWinSystemX11::NotifyAppActiveChange(bool bActivated) + { + if (bActivated && m_bWasFullScreenBeforeMinimize && !m_bFullScreen) +@@ -764,6 +791,8 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + // create main window + if (!m_glWindow) + { ++ EnableSystemScreenSaver(false); ++ + GLint att[] = + { + GLX_RGBA, +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 5b52d6c..b2bd5a0 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -53,6 +53,7 @@ public: + virtual void ShowOSMouse(bool show); + virtual void ResetOSScreensaver(); + virtual bool EnableFrameLimiter(); ++ virtual void EnableSystemScreenSaver(bool bEnable); + + virtual void NotifyAppActiveChange(bool bActivated); + virtual void NotifyAppFocusChange(bool bGaining); +-- +1.9.1 + + +From 2cd34f3f2ac582f71a042902d777b890234c7f93 Mon Sep 17 00:00:00 2001 +From: FernetMenta +Date: Thu, 5 Jul 2012 12:10:09 +0200 +Subject: [PATCH 23/96] X11: change method of going full-screen + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index b76b229..869baa8 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -38,6 +38,7 @@ + #include "utils/StringUtils.h" + #include "settings/Settings.h" + #include "windowing/WindowingFactory.h" ++#include + + #if defined(HAS_XRANDR) + #include +@@ -816,7 +817,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone); + + int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen)); +- swa.override_redirect = fullscreen ? True : False; ++ swa.override_redirect = False; + swa.border_pixel = fullscreen ? 0 : 5; + swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; + swa.colormap = cmap; +@@ -832,6 +833,12 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + InputOutput, vi->visual, + mask, &swa); + ++ if (fullscreen) ++ { ++ Atom fs = XInternAtom(m_dpy, "_NET_WM_STATE_FULLSCREEN", True); ++ XChangeProperty(m_dpy, m_glWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1); ++ } ++ + // define invisible cursor + Pixmap bitmapNoData; + XColor black; +-- +1.9.1 + + +From 7ea6a5a0a6040f2277a510fc8752d7ca134e1f07 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Thu, 28 Jun 2012 19:12:39 +0200 +Subject: [PATCH 24/96] X11: reset key repeat and key modifier on focus lost + and gain + +--- + xbmc/windowing/WinEventsX11.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index d98f12f..743aca9 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -368,6 +368,8 @@ bool CWinEventsX11Imp::MessagePump() + if (WinEvents->m_xic) + XSetICFocus(WinEvents->m_xic); + g_application.m_AppFocused = true; ++ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); ++ WinEvents->m_keymodState = 0; + if (serial == xevent.xfocus.serial) + break; + g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); +@@ -379,6 +381,7 @@ bool CWinEventsX11Imp::MessagePump() + if (WinEvents->m_xic) + XUnsetICFocus(WinEvents->m_xic); + g_application.m_AppFocused = false; ++ memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); + g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); + serial = xevent.xfocus.serial; + break; +-- +1.9.1 + + +From d3c56229317ecf38e4b3957f82669281a722482f Mon Sep 17 00:00:00 2001 +From: Joakim Plate +Date: Thu, 5 Jul 2012 14:18:46 +0200 +Subject: [PATCH 25/96] X11: replace custom utf8 to unicode with charset + convertor (squash to x11 events) + +--- + xbmc/windowing/WinEventsX11.cpp | 119 ++++------------------------------------ + xbmc/windowing/WinEventsX11.h | 2 - + 2 files changed, 11 insertions(+), 110 deletions(-) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index 743aca9..6b98e67 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -32,6 +32,7 @@ + #include "X11/keysymdef.h" + #include "X11/XF86keysym.h" + #include "utils/log.h" ++#include "utils/CharsetConverter.h" + #include "guilib/GUIWindowManager.h" + #include "input/MouseStat.h" + +@@ -170,7 +171,6 @@ CWinEventsX11Imp::CWinEventsX11Imp() + m_display = 0; + m_window = 0; + m_keybuf = 0; +- m_utf16buf = 0; + } + + CWinEventsX11Imp::~CWinEventsX11Imp() +@@ -181,12 +181,6 @@ CWinEventsX11Imp::~CWinEventsX11Imp() + m_keybuf = 0; + } + +- if (m_utf16buf) +- { +- free(m_utf16buf); +- m_utf16buf = 0; +- } +- + if (m_xic) + { + XUnsetICFocus(m_xic); +@@ -212,7 +206,6 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win) + WinEvents->m_display = dpy; + WinEvents->m_window = win; + WinEvents->m_keybuf = (char*)malloc(32*sizeof(char)); +- WinEvents->m_utf16buf = (uint16_t*)malloc(32*sizeof(uint16_t)); + WinEvents->m_keymodState = 0; + WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + WinEvents->m_structureChanged = false; +@@ -442,8 +435,6 @@ bool CWinEventsX11Imp::MessagePump() + } + + Status status; +- int utf16size; +- int utf16length; + int len; + len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, + WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf), +@@ -462,36 +453,29 @@ bool CWinEventsX11Imp::MessagePump() + case XLookupChars: + case XLookupBoth: + { +- if (len == 0) +- break; +- utf16size = len * sizeof(uint16_t); +- if (utf16size > sizeof(WinEvents->m_utf16buf)) +- { +- WinEvents->m_utf16buf = (uint16_t *)realloc(WinEvents->m_utf16buf,utf16size); +- if (WinEvents->m_utf16buf == NULL) +- { +- break; +- } +- } +- utf16length = Utf8ToUnicode(WinEvents->m_keybuf, len, WinEvents->m_utf16buf, utf16size); +- if (utf16length < 0) ++ CStdString data(WinEvents->m_keybuf, len); ++ CStdStringW keys; ++ g_charsetConverter.utf8ToW(data, keys, false); ++ ++ if (keys.length() == 0) + { + break; + } +- for (unsigned int i = 0; i < utf16length - 1; i++) ++ ++ for (unsigned int i = 0; i < keys.length() - 1; i++) + { + newEvent.key.keysym.sym = XBMCK_UNKNOWN; +- newEvent.key.keysym.unicode = WinEvents->m_utf16buf[i]; ++ newEvent.key.keysym.unicode = keys[i]; + newEvent.key.state = xevent.xkey.state; + newEvent.key.type = xevent.xkey.type; + ret |= ProcessKey(newEvent, 500); + } +- if (utf16length > 0) ++ if (keys.length() > 0) + { + newEvent.key.keysym.scancode = xevent.xkey.keycode; + xkeysym = XLookupKeysym(&xevent.xkey, 0); + newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); +- newEvent.key.keysym.unicode = WinEvents->m_utf16buf[utf16length - 1]; ++ newEvent.key.keysym.unicode = keys[keys.length() - 1]; + newEvent.key.state = xevent.xkey.state; + newEvent.key.type = xevent.xkey.type; + +@@ -762,87 +746,6 @@ bool CWinEventsX11Imp::ProcessKeyRepeat() + return false; + } + +-int CWinEventsX11Imp::Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength) +-{ +- // p moves over the output buffer. max_ptr points to the next to the last slot of the buffer. +- uint16_t *p = utf16; +- uint16_t const *const maxPtr = utf16 + utf16MaxLength; +- +- // end_of_input points to the last byte of input as opposed to the next to the last byte. +- char const *const endOfInput = utf8 + utf8Length - 1; +- +- while (utf8 <= endOfInput) +- { +- unsigned char const c = *utf8; +- if (p >= maxPtr) +- { +- //No more output space. +- return -1; +- } +- if (c < 0x80) +- { +- //One byte ASCII. +- *p++ = c; +- utf8 += 1; +- } +- else if (c < 0xC0) +- { +- // Follower byte without preceding leader bytes. +- return -1; +- } +- // 11 bits +- else if (c < 0xE0) +- { +- // Two byte sequence. We need one follower byte. +- if (endOfInput - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0)) +- { +- return -1; +- } +- *p++ = (uint16_t)(((c & 0x1F) << 6) + (utf8[1] & 0x3F)); +- utf8 += 2; +- } +- // 16 bis +- else if (c < 0xF0) +- { +- // Three byte sequence. We need two follower byte. +- if (endOfInput - utf8 < 2 || ((utf8[1] ^ 0x80) & 0xC0) || ((utf8[2] ^ 0x80) & 0xC0)) +- { +- return -1; +- } +- *p++ = (uint16_t)(((c & 0xF) << 12) + ((utf8[1] & 0x3F) << 6) + (utf8[2] & 0x3F)); +- utf8 += 3; +- } +- // 21 bits +- else if (c < 0xF8) +- { +- int plane; +- // Four byte sequence. We need three follower bytes. +- if (endOfInput - utf8 < 3 || ((utf8[1] ^ 0x80) & 0xC0) || +- ((utf8[2] ^ 0x80) & 0xC0) || ((utf8[3] ^ 0x80) & 0xC0)) +- { +- return -1; +- } +- uint32_t unicode = ((c & 0x7) << 18) + ((utf8[1] & 0x3F) << 12) + +- ((utf8[2] & 0x3F) << 6) + (utf8[3] & 0x3F); +- utf8 += 4; +- CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); +- } +- // 26 bits +- else if (c < 0xFC) +- { +- CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); +- utf8 += 5; +- } +- // 31 bit +- else +- { +- CLog::Log(LOGERROR, "CWinEventsX11::Utf8ToUnicode: 4 byte unicode not supported"); +- utf8 += 6; +- } +- } +- return p - utf16; +-} +- + XBMCKey CWinEventsX11Imp::LookupXbmcKeySym(KeySym keysym) + { + // try direct mapping first +diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h +index a412f32..9a8a912 100644 +--- a/xbmc/windowing/WinEventsX11.h ++++ b/xbmc/windowing/WinEventsX11.h +@@ -46,7 +46,6 @@ public: + static size_t GetQueueSize(); + + protected: +- static int Utf8ToUnicode(const char *utf8, const int utf8Length, uint16_t *utf16, const int utf16MaxLength); + static XBMCKey LookupXbmcKeySym(KeySym keysym); + static bool ProcessKey(XBMC_Event &event, int repeatDelay); + static bool ProcessKeyRepeat(); +@@ -56,7 +55,6 @@ protected: + Window m_window; + Atom m_wmDeleteMessage; + char *m_keybuf; +- uint16_t *m_utf16buf; + XIM m_xim; + XIC m_xic; + XBMC_Event m_lastKey; +-- +1.9.1 + + +From 17f4e2e5c33d0574e944cba76a561e618051551a Mon Sep 17 00:00:00 2001 +From: Joakim Plate +Date: Thu, 5 Jul 2012 14:23:54 +0200 +Subject: [PATCH 26/96] X11: fixed invalid usage of sizeof() (squash into x11 + changes) + +--- + xbmc/windowing/WinEventsX11.cpp | 11 +++++++---- + xbmc/windowing/WinEventsX11.h | 1 + + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index 6b98e67..a62521f 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -171,6 +171,7 @@ CWinEventsX11Imp::CWinEventsX11Imp() + m_display = 0; + m_window = 0; + m_keybuf = 0; ++ m_keybuf_len = 0; + } + + CWinEventsX11Imp::~CWinEventsX11Imp() +@@ -205,7 +206,8 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win) + WinEvents = new CWinEventsX11Imp(); + WinEvents->m_display = dpy; + WinEvents->m_window = win; +- WinEvents->m_keybuf = (char*)malloc(32*sizeof(char)); ++ WinEvents->m_keybuf_len = 32*sizeof(char); ++ WinEvents->m_keybuf = (char*)malloc(WinEvents->m_keybuf_len); + WinEvents->m_keymodState = 0; + WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + WinEvents->m_structureChanged = false; +@@ -437,13 +439,14 @@ bool CWinEventsX11Imp::MessagePump() + Status status; + int len; + len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, +- WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf), ++ WinEvents->m_keybuf, WinEvents->m_keybuf_len, + &xkeysym, &status); + if (status == XBufferOverflow) + { +- WinEvents->m_keybuf = (char*)realloc(WinEvents->m_keybuf, len*sizeof(char)); ++ WinEvents->m_keybuf_len = len; ++ WinEvents->m_keybuf = (char*)realloc(WinEvents->m_keybuf, WinEvents->m_keybuf_len); + len = Xutf8LookupString(WinEvents->m_xic, &xevent.xkey, +- WinEvents->m_keybuf, sizeof(WinEvents->m_keybuf), ++ WinEvents->m_keybuf, WinEvents->m_keybuf_len, + &xkeysym, &status); + } + switch (status) +diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h +index 9a8a912..c69169c 100644 +--- a/xbmc/windowing/WinEventsX11.h ++++ b/xbmc/windowing/WinEventsX11.h +@@ -55,6 +55,7 @@ protected: + Window m_window; + Atom m_wmDeleteMessage; + char *m_keybuf; ++ size_t m_keybuf_len; + XIM m_xim; + XIC m_xic; + XBMC_Event m_lastKey; +-- +1.9.1 + + +From 90af49c63d9469c783629881e1846979594a8ff2 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sat, 9 Jun 2012 18:23:53 +0200 +Subject: [PATCH 27/96] add missing keys to xbmc keytable + +--- + xbmc/input/XBMC_keytable.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xbmc/input/XBMC_keytable.cpp b/xbmc/input/XBMC_keytable.cpp +index d57f4d3..b807897 100644 +--- a/xbmc/input/XBMC_keytable.cpp ++++ b/xbmc/input/XBMC_keytable.cpp +@@ -180,6 +180,8 @@ static const XBMCKEYTABLE XBMCKeyTable[] = + , { XBMCK_LAUNCH_APP2, 0, 0, XBMCVK_LAUNCH_APP2, "launch_app2_pc_icon" } + , { XBMCK_LAUNCH_FILE_BROWSER, 0, 0, XBMCVK_LAUNCH_FILE_BROWSER, "launch_file_browser" } + , { XBMCK_LAUNCH_MEDIA_CENTER, 0, 0, XBMCVK_LAUNCH_MEDIA_CENTER, "launch_media_center" } ++, { XBMCK_PLAY, 0, 0, XBMCVK_MEDIA_PLAY_PAUSE, "play_pause" } ++, { XBMCK_STOP, 0, 0, XBMCVK_MEDIA_STOP, "stop" } + + // Function keys + , { XBMCK_F1, 0, 0, XBMCVK_F1, "f1"} +-- +1.9.1 + + +From 049f7e527bf12b7322c7343f01e6f08a2415fe8e Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Fri, 16 Mar 2012 15:57:51 +0100 +Subject: [PATCH 28/96] videorefclock: temp deactivate of nv settings + +--- + xbmc/video/VideoReferenceClock.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp +index 0ddf102..3ae7107 100644 +--- a/xbmc/video/VideoReferenceClock.cpp ++++ b/xbmc/video/VideoReferenceClock.cpp +@@ -136,7 +136,7 @@ CVideoReferenceClock::CVideoReferenceClock() : CThread("VideoReferenceClock") + m_Context = NULL; + m_pixmap = None; + m_glPixmap = None; +- m_UseNvSettings = true; ++ m_UseNvSettings = false; + m_bIsATI = false; + #endif + } +-- +1.9.1 + + +From 23b43d522cb691b21ef572f3ee003b152fea4b3a Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 20 Aug 2012 09:09:09 +0200 +Subject: [PATCH 29/96] videorefclock: ask graphics context for refresh rate + +--- + xbmc/video/VideoReferenceClock.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp +index 3ae7107..27bebde 100644 +--- a/xbmc/video/VideoReferenceClock.cpp ++++ b/xbmc/video/VideoReferenceClock.cpp +@@ -31,6 +31,7 @@ + #include + #include + #include "windowing/WindowingFactory.h" ++ #include "guilib/GraphicContext.h" + #define NVSETTINGSCMD "nvidia-settings -nt -q RefreshRate3" + #elif defined(TARGET_DARWIN_OSX) + #include +@@ -1254,7 +1255,7 @@ bool CVideoReferenceClock::UpdateRefreshrate(bool Forced /*= false*/) + } + + CSingleLock SingleLock(m_CritSection); +- m_RefreshRate = GetRandRRate(); ++ m_RefreshRate = MathUtils::round_int(g_graphicsContext.GetFPS()); + + CLog::Log(LOGDEBUG, "CVideoReferenceClock: Detected refreshrate: %i hertz", (int)m_RefreshRate); + +-- +1.9.1 + + +From 263d964167a2eaf52713f513ef8cc4c912241e3b Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 9 Jul 2012 14:00:18 +0200 +Subject: [PATCH 30/96] X11: fix icon texture after + cc5ed3c2474084ebc0373a3046410e6f766e03f4 + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 43 ++++++++++++++++++++++--------------- + 1 file changed, 26 insertions(+), 17 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 869baa8..bfe3797 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -874,22 +874,24 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + if (!fullscreen) + { + CreateIconPixmap(); +- XWMHints wm_hints; +- XClassHint class_hints; ++ XWMHints *wm_hints; + XTextProperty windowName, iconName; + std::string titleString = "XBMC Media Center"; + char *title = (char*)titleString.c_str(); + + XStringListToTextProperty(&title, 1, &windowName); + XStringListToTextProperty(&title, 1, &iconName); +- wm_hints.initial_state = NormalState; +- wm_hints.input = True; +- wm_hints.icon_pixmap = m_icon; +- wm_hints.flags = StateHint | IconPixmapHint | InputHint; + ++ wm_hints = XAllocWMHints(); ++ wm_hints->initial_state = NormalState; ++ wm_hints->icon_pixmap = m_icon; ++ wm_hints->flags = StateHint | IconPixmapHint; ++ ++ XSync(m_dpy,False); + XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName, +- NULL, 0, NULL, &wm_hints, ++ NULL, 0, NULL, wm_hints, + NULL); ++ XFree(wm_hints); + + // register interest in the delete window message + Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False); +@@ -974,16 +976,21 @@ bool CWinSystemX11::CreateIconPixmap() + gRatio = vis->green_mask / 255.0; + bRatio = vis->blue_mask / 255.0; + +- CTexture iconTexture; +- iconTexture.LoadFromFile("special://xbmc/media/icon256x256.png"); +- buf = iconTexture.GetPixels(); ++ CBaseTexture *iconTexture = CBaseTexture::LoadFromFile("special://xbmc/media/icon256x256.png"); ++ ++ if (!iconTexture) ++ return false; + +- numBufBytes = iconTexture.GetWidth() * iconTexture.GetHeight() * 4; ++ buf = iconTexture->GetPixels(); ++ ++ numBufBytes = iconTexture->GetWidth() * iconTexture->GetHeight() * 4; ++ int wid = iconTexture->GetWidth(); ++ int hi = iconTexture->GetHeight(); + + if (depth>=24) +- numNewBufBytes = (4 * (iconTexture.GetWidth() * iconTexture.GetHeight())); ++ numNewBufBytes = (4 * (iconTexture->GetWidth() * iconTexture->GetHeight())); + else +- numNewBufBytes = (2 * (iconTexture.GetWidth() * iconTexture.GetHeight())); ++ numNewBufBytes = (2 * (iconTexture->GetWidth() * iconTexture->GetHeight())); + + newBuf = (uint32_t*)malloc(numNewBufBytes); + if (!newBuf) +@@ -992,11 +999,11 @@ bool CWinSystemX11::CreateIconPixmap() + return false; + } + +- for (i=0; iGetHeight();++i) + { +- for (j=0; jGetWidth();++j) + { +- unsigned int pos = i*iconTexture.GetPitch()+j*4; ++ unsigned int pos = i*iconTexture->GetPitch()+j*4; + unsigned int r, g, b; + r = (buf[pos+2] * rRatio); + g = (buf[pos+1] * gRatio); +@@ -1009,7 +1016,7 @@ bool CWinSystemX11::CreateIconPixmap() + } + } + img = XCreateImage(m_dpy, vis, depth,ZPixmap, 0, (char *)newBuf, +- iconTexture.GetWidth(), iconTexture.GetHeight(), ++ iconTexture->GetWidth(), iconTexture->GetHeight(), + (depth>=24)?32:16, 0); + if (!img) + { +@@ -1047,6 +1054,8 @@ bool CWinSystemX11::CreateIconPixmap() + XFreeGC(m_dpy, gc); + XDestroyImage(img); // this also frees newBuf + ++ delete iconTexture; ++ + return true; + } + +-- +1.9.1 + + +From 648af86aa01874210d8ea6732cf7cef4f8e466e0 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Tue, 10 Jul 2012 11:14:12 +0200 +Subject: [PATCH 31/96] X11: check for window manager + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 74 ++++++++++++++++++++++++++++++++++++- + xbmc/windowing/X11/WinSystemX11.h | 1 + + 2 files changed, 73 insertions(+), 2 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index bfe3797..af82061 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -816,8 +816,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + vi = glXChooseVisual(m_dpy, m_nScreen, att); + cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone); + ++ bool hasWM = HasWindowManager(); ++ + int def_vis = (vi->visual == DefaultVisual(m_dpy, vi->screen)); +- swa.override_redirect = False; ++ swa.override_redirect = hasWM ? False : True; + swa.border_pixel = fullscreen ? 0 : 5; + swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; + swa.colormap = cmap; +@@ -833,7 +835,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + InputOutput, vi->visual, + mask, &swa); + +- if (fullscreen) ++ if (fullscreen && hasWM) + { + Atom fs = XInternAtom(m_dpy, "_NET_WM_STATE_FULLSCREEN", True); + XChangeProperty(m_dpy, m_glWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1); +@@ -1059,4 +1061,72 @@ bool CWinSystemX11::CreateIconPixmap() + return true; + } + ++bool CWinSystemX11::HasWindowManager() ++{ ++ Window wm_check; ++ unsigned char *data; ++ int status, real_format; ++ Atom real_type, prop; ++ unsigned long items_read, items_left, i; ++ char req = 0; ++ ++ prop = XInternAtom(m_dpy, "_NET_SUPPORTING_WM_CHECK", True); ++ if (prop == None) ++ return false; ++ status = XGetWindowProperty(m_dpy, DefaultRootWindow(m_dpy), prop, ++ 0L, 1L, False, XA_WINDOW, &real_type, &real_format, ++ &items_read, &items_left, &data); ++ if(status != Success || ! items_read) ++ { ++ if(status == Success) ++ XFree(data); ++ return false; ++ } ++ ++ wm_check = ((Window*)data)[0]; ++ XFree(data); ++ ++ status = XGetWindowProperty(m_dpy, wm_check, prop, ++ 0L, 1L, False, XA_WINDOW, &real_type, &real_format, ++ &items_read, &items_left, &data); ++ ++ if(status != Success || !items_read) ++ { ++ if(status == Success) ++ XFree(data); ++ return false; ++ } ++ ++ if(wm_check != ((Window*)data)[0]) ++ { ++ XFree(data); ++ return false; ++ } ++ ++ XFree(data); ++ ++ prop = XInternAtom(m_dpy, "_NET_WM_NAME", True); ++ if (prop == None) ++ { ++ CLog::Log(LOGDEBUG,"Window Manager Name: "); ++ return true; ++ } ++ ++ status = XGetWindowProperty(m_dpy, wm_check, prop, ++ 0L, (~0L), False, AnyPropertyType, &real_type, &real_format, ++ &items_read, &items_left, &data); ++ ++ if(status == Success && items_read) ++ { ++ CLog::Log(LOGDEBUG,"Window Manager Name: %s", data); ++ } ++ else ++ CLog::Log(LOGDEBUG,"Window Manager Name: "); ++ ++ if(status == Success) ++ XFree(data); ++ ++ return true; ++} ++ + #endif +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index b2bd5a0..3e62cd8 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -103,6 +103,7 @@ private: + bool IsSuitableVisual(XVisualInfo *vInfo); + static int XErrorHandler(Display* dpy, XErrorEvent* error); + bool CreateIconPixmap(); ++ bool HasWindowManager(); + + CStopWatch m_screensaverReset; + }; +-- +1.9.1 + + +From f4ed19185a171a1967c30999e119abd661654102 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Thu, 12 Jul 2012 11:11:47 +0200 +Subject: [PATCH 32/96] X11: dont set window on xrandr if no mode available + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index af82061..4f33c68 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -665,16 +665,17 @@ void CWinSystemX11::NotifyXRREvent() + CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); + m_windowDirty = true; + ++ if (!g_xrandr.Query(true)) ++ { ++ CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); ++ return; ++ } ++ + // if external event update resolutions + if (!m_bIsInternalXrr) + { + UpdateResolutions(); + } +- else if (!g_xrandr.Query(true)) +- { +- CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); +- return; +- } + m_bIsInternalXrr = false; + + CStdString currentOutput = CSettings::Get().GetString("videoscreen.monitor"); +-- +1.9.1 + + +From d174bc51e0e31ec6666bdc0479a4c948efc5bd63 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Thu, 26 Jul 2012 09:34:28 +0200 +Subject: [PATCH 33/96] X11: fix crash after a resolution change on startup + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 4f33c68..bc4e963 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -223,7 +223,8 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + OnLostDevice(); + m_bIsInternalXrr = true; + g_xrandr.SetMode(out, mode); +- return true; ++ if (m_glWindow) ++ return true; + } + #endif + +-- +1.9.1 + + +From b685749adb461364ad288593d1e62e4927c439c8 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sat, 15 Sep 2012 18:27:29 +0200 +Subject: [PATCH 34/96] X11: lock graphics context in NotifyXRREvent + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index bc4e963..57a8d20 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -666,6 +666,8 @@ void CWinSystemX11::NotifyXRREvent() + CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); + m_windowDirty = true; + ++ CSingleLock lock(g_graphicsContext); ++ + if (!g_xrandr.Query(true)) + { + CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); +-- +1.9.1 + + +From 9ac337cb7338a191037bb3e05599ce1f9de3419b Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 20 Aug 2012 16:06:39 +0200 +Subject: [PATCH 35/96] dvdplayer: observe pts counter overflow + +--- + .../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 197 ++++++++++++++++++++- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 4 + + 2 files changed, 200 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index 4ce1b87..afa3024 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -18,7 +18,6 @@ + * + */ + +-#include "system.h" + #ifndef __STDC_CONSTANT_MACROS + #define __STDC_CONSTANT_MACROS + #endif +@@ -26,6 +25,7 @@ + #define __STDC_LIMIT_MACROS + #endif + #ifdef TARGET_POSIX ++#include "system.h" + #include "stdint.h" + #endif + #include "DVDDemuxFFmpeg.h" +@@ -489,6 +489,9 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) + + CreateStreams(); + ++ m_bPtsWrapChecked = false; ++ m_bPtsWrap = false; ++ + return true; + } + +@@ -634,6 +637,12 @@ double CDVDDemuxFFmpeg::ConvertTimestamp(int64_t pts, int den, int num) + if (pts == (int64_t)AV_NOPTS_VALUE) + return DVD_NOPTS_VALUE; + ++ if (m_bPtsWrap) ++ { ++ if (pts < m_iStartTime && pts < m_iEndTime) ++ pts += m_iMaxTime; ++ } ++ + // do calculations in floats as they can easily overflow otherwise + // we don't care for having a completly exact timestamp anyway + double timestamp = (double)pts * num / den; +@@ -773,6 +782,24 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + m_pkt.pkt.pts = AV_NOPTS_VALUE; + } + ++ if (!m_bPtsWrapChecked && m_pFormatContext->iformat->flags & AVFMT_TS_DISCONT) ++ { ++ int defaultStream = av_find_default_stream_index(m_pFormatContext); ++ int64_t duration = m_pFormatContext->streams[defaultStream]->duration * 1.5; ++ m_iMaxTime = 1LL<streams[defaultStream]->pts_wrap_bits; ++ m_iStartTime = m_pFormatContext->streams[defaultStream]->start_time; ++ if (m_iStartTime != DVD_NOPTS_VALUE) ++ { ++ m_iEndTime = (m_iStartTime + duration) & ~m_iMaxTime; ++ if (m_iEndTime < m_iStartTime) ++ { ++ CLog::Log(LOGNOTICE,"CDVDDemuxFFmpeg::Read - file contains pts overflow"); ++ m_bPtsWrap = true; ++ } ++ } ++ m_bPtsWrapChecked = true; ++ } ++ + // copy contents into our own packet + pPacket->iSize = m_pkt.pkt.size; + +@@ -906,7 +933,16 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts) + ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, seek_pts, backwords ? AVSEEK_FLAG_BACKWARD : 0); + + if(ret >= 0) ++ { + UpdateCurrentPTS(); ++ ++ // seek may fail silently on streams which allow discontinuity ++ // if current timestamp is way off asume a pts overflow and try bisect seek ++ if (m_bPtsWrap && fabs(time - m_iCurrentPts/1000) > 10000) ++ { ++ ret = SeekTimeDiscont(seek_pts, backwords) ? 1 : -1; ++ } ++ } + } + + if(m_iCurrentPts == DVD_NOPTS_VALUE) +@@ -925,6 +961,165 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts) + return (ret >= 0); + } + ++bool CDVDDemuxFFmpeg::SeekTimeDiscont(int64_t pts, bool backwards) ++{ ++ // this code is taken from ffmpeg function ff_gen_search ++ // it is modified to assume a pts overflow if timestamp < start_time ++ if (!m_pFormatContext->iformat->read_timestamp) ++ return false; ++ ++ int defaultStream = av_find_default_stream_index(m_pFormatContext); ++ ++ if (defaultStream < 0) ++ { ++ return false; ++ } ++ ++ // timestamp for default must be expressed in AV_TIME_BASE units ++ pts = av_rescale_rnd(pts, m_pFormatContext->streams[defaultStream]->time_base.den, ++ AV_TIME_BASE * (int64_t)m_pFormatContext->streams[defaultStream]->time_base.num, ++ AV_ROUND_NEAR_INF); ++ ++ int64_t pos, pos_min, pos_max, pos_limit, ts, ts_min, ts_max; ++ int64_t start_pos, filesize; ++ int no_change; ++ ++ pos_min = m_pFormatContext->data_offset; ++ ts_min = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream, ++ &pos_min, INT64_MAX); ++ if (ts_min == AV_NOPTS_VALUE) ++ return false; ++ ++ if(ts_min >= pts) ++ { ++ pos = pos_min; ++ return true; ++ } ++ ++ int step= 1024; ++ filesize = m_pInput->GetLength(); ++ pos_max = filesize - 1; ++ do ++ { ++ pos_max -= step; ++ ts_max = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream, ++ &pos_max, pos_max + step); ++ step += step; ++ }while (ts_max == AV_NOPTS_VALUE && pos_max >= step); ++ ++ if (ts_max == AV_NOPTS_VALUE) ++ return false; ++ ++ if (ts_max < m_iStartTime && ts_max < m_iEndTime) ++ ts_max += m_iMaxTime; ++ ++ for(;;) ++ { ++ int64_t tmp_pos = pos_max + 1; ++ int64_t tmp_ts = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream, ++ &tmp_pos, INT64_MAX); ++ if(tmp_ts == AV_NOPTS_VALUE) ++ break; ++ ++ if (tmp_ts < m_iStartTime && tmp_ts < m_iEndTime) ++ tmp_ts += m_iMaxTime; ++ ++ ts_max = tmp_ts; ++ pos_max = tmp_pos; ++ if (tmp_pos >= filesize) ++ break; ++ } ++ pos_limit = pos_max; ++ ++ if(ts_max <= pts) ++ { ++ bool ret = SeekByte(pos_max); ++ if (ret) ++ { ++ m_iCurrentPts = ConvertTimestamp(ts_max, m_pFormatContext->streams[defaultStream]->time_base.den, ++ m_pFormatContext->streams[defaultStream]->time_base.num); ++ } ++ return ret; ++ } ++ ++ if(ts_min > ts_max) ++ { ++ return false; ++ } ++ else if (ts_min == ts_max) ++ { ++ pos_limit = pos_min; ++ } ++ ++ no_change=0; ++ while (pos_min < pos_limit) ++ { ++ if (no_change == 0) ++ { ++ int64_t approximate_keyframe_distance= pos_max - pos_limit; ++ // interpolate position (better than dichotomy) ++ pos = av_rescale_rnd(pts - ts_min, pos_max - pos_min, ++ ts_max - ts_min, AV_ROUND_NEAR_INF) ++ + pos_min - approximate_keyframe_distance; ++ } ++ else if (no_change == 1) ++ { ++ // bisection, if interpolation failed to change min or max pos last time ++ pos = (pos_min + pos_limit) >> 1; ++ } ++ else ++ { ++ /* linear search if bisection failed, can only happen if there ++ are very few or no keyframes between min/max */ ++ pos = pos_min; ++ } ++ if (pos <= pos_min) ++ pos= pos_min + 1; ++ else if (pos > pos_limit) ++ pos= pos_limit; ++ start_pos = pos; ++ ++ ts = m_pFormatContext->iformat->read_timestamp(m_pFormatContext, defaultStream, ++ &pos, INT64_MAX); ++ if (pos == pos_max) ++ no_change++; ++ else ++ no_change=0; ++ ++ if (ts == AV_NOPTS_VALUE) ++ { ++ return false; ++ } ++ ++ if (ts < m_iStartTime && ts < m_iEndTime) ++ ts += m_iMaxTime; ++ ++ if (pts <= ts) ++ { ++ pos_limit = start_pos - 1; ++ pos_max = pos; ++ ts_max = ts; ++ } ++ if (pts >= ts) ++ { ++ pos_min = pos; ++ ts_min = ts; ++ } ++ } ++ ++ pos = (backwards) ? pos_min : pos_max; ++ ts = (backwards) ? ts_min : ts_max; ++ ++ bool ret = SeekByte(pos); ++ if (ret) ++ { ++ m_iCurrentPts = ConvertTimestamp(ts, m_pFormatContext->streams[defaultStream]->time_base.den, ++ m_pFormatContext->streams[defaultStream]->time_base.num); ++ } ++ ++ return ret; ++} ++ + bool CDVDDemuxFFmpeg::SeekByte(int64_t pos) + { + CSingleLock lock(m_critSection); +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +index aef5ab1..35abbdf 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +@@ -100,6 +100,7 @@ public: + DemuxPacket* Read(); + + bool SeekTime(int time, bool backwords = false, double* startpts = NULL); ++ bool SeekTimeDiscont(int64_t pts, bool backwards); + bool SeekByte(int64_t pos); + int GetStreamLength(); + CDemuxStream* GetStream(int iStreamId); +@@ -158,5 +159,8 @@ protected: + AVPacket pkt; // packet ffmpeg returned + int result; // result from av_read_packet + }m_pkt; ++ ++ bool m_bPtsWrap, m_bPtsWrapChecked; ++ int64_t m_iStartTime, m_iMaxTime, m_iEndTime; + }; + +-- +1.9.1 + + +From edec7054fd66168c26cb16d624139a85d0feeb82 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Tue, 2 Oct 2012 13:02:10 +0200 +Subject: [PATCH 36/96] dvdplayer: avoid short screen flicker caused by + unnecessary reconfigure of renderer + +--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 9c36bdb..322a581 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -1054,13 +1054,16 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) + + #ifdef HAS_VIDEO_PLAYBACK + double config_framerate = m_bFpsInvalid ? 0.0 : m_fFrameRate; ++ double render_framerate = g_graphicsContext.GetFPS(); ++ if (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") == ADJUST_REFRESHRATE_OFF) ++ render_framerate = config_framerate; + /* check so that our format or aspect has changed. if it has, reconfigure renderer */ + if (!g_renderManager.IsConfigured() + || ( m_output.width != pPicture->iWidth ) + || ( m_output.height != pPicture->iHeight ) + || ( m_output.dwidth != pPicture->iDisplayWidth ) + || ( m_output.dheight != pPicture->iDisplayHeight ) +- || ( m_output.framerate != config_framerate ) ++ || (!m_bFpsInvalid && fmod(m_output.framerate, config_framerate) != 0.0 && render_framerate != config_framerate) + || ( m_output.color_format != (unsigned int)pPicture->format ) + || ( m_output.extended_format != pPicture->extended_format ) + || ( m_output.color_matrix != pPicture->color_matrix && pPicture->color_matrix != 0 ) // don't reconfigure on unspecified +-- +1.9.1 + + +From aea69ca48e5ae5888feec63cd9ce8f16c971f5cf Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Thu, 11 Oct 2012 12:05:50 +0200 +Subject: [PATCH 37/96] vdpau: advanced settings for auto deinterlacing + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 8 ++++---- + xbmc/settings/AdvancedSettings.cpp | 4 ++++ + xbmc/settings/AdvancedSettings.h | 2 ++ + 3 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +index b4d2d38..cd72cc6 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +@@ -1987,10 +1987,10 @@ EINTERLACEMETHOD CMixer::GetDeinterlacingMethod(bool log /* = false */) + if (method == VS_INTERLACEMETHOD_AUTO) + { + int deint = -1; +-// if (m_config.outHeight >= 720) +-// deint = g_advancedSettings.m_videoVDPAUdeintHD; +-// else +-// deint = g_advancedSettings.m_videoVDPAUdeintSD; ++ if (m_config.outHeight >= 720) ++ deint = g_advancedSettings.m_videoVDPAUdeintHD; ++ else ++ deint = g_advancedSettings.m_videoVDPAUdeintSD; + + if (deint != -1) + { +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index eff43dd..7532914 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -163,6 +163,8 @@ void CAdvancedSettings::Initialize() + m_videoAutoScaleMaxFps = 30.0f; + m_videoDisableBackgroundDeinterlace = false; + m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect ++ m_videoVDPAUdeintHD = -1; ++ m_videoVDPAUdeintSD = -1; + m_videoVDPAUtelecine = false; + m_videoVDPAUdeintSkipChromaHD = false; + m_DXVACheckCompatibility = false; +@@ -600,6 +602,8 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) + XMLUtils::GetBoolean(pElement,"disablehi10pmultithreading",m_videoDisableHi10pMultithreading); + XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace); + XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1); ++ XMLUtils::GetInt(pElement,"vdpauHDdeint",m_videoVDPAUdeintHD); ++ XMLUtils::GetInt(pElement,"vdpauSDdeint",m_videoVDPAUdeintSD); + XMLUtils::GetBoolean(pElement,"vdpauInvTelecine",m_videoVDPAUtelecine); + XMLUtils::GetBoolean(pElement,"vdpauHDdeintSkipChroma",m_videoVDPAUdeintSkipChromaHD); + +diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h +index 3995f35..c43351d 100644 +--- a/xbmc/settings/AdvancedSettings.h ++++ b/xbmc/settings/AdvancedSettings.h +@@ -160,6 +160,8 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler + int m_videoPercentSeekBackwardBig; + CStdString m_videoPPFFmpegDeint; + CStdString m_videoPPFFmpegPostProc; ++ int m_videoVDPAUdeintHD; ++ int m_videoVDPAUdeintSD; + bool m_videoVDPAUtelecine; + bool m_videoVDPAUdeintSkipChromaHD; + bool m_musicUseTimeSeeking; +-- +1.9.1 + + +From 075908a1dae8d28b939fe754686105b2106a97d1 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Fri, 2 Nov 2012 13:20:03 +0100 +Subject: [PATCH 38/96] player: fix rewind + +--- + xbmc/cores/dvdplayer/DVDMessage.h | 5 ++++- + xbmc/cores/dvdplayer/DVDPlayer.cpp | 30 +++++++++++++++++++----------- + xbmc/cores/dvdplayer/DVDPlayer.h | 7 ++++--- + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 4 +++- + xbmc/cores/dvdplayer/DVDPlayerVideo.h | 1 + + 5 files changed, 31 insertions(+), 16 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDMessage.h b/xbmc/cores/dvdplayer/DVDMessage.h +index 2ea8b8f..e8274f9 100644 +--- a/xbmc/cores/dvdplayer/DVDMessage.h ++++ b/xbmc/cores/dvdplayer/DVDMessage.h +@@ -220,7 +220,7 @@ private: + class CDVDMsgPlayerSeek : public CDVDMsg + { + public: +- CDVDMsgPlayerSeek(int time, bool backward, bool flush = true, bool accurate = true, bool restore = true, bool trickplay = false) ++ CDVDMsgPlayerSeek(int time, bool backward, bool flush = true, bool accurate = true, bool restore = true, bool trickplay = false, bool sync = true) + : CDVDMsg(PLAYER_SEEK) + , m_time(time) + , m_backward(backward) +@@ -228,6 +228,7 @@ public: + , m_accurate(accurate) + , m_restore(restore) + , m_trickplay(trickplay) ++ , m_sync(sync) + {} + int GetTime() { return m_time; } + bool GetBackward() { return m_backward; } +@@ -235,6 +236,7 @@ public: + bool GetAccurate() { return m_accurate; } + bool GetRestore() { return m_restore; } + bool GetTrickPlay() { return m_trickplay; } ++ bool GetSync() { return m_sync; } + private: + int m_time; + bool m_backward; +@@ -242,6 +244,7 @@ private: + bool m_accurate; + bool m_restore; // whether to restore any EDL cut time + bool m_trickplay; ++ bool m_sync; + }; + + class CDVDMsgPlayerSeekChapter : public CDVDMsg +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp +index 15e490c..2474b39 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp +@@ -1634,11 +1634,13 @@ void CDVDPlayer::HandlePlaySpeed() + } + else if (m_CurrentVideo.id >= 0 + && (m_CurrentVideo.inited == true || GetPlaySpeed() < 0) // allow rewind at end of file +- && m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts() ++ && (m_SpeedState.lastpts != m_dvdPlayerVideo.GetCurrentPts() || fabs(m_SpeedState.lastabstime - CDVDClock::GetAbsoluteClock()) > DVD_MSEC_TO_TIME(200)) ++ && (m_dvdPlayerVideo.GetCurrentPts() != DVD_NOPTS_VALUE) + && m_SpeedState.lasttime != GetTime()) + { + m_SpeedState.lastpts = m_dvdPlayerVideo.GetCurrentPts(); + m_SpeedState.lasttime = GetTime(); ++ m_SpeedState.lastabstime = CDVDClock::GetAbsoluteClock(); + // check how much off clock video is when ff/rw:ing + // a problem here is that seeking isn't very accurate + // and since the clock will be resynced after seek +@@ -1657,7 +1659,7 @@ void CDVDPlayer::HandlePlaySpeed() + { + CLog::Log(LOGDEBUG, "CDVDPlayer::Process - Seeking to catch up"); + int64_t iTime = (int64_t)DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset + 500000.0 * m_playSpeed / DVD_PLAYSPEED_NORMAL); +- m_messenger.Put(new CDVDMsgPlayerSeek(iTime, (GetPlaySpeed() < 0), true, false, false, true)); ++ m_messenger.Put(new CDVDMsgPlayerSeek(iTime, (GetPlaySpeed() < 0), true, false, false, true, false)); + } + } + } +@@ -2143,7 +2145,7 @@ void CDVDPlayer::HandleMessages() + else + m_StateInput.dts = start; + +- FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate()); ++ FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate(), msg.GetSync()); + } + else + CLog::Log(LOGWARNING, "error while seeking"); +@@ -2279,9 +2281,10 @@ void CDVDPlayer::HandleMessages() + double offset; + offset = CDVDClock::GetAbsoluteClock() - m_State.timestamp; + offset *= m_playSpeed / DVD_PLAYSPEED_NORMAL; ++ offset = DVD_TIME_TO_MSEC(offset); + if(offset > 1000) offset = 1000; + if(offset < -1000) offset = -1000; +- m_State.time += DVD_TIME_TO_MSEC(offset); ++ m_State.time += offset; + m_State.timestamp = CDVDClock::GetAbsoluteClock(); + } + +@@ -2297,7 +2300,8 @@ void CDVDPlayer::HandleMessages() + // do a seek after rewind, clock is not in sync with current pts + if (m_playSpeed < 0 && speed >= 0) + { +- m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), true, true, true)); ++ int64_t iTime = (int64_t)DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset); ++ m_messenger.Put(new CDVDMsgPlayerSeek(iTime, true, true, false, false, true)); + } + + // if playspeed is different then DVD_PLAYSPEED_NORMAL or DVD_PLAYSPEED_PAUSE +@@ -3294,7 +3298,7 @@ bool CDVDPlayer::CloseTeletextStream(bool bWaitForBuffers) + return true; + } + +-void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate) ++void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate, bool sync) + { + double startpts; + if(accurate) +@@ -3306,19 +3310,23 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate) + if(startpts != DVD_NOPTS_VALUE) + startpts -= m_offset_pts; + +- m_CurrentAudio.inited = false; ++ if (sync) ++ { ++ m_CurrentAudio.inited = false; ++ m_CurrentVideo.inited = false; ++ m_CurrentSubtitle.inited = false; ++ m_CurrentTeletext.inited = false; ++ } ++ + m_CurrentAudio.dts = DVD_NOPTS_VALUE; + m_CurrentAudio.startpts = startpts; + +- m_CurrentVideo.inited = false; + m_CurrentVideo.dts = DVD_NOPTS_VALUE; + m_CurrentVideo.startpts = startpts; + +- m_CurrentSubtitle.inited = false; + m_CurrentSubtitle.dts = DVD_NOPTS_VALUE; + m_CurrentSubtitle.startpts = startpts; + +- m_CurrentTeletext.inited = false; + m_CurrentTeletext.dts = DVD_NOPTS_VALUE; + m_CurrentTeletext.startpts = startpts; + +@@ -3362,7 +3370,7 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate) + m_CurrentTeletext.started = false; + } + +- if(pts != DVD_NOPTS_VALUE) ++ if(pts != DVD_NOPTS_VALUE && sync) + m_clock.Discontinuity(pts); + UpdatePlayState(0); + +diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h +index e2a836b..6ecaf3f 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayer.h ++++ b/xbmc/cores/dvdplayer/DVDPlayer.h +@@ -308,7 +308,7 @@ protected: + bool GetCachingTimes(double& play_left, double& cache_left, double& file_offset); + + +- void FlushBuffers(bool queued, double pts = DVD_NOPTS_VALUE, bool accurate = true); ++ void FlushBuffers(bool queued, double pts = DVD_NOPTS_VALUE, bool accurate = true, bool sync = true); + + void HandleMessages(); + void HandlePlaySpeed(); +@@ -357,8 +357,9 @@ protected: + int m_playSpeed; + struct SSpeedState + { +- double lastpts; // holds last display pts during ff/rw operations +- double lasttime; ++ double lastpts; // holds last display pts during ff/rw operations ++ int64_t lasttime; ++ double lastabstime; + } m_SpeedState; + + int m_errorCount; +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 322a581..9c5469b 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -1470,7 +1470,7 @@ double CDVDPlayerVideo::GetCurrentPts() + + if( m_stalled ) + iRenderPts = DVD_NOPTS_VALUE; +- else ++ else if ( m_speed == DVD_PLAYSPEED_NORMAL) + iRenderPts = iRenderPts - max(0.0, iSleepTime); + + return iRenderPts; +@@ -1570,6 +1570,8 @@ int CDVDPlayerVideo::CalcDropRequirement(double pts) + int iSkippedDeint = 0; + int iBufferLevel; + ++ m_droppingStats.m_lastPts = pts; ++ + // get decoder stats + if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iSkippedDeint, interlaced)) + iDecoderPts = pts; +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +index 59c7f09..65dea76 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h +@@ -50,6 +50,7 @@ public: + double m_totalGain; + double m_lastDecoderPts; + double m_lastRenderPts; ++ double m_lastPts; + unsigned int m_lateFrames; + unsigned int m_dropRequests; + }; +-- +1.9.1 + + +From 7070e0502de0d996e39c2a379dea650f773e220e Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Fri, 23 Nov 2012 17:41:12 +0100 +Subject: [PATCH 39/96] xrandr: fix query for multiple screens + +--- + xbmc/windowing/X11/XRandR.cpp | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp +index 4685413..e610150 100644 +--- a/xbmc/windowing/X11/XRandR.cpp ++++ b/xbmc/windowing/X11/XRandR.cpp +@@ -58,12 +58,14 @@ bool CXRandR::Query(bool force) + + m_outputs.clear(); + // query all screens ++ // we are happy if at least one screen returns results ++ bool success = false; + for(unsigned int screennum=0; screennum +Date: Sun, 2 Dec 2012 15:46:55 +0100 +Subject: [PATCH 40/96] X11: add debug log to print out refresh after xrr event + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 57a8d20..a237dc0 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -685,6 +685,12 @@ void CWinSystemX11::NotifyXRREvent() + XOutput *out = g_xrandr.GetOutput(currentOutput); + XMode mode = g_xrandr.GetCurrentMode(currentOutput); + ++ if (out) ++ CLog::Log(LOGDEBUG, "%s - current output: %s, mode: %s, refresh: %.3f", __FUNCTION__ ++ , out->name.c_str(), mode.id.c_str(), mode.hz); ++ else ++ CLog::Log(LOGWARNING, "%s - output name not set", __FUNCTION__); ++ + RESOLUTION_INFO res; + unsigned int i; + bool found(false); +-- +1.9.1 + + +From 0b610b8e1040605b28907f72866a2be58b963a13 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Tue, 11 Dec 2012 11:08:13 +0100 +Subject: [PATCH 41/96] X11: dont call XCloseDisplay on shutdown, it crashes + when powered doen by cec on ATI + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index a237dc0..ab660b1 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -112,7 +112,8 @@ bool CWinSystemX11::DestroyWindowSystem() + //we don't call XCloseDisplay() here, since ati keeps a pointer to our m_dpy + //so instead we just let m_dpy die on exit + // i have seen core dumps on ATI if the display is not closed here +- XCloseDisplay(m_dpy); ++ // crashes when shutting down via cec ++// XCloseDisplay(m_dpy); + } + + // m_SDLSurface is free()'d by SDL_Quit(). +-- +1.9.1 + + +From 1501643dfcda4e8e1c46feade3370964f8f344b9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Gr=C3=A9gory=20Coutant?= +Date: Wed, 12 Dec 2012 19:49:47 +0100 +Subject: [PATCH 42/96] x11: support for multiple x screens + +--- + xbmc/windowing/X11/XRandR.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp +index e610150..5c53574 100644 +--- a/xbmc/windowing/X11/XRandR.cpp ++++ b/xbmc/windowing/X11/XRandR.cpp +@@ -93,7 +93,7 @@ bool CXRandR::Query(bool force, int screennum) + pclose(file); + + TiXmlElement *pRootElement = xmlDoc.RootElement(); +- if (strcasecmp(pRootElement->Value(), "screen") != screennum) ++ if (atoi(pRootElement->Attribute("id")) != screennum) + { + // TODO ERROR + return false; +-- +1.9.1 + + +From 00c856df34e3941787d98d871b9b6d8905717d76 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 24 Dec 2012 16:02:42 +0100 +Subject: [PATCH 43/96] pvr: increase changes counter of stream on stream + change, cosmetics after dd307930d39d92f145a01a16600cd00e01ec39be + +--- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp +index 7d0a732..d066610 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp +@@ -339,9 +339,7 @@ void CDVDDemuxPVRClient::RequestStreams() + if (stm) + { + st = dynamic_cast(stm); +- if (!st +- || (st->codec != (AVCodecID)props.stream[i].iCodecId) +- || (st->iChannels != props.stream[i].iChannels)) ++ if (!st || (st->codec != (AVCodecID)props.stream[i].iCodecId)) + DisposeStream(i); + } + if (!m_streams[i]) +@@ -358,6 +356,7 @@ void CDVDDemuxPVRClient::RequestStreams() + st->iBitsPerSample = props.stream[i].iBitsPerSample; + m_streams[i] = st; + st->m_parser_split = true; ++ st->changes++; + } + else if (props.stream[i].iCodecType == XBMC_CODEC_TYPE_VIDEO) + { +-- +1.9.1 + + +From 3021decc0764c58d5aa8e1d668106527f076343e Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Thu, 17 Jan 2013 16:03:22 +0100 +Subject: [PATCH 44/96] X11: add keymapping for XF86XK_Sleep + +--- + xbmc/windowing/WinEventsX11.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index a62521f..263cb5a 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -143,6 +143,7 @@ static uint32_t SymMappingsX11[][2] = + , {XK_Break, XBMCK_BREAK} + , {XK_Menu, XBMCK_MENU} + , {XF86XK_PowerOff, XBMCK_POWER} ++, {XF86XK_Sleep, XBMCK_SLEEP} + , {XK_EcuSign, XBMCK_EURO} + , {XK_Undo, XBMCK_UNDO} + /* Media keys */ +-- +1.9.1 + + +From 3064c39cb89bc411e235fd4fdc0d82f795c894f7 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Mon, 21 Jan 2013 09:00:19 +0100 +Subject: [PATCH 45/96] X11: remove toggle full screen after resume + +--- + xbmc/powermanagement/PowerManager.cpp | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp +index 590a887..35b5a21 100644 +--- a/xbmc/powermanagement/PowerManager.cpp ++++ b/xbmc/powermanagement/PowerManager.cpp +@@ -268,11 +268,6 @@ void CPowerManager::OnWake() + #if defined(TARGET_WINDOWS) + ShowWindow(g_hWnd,SW_RESTORE); + SetForegroundWindow(g_hWnd); +-#elif !defined(TARGET_DARWIN_OSX) +- // Hack to reclaim focus, thus rehiding system mouse pointer. +- // Surely there's a better way? +- g_graphicsContext.ToggleFullScreenRoot(); +- g_graphicsContext.ToggleFullScreenRoot(); + #endif + } + g_application.ResetScreenSaver(); +-- +1.9.1 + + +From ad652ac8add735a9796acf9545eceba8c1e4d2fe Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Wed, 23 Jan 2013 17:03:02 +0100 +Subject: [PATCH 46/96] xrandr: set screen on mode change command + +--- + xbmc/windowing/X11/XRandR.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp +index 5c53574..4355ef7 100644 +--- a/xbmc/windowing/X11/XRandR.cpp ++++ b/xbmc/windowing/X11/XRandR.cpp +@@ -246,7 +246,7 @@ bool CXRandR::SetMode(XOutput output, XMode mode) + m_currentMode = modeFound.id; + char cmd[255]; + if (getenv("XBMC_BIN_HOME")) +- snprintf(cmd, sizeof(cmd), "%s/xbmc-xrandr --output %s --mode %s", getenv("XBMC_BIN_HOME"), outputFound.name.c_str(), modeFound.id.c_str()); ++ snprintf(cmd, sizeof(cmd), "%s/xbmc-xrandr --screen %d --output %s --mode %s", getenv("XBMC_BIN_HOME"), outputFound.screen, outputFound.name.c_str(), modeFound.id.c_str()); + else + return false; + CLog::Log(LOGINFO, "XRANDR: %s", cmd); +-- +1.9.1 + + +From 10b7c59751e8b809a2fdf5e0c0edd01a2acbc5f7 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Wed, 23 Jan 2013 17:03:39 +0100 +Subject: [PATCH 47/96] X11: recreate glx context when output changes + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 6 +++--- + xbmc/windowing/X11/WinSystemX11.h | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index ab660b1..4329a22 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -409,11 +409,11 @@ bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) + return true; + } + +-bool CWinSystemX11::RefreshGlxContext() ++bool CWinSystemX11::RefreshGlxContext(bool force) + { + bool retVal = false; + +- if (m_glContext) ++ if (m_glContext && !force) + { + CLog::Log(LOGDEBUG, "CWinSystemX11::RefreshGlxContext: refreshing context"); + glXMakeCurrent(m_dpy, None, NULL); +@@ -930,7 +930,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + } + + CDirtyRegionList dr; +- RefreshGlxContext(); ++ RefreshGlxContext(!m_currentOutput.Equals(output)); + XSync(m_dpy, FALSE); + g_graphicsContext.Clear(0); + g_graphicsContext.Flip(dr); +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 3e62cd8..2a1fb41 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -76,7 +76,7 @@ public: + void NotifyMouseCoverage(bool covered); + + protected: +- bool RefreshGlxContext(); ++ bool RefreshGlxContext(bool force); + void CheckDisplayEvents(); + void OnLostDevice(); + bool SetWindow(int width, int height, bool fullscreen, const CStdString &output); +-- +1.9.1 + + +From 353c653d504a568b28cf3e90380c8aeff0629c75 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Fri, 14 Dec 2012 14:19:15 +0100 +Subject: [PATCH 48/96] pvr: do not show selection dialog for a single menu + hook + +--- + xbmc/pvr/addons/PVRClients.cpp | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/xbmc/pvr/addons/PVRClients.cpp b/xbmc/pvr/addons/PVRClients.cpp +index 14c9cde..57b18a5 100644 +--- a/xbmc/pvr/addons/PVRClients.cpp ++++ b/xbmc/pvr/addons/PVRClients.cpp +@@ -733,6 +733,7 @@ void CPVRClients::ProcessMenuHooks(int iClientID, PVR_MENUHOOK_CAT cat, const CF + { + hooks = client->GetMenuHooks(); + std::vector hookIDs; ++ int selection = 0; + + CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); + pDialog->Reset(); +@@ -743,9 +744,11 @@ void CPVRClients::ProcessMenuHooks(int iClientID, PVR_MENUHOOK_CAT cat, const CF + pDialog->Add(client->GetString(hooks->at(i).iLocalizedStringId)); + hookIDs.push_back(i); + } +- pDialog->DoModal(); +- +- int selection = pDialog->GetSelectedLabel(); ++ if (hookIDs.size() > 1) ++ { ++ pDialog->DoModal(); ++ selection = pDialog->GetSelectedLabel(); ++ } + if (selection >= 0) + client->CallMenuHook(hooks->at(hookIDs.at(selection)), item); + } +-- +1.9.1 + + +From 3f1eb64980be5bf9c5676c93e3a99bf107824c25 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sun, 3 Feb 2013 08:17:16 +0100 +Subject: [PATCH 49/96] X11: use default screen parameters if no output + connected + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 55 ++++++++++++++++++++++--------------- + 1 file changed, 33 insertions(+), 22 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 4329a22..2adf8a0 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -207,25 +207,27 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + } + + XMode currmode = g_xrandr.GetCurrentMode(out.name); +- +- // flip h/w when rotated +- if (m_bIsRotated) ++ if (!currmode.name.empty()) + { +- int w = mode.w; +- mode.w = mode.h; +- mode.h = w; +- } ++ // flip h/w when rotated ++ if (m_bIsRotated) ++ { ++ int w = mode.w; ++ mode.w = mode.h; ++ mode.h = w; ++ } + +- // only call xrandr if mode changes +- if (currmode.w != mode.w || currmode.h != mode.h || +- currmode.hz != mode.hz || currmode.id != mode.id) +- { +- CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr"); +- OnLostDevice(); +- m_bIsInternalXrr = true; +- g_xrandr.SetMode(out, mode); +- if (m_glWindow) +- return true; ++ // only call xrandr if mode changes ++ if (currmode.w != mode.w || currmode.h != mode.h || ++ currmode.hz != mode.hz || currmode.id != mode.id) ++ { ++ CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr"); ++ OnLostDevice(); ++ m_bIsInternalXrr = true; ++ g_xrandr.SetMode(out, mode); ++ if (m_glWindow) ++ return true; ++ } + } + #endif + +@@ -272,9 +274,10 @@ void CWinSystemX11::UpdateResolutions() + else + #endif + { +- int x11screen = m_nScreen; +- int w = DisplayWidth(m_dpy, x11screen); +- int h = DisplayHeight(m_dpy, x11screen); ++ CSettings::Get().SetString("videoscreen.monitor", "Default"); ++ m_nScreen = DefaultScreen(m_dpy); ++ int w = DisplayWidth(m_dpy, m_nScreen); ++ int h = DisplayHeight(m_dpy, m_nScreen); + UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, w, h, 0.0); + } + +@@ -819,11 +822,19 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + Colormap cmap; + XSetWindowAttributes swa; + XVisualInfo *vi; ++ int x0 = 0; ++ int y0 = 0; + + XOutput *out = g_xrandr.GetOutput(output); + if (!out) + out = g_xrandr.GetOutput(m_currentOutput); +- m_nScreen = out->screen; ++ if (out) ++ { ++ m_nScreen = out->screen; ++ x0 = out->x; ++ y0 = out->y; ++ } ++ + vi = glXChooseVisual(m_dpy, m_nScreen, att); + cmap = XCreateColormap(m_dpy, RootWindow(m_dpy, vi->screen), vi->visual, AllocNone); + +@@ -842,7 +853,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask; + + m_glWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen), +- out->x, out->y, width, height, 0, vi->depth, ++ x0, y0, width, height, 0, vi->depth, + InputOutput, vi->visual, + mask, &swa); + +-- +1.9.1 + + +From aaeedaed5098ef4771c643a8d61b5d641e20c8ae Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sat, 23 Mar 2013 15:13:32 +0100 +Subject: [PATCH 50/96] X11: create parent window + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 69 +++++++++++++++++++++++-------------- + xbmc/windowing/X11/WinSystemX11.h | 2 +- + 2 files changed, 44 insertions(+), 27 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 2adf8a0..07f3f3d 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -55,6 +55,7 @@ CWinSystemX11::CWinSystemX11() : CWinSystemBase() + m_glContext = NULL; + m_dpy = NULL; + m_glWindow = 0; ++ m_mainWindow = 0; + m_bWasFullScreenBeforeMinimize = false; + m_minimized = false; + m_bIgnoreNextFocusMessage = false; +@@ -132,7 +133,7 @@ bool CWinSystemX11::CreateNewWindow(const CStdString& name, bool fullScreen, RES + + bool CWinSystemX11::DestroyWindow() + { +- if (!m_glWindow) ++ if (!m_mainWindow) + return true; + + if (m_glContext) +@@ -143,19 +144,21 @@ bool CWinSystemX11::DestroyWindow() + + if (m_invisibleCursor) + { +- XUndefineCursor(m_dpy, m_glWindow); ++ XUndefineCursor(m_dpy, m_mainWindow); + XFreeCursor(m_dpy, m_invisibleCursor); + m_invisibleCursor = 0; + } + + CWinEventsX11Imp::Quit(); + +- XUnmapWindow(m_dpy, m_glWindow); ++ XUnmapWindow(m_dpy, m_mainWindow); + XSync(m_dpy,TRUE); + XUngrabKeyboard(m_dpy, CurrentTime); + XUngrabPointer(m_dpy, CurrentTime); + XDestroyWindow(m_dpy, m_glWindow); ++ XDestroyWindow(m_dpy, m_mainWindow); + m_glWindow = 0; ++ m_mainWindow = 0; + + if (m_icon) + XFreePixmap(m_dpy, m_icon); +@@ -225,7 +228,7 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + OnLostDevice(); + m_bIsInternalXrr = true; + g_xrandr.SetMode(out, mode); +- if (m_glWindow) ++ if (m_mainWindow) + return true; + } + } +@@ -503,9 +506,9 @@ bool CWinSystemX11::RefreshGlxContext(bool force) + void CWinSystemX11::ShowOSMouse(bool show) + { + if (show) +- XUndefineCursor(m_dpy,m_glWindow); ++ XUndefineCursor(m_dpy,m_mainWindow); + else if (m_invisibleCursor) +- XDefineCursor(m_dpy,m_glWindow, m_invisibleCursor); ++ XDefineCursor(m_dpy,m_mainWindow, m_invisibleCursor); + } + + void CWinSystemX11::ResetOSScreensaver() +@@ -588,10 +591,10 @@ void CWinSystemX11::NotifyMouseCoverage(bool covered) + int result = -1; + while (result != GrabSuccess && result != AlreadyGrabbed) + { +- result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); ++ result = XGrabPointer(m_dpy, m_mainWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + XbmcThreads::ThreadSleep(100); + } +- XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); ++ XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); + } + else + { +@@ -609,7 +612,7 @@ bool CWinSystemX11::Minimize() + g_graphicsContext.ToggleFullScreenRoot(); + } + +- XIconifyWindow(m_dpy, m_glWindow, m_nScreen); ++ XIconifyWindow(m_dpy, m_mainWindow, m_nScreen); + + m_minimized = true; + return true; +@@ -620,13 +623,13 @@ bool CWinSystemX11::Restore() + } + bool CWinSystemX11::Hide() + { +- XUnmapWindow(m_dpy, m_glWindow); ++ XUnmapWindow(m_dpy, m_mainWindow); + XSync(m_dpy, False); + return true; + } + bool CWinSystemX11::Show(bool raise) + { +- XMapWindow(m_dpy, m_glWindow); ++ XMapWindow(m_dpy, m_mainWindow); + XSync(m_dpy, False); + m_minimized = false; + return true; +@@ -776,7 +779,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + bool mouseActive = false; + float mouseX, mouseY; + +- if (m_glWindow && ((m_bFullScreen != fullscreen) || !m_currentOutput.Equals(output) || m_windowDirty)) ++ if (m_mainWindow && ((m_bFullScreen != fullscreen) || !m_currentOutput.Equals(output) || m_windowDirty)) + { + mouseActive = g_Mouse.IsActive(); + if (mouseActive) +@@ -785,7 +788,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + int root_x_return, root_y_return; + int win_x_return, win_y_return; + unsigned int mask_return; +- bool isInWin = XQueryPointer(m_dpy, m_glWindow, &root_return, &child_return, ++ bool isInWin = XQueryPointer(m_dpy, m_mainWindow, &root_return, &child_return, + &root_x_return, &root_y_return, + &win_x_return, &win_y_return, + &mask_return); +@@ -804,7 +807,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + } + + // create main window +- if (!m_glWindow) ++ if (!m_mainWindow) + { + EnableSystemScreenSaver(false); + +@@ -845,22 +848,31 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + swa.border_pixel = fullscreen ? 0 : 5; + swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; + swa.colormap = cmap; +- swa.background_pixel = def_vis ? BlackPixel(m_dpy, vi->screen) : 0; + swa.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | PointerMotionMask | + PropertyChangeMask | StructureNotifyMask | KeymapStateMask | + EnterWindowMask | LeaveWindowMask | ExposureMask; + unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask; + +- m_glWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen), ++ m_mainWindow = XCreateWindow(m_dpy, RootWindow(m_dpy, vi->screen), + x0, y0, width, height, 0, vi->depth, + InputOutput, vi->visual, + mask, &swa); + ++ swa.override_redirect = False; ++ swa.border_pixel = 0; ++ swa.event_mask = 0; ++ mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWColormap; ++ ++ m_glWindow = XCreateWindow(m_dpy, m_mainWindow, ++ 0, 0, width, height, 0, vi->depth, ++ InputOutput, vi->visual, ++ mask, &swa); ++ + if (fullscreen && hasWM) + { + Atom fs = XInternAtom(m_dpy, "_NET_WM_STATE_FULLSCREEN", True); +- XChangeProperty(m_dpy, m_glWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1); ++ XChangeProperty(m_dpy, m_mainWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1); + } + + // define invisible cursor +@@ -869,14 +881,14 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + static char noData[] = { 0,0,0,0,0,0,0,0 }; + black.red = black.green = black.blue = 0; + +- bitmapNoData = XCreateBitmapFromData(m_dpy, m_glWindow, noData, 8, 8); ++ bitmapNoData = XCreateBitmapFromData(m_dpy, m_mainWindow, noData, 8, 8); + m_invisibleCursor = XCreatePixmapCursor(m_dpy, bitmapNoData, bitmapNoData, + &black, &black, 0, 0); + XFreePixmap(m_dpy, bitmapNoData); +- XDefineCursor(m_dpy,m_glWindow, m_invisibleCursor); ++ XDefineCursor(m_dpy,m_mainWindow, m_invisibleCursor); + + //init X11 events +- CWinEventsX11Imp::Init(m_dpy, m_glWindow); ++ CWinEventsX11Imp::Init(m_dpy, m_mainWindow); + + changeWindow = true; + changeSize = true; +@@ -889,13 +901,17 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + + if (changeSize || changeWindow) + { ++ XResizeWindow(m_dpy, m_mainWindow, width, height); ++ } ++ ++ if ((width != m_nWidth) || (height != m_nHeight) || changeWindow) ++ { + XResizeWindow(m_dpy, m_glWindow, width, height); + } + + if (changeWindow) + { + m_icon = None; +- if (!fullscreen) + { + CreateIconPixmap(); + XWMHints *wm_hints; +@@ -912,21 +928,22 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + wm_hints->flags = StateHint | IconPixmapHint; + + XSync(m_dpy,False); +- XSetWMProperties(m_dpy, m_glWindow, &windowName, &iconName, ++ XSetWMProperties(m_dpy, m_mainWindow, &windowName, &iconName, + NULL, 0, NULL, wm_hints, + NULL); + XFree(wm_hints); + + // register interest in the delete window message + Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False); +- XSetWMProtocols(m_dpy, m_glWindow, &wmDeleteMessage, 1); ++ XSetWMProtocols(m_dpy, m_mainWindow, &wmDeleteMessage, 1); + } + XMapRaised(m_dpy, m_glWindow); ++ XMapRaised(m_dpy, m_mainWindow); + XSync(m_dpy,TRUE); + + if (changeWindow && mouseActive) + { +- XWarpPointer(m_dpy, None, m_glWindow, 0, 0, 0, 0, mouseX*width, mouseY*height); ++ XWarpPointer(m_dpy, None, m_mainWindow, 0, 0, 0, 0, mouseX*width, mouseY*height); + } + + if (fullscreen) +@@ -934,10 +951,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + int result = -1; + while (result != GrabSuccess && result != AlreadyGrabbed) + { +- result = XGrabPointer(m_dpy, m_glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); ++ result = XGrabPointer(m_dpy, m_mainWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + XbmcThreads::ThreadSleep(100); + } +- XGrabKeyboard(m_dpy, m_glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); ++ XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); + } + + CDirtyRegionList dr; +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 2a1fb41..e8993f1 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -81,7 +81,7 @@ protected: + void OnLostDevice(); + bool SetWindow(int width, int height, bool fullscreen, const CStdString &output); + +- Window m_glWindow; ++ Window m_glWindow, m_mainWindow; + GLXContext m_glContext; + Display* m_dpy; + Cursor m_invisibleCursor; +-- +1.9.1 + + +From 085ec3cdb8b45b3885a7fc0cec7355ca211c055f Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sun, 24 Mar 2013 12:30:12 +0100 +Subject: [PATCH 51/96] X11: use system key repeat rate instead of hardcoded + one, taken from 58fd64b194e38b73b5f3132744bab35e994e7441 + +--- + xbmc/windowing/WinEventsX11.cpp | 58 +++++++++++++---------------------------- + xbmc/windowing/WinEventsX11.h | 5 +--- + 2 files changed, 19 insertions(+), 44 deletions(-) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index 263cb5a..09f56ff 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -213,7 +213,6 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win) + WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + WinEvents->m_structureChanged = false; + WinEvents->m_xrrEventPending = false; +- memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); + + // open input method + char *old_locale = NULL, *old_modifiers = NULL; +@@ -328,20 +327,6 @@ bool CWinEventsX11Imp::MessagePump() + memset(&xevent, 0, sizeof (XEvent)); + XNextEvent(WinEvents->m_display, &xevent); + +- // ignore events generated by auto-repeat +- if (xevent.type == KeyRelease && XPending(WinEvents->m_display)) +- { +- XEvent peekevent; +- XPeekEvent(WinEvents->m_display, &peekevent); +- if ((peekevent.type == KeyPress) && +- (peekevent.xkey.keycode == xevent.xkey.keycode) && +- ((peekevent.xkey.time - xevent.xkey.time) < 2)) +- { +- XNextEvent(WinEvents->m_display, &peekevent); +- continue; +- } +- } +- + if (XFilterEvent(&xevent, None)) + continue; + +@@ -364,7 +349,6 @@ bool CWinEventsX11Imp::MessagePump() + if (WinEvents->m_xic) + XSetICFocus(WinEvents->m_xic); + g_application.m_AppFocused = true; +- memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); + WinEvents->m_keymodState = 0; + if (serial == xevent.xfocus.serial) + break; +@@ -377,7 +361,6 @@ bool CWinEventsX11Imp::MessagePump() + if (WinEvents->m_xic) + XUnsetICFocus(WinEvents->m_xic); + g_application.m_AppFocused = false; +- memset(&(WinEvents->m_lastKey), 0, sizeof(XBMC_Event)); + g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); + serial = xevent.xfocus.serial; + break; +@@ -433,7 +416,7 @@ bool CWinEventsX11Imp::MessagePump() + { + newEvent.key.keysym.unicode = keybuf[0]; + } +- ret |= ProcessKey(newEvent, 500); ++ ret |= ProcessKey(newEvent); + break; + } + +@@ -472,7 +455,7 @@ bool CWinEventsX11Imp::MessagePump() + newEvent.key.keysym.unicode = keys[i]; + newEvent.key.state = xevent.xkey.state; + newEvent.key.type = xevent.xkey.type; +- ret |= ProcessKey(newEvent, 500); ++ ret |= ProcessKey(newEvent); + } + if (keys.length() > 0) + { +@@ -483,7 +466,7 @@ bool CWinEventsX11Imp::MessagePump() + newEvent.key.state = xevent.xkey.state; + newEvent.key.type = xevent.xkey.type; + +- ret |= ProcessKey(newEvent, 500); ++ ret |= ProcessKey(newEvent); + } + break; + } +@@ -494,7 +477,7 @@ bool CWinEventsX11Imp::MessagePump() + newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); + newEvent.key.state = xevent.xkey.state; + newEvent.key.type = xevent.xkey.type; +- ret |= ProcessKey(newEvent, 500); ++ ret |= ProcessKey(newEvent); + break; + } + +@@ -504,6 +487,18 @@ bool CWinEventsX11Imp::MessagePump() + + case KeyRelease: + { ++ // if we have a queued press directly after, this is a repeat ++ if( XEventsQueued( WinEvents->m_display, QueuedAfterReading ) ) ++ { ++ XEvent next_event; ++ XPeekEvent( WinEvents->m_display, &next_event ); ++ if(next_event.type == KeyPress ++ && next_event.xkey.window == xevent.xkey.window ++ && next_event.xkey.keycode == xevent.xkey.keycode ++ && (next_event.xkey.time - xevent.xkey.time < 2) ) ++ continue; ++ } ++ + XBMC_Event newEvent; + KeySym xkeysym; + memset(&newEvent, 0, sizeof(newEvent)); +@@ -513,7 +508,7 @@ bool CWinEventsX11Imp::MessagePump() + newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); + newEvent.key.state = xevent.xkey.state; + newEvent.key.type = xevent.xkey.type; +- ret |= ProcessKey(newEvent, 0); ++ ret |= ProcessKey(newEvent); + break; + } + +@@ -589,8 +584,6 @@ bool CWinEventsX11Imp::MessagePump() + + }// while + +- ret |= ProcessKeyRepeat(); +- + #if defined(HAS_XRANDR) + if (WinEvents && WinEvents->m_xrrEventPending && WinEvents->m_xrrFailSafeTimer.IsTimePast()) + { +@@ -635,7 +628,7 @@ size_t CWinEventsX11Imp::GetQueueSize() + return ret; + } + +-bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event, int repeatDelay) ++bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event) + { + if (event.type == XBMC_KEYDOWN) + { +@@ -673,8 +666,6 @@ bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event, int repeatDelay) + break; + } + event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState; +- memcpy(&(WinEvents->m_lastKey), &event, sizeof(event)); +- WinEvents->m_repeatKeyTimeout.Set(repeatDelay); + + bool ret = ProcessShortcuts(event); + if (ret) +@@ -715,7 +706,6 @@ bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event, int repeatDelay) + break; + } + event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState; +- memset(&(WinEvents->m_lastKey), 0, sizeof(event)); + } + + return g_application.OnEvent(event); +@@ -738,18 +728,6 @@ bool CWinEventsX11Imp::ProcessShortcuts(XBMC_Event& event) + return false; + } + +-bool CWinEventsX11Imp::ProcessKeyRepeat() +-{ +- if (WinEvents && (WinEvents->m_lastKey.type == XBMC_KEYDOWN)) +- { +- if (WinEvents->m_repeatKeyTimeout.IsTimePast()) +- { +- return ProcessKey(WinEvents->m_lastKey, 10); +- } +- } +- return false; +-} +- + XBMCKey CWinEventsX11Imp::LookupXbmcKeySym(KeySym keysym) + { + // try direct mapping first +diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h +index c69169c..6429291 100644 +--- a/xbmc/windowing/WinEventsX11.h ++++ b/xbmc/windowing/WinEventsX11.h +@@ -47,8 +47,7 @@ public: + + protected: + static XBMCKey LookupXbmcKeySym(KeySym keysym); +- static bool ProcessKey(XBMC_Event &event, int repeatDelay); +- static bool ProcessKeyRepeat(); ++ static bool ProcessKey(XBMC_Event &event); + static bool ProcessShortcuts(XBMC_Event& event); + static CWinEventsX11Imp *WinEvents; + Display *m_display; +@@ -58,8 +57,6 @@ protected: + size_t m_keybuf_len; + XIM m_xim; + XIC m_xic; +- XBMC_Event m_lastKey; +- XbmcThreads::EndTime m_repeatKeyTimeout; + std::map m_symLookupTable; + int m_keymodState; + bool m_structureChanged; +-- +1.9.1 + + +From dcb0640d4f41cc444f6b212799505d1d122170a7 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sun, 24 Mar 2013 16:04:48 +0100 +Subject: [PATCH 52/96] linux: use CLOCK_MONOTONIC_RAW as this is not subject + to NTP + +--- + xbmc/threads/SystemClock.cpp | 2 +- + xbmc/utils/TimeUtils.cpp | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/threads/SystemClock.cpp b/xbmc/threads/SystemClock.cpp +index 657a154..35e3abf 100644 +--- a/xbmc/threads/SystemClock.cpp ++++ b/xbmc/threads/SystemClock.cpp +@@ -43,7 +43,7 @@ namespace XbmcThreads + now_time = (uint64_t)timeGetTime(); + #else + struct timespec ts = {}; +- clock_gettime(CLOCK_MONOTONIC, &ts); ++ clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + now_time = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); + #endif + if (!start_time_set) +diff --git a/xbmc/utils/TimeUtils.cpp b/xbmc/utils/TimeUtils.cpp +index c06b8c5..4390d2e 100644 +--- a/xbmc/utils/TimeUtils.cpp ++++ b/xbmc/utils/TimeUtils.cpp +@@ -43,7 +43,7 @@ int64_t CurrentHostCounter(void) + return( (int64_t)PerformanceCount.QuadPart ); + #else + struct timespec now; +- clock_gettime(CLOCK_MONOTONIC, &now); ++ clock_gettime(CLOCK_MONOTONIC_RAW, &now); + return( ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec ); + #endif + } +-- +1.9.1 + + +From feb8150d84f4b83dbba365cad5eafa8831914654 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Thu, 28 Mar 2013 15:18:53 +0100 +Subject: [PATCH 53/96] OMXPlayer: some caching fixes for pvr + +--- + xbmc/cores/omxplayer/OMXPlayer.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/omxplayer/OMXPlayer.cpp b/xbmc/cores/omxplayer/OMXPlayer.cpp +index 0b80be5..8eab2fd 100644 +--- a/xbmc/cores/omxplayer/OMXPlayer.cpp ++++ b/xbmc/cores/omxplayer/OMXPlayer.cpp +@@ -2548,7 +2548,8 @@ void COMXPlayer::HandleMessages() + m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), (speed < 0), true, false, false, true)); + + m_playSpeed = speed; +- m_caching = CACHESTATE_DONE; ++ if (m_caching != CACHESTATE_PVR && m_playSpeed != DVD_PLAYSPEED_NORMAL) ++ m_caching = CACHESTATE_DONE; + m_clock.SetSpeed(speed); + m_av_clock.OMXSetSpeed(speed); + m_av_clock.OMXPause(); +-- +1.9.1 + + +From c66609611e7e6da48d14069e0a047bca7ea1b694 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Thu, 28 Mar 2013 20:50:59 +0100 +Subject: [PATCH 54/96] fix incorrect display of fps when dr kicks in + +--- + xbmc/Application.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp +index 5a24ffb..a0ca53a 100644 +--- a/xbmc/Application.cpp ++++ b/xbmc/Application.cpp +@@ -2320,10 +2320,11 @@ void CApplication::Render() + if (frameTime < singleFrameTime) + Sleep(singleFrameTime - frameTime); + } +- m_lastFrameTime = XbmcThreads::SystemClockMillis(); + + if (flip) + g_graphicsContext.Flip(dirtyRegions); ++ ++ m_lastFrameTime = XbmcThreads::SystemClockMillis(); + CTimeUtils::UpdateFrameTime(flip); + + g_renderManager.UpdateResolution(); +-- +1.9.1 + + +From 33ee35d980ddf952da1d577903154e19f8bad525 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sat, 13 Apr 2013 08:32:06 +0200 +Subject: [PATCH 55/96] X11: fix mouse coverage + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 11 ++++++++--- + xbmc/windowing/X11/WinSystemX11.h | 1 + + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 07f3f3d..2acb36d 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -583,10 +583,10 @@ void CWinSystemX11::NotifyAppFocusChange(bool bGaining) + + void CWinSystemX11::NotifyMouseCoverage(bool covered) + { +- if (!m_bFullScreen) ++ if (!m_bFullScreen || !m_mainWindow) + return; + +- if (covered) ++ if (covered && !m_bIsGrabbed) + { + int result = -1; + while (result != GrabSuccess && result != AlreadyGrabbed) +@@ -595,11 +595,13 @@ void CWinSystemX11::NotifyMouseCoverage(bool covered) + XbmcThreads::ThreadSleep(100); + } + XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); ++ m_bIsGrabbed = true; + } +- else ++ else if (!covered && m_bIsGrabbed) + { + XUngrabKeyboard(m_dpy, CurrentTime); + XUngrabPointer(m_dpy, CurrentTime); ++ m_bIsGrabbed = false; + } + } + +@@ -955,7 +957,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + XbmcThreads::ThreadSleep(100); + } + XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); ++ m_bIsGrabbed = true; + } ++ else ++ m_bIsGrabbed = false; + + CDirtyRegionList dr; + RefreshGlxContext(!m_currentOutput.Equals(output)); +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index e8993f1..5cccfb7 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -90,6 +90,7 @@ protected: + bool m_bWasFullScreenBeforeMinimize; + bool m_minimized; + bool m_bIgnoreNextFocusMessage; ++ bool m_bIsGrabbed; + int m_RREventBase; + CCriticalSection m_resourceSection; + std::vector m_resources; +-- +1.9.1 + + +From 6b23cb08d6e6b72909750bd69630be1a4b381895 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Wed, 8 May 2013 13:14:58 +0200 +Subject: [PATCH 56/96] X11: fix incorrectly used screen num in desktop + resolution + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 2acb36d..101ba98 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -268,9 +268,9 @@ void CWinSystemX11::UpdateResolutions() + XMode mode = g_xrandr.GetCurrentMode(currentMonitor); + m_bIsRotated = out->isRotated; + if (!m_bIsRotated) +- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), out->screen, mode.w, mode.h, mode.hz); ++ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz); + else +- UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), out->screen, mode.h, mode.w, mode.hz); ++ UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz); + CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id; + CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = currentMonitor; + } +@@ -305,6 +305,7 @@ void CWinSystemX11::UpdateResolutions() + CLog::Log(LOGINFO, "ID:%s Name:%s Refresh:%f Width:%d Height:%d", + mode.id.c_str(), mode.name.c_str(), mode.hz, mode.w, mode.h); + RESOLUTION_INFO res; ++ res.iScreen = 0; // not used by X11 + res.iWidth = mode.w; + res.iHeight = mode.h; + res.iScreenWidth = mode.w; +-- +1.9.1 + + +From 30326f85a2b363432abe0979d09f5eadd8520db1 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 9 May 2013 12:07:09 +0200 +Subject: [PATCH 57/96] X11: do not overwrite user selected monitor with + fallback + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 31 ++++++++++++++----------------- + xbmc/windowing/X11/WinSystemX11.h | 1 + + 2 files changed, 15 insertions(+), 17 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 101ba98..c614c9b 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -172,7 +172,7 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n + && m_nHeight == newHeight) + return true; + +- if (!SetWindow(newWidth, newHeight, false, CSettings::Get().GetString("videoscreen.monitor"))) ++ if (!SetWindow(newWidth, newHeight, false, m_userOutput)) + { + return false; + } +@@ -180,7 +180,7 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n + m_nWidth = newWidth; + m_nHeight = newHeight; + m_bFullScreen = false; +- m_currentOutput = CSettings::Get().GetString("videoscreen.monitor"); ++ m_currentOutput = m_userOutput; + + return false; + } +@@ -234,13 +234,13 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + } + #endif + +- if (!SetWindow(res.iWidth, res.iHeight, fullScreen, CSettings::Get().GetString("videoscreen.monitor"))) ++ if (!SetWindow(res.iWidth, res.iHeight, fullScreen, m_userOutput)) + return false; + + m_nWidth = res.iWidth; + m_nHeight = res.iHeight; + m_bFullScreen = fullScreen; +- m_currentOutput = CSettings::Get().GetString("videoscreen.monitor"); ++ m_currentOutput = m_userOutput; + + return true; + } +@@ -250,34 +250,32 @@ void CWinSystemX11::UpdateResolutions() + CWinSystemBase::UpdateResolutions(); + + #if defined(HAS_XRANDR) +- CStdString currentMonitor; + int numScreens = XScreenCount(m_dpy); + g_xrandr.SetNumScreens(numScreens); + if(g_xrandr.Query(true)) + { +- currentMonitor = CSettings::Get().GetString("videoscreen.monitor"); ++ m_userOutput = CSettings::Get().GetString("videoscreen.monitor"); + // check if the monitor is connected +- XOutput *out = g_xrandr.GetOutput(currentMonitor); ++ XOutput *out = g_xrandr.GetOutput(m_userOutput); + if (!out) + { + // choose first output +- currentMonitor = g_xrandr.GetModes()[0].name; +- out = g_xrandr.GetOutput(currentMonitor); +- CSettings::Get().SetString("videoscreen.monitor", currentMonitor); ++ m_userOutput = g_xrandr.GetModes()[0].name; ++ out = g_xrandr.GetOutput(m_userOutput); + } +- XMode mode = g_xrandr.GetCurrentMode(currentMonitor); ++ XMode mode = g_xrandr.GetCurrentMode(m_userOutput); + m_bIsRotated = out->isRotated; + if (!m_bIsRotated) + UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz); + else + UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.h, mode.w, mode.hz); + CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strId = mode.id; +- CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = currentMonitor; ++ CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP).strOutput = m_userOutput; + } + else + #endif + { +- CSettings::Get().SetString("videoscreen.monitor", "Default"); ++ m_userOutput = "No Output"; + m_nScreen = DefaultScreen(m_dpy); + int w = DisplayWidth(m_dpy, m_nScreen); + int h = DisplayHeight(m_dpy, m_nScreen); +@@ -291,7 +289,7 @@ void CWinSystemX11::UpdateResolutions() + + CLog::Log(LOGINFO, "Available videomodes (xrandr):"); + +- XOutput *out = g_xrandr.GetOutput(currentMonitor); ++ XOutput *out = g_xrandr.GetOutput(m_userOutput); + string modename = ""; + + if (out != NULL) +@@ -691,9 +689,8 @@ void CWinSystemX11::NotifyXRREvent() + } + m_bIsInternalXrr = false; + +- CStdString currentOutput = CSettings::Get().GetString("videoscreen.monitor"); +- XOutput *out = g_xrandr.GetOutput(currentOutput); +- XMode mode = g_xrandr.GetCurrentMode(currentOutput); ++ XOutput *out = g_xrandr.GetOutput(m_userOutput); ++ XMode mode = g_xrandr.GetCurrentMode(m_userOutput); + + if (out) + CLog::Log(LOGDEBUG, "%s - current output: %s, mode: %s, refresh: %.3f", __FUNCTION__ +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 5cccfb7..1b658e2 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -96,6 +96,7 @@ protected: + std::vector m_resources; + uint64_t m_dpyLostTime; + CStdString m_currentOutput; ++ CStdString m_userOutput; + bool m_windowDirty; + bool m_bIsInternalXrr; + bool m_newGlContext; +-- +1.9.1 + + +From 640834140bad33d23f0d0228ac4a6f022405f276 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sun, 12 May 2013 10:50:30 +0200 +Subject: [PATCH 58/96] xrandr: add turn on/off to wrapper + +--- + xbmc/windowing/X11/XRandR.cpp | 78 +++++++++++++++++++++++++++++++++++++++---- + xbmc/windowing/X11/XRandR.h | 6 ++-- + 2 files changed, 75 insertions(+), 9 deletions(-) + +diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp +index 4355ef7..223472c 100644 +--- a/xbmc/windowing/X11/XRandR.cpp ++++ b/xbmc/windowing/X11/XRandR.cpp +@@ -29,6 +29,7 @@ + #include "utils/XBMCTinyXML.h" + #include "utils/StringUtils.h" + #include "../xbmc/utils/log.h" ++#include "threads/SystemClock.h" + + #if defined(TARGET_FREEBSD) + #include +@@ -45,7 +46,7 @@ CXRandR::CXRandR(bool query) + Query(); + } + +-bool CXRandR::Query(bool force) ++bool CXRandR::Query(bool force, bool ignoreoff) + { + if (!force) + if (m_bInit) +@@ -62,13 +63,13 @@ bool CXRandR::Query(bool force) + bool success = false; + for(unsigned int screennum=0; screennumAttribute("current"), "true") == 0); + xoutput.modes.push_back(xmode); + if (xmode.isCurrent) +- { + hascurrent = true; +- } + } +- if (hascurrent) ++ if (hascurrent || !ignoreoff) + m_outputs.push_back(xoutput); + else + CLog::Log(LOGWARNING, "CXRandR::Query - output %s has no current mode, assuming disconnected", xoutput.name.c_str()); +@@ -148,6 +147,71 @@ bool CXRandR::Query(bool force, int screennum) + return m_outputs.size() > 0; + } + ++bool CXRandR::TurnOffOutput(CStdString name) ++{ ++ CStdString cmd; ++ cmd = getenv("XBMC_BIN_HOME"); ++ cmd += "/xbmc-xrandr"; ++ cmd.AppendFormat(" --output %s --off", name.c_str()); ++ ++ int status = system(cmd.c_str()); ++ if (status == -1) ++ return false; ++ ++ if (WEXITSTATUS(status) != 0) ++ return false; ++ ++ return true; ++} ++ ++bool CXRandR::TurnOnOutput(CStdString name) ++{ ++ XOutput *output = GetOutput(name); ++ if (!output) ++ return false; ++ ++ XMode mode = GetCurrentMode(output->name); ++ if (mode.isCurrent) ++ return true; ++ ++ // get preferred mode ++ for (unsigned int j = 0; j < m_outputs.size(); j++) ++ { ++ if (m_outputs[j].name == output->name) ++ { ++ for (unsigned int i = 0; i < m_outputs[j].modes.size(); i++) ++ { ++ if (m_outputs[j].modes[i].isPreferred) ++ { ++ mode = m_outputs[j].modes[i]; ++ break; ++ } ++ } ++ } ++ } ++ ++ if (!mode.isPreferred) ++ return false; ++ ++ if (!SetMode(*output, mode)) ++ return false; ++ ++ XbmcThreads::EndTime timeout(5000); ++ while (!timeout.IsTimePast()) ++ { ++ if (!Query(true)) ++ return false; ++ ++ output = GetOutput(name); ++ if (output && output->h > 0) ++ return true; ++ ++ Sleep(200); ++ } ++ ++ return false; ++} ++ + std::vector CXRandR::GetModes(void) + { + Query(); +@@ -161,7 +225,7 @@ void CXRandR::SaveState() + + bool CXRandR::SetMode(XOutput output, XMode mode) + { +- if ((output.name == m_currentOutput && mode.id == m_currentMode) || (output.name == "" && mode.id == "")) ++ if ((output.name == "" && mode.id == "")) + return true; + + Query(); +diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h +index d37838a..059062f 100644 +--- a/xbmc/windowing/X11/XRandR.h ++++ b/xbmc/windowing/X11/XRandR.h +@@ -94,8 +94,8 @@ class CXRandR + { + public: + CXRandR(bool query=false); +- bool Query(bool force=false); +- bool Query(bool force, int screennum); ++ bool Query(bool force=false, bool ignoreoff=true); ++ bool Query(bool force, int screennum, bool ignoreoff=true); + std::vector GetModes(void); + XMode GetCurrentMode(CStdString outputName); + XOutput *GetOutput(CStdString outputName); +@@ -104,6 +104,8 @@ public: + void SaveState(); + void SetNumScreens(unsigned int num); + bool IsOutputConnected(CStdString name); ++ bool TurnOffOutput(CStdString name); ++ bool TurnOnOutput(CStdString name); + //bool Has1080i(); + //bool Has1080p(); + //bool Has720p(); +-- +1.9.1 + + +From eb767b125450fc14c15cfe05dec4b696e1439bbe Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sun, 19 May 2013 12:55:35 +0200 +Subject: [PATCH 59/96] xrandr: add GetPreferredMode to wrapper + +--- + xbmc/windowing/X11/XRandR.cpp | 23 +++++++++++++++++++++++ + xbmc/windowing/X11/XRandR.h | 1 + + 2 files changed, 24 insertions(+) + +diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp +index 223472c..62003f5 100644 +--- a/xbmc/windowing/X11/XRandR.cpp ++++ b/xbmc/windowing/X11/XRandR.cpp +@@ -347,6 +347,29 @@ XMode CXRandR::GetCurrentMode(CStdString outputName) + return result; + } + ++XMode CXRandR::GetPreferredMode(CStdString outputName) ++{ ++ Query(); ++ XMode result; ++ ++ for (unsigned int j = 0; j < m_outputs.size(); j++) ++ { ++ if (m_outputs[j].name == outputName || outputName == "") ++ { ++ for (unsigned int i = 0; i < m_outputs[j].modes.size(); i++) ++ { ++ if (m_outputs[j].modes[i].isPreferred) ++ { ++ result = m_outputs[j].modes[i]; ++ break; ++ } ++ } ++ } ++ } ++ ++ return result; ++} ++ + void CXRandR::LoadCustomModeLinesToAllOutputs(void) + { + Query(); +diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h +index 059062f..ab7cc63 100644 +--- a/xbmc/windowing/X11/XRandR.h ++++ b/xbmc/windowing/X11/XRandR.h +@@ -98,6 +98,7 @@ public: + bool Query(bool force, int screennum, bool ignoreoff=true); + std::vector GetModes(void); + XMode GetCurrentMode(CStdString outputName); ++ XMode GetPreferredMode(CStdString outputName); + XOutput *GetOutput(CStdString outputName); + bool SetMode(XOutput output, XMode mode); + void LoadCustomModeLinesToAllOutputs(void); +-- +1.9.1 + + +From 24471c2dd68d3bf52d1a5204d73fb48ac6b4d189 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sat, 11 May 2013 17:12:12 +0200 +Subject: [PATCH 60/96] X11: multi-head improvement - poll for desired output + if we do not get an xrr event + +--- + language/English/strings.po | 9 +++- + system/settings/settings.xml | 8 +++- + xbmc/settings/DisplaySettings.cpp | 4 ++ + xbmc/windowing/WinEventsX11.cpp | 6 +++ + xbmc/windowing/WinEventsX11.h | 1 + + xbmc/windowing/X11/WinSystemX11.cpp | 83 +++++++++++++++++++++++++++++++++---- + xbmc/windowing/X11/WinSystemX11.h | 2 +- + xbmc/windowing/X11/XRandR.cpp | 6 ++- + 8 files changed, 106 insertions(+), 13 deletions(-) + +diff --git a/language/English/strings.po b/language/English/strings.po +index 685847c..9cc2090 100755 +--- a/language/English/strings.po ++++ b/language/English/strings.po +@@ -6558,7 +6558,7 @@ msgctxt "#14071" + msgid "Allow file renaming and deletion" + msgstr "" + +-#empty strings from id 14072 to 14073 ++#empty strings from id 14073 to 14073 + + msgctxt "#14074" + msgid "Set timezone" +@@ -6696,7 +6696,12 @@ msgctxt "#14101" + msgid "Acceleration" + msgstr "" + +-#empty strings from id 14102 to 15011 ++#: xbmc/settings/settings.xml ++msgctxt "#14102" ++msgid "Switch off other Monitor" ++msgstr "" ++ ++#empty strings from id 14103 to 15011 + + #: xbmc/video/VideoDatabase.cpp + msgctxt "#15012" +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index fba4561..798be52 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -2252,7 +2252,7 @@ + + + +- HAS_GLX ++ HAS_GLX + 0 + Default + +@@ -2260,6 +2260,11 @@ + + + ++ ++ HAS_GLX ++ 0 ++ false ++ + + 0 + 0 +@@ -2312,6 +2317,7 @@ + + + ++ !HAS_GLX + 1 + false + +diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp +index db2f667..efb6cb1 100644 +--- a/xbmc/settings/DisplaySettings.cpp ++++ b/xbmc/settings/DisplaySettings.cpp +@@ -274,6 +274,10 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting) + m_resolutionChangeAborted = false; + } + } ++ else if (settingId == "videoscreen.monitorsingle") ++ { ++ g_Windowing.UpdateResolutions(); ++ } + + return true; + } +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index 09f56ff..908c8b6 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -213,6 +213,7 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win) + WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + WinEvents->m_structureChanged = false; + WinEvents->m_xrrEventPending = false; ++ WinEvents->m_xrrPollTimer.Set(3000); + + // open input method + char *old_locale = NULL, *old_modifiers = NULL; +@@ -591,6 +592,11 @@ bool CWinEventsX11Imp::MessagePump() + g_Windowing.NotifyXRREvent(); + WinEvents->m_xrrEventPending = false; + } ++ else if (!g_application.m_pPlayer->IsPlaying() && WinEvents && WinEvents->m_xrrPollTimer.IsTimePast()) ++ { ++ g_Windowing.NotifyXRREvent(true); ++ WinEvents->m_xrrPollTimer.Set(3000); ++ } + #endif + + #ifdef HAS_SDL_JOYSTICK +diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h +index 6429291..91a604f 100644 +--- a/xbmc/windowing/WinEventsX11.h ++++ b/xbmc/windowing/WinEventsX11.h +@@ -62,5 +62,6 @@ protected: + bool m_structureChanged; + int m_RREventBase; + XbmcThreads::EndTime m_xrrFailSafeTimer; ++ XbmcThreads::EndTime m_xrrPollTimer; + bool m_xrrEventPending; + }; +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index c614c9b..b3fe510 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -252,18 +252,62 @@ void CWinSystemX11::UpdateResolutions() + #if defined(HAS_XRANDR) + int numScreens = XScreenCount(m_dpy); + g_xrandr.SetNumScreens(numScreens); +- if(g_xrandr.Query(true)) ++ ++ bool switchOnOff = CSettings::Get().GetBool("videoscreen.monitorsingle"); ++ m_userOutput = CSettings::Get().GetString("videoscreen.monitor"); ++ if (m_userOutput.Equals("Default")) ++ switchOnOff = false; ++ ++ if(g_xrandr.Query(true, !switchOnOff)) + { +- m_userOutput = CSettings::Get().GetString("videoscreen.monitor"); + // check if the monitor is connected +- XOutput *out = g_xrandr.GetOutput(m_userOutput); ++ // might take a while when connected to a receiver ++ XbmcThreads::EndTime timeout(3000); ++ XOutput *out = NULL; ++ while (!m_userOutput.Equals("Default") && !timeout.IsTimePast()) ++ { ++ out = g_xrandr.GetOutput(m_userOutput); ++ if (out) ++ { ++ XMode mode = g_xrandr.GetCurrentMode(m_userOutput); ++ if (mode.isCurrent || switchOnOff) ++ break; ++ else ++ { ++ out = NULL; ++ break; ++ } ++ } ++ ++ Sleep(500); ++ if (!g_xrandr.Query(true, !switchOnOff)) ++ break; ++ } + if (!out) + { +- // choose first output + m_userOutput = g_xrandr.GetModes()[0].name; + out = g_xrandr.GetOutput(m_userOutput); + } ++ ++ // switch on output ++ if(switchOnOff) ++ g_xrandr.TurnOnOutput(m_userOutput); ++ ++ // switch off other outputs if desired ++ if (switchOnOff) ++ { ++ std::vector outputs = g_xrandr.GetModes(); ++ for (int i=0; iisRotated; + if (!m_bIsRotated) + UpdateDesktopResolution(CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP), 0, mode.w, mode.h, mode.hz); +@@ -382,7 +426,9 @@ bool CWinSystemX11::HasCalibration(const RESOLUTION_INFO &resInfo) + void CWinSystemX11::GetConnectedOutputs(std::vector *outputs) + { + vector outs; ++ g_xrandr.Query(true); + outs = g_xrandr.GetModes(); ++ outputs->push_back("Default"); + for(unsigned int i=0; ipush_back(outs[i].name); +@@ -669,14 +715,34 @@ void CWinSystemX11::CheckDisplayEvents() + #endif + } + +-void CWinSystemX11::NotifyXRREvent() ++void CWinSystemX11::NotifyXRREvent(bool poll) + { +- CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); ++ // we may not get an event if desired monitor becomes available ++ // hence we need to poll ++ if (poll) ++ { ++ CStdString output = CSettings::Get().GetString("videoscreen.monitor"); ++ if (output.Equals(m_currentOutput) || m_userOutput.Equals("Default")) ++ return; ++ ++ int numScreens = XScreenCount(m_dpy); ++ g_xrandr.SetNumScreens(numScreens); ++ g_xrandr.Query(true); ++ if (!g_xrandr.IsOutputConnected(output)) ++ return; ++ ++ // if output is turned off by user, respect it ++ XMode mode = g_xrandr.GetCurrentMode(output); ++ if (!mode.isCurrent) ++ return; ++ } ++ ++ CLog::Log(LOGDEBUG, "%s - notify display reset event, poll: %d", __FUNCTION__, poll); + m_windowDirty = true; + + CSingleLock lock(g_graphicsContext); + +- if (!g_xrandr.Query(true)) ++ if (!g_xrandr.Query(!poll)) + { + CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); + return; +@@ -703,7 +769,8 @@ void CWinSystemX11::NotifyXRREvent() + bool found(false); + for (i = RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); ++i) + { +- if (CDisplaySettings::Get().GetResolutionInfo(i).strId == mode.id) ++ res = CDisplaySettings::Get().GetResolutionInfo(i); ++ if (CDisplaySettings::Get().GetResolutionInfo(i).strId.Equals(mode.id)) + { + found = true; + break; +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 1b658e2..7ec5be4 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -70,7 +70,7 @@ public: + Display* GetDisplay() { return m_dpy; } + GLXWindow GetWindow() { return m_glWindow; } + GLXContext GetGlxContext() { return m_glContext; } +- void NotifyXRREvent(); ++ void NotifyXRREvent(bool poll = false); + void GetConnectedOutputs(std::vector *outputs); + bool IsCurrentOutput(CStdString output); + void NotifyMouseCoverage(bool covered); +diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp +index 62003f5..8525ede 100644 +--- a/xbmc/windowing/X11/XRandR.cpp ++++ b/xbmc/windowing/X11/XRandR.cpp +@@ -149,10 +149,14 @@ bool CXRandR::Query(bool force, int screennum, bool ignoreoff) + + bool CXRandR::TurnOffOutput(CStdString name) + { ++ XOutput *output = GetOutput(name); ++ if (!output) ++ return false; ++ + CStdString cmd; + cmd = getenv("XBMC_BIN_HOME"); + cmd += "/xbmc-xrandr"; +- cmd.AppendFormat(" --output %s --off", name.c_str()); ++ cmd.AppendFormat(" --screen %d --output %s --off", output->screen, name.c_str()); + + int status = system(cmd.c_str()); + if (status == -1) +-- +1.9.1 + + +From ca045d99ebbe5f35ea3d39a8f2356f53533a7269 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Wed, 15 May 2013 09:14:34 +0200 +Subject: [PATCH 61/96] X11: ignore mouse move event form other windows + +--- + xbmc/windowing/WinEventsX11.cpp | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index 908c8b6..938ad26 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -328,7 +328,7 @@ bool CWinEventsX11Imp::MessagePump() + memset(&xevent, 0, sizeof (XEvent)); + XNextEvent(WinEvents->m_display, &xevent); + +- if (XFilterEvent(&xevent, None)) ++ if (XFilterEvent(&xevent, WinEvents->m_window)) + continue; + + switch (xevent.type) +@@ -529,6 +529,8 @@ bool CWinEventsX11Imp::MessagePump() + + case MotionNotify: + { ++ if (xevent.xmotion.window != WinEvents->m_window) ++ break; + XBMC_Event newEvent; + memset(&newEvent, 0, sizeof(newEvent)); + newEvent.type = XBMC_MOUSEMOTION; +-- +1.9.1 + + + +From e7fb60e0d020111598f477e775c5c2aaac7f7aa5 Mon Sep 17 00:00:00 2001 +From: xbmc +Date: Sun, 16 Jun 2013 13:22:58 +0200 +Subject: [PATCH 63/96] X11: another fix for mouse coverage + +--- + xbmc/windowing/WinEventsX11.cpp | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index 938ad26..e4ca56d 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -515,14 +515,16 @@ bool CWinEventsX11Imp::MessagePump() + + case EnterNotify: + { +- g_Windowing.NotifyMouseCoverage(true); ++ if (xevent.xcrossing.mode == NotifyNormal) ++ g_Windowing.NotifyMouseCoverage(true); + break; + } + + // lose mouse coverage + case LeaveNotify: + { +- g_Windowing.NotifyMouseCoverage(false); ++ if (xevent.xcrossing.mode == NotifyNormal) ++ g_Windowing.NotifyMouseCoverage(false); + g_Mouse.SetActive(false); + break; + } +-- +1.9.1 + + +From 96d631b30b33312b8041ece09a5660740e9bade3 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 5 Jul 2013 12:14:00 +0200 +Subject: [PATCH 64/96] X11: set windows class name + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index b3fe510..df5fe9b 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -982,8 +982,10 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + { + CreateIconPixmap(); + XWMHints *wm_hints; ++ XClassHint *class_hints; + XTextProperty windowName, iconName; + std::string titleString = "XBMC Media Center"; ++ std::string classString = "xbmc.bin"; + char *title = (char*)titleString.c_str(); + + XStringListToTextProperty(&title, 1, &windowName); +@@ -994,10 +996,15 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + wm_hints->icon_pixmap = m_icon; + wm_hints->flags = StateHint | IconPixmapHint; + ++ class_hints = XAllocClassHint(); ++ class_hints->res_class = (char*)classString.c_str(); ++ class_hints->res_name = (char*)classString.c_str(); ++ + XSync(m_dpy,False); + XSetWMProperties(m_dpy, m_mainWindow, &windowName, &iconName, + NULL, 0, NULL, wm_hints, +- NULL); ++ class_hints); ++ XFree(class_hints); + XFree(wm_hints); + + // register interest in the delete window message +-- +1.9.1 + + +From 2594e2e409853924926bc3330d3bee0280c2c298 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 25 Jul 2013 17:18:13 +0200 +Subject: [PATCH 65/96] ActiveAE: slightly reduce buffer size + +--- + xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +index 3b7dbe1..6c5acfb 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +@@ -30,8 +30,8 @@ using namespace ActiveAE; + #include "settings/AdvancedSettings.h" + #include "windowing/WindowingFactory.h" + +-#define MAX_CACHE_LEVEL 0.5 // total cache time of stream in seconds +-#define MAX_WATER_LEVEL 0.25 // buffered time after stream stages in seconds ++#define MAX_CACHE_LEVEL 0.4 // total cache time of stream in seconds ++#define MAX_WATER_LEVEL 0.2 // buffered time after stream stages in seconds + #define MAX_BUFFER_TIME 0.1 // max time of a buffer in seconds + + void CEngineStats::Reset(unsigned int sampleRate) +-- +1.9.1 + + +From fd891b820c51301bda8391b1b599d4b10a44648f Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sun, 4 Aug 2013 10:11:16 +0200 +Subject: [PATCH 66/96] Revert "vdpau: comment some features that will be added + later" + +This reverts commit e00b4f65864d623ab4d2e9e5c06db138e661f1cf. +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +index cd72cc6..351586a 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +@@ -1117,8 +1117,7 @@ int CDecoder::Decode(AVCodecContext *avctx, AVFrame *pFrame) + m_bufferStats.IncDecoded(); + m_vdpauOutput.m_dataPort.SendOutMessage(COutputDataProtocol::NEWFRAME, &pic, sizeof(pic)); + +- //TODO +- // m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC); ++ m_codecControl = pic.DVDPic.iFlags & (DVP_FLAG_DRAIN | DVP_FLAG_NO_POSTPROC); + } + + int retval = 0; +@@ -2311,8 +2310,7 @@ void CMixer::InitCycle() + int flags; + uint64_t latency; + m_config.stats->GetParams(latency, flags); +- // TODO +- if (0) //flags & DVP_FLAG_NO_POSTPROC) ++ if (flags & DVP_FLAG_NO_POSTPROC) + SetPostProcFeatures(false); + else + SetPostProcFeatures(true); +@@ -2324,8 +2322,7 @@ void CMixer::InitCycle() + bool interlaced = m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_INTERLACED; + m_SeenInterlaceFlag |= interlaced; + +- // TODO +- if (//!(flags & DVP_FLAG_NO_POSTPROC) && ++ if (!(flags & DVP_FLAG_NO_POSTPROC) && + (mode == VS_DEINTERLACEMODE_FORCE || + (mode == VS_DEINTERLACEMODE_AUTO && interlaced))) + { +@@ -2347,8 +2344,7 @@ void CMixer::InitCycle() + m_config.stats->SetCanSkipDeint(true); + } + +- // TODO +- if (0) //m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_DROPDEINT) ++ if (m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_DROPDEINT) + { + m_mixersteps = 1; + } +-- +1.9.1 + + +From 86b169528568416e4fe5a1dc718021d06ff78d26 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 9 Aug 2013 18:01:40 +0200 +Subject: [PATCH 67/96] X11: fix keysyms + +--- + xbmc/windowing/WinEventsX11.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index e4ca56d..b20130c 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -461,7 +461,7 @@ bool CWinEventsX11Imp::MessagePump() + if (keys.length() > 0) + { + newEvent.key.keysym.scancode = xevent.xkey.keycode; +- xkeysym = XLookupKeysym(&xevent.xkey, 0); ++ XLookupString(&xevent.xkey, NULL, 0, &xkeysym, NULL); + newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); + newEvent.key.keysym.unicode = keys[keys.length() - 1]; + newEvent.key.state = xevent.xkey.state; +-- +1.9.1 + + +From c7461145c0659e131b23fcc129739a1b06da1495 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 9 Aug 2013 18:42:36 +0200 +Subject: [PATCH 68/96] X11: fix keysym for non-IM + +--- + xbmc/windowing/WinEventsX11.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index b20130c..a38890c 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -408,7 +408,7 @@ bool CWinEventsX11Imp::MessagePump() + { + static XComposeStatus state; + char keybuf[32]; +- xkeysym = XLookupKeysym(&xevent.xkey, 0); ++ XLookupString(&xevent.xkey, NULL, 0, &xkeysym, NULL); + newEvent.key.keysym.sym = LookupXbmcKeySym(xkeysym); + newEvent.key.keysym.scancode = xevent.xkey.keycode; + newEvent.key.state = xevent.xkey.state; +-- +1.9.1 + + +From ea94f4df86043896ad7ae622411aba08bfb1b80d Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sat, 10 Aug 2013 11:18:16 +0200 +Subject: [PATCH] add some missing multi media keys + +--- + system/keymaps/keyboard.xml | 3 +++ + xbmc/input/XBMC_keytable.cpp | 4 ++++ + xbmc/input/XBMC_vkeys.h | 1 + + 3 files changed, 8 insertions(+) + +diff --git a/system/keymaps/keyboard.xml b/system/keymaps/keyboard.xml +index 45682a2..01f7904 100644 +--- a/system/keymaps/keyboard.xml ++++ b/system/keymaps/keyboard.xml +@@ -119,6 +119,9 @@ + SkipPrevious + Stop + Pause ++ FastForward ++ Rewind ++ + + XBMC.ActivateWindow(MyMusic) + ActivateWindow(MyPrograms) +diff --git a/xbmc/input/XBMC_keytable.cpp b/xbmc/input/XBMC_keytable.cpp +index 53b9dce..834cccb 100644 +--- a/xbmc/input/XBMC_keytable.cpp ++++ b/xbmc/input/XBMC_keytable.cpp +@@ -184,6 +184,10 @@ static const XBMCKEYTABLE XBMCKeyTable[] = + , { XBMCK_LAUNCH_MEDIA_CENTER, 0, 0, XBMCVK_LAUNCH_MEDIA_CENTER, "launch_media_center" } + , { XBMCK_PLAY, 0, 0, XBMCVK_MEDIA_PLAY_PAUSE, "play_pause" } + , { XBMCK_STOP, 0, 0, XBMCVK_MEDIA_STOP, "stop" } ++, { XBMCK_REWIND, 0, 0, XBMCVK_MEDIA_REWIND, "rewind" } ++, { XBMCK_FASTFORWARD, 0, 0, XBMCVK_MEDIA_FASTFORWARD, "fastforward" } ++, { XBMCK_RECORD, 0, 0, XBMCVK_MEDIA_RECORD, "record" } ++ + + // Function keys + , { XBMCK_F1, 0, 0, XBMCVK_F1, "f1"} +diff --git a/xbmc/input/XBMC_vkeys.h b/xbmc/input/XBMC_vkeys.h +index 00437db..981c62a 100644 +--- a/xbmc/input/XBMC_vkeys.h ++++ b/xbmc/input/XBMC_vkeys.h +@@ -190,6 +190,7 @@ typedef enum { + XBMCVK_LAUNCH_MEDIA_CENTER = 0xC3, + XBMCVK_MEDIA_REWIND = 0xC4, + XBMCVK_MEDIA_FASTFORWARD = 0xC5, ++ XBMCVK_MEDIA_RECORD = 0xC6, + + XBMCVK_LCONTROL = 0xD0, + XBMCVK_RCONTROL = 0xD1, +-- +1.9.1 + + +From 0112e8256276aa87c5587cd53914eb3b84b3e53a Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sat, 10 Aug 2013 15:53:45 +0200 +Subject: [PATCH 70/96] X11: squash multi + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index df5fe9b..d8e04d6 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -437,7 +437,7 @@ void CWinSystemX11::GetConnectedOutputs(std::vector *outputs) + + bool CWinSystemX11::IsCurrentOutput(CStdString output) + { +- return m_currentOutput.Equals(output); ++ return output.Equals("Default") || m_currentOutput.Equals(output); + } + + bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) +-- +1.9.1 + + +From 60af8bad18fc0b752ff179039d0410401fdbcad2 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 3 Sep 2013 20:46:17 +0200 +Subject: [PATCH 71/96] X11: do not poll default monitor + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index d8e04d6..01f5272 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -722,7 +722,7 @@ void CWinSystemX11::NotifyXRREvent(bool poll) + if (poll) + { + CStdString output = CSettings::Get().GetString("videoscreen.monitor"); +- if (output.Equals(m_currentOutput) || m_userOutput.Equals("Default")) ++ if (output.Equals(m_currentOutput) || output.Equals("Default")) + return; + + int numScreens = XScreenCount(m_dpy); +-- +1.9.1 + + +From 0a2561c6afe499cea97e6f806db3a0be47eba77e Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 29 Oct 2013 20:57:28 +0100 +Subject: [PATCH 72/96] X11: fix broken monitor switching + +--- + system/settings/settings.xml | 1 - + xbmc/settings/DisplaySettings.cpp | 40 ++++++++++++++++++++++++++------------- + 2 files changed, 27 insertions(+), 14 deletions(-) + +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 798be52..890bb10 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -2304,7 +2304,6 @@ + -1 + + +- + + + +diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp +index efb6cb1..da5873f 100644 +--- a/xbmc/settings/DisplaySettings.cpp ++++ b/xbmc/settings/DisplaySettings.cpp +@@ -219,8 +219,7 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting) + + const std::string &settingId = setting->GetId(); + if (settingId == "videoscreen.resolution" || +- settingId == "videoscreen.screen" || +- settingId == "videoscreen.monitor") ++ settingId == "videoscreen.screen") + { + RESOLUTION newRes = RES_DESKTOP; + if (settingId == "videoscreen.resolution") +@@ -236,11 +235,6 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting) + // get desktop resolution for screen + newRes = GetResolutionForScreen(); + } +- else if (settingId == "videoscreen.monitor") +- { +- g_Windowing.UpdateResolutions(); +- newRes = GetResolutionForScreen(); +- } + + string screenmode = GetStringFromResolution(newRes); + CSettings::Get().SetString("videoscreen.screenmode", screenmode); +@@ -251,11 +245,7 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting) + RESOLUTION newRes = GetResolutionFromString(((CSettingString*)setting)->GetValue()); + + SetCurrentResolution(newRes, false); +- bool outputChanged = false; +-#if defined(HAS_GLX) +- outputChanged = !g_Windowing.IsCurrentOutput(CSettings::Get().GetString("videoscreen.monitor")); +-#endif +- g_graphicsContext.SetVideoResolution(newRes, outputChanged); ++ g_graphicsContext.SetVideoResolution(newRes); + + // check if the old or the new resolution was/is windowed + // in which case we don't show any prompt to the user +@@ -274,6 +264,28 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting) + m_resolutionChangeAborted = false; + } + } ++ else if (settingId == "videoscreen.monitor") ++ { ++ g_Windowing.UpdateResolutions(); ++ RESOLUTION newRes = GetResolutionForScreen(); ++ ++ SetCurrentResolution(newRes, false); ++ g_graphicsContext.SetVideoResolution(newRes, true); ++ ++ if (!m_resolutionChangeAborted) ++ { ++ bool cancelled = false; ++ if (!CGUIDialogYesNo::ShowAndGetInput(13110, 13111, 20022, 20022, -1, -1, cancelled, 10000)) ++ { ++ m_resolutionChangeAborted = true; ++ return false; ++ } ++ } ++ else ++ m_resolutionChangeAborted = false; ++ ++ return true; ++ } + else if (settingId == "videoscreen.monitorsingle") + { + g_Windowing.UpdateResolutions(); +@@ -708,9 +720,11 @@ void CDisplaySettings::SettingOptionsMonitorsFiller(const CSetting *setting, std + #if defined(HAS_GLX) + std::vector monitors; + g_Windowing.GetConnectedOutputs(&monitors); ++ std::string currentMonitor = CSettings::Get().GetString("videoscreen.monitor"); + for (unsigned int i=0; i +Date: Tue, 29 Oct 2013 20:57:59 +0100 +Subject: [PATCH 73/96] X11: remove polling for connected outputs, use xrr + events + +--- + xbmc/windowing/WinEventsX11.cpp | 44 +++++++++++---------- + xbmc/windowing/WinEventsX11.h | 1 - + xbmc/windowing/X11/WinSystemX11.cpp | 76 ++++++++++++++----------------------- + xbmc/windowing/X11/WinSystemX11.h | 8 ++-- + 4 files changed, 58 insertions(+), 71 deletions(-) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index a38890c..fe91a2b 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -213,7 +213,6 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win) + WinEvents->m_wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + WinEvents->m_structureChanged = false; + WinEvents->m_xrrEventPending = false; +- WinEvents->m_xrrPollTimer.Set(3000); + + // open input method + char *old_locale = NULL, *old_modifiers = NULL; +@@ -280,7 +279,11 @@ bool CWinEventsX11Imp::Init(Display *dpy, Window win) + #if defined(HAS_XRANDR) + int iReturn; + XRRQueryExtension(WinEvents->m_display, &WinEvents->m_RREventBase, &iReturn); +- XRRSelectInput(WinEvents->m_display, WinEvents->m_window, RRScreenChangeNotifyMask); ++ int numScreens = XScreenCount(WinEvents->m_display); ++ for (int i = 0; i < numScreens; i++) ++ { ++ XRRSelectInput(WinEvents->m_display, RootWindow(WinEvents->m_display, i), RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask); ++ } + #endif + + return true; +@@ -328,6 +331,26 @@ bool CWinEventsX11Imp::MessagePump() + memset(&xevent, 0, sizeof (XEvent)); + XNextEvent(WinEvents->m_display, &xevent); + ++#if defined(HAS_XRANDR) ++ if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRScreenChangeNotify)) ++ { ++ XRRUpdateConfiguration(&xevent); ++ if (xevent.xgeneric.serial != serial) ++ g_Windowing.NotifyXRREvent(); ++ WinEvents->m_xrrEventPending = false; ++ serial = xevent.xgeneric.serial; ++ continue; ++ } ++ else if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRNotify)) ++ { ++ if (xevent.xgeneric.serial != serial) ++ g_Windowing.NotifyXRREvent(); ++ WinEvents->m_xrrEventPending = false; ++ serial = xevent.xgeneric.serial; ++ continue; ++ } ++#endif ++ + if (XFilterEvent(&xevent, WinEvents->m_window)) + continue; + +@@ -575,18 +598,6 @@ bool CWinEventsX11Imp::MessagePump() + break; + } + }// switch event.type +- +-#if defined(HAS_XRANDR) +- if (WinEvents && (xevent.type == WinEvents->m_RREventBase + RRScreenChangeNotify)) +- { +- XRRUpdateConfiguration(&xevent); +- if (xevent.xgeneric.serial != serial) +- g_Windowing.NotifyXRREvent(); +- WinEvents->m_xrrEventPending = false; +- serial = xevent.xgeneric.serial; +- } +-#endif +- + }// while + + #if defined(HAS_XRANDR) +@@ -596,11 +607,6 @@ bool CWinEventsX11Imp::MessagePump() + g_Windowing.NotifyXRREvent(); + WinEvents->m_xrrEventPending = false; + } +- else if (!g_application.m_pPlayer->IsPlaying() && WinEvents && WinEvents->m_xrrPollTimer.IsTimePast()) +- { +- g_Windowing.NotifyXRREvent(true); +- WinEvents->m_xrrPollTimer.Set(3000); +- } + #endif + + #ifdef HAS_SDL_JOYSTICK +diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h +index 91a604f..6429291 100644 +--- a/xbmc/windowing/WinEventsX11.h ++++ b/xbmc/windowing/WinEventsX11.h +@@ -62,6 +62,5 @@ protected: + bool m_structureChanged; + int m_RREventBase; + XbmcThreads::EndTime m_xrrFailSafeTimer; +- XbmcThreads::EndTime m_xrrPollTimer; + bool m_xrrEventPending; + }; +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 01f5272..442efa6 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -168,8 +168,21 @@ bool CWinSystemX11::DestroyWindow() + + bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) + { ++ m_userOutput = CSettings::Get().GetString("videoscreen.monitor"); ++ if (m_userOutput.compare("Default") == 0) ++ { ++ std::vector outputs = g_xrandr.GetModes(); ++ if (outputs.size() > 0) ++ { ++ m_userOutput = outputs[0].name; ++ } ++ } ++ ++ m_userOutput = g_xrandr.GetModes()[0].name; ++ + if(m_nWidth == newWidth +- && m_nHeight == newHeight) ++ && m_nHeight == newHeight ++ && m_userOutput.compare(m_currentOutput) == 0) + return true; + + if (!SetWindow(newWidth, newHeight, false, m_userOutput)) +@@ -255,33 +268,23 @@ void CWinSystemX11::UpdateResolutions() + + bool switchOnOff = CSettings::Get().GetBool("videoscreen.monitorsingle"); + m_userOutput = CSettings::Get().GetString("videoscreen.monitor"); +- if (m_userOutput.Equals("Default")) ++ if (m_userOutput.compare("Default") == 0) + switchOnOff = false; + + if(g_xrandr.Query(true, !switchOnOff)) + { +- // check if the monitor is connected +- // might take a while when connected to a receiver +- XbmcThreads::EndTime timeout(3000); + XOutput *out = NULL; +- while (!m_userOutput.Equals("Default") && !timeout.IsTimePast()) ++ if (m_userOutput.compare("Default") != 0) + { + out = g_xrandr.GetOutput(m_userOutput); + if (out) + { + XMode mode = g_xrandr.GetCurrentMode(m_userOutput); +- if (mode.isCurrent || switchOnOff) +- break; +- else ++ if (!mode.isCurrent && !switchOnOff) + { + out = NULL; +- break; + } + } +- +- Sleep(500); +- if (!g_xrandr.Query(true, !switchOnOff)) +- break; + } + if (!out) + { +@@ -289,17 +292,16 @@ void CWinSystemX11::UpdateResolutions() + out = g_xrandr.GetOutput(m_userOutput); + } + +- // switch on output +- if(switchOnOff) +- g_xrandr.TurnOnOutput(m_userOutput); +- +- // switch off other outputs if desired + if (switchOnOff) + { ++ // switch on output ++ g_xrandr.TurnOnOutput(m_userOutput); ++ ++ // switch off other outputs + std::vector outputs = g_xrandr.GetModes(); + for (int i=0; i *outputs) + + bool CWinSystemX11::IsCurrentOutput(CStdString output) + { +- return output.Equals("Default") || m_currentOutput.Equals(output); ++ return (output.Equals("Default")) || (m_currentOutput.compare(output) == 0); + } + + bool CWinSystemX11::IsSuitableVisual(XVisualInfo *vInfo) +@@ -715,34 +717,14 @@ void CWinSystemX11::CheckDisplayEvents() + #endif + } + +-void CWinSystemX11::NotifyXRREvent(bool poll) ++void CWinSystemX11::NotifyXRREvent() + { +- // we may not get an event if desired monitor becomes available +- // hence we need to poll +- if (poll) +- { +- CStdString output = CSettings::Get().GetString("videoscreen.monitor"); +- if (output.Equals(m_currentOutput) || output.Equals("Default")) +- return; +- +- int numScreens = XScreenCount(m_dpy); +- g_xrandr.SetNumScreens(numScreens); +- g_xrandr.Query(true); +- if (!g_xrandr.IsOutputConnected(output)) +- return; +- +- // if output is turned off by user, respect it +- XMode mode = g_xrandr.GetCurrentMode(output); +- if (!mode.isCurrent) +- return; +- } +- +- CLog::Log(LOGDEBUG, "%s - notify display reset event, poll: %d", __FUNCTION__, poll); ++ CLog::Log(LOGDEBUG, "%s - notify display reset event", __FUNCTION__); + m_windowDirty = true; + + CSingleLock lock(g_graphicsContext); + +- if (!g_xrandr.Query(!poll)) ++ if (!g_xrandr.Query(true)) + { + CLog::Log(LOGERROR, "WinSystemX11::RefreshWindow - failed to query xrandr"); + return; +@@ -839,14 +821,14 @@ bool CWinSystemX11::EnableFrameLimiter() + return m_minimized; + } + +-bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStdString &output) ++bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std::string &output) + { + bool changeWindow = false; + bool changeSize = false; + bool mouseActive = false; + float mouseX, mouseY; + +- if (m_mainWindow && ((m_bFullScreen != fullscreen) || !m_currentOutput.Equals(output) || m_windowDirty)) ++ if (m_mainWindow && ((m_bFullScreen != fullscreen) || m_currentOutput.compare(output) != 0 || m_windowDirty)) + { + mouseActive = g_Mouse.IsActive(); + if (mouseActive) +@@ -1035,7 +1017,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const CStd + m_bIsGrabbed = false; + + CDirtyRegionList dr; +- RefreshGlxContext(!m_currentOutput.Equals(output)); ++ RefreshGlxContext(m_currentOutput.compare(output) != 0); + XSync(m_dpy, FALSE); + g_graphicsContext.Clear(0); + g_graphicsContext.Flip(dr); +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 7ec5be4..14622cb 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -70,7 +70,7 @@ public: + Display* GetDisplay() { return m_dpy; } + GLXWindow GetWindow() { return m_glWindow; } + GLXContext GetGlxContext() { return m_glContext; } +- void NotifyXRREvent(bool poll = false); ++ void NotifyXRREvent(); + void GetConnectedOutputs(std::vector *outputs); + bool IsCurrentOutput(CStdString output); + void NotifyMouseCoverage(bool covered); +@@ -79,7 +79,7 @@ protected: + bool RefreshGlxContext(bool force); + void CheckDisplayEvents(); + void OnLostDevice(); +- bool SetWindow(int width, int height, bool fullscreen, const CStdString &output); ++ bool SetWindow(int width, int height, bool fullscreen, const std::string &output); + + Window m_glWindow, m_mainWindow; + GLXContext m_glContext; +@@ -95,8 +95,8 @@ protected: + CCriticalSection m_resourceSection; + std::vector m_resources; + uint64_t m_dpyLostTime; +- CStdString m_currentOutput; +- CStdString m_userOutput; ++ std::string m_currentOutput; ++ std::string m_userOutput; + bool m_windowDirty; + bool m_bIsInternalXrr; + bool m_newGlContext; +-- +1.9.1 + + +From e84bb7507d0ed31b25ab3a2124b57b44e768e3d3 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 31 Oct 2013 09:37:13 +0100 +Subject: [PATCH 74/96] X11: remove grabbing of keyboard and mouse + +--- + xbmc/windowing/WinEventsX11.cpp | 4 ---- + xbmc/windowing/X11/WinSystemX11.cpp | 40 ------------------------------------- + xbmc/windowing/X11/WinSystemX11.h | 2 -- + 3 files changed, 46 deletions(-) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index fe91a2b..550c84d 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -538,16 +538,12 @@ bool CWinEventsX11Imp::MessagePump() + + case EnterNotify: + { +- if (xevent.xcrossing.mode == NotifyNormal) +- g_Windowing.NotifyMouseCoverage(true); + break; + } + + // lose mouse coverage + case LeaveNotify: + { +- if (xevent.xcrossing.mode == NotifyNormal) +- g_Windowing.NotifyMouseCoverage(false); + g_Mouse.SetActive(false); + break; + } +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 442efa6..695b352 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -153,8 +153,6 @@ bool CWinSystemX11::DestroyWindow() + + XUnmapWindow(m_dpy, m_mainWindow); + XSync(m_dpy,TRUE); +- XUngrabKeyboard(m_dpy, CurrentTime); +- XUngrabPointer(m_dpy, CurrentTime); + XDestroyWindow(m_dpy, m_glWindow); + XDestroyWindow(m_dpy, m_mainWindow); + m_glWindow = 0; +@@ -628,30 +626,6 @@ void CWinSystemX11::NotifyAppFocusChange(bool bGaining) + m_bIgnoreNextFocusMessage = false; + } + +-void CWinSystemX11::NotifyMouseCoverage(bool covered) +-{ +- if (!m_bFullScreen || !m_mainWindow) +- return; +- +- if (covered && !m_bIsGrabbed) +- { +- int result = -1; +- while (result != GrabSuccess && result != AlreadyGrabbed) +- { +- result = XGrabPointer(m_dpy, m_mainWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); +- XbmcThreads::ThreadSleep(100); +- } +- XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); +- m_bIsGrabbed = true; +- } +- else if (!covered && m_bIsGrabbed) +- { +- XUngrabKeyboard(m_dpy, CurrentTime); +- XUngrabPointer(m_dpy, CurrentTime); +- m_bIsGrabbed = false; +- } +-} +- + bool CWinSystemX11::Minimize() + { + m_bWasFullScreenBeforeMinimize = m_bFullScreen; +@@ -1002,20 +976,6 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std: + XWarpPointer(m_dpy, None, m_mainWindow, 0, 0, 0, 0, mouseX*width, mouseY*height); + } + +- if (fullscreen) +- { +- int result = -1; +- while (result != GrabSuccess && result != AlreadyGrabbed) +- { +- result = XGrabPointer(m_dpy, m_mainWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); +- XbmcThreads::ThreadSleep(100); +- } +- XGrabKeyboard(m_dpy, m_mainWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); +- m_bIsGrabbed = true; +- } +- else +- m_bIsGrabbed = false; +- + CDirtyRegionList dr; + RefreshGlxContext(m_currentOutput.compare(output) != 0); + XSync(m_dpy, FALSE); +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index 14622cb..d1c8729 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -73,7 +73,6 @@ public: + void NotifyXRREvent(); + void GetConnectedOutputs(std::vector *outputs); + bool IsCurrentOutput(CStdString output); +- void NotifyMouseCoverage(bool covered); + + protected: + bool RefreshGlxContext(bool force); +@@ -90,7 +89,6 @@ protected: + bool m_bWasFullScreenBeforeMinimize; + bool m_minimized; + bool m_bIgnoreNextFocusMessage; +- bool m_bIsGrabbed; + int m_RREventBase; + CCriticalSection m_resourceSection; + std::vector m_resources; +-- +1.9.1 + + +From 3ead8999a2b3509f552b4a0f6be22df4f7b3954f Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 31 Oct 2013 10:46:40 +0100 +Subject: [PATCH 75/96] X11: set ExposureMask on gl window, fixes not updated + areas + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 695b352..e55583c 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -884,8 +884,8 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std: + + swa.override_redirect = False; + swa.border_pixel = 0; +- swa.event_mask = 0; +- mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWColormap; ++ swa.event_mask = ExposureMask; ++ mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWColormap | CWEventMask; + + m_glWindow = XCreateWindow(m_dpy, m_mainWindow, + 0, 0, width, height, 0, vi->depth, +-- +1.9.1 + + +From 56dcd536fd8135ec06ef4cf317db86858ead89c8 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 31 Oct 2013 11:25:19 +0100 +Subject: [PATCH 76/96] X11: drop shortcuts, have WM do this + +--- + xbmc/windowing/WinEventsX11.cpp | 21 --------------------- + xbmc/windowing/WinEventsX11.h | 1 - + 2 files changed, 22 deletions(-) + +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index 550c84d..a5b4ba2 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -678,10 +678,6 @@ bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event) + break; + } + event.key.keysym.mod = (XBMCMod)WinEvents->m_keymodState; +- +- bool ret = ProcessShortcuts(event); +- if (ret) +- return ret; + } + else if (event.type == XBMC_KEYUP) + { +@@ -723,23 +719,6 @@ bool CWinEventsX11Imp::ProcessKey(XBMC_Event &event) + return g_application.OnEvent(event); + } + +-bool CWinEventsX11Imp::ProcessShortcuts(XBMC_Event& event) +-{ +- if (event.key.keysym.mod & XBMCKMOD_ALT) +- { +- switch(event.key.keysym.sym) +- { +- case XBMCK_TAB: // ALT+TAB to minimize/hide +- g_application.Minimize(); +- return true; +- +- default: +- return false; +- } +- } +- return false; +-} +- + XBMCKey CWinEventsX11Imp::LookupXbmcKeySym(KeySym keysym) + { + // try direct mapping first +diff --git a/xbmc/windowing/WinEventsX11.h b/xbmc/windowing/WinEventsX11.h +index 6429291..4334d21 100644 +--- a/xbmc/windowing/WinEventsX11.h ++++ b/xbmc/windowing/WinEventsX11.h +@@ -48,7 +48,6 @@ public: + protected: + static XBMCKey LookupXbmcKeySym(KeySym keysym); + static bool ProcessKey(XBMC_Event &event); +- static bool ProcessShortcuts(XBMC_Event& event); + static CWinEventsX11Imp *WinEvents; + Display *m_display; + Window m_window; +-- +1.9.1 + + +From 7c7bd83bede5ceaaca6e153486bef8d66662c4c5 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 7 Nov 2013 15:02:00 +0100 +Subject: [PATCH 77/96] X11: adapt to new settings + +--- + system/settings/settings.xml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 890bb10..124a14d 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -2264,6 +2264,7 @@ + HAS_GLX + 0 + false ++ + + + 0 +-- +1.9.1 + + +From 97bc3eb5a047e69019c70221d35e478c4b66a363 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 14 Nov 2013 09:28:24 +0100 +Subject: [PATCH 78/96] X11: adapt to changes in cstdstring + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 4 ++-- + xbmc/windowing/X11/XRandR.cpp | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index e55583c..9962f08 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -369,8 +369,8 @@ void CWinSystemX11::UpdateResolutions() + + CLog::Log(LOGINFO, "Pixel Ratio: %f", res.fPixelRatio); + +- res.strMode = StringUtils::Format("%s: %s @ %.2fHz", out.name.c_str(), mode.name.c_str(), mode.hz); +- res.strOutput = out.name; ++ res.strMode = StringUtils::Format("%s: %s @ %.2fHz", out->name.c_str(), mode.name.c_str(), mode.hz); ++ res.strOutput = out->name; + res.strId = mode.id; + res.iSubtitles = (int)(0.965*mode.h); + res.fRefreshRate = mode.hz; +diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp +index 8525ede..c94f2e3 100644 +--- a/xbmc/windowing/X11/XRandR.cpp ++++ b/xbmc/windowing/X11/XRandR.cpp +@@ -74,7 +74,7 @@ bool CXRandR::Query(bool force, int screennum, bool ignoreoff) + CStdString cmd; + cmd = getenv("XBMC_BIN_HOME"); + cmd += "/xbmc-xrandr"; +- cmd.AppendFormat(" -q --screen %d", screennum); ++ cmd = StringUtils::Format("%s -q --screen %d", cmd.c_str(), screennum); + + FILE* file = popen(cmd.c_str(),"r"); + if (!file) +@@ -156,7 +156,7 @@ bool CXRandR::TurnOffOutput(CStdString name) + CStdString cmd; + cmd = getenv("XBMC_BIN_HOME"); + cmd += "/xbmc-xrandr"; +- cmd.AppendFormat(" --screen %d --output %s --off", output->screen, name.c_str()); ++ cmd = StringUtils::Format("%s --screen %d --output %s --off", cmd.c_str(), output->screen, name.c_str()); + + int status = system(cmd.c_str()); + if (status == -1) +-- +1.9.1 + + +From 2ec9169c90eb33866d139a09b38ff04018cae905 Mon Sep 17 00:00:00 2001 +From: Marcel Groothuis +Date: Thu, 5 Dec 2013 22:02:50 +0100 +Subject: [PATCH 80/96] ffmpeg demuxer: faster channel change for PVR addons + without internal demuxing (such as MediaPortal, ArgusTV, MythTV, NextPVR) + Credits: FernetMenta, Davilla, Popcornmix, Whaupt + +--- + .../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 143 ++++++++++++++++++--- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 5 +- + .../dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp | 13 +- + 3 files changed, 139 insertions(+), 22 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index afa3024..3409b67 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -51,6 +51,8 @@ + #include "utils/StringUtils.h" + #include "URL.h" + ++#define FF_MAX_EXTRADATA_SIZE ((1 << 28) - FF_INPUT_BUFFER_PADDING_SIZE) ++ + void CDemuxStreamAudioFFmpeg::GetStreamInfo(std::string& strInfo) + { + if(!m_stream) return; +@@ -217,6 +219,7 @@ CDVDDemuxFFmpeg::CDVDDemuxFFmpeg() : CDVDDemux() + m_program = UINT_MAX; + m_pkt.result = -1; + memset(&m_pkt.pkt, 0, sizeof(AVPacket)); ++ m_streaminfo = true; /* set to true if we want to look for streams before playback */ + } + + CDVDDemuxFFmpeg::~CDVDDemuxFFmpeg() +@@ -237,10 +240,11 @@ bool CDVDDemuxFFmpeg::Aborted() + return false; + } + +-bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) ++bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo) + { + AVInputFormat* iformat = NULL; + std::string strFile; ++ m_streaminfo = streaminfo; + m_iCurrentPts = DVD_NOPTS_VALUE; + m_speed = DVD_PLAYSPEED_NORMAL; + m_program = UINT_MAX; +@@ -259,8 +263,6 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) + m_pInput = pInput; + strFile = m_pInput->GetFileName(); + +- bool streaminfo = true; /* set to true if we want to look for streams before playback*/ +- + if( m_pInput->GetContent().length() > 0 ) + { + std::string content = m_pInput->GetContent(); +@@ -450,13 +452,12 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) + m_bMatroska = strncmp(m_pFormatContext->iformat->name, "matroska", 8) == 0; // for "matroska.webm" + m_bAVI = strcmp(m_pFormatContext->iformat->name, "avi") == 0; + +- if (streaminfo) ++ if (m_streaminfo) + { +- /* too speed up dvd switches, only analyse very short */ ++ /* to speed up dvd switches, only analyse very short */ + if(m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD)) + m_pFormatContext->max_analyze_duration = 500000; + +- + CLog::Log(LOGDEBUG, "%s - avformat_find_stream_info starting", __FUNCTION__); + int iErr = m_dllAvFormat.avformat_find_stream_info(m_pFormatContext, NULL); + if (iErr < 0) +@@ -476,6 +477,9 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) + } + CLog::Log(LOGDEBUG, "%s - av_find_stream_info finished", __FUNCTION__); + } ++ else ++ m_program = 0; ++ + // reset any timeout + m_timeout.SetInfinite(); + +@@ -533,7 +537,7 @@ void CDVDDemuxFFmpeg::Reset() + { + CDVDInputStream* pInputStream = m_pInput; + Dispose(); +- Open(pInputStream); ++ Open(pInputStream, m_streaminfo); + } + + void CDVDDemuxFFmpeg::Flush() +@@ -728,25 +732,32 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() + } + else + { ++ ParsePacket(&m_pkt.pkt); ++ + AVStream *stream = m_pFormatContext->streams[m_pkt.pkt.stream_index]; + +- if (m_program != UINT_MAX) ++ if (IsVideoReady()) + { +- /* check so packet belongs to selected program */ +- for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) ++ if (m_program != UINT_MAX) + { +- if(m_pkt.pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i]) ++ /* check so packet belongs to selected program */ ++ for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) + { +- pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); +- break; ++ if(m_pkt.pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i]) ++ { ++ pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); ++ break; ++ } + } +- } + +- if (!pPacket) +- bReturnEmpty = true; ++ if (!pPacket) ++ bReturnEmpty = true; ++ } ++ else ++ pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); + } + else +- pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); ++ bReturnEmpty = true; + + if (pPacket) + { +@@ -1684,3 +1695,101 @@ bool CDVDDemuxFFmpeg::IsProgramChange() + } + return false; + } ++ ++void CDVDDemuxFFmpeg::ParsePacket(AVPacket *pkt) ++{ ++ AVStream *st = m_pFormatContext->streams[pkt->stream_index]; ++ CDemuxStream *stream = GetStreamInternal(pkt->stream_index); ++ ++ // if the stream is new, tell ffmpeg to parse the stream ++ if (!stream && !st->parser) ++ { ++ st->need_parsing = AVSTREAM_PARSE_FULL; ++ } ++ ++ // split extradata ++ if(st->parser && st->parser->parser->split && !st->codec->extradata) ++ { ++ int i = st->parser->parser->split(st->codec, pkt->data, pkt->size); ++ if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) ++ { ++ // Found extradata, fill it in. This will cause ++ // a new stream to be created and used. ++ st->codec->extradata_size = i; ++ st->codec->extradata = (uint8_t*)av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); ++ if (st->codec->extradata) ++ { ++ CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::Read() fetching extradata, extradata_size(%d)", st->codec->extradata_size); ++ memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size); ++ memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE); ++ } ++ else ++ { ++ st->codec->extradata_size = 0; ++ } ++ } ++ } ++ ++ // for video we need a decoder to get desired information into codec context ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ++ (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) ++ { ++ // open a decoder, it will be cleared down by ffmpeg on closing the stream ++ if (!st->codec->codec) ++ { ++ const AVCodec* codec; ++ AVDictionary *thread_opt = NULL; ++ codec = avcodec_find_decoder(st->codec->codec_id); ++ // Force thread count to 1 since the h264 decoder will not extract ++ // SPS and PPS to extradata during multi-threaded decoding ++ av_dict_set(&thread_opt, "threads", "1", 0); ++ avcodec_open2(st->codec, codec, &thread_opt); ++ ++ av_dict_free(&thread_opt); ++ } ++ ++ // We don't need to actually decode here ++ // we just want to transport SPS data into codec context ++ st->codec->skip_idct = AVDISCARD_ALL; ++ st->codec->skip_frame = AVDISCARD_ALL; ++ st->codec->skip_loop_filter = AVDISCARD_ALL; ++ ++ // We are looking for an IDR frame ++ AVFrame picture; ++ memset(&picture, 0, sizeof(AVFrame)); ++ picture.pts = picture.pkt_dts = picture.pkt_pts = picture.best_effort_timestamp = AV_NOPTS_VALUE; ++ picture.pkt_pos = -1; ++ picture.key_frame = 1; ++ picture.format = -1; ++ ++ int got_picture = 0; ++ avcodec_decode_video2(st->codec, &picture, &got_picture, pkt); ++ } ++} ++ ++bool CDVDDemuxFFmpeg::IsVideoReady() ++{ ++ AVStream *st; ++ if(m_program != UINT_MAX) ++ { ++ for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) ++ { ++ int idx = m_pFormatContext->programs[m_program]->stream_index[i]; ++ st = m_pFormatContext->streams[idx]; ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ++ (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) ++ return false; ++ } ++ } ++ else ++ { ++ for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++) ++ { ++ st = m_pFormatContext->streams[i]; ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ++ (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) ++ return false; ++ } ++ } ++ return true; ++} +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +index 35abbdf..acde9a8 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +@@ -89,7 +89,7 @@ public: + CDVDDemuxFFmpeg(); + virtual ~CDVDDemuxFFmpeg(); + +- bool Open(CDVDInputStream* pInput); ++ bool Open(CDVDInputStream* pInput, bool streaminfo = true); + void Dispose(); + void Reset(); + void Flush(); +@@ -128,6 +128,8 @@ protected: + CDemuxStream* GetStreamInternal(int iStreamId); + void CreateStreams(unsigned int program = UINT_MAX); + void DisposeStreams(); ++ void ParsePacket(AVPacket *pkt); ++ bool IsVideoReady(); + + AVDictionary *GetFFMpegOptionsFromURL(const CURL &url); + double ConvertTimestamp(int64_t pts, int den, int num); +@@ -162,5 +164,6 @@ protected: + + bool m_bPtsWrap, m_bPtsWrapChecked; + int64_t m_iStartTime, m_iMaxTime, m_iEndTime; ++ bool m_streaminfo; + }; + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp +index ca689d0..f383563 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp +@@ -99,26 +99,31 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) + } + #endif + ++ bool streaminfo = true; /* Look for streams before playback */ + if (pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) + { + CDVDInputStreamPVRManager* pInputStreamPVR = (CDVDInputStreamPVRManager*)pInputStream; + CDVDInputStream* pOtherStream = pInputStreamPVR->GetOtherStream(); ++ ++ /* Don't parse the streaminfo for live streams to reduce the channel switch time */ ++ bool liveStream = (pInputStream->GetFileName().substr(0, 14) == "pvr://channels"); ++ streaminfo = !liveStream; ++ + if(pOtherStream) + { + /* Used for MediaPortal PVR addon (uses PVR otherstream for playback of rtsp streams) */ + if (pOtherStream->IsStreamType(DVDSTREAM_TYPE_FFMPEG)) + { + auto_ptr demuxer(new CDVDDemuxFFmpeg()); +- if(demuxer->Open(pOtherStream)) ++ if(demuxer->Open(pOtherStream, streaminfo)) + return demuxer.release(); + else + return NULL; + } + } + +- std::string filename = pInputStream->GetFileName(); + /* Use PVR demuxer only for live streams */ +- if (filename.substr(0, 14) == "pvr://channels") ++ if (liveStream) + { + boost::shared_ptr client; + if (g_PVRClients->GetPlayingClient(client) && +@@ -134,7 +139,7 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) + } + + auto_ptr demuxer(new CDVDDemuxFFmpeg()); +- if(demuxer->Open(pInputStream)) ++ if(demuxer->Open(pInputStream, streaminfo)) + return demuxer.release(); + else + return NULL; +-- +1.9.1 + + +From 1c6901d50fc7b5d499e423fd2d5721da1913c203 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 14 Nov 2013 20:35:04 +0100 +Subject: [PATCH 81/96] ffmpeg demuxer: make sure we start mpegts video with an + i-frame + +--- + .../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 31 +++++++++++++++++++++- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 1 + + 2 files changed, 31 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index 3409b67..d5da14b 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -448,6 +448,13 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo) + if (iformat && (strcmp(iformat->name, "mjpeg") == 0) && m_ioContext->seekable == 0) + m_pFormatContext->max_analyze_duration = 500000; + ++ bool short_analyze = false; ++ if (iformat && (strcmp(iformat->name, "mpegts") == 0)) ++ { ++ m_pFormatContext->max_analyze_duration = 500000; ++ short_analyze = true; ++ } ++ + // we need to know if this is matroska or avi later + m_bMatroska = strncmp(m_pFormatContext->iformat->name, "matroska", 8) == 0; // for "matroska.webm" + m_bAVI = strcmp(m_pFormatContext->iformat->name, "avi") == 0; +@@ -476,6 +483,12 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo) + } + } + CLog::Log(LOGDEBUG, "%s - av_find_stream_info finished", __FUNCTION__); ++ ++ if (short_analyze) ++ { ++ // make sure we start video with an i-frame ++ ResetVideoStreams(); ++ } + } + else + m_program = 0; +@@ -1731,7 +1744,7 @@ void CDVDDemuxFFmpeg::ParsePacket(AVPacket *pkt) + } + + // for video we need a decoder to get desired information into codec context +- if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->codec->extradata && + (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) + { + // open a decoder, it will be cleared down by ffmpeg on closing the stream +@@ -1793,3 +1806,19 @@ bool CDVDDemuxFFmpeg::IsVideoReady() + } + return true; + } ++ ++void CDVDDemuxFFmpeg::ResetVideoStreams() ++{ ++ AVStream *st; ++ for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++) ++ { ++ st = m_pFormatContext->streams[i]; ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ++ { ++ if (st->codec->extradata) ++ m_dllAvUtil.av_free(st->codec->extradata); ++ st->codec->extradata = NULL; ++ st->codec->width = 0; ++ } ++ } ++} +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +index acde9a8..9ec0877 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +@@ -130,6 +130,7 @@ protected: + void DisposeStreams(); + void ParsePacket(AVPacket *pkt); + bool IsVideoReady(); ++ void ResetVideoStreams(); + + AVDictionary *GetFFMpegOptionsFromURL(const CURL &url); + double ConvertTimestamp(int64_t pts, int den, int num); +-- +1.9.1 + + +From 75043ecb88a683165524d49f5cdd6809af3443fd Mon Sep 17 00:00:00 2001 +From: Wolfgang Haupt +Date: Thu, 5 Dec 2013 22:11:57 +0100 +Subject: [PATCH 82/96] DVDFactoryDemuxer: skip streaminfo for udp tcp and + pvr-channels + +--- + .../dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp | 14 ++++++--- + xbmc/utils/URIUtils.cpp | 35 ++++++++++++++++++++++ + xbmc/utils/URIUtils.h | 4 +++ + 3 files changed, 49 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp +index f383563..d6580fd 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp +@@ -105,9 +105,9 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) + CDVDInputStreamPVRManager* pInputStreamPVR = (CDVDInputStreamPVRManager*)pInputStream; + CDVDInputStream* pOtherStream = pInputStreamPVR->GetOtherStream(); + +- /* Don't parse the streaminfo for live streams to reduce the channel switch time */ +- bool liveStream = (pInputStream->GetFileName().substr(0, 14) == "pvr://channels"); +- streaminfo = !liveStream; ++ /* Don't parse the streaminfo for some cases of streams to reduce the channel switch time */ ++ bool useFastswitch = URIUtils::IsUsingFastSwitch(pInputStream->GetFileName()); ++ streaminfo = !useFastswitch; + + if(pOtherStream) + { +@@ -123,7 +123,7 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) + } + + /* Use PVR demuxer only for live streams */ +- if (liveStream) ++ if (URIUtils::IsPVRChannel(pInputStream->GetFileName())) + { + boost::shared_ptr client; + if (g_PVRClients->GetPlayingClient(client) && +@@ -138,6 +138,12 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) + } + } + ++ if (pInputStream->IsStreamType(DVDSTREAM_TYPE_FFMPEG)) ++ { ++ bool useFastswitch = URIUtils::IsUsingFastSwitch(pInputStream->GetFileName()); ++ streaminfo = !useFastswitch; ++ } ++ + auto_ptr demuxer(new CDVDDemuxFFmpeg()); + if(demuxer->Open(pInputStream, streaminfo)) + return demuxer.release(); +diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp +index fd2eb5a..22932b7 100644 +--- a/xbmc/utils/URIUtils.cpp ++++ b/xbmc/utils/URIUtils.cpp +@@ -788,6 +788,36 @@ bool URIUtils::IsFTP(const CStdString& strFile) + StringUtils::StartsWithNoCase(strFile2, "ftps:"); + } + ++bool URIUtils::IsUDP(const CStdString& strFile) ++{ ++ CStdString strFile2(strFile); ++ ++ if (IsStack(strFile)) ++ strFile2 = CStackDirectory::GetFirstStackedFile(strFile); ++ ++ return StringUtils::StartsWithNoCase(strFile2, "udp:"); ++} ++ ++bool URIUtils::IsTCP(const CStdString& strFile) ++{ ++ CStdString strFile2(strFile); ++ ++ if (IsStack(strFile)) ++ strFile2 = CStackDirectory::GetFirstStackedFile(strFile); ++ ++ return StringUtils::StartsWithNoCase(strFile2, "tcp:"); ++} ++ ++bool URIUtils::IsPVRChannel(const CStdString& strFile) ++{ ++ CStdString strFile2(strFile); ++ ++ if (IsStack(strFile)) ++ strFile2 = CStackDirectory::GetFirstStackedFile(strFile); ++ ++ return StringUtils::StartsWithNoCase(strFile2, "pvr://channels"); ++} ++ + bool URIUtils::IsDAV(const CStdString& strFile) + { + CStdString strFile2(strFile); +@@ -1284,3 +1314,8 @@ bool URIUtils::UpdateUrlEncoding(std::string &strFilename) + strFilename = newFilename; + return true; + } ++ ++bool URIUtils::IsUsingFastSwitch(const CStdString& strFile) ++{ ++ return IsUDP(strFile) || IsTCP(strFile) || IsPVRChannel(strFile); ++} +diff --git a/xbmc/utils/URIUtils.h b/xbmc/utils/URIUtils.h +index b94e94c..b45630f 100644 +--- a/xbmc/utils/URIUtils.h ++++ b/xbmc/utils/URIUtils.h +@@ -88,6 +88,8 @@ public: + static bool IsDOSPath(const CStdString &path); + static bool IsDVD(const CStdString& strFile); + static bool IsFTP(const CStdString& strFile); ++ static bool IsUDP(const CStdString& strFile); ++ static bool IsTCP(const CStdString& strFile); + static bool IsHD(const CStdString& strFileName); + static bool IsHDHomeRun(const CStdString& strFile); + static bool IsSlingbox(const CStdString& strFile); +@@ -127,6 +129,8 @@ public: + static bool IsAndroidApp(const CStdString& strFile); + static bool IsLibraryFolder(const CStdString& strFile); + static bool IsLibraryContent(const std::string& strFile); ++ static bool IsPVRChannel(const CStdString& strFile); ++ static bool IsUsingFastSwitch(const CStdString& strFile); + + static void AddSlashAtEnd(std::string& strFolder); + static bool HasSlashAtEnd(const std::string& strFile, bool checkURL = false); +-- +1.9.1 + + +From 3041272619e91e0b028462b53c59bd0cf620e1f9 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 28 Jan 2014 08:43:29 +0100 +Subject: [PATCH 83/96] squash fast switch + +--- + .../cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 23 ++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index d5da14b..f4ba29c 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -1783,15 +1783,19 @@ void CDVDDemuxFFmpeg::ParsePacket(AVPacket *pkt) + bool CDVDDemuxFFmpeg::IsVideoReady() + { + AVStream *st; ++ bool hasVideo = false; + if(m_program != UINT_MAX) + { + for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) + { + int idx = m_pFormatContext->programs[m_program]->stream_index[i]; + st = m_pFormatContext->streams[idx]; +- if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && +- (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) +- return false; ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ++ { ++ if (st->codec->width && st->codec->pix_fmt != PIX_FMT_NONE) ++ return true; ++ hasVideo = true; ++ } + } + } + else +@@ -1799,12 +1803,15 @@ bool CDVDDemuxFFmpeg::IsVideoReady() + for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++) + { + st = m_pFormatContext->streams[i]; +- if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && +- (!st->codec->width || st->codec->pix_fmt == PIX_FMT_NONE)) +- return false; ++ if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ++ { ++ if (st->codec->width && st->codec->pix_fmt != PIX_FMT_NONE) ++ return true; ++ hasVideo = true; ++ } + } + } +- return true; ++ return !hasVideo; + } + + void CDVDDemuxFFmpeg::ResetVideoStreams() +@@ -1816,7 +1823,7 @@ void CDVDDemuxFFmpeg::ResetVideoStreams() + if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + { + if (st->codec->extradata) +- m_dllAvUtil.av_free(st->codec->extradata); ++ av_free(st->codec->extradata); + st->codec->extradata = NULL; + st->codec->width = 0; + } +-- +1.9.1 + + +From c70b0943cb55465cde76dde9a2dbcf4db1ced09b Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sun, 22 Dec 2013 14:52:29 +0100 +Subject: [PATCH 84/96] linux: add shared lib for sse4 operations + +--- + Makefile.in | 8 ++- + configure.in | 18 +++++++ + xbmc/DllPaths_generated.h.in | 3 ++ + xbmc/linux/sse4/CopyFrame.cpp | 115 ++++++++++++++++++++++++++++++++++++++++++ + xbmc/linux/sse4/DllLibSSE4.h | 43 ++++++++++++++++ + xbmc/linux/sse4/Makefile.in | 20 ++++++++ + 6 files changed, 206 insertions(+), 1 deletion(-) + create mode 100644 xbmc/linux/sse4/CopyFrame.cpp + create mode 100644 xbmc/linux/sse4/DllLibSSE4.h + create mode 100644 xbmc/linux/sse4/Makefile.in + +diff --git a/Makefile.in b/Makefile.in +index 6f689cf..a79adc7 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -316,6 +316,12 @@ CHECK_LIBADD=@WAYLAND_TEST_LIBS@ + endif + endif + ++ifeq (@USE_SSE4@,1) ++LIBSSE4+=sse4 ++sse4 : force ++ $(MAKE) -C xbmc/linux/sse4 ++endif ++ + CHECK_PROGRAMS = xbmc-test + + CLEAN_FILES += $(CHECK_PROGRAMS) $(CHECK_EXTENSIONS) +@@ -444,7 +450,7 @@ endif + + codecs: papcodecs dvdpcodecs dvdpextcodecs + +-libs: libhdhomerun imagelib libexif system/libcpluff-@ARCH@.so $(CMYTH) ++libs: $(LIBSSE4) libhdhomerun imagelib libexif system/libcpluff-@ARCH@.so $(CMYTH) + + externals: codecs libs visualizations screensavers libaddon pvraddons + +diff --git a/configure.in b/configure.in +index d0775a9..6cf2a44 100644 +--- a/configure.in ++++ b/configure.in +@@ -883,6 +883,19 @@ if test "$use_static_ffmpeg" = "yes"; then + VORBISENC_ALL_LIBS=`${PKG_CONFIG} --static --libs-only-l --silence-errors vorbisenc` + fi + ++use_sse4=no ++if test "$ARCH" = "x86_64-linux" || test "$ARCH" = "i486-linux"; then ++ SAVE_CFLAGS="$CFLAGS" ++ CFLAGS="-msse4.1" ++ AC_COMPILE_IFELSE( ++ [AC_LANG_SOURCE([int foo;])], ++ [ use_sse4=yes ++ USE_SSE4=1], ++ [ use_sse=no ++ USE_SSE4=0]) ++ CFLAGS="$SAVE_CFLAGS" ++fi ++ + # Checks for library functions. + AC_FUNC_ALLOCA + AC_FUNC_CHOWN +@@ -2590,6 +2603,10 @@ if test "$use_codec_libstagefright" = "yes"; then + OUTPUT_FILES="$OUTPUT_FILES xbmc/cores/dvdplayer/DVDCodecs/Video/libstagefrightICS/Makefile" + fi + ++if test "$use_sse4" = "yes"; then ++OUTPUT_FILES="$OUTPUT_FILES xbmc/linux/sse4/Makefile" ++fi ++ + OUTPUT_FILES="$OUTPUT_FILES \ + xbmc/interfaces/python/Makefile \ + xbmc/interfaces/python/test/Makefile" +@@ -2668,6 +2685,7 @@ AC_SUBST(USE_DOXYGEN) + AC_SUBST(USE_PVR_ADDONS) + AC_SUBST(GNUTLS_ALL_LIBS) + AC_SUBST(VORBISENC_ALL_LIBS) ++AC_SUBST(USE_SSE4) + + # pushd and popd are not available in other shells besides bash, so implement + # our own pushd/popd functions +diff --git a/xbmc/DllPaths_generated.h.in b/xbmc/DllPaths_generated.h.in +index 4953236..e42344c 100644 +--- a/xbmc/DllPaths_generated.h.in ++++ b/xbmc/DllPaths_generated.h.in +@@ -103,4 +103,7 @@ + /* xkbcommon */ + #define DLL_PATH_XKBCOMMON "@XKBCOMMON_LIBRARY_SONAME@" + ++/* sse4 */ ++#define DLL_PATH_LIBSSE4 "special://xbmcbin/system/libsse4-@ARCH@.so" ++ + #endif +diff --git a/xbmc/linux/sse4/CopyFrame.cpp b/xbmc/linux/sse4/CopyFrame.cpp +new file mode 100644 +index 0000000..6d23d83 +--- /dev/null ++++ b/xbmc/linux/sse4/CopyFrame.cpp +@@ -0,0 +1,115 @@ ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This library 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 library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "smmintrin.h" ++ ++#define CACHED_BUFFER_SIZE 4096 ++typedef unsigned int UINT; ++ ++extern "C" ++{ ++ ++/* ++ * http://software.intel.com/en-us/articles/copying-accelerated-video-decode-frame-buffers ++ * COPIES VIDEO FRAMES FROM USWC MEMORY TO WB SYSTEM MEMORY VIA CACHED BUFFER ++ * ASSUMES PITCH IS A MULTIPLE OF 64B CACHE LINE SIZE, WIDTH MAY NOT BE ++ */ ++void copy_frame( void * pSrc, void * pDest, void * pCacheBlock, ++ UINT width, UINT height, UINT pitch ) ++{ ++ __m128i x0, x1, x2, x3; ++ __m128i *pLoad; ++ __m128i *pStore; ++ __m128i *pCache; ++ UINT x, y, yLoad, yStore; ++ UINT rowsPerBlock; ++ UINT width64; ++ UINT extraPitch; ++ ++ ++ rowsPerBlock = CACHED_BUFFER_SIZE / pitch; ++ width64 = (width + 63) & ~0x03f; ++ extraPitch = (pitch - width64) / 16; ++ ++ pLoad = (__m128i *)pSrc; ++ pStore = (__m128i *)pDest; ++ ++ // COPY THROUGH 4KB CACHED BUFFER ++ for( y = 0; y < height; y += rowsPerBlock ) ++ { ++ // ROWS LEFT TO COPY AT END ++ if( y + rowsPerBlock > height ) ++ rowsPerBlock = height - y; ++ ++ pCache = (__m128i *)pCacheBlock; ++ ++ _mm_mfence(); ++ ++ // LOAD ROWS OF PITCH WIDTH INTO CACHED BLOCK ++ for( yLoad = 0; yLoad < rowsPerBlock; yLoad++ ) ++ { ++ // COPY A ROW, CACHE LINE AT A TIME ++ for( x = 0; x < pitch; x +=64 ) ++ { ++ x0 = _mm_stream_load_si128( pLoad +0 ); ++ x1 = _mm_stream_load_si128( pLoad +1 ); ++ x2 = _mm_stream_load_si128( pLoad +2 ); ++ x3 = _mm_stream_load_si128( pLoad +3 ); ++ ++ _mm_store_si128( pCache +0, x0 ); ++ _mm_store_si128( pCache +1, x1 ); ++ _mm_store_si128( pCache +2, x2 ); ++ _mm_store_si128( pCache +3, x3 ); ++ ++ pCache += 4; ++ pLoad += 4; ++ } ++ } ++ ++ _mm_mfence(); ++ ++ pCache = (__m128i *)pCacheBlock; ++ ++ // STORE ROWS OF FRAME WIDTH FROM CACHED BLOCK ++ for( yStore = 0; yStore < rowsPerBlock; yStore++ ) ++ { ++ // copy a row, cache line at a time ++ for( x = 0; x < width64; x +=64 ) ++ { ++ x0 = _mm_load_si128( pCache ); ++ x1 = _mm_load_si128( pCache +1 ); ++ x2 = _mm_load_si128( pCache +2 ); ++ x3 = _mm_load_si128( pCache +3 ); ++ ++ _mm_stream_si128( pStore, x0 ); ++ _mm_stream_si128( pStore +1, x1 ); ++ _mm_stream_si128( pStore +2, x2 ); ++ _mm_stream_si128( pStore +3, x3 ); ++ ++ pCache += 4; ++ pStore += 4; ++ } ++ ++ pCache += extraPitch; ++ pStore += extraPitch; ++ } ++ } ++} ++} +diff --git a/xbmc/linux/sse4/DllLibSSE4.h b/xbmc/linux/sse4/DllLibSSE4.h +new file mode 100644 +index 0000000..01424ac +--- /dev/null ++++ b/xbmc/linux/sse4/DllLibSSE4.h +@@ -0,0 +1,43 @@ ++#pragma once ++/* ++ * Copyright (C) 2005-2013 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, 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 General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "DynamicDll.h" ++ ++extern "C" { ++ ++} ++ ++class DllLibSSE4Interface ++{ ++public: ++ virtual ~DllLibSSE4Interface() {} ++ virtual void copy_frame(void * pSrc, void * pDest, void * pCacheBlock, UINT width, UINT height, UINT pitch) = 0; ++}; ++ ++class DllLibSSE4 : public DllDynamic, DllLibSSE4Interface ++{ ++ DECLARE_DLL_WRAPPER(DllLibSSE4, DLL_PATH_LIBSSE4) ++ DEFINE_METHOD6(void, copy_frame, (void *p1, void *p2, void *p3, UINT p4, UINT p5, UINT p6)) ++ ++ BEGIN_METHOD_RESOLVE() ++ RESOLVE_METHOD(copy_frame) ++ END_METHOD_RESOLVE() ++}; +diff --git a/xbmc/linux/sse4/Makefile.in b/xbmc/linux/sse4/Makefile.in +new file mode 100644 +index 0000000..45aa826 +--- /dev/null ++++ b/xbmc/linux/sse4/Makefile.in +@@ -0,0 +1,20 @@ ++ARCH=@ARCH@ ++DEFINES+= ++CXXFLAGS=-fPIC -msse4.1 ++LIBNAME=libsse4 ++OBJS=CopyFrame.o ++ ++LIB_SHARED=@abs_top_srcdir@/system/$(LIBNAME)-$(ARCH).so ++ ++all: $(LIB_SHARED) ++ ++$(LIB_SHARED): $(OBJS) ++ $(CXX) $(CFLAGS) $(LDFLAGS) -shared -g -o $(LIB_SHARED) $(OBJS) ++ ++CLEAN_FILES = \ ++ $(LIB_SHARED) \ ++ ++DISTCLEAN_FILES= \ ++ Makefile \ ++ ++include ../../../Makefile.include +-- +1.9.1 + + +From d8669de8aeb2268b9ae0b91602215b4890366f15 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Thu, 19 Dec 2013 15:36:11 +0100 +Subject: [PATCH 85/96] vaapi: option to enable sw filters + +--- + language/English/strings.po | 17 ++- + system/settings/settings.xml | 15 ++ + xbmc/cores/VideoRenderers/RenderManager.cpp | 4 +- + xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp | 1 + + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 76 ++++++++-- + .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 3 + + xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 154 +++++++++++++++++++++ + xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h | 34 +++++ + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 32 ++--- + 9 files changed, 295 insertions(+), 41 deletions(-) + +diff --git a/language/English/strings.po b/language/English/strings.po +index 9cc2090..88b945e 100755 +--- a/language/English/strings.po ++++ b/language/English/strings.po +@@ -6092,7 +6092,13 @@ msgctxt "#13456" + msgid "Hardware accelerated" + msgstr "" + +-#empty strings from id 13457 to 13499 ++#. Option for video related setting #13454: sw filter ++#: system/settings/settings.xml ++msgctxt "#13457" ++msgid "Use SW Filter for VAAPI" ++msgstr "" ++ ++#empty strings from id 13458 to 13499 + + #: system/settings/settings.xml + msgctxt "#13500" +@@ -15177,7 +15183,14 @@ msgctxt "#36431" + msgid "Defines whether video decoding should be performed in software (requires more CPU) or with hardware acceleration where possible." + msgstr "" + +-#empty strings from id 36432 to 36499 ++#. Description for video related setting #13457: vaapi sw filter ++#: system/settings/settings.xml ++msgctxt "#36432" ++msgid "This option enables the deinterlacing methods available for software decoding. It gives the possiblity to use high quality deinterlacers in combination with VAAPI." ++msgstr "" ++ ++#empty strings from id 36433 to 36499 ++ + #end reservation + + #: system/settings/settings.xml +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 124a14d..fdf5f41 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -715,6 +715,21 @@ + false + + ++ ++ HAVE_LIBVA ++ ++ ++ ++ true ++ 1 ++ ++ ++ true ++ ++ 3 ++ false ++ ++ + + HasDXVA2 + +diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp +index 8dc8a91..c15f559 100644 +--- a/xbmc/cores/VideoRenderers/RenderManager.cpp ++++ b/xbmc/cores/VideoRenderers/RenderManager.cpp +@@ -986,10 +986,10 @@ EINTERLACEMETHOD CXBMCRenderManager::AutoInterlaceMethodInternal(EINTERLACEMETHO + if (mInt == VS_INTERLACEMETHOD_NONE) + return VS_INTERLACEMETHOD_NONE; + +- if(!m_pRenderer->Supports(mInt)) ++ if(m_pRenderer && !m_pRenderer->Supports(mInt)) + mInt = VS_INTERLACEMETHOD_AUTO; + +- if (mInt == VS_INTERLACEMETHOD_AUTO) ++ if (m_pRenderer && mInt == VS_INTERLACEMETHOD_AUTO) + return m_pRenderer->AutoInterlaceMethod(); + + return mInt; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp +index 5443cb3..002c8e1 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecUtils.cpp +@@ -456,6 +456,7 @@ static const EFormatMap g_format_map[] = { + , { PIX_FMT_YUV420P16, RENDER_FMT_YUV420P16 } + , { PIX_FMT_UYVY422, RENDER_FMT_UYVY422 } + , { PIX_FMT_YUYV422, RENDER_FMT_YUYV422 } ++, { PIX_FMT_NV12, RENDER_FMT_NV12 } + , { PIX_FMT_VAAPI_VLD, RENDER_FMT_VAAPI } + , { PIX_FMT_DXVA2_VLD, RENDER_FMT_DXVA } + , { PIX_FMT_NONE , RENDER_FMT_NONE } +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index b59c1ee..2df9de9 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -38,6 +38,7 @@ + #include "utils/log.h" + #include "boost/shared_ptr.hpp" + #include "threads/Atomics.h" ++#include "settings/MediaSettings.h" + + #ifndef TARGET_POSIX + #define RINT(x) ((x) >= 0 ? ((int)((x) + 0.5)) : ((int)((x) - 0.5))) +@@ -165,6 +166,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec() + m_dts = DVD_NOPTS_VALUE; + m_started = false; + m_decoderPts = DVD_NOPTS_VALUE; ++ m_interlace = false; + } + + CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg() +@@ -388,7 +390,7 @@ unsigned int CDVDVideoCodecFFmpeg::SetFilters(unsigned int flags) + { + m_filters_next.clear(); + +- if(m_pHardware) ++ if(m_pHardware && !m_pHardware->UseFilter()) + return 0; + + if(flags & FILTER_ROTATE) +@@ -462,10 +464,10 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + if(section) + lock = shared_ptr(new CSingleLock(*section)); + +- int result; ++ int result = 0; + if(pData) + result = m_pHardware->Check(m_pCodecContext); +- else ++ else if (!m_pHardware->UseFilter()) + result = m_pHardware->Decode(m_pCodecContext, NULL); + + if(result) +@@ -520,19 +522,60 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + || m_pCodecContext->codec_id == AV_CODEC_ID_SVQ3) + m_started = true; + +- if(m_pHardware == NULL) ++ m_interlace = m_pFrame->interlaced_frame; ++ ++ if(m_pHardware == NULL || m_pHardware->UseFilter()) + { ++ if (m_pHardware) ++ { ++ m_pFrame->pkt_dts = pts_dtoi(m_dts); ++ int result = m_pHardware->Decode(m_pCodecContext, m_pFrame); ++ if (result == VC_BUFFER) ++ return result; ++ m_pHardware->MapFrame(m_pCodecContext, m_pFrame); ++ m_dts = pts_itod(m_pFrame->pkt_dts); ++ m_pFrame->pkt_dts = 0; ++ } ++ + bool need_scale = std::find( m_formats.begin() + , m_formats.end() +- , m_pCodecContext->pix_fmt) == m_formats.end(); ++ , m_pFrame->format) == m_formats.end(); + + bool need_reopen = false; ++ ++ ++ // ask codec to do deinterlacing if possible ++ EDEINTERLACEMODE mDeintMode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; ++ EINTERLACEMETHOD mInt = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod); ++ ++ unsigned int mFilters = 0; ++ ++ if (mDeintMode != VS_DEINTERLACEMODE_OFF) ++ { ++ if (mDeintMode == VS_DEINTERLACEMODE_FORCE || ++ m_pFrame->interlaced_frame) ++ { ++ if (mInt == VS_INTERLACEMETHOD_DEINTERLACE) ++ mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY; ++ else if(mInt == VS_INTERLACEMETHOD_DEINTERLACE_HALF) ++ mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY | CDVDVideoCodec::FILTER_DEINTERLACE_HALFED; ++ ++ if (mDeintMode == VS_DEINTERLACEMODE_AUTO && mFilters) ++ mFilters |= CDVDVideoCodec::FILTER_DEINTERLACE_FLAGGED; ++ } ++ } ++ ++ if (!g_renderManager.Supports(RENDERFEATURE_ROTATION)) ++ mFilters |= CDVDVideoCodec::FILTER_ROTATE; ++ ++ SetFilters(mFilters); ++ + if(!m_filters.Equals(m_filters_next)) + need_reopen = true; + + if(m_pFilterIn) + { +- if(m_pFilterIn->outputs[0]->format != m_pCodecContext->pix_fmt ++ if(m_pFilterIn->outputs[0]->format != m_pFrame->format + || m_pFilterIn->outputs[0]->w != m_pCodecContext->width + || m_pFilterIn->outputs[0]->h != m_pCodecContext->height) + need_reopen = true; +@@ -549,7 +592,7 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + } + + int result; +- if(m_pHardware) ++ if(m_pHardware && !m_pHardware->UseFilter()) + result = m_pHardware->Decode(m_pCodecContext, m_pFrame); + else if(m_pFilterGraph) + result = FilterProcess(m_pFrame); +@@ -645,6 +688,7 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + pDvdVideoPicture->chroma_position = m_pCodecContext->chroma_sample_location; + pDvdVideoPicture->color_primaries = m_pCodecContext->color_primaries; + pDvdVideoPicture->color_transfer = m_pCodecContext->color_trc; ++ pDvdVideoPicture->color_matrix = m_pCodecContext->colorspace; + if(m_pCodecContext->color_range == AVCOL_RANGE_JPEG + || m_pCodecContext->pix_fmt == PIX_FMT_YUVJ420P) + pDvdVideoPicture->color_range = 1; +@@ -668,7 +712,11 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + pDvdVideoPicture->qscale_type = DVP_QSCALE_UNKNOWN; + } + +- pDvdVideoPicture->dts = m_dts; ++ if (pDvdVideoPicture->iRepeatPicture) ++ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; ++ else ++ pDvdVideoPicture->dts = m_dts; ++ + m_dts = DVD_NOPTS_VALUE; + if (m_pFrame->reordered_opaque) + pDvdVideoPicture->pts = pts_itod(m_pFrame->reordered_opaque); +@@ -699,7 +747,7 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + + bool CDVDVideoCodecFFmpeg::GetPicture(DVDVideoPicture* pDvdVideoPicture) + { +- if(m_pHardware) ++ if(m_pHardware && !m_pHardware->UseFilter()) + return m_pHardware->GetPicture(m_pCodecContext, m_pFrame, pDvdVideoPicture); + + if(!GetPictureCommon(pDvdVideoPicture)) +@@ -724,6 +772,7 @@ bool CDVDVideoCodecFFmpeg::GetPicture(DVDVideoPicture* pDvdVideoPicture) + pix_fmt = (PixelFormat)m_pFrame->format; + + pDvdVideoPicture->format = CDVDCodecUtils::EFormatFromPixfmt(pix_fmt); ++ + return true; + } + +@@ -738,7 +787,7 @@ int CDVDVideoCodecFFmpeg::FilterOpen(const CStdString& filters, bool scale) + if (filters.empty() && !scale) + return 0; + +- if (m_pHardware) ++ if (m_pHardware && !m_pHardware->UseFilter()) + { + CLog::Log(LOGWARNING, "CDVDVideoCodecFFmpeg::FilterOpen - skipped opening filters on hardware decode"); + return 0; +@@ -756,7 +805,7 @@ int CDVDVideoCodecFFmpeg::FilterOpen(const CStdString& filters, bool scale) + CStdString args = StringUtils::Format("%d:%d:%d:%d:%d:%d:%d", + m_pCodecContext->width, + m_pCodecContext->height, +- m_pCodecContext->pix_fmt, ++ m_pFrame->format, + m_pCodecContext->time_base.num, + m_pCodecContext->time_base.den, + m_pCodecContext->sample_aspect_ratio.num, +@@ -955,10 +1004,7 @@ bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &skippedDeint, int &in + { + pts = m_decoderPts; + skippedDeint = m_skippedDeint; +- if (m_pFrame) +- interlaced = m_pFrame->interlaced_frame; +- else +- interlaced = 0; ++ interlaced = m_interlace; + return true; + } + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +index c0ce198..4f88532 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +@@ -48,6 +48,8 @@ public: + virtual bool CanSkipDeint() {return false; } + virtual const std::string Name() = 0; + virtual CCriticalSection* Section() { return NULL; } ++ virtual bool UseFilter() { return false; } ++ virtual bool MapFrame(AVCodecContext* avctx, AVFrame* frame) { return false; } + }; + + CDVDVideoCodecFFmpeg(); +@@ -134,4 +136,5 @@ protected: + int m_skippedDeint; + bool m_requestSkipDeint; + int m_codecControlFlags; ++ bool m_interlace; + }; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp +index bfefc9d..51f9bed 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp +@@ -24,6 +24,17 @@ + #include "DVDVideoCodec.h" + #include + #include ++#include "utils/log.h" ++#include "threads/SingleLock.h" ++#include "XMemUtils.h" ++#include "utils/CPUInfo.h" ++#include "settings/Settings.h" ++ ++extern "C" { ++#include "libavutil/avutil.h" ++} ++ ++#define CACHED_BUFFER_SIZE 4096 + + #define CHECK(a) \ + do { \ +@@ -166,12 +177,17 @@ CDecoder::CDecoder() + m_context = 0; + m_hwaccel = (vaapi_context*)calloc(1, sizeof(vaapi_context)); + memset(m_surfaces, 0, sizeof(*m_surfaces)); ++ m_frame_buffer = NULL; ++ m_cache = NULL; + } + + CDecoder::~CDecoder() + { + Close(); + free(m_hwaccel); ++ _aligned_free(m_frame_buffer); ++ _aligned_free(m_cache); ++ m_dllSSE4.Unload(); + } + + void CDecoder::RelBuffer(AVCodecContext *avctx, AVFrame *pic) +@@ -388,6 +404,11 @@ bool CDecoder::Open(AVCodecContext *avctx, enum PixelFormat fmt, unsigned int su + if (!EnsureContext(avctx)) + return false; + ++ if (avctx->width <= 1920 && avctx->height <= 1088) ++ CheckUseFilter(); ++ else ++ m_use_filter = false; ++ + m_hwaccel->display = m_display->get(); + + avctx->hwaccel_context = m_hwaccel; +@@ -472,7 +493,35 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame) + return status; + + if(frame) ++ { ++ if (m_use_filter) ++ { ++ VASurfaceID surface = GetSurfaceID(frame); ++ std::list::iterator it; ++ for(it = m_surfaces_used.begin(); it != m_surfaces_used.end(); ++it) ++ { ++ if((*it)->m_id == surface) ++ { ++ m_holder.surface = *it; ++ break; ++ } ++ } ++ if (it == m_surfaces_used.end()) ++ { ++ CLog::Log(LOGERROR, "VAAPI::Decode - surface not found"); ++ return VC_ERROR; ++ } ++ CProcPic pic; ++ memset(&pic.frame, 0, sizeof(AVFrame)); ++ av_frame_ref(&pic.frame, frame); ++ pic.surface = *it; ++ m_surfaces_proc.push_back(pic); ++ if (m_surfaces_proc.size() < m_renderbuffers_count) ++ return VC_BUFFER; ++ } ++ + return VC_BUFFER | VC_PICTURE; ++ } + else + return VC_BUFFER; + } +@@ -550,4 +599,109 @@ unsigned CDecoder::GetAllowedReferences() + return m_renderbuffers_count; + } + ++void CDecoder::Reset() ++{ ++ m_surfaces_proc.clear(); ++} ++ ++void CDecoder::CheckUseFilter() ++{ ++ m_use_filter = true; ++ _aligned_free(m_frame_buffer); ++ _aligned_free(m_cache); ++ if (CSettings::Get().GetBool("videoplayer.usevaapiswfilter")) ++ { ++ if (!(g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_SSE4)) ++ { ++ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter cpu does not support SSE4"); ++ m_use_filter = false; ++ return; ++ } ++ if (!m_dllSSE4.Load()) ++ { ++ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter failed loading sse4 lib"); ++ m_use_filter = false; ++ return; ++ } ++ VAImage image; ++ VASurfaceID surface = m_surfaces_free.front()->m_id; ++ VAStatus status = vaDeriveImage(m_display->get(), surface, &image); ++ m_use_filter = true; ++ if (status != VA_STATUS_SUCCESS) ++ { ++ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter vaDeriveImage not supported"); ++ m_use_filter = false; ++ } ++ if (image.format.fourcc != VA_FOURCC_NV12) ++ { ++ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter image format not NV12"); ++ m_use_filter = false; ++ } ++ if ((image.pitches[0] % 64) || (image.pitches[1] % 64)) ++ { ++ CLog::Log(LOGNOTICE,"VAAPI::CheckUseFilter patches no multiple of 64"); ++ m_use_filter = false; ++ } ++ if (m_use_filter) ++ { ++ m_frame_buffer = (uint8_t*)_aligned_malloc(image.height*image.width*2 + 256, 64); ++ m_cache = (uint8_t*)_aligned_malloc(CACHED_BUFFER_SIZE, 64); ++ } ++ vaDestroyImage(m_display->get(),image.image_id); ++ } ++ else ++ { ++ m_use_filter = false; ++ } ++} ++ ++bool CDecoder::MapFrame(AVCodecContext* avctx, AVFrame* frame) ++{ ++ if (m_surfaces_proc.empty()) ++ { ++ return false; ++ } ++ if(frame) ++ { ++ CProcPic pic = m_surfaces_proc.front(); ++ m_surfaces_proc.pop_front(); ++ VASurfaceID surface = pic.surface->m_id; ++ VASurfaceStatus surf_status; ++ VAImage image; ++ uint8_t *buf; ++ CHECK(vaQuerySurfaceStatus(m_display->get(), surface, &surf_status)) ++ while (surf_status != VASurfaceReady) ++ { ++ Sleep(1); ++ CHECK(vaQuerySurfaceStatus(m_display->get(), surface, &surf_status)) ++ } ++ CHECK(vaDeriveImage(m_display->get(), surface, &image)); ++ CHECK(vaMapBuffer(m_display->get(), image.buf, (void**)&buf)) ++ ++ uint8_t *src, *dst; ++ src = buf + image.offsets[0]; ++ dst = m_frame_buffer + image.offsets[0]; ++ m_dllSSE4.copy_frame(src, dst, m_cache, image.width, image.height, image.pitches[0]); ++ src = buf + image.offsets[1]; ++ dst = m_frame_buffer + image.offsets[1]; ++ m_dllSSE4.copy_frame(src, dst, m_cache, image.width, image.height/2, image.pitches[1]); ++ ++ av_frame_unref(frame); ++ av_frame_move_ref(frame, &pic.frame); ++ ++ frame->format = AV_PIX_FMT_NV12; ++ frame->data[0] = m_frame_buffer + image.offsets[0]; ++ frame->linesize[0] = image.pitches[0]; ++ frame->data[1] = m_frame_buffer + image.offsets[1]; ++ frame->linesize[1] = image.pitches[1]; ++ frame->data[2] = NULL; ++ frame->data[3] = NULL; ++ frame->pkt_size = image.data_size; ++ ++ CHECK(vaUnmapBuffer(m_display->get(), image.buf)) ++ CHECK(vaDestroyImage(m_display->get(),image.image_id)) ++ } ++ return true; ++} ++ + #endif +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h +index a520e42..755c192 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h +@@ -29,7 +29,12 @@ + #include + #include + #include ++#include "linux/sse4/DllLibSSE4.h" + ++extern "C" { ++#include "libavcodec/vaapi.h" ++#include "libavcodec/avcodec.h" ++} + + namespace VAAPI { + +@@ -101,11 +106,31 @@ struct CHolder + {} + }; + ++struct CProcPic ++{ ++ AVFrame frame; ++ CSurfacePtr surface; ++ CProcPic() ++ {} ++ CProcPic(const CProcPic &other) ++ { ++ memcpy(&this->frame, &other.frame, sizeof(AVFrame)); ++ surface = other.surface; ++ } ++ CProcPic & operator= (const CProcPic &other) ++ { ++ memcpy(&this->frame, &other.frame, sizeof(AVFrame)); ++ surface = other.surface; ++ return *this; ++ } ++}; ++ + class CDecoder + : public CDVDVideoCodecFFmpeg::IHardwareDecoder + { + bool EnsureContext(AVCodecContext *avctx); + bool EnsureSurfaces(AVCodecContext *avctx, unsigned n_surfaces_count); ++ void CheckUseFilter(); + public: + CDecoder(); + ~CDecoder(); +@@ -114,9 +139,12 @@ public: + virtual bool GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture); + virtual int Check (AVCodecContext* avctx); + virtual void Close(); ++ virtual void Reset(); + virtual const std::string Name() { return "vaapi"; } + virtual CCriticalSection* Section() { if(m_display) return m_display.get(); else return NULL; } + virtual unsigned GetAllowedReferences(); ++ virtual bool UseFilter() { return m_use_filter; } ++ virtual bool MapFrame(AVCodecContext* avctx, AVFrame* frame); + + int GetBuffer(AVCodecContext *avctx, AVFrame *pic); + void RelBuffer(AVCodecContext *avctx, AVFrame *pic); +@@ -132,14 +160,20 @@ protected: + int m_refs; + std::list m_surfaces_used; + std::list m_surfaces_free; ++ std::list m_surfaces_proc; + + CDisplayPtr m_display; + VAConfigID m_config; + VAContextID m_context; ++ bool m_use_filter; ++ uint8_t *m_frame_buffer; ++ uint8_t *m_cache; + + vaapi_context *m_hwaccel; + + CHolder m_holder; // silly struct to pass data to renderer ++ ++ DllLibSSE4 m_dllSSE4; + }; + + } +diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +index 9c5469b..b30e450 100644 +--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp ++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +@@ -554,28 +554,6 @@ void CDVDPlayerVideo::Process() + // decoder still needs to provide an empty image structure, with correct flags + m_pVideoCodec->SetDropState(bRequestDrop); + +- // ask codec to do deinterlacing if possible +- EDEINTERLACEMODE mDeintMode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; +- EINTERLACEMETHOD mInt = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod); +- +- unsigned int mFilters = 0; +- +- if (mDeintMode != VS_DEINTERLACEMODE_OFF) +- { +- if (mInt == VS_INTERLACEMETHOD_DEINTERLACE) +- mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY; +- else if(mInt == VS_INTERLACEMETHOD_DEINTERLACE_HALF) +- mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY | CDVDVideoCodec::FILTER_DEINTERLACE_HALFED; +- +- if (mDeintMode == VS_DEINTERLACEMODE_AUTO && mFilters) +- mFilters |= CDVDVideoCodec::FILTER_DEINTERLACE_FLAGGED; +- } +- +- if (!g_renderManager.Supports(RENDERFEATURE_ROTATION)) +- mFilters |= CDVDVideoCodec::FILTER_ROTATE; +- +- mFilters = m_pVideoCodec->SetFilters(mFilters); +- + int iDecoderState = m_pVideoCodec->Decode(pPacket->pData, pPacket->iSize, pPacket->dts, pPacket->pts); + + // buffer packets so we can recover should decoder flush for some reason +@@ -662,6 +640,8 @@ void CDVDPlayerVideo::Process() + + //Deinterlace if codec said format was interlaced or if we have selected we want to deinterlace + //this video ++ EDEINTERLACEMODE mDeintMode = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode; ++ EINTERLACEMETHOD mInt = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod); + if ((mDeintMode == VS_DEINTERLACEMODE_AUTO && (picture.iFlags & DVP_FLAG_INTERLACED)) || mDeintMode == VS_DEINTERLACEMODE_FORCE) + { + if(mInt == VS_INTERLACEMETHOD_SW_BLEND) +@@ -704,7 +684,15 @@ void CDVDPlayerVideo::Process() + } + + if (picture.iRepeatPicture) ++ { ++ double pts; ++ int skipped, deint; ++ m_pVideoCodec->GetCodecStats(pts, skipped, deint); ++ picture.iDuration = frametime; ++ if (deint && (frametime <= 0.02*DVD_TIME_BASE)) ++ picture.iDuration *= 2; + picture.iDuration *= picture.iRepeatPicture + 1; ++ } + + int iResult = OutputPicture(&picture, pts); + +-- +1.9.1 + + +From a866228fc54a4e95423387a83c8de012e247efc3 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 3 Jan 2014 20:50:46 +0100 +Subject: [PATCH 86/96] X11: check for user output on resize window + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index 9962f08..c95f4ec 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -167,7 +167,20 @@ bool CWinSystemX11::DestroyWindow() + bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop) + { + m_userOutput = CSettings::Get().GetString("videoscreen.monitor"); +- if (m_userOutput.compare("Default") == 0) ++ XOutput *out = NULL; ++ if (m_userOutput.compare("Default") != 0) ++ { ++ out = g_xrandr.GetOutput(m_userOutput); ++ if (out) ++ { ++ XMode mode = g_xrandr.GetCurrentMode(m_userOutput); ++ if (!mode.isCurrent) ++ { ++ out = NULL; ++ } ++ } ++ } ++ if (!out) + { + std::vector outputs = g_xrandr.GetModes(); + if (outputs.size() > 0) +@@ -176,8 +189,6 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n + } + } + +- m_userOutput = g_xrandr.GetModes()[0].name; +- + if(m_nWidth == newWidth + && m_nHeight == newHeight + && m_userOutput.compare(m_currentOutput) == 0) +-- +1.9.1 + + +From a153c72c0b53c9cbad7fc545abb7730e8eecaf19 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Fri, 24 Jan 2014 18:29:33 +0100 +Subject: [PATCH 87/96] dvdplayer: flush ffmpeg after hw decoder returned an + error + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index 2df9de9..f4c9929 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -471,7 +471,12 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + result = m_pHardware->Decode(m_pCodecContext, NULL); + + if(result) ++ { ++ if (result & VC_ERROR) ++ avcodec_flush_buffers(m_pCodecContext); ++ + return result; ++ } + } + + if(m_pFilterGraph) +@@ -593,7 +598,11 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + + int result; + if(m_pHardware && !m_pHardware->UseFilter()) ++ { + result = m_pHardware->Decode(m_pCodecContext, m_pFrame); ++ if (result & VC_ERROR) ++ avcodec_flush_buffers(m_pCodecContext); ++ } + else if(m_pFilterGraph) + result = FilterProcess(m_pFrame); + else +-- +1.9.1 + + +From d4e3e0920e61b7115b1053010fc7a00e1631e04a Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 28 Jan 2014 10:05:26 +0100 +Subject: [PATCH 88/96] xbmc pr 3080 + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index f4c9929..283af9e 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -495,6 +495,14 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p + m_dllAvCodec.av_init_packet(&avpkt); + avpkt.data = pData; + avpkt.size = iSize; ++#define SET_PKT_TS(ts) \ ++ if(ts != DVD_NOPTS_VALUE)\ ++ avpkt.ts = (ts / DVD_TIME_BASE) * AV_TIME_BASE;\ ++ else\ ++ avpkt.ts = AV_NOPTS_VALUE ++ SET_PKT_TS(pts); ++ SET_PKT_TS(dts); ++#undef SET_PKT_TS + /* We lie, but this flag is only used by pngdec.c. + * Setting it correctly would allow CorePNG decoding. */ + avpkt.flags = AV_PKT_FLAG_KEY; +@@ -727,8 +735,10 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + pDvdVideoPicture->dts = m_dts; + + m_dts = DVD_NOPTS_VALUE; +- if (m_pFrame->reordered_opaque) +- pDvdVideoPicture->pts = pts_itod(m_pFrame->reordered_opaque); ++ ++ int64_t bpts = av_frame_get_best_effort_timestamp(m_pFrame); ++ if(bpts != AV_NOPTS_VALUE) ++ pDvdVideoPicture->pts = (double)bpts * DVD_TIME_BASE / AV_TIME_BASE; + else + pDvdVideoPicture->pts = DVD_NOPTS_VALUE; + +-- +1.9.1 + + +From 23e4b30e3463b01d5f9acf1287767ca96c88fdb0 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 28 Jan 2014 17:24:58 +0100 +Subject: [PATCH 89/96] set preatpicture if pts is equal to last frame + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index 283af9e..ff18b73 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -738,7 +738,15 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) + + int64_t bpts = av_frame_get_best_effort_timestamp(m_pFrame); + if(bpts != AV_NOPTS_VALUE) ++ { + pDvdVideoPicture->pts = (double)bpts * DVD_TIME_BASE / AV_TIME_BASE; ++ if (pDvdVideoPicture->pts == m_decoderPts) ++ { ++ pDvdVideoPicture->iRepeatPicture = -0.5; ++ pDvdVideoPicture->pts = DVD_NOPTS_VALUE; ++ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; ++ } ++ } + else + pDvdVideoPicture->pts = DVD_NOPTS_VALUE; + +-- +1.9.1 + + +From 3732925c369d10341ed813ea6c0775ea5ecc1cb5 Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Mon, 27 Jan 2014 19:49:03 +0100 +Subject: [PATCH 90/96] Introduce SWCodec - these are codecs that don't have + any GPU acceleration (yet) - add HVEC + +--- + .../dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 15 +++++++++------ + .../cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 2 +- + xbmc/settings/AdvancedSettings.cpp | 4 ++-- + xbmc/settings/AdvancedSettings.h | 2 +- + 4 files changed, 13 insertions(+), 10 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index ff18b73..354e206 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -160,7 +160,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec() + m_iScreenHeight = 0; + m_iOrientation = 0; + m_bSoftware = false; +- m_isHi10p = false; ++ m_isSWCodec = false; + m_pHardware = NULL; + m_iLastKeyframe = 0; + m_dts = DVD_NOPTS_VALUE; +@@ -216,10 +216,12 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options + // this is needed to not open the decoders + m_bSoftware = true; + // this we need to enable multithreading for hi10p via advancedsettings +- m_isHi10p = true; ++ m_isSWCodec = true; + break; + } + } ++ else if (hints.codec == AV_CODEC_ID_HEVC) ++ m_isSWCodec = true; + + if(pCodec == NULL) + pCodec = m_dllAvCodec.avcodec_find_decoder(hints.codec); +@@ -245,12 +247,12 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options + * sensitive to changes in frame sizes, and it causes crashes + * during HW accell - so we unset it in this case. + * +- * When we detect Hi10p and user did not disable hi10pmultithreading ++ * When we detect a pure SW codec and user did not disable SWmultithreading + * via advancedsettings.xml we keep the ffmpeg default thread type. + * */ +- if(m_isHi10p && !g_advancedSettings.m_videoDisableHi10pMultithreading) ++ if(m_isSWCodec && !g_advancedSettings.m_videoDisableSWMultithreading) + { +- CLog::Log(LOGDEBUG,"CDVDVideoCodecFFmpeg::Open() Keep default threading for Hi10p: %d", ++ CLog::Log(LOGDEBUG,"CDVDVideoCodecFFmpeg::Open() Keep default threading for swcodec: %d", + m_pCodecContext->thread_type); + } + else if ((EDECODEMETHOD) CSettings::Get().GetInt("videoplayer.decodingmethod") == VS_DECODEMETHOD_SOFTWARE && CSettings::Get().GetBool("videoplayer.useframemtdec")) +@@ -302,7 +304,8 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options + int num_threads = std::min(8 /*MAX_THREADS*/, g_cpuInfo.getCPUCount()); + if( num_threads > 1 && !hints.software && m_pHardware == NULL // thumbnail extraction fails when run threaded + && ( pCodec->id == AV_CODEC_ID_H264 +- || pCodec->id == AV_CODEC_ID_MPEG4 )) ++ || pCodec->id == AV_CODEC_ID_MPEG4 ++ || pCodec->id == AV_CODEC_ID_HEVC)) + m_pCodecContext->thread_count = num_threads; + + if (m_dllAvCodec.avcodec_open2(m_pCodecContext, pCodec, NULL) < 0) +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +index 4f88532..e301aa8 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +@@ -126,7 +126,7 @@ protected: + + std::string m_name; + bool m_bSoftware; +- bool m_isHi10p; ++ bool m_isSWCodec; + IHardwareDecoder *m_pHardware; + int m_iLastKeyframe; + double m_dts; +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index 7532914..0d5e546 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -182,7 +182,7 @@ void CAdvancedSettings::Initialize() + m_stagefrightConfig.useInputDTS = false; + + m_videoDefaultLatency = 0.0; +- m_videoDisableHi10pMultithreading = false; ++ m_videoDisableSWMultithreading = false; + + m_musicUseTimeSeeking = true; + m_musicTimeSeekForward = 10; +@@ -599,7 +599,7 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) + XMLUtils::GetFloat(pElement, "nonlinearstretchratio", m_videoNonLinStretchRatio, 0.01f, 1.0f); + XMLUtils::GetBoolean(pElement,"enablehighqualityhwscalers", m_videoEnableHighQualityHwScalers); + XMLUtils::GetFloat(pElement,"autoscalemaxfps",m_videoAutoScaleMaxFps, 0.0f, 1000.0f); +- XMLUtils::GetBoolean(pElement,"disablehi10pmultithreading",m_videoDisableHi10pMultithreading); ++ XMLUtils::GetBoolean(pElement,"disableswmultithreading",m_videoDisableSWMultithreading); + XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace); + XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1); + XMLUtils::GetInt(pElement,"vdpauHDdeint",m_videoVDPAUdeintHD); +diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h +index c43351d..7075f05 100644 +--- a/xbmc/settings/AdvancedSettings.h ++++ b/xbmc/settings/AdvancedSettings.h +@@ -194,7 +194,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler + bool m_DXVANoDeintProcForProgressive; + int m_videoFpsDetect; + int m_videoBusyDialogDelay_ms; +- bool m_videoDisableHi10pMultithreading; ++ bool m_videoDisableSWMultithreading; + StagefrightConfig m_stagefrightConfig; + + CStdString m_videoDefaultPlayer; +-- +1.9.1 + + +From 552f5cec0cd0a753fcd920a1d5d7b3eb6d37e696 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 11 Feb 2014 18:15:06 +0100 +Subject: [PATCH 91/96] ActiveAE: add some debug logging + +--- + xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp +index 0287e73..6904cb9 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp +@@ -276,7 +276,13 @@ unsigned int CActiveAEStream::AddData(void *data, unsigned int size) + } + } + if (!m_inMsgEvent.WaitMSec(200)) ++ { ++ double cachetime = GetCacheTime(); ++ CSingleLock lock(m_streamLock); ++ CLog::Log(LOGWARNING, "CActiveAEStream::AddData - timeout waiting for buffer, paused: %d, cache time: %f, free buffers: %d", ++ m_paused, cachetime, m_streamFreeBuffers); + break; ++ } + } + return copied; + } +-- +1.9.1 + + +From b10b79798aa7827134f34e5ad436e491a402cf77 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Tue, 1 Apr 2014 15:45:16 +0200 +Subject: [PATCH 92/96] X11: remove obsolete sdl include + +--- + xbmc/windowing/X11/WinSystemX11.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.h b/xbmc/windowing/X11/WinSystemX11.h +index d1c8729..5489543 100644 +--- a/xbmc/windowing/X11/WinSystemX11.h ++++ b/xbmc/windowing/X11/WinSystemX11.h +@@ -25,7 +25,6 @@ + + #include "system_gl.h" + #include +-#include + + #include "windowing/WinSystem.h" + #include "utils/Stopwatch.h" +-- +1.9.1 + + +From da2f57d73f6df8892b759b465ee47d9401b390f9 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sun, 13 Apr 2014 10:52:26 +0200 +Subject: [PATCH 93/96] squash fast channel + +--- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 13 ++++++++++--- + xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h | 1 + + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +index f4ba29c..ca545c0 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +@@ -220,6 +220,7 @@ CDVDDemuxFFmpeg::CDVDDemuxFFmpeg() : CDVDDemux() + m_pkt.result = -1; + memset(&m_pkt.pkt, 0, sizeof(AVPacket)); + m_streaminfo = true; /* set to true if we want to look for streams before playback */ ++ m_checkvideo = false; + } + + CDVDDemuxFFmpeg::~CDVDDemuxFFmpeg() +@@ -448,11 +449,10 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo) + if (iformat && (strcmp(iformat->name, "mjpeg") == 0) && m_ioContext->seekable == 0) + m_pFormatContext->max_analyze_duration = 500000; + +- bool short_analyze = false; + if (iformat && (strcmp(iformat->name, "mpegts") == 0)) + { + m_pFormatContext->max_analyze_duration = 500000; +- short_analyze = true; ++ m_checkvideo = true; + } + + // we need to know if this is matroska or avi later +@@ -484,14 +484,17 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo) + } + CLog::Log(LOGDEBUG, "%s - av_find_stream_info finished", __FUNCTION__); + +- if (short_analyze) ++ if (m_checkvideo) + { + // make sure we start video with an i-frame + ResetVideoStreams(); + } + } + else ++ { + m_program = 0; ++ m_checkvideo = true; ++ } + + // reset any timeout + m_timeout.SetInfinite(); +@@ -1784,6 +1787,10 @@ bool CDVDDemuxFFmpeg::IsVideoReady() + { + AVStream *st; + bool hasVideo = false; ++ ++ if(!m_checkvideo) ++ return true; ++ + if(m_program != UINT_MAX) + { + for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) +diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +index 9ec0877..c8d706b 100644 +--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h ++++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +@@ -166,5 +166,6 @@ protected: + bool m_bPtsWrap, m_bPtsWrapChecked; + int64_t m_iStartTime, m_iMaxTime, m_iEndTime; + bool m_streaminfo; ++ bool m_checkvideo; + }; + +-- +1.9.1 + + +From 303fbf8b6724f2a01cb0ed213922dc8a6bd57b01 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker +Date: Sun, 13 Apr 2014 15:34:26 +0200 +Subject: [PATCH 94/96] X11: do not call xrandr until we have a window + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index c95f4ec..d1e6c1f 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -243,15 +243,17 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl + } + + // only call xrandr if mode changes +- if (currmode.w != mode.w || currmode.h != mode.h || +- currmode.hz != mode.hz || currmode.id != mode.id) ++ if (m_mainWindow) + { +- CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr"); +- OnLostDevice(); +- m_bIsInternalXrr = true; +- g_xrandr.SetMode(out, mode); +- if (m_mainWindow) ++ if (currmode.w != mode.w || currmode.h != mode.h || ++ currmode.hz != mode.hz || currmode.id != mode.id) ++ { ++ CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr"); ++ OnLostDevice(); ++ m_bIsInternalXrr = true; ++ g_xrandr.SetMode(out, mode); + return true; ++ } + } + } + #endif +-- +1.9.1 + + +From 836de0e5d789ea37b526d5869477f356c5cebfd1 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Wed, 16 Apr 2014 12:40:42 +0300 +Subject: [PATCH 95/96] vaapi: fix build + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp | 13 ++----------- + xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h | 5 ----- + 2 files changed, 2 insertions(+), 16 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp +index 51f9bed..f957393 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.cpp +@@ -24,16 +24,10 @@ + #include "DVDVideoCodec.h" + #include + #include +-#include "utils/log.h" +-#include "threads/SingleLock.h" + #include "XMemUtils.h" + #include "utils/CPUInfo.h" + #include "settings/Settings.h" + +-extern "C" { +-#include "libavutil/avutil.h" +-} +- + #define CACHED_BUFFER_SIZE 4096 + + #define CHECK(a) \ +@@ -512,8 +506,7 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame) + return VC_ERROR; + } + CProcPic pic; +- memset(&pic.frame, 0, sizeof(AVFrame)); +- av_frame_ref(&pic.frame, frame); ++ memcpy(&pic.frame, frame, sizeof(AVFrame)); + pic.surface = *it; + m_surfaces_proc.push_back(pic); + if (m_surfaces_proc.size() < m_renderbuffers_count) +@@ -686,9 +679,7 @@ bool CDecoder::MapFrame(AVCodecContext* avctx, AVFrame* frame) + dst = m_frame_buffer + image.offsets[1]; + m_dllSSE4.copy_frame(src, dst, m_cache, image.width, image.height/2, image.pitches[1]); + +- av_frame_unref(frame); +- av_frame_move_ref(frame, &pic.frame); +- ++ memcpy(frame, &pic.frame, sizeof(AVFrame)); + frame->format = AV_PIX_FMT_NV12; + frame->data[0] = m_frame_buffer + image.offsets[0]; + frame->linesize[0] = image.pitches[0]; +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h +index 755c192..b6fb320 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VAAPI.h +@@ -31,11 +31,6 @@ + #include + #include "linux/sse4/DllLibSSE4.h" + +-extern "C" { +-#include "libavcodec/vaapi.h" +-#include "libavcodec/avcodec.h" +-} +- + namespace VAAPI { + + typedef boost::shared_ptr VASurfacePtr; +-- +1.9.1 + + +From d54319d818ed995076e5e4470673891788d0ef8e Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Mon, 24 Feb 2014 20:58:52 +0200 +Subject: [PATCH 96/96] no hevc in ffmpeg 1.2 + +--- + xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +index 354e206..6bc35b1 100644 +--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp ++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +@@ -220,8 +220,11 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options + break; + } + } ++ #ifdef AV_CODEC_ID_HEVC + else if (hints.codec == AV_CODEC_ID_HEVC) + m_isSWCodec = true; ++ #endif ++ + + if(pCodec == NULL) + pCodec = m_dllAvCodec.avcodec_find_decoder(hints.codec); +@@ -304,8 +307,7 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options + int num_threads = std::min(8 /*MAX_THREADS*/, g_cpuInfo.getCPUCount()); + if( num_threads > 1 && !hints.software && m_pHardware == NULL // thumbnail extraction fails when run threaded + && ( pCodec->id == AV_CODEC_ID_H264 +- || pCodec->id == AV_CODEC_ID_MPEG4 +- || pCodec->id == AV_CODEC_ID_HEVC)) ++ || pCodec->id == AV_CODEC_ID_MPEG4 )) + m_pCodecContext->thread_count = num_threads; + + if (m_dllAvCodec.avcodec_open2(m_pCodecContext, pCodec, NULL) < 0) +-- +1.9.1 + diff --git a/projects/RPi/patches/xbmc/xbmc-995.02-dont-set-_NET_WM_STATE_FULLSCREEN.patch b/projects/RPi/patches/xbmc/xbmc-995.02-dont-set-_NET_WM_STATE_FULLSCREEN.patch new file mode 100644 index 0000000000..3f331b1574 --- /dev/null +++ b/projects/RPi/patches/xbmc/xbmc-995.02-dont-set-_NET_WM_STATE_FULLSCREEN.patch @@ -0,0 +1,29 @@ +From 4f6188bc2bcee52ab3a150fff336b58c11f8928a Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Sat, 22 Mar 2014 22:18:28 +0200 +Subject: [PATCH] dont set _NET_WM_STATE_FULLSCREEN + +--- + xbmc/windowing/X11/WinSystemX11.cpp | 6 ------ + 1 files changed, 0 insertions(+), 6 deletions(-) + +diff --git a/xbmc/windowing/X11/WinSystemX11.cpp b/xbmc/windowing/X11/WinSystemX11.cpp +index c95f4ec..d12e050 100644 +--- a/xbmc/windowing/X11/WinSystemX11.cpp ++++ b/xbmc/windowing/X11/WinSystemX11.cpp +@@ -903,12 +903,6 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std: + InputOutput, vi->visual, + mask, &swa); + +- if (fullscreen && hasWM) +- { +- Atom fs = XInternAtom(m_dpy, "_NET_WM_STATE_FULLSCREEN", True); +- XChangeProperty(m_dpy, m_mainWindow, XInternAtom(m_dpy, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *) &fs, 1); +- } +- + // define invisible cursor + Pixmap bitmapNoData; + XColor black; +-- +1.7.2.5 + diff --git a/projects/RPi/patches/xbmc/xbmc-995.03-keymap.patch b/projects/RPi/patches/xbmc/xbmc-995.03-keymap.patch new file mode 100644 index 0000000000..d2b054f23f --- /dev/null +++ b/projects/RPi/patches/xbmc/xbmc-995.03-keymap.patch @@ -0,0 +1,13 @@ +diff --git a/xbmc/windowing/WinEventsX11.cpp b/xbmc/windowing/WinEventsX11.cpp +index a5b4ba2..3586a6a 100644 +--- a/xbmc/windowing/WinEventsX11.cpp ++++ b/xbmc/windowing/WinEventsX11.cpp +@@ -731,7 +731,7 @@ XBMCKey CWinEventsX11Imp::LookupXbmcKeySym(KeySym keysym) + + // try ascii mappings + if (keysym>>8 == 0x00) +- return (XBMCKey)(keysym & 0xFF); ++ return (XBMCKey)tolower(keysym & 0xFF); + + return (XBMCKey)keysym; + } \ No newline at end of file diff --git a/projects/RPi/patches/xbmc/xbmc-gotham_rbp_backports.patch b/projects/RPi/patches/xbmc/xbmc-gotham_rbp_backports.patch index 24704fbdc1..b9c6c21e9a 100644 --- a/projects/RPi/patches/xbmc/xbmc-gotham_rbp_backports.patch +++ b/projects/RPi/patches/xbmc/xbmc-gotham_rbp_backports.patch @@ -19375,681 +19375,6 @@ index 6f19395..8eff32f 100644 2.0.4 -From 09c1715be013bc927d975761513a358f010cec52 Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Mon, 28 May 2012 10:34:39 +0200 -Subject: [PATCH 084/106] videoplayer: adapt lateness detection and dropping to - buffering - ---- - xbmc/cores/VideoRenderers/RenderManager.cpp | 16 +- - xbmc/cores/VideoRenderers/RenderManager.h | 12 +- - .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 38 +++- - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 41 +++++ - .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 7 + - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 197 +++++++++++++++++---- - xbmc/cores/dvdplayer/DVDPlayerVideo.h | 23 +++ - 7 files changed, 296 insertions(+), 38 deletions(-) - -diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp -index a7b4721..d31c6c7 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.cpp -+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp -@@ -286,6 +286,8 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi - m_bIsStarted = true; - m_bReconfigured = true; - m_presentstep = PRESENT_IDLE; -+ m_presentpts = DVD_NOPTS_VALUE; -+ m_sleeptime = 1.0; - m_presentevent.notifyAll(); - - m_firstFlipPage = false; // tempfix -@@ -631,7 +633,7 @@ void CXBMCRenderManager::SetViewMode(int iViewMode) - m_pRenderer->SetViewMode(iViewMode); - } - --void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) -+void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, double pts /* = 0 */, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/) - { - { CSharedLock lock(m_sharedSection); - -@@ -699,6 +701,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L - m.timestamp = timestamp; - m.presentfield = sync; - m.presentmethod = presentmethod; -+ m.pts = pts; - requeue(m_queued, m_free); - - /* signal to any waiters to check state */ -@@ -1073,6 +1076,8 @@ void CXBMCRenderManager::PrepareNextRender() - m_discard.push_back(m_presentsource); - m_presentsource = idx; - m_queued.pop_front(); -+ m_sleeptime = m_Queue[idx].timestamp - clocktime; -+ m_presentpts = m_Queue[idx].pts; - m_presentevent.notifyAll(); - } - } -@@ -1089,3 +1094,12 @@ void CXBMCRenderManager::DiscardBuffer() - m_presentstep = PRESENT_IDLE; - m_presentevent.notifyAll(); - } -+ -+bool CXBMCRenderManager::GetStats(double &sleeptime, double &pts, int &bufferLevel) -+{ -+ CSingleLock lock(m_presentlock); -+ sleeptime = m_sleeptime; -+ pts = m_presentpts; -+ bufferLevel = m_queued.size() + m_discard.size(); -+ return true; -+} -diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h -index c3f5517..d84ff6c 100644 ---- a/xbmc/cores/VideoRenderers/RenderManager.h -+++ b/xbmc/cores/VideoRenderers/RenderManager.h -@@ -98,10 +98,11 @@ class CXBMCRenderManager - * - * @param bStop reference to stop flag of calling thread - * @param timestamp of frame delivered with AddVideoPicture -+ * @param pts used for lateness detection - * @param source depreciated - * @param sync signals frame, top, or bottom field - */ -- void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE); -+ void FlipPage(volatile bool& bStop, double timestamp = 0.0, double pts = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE); - unsigned int PreInit(); - void UnInit(); - bool Flush(); -@@ -176,6 +177,12 @@ class CXBMCRenderManager - int WaitForBuffer(volatile bool& bStop, int timeout = 100); - - /** -+ * Can be called by player for lateness detection. This is done best by -+ * looking at the end of the queue. -+ */ -+ bool GetStats(double &sleeptime, double &pts, int &bufferLevel); -+ -+ /** - * Video player call this on flush in oder to discard any queued frames - */ - void DiscardBuffer(); -@@ -222,6 +229,7 @@ class CXBMCRenderManager - - struct SPresent - { -+ double pts; - double timestamp; - EFIELDSYNC presentfield; - EPRESENTMETHOD presentmethod; -@@ -233,6 +241,8 @@ class CXBMCRenderManager - - ERenderFormat m_format; - -+ double m_sleeptime; -+ double m_presentpts; - double m_presentcorr; - double m_presenterr; - double m_errorbuff[ERRORBUFFSIZE]; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -index dc047d7..c09939c 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h -@@ -129,6 +129,10 @@ struct DVDVideoUserData - #define DVP_FLAG_NOSKIP 0x00000010 // indicate this picture should never be dropped - #define DVP_FLAG_DROPPED 0x00000020 // indicate that this picture has been dropped in decoder stage, will have no data - -+#define DVP_FLAG_DROPDEINT 0x00000040 // indicate that this picture was requested to have been dropped in deint stage -+#define DVP_FLAG_NO_POSTPROC 0x00000100 // see GetCodecStats -+#define DVP_FLAG_DRAIN 0x00000200 // see GetCodecStats -+ - // DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2! - - #define DVP_QSCALE_UNKNOWN 0 -@@ -146,6 +150,8 @@ class CDVDCodecOptions; - #define VC_PICTURE 0x00000004 // the decoder got a picture, call Decode(NULL, 0) again to parse the rest of the data - #define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data - #define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again -+#define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped -+ - class CDVDVideoCodec - { - public: -@@ -263,7 +269,6 @@ class CDVDVideoCodec - return 0; - } - -- - /** - * Number of references to old pictures that are allowed to - * be retained when calling decode on the next demux packet -@@ -280,4 +285,35 @@ class CDVDVideoCodec - * Interact with user settings so that user disabled codecs are disabled - */ - static bool IsCodecDisabled(DVDCodecAvailableType* map, unsigned int size, AVCodecID id); -+ -+ /* For calculation of dropping requirements player asks for some information. -+ * -+ * - pts : right after decoder, used to detect gaps (dropped frames in decoder) -+ * - droppedPics : indicates if decoder has dropped a picture -+ * -1 means that decoder has no info on this. -+ * -+ * If codec does not implement this method, pts of decoded frame at input -+ * video player is used. In case decoder does post-proc and de-interlacing there -+ * may be quite some frames queued up between exit decoder and entry player. -+ */ -+ virtual bool GetCodecStats(double &pts, int &droppedPics) -+ { -+ droppedPics= -1; -+ return false; -+ } -+ -+ /** -+ * Codec can be informed by player with the following flags: -+ * -+ * DVP_FLAG_NO_POSTPROC : if speed is not normal the codec can switch off -+ * postprocessing and de-interlacing -+ * -+ * DVP_FLAG_DRAIN : codecs may do postprocessing and de-interlacing. -+ * If video buffers in RenderManager are about to run dry, -+ * this is signaled to codec. Codec can wait for post-proc -+ * to be finished instead of returning empty and getting another -+ * packet. -+ * -+ */ -+ virtual void SetCodecControl(int flags) {} - }; -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -index 9b6a34d..81fe0cf 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp -@@ -164,6 +164,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec() - m_iLastKeyframe = 0; - m_dts = DVD_NOPTS_VALUE; - m_started = false; -+ m_decoderPts = DVD_NOPTS_VALUE; - } - - CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg() -@@ -355,6 +356,14 @@ void CDVDVideoCodecFFmpeg::SetDropState(bool bDrop) - { - if( m_pCodecContext ) - { -+ if (bDrop && m_pHardware && m_pHardware->CanSkipDeint()) -+ { -+ m_requestSkipDeint = true; -+ bDrop = false; -+ } -+ else -+ m_requestSkipDeint = false; -+ - // i don't know exactly how high this should be set - // couldn't find any good docs on it. think it varies - // from codec to codec on what it does -@@ -556,6 +565,7 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p - void CDVDVideoCodecFFmpeg::Reset() - { - m_started = false; -+ m_decoderPts = DVD_NOPTS_VALUE; - m_iLastKeyframe = m_pCodecContext->has_b_frames; - m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext); - -@@ -665,6 +675,22 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture) - else - pDvdVideoPicture->pts = DVD_NOPTS_VALUE; - -+ if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE) -+ m_decoderPts = pDvdVideoPicture->pts; -+ else -+ m_decoderPts = m_dts; -+ -+ if (m_requestSkipDeint) -+ { -+ pDvdVideoPicture->iFlags |= DVP_FLAG_DROPDEINT; -+ m_skippedDeint = 1; -+ } -+ else -+ m_skippedDeint = 0; -+ -+ m_requestSkipDeint = false; -+ pDvdVideoPicture->iFlags |= m_codecControlFlags; -+ - if(!m_started) - pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED; - -@@ -924,3 +950,18 @@ unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences() - else - return 0; - } -+ -+bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &droppedPics) -+{ -+ pts = m_decoderPts; -+ if (m_skippedDeint) -+ droppedPics = m_skippedDeint; -+ else -+ droppedPics = -1; -+ return true; -+} -+ -+void CDVDVideoCodecFFmpeg::SetCodecControl(int flags) -+{ -+ m_codecControlFlags = flags; -+} -diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -index 2287031..827c9507 100644 ---- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h -@@ -45,6 +45,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec - virtual int Check (AVCodecContext* avctx) = 0; - virtual void Reset () {} - virtual unsigned GetAllowedReferences() { return 0; } -+ virtual bool CanSkipDeint() {return false; } - virtual const std::string Name() = 0; - virtual CCriticalSection* Section() { return NULL; } - }; -@@ -62,6 +63,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec - virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open - virtual unsigned GetConvergeCount(); - virtual unsigned GetAllowedReferences(); -+ virtual bool GetCodecStats(double &pts, int &droppedPics); -+ virtual void SetCodecControl(int flags); - - bool IsHardwareAllowed() { return !m_bSoftware; } - IHardwareDecoder * GetHardware() { return m_pHardware; }; -@@ -127,4 +130,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec - double m_dts; - bool m_started; - std::vector m_formats; -+ double m_decoderPts, m_decoderInterval; -+ int m_skippedDeint; -+ bool m_requestSkipDeint; -+ int m_codecControlFlags; - }; -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index fddb7f7..181ff74 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -38,6 +38,7 @@ - #include "DVDCodecs/DVDCodecs.h" - #include "DVDCodecs/Overlay/DVDOverlayCodecCC.h" - #include "DVDCodecs/Overlay/DVDOverlaySSA.h" -+#include "guilib/GraphicContext.h" - #include - #include - #include -@@ -320,8 +321,10 @@ void CDVDPlayerVideo::Process() - - int iDropped = 0; //frames dropped in a row - bool bRequestDrop = false; -+ int iDropDirective; - - m_videoStats.Start(); -+ m_droppingStats.Reset(); - - while (!m_bStop) - { -@@ -436,6 +439,7 @@ void CDVDPlayerVideo::Process() - picture.iFlags &= ~DVP_FLAG_ALLOCATED; - m_packets.clear(); - m_started = false; -+ m_droppingStats.Reset(); - } - else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush()) - { -@@ -448,6 +452,7 @@ void CDVDPlayerVideo::Process() - //we need to recalculate the framerate - //TODO: this needs to be set on a streamchange instead - ResetFrameRateCalc(); -+ m_droppingStats.Reset(); - - m_stalled = true; - m_started = false; -@@ -467,6 +472,7 @@ void CDVDPlayerVideo::Process() - m_iNrOfPicturesNotToSkip = 0; - if (m_pVideoCodec) - m_pVideoCodec->SetSpeed(m_speed); -+ m_droppingStats.Reset(); - } - else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED)) - { -@@ -515,6 +521,28 @@ void CDVDPlayerVideo::Process() - m_iNrOfPicturesNotToSkip = 1; - } - -+ bRequestDrop = false; -+ iDropDirective = CalcDropRequirement(pts); -+ if (iDropDirective & EOS_VERYLATE) -+ { -+ if (m_bAllowDrop) -+ { -+ m_pullupCorrection.Flush(); -+ bRequestDrop = true; -+ } -+ } -+ int codecControl = 0; -+ if (iDropDirective & EOS_BUFFER_LEVEL) -+ codecControl |= DVP_FLAG_DRAIN; -+ if (m_speed > DVD_PLAYSPEED_NORMAL) -+ codecControl |= DVP_FLAG_NO_POSTPROC; -+ m_pVideoCodec->SetCodecControl(codecControl); -+ if (iDropDirective & EOS_DROPPED) -+ { -+ m_iDroppedFrames++; -+ iDropped++; -+ } -+ - if (m_messageQueue.GetDataSize() == 0 - || m_speed < 0) - { -@@ -567,15 +595,7 @@ void CDVDPlayerVideo::Process() - } - - m_videoStats.AddSampleBytes(pPacket->iSize); -- // assume decoder dropped a picture if it didn't give us any -- // picture from a demux packet, this should be reasonable -- // for libavformat as a demuxer as it normally packetizes -- // pictures when they come from demuxer -- if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE)) -- { -- m_iDroppedFrames++; -- iDropped++; -- } -+ - // reset the request, the following while loop may break before - // setting the flag to a new value - bRequestDrop = false; -@@ -1185,33 +1205,12 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - m_FlipTimeStamp += max(0.0, iSleepTime); - m_FlipTimeStamp += iFrameDuration; - -- if (iSleepTime <= 0 && m_speed) -- m_iLateFrames++; -- else -- m_iLateFrames = 0; -- -- // ask decoder to drop frames next round, as we are very late -- if(m_iLateFrames > 10) -+ if ((pPicture->iFlags & DVP_FLAG_DROPPED)) - { -- if (!(pPicture->iFlags & DVP_FLAG_NOSKIP)) -- { -- //if we're calculating the framerate, -- //don't drop frames until we've calculated a stable framerate -- if (m_bAllowDrop || m_speed != DVD_PLAYSPEED_NORMAL) -- { -- result |= EOS_VERYLATE; -- m_pullupCorrection.Flush(); //dropped frames mess up the pattern, so just flush it -- } -- m_iDroppedRequest++; -- } -- } -- else -- { -- m_iDroppedRequest = 0; -- } -- -- if( (pPicture->iFlags & DVP_FLAG_DROPPED) ) -+ m_droppingStats.AddOutputDropGain(pts, 1/m_fFrameRate); -+ CLog::Log(LOGDEBUG,"%s - dropped in output", __FUNCTION__); - return result | EOS_DROPPED; -+ } - - // set fieldsync if picture is interlaced - EFIELDSYNC mDisplayField = FS_NONE; -@@ -1244,7 +1243,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) - if (index < 0) - return EOS_DROPPED; - -- g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField); -+ g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, pts, -1, mDisplayField); - - return result; - #else -@@ -1544,3 +1543,131 @@ void CDVDPlayerVideo::CalcFrameRate() - m_iFrameRateCount = 0; - } - } -+ -+int CDVDPlayerVideo::CalcDropRequirement(double pts) -+{ -+ int result = 0; -+ double iSleepTime; -+ double iDecoderPts, iRenderPts; -+ double iInterval; -+ double iGain; -+ double iLateness; -+ bool bNewFrame; -+ int iDroppedPics = -1; -+ int iBufferLevel; -+ -+ // get decoder stats -+ if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iDroppedPics)) -+ iDecoderPts = pts; -+ if (iDecoderPts == DVD_NOPTS_VALUE) -+ iDecoderPts = pts; -+ -+ // get render stats -+ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel); -+ -+ if (iBufferLevel < 0) -+ result |= EOS_BUFFER_LEVEL; -+ else if (iBufferLevel < 2) -+ { -+ result |= EOS_BUFFER_LEVEL; -+ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - hurry: %d", iBufferLevel); -+ } -+ -+ bNewFrame = iDecoderPts != m_droppingStats.m_lastDecoderPts; -+ -+ iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE; -+ -+ m_FlipTimeStamp = m_pClock->GetAbsoluteClock() + max(0.0, iSleepTime) + iInterval; -+ -+ if (m_stalled) -+ m_iCurrentPts = DVD_NOPTS_VALUE; -+ else -+ m_iCurrentPts = iRenderPts - max(0.0, iSleepTime); -+ -+ if (m_droppingStats.m_lastDecoderPts > 0 -+ && bNewFrame -+ && m_bAllowDrop) -+ { -+ iGain = (iDecoderPts - m_droppingStats.m_lastDecoderPts - iInterval)/(double)DVD_TIME_BASE; -+ if (iDroppedPics > 0) -+ { -+ CDroppingStats::CGain gain; -+ gain.gain = iDroppedPics * 1/m_fFrameRate; -+ gain.pts = iDecoderPts; -+ m_droppingStats.m_gain.push_back(gain); -+ m_droppingStats.m_totalGain += gain.gain; -+ result |= EOS_DROPPED; -+ m_droppingStats.m_dropRequests = 0; -+ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped pictures, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain); -+ } -+ else if (iDroppedPics < 0 && iGain > 1/m_fFrameRate) -+ { -+ CDroppingStats::CGain gain; -+ gain.gain = iGain; -+ gain.pts = iDecoderPts; -+ m_droppingStats.m_gain.push_back(gain); -+ m_droppingStats.m_totalGain += iGain; -+ result |= EOS_DROPPED; -+ m_droppingStats.m_dropRequests = 0; -+ CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped in decoder, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain); -+ } -+ } -+ m_droppingStats.m_lastDecoderPts = iDecoderPts; -+ -+ // subtract gains -+ while (!m_droppingStats.m_gain.empty() && -+ iRenderPts >= m_droppingStats.m_gain.front().pts) -+ { -+ m_droppingStats.m_totalGain -= m_droppingStats.m_gain.front().gain; -+ m_droppingStats.m_gain.pop_front(); -+ } -+ -+ // calculate lateness -+ iLateness = iSleepTime + m_droppingStats.m_totalGain; -+ if (iLateness < 0 && m_speed) -+ { -+ if (bNewFrame) -+ m_droppingStats.m_lateFrames++; -+ -+ // if lateness is smaller than frametime, we observe this state -+ // for 10 cycles -+ if (m_droppingStats.m_lateFrames > 10 || iLateness < -2/m_fFrameRate) -+ { -+ // is frame allowed to skip -+ if (m_iNrOfPicturesNotToSkip <= 0) -+ { -+ if (bNewFrame || m_droppingStats.m_dropRequests < 5) -+ { -+ result |= EOS_VERYLATE; -+ } -+ m_droppingStats.m_dropRequests++; -+ } -+ } -+ } -+ else -+ { -+ m_droppingStats.m_dropRequests = 0; -+ m_droppingStats.m_lateFrames = 0; -+ } -+ m_droppingStats.m_lastRenderPts = iRenderPts; -+ return result; -+} -+ -+void CDroppingStats::Reset() -+{ -+ m_gain.clear(); -+ m_totalGain = 0; -+ m_lastDecoderPts = 0; -+ m_lastRenderPts = 0; -+ m_lateFrames = 0; -+ m_dropRequests = 0; -+} -+ -+void CDroppingStats::AddOutputDropGain(double pts, double frametime) -+{ -+ CDroppingStats::CGain gain; -+ gain.gain = frametime; -+ gain.pts = pts; -+ m_gain.push_back(gain); -+ m_totalGain += frametime; -+} -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -index f8ad541..186e271 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -@@ -36,6 +36,25 @@ class CDVDOverlayCodecCC; - - #define VIDEO_PICTURE_QUEUE_SIZE 1 - -+class CDroppingStats -+{ -+public: -+ void Reset(); -+ void AddOutputDropGain(double pts, double frametime); -+ struct CGain -+ { -+ double gain; -+ double pts; -+ }; -+ std::deque m_gain; -+ double m_totalGain; -+ double m_lastDecoderPts; -+ double m_lastRenderPts; -+ unsigned int m_lateFrames; -+ unsigned int m_dropRequests; -+}; -+ -+ - class CDVDPlayerVideo : public CThread - { - public: -@@ -104,6 +123,7 @@ class CDVDPlayerVideo : public CThread - #define EOS_ABORT 1 - #define EOS_DROPPED 2 - #define EOS_VERYLATE 4 -+#define EOS_BUFFER_LEVEL 8 - - void AutoCrop(DVDVideoPicture* pPicture); - void AutoCrop(DVDVideoPicture *pPicture, RECT &crop); -@@ -129,6 +149,7 @@ class CDVDPlayerVideo : public CThread - - void ResetFrameRateCalc(); - void CalcFrameRate(); -+ int CalcDropRequirement(double pts); - - double m_fFrameRate; //framerate of the video currently playing - bool m_bCalcFrameRate; //if we should calculate the framerate from the timestamps -@@ -182,5 +203,7 @@ class CDVDPlayerVideo : public CThread - CPullupCorrection m_pullupCorrection; - - std::list m_packets; -+ -+ CDroppingStats m_droppingStats; - }; - --- -2.0.4 - - -From 5d8f78e836ee606751959e2704a1eec93a84717f Mon Sep 17 00:00:00 2001 -From: xbmc -Date: Sun, 2 Sep 2012 16:05:21 +0200 -Subject: [PATCH 085/106] video player: present correct pts to user for a/v - sync (after buffering in renderer) - ---- - xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 16 ++++++++++++++++ - xbmc/cores/dvdplayer/DVDPlayerVideo.h | 2 +- - 2 files changed, 17 insertions(+), 1 deletion(-) - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -index 181ff74..01757cc 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp -@@ -1463,6 +1463,22 @@ void CDVDPlayerVideo::ResetFrameRateCalc() - g_advancedSettings.m_videoFpsDetect == 0; - } - -+double CDVDPlayerVideo::GetCurrentPts() -+{ -+ double iSleepTime, iRenderPts; -+ int iBufferLevel; -+ -+ // get render stats -+ g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel); -+ -+ if( m_stalled ) -+ iRenderPts = DVD_NOPTS_VALUE; -+ else -+ iRenderPts = iRenderPts - max(0.0, iSleepTime); -+ -+ return iRenderPts; -+} -+ - #define MAXFRAMERATEDIFF 0.01 - #define MAXFRAMESERR 1000 - -diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -index 186e271..59c7f09 100644 ---- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h -+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h -@@ -100,7 +100,7 @@ class CDVDPlayerVideo : public CThread - - bool InitializedOutputDevice(); - -- double GetCurrentPts() { return m_iCurrentPts; } -+ double GetCurrentPts(); - int GetPullupCorrection() { return m_pullupCorrection.GetPatternLength(); } - - double GetOutputDelay(); /* returns the expected delay, from that a packet is put in queue */ --- -2.0.4 - - From 499e5f43bb88de9d5f343e43cfb1e1fbb3c868d6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 12 May 2014 23:06:43 +0100