mythtvgui.py :  » Game-2D-3D » XBMC-MythTV » xbmcmythtv » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Game 2D 3D » XBMC MythTV 
XBMC MythTV » xbmcmythtv » mythtvgui.py
"""
$Id: mythtvgui.py,v 1.26 2007/05/12 23:43:24 frooby Exp $

Copyright (C) 2005 Tom Warkentin <tom@ixionstudios.com>

Myth TV specific utility library for XBMC.

"""
from singleton import getInstance
import mythtv
import mythtvskin
import mythtvutil
import os
import string
import time
import traceback
import xbmcgui

ACTION_MOVE_LEFT                    = 1
ACTION_MOVE_RIGHT                   = 2
ACTION_MOVE_UP                      = 3
ACTION_MOVE_DOWN                    = 4
ACTION_PAGE_UP                      = 5
ACTION_PAGE_DOWN                    = 6
ACTION_SELECT_ITEM                  = 7
ACTION_HIGHLIGHT_ITEM               = 8
ACTION_PARENT_DIR                   = 9
ACTION_PREVIOUS_MENU                = 10
ACTION_SHOW_INFO                    = 11
ACTION_PAUSE                        = 12
ACTION_STOP                         = 13
ACTION_NEXT_ITEM                    = 14
ACTION_PREV_ITEM                    = 15
ACTION_SCROLL_UP                    = 111
ACTION_SCROLL_DOWN                  = 112
ACTION_CONTEXT_MENU                 = 117

# from xbmc/guilib/common/xbfont.h
ALIGN_LEFT                          = 0
ALIGN_RIGHT                         = 1
ALIGN_CENTER_X                      = 2
ALIGN_CENTER_Y                      = 4
ALIGN_TRUNCATED                     = 8

picBase = os.getcwd()[:-1]+'\\images\\'

# channel icons should be placed in images\channel and named after channel id
picType = "_square.png"  # change to reflect you image type
#picType = ".png"

def debug( str ):
    mythtvutil.debug( mythtvutil.DEBUG_MISC, str )

def checkSettings():
    debug( "> mythtvgui.checkSettings()" )

    try:
        s = getInstance( mythtv.Settings )
        s.loadSettings()
        s.verifySettings()
    except mythtv.SettingsException, ex:
        raise Exception, mythtvutil.getLocalizedString( 86 )

    debug( "< mythtvgui.checkSettings()" )

class BaseWindow( mythtvskin.XBMC_SKIN ):
    def __init__( self ):
        mythtvskin.XBMC_SKIN.__init__( self )
        self.actionConsumed = 0
        self.lock = 0

    def onAction( self, action ):
        debug( "> mythtvgui.BaseWindow.onAction( action=[%s] )"%action )

        try:
            # Lock out concurrent events - XBMC fires events in separate
            # threads.  Without the lock, two threads can be modifying window
            # objects at the same time corrupting data structures.
            if self.lock == 0:
                try:
                    self.lock += 1

                    # call subclass defined hook
                    actionConsumed = self.onActionHook( action )

                    # check if action was not consumed
                    if actionConsumed == 0:
                        # process help request - if subclass hook overrides
                        # this behavior then it should have consumed the event
                        if action in (ACTION_SHOW_INFO, ACTION_CONTEXT_MENU):
                            id = self.getcontrolid( self.getFocus() )
                            if len( id ) > 0:
                                help = self.controls[id].getoption( 'help' )
                            else:
                                help = ""

                            if len( help ) > 0:
                                Dialog().ok(
                                    mythtvutil.getLocalizedString( 26 ),
                                    help )
                                actionConsumed = 1

                    # check if event was consumed
                    if actionConsumed == 0:
                        # check if parent dir selected
                        if action == ACTION_PARENT_DIR:
                            self.close()
                        else:
                            mythtvskin.XBMC_SKIN.onAction( self, action )

                    self.onActionPostHook( action )

                    self.lock -= 1
                except:
                    self.lock -= 1
                    raise
        except mythtv.ProtocolVersionException, ex:
            Dialog().ok(
                mythtvutil.getLocalizedString( 27 ),
                mythtvutil.getLocalizedString( 109 )%str( ex ) )
        except Exception, ex:
            traceback.print_exc()
            Dialog().ok( mythtvutil.getLocalizedString( 27 ), str( ex ) )

        debug( "< mythtvgui.BaseWindow.onAction( action=[%s] )"%action )

    def onActionHook( self, action ):
        """
        Method that is called by BaseWindow class.  This method is intended to
        be overridden by subclasses to perform custom logic.
        
        Return values:

        0   Event was not consumed by the hook.  Event will be handled
            internally. (default)
        1   Event was consumed by hook.  No further processing will be done.

        BaseWindow catches exceptions and displays dialog.  Therefore this
        type of logic does not need to replicated in this hook.
        """
        return 0
        
    def onActionPostHook( self, action ):
        """
        Method that is called after internal processing is done on an action.
        This is meant to be overridden if additional logic needs to be
        performed after the internal processing is complete.
        """
        pass

    def onControl( self, control ):
        debug( "> mythtvgui.BaseWindow.onControl( control=[%s] )"%control )

        try:
            if self.lock == 0:
                try:
                    self.lock += 1
                    rc = self.onControlHook( control )
                    self.lock -= 1
                except:
                    self.lock -= 1
                    raise
        except mythtv.ProtocolVersionException, ex:
            Dialog().ok(
                mythtvutil.getLocalizedString( 27 ),
                mythtvutil.getLocalizedString( 109 )%str( ex ) )
        except Exception, ex:
            traceback.print_exc( ex )
            Dialog().ok( mythtvutil.getLocalizedString( 27 ), str( ex ) )

        debug( "< mythtvgui.BaseWindow.onControl( control=[%s] )"%control )

    def onControlHook( self, control ):
        """
        Method that is called by BaseWindow class.  This method is intended to
        be overridden by subclasses to perform custom logic.
        
        Return values:

        0   Event was not consumed by the hook.  Event will be handled
            internally.
        1   Event was consumed by hook.  No further processing will be done.
            (default)

        BaseWindow catches exceptions and displays dialog.  Therefore this
        type of logic does not need to replicated in this hook.
        """
        return 1

## Needed a new class for a DialogWindow as required for OSD        
class BaseWindowDialog( mythtvskin.XBMC_SKIN_DIALOG ):
    def __init__( self ):
        mythtvskin.XBMC_SKIN_DIALOG.__init__( self )
        self.actionConsumed = 0
        self.lock = 0

    def onAction( self, action ):
        debug( "> mythtvgui.BaseWindowDialog.onAction( action=[%s] )"%action )

        try:
            # Lock out concurrent events - XBMC fires events in separate
            # threads.  Without the lock, two threads can be modifying window
            # objects at the same time corrupting data structures.
            if self.lock == 0:
                try:
                    self.lock += 1

                    # call subclass defined hook
                    actionConsumed = self.onActionHook( action )

                    # check if action was not consumed
                    if actionConsumed == 0:
                        # process help request - if subclass hook overrides
                        # this behavior then it should have consumed the event
                        if action in (ACTION_SHOW_INFO, ACTION_CONTEXT_MENU):
                            id = self.getcontrolid( self.getFocus() )
                            if len( id ) > 0:
                                help = self.controls[id].getoption( 'help' )
                            else:
                                help = ""

                            if len( help ) > 0:
                                Dialog().ok(
                                    mythtvutil.getLocalizedString( 26 ),
                                    help )
                                actionConsumed = 1

                    # check if event was consumed
                    if actionConsumed == 0:
                        # check if parent dir selected
                        if action == ACTION_PARENT_DIR:
                            self.close()
                        else:
                            mythtvskin.XBMC_SKIN_DIALOG.onAction( self, action )

                    self.onActionPostHook( action )

                    self.lock -= 1
                except:
                    self.lock -= 1
                    raise
        except mythtv.ProtocolVersionException, ex:
            Dialog().ok(
                mythtvutil.getLocalizedString( 27 ),
                mythtvutil.getLocalizedString( 109 )%str( ex ) )
        except Exception, ex:
            traceback.print_exc()
            Dialog().ok( mythtvutil.getLocalizedString( 27 ), str( ex ) )

        debug( "< mythtvgui.BaseWindowDialog.onAction( action=[%s] )"%action )

    def onActionHook( self, action ):
        """
        Method that is called by BaseWindowDialog class.  This method is intended to
        be overridden by subclasses to perform custom logic.
        
        Return values:

        0   Event was not consumed by the hook.  Event will be handled
            internally. (default)
        1   Event was consumed by hook.  No further processing will be done.

        BaseWindowDialog catches exceptions and displays dialog.  Therefore this
        type of logic does not need to replicated in this hook.
        """
        return 0
        
    def onActionPostHook( self, action ):
        """
        Method that is called after internal processing is done on an action.
        This is meant to be overridden if additional logic needs to be
        performed after the internal processing is complete.
        """
        pass

    def onControl( self, control ):
        debug( "> mythtvgui.BaseWindowDialog.onControl( control=[%s] )"%control )

        try:
            if self.lock == 0:
                try:
                    self.lock += 1
                    rc = self.onControlHook( control )
                    self.lock -= 1
                except:
                    self.lock -= 1
                    raise
        except mythtv.ProtocolVersionException, ex:
            Dialog().ok(
                mythtvutil.getLocalizedString( 27 ),
                mythtvutil.getLocalizedString( 109 )%str( ex ) )
        except Exception, ex:
            traceback.print_exc( ex )
            Dialog().ok( mythtvutil.getLocalizedString( 27 ), str( ex ) )

        debug( "< mythtvgui.BaseWindowDialog.onControl( control=[%s] )"%control )

    def onControlHook( self, control ):
        """
        Method that is called by BaseWindowDialog class.  This method is intended to
        be overridden by subclasses to perform custom logic.
        
        Return values:

        0   Event was not consumed by the hook.  Event will be handled
            internally.
        1   Event was consumed by hook.  No further processing will be done.
            (default)

        BaseWindowDialog catches exceptions and displays dialog.  Therefore this
        type of logic does not need to replicated in this hook.
        """
        return 1
        
class DialogWin( object ):
    def __init__( self ):
        pass
    def choose( self, event ):
        return xbmcgui.Dialog().choose( event )
    def ok( self, title, line1, line2 = "", line3 = "" ):
        return xbmcgui.Dialog().ok( title, line1, line2, line3 )
    def select( self, title, li ):
        return xbmcgui.Dialog().select( title, li )
    def yesno( self, title, line1, line2 = "", line3 = "" ):
        return xbmcgui.Dialog().yesno( title, line1, line2, line3 )
    
def Dialog():
    return getInstance( DialogWin )

class ChannelIconCache( mythtvutil.FileCache ):
    def __init__( self ):
        mythtvutil.FileCache.__init__(
            self,
            picBase + "channels",
            numDays=0 ) # never delete these

    def buildPath( self, channel ):
        debug( "> mythtvgui.ChannelIconCache.buildPath()" )
        file = self.getIconFile( channel )
        if file:
            file = self.cachePath + os.sep + file
        debug( "< mythtvgui.ChannelIconCache.buildPath() => [%s]"%file )
        return file

    def getIconFile( self, channel ):
        debug( "> mythtvgui.ChannelIconCache.getIconFile()" )
        file = channel.icon()
        if file:
            file = string.replace( file, "/", os.sep )
            file = os.path.basename( file )
        debug( "< mythtvgui.ChannelIconCache.getIconFile() => [%s]"%file )
        return file

    def storeFile( self, chan ):
        debug( "> mythtvgui.ChannelIconCache.storeFile( chan=[%s])"%(chan) )

        localPath = None
        file = chan.icon()
        if file:
            s = getInstance( mythtv.Settings )
            host = s.getSetting( "mythtv_host" )
            port = int( s.getSetting( "mythtv_port" ) )
            remotePath = "myth://%s:%d%s"%(host,port,file)
            localPath = self.buildPath( chan )

            c = getInstance( mythtv.Connection )
            rc = c.transferFile(
                remotePath, localPath, host )
            if rc != 0:
                localPath = None
            del c
        debug( "< mythtvgui.ChannelIconCache.storeFile() => [%s]"%localPath )
        return localPath

class ThumbnailCache( mythtvutil.FileCache ):
    def __init__( self ):
        mythtvutil.FileCache.__init__(
            self, picBase + "thumbs" )

    def buildThumbnailRemoteFilename( self, chanid, starttime, endtime ):
        if mythtv.mythProtocolVersion >= 26:
            return "%s_%s.mpg.png"%(chanid, starttime)
        else:
            return "%s_%s_%s.nuv.png"%(chanid, starttime, endtime)
        
    def buildThumbnailFilename( self, chanid, starttime, endtime ):
        return "%s_%s_%s.png"%(chanid, starttime, endtime)
        
    def buildThumbnailPath( self, chanid, starttime, endtime ):
        return self.cachePath + os.sep + \
            self.buildThumbnailFilename( chanid, starttime, endtime )
        
    def buildPath( self, program ):
        chanid = program.chanid()
        starttime = program.starttime()
        endtime = program.endtime()
        return self.buildThumbnailPath( chanid, starttime, endtime )

    def storeFile( self, program, theHost ):
        debug( "> mythtvgui.ThumbnailCache.storeFile( " + \
            "program=[%s])"%(program) )

        chanid = program.chanid()
        starttime = program.starttime()
        endtime = program.endtime()

#        s = getInstance( mythtv.Settings )
#        host = s.getSetting( "mythtv_host" )
#        port = int( s.getSetting( "mythtv_port" ) )
#        file = "/" + self.buildThumbnailRemoteFilename( \
#            chanid, starttime, endtime )
#        remotePath = "myth://%s:%d%s"%(host,port,file)
        remotePath = "%s.png" % program.remoteMythPath()
        localPath = self.buildThumbnailPath( chanid, starttime, endtime )

        c = getInstance( mythtv.Connection )
        rc = c.transferFile( remotePath, localPath, theHost )
        if rc != 0:
            rc = c.genPixmap( program, theHost )
            if rc == 0:
                for i in range(0,3):
                    time.sleep( 0.5 )
                    rc = c.transferFile( remotePath, localPath, theHost )
                    if rc == 0:
                        break
        del c
        if rc != 0:
            localPath = None
        debug( "< mythtvgui.ThumbnailCache.storeThumbnail() => [%s]"%localPath )
        return localPath

################################################################################
# For testing purposes
################################################################################
if __name__ == '__main__':

    import unittest

    mythtvutil.debugSetLevel( mythtvutil.DEBUG_ALL )
    mythtvutil.initialize()

    class PublicInterfaceTest( unittest.TestCase ):
        def testDialogOK( self ):
            Dialog().ok( "ok test", "Hello World" )

        def testDialogYesNo( self ):
            Dialog().yesno( "yes no test", "Are you sure?" )

    unittest.main()

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.