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

mythtv-dev@snowman.net mythtv-dev@snowman.net
Tue, 17 Dec 2002 13:13:20 -0600 (CST)


--1547859840-1804289383-1040152406=:9739
Content-Type: TEXT/plain; CHARSET=US-ASCII

Ok, here is a revision of my previous patch. It should apply to  CVS as
of Dec 17 12:30.

Nothing new. just moved over/underscan out of XvOutput::Show() to a new
function XVoutput:MoveResize. I haven't added true fullscreen yet. I
wanted to get this in first because it is a pain keeping up with all
the other patches going into CVS. 

-matthew


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

diff -uNr 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-17 12:44:51.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,66 +409,18 @@
     {
         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);
-
-    XRaiseWindow(data->XJ_disp, data->XJ_win);
-    XFlush(data->XJ_disp);
+    MoveResize();
 
     pthread_mutex_unlock(&lock);
 }
@@ -520,11 +481,11 @@
         memcpy((unsigned char *)image->data + (width * height) * 5 / 4,
                scratchspace, width * height / 4);
     }
-   
+
     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);
@@ -559,3 +520,104 @@
 
     return key;
 }
+
+void XvVideoOutput::MoveResize(void)
+{
+    int yoff, xoff;
+
+    XMoveResizeWindow(data->XJ_disp, data->XJ_win, curx, cury, curw, curh);
+    XMapRaised(data->XJ_disp, data->XJ_win);
+
+    XRaiseWindow(data->XJ_disp, data->XJ_win);
+    XFlush(data->XJ_disp);
+
+    // Preset all image placement and sizing variables.
+    imgx = 0; imgy = 0;
+    imgw = XJ_width; imgh = XJ_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(XJ_height * img_vscanf);
+        imgh = (int)ceil(XJ_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(XJ_width * img_hscanf);
+        imgw = (int)ceil(XJ_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;
+        }
+    }
+
+}
+
+
+
diff -uNr 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-17 12:44:51.000000000 -0600
@@ -22,6 +22,7 @@
 
     void EmbedInWidget(unsigned long wid, int x, int y, int w, int h);
     void StopEmbedding(void);
+    void MoveResize(void);
 
 
   private:
@@ -45,6 +46,9 @@
 
     int oldx, oldy, oldw, oldh;
     int curx, cury, curw, curh;
+    int img_xoff, img_yoff; 
+    int imgx, imgy, imgw, imgh, dispxoff, dispyoff, dispwoff, disphoff;
+    float img_hscanf, img_vscanf;
 
     int dispx, dispy, dispw, disph;
     int olddispx, olddispy, olddispw, olddisph;
diff -uNr cvs.orig/MC/libs/libmyth/mythwidgets.cpp cvs/MC/libs/libmyth/mythwidgets.cpp
--- cvs.orig/MC/libs/libmyth/mythwidgets.cpp	2002-12-17 00:09:26.000000000 -0600
+++ cvs/MC/libs/libmyth/mythwidgets.cpp	2002-12-17 12:50:25.000000000 -0600
@@ -7,6 +7,7 @@
 
 #include "mythwidgets.h"
 #include "mythcontext.h"
+#include "util.h"
 
 void MythComboBox::keyPressEvent(QKeyEvent *e)
 {
@@ -283,7 +284,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 -uNr cvs.orig/MC/libs/libmyth/util.cpp cvs/MC/libs/libmyth/util.cpp
--- cvs.orig/MC/libs/libmyth/util.cpp	2002-12-16 23:18:19.000000000 -0600
+++ cvs/MC/libs/libmyth/util.cpp	2002-12-17 12:47:47.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)
 {
@@ -120,3 +127,50 @@
 
     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 -uNr 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-17 12:48:40.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 -uNr 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-17 13:05:02.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 -uNr 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-17 12:52:13.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 -uNr 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-17 12:51:53.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 -uNr 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-17 12:44:51.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-1040152406=:9739--