diff -Naur xine-0.9.4_orig/xineDevice.c xine-0.9.4/xineDevice.c --- xine-0.9.4_orig/xineDevice.c 2011-02-27 19:14:19.000000000 +0100 +++ xine-0.9.4/xineDevice.c 2012-12-23 22:06:02.578457473 +0100 @@ -4405,5 +4405,84 @@ { return theXineDevice; } +#if APIVERSNUM >= 10733 + ///< Asks the output device whether it can scale the currently shown video in + ///< such a way that it fits into the given Rect, while retaining its proper + ///< aspect ratio. If the scaled video doesn't exactly fit into Rect, Alignment + ///< is used to determine how to align the actual rectangle with the requested + ///< one. The actual rectangle can be smaller, larger or the same size as the + ///< given Rect, and its location may differ, depending on the capabilities of + ///< the output device, which may not be able to display a scaled video at + ///< arbitrary sizes and locations. The device shall, however, do its best to + ///< match the requested Rect as closely as possible, preferring a size and + ///< location that fits completely into the requested Rect if possible. + ///< Returns the rectangle that can actually be used when scaling the video. + ///< A skin plugin using this function should rearrange its content according + ///< to the rectangle returned from calling this function, and should especially + ///< be prepared for cases where the returned rectangle is way off the requested + ///< Rect, or even Null. In such cases, the skin may want to fall back to + ///< working with full screen video. + ///< If this device can't scale the video, a Null rectangle is returned (this + ///< is also the default implementation). + cRect cXineDevice::CanScaleVideo(const cRect &Rect, int Alignment/* = taCenter*/) + { + // first implementation: we can always scale, we're a soft device ;-), ignore alignment for now + + // so let's just remember what the next call to ScaleVideo should actually use as a rectangle + // argument if called with cRect(-1,-1,-1,-1) + vidWinRect = Rect; + return vidWinRect; + } + ///< Scales the currently shown video in such a way that it fits into the given + ///< Rect. Rect should be one retrieved through a previous call to + ///< CanScaleVideo() (otherwise results may be undefined). + ///< Even if video output is scaled, the functions GetVideoSize() and + ///< GetOsdSize() must still return the same values as if in full screen mode! + ///< If this device can't scale the video, nothing happens. + ///< To restore full screen video, call this function with a Null rectangle. + void cXineDevice::ScaleVideo(const cRect &Rect/* = cRect::Null*/) + { + const cRect * actualRect = &Rect; + if (Rect == cRect(-1,-1,-1,-1)) { + // actual rectangle was stored here by the previous call to CanScaleVideo + actualRect = &vidWinRect; + } else { + actualRect = &Rect; + // remember the value, just for the case we were called explicitly with a real value + vidWinRect = *actualRect; + } + // let our specialized code do the actual resizing / repositioning, get accurate parameters first + int videoLeft, videoTop, videoWidth, videoHeight, videoZoomX, videoZoomY, osdWidth, osdHeight; + double videoAspect, pixelAspect; + m_xineLib.execFuncVideoSize(videoLeft, videoTop, videoWidth, videoHeight, videoZoomX, videoZoomY, &videoAspect); + GetOsdSize(osdWidth, osdHeight, pixelAspect); + tArea vidWinArea; + vidWinArea.x1 = actualRect->X(); + vidWinArea.y1 = actualRect->Y(); + vidWinArea.x2 = actualRect->X() + actualRect->Width(); + vidWinArea.y2 = actualRect->Y() + actualRect->Height(); + if (*actualRect == cRect::Null) { + // will just resize to full size + vidWinArea.bpp = 0; + } else { + vidWinArea.bpp = 12; + // make corrections + double aspectFactor = (double(osdWidth) / double(osdHeight)) / videoAspect; + int output_width = actualRect->Height() * (videoAspect * aspectFactor); + int output_height = actualRect->Width() / (videoAspect * aspectFactor); + if (double(actualRect->Width())/double(actualRect->Height()) > videoAspect * aspectFactor) { + output_height = actualRect->Height(); + vidWinArea.x1 += (actualRect->Width() - output_width) / 2; + } + else if (double(actualRect->Width())/double(actualRect->Height()) < videoAspect * aspectFactor) { + output_width = actualRect->Width(); + vidWinArea.y1 += (actualRect->Height() - output_height) / 2; + } + vidWinArea.x2 = vidWinArea.x1 + output_width; + vidWinArea.y2 = vidWinArea.y1 + output_height; + } + m_xineLib.SetVideoWindow(videoWidth, videoHeight, vidWinArea); + } +#endif }; diff -Naur xine-0.9.4_orig/xineDevice.h xine-0.9.4/xineDevice.h --- xine-0.9.4_orig/xineDevice.h 2011-02-27 15:28:58.000000000 +0100 +++ xine-0.9.4/xineDevice.h 2012-12-23 22:03:34.530316428 +0100 @@ -162,7 +162,13 @@ #else void OnFreeOsd(cOsd *const osd); #endif - +#if APIVERSNUM >= 10733 + virtual cRect CanScaleVideo(const cRect &Rect, int Alignment = taCenter); + virtual void ScaleVideo(const cRect &Rect = cRect::Null); + private: + cRect vidWinRect; + public: +#endif cXineLib m_xineLib; cMutex m_osdMutex; diff -Naur xine-0.9.4_orig/xineOsd.c xine-0.9.4/xineOsd.c --- xine-0.9.4_orig/xineOsd.c 2011-03-15 21:00:18.000000000 +0100 +++ xine-0.9.4/xineOsd.c 2012-12-23 22:03:16.702299730 +0100 @@ -105,11 +105,21 @@ #else +#if APIVERSNUM >= 10733 + + // scale to the size and position stored by the last call to cDevice::CanScaleVideo + // by passing a cRect(-1,-1,-1,-1) as by our convention + m_xineDevice.ScaleVideo(cRect(-1,-1,-1,-1)); + +#else + #ifdef SET_VIDEO_WINDOW m_xineLib.SetVideoWindow(maxOsdWidth, maxOsdHeight, vidWin, dontOptimize); #endif + +#endif // APIVERSNUM >= 10733 int videoLeft = frameLeft; int videoTop = frameTop; @@ -175,6 +185,13 @@ cXineOsd::~cXineOsd() { +#if APIVERSNUM >= 10733 + + // re-scale to full size when distroying the Osd + m_xineDevice.ScaleVideo(); + +#endif + #if APIVERSNUM < 10509 HideOsd(); #else @@ -410,11 +427,21 @@ int maxOsdWidth, maxOsdHeight; GetMaxOsdSize(maxOsdWidth, maxOsdHeight); +#if APIVERSNUM >= 10733 + + // scale to the size and position stored by the last call to cDevice::CanScaleVideo + // by passing a cRect(-1,-1,-1,-1) as by our convention + m_xineDevice.ScaleVideo(cRect(-1,-1,-1,-1)); + +#else + #ifdef SET_VIDEO_WINDOW m_xineLib.SetVideoWindow(maxOsdWidth, maxOsdHeight, vidWin); #endif + +#endif // APIVERSNUM >= 10733 int videoLeft = -1; int videoTop = -1;