From 62edc69faf2b233f2e9bd844b53052441d63d7f8 Mon Sep 17 00:00:00 2001 From: noisymime Date: Sun, 23 Mar 2008 12:17:18 +0000 Subject: [PATCH] - Added smooth handling of protocol version failure - Further work on music display --- GlossMgr.py | 25 ++- modules/music_player/music_player.py | 14 +- modules/myth_tv_player/MythBackendConn.py | 7 +- modules/myth_tv_player/myth_tv_player.py | 18 +- ui_elements/label_list.py | 217 +++++++++++++--------- 5 files changed, 173 insertions(+), 108 deletions(-) diff --git a/GlossMgr.py b/GlossMgr.py index 5a15fd4..5b8229d 100644 --- a/GlossMgr.py +++ b/GlossMgr.py @@ -120,22 +120,27 @@ class GlossMgr: if not self.currentPlugin == None: #Plugins on_key_press_event should return true if the plugin is finishing if self.currentPlugin.on_key_press_event(stage, event): - self.currentPlugin.stop() - self.currentPlugin = None - - timeline_stop = clutter.Timeline(10,30) - alpha = clutter.Alpha(timeline_stop, clutter.ramp_inc_func) - self.stop_behaviour = clutter.BehaviourOpacity(opacity_start=0, opacity_end=255, alpha=alpha) - self.currentMenu.set_opacity(0) - self.currentMenu.show() - self.stop_behaviour.apply(self.currentMenu) - timeline_stop.start() + self.kill_plugin() #If there's no plugin running, go back one in the menu list (Providing we're not already at the first item. else: if len(self.menuHistory)>1: self.transition.do_transition(self.menuHistory.pop(), self.menuHistory[-1]) self.currentMenu = self.menuHistory[-1] #print event.hardware_keycode + + #Kills any currently running plugin/s + def kill_plugin(self): + if not self.currentPlugin is None: + self.currentPlugin.stop() + self.currentPlugin = None + + timeline_stop = clutter.Timeline(10,30) + alpha = clutter.Alpha(timeline_stop, clutter.ramp_inc_func) + self.stop_behaviour = clutter.BehaviourOpacity(opacity_start=0, opacity_end=255, alpha=alpha) + self.currentMenu.set_opacity(0) + self.currentMenu.show() + self.stop_behaviour.apply(self.currentMenu) + timeline_stop.start() def get_current_menu(self): return self.currentMenu diff --git a/modules/music_player/music_player.py b/modules/music_player/music_player.py index d645857..08984cd 100644 --- a/modules/music_player/music_player.py +++ b/modules/music_player/music_player.py @@ -6,6 +6,7 @@ from modules.music_player.backends.myth_music import Backend from modules.music_player.lastFM_interface import lastFM_interface from modules.music_player.music_object_row import MusicObjectRow from ui_elements.image_frame import ImageFrame +from ui_elements.label_list import LabelList class Module: title = "Music" @@ -79,10 +80,12 @@ class Module: #Just a little test code artist = self.artistImageRow.get_current_object() albums = self.backend.get_albums_by_artistID(artist.artistID) - name_string = "" + self.list1.clear() for album in albums: - name_string += album.name - self.tmpLabel.set_text(name_string) + self.list1.add_item(album.name) + #name_string += album.name + self.list1.display() + #self.tmpLabel.set_text(name_string) pixbuf = albums[0].get_image() if not pixbuf is None: self.main_img.set_pixbuf(pixbuf) @@ -112,12 +115,17 @@ class Module: self.backdrop_behaviour.apply(self.artistImageRow) #Just a nasty temp label for outputting stuff + self.list1 = LabelList(5) + self.list1.set_position(self.stage.get_width()/2, 350) + self.stage.add(self.list1) + """ self.tmpLabel = clutter.Label() self.tmpLabel.set_color(clutter.color_parse('White')) self.tmpLabel.set_position(0, 350) self.tmpLabel.set_text("Test") self.tmpLabel.show() self.stage.add(self.tmpLabel) + """ #The preview img self.main_img = ImageFrame(None, 300, True) #clutter.Texture() diff --git a/modules/myth_tv_player/MythBackendConn.py b/modules/myth_tv_player/MythBackendConn.py index 54ad77b..ac2ceb8 100644 --- a/modules/myth_tv_player/MythBackendConn.py +++ b/modules/myth_tv_player/MythBackendConn.py @@ -77,7 +77,9 @@ class MythBackendConnection(threading.Thread): if not result == protRecvString: #Protocol Version check failed - raise RuntimeError, "Myth Protocol version failure. Aborting." + backend_protocol = result.rsplit("[]:[]")[1] + err_string = "Myth Protocol version failure. This client uses protocol %s however backend is using %s." % (self.protocolVersion, backend_protocol) + raise RuntimeError(err_string) #Perform the mandatory ANN ANNstring = "ANN Playback " + self.localhost_name + " 0" @@ -214,7 +216,8 @@ class MythBackendConnection(threading.Thread): result = self.receive_reply(self.msg_sock) if not result == protRecvString: #Protocol Version check failed - raise RuntimeError, "Myth Protocol version failure. Aborting." + return + #Perform the mandatory ANN (The 1 at the end says that we want to receive all messages from the server) ANNstring = "ANN Monitor " + self.localhost_name + " 1" diff --git a/modules/myth_tv_player/myth_tv_player.py b/modules/myth_tv_player/myth_tv_player.py index f273156..082e4dd 100644 --- a/modules/myth_tv_player/myth_tv_player.py +++ b/modules/myth_tv_player/myth_tv_player.py @@ -38,10 +38,10 @@ class Module: def action(self): return self - def begin(self, menuMgr): - self.menuMgr = menuMgr + def begin(self, glossMgr): + self.glossMgr = glossMgr #self.buffer_file_reader = open("test.mpg","r") - menuMgr.get_selector_bar().set_spinner(True) + glossMgr.get_selector_bar().set_spinner(True) self.loading_scr = SplashScr(self.stage) self.loading_scr.set_msg("Starting TV...") self.loading_scr.backdrop.set_opacity(180) @@ -49,14 +49,22 @@ class Module: (self.server, self.port) = self.dbMgr.get_backend_server() - self.myConn = MythBackendConnection(self, self.server, self.port) + try: + self.myConn = MythBackendConnection(self, self.server, self.port) + except RuntimeError, e: + self.loading_scr.remove_elegant() + glossMgr.get_selector_bar().set_spinner(False) + self.glossMgr.display_msg("Error", str(e.args[0])) + glossMgr.kill_plugin() + return + self.videoController.connect("playing", self.complete_change) self.myConn.start() self.isRunning = True def begin_playback(self, fd):#buffer_file): - self.menuMgr.get_selector_bar().set_spinner(False) + self.glossMgr.get_selector_bar().set_spinner(False) #uri = "file://" + os.getcwd() +"/" + buffer_file #f = open(os.getcwd() +"/" + buffer_file, 'r') diff --git a/ui_elements/label_list.py b/ui_elements/label_list.py index f2c8e4c..4156317 100644 --- a/ui_elements/label_list.py +++ b/ui_elements/label_list.py @@ -1,58 +1,122 @@ import clutter +import pango +from InputQueue import InputQueue class LabelList(clutter.Group): DIRECTION_UP, DIRECTION_DOWN = range(2) - def __init__(self): + fps = 35 + frames = 25 + + #Default font + font_string = "Tahoma 30" + item_gap = 0 + + def __init__(self, length): clutter.Group.__init__(self) + self.items = [] + + #Setup input queue controller + self.input_queue = InputQueue() + self.input_queue.set_action(InputQueue.NORTH, self.move_up) + self.input_queue.set_action(InputQueue.SOUTH, self.move_down) + + self.selected = 0 + self.displayMin = 0 #The number of menu items that will be shown at a time + self.displayMax = length + self.displaySize = self.displayMax - self.displayMin + + def on_key_press_event (self, event): + self.input_queue.input(event) + return self.timeline + + def add_item(self, itemLabel): + if len(self.items) == 0: + #Perform a cheap hack to figure out the height of a label + tempLabel = clutter.Label() + tempLabel.set_font_name(self.font_string) + tempLabel.set_text("S") + + self.label_height = tempLabel.get_height() + label_width = 0 + + label_y = len(self.items) * (self.label_height + self.item_gap) + + newItem = ListItem(self.font_string, itemLabel) + newItem.set_position(0, label_y) + newItem.show() + self.items.append(newItem) + + self.add(newItem) + return newItem + + #Removes all items from the list + def clear(self): + for item in self.items: + self.remove(item) + item = None + self.items = [] + + + def display(self): + if self.displayMax > len(self.items): + self.displayMax = len(self.items) + self.displaySize = self.displayMax - self.displayMin + + #for i in range(self.displaySize): + # self.menuItems[i].show() + + self.show() def move_selection(self, direction): - - #Check if we're at the first item in the list - if (self.selected) != 0: - self.timeline = clutter.Timeline (15,85) - self.input_queue.set_timeline(self.timeline) - #self.timeline.connect('completed', self.completeMove) - - if not self.moveQueue == 0: - self.selected = self.selected -1 #+ self.moveQueue - self.moveQueue = self.moveQueue + 1 # 0 - if self.selected < 0: - self.selected = 0 + + if direction == self.DIRECTION_DOWN: + #Check if we're at the last item in the list + if (self.selected) == (len(self.menuItems)-1): + return + else: + self.selected = self.selected+1 + elif direction == self.DIRECTION_UP: + #Check if we're at the first / last item in the list + if (self.selected) == 0: + return else: self.selected = self.selected-1 - - #This horrible loop does all the scaling - #This includes, the selected item and the ones on either side of it - for i in range(len(self.menuItems)): - #print str(i) - if i == self.selected: - self.menuItems[i].scaleLabel(0, self.timeline) - elif (i == self.selected-1) and (i >= self.displayMin): - self.menuItems[i].scaleLabel(1, self.timeline) - elif (i == self.selected+1) and (i <= self.displayMax-1): - self.menuItems[i].scaleLabel(1, self.timeline) - else: - self.menuItems[i].scaleLabel(2, self.timeline) - - #Do the transition of the menu graphic - #If there's no transition set (Would have been set in the theme) then the item is simply show - if not self.menu_item_transition is None: - self.menu_item_transition.backward(self.timeline, self.menuItems[self.selected+1].itemTexturesGroup, self.menuItems[self.selected].itemTexturesGroup) - else: - self.menuItems[self.selected].itemTexturesGroup.show() - - #Check we're at the top of the viewable list - if self.selected < (self.displayMin): - #If yes, move the menu, leave the selection bar where is - #self.menuItems[self.selected].set_opacity(0) - #self.menuItems[self.selected].show() - self.rollMenu( self.menuItems[self.selected], self.menuItems[self.selected+self.displaySize], self.timeline) - else: - #move the selection bar - self.glossMgr.get_selector_bar().selectItem(self.menuItems[self.selected], self.timeline) + + self.timeline = clutter.Timeline (self.frames, self.fps) + self.input_queue.set_timeline(self.timeline) - self.timeline.start() + + #This horrible loop does all the scaling + #This includes, the selected item and the ones on either side of it + for i in range(len(self.items)): + #print str(i) + if i == self.selected: + self.items[i].scaleLabel(ListItem.SCALE_FULL, self.timeline) + elif (i == self.selected-1) and (i >= self.displayMin): + self.items[i].scaleLabel(ListItem.SCALE_MEDIUM, self.timeline) + elif (i == self.selected+1) and (i <= self.displayMax-1): + self.items[i].scaleLabel(ListItem.SCALE_MEDIUM, self.timeline) + else: + self.items[i].scaleLabel(ListItem.SCALE_None, self.timeline) + + #Check we're at the top of the viewable list + if self.selected < (self.displayMin): + #If yes, move the menu, leave the selection bar where is + #self.menuItems[self.selected].set_opacity(0) + #self.menuItems[self.selected].show() + self.rollList( self.menuItems[self.selected], self.menuItems[self.selected+self.displaySize], self.timeline) + else: + #move the selection bar + self.glossMgr.get_selector_bar().selectItem(self.menuItems[self.selected], self.timeline) + + self.timeline.start() + + def move_up(self): + self.move_selection(self.DIRECTION_UP) + + def move_down(self): + self.move_selection(self.DIRECTION_DOWN) def selectFirst(self, moveBar): if self.timeline.is_playing: @@ -60,13 +124,13 @@ class LabelList(clutter.Group): self.timeline = clutter.Timeline(1, 75) self.selected = 0 - for i in range(0,len(self.menuItems)): + for i in range(0,len(self.items)): if i == 0: - self.menuItems[i].scaleLabel(0, self.timeline) + self.items[i].scaleLabel(ListItem.SCALE_FULL, self.timeline) elif i == 1: - self.menuItems[i].scaleLabel(1, self.timeline) + self.items[i].scaleLabel(ListItem.SCALE_MEDIUM, self.timeline) else: - self.menuItems[i].scaleLabel(2, self.timeline) + self.items[i].scaleLabel(ListItem.SCALE_NONE, self.timeline) #Show the current menu item's graphic self.menuItems[self.selected].itemTexturesGroup.show() @@ -78,7 +142,7 @@ class LabelList(clutter.Group): #When the menu needs to display a new item from the top or bottom, it rolls # The distance the menu moves is the distance (in pixels) between the incoming item and the selector bar - def rollMenu(self, incomingMenuItem, outgoingMenuItem, timeline): + def rollList(self, incomingMenuItem, outgoingMenuItem, timeline): print "Rolling: " + incomingMenuItem.data + "<------" + outgoingMenuItem.data (group_x, group_y) = self.itemGroup.get_abs_position() (bar_x, bar_y) = self.glossMgr.get_selector_bar().get_abs_position() # incomingMenuItem.get_menu().getMenuMgr(). @@ -121,7 +185,7 @@ class LabelList(clutter.Group): self.behaviour2.apply(outgoingMenuItem) -class SimpleListItem(clutter.group): +class ListItem(clutter.Group): SCALE_NONE, SCALE_MEDIUM, SCALE_FULL = range(3) #Default values for zoom and opacity @@ -131,42 +195,31 @@ class SimpleListItem(clutter.group): scale_step_full = 1 scale_step_medium = 0.5 scale_step_none = 0.4 - - #Default font - font_string = "Tahoma 30" - - label_left = clutter.Label() - label_right = clutter.Label() - def __init__ (self, font, label_left = "", label_right = "", y): + def __init__ (self, font, label_left = "", label_right = ""): clutter.Group.__init__ (self) #, menu, itemLabel, y) - self.glossMgr = menu.getGlossMgr() - #self.menu = menu - #self.stage = glossMgr.get_stage() - #ItemTexturesGroup is what shows any images / reflections associated with the item - #self.itemTexturesGroup = clutter.Group() - #self.itemTexturesGroup.set_position(menu.menu_image_x, menu.menu_image_y) + self.label_left = clutter.Label() + self.label_right = clutter.Label() - - #setup the label - """ - font = menu.font - self.set_font_name(font) - self.set_text(itemLabel) + #setup the label/s + self.add(self.label_left) + self.label_left.show() + self.label_left.set_font_name(font) + self.label_left.set_text(label_left) self.color = clutter.Color(0xff, 0xff, 0xff, 0xdd) - self.set_color(self.color) + self.label_left.set_color(self.color) self.currentOpacity = 255 - self.data = itemLabel #By default the items data is simply its label + self.data = label_left #By default the items data is simply its label #The width is the length of the selector bar minus its offset - width = self.glossMgr.get_selector_bar().get_width() + self.glossMgr.get_selector_bar().get_x_offset() - self.set_width(width) + #width = self.glossMgr.get_selector_bar().get_width() + self.glossMgr.get_selector_bar().get_x_offset() + #self.set_width(width) + + self.label_left.set_ellipsize(pango.ELLIPSIZE_END) - self.set_ellipsize(pango.ELLIPSIZE_END) - """ #Text is actually scaled down in 'regular' position so that it doesn't get jaggies when zoomed in - self.set_scale(self.zoomLevel, self.zoomLevel) + #self.set_scale(self.zoomLevel, self.zoomLevel) self.currentZoom = 0 """ @@ -174,10 +227,6 @@ class SimpleListItem(clutter.group): label_x = 0 #x #self.stage.get_width() - label_width - 50 label_y = y #self.stage.get_height() - label_height self.set_position(0, y) - - #Add textures group and mark whether or not the textures are currently on the stage - self.itemTexturesGroup.show_all() - self.onStage = False """ def scaleLabel(self, level, timeline): @@ -217,14 +266,6 @@ class SimpleListItem(clutter.group): def get_zoom_level(self): return self.zoomLevel - - - def add_image_from_path(self, path, x, y): - self.tempTexture = clutter.Texture() - pixbuf = gtk.gdk.pixbuf_new_from_file(path) - tempTexture.set_pixbuf(pixbuf) - - self.add_image_from_texture(tempTexture, x, y) def set_data(self, data): self.data = data