""" Contains the main GUI class (KPart), use as if a MainWindow """ ## MODULE IMPORTS ######################################################## import os, sys, time, commands KBTV_MAINPATH = os.path.dirname(os.path.abspath(sys.argv[0])) if not KBTV_MAINPATH in sys.path: sys.path.append(KBTV_MAINPATH) import btcopyright, bthardware, btchannels, btdriver, bt848, buildprefs if buildprefs.WITH_SAA: import saa if buildprefs.WITH_PWC: import pwc from qt import QLabel, QPixmap, QIconSet, Qt, QSize, QString, QSizePolicy, \ QWidget, QMenuData, QApplication from kdecore import i18n, KGlobal, KIcon, KIconLoader, KShortcut, KKey, \ KStdAccel from kparts import KParts from kdeui import KStdAction, KAction, KSelectAction, KActionSeparator, \ KActionMenu, KXMLGUIClient, KRadioAction, KActionCollection, \ KToggleFullScreenAction, KToggleAction, KToolBar, QXEmbed, KMessageBox from kbtv_picture import KbtvPictureSettings from kbtv_channels import KbtvChannelEditor from kbtv_hardware import KbtvHardwareInfo from kbtv_toolbar import KbtvToolbarWidget ## MODULE COPYRIGHT ###################################################### MODULE_AUTHOR = btcopyright.MY_NAME MODULE_AUTHOR_EMAIL = btcopyright.MY_EMAIL MODULE_COPYRIGHT = btcopyright.MY_COPYRIGHT MODULE_LICENSE = btcopyright.BSD_LICENSE MODULE_LICENSE_TEXT = btcopyright.BSD_LICENSE_TEXT ## CONSTANTS ############################################################# STATUSBAR_LEFT = 1 STATUSBAR_MIDDLE = 2 STATUSBAR_RIGHT = 3 MINVOL, MAXVOL = 0, 100 KBTV_XMLFILE = "kbtvui.rc" KBTV_SCREENSIZE_SMALL = (240, 180) KBTV_SCREENSIZE_MEDIUM = (400, 300) KBTV_SCREENSIZE_LARGE = (640, 480) ## KBTVPART CLASS ######################################################## class KbtvPart(KParts.MainWindow): """ Main GUI class, inherits KParts.MainWindow. """ def __init__(self, *args): """ -> KbtvPart The constructor takes the usual QObject/Mainwindow arguments, they are just passed through to KParts.MainWindow which is inherited. The first of these is always the parent. The KbtvPart is meant to be the main widget of the application. First it creates the editor, picture settings, and channel editor dialogs. Reuses the chanlist from the editor. Initializes the menus and toolbars and associated actions. Creates a videoarea central widget (where the viewer ultimately embeds into) and makes this a KPart. Finally reads XML GUI layout, creates the GUI, finishes up the toolbar, and sets up the statusbar. """ KParts.MainWindow.__init__(self, *args) self.muteAudio() self.screensize = KBTV_SCREENSIZE_MEDIUM self.maxsize = KBTV_SCREENSIZE_LARGE if btdriver.use_driver == "saa": if "PAL" in bthardware.saa_norm(): self.maxsize = (720 * 16/15, 576) if btdriver.use_driver == "bt848": if bthardware.bktr_norm() == bthardware.NORM_PAL: self.maxsize = (768, 576) # Dialogs, persistant objects; argument self means we are parent self.hwinfo = KbtvHardwareInfo(self) self.editor = KbtvChannelEditor(self) #self.picsettings = KbtvPictureSettings(None, self) self.picsettings = None # Create this at viewer_init, tuner_init # Use chanlist object from editor self.chanlist = self.editor.chanlist # Current channel set to number 0 or 1 if it exists if self.chanlist.len() > 1: self.current = 1 else: self.current = 0 # The chosen mixer channel (name) self.mixerchan = "line" # Available mixer channels (names) self.mixerchans = [] for chan in bthardware.mixer_channels(): self.mixerchans.append(bthardware.MIXER_CHANNEL_NAMES[ bthardware.MIXER_CHANNELS.index(chan)]) # Actions, menus, toolbar. Of StdActions, only Help can be used. self.initActions() # Video area self.initVideoArea() # Part, GUI self.initPartGUI() # Add custom widget to toolbar self.extendToolbar() # Status self.status = ["", "", ""] self.initStatusBar() # Hide camera menu self.menuBar().setItemVisible(self.menuBar().idAt(1), False) # Or show it if btdriver.use_driver == "pwc": self.switchToCameraGUI() self.desktop = QApplication.desktop() self.fullscreensize = (self.desktop.width(), self.desktop.height()) self.fullscreen = False self.paused = False ## ACTIONS ########################################################### def initActions(self): """ -> void Defines actions, creates menus and toolbar for GUI actions. """ # Collection a = self.actionCollection() # Define shortcuts sc_null = KShortcut.null() # empty sc_tuneup = KShortcut(KKey(Qt.Key_PageUp)) # PageUp sc_tunedown = KShortcut(KKey(Qt.Key_PageDown)) # PageDown sc_quit = KStdAccel.quit() # Ctrl+Q sc_editor = KShortcut(KKey(Qt.Key_F10)) # F10 sc_hardware = KShortcut(KKey(Qt.Key_F11)) # F11 sc_picture = KShortcut(KKey(Qt.Key_F12)) # F12 sc_volumedown = KShortcut(KKey(Qt.Key_Minus)) # - sc_volumeup = KShortcut(KKey(Qt.Key_Plus)) # + sc_bt848 = KShortcut(KKey("ALT+b")) # ALT+b sc_saa = KShortcut(KKey("ALT+s")) # ALT+s sc_pwc = KShortcut(KKey("ALT+p")) # ALT+p sc_small = KShortcut(KKey(Qt.Key_F6)) # F6 sc_medium = KShortcut(KKey(Qt.Key_F7)) # F7 sc_large = KShortcut(KKey(Qt.Key_F8)) # F8 sc_full = KShortcut(KKey(Qt.Key_F9)) # F9 sc_tiltup = KShortcut(KKey(Qt.Key_Up)) # Up sc_tiltdown = KShortcut(KKey(Qt.Key_Down)) # Down sc_panleft = KShortcut(KKey(Qt.Key_Left)) # Left sc_panright = KShortcut(KKey(Qt.Key_Right)) # Right sc_pause = KShortcut(KKey(Qt.Key_Space)) # Space sc_mixer1 = KShortcut(KKey("ALT+1")) # ALT+1 sc_mixer2 = KShortcut(KKey("ALT+2")) # ALT+2 sc_mixer3 = KShortcut(KKey("ALT+3")) # ALT+3 sc_mixer4 = KShortcut(KKey("ALT+4")) # ALT+4 sc_mixer5 = KShortcut(KKey("ALT+5")) # ALT+5 sc_mixer6 = KShortcut(KKey("ALT+6")) # ALT+6 # Menu separator self.separatorAct = KActionSeparator(a, "separatorAct") # Channel menu - Tune up self.tuneUpAct = KAction(i18n("&Up"), sc_tuneup, self.tuneUp, a ,"tuneUpAct") # Channel menu - Tune down self.tuneDownAct = KAction(i18n("&Down"), sc_tunedown, self.tuneDown, a, "tuneDownAct") # Camera menu - Tilt up self.tiltUpAct = KAction(i18n("&Up"), sc_tiltup, self.tiltUp, a, "tiltUpAct") self.tiltUpAct.setEnabled(False) # Camera menu - Tilt down self.tiltDownAct = KAction(i18n("&Down"), sc_tiltdown, self.tiltDown, a, "tiltDownAct") self.tiltDownAct.setEnabled(False) # Camera menu - Pan left self.panLeftAct = KAction(i18n("&Left"), sc_panleft, self.panLeft, a, "panLeftAct") self.panLeftAct.setEnabled(False) # Camera menu - Pan right self.panRightAct = KAction(i18n("&Right"), sc_panright, self.panRight, a, "panRightAct") self.panRightAct.setEnabled(False) # Channel/camera menu - Quit self.quitAct = KAction(i18n("&Quit"), sc_quit, self.quit, a, "quitAct") # Tools menu - Edit channels self.editChansAct = KAction(i18n("Channel &Editor..."), sc_editor, self.editChans, a, "editChansAct") # Tools menu - Hardware info self.hwInfoAct = KAction(i18n("Hardware &Info..."), sc_hardware, self.hwInfo, a, "hwInfoAct") # Settings menu - Picture settings self.setPictureAct = KAction(i18n("&Picture..."), sc_picture, self.setPicture, a, "setPictureAct") # Settings menu - Toggle fullscreen self.fullScreenAct = KToggleFullScreenAction(sc_full, self.fullScreen, a, self, "fullScreenAct") self.fullScreenAct.setChecked(False) # Settings menu - Capture mode (TV or webcam) self.capModeMenuAct = KActionMenu(i18n("&Capture mode"), a, "capModeMenuAct") # Settings menu - Screen size self.sizeMenuAct = KActionMenu(i18n("&Size"), a, "sizeMenuAct") # Settings menu - Screen size submenu items self.sizeSmallAct = KRadioAction(i18n("&Small"), sc_small, self.sizeSmall, a, "sizeSmallAct") self.sizeMediumAct = KRadioAction(i18n("&Medium"), sc_medium, self.sizeMedium, a, "sizeMediumAct") self.sizeLargeAct = KRadioAction(i18n("&Large"), sc_large, self.sizeLarge, a, "sizeLargeAct") self.sizeSmallAct.setExclusiveGroup("screensize") self.sizeMediumAct.setExclusiveGroup("screensize") self.sizeLargeAct.setExclusiveGroup("screensize") self.sizeMenuAct.insert(self.sizeSmallAct) self.sizeMenuAct.insert(self.sizeMediumAct) self.sizeMenuAct.insert(self.sizeLargeAct) self.sizeMediumAct.setChecked(True) # Settings menu - Driver submenu self.driverMenuAct = KActionMenu(i18n("&Driver"), a, "driverMenuAct") # Settings menu - Driver submenu items self.driverBktrAct = KRadioAction(i18n("&Bktr"), sc_bt848, self.driverBktr, a, "driverBktrAct") self.driverSaaAct = KRadioAction(i18n("&Saa"), sc_saa, self.driverSaa, a, "driverSaaAct") self.driverPwcAct = KRadioAction(i18n("&Pwc"), sc_pwc, self.driverPwc, a, "driverPwcAct") # Settings menu - Driver submenu items: exclusively group and insert self.driverBktrAct.setExclusiveGroup("driver") self.driverSaaAct.setExclusiveGroup("driver") self.driverPwcAct.setExclusiveGroup("driver") self.driverMenuAct.insert(self.driverBktrAct) self.driverMenuAct.insert(self.driverSaaAct) self.driverMenuAct.insert(self.driverPwcAct) if btdriver.use_driver == "saa": self.driverSaaAct.setChecked(True) if bthardware.bktr_card_tuner() == ('', ''): self.driverBktrAct.setEnabled(False) if btdriver.use_driver == "pwc": self.driverPwcAct.setChecked(True) if btdriver.use_driver == "bt848": self.driverBktrAct.setChecked(True) if not (buildprefs.WITH_SAA and bthardware.saa_module_loaded()): self.driverSaaAct.setEnabled(False) if not (buildprefs.WITH_PWC and bthardware.pwc_module_loaded()): self.driverPwcAct.setEnabled(False) # Settings menu - Mixer channel submenu self.mixerMenuAct = KActionMenu(i18n("&Mixer channel"), a, "mixerMenuAct") # Settings menu - Mixer submenu items l = len(self.mixerchans) if l > 0: self.mixer1Act = KRadioAction(self.mixerchans[0].capitalize(), sc_mixer1, self.mixer1, a, "mixer1Act") self.mixer1Act.setExclusiveGroup("mixer") self.mixerMenuAct.insert(self.mixer1Act) if l > 1: self.mixer2Act = KRadioAction(self.mixerchans[1].capitalize(), sc_mixer2, self.mixer2, a, "mixer2Act") self.mixer2Act.setExclusiveGroup("mixer") self.mixerMenuAct.insert(self.mixer2Act) if l > 2: self.mixer3Act = KRadioAction(self.mixerchans[2].capitalize(), sc_mixer3, self.mixer3, a, "mixer3Act") self.mixer3Act.setExclusiveGroup("mixer") self.mixerMenuAct.insert(self.mixer3Act) if l > 3: self.mixer4Act = KRadioAction(self.mixerchans[3].capitalize(), sc_mixer4, self.mixer4, a, "mixer4Act") self.mixer4Act.setExclusiveGroup("mixer") self.mixerMenuAct.insert(self.mixer4Act) if l > 4: self.mixer5Act = KRadioAction(self.mixerchans[4].capitalize(), sc_mixer5, self.mixer5, a, "mixer5Act") self.mixer5Act.setExclusiveGroup("mixer") self.mixerMenuAct.insert(self.mixer5Act) if l > 5: self.mixer6Act = KRadioAction(self.mixerchans[5].capitalize(), sc_mixer6, self.mixer6, a, "mixer6Act") self.mixer6Act.setExclusiveGroup("mixer") self.mixerMenuAct.insert(self.mixer6Act) self.mixer1Act.setChecked(True) # Settings menu - Volume submenu self.volumeMenuAct = KActionMenu(i18n("&Volume"), a, "volumeMenuAct") # Settings menu - Volume submenu items self.volumeUpAct = KAction(i18n("&Up"), sc_volumeup, self.volumeUp, a, "volumeUpAct") self.volumeDownAct = KAction(i18n("&Down"), sc_volumedown, self.volumeDown, a, "volumeDownAct") self.volumeMenuAct.insert(self.volumeUpAct) self.volumeMenuAct.insert(self.volumeDownAct) # Not in menu - Pause/unpause with Spacebar self.pauseAct = KAction(i18n("Pause"), sc_pause, self.pause, a, "pauseAct") # Icons for actions self.tuneUpAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("up", KIcon.Small))) self.tuneDownAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("down", KIcon.Small))) self.quitAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("exit", KIcon.Small))) self.editChansAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("edit", KIcon.Small))) self.hwInfoAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("hwinfo", KIcon.Small))) self.setPictureAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("colors", KIcon.Small))) self.sizeMenuAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("randr", KIcon.Small))) self.driverMenuAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("kcmpci", KIcon.Small))) self.mixerMenuAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("kmix", KIcon.Small))) self.volumeMenuAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("volume_up", KIcon.Small))) self.volumeUpAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("volume_up", KIcon.Small))) self.volumeDownAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("volume_down", KIcon.Small))) self.tiltUpAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("up", KIcon.Small))) self.tiltDownAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("down", KIcon.Small))) self.panLeftAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("back", KIcon.Small))) self.panRightAct.setIconSet(QIconSet( KGlobal.instance().iconLoader().loadIcon("forward", KIcon.Small))) ## INIT ############################################################## def initVideoArea(self): """ -> void Creates a widget to display the video in. """ self.videoarea = QXEmbed(self, "videoarea") s = QSize(self.screensize[0], self.screensize[1] - 2) self.videoarea.setFixedSize(s) self.videoarea.setBackgroundMode(QWidget.NoBackground) self.setCentralWidget(self.videoarea) def initPartGUI(self): """ -> void Creates the KPart and GUI using KBTV_XMLFILE. """ self.part = KParts.Part() self.part.setWidget(self.videoarea) # rc file, can be used to extend the part self.setXMLFile(os.path.join(KBTV_MAINPATH, KBTV_XMLFILE)) self.createGUI(self.part) # After this toolbar, statusbar etc exist and can be referred to def switchToCameraGUI(self): # Disable channel up and down actions (and accels) for item in (self.tuneUpAct, self.tuneDownAct): item.setEnabled(False) # Enable pan and tilt actions for item in (self.tiltUpAct, self.tiltDownAct, self.panLeftAct, self.panRightAct): item.setEnabled(True) # Channel menu invisible, Camera menu visible. mb = self.menuBar() mb.setItemVisible(mb.idAt(0), False) mb.setItemVisible(mb.idAt(1), True) # Disable channel editor action. Not volume (not anymore) self.editChansAct.setEnabled(False) #for item in (self.editChansAct, self.volumeMenuAct, self.volumeUpAct, # self.volumeDownAct): # item.setEnabled(False) # Toolbar extreme makeover tb = self.toolBar() for item in (self.tuneUpAct, self.tuneDownAct): item.unplug(tb) i = 1 for item in (self.tiltUpAct, self.tiltDownAct, self.panLeftAct, self.panRightAct): item.plug(tb, i) i += 1 # Channel box/volume slider #tb.removeItemDelayed(tb.idAt(6)) #tb.removeItemDelayed(tb.idAt(5)) # Different status bar contents self.updateStatus() def switchToTelevisionGUI(self): # Disable pan and tilt actions for item in (self.tiltUpAct, self.tiltDownAct, self.panLeftAct, self.panRightAct): item.setEnabled(False) # Enable channel up and down actions (and accels) for item in (self.tuneUpAct, self.tuneDownAct): item.setEnabled(True) # Channel menu visible, Camera menu invisible mb = self.menuBar() mb.setItemVisible(mb.idAt(1), False) mb.setItemVisible(mb.idAt(0), True) # Enable channel editor action and volume menu action for item in (self.editChansAct, self.volumeMenuAct, self.volumeUpAct, self.volumeDownAct): item.setEnabled(True) # Toolbar extreme makeover tb = self.toolBar() for item in (self.tiltUpAct, self.tiltDownAct, self.panLeftAct, self.panRightAct): item.unplug(tb) i = 1 for item in (self.tuneUpAct, self.tuneDownAct): item.plug(tb, i) i += 1 # Channel box/volume slider #self.extendToolbar() self.editChansAct.setEnabled(True) # Different status bar contents self.updateStatus() def extendToolbar(self): """ -> void Extends the toolbar with a widget containing a channel input box (restricted line edit) and a volume slider. """ tb = self.toolBar() tb.setStretchableWidget(QLabel("", tb)) self.toolbarwidget = KbtvToolbarWidget(self, tb) self.channelbox = self.toolbarwidget.channelbox self.volumeslider = self.toolbarwidget.volumeslider tb.insertWidget(self.toolbarwidget.winId(), 100, self.toolbarwidget) tb.setItemAutoSized(self.toolbarwidget.winId(), True) tb.setMovingEnabled(False) def initStatusBar(self): """ -> void Initializes the statusbar in 3 parts, relative weights 5:85:10 """ sb = self.statusBar() sb.insertItem("", STATUSBAR_LEFT, 5, True) sb.insertItem("", STATUSBAR_MIDDLE, 85, True) sb.insertItem("", STATUSBAR_RIGHT, 10, True) ## VIEWER ############################################################ def initViewer(self): """ -> bool Initializes the SDL viewer. Returns True if no errors occured, False if something went wrong. It will show a messagebox with error number. """ res = -1 if btdriver.use_driver == "bt848": norm = bthardware.bktr_norm() n = 0 if norm == bthardware.NORM_NTSC: n = 1 if norm == bthardware.NORM_SECAM: n = 2 # Init opens the tuner device (tuner_quit closes it) bt848.tuner_init() res = bt848.viewer_init(self.screensize[0], self.screensize[1], n) # Dialog for brightness, etc (if done here its values get set) self.picsettings = KbtvPictureSettings(None, self) if btdriver.use_driver == "saa": try: # Init opens the iic device (tuner_quit closes it) saa.tuner_init() saa.tuner_if_init() saa.tuner_audio_init() res = saa.viewer_init(self.screensize[0], self.screensize[1]) self.picsettings = KbtvPictureSettings(None, self) except NameError: pass if btdriver.use_driver == "pwc" and btdriver.pwc_fd: try: # Fixed values for now f = btdriver.pwc_fd.fileno() pwc.camera_framerate_set(f, 15) pwc.camera_capsize_set(f, 3) pwc.camera_gamma_set(f, 20) res = pwc.viewer_init(f, self.screensize[0], self.screensize[1]) self.picsettings = KbtvPictureSettings(btdriver.pwc_fd, self) except NameError: pass if res != 0: KMessageBox.error(None, i18n("Viewer init failed. Driver " + btdriver.use_driver + ", error " + str(res))) return False return True def startViewer(self): """ -> void Starts/unpauses the viewer. """ if btdriver.use_driver == "bt848": bt848.viewer_start() if btdriver.use_driver == "saa": try: saa.viewer_start() except NameError: pass if btdriver.use_driver == "pwc" and btdriver.pwc_fd: try: pwc.viewer_start() except NameError: pass def pauseViewer(self): """ -> void Pauses the viewer. """ if btdriver.use_driver == "bt848": bt848.viewer_pause() if btdriver.use_driver == "saa": try: saa.viewer_pause() except NameError: pass if btdriver.use_driver == "pwc" and btdriver.pwc_fd: try: pwc.viewer_pause() except NameError: pass def quitViewer(self): """ -> void Quits the viewer. """ if btdriver.use_driver == "bt848": bt848.tuner_quit() bt848.viewer_quit() if btdriver.use_driver == "saa": try: saa.tuner_quit() saa.viewer_quit() except NameError: pass if btdriver.use_driver == "pwc" and btdriver.pwc_fd: try: pwc.viewer_quit() except NameError: pass def resizeViewer(self, w, h): """ -> void Resizes the viewer to w x h. """ if btdriver.use_driver == "bt848": bt848.viewer_resize(w, h) if btdriver.use_driver == "saa": try: saa.viewer_resize(w, h) except NameError: pass if btdriver.use_driver == "pwc" and btdriver.pwc_fd: try: pwc.viewer_resize(w, h) except NameError: pass ## VARIOUS METHODS; SLOTS, HELPERS, DCOP FUNCTIONS ################### def tuneTo(self, c): """ -> void SLOT/DCOP. Tunes to channel index c. If < 0 or too high it tunes to the highest channel. Updates channel box if need be and runs updateStatus(). This method is also called by the channelbox widget's setChannel() slot (on ReturnPressed). """ if btdriver.use_driver in ("bt848", "saa"): self.tuneUpAct.setEnabled(False) self.tuneDownAct.setEnabled(False) self.muteAudio() self.pauseViewer() len = self.chanlist.len() if c >= len: c = len -1 self.chanlist.tuneToIndex(c) self.current = c self.channelbox.setText(str(self.current)) self.channelbox.selectAll() self.updateStatus() time.sleep(0.5) self.startViewer() self.unmuteAudio() self.tuneUpAct.setEnabled(True) self.tuneDownAct.setEnabled(True) def updateStatus(self): """ -> void Updates statusbar and main window caption. """ if btdriver.use_driver in ("bt848", "saa"): chan = self.chanlist.channels[self.current] self.status[0] = str(self.current) if self.chanlist.isBTComposite(chan): self.status[2] = chan.id else: self.status[2] = str(chan.frequency) self.status[1] = chan.name elif btdriver.use_driver == "pwc": self.status[0] = "0" self.status[1] = bthardware.pwc_vendor_product()[0] self.status[2] = "USB" sb = self.statusBar() sb.changeItem(self.status[0], STATUSBAR_LEFT) sb.changeItem(self.status[1], STATUSBAR_MIDDLE) sb.changeItem(self.status[2], STATUSBAR_RIGHT) self.setCaption(self.status[1]) def currentChannel(self): """ -> int DCOP. Returns the current channel index. """ if btdriver.use_driver in ("bt848", "saa"): return self.current def currentStatus(self): """ -> QString DCOP. Returns a QString that has the status information, same as in the statusbar. Format is "NUMBER ID|FREQ NAME" where NAME can have spaces and may be empty. """ return QString(self.status[0] + " " + self.status[2] + " " + self.status[1]) def tuneUp(self): """ -> void SLOT/DCOP. Tunes the channel up, updates status. """ if btdriver.use_driver in ("bt848", "saa"): self.tuneUpAct.setEnabled(False) self.tuneDownAct.setEnabled(False) self.muteAudio() self.pauseViewer() self.chanlist.tuneUp() self.current = self.chanlist.currentChannelIndex() self.channelbox.setText(str(self.current)) self.channelbox.selectAll() self.updateStatus() time.sleep(0.5) self.startViewer() self.unmuteAudio() self.tuneUpAct.setEnabled(True) self.tuneDownAct.setEnabled(True) def tuneDown(self): """ -> void SLOT/DCOP. Tunes the channel down, updates status. """ if btdriver.use_driver in ("bt848", "saa"): self.tuneDownAct.setEnabled(False) self.tuneDownAct.setEnabled(False) self.muteAudio() self.pauseViewer() self.chanlist.tuneDown() self.current = self.chanlist.currentChannelIndex() self.channelbox.setText(str(self.current)) self.channelbox.selectAll() self.updateStatus() time.sleep(0.5) self.startViewer() self.unmuteAudio() self.tuneUpAct.setEnabled(True) self.tuneDownAct.setEnabled(True) def quit(self): """ -> void SLOT/DCOP. Stop backend, close mainwindow/part. """ self.close() def editChans(self): """ -> void SLOT/DCOP. Shows the channel editor (modal) dialog. """ sb = self.statusBar() txt = i18n("Running Channel Editor") sb.changeItem("", STATUSBAR_LEFT) sb.changeItem(txt, STATUSBAR_MIDDLE) sb.changeItem("", STATUSBAR_RIGHT) self.setCaption(txt) self.editor.exec_loop() # Switch back to what the channel was self.tuneTo(self.current) self.updateStatus() def hwInfo(self): """ -> void SLOT/DCOP. Shows the hardware info (non-modal) dialog. """ self.hwinfo.show() def setPicture(self): """ -> void SLOT/DCOP. Shows the picture settings (non-modal) dialog. """ self.picsettings.show() def setBrightness(self, b): """ -> void DCOP. Sets the brightness to b (0..100). """ self.picsettings.brightness.setValue(b) def setContrast(self, c): """ -> void DCOP. Sets the contrast to c (0..100). """ self.picsettings.contrast.setValue(c) def setColor(self, c): """ -> void DCOP. Sets the color balance to c (0..100). """ self.picsettings.color.setValue(c) def setSaturation(self, s): """ -> void DCOP. Sets the color saturation to s (0..100). """ self.picsettings.saturation.setValue(s) def brightness(self): """ -> int DCOP. Returns the current brightness (0..100). """ return self.picsettings.brightness.value() def contrast(self): """ -> int DCOP. Returns the current contrast (0..100). """ return self.picsettings.contrast.value() def color(self): """ -> int DCOP. Returns the current color balance (0..100). """ return self.picsettings.color.value() def saturation(self): """ -> int DCOP. Returns the current color saturation (0..100). """ return self.picsettings.saturation.value() def volume(self): """ -> int DCOP. Returns the current volume (0..100). """ return self.volumeslider.value() def setVolume(self, v=-1): """ -> void SLOT/DCOP. Calls the toolbar widget's setVolume() slot. If the target volume v is not what the slider has, the slider is moved. If v=-1 this simply wraps the volume slider's setVolume() slot. """ if v == -1: # Slot was triggered by user action self.volumeslider.setVolume() else: if self.volumeslider.value() != v: # Triggers the slot (v set by DCOP) self.volumeslider.setValue(v) def volumeUp(self): """ -> void SLOT/DCOP. Turns the volume up by (max) 5 percent points. """ val = self.volumeslider.value() if val == MINVOL: # Was 0, will become 5, volumeDown must be enabled self.volumeDownAct.setEnabled(True) val += 5 self.volumeslider.setValue(val) if val >= MAXVOL: # Can't go further up, volumeUp must be disabled self.volumeUpAct.setEnabled(False) def volumeDown(self): """ -> void SLOT/DCOP. Turns the volume down by (max) 5 percent points. """ val = self.volumeslider.value() if val == MAXVOL: # Was max, will become max-5, volumeUp must be enabled self.volumeUpAct.setEnabled(True) val -= 5 self.volumeslider.setValue(val) if val <= MINVOL: # Can't go further down, volumeDown must be disabled self.volumeDownAct.setEnabled(False) def muteAudio(self): """ -> void SLOT/DCOP. Mutes the audio (if using a TV card). """ if btdriver.use_driver == "bt848": bt848.tuner_audiosource_set(0x80) if btdriver.use_driver == "saa": try: saa.tuner_audiosource_set(0x80) except NameError: pass def unmuteAudio(self): """ -> void SLOT/DCOP. Unmutes the audio (if using a TV card). """ if btdriver.use_driver == "bt848": bt848.tuner_audiosource_set(0x81) if btdriver.use_driver == "saa": try: saa.tuner_audiosource_set(0x81) except NameError: pass self.update() def mixer1(self): """ -> void SLOT/DCOP. Use the first available mixerchannel (if any). The ones that are eligible (sp?) are (in order) line, line1 to 3, mic, video. """ if len(self.mixerchans) > 0: self.mixerchan = self.mixerchans[0] self.toolbarwidget.mixerchan = bthardware.MIXER_CHANNEL_NAMES.index(self.mixerchan) self.setVolume(self.volume()) def mixer2(self): """ -> void SLOT/DCOP. Use the second available mixerchannel (if any). The ones that are eligible (sp?) are (in order) line, line1 to 3, mic, video. """ if len(self.mixerchans) > 1: self.mixerchan = self.mixerchans[1] self.toolbarwidget.mixerchan = bthardware.MIXER_CHANNEL_NAMES.index(self.mixerchan) self.setVolume(self.volume()) def mixer3(self): """ -> void SLOT/DCOP. Use the third available mixerchannel (if any). The ones that are eligible (sp?) are (in order) line, line1 to 3, mic, video. """ if len(self.mixerchans) > 2: self.mixerchan = self.mixerchans[2] self.toolbarwidget.mixerchan = bthardware.MIXER_CHANNEL_NAMES.index(self.mixerchan) self.setVolume(self.volume()) def mixer4(self): """ -> void SLOT/DCOP. Use the fourth available mixerchannel (if any). The ones that are eligible (sp?) are (in order) line, line1 to 3, mic, video. """ if len(self.mixerchans) > 3: self.mixerchan = self.mixerchans[3] self.toolbarwidget.mixerchan = bthardware.MIXER_CHANNEL_NAMES.index(self.mixerchan) self.setVolume(self.volume()) def mixer5(self): """ -> void SLOT/DCOP. Use the fifth available mixerchannel (if any). The ones that are eligible (sp?) are (in order) line, line1 to 3, mic, video. """ if len(self.mixerchans) > 4: self.mixerchan = self.mixerchans[4] self.toolbarwidget.mixerchan = bthardware.MIXER_CHANNEL_NAMES.index(self.mixerchan) self.setVolume(self.volume()) def mixer6(self): """ -> void SLOT/DCOP. Use the sixth available mixerchannel (if any). The ones that are eligible (sp?) are (in order) line, line1 to 3, mic, video. """ if len(self.mixerchans) > 5: self.mixerchan = self.mixerchans[5] self.toolbarwidget.mixerchan = bthardware.MIXER_CHANNEL_NAMES.index(self.mixerchan) self.setVolume(self.volume()) def driver(self): """ -> QString DCOP. Returns the driver currently used ("bt848", "saa", "pwd"). """ return QString(btdriver.use_driver) def driverBktr(self): """ -> void SLOT/DCOP. Stops viewer if not using bt848 driver already, and starts bt848 viewer. """ switchgui = False if not btdriver.use_driver == "bt848": self.quitViewer() if btdriver.use_driver == "saa": self.muteAudio() if btdriver.use_driver == "pwc": if btdriver.pwc_fd: btdriver.pwc_fd.close() btdriver.pwc_fd = None switchgui = True btdriver.use_driver = "bt848" if bthardware.bktr_norm() == bthardware.NORM_PAL: self.maxsize = (768, 576) if self.initViewer(): self.startViewer() if self.fullscreen: self.fullScreen() self.editor = KbtvChannelEditor(self) self.hwinfo = KbtvHardwareInfo(self) # Moved to viewer_init #self.picsettings = KbtvPictureSettings(None, self) self.chanlist = self.editor.chanlist if switchgui: self.switchToTelevisionGUI() self.tuneTo(self.current) def driverSaa(self): """ -> void SLOT/DCOP. Stops viewer if not using saa driver already, and starts saa viewer. """ switchgui = False if not btdriver.use_driver == "saa": self.quitViewer() if btdriver.use_driver == "bt848": self.muteAudio() if btdriver.use_driver == "pwc": if btdriver.pwc_fd: btdriver.pwc_fd.close() btdriver.pwc_fd = None switchgui = True btdriver.use_driver = "saa" if "PAL" in bthardware.saa_norm(): self.maxsize = (720 * 16/15, 576) if self.initViewer(): self.startViewer() if self.fullscreen: self.fullScreen() self.editor = KbtvChannelEditor(self) self.hwinfo = KbtvHardwareInfo(self) #self.picsettings = KbtvPictureSettings(None, self) self.chanlist = self.editor.chanlist if switchgui: self.switchToTelevisionGUI() self.tuneTo(self.current) def driverPwc(self): """ -> void SLOT/DCOP. Stops viewer if not using pwc driver already, and starts pwc viewer. Switches to camera GUI. """ if not btdriver.use_driver == "pwc": self.quitViewer() self.muteAudio() btdriver.use_driver = "pwc" btdriver.pwc_fd = open(bthardware.PWC_DEVICE, "r") if self.initViewer(): self.startViewer() if self.fullscreen: self.fullScreen() self.maxsize = KBTV_SCREENSIZE_LARGE self.hwinfo = KbtvHardwareInfo(self) # Moved to viewer_init #self.picsettings = KbtvPictureSettings(btdriver.pwc_fd, self) self.switchToCameraGUI() def panLeft(self): """ -> void SLOT/DCOP. Pans the camera to the left by 5 percent points (0-50 is left of center, 50-100 is right of). For cameras that support motorized panning and tilting. From user's POV, not camera's. """ if btdriver.use_driver == "pwc": pan = pwc.camera_panning(btdriver.pwc_fd.fileno()) + 5 pwc.camera_panning_set(btdriver.pwc_fd.fileno(), pan) def panRight(self): """ -> void SLOT/DCOP. Pans the camera to the right by 5 percent points (50-100 is right of center, 0-50 is left of). For cameras that support motorized panning and tilting. From user's POV, not camera's. """ if btdriver.use_driver == "pwc": pan = pwc.camera_panning(btdriver.pwc_fd.fileno()) - 5 pwc.camera_panning_set(btdriver.pwc_fd.fileno(), pan) def tiltUp(self): """ -> void SLOT/DCOP. Tilts the camera upward by 5 percent points (50-100 is up from center, 0-50 is down). For cameras that support motorized panning and tilting. """ if btdriver.use_driver == "pwc": tilt = pwc.camera_tilting(btdriver.pwc_fd.fileno()) + 5 pwc.camera_tilting_set(btdriver.pwc_fd.fileno(), tilt) def tiltDown(self): """ -> void SLOT/DCOP. Tilts the camera downward by 5 percent points (50-100 is up from center, 0-50 is down). For cameras that support motorized panning and tilting. """ if btdriver.use_driver == "pwc": tilt = pwc.camera_tilting(btdriver.pwc_fd.fileno()) - 5 pwc.camera_tilting_set(btdriver.pwc_fd.fileno(), tilt) def changeSize(self, size): """ -> void Change size of video area. """ self.screensize = size s = QSize(self.screensize[0], self.screensize[1] - 2) self.videoarea.setFixedSize(s) self.resizeViewer(self.screensize[0], self.screensize[1]) self.fullscreen = False def sizeSmall(self): """ -> void SLOT/DCOP. Sets video size to KBTV_SCREENSIZE_SMALL. """ if self.screensize != KBTV_SCREENSIZE_SMALL: self.changeSize(KBTV_SCREENSIZE_SMALL) def sizeMedium(self): """ -> void SLOT/DCOP. Sets video size to KBTV_SCREENSIZE_MEDIUM. """ if self.screensize != KBTV_SCREENSIZE_MEDIUM: self.changeSize(KBTV_SCREENSIZE_MEDIUM) def sizeLarge(self): """ -> void SLOT/DCOP. Sets video size to KBTV_SCREENSIZE_LARGE. """ if self.screensize != self.maxsize: self.changeSize(self.maxsize) def fullScreen(self): """ -> void SLOT/DCOP. Toggles full screen mode. In full screen mode the toolbar remains shown as it hardly changes the aspect ratio (and is the most straightforward way for the user to get back to former state). """ self.fullscreensize = (self.desktop.width(), self.desktop.height()) if self.fullScreenAct.isChecked(): self.menuBar().hide() self.statusBar().hide() s = QSize(self.fullscreensize[0], self.fullscreensize[1] - 2) self.videoarea.setFixedSize(s) self.resizeViewer(self.fullscreensize[0], self.fullscreensize[1]) self.setWindowState(Qt.WindowFullScreen) self.fullscreen = True else: self.menuBar().show() self.statusBar().show() s = QSize(self.screensize[0], self.screensize[1] - 2) self.videoarea.setFixedSize(s) self.resizeViewer(self.screensize[0], self.screensize[1]) self.setWindowState(self.windowState() ^ Qt.WindowFullScreen) self.fullscreen = False def pause(self): """ -> void SLOT/DCOP. Toggles pause/unpause. """ if not self.paused: self.pauseViewer() self.paused = True else: self.startViewer() self.paused = False ## END ################################################################### if __name__ == "__main__": print "This is a module. Import it instead."