/* * Copyright (C) 2000-2002 the xine project * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * 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.15 2003/05/16 11:39:50 hadess Exp $ * * tvmode - TV output selection * * Currently uses nvtvd (Dirk Thierbach ) * for setting TV mode * xine support hacked in by Matthias Hopf */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "xine_internal.h" #include "xineutils.h" #ifdef XINE_HAVE_NVTV #include "nvtv/back_client.h" /* * PRIVATE */ BackCardPtr back_card = 0; BackAccessPtr back_access = 0; static int current_type, current_width, current_height; static double current_fps; static TVRegs old_tvregs; static TVSettings old_settings; static int tvmode_enabled = 1; static int was_enabled = 0; static TVSystem opt_system = TV_SYSTEM_PAL; static TVConnect opt_connect = CONNECT_NONE; static TVMode *modes_pal = NULL; static int size_modes_pal = 0; static TVMode *modes_ntsc =NULL; static int size_modes_ntsc = 0; static double opt_aspect = 4.0 / 3.0; /* Try to connect to nvtvd server */ static void tvmode_connect(xine_t *this) { CardPtr main_card_list, main_card = NULL; if (was_enabled) { if (this->verbosity >= XINE_VERBOSITY_LOG) printf ("tvmode: Already initialized!\n"); return; } if (back_client_avail ()) { main_card_list = back_client_init (); } else { if (this->verbosity >= XINE_VERBOSITY_LOG) printf ("tvmode: Nvtvd not detected, make sure nvtvd is running.\n"); /* Handle well in some way... */ return; } if (back_access) { back_access->closeCard (); } if (!main_card_list) { if (this->verbosity >= XINE_VERBOSITY_LOG) printf ("tvmode: No supported video card found.\n"); /* Handle well in some way... */ return; } /* Just pick the first, here we might want to pick an alternative card... */ main_card = main_card_list; if (!main_card) { if (this->verbosity >= XINE_VERBOSITY_LOG) printf ("tvmode: No supported video card found at specified address.\n"); /* Handle well in some way... */ return; } if (back_access) { back_access->openCard (main_card); if (this->verbosity >= XINE_VERBOSITY_LOG) printf("tvmode: Using card %s for tvout\n", main_card->name); was_enabled = 1; } else { if (this->verbosity >= XINE_VERBOSITY_LOG) printf("tvmode: cannot connect to nvtvd - no TV mode switching available\n"); } } /* Disconnect from server */ static void tvmode_disconnect (xine_t *this) { back_access->closeCard (); back_access = 0; was_enabled = 0; } /* Save current CRT and TV register configuration */ static void tvmode_savestate (xine_t *this) { back_card->getSettings(&old_settings); back_card->getMode (&old_tvregs); } /* Restore CRT and TV register configuration */ static void tvmode_restorestate (xine_t *this) { back_card->setModeSettings (&old_tvregs,&old_settings); if (this->verbosity >= XINE_VERBOSITY_LOG) printf("tvmode: Old mode saved!"); current_type = 0; } /* Set CRT and TV registers to given TV-Out configuration */ static void tvmode_settvstate (xine_t *this, int width, int height, double fps) { TVSettings settings; TVMode mode; TVMode *modes; int size; int found = 0; int tmp_fps; int i; /* TODO: do that at initialization and save possible combinations */ /* Find supported TV mode */ if (opt_system == TV_SYSTEM_NTSC) { modes = modes_ntsc; size = size_modes_ntsc; tmp_fps = 29.97; } else { modes = modes_pal; tmp_fps = 25; size = size_modes_pal; } for (i=0; i < size; i++) { /* printf ("Trying mode %dx%d %f %f\n", modes[i].spec.res_x, modes[i].spec.res_y, modes[i].spec.hoc, modes[i].spec.voc); */ if ((width <= modes[i].spec.res_x) && (height <= modes[i].spec.res_y) && (back_card->findByOverscan (opt_system, modes[i].spec.res_x, modes[i].spec.res_y, 10, 5, &mode))) { current_width = mode.spec.res_x; current_height = mode.spec.res_y; current_fps = tmp_fps; found++; } } /* Switch to mode */ if (found) { back_card->getSettings (&settings); if (opt_connect > CONNECT_NONE) { settings.connector = opt_connect; } else { settings.connector = CONNECT_BOTH; } mode.regs.devFlags = DEV_MONITOR | DEV_TELEVISION; settings.flags |= TV_DESC_DUALVIEW; back_card->setModeSettings (&mode.regs, &settings); if (this->verbosity >= XINE_VERBOSITY_LOG) printf("tvmode: Trying to use mode %i x %i\n",current_width,current_height); current_type = 1; } else { if (this->verbosity >= XINE_VERBOSITY_LOG) printf("tvmode: cannot find any valid TV mode - TV output disabled\n"); xine_tvmode_exit (this); } } /* * PUBLIC */ /* 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) { xine_tvmode_init(this); } if (back_card) { if (this->verbosity >= XINE_VERBOSITY_LOG) printf("tvmode: switching to %s\n", type ? "TV" : "default"); switch (type) { case 0: tvmode_restorestate (this); break; case 1: tvmode_settvstate (this, width, height, fps); break; default: if (this->verbosity >= XINE_VERBOSITY_LOG) printf("tvmode: illegal type for switching\n"); tvmode_restorestate (this); } } else { if (this->verbosity >= XINE_VERBOSITY_LOG) printf("tvmode: not connected to nvtvd for switching\n"); } } return current_type; } /* Addapt (maximum) output size to visible area and set pixel aspect and fps */ void xine_tvmode_size (xine_t *this, int *width, int *height, double *pixelratio, double *fps) { if(tvmode_enabled) { switch (current_type) { case 1: /* if (width && *width > current_width) */ if (width) *width = current_width; /* if (height && *height > current_height) */ if (height) *height = current_height; if (pixelratio) *pixelratio = ((double) current_width / current_height) / opt_aspect; if (fps) *fps = current_fps; break; } } } void init_modes() { int i; size_modes_pal = back_card->listModes(TV_SYSTEM_PAL, &modes_pal); size_modes_ntsc = back_card->listModes(TV_SYSTEM_NTSC, &modes_ntsc); /* for (i=0; i < size_modes_pal; i++) { printf ("Modes PAL %dx%d %f %f\n", modes_pal[i].spec.res_x, modes_pal[i].spec.res_y, modes_pal[i].spec.hoc, modes_pal[i].spec.voc); } for (i=0; i < size_modes_pal; i++) { printf ("Modes NTSC %dx%d %f %f\n", modes_ntsc[i].spec.res_x, modes_ntsc[i].spec.res_y, modes_ntsc[i].spec.hoc, modes_ntsc[i].spec.voc); } */ } /* Connect to nvtvd server if possible and store settings */ int xine_tvmode_init(xine_t *self) { tvmode_connect (self); if (back_card) { tvmode_savestate (self); init_modes(); return 1; } return 0; } int xine_tvmode_use(xine_t *self, int use_tvmode) { tvmode_enabled = 0; if (use_tvmode) { if (was_enabled || xine_tvmode_init(self)) { tvmode_enabled = 1; } } return (tvmode_enabled); } void xine_tvmode_set_tvsystem(xine_t *self, xine_tvsystem system) { switch (system) { case XINE_TVSYSTEM_PAL: opt_system = TV_SYSTEM_PAL; break; case XINE_TVSYSTEM_NTSC: opt_system = TV_SYSTEM_NTSC; break; default: opt_system = TV_SYSTEM_PAL; } } /* 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); } if (modes_pal != NULL) { free(modes_pal); } if (modes_ntsc != NULL) { free(modes_ntsc); } } } #else /* no nvtv support compiled in lib */ int xine_tvmode_switch (xine_t *this, int type, int width, int height, double fps) { /* not supported: return regular mode */ return 0; } void xine_tvmode_size (xine_t *this, int *width, int *height, double *pixelratio, double *fps) { } int xine_tvmode_init (xine_t *this) { return 0; } void xine_tvmode_exit (xine_t *this) { } void xine_tvmode_set_tvsystem(xine_t *self, xine_tvsystem system) { } int xine_tvmode_use(xine_t *self, int use_tvmode) { return 0; } #endif