def __init__(self, session, url, pathForRecordings, pictureTitle):
        self.session = session
        Screen.__init__(self, session)
        self.onStartCalled = False
        
        self.recordingPath = pathForRecordings
        try:
            self.filePath = os.path.join(pathForRecordings, '.iptv_buffering.jpg')
        except:
            self.filePath = ''
            printExc()
            
        self.url           = url
        self.pictureTitle  = pictureTitle
        self.audioUrl      = strwithmeta(url).meta.get("iptv_audio_url", '')
       
        self["actions"] = ActionMap(['IPTVAlternateVideoPlayer', 'MoviePlayerActions', 'MediaPlayerActions', 'WizardActions', 'DirectionActions'],
        {
            'leavePlayer'  : self.key_exit,
            'play'         : self.key_play,
            'pause'        : self.key_pause,
            'exit'         : self.key_exit,
            'back'         : self.key_exit,
            'ok'           : self.key_ok,
        }, -1)     

        self["status"]  = Label()
        self["console"] = Label()
        self["icon"]    = SimpleAnimatedCover()
        self["picture"] = Cover()

        # prepare icon frames path
        frames = []
        for idx in range(1,self.NUM_OF_ICON_FRAMES+1): frames.append( GetIconDir('/buffering/buffering_%d.png' % idx) )
        self["icon"].loadFrames(frames) 
        
        #main Timer
        self.mainTimer = eTimer()
        self.mainTimerEnabled = False
        self.mainTimer_conn = eConnectCallback(self.mainTimer.timeout, self.updateDisplay)
        self.mainTimerInterval = 100 # by default 0,1s
        # download
        self.downloader = DownloaderCreator(self.url)
        
        self.onClose.append(self.__onClose)
        self.onShow.append(self.doStart)
        #self.onLayoutFinish.append(self.doStart)
        
        self.autoRefresh = False
        self.refreshPostfixes = ['_0', '_1']
        self.refreshCount = 0
        self.refreshing = False
        
        if len(self.audioUrl) and len(config.plugins.iptvplayer.gstplayerpath.value):
            self.audioPlayer = IPTVSimpleAudioPlayer()
        else: self.audioPlayer  = None
 def _doStart(self, force=False):
     if self.autoRefresh or force:
         self.refreshing = True
         self.downloader = DownloaderCreator(self.url)
         
         url,downloaderParams = DMHelper.getDownloaderParamFromUrl(self.url)
         self.downloader.subscribeFor_Finish(self.downloaderEnd)
         self.downloader.start(url, self._getDownloadFilePath(), downloaderParams)
         self.setMainTimerSts(True)
     else: self.refreshing = False
 def startDownload(self, item):
     self.setListMode(False)
     self.cleanDownloader()
     self.currItem = item
     self["console"].setText(_("Downloading subtitles.\n ('%r').") % self.currItem.get('url', ''))
     # create downloader
     self.downloader = DownloaderCreator(self.currItem.get('url', ''))
     if self.downloader:
         self.downloader.isWorkingCorrectly(self._startDownloader)
     else:
         self["console"].setText(_("Download can not be started.\n Incorrect address ('%r')."))
Example #4
0
 def onStart(self):
     '''
         this method is called once like __init__ but in __init__ we cannot display MessageBox
     '''
     self.lastPosition  = None
     self.lastSize = 0
     # create downloader
     self.downloader = DownloaderCreator(self.url)
     self._cleanedUp()
     if self.downloader:
         self.downloader.isWorkingCorrectly(self._startDownloader)
     else:
         self.session.openWithCallback(self.close, MessageBox, _("Pobieranie nie może zostać rozpoczęte.\n Podany adres ('%r') jest niepoprawny.") % self.url, type = MessageBox.TYPE_ERROR, timeout = 10)
Example #5
0
 def onStart(self):
     '''
         this method is called once like __init__ but in __init__ we cannot display MessageBox
     '''
     self.lastPosition  = None
     self.lastSize = 0
     # create downloader
     self.downloader = DownloaderCreator(self.url)
     self._cleanedUp()
     if self.downloader:
         self.downloader.isWorkingCorrectly(self._startDownloader)
     else:
         self.session.openWithCallback(self.close, MessageBox, _("Downloading can not be started.\n The address ('%r') is incorrect.") % self.url, type = MessageBox.TYPE_ERROR, timeout = 10)
    def loadCover(self):
        self["cover"].hide()
        if 0 == len(self.artItem.images):
            return
        self.cover['src'] = self.artItem.images[0].get('url', '')
        if not self.cover['src'].startswith('http'):
            return

        self.cover['downloader'] = DownloaderCreator(self.cover['src'])
        if self.cover['downloader']:
            self.cover['downloader'].isWorkingCorrectly(self.startDownloader)
        else:
            self.session.openWithCallback(
                self.close,
                MessageBox,
                _("Downloading cannot be started.\n Invalid URI[%s].") %
                self.cover['src'],
                type=MessageBox.TYPE_ERROR,
                timeout=10)
Example #7
0
    def runCMD(self, item):
        printDBG("runCMD for downloadIdx[%d]" % item.downloadIdx)

        if DMHelper.DOWNLOAD_TYPE.INITIAL == item.tries:
            item.fileName = DMHelper.makeUnikalFileName(
                item.fileName, False, False)

        printDBG("Downloading started downloadIdx[%s] File[%s] URL[%s]" %
                 (item.downloadIdx, item.fileName, item.url))

        listUDIdx = self.findIdxInQueueUD(item.downloadIdx)
        self.queueUD[listUDIdx].status = DMHelper.STS.DOWNLOADING
        self.queueUD[listUDIdx].fileName = item.fileName

        url, downloaderParams = DMHelper.getDownloaderParamFromUrl(item.url)
        self.queueUD[listUDIdx].downloader = DownloaderCreator(url)
        self.queueUD[listUDIdx].callback = boundFunction(
            self.cmdFinished, item.downloadIdx)
        self.queueUD[listUDIdx].downloader.subscribeFor_Finish(
            self.queueUD[listUDIdx].callback)
        self.queueUD[listUDIdx].downloader.start(url, item.fileName,
                                                 downloaderParams)
Example #8
0
class IPTVPlayerBufferingWidget(Screen):
    GST_FLV_DEMUX_IS_DEMUXING_INFINITE_FILE = "/tmp/gst_flv_demux_is_demuxing_infinite_file"
    NUM_OF_ICON_FRAMES = 8
    #######################
    #       SIZES
    #######################
    # screen size
    # we do not want borders, so make the screen lager than a desktop
    sz_w = getDesktop(0).size().width()
    sz_h = getDesktop(0).size().height()
    # icon
    i_w = 128
    i_h = 128
    # percentage
    p_w = 120
    p_h = 120
    # console
    c_w = sz_w
    c_h = 80
    #######################
    #     POSITIONS
    #######################
    start_y = (sz_h - (i_h + c_h)) / 2
    # icon
    i_x = (sz_w - i_w) / 2
    i_y = start_y
    # percentage
    p_x = (sz_w - p_w) / 2
    p_y = start_y + (i_h - p_h) / 2
    # console
    c_x = 0
    c_y = i_y + i_h

    printDBG("[IPTVPlayerBufferingWidget] desktop size %dx%d" % (sz_w, sz_h))
    skin = """
        <screen name="IPTVPlayerBufferingWidget"  position="center,center" size="%d,%d" title="IPTV Player Buffering...">
         <widget name="percentage" size="%d,%d"   position="%d,%d"  zPosition="5" valign="center" halign="center"  font="Regular;21" backgroundColor="black" transparent="1" /> #foregroundColor="white" shadowColor="black" shadowOffset="-1,-1"
         <widget name="console"    size="%d,%d"   position="%d,%d"  zPosition="5" valign="center" halign="center"  font="Regular;21" backgroundColor="black" transparent="1" />
         <widget name="icon"       size="%d,%d"   position="%d,%d"  zPosition="4" transparent="1" alphatest="blend" />
        </screen>""" % (
        sz_w,
        sz_h,  # screen
        p_w,
        p_h,
        p_x,
        p_y,  # percentage
        c_w,
        c_h,
        c_x,
        c_y,  # console
        i_w,
        i_h,
        i_x,
        i_y  # icon
    )

    def __init__(self,
                 session,
                 url,
                 pathForRecordings,
                 movieTitle,
                 activMoviePlayer,
                 requestedBuffSize,
                 playerAdditionalParams={}):
        self.session = session
        Screen.__init__(self, session)
        self.onStartCalled = False

        self.recordingPath = pathForRecordings
        self.filePath = pathForRecordings + '/.iptv_buffering.flv'
        self.url = url
        self.movieTitle = movieTitle

        self.currentService = self.session.nav.getCurrentlyPlayingServiceReference(
        )
        self.activMoviePlayer = activMoviePlayer

        self.onClose.append(self.__onClose)
        #self.onLayoutFinish.append(self.doStart)
        self.onShow.append(self.onWindowShow)
        #self.onHide.append(self.onWindowHide)

        self["actions"] = ActionMap(
            ["WizardActions", "MoviePlayerActions"], {
                "ok": self.ok_pressed,
                "back": self.back_pressed,
                "leavePlayer": self.back_pressed,
            }, -1)

        self["console"] = Label()
        self["percentage"] = Label()

        self["icon"] = SimpleAnimatedCover()
        # prepare icon frames path
        frames = []
        for idx in range(1, self.NUM_OF_ICON_FRAMES + 1):
            frames.append(
                resolveFilename(
                    SCOPE_PLUGINS,
                    'Extensions/IPTVPlayer/icons/buffering/buffering_%d.png' %
                    idx))
        self["icon"].loadFrames(frames)

        self.inMoviePlayer = False
        self.canRunMoviePlayer = False  # used in function updateDisplay, so must be first initialized
        #main Timer
        self.mainTimer = eTimer()
        self.mainTimerEnabled = False
        self.mainTimer_conn = eConnectCallback(self.mainTimer.timeout,
                                               self.updateDisplay)
        self.mainTimerInterval = 1000  # by default 1s

        self.requestedBuffSize = requestedBuffSize
        self.playerAdditionalParams = playerAdditionalParams

    #end def __init__(self, session):

    def onStart(self):
        '''
            this method is called once like __init__ but in __init__ we cannot display MessageBox
        '''
        self.lastPosition = None
        self.lastSize = 0
        # create downloader
        self.downloader = DownloaderCreator(self.url)
        self._cleanedUp()
        if self.downloader:
            self.downloader.isWorkingCorrectly(self._startDownloader)
        else:
            self.session.openWithCallback(
                self.close,
                MessageBox,
                _("Pobieranie nie może zostać rozpoczęte.\n Podany adres ('%r') jest niepoprawny."
                  ) % self.url,
                type=MessageBox.TYPE_ERROR,
                timeout=10)

    def _isFlvInfiniteFile(self, url):
        try:
            url = strwithmeta(url)
            if (url.startswith('rtmp')
                    or url.split('?')[0].endswith('.f4m')) and url.meta.get(
                        'iptv_livestream', True):
                return True
        except:
            printExc()
        return False

    def _startDownloader(self, sts, reason):
        if sts:
            url, downloaderParams = DMHelper.getDownloaderParamFromUrl(
                self.url)
            if self._isFlvInfiniteFile(self.url):
                ret = touch(
                    self.GST_FLV_DEMUX_IS_DEMUXING_INFINITE_FILE
                )  # TODO: check returns value, and display message in case of False
            self.downloader.start(url, self.filePath, downloaderParams)
            self.setMainTimerSts(True)
            self.canRunMoviePlayer = True
        else:
            self.session.openWithCallback(
                self.close,
                MessageBox,
                _("Pobieranie nie może zostać rozpoczęte.\n Downloader %s nie działa prawidłowo.\nStatus[%s]"
                  ) % (self.downloader.getName(), reason.strip()),
                type=MessageBox.TYPE_ERROR,
                timeout=10)

    def _isInLiveMode(self):
        if isinstance(self.url, strwithmeta):
            if 'iptv_livestream' in self.url.meta:
                return self.url.meta['iptv_livestream']
        # if we do not have information if it is live try to figure out from other sources
        if self.downloader:
            tmp = self.downloader.isLiveStream()
            if None != tmp:
                return tmp
        if self.url.startswith('rtmp'):
            return True

    def onEnd(self):
        self.setMainTimerSts(False)
        if self.downloader:
            self.downloader.terminate()
            self.downloader = None
        self._cleanedUp()

    def leaveMoviePlayer(self, ret=None, lastPosition=None, *args, **kwargs):
        printDBG("leaveMoviePlayer ret[%r], lastPosition[%r]" %
                 (ret, lastPosition))
        # There is need to set None for current service
        # otherwise there is a problem with resuming play
        self.session.nav.playService(None)
        self.lastPosition = lastPosition
        self.canRunMoviePlayer = False
        self.inMoviePlayer = False

        #  ret == 1 - no data in buffer
        #  ret == 0 - triggered by user
        if 1 == ret:
            if DMHelper.STS.DOWNLOADING == self.downloader.getStatus():
                self.lastSize = self.downloader.getLocalFileSize(True)
                printDBG(
                    "IPTVPlayerBufferingWidget.leaveMoviePlayer: movie player consume all data from buffer - still downloading"
                )
                self.confirmExitCallBack()  # continue
            else:
                printDBG(
                    "IPTVPlayerBufferingWidget.leaveMoviePlayer: movie player consume all data from buffer - downloading finished"
                )
                if DMHelper.STS.DOWNLOADED != self.downloader.getStatus():
                    self.session.openWithCallback(
                        self.close,
                        MessageBox,
                        text=_("Nastąpił błąd pobierania."),
                        type=MessageBox.TYPE_ERROR,
                        timeout=5)
                else:
                    self.close()
        elif 0 == ret or None == ret:
            # ask if we should close
            self.lastSize = self.downloader.getLocalFileSize(True)
            self.session.openWithCallback(self.confirmExitCallBack,
                                          MessageBox,
                                          text=_("Zakończyć odtwarzanie?"),
                                          type=MessageBox.TYPE_YESNO)

    def confirmExitCallBack(self, ret=None):
        if ret and ret == True:
            self.close()
        else:
            if not self._isInLiveMode():
                self.canRunMoviePlayer = True
                self.setMainTimerSts(True)
            else:
                # for live streams we will remove old buffer and start downloader once again
                self.onEnd()
                self.onStart()

    def back_pressed(self):
        self.close()
        return

    def ok_pressed(self):
        if self.canRunMoviePlayer and self.downloader.getLocalFileSize() > 0:
            self.runMovePlayer()

    def runMovePlayer(self):
        # this shoudl not happen but to make sure
        if not self.canRunMoviePlayer:
            printDBG(
                'called runMovePlayer with canRunMoviePlayer set to False')
            return

        self.inMoviePlayer = True
        buffSize = self.downloader.getLocalFileSize() - self.lastSize
        printDBG("Run MoviePlayer with buffer size [%s]" %
                 formatBytes(float(buffSize)))
        self.setMainTimerSts(False)

        exteplayerBlocked = strwithmeta(self.url).meta.get(
            'iptv_block_exteplayer', False)
        printDBG(
            "runMovePlayer >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> exteplayerBlocked[%s]"
            % exteplayerBlocked)

        player = self.activMoviePlayer
        printDBG('IPTVPlayerBufferingWidget.runMovePlayer [%r]' % player)
        playerAdditionalParams = dict(self.playerAdditionalParams)
        playerAdditionalParams['downloader'] = self.downloader
        if strwithmeta(self.url).meta.get('iptv_proto',
                                          '') in ['f4m', 'uds', 'm3u8']:
            playerAdditionalParams['file-download-timeout'] = 90000  # 90s
        else:
            playerAdditionalParams['file-download-timeout'] = 10000  # 10s
        playerAdditionalParams['file-download-live'] = self._isInLiveMode()
        if "mini" == player:
            self.session.openWithCallback(self.leaveMoviePlayer,
                                          IPTVMiniMoviePlayer, self.filePath,
                                          self.movieTitle, self.lastPosition,
                                          4)
        elif "exteplayer" == player:
            if not exteplayerBlocked:
                self.session.openWithCallback(self.leaveMoviePlayer,
                                              IPTVExtMoviePlayer,
                                              self.filePath, self.movieTitle,
                                              self.lastPosition, 'eplayer',
                                              playerAdditionalParams)
            else:
                self.session.openWithCallback(self.leaveMoviePlayer,
                                              IPTVExtMoviePlayer,
                                              self.filePath, self.movieTitle,
                                              self.lastPosition, 'gstplayer',
                                              playerAdditionalParams)
        elif "extgstplayer" == player:
            self.session.openWithCallback(self.leaveMoviePlayer,
                                          IPTVExtMoviePlayer, self.filePath,
                                          self.movieTitle, self.lastPosition,
                                          'gstplayer', playerAdditionalParams)
        else:
            self.session.openWithCallback(self.leaveMoviePlayer,
                                          IPTVStandardMoviePlayer,
                                          self.filePath, self.movieTitle)
        playerAdditionalParams = None

    def setMainTimerSts(self, start):
        try:
            if start:
                if not self.mainTimerEnabled:
                    self.mainTimer.start(self.mainTimerInterval)
                    self.mainTimerEnabled = True
                    self.updateDisplay()
            else:
                if self.mainTimerEnabled:
                    self.mainTimer.stop()
                    self.mainTimerEnabled = False
        except:
            printDBG("setMainTimerSts status[%r] EXCEPTION" % start)

    def updateDisplay(self):
        printDBG("updateDisplay")
        if self.inMoviePlayer:
            printDBG("updateDisplay aborted - we are in moviePlayer")
            return

        if not self.mainTimerEnabled:
            printDBG("updateDisplay aborted - timer stoped")
            return

        self.downloader.updateStatistic()
        tmpBuffSize = self.downloader.getLocalFileSize(
        ) - self.lastSize + 1  # simple when getLocalFileSize() returns -1
        # remote size
        rFileSize = self.downloader.getRemoteFileSize()
        if -1 == rFileSize: rFileSize = '??'
        else: rFileSize = formatBytes(float(rFileSize))
        # local size
        lFileSize = self.downloader.getLocalFileSize()
        if -1 == lFileSize: lFileSize = '??'
        else: lFileSize = formatBytes(float(lFileSize))
        # download speed
        dSpeed = self.downloader.getDownloadSpeed()
        if -1 == dSpeed: dSpeed = ''
        else: dSpeed = formatBytes(float(dSpeed))

        speed = self.downloader.getDownloadSpeed()
        tmpStr = ''
        if 0 < self.downloader.getLocalFileSize():
            if 0 <= self.downloader.getRemoteFileSize():
                tmpStr = "\n%s/%s" % (lFileSize, rFileSize)
            else:
                tmpStr = "\n%s" % (lFileSize)
            if 0 <= dSpeed:
                tmpStr += "\n%s/s" % (dSpeed)
        else:
            tmpStr += '\n\n'

        self["console"].setText(self.movieTitle + tmpStr)
        if tmpBuffSize > self.requestedBuffSize: percentage = 100
        else: percentage = (100 * tmpBuffSize) / self.requestedBuffSize
        self["percentage"].setText(str(percentage))
        self["icon"].nextFrame()

        # check if we start move player
        if self.canRunMoviePlayer:
            if tmpBuffSize >= self.requestedBuffSize or (
                    self.downloader.getStatus() == DMHelper.STS.DOWNLOADED
                    and 0 < self.downloader.getLocalFileSize()):
                self.runMovePlayer()
                return

        # check if it is downloading
        if self.downloader.getStatus() not in [
                DMHelper.STS.DOWNLOADING, DMHelper.STS.WAITING
        ]:
            self.session.openWithCallback(
                self.close,
                MessageBox,
                "Nastąpił błąd pobierania. \nStatus[%s], tmpBuffSize[%r], canRunMoviePlayer[%r]"
                % (self.downloader.getStatus(), tmpBuffSize,
                   self.canRunMoviePlayer),
                type=MessageBox.TYPE_ERROR,
                timeout=10)
            self.canRunMoviePlayer = False
            # stop timer before message
            self.setMainTimerSts(False)

        return

    def __del__(self):
        printDBG(
            'IPTVPlayerBufferingWidget.__del__ --------------------------------------'
        )

    def __onClose(self):
        printDBG(
            'IPTVPlayerBufferingWidget.__onClose ------------------------------------'
        )
        self.onEnd()
        self.session.nav.playService(self.currentService)
        try:
            self.mainTimer_conn = None
            self.mainTimer = None
        except:
            printExc()

        self.onClose.remove(self.__onClose)
        #self.onLayoutFinish.remove(self.doStart)
        self.onShow.remove(self.onWindowShow)
        #self.onHide.remove(self.onWindowHide)

    def _cleanedUp(self):
        if fileExists(self.filePath):
            try:
                os_remove(self.filePath)
            except:
                printDBG('Problem with removing old buffering file')
        if fileExists(self.GST_FLV_DEMUX_IS_DEMUXING_INFINITE_FILE):
            try:
                os_remove(self.GST_FLV_DEMUX_IS_DEMUXING_INFINITE_FILE)
            except:
                printDBG('Problem with removing gstreamer flag file [%s]' %
                         self.GST_FLV_DEMUX_IS_DEMUXING_INFINITE_FILE)

    '''
    def doStart(self):
        if not self.onStartCalled:
            self.onStartCalled = True
            self.onStart()
    
    
    def onWindowHide(self): 
        self.visible = False
    '''

    def onWindowShow(self):
        if not self.onStartCalled:
            self.onStartCalled = True
            self.onStart()


#class IPTVPlayerWidget
Example #9
0
class IPTVPlayerBufferingWidget(Screen):
    GST_FLV_DEMUX_IS_DEMUXING_INFINITE_FILE = "/tmp/gst_flv_demux_is_demuxing_infinite_file"
    NUM_OF_ICON_FRAMES = 8
    #######################
    #       SIZES
    #######################
    # screen size
    # we do not want borders, so make the screen lager than a desktop
    sz_w = getDesktop(0).size().width() 
    sz_h = getDesktop(0).size().height()
    # icon
    i_w = 128
    i_h = 128
    # percentage
    p_w = 120
    p_h = 120
    # console
    c_w = sz_w
    c_h = 80
    #######################
    #     POSITIONS
    #######################  
    start_y = (sz_h - (i_h + c_h)) / 2 
    # icon
    i_x = (sz_w - i_w) / 2
    i_y = start_y
    # percentage
    p_x = (sz_w - p_w) / 2
    p_y = start_y + (i_h - p_h) / 2
    # console
    c_x = 0
    c_y = i_y + i_h
    
    printDBG("[IPTVPlayerBufferingWidget] desktop size %dx%d" % (sz_w, sz_h) )
    skin = """
        <screen name="IPTVPlayerBufferingWidget"  position="center,center" size="%d,%d" title="IPTV Player Buffering...">
         <widget name="percentage" size="%d,%d"   position="%d,%d"  zPosition="5" valign="center" halign="center"  font="Regular;21" backgroundColor="black" transparent="1" /> #foregroundColor="white" shadowColor="black" shadowOffset="-1,-1"
         <widget name="console"    size="%d,%d"   position="%d,%d"  zPosition="5" valign="center" halign="center"  font="Regular;21" backgroundColor="black" transparent="1" />
         <widget name="icon"       size="%d,%d"   position="%d,%d"  zPosition="4" transparent="1" alphatest="blend" />
        </screen>""" %( sz_w, sz_h,         # screen
                        p_w, p_h, p_x, p_y, # percentage
                        c_w, c_h, c_x, c_y, # console
                        i_w, i_h, i_x, i_y  # icon
                      )
   
    def __init__(self, session, url, pathForRecordings, movieTitle, activMoviePlayer, requestedBuffSize, playerAdditionalParams={}):
        self.session = session
        Screen.__init__(self, session)
        self.onStartCalled = False
        
        self.recordingPath = pathForRecordings
        self.filePath      = pathForRecordings + '/.iptv_buffering.flv'
        self.url           = url
        self.movieTitle    = movieTitle
        
        self.currentService   = self.session.nav.getCurrentlyPlayingServiceReference()
        self.activMoviePlayer = activMoviePlayer
        
        self.onClose.append(self.__onClose)
        #self.onLayoutFinish.append(self.doStart)
        self.onShow.append(self.onWindowShow)
        #self.onHide.append(self.onWindowHide)
        
        self["actions"] = ActionMap(["WizardActions", "MoviePlayerActions"],
        {
            "ok":          self.ok_pressed,
            "back":        self.back_pressed,
            "leavePlayer": self.back_pressed,
        }, -1)     

        self["console"] = Label()
        self["percentage"] = Label()
             
        self["icon"] = SimpleAnimatedCover()
        # prepare icon frames path
        frames = []
        for idx in range(1,self.NUM_OF_ICON_FRAMES+1): frames.append( resolveFilename(SCOPE_PLUGINS, 'Extensions/IPTVPlayer/icons/buffering/buffering_%d.png' % idx) )
        self["icon"].loadFrames(frames) 
        
        self.inMoviePlayer = False
        self.canRunMoviePlayer = False # used in function updateDisplay, so must be first initialized
        #main Timer
        self.mainTimer = eTimer()
        self.mainTimerEnabled = False
        self.mainTimer_conn = eConnectCallback(self.mainTimer.timeout, self.updateDisplay)
        self.mainTimerInterval = 1000 # by default 1s
        
        self.requestedBuffSize = requestedBuffSize
        self.playerAdditionalParams = playerAdditionalParams
        
        
    #end def __init__(self, session):
 
    def onStart(self):
        '''
            this method is called once like __init__ but in __init__ we cannot display MessageBox
        '''
        self.lastPosition  = None
        self.lastSize = 0
        # create downloader
        self.downloader = DownloaderCreator(self.url)
        self._cleanedUp()
        if self.downloader:
            self.downloader.isWorkingCorrectly(self._startDownloader)
        else:
            self.session.openWithCallback(self.close, MessageBox, _("Pobieranie nie może zostać rozpoczęte.\n Podany adres ('%r') jest niepoprawny.") % self.url, type = MessageBox.TYPE_ERROR, timeout = 10)

    def _isFlvInfiniteFile(self, url):
        try:
            url = strwithmeta(url)
            if (url.startswith('rtmp') or url.split('?')[0].endswith('.f4m')) and url.meta.get('iptv_livestream', True): return True
        except: printExc()
        return False
        
    def _startDownloader(self, sts, reason):
        if sts:
            url,downloaderParams = DMHelper.getDownloaderParamFromUrl(self.url)
            if self._isFlvInfiniteFile(self.url):
                ret = touch(self.GST_FLV_DEMUX_IS_DEMUXING_INFINITE_FILE) # TODO: check returns value, and display message in case of False
            self.downloader.start(url, self.filePath, downloaderParams)
            self.setMainTimerSts(True)
            self.canRunMoviePlayer = True
        else:
            self.session.openWithCallback(self.close, MessageBox, _("Pobieranie nie może zostać rozpoczęte.\n Downloader %s nie działa prawidłowo.\nStatus[%s]") % (self.downloader.getName(), reason.strip()), type = MessageBox.TYPE_ERROR, timeout = 10 )

    def _isInLiveMode(self):
        if isinstance(self.url, strwithmeta):
            if 'iptv_livestream' in self.url.meta:
                return self.url.meta['iptv_livestream']
        # if we do not have information if it is live try to figure out from other sources
        if self.downloader:
            tmp = self.downloader.isLiveStream()
            if None != tmp:
                return tmp
        if self.url.startswith('rtmp'):
            return True
        
    def onEnd(self):
        self.setMainTimerSts(False)
        if self.downloader:
            self.downloader.terminate()
            self.downloader = None
        self._cleanedUp()

    def leaveMoviePlayer(self, ret=None, lastPosition=None, *args, **kwargs):
        printDBG("leaveMoviePlayer ret[%r], lastPosition[%r]" % (ret, lastPosition))
        # There is need to set None for current service
        # otherwise there is a problem with resuming play
        self.session.nav.playService(None)
        self.lastPosition = lastPosition
        self.canRunMoviePlayer = False
        self.inMoviePlayer = False
        
        #  ret == 1 - no data in buffer
        #  ret == 0 - triggered by user
        if 1 == ret:
            if DMHelper.STS.DOWNLOADING == self.downloader.getStatus():
                self.lastSize = self.downloader.getLocalFileSize(True)
                printDBG("IPTVPlayerBufferingWidget.leaveMoviePlayer: movie player consume all data from buffer - still downloading")
                self.confirmExitCallBack() # continue
            else:
                printDBG("IPTVPlayerBufferingWidget.leaveMoviePlayer: movie player consume all data from buffer - downloading finished")
                if DMHelper.STS.DOWNLOADED != self.downloader.getStatus(): 
                    self.session.openWithCallback(self.close, MessageBox, text=_("Nastąpił błąd pobierania."), type = MessageBox.TYPE_ERROR, timeout=5)
                else:
                    self.close()
        elif 0 == ret or None == ret:
            # ask if we should close
            self.lastSize = self.downloader.getLocalFileSize(True)
            self.session.openWithCallback(self.confirmExitCallBack, MessageBox, text=_("Zakończyć odtwarzanie?"), type=MessageBox.TYPE_YESNO)

    def confirmExitCallBack(self, ret=None):
        if ret and ret == True:
            self.close()
        else:
            if not self._isInLiveMode():
                self.canRunMoviePlayer = True
                self.setMainTimerSts(True)
            else:
                # for live streams we will remove old buffer and start downloader once again
                self.onEnd()
                self.onStart()

    def back_pressed(self):
        self.close()
        return

    def ok_pressed(self):
        if self.canRunMoviePlayer and self.downloader.getLocalFileSize() > 0:
            self.runMovePlayer()

    def runMovePlayer(self):
        # this shoudl not happen but to make sure
        if not self.canRunMoviePlayer:
            printDBG('called runMovePlayer with canRunMoviePlayer set to False')
            return
        
        self.inMoviePlayer = True
        buffSize = self.downloader.getLocalFileSize() - self.lastSize 
        printDBG("Run MoviePlayer with buffer size [%s]" % formatBytes(float(buffSize)) )
        self.setMainTimerSts(False)
        
        exteplayerBlocked =  strwithmeta(self.url).meta.get('iptv_block_exteplayer', False)
        printDBG("runMovePlayer >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> exteplayerBlocked[%s]" % exteplayerBlocked)
        
        player = self.activMoviePlayer
        printDBG('IPTVPlayerBufferingWidget.runMovePlayer [%r]' % player)
        playerAdditionalParams = dict(self.playerAdditionalParams)
        playerAdditionalParams['downloader'] = self.downloader
        if strwithmeta(self.url).meta.get('iptv_proto', '') in ['f4m', 'uds', 'm3u8']:
            playerAdditionalParams['file-download-timeout'] = 90000 # 90s
        else:
            playerAdditionalParams['file-download-timeout'] = 10000 # 10s
        playerAdditionalParams['file-download-live'] = self._isInLiveMode()
        if "mini" == player:
            self.session.openWithCallback(self.leaveMoviePlayer, IPTVMiniMoviePlayer, self.filePath, self.movieTitle, self.lastPosition, 4)
        elif "exteplayer" == player:
            if not exteplayerBlocked: self.session.openWithCallback(self.leaveMoviePlayer, IPTVExtMoviePlayer, self.filePath, self.movieTitle, self.lastPosition, 'eplayer', playerAdditionalParams)
            else: self.session.openWithCallback(self.leaveMoviePlayer, IPTVExtMoviePlayer, self.filePath, self.movieTitle, self.lastPosition, 'gstplayer', playerAdditionalParams)
        elif "extgstplayer" == player: self.session.openWithCallback(self.leaveMoviePlayer, IPTVExtMoviePlayer, self.filePath, self.movieTitle, self.lastPosition, 'gstplayer', playerAdditionalParams)
        else: self.session.openWithCallback(self.leaveMoviePlayer, IPTVStandardMoviePlayer, self.filePath, self.movieTitle)
        playerAdditionalParams = None
        
    def setMainTimerSts(self, start):
        try:
            if start:
                if not self.mainTimerEnabled:
                    self.mainTimer.start(self.mainTimerInterval)
                    self.mainTimerEnabled = True
                    self.updateDisplay()
            else:
                if self.mainTimerEnabled:
                    self.mainTimer.stop()
                    self.mainTimerEnabled = False
        except: printDBG("setMainTimerSts status[%r] EXCEPTION" % start)
            
    def updateDisplay(self):
        printDBG("updateDisplay")
        if self.inMoviePlayer:
            printDBG("updateDisplay aborted - we are in moviePlayer")
            return

        if not self.mainTimerEnabled:
            printDBG("updateDisplay aborted - timer stoped")
            return

        self.downloader.updateStatistic()
        tmpBuffSize = self.downloader.getLocalFileSize() - self.lastSize + 1 # simple when getLocalFileSize() returns -1
        # remote size
        rFileSize = self.downloader.getRemoteFileSize()       
        if -1 == rFileSize: rFileSize = '??'
        else: rFileSize = formatBytes(float(rFileSize))
        # local size
        lFileSize = self.downloader.getLocalFileSize()
        if -1 == lFileSize: lFileSize = '??'
        else: lFileSize = formatBytes(float(lFileSize))
        # download speed
        dSpeed = self.downloader.getDownloadSpeed()
        if -1 == dSpeed: dSpeed = ''
        else: dSpeed = formatBytes(float(dSpeed))

        speed     = self.downloader.getDownloadSpeed()
        tmpStr    = ''
        if 0 < self.downloader.getLocalFileSize():
            if 0 <= self.downloader.getRemoteFileSize():
                tmpStr = "\n%s/%s" % (lFileSize, rFileSize)
            else:
                tmpStr = "\n%s" % (lFileSize)
            if 0 <= dSpeed:
               tmpStr += "\n%s/s" % (dSpeed)
        else:
            tmpStr += '\n\n'
        
        self["console"].setText(self.movieTitle + tmpStr)
        if tmpBuffSize > self.requestedBuffSize: percentage = 100
        else: percentage = (100 * tmpBuffSize) / self.requestedBuffSize
        self["percentage"].setText(str(percentage))
        self["icon"].nextFrame()
        
        # check if we start move player
        if self.canRunMoviePlayer:
            if tmpBuffSize >= self.requestedBuffSize or (self.downloader.getStatus() == DMHelper.STS.DOWNLOADED and 0 < self.downloader.getLocalFileSize()):
                self.runMovePlayer()
                return
        
        # check if it is downloading 
        if self.downloader.getStatus() not in [DMHelper.STS.DOWNLOADING, DMHelper.STS.WAITING]:
            self.session.openWithCallback(self.close, MessageBox, "Nastąpił błąd pobierania. \nStatus[%s], tmpBuffSize[%r], canRunMoviePlayer[%r]" % (self.downloader.getStatus(), tmpBuffSize, self.canRunMoviePlayer), type = MessageBox.TYPE_ERROR, timeout = 10 )
            self.canRunMoviePlayer = False
            # stop timer before message
            self.setMainTimerSts(False)

        return
    
    def __del__(self):
        printDBG('IPTVPlayerBufferingWidget.__del__ --------------------------------------')
        
    def __onClose(self):
        printDBG('IPTVPlayerBufferingWidget.__onClose ------------------------------------')
        self.onEnd()
        self.session.nav.playService(self.currentService)
        try:
            self.mainTimer_conn = None
            self.mainTimer = None
        except:   printExc()

        self.onClose.remove(self.__onClose)
        #self.onLayoutFinish.remove(self.doStart)
        self.onShow.remove(self.onWindowShow)
        #self.onHide.remove(self.onWindowHide)
        
    def _cleanedUp(self):
        if fileExists(self.filePath):
            try: os_remove(self.filePath)
            except: printDBG('Problem with removing old buffering file')
        if fileExists(self.GST_FLV_DEMUX_IS_DEMUXING_INFINITE_FILE):
            try: os_remove(self.GST_FLV_DEMUX_IS_DEMUXING_INFINITE_FILE)
            except: printDBG('Problem with removing gstreamer flag file [%s]' % self.GST_FLV_DEMUX_IS_DEMUXING_INFINITE_FILE)
    '''
    def doStart(self):
        if not self.onStartCalled:
            self.onStartCalled = True
            self.onStart()
    
    
    def onWindowHide(self): 
        self.visible = False
    '''

    def onWindowShow(self):
        if not self.onStartCalled:
            self.onStartCalled = True
            self.onStart()

#class IPTVPlayerWidget
Example #10
0
    def __init__(self,
                 session,
                 url,
                 pathForRecordings,
                 pictureTitle,
                 addParams={}):
        self.session = session
        Screen.__init__(self, session)
        self.onStartCalled = False

        self.recordingPath = pathForRecordings
        try:
            self.filePath = os.path.join(pathForRecordings,
                                         '.iptv_buffering.jpg')
        except Exception:
            self.filePath = ''
            printExc()

        self.addParams = {'seq_mode': False}
        self.addParams.update(addParams)

        self.url = url
        self.pictureTitle = pictureTitle
        self.audioUrl = strwithmeta(url).meta.get("iptv_audio_url", '')

        self["actions"] = ActionMap(
            [
                'IPTVAlternateVideoPlayer', 'MoviePlayerActions',
                'MediaPlayerActions', 'WizardActions', 'DirectionActions'
            ], {
                'leavePlayer': self.key_exit,
                'play': self.key_play,
                'pause': self.key_pause,
                'exit': self.key_exit,
                'back': self.key_exit,
                'ok': self.key_ok,
            }, -1)

        self["status"] = Label()
        self["console"] = Label()
        self["icon"] = SimpleAnimatedCover()
        self["picture"] = Cover()

        # prepare icon frames path
        frames = []
        for idx in range(1, self.NUM_OF_ICON_FRAMES + 1):
            frames.append(GetIconDir('/buffering/buffering_%d.png' % idx))
        self["icon"].loadFrames(frames)

        #main Timer
        self.mainTimer = eTimer()
        self.mainTimerEnabled = False

        if self.addParams['seq_mode']:
            self.canAutoClose = True
            self.mainTimer_conn = eConnectCallback(self.mainTimer.timeout,
                                                   self.closeAfterTimeout)
            self.mainTimerInterval = 1000 * 10  #10s
        else:
            self.mainTimer_conn = eConnectCallback(self.mainTimer.timeout,
                                                   self.updateDisplay)
            self.mainTimerInterval = 100  # by default 0,1s
        # download
        self.downloader = DownloaderCreator(self.url)

        self.onClose.append(self.__onClose)
        self.onShow.append(self.doStart)
        #self.onLayoutFinish.append(self.doStart)

        self.autoRefresh = False
        self.refreshPostfixes = ['_0', '_1']
        self.refreshCount = 0
        self.refreshing = False

        if len(self.audioUrl) and len(
                config.plugins.iptvplayer.gstplayerpath.value):
            self.audioPlayer = IPTVSimpleAudioPlayer()
        else:
            self.audioPlayer = None
Example #11
0
class IPTVPicturePlayerWidget(Screen):
    NUM_OF_ICON_FRAMES = 8
    #######################
    #       SIZES
    #######################
    # screen size
    # we do not want borders, so make the screen lager than a desktop
    sz_w = getDesktop(0).size().width()
    sz_h = getDesktop(0).size().height()
    # percentage
    s_w = 120
    s_h = 120
    # icon
    i_w = 128
    i_h = 128
    # console
    c_w = sz_w
    c_h = 80
    # picture
    p_w = sz_w - 20
    p_h = sz_h - 20
    #######################
    #     POSITIONS
    #######################
    start_y = (sz_h - (i_h + c_h)) / 2
    # percentage
    s_x = (sz_w - s_w) / 2
    s_y = start_y + (i_h - s_h) / 2
    # icon
    i_x = (sz_w - i_w) / 2
    i_y = start_y
    # console
    c_x = 0
    c_y = i_y + i_h
    # picture
    p_x = 10
    p_y = 10

    printDBG("[IPTVPicturePlayerWidget] desktop size %dx%d" % (sz_w, sz_h))
    skin = """
        <screen name="IPTVPicturePlayerWidget"  position="center,center" size="%d,%d" title="IPTV Picture Player...">
         <widget name="status"     size="%d,%d"   position="%d,%d"  zPosition="5" valign="center" halign="center"  font="Regular;21" backgroundColor="black" transparent="1" /> #foregroundColor="white" shadowColor="black" shadowOffset="-1,-1"
         <widget name="console"    size="%d,%d"   position="%d,%d"  zPosition="5" valign="center" halign="center"  font="Regular;21" backgroundColor="black" transparent="1" />
         <widget name="icon"       size="%d,%d"   position="%d,%d"  zPosition="4" transparent="1" alphatest="on" />
         <widget name="picture"    size="%d,%d"   position="%d,%d"  zPosition="6" transparent="1" alphatest="on" />
        </screen>""" % (
        sz_w,
        sz_h,  # screen
        s_w,
        s_h,
        s_x,
        s_y,  # status
        c_w,
        c_h,
        c_x,
        c_y,  # console
        i_w,
        i_h,
        i_x,
        i_y,  # icon
        p_w,
        p_h,
        p_x,
        p_y  # picture
    )

    def __init__(self,
                 session,
                 url,
                 pathForRecordings,
                 pictureTitle,
                 addParams={}):
        self.session = session
        Screen.__init__(self, session)
        self.onStartCalled = False

        self.recordingPath = pathForRecordings
        try:
            self.filePath = os.path.join(pathForRecordings,
                                         '.iptv_buffering.jpg')
        except Exception:
            self.filePath = ''
            printExc()

        self.addParams = {'seq_mode': False}
        self.addParams.update(addParams)

        self.url = url
        self.pictureTitle = pictureTitle
        self.audioUrl = strwithmeta(url).meta.get("iptv_audio_url", '')

        self["actions"] = ActionMap(
            [
                'IPTVAlternateVideoPlayer', 'MoviePlayerActions',
                'MediaPlayerActions', 'WizardActions', 'DirectionActions'
            ], {
                'leavePlayer': self.key_exit,
                'play': self.key_play,
                'pause': self.key_pause,
                'exit': self.key_exit,
                'back': self.key_exit,
                'ok': self.key_ok,
            }, -1)

        self["status"] = Label()
        self["console"] = Label()
        self["icon"] = SimpleAnimatedCover()
        self["picture"] = Cover()

        # prepare icon frames path
        frames = []
        for idx in range(1, self.NUM_OF_ICON_FRAMES + 1):
            frames.append(GetIconDir('/buffering/buffering_%d.png' % idx))
        self["icon"].loadFrames(frames)

        #main Timer
        self.mainTimer = eTimer()
        self.mainTimerEnabled = False

        if self.addParams['seq_mode']:
            self.canAutoClose = True
            self.mainTimer_conn = eConnectCallback(self.mainTimer.timeout,
                                                   self.closeAfterTimeout)
            self.mainTimerInterval = 1000 * 10  #10s
        else:
            self.mainTimer_conn = eConnectCallback(self.mainTimer.timeout,
                                                   self.updateDisplay)
            self.mainTimerInterval = 100  # by default 0,1s
        # download
        self.downloader = DownloaderCreator(self.url)

        self.onClose.append(self.__onClose)
        self.onShow.append(self.doStart)
        #self.onLayoutFinish.append(self.doStart)

        self.autoRefresh = False
        self.refreshPostfixes = ['_0', '_1']
        self.refreshCount = 0
        self.refreshing = False

        if len(self.audioUrl) and len(
                config.plugins.iptvplayer.gstplayerpath.value):
            self.audioPlayer = IPTVSimpleAudioPlayer()
        else:
            self.audioPlayer = None

    #end def __init__(self, session):

    def __del__(self):
        printDBG(
            'IPTVPicturePlayerWidget.__del__ --------------------------------------'
        )

    def __onClose(self):
        printDBG(
            'IPTVPicturePlayerWidget.__onClose ------------------------------------'
        )
        if None != self.audioPlayer: self.audioPlayer.close()
        self.onEnd()
        if None != self.mainTimer:
            try:
                self.mainTimer.stop()
            except Exception:
                pass
        self.mainTimer_conn = None
        self.mainTimer = None

        self.onClose.remove(self.__onClose)
        #self.onLayoutFinish.remove(self.doStart)

    def _getDownloadFilePath(self):
        return self.filePath + self.refreshPostfixes[self.refreshCount % len(
            self.refreshPostfixes)]

    def closeAfterTimeout(self):
        if self.canAutoClose:
            self.close()

    def onStart(self):
        '''
            this method is called once like __init__ but in __init__ we cannot display MessageBox
        '''
        self["picture"].hide()
        self["console"].setText(self.pictureTitle)
        self["status"].setText(_("--"))
        self._cleanedUp()

        if self.url.startswith('file://'):
            self.filePath = self.url[7:]
            self["status"].setText(_("++"))
            if -1 == self["picture"].decodeCover(self.filePath,
                                                 self.decodePictureEnd, ' '):
                self.decodePictureEnd()
        else:
            if self.downloader:
                self.downloader.isWorkingCorrectly(self._startDownloader)
            else:
                self.session.openWithCallback(
                    self.close,
                    MessageBox,
                    _("Downloading cannot be started.\n Invalid URI[%s].") %
                    self.url,
                    type=MessageBox.TYPE_ERROR,
                    timeout=10)

    def _doStart(self, force=False):
        if self.addParams['seq_mode']:
            self.mainTimer.start(self.mainTimerInterval, True)  #single shot
            return
        if self.autoRefresh or force:
            self.refreshing = True
            self.downloader = DownloaderCreator(self.url)

            url, downloaderParams = DMHelper.getDownloaderParamFromUrl(
                self.url)
            self.downloader.subscribeFor_Finish(self.downloaderEnd)
            self.downloader.start(url, self._getDownloadFilePath(),
                                  downloaderParams)
            self.setMainTimerSts(True)
        else:
            self.refreshing = False

    def _startDownloader(self, sts, reason):
        if sts: self._doStart(True)
        else:
            self.session.openWithCallback(
                self.close,
                MessageBox,
                _("Downloading cannot be started.\n Downloader [%s] not working properly.\n Status[%s]"
                  ) % (self.downloader.getName(), reason.strip()),
                type=MessageBox.TYPE_ERROR,
                timeout=10)

    def onEnd(self, withCleanUp=True):
        self.setMainTimerSts(False)
        if self.downloader:
            self.downloader.unsubscribeFor_Finish(self.downloaderEnd)
            downloader = self.downloader
            self.downloader = None
            downloader.terminate()
            downloader = None
        if withCleanUp:
            self._cleanedUp()

    def key_exit(self):
        self.close('key_exit')

    def key_play(self):
        if self.addParams['seq_mode']:
            self.canAutoClose = False
            return

        if not self.autoRefresh and not self.url.startswith('file://'):
            if None != self.audioPlayer: self.audioPlayer.start(self.audioUrl)
            self.autoRefresh = True
            if not self.refreshing: self._doStart()

    def key_pause(self):
        if self.addParams['seq_mode']:
            self.canAutoClose = False
            return
        if self.autoRefresh:
            if None != self.audioPlayer: self.audioPlayer.stop()
            self.autoRefresh = False

    def key_ok(self):
        if self.addParams['seq_mode']:
            self.canAutoClose = False
            return
        if self.autoRefresh: self.key_pause()
        else: self.key_play()

    def downloaderEnd(self, status):
        if None != self.downloader:
            self.onEnd(False)
            if DMHelper.STS.DOWNLOADED == status:
                self["status"].setText(_("++"))
                if -1 == self["picture"].decodeCover(
                        self._getDownloadFilePath(), self.decodePictureEnd,
                        ' '):
                    self.decodePictureEnd()
            else:
                if 0 == self.refreshCount:
                    self.session.openWithCallback(
                        self.close,
                        MessageBox,
                        (_("Downloading file [%s] problem.") % self.url) +
                        (" sts[%r]" % status),
                        type=MessageBox.TYPE_ERROR,
                        timeout=10)
                self._doStart()

    def decodePictureEnd(self, ret={}):
        printDBG('IPTVPicturePlayerWidget.decodePictureEnd')
        if None == ret.get('Pixmap', None):
            if 0 == self.refreshCount:
                self.session.openWithCallback(self.close,
                                              MessageBox,
                                              _("Decode file [%s] problem.") %
                                              self.filePath,
                                              type=MessageBox.TYPE_ERROR,
                                              timeout=10)
        else:
            self.refreshCount += 1
            self["status"].hide()
            self["console"].hide()
            self["icon"].hide()
            self["picture"].updatePixmap(ret.get('Pixmap', None),
                                         ret.get('FileName', self.filePath))
            self["picture"].show()
        self.setMainTimerSts(False)
        self._doStart()

    def setMainTimerSts(self, start):
        try:
            if start:
                if not self.mainTimerEnabled:
                    self.mainTimer.start(self.mainTimerInterval)
                    self.mainTimerEnabled = True
                    self.updateDisplay()
            else:
                if self.mainTimerEnabled:
                    self.mainTimer.stop()
                    self.mainTimerEnabled = False
        except Exception:
            printExc(
                "IPTVPicturePlayerWidget.setMainTimerSts status[%r] EXCEPTION"
                % start)

    def updateDisplay(self):
        printDBG("updateDisplay")
        if not self.mainTimerEnabled:
            printDBG("updateDisplay aborted - timer stopped")
            return
        self["icon"].nextFrame()
        return

    def _cleanedUp(self):
        for item in self.refreshPostfixes:
            filePath = self.filePath + item
            if fileExists(filePath):
                try:
                    os.remove(filePath)
                except Exception:
                    printDBG('Problem with removing old buffering file')

    def doStart(self):
        self.onShow.remove(self.doStart)
        if not self.onStartCalled:
            self.onStartCalled = True
            self.onStart()
Example #12
0
class IPTVPlayerBufferingWidget(Screen):
    NUM_OF_ICON_FRAMES = 8
    #######################
    #       SIZES
    #######################
    # screen size
    # we do not want borders, so make the screen lager than a desktop
    sz_w = 1980 
    sz_h = getDesktop(0).size().height()
    # icon
    i_w = 128
    i_h = 128
    # percentage
    p_w = 120
    p_h = 120
    # console
    c_w = sz_w
    c_h = 80
    # addinfo
    a_w = sz_w - 10
    a_h = 80
    #######################
    #     POSITIONS
    #######################  
    start_y = (sz_h - (i_h + c_h)) / 2 
    # icon
    i_x = (sz_w - i_w) / 2
    i_y = start_y
    # percentage
    p_x = (sz_w - p_w) / 2
    p_y = start_y + (i_h - p_h) / 2
    # console
    c_x = 0
    c_y = i_y + i_h
    # addinfo
    a_x = 10
    a_y = sz_h - 160
    printDBG("[IPTVPlayerBufferingWidget] desktop size %dx%d" % (sz_w, sz_h) )
    skin = """
        <screen name="IPTVPlayerBufferingWidget"  position="center,center" size="%d,%d" title="IPTV Player Buffering...">
         <widget name="percentage" size="%d,%d"   position="%d,%d"  zPosition="5" valign="center" halign="center"  font="Regular;21" backgroundColor="black" transparent="1" /> #foregroundColor="white" shadowColor="black" shadowOffset="-1,-1"
         <widget name="console"    size="%d,%d"   position="%d,%d"  zPosition="5" valign="center" halign="center"  font="Regular;21" backgroundColor="black" transparent="1" />
         <widget name="icon"       size="%d,%d"   position="%d,%d"  zPosition="4" transparent="1" alphatest="blend" />
         <widget name="addinfo"   size="%d,%d"   position="%d,%d"  zPosition="5" valign="center" halign="center"  font="Regular;21" backgroundColor="black" transparent="1" />
        </screen>""" %( sz_w, sz_h,         # screen
                        p_w, p_h, p_x, p_y, # percentage
                        c_w, c_h, c_x, c_y, # console
                        i_w, i_h, i_x, i_y, # icon
                        a_w, a_h, a_x, a_y  # addinfo
                      )
   
    def __init__(self, session, url, pathForRecordings, movieTitle, activMoviePlayer, requestedBuffSize, playerAdditionalParams={}):
        self.session = session
        Screen.__init__(self, session)
        self.onStartCalled = False
        
        self.recordingPath = pathForRecordings
        self.filePath      = pathForRecordings + '/.iptv_buffering.flv'
        self.url           = url
        self.movieTitle    = movieTitle
        
        self.currentService   = self.session.nav.getCurrentlyPlayingServiceReference()
        self.activMoviePlayer = activMoviePlayer
        
        self.onClose.append(self.__onClose)
        #self.onLayoutFinish.append(self.doStart)
        self.onShow.append(self.onWindowShow)
        #self.onHide.append(self.onWindowHide)
        
        self["actions"] = ActionMap(["WizardActions", "MoviePlayerActions"],
        {
            "ok":          self.ok_pressed,
            "back":        self.back_pressed,
            "leavePlayer": self.back_pressed,
        }, -1)     

        self["console"] = Label()
        self["percentage"] = Label()
        self["addinfo"] = Label()
        
        self["icon"] = SimpleAnimatedCover()
        # prepare icon frames path
        frames = []
        for idx in range(1,self.NUM_OF_ICON_FRAMES+1): frames.append( resolveFilename(SCOPE_PLUGINS, 'Extensions/IPTVPlayer/icons/buffering/buffering_%d.png' % idx) )
        self["icon"].loadFrames(frames) 
        
        self.inMoviePlayer = False
        self.canRunMoviePlayer = False # used in function updateDisplay, so must be first initialized
        #main Timer
        self.mainTimer = eTimer()
        self.mainTimerEnabled = False
        self.mainTimer_conn = eConnectCallback(self.mainTimer.timeout, self.updateDisplay)
        self.mainTimerInterval = 1000 # by default 1s
        
        self.requestedBuffSize = requestedBuffSize
        self.playerAdditionalParams = playerAdditionalParams
        
        self.clipLength = None
        self.lastPosition = None
        self.lastSize = 0
        
        # Some MP4 files are not prepared for streaming
        # MOOV atom is needed to start playback
        # if it is located at the end of file, then 
        # will try to download it separately to start playback
        # without downloading the whole file
        self.clouldBeMP4 = False
        self.isMOOVAtomAtTheBeginning = None
        self.checkMOOVAtom = True
        self.maxMOOVAtomSize = 10 * 1024 * 1024 # 10 MB max moov atom size
        self.moovAtomOffset = 0
        self.moovAtomSize = 0
        
        self.MOOV_STS = enum( UNKNOWN     = 0,
                              WAITING     = 1,
                              DOWNLOADING = 2,
                              DOWNLOADED  = 3,
                              ERROR       = 4)
        self.moovAtomStatus = self.MOOV_STS.UNKNOWN
        self.moovAtomDownloader = None
        self.moovAtomPath  = pathForRecordings + '/.iptv_buffering_moov.flv'
        
        printDBG(">> activMoviePlayer[%s]" % self.activMoviePlayer)
        
    #end def __init__(self, session):
 
    def onStart(self):
        '''
            this method is called once like __init__ but in __init__ we cannot display MessageBox
        '''
        # create downloader
        self.downloader = DownloaderCreator(self.url)
        self._cleanedUp()
        if self.downloader:
            self.downloader.isWorkingCorrectly(self._startDownloader)
        else:
            self.session.openWithCallback(self.iptvDoClose, MessageBox, _("Downloading can not be started.\n The address ('%r') is incorrect.") % self.url, type = MessageBox.TYPE_ERROR, timeout = 10)
        
    def _startDownloader(self, sts, reason):
        if sts:
            url,downloaderParams = DMHelper.getDownloaderParamFromUrl(self.url)
            if url.split('?', 1)[0].lower().endswith('.mp4'):
                self.clouldBeMP4 = True
            self.downloader.start(url, self.filePath, downloaderParams)
            self.setMainTimerSts(True)
            self.canRunMoviePlayer = True
        else:
            self.session.openWithCallback(self.iptvDoClose, MessageBox, _("Downloading can not be started.\n Downloader %s does not work properly.\nStatus[%s]") % (self.downloader.getName(), reason.strip()), type = MessageBox.TYPE_ERROR, timeout = 10 )

    def _isInLiveMode(self):
        if isinstance(self.url, strwithmeta):
            if 'iptv_livestream' in self.url.meta:
                return self.url.meta['iptv_livestream']
        # if we do not have information if it is live try to figure out from other sources
        if self.downloader:
            tmp = self.downloader.isLiveStream()
            if None != tmp:
                return tmp
        if self.url.startswith('rtmp'):
            return True
        
    def onEnd(self):
        self.setMainTimerSts(False)
        if self.downloader:
            self.downloader.terminate()
            self.downloader = None
        
        if self.downloader:
            self.moovAtomDownloader.terminate()
            self.downloader = None
        self._cleanedUp()

    def leaveMoviePlayer(self, ret=None, lastPosition=None, clipLength=None, *args, **kwargs):
        printDBG("leaveMoviePlayer ret[%r], lastPosition[%r]" % (ret, lastPosition))
        # There is need to set None for current service
        # otherwise there is a problem with resuming play
        self.session.nav.playService(None)
        self.lastPosition = lastPosition
        self.clipLength = clipLength
        self.canRunMoviePlayer = False
        self.inMoviePlayer = False
        
        #  ret == 1 - no data in buffer
        #  ret == 0 - triggered by user
        if 1 == ret:
            if DMHelper.STS.DOWNLOADING == self.downloader.getStatus():
                self.lastSize = self.downloader.getLocalFileSize(True)
                printDBG("IPTVPlayerBufferingWidget.leaveMoviePlayer: movie player consume all data from buffer - still downloading")
                self.confirmExitCallBack() # continue
            else:
                printDBG("IPTVPlayerBufferingWidget.leaveMoviePlayer: movie player consume all data from buffer - downloading finished")
                if DMHelper.STS.DOWNLOADED != self.downloader.getStatus(): 
                    self.session.openWithCallback(self.iptvDoClose, MessageBox, text=_("Error occurs during download."), type = MessageBox.TYPE_ERROR, timeout=5)
                else:
                    self.iptvDoClose()
        elif 0 == ret or None == ret:
            # ask if we should close
            self.lastSize = self.downloader.getLocalFileSize(True)
            self.session.openWithCallback(self.confirmExitCallBack, MessageBox, text=_("Stop playing?"), type=MessageBox.TYPE_YESNO)

    def confirmExitCallBack(self, ret=None):
        if ret and ret == True:
            self.iptvDoClose()
        else:
            if not self._isInLiveMode():
                self.canRunMoviePlayer = True
                self.setMainTimerSts(True)
            else:
                # for live streams we will remove old buffer and start downloader once again
                self.lastSize = 0
                self.onEnd()
                self.onStart()

    def back_pressed(self):
        self.iptvDoClose()
        return
        
    def iptvDoClose(self, *args, **kwargs):
        self.onEnd()
        self.close(None, self.lastPosition, self.clipLength)
    
    def ok_pressed(self):
        if self.canRunMoviePlayer and self.downloader.getPlayableFileSize() > 0:
            self.runMovePlayer()

    def runMovePlayer(self):
        # this shoudl not happen but to make sure
        if not self.canRunMoviePlayer:
            printDBG('called runMovePlayer with canRunMoviePlayer set to False')
            return
        
        self.inMoviePlayer = True
        buffSize = self.downloader.getLocalFileSize() - self.lastSize 
        printDBG("Run MoviePlayer with buffer size [%s]" % formatBytes(float(buffSize)) )
        self.setMainTimerSts(False)
        
        player = self.activMoviePlayer
        printDBG('IPTVPlayerBufferingWidget.runMovePlayer [%r]' % player)
        playerAdditionalParams = dict(self.playerAdditionalParams)
        playerAdditionalParams['downloader'] = self.downloader
        if self.isMOOVAtomAtTheBeginning:
            playerAdditionalParams['moov_atom_info'] = {'offset':0, 'size':self.moovAtomOffset + self.moovAtomSize, 'file':''}
        elif self.moovAtomStatus == self.MOOV_STS.DOWNLOADED and \
             DMHelper.STS.DOWNLOADED != self.downloader.getStatus(): 
            playerAdditionalParams['moov_atom_info'] = {'offset':self.moovAtomOffset, 'size': self.moovAtomSize, 'file':self.moovAtomPath}
        
        if strwithmeta(self.url).meta.get('iptv_proto', '') in ['f4m', 'uds', 'm3u8']:
            playerAdditionalParams['file-download-timeout'] = 90000 # 90s
        else:
            playerAdditionalParams['file-download-timeout'] = 10000 # 10s
        playerAdditionalParams['file-download-live'] = self._isInLiveMode()
        if "mini" == player: self.session.openWithCallback(self.leaveMoviePlayer, IPTVMiniMoviePlayer, self.filePath, self.movieTitle, self.lastPosition, 4)
        elif "exteplayer" == player: self.session.openWithCallback(self.leaveMoviePlayer, IPTVExtMoviePlayer, self.filePath, self.movieTitle, self.lastPosition, 'eplayer', playerAdditionalParams)
        elif "extgstplayer" == player: self.session.openWithCallback(self.leaveMoviePlayer, IPTVExtMoviePlayer, self.filePath, self.movieTitle, self.lastPosition, 'gstplayer', playerAdditionalParams)
        else: self.session.openWithCallback(self.leaveMoviePlayer, IPTVStandardMoviePlayer, self.filePath, self.movieTitle)
        playerAdditionalParams = None
        
    def setMainTimerSts(self, start):
        try:
            if start:
                if not self.mainTimerEnabled:
                    self.mainTimer.start(self.mainTimerInterval)
                    self.mainTimerEnabled = True
                    self.updateDisplay()
            else:
                if self.mainTimerEnabled:
                    self.mainTimer.stop()
                    self.mainTimerEnabled = False
        except Exception: printDBG("setMainTimerSts status[%r] EXCEPTION" % start)
    
    def updateDisplay(self):
        printDBG("updateDisplay")
        if self.inMoviePlayer:
            printDBG("updateDisplay aborted - we are in moviePlayer")
            return

        if not self.mainTimerEnabled:
            printDBG("updateDisplay aborted - timer stoped")
            return

        self.downloader.updateStatistic()
        localSize  = self.downloader.getLocalFileSize()
        remoteSize = self.downloader.getRemoteFileSize()
        
        if self.checkMOOVAtom and \
           localSize > 10240:
            self.checkMOOVAtom = False
            
            if remoteSize > self.maxMOOVAtomSize and \
               self.downloader.getName() == "wget" and \
               (self.clouldBeMP4 or (None != self.downloader.getMimeType() and \
               'mp4' in self.downloader.getMimeType())):
                # check moov atom position
                # if it is located at the begining of MP4 file
                # it should be just after ftyp atom
                try:
                    f = open(self.filePath, "rb")
                    currOffset = 0
                    while currOffset < localSize:
                        rawSize =  ReadUint32(f.read(4), False)
                        rawType = f.read(4)
                        printDBG(">> rawType [%s]" % rawType)
                        printDBG(">> rawSize [%d]" % rawSize)
                        if currOffset == 0 and rawType != "ftyp":
                            # this does not looks like MP4 file
                            break
                        else:
                            if rawType == "moov":
                                self.moovAtomOffset = currOffset
                                self.moovAtomSize = rawSize
                                self.isMOOVAtomAtTheBeginning = True
                                break
                            elif rawType == "mdat":
                                # we are not sure if after mdat will be moov atom but 
                                # if this will be max last 10MB of file then 
                                # we will download it
                                self.moovAtomOffset = currOffset + rawSize
                                self.moovAtomSize = remoteSize - self.moovAtomOffset
                                self.isMOOVAtomAtTheBeginning = False
                                break
                            currOffset += rawSize
                        f.seek(currOffset, 0)
                    printDBG(">> moovAtomOffset[%d]" % self.moovAtomOffset)
                    printDBG(">> moovAtomSize[%d]" % self.moovAtomSize)
                except Exception:
                    printExc()
        
        if None != self.downloader and self.downloader.hasDurationInfo() \
           and self.downloader.getTotalFileDuration() > 0:
            totalDuration = self.downloader.getTotalFileDuration()
            downloadDuration = self.downloader.getDownloadedFileDuration()
            rFileSize = str(timedelta(seconds=totalDuration))
            lFileSize = str(timedelta(seconds=downloadDuration))
            if rFileSize.startswith('0:'):
                rFileSize = rFileSize[2:]
            if lFileSize.startswith('0:'):
                lFileSize = lFileSize[2:]
        else:
            # remote size
            if -1 == remoteSize: rFileSize = '??'
            else: rFileSize = formatBytes(float(remoteSize))
            # local size
            if -1 == localSize: lFileSize = '??'
            else: lFileSize = formatBytes(float(localSize))
        
        
        # download speed
        dSpeed = self.downloader.getDownloadSpeed()
        if dSpeed > -1 and localSize > 0:
            dSpeed = formatBytes(float(dSpeed))
        else:
            dSpeed = ''
        
        speed     = self.downloader.getDownloadSpeed()
        tmpStr    = ''
        if '??' != lFileSize:
            if '??' != rFileSize:
                tmpStr = "\n%s/%s" % (lFileSize, rFileSize)
            else:
                tmpStr = "\n%s" % (lFileSize)
            if '' != dSpeed:
               tmpStr += "\n%s/s" % (dSpeed)
        else:
            tmpStr += '\n\n'
        
        self["console"].setText(self.movieTitle + tmpStr)
        
        handled = False
        percentage = 0
        requestedBuffSize = -1
        tmpBuffSize = 0
        if self.isMOOVAtomAtTheBeginning == True:
            moovAtomDataSize = self.moovAtomOffset + self.moovAtomSize
            if moovAtomDataSize > localSize:
                if self.moovAtomStatus != self.MOOV_STS.DOWNLOADING:
                    self["addinfo"].setText(_("Please wait for initialization data."))
                    self.moovAtomStatus = self.MOOV_STS.DOWNLOADING
                remoteSize = self.moovAtomOffset + self.moovAtomSize
                if localSize > remoteSize: percentage = 100
                else: percentage = (100 * localSize) / remoteSize
            else:
                requestedBuffSize = self.requestedBuffSize
                if self.lastSize > moovAtomDataSize: tmpBuffSize = localSize - self.lastSize
                else: tmpBuffSize = localSize - moovAtomDataSize
                if tmpBuffSize > requestedBuffSize: percentage = 100
                else: percentage = (100 * tmpBuffSize) / requestedBuffSize
                if self.moovAtomStatus != self.MOOV_STS.DOWNLOADED:
                    self["addinfo"].setText("")
                    self.moovAtomStatus = self.MOOV_STS.DOWNLOADED
            handled = True
        elif self.isMOOVAtomAtTheBeginning == False and self.moovAtomStatus not in [self.MOOV_STS.WAITING, self.MOOV_STS.ERROR, self.MOOV_STS.DOWNLOADED]:
            # At now only exteplayer3 is able to use moov atom in separate file
            if self.activMoviePlayer == 'exteplayer' and self.moovAtomStatus == self.MOOV_STS.UNKNOWN:
                url, downloaderParams = DMHelper.getDownloaderParamFromUrl(self.url)
                downloaderParams['start_pos'] = self.moovAtomOffset
                self.moovAtomDownloader = DownloaderCreator(self.url)
                self.moovAtomDownloader.start(url, self.moovAtomPath, downloaderParams)
                self.moovAtomStatus = self.MOOV_STS.DOWNLOADING
                self["addinfo"].setText(_("Please wait - downloading initialization data."))
            elif self.moovAtomStatus == self.MOOV_STS.DOWNLOADING:
                self.moovAtomDownloader.updateStatistic()
                status = self.moovAtomDownloader.getStatus()
                moovLocalSize  = self.moovAtomDownloader.getLocalFileSize()
                moovRemoteSize = self.moovAtomDownloader.getRemoteFileSize()
                if status == DMHelper.STS.DOWNLOADING:
                    if moovLocalSize > 0 and self.moovAtomSize > 0:
                        if moovLocalSize > self.moovAtomSize: percentage = 100
                        else: percentage = (100 * moovLocalSize) / self.moovAtomSize
                elif status == DMHelper.STS.DOWNLOADED or (status == DMHelper.STS.INTERRUPTED and moovLocalSize == self.moovAtomSize):
                    self.moovAtomStatus = self.MOOV_STS.DOWNLOADED
                    self["addinfo"].setText("")
                else:
                    self.moovAtomStatus = self.MOOV_STS.ERROR
            
            handled = True
            if self.moovAtomStatus in [self.MOOV_STS.UNKNOWN, self.MOOV_STS.ERROR]:
                printDBG(">> [%s] [%s]" % (self.activMoviePlayer, self.moovAtomStatus))
                msg = [_("Whole file must be downloaded to start playback!")]
                if self.moovAtomStatus == self.MOOV_STS.UNKNOWN and self.activMoviePlayer != 'exteplayer':
                    msg.append(_("You can use external eplayer to start playback faster."))
                self["addinfo"].setText('\n'.join(msg))
                self.moovAtomStatus = self.MOOV_STS.WAITING
                handled = False
        
        if not handled and self.moovAtomStatus != self.MOOV_STS.WAITING:
            tmpBuffSize = localSize - self.lastSize + 1 # simple when getLocalFileSize() returns -1
            if self.downloader.getPlayableFileSize() > 0:
                requestedBuffSize = self.requestedBuffSize
                if tmpBuffSize > requestedBuffSize: percentage = 100
                else: percentage = (100 * tmpBuffSize) / requestedBuffSize
                handled = True
        
        if not handled and localSize > 0 and remoteSize > 0:
            if localSize > remoteSize: percentage = 100
            else: percentage = (100 * localSize) / remoteSize
        
        self["percentage"].setText(str(percentage))
        self["icon"].nextFrame()
        
        # check if we start movie player
        if self.canRunMoviePlayer:
            if (requestedBuffSize > -1 and tmpBuffSize >= requestedBuffSize) or \
               (self.downloader.getStatus() == DMHelper.STS.DOWNLOADED and 0 < localSize):
                self.runMovePlayer()
                return
        
        # check if it is downloading 
        if self.downloader.getStatus() not in [DMHelper.STS.POSTPROCESSING, DMHelper.STS.DOWNLOADING, DMHelper.STS.WAITING]:
            self.session.openWithCallback(self.iptvDoClose, MessageBox, _("Error occurs during download. \nStatus[%s], tmpBuffSize[%r], canRunMoviePlayer[%r]") % (self.downloader.getStatus(), tmpBuffSize, self.canRunMoviePlayer), type = MessageBox.TYPE_ERROR, timeout = 10 )
            self.canRunMoviePlayer = False
            # stop timer before message
            self.setMainTimerSts(False)

        return
    
    def __del__(self):
        printDBG('IPTVPlayerBufferingWidget.__del__ --------------------------------------')
        
    def __onClose(self):
        printDBG('IPTVPlayerBufferingWidget.__onClose ------------------------------------')
        self.onEnd()
        self.session.nav.playService(self.currentService)
        try:
            self.mainTimer_conn = None
            self.mainTimer = None
        except Exception:   printExc()

        self.onClose.remove(self.__onClose)
        #self.onLayoutFinish.remove(self.doStart)
        self.onShow.remove(self.onWindowShow)
        #self.onHide.remove(self.onWindowHide)
        
    def _cleanedUp(self):
        if fileExists(self.filePath):
            try: os_remove(self.filePath)
            except Exception: printDBG('Problem with removing old buffering file (%s)' % self.filePath)
        
        if fileExists(self.moovAtomPath):
            try: os_remove(self.moovAtomPath)
            except Exception: printDBG('Problem with removing old buffering file (%s)' % self.moovAtomPath)
    '''
    def doStart(self):
        if not self.onStartCalled:
            self.onStartCalled = True
            self.onStart()
    
    
    def onWindowHide(self): 
        self.visible = False
    '''

    def onWindowShow(self):
        if not self.onStartCalled:
            self.onStartCalled = True
            self.onStart()

#class IPTVPlayerWidget
class IPTVSubSimpleDownloaderWidget(Screen):
    _TMP_FILE_NAME = '.externaltmpsub'
    sz_w = getDesktop(0).size().width() - 190
    sz_h = getDesktop(0).size().height() - 195
    if sz_h < 500: sz_h += 4
    skin = """
        <screen name="IPTVSubSimpleDownloaderWidget" position="center,center" title="%s" size="%d,%d">
         <widget name="icon_red"    position="5,9"   zPosition="4" size="30,30" transparent="1" alphatest="on" />
         <widget name="icon_green"  position="355,9" zPosition="4" size="30,30" transparent="1" alphatest="on" />
         
         <widget name="label_red"     position="45,9"  size="175,27" zPosition="5" valign="center" halign="left" backgroundColor="black" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
         <widget name="label_green"   position="395,9" size="175,27" zPosition="5" valign="center" halign="left" backgroundColor="black" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
         
         <widget name="list"  position="5,80"  zPosition="2" size="%d,%d" scrollbarMode="showOnDemand" transparent="1"  backgroundColor="#00000000" enableWrapAround="1" />
         <widget name="title" position="5,47"  zPosition="1" size="%d,23" font="Regular;20"            transparent="1"  backgroundColor="#00000000"/>
         
         <widget name="console"      position="10,%d"   zPosition="2" size="%d,160" valign="center" halign="center"   font="Regular;24" transparent="0" foregroundColor="white" backgroundColor="black"/>
        </screen>""" % (
        _("Simple subtitles downloader"),
        sz_w,
        sz_h,  # size
        sz_w - 10,
        sz_h - 105,  # size list
        sz_w - 135,  # size title
        (sz_h - 160) / 2,
        sz_w - 20,  # console
    )

    def __init__(self, session, params={}):
        # params: movie_title, sub_list: [{'title':'', 'lang':'', 'url':''}]
        self.session = session
        Screen.__init__(self, session)

        self.params = params

        self.onShown.append(self.onStart)
        self.onClose.append(self.__onClose)

        self["title"] = Label(" ")
        self["console"] = Label(" ")

        self["label_red"] = Label(_("Cancel"))
        self["label_yellow"] = Label(_("Move group"))
        self["label_green"] = Label(_("Apply"))

        self["icon_red"] = Cover3()
        self["icon_green"] = Cover3()

        self["list"] = IPTVMainNavigatorList()
        self["list"].connectSelChanged(self.onSelectionChanged)

        self["actions"] = ActionMap(
            [
                "ColorActions", "SetupActions", "WizardActions",
                "ListboxActions"
            ], {
                "cancel": self.keyExit,
                "ok": self.keyOK,
                "red": self.keyRed,
                "green": self.keyGreen,
            }, -2)

        self.iconPixmap = {}
        for icon in ['red', 'green']:
            self.iconPixmap[icon] = LoadPixmap(GetIconDir(icon + '.png'))

        self.movieTitle = ''
        self.stackList = []
        self.stackItems = []

        self.defaultLanguage = GetDefaultLang()

        self.listMode = False
        self.downloadedSubFilePath = ""
        self.currItem = {}
        self.downloader = None
        self.cleanDownloader()
        self.workconsole = None

    def __onClose(self):
        self["list"].disconnectSelChanged(self.onSelectionChanged)
        if None != self.workconsole:
            self.workconsole.kill()
        self.workconsole = None
        self.cleanDownloader()

    def cleanDownloader(self):
        self.downloadedSubFilePath = ""
        self.currItem = {}
        if self.downloader != None:
            self.downloader.unsubscribeFor_Finish(self.downloadFinished)
            self.downloader.terminate()
        self.downloader = None

    def startDownload(self, item):
        self.setListMode(False)
        self.cleanDownloader()
        self.currItem = item
        self["console"].setText(
            _("Downloading subtitles.\n ('%r').") %
            self.currItem.get('url', ''))
        # create downloader
        self.downloader = DownloaderCreator(self.currItem.get('url', ''))
        if self.downloader:
            self.downloader.isWorkingCorrectly(self._startDownloader)
        else:
            self["console"].setText(
                _("Download can not be started.\n Incorrect address ('%r')."))

    def _startDownloader(self, sts, reason):
        if sts:
            self.downloader.subscribeFor_Finish(self.downloadFinished)
            url, downloaderParams = DMHelper.getDownloaderParamFromUrl(
                self.currItem.get('url', ''))
            self.downloader.start(url, GetTmpDir(self._TMP_FILE_NAME),
                                  downloaderParams)
        else:
            self["console"].setText(
                _("Download can not be started.\nDownloader %s not working correctly.\nStatus[%s]"
                  ))

    def downloadFinished(self, status):
        if status != DMHelper.STS.DOWNLOADED:
            self["console"].setText(_("Download failed.\nStatus[%s]") % status)
        else:
            self["console"].setText(
                _('Subtitles downloaded successfully. [%s], conversion to UTF-8.'
                  ) % self.downloader.getFullFileName())
            cmd = '%s "%s"' % (config.plugins.iptvplayer.uchardetpath.value,
                               self.downloader.getFullFileName())
            printDBG("cmd[%s]" % cmd)
            self.workconsole = iptv_system(cmd, self.convertSubtitles)

    def convertSubtitles(self, code=127, encoding=""):
        encoding = MapUcharEncoding(encoding)
        if 0 != code or 'unknown' in encoding:
            encoding = 'utf-8'
        else:
            encoding = encoding.strip()
        try:
            with codecs.open(self.downloader.getFullFileName(), 'r', encoding,
                             'replace') as fp:
                subText = fp.read().encode('utf-8').strip()

            ext = self.currItem.get('format', '')
            if ext == '':
                ext = self.currItem.get('url',
                                        '').split('?')[-1].split('.')[-1]
            filePath = '{0}_{1}_{2}'.format(self.params['movie_title'],
                                            self.currItem.get('title', ''),
                                            self.currItem.get('lang', ''))
            filePath = RemoveDisallowedFilenameChars(filePath)
            filePath += '.' + ext

            with open(GetSubtitlesDir(filePath), 'w') as fp:
                fp.write(subText)

            self.downloadedSubFilePath = GetSubtitlesDir(filePath)
            self.showButtons(['green'])
            tmpList = self.params.get('sub_list', [])
            if len(tmpList) == 1:
                self.acceptSub()
        except Exception:
            printExc()
            self["console"].setText(_('Subtitles conversion to UTF-8 failed.'))

    def loadIcons(self):
        try:
            for icon in self.iconPixmap:
                self['icon_' + icon].setPixmap(self.iconPixmap[icon])
        except Exception:
            printExc()

    def hideButtons(self, buttons=['red', 'green']):
        try:
            for button in buttons:
                self['icon_' + button].hide()
                self['label_' + button].hide()
        except Exception:
            printExc()

    def showButtons(self, buttons=['red', 'green']):
        try:
            for button in buttons:
                self['icon_' + button].show()
                self['label_' + button].show()
        except Exception:
            printExc()

    def onStart(self):
        self.onShown.remove(self.onStart)
        self.setTitle(
            _("Subtitles for: %s") % self.params.get('movie_title', ''))
        self.loadIcons()
        tmpList = self.params.get('sub_list', [])
        if len(tmpList) > 1:
            self.displayList()
        else:
            self.startDownload(tmpList[0])

    def setListMode(self, sts=False):
        if False == sts:
            self['list'].hide()
            self["title"].hide()
            self.hideButtons()
            self.showButtons(['red'])
            self["console"].show()
            self["console"].setText(" ")
        else:
            self.hideButtons(['green'])
            self["console"].hide()
            self["console"].setText(" ")

        self.listMode = sts

    def displayList(self):
        list = []
        self["title"].setText(_("Select subtitles to download"))
        self["title"].show()

        tmpList = self.params.get('sub_list', [])
        try:
            for item in tmpList:
                printDBG(item)
                dItem = CDisplayListItem(name=item['title'],
                                         type=CDisplayListItem.TYPE_ARTICLE)
                dItem.privateData = item
                list.append((dItem, ))
        except Exception:
            printExc()
        self["list"].setList(list)
        self["list"].show()
        self.setListMode(True)

    def onSelectionChanged(self):
        pass

    def keyExit(self):
        if False == self.listMode:
            if self.downloader != None and self.downloader.isDownloading():
                self.downloader.terminate()
            else:
                tmpList = self.params.get('sub_list', [])
                if len(tmpList) > 1:
                    self.displayList()
                else:
                    self.close(None)
        else:
            self.close(None)

    def keyOK(self):
        if False == self.listMode: return
        idx, item = self.getSelectedItem()
        if None != item:
            self.startDownload(item.privateData)

    def keyRed(self):
        self.close(None)

    def keyGreen(self):
        self.acceptSub()

    def acceptSub(self):
        try:
            if self["icon_green"].visible:
                track = {
                    'title': self.currItem.get('lang', _('default')),
                    'lang': self.currItem.get('lang', _('default')),
                    'path': self.downloadedSubFilePath
                }
                track['id'] = self.currItem.get('url', '')
                self.close(track)
        except Exception:
            printExc()

    def getSelectedItem(self):
        try:
            idx = self["list"].getCurrentIndex()
        except Exception:
            idx = 0
        sel = None
        try:
            if self["list"].visible:
                sel = self["list"].l.getCurrentSelection()[0]
                if None != sel:
                    return idx, sel
        except Exception:
            printExc()
            sel = None
        return -1, None
class IPTVPicturePlayerWidget(Screen):
    NUM_OF_ICON_FRAMES = 8
    #######################
    #       SIZES
    #######################
    # screen size
    # we do not want borders, so make the screen lager than a desktop
    sz_w = getDesktop(0).size().width() 
    sz_h = getDesktop(0).size().height()
    # percentage
    s_w = 120
    s_h = 120
    # icon
    i_w = 128
    i_h = 128
    # console
    c_w = sz_w
    c_h = 80
    # picture 
    p_w = sz_w-20
    p_h = sz_h-20
    #######################
    #     POSITIONS
    #######################  
    start_y = (sz_h - (i_h + c_h)) / 2 
    # percentage
    s_x = (sz_w - s_w) / 2
    s_y = start_y + (i_h - s_h) / 2
    # icon
    i_x = (sz_w - i_w) / 2
    i_y = start_y
    # console
    c_x = 0
    c_y = i_y + i_h
    # picture 
    p_x = 10
    p_y = 10
    
    printDBG("[IPTVPicturePlayerWidget] desktop size %dx%d" % (sz_w, sz_h) )
    skin = """
        <screen name="IPTVPicturePlayerWidget"  position="center,center" size="%d,%d" title="IPTV Picture Player...">
         <widget name="status"     size="%d,%d"   position="%d,%d"  zPosition="5" valign="center" halign="center"  font="Regular;21" backgroundColor="black" transparent="1" /> #foregroundColor="white" shadowColor="black" shadowOffset="-1,-1"
         <widget name="console"    size="%d,%d"   position="%d,%d"  zPosition="5" valign="center" halign="center"  font="Regular;21" backgroundColor="black" transparent="1" />
         <widget name="icon"       size="%d,%d"   position="%d,%d"  zPosition="4" transparent="1" alphatest="on" />
         <widget name="picture"    size="%d,%d"   position="%d,%d"  zPosition="6" transparent="1" alphatest="on" />
        </screen>""" %( sz_w, sz_h,         # screen
                        s_w, s_h, s_x, s_y, # status
                        c_w, c_h, c_x, c_y, # console
                        i_w, i_h, i_x, i_y, # icon
                        p_w, p_h, p_x, p_y  # picture
                      )
   
    def __init__(self, session, url, pathForRecordings, pictureTitle):
        self.session = session
        Screen.__init__(self, session)
        self.onStartCalled = False
        
        self.recordingPath = pathForRecordings
        try:
            self.filePath = os.path.join(pathForRecordings, '.iptv_buffering.jpg')
        except:
            self.filePath = ''
            printExc()
            
        self.url           = url
        self.pictureTitle  = pictureTitle
        self.audioUrl      = strwithmeta(url).meta.get("iptv_audio_url", '')
       
        self["actions"] = ActionMap(['IPTVAlternateVideoPlayer', 'MoviePlayerActions', 'MediaPlayerActions', 'WizardActions', 'DirectionActions'],
        {
            'leavePlayer'  : self.key_exit,
            'play'         : self.key_play,
            'pause'        : self.key_pause,
            'exit'         : self.key_exit,
            'back'         : self.key_exit,
            'ok'           : self.key_ok,
        }, -1)     

        self["status"]  = Label()
        self["console"] = Label()
        self["icon"]    = SimpleAnimatedCover()
        self["picture"] = Cover()

        # prepare icon frames path
        frames = []
        for idx in range(1,self.NUM_OF_ICON_FRAMES+1): frames.append( GetIconDir('/buffering/buffering_%d.png' % idx) )
        self["icon"].loadFrames(frames) 
        
        #main Timer
        self.mainTimer = eTimer()
        self.mainTimerEnabled = False
        self.mainTimer_conn = eConnectCallback(self.mainTimer.timeout, self.updateDisplay)
        self.mainTimerInterval = 100 # by default 0,1s
        # download
        self.downloader = DownloaderCreator(self.url)
        
        self.onClose.append(self.__onClose)
        self.onLayoutFinish.append(self.doStart)
        
        self.autoRefresh = False
        self.refreshPostfixes = ['_0', '_1']
        self.refreshCount = 0
        self.refreshing = False
        
        if len(self.audioUrl) and len(config.plugins.iptvplayer.gstplayerpath.value):
            self.audioPlayer = IPTVSimpleAudioPlayer()
        else: self.audioPlayer  = None
       
    #end def __init__(self, session):
    
    def __del__(self):
        printDBG('IPTVPicturePlayerWidget.__del__ --------------------------------------')
        
    def __onClose(self):
        printDBG('IPTVPicturePlayerWidget.__onClose ------------------------------------')
        if None != self.audioPlayer: self.audioPlayer.close()
        self.onEnd()
        self.mainTimer_conn = None
        self.mainTimer = None
        
        self.onClose.remove(self.__onClose)
        self.onLayoutFinish.remove(self.doStart)
        
    def _getDownloadFilePath(self):
        return self.filePath + self.refreshPostfixes[self.refreshCount % len(self.refreshPostfixes) ]
 
    def onStart(self):
        '''
            this method is called once like __init__ but in __init__ we cannot display MessageBox
        '''
        self["picture"].hide()
        self["console"].setText(self.pictureTitle)
        self["status"].setText(_("--"))
        self._cleanedUp()
        if self.downloader:
            self.downloader.isWorkingCorrectly(self._startDownloader)
        else:
            self.session.openWithCallback(self.close, MessageBox, _("Downloading cannot be started.\n Invalid URI[%s].") % self.url, type = MessageBox.TYPE_ERROR, timeout = 10)
            
    def _doStart(self, force=False):
        if self.autoRefresh or force:
            self.refreshing = True
            self.downloader = DownloaderCreator(self.url)
            
            url,downloaderParams = DMHelper.getDownloaderParamFromUrl(self.url)
            self.downloader.subscribeFor_Finish(self.downloaderEnd)
            self.downloader.start(url, self._getDownloadFilePath(), downloaderParams)
            self.setMainTimerSts(True)
        else: self.refreshing = False

    def _startDownloader(self, sts, reason):
        if sts: self._doStart(True)
        else: self.session.openWithCallback(self.close, MessageBox, _("Downloading cannot be started.\n Downloader [%s] not working properly.\n Status[%s]") % (self.downloader.getName(), reason.strip()), type = MessageBox.TYPE_ERROR, timeout = 10 )        
        
    def onEnd(self, withCleanUp=True):
        self.setMainTimerSts(False)
        if self.downloader:
            self.downloader.unsubscribeFor_Finish(self.downloaderEnd)
            downloader = self.downloader
            self.downloader = None
            downloader.terminate()
            downloader = None
        if withCleanUp:
            self._cleanedUp()

    def key_exit(self):
        self.close()
        
    def key_play(self):
        if not self.autoRefresh:
            if None != self.audioPlayer: self.audioPlayer.start(self.audioUrl)
            self.autoRefresh = True
            if not self.refreshing: self._doStart()

    def key_pause(self):
        if self.autoRefresh:
            if None != self.audioPlayer: self.audioPlayer.stop()
            self.autoRefresh = False
        
    def key_ok(self):
        if self.autoRefresh: self.key_pause()
        else: self.key_play()

    def downloaderEnd(self, status):
        if None != self.downloader:
            self.onEnd(False)
            if DMHelper.STS.DOWNLOADED == status:
                self["status"].setText(_("++"))
                self["picture"].decodeCover(self._getDownloadFilePath(), self.decodePictureEnd, ' ')
            else:
                if 0 == self.refreshCount: self.session.openWithCallback(self.close, MessageBox, (_("Downloading file [%s] problem.") % self.url) + (" sts[%r]" % status), type=MessageBox.TYPE_ERROR, timeout=10)
                self._doStart()

    def decodePictureEnd(self, ret={}):
        if None == ret.get('Pixmap', None):
            if 0 == self.refreshCount: self.session.openWithCallback(self.close, MessageBox, _("Downloading file [%s] problem.") % self.filePath, type=MessageBox.TYPE_ERROR, timeout=10)        
        else:
            self.refreshCount += 1
            self["status"].hide()
            self["console"].hide()
            self["icon"].hide()
            self["picture"].updatePixmap(ret.get('Pixmap', None), ret.get('FileName', self.filePath))
            self["picture"].show()
        self.setMainTimerSts(False)
        self._doStart()

    def setMainTimerSts(self, start):
        try:
            if start:
                if not self.mainTimerEnabled:
                    self.mainTimer.start(self.mainTimerInterval)
                    self.mainTimerEnabled = True
                    self.updateDisplay()
            else:
                if self.mainTimerEnabled:
                    self.mainTimer.stop()
                    self.mainTimerEnabled = False
        except:
            printExc("IPTVPicturePlayerWidget.setMainTimerSts status[%r] EXCEPTION" % start)
            
    def updateDisplay(self):
        printDBG("updateDisplay")
        if not self.mainTimerEnabled:
            printDBG("updateDisplay aborted - timer stopped")
            return
        self["icon"].nextFrame()
        return
        
    def _cleanedUp(self):
        for item in self.refreshPostfixes:
            filePath = self.filePath + item
            if fileExists(filePath):
                try: os.remove(filePath)
                except: printDBG('Problem with removing old buffering file')
            
    def doStart(self):
        if not self.onStartCalled:
            self.onStartCalled = True
            self.onStart()
            
class IPTVSubSimpleDownloaderWidget(Screen):
    _TMP_FILE_NAME='.externaltmpsub'
    sz_w = getDesktop(0).size().width() - 190
    sz_h = getDesktop(0).size().height() - 195
    if sz_h < 500: sz_h += 4
    skin = """
        <screen name="IPTVSubSimpleDownloaderWidget" position="center,center" title="%s" size="%d,%d">
         <widget name="icon_red"    position="5,9"   zPosition="4" size="30,30" transparent="1" alphatest="on" />
         <widget name="icon_green"  position="355,9" zPosition="4" size="30,30" transparent="1" alphatest="on" />
         
         <widget name="label_red"     position="45,9"  size="175,27" zPosition="5" valign="center" halign="left" backgroundColor="black" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
         <widget name="label_green"   position="395,9" size="175,27" zPosition="5" valign="center" halign="left" backgroundColor="black" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
         
         <widget name="list"  position="5,80"  zPosition="2" size="%d,%d" scrollbarMode="showOnDemand" transparent="1"  backgroundColor="#00000000" enableWrapAround="1" />
         <widget name="title" position="5,47"  zPosition="1" size="%d,23" font="Regular;20"            transparent="1"  backgroundColor="#00000000"/>
         
         <widget name="console"      position="10,%d"   zPosition="2" size="%d,160" valign="center" halign="center"   font="Regular;24" transparent="0" foregroundColor="white" backgroundColor="black"/>
        </screen>""" %(
            _("Simple subtitles downloader"),
            sz_w, sz_h, # size
            sz_w - 10, sz_h - 105, # size list
            sz_w - 135, # size title
            (sz_h - 160)/2, sz_w - 20, # console
            )
    
    def __init__(self, session, params={}):
        # params: movie_title, sub_list: [{'title':'', 'lang':'', 'url':''}]
        self.session = session
        Screen.__init__(self, session)
        
        self.params = params
        
        self.onShown.append(self.onStart)
        self.onClose.append(self.__onClose)
        
        self["title"]         = Label(" ")
        self["console"]       = Label(" ")
        
        self["label_red"]     = Label(_("Cancel"))
        self["label_yellow"]  = Label(_("Move group"))
        self["label_green"]   = Label(_("Apply"))
        
        self["icon_red"]     = Cover3()
        self["icon_green"]   = Cover3()
        
        self["list"] = IPTVMainNavigatorList()
        self["list"].connectSelChanged(self.onSelectionChanged)
        
        self["actions"] = ActionMap(["ColorActions", "SetupActions", "WizardActions", "ListboxActions"],
            {
                "cancel": self.keyExit,
                "ok"    : self.keyOK,
                "red"   : self.keyRed,
                "green" : self.keyGreen,
            }, -2)
        
        self.iconPixmap = {}
        for icon in ['red', 'green']:
            self.iconPixmap[icon] = LoadPixmap(GetIconDir(icon+'.png'))
            
        self.movieTitle = ''
        self.stackList  = []
        self.stackItems = []
        
        self.defaultLanguage = GetDefaultLang()
    
        self.listMode = False
        self.downloadedSubFilePath = ""
        self.currItem = {}
        self.downloader = None
        self.cleanDownloader()
        self.workconsole = None
        
    def __onClose(self):
        self["list"].disconnectSelChanged(self.onSelectionChanged)
        if None != self.workconsole:
            self.workconsole.kill()
        self.workconsole = None
        self.cleanDownloader()
        
    def cleanDownloader(self):
        self.downloadedSubFilePath = ""
        self.currItem = {}
        if self.downloader != None:
            self.downloader.unsubscribeFor_Finish(self.downloadFinished)
            self.downloader.terminate()
        self.downloader = None
        
    def startDownload(self, item):
        self.setListMode(False)
        self.cleanDownloader()
        self.currItem = item
        self["console"].setText(_("Downloading subtitles.\n ('%r').") % self.currItem.get('url', ''))
        # create downloader
        self.downloader = DownloaderCreator(self.currItem.get('url', ''))
        if self.downloader:
            self.downloader.isWorkingCorrectly(self._startDownloader)
        else:
            self["console"].setText(_("Download can not be started.\n Incorrect address ('%r')."))

    def _startDownloader(self, sts, reason):
        if sts:
            self.downloader.subscribeFor_Finish(self.downloadFinished)
            url,downloaderParams = DMHelper.getDownloaderParamFromUrl(self.currItem.get('url', ''))
            self.downloader.start(url, GetTmpDir(self._TMP_FILE_NAME), downloaderParams)
        else:
            self["console"].setText(_("Download can not be started.\nDownloader %s not working correctly.\nStatus[%s]"))
        
    def downloadFinished(self, status):
        if status != DMHelper.STS.DOWNLOADED:
            self["console"].setText(_("Download failed.\nStatus[%s]") % status)
        else:
            self["console"].setText(_('Subtitles downloaded successfully. [%s], conversion to UTF-8.') % self.downloader.getFullFileName())
            cmd = '%s "%s"' % (config.plugins.iptvplayer.uchardetpath.value, self.downloader.getFullFileName()) 
            printDBG("cmd[%s]" % cmd)
            self.workconsole = iptv_system(cmd, self.convertSubtitles)
    
    def convertSubtitles(self, code=127, encoding=""):
        if 0 != code or 'unknown' in encoding:
            encoding = 'utf-8'
        else:
            encoding = encoding.strip()
        try:
            with codecs.open(self.downloader.getFullFileName(), 'r', encoding, 'replace') as fp:
                subText = fp.read().encode('utf-8')
            
            ext = self.currItem.get('format', '')
            if ext == '':
                ext = self.currItem.get('url', '').split('?')[-1].split('.')[-1]
            filePath = '{0}_{1}_{2}'.format(self.params['movie_title'], self.currItem.get('title', ''), self.currItem.get('lang', ''))
            filePath = RemoveDisallowedFilenameChars(filePath)
            filePath += '.' + ext
            
            with open(GetSubtitlesDir(filePath), 'w') as fp:
                fp.write(subText)

            self.downloadedSubFilePath = GetSubtitlesDir(filePath)
            self.showButtons(['green'])
            tmpList = self.params.get('sub_list', [])
            if len(tmpList) == 1:
                self.acceptSub()
        except:
            printExc()
            self["console"].setText(_('Subtitles conversion to UTF-8 failed.'))
    
    def loadIcons(self):
        try:
            for icon in self.iconPixmap:
                self['icon_'+icon].setPixmap(self.iconPixmap[icon])
        except: printExc()
        
    def hideButtons(self, buttons=['red', 'green']):
        try:
            for button in buttons:
                self['icon_'+button].hide()
                self['label_'+button].hide()
        except: printExc()
        
    def showButtons(self, buttons=['red', 'green']):
        try:
            for button in buttons:
                self['icon_'+button].show()
                self['label_'+button].show()
        except: printExc()
    
    def onStart(self):
        self.onShown.remove(self.onStart)
        self.setTitle( _("Subtitles for: %s") % self.params.get('movie_title', '') )
        self.loadIcons()
        tmpList = self.params.get('sub_list', [])
        if len(tmpList) > 1:
            self.displayList()
        else:   
            self.startDownload(tmpList[0])
    
    def setListMode(self, sts=False):
        if False == sts:
            self['list'].hide()
            self["title"].hide()
            self.hideButtons()
            self.showButtons(['red'])
            self["console"].show()
            self["console"].setText(" ")
        else:
            self.hideButtons(['green'])
            self["console"].hide()
            self["console"].setText(" ")
            
        self.listMode = sts
    
    def displayList(self):
        list = []
        self["title"].setText(_("Select subtitles to download"))
        self["title"].show()
        
        tmpList = self.params.get('sub_list', [])
        try:
            for item in tmpList:
                printDBG(item)
                dItem = CDisplayListItem(name = item['title'], type=CDisplayListItem.TYPE_ARTICLE)
                dItem.privateData = item
                list.append( (dItem,) )
        except: 
            printExc()
        self["list"].setList(list)
        self["list"].show()
        self.setListMode(True)
        
    def onSelectionChanged(self):
        pass
        
    def keyExit(self):
        if False == self.listMode:
            if self.downloader != None and self.downloader.isDownloading():
                self.downloader.terminate()
            else:
                tmpList = self.params.get('sub_list', [])
                if len(tmpList) > 1:
                    self.displayList()
                else:
                    self.close(None)
        else:
            self.close(None)
            
    def keyOK(self):
        if False == self.listMode: return
        idx, item = self.getSelectedItem()
        if None != item:
            self.startDownload(item.privateData)
            
    def keyRed(self):
        self.close(None)
        
    def keyGreen(self):
        self.acceptSub()
    
    def acceptSub(self):
        try: 
            if self["icon_green"].visible:
                track = {'title':self.currItem.get('lang', _('default')), 'lang':self.currItem.get('lang', _('default')), 'path':self.downloadedSubFilePath}
                track['id'] = self.currItem.get('url', '')
                self.close(track)
        except: printExc()
    
    def getSelectedItem(self):
        try: idx = self["list"].getCurrentIndex()
        except: idx = 0
        sel = None
        try: 
            if self["list"].visible:
                sel = self["list"].l.getCurrentSelection()[0]
                if None != sel:
                    return idx, sel
        except: 
            printExc()
            sel = None
        return -1, None
Example #16
0
    def run(self):
        ret=None
        _temp = __import__('hosts.' + self.hostName, globals(), locals(), ['IPTVHost'], -1)
        self.title = _temp.gettytul()
        logState("Host title: %s\n" % self.title)
        self.host = _temp.IPTVHost()
        self.SelectedLink = ''
        try:
            if not isinstance(self.host, IHost):
                logState("Host [%r] inherits from IHost :)\n" % (self.hostName))
        except:
            logState( 'Cannot import class IPTVHost for host [%r]\n' %  self.hostName)
            self.stop()
            return

        hostconfig = __import__('hosts.' + self.hostName, globals(), locals(), ['GetConfigList'], -1)
        ConfList = hostconfig.GetConfigList()
        configureHOST(self.hostName)

        monitor = xbmc.Monitor()
        while not monitor.abortRequested() or xbmcgui.Window(10000).getProperty('plugin.video.IPTVplayer.HOST') == self.hostName:
            #logState("plugin.video.IPTVplayer.HOST=%s self.hostName=%s\n" %(xbmcgui.Window(10000).getProperty('plugin.video.IPTVplayer.HOST'),self.hostName))
            timestamp = long(myTime())
            xbmcgui.Window(10000).setProperty("kodiIPTVserviceHeartBeat", str(timestamp))
            # Sleep/wait for abort for 10 seconds
            if monitor.waitForAbort(1):
                break # Abort was requested while waiting. We should exit
            self.myCommand = getCMD()
            if self.myCommand == '':
                continue
            elif self.myCommand == 'STOPservice':
                self.stop()
                return
            elif self.myCommand == 'Title':
                myAnswer(self.title)
                continue
            elif self.myCommand == 'LogoPath':
                myAnswer(self.host.getLogoPath().value)
                continue
            elif self.myCommand == 'SupportedTypes':
                myAnswer(self.host.getSupportedFavoritesTypes().value)
                continue
            elif self.myCommand == 'InitList':
                ret = self.host.getInitList()
                if len(ConfList) > 0:
                    #### TBC    myAnswer(ToItemsListTable(ret.value, self.clientType) + ToConfigTable(ConfList, clientType)) #if host hasconfig, return it too
                    myAnswer(ToItemsListTable(ret.value, self.clientType)) #if host hasconfig, return it too
                else:
                    myAnswer(ToItemsListTable(ret.value, self.clientType))
                continue
            elif self.myCommand == 'RefreshList':
                ret = self.host.getCurrentList()
                myAnswer(ToItemsListTable(ret.value, self.clientType))
                continue
            elif self.myCommand == 'PreviousList':
                ret= self.host.getPrevList()
                myAnswer(ToItemsListTable(ret.value, self.clientType))
                continue
            elif self.myCommand.startswith('ListForItem='): #Param: item ID
                myID = self.myCommand.split('=')[1]
                if myID.isdigit():
                    myID = int(myID)
                    ret= self.host.getListForItem(myID,0,ret.value[myID])
                    myAnswer(ToItemsListTable(ret.value, self.clientType))
                else:
                    myAnswer('ERROR: wrong index')
                continue
            elif self.myCommand.startswith('getVideoLinks='): #Param: link ID
                myID = self.myCommand.split('=')[1]
                daemonLog("daemon:getVideoLinks=%s" % myID)
                if myID.isdigit():
                    myID = int(myID)
                    self.movieTitle = ret.value[myID].name.replace('"', "'")
                    try:
                        links = ret.value[myID].urlItems
                    except:
                        links='NOVALIDURLS'
                    try:
                        retUrl= self.host.getLinksForVideo(myID,ret.value[myID]) #returns "NOT_IMPLEMENTED" when host is using curlitem
                        myAnswer(ToUrlsTable(retUrl.value, self.clientType))
                        daemonLog("retUrl found")
                    except:
                        daemonLog("Exception running getLinksForVideo (means not implemented), using CUrlItem")
                        retUrl = RetHost(RetHost.NOT_IMPLEMENTED, value = [])
                    if retUrl.status == "NOT_IMPLEMENTED" and links != 'NOVALIDURLS': 
                        daemonLog("getLinksForVideo not implemented, using CUrlItem")
                        tempUrls=[]
                        daemonLog("Iterating links...")
                        iindex=1
                        for link in links:
                            if link.name == '':
                                tempUrls.append(CUrlItem('link %d' % iindex, link.url, link.urlNeedsResolve))
                            else:
                                tempUrls.append(CUrlItem(link.name, link.url, link.urlNeedsResolve))
                            iindex += 1
                        retUrl = RetHost(RetHost.OK, value = tempUrls)
                        myAnswer(ToUrlsTable(tempUrls, self.clientType))
                else:
                    myAnswer('ERROR: wrong index')
                continue
            #### ResolveURL ####
            elif self.myCommand.startswith('ResolveURL='): #Param: selected quality link ID
                myParm = self.myCommand.split('=')[1]
                url = "NOVALIDURLS"
                linksList = []
                if myParm.isdigit():
                    myID = int(myParm)
                    #czasami jest zwracana lista linkow wiec trzeba ja sparsowac
                    linksList = self.host.getResolvedURL(retUrl.value[myID].url).value
                    daemonLog("myParm.isdigit and points to:%s" % retUrl.value[myID].url)
                else:
                    linksList = self.host.getResolvedURL(myParm).value
                if len(linksList) == 0: #There is no free links for current video
                    daemonLog("linksList has no items :(")
                elif len(linksList) >1:
                    daemonLog('WARNING: more than one link returned, selecting first')
                if isinstance(linksList[0], CUrlItem):
                    if int(linksList[0].urlNeedsResolve) == 1:
                        daemonLog('ERROR: url should be already resolved. :(')
                    else:
                        url = linksList[0].url
                        daemonLog("CUrlItem url:%s" %url)
                elif isinstance(linksList[0], basestring):
                        url = linksList[0]
                        daemonLog("basestring url:%s" %url)
                elif isinstance(linksList, (list, tuple)):
                        url = linksList[0] 
                        daemonLog("list/tuple url:%s" %url)
                myAnswer( url )
            #### Download movie ####
            elif self.myCommand.startswith('DownloadURL='):  #Param: full download url
                url = self.myCommand[len('DownloadURL='):]   #using split results in wrong links
                from Plugins.Extensions.IPTVPlayer.iptvdm.iptvdownloadercreator import IsUrlDownloadable, DownloaderCreator
                if IsUrlDownloadable(url):
                    from Plugins.Extensions.IPTVPlayer.iptvdm.iptvdh import DMHelper
                    url, downloaderParams = DMHelper.getDownloaderParamFromUrl(url)
                    currentDownloader = DownloaderCreator(url) #correct downloader is assigned e.g. wget
                    MovieRecordFileName = os.path.join(config.plugins.iptvplayer.NaszaSciezka.value , getValidFileName(self.movieTitle))
                    MovieRecordFileNameExt = MovieRecordFileName[-4:]
                    if not MovieRecordFileNameExt in ('.mpg', '.flv', '.mp4'):
                        MovieRecordFileName += ".mp4"
                    currentDownloader.start(url, MovieRecordFileName, downloaderParams)
                    myAnswer(MovieRecordFileName)
                else:
                    myAnswer( 'ERROR:wrong url' )
            #### buffer movie ####
            elif self.myCommand.startswith('BufferURL='):  #Param: full download url
                url = self.myCommand[len('BufferURL='):]   #using split results in wrong links
                from Plugins.Extensions.IPTVPlayer.iptvdm.iptvdownloadercreator import IsUrlDownloadable, DownloaderCreator
                if IsUrlDownloadable(url):
                    from Plugins.Extensions.IPTVPlayer.iptvdm.iptvdh import DMHelper
                    url, downloaderParams = DMHelper.getDownloaderParamFromUrl(url)
                    currentDownloader = DownloaderCreator(url) #correct downloader is assigned e.g. wget
                    MovieRecordFileName = config.plugins.iptvplayer.NaszaSciezka.value + "iptv_buffering.mp4"
                    currentDownloader.start(url, MovieRecordFileName, downloaderParams)
                    myAnswer(MovieRecordFileName)
                else:
                    myAnswer( 'ERROR:wrong url' )
            #### Search items ####
            elif self.myCommand.startswith('Search='):  #Param: search pattern
                self.searchPattern = self.myCommand[len('Search='):] #param can contain '='. Using split function would brake everything ;)
                ret = self.host.getSearchResults(self.searchPattern)
                myAnswer(ToItemsListTable(ret.value, self.clientType))

            #### doCommand - not finished####
            elif self.myCommand.startswith('doCommand='): #Param: selected quality link ID
                execCMD = self.myCommand.replace('doCommand=','')
                try:
                    exec(execCMD)
                    myAnswer( 'OK' )
                except Exception:
                    myAnswer( 'ERROR executing command.')
            elif self.myCommand.startswith('doUnsafeCommand='): #Param: selected quality link ID
                execCMD = self.myCommand.replace('doUnsafeCommand=','')
                exec(execCMD)
                myAnswer( 'OK' )
            else:
                daemonLog("Unknown command:'%s'\n" % self.myCommand)
                myAnswer("ERROR: Unknown command:'%s'\n" % self.myCommand)
        self.stop()
        return
Example #17
0
class SingleFileDownloaderWidget(Screen):
    sz_w = getDesktop(0).size().width() - 190
    sz_h = getDesktop(0).size().height() - 195
    if sz_h < 500:
        sz_h += 4
    skin = """
        <screen position="center,center" title="%s" size="%d,%d">
         <widget name="icon_red"    position="5,9"   zPosition="4" size="30,30" transparent="1" alphatest="on" />
         <widget name="icon_green"  position="355,9" zPosition="4" size="30,30" transparent="1" alphatest="on" />

         <widget name="label_red"     position="45,9"  size="175,27" zPosition="5" valign="center" halign="left" backgroundColor="black" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
         <widget name="label_green"   position="395,9" size="175,27" zPosition="5" valign="center" halign="left" backgroundColor="black" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />

         <widget name="title" position="5,47"  zPosition="1" size="%d,23" font="Regular;20"            transparent="1"  backgroundColor="#00000000"/>

         <widget name="console"      position="10,%d"   zPosition="2" size="%d,160" valign="center" halign="center"   font="Regular;24" transparent="0" foregroundColor="white" backgroundColor="black"/>
        </screen>""" % (
        _("Single file downloader"),
        sz_w,
        sz_h,  # size
        sz_w - 135,  # size title
        (sz_h - 160) / 2,
        sz_w - 20,  # console
    )

    def __init__(self, session, uri, outFile, title=''):
        self.session = session
        Screen.__init__(self, session)

        self.uri = uri
        self.outFile = outFile
        self.title = title

        self.onShown.append(self.onStart)
        self.onClose.append(self.__onClose)

        self["title"] = Label(" ")
        self["console"] = Label(" ")

        self["label_red"] = Label(_("Cancel"))
        self["label_green"] = Label(_("Apply"))

        self["icon_red"] = Cover3()
        self["icon_green"] = Cover3()

        self["actions"] = ActionMap([
            "ColorActions", "SetupActions", "WizardActions", "ListboxActions"
        ], {
            "cancel": self.keyExit,
            "red": self.keyRed,
            "green": self.keyGreen,
        }, -2)

        self.iconPixmap = {}
        for icon in ['red', 'green']:
            self.iconPixmap[icon] = LoadPixmap(GetIconDir(icon + '.png'))

        self.downloader = None
        self.cleanDownloader()

    def __onClose(self):
        self.cleanDownloader()

    def cleanDownloader(self):
        if self.downloader != None:
            self.downloader.unsubscribeFor_Finish(self.downloadFinished)
            self.downloader.terminate()
        self.downloader = None

    def startDownload(self):
        self.cleanDownloader()
        self["console"].setText(_("Downloading file:\n%r.") % self.uri)

        self.downloader = DownloaderCreator(self.uri)
        if self.downloader:
            self.downloader.isWorkingCorrectly(self._startDownloader)
        else:
            self["console"].setText(
                _("Download can not be started.\nIncorrect address \"%r\".") %
                self.uri)

    def _startDownloader(self, sts, reason):
        if sts:
            self.downloader.subscribeFor_Finish(self.downloadFinished)
            url, downloaderParams = DMHelper.getDownloaderParamFromUrl(
                self.uri)
            self.downloader.start(url, self.outFile, downloaderParams)
        else:
            error, desc = self.downloader.getLastError()
            self["console"].setText(
                _("Download can not be started.\nDownloader %s not working correctly.\nLast error \"%s (%s)\"."
                  ) % (self.downloader.getName(), desc, error))

    def downloadFinished(self, status):
        if status != DMHelper.STS.DOWNLOADED:
            error, desc = self.downloader.getLastError()
            self["console"].setText(
                _("Download failed.\nLast error \"%s (%s)\".") % (desc, error))
            rm(self.outFile)
        else:
            self.close(True)

    def loadIcons(self):
        try:
            for icon in self.iconPixmap:
                self['icon_' + icon].setPixmap(self.iconPixmap[icon])
        except Exception:
            printExc()

    def hideButtons(self, buttons=['green']):
        try:
            for button in buttons:
                self['icon_' + button].hide()
                self['label_' + button].hide()
        except Exception:
            printExc()

    def showButtons(self, buttons=['red', 'green']):
        try:
            for button in buttons:
                self['icon_' + button].show()
                self['label_' + button].show()
        except Exception:
            printExc()

    def onStart(self):
        self.onShown.remove(self.onStart)
        self.setTitle(self.title)
        self.loadIcons()
        self.hideButtons()
        self.startDownload()

    def keyExit(self):
        if self.downloader != None and self.downloader.isDownloading():
            self.downloader.terminate()
        else:
            self.close(None)

    def keyRed(self):
        self.keyExit()

    def keyGreen(self):
        pass
Example #18
0
    def updateDisplay(self):
        printDBG("updateDisplay")
        if self.inMoviePlayer:
            printDBG("updateDisplay aborted - we are in moviePlayer")
            return

        if not self.mainTimerEnabled:
            printDBG("updateDisplay aborted - timer stoped")
            return

        self.downloader.updateStatistic()
        localSize  = self.downloader.getLocalFileSize()
        remoteSize = self.downloader.getRemoteFileSize()
        
        if self.checkMOOVAtom and \
           localSize > 10240:
            self.checkMOOVAtom = False
            
            if remoteSize > self.maxMOOVAtomSize and \
               self.downloader.getName() == "wget" and \
               (self.clouldBeMP4 or (None != self.downloader.getMimeType() and \
               'mp4' in self.downloader.getMimeType())):
                # check moov atom position
                # if it is located at the begining of MP4 file
                # it should be just after ftyp atom
                try:
                    f = open(self.filePath, "rb")
                    currOffset = 0
                    while currOffset < localSize:
                        rawSize =  ReadUint32(f.read(4), False)
                        rawType = f.read(4)
                        printDBG(">> rawType [%s]" % rawType)
                        printDBG(">> rawSize [%d]" % rawSize)
                        if currOffset == 0 and rawType != "ftyp":
                            # this does not looks like MP4 file
                            break
                        else:
                            if rawType == "moov":
                                self.moovAtomOffset = currOffset
                                self.moovAtomSize = rawSize
                                self.isMOOVAtomAtTheBeginning = True
                                break
                            elif rawType == "mdat":
                                # we are not sure if after mdat will be moov atom but 
                                # if this will be max last 10MB of file then 
                                # we will download it
                                self.moovAtomOffset = currOffset + rawSize
                                self.moovAtomSize = remoteSize - self.moovAtomOffset
                                self.isMOOVAtomAtTheBeginning = False
                                break
                            currOffset += rawSize
                        f.seek(currOffset, 0)
                    printDBG(">> moovAtomOffset[%d]" % self.moovAtomOffset)
                    printDBG(">> moovAtomSize[%d]" % self.moovAtomSize)
                except Exception:
                    printExc()
        
        if None != self.downloader and self.downloader.hasDurationInfo() \
           and self.downloader.getTotalFileDuration() > 0:
            totalDuration = self.downloader.getTotalFileDuration()
            downloadDuration = self.downloader.getDownloadedFileDuration()
            rFileSize = str(timedelta(seconds=totalDuration))
            lFileSize = str(timedelta(seconds=downloadDuration))
            if rFileSize.startswith('0:'):
                rFileSize = rFileSize[2:]
            if lFileSize.startswith('0:'):
                lFileSize = lFileSize[2:]
        else:
            # remote size
            if -1 == remoteSize: rFileSize = '??'
            else: rFileSize = formatBytes(float(remoteSize))
            # local size
            if -1 == localSize: lFileSize = '??'
            else: lFileSize = formatBytes(float(localSize))
        
        
        # download speed
        dSpeed = self.downloader.getDownloadSpeed()
        if dSpeed > -1 and localSize > 0:
            dSpeed = formatBytes(float(dSpeed))
        else:
            dSpeed = ''
        
        speed     = self.downloader.getDownloadSpeed()
        tmpStr    = ''
        if '??' != lFileSize:
            if '??' != rFileSize:
                tmpStr = "\n%s/%s" % (lFileSize, rFileSize)
            else:
                tmpStr = "\n%s" % (lFileSize)
            if '' != dSpeed:
               tmpStr += "\n%s/s" % (dSpeed)
        else:
            tmpStr += '\n\n'
        
        self["console"].setText(self.movieTitle + tmpStr)
        
        handled = False
        percentage = 0
        requestedBuffSize = -1
        tmpBuffSize = 0
        if self.isMOOVAtomAtTheBeginning == True:
            moovAtomDataSize = self.moovAtomOffset + self.moovAtomSize
            if moovAtomDataSize > localSize:
                if self.moovAtomStatus != self.MOOV_STS.DOWNLOADING:
                    self["addinfo"].setText(_("Please wait for initialization data."))
                    self.moovAtomStatus = self.MOOV_STS.DOWNLOADING
                remoteSize = self.moovAtomOffset + self.moovAtomSize
                if localSize > remoteSize: percentage = 100
                else: percentage = (100 * localSize) / remoteSize
            else:
                requestedBuffSize = self.requestedBuffSize
                if self.lastSize > moovAtomDataSize: tmpBuffSize = localSize - self.lastSize
                else: tmpBuffSize = localSize - moovAtomDataSize
                if tmpBuffSize > requestedBuffSize: percentage = 100
                else: percentage = (100 * tmpBuffSize) / requestedBuffSize
                if self.moovAtomStatus != self.MOOV_STS.DOWNLOADED:
                    self["addinfo"].setText("")
                    self.moovAtomStatus = self.MOOV_STS.DOWNLOADED
            handled = True
        elif self.isMOOVAtomAtTheBeginning == False and self.moovAtomStatus not in [self.MOOV_STS.WAITING, self.MOOV_STS.ERROR, self.MOOV_STS.DOWNLOADED]:
            # At now only exteplayer3 is able to use moov atom in separate file
            if self.activMoviePlayer == 'exteplayer' and self.moovAtomStatus == self.MOOV_STS.UNKNOWN:
                url, downloaderParams = DMHelper.getDownloaderParamFromUrl(self.url)
                downloaderParams['start_pos'] = self.moovAtomOffset
                self.moovAtomDownloader = DownloaderCreator(self.url)
                self.moovAtomDownloader.start(url, self.moovAtomPath, downloaderParams)
                self.moovAtomStatus = self.MOOV_STS.DOWNLOADING
                self["addinfo"].setText(_("Please wait - downloading initialization data."))
            elif self.moovAtomStatus == self.MOOV_STS.DOWNLOADING:
                self.moovAtomDownloader.updateStatistic()
                status = self.moovAtomDownloader.getStatus()
                moovLocalSize  = self.moovAtomDownloader.getLocalFileSize()
                moovRemoteSize = self.moovAtomDownloader.getRemoteFileSize()
                if status == DMHelper.STS.DOWNLOADING:
                    if moovLocalSize > 0 and self.moovAtomSize > 0:
                        if moovLocalSize > self.moovAtomSize: percentage = 100
                        else: percentage = (100 * moovLocalSize) / self.moovAtomSize
                elif status == DMHelper.STS.DOWNLOADED or (status == DMHelper.STS.INTERRUPTED and moovLocalSize == self.moovAtomSize):
                    self.moovAtomStatus = self.MOOV_STS.DOWNLOADED
                    self["addinfo"].setText("")
                else:
                    self.moovAtomStatus = self.MOOV_STS.ERROR
            
            handled = True
            if self.moovAtomStatus in [self.MOOV_STS.UNKNOWN, self.MOOV_STS.ERROR]:
                printDBG(">> [%s] [%s]" % (self.activMoviePlayer, self.moovAtomStatus))
                msg = [_("Whole file must be downloaded to start playback!")]
                if self.moovAtomStatus == self.MOOV_STS.UNKNOWN and self.activMoviePlayer != 'exteplayer':
                    msg.append(_("You can use external eplayer to start playback faster."))
                self["addinfo"].setText('\n'.join(msg))
                self.moovAtomStatus = self.MOOV_STS.WAITING
                handled = False
        
        if not handled and self.moovAtomStatus != self.MOOV_STS.WAITING:
            tmpBuffSize = localSize - self.lastSize + 1 # simple when getLocalFileSize() returns -1
            if self.downloader.getPlayableFileSize() > 0:
                requestedBuffSize = self.requestedBuffSize
                if tmpBuffSize > requestedBuffSize: percentage = 100
                else: percentage = (100 * tmpBuffSize) / requestedBuffSize
                handled = True
        
        if not handled and localSize > 0 and remoteSize > 0:
            if localSize > remoteSize: percentage = 100
            else: percentage = (100 * localSize) / remoteSize
        
        self["percentage"].setText(str(percentage))
        self["icon"].nextFrame()
        
        # check if we start movie player
        if self.canRunMoviePlayer:
            if (requestedBuffSize > -1 and tmpBuffSize >= requestedBuffSize) or \
               (self.downloader.getStatus() == DMHelper.STS.DOWNLOADED and 0 < localSize):
                self.runMovePlayer()
                return
        
        # check if it is downloading 
        if self.downloader.getStatus() not in [DMHelper.STS.POSTPROCESSING, DMHelper.STS.DOWNLOADING, DMHelper.STS.WAITING]:
            self.session.openWithCallback(self.iptvDoClose, MessageBox, _("Error occurs during download. \nStatus[%s], tmpBuffSize[%r], canRunMoviePlayer[%r]") % (self.downloader.getStatus(), tmpBuffSize, self.canRunMoviePlayer), type = MessageBox.TYPE_ERROR, timeout = 10 )
            self.canRunMoviePlayer = False
            # stop timer before message
            self.setMainTimerSts(False)

        return