コード例 #1
0
ファイル: screen.py プロジェクト: DirkUK/RPi-InfoScreen-Kivy
class MythTVScreen(Screen):
    """Main screen class for MythTV schedule.

       Screen attempts to connect to MythTV backend and retrieve list of
       upcoming recordings and display this.

       Data is cached so that information can still be viewed even if backend
       is offline (e.g. for power saving purposes).
    """
    backendonline = BooleanProperty(False)
    isrecording = BooleanProperty(False)

    def __init__(self, **kwargs):
        super(MythTVScreen, self).__init__(**kwargs)

        # Get the path for the folder
        scr = sys.modules[self.__class__.__module__].__file__

        # Create variable to retain path to our cache fie
        self.screendir = os.path.dirname(scr)
        self.cacheFile = os.path.join(self.screendir, "cache", "cache.json")

        # Some other useful variable
        self.running = False
        self.rec_timer = None
        self.status_timer = None
        self.be = None
        self.recs = None

    def on_enter(self):
        # We only update when we enter the screen. No need for regular updates.
        self.getRecordings()
        self.drawScreen()
        self.checkRecordingStatus()

    def on_leave(self):
        pass

    def cacheRecs(self, recs):
        """Method to save local copy of recordings. Backend may not be online
           all the time so a cache enables us to display recordings if if we
           can't poll the server for an update.
        """
        with open(self.cacheFile, 'w') as outfile:
            json.dump(recs, outfile)

    def loadCache(self):
        """Retrieves cached recorings and returns as a python list object."""
        try:
            raw = open(self.cacheFile, 'r')
            recs = json.load(raw)
        except:
            recs = []

        return recs

    def recs_to_dict(self, uprecs):
        """Converts the MythTV upcoming recording iterator into a list of
           dict objects.
        """
        raw_recs = []
        recs = []

        # Turn the response into a dict object and add to our list of recorings
        for r in uprecs:
            rec = {}
            st = r.starttime
            et = r.endtime
            rec["title"] = r.title
            rec["subtitle"] = r.subtitle if r.subtitle else ""
            day = dt.datetime(st.year, st.month, st.day)
            rec["day"] = (day - EPOCH).total_seconds()
            rec["time"] = "{} - {}".format(st.strftime("%H:%M"),
                                           et.strftime("%H:%M"))
            rec["timestamp"] = (st - EPOCH).total_seconds()
            rec["desc"] = r.description
            raw_recs.append(rec)

        # Group the recordings by day (so we can print a header)
        for k, g in groupby(raw_recs, lambda x: x["day"]):
            recs.append((k, list(g)))

        return recs

    def getRecordings(self):
        """Attempts to connect to MythTV backend and retrieve recordings."""
        try:
            # If we can connect then get recordings and save a local cache.
            self.be = MythBE()
            uprecs = self.be.getUpcomingRecordings()
            self.recs = self.recs_to_dict(uprecs)
            self.cacheRecs(self.recs)
            self.backendonline = True
        except:
            # Can't connect so we need to set variables accordinly and try
            # to load data from the cache.
            self.be = None
            self.recs = self.loadCache()
            self.backendonline = False

    def checkRecordingStatus(self):
        """Checks whether the backend is currently recording."""
        try:
            recbe = MythBE()
            for recorder in recbe.getRecorderList():
                if recbe.isRecording(recorder):
                    self.isrecording = True
                    break
        except:
            # If we can't connect to it then it can't be recording.
            self.isrecording = False

    def drawScreen(self):
        """Main method for rendering screen.

        If there is recording data (live or cached) then is laid out in a
        scroll view.

        If not, the user is notified that the backend is unreachable.
        """
        sv = self.ids.myth_scroll
        sv.clear_widgets()

        if self.recs:
            # Create a child widget to hold the recordings.
            self.sl = GridLayout(cols=1, size_hint=(1, None), spacing=2)
            self.sl.bind(minimum_height=self.sl.setter('height'))

            # Loop over the list of recordings.
            for rec in self.recs:

                # These are grouped by day so we need a header
                day = dt.timedelta(0, rec[0]) + EPOCH
                mrh = MythRecordingHeader(rec_date=day.strftime("%A %d %B"))
                self.sl.add_widget(mrh)

                # Then we loop over the recordings scheduled for that day
                for r in rec[1]:
                    # and add them to the display.
                    mr = MythRecording(rec=r)
                    self.sl.add_widget(mr)

            sv.add_widget(self.sl)

        else:
            lb = Label(text="Backend is unreachable and there is no cached"
                            " information")
            sv.add_widget(lb)
コード例 #2
0
class myScreen(PiInfoScreen):
    refreshtime = 60
    displaytime = 10
    pluginname = "MythTV"
    plugininfo = "Displays details of upcoming recordings"
    supportedsizes = [(694, 466)]

    def setPluginVariables(self):
        self.be = None
        self.backendfail = False
        self.cachedmode = False
        self.isrecording = False
        self.regularfont = os.path.join(self.plugindir, "resources",
                                        "ArchivoNarrow-Regular.otf")
        self.italicfont = os.path.join(self.plugindir, "resources",
                                       "ArchivoNarrow-Italic.otf")
        self.boldfont = os.path.join(self.plugindir, "resources",
                                     "ArchivoNarrow-Bold.otf")
        self.cacheFile = os.path.join(self.plugindir, "resources",
                                      "cachedRecordings.json")
        self.mytitlefont = pygame.font.Font(self.boldfont, 24)
        self.myboldfont = pygame.font.Font(self.boldfont, 20)
        self.myregularfont = pygame.font.Font(self.regularfont, 16)
        self.myitalicfont = pygame.font.Font(self.italicfont, 16)
        self.rectwidth = 132
        self.rectgap = 5
        self.rectadjust = 2

    def cacheRecs(self, recs):
        with open(self.cacheFile, 'w') as outfile:
            json.dump(recs, outfile)

    def loadCache(self):
        try:
            raw = open(self.cacheFile, 'r')
            recs = json.load(raw)
        except:
            recs = []

        return recs

    def showScreen(self):
        self.surface.fill([0, 0, 0])

        if self.be == None:
            try:
                recs = []
                self.be = MythBE()
                self.upcomingrecs = self.be.getUpcomingRecordings()
                for r in self.upcomingrecs:
                    rec = {}
                    rec["title"] = r.title
                    rec["subtitle"] = r.subtitle
                    rec["time"] = r.starttime.strftime("%a %d %b %H:%M")
                    rec["desc"] = r.description
                    recs.append(rec)
                recorders = MythBE().getRecorderList()
                for recorder in recorders:
                    if MythBE().isRecording(recorder):
                        self.isrecording = True
                        break
                self.backendfail = False
                self.cachedmode = False
            except:
                self.backendfail = True

        if self.backendfail:
            recs = self.loadCache()
            if recs:
                self.backendfail = False
                self.cachedmode = True

        if not self.backendfail:

            self.cacheRecs(recs)

            screentitle = self.mytitlefont.render("MythTV upcoming recordings",
                                                  1, (255, 255, 255))
            screenrect = screentitle.get_rect()
            screenrect.centerx = self.surface.get_rect().centerx
            screenrect.centery = 20
            self.surface.blit(screentitle, screenrect)

            n = min(len(recs), 5)
            if n > 0:
                for i in range(n):
                    mytitlerect = pygame.Rect((0, 0, self.rectwidth, 60))
                    mytimerect = pygame.Rect((0, 0, self.rectwidth, 30))
                    mydescrect = pygame.Rect((0, 0, self.rectwidth, 330))
                    fontcolour = (255, 255, 255)
                    rectcolour = (0, 50, 75)
                    titletext = self.render_textrect(recs[i]["title"],
                                                     self.myboldfont,
                                                     mytitlerect, fontcolour,
                                                     rectcolour, 1)
                    timetext = self.render_textrect(recs[i]["time"],
                                                    self.myitalicfont,
                                                    mytimerect, fontcolour,
                                                    rectcolour, 1)
                    desctext = self.render_textrect(recs[i]["desc"],
                                                    self.myregularfont,
                                                    mydescrect,
                                                    fontcolour,
                                                    rectcolour,
                                                    0,
                                                    margin=5)
                    self.surface.blit(titletext,
                                      ((self.rectwidth * i) +
                                       (self.rectgap *
                                        (i + 1) + self.rectadjust), 40))
                    self.surface.blit(timetext,
                                      ((self.rectwidth * i) +
                                       (self.rectgap *
                                        (i + 1) + self.rectadjust), 80))
                    self.surface.blit(desctext,
                                      ((self.rectwidth * i) +
                                       (self.rectgap *
                                        (i + 1) + self.rectadjust), 105))

                if self.cachedmode:
                    mystatus = self.myitalicfont.render(
                        "Backend is offline. Displaying cached recording list",
                        1, (255, 255, 255))
                else:
                    if self.isrecording:
                        recording = "currently"
                    else:
                        recording = "not"
                    mystatus = self.myitalicfont.render(
                        "Backend is online and is " + recording +
                        " recording.", 1, (255, 255, 255))

                self.surface.blit(mystatus, (5, 445))
            else:
                failtext = self.myboldfont.render(
                    "No upcoming recordings found.", 1, (255, 255, 255))
                failrect = failtext.get_rect()
                failrect.centerx = self.surface.get_rect().centerx
                failrect.centery = self.surface.get_rect().centery
                self.surface.blit(failtext, failrect)

        else:
            failtext = self.myboldfont.render("MythTV backend unavailable.", 1,
                                              (255, 255, 255))
            failrect = failtext.get_rect()
            failrect.centerx = self.surface.get_rect().centerx
            failrect.centery = self.surface.get_rect().centery
            self.surface.blit(failtext, failrect)

        self.be = None

        # Scale our surface to the required screensize before sending back
        scaled = pygame.transform.scale(self.surface, self.screensize)
        self.screen.blit(scaled, (0, 0))

        return self.screen
コード例 #3
0
ファイル: screen.py プロジェクト: 9and3r/RPI-Info-Screen
class myScreen(PiInfoScreen):
    refreshtime = 60
    displaytime = 10
    pluginname = "MythTV"
    plugininfo = "Displays details of upcoming recordings"
    supportedsizes = [ (694, 466) ]
    
    def setPluginVariables(self):
        self.be = None
        self.backendfail = False
        self.cachedmode = False
        self.isrecording = False
        self.regularfont = os.path.join(self.plugindir, "resources", "ArchivoNarrow-Regular.otf") 
        self.italicfont = os.path.join(self.plugindir, "resources", "ArchivoNarrow-Italic.otf") 
        self.boldfont = os.path.join(self.plugindir, "resources", "ArchivoNarrow-Bold.otf") 
        self.cacheFile = os.path.join(self.plugindir, "resources", "cachedRecordings.json")
        self.mytitlefont = pygame.font.Font(self.boldfont, 24)
        self.myboldfont = pygame.font.Font(self.boldfont, 20)
        self.myregularfont = pygame.font.Font(self.regularfont, 16)
        self.myitalicfont = pygame.font.Font(self.italicfont, 16)
        self.rectwidth = 132
        self.rectgap = 5
        self.rectadjust = 2
    
    def cacheRecs(self, recs):
        with open(self.cacheFile, 'w') as outfile:
            json.dump(recs, outfile)   
    
    def loadCache(self):
        try:
            raw = open(self.cacheFile, 'r')
            recs = json.load(raw)
        except:
            recs = []
        
        return recs

    def showScreen(self):
        self.surface.fill([0,0,0])

        if self.be == None:
            try:
                recs = []
                self.be = MythBE()
                self.upcomingrecs = self.be.getUpcomingRecordings()
                for r in self.upcomingrecs:
                    rec = {}
                    rec["title"] = r.title
                    rec["subtitle"] = r.subtitle
                    rec["time"] = r.starttime.strftime("%a %d %b %H:%M")
                    rec["desc"] = r.description
                    recs.append(rec)
                recorders = MythBE().getRecorderList()
                for recorder in recorders:
                    if MythBE().isRecording(recorder):
                        self.isrecording = True
                        break
                self.backendfail = False
                self.cachedmode = False
            except:
                self.backendfail = True
        
        if self.backendfail:
            recs = self.loadCache()
            if recs: 
                self.backendfail = False
                self.cachedmode = True
        
        if not self.backendfail:
            
            self.cacheRecs(recs)
            
            screentitle = self.mytitlefont.render("MythTV upcoming recordings",1,(255,255,255))
            screenrect = screentitle.get_rect()
            screenrect.centerx = self.surface.get_rect().centerx
            screenrect.centery = 20
            self.surface.blit(screentitle, screenrect)
            
            n = min(len(recs),5)
            if n > 0:
                for i in range(n):
                    mytitlerect = pygame.Rect((0,0,self.rectwidth,60))
                    mytimerect = pygame.Rect((0,0,self.rectwidth,30))
                    mydescrect = pygame.Rect((0,0,self.rectwidth,330))
                    fontcolour = (255,255,255)
                    rectcolour = (0,50,75)
                    titletext = self.render_textrect(recs[i]["title"], self.myboldfont, mytitlerect, fontcolour, rectcolour,1)
                    timetext = self.render_textrect(recs[i]["time"], self.myitalicfont, mytimerect, fontcolour, rectcolour,1)
                    desctext = self.render_textrect(recs[i]["desc"], self.myregularfont, mydescrect, fontcolour, rectcolour,0,margin=5)
                    self.surface.blit(titletext,((self.rectwidth*i)+(self.rectgap*(i+1)+self.rectadjust), 40))
                    self.surface.blit(timetext,((self.rectwidth*i)+(self.rectgap*(i+1)+self.rectadjust), 80))
                    self.surface.blit(desctext,((self.rectwidth*i)+(self.rectgap*(i+1)+self.rectadjust), 105))
                    
                if self.cachedmode:
                    mystatus = self.myitalicfont.render("Backend is offline. Displaying cached recording list",1,(255,255,255))
                else:
                    if self.isrecording:
                        recording = "currently"
                    else:
                        recording = "not"
                    mystatus = self.myitalicfont.render("Backend is online and is " + recording + " recording.",1,(255,255,255))
                    
                self.surface.blit(mystatus,(5,445))
            else:
                failtext = self.myboldfont.render("No upcoming recordings found.",1, (255,255,255))
                failrect = failtext.get_rect()
                failrect.centerx = self.surface.get_rect().centerx
                failrect.centery = self.surface.get_rect().centery
                self.surface.blit(failtext, failrect)                
            
        else:
            failtext = self.myboldfont.render("MythTV backend unavailable.",1, (255,255,255))
            failrect = failtext.get_rect()
            failrect.centerx = self.surface.get_rect().centerx
            failrect.centery = self.surface.get_rect().centery
            self.surface.blit(failtext, failrect)
        
        self.be = None

        # Scale our surface to the required screensize before sending back
        scaled = pygame.transform.scale(self.surface,self.screensize)
        self.screen.blit(scaled,(0,0))

        return self.screen
コード例 #4
0
class MythTVScreen(Screen):
    """Main screen class for MythTV schedule.

       Screen attempts to connect to MythTV backend and retrieve list of
       upcoming recordings and display this.

       Data is cached so that information can still be viewed even if backend
       is offline (e.g. for power saving purposes).
    """
    backendonline = BooleanProperty(False)
    isrecording = BooleanProperty(False)

    def __init__(self, **kwargs):
        super(MythTVScreen, self).__init__(**kwargs)

        # Get the path for the folder
        scr = sys.modules[self.__class__.__module__].__file__

        # Create variable to retain path to our cache fie
        self.screendir = os.path.dirname(scr)
        self.cacheFile = os.path.join(self.screendir, "cache", "cache.json")

        # Some other useful variable
        self.running = False
        self.rec_timer = None
        self.status_timer = None
        self.be = None
        self.recs = None

    def on_enter(self):
        # We only update when we enter the screen. No need for regular updates.
        self.getRecordings()
        self.drawScreen()
        self.checkRecordingStatus()

    def on_leave(self):
        pass

    def cacheRecs(self, recs):
        """Method to save local copy of recordings. Backend may not be online
           all the time so a cache enables us to display recordings if if we
           can't poll the server for an update.
        """
        with open(self.cacheFile, 'w') as outfile:
            json.dump(recs, outfile)

    def loadCache(self):
        """Retrieves cached recorings and returns as a python list object."""
        try:
            raw = open(self.cacheFile, 'r')
            recs = json.load(raw)
        except:
            recs = []

        return recs

    def recs_to_dict(self, uprecs):
        """Converts the MythTV upcoming recording iterator into a list of
           dict objects.
        """
        raw_recs = []
        recs = []

        # Turn the response into a dict object and add to our list of recorings
        for r in uprecs:
            rec = {}
            st = r.starttime
            et = r.endtime
            rec["title"] = r.title
            rec["subtitle"] = r.subtitle if r.subtitle else ""
            day = dt.datetime(st.year, st.month, st.day)
            rec["day"] = (day - EPOCH).total_seconds()
            rec["time"] = "{} - {}".format(st.strftime("%H:%M"),
                                           et.strftime("%H:%M"))
            rec["timestamp"] = (st - EPOCH).total_seconds()
            rec["desc"] = r.description
            raw_recs.append(rec)

        # Group the recordings by day (so we can print a header)
        for k, g in groupby(raw_recs, lambda x: x["day"]):
            recs.append((k, list(g)))

        return recs

    def getRecordings(self):
        """Attempts to connect to MythTV backend and retrieve recordings."""
        try:
            # If we can connect then get recordings and save a local cache.
            self.be = MythBE()
            uprecs = self.be.getUpcomingRecordings()
            self.recs = self.recs_to_dict(uprecs)
            self.cacheRecs(self.recs)
            self.backendonline = True
        except:
            # Can't connect so we need to set variables accordinly and try
            # to load data from the cache.
            self.be = None
            self.recs = self.loadCache()
            self.backendonline = False

    def checkRecordingStatus(self):
        """Checks whether the backend is currently recording."""
        try:
            recbe = MythBE()
            for recorder in recbe.getRecorderList():
                if recbe.isRecording(recorder):
                    self.isrecording = True
                    break
        except:
            # If we can't connect to it then it can't be recording.
            self.isrecording = False

    def drawScreen(self):
        """Main method for rendering screen.

        If there is recording data (live or cached) then is laid out in a
        scroll view.

        If not, the user is notified that the backend is unreachable.
        """
        sv = self.ids.myth_scroll
        sv.clear_widgets()

        if self.recs:
            # Create a child widget to hold the recordings.
            self.sl = GridLayout(cols=1, size_hint=(1, None), spacing=2)
            self.sl.bind(minimum_height=self.sl.setter('height'))

            # Loop over the list of recordings.
            for rec in self.recs:

                # These are grouped by day so we need a header
                day = dt.timedelta(0, rec[0]) + EPOCH
                mrh = MythRecordingHeader(rec_date=day.strftime("%A %d %B"))
                self.sl.add_widget(mrh)

                # Then we loop over the recordings scheduled for that day
                for r in rec[1]:
                    # and add them to the display.
                    mr = MythRecording(rec=r)
                    self.sl.add_widget(mr)

            sv.add_widget(self.sl)

        else:
            lb = Label(text="Backend is unreachable and there is no cached"
                       " information")
            sv.add_widget(lb)