Ejemplo n.º 1
0
 def bootstrapDebugShell(self):
     # debug shell only packaged with bin/package-debug-zip
     try:
         from mythbox.shell import DebugShell
         globals()['bootstrapper'] = self
         self.shell = DebugShell(self.bus, namespace=globals())
         self.shell.start()
     except ImportError:
         self.log.debug('Punting on debug shell -- not packaged')
Ejemplo n.º 2
0
 def bootstrapDebugShell(self):
     # debug shell only packaged with bin/package-debug-zip
     try: 
         from mythbox.shell import DebugShell
         globals()['bootstrapper'] = self
         self.shell = DebugShell(self.bus, namespace=globals())
         self.shell.start()
     except ImportError:
         self.log.debug('Punting on debug shell -- not packaged')
Ejemplo n.º 3
0
class BootStrapper(object):
    
    def __init__(self, splash):
        self.log = None
        self.platform = None
        self.stage = 'Initializing'
        self.shell = None
        self.splash = splash
        self.failSilent = False
        
    def run(self):
        try:
            try:
                self.bootstrapLogger()
                self.bootstrapPlatform()
                self.bootstrapEventBus()            
                self.bootstrapCaches()
                self.bootstrapSettings()
                self.bootstrapUpdater()
                self.bootstrapFeeds()
                # TODO: Re-enable when twisted not loaded from dist-packages
                #self.bootstrapDebugShell()
                self.bootstrapHomeScreen()
            except Exception, ex:
                if not self.failSilent:
                    self.handleFailure(ex)
        finally:
            if self.splash:
                self.splash.close()
            
    def handleFailure(self, cause):
        msg = 'MythBox:%s - Error: %s' % (self.stage, cause)
        xbmc.log(msg)
        print traceback.print_exc()
        if self.log:
            self.log.exception(str(cause))
        xbmcgui.Dialog().ok('MythBox Error', 'Stage: %s' % self.stage, 'Exception: %s' % str(cause))
        
    def updateProgress(self, msg):
        self.log.info(msg)

    def bootstrapLogger(self):
        import logging
        import logging.config
        self.stage = 'Initializing Logger'
        
        import xbmcaddon
        scriptDir = xbmcaddon.Addon('script.mythbox').getAddonInfo('path')
        loggerIniFile = os.path.join(scriptDir, 'mythbox_log.ini')

        # needs to be in local scope for fileConfig to find it
        from mythbox.log import XbmcLogHandler
        
        xbmc.log('MythBox: loggerIniFile = %s' % loggerIniFile)
        logging.config.fileConfig(loggerIniFile)
        self.log = logging.getLogger('mythbox.core')
        self.log.info('Mythbox Logger Initialized')

    def bootstrapPlatform(self):
        self.stage = 'Initializing Platform'
        import mythbox.platform
        self.platform = mythbox.platform.getPlatform()
        self.platform.addLibsToSysPath()
        sys.setcheckinterval(0)
        cacheDir = self.platform.getCacheDir()
        from mythbox.util import requireDir
        requireDir(cacheDir)
        
        self.log.info('MythBox %s Initialized' % self.platform.addonVersion())

    def bootstrapEventBus(self):
        self.bus = EventBus()

    def bootstrapCaches(self):
        self.stage = 'Initializing Caches'
        
        from mythbox.util import NativeTranslator
        from mythbox.filecache import FileCache, HttpResolver, MythThumbnailFileCache
        from mythbox.mythtv.resolver import MythChannelIconResolver, MythThumbnailResolver 
        from os.path import join

        from mythbox.mythtv.cache import DomainCache
        self.domainCache = DomainCache(bus=self.bus)
        
        cacheDir = self.platform.getCacheDir()
        self.translator = NativeTranslator(self.platform.getScriptDir())
        self.mythThumbnailCache = MythThumbnailFileCache(join(cacheDir, 'thumbnail'), MythThumbnailResolver(), self.bus, self.domainCache)
        self.mythChannelIconCache = FileCache(join(cacheDir, 'channel'), MythChannelIconResolver())
        self.httpCache = FileCache(join(cacheDir, 'http'), HttpResolver())
        
        self.cachesByName = {
            'mythThumbnailCache'  : self.mythThumbnailCache, 
            'mythChannelIconCache': self.mythChannelIconCache, 
            'httpCache'           : self.httpCache,
            'domainCache'         : self.domainCache
        }

    def bootstrapSettings(self):
        self.stage = 'Initializing Settings'
        from mythbox.settings import MythSettings
        self.settings = MythSettings(self.platform, self.translator, 'settings.xml', self.bus)

        #from fanart import FanArt
        #self.log.debug('Settings = \n %s' % self.settings)

        class DelayedInstantiationProxy(object):
            '''Could use a little introspection to sort this out but eh...'''
            
            def __init__(self, *args, **kwargs):
                self.args = args
                self.kwargs = kwargs
                self.fanArt = None
                
            def requireDelegate(self):
                if self.fanArt is None:
                    from fanart import FanArt
                    self.fanArt = FanArt(*self.args, **self.kwargs)
            
            def getSeasonAndEpisode(self, program):
                self.requireDelegate()
                return self.fanArt.getSeasonAndEpisode(program)
            
            def getRandomPoster(self, program):
                self.requireDelegate()
                return self.fanArt.getRandomPoster(program)
            
            def getPosters(self, program):
                self.requireDelegate()
                return self.fanArt.getPosters(program)
        
            def hasPosters(self, program):
                self.requireDelegate()
                return self.fanArt.hasPosters(program)
            
            def clear(self):
                self.requireDelegate()
                self.fanArt.clear() 
        
            def shutdown(self):
                self.requireDelegate()
                self.fanArt.shutdown()
                
            def configure(self, settings):
                self.requireDelegate()
                self.fanArt.configure(settings)
            
            def onEvent(self, event):
                self.requireDelegate()
                self.fanArt.onEvent(event)
                    
        from fanart import FanArt
        self.fanArt = FanArt(self.platform, self.httpCache, self.settings, self.bus)
        #self.fanArt = DelayedInstantiationProxy(self.platform, self.httpCache, self.settings, self.bus)
        
        try:
            import socket
            socket.setdefaulttimeout(float(os.getenv('MYTHBOX_TIMEOUT', '30')))
        except:
            self.log.exception('Error setting socket timeout')
            
        self.bus.register(self)

        # Generate fake event to reflect value in settings.xml instead of mythbox_log.ini
        from bus import Event
        self.onEvent({'id': Event.SETTING_CHANGED, 'tag':'logging_enabled', 'old':'DontCare', 'new':self.settings.get('logging_enabled')})
        
    def bootstrapUpdater(self):
        self.stage = 'Initializing Updater'
        from mythbox.updater import UpdateChecker
        UpdateChecker(self.platform).run()

    def bootstrapFeeds(self):
        from mythbox.feeds import FeedHose
        self.feedHose = FeedHose(self.settings, self.bus)

    def bootstrapDebugShell(self):
        # debug shell only packaged with bin/package-debug-zip
        try: 
            from mythbox.shell import DebugShell
            globals()['bootstrapper'] = self
            self.shell = DebugShell(self.bus, namespace=globals())
            self.shell.start()
        except ImportError:
            self.log.debug('Punting on debug shell -- not packaged')

    def bootstrapXbmcShutdownListener(self):
        from threading import Thread
        
        class XbmcShutdownListener(Thread):        

            def __init__(self, home, bus, log):
                Thread.__init__(self)
                self.home = home
                self.log = log
                self.shutdownReceived = False
                bus.register(self)
             
            def onEvent(self, event):
                from bus import Event
                if event['id'] == Event.SHUTDOWN:
                    self.shutdownReceived = True
                    self.join()
                    xbmc.log('Joined shutdown listener') 
                
            def run(self):
                import time
                xbmc.log('XbmcShutdownListener thread running..')
                cnt = 1
                while not xbmc.abortRequested and not self.shutdownReceived:
                    #xbmc.sleep(1000)
                    time.sleep(1)
                    xbmc.log('XbmcShutdownListner abort = %s user = %s tick %d ...' % (xbmc.abortRequested, self.shutdownReceived, cnt))
                    cnt += 1
                    
                if xbmc.abortRequested:
                    xbmc.log('XBMC requested shutdown..')
                    self.home.shutdown()
                    xbmc.log('XBMC requested shutdown complete')
                    
                xbmc.log('XbmcShutdownListener thread terminating')
                
        self.shutdownListener = XbmcShutdownListener(self.home, self.bus, self.log)
        self.shutdownListener.start()

    def bootstrapHomeScreen(self):
        
        from mythbox.ui.home import HomeWindow
        self.home = HomeWindow(
                'mythbox_home.xml', 
                self.platform.getScriptDir(), 
                settings=self.settings, 
                translator=self.translator, 
                platform=self.platform, 
                fanArt=self.fanArt, 
                cachesByName=self.cachesByName,
                bus=self.bus,
                feedHose=self.feedHose)
        if self.splash:
            self.splash.close()
        #self.bootstrapXbmcShutdownListener()
        self.home.doModal()

    def onEvent(self, event):
        from bus import Event
        
        #
        # Apply changes to logger when user turns debug logging on/off
        #
        if event['id'] == Event.SETTING_CHANGED and event['tag'] == 'logging_enabled':
            import logging
            logging.root.debug('Setting changed: %s %s %s' % (event['tag'], event['old'], event['new']))

            if event['new'] == 'True': 
                level = logging.DEBUG
            else: 
                level = logging.WARN
                
            loggerNames = 'unittest mysql core method skin ui perf fanart settings cache event'.split() # wire inject'.split()
                
            for name in loggerNames:
                logger = logging.getLogger('mythbox.%s' %  name)
                logger.setLevel(level)
Ejemplo n.º 4
0
class BootStrapper(object):
    def __init__(self, splash):
        self.log = None
        self.platform = None
        self.stage = 'Initializing'
        self.shell = None
        self.splash = splash
        self.failSilent = False

    def run(self):
        try:
            try:
                self.bootstrapLogger()
                self.bootstrapPlatform()
                self.bootstrapEventBus()
                self.bootstrapCaches()
                self.bootstrapSettings()
                self.bootstrapUpdater()
                self.bootstrapFeeds()
                # TODO: Re-enable when twisted not loaded from dist-packages
                #self.bootstrapDebugShell()
                self.bootstrapHomeScreen()
            except Exception, ex:
                if not self.failSilent:
                    self.handleFailure(ex)
        finally:
            if self.splash:
                self.splash.close()

    def handleFailure(self, cause):
        msg = 'MythBox:%s - Error: %s' % (self.stage, cause)
        xbmc.log(msg)
        print traceback.print_exc()
        if self.log:
            self.log.exception(str(cause))
        xbmcgui.Dialog().ok('MythBox Error', 'Stage: %s' % self.stage,
                            'Exception: %s' % str(cause))

    def updateProgress(self, msg):
        self.log.info(msg)

    def bootstrapLogger(self):
        import logging
        import logging.config
        self.stage = 'Initializing Logger'

        import xbmcaddon
        scriptDir = xbmcaddon.Addon('script.mythbox').getAddonInfo('path')
        loggerIniFile = os.path.join(scriptDir, 'mythbox_log.ini')

        # needs to be in local scope for fileConfig to find it
        from mythbox.log import XbmcLogHandler

        xbmc.log('MythBox: loggerIniFile = %s' % loggerIniFile)
        logging.config.fileConfig(loggerIniFile)
        self.log = logging.getLogger('mythbox.core')
        self.log.info('Mythbox Logger Initialized')

    def bootstrapPlatform(self):
        self.stage = 'Initializing Platform'
        import mythbox.platform
        self.platform = mythbox.platform.getPlatform()
        self.platform.addLibsToSysPath()
        sys.setcheckinterval(0)
        cacheDir = self.platform.getCacheDir()
        from mythbox.util import requireDir
        requireDir(cacheDir)

        self.log.info('MythBox %s Initialized' % self.platform.addonVersion())

    def bootstrapEventBus(self):
        self.bus = EventBus()

    def bootstrapCaches(self):
        self.stage = 'Initializing Caches'

        from mythbox.util import NativeTranslator
        from mythbox.filecache import FileCache, HttpResolver, MythThumbnailFileCache
        from mythbox.mythtv.resolver import MythChannelIconResolver, MythThumbnailResolver
        from os.path import join

        from mythbox.mythtv.cache import DomainCache
        self.domainCache = DomainCache(bus=self.bus)

        cacheDir = self.platform.getCacheDir()
        self.translator = NativeTranslator(self.platform.getScriptDir())
        self.mythThumbnailCache = MythThumbnailFileCache(
            join(cacheDir, 'thumbnail'), MythThumbnailResolver(), self.bus,
            self.domainCache)
        self.mythChannelIconCache = FileCache(join(cacheDir, 'channel'),
                                              MythChannelIconResolver())
        self.httpCache = FileCache(join(cacheDir, 'http'), HttpResolver())

        self.cachesByName = {
            'mythThumbnailCache': self.mythThumbnailCache,
            'mythChannelIconCache': self.mythChannelIconCache,
            'httpCache': self.httpCache,
            'domainCache': self.domainCache
        }

    def bootstrapSettings(self):
        self.stage = 'Initializing Settings'
        from mythbox.settings import MythSettings
        self.settings = MythSettings(self.platform, self.translator,
                                     'settings.xml', self.bus)

        #from fanart import FanArt
        #self.log.debug('Settings = \n %s' % self.settings)

        class DelayedInstantiationProxy(object):
            '''Could use a little introspection to sort this out but eh...'''
            def __init__(self, *args, **kwargs):
                self.args = args
                self.kwargs = kwargs
                self.fanArt = None

            def requireDelegate(self):
                if self.fanArt is None:
                    from fanart import FanArt
                    self.fanArt = FanArt(*self.args, **self.kwargs)

            def getSeasonAndEpisode(self, program):
                self.requireDelegate()
                return self.fanArt.getSeasonAndEpisode(program)

            def getRandomPoster(self, program):
                self.requireDelegate()
                return self.fanArt.getRandomPoster(program)

            def getPosters(self, program):
                self.requireDelegate()
                return self.fanArt.getPosters(program)

            def hasPosters(self, program):
                self.requireDelegate()
                return self.fanArt.hasPosters(program)

            def clear(self):
                self.requireDelegate()
                self.fanArt.clear()

            def shutdown(self):
                self.requireDelegate()
                self.fanArt.shutdown()

            def configure(self, settings):
                self.requireDelegate()
                self.fanArt.configure(settings)

            def onEvent(self, event):
                self.requireDelegate()
                self.fanArt.onEvent(event)

        from fanart import FanArt
        self.fanArt = FanArt(self.platform, self.httpCache, self.settings,
                             self.bus)
        #self.fanArt = DelayedInstantiationProxy(self.platform, self.httpCache, self.settings, self.bus)

        try:
            import socket
            socket.setdefaulttimeout(float(os.getenv('MYTHBOX_TIMEOUT', '30')))
        except:
            self.log.exception('Error setting socket timeout')

        self.bus.register(self)

        # Generate fake event to reflect value in settings.xml instead of mythbox_log.ini
        from bus import Event
        self.onEvent({
            'id': Event.SETTING_CHANGED,
            'tag': 'logging_enabled',
            'old': 'DontCare',
            'new': self.settings.get('logging_enabled')
        })

    def bootstrapUpdater(self):
        self.stage = 'Initializing Updater'
        from mythbox.updater import UpdateChecker
        UpdateChecker(self.platform).run()

    def bootstrapFeeds(self):
        from mythbox.feeds import FeedHose
        self.feedHose = FeedHose(self.settings, self.bus)

    def bootstrapDebugShell(self):
        # debug shell only packaged with bin/package-debug-zip
        try:
            from mythbox.shell import DebugShell
            globals()['bootstrapper'] = self
            self.shell = DebugShell(self.bus, namespace=globals())
            self.shell.start()
        except ImportError:
            self.log.debug('Punting on debug shell -- not packaged')

    def bootstrapXbmcShutdownListener(self):
        from threading import Thread

        class XbmcShutdownListener(Thread):
            def __init__(self, home, bus, log):
                Thread.__init__(self)
                self.home = home
                self.log = log
                self.shutdownReceived = False
                bus.register(self)

            def onEvent(self, event):
                from bus import Event
                if event['id'] == Event.SHUTDOWN:
                    self.shutdownReceived = True
                    self.join()
                    xbmc.log('Joined shutdown listener')

            def run(self):
                import time
                xbmc.log('XbmcShutdownListener thread running..')
                cnt = 1
                while not xbmc.abortRequested and not self.shutdownReceived:
                    #xbmc.sleep(1000)
                    time.sleep(1)
                    xbmc.log(
                        'XbmcShutdownListner abort = %s user = %s tick %d ...'
                        % (xbmc.abortRequested, self.shutdownReceived, cnt))
                    cnt += 1

                if xbmc.abortRequested:
                    xbmc.log('XBMC requested shutdown..')
                    self.home.shutdown()
                    xbmc.log('XBMC requested shutdown complete')

                xbmc.log('XbmcShutdownListener thread terminating')

        self.shutdownListener = XbmcShutdownListener(self.home, self.bus,
                                                     self.log)
        self.shutdownListener.start()

    def bootstrapHomeScreen(self):

        from mythbox.ui.home import HomeWindow
        self.home = HomeWindow('mythbox_home.xml',
                               self.platform.getScriptDir(),
                               settings=self.settings,
                               translator=self.translator,
                               platform=self.platform,
                               fanArt=self.fanArt,
                               cachesByName=self.cachesByName,
                               bus=self.bus,
                               feedHose=self.feedHose)
        if self.splash:
            self.splash.close()
        #self.bootstrapXbmcShutdownListener()
        self.home.doModal()

    def onEvent(self, event):
        from bus import Event

        #
        # Apply changes to logger when user turns debug logging on/off
        #
        if event['id'] == Event.SETTING_CHANGED and event[
                'tag'] == 'logging_enabled':
            import logging
            logging.root.debug('Setting changed: %s %s %s' %
                               (event['tag'], event['old'], event['new']))

            if event['new'] == 'True':
                level = logging.DEBUG
            else:
                level = logging.WARN

            loggerNames = 'unittest mysql core method skin ui perf fanart settings cache event'.split(
            )  # wire inject'.split()

            for name in loggerNames:
                logger = logging.getLogger('mythbox.%s' % name)
                logger.setLevel(level)