Pluggable modules now complete.
This commit is contained in:
parent
34b46395d1
commit
77bc6a25af
7
Menu.py
7
Menu.py
|
@ -70,8 +70,8 @@ class Menu:
|
|||
menu_x = (self.stage.get_width()-self.itemGroup.get_width())/2
|
||||
self.itemGroup.set_position(menu_x, menu_y)
|
||||
self.displayPosition = (menu_x, menu_y)
|
||||
print "Original Group size: " + str(self.itemGroup.get_width())
|
||||
print "Starting at : " + str(menu_x) + ":" + str(menu_y)
|
||||
#print "Original Group size: " + str(self.itemGroup.get_width())
|
||||
#print "Starting at : " + str(menu_x) + ":" + str(menu_y)
|
||||
|
||||
#The display position is the x, y coords of where the menu is when it is active
|
||||
def get_display_position(self):
|
||||
|
@ -299,7 +299,8 @@ class ListItem (clutter.Label):
|
|||
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)
|
||||
self.addImage(imagePath, True)
|
||||
if not (imagePath == "" or imagePath is None):
|
||||
self.addImage(imagePath, True)
|
||||
|
||||
#Add textures group and hide it
|
||||
self.menu.getMenuGroup().add(self.itemTexturesGroup)
|
||||
|
|
|
@ -147,6 +147,12 @@ class MenuMgr:
|
|||
|
||||
def get_current_menu(self):
|
||||
return self.currentMenu
|
||||
|
||||
def go_up_x_levels(self, num_levels):
|
||||
for i in range(1, num_levels):
|
||||
if len(self.menuHistory)>1:
|
||||
self.transition_fade_zoom(self.menuHistory.pop(), self.menuHistory[-1])
|
||||
self.currentMenu = self.menuHistory[-1]
|
||||
|
||||
class MenuSelector(clutter.Texture):
|
||||
x_offset = -50
|
||||
|
|
BIN
MenuMgr.pyc
BIN
MenuMgr.pyc
Binary file not shown.
|
@ -8,6 +8,7 @@ class VideoController:
|
|||
self.stage = stage
|
||||
self.overlay = None
|
||||
self.blackdrop = None
|
||||
|
||||
# Primary video texture & sink definition
|
||||
self.video_texture = clutter.cluttergst.VideoTexture()
|
||||
self.video_sink = clutter.cluttergst.VideoSink(self.video_texture)
|
||||
|
@ -48,7 +49,9 @@ class VideoController:
|
|||
self.isPlaying = True
|
||||
|
||||
return self.video_texture
|
||||
|
||||
|
||||
#This handles any messages that are sent accross the playbin
|
||||
#Currently the only message being checked for it a "codec not found"
|
||||
def on_bus_message(self, bus, message):
|
||||
t = message.type
|
||||
|
||||
|
@ -69,6 +72,7 @@ class VideoController:
|
|||
def stop_video(self):
|
||||
if self.video_texture.get_playing():
|
||||
self.isPlaying = False
|
||||
self.player.stop_video()
|
||||
self.player = None
|
||||
self.video_texture.set_playing(False)
|
||||
|
||||
|
@ -77,13 +81,13 @@ class VideoController:
|
|||
alpha = clutter.Alpha(timeline, clutter.ramp_inc_func)
|
||||
self.behaviour = clutter.BehaviourOpacity(alpha, 255,0)
|
||||
self.behaviour.apply(self.video_texture)
|
||||
#behaviour.apply(self.blackdrop)
|
||||
self.behaviour.apply(self.blackdrop)
|
||||
|
||||
timeline.start()
|
||||
|
||||
def end_video_event(self, data):
|
||||
self.stage.remove(self.video_texture)
|
||||
# self.stage.remove(self.blackdrop)
|
||||
self.stage.remove(self.blackdrop)
|
||||
self.blackdrop = None
|
||||
|
||||
def customBin(self):
|
||||
|
|
65
gloss.py
65
gloss.py
|
@ -60,31 +60,14 @@ class MainApp:
|
|||
|
||||
#Update splash status msg
|
||||
self.splashScreen.set_msg("Creating menus")
|
||||
menu1 = Menu(self.menuMgr)
|
||||
menu1.addItem("TV", "ui/dvd.png")
|
||||
menu1.addItem("Slideshow", "ui/gallery.png")
|
||||
menu1.addItem("Videos", "ui/videos.png")
|
||||
menu1.addItem("Link", "ui/link.png")
|
||||
menu1.addItem("DVD", "ui/dvd.png")
|
||||
menu1.addItem("nothing", "ui/dvd.png")
|
||||
menu1.addItem("nothing", "ui/dvd.png")
|
||||
menu1.addItem("nothing", "ui/dvd.png")
|
||||
MainMenu = Menu(self.menuMgr)
|
||||
#menu1.addItem("nothing", "ui/dvd.png")
|
||||
#menu1.addItem("nothing", "ui/dvd.png")
|
||||
#menu1.addItem("nothing", "ui/dvd.png")
|
||||
|
||||
#menu1.setListFont('Tahoma 42')
|
||||
menu1.setMenuPositionByName("center")
|
||||
self.menu1 = menu1
|
||||
|
||||
self.menu2 = Menu(self.menuMgr)
|
||||
self.menu2.addItem("Nothing", "ui/dvd.png")
|
||||
self.menu2.addItem("Link", "ui/gallery.png")
|
||||
self.menu2.addItem("blah3", "ui/game.png")
|
||||
self.menu2.addItem("blah4", "ui/music.png")
|
||||
self.menu2.addItem("blah", "ui/dvd.png")
|
||||
self.menu2.addItem("blah2", "ui/dvd.png")
|
||||
self.menu2.addItem("blah3", "ui/dvd.png")
|
||||
self.menu2.addItem("blah4", "ui/dvd.png")
|
||||
#self.menu2.setListFont('Tahoma 42')
|
||||
self.menu2.setMenuPositionByName("center")
|
||||
MainMenu.setMenuPositionByName("center")
|
||||
#self.MainMenu = menu
|
||||
|
||||
|
||||
#Update splash status msg
|
||||
|
@ -93,35 +76,19 @@ class MainApp:
|
|||
self.dbMgr = mythDB()
|
||||
|
||||
#Update splash status msg
|
||||
self.splashScreen.set_msg("Loading gallery")
|
||||
self.mySlideshow = modules[0].Slideshow(self.menuMgr, self.dbMgr)
|
||||
|
||||
#Update splash status msg
|
||||
self.splashScreen.set_msg("Loading videos")
|
||||
self.vidPlayer = modules[2].VideoPlayer(self.stage, self.dbMgr)
|
||||
#Update splash status msg
|
||||
self.splashScreen.set_msg("Setting up TV player")
|
||||
self.tvPlayer = modules[1].TVPlayer(self.stage, self.dbMgr)
|
||||
#Update splash status msg
|
||||
self.splashScreen.set_msg("Setting up DVD player")
|
||||
self.dvdPlayer = modules[3].DvdPlayer(self.stage)
|
||||
#Update splash status msg
|
||||
self.splashScreen.set_msg("Setting up Music player")
|
||||
self.musicPlayer = modules[4].MusicPlayer(self.stage)
|
||||
|
||||
menu1.getItem(0).setAction(self.tvPlayer)
|
||||
#menu1.getItem(1).setAction(self.mySlideshow)
|
||||
menu1.getItem(1).setAction(self.mySlideshow.generateMenu())
|
||||
menu1.getItem(2).setAction(self.vidPlayer)
|
||||
menu1.getItem(3).setAction(self.menu2)
|
||||
menu1.getItem(4).setAction(self.dvdPlayer)
|
||||
|
||||
self.menu2.getItem(1).setAction(self.menu1)
|
||||
for mods in modules:
|
||||
title = mods.Module.title
|
||||
image_uri = "ui/"+mods.Module.menu_image
|
||||
self.splashScreen.set_msg("Loading "+title)
|
||||
tempMod = mods.Module(self.menuMgr, self.dbMgr)
|
||||
temp_menu_item = MainMenu.addItem(title, image_uri)
|
||||
|
||||
temp_menu_item.setAction(tempMod.action())
|
||||
|
||||
self.splashScreen.remove()
|
||||
self.stage.connect('key-press-event', self.menuMgr.on_key_press_event)
|
||||
self.menu1.display()
|
||||
self.menu1.selectFirst(True)
|
||||
MainMenu.display()
|
||||
MainMenu.selectFirst(True)
|
||||
|
||||
return False
|
||||
#print self.menuMgr.get_selector_bar().get_abs_position()
|
||||
|
|
|
@ -2,15 +2,19 @@ import clutter
|
|||
from clutter import cluttergst
|
||||
from VideoController import VideoController
|
||||
|
||||
class DvdPlayer:
|
||||
class Module:
|
||||
title = "DVD"
|
||||
menu_image = "dvd.png"
|
||||
|
||||
def __init__(self, Stage):
|
||||
self.stage = Stage
|
||||
def __init__(self, MenuMgr, dbMgr):
|
||||
self.stage = MenuMgr.get_stage()
|
||||
self.paused = False
|
||||
self.isPlaying = False
|
||||
self.overlay = None
|
||||
|
||||
|
||||
#Action to take when menu item is selected
|
||||
def action(self):
|
||||
return self
|
||||
|
||||
def on_key_press_event (self, stage, event):
|
||||
if self.isPlaying:
|
||||
|
|
|
@ -3,14 +3,20 @@ import gtk
|
|||
import clutter
|
||||
import eyeD3
|
||||
|
||||
class MusicPlayer():
|
||||
class Module():
|
||||
title = "Music"
|
||||
menu_image = "dvd.png"
|
||||
|
||||
def __init__(self, stage):
|
||||
self.stage = stage
|
||||
def __init__(self, MenuMgr, dbMgr):
|
||||
self.stage = MenuMgr.get_stage()
|
||||
self.cover_viewer = coverViewer(self.stage)
|
||||
|
||||
self.is_playing = False
|
||||
|
||||
#Action to take when menu item is selected
|
||||
def action(self):
|
||||
return self
|
||||
|
||||
def on_key_press_event (self, stage, event):
|
||||
if event.keyval == clutter.keysyms.p:
|
||||
if self.paused:
|
||||
|
|
|
@ -9,14 +9,19 @@ from modules.myth_tv_player.MythBackendConn import MythBackendConnection
|
|||
from Menu import Menu
|
||||
from VideoController import VideoController
|
||||
|
||||
class TVPlayer:
|
||||
class Module:
|
||||
title = "TV"
|
||||
menu_image = "dvd.png"
|
||||
|
||||
def __init__(self, stage, dbMgr):
|
||||
self.videoController = VideoController(stage)
|
||||
self.stage = stage
|
||||
def __init__(self, MenuMgr, dbMgr):
|
||||
self.stage = MenuMgr.get_stage()
|
||||
self.videoController = VideoController(self.stage)
|
||||
self.dbMgr = dbMgr
|
||||
self.isRunning = False
|
||||
|
||||
|
||||
#Action to take when menu item is selected
|
||||
def action(self):
|
||||
return self
|
||||
|
||||
def begin(self, menuMgr):
|
||||
self.menuMgr = menuMgr
|
||||
|
|
|
@ -9,7 +9,10 @@ import gtk
|
|||
import random
|
||||
#import thread
|
||||
|
||||
class Slideshow:
|
||||
class Module:
|
||||
title = "Slideshow"
|
||||
menu_image= "gallery.png"
|
||||
|
||||
image_file_types = ["jpg", "gif", "jpeg", "png", "bmp"]
|
||||
sound_file_types = ["mp3", "wav", "ogg"] #possibly more supported by default?
|
||||
imageDuration = 7 # In seconds
|
||||
|
@ -28,6 +31,9 @@ class Slideshow:
|
|||
#Load the base image directory. This is pulled from the myth db's settings table
|
||||
self.baseDir = dbMgr.get_setting('GalleryDir')
|
||||
|
||||
def action(self):
|
||||
return self.generateMenu()
|
||||
|
||||
def on_key_press_event (self, stage, event):
|
||||
#print event.hardware_keycode
|
||||
if event.keyval == clutter.keysyms.p:
|
||||
|
@ -90,6 +96,10 @@ class Slideshow:
|
|||
def begin(self, MenuMgr):
|
||||
self.stage = self.MenuMgr.get_stage()
|
||||
|
||||
#Check for an empty baseDir, this means there are no slideshows or no db connection. We simply tell the menuMgr to go back a menu level when this occurs
|
||||
if self.baseDir is None:
|
||||
MenuMgr.go_up_x_levels(1)
|
||||
return
|
||||
#self.MenuMgr.get_selector_bar().set_spinner(True)
|
||||
#self.stage.queue_redraw()
|
||||
|
||||
|
@ -326,6 +336,12 @@ class Slideshow:
|
|||
|
||||
tempMenu = Menu(self.MenuMgr)
|
||||
#print self.baseDir
|
||||
#This occurs when there are not slideshows or we could not connect to the db to establish baseDir
|
||||
if self.baseDir is None:
|
||||
tempItem = tempMenu.addItem("No slideshows available", "")
|
||||
tempItem.setAction(self)
|
||||
return
|
||||
|
||||
file_list = os.listdir(self.baseDir)
|
||||
|
||||
for directoryEntry in file_list:
|
||||
|
@ -334,7 +350,7 @@ class Slideshow:
|
|||
if not (len(os.listdir(subdir)) == 0):
|
||||
imgPath = subdir + "/" + os.listdir(subdir)[0]
|
||||
#print imgPath
|
||||
tempItem = tempMenu.addItem(directoryEntry, "/home/josh/.mythtv/MythVideo/0088763.jpg")
|
||||
tempItem = tempMenu.addItem(directoryEntry, "")
|
||||
tempItem.setAction(self)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,327 @@
|
|||
import pygtk
|
||||
import gtk
|
||||
import pygst
|
||||
import gst
|
||||
import gobject
|
||||
import pango
|
||||
import clutter
|
||||
|
||||
class coverViewer(clutter.Group):
|
||||
scaleFactor = 1.4
|
||||
inactiveOpacity = 150
|
||||
|
||||
|
||||
def __init__(self, stage, width, height):
|
||||
clutter.Group.__init__(self)
|
||||
self.stage = stage
|
||||
self.videoLibrary = []
|
||||
self.textureLibrary = []
|
||||
self.current_video_details = video_details_group(width)
|
||||
self.covers_group = clutter.Group()
|
||||
self.num_covers = 0
|
||||
|
||||
self.cover_gap = 1
|
||||
|
||||
self.num_visible_rows = 3
|
||||
self.num_columns = 4
|
||||
self.cover_size = int(width / self.num_columns) #200 #A cover will be cover_size * cover_size (X * Y)
|
||||
|
||||
#Setup the current min and max viewable rows
|
||||
self.min_visible_rows = 0
|
||||
self.max_visible_rows = self.num_visible_rows
|
||||
|
||||
self.currentSelection = 0
|
||||
|
||||
self.add(self.covers_group)
|
||||
self.covers_group.show()
|
||||
|
||||
#self.stage.add(self.current_video_description)
|
||||
self.current_video_details.show()
|
||||
self.current_video_details.show_all()
|
||||
|
||||
|
||||
#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)
|
||||
|
||||
def add_video(self, video):
|
||||
self.videoLibrary.append(video)
|
||||
imagePath = video.getCoverfile()
|
||||
tempTexture = clutter.Texture()
|
||||
pixbuf = gtk.gdk.pixbuf_new_from_file(imagePath)
|
||||
tempTexture.set_pixbuf(pixbuf)
|
||||
xy_ratio = float(tempTexture.get_width()) / tempTexture.get_height()
|
||||
|
||||
width = int(self.cover_size * xy_ratio)
|
||||
tempTexture.set_width(width)
|
||||
tempTexture.set_height(self.cover_size)
|
||||
tempTexture.set_opacity(self.inactiveOpacity)
|
||||
|
||||
tempTexture.set_position( (self.num_covers * self.cover_size), 0)
|
||||
tempTexture.set_depth(1)
|
||||
|
||||
self.textureLibrary.append(tempTexture)
|
||||
|
||||
#x = (self.cover_gap + self.cover_size) * (self.num_covers/self.num_rows)
|
||||
#y = (self.num_covers % self.num_rows) * self.cover_size + ( (self.num_covers % self.num_rows) * self.cover_gap)
|
||||
x = (self.num_covers % self.num_columns) * self.cover_size + ( (self.num_covers % self.num_columns) * self.cover_gap)
|
||||
y = (self.cover_gap + self.cover_size) * (self.num_covers/self.num_columns)
|
||||
|
||||
#Center the cover
|
||||
if width < self.cover_size:
|
||||
x = x + (self.cover_size - width)/2
|
||||
|
||||
tempTexture.set_position(x, y)
|
||||
|
||||
#If we're past the maximum rows, make the pics invistible
|
||||
if self.num_covers > (self.num_columns * self.num_visible_rows)-1:
|
||||
tempTexture.set_opacity(0)
|
||||
else:
|
||||
self.covers_group.add(tempTexture)
|
||||
|
||||
tempTexture.show()
|
||||
self.num_covers = self.num_covers +1
|
||||
|
||||
def select_item(self, incomingItem, outgoingItem):
|
||||
self.timeline = clutter.Timeline(10,35)
|
||||
self.current_video_details.set_video(self.videoLibrary[incomingItem], self.timeline)
|
||||
|
||||
#Check if the cover is currently not visible
|
||||
rolling = False
|
||||
if incomingItem > (self.num_columns * self.max_visible_rows-1):
|
||||
self.rollViewer(True, self.timeline)
|
||||
rolling = True
|
||||
if incomingItem < (self.num_columns * self.min_visible_rows):
|
||||
self.rollViewer(False, self.timeline)
|
||||
rolling = True
|
||||
|
||||
outgoingTexture = self.textureLibrary[outgoingItem]
|
||||
incomingTexture = self.textureLibrary[incomingItem]
|
||||
|
||||
alpha = clutter.Alpha(self.timeline, clutter.smoothstep_inc_func)# clutter.ramp_inc_func)
|
||||
self.behaviourNew_scale = clutter.BehaviourScale(alpha, 1, self.scaleFactor, clutter.GRAVITY_CENTER)
|
||||
self.behaviourNew_z = clutter.BehaviourDepth(alpha, 1, 2)
|
||||
#If we're performing a roll (See above) then the incoming opacity should start at 0 rather than the normal inactive opacity
|
||||
if rolling:
|
||||
self.behaviourNew_opacity = clutter.BehaviourOpacity(alpha, 0, 255)
|
||||
else:
|
||||
self.behaviourNew_opacity = clutter.BehaviourOpacity(alpha, self.inactiveOpacity, 255)
|
||||
|
||||
self.behaviourOld_scale = clutter.BehaviourScale(alpha, self.scaleFactor, 1, clutter.GRAVITY_CENTER)
|
||||
self.behaviourOld_z = clutter.BehaviourDepth(alpha, 2, 1)
|
||||
self.behaviourOld_opacity = clutter.BehaviourOpacity(alpha, 255, self.inactiveOpacity)
|
||||
|
||||
self.behaviourNew_scale.apply(incomingTexture)
|
||||
self.behaviourNew_z.apply(incomingTexture)
|
||||
self.behaviourNew_opacity.apply(incomingTexture)
|
||||
self.behaviourOld_scale.apply(outgoingTexture)
|
||||
self.behaviourOld_z.apply(outgoingTexture)
|
||||
self.behaviourOld_opacity.apply(outgoingTexture)
|
||||
|
||||
self.currentSelection = incomingItem
|
||||
|
||||
self.timeline.start()
|
||||
|
||||
def select_first(self):
|
||||
self.timeline = clutter.Timeline(20,80)
|
||||
self.current_video_details.set_video(self.videoLibrary[0], self.timeline)
|
||||
|
||||
|
||||
incomingItem = 0
|
||||
incomingTexture = self.textureLibrary[incomingItem]
|
||||
|
||||
alpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
|
||||
self.behaviourNew_scale = clutter.BehaviourScale(alpha, 1, self.scaleFactor, clutter.GRAVITY_CENTER)
|
||||
self.behaviourNew_z = clutter.BehaviourDepth(alpha, 1, 2)
|
||||
self.behaviourNew_opacity = clutter.BehaviourOpacity(alpha, self.inactiveOpacity, 255)
|
||||
|
||||
self.behaviourNew_scale.apply(incomingTexture)
|
||||
self.behaviourNew_z.apply(incomingTexture)
|
||||
self.behaviourNew_opacity.apply(incomingTexture)
|
||||
|
||||
self.currentSelection = incomingItem
|
||||
self.timeline.start()
|
||||
|
||||
#This moves the visible row of covers up and down
|
||||
# moveUp: True if the covers are to come up, false if they're to go down
|
||||
def rollViewer(self, moveUp, timeline):
|
||||
if moveUp:
|
||||
new_y = self.covers_group.get_y() - self.cover_size
|
||||
self.max_visible_rows = self.max_visible_rows + 1
|
||||
self.min_visible_rows = self.min_visible_rows + 1
|
||||
|
||||
#Define the row of covers that now needs to disapear / appear
|
||||
min_outgoing = (self.min_visible_rows-1) * self.num_columns
|
||||
max_outgoing = min_outgoing + self.num_columns
|
||||
min_incoming = (self.max_visible_rows-1) * self.num_columns
|
||||
max_incoming = min_incoming + self.num_columns
|
||||
|
||||
#Quick check to make sure that max_incoming isn't greater than the max number of images (This occurs when the final row is incomplete)
|
||||
if max_incoming > self.num_covers:
|
||||
max_incoming = min_incoming + (self.num_covers % self.num_columns)
|
||||
else:
|
||||
new_y = self.covers_group.get_y() + self.cover_size
|
||||
self.max_visible_rows = self.max_visible_rows - 1
|
||||
self.min_visible_rows = self.min_visible_rows - 1
|
||||
|
||||
#Define the row of covers that now needs to disapear / appear
|
||||
min_incoming = (self.min_visible_rows) * self.num_columns
|
||||
max_incoming = min_incoming + self.num_columns
|
||||
min_outgoing = (self.max_visible_rows) * self.num_columns
|
||||
max_outgoing = min_outgoing + self.num_columns
|
||||
|
||||
#Quick check to make sure that max_outgoing isn't greater than the max number of images (This occurs when the final row is incomplete)
|
||||
if max_outgoing > self.num_covers:
|
||||
max_outgoing = min_outgoing + (self.num_covers % self.num_columns)
|
||||
|
||||
#Need to add the new row to the group
|
||||
self.addIncomingRow(min_incoming, max_incoming)
|
||||
#And set the outgoing row to remove after the timeline finishes
|
||||
self.timeline.connect('completed', self.removeOutgoingRow, min_outgoing, max_outgoing)
|
||||
|
||||
|
||||
knots = (\
|
||||
(self.covers_group.get_x(), self.covers_group.get_y()),\
|
||||
(self.covers_group.get_x(), new_y) \
|
||||
)
|
||||
|
||||
alpha = clutter.Alpha(timeline, clutter.ramp_inc_func)
|
||||
self.behaviour_path = clutter.BehaviourPath(alpha, knots)
|
||||
self.behaviour_incoming = clutter.BehaviourOpacity(alpha, 0, self.inactiveOpacity)
|
||||
self.behaviour_outgoing = clutter.BehaviourOpacity(alpha, self.inactiveOpacity, 0)
|
||||
|
||||
self.behaviour_path.apply(self.covers_group)
|
||||
#Also need to change a few opacities - This is really messy, but works
|
||||
for i in range(min_outgoing, max_outgoing):
|
||||
self.behaviour_outgoing.apply(self.textureLibrary[i])
|
||||
for i in range(min_incoming, max_incoming):
|
||||
self.behaviour_incoming.apply(self.textureLibrary[i])
|
||||
|
||||
def removeOutgoingRow(self, timeline, min, max):
|
||||
for i in range(min, max):
|
||||
self.covers_group.remove(self.textureLibrary[i])
|
||||
|
||||
def addIncomingRow(self, min, max):
|
||||
for i in range(min, max):
|
||||
self.covers_group.add(self.textureLibrary[i])
|
||||
|
||||
#xy_ratio = float(self.textureLibrary[i].get_width()) / self.textureLibrary[i].get_height()
|
||||
#width = int(self.cover_size * xy_ratio)
|
||||
|
||||
#x = (i % self.num_columns) * self.cover_size + ( (i % self.num_columns) * self.cover_gap)
|
||||
#y = (self.cover_gap + self.cover_size) * (i/self.num_columns)
|
||||
|
||||
#Center the cover
|
||||
#if width < self.cover_size:
|
||||
# x = x + (self.cover_size - width)/2
|
||||
|
||||
#self.textureLibrary[i].set_position(x, y)
|
||||
self.textureLibrary[i].show()
|
||||
|
||||
def get_current_video(self):
|
||||
return self.videoLibrary[self.currentSelection]
|
||||
|
||||
def on_key_press_event(self, event):
|
||||
newItem = None
|
||||
if event.keyval == clutter.keysyms.Left:
|
||||
#Make sure we're not already on the first cover
|
||||
if not self.currentSelection == 0:
|
||||
newItem = self.currentSelection - 1
|
||||
elif event.keyval == clutter.keysyms.Right:
|
||||
#This check makes sure that we're not on the last cover already
|
||||
if not self.currentSelection == (self.num_covers-1):
|
||||
newItem = self.currentSelection + 1
|
||||
elif event.keyval == clutter.keysyms.Down:
|
||||
#Check if we're already on the bottom row
|
||||
if not (self.currentSelection > (len(self.textureLibrary)-1 - self.num_columns)):
|
||||
newItem = self.currentSelection + self.num_columns
|
||||
elif event.keyval == clutter.keysyms.Up:
|
||||
#Check if we're already on the top row
|
||||
if not (self.currentSelection < self.num_columns):
|
||||
newItem = self.currentSelection - self.num_columns
|
||||
|
||||
#Final sanity check
|
||||
if (newItem < 0) and (not newItem == None):
|
||||
newItem = self.currentSelection
|
||||
|
||||
#If there is movement, make the scale happen
|
||||
if not newItem == None:
|
||||
self.select_item(newItem, self.currentSelection)
|
||||
|
||||
class video_details_group(clutter.Group):
|
||||
font = "Lucida Grande "
|
||||
title_font_size = 30
|
||||
main_font_size = 22
|
||||
plot_font_size = 18
|
||||
|
||||
def __init__(self, desired_width):
|
||||
clutter.Group.__init__(self)
|
||||
self.width = desired_width
|
||||
|
||||
#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)
|
|
@ -7,13 +7,16 @@ import pango
|
|||
import clutter
|
||||
from clutter import cluttergst
|
||||
from VideoController import VideoController
|
||||
from modules.video_player.cover_viewer import coverViewer
|
||||
|
||||
class VideoPlayer():
|
||||
class Module():
|
||||
title = "Videos"
|
||||
menu_image= "videos.png"
|
||||
|
||||
def __init__(self, stage, dbMgr):
|
||||
self.stage = stage
|
||||
def __init__(self, MenuMgr, dbMgr):
|
||||
self.stage = MenuMgr.get_stage()
|
||||
self.cover_viewer = coverViewer(self.stage, 800, 600)
|
||||
self.videoController = VideoController(stage)
|
||||
self.videoController = VideoController(self.stage)
|
||||
self.is_playing = False
|
||||
|
||||
#This block can be moved to begin() but causes a performance hit when loading the module *shrug*
|
||||
|
@ -27,7 +30,9 @@ class VideoPlayer():
|
|||
tempVideo.importFromMythObject(record)
|
||||
self.cover_viewer.add_video(tempVideo)
|
||||
|
||||
|
||||
#Action to take when menu item is selected
|
||||
def action(self):
|
||||
return self
|
||||
|
||||
def on_key_press_event (self, stage, event):
|
||||
if self.is_playing:
|
||||
|
@ -120,6 +125,16 @@ class VideoPlayer():
|
|||
|
||||
self.is_playing = False
|
||||
|
||||
timeline = clutter.Timeline(15, 25)
|
||||
self.cover_viewer.set_opacity(0)
|
||||
alpha = clutter.Alpha(timeline, clutter.ramp_inc_func)
|
||||
self.behaviour = clutter.BehaviourOpacity(alpha, 0,255)
|
||||
self.behaviour.apply(self.cover_viewer)
|
||||
|
||||
self.stage.add(self.cover_viewer)
|
||||
self.cover_viewer.show()
|
||||
timeline.start()
|
||||
|
||||
def pause(self):
|
||||
pass
|
||||
|
||||
|
@ -153,321 +168,4 @@ class videoItem():
|
|||
def getCoverfile(self):
|
||||
return self.coverfile
|
||||
|
||||
class coverViewer(clutter.Group):
|
||||
scaleFactor = 1.4
|
||||
inactiveOpacity = 150
|
||||
|
||||
def __init__(self, stage, width, height):
|
||||
clutter.Group.__init__(self)
|
||||
self.stage = stage
|
||||
self.videoLibrary = []
|
||||
self.textureLibrary = []
|
||||
self.current_video_details = video_details_group(width)
|
||||
self.covers_group = clutter.Group()
|
||||
self.num_covers = 0
|
||||
|
||||
self.cover_gap = 1
|
||||
|
||||
self.num_visible_rows = 3
|
||||
self.num_columns = 4
|
||||
self.cover_size = int(width / self.num_columns) #200 #A cover will be cover_size * cover_size (X * Y)
|
||||
|
||||
#Setup the current min and max viewable rows
|
||||
self.min_visible_rows = 0
|
||||
self.max_visible_rows = self.num_visible_rows
|
||||
|
||||
self.currentSelection = 0
|
||||
|
||||
self.add(self.covers_group)
|
||||
self.covers_group.show()
|
||||
|
||||
#self.stage.add(self.current_video_description)
|
||||
self.current_video_details.show()
|
||||
self.current_video_details.show_all()
|
||||
|
||||
|
||||
#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)
|
||||
|
||||
def add_video(self, video):
|
||||
self.videoLibrary.append(video)
|
||||
imagePath = video.getCoverfile()
|
||||
tempTexture = clutter.Texture()
|
||||
pixbuf = gtk.gdk.pixbuf_new_from_file(imagePath)
|
||||
tempTexture.set_pixbuf(pixbuf)
|
||||
xy_ratio = float(tempTexture.get_width()) / tempTexture.get_height()
|
||||
|
||||
width = int(self.cover_size * xy_ratio)
|
||||
tempTexture.set_width(width)
|
||||
tempTexture.set_height(self.cover_size)
|
||||
tempTexture.set_opacity(self.inactiveOpacity)
|
||||
|
||||
tempTexture.set_position( (self.num_covers * self.cover_size), 0)
|
||||
tempTexture.set_depth(1)
|
||||
|
||||
self.textureLibrary.append(tempTexture)
|
||||
|
||||
#x = (self.cover_gap + self.cover_size) * (self.num_covers/self.num_rows)
|
||||
#y = (self.num_covers % self.num_rows) * self.cover_size + ( (self.num_covers % self.num_rows) * self.cover_gap)
|
||||
x = (self.num_covers % self.num_columns) * self.cover_size + ( (self.num_covers % self.num_columns) * self.cover_gap)
|
||||
y = (self.cover_gap + self.cover_size) * (self.num_covers/self.num_columns)
|
||||
|
||||
#Center the cover
|
||||
if width < self.cover_size:
|
||||
x = x + (self.cover_size - width)/2
|
||||
|
||||
tempTexture.set_position(x, y)
|
||||
|
||||
#If we're past the maximum rows, make the pics invistible
|
||||
if self.num_covers > (self.num_columns * self.num_visible_rows)-1:
|
||||
tempTexture.set_opacity(0)
|
||||
else:
|
||||
self.covers_group.add(tempTexture)
|
||||
|
||||
tempTexture.show()
|
||||
self.num_covers = self.num_covers +1
|
||||
|
||||
def select_item(self, incomingItem, outgoingItem):
|
||||
self.timeline = clutter.Timeline(10,35)
|
||||
self.current_video_details.set_video(self.videoLibrary[incomingItem], self.timeline)
|
||||
|
||||
#Check if the cover is currently not visible
|
||||
rolling = False
|
||||
if incomingItem > (self.num_columns * self.max_visible_rows-1):
|
||||
self.rollViewer(True, self.timeline)
|
||||
rolling = True
|
||||
if incomingItem < (self.num_columns * self.min_visible_rows):
|
||||
self.rollViewer(False, self.timeline)
|
||||
rolling = True
|
||||
|
||||
outgoingTexture = self.textureLibrary[outgoingItem]
|
||||
incomingTexture = self.textureLibrary[incomingItem]
|
||||
|
||||
alpha = clutter.Alpha(self.timeline, clutter.smoothstep_inc_func)# clutter.ramp_inc_func)
|
||||
self.behaviourNew_scale = clutter.BehaviourScale(alpha, 1, self.scaleFactor, clutter.GRAVITY_CENTER)
|
||||
self.behaviourNew_z = clutter.BehaviourDepth(alpha, 1, 2)
|
||||
#If we're performing a roll (See above) then the incoming opacity should start at 0 rather than the normal inactive opacity
|
||||
if rolling:
|
||||
self.behaviourNew_opacity = clutter.BehaviourOpacity(alpha, 0, 255)
|
||||
else:
|
||||
self.behaviourNew_opacity = clutter.BehaviourOpacity(alpha, self.inactiveOpacity, 255)
|
||||
|
||||
self.behaviourOld_scale = clutter.BehaviourScale(alpha, self.scaleFactor, 1, clutter.GRAVITY_CENTER)
|
||||
self.behaviourOld_z = clutter.BehaviourDepth(alpha, 2, 1)
|
||||
self.behaviourOld_opacity = clutter.BehaviourOpacity(alpha, 255, self.inactiveOpacity)
|
||||
|
||||
self.behaviourNew_scale.apply(incomingTexture)
|
||||
self.behaviourNew_z.apply(incomingTexture)
|
||||
self.behaviourNew_opacity.apply(incomingTexture)
|
||||
self.behaviourOld_scale.apply(outgoingTexture)
|
||||
self.behaviourOld_z.apply(outgoingTexture)
|
||||
self.behaviourOld_opacity.apply(outgoingTexture)
|
||||
|
||||
self.currentSelection = incomingItem
|
||||
|
||||
self.timeline.start()
|
||||
|
||||
def select_first(self):
|
||||
self.timeline = clutter.Timeline(20,80)
|
||||
self.current_video_details.set_video(self.videoLibrary[0], self.timeline)
|
||||
|
||||
|
||||
incomingItem = 0
|
||||
incomingTexture = self.textureLibrary[incomingItem]
|
||||
|
||||
alpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
|
||||
self.behaviourNew_scale = clutter.BehaviourScale(alpha, 1, self.scaleFactor, clutter.GRAVITY_CENTER)
|
||||
self.behaviourNew_z = clutter.BehaviourDepth(alpha, 1, 2)
|
||||
self.behaviourNew_opacity = clutter.BehaviourOpacity(alpha, self.inactiveOpacity, 255)
|
||||
|
||||
self.behaviourNew_scale.apply(incomingTexture)
|
||||
self.behaviourNew_z.apply(incomingTexture)
|
||||
self.behaviourNew_opacity.apply(incomingTexture)
|
||||
|
||||
self.currentSelection = incomingItem
|
||||
self.timeline.start()
|
||||
|
||||
#This moves the visible row of covers up and down
|
||||
# moveUp: True if the covers are to come up, false if they're to go down
|
||||
def rollViewer(self, moveUp, timeline):
|
||||
if moveUp:
|
||||
new_y = self.covers_group.get_y() - self.cover_size
|
||||
self.max_visible_rows = self.max_visible_rows + 1
|
||||
self.min_visible_rows = self.min_visible_rows + 1
|
||||
|
||||
#Define the row of covers that now needs to disapear / appear
|
||||
min_outgoing = (self.min_visible_rows-1) * self.num_columns
|
||||
max_outgoing = min_outgoing + self.num_columns
|
||||
min_incoming = (self.max_visible_rows-1) * self.num_columns
|
||||
max_incoming = min_incoming + self.num_columns
|
||||
|
||||
#Quick check to make sure that max_incoming isn't greater than the max number of images (This occurs when the final row is incomplete)
|
||||
if max_incoming > self.num_covers:
|
||||
max_incoming = min_incoming + (self.num_covers % self.num_columns)
|
||||
else:
|
||||
new_y = self.covers_group.get_y() + self.cover_size
|
||||
self.max_visible_rows = self.max_visible_rows - 1
|
||||
self.min_visible_rows = self.min_visible_rows - 1
|
||||
|
||||
#Define the row of covers that now needs to disapear / appear
|
||||
min_incoming = (self.min_visible_rows) * self.num_columns
|
||||
max_incoming = min_incoming + self.num_columns
|
||||
min_outgoing = (self.max_visible_rows) * self.num_columns
|
||||
max_outgoing = min_outgoing + self.num_columns
|
||||
|
||||
#Quick check to make sure that max_outgoing isn't greater than the max number of images (This occurs when the final row is incomplete)
|
||||
if max_outgoing > self.num_covers:
|
||||
max_outgoing = min_outgoing + (self.num_covers % self.num_columns)
|
||||
|
||||
#Need to add the new row to the group
|
||||
self.addIncomingRow(min_incoming, max_incoming)
|
||||
#And set the outgoing row to remove after the timeline finishes
|
||||
self.timeline.connect('completed', self.removeOutgoingRow, min_outgoing, max_outgoing)
|
||||
|
||||
|
||||
knots = (\
|
||||
(self.covers_group.get_x(), self.covers_group.get_y()),\
|
||||
(self.covers_group.get_x(), new_y) \
|
||||
)
|
||||
|
||||
alpha = clutter.Alpha(timeline, clutter.ramp_inc_func)
|
||||
self.behaviour_path = clutter.BehaviourPath(alpha, knots)
|
||||
self.behaviour_incoming = clutter.BehaviourOpacity(alpha, 0, self.inactiveOpacity)
|
||||
self.behaviour_outgoing = clutter.BehaviourOpacity(alpha, self.inactiveOpacity, 0)
|
||||
|
||||
self.behaviour_path.apply(self.covers_group)
|
||||
#Also need to change a few opacities - This is really messy, but works
|
||||
for i in range(min_outgoing, max_outgoing):
|
||||
self.behaviour_outgoing.apply(self.textureLibrary[i])
|
||||
for i in range(min_incoming, max_incoming):
|
||||
self.behaviour_incoming.apply(self.textureLibrary[i])
|
||||
|
||||
def removeOutgoingRow(self, timeline, min, max):
|
||||
for i in range(min, max):
|
||||
self.covers_group.remove(self.textureLibrary[i])
|
||||
|
||||
def addIncomingRow(self, min, max):
|
||||
for i in range(min, max):
|
||||
self.covers_group.add(self.textureLibrary[i])
|
||||
|
||||
xy_ratio = float(self.textureLibrary[i].get_width()) / self.textureLibrary[i].get_height()
|
||||
width = int(self.cover_size * xy_ratio)
|
||||
|
||||
x = (i % self.num_columns) * self.cover_size + ( (i % self.num_columns) * self.cover_gap)
|
||||
y = (self.cover_gap + self.cover_size) * (i/self.num_columns)
|
||||
|
||||
#Center the cover
|
||||
if width < self.cover_size:
|
||||
x = x + (self.cover_size - width)/2
|
||||
|
||||
self.textureLibrary[i].set_position(x, y)
|
||||
self.textureLibrary[i].show()
|
||||
|
||||
def get_current_video(self):
|
||||
return self.videoLibrary[self.currentSelection]
|
||||
|
||||
def on_key_press_event(self, event):
|
||||
newItem = None
|
||||
if event.keyval == clutter.keysyms.Left:
|
||||
#Make sure we're not already on the first cover
|
||||
if not self.currentSelection == 0:
|
||||
newItem = self.currentSelection - 1
|
||||
elif event.keyval == clutter.keysyms.Right:
|
||||
#This check makes sure that we're not on the last cover already
|
||||
if not self.currentSelection == (self.num_covers-1):
|
||||
newItem = self.currentSelection + 1
|
||||
elif event.keyval == clutter.keysyms.Down:
|
||||
#Check if we're already on the bottom row
|
||||
if not (self.currentSelection > (len(self.textureLibrary)-1 - self.num_columns)):
|
||||
newItem = self.currentSelection + self.num_columns
|
||||
elif event.keyval == clutter.keysyms.Up:
|
||||
#Check if we're already on the top row
|
||||
if not (self.currentSelection < self.num_columns):
|
||||
newItem = self.currentSelection - self.num_columns
|
||||
|
||||
#Final sanity check
|
||||
if (newItem < 0) and (not newItem == None):
|
||||
newItem = self.currentSelection
|
||||
|
||||
#If there is movement, make the scale happen
|
||||
if not newItem == None:
|
||||
self.select_item(newItem, self.currentSelection)
|
||||
|
||||
class video_details_group(clutter.Group):
|
||||
font = "Lucida Grande "
|
||||
title_font_size = 30
|
||||
main_font_size = 22
|
||||
plot_font_size = 18
|
||||
|
||||
def __init__(self, desired_width):
|
||||
clutter.Group.__init__(self)
|
||||
self.width = desired_width
|
||||
|
||||
#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)
|
||||
|
|
Loading…
Reference in New Issue