[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--