class WebRecorder():
    '''
    API methods are called by the RecorderPlugin in the RecorderWebService module.
    '''
    # signal modes
    # TODO change mode to STATUS und ERROR...
    MSG_STATUS = MessageListener.MSG_STATUS
    # MSG_EPG = MessageListener.MSG_EPG
    MSG_REFRESH = MessageListener.MSG_REFRESH
    
    # Modes or types of rec? 
    (MODE_DATA, MODE_REC, MODE_BLOCK) = range(0xA0, 0xA3)
    (TYPE_HEAD, TYPE_PROG, TYPE_INFO) = range(3)



    def __init__(self):
        '''
        starts the app
        '''
        self.configuration = Config()
        self.configuration.setupLogging("webdvb.log")
        
        self._lastMessage = None
        ml = MessageListener();
        ml.addListener(ml.MSG_STATUS, self.storeLastMessage)
        # ml.addListener(ml.MSG_EPG, this.storeLastMessage)
        ml.addListener(ml.MSG_REFRESH, self.storeLastMessage)
        
        channelReader = ChannelReader()
        cPath = self.configuration.getChannelFilePath()

        channelReader.readChannels(cPath)
        self.channelList = channelReader.getChannels()
        self.progProvider = EPGProgramProvider(self, self.channelList, self.configuration)
        self._lastEpgRead = 0.0
        # self._readCachedEpgData()
        self.checkEPGData()
  

  
    def _readCachedEpgData(self):
        ml = MessageListener();
        if not self.channelList:
            ml.signalMessage(self.MSG_STATUS, "Where is that channel.conf? RTF!")
            return

        ml.signalMessage(self.MSG_STATUS, "Reading programm info")
        msg = "Idle"
        try:
            self.progProvider.readEPGCache()
            ml.signalMessage(self.MSG_REFRESH, "Program info read")  # enforces a new list
        except IOError:
            msg = "No EPG data"
        except Exception, ex:
            msg = "Error reading cached EPG Data: " + str(ex.args[0])
            self.configuration.getLogger().exception(msg)
            print msg
        self.configuration.logInfo(msg)                        
        ml.signalMessage(self.MSG_STATUS, msg)
Exemplo n.º 2
0
class DVBRecorder():
    '''
    startup main class
    '''
    def __init__(self):
        '''
        starts the app
        '''
        self.configuration = Config()
        self.configuration.setupLogging("dvb.log")

        channelReader = ChannelReader()
        cPath = self.configuration.getChannelFilePath()

        channelReader.readChannels(cPath)
        self.channelList = channelReader.getChannels()
        self.progProvider = EPGProgramProvider(self, self.channelList,
                                               self.configuration)
        recView = RecorderView(self.progProvider)
        ml = MessageListener()
        ml.addListener(ml.MSG_STATUS, recView.setStatusLine)
        ml.addListener(ml.MSG_EPG, recView.notifyEPGStatus)
        ml.addListener(ml.MSG_REFRESH, recView.refreshProgrammInfos)
        t1 = ReaderThread(False, self._readCachedEpgData)
        t1.start()
        recView.openView()
        #returns on close
        t1.join()

    def _readCachedEpgData(self):
        ml = MessageListener()
        if not self.channelList:
            ml.signalMessage(ml.MSG_STATUS, "Where is that channel.conf? RTF!")
            return

        ml.signalMessage(ml.MSG_STATUS, "Reading programm info")
        msg = "Idle"
        try:
            self.progProvider.readEPGCache()
            ml.signalMessage(ml.MSG_REFRESH)  # enforces a new list
        except IOError:
            msg = "No EPG data"
        except Exception as ex:
            msg = "Error reading cached EPG Data: " + str(ex.args[0])

        self.configuration.logInfo(msg)
        ml.signalMessage(ml.MSG_STATUS, msg)

    ##callback for the epg program provider:
    def readEPGDeviceData(self):
        self._EPGThread = ReaderThread(False, self._collectEPGFromDevice)
        #TEST code: self._EPGThread = ReaderThread(False,self._readEPGSimData)
        self._EPGThread.start()

    def _collectEPGFromDevice(self):
        ml = MessageListener()
        ml.signalMessage(ml.MSG_EPG, True)
        ml.signalMessage(ml.MSG_STATUS, "Retrieving new EPG data")

        epgUpdater = self.progProvider.getEPGUpdater()
        epgUpdater.updateDatabase()
        if epgUpdater.hasError():
            ml.signalMessage(ml.MSG_STATUS, epgUpdater.getErrorMessage())
            ml.signalMessage(ml.MSG_EPG, False)
            return

        ml.signalMessage(ml.MSG_REFRESH)  # enforces redraw!
        ml.signalMessage(ml.MSG_STATUS, "EPG data up to date !")
        ml.signalMessage(ml.MSG_EPG, False)


#    def _readEPGSimData(self):
#        rawEPGPath = "/home/matze/JWSP/py1/VideoRecorder/src/xmltv/rawepg.xmltv"
#        with open(rawEPGPath, 'r') as aFile:
#            dvbList=aFile.readlines()
#
#        epgReader=EpgReader(self.channelList)
#        for xmls in dvbList:
#            print "parse xml"
#            epgReader.parseXML_TVString(xmls,UTC=True)
#
#        infoDictionary = epgReader.getInfoDictionary()
#        self.progProvider.updateProgramms(infoDictionary)
#        ml = MessageListener();
#        ml.signalMessage(ml.MODE_REFRESH)# enforces redraw!
#        ml.signalMessage(ml.MODE_STATUS,"EPG data up to date !")
#        ml.signalMessage(ml.MODE_EPG,False)

    def _getEPGDevice(self):
        return DVBDevice.getGrabber(self.channelList, self.configuration)

    def persistEPGData(self):
        self.configuration.logInfo("Saving data...")
        epgUpdater = self.progProvider.getEPGUpdater()
        self.progProvider.getAutoSelector().saveAutoSelectData()
        epgUpdater.persistDatabase()
        if epgUpdater.hasError():
            self.configuration.logError("Error saving xml data")
Exemplo n.º 3
0
class WebRecorder():
    '''
    API methods are called by the RecorderPlugin in the RecorderWebService module.
    '''
    # signal modes
    # TODO change mode to STATUS und ERROR...
    MSG_STATUS = MessageListener.MSG_STATUS
    # MSG_EPG = MessageListener.MSG_EPG
    MSG_REFRESH = MessageListener.MSG_REFRESH

    # Modes or types of rec?
    (MODE_DATA, MODE_REC, MODE_BLOCK) = list(range(0xA0, 0xA3))
    (TYPE_HEAD, TYPE_PROG, TYPE_INFO) = list(range(3))

    def __init__(self):
        '''
        starts the app
        '''
        self.configuration = Config()
        self.configuration.setupLogging("webdvb.log")

        self._lastMessage = None
        ml = MessageListener()
        ml.addListener(ml.MSG_STATUS, self.storeLastMessage)
        # ml.addListener(ml.MSG_EPG, this.storeLastMessage)
        ml.addListener(ml.MSG_REFRESH, self.storeLastMessage)

        channelReader = ChannelReader()
        cPath = self.configuration.getChannelFilePath()

        channelReader.readChannels(cPath)
        self.channelList = channelReader.getChannels()
        self.progProvider = EPGProgramProvider(self, self.channelList,
                                               self.configuration)
        self._lastEpgRead = 0.0
        # self._readCachedEpgData()
        self.checkEPGData()

    def _readCachedEpgData(self):
        ml = MessageListener()
        if not self.channelList:
            ml.signalMessage(self.MSG_STATUS,
                             "Where is that channel.conf? RTF!")
            return

        ml.signalMessage(self.MSG_STATUS, "Reading programm info")
        msg = "Idle"
        try:
            self.progProvider.readEPGCache()
            ml.signalMessage(self.MSG_REFRESH,
                             "Program info read")  # enforces a new list
        except IOError:
            msg = "No EPG data"
        except Exception as ex:
            msg = "Error reading cached EPG Data: " + str(ex.args[0])
            self.configuration.getLogger().exception(msg)
            print(msg)
        self.configuration.logInfo(msg)
        ml.signalMessage(self.MSG_STATUS, msg)

    def _getEPGDevice(self):
        return DVBDevice.getGrabber(self.channelList, self.configuration)

    def _collectEPGFromDevice(self):
        epgUpdater = self.progProvider.getEPGUpdater()
        self._updater.updateDatabase()
        if epgUpdater.hasError():
            MessageListener().signalMessage(self.MSG_STATUS,
                                            epgUpdater.getErrorMessage())

    '''
    API to Recorder plugin
    Basic idea: should be json objects
    '''

    def storeLastMessage(self, message):
        self._lastMessage = message

    def getLastSignal(self):
        msg = self._lastMessage
        self._lastMessage = None
        return msg

    def readEPGDeviceData(self):
        self._collectEPGFromDevice()

    def getChannelList(self):
        channelNames = []
        for channel in self.channelList:
            channelNames.append(channel.getName())
        jchannels = json.dumps(channelNames)
        return jchannels

    def getProgrammInfoForChannel(self, aChannelString):
        daytoDayList = self.progProvider.getInfosForChannel(aChannelString)
        jDayToDayArray = self._formatProgramList(daytoDayList)
        jInfos = json.dumps(jDayToDayArray)
        return jInfos

    def toggleRecordMode(self, jsonString):
        jsonDict = json.loads(jsonString)
        epgInfo = self._lookupEPGInfoFromJSON(jsonDict)
        forceRemove = jsonDict["type"] == self.TYPE_INFO
        if epgInfo is not None:
            self.progProvider.toggleRecordInfo(epgInfo, forceRemove)
            result = self._formatProgramRow(epgInfo)
        else:
            jsonDict["error"] = "Entry not found"
            result = jsonDict
        if self._lastMessage is not None:
            result["error"] = self.getLastSignal()
        return json.dumps(result)

    def getFilterList(self, searchTuple):
        channelName = searchTuple[0]
        filterString = searchTuple[1]
        epgInfoList = self.progProvider.searchInChannel(
            channelName, filterString)
        jDayToDayArray = self._formatProgramList(epgInfoList)
        return json.dumps(jDayToDayArray)

    def getAutoSelectList(self):
        autoselectList = self.progProvider.getAutoSelector(
        ).getAutoSelectionList()

        jList = self._formatAutoSelectList(autoselectList)
        return json.dumps(jList)

    def addToAutoSelection(self, jsonString):
        jsonDict = json.loads(jsonString)
        epgInfo = self._lookupEPGInfoFromJSON(jsonDict)
        autoSelector = self.progProvider.getAutoSelector()
        autoSelector.addAutoSelectPreference(epgInfo)
        autoSelector.saveAutoSelectData()

    def saveAutoSelectionSetting(self, jsonString):
        # weekmode has changed. single entry. update & save
        jsonDict = json.loads(jsonString)
        hourString = jsonDict["timetext"]
        # Text is unicode!!
        titleString = jsonDict["text"]
        channelName = jsonDict["chanID"]
        weekModeString = jsonDict["weekMode"]

        autoSelector = self.progProvider.getAutoSelector()
        autoSelector.updateWeekMode(hourString, titleString, channelName,
                                    weekModeString)
        autoSelector.saveAutoSelectData()

    def removeFromAutoSelection(self, jsonString):
        # NOTE: json makes unicode out of the string
        jsonDict = json.loads(jsonString)
        hourString = jsonDict["timetext"]
        titleString = jsonDict["text"]
        channelName = jsonDict["chanID"]
        autoSelector = self.progProvider.getAutoSelector()
        autoSelector.removeFromAutoSelectPreference(hourString,
                                                    str(titleString),
                                                    str(channelName))
        autoSelector.saveAutoSelectData()

    def getRecordingList(self):
        recInfoList = self.progProvider.getRecordQueue().getRecList()
        jList = self._formatRecordingList(recInfoList)
        return json.dumps(jList)

    #### dict: {u'marginStop': 600, u'marginStart': 300, u'jobID': u'1'}
    def updateRecorderMargins(self, jsonString):
        jsonList = json.loads(jsonString)
        recInfoList = self.progProvider.getRecordQueue().getRecList()
        for jEntry in jsonList:
            jobID = jEntry["jobID"]
            found = next((recEntry for recEntry in recInfoList
                          if recEntry.getEPGInfo().getJobID() == jobID), None)
            if found:
                found.setMarginStart(jEntry["marginStart"])
                found.setMarginStop(jEntry["marginStop"])

        self.progProvider.getRecordQueue()._storeRecordQueue(recInfoList)

    '''
    search the database for a string
    "cmd":"SEARCH_ALL","arg":"test","data":""}
    '''

    def searchAll(self, searchString):
        epgInfoList = self.progProvider.searchAll(searchString)
        #jDayToDayArray = self._formatProgramList(epgInfoList)
        #return json.dumps(jDayToDayArray)
        #maybe sort them per channel?
        jDayList = []
        for epgInfo in epgInfoList:
            jInfo = self._formatProgramRow(epgInfo)
            jDayList.append(jInfo)

        errorMsg = None
        if len(jDayList) == 0:
            errorMsg = "Nothing found"
        jAnswer = {"type": self.TYPE_INFO, "error": errorMsg, "list": jDayList}
        return json.dumps(jAnswer)

    '''
    reread epg info if a modification took place.If changes took place (like a daemon epg update)
    update the database 
    '''

    def checkEPGData(self):
        fileName = self.configuration.getCachedXMLTVFilePath()
        currentModificationtime = 0
        try:
            currentModificationtime = OSTools.getLastModificationTime(fileName)
        except OSError as osError:
            msg = "CheckEpgData:" + osError.strerror
            self.configuration.logError(msg)
            self.storeLastMessage(msg)
            return


#         if self._lastEpgRead is None:
#             self._lastEpgRead= currentModificationtime-100

        if currentModificationtime - self._lastEpgRead > 60:
            self._lastEpgRead = currentModificationtime
            self._readCachedEpgData()

    '''
    End of WebRecorder API
    --
    
    Helper/conversion methods -- aka WebViewGenerator?
    '''
    def _formatHeader(self, epgInfo):
        header = epgInfo.getStartTime().strftime("%A %d %B")
        headerText = "<b>%s</b>" % header
        return {
            "type": self.TYPE_HEAD,
            "text": headerText,
            "time": None
        }

    def _formatProgramRow(self, epgInfo):
        epgTime = epgInfo.getStartTimeString()
        epgDate = epgInfo.getDateString()
        title = epgInfo.getTitle()
        duration = str(epgInfo.getDuration())
        description = epgInfo.getDescription()
        # TODO: Formating is client work- only the data!
        programText = "<b>%s</b><br>%s<small><i> Duration: %s</i></small>" % (
            title, description, duration)

        jobID = None
        if epgInfo.isMarkedForRecord():
            recmode = self.MODE_REC
            jobID = epgInfo.getJobID()
        elif epgInfo.isBlockedForRecord():
            recmode = self.MODE_BLOCK
        else:
            recmode = self.MODE_DATA
        return {
            "type": self.TYPE_PROG,
            "text": programText,
            "time": epgTime,
            "date": epgDate,
            "recordMode": recmode,
            "jobID": jobID,
            "title": title,
            "channel": epgInfo.getChannel().getName(),
            "epgOK": epgInfo.isConsistent,
            "error": None
        }

    def _formatProgramList(self, daytoDayList):
        jDayToDayArray = []
        for singleDayList in daytoDayList:
            jDayList = []
            # adds the header - setting the date only
            # TODO: Empty singleDayList! Should not happen
            if len(singleDayList) == 0:
                print("ERROR: Empty single day list")
                continue

            headerText = self._formatHeader(singleDayList[0])
            for epgInfo in singleDayList:
                jInfo = self._formatProgramRow(epgInfo)
                jDayList.append(jInfo)

            jDayObject = {
                "head": headerText,
                "list": jDayList
            }
            jDayToDayArray.append(jDayObject)
        if len(jDayToDayArray) == 0:
            return self.asJsonError("No data", self.getLastSignal())
        return jDayToDayArray

    def asJsonError(self, errorMsg, argumentString):
        reason = argumentString
        if not reason:
            reason = errorMsg
        return {"type": self.TYPE_INFO, "error": errorMsg, "args": reason}

    def _lookupEPGInfoFromJSON(self, jsonData):
        aChannelString = jsonData["channel"]
        dayString = jsonData["date"]
        timeString = jsonData["time"]
        # Note JSON data always uses unicode - convert it to byte encoding it to uf8
        daytoDayList = self.progProvider.getInfosForChannel(aChannelString)
        # Well... get the right DAY first....
        for singleDayList in daytoDayList:
            if singleDayList[0].getDateString() in dayString:
                for epgInfo in singleDayList:
                    if epgInfo.getStartTimeString() in timeString:
                        return epgInfo
        return None

    def _formatAutoSelectList(self, autoSelectList):

        jDayList = []
        for autoSelection in autoSelectList:
            timeString = autoSelection.getHourListString()
            title = autoSelection.getTitle()
            chanID = autoSelection.getChannelID()
            weekMode = autoSelection.getWeekMode()
            jInfo = {
                "type": self.TYPE_INFO,
                "timetext": timeString,
                "text": title,
                "title": title,
                "chanID": chanID,
                "weekMode": weekMode,
                "error": None
            }
            jDayList.append(jInfo)
        jsonASList = {
            "weekTypes": ["Mo-Fri", "Sa-Su", "Mo-Su"],
            "elements": jDayList
        }
        return jsonASList

    def _formatRecordingList(self, recInfoList):
        jDayList = []
        for recInfo in recInfoList:
            jInfo = self._formatRecordingRow(recInfo)
            jDayList.append(jInfo)
        return jDayList

    def _formatRecordingRow(self, recInfo):
        epgInfo = recInfo.getEPGInfo()
        epgTime = epgInfo.getStartTimeString()
        epgDate = epgInfo.getDateString()
        theDay = epgInfo.getStartTime().strftime("%a %d")
        start = epgInfo.getStartTime().strftime("%H:%M-")
        end = epgInfo.getEndTime().strftime("%H:%M")
        channel = epgInfo.getChannel().getName()
        formatTime = "<b>%s</b><i> %s</i><br><small>%s%s</small>" % (
            channel, theDay, start, end)

        title = epgInfo.getTitle()
        description = epgInfo.getDescription()
        jobID = epgInfo.getJobID()
        marginStart = recInfo.getMarginAsString(recInfo.marginStart)
        marginStop = recInfo.getMarginAsString(recInfo.marginEnd)
        if len(jobID) > 0:
            programText = "<b>%s</b><br>%s <i>(%s)</i>" % (title, description,
                                                           jobID)
        else:
            programText = "<b>%s</b><br>%s" % (title, description)
        return {
            "type": self.TYPE_INFO,
            "timetext": formatTime,
            "text": programText,
            "time": epgTime,
            "date": epgDate,
            "jobID": jobID,
            "title": title,
            "channel": channel,
            "marginStart": marginStart,
            "marginStop": marginStop,
            "error": None
        }