diff options
author | Matthias Hopf <mat@mshopf.de> | 2002-08-02 14:09:05 +0000 |
---|---|---|
committer | Matthias Hopf <mat@mshopf.de> | 2002-08-02 14:09:05 +0000 |
commit | e99e0c28715fd6fd81482076cd683a3566ffcbff (patch) | |
tree | b194dd4ec7b340ab0ee3e1db739c9c6c907ce73d | |
parent | 9bb5df799a3955eb5cdf8e8108d31b7367186379 (diff) | |
download | xine-lib-e99e0c28715fd6fd81482076cd683a3566ffcbff.tar.gz xine-lib-e99e0c28715fd6fd81482076cd683a3566ffcbff.tar.bz2 |
TV mode selection enhanced.
CVS patchset: 2384
CVS date: 2002/08/02 14:09:05
-rw-r--r-- | src/xine-engine/nvtvd.h | 16 | ||||
-rw-r--r-- | src/xine-engine/tvmode.c | 612 |
2 files changed, 498 insertions, 130 deletions
diff --git a/src/xine-engine/nvtvd.h b/src/xine-engine/nvtvd.h index 4bbefc756..0e7303691 100644 --- a/src/xine-engine/nvtvd.h +++ b/src/xine-engine/nvtvd.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: nvtvd.h,v 1.2 2002/06/26 15:57:47 jkeil Exp $ + * $Id: nvtvd.h,v 1.3 2002/08/02 14:09:05 mshopf Exp $ * * nvtvd - Routines for communication with nvtvd. * @@ -231,10 +231,14 @@ typedef union _DevUnion { #include <X11/Xmd.h> #ifdef __GNUC__ -#define DEBUG(x) /*x*/ +#ifndef DEBUG +# define DEBUG(x) /*x*/ +#endif #define ErrorF(x...) fprintf(stderr,x) #else -#define DEBUG(x) /*x*/ +#ifndef DEBUG +# define DEBUG(x) /*x*/ +#endif #define ErrorF(...) fprintf(stderr, __VA_ARGS__) #endif @@ -578,7 +582,7 @@ typedef struct _riva_hw_inst * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: nvtvd.h,v 1.2 2002/06/26 15:57:47 jkeil Exp $ + * $Id: nvtvd.h,v 1.3 2002/08/02 14:09:05 mshopf Exp $ * * Contents: * @@ -1095,7 +1099,7 @@ typedef struct { * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: nvtvd.h,v 1.2 2002/06/26 15:57:47 jkeil Exp $ + * $Id: nvtvd.h,v 1.3 2002/08/02 14:09:05 mshopf Exp $ * * Contents: * @@ -1211,7 +1215,7 @@ extern BackCardPtr back_card; * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: nvtvd.h,v 1.2 2002/06/26 15:57:47 jkeil Exp $ + * $Id: nvtvd.h,v 1.3 2002/08/02 14:09:05 mshopf Exp $ * * Contents: * diff --git a/src/xine-engine/tvmode.c b/src/xine-engine/tvmode.c index 6ac3497bd..4df7fff8d 100644 --- a/src/xine-engine/tvmode.c +++ b/src/xine-engine/tvmode.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: tvmode.c,v 1.5 2002/07/12 20:36:04 f1rmb Exp $ + * $Id: tvmode.c,v 1.6 2002/08/02 14:09:05 mshopf Exp $ * * tvmode - TV output selection * @@ -30,76 +30,102 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <ctype.h> #include <unistd.h> +#include <limits.h> #include "nvtvd.h" +#include "xine_internal.h" +/* FIXME: how to include that? */ +/*#include "xine.h" */ #include "xine_internal.h" #include "xineutils.h" +#define ABS(x) ((x)>0?(x):-(x)) +#define APPROX(x,y) (ABS((x)-(y)) < 1e-2) /* less than 1% difference */ + /* * PRIVATE */ +/* TODO: config */ +static TVConnect opt_connect = CONNECT_AUTO; +static int opt_flicker = -1; + +typedef struct { + int width, height; + int fps; + int quality; + char overscan[16]; +} scan_mode_t; + /* FIXME: currently the used backend only supports one (1) connection * to a server and needs this global, external pointer */ +/* Thus we do not care about saving data in a own structure now... */ BackCardRec *back_card = 0; BackAccessRec *back_access = 0; -static int current_type, current_width, current_height; -static double current_fps; -static TVCrtRegs old_crt; -static TVRegs old_tv; - -static int tvmode_enabled; -static int was_enabled = 0; - - -/* TODO: config, and better */ -static TVSystem opt_system = TV_SYSTEM_PAL; -static TVConnect opt_connect = CONNECT_AUTO; - -/* This is the list of possible modes for the used TV system. - * TODO: - * if select_origsize == false: - * The one closest (but larger) to the input stream size is selected. - * if select_origsize == true: - * The first available mode is selected (stick to tv resolution) */ -static int scan_mode_pal[][2] = { - { 768, 576 }, { 800, 576 }, { 720, 576 }, - { 800, 600 }, - { 720, 480 }, { 640, 480 }, - { 800, 450 }, - { 1024, 768 }, - { 0 } -} ; +static int tv_stream_width, tv_stream_height; +static double tv_stream_fps; +static int tv_current_type, tv_current_system; +static int tv_current_width, tv_current_height; +static double tv_current_fps; +static TVCrtRegs tv_old_crt; +static TVRegs tv_old_tv; + +static int tv_verbose; +static int tv_capabilities; +static int tv_policy; +static int tv_prefered_fps; +static double tv_aspect; + +/* This is the list of possible modes for the used refresh rates */ +static const char *tv_scan_mode; + +/* Constant data */ +enum { TV_CAP_PAL = 1, TV_CAP_PAL60 = 2, TV_CAP_NTSC = 4 }; +static char *tv_systems_list[] = { + "No TV connected", "PAL only", "NTSC only", + "PAL and PAL60", "PAL and NTSC", "PAL, PAL60, NTSC", NULL +}; +static const int tv_system_caps[] = { + 0, TV_CAP_PAL, TV_CAP_NTSC, + TV_CAP_PAL|TV_CAP_PAL60, TV_CAP_PAL|TV_CAP_NTSC, + TV_CAP_PAL|TV_CAP_PAL60|TV_CAP_NTSC +}; + +#define SCAN_NATIVE_25 576 +#define SCAN_NATIVE_30 480 +static char *tv_scan_mode_default = +"768x576*25,800x576*25,720x576*25,704x576*25," /* Best PAL modes */ +"768x480*30,800x480*30,720x480*30," /* Best NTSC modes */ +"640x576*25,640x480*30,480x576*25,480x480*30," /* Smaller width modes */ +"800x600,800x450,1024x768"; /* Non-Native modes */ +/* Modes that are not included due to common misconfigurations: + * 640x400*30,640x480*25 + */ +enum { TV_POL_FPS_BEST = 0, TV_POL_FPS_MATCH, + TV_POL_FPS_LIST, TV_POL_MATCH_FPS }; +static char *tv_policies_list[] = { + "FPS - Best Native Match", "FPS - Best Match", "FPS - List Order", + "Best Match - FPS", NULL +}; + +static char *tv_aspect_list[] = { + "4:3", "16:9", NULL +}; +static const double tv_aspect_aspects[] = { 4.0/3.0, 16.0/9.0 }; /* Overscan sizes to be scaned for - note that we do *not* scan for 'Small' */ static char *scan_overscan[] = { - "Interl", "Huge", "Large", "DVD", "Normal", 0 -} ; + "DVD", "Interl", "Huge", "Large", "Normal", 0 +}; -/* TODO: flexible */ -static int opt_flicker = -1; -static double opt_aspect = 4.0 / 3.0; /* Just turn off warnings */ -static void _tvmode_init(xine_t *this); void xine_tvmode_exit (xine_t *this); -/* - * Config callback for tvmode enability. - */ -static void nvtvmode_enable_cb(void *this_gen, cfg_entry_t *entry) { - xine_t *this = (xine_t *) this_gen; - - tvmode_enabled = entry->num_value; - - if(!tvmode_enabled && was_enabled) { - xine_tvmode_exit(this); - was_enabled = 0; - } -} /* Try to connect to nvtvd server */ static void tvmode_connect(xine_t *this) { @@ -116,35 +142,158 @@ static void tvmode_connect(xine_t *this) { back_card = 0; } - if (back_card) { - back_card->openCard (card); - was_enabled = 1; + if (back_card) + { + printf ("tvmode: connected to nvtvd\n"); + back_card->openCard (card); } else - printf("tvmode: cannot connect to nvtvd - no TV mode switching available\n"); + printf ("tvmode: cannot connect to nvtvd - TV mode switching disabled\n"); } /* Disconnect from server */ static void tvmode_disconnect (xine_t *this) { back_card->closeCard (); + printf ("tvmode: disconnected\n"); back_card = 0; } /* Save current CRT and TV register configuration */ static void tvmode_savestate (xine_t *this) { - back_card->getMode (&old_crt, &old_tv); + back_card->getMode (&tv_old_crt, &tv_old_tv); } /* Restore CRT and TV register configuration */ static void tvmode_restorestate (xine_t *this) { - back_card->setMode (0, &old_crt, &old_tv); - current_type = 0; + printf ("tvmode: switching back to regular display\n"); + back_card->setMode (0, &tv_old_crt, &tv_old_tv); + tv_current_type = 0; } +/* Connect to nvtvd server if possible and save current card config */ +static void tvmode_startup (xine_t *this) { + if (tv_capabilities && ! back_card) + tvmode_connect (this); + if (back_card) + tvmode_savestate (this); +} + + +/* Disconnect and recover */ +static void tvmode_closedown (xine_t *this) { + if (back_card) { + tvmode_restorestate (this); + tvmode_disconnect (this); + } +} + + +/* Sort callback */ +static int tvmode_cmp_scanmode_cb (const void *a, const void *b) { + return ((const scan_mode_t *) b) -> quality - + ((const scan_mode_t *) a) -> quality; +} + + +/* Parse mode string and set mode scan table accordingly */ +/* Returns next free mode slot */ +/* Table will be sorted based on prefwidth/prefheight/fps, when sortmode!=0 */ +static scan_mode_t *set_modes (xine_t *this, scan_mode_t *modes, int maxnum, + scan_mode_t *sortmodes, + const char *string, int fps, + int prefwidth, int minwidth, int maxwidth, + int prefheight, int minheight, int maxheight) { + const char *s = string; + int num = 0; + int i, w, h, f; + char overscan[16], *os; + + /* Check whether system is available */ + if (fps == 30 && ! (tv_capabilities & (TV_CAP_PAL60 | TV_CAP_NTSC))) + return modes; + if (fps == 25 && ! (tv_capabilities & TV_CAP_PAL)) + return modes; + + if (tv_verbose) + printf ("tmode: selecting modes, preferred %dx%d fps %d, min %dx%d\n", + prefwidth, prefheight, fps, minwidth, minheight); + /* scan modes */ + while (num < maxnum) { + while (isspace ((int) *s) || *s == ',') s++; + if (! *s) + break; + i = w = h = -1; + sscanf (s, " %d x %d %n", &w, &h, &i); + if (i < 2 || w <= 0 || h <= 0) { + printf ("tvmode: mode line syntax error after '%s'\n", s); + break; + } + s += i; + overscan [0] = 0; + if (*s == '/') { + s++; + os = overscan; + while (isspace ((int) *s)) s++; + while (isalnum ((int) *s) && os < &overscan[16-1]) + *os++ = *s++; + *os = 0; + } + f = fps; + if (*s == '*') { + f = -1; + sscanf (s, "* %d %n", &f, &i); + if (i < 1 || f <= 0) { + printf ("tvmode: mode line syntax error after '%s'\n", s); + break; + } + s += i; + } + if (w >= minwidth && w <= maxwidth + && h >= minheight && h <= maxheight + && f == fps) { + + int diff = prefwidth*prefheight - w*h; + modes[num].width = w; + modes[num].width = w; + modes[num].height = h; + modes[num].fps = f; + strncpy (modes[num].overscan, overscan, 16); + /* Set quality = Size diff in pixels + Diff in fps + * + penalty for too small sizes */ + modes[num].quality = - ABS (diff) - ABS (f - fps) + - (prefwidth > w ? 1000 * h : 0) + - (prefheight > h ? 2000 * w : 0); + if (tv_verbose) + printf ("tvmode: entry %dx%d [%s] fps %d quality %d\n", + w, h, overscan, f, modes[num].quality); + num++; + } else { + if (tv_verbose) + printf ("tvmode: entry %dx%d [%s] fps %d rejected\n", + w, h, overscan, f); + } + if (*s != ',') { + if (*s) + printf ("tvmode: mode line syntax error after '%s'\n", s); + break; + } + } + if (num >= maxnum) + printf ("tvmode: mode array overflow - some modes are not tested\n"); + if (! sortmodes) + return modes + num; + /* Now sort */ + qsort (sortmodes, (modes-sortmodes) + num, sizeof (scan_mode_t), + tvmode_cmp_scanmode_cb); + if (tv_verbose) + printf ("tvmode: sorted\n"); + return modes + num; +} + /* Set CRT and TV registers to given TV-Out configuration */ static void tvmode_settvstate (xine_t *this, int width, int height, double fps) { @@ -153,43 +302,184 @@ static void tvmode_settvstate (xine_t *this, int width, int height, double fps) TVCrtRegs crt; TVRegs tv; int found = 0; - int *scanm; - char **scano; - + scan_mode_t modes[256]; /* FIXME: shouldn't be fix */ + scan_mode_t *m = modes; + scan_mode_t *last_mode; + int best_rate; + char **scano; + char *current_overscan = ""; + TVSystem sys; + int i; + + if (tv_verbose) + printf ("tvmode: Requested mode for %dx%d, %g fps\n", + width, height, fps); + /* Modify the settings */ back_card->getSettings (&settings); - if (opt_connect > CONNECT_NONE) { - settings.connector = opt_connect; - } else { - settings.connector = CONNECT_BOTH; - } - if (opt_flicker >= 0) { + settings.connector = opt_connect; + if (opt_flicker >= 0) settings.flicker = opt_flicker; + + /* Check fps for capability selection */ + best_rate = tv_prefered_fps; + if (APPROX (fps, 60) || APPROX (fps, 30) || + APPROX (fps, 20) || APPROX (fps, 15)) + best_rate = 30; + if (APPROX (fps, 50) || APPROX (fps, 25) || + APPROX (fps, 50.0/3) || APPROX (fps, 12.5)) + best_rate = 25; + + /* Scan mode strings and create scan table */ + /* TODO: do that at initialization and save possible combinations ?!? */ + switch (tv_policy) { + case TV_POL_FPS_BEST: + if (APPROX (fps, 24)) /* FIXME: hardcoded for this policy only */ + best_rate = 30; + if (best_rate == 30) + { + m = set_modes (this, m, &modes[256]-m, m, tv_scan_mode, 30, + width, 0, INT_MAX, + SCAN_NATIVE_30, SCAN_NATIVE_30, SCAN_NATIVE_30); + m = set_modes (this, m, &modes[256]-m, m, tv_scan_mode, 30, + width, 0, INT_MAX, height, 0, INT_MAX); + } + m = set_modes (this, m, &modes[256]-m, m, tv_scan_mode, 25, + width, 0, INT_MAX, + SCAN_NATIVE_25, SCAN_NATIVE_25, SCAN_NATIVE_25); + m = set_modes (this, m, &modes[256]-m, m, tv_scan_mode, 25, + width, 0, INT_MAX, height, 0, INT_MAX); + if (best_rate != 30) + { + m = set_modes (this, m, &modes[256]-m, m, tv_scan_mode, 30, + width, 0, INT_MAX, + SCAN_NATIVE_30, SCAN_NATIVE_30, SCAN_NATIVE_30); + m = set_modes (this, m, &modes[256]-m, m, tv_scan_mode, 30, + width, 0, INT_MAX, height, 0, INT_MAX); + } + break; + case TV_POL_FPS_MATCH: + if (best_rate == 30) + m = set_modes (this, m, &modes[256]-m, m, tv_scan_mode, 30, + width, 0, INT_MAX, height, 0, INT_MAX); + m = set_modes (this, m, &modes[256]-m, m, tv_scan_mode, 25, + width, 0, INT_MAX, height, 0, INT_MAX); + if (best_rate != 30) + m = set_modes (this, m, &modes[256]-m, m, tv_scan_mode, 30, + width, 0, INT_MAX, height, 0, INT_MAX); + break; + case TV_POL_FPS_LIST: + if (best_rate == 30) + m = set_modes (this, m, &modes[256]-m, NULL, tv_scan_mode, 30, + width, 0, INT_MAX, height, 0, INT_MAX); + m = set_modes (this, m, &modes[256]-m, NULL, tv_scan_mode, 25, + width, 0, INT_MAX, height, 0, INT_MAX); + if (best_rate != 30) + m = set_modes (this, m, &modes[256]-m, NULL, tv_scan_mode, 30, + 0, 0, INT_MAX, 0, 0, INT_MAX); + break; + case TV_POL_MATCH_FPS: + if (height <= SCAN_NATIVE_30 && best_rate == 30) { + m = set_modes (this, m, &modes[256]-m, NULL, tv_scan_mode, 30, + width, 0, INT_MAX, height, 0, INT_MAX); + m = set_modes (this, m, &modes[256]-m, modes, tv_scan_mode, 25, + width, 0, INT_MAX, height, 0, INT_MAX); + } else { + m = set_modes (this, m, &modes[256]-m, NULL, tv_scan_mode, 25, + width, 0, INT_MAX, height, 0, INT_MAX); + m = set_modes (this, m, &modes[256]-m, modes, tv_scan_mode, 30, + width, 0, INT_MAX, height, 0, INT_MAX); + } + break; + default: + abort (); } - /* TODO: do that at initialization and save possible combinations */ - /* Find supported TV mode */ - for (scanm = &scan_mode_pal[0][0]; *scanm && ! found; scanm += 2) { - for (scano = scan_overscan; *scano && ! found; scano++) { - printf("tvmode: trying to use %dx%d %s\n", - scanm[0], scanm[1], *scano); - if (back_card->findBySize (opt_system, scanm[0], scanm[1], *scano, + last_mode = m; + + if (tv_verbose) { + printf ("tvmode: ->"); + for (i = 0; i < last_mode-modes; i++) + printf (" %dx%d/%s*%d", modes[i].width, modes[i].height, + modes[i].overscan, modes[i].fps); + printf ("\n"); + } + + /* Select first mode that is actually known to the chip */ + for (m = modes; m < last_mode && !found; m++) { + sys = TV_SYSTEM_PAL; + if (m->fps == 30 && (tv_capabilities & TV_CAP_PAL60)) + sys = TV_SYSTEM_PAL_60; + else if (m->fps == 30 && (tv_capabilities & TV_CAP_NTSC)) + sys = TV_SYSTEM_NTSC; + if (! *m->overscan) { + for (scano = scan_overscan; *scano && !found; scano++) { + if (tv_verbose) + printf ("tvmore: trying to use %dx%d [%s] fps %d\n", + m->width, m->height, *scano, m->fps); + if (back_card->findBySize (sys, m->width, m->height, *scano, + &mode, &crt, &tv)) { + tv_current_width = m->width; + tv_current_height = m->height; + tv_current_system = sys; + tv_current_fps = m->fps; + current_overscan = *scano; + found++; + } else if (sys == TV_SYSTEM_PAL_60 && + (tv_capabilities & TV_CAP_NTSC) && + back_card->findBySize (TV_SYSTEM_NTSC, + m->width, m->height, *scano, + &mode, &crt, &tv)) { + tv_current_width = m->width; + tv_current_height = m->height; + tv_current_system = TV_SYSTEM_NTSC; + tv_current_fps = m->fps; + current_overscan = *scano; + found++; + } + } + } else { + if (tv_verbose) + printf ("tvmore: trying to use %dx%d [%s] fps %d\n", + m->width, m->height, m->overscan, m->fps); + if (back_card->findBySize (sys, m->width, m->height, m->overscan, &mode, &crt, &tv)) { - current_width = scanm[0]; - current_height = scanm[1]; - current_fps = 25; /* TODO: currently this is PAL only */ + tv_current_width = m->width; + tv_current_height = m->height; + tv_current_system = sys; + tv_current_fps = m->fps; + current_overscan = m->overscan; + found++; + } else if (sys == TV_SYSTEM_PAL_60 && + (tv_capabilities & TV_CAP_NTSC) && + back_card->findBySize (TV_SYSTEM_NTSC, + m->width, m->height, m->overscan, + &mode, &crt, &tv)) { + tv_current_width = m->width; + tv_current_height = m->height; + tv_current_system = TV_SYSTEM_NTSC; + tv_current_fps = m->fps; + current_overscan = m->overscan; found++; } } } + + /* Modify found Crt settings */ + crt.PrivFlags &= ~TV_MODE_MACROVISION; /* Switch to mode */ if (found) { + printf ("tvmode: Switching to TV %dx%d [%s] fps %g %s\n", + tv_current_width, tv_current_height, current_overscan, + tv_current_fps, tv_current_system == TV_SYSTEM_PAL ? "PAL" : + tv_current_system == TV_SYSTEM_PAL_60 ? "PAL60" : + tv_current_system == TV_SYSTEM_NTSC ? "NTSC" : "UNKNOWN"); back_card->setModeSettings (TV_PRIV_TVMODE | TV_PRIV_DUALVIEW, &crt, &tv, &settings); - current_type = 1; + tv_current_type = 1; } else { - printf("tvmode: cannot find any valid TV mode - TV output disabled\n"); - xine_tvmode_exit (this); + printf ("tvmode: cannot find any valid TV mode - TV output disabled\n"); + tvmode_closedown (this); } } @@ -201,34 +491,23 @@ static void tvmode_settvstate (xine_t *this, int width, int height, double fps) /* Set to 'regular'(0) or 'tv'(1) state, that is if it is enabled */ int xine_tvmode_switch (xine_t *this, int type, int width, int height, double fps) { - if(tvmode_enabled) { - - /* - * Wasn't initialized - */ - if(!was_enabled) - _tvmode_init(this); - if (back_card) { - printf("tvmode: switching to %s\n", type ? "TV" : "default"); switch (type) { case 0: tvmode_restorestate (this); break; case 1: + tv_stream_width = width; + tv_stream_height = height; + tv_stream_fps = fps; tvmode_settvstate (this, width, height, fps); break; default: - printf("tvmode: illegal type for switching\n"); + printf ("tvmode: illegal type for switching\n"); tvmode_restorestate (this); } - } else { - printf("tvmode: not connected to nvtvd for switching\n"); } - - } - - return current_type; + return tv_current_type; } @@ -236,48 +515,133 @@ int xine_tvmode_switch (xine_t *this, int type, int width, int height, double fp void xine_tvmode_size (xine_t *this, int *width, int *height, double *pixelratio, double *fps) { - if(tvmode_enabled) { - - switch (current_type) { + switch (tv_current_type) { case 1: - if (width && *width > current_width) - *width = current_width; - if (height && *height > current_height) - *height = current_height; - if (pixelratio) - *pixelratio = ((double) current_width / current_height) / opt_aspect; - if (fps) - *fps = current_fps; - break; + if (width && *width > tv_current_width) + *width = tv_current_width; + if (height && *height > tv_current_height) + *height = tv_current_height; + if (pixelratio) + *pixelratio = ((double) tv_current_width / tv_current_height) + / tv_aspect; + if (fps) + *fps = tv_current_fps; + break; } - - } } -/* Connect to nvtvd server if possible and fetch settings */ -static void _tvmode_init(xine_t *this) { - if(tvmode_enabled) { - tvmode_connect (this); - if (back_card) - tvmode_savestate (this); - } + +/* Configuration callbacks */ +static void tvmode_system_cb (void *data, cfg_entry_t *entry) { + xine_t *this = (xine_t *) data; + tv_capabilities = tv_system_caps [entry->num_value]; + if (tv_capabilities && !back_card) + tvmode_startup (this); + else if (!tv_capabilities && back_card) + tvmode_closedown (this); +} +static void tvmode_policy_cb (void *data, cfg_entry_t *entry) { + xine_t *this = (xine_t *) data; + tv_policy = entry->num_value; + xine_tvmode_switch (this, tv_current_type, tv_stream_width, + tv_stream_height, tv_stream_fps); +} +static void tvmode_mode_cb (void *data, cfg_entry_t *entry) { + xine_t *this = (xine_t *) data; + tv_scan_mode = entry->str_value; + if (*tv_scan_mode == '-') + this->config->update_string (this->config, "tv.modes", tv_scan_mode_default); + xine_tvmode_switch (this, tv_current_type, tv_stream_width, + tv_stream_height, tv_stream_fps); } +static void tvmode_aspect_cb (void *data, cfg_entry_t *entry) { + xine_t *this = (xine_t *) data; + tv_aspect = tv_aspect_aspects[entry->num_value]; + xine_tvmode_switch (this, tv_current_type, tv_stream_width, + tv_stream_height, tv_stream_fps); +} +static void tvmode_preferred_fps_cb (void *data, cfg_entry_t *entry) { + xine_t *this = (xine_t *) data; + tv_prefered_fps = entry->num_value ? 25 : 30; + xine_tvmode_switch (this, tv_current_type, tv_stream_width, + tv_stream_height, tv_stream_fps); +} +static void tvmode_verbose_cb (void *data, cfg_entry_t *entry) { + tv_verbose = entry->num_value; +} + + +/* Connect to nvtvd server if possible and register settings */ void xine_tvmode_init (xine_t *this) { - - tvmode_enabled = this->config->register_bool(this->config, "misc.nv_tvmode", 0, - _("NVidia TV-Out support."), - NULL, nvtvmode_enable_cb, this); - _tvmode_init(this); + /* TODO: + * more config options that can be imagined: + * - disable deinterlacing for tv mode only + * - flickerfilter + * - input filters + * - connectors + dual view + * - color systems (PAL / PAL_M / etc.) + * - FILM (24 fps) -> 50 / 60Hz / 50Hz+Speedup ? + */ + tv_capabilities = tv_system_caps [this->config->register_enum ( + this->config, "tv.capabilities", + 0, tv_systems_list, _("TV System"), + "Capabilities of the connected TV system", + tvmode_system_cb, this)]; + tv_policy = this->config->register_enum ( + this->config, "tv.policy", + 0, tv_policies_list, _("Mode Selection Policy"), + "FPS - Best Native Match:\n" + "Select system (50/60Hz) according to frame rate and TV system,\n" + "select 60Hz for FILM (24 fps),\n" + "select native resolutions only if available,\n" + "select best matching mode for given video size.\n" + "This policy prefers correct frame rates to better resolutions." + "Recommended.\n\n" + "FPS - Best Match:\n" + "Select system (50/60Hz) according to frame rate,\n" + "select 50Hz for FILM (24 fps),\n" + "select best matching mode for given video size.\n\n" + "FPS - List Order:\n" + "Select system (50/60Hz) according to frame rate,\n" + "select 50Hz for FILM (24 fps),\n" + "select first available mode in the modes list.\n\n" + "Best Match - FPS:\n" + "Select best matching mode for the given video size,\n" + "select system (50/60Hz) according to frame rate and TV system.\n" + "This policy prefers better resolutions to correct frame rates.", + tvmode_policy_cb, this); + tv_scan_mode = this->config->register_string ( + this->config, "tv.modes", + tv_scan_mode_default, _("Modes"), + "Specify valid resolutions.\n" + "<width>x<height>[/<overscan>][*<fps>][, ...]\n" + "Enter '-' to use default list.\n" + "When no overscan mode is given, the following list is tried:\n" + "'Interl', 'Huge', 'Large', 'DVD', 'Normal'\n" + "When no FPS value is given, mode is valid for both, " + "25 (PAL) and 30 (PAL60/NTSC).", + tvmode_mode_cb, this); + tv_prefered_fps = this->config->register_bool ( + this->config, "tv.preferPAL", 1, _("Prefer PAL"), + "Prefer 50Hz modes to 60Hz modes for videos " + "with nonstandard frame rates", + tvmode_preferred_fps_cb, this) + ? 25 : 30; + tv_verbose = this->config->register_bool ( + this->config, "tv.verbose", 0, _("Verbose resolution selection"), + NULL, tvmode_verbose_cb, this); + if (*tv_scan_mode == '-') + this->config->update_string (this->config, "tv.modes", tv_scan_mode_default); + tv_aspect = tv_aspect_aspects [this->config->register_enum ( + this->config, "tv.aspect", + 0, tv_aspect_list, _("Screen Aspect Ratio"), NULL, + tvmode_aspect_cb, this)]; + tvmode_startup (this); } /* Restore old CRT and TV registers and close nvtvd connection */ void xine_tvmode_exit (xine_t *this) { - if(tvmode_enabled || was_enabled) { - if (back_card) { - tvmode_restorestate (this); - tvmode_disconnect (this); - } - } + tvmode_closedown (this); } |