[mythtv] CVS Patch: Xinerama + new over/underscan

mythtv-dev@snowman.net mythtv-dev@snowman.net
Mon, 16 Dec 2002 01:30:41 -0600 (CST)


--1547859840-1804289383-1040023847=:16793
Content-Type: TEXT/plain; CHARSET=US-ASCII

Attached is a patch to CVS snapshot Dec 16 1:00 CST. 

Included:

Full Xinerama support. You can now specify what screen MythTV should
run on. It will start there  The video playback will default to filling
 the fullscreen (just one Xinerama screen), but but you will have to
specify a Theme height and width that matches the Xinerama screen
resolution. Hope to fix this later. If you don't have Xinerama, you
should not notice any difference.

I moved all the over/underscan stuff out of "XvOutput::ToggleFullscreen"
to XvOutput::Show. Its works better there. 

-matthew (DigDug on IRC)


--1547859840-1804289383-1040023847=:16793
Content-Type: TEXT/plain; CHARSET=US-ASCII
Content-Disposition: attachment ; filename="patch.txt"

diff -urN cvs.orig/MC/libs/libNuppelVideo/XJ.cpp cvs/MC/libs/libNuppelVideo/XJ.cpp
--- cvs.orig/MC/libs/libNuppelVideo/XJ.cpp	2002-12-13 21:39:42.000000000 -0600
+++ cvs/MC/libs/libNuppelVideo/XJ.cpp	2002-12-16 00:33:52.000000000 -0600
@@ -16,6 +16,7 @@
 
 #include "XJ.h"
 #include "../libmyth/oldsettings.h"
+#include "../libmyth/util.h"
 
 #include <X11/keysym.h>
 #include <X11/Xatom.h>
@@ -25,7 +26,6 @@
 #include <X11/extensions/Xv.h>
 #include <X11/extensions/Xvlib.h>
 
-
 extern "C" {
 extern int      XShmQueryExtension(Display*);
 extern int      XShmGetEventBase(Display*);
@@ -127,13 +127,37 @@
         printf("open display failed\n"); 
         return false;
     }
-  
+
+    
     data->XJ_screen = DefaultScreenOfDisplay(data->XJ_disp);
     XJ_screen_num = DefaultScreen(data->XJ_disp);
 
-    XJ_screenwidth = DisplayWidth(data->XJ_disp, XJ_screen_num);
-    XJ_screenheight = DisplayHeight(data->XJ_disp, XJ_screen_num);
-  
+    char *prefix = (char *)PREFIX;
+
+    Settings *settings = new Settings();
+    settings->LoadSettingsFiles(QString("settings.txt"), QString(prefix));
+
+    QString HorizScanMode = settings->GetSetting("HorizScanMode", "overscan");
+    QString VertScanMode = settings->GetSetting("VertScanMode", "overscan");
+
+    img_hscanf = settings->GetNumSetting("HorizScanPercentage", 5) / 100.0;
+    img_vscanf = settings->GetNumSetting("VertScanPercentage",5) / 100.0;
+   
+    img_xoff = settings->GetNumSetting("xScanDisplacement", 0);
+    img_yoff = settings->GetNumSetting("yScanDisplacement",0);
+
+
+    if (VertScanMode == "underscan") {
+        img_vscanf = 0 - img_vscanf;
+    }
+    if (HorizScanMode == "underscan") {
+        img_hscanf = 0 - img_hscanf;
+    }
+
+    printf("Over/underscanning. V: %f, H: %f, XOff: %d, YOff: %d\n", img_vscanf,img_hscanf,img_xoff,img_yoff);
+
+    delete settings;
+
     XJ_white=XWhitePixel(data->XJ_disp, XJ_screen_num);
     XJ_black=XBlackPixel(data->XJ_disp, XJ_screen_num);
   
@@ -141,7 +165,7 @@
   
     data->XJ_root = DefaultRootWindow(data->XJ_disp);
 
-    curx = 0; cury = 0;
+    GetMythTVGeometry(data->XJ_disp, XJ_screen_num, &curx, &cury, &XJ_screenwidth, &XJ_screenheight);
     curw = XJ_width; curh = XJ_height;
 
     dispx = 0; dispy = 0;
@@ -159,7 +183,7 @@
 
     if (createwindow)
     {
-        data->XJ_win = XCreateSimpleWindow(data->XJ_disp, data->XJ_root, 0, 0,
+        data->XJ_win = XCreateSimpleWindow(data->XJ_disp, data->XJ_root, curx, cury,
                                            XJ_width, XJ_height, 0, XJ_white,
                                            XJ_black);
         data->XJ_curwin = data->XJ_win;
@@ -374,21 +398,6 @@
 {
     pthread_mutex_lock(&lock);
 
-    float HorizScanFactor, VertScanFactor;
-    int xScanDisp, yScanDisp;
-    char *prefix = (char *)PREFIX;
-
-    Settings *settings = new Settings();
-    settings->LoadSettingsFiles(QString("settings.txt"), QString(prefix));
-
-    QString HorizScanMode = settings->GetSetting("HorizScanMode", "overscan");
-    QString VertScanMode = settings->GetSetting("VertScanMode", "overscan");
-
-    HorizScanFactor = settings->GetNumSetting("HorizScanPercentage", 5) / 100.0;
-    VertScanFactor = settings->GetNumSetting("VertScanPercentage",5) / 100.0;
-    xScanDisp = settings->GetNumSetting("xScanDisplacement", 0);
-    yScanDisp = settings->GetNumSetting("yScanDisplacement",0);
- 
     if (XJ_fullscreen)
     {
         XJ_fullscreen = 0; 
@@ -400,61 +409,19 @@
     {
         XJ_fullscreen = 1;
         oldx = curx; oldy = cury; oldw = curw; oldh = curh;
-
-        if (VertScanMode == "overscan")
-        {
-            if (HorizScanMode == "overscan")
-            {
-                curx = xScanDisp - (int)ceil(XJ_screenwidth * HorizScanFactor);
-                curw = (int)ceil(XJ_screenwidth * (1 + 2 * HorizScanFactor));
-            }
-            else
-            {
-                curx = xScanDisp + (int)ceil(XJ_screenwidth * HorizScanFactor);
-                curw = (int)ceil(XJ_screenwidth * (1 - 2 * HorizScanFactor));
-            }
-
-            cury = yScanDisp - (int)ceil(XJ_screenheight * VertScanFactor);
-            curh = (int)ceil(XJ_screenheight * (1 + 2 * (VertScanFactor + 0.01)));
-        }
-        else
-        {
-            if (HorizScanMode == "overscan")
-            {
-                curx = xScanDisp - (int)ceil(XJ_screenwidth * HorizScanFactor);
-                curw = (int)ceil(XJ_screenwidth * (1 + 2 * HorizScanFactor));
-            }
-            else
-            {
-                curx = xScanDisp + (int)ceil(XJ_screenwidth * HorizScanFactor);
-                curw = (int)ceil(XJ_screenwidth * (1 - 2 * HorizScanFactor));
-            }
-
-            cury = yScanDisp + (int)ceil(XJ_screenheight * VertScanFactor);
-            curh = (int)ceil(XJ_screenheight * (1 - 2 * VertScanFactor));
-        }
-
+        curw = XJ_screenwidth;
+ 	curh = XJ_screenheight;
         hide_cursor();
         decorate(0);
     }
 
-    curx = ((curx - 1) / 2) * 2;
-    cury = ((cury - 1) / 2) * 2;
-
-    int hclamp = XJ_height / 4;
-
-    curh = (int)((rintf(curh) / hclamp) * hclamp) + 4;
-    curw = ((curw) / 2) * 2 + 4;
-
     dispx = 0;
     dispy = 0;
     dispw = curw;
     disph = curh;
 
-    delete settings;
-
     sizehint(curx, cury, curw, curh, 0);
- 
+
     XMoveResizeWindow(data->XJ_disp, data->XJ_win, curx, cury, curw, curh);
     XMapRaised(data->XJ_disp, data->XJ_win);
 
@@ -509,6 +476,8 @@
 void XvVideoOutput::Show(unsigned char *buffer, int width, int height)
 {
     XvImage *image = data->buffers[buffer];
+    int imgx, imgy, imgw, imgh, dispxoff, dispyoff, dispwoff, disphoff;
+    int yoff, xoff;
 
     if (colorid == GUID_YV12_PLANAR)
     {
@@ -520,11 +489,97 @@
         memcpy((unsigned char *)image->data + (width * height) * 5 / 4,
                scratchspace, width * height / 4);
     }
-   
+
+    // Preset all image placement and sizing variables. 
+    imgx = 0; imgy = 0; 
+    imgw = width; imgh = height;
+    xoff = img_xoff; yoff = img_yoff;
+    dispxoff = dispx; dispyoff = dispy; 
+    dispwoff = dispw; disphoff = disph;
+
+/*
+    Here we apply playback over/underscanning and offsetting (if any apply).
+
+    It doesn't make any sense to me to offset an image such that it is clipped.
+    Therefore, we only apply offsets if there is an underscan or overscan which creates
+    "room" to move the image around. That is, if we overscan, we can move the "viewport".
+    If we underscan, we change where we place the image into the display window. If
+    no over/underscanning is performed, you just get the full original image scaled into
+    the full display area.
+*/
+
+    if (img_vscanf > 0) {
+        // Veritcal overscan. Move the Y start point in original image.
+        imgy = (int)ceil(height * img_vscanf); 
+        imgh = (int)ceil(height * (1 - 2 * img_vscanf));
+
+        // If there is an offset, apply it now that we have a room.
+        // To move the image down, move the start point up.
+        if(yoff > 0) {
+            // Can't offset the image more than we have overscanned.
+            if(yoff > imgy) yoff = imgy;
+            imgy -= yoff;
+        }
+        // To move the image up, move the start point down.
+        if(yoff < 0) {
+            // Again, can't offset more than overscanned.
+            if( abs(yoff) > imgy ) yoff = 0 - imgy;
+            imgy -= yoff;
+        }
+    }
+
+    if (img_hscanf > 0) {
+        // Horizontal overscan. Move the X start point in original image.
+        imgx = (int)ceil(width * img_hscanf);
+        imgw = (int)ceil(width * (1 - 2 * img_hscanf));
+        if(xoff > 0) {
+            if(xoff > imgx) xoff = imgx;
+            imgx -= xoff;
+        }
+        if(xoff < 0) {
+            if( abs(xoff) > imgx ) xoff = 0 - imgx;
+            imgx -= xoff;
+        }
+    }
+
+    float vscanf, hscanf;
+    if (img_vscanf < 0) {
+        // Veritcal underscan. Move the starting Y point in the display window. 
+        // Use the abolute value of scan factor.
+        vscanf = fabs(img_vscanf);
+        dispyoff = (int)ceil(disph * vscanf);
+        disphoff = (int)ceil(disph * (1 - 2 * vscanf));
+        // Now offset the image within the extra blank space created by underscanning.
+        // To move the image down, increase the Y offset inside the display window.
+        if(yoff > 0) {
+            // Can't offset more than we have underscanned.
+            if(yoff > dispyoff) yoff = dispyoff;
+            dispyoff += yoff;
+        }
+        if(yoff < 0) {
+            if( abs(yoff) > dispyoff ) yoff = 0 - dispyoff;
+            dispyoff += yoff;
+        }
+    }
+
+    if (img_hscanf < 0) {
+        hscanf = fabs(img_hscanf);
+        dispxoff = (int)ceil(dispw * hscanf);
+        dispwoff = (int)ceil(dispw * (1 - 2 * hscanf));
+        if(xoff > 0) {
+            if(xoff > dispxoff) xoff = dispxoff;
+            dispxoff += xoff;
+        }
+        if(xoff < 0) {
+            if( abs(xoff) > dispxoff ) xoff = 0 - dispxoff;
+            dispxoff += xoff;
+        }
+    }
+
     pthread_mutex_lock(&lock);
  
     XvShmPutImage(data->XJ_disp, xv_port, data->XJ_curwin, data->XJ_gc, image, 
-                  0, 0, width, height, dispx, dispy, dispw, disph, False);
+                  imgx, imgy, imgw, imgh, dispxoff, dispyoff, dispwoff, disphoff, False);
     XSync(data->XJ_disp, False);
 
     pthread_mutex_unlock(&lock);
diff -urN cvs.orig/MC/libs/libNuppelVideo/XJ.h cvs/MC/libs/libNuppelVideo/XJ.h
--- cvs.orig/MC/libs/libNuppelVideo/XJ.h	2002-12-13 21:39:42.000000000 -0600
+++ cvs/MC/libs/libNuppelVideo/XJ.h	2002-12-15 19:16:58.000000000 -0600
@@ -45,6 +45,8 @@
 
     int oldx, oldy, oldw, oldh;
     int curx, cury, curw, curh;
+    int img_xoff, img_yoff; 
+    float img_hscanf, img_vscanf;
 
     int dispx, dispy, dispw, disph;
     int olddispx, olddispy, olddispw, olddisph;
diff -urN cvs.orig/MC/libs/libmyth/mythwidgets.cpp cvs/MC/libs/libmyth/mythwidgets.cpp
--- cvs.orig/MC/libs/libmyth/mythwidgets.cpp	2002-12-14 07:04:35.000000000 -0600
+++ cvs/MC/libs/libmyth/mythwidgets.cpp	2002-12-15 21:33:14.000000000 -0600
@@ -7,6 +7,7 @@
 
 #include "mythwidgets.h"
 #include "mythcontext.h"
+#include "util.h"
 
 void MyToolButton::drawButton( QPainter * p )
 {
@@ -136,7 +137,10 @@
 
     context->GetScreenSettings(screenwidth, wmult, screenheight, hmult);
 
-    setGeometry(0, 0, screenwidth, screenheight);
+    int x, y, w, h;
+    GetMythTVGeometry(qt_xdisplay(), qt_xscreen(), &x, &y, &w, &h);
+
+    setGeometry(x, y, screenwidth, screenheight);
     setFixedSize(QSize(screenwidth, screenheight));
 
     setFont(QFont("Arial", (int)(context->GetMediumFontSize() * hmult),
diff -urN cvs.orig/MC/libs/libmyth/util.cpp cvs/MC/libs/libmyth/util.cpp
--- cvs.orig/MC/libs/libmyth/util.cpp	2002-12-10 04:56:43.000000000 -0600
+++ cvs/MC/libs/libmyth/util.cpp	2002-12-15 19:16:58.000000000 -0600
@@ -6,6 +6,13 @@
 using namespace std;
 
 #include "util.h"
+#include "../libmyth/oldsettings.h"
+
+extern "C" {
+#include <X11/Xlib.h>
+#include <X11/extensions/Xinerama.h>
+}
+
 
 bool WriteStringList(QSocket *socket, QStringList &list)
 {
@@ -117,3 +124,49 @@
 
     return retval;
 } 
+
+void GetMythTVGeometry(Display *dpy, int screen_num, int *x, int *y, int *w, int *h) {
+    int event_base, error_base;
+
+    char *prefix = (char *)PREFIX;
+
+    Settings *settings = new Settings();
+    settings->LoadSettingsFiles(QString("settings.txt"), QString(prefix));
+
+    if( XineramaQueryExtension(dpy, &event_base, &error_base) &&
+        XineramaIsActive(dpy) ) {
+
+        XineramaScreenInfo *xinerama_screens;
+        XineramaScreenInfo *screen;
+        int nr_xinerama_screens;
+
+        int screen_nr = settings->GetNumSetting("XineramaScreen",0);
+
+        xinerama_screens = XineramaQueryScreens(dpy, &nr_xinerama_screens);
+
+        printf("Found %d Xinerama Screens.\n", nr_xinerama_screens);
+
+        if( screen_nr > 0 && screen_nr < nr_xinerama_screens ) {
+            screen = &xinerama_screens[screen_nr];
+            printf("Using screen %d, %dx%d+%d+%d\n",
+                screen_nr, screen->width, screen->height, screen->x_org, screen->y_org );
+        } else {
+            screen = &xinerama_screens[0];
+            printf("Using first Xinerama screen, %dx%d+%d+%d\n",
+                screen->width, screen->height, screen->x_org, screen->y_org);
+        }
+
+        *w = screen->width;
+        *h = screen->height;
+        *x = screen->x_org;
+        *y = screen->y_org;
+
+        XFree(xinerama_screens);
+    } else {
+        *w = DisplayWidth(dpy, screen_num);
+        *h = DisplayHeight(dpy, screen_num);
+        *x = 0; *y = 0;
+    }
+
+    delete settings;
+}
diff -urN cvs.orig/MC/libs/libmyth/util.h cvs/MC/libs/libmyth/util.h
--- cvs.orig/MC/libs/libmyth/util.h	2002-12-10 04:56:43.000000000 -0600
+++ cvs/MC/libs/libmyth/util.h	2002-12-15 19:16:58.000000000 -0600
@@ -13,4 +13,6 @@
 void encodeLongLong(QStringList &list, long long num);
 long long decodeLongLong(QStringList &list, int offset);
 
+void GetMythTVGeometry(Display *dpy, int screen_num, int *x, int *y, int *w, int *h);
+
 #endif
diff -urN cvs.orig/MC/libs/libmythtv/settings.txt cvs/MC/libs/libmythtv/settings.txt
--- cvs.orig/MC/libs/libmythtv/settings.txt	2002-12-14 05:56:57.000000000 -0600
+++ cvs/MC/libs/libmythtv/settings.txt	2002-12-16 01:03:32.000000000 -0600
@@ -62,6 +62,10 @@
 # Which input on the tuner card to start on?
 str TunerCardInput=Television
 
+# If using Xinerama, what screen to use?
+# Ignored if not using Xinerama
+int XineramaScreen=0
+
 # TV options
 # 
 #
@@ -74,8 +78,8 @@
 str VertScanMode=overscan
 str HorizScanMode=overscan
 # How much do we chop (or add)?  %, 0 - 100
-int VertScanPercentage=5
-int HorizScanPercentage=5
+int VertScanPercentage=1
+int HorizScanPercentage=1
 # How much do we offset the picture?
 int xScanDisplacement=0
 int yScanDisplacement=0
diff -urN cvs.orig/MC/programs/mythbackend/mythbackend.pro cvs/MC/programs/mythbackend/mythbackend.pro
--- cvs.orig/MC/programs/mythbackend/mythbackend.pro	2002-12-12 02:44:15.000000000 -0600
+++ cvs/MC/programs/mythbackend/mythbackend.pro	2002-12-15 19:42:26.000000000 -0600
@@ -20,7 +20,7 @@
 LIBS += -L../../libs/libmythtv -L../../libs/libNuppelVideo 
 LIBS += -L../../libs/libavcodec -L../../libs/libmyth
 
-LIBS += -lmythtv -lNuppelVideo -lavcodec -lmyth-$$LIBVERSION -lXv -lmp3lame 
+LIBS += -lmythtv -lNuppelVideo -lavcodec -lmyth-$$LIBVERSION -lXv -lXinerama -lmp3lame 
 
 TARGETDEPS  = ../../libs/libNuppelVideo/libNuppelVideo.a 
 TARGETDEPS += ../../libs/libmythtv/libmythtv.a
diff -urN cvs.orig/MC/programs/mythfrontend/mythfrontend.pro cvs/MC/programs/mythfrontend/mythfrontend.pro
--- cvs.orig/MC/programs/mythfrontend/mythfrontend.pro	2002-12-08 23:37:04.000000000 -0600
+++ cvs/MC/programs/mythfrontend/mythfrontend.pro	2002-12-15 19:42:03.000000000 -0600
@@ -21,7 +21,7 @@
 LIBS += -L../../libs/libmythtv -L../../libs/libNuppelVideo 
 LIBS += -L../../libs/libavcodec -L../../libs/libmyth
 
-LIBS += -lmythtv -lNuppelVideo -lavcodec -lmyth-$$LIBVERSION -lXv -lmp3lame 
+LIBS += -lmythtv -lNuppelVideo -lavcodec -lmyth-$$LIBVERSION -lXv -lXinerama -lmp3lame 
 
 TARGETDEPS  = ../../libs/libNuppelVideo/libNuppelVideo.a 
 TARGETDEPS += ../../libs/libmythtv/libmythtv.a
diff -urN cvs.orig/MC/programs/mythtv/mythtv.pro cvs/MC/programs/mythtv/mythtv.pro
--- cvs.orig/MC/programs/mythtv/mythtv.pro	2002-10-28 22:58:52.000000000 -0600
+++ cvs/MC/programs/mythtv/mythtv.pro	2002-12-15 19:41:40.000000000 -0600
@@ -14,7 +14,7 @@
 LIBS += -L../../libs/libNuppelVideo -L../../libs/libmythtv 
 LIBS += -L../../libs/libavcodec -L../../libs/libmyth
 
-LIBS += -lmythtv -lNuppelVideo -lavcodec -lmyth-$$LIBVERSION -lXv -lmp3lame
+LIBS += -lmythtv -lNuppelVideo -lavcodec -lmyth-$$LIBVERSION -lXv -lXinerama -lmp3lame
 
 TARGETDEPS  = ../../libs/libNuppelVideo/libNuppelVideo.a
 TARGETDEPS += ../../libs/libmythtv/libmythtv.a

--1547859840-1804289383-1040023847=:16793--