From dceec7074dcf028de202f10f4161cf38068733c6 Mon Sep 17 00:00:00 2001 From: noisymime Date: Thu, 17 Jan 2008 12:27:52 +0000 Subject: [PATCH] Some neat updates/refactoring to the video player module. Folder list now implements the cover viewer to take advantage of all its scrolling abilities --- GlossMgr.py | 15 +- InputQueue.py | 8 +- VideoController.py | 12 +- .../video_player/{ => elements}/CoverItem.py | 0 modules/video_player/elements/__init__.py | 0 .../{ => elements}/cover_viewer.py | 138 +++--------------- .../{ => elements}/folder_menu.py | 18 ++- .../video_player/elements/video_details.py | 84 +++++++++++ modules/video_player/video_object.py | 26 ++++ modules/video_player/video_player.py | 66 ++++----- 10 files changed, 199 insertions(+), 168 deletions(-) rename modules/video_player/{ => elements}/CoverItem.py (100%) create mode 100644 modules/video_player/elements/__init__.py rename modules/video_player/{ => elements}/cover_viewer.py (74%) rename modules/video_player/{ => elements}/folder_menu.py (91%) create mode 100644 modules/video_player/elements/video_details.py create mode 100644 modules/video_player/video_object.py diff --git a/GlossMgr.py b/GlossMgr.py index c524129..28fee48 100644 --- a/GlossMgr.py +++ b/GlossMgr.py @@ -44,11 +44,12 @@ class GlossMgr: print "Perspective: " + str(stage.get_perspective()) #stage.set_perspective(60.0, 1.0, 0.1, 1) + #Setip the selector bar self.selector_bar = MenuSelector(self) - self.stage.add(self.selector_bar)#Load the theme manager - #self.themeMgr = ThemeMgr(self.stage) + self.selector_bar.show_all() + self.stage.add(self.selector_bar) - self.selector_bar.show_all() + self.currentPlugin = None def addMenu(self, newMenu): @@ -61,7 +62,15 @@ class GlossMgr: self.currentMenu.getItemGroup().show_all() self.currentMenu.show_all() self.currentMenu.show() + + #This is a bit hacky, but we set the selector bar size based on the font size + tmpLabel = clutter.Label() + tmpLabel.set_text("AAA") + tmpLabel.set_font_name(self.currentMenu.font) + #Selector bar height is 20% larger than the labels + self.selector_bar.set_height( int(tmpLabel.get_height()*1.2) ) self.selector_bar.set_menu(self.currentMenu) + tmpLabel = None def get_selector_bar(self): return self.selector_bar diff --git a/InputQueue.py b/InputQueue.py index 5d449dc..5b78fc6 100644 --- a/InputQueue.py +++ b/InputQueue.py @@ -74,4 +74,10 @@ class InputQueue: self.queue_east = 0 self.queue_south = 0 self.queue_west = 0 - self.queue_north = 0 \ No newline at end of file + self.queue_north = 0 + + def is_in_queue(self): + if (self.queue_north > 0) or (self.queue_south > 0) or (self.queue_east > 0) or (self.queue_west > 0): + return True + else: + return False \ No newline at end of file diff --git a/VideoController.py b/VideoController.py index 964311d..710ebf2 100644 --- a/VideoController.py +++ b/VideoController.py @@ -33,18 +33,14 @@ class VideoController: #return self.player = player - self.stage.add(self.video_texture) self.video_texture.set_uri(uri) - #fd = uri[5:7] - #self.customBin(fd) - self.video_texture.set_position(0, 0) - self.video_texture.show() + #We need to connect to the message queue on the playbin to watch for any message (ie codec or file not found errors) self.bin = self.video_texture.get_playbin() #print "Queue: " + str(self.bin.get_property("queue_size")) #print "Queue: " + str(self.bin.get_property("queue_threshold")) - print "Queue: " + str(self.bin.get_property("queue_min_threshold")) + #print "Queue: " + str(self.bin.get_property("queue_min_threshold")) bus = self.video_texture.get_playbin().get_bus() bus.add_signal_watch() bus.connect('message', self.on_bus_message) @@ -73,6 +69,10 @@ class VideoController: #self.bin.add(self.queue2) #decodebin.link(self.queue1) #self.queue1.link(decodebin) + self.video_texture.set_opacity(255) + self.video_texture.set_position(0, 0) + self.video_texture.show() + self.stage.add(self.video_texture) return self.video_texture diff --git a/modules/video_player/CoverItem.py b/modules/video_player/elements/CoverItem.py similarity index 100% rename from modules/video_player/CoverItem.py rename to modules/video_player/elements/CoverItem.py diff --git a/modules/video_player/elements/__init__.py b/modules/video_player/elements/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/modules/video_player/cover_viewer.py b/modules/video_player/elements/cover_viewer.py similarity index 74% rename from modules/video_player/cover_viewer.py rename to modules/video_player/elements/cover_viewer.py index 35cd85a..4e09489 100644 --- a/modules/video_player/cover_viewer.py +++ b/modules/video_player/elements/cover_viewer.py @@ -6,7 +6,7 @@ import gobject import pango import clutter import os -from modules.video_player.CoverItem import cover_item +from modules.video_player.elements.CoverItem import cover_item from InputQueue import InputQueue class coverViewer(clutter.Group): @@ -14,7 +14,7 @@ class coverViewer(clutter.Group): inactiveOpacity = 150 covers_size_percent = 0.90 #This is the percentage of the total group size that the covers will take detailBox_height = 160 #Needs a percent - + update_details = False def __init__(self, stage, width, height, rows, columns): @@ -45,7 +45,7 @@ class coverViewer(clutter.Group): self.covers_group_clip.set_clip(-(scale_amount/2), -(scale_amount/2), clip_width, clip_height) - self.current_video_details = video_details_group(self.covers_width) + #self.current_video_details = video_details_group(self.covers_width) self.num_covers = 0 self.cover_gap = 1 @@ -73,25 +73,8 @@ class coverViewer(clutter.Group): self.covers_group_clip.show() #self.stage.add(self.current_video_description) - self.current_video_details.show() - self.current_video_details.show_all() - - #Loads the various UI elements using the theme mgr - def load_theme(self): - pass - - #Turns the description group off and on - def toggle_details(self): - if self.current_video_details.get_parent() == None: - self.add(self.current_video_details) - #Set the position of the details group - (pos_x, pos_y) = self.get_abs_position() - #The next two lines are horribly ugly, but all they do is position the details viewer in the middle of the gap between the bottom of the visible cover viewer and the bottom of the stage - viewer_lower_y = int(pos_y + (self.max_visible_rows * self.cover_size)) - pos_y = viewer_lower_y# + int( (self.stage.get_height() - viewer_lower_y) / 2 - int(self.current_video_details.get_height()/2)) - self.current_video_details.set_position(20, pos_y) - else: - self.stage.remove(self.current_video_details) + #self.current_video_details.show() + #self.current_video_details.show_all() def add_video(self, video): self.videoLibrary.append(video) @@ -135,7 +118,6 @@ class coverViewer(clutter.Group): numFolders = len(self.folderLibrary) if incomingItem >= numFolders: incomingItemVideo = incomingItem - numFolders - self.current_video_details.set_video(self.videoLibrary[incomingItemVideo], self.timeline) #Check if the cover is currently not visible rolling = False @@ -151,7 +133,6 @@ class coverViewer(clutter.Group): alpha = clutter.Alpha(self.timeline, clutter.smoothstep_inc_func)# clutter.ramp_inc_func) self.behaviourNew_scale = clutter.BehaviourScale(scale_start=1, scale_end=self.scaleFactor, alpha=alpha) #clutter.GRAVITY_CENTER) - #self.behaviourNew_scale.set_property("scale-gravity", clutter.GRAVITY_CENTER) self.behaviourNew_z = clutter.BehaviourDepth(depth_start=1, depth_end=2, alpha=alpha) #If we're performing a roll (See above) then the incoming opacity should start at 0 rather than the normal inactive opacity if rolling: @@ -160,7 +141,6 @@ class coverViewer(clutter.Group): self.behaviourNew_opacity = clutter.BehaviourOpacity(opacity_start=self.inactiveOpacity, opacity_end=255, alpha=alpha) self.behaviourOld_scale = clutter.BehaviourScale(scale_start=self.scaleFactor, scale_end=1, alpha=alpha) - #self.behaviourOld_scale.set_property("scale-gravity", clutter.GRAVITY_CENTER) self.behaviourOld_z = clutter.BehaviourDepth(depth_start=2, depth_end=1, alpha=alpha) self.behaviourOld_opacity = clutter.BehaviourOpacity(opacity_start=255, opacity_end=self.inactiveOpacity, alpha=alpha) @@ -196,11 +176,12 @@ class coverViewer(clutter.Group): def select_first(self): self.timeline = clutter.Timeline(20,80) self.input_queue.set_timeline(self.timeline) + """ if not len(self.folderLibrary) == 0: pass else: self.current_video_details.set_video(self.videoLibrary[0], self.timeline) - + """ incomingItem = 0 incomingTexture = self.textureLibrary[incomingItem] @@ -225,16 +206,13 @@ class coverViewer(clutter.Group): alpha = clutter.Alpha(self.timeline, clutter.smoothstep_inc_func) self.behaviourOld_scale = clutter.BehaviourScale(scale_start=self.scaleFactor, scale_end=1, alpha=alpha) - self.behaviourOld_scale.set_property("scale-gravity", clutter.GRAVITY_CENTER) self.behaviourOld_z = clutter.BehaviourDepth(depth_start=2, depth_end=1, alpha=alpha) self.behaviourOld_opacity = clutter.BehaviourOpacity(opacity_start=255, opacity_end=self.inactiveOpacity, alpha=alpha) - self.behaviourOldDetails_opacity = clutter.BehaviourOpacity(opacity_start=255, opacity_end=0, alpha=alpha) current_cover = self.textureLibrary[self.currentSelection] self.behaviourOld_scale.apply(current_cover) self.behaviourOld_z.apply(current_cover) self.behaviourOld_opacity.apply(current_cover) - self.behaviourOldDetails_opacity.apply(self.current_video_details) self.timeline.start() @@ -306,23 +284,24 @@ class coverViewer(clutter.Group): def get_current_item(self): return self.textureLibrary[self.currentSelection] - #If the current item # is greater than the number of folders, we have a video - """ - if self.currentSelection >= len(self.folderLibrary): - selection = self.currentSelection - len(self.folderLibrary) - return self.videoLibrary[selection] - else: - return self.folderLibrary[self.currentSelection] - """ + + def get_current_video(self): + return self.videoLibrary[self.currentSelection] def get_item_x(self, itemNo): return self.textureLibrary[itemNo] def get_item_library(self): return self.textureLibrary + + def set_details_update(self, on_off, details): + self.update_details = on_off + self.details_group = details def on_key_press_event(self, event): self.input_queue.input(event) + return self.timeline + #These are the basic movement functions def move_left(self): @@ -353,85 +332,8 @@ class coverViewer(clutter.Group): #If there is movement, make the scale happen if not newItem == None: self.select_item(newItem, self.currentSelection) + + if self.update_details: + self.details_group.set_video_bare(self.videoLibrary[self.currentSelection]) + self.update_details = False -class video_details_group(clutter.Group): - font = "Lucida Grande " - title_font_size = 30 - main_font_size = 22 - plot_font_size = 18 - backgroundImg = "ui/vid_details_bg.png" - - def __init__(self, desired_width): - clutter.Group.__init__(self) - self.width = desired_width - - """ - self.bgImg = clutter.Texture() - pixbuf = gtk.gdk.pixbuf_new_from_file(self.backgroundImg) - self.bgImg.set_pixbuf(pixbuf) - yx_ratio = float(self.bgImg.get_height()) / float(self.bgImg.get_width()) - bg_height = int(desired_width * yx_ratio) - self.bgImg.set_size(desired_width, bg_height) - #self.bgImg.set_opacity(200) - self.bgImg.show() - self.add(self.bgImg) - """ - - #Add the various labels - self.title = clutter.Label() - self.title.set_font_name(self.font + str(self.title_font_size)) - self.title.set_color(clutter.color_parse('White')) - self.title.set_text("") - self.title.set_ellipsize(pango.ELLIPSIZE_END) - self.add(self.title) - - #Not sure how to get the row height before the text is set :( - self.row_gap = self.title.get_height() - - self.year = clutter.Label() - self.year.set_font_name(self.font + str(self.main_font_size)) - self.year.set_color(clutter.color_parse('White')) - self.year.set_text("") - self.year.set_opacity(220) - self.year.set_ellipsize(pango.ELLIPSIZE_END) - self.year.set_position(0, self.row_gap) - self.add(self.year) - - self.director = clutter.Label() - self.director.set_font_name(self.font + str(self.main_font_size)) - self.director.set_color(clutter.color_parse('White')) - self.director.set_text("") - self.director.set_opacity(220) - self.director.set_ellipsize(pango.ELLIPSIZE_END) - self.director.set_position(int(self.year.get_width()), self.row_gap) - self.add(self.director) - - self.plot = clutter.Label() - self.plot.set_font_name(self.font + str(self.plot_font_size)) - self.plot.set_color(clutter.color_parse('White')) - self.plot.set_text("") - self.plot.set_opacity(220) - #self.plot.set_ellipsize(pango.ELLIPSIZE_END) - self.plot.set_position(0, int(self.row_gap*2)) - self.add(self.plot) - - self.show_all() - - def set_video_bare(self,video): - self.timeline = clutter.Timeline(10,45) - self.set_video(video, self.timeline) - - def set_video(self, video, timeline): - self.video = video - - self.title.set_text(video.title) - self.title.set_width(self.width) - - self.year.set_text("Year: " + str(video.year)) - - self.director.set_text(" Director: " + str(video.director)) - self.director.set_position(int(self.year.get_width()), self.row_gap) - self.director.set_width(int(self.width - self.year.get_width())) - - self.plot.set_text(video.plot) - self.plot.set_width(self.width) \ No newline at end of file diff --git a/modules/video_player/folder_menu.py b/modules/video_player/elements/folder_menu.py similarity index 91% rename from modules/video_player/folder_menu.py rename to modules/video_player/elements/folder_menu.py index e003b64..468176f 100644 --- a/modules/video_player/folder_menu.py +++ b/modules/video_player/elements/folder_menu.py @@ -6,7 +6,8 @@ import gobject import pango import clutter import os -from modules.video_player.CoverItem import cover_item +from modules.video_player.elements.CoverItem import cover_item +from modules.video_player.elements.cover_viewer import coverViewer class folderMenu(clutter.Group): scaleFactor = 1.4 @@ -24,12 +25,17 @@ class folderMenu(clutter.Group): pixbuf = gtk.gdk.pixbuf_new_from_file(self.selection_box_src) self.selector_box.set_pixbuf(pixbuf) self.selector_box.set_size(item_size, item_size) - self.add(self.selector_box) + #self.add(self.selector_box) self.selector_box.show() self.folderLibrary = [] self.viewerLibrary = [] + self.folder_group = coverViewer(self.stage, item_size, (item_size*rows), rows, 1) + self.folder_group.scaleFactor = 1 + self.folder_group.show() + self.add(self.folder_group) + def add_base_dir(self, folderName, cover_viewer): tempItem = cover_item(None, folderName, self.item_size) rows = len(self.folderLibrary) @@ -37,11 +43,13 @@ class folderMenu(clutter.Group): y = rows * self.item_size tempItem.set_position(x, y) tempItem.show() - self.add(tempItem) + #self.add(tempItem) + self.folder_group.add_folder(folderName) #Check if this is the first folder if len(self.folderLibrary) == 0: self.currentItemNo = 0 + self.folder_group.select_first() self.folderLibrary.append(tempItem) self.viewerLibrary.append(cover_viewer) @@ -64,6 +72,7 @@ class folderMenu(clutter.Group): newItemNo = self.currentItemNo + 1 self.switch_viewer(self.viewerLibrary[newItemNo], 1) self.currentItemNo = newItemNo + self.folder_group.on_key_press_event(event) elif (event.keyval == up): #Check if we're already at the end of the line if self.currentItemNo == 0: @@ -72,7 +81,8 @@ class folderMenu(clutter.Group): newItemNo = self.currentItemNo - 1 self.switch_viewer(self.viewerLibrary[newItemNo], -1) self.currentItemNo = newItemNo - + self.folder_group.on_key_press_event(event) + # This is called when the folder menu changes the currently selected folder. # It causes the coverViewer that's currently on display to roll out and new one come in # Direction is negative for up, positive for down diff --git a/modules/video_player/elements/video_details.py b/modules/video_player/elements/video_details.py new file mode 100644 index 0000000..fe0b12e --- /dev/null +++ b/modules/video_player/elements/video_details.py @@ -0,0 +1,84 @@ +import pango +import clutter + +class video_details(clutter.Group): + font = "Lucida Grande " + title_font_size = 30 + main_font_size = 22 + plot_font_size = 18 + backgroundImg = "ui/vid_details_bg.png" + + def __init__(self, desired_width): + clutter.Group.__init__(self) + self.width = desired_width + + """ + self.bgImg = clutter.Texture() + pixbuf = gtk.gdk.pixbuf_new_from_file(self.backgroundImg) + self.bgImg.set_pixbuf(pixbuf) + yx_ratio = float(self.bgImg.get_height()) / float(self.bgImg.get_width()) + bg_height = int(desired_width * yx_ratio) + self.bgImg.set_size(desired_width, bg_height) + #self.bgImg.set_opacity(200) + self.bgImg.show() + self.add(self.bgImg) + """ + + #Add the various labels + self.title = clutter.Label() + self.title.set_font_name(self.font + str(self.title_font_size)) + self.title.set_color(clutter.color_parse('White')) + self.title.set_text("") + self.title.set_ellipsize(pango.ELLIPSIZE_END) + self.add(self.title) + + #Not sure how to get the row height before the text is set :( + self.row_gap = self.title.get_height() + + self.year = clutter.Label() + self.year.set_font_name(self.font + str(self.main_font_size)) + self.year.set_color(clutter.color_parse('White')) + self.year.set_text("") + self.year.set_opacity(220) + self.year.set_ellipsize(pango.ELLIPSIZE_END) + self.year.set_position(0, self.row_gap) + self.add(self.year) + + self.director = clutter.Label() + self.director.set_font_name(self.font + str(self.main_font_size)) + self.director.set_color(clutter.color_parse('White')) + self.director.set_text("") + self.director.set_opacity(220) + self.director.set_ellipsize(pango.ELLIPSIZE_END) + self.director.set_position(int(self.year.get_width()), self.row_gap) + self.add(self.director) + + self.plot = clutter.Label() + self.plot.set_font_name(self.font + str(self.plot_font_size)) + self.plot.set_color(clutter.color_parse('White')) + self.plot.set_text("") + self.plot.set_opacity(220) + #self.plot.set_ellipsize(pango.ELLIPSIZE_END) + self.plot.set_position(0, int(self.row_gap*2)) + self.add(self.plot) + + self.show_all() + + def set_video_bare(self,video): + self.timeline = clutter.Timeline(10,45) + self.set_video(video, self.timeline) + + def set_video(self, video, timeline): + self.video = video + + self.title.set_text(video.title) + self.title.set_width(self.width) + + self.year.set_text("Year: " + str(video.year)) + + self.director.set_text(" Director: " + str(video.director)) + self.director.set_position(int(self.year.get_width()), self.row_gap) + self.director.set_width(int(self.width - self.year.get_width())) + + self.plot.set_text(video.plot) + self.plot.set_width(self.width) \ No newline at end of file diff --git a/modules/video_player/video_object.py b/modules/video_player/video_object.py new file mode 100644 index 0000000..279e716 --- /dev/null +++ b/modules/video_player/video_object.py @@ -0,0 +1,26 @@ +class videoItem(): + def __init(self): + self.mythID = None + + def importFromMythObject(self, mythObject): + self.mythID = mythObject[0] + self.title = mythObject[1] + self.director = mythObject[2] + self.plot = mythObject[3] + self.rating = mythObject[4] + self.inetRef = mythObject[5] + self.year = mythObject[6] + self.userRating = mythObject[7] + self.length = mythObject[8] + self.showLevel = mythObject[9] + self.filename = mythObject[10] + self.coverfile = mythObject[11] + self.childID = mythObject[12] + self.browse = mythObject[13] + self.playCommand = mythObject[14] + self.category = mythObject[15] + + def getTitle(self): + return self.title + def getCoverfile(self): + return self.coverfile \ No newline at end of file diff --git a/modules/video_player/video_player.py b/modules/video_player/video_player.py index b0bc4f9..ec72e62 100644 --- a/modules/video_player/video_player.py +++ b/modules/video_player/video_player.py @@ -8,8 +8,10 @@ import clutter import os from clutter import cluttergst from VideoController import VideoController -from modules.video_player.cover_viewer import coverViewer -from modules.video_player.folder_menu import folderMenu +from modules.video_player.elements.cover_viewer import coverViewer +from modules.video_player.elements.video_details import video_details +from modules.video_player.elements.folder_menu import folderMenu +from modules.video_player.video_object import videoItem #=============================================================================== #This module displays a basic cover viewer for videos within myth's Mythvideo table @@ -56,6 +58,7 @@ class Module(): self.load_base_folders(self.baseDir, base_folder_menu) self.currentViewer = base_folder_menu.get_current_viewer() + self.video_details = video_details(200) def setup_ui(self): self.menu_image = self.glossMgr.themeMgr.get_texture("video_menu_image", None, None) @@ -177,7 +180,15 @@ class Module(): #********************************************************** elif self.controlState == self.STATE_COVERS: if (event.keyval == up) or (event.keyval == down) or (event.keyval == left) or (event.keyval == right): - self.currentViewer.on_key_press_event(event) + timeline = self.currentViewer.on_key_press_event(event) + video = self.currentViewer.get_current_video() + #Do a check to see if the input queue is currently processing + # + if not self.currentViewer.input_queue.is_in_queue(): + self.video_details.set_video_bare(video) + self.currentViewer.set_details_update(False, None) + else: + self.currentViewer.set_details_update(True, self.video_details) if event.keyval == clutter.keysyms.Return: #Find whether the current item is a folder or video @@ -215,18 +226,22 @@ class Module(): self.stage.add(self.covers_background) #Add the folders menu - self.stage.add(self.folderLibrary[0]) + self.folderLibrary[0].set_opacity(0) self.folderLibrary[0].show() + self.stage.add(self.folderLibrary[0]) #Add the cover viewer self.currentViewer.set_opacity(0) self.currentViewer.show_all() self.currentViewer.show() - #self.currentViewer_clip.show() self.currentViewer.set_position(self.coverViewerPosX, self.coverViewerPosY) - - #self.stage.add(self.currentViewer) self.stage.add(self.currentViewer) + + #Add the video details + self.video_details.set_opacity(0) + self.video_details.show_all() + self.video_details.show() + self.stage.add(self.video_details) #Fade everything in @@ -236,13 +251,14 @@ class Module(): self.begin_behaviour.apply(self.backdrop) + self.begin_behaviour.apply(self.folderLibrary[0]) self.begin_behaviour.apply(self.covers_background) self.begin_behaviour.apply(self.currentViewer) - + self.begin_behaviour.apply(self.video_details) #self.viewerLibrary[0].set_position(50, 40) - self.currentViewer.toggle_details() #Turns the details group on + #self.currentViewer.toggle_details() #Turns the details group on #self.currentViewer.select_first() @@ -261,12 +277,16 @@ class Module(): self.stop_behaviour.apply(self.currentViewer) self.stop_behaviour.apply(self.backdrop) self.stop_behaviour.apply(self.folderLibrary[self.folder_level]) + self.stop_behaviour.apply(self.video_details) + self.stop_behaviour.apply(self.covers_background) timeline_stop.connect('completed', self.destroyPlugin) timeline_stop.start() def destroyPlugin(self, data): self.stage.remove(self.currentViewer) self.stage.remove(self.folderLibrary[self.folder_level]) + self.stage.remove(self.video_details) + self.stage.remove(self.covers_background) self.backdrop.hide() #self.stage.remove(self.overlay) @@ -300,32 +320,6 @@ class Module(): def unpause(self): pass - -class videoItem(): - def __init(self): - self.mythID = None - - def importFromMythObject(self, mythObject): - self.mythID = mythObject[0] - self.title = mythObject[1] - self.director = mythObject[2] - self.plot = mythObject[3] - self.rating = mythObject[4] - self.inetRef = mythObject[5] - self.year = mythObject[6] - self.userRating = mythObject[7] - self.length = mythObject[8] - self.showLevel = mythObject[9] - self.filename = mythObject[10] - self.coverfile = mythObject[11] - self.childID = mythObject[12] - self.browse = mythObject[13] - self.playCommand = mythObject[14] - self.category = mythObject[15] - - def getTitle(self): - return self.title - def getCoverfile(self): - return self.coverfile +