Initial commit
|
@ -0,0 +1,255 @@
|
||||||
|
import clutter
|
||||||
|
import pygtk
|
||||||
|
import gtk
|
||||||
|
import time
|
||||||
|
from ReflectionTexture import Texture_Reflection
|
||||||
|
|
||||||
|
class Menu:
|
||||||
|
item_gap = 10 #Distance between items
|
||||||
|
|
||||||
|
def __init__ (self, menuMgr):
|
||||||
|
self.menuMgr = menuMgr
|
||||||
|
self.stage = self.menuMgr.get_stage()
|
||||||
|
self.menuItems = []
|
||||||
|
self.selected = 0
|
||||||
|
self.displayPosition = (0, 0)
|
||||||
|
self.itemGroup = clutter.Group()
|
||||||
|
self.menuGroup = clutter.Group()
|
||||||
|
self.stage.add(self.itemGroup)
|
||||||
|
self.stage.add(self.menuGroup)
|
||||||
|
#self.hasTimeline = False
|
||||||
|
self.timeline = clutter.Timeline(15, 75) #This timeline is used on any movements that occur when changing items
|
||||||
|
self.timeline_completed=True
|
||||||
|
self.menuMgr.addMenu(self)
|
||||||
|
#self.itemGroup.hide_all()
|
||||||
|
|
||||||
|
def addItem(self, itemLabel, imagePath):
|
||||||
|
if len(self.menuItems) == 0:
|
||||||
|
label_height = 0
|
||||||
|
label_width = 0
|
||||||
|
else:
|
||||||
|
(label_width, label_height) = self.menuItems[0].get_size()
|
||||||
|
|
||||||
|
label_y = label_height * len(self.menuItems)+self.item_gap
|
||||||
|
|
||||||
|
newItem = ListItem(self, itemLabel, label_y, imagePath)
|
||||||
|
self.menuItems.append(newItem)
|
||||||
|
self.itemGroup.add(newItem)
|
||||||
|
|
||||||
|
group_x = self.itemGroup.get_x()
|
||||||
|
group_y = self.itemGroup.get_y() - (label_height)
|
||||||
|
self.itemGroup.set_position(group_x, group_y)
|
||||||
|
|
||||||
|
return newItem
|
||||||
|
|
||||||
|
def getItem(self, index):
|
||||||
|
return self.menuItems[index]
|
||||||
|
def getStage(self):
|
||||||
|
return self.stage
|
||||||
|
def getMenuMgr(self):
|
||||||
|
return self.menuMgr
|
||||||
|
|
||||||
|
def setMenuPositionByName(self, location):
|
||||||
|
if location == "center":
|
||||||
|
menu_y = (self.stage.get_height()-self.itemGroup.get_height())/2
|
||||||
|
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)
|
||||||
|
|
||||||
|
#The display position is the x, y coords of where the menu is when it is active
|
||||||
|
def get_display_position(self):
|
||||||
|
return self.displayPosition
|
||||||
|
|
||||||
|
def setMenuPosition(self, x, y):
|
||||||
|
self.itemGroup.set_position(x,y)
|
||||||
|
|
||||||
|
def getItemGroup(self):
|
||||||
|
return self.itemGroup
|
||||||
|
|
||||||
|
def getMenuGroup(self):
|
||||||
|
return self.menuGroup
|
||||||
|
|
||||||
|
def setListFont(self, newFont):
|
||||||
|
currentY= 0 #self.itemGroup.get_y()
|
||||||
|
self.font = newFont
|
||||||
|
for li in self.menuItems:
|
||||||
|
x = li.get_x()
|
||||||
|
#y = li.getPositionY()
|
||||||
|
li.set_font_name(newFont)
|
||||||
|
li.set_position(x,currentY)
|
||||||
|
currentY = currentY + li.get_height()
|
||||||
|
|
||||||
|
#Returns the newly selected item
|
||||||
|
def selectNext(self):
|
||||||
|
|
||||||
|
#Initially check whether the last animation is still going
|
||||||
|
if self.timeline.is_playing():
|
||||||
|
self.timeline.set_speed(1000) # Nasty hack to make sure the timeline finishes
|
||||||
|
|
||||||
|
|
||||||
|
self.timeline = clutter.Timeline (15,85)
|
||||||
|
#Check if we're at the last item in the list
|
||||||
|
if (self.selected) != (len(self.menuItems)-1):
|
||||||
|
self.selected = self.selected+1
|
||||||
|
|
||||||
|
self.menuItems[self.selected].scaleLabel(0, self.timeline)
|
||||||
|
self.menuItems[self.selected-1].scaleLabel(1, self.timeline)
|
||||||
|
if (self.selected >= 2):
|
||||||
|
self.menuItems[self.selected-2].scaleLabel(2, self.timeline)
|
||||||
|
#Finally move the selection bar
|
||||||
|
self.menuMgr.get_selector_bar().selectItem(self.menuItems[self.selected], self.timeline)
|
||||||
|
|
||||||
|
if self.selected != (len(self.menuItems)-1):
|
||||||
|
self.menuItems[self.selected+1].scaleLabel(1, self.timeline)
|
||||||
|
|
||||||
|
self.timeline.start()
|
||||||
|
|
||||||
|
#Returns the newly selected item
|
||||||
|
def selectPrevious(self):
|
||||||
|
|
||||||
|
#Initially check whether the last animation is still going
|
||||||
|
if self.timeline.is_playing():
|
||||||
|
self.timeline.set_speed(1000) # Nasty hack to make sure the timeline finishes
|
||||||
|
|
||||||
|
self.timeline = clutter.Timeline (15,85)
|
||||||
|
self.timeline_completed=False
|
||||||
|
|
||||||
|
#Check if we're at the first item in the list
|
||||||
|
if (self.selected) != 0:
|
||||||
|
self.selected = self.selected-1
|
||||||
|
#Move the selection bar
|
||||||
|
self.menuMgr.get_selector_bar().selectItem(self.menuItems[self.selected], self.timeline)
|
||||||
|
|
||||||
|
self.menuItems[self.selected].scaleLabel(0, self.timeline)
|
||||||
|
self.menuItems[self.selected+1].scaleLabel(1, self.timeline)
|
||||||
|
if self.selected <= (len(self.menuItems)-3):
|
||||||
|
self.menuItems[self.selected+2].scaleLabel(2, self.timeline)
|
||||||
|
|
||||||
|
if self.selected != 0:
|
||||||
|
self.menuItems[self.selected-1].scaleLabel(1, self.timeline)
|
||||||
|
|
||||||
|
self.timeline.start()
|
||||||
|
|
||||||
|
def selectFirst(self, moveBar):
|
||||||
|
self.timeline = clutter.Timeline(15, 75)
|
||||||
|
self.selected = 0
|
||||||
|
for i in range(0,len(self.menuItems)):
|
||||||
|
if i == 0:
|
||||||
|
self.menuItems[i].scaleLabel(0, self.timeline)
|
||||||
|
elif i == 1:
|
||||||
|
self.menuItems[i].scaleLabel(1, self.timeline)
|
||||||
|
else:
|
||||||
|
self.menuItems[i].scaleLabel(2, self.timeline)
|
||||||
|
|
||||||
|
if moveBar:
|
||||||
|
self.menuMgr.get_selector_bar().selectItem(self.menuItems[self.selected], self.timeline)
|
||||||
|
|
||||||
|
self.timeline.start()
|
||||||
|
|
||||||
|
def get_item_gap(self):
|
||||||
|
return self.item_gap
|
||||||
|
|
||||||
|
def get_current_item(self):
|
||||||
|
return self.menuItems[self.selected]
|
||||||
|
|
||||||
|
|
||||||
|
class ListItem (clutter.Label):
|
||||||
|
zoomLevel = 0.5
|
||||||
|
opacityStep = 120
|
||||||
|
|
||||||
|
def __init__ (self, menu, itemLabel, y, imagePath):
|
||||||
|
clutter.Label.__init__ (self)
|
||||||
|
self.itemTexturesGroup = clutter.Group()
|
||||||
|
font = menu.getMenuMgr().get_skinMgr().get_menu_font()
|
||||||
|
self.set_font_name(font)
|
||||||
|
self.set_text(itemLabel)
|
||||||
|
self.color = clutter.Color(0xff, 0xff, 0xff, 0xdd)
|
||||||
|
self.set_color(self.color)
|
||||||
|
self.currentOpacity = 255
|
||||||
|
self.menu = menu
|
||||||
|
|
||||||
|
#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.currentZoom = self.zoomLevel
|
||||||
|
|
||||||
|
|
||||||
|
#(label_width, label_height) = self.label.get_size()
|
||||||
|
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)
|
||||||
|
|
||||||
|
#Add textures group and hide it
|
||||||
|
self.menu.getMenuGroup().add(self.itemTexturesGroup)
|
||||||
|
self.itemTexturesGroup.hide_all()
|
||||||
|
|
||||||
|
def scaleLabel(self, level, timeline):
|
||||||
|
self.timeline = timeline
|
||||||
|
self.timeline.set_loop(False)
|
||||||
|
|
||||||
|
#Determine the zooming level
|
||||||
|
zoomTo=0
|
||||||
|
opacityTo = 255
|
||||||
|
if level==0:
|
||||||
|
zoomTo = 1 #self.zoomLevel * 1.5
|
||||||
|
opacityTo = 255
|
||||||
|
self.itemTexturesGroup.show_all()
|
||||||
|
if level==1:
|
||||||
|
zoomTo = self.zoomLevel * 1.2
|
||||||
|
opacityTo = 255 - self.opacityStep
|
||||||
|
self.itemTexturesGroup.hide_all()
|
||||||
|
if level==2:
|
||||||
|
zoomTo = self.zoomLevel
|
||||||
|
opacityTo = 255 - 2*self.opacityStep
|
||||||
|
self.itemTexturesGroup.hide_all()
|
||||||
|
|
||||||
|
alpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
|
||||||
|
self.behaviour1 = clutter.BehaviourScale(alpha, self.currentZoom, zoomTo, clutter.GRAVITY_WEST)
|
||||||
|
self.behaviour2 = clutter.BehaviourOpacity(alpha, self.currentOpacity, opacityTo)
|
||||||
|
self.behaviour1.apply(self)
|
||||||
|
self.behaviour2.apply(self)
|
||||||
|
|
||||||
|
|
||||||
|
self.currentZoom = zoomTo
|
||||||
|
self.currentOpacity = opacityTo
|
||||||
|
return self.timeline
|
||||||
|
|
||||||
|
def get_zoom_level(self):
|
||||||
|
return self.zoomLevel
|
||||||
|
|
||||||
|
|
||||||
|
def addImage(self, path, useReflection):
|
||||||
|
self.tempTexture = clutter.Texture()
|
||||||
|
pixbuf = gtk.gdk.pixbuf_new_from_file(path)
|
||||||
|
|
||||||
|
self.tempTexture.set_pixbuf(pixbuf)
|
||||||
|
(abs_x, abs_y) = self.get_abs_position()
|
||||||
|
print abs_x
|
||||||
|
x = abs_x# - self.tempTexture.get_width()
|
||||||
|
y = (self.menu.getStage().get_height()/2) - (self.tempTexture.get_height()/2)
|
||||||
|
self.tempTexture.set_position(x, y)
|
||||||
|
|
||||||
|
self.tempTexture.rotate_y(45,0,0)
|
||||||
|
self.itemTexturesGroup.add(self.tempTexture)
|
||||||
|
self.tempTexture.hide_all()
|
||||||
|
|
||||||
|
#Scale the image down by half
|
||||||
|
#self.tempTexture.set_width(self.tempTexture.get_width()/2)
|
||||||
|
#self.tempTexture.set_height(self.tempTexture.get_height()/2)
|
||||||
|
|
||||||
|
if useReflection:
|
||||||
|
self.reflectionTexture = Texture_Reflection(self.tempTexture)
|
||||||
|
#self.reflectionTexture.set_position(0, 0)#self.tempTexture.get_height())
|
||||||
|
self.itemTexturesGroup.add(self.reflectionTexture)
|
||||||
|
self.itemTexturesGroup.hide_all()
|
||||||
|
|
||||||
|
def setAction(self, newAction):
|
||||||
|
self.action = newAction
|
||||||
|
|
||||||
|
def getAction(self):
|
||||||
|
return self.action
|
||||||
|
|
||||||
|
def get_menu(self):
|
||||||
|
return self.menu
|
|
@ -0,0 +1,203 @@
|
||||||
|
import clutter
|
||||||
|
from SkinMgr import SkinMgr
|
||||||
|
from Spinner import Spinner
|
||||||
|
import pygtk
|
||||||
|
import gtk
|
||||||
|
|
||||||
|
class MenuMgr():
|
||||||
|
|
||||||
|
def __init__ (self, stage):
|
||||||
|
self.stage = stage
|
||||||
|
self.menus = []
|
||||||
|
self.currentMenu = None
|
||||||
|
|
||||||
|
self.skinMgr = SkinMgr(self.stage)
|
||||||
|
background = self.skinMgr.get_Background()
|
||||||
|
self.stage.add(background)
|
||||||
|
|
||||||
|
self.selector_bar = MenuSelector(self)
|
||||||
|
self.stage.add(self.selector_bar)
|
||||||
|
self.selector_bar.show_all()
|
||||||
|
self.currentPlugin = None
|
||||||
|
|
||||||
|
def addMenu(self, newMenu):
|
||||||
|
self.menus.append(newMenu)
|
||||||
|
|
||||||
|
#If this is the first menu, make it the active one
|
||||||
|
if self.currentMenu == None:
|
||||||
|
self.currentMenu = newMenu
|
||||||
|
self.currentMenu.getItemGroup().show_all()
|
||||||
|
self.currentMenu.getMenuGroup().show_all()
|
||||||
|
self.selector_bar.set_menu(self.currentMenu)
|
||||||
|
|
||||||
|
def get_selector_bar(self):
|
||||||
|
return self.selector_bar
|
||||||
|
|
||||||
|
def get_stage(self):
|
||||||
|
return self.stage
|
||||||
|
|
||||||
|
def get_skinMgr(self):
|
||||||
|
return self.skinMgr
|
||||||
|
|
||||||
|
def transition_fade_zoom(self, fromMenu, toMenu):
|
||||||
|
oldGroup = fromMenu.getItemGroup()
|
||||||
|
oldMenuGroup = fromMenu.getMenuGroup()
|
||||||
|
newGroup = toMenu.getItemGroup()
|
||||||
|
newMenuGroup = toMenu.getMenuGroup()
|
||||||
|
|
||||||
|
oldGroup.set_opacity(255)
|
||||||
|
|
||||||
|
self.timeline = clutter.Timeline(25, 50)
|
||||||
|
self.alpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
|
||||||
|
#self.exit_behaviour_scale = clutter.BehaviourScale(self.alpha, 1, 0.5, clutter.GRAVITY_CENTER)
|
||||||
|
self.exit_behaviour_opacity = clutter.BehaviourOpacity(self.alpha, 150, 0)
|
||||||
|
|
||||||
|
#Setup some knots
|
||||||
|
knots_exiting = (\
|
||||||
|
(oldGroup.get_x(), oldGroup.get_y()),\
|
||||||
|
#(-oldGroup.get_x(), int(fromMenu.getStage().get_height()/2))
|
||||||
|
(-oldGroup.get_x(), oldGroup.get_y())\
|
||||||
|
)
|
||||||
|
self.exit_behaviour_path = clutter.BehaviourPath(self.alpha, knots_exiting)
|
||||||
|
|
||||||
|
#self.exit_behaviour_scale.apply(oldGroup)
|
||||||
|
self.exit_behaviour_opacity.apply(oldGroup)
|
||||||
|
self.exit_behaviour_opacity.apply(oldMenuGroup)
|
||||||
|
self.exit_behaviour_path.apply(oldGroup)
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################
|
||||||
|
#Start incoming menu
|
||||||
|
#self.exit_behaviour_scale = clutter.BehaviourScale(self.alpha, 1, 0.5, clutter.GRAVITY_CENTER)
|
||||||
|
self.entrance_behaviour_opacity = clutter.BehaviourOpacity(self.alpha, 0, 255)
|
||||||
|
|
||||||
|
#Setup some knots
|
||||||
|
start_y = int(self.stage.get_height()/2 - newGroup.get_height()/2)
|
||||||
|
start_x = int(self.stage.get_width())
|
||||||
|
newGroup.set_position(start_x, start_y)
|
||||||
|
#end_x = int(self.stage.get_width() - newGroup.get_width())/2
|
||||||
|
(end_x, end_y) = toMenu.get_display_position()
|
||||||
|
end_x = oldGroup.get_x() #int(end_x)
|
||||||
|
end_y = oldGroup.get_y() #int(end_y)
|
||||||
|
knots_entering = (\
|
||||||
|
(newGroup.get_x(), newGroup.get_y()),\
|
||||||
|
#(-oldGroup.get_x(), int(fromMenu.getStage().get_height()/2))
|
||||||
|
(end_x, end_y) \
|
||||||
|
#toMenu.get_display_position()
|
||||||
|
)
|
||||||
|
|
||||||
|
self.entrance_behaviour_path = clutter.BehaviourPath(self.alpha, knots_entering)
|
||||||
|
|
||||||
|
self.entrance_behaviour_opacity.apply(newGroup)
|
||||||
|
self.entrance_behaviour_opacity.apply(newMenuGroup)
|
||||||
|
self.entrance_behaviour_path.apply(newGroup)
|
||||||
|
newGroup.show_all()
|
||||||
|
newMenuGroup.show_all()
|
||||||
|
|
||||||
|
#Finally, move the selector bar
|
||||||
|
self.selector_bar.selectItem(fromMenu.getItem(0), self.timeline)
|
||||||
|
#(to_x, to_y) = toMenu.get_display_position() #fromMenu.getItem(0).get_abs_position()
|
||||||
|
#self.selector_bar.move_to(int(to_x), int(to_y), self.timeline)
|
||||||
|
toMenu.selectFirst(False)
|
||||||
|
|
||||||
|
#self.timeline.connect('completed', self.on_transition_complete)
|
||||||
|
self.timeline.start()
|
||||||
|
self.currentMenu = toMenu
|
||||||
|
|
||||||
|
def on_key_press_event (self, stage, event):
|
||||||
|
#Firstly checking whether we are in the process of running a plugin (And that the key isn't escape)
|
||||||
|
if (not self.currentPlugin == None) and (not event.keyval == clutter.keysyms.Escape):
|
||||||
|
#If it is, simply pass the event details along to the plugin
|
||||||
|
self.currentPlugin.on_key_press_event(stage, event)
|
||||||
|
return None
|
||||||
|
|
||||||
|
#print event.hardware_keycode
|
||||||
|
if event.keyval == clutter.keysyms.Up: #Up button pressed
|
||||||
|
self.currentMenu.selectPrevious()
|
||||||
|
if event.keyval == clutter.keysyms.Down: #Down button pressed
|
||||||
|
self.currentMenu.selectNext()
|
||||||
|
if event.keyval == clutter.keysyms.q:
|
||||||
|
clutter.main_quit()
|
||||||
|
if event.hardware_keycode == 36: #return button pressed
|
||||||
|
#self.aList.set_processing(True)
|
||||||
|
action = self.currentMenu.get_current_item().getAction()
|
||||||
|
if action.__class__.__name__ == "Menu": # Check whether we're a pointing to a menu object
|
||||||
|
self.transition_fade_zoom(self.currentMenu, action)
|
||||||
|
else:
|
||||||
|
#We have a plugin and need to start it
|
||||||
|
self.currentPlugin = action
|
||||||
|
action.begin(self)
|
||||||
|
if event.keyval == clutter.keysyms.p:
|
||||||
|
self.mySlideshow.startShow(self.stage)
|
||||||
|
if event.keyval == clutter.keysyms.Escape:
|
||||||
|
if not self.currentPlugin == None:
|
||||||
|
self.currentPlugin.stop()
|
||||||
|
self.currentPlugin = None
|
||||||
|
#print event.hardware_keycode
|
||||||
|
|
||||||
|
def get_current_menu(self):
|
||||||
|
return self.currentMenu
|
||||||
|
|
||||||
|
class MenuSelector(clutter.Texture):
|
||||||
|
x_offset = -50
|
||||||
|
|
||||||
|
def __init__ (self, menuMgr):
|
||||||
|
clutter.Texture.__init__ (self)
|
||||||
|
self.menuMgr = menuMgr
|
||||||
|
pixbuf = gtk.gdk.pixbuf_new_from_file("ui/active_bar.png")
|
||||||
|
self.set_pixbuf(pixbuf)
|
||||||
|
self.set_width(400)
|
||||||
|
|
||||||
|
pixbuf = gtk.gdk.pixbuf_new_from_file("ui/spinner1.gif")
|
||||||
|
self.spinner = clutter.Texture()
|
||||||
|
self.spinner.set_pixbuf(pixbuf)
|
||||||
|
self.spinner.hide()
|
||||||
|
|
||||||
|
|
||||||
|
def selectItem(self, selectee, timeline):
|
||||||
|
(x, y) = selectee.get_abs_position()
|
||||||
|
|
||||||
|
group_x = selectee.get_menu().getItemGroup().get_x()
|
||||||
|
group_y = selectee.get_menu().getItemGroup().get_y()
|
||||||
|
|
||||||
|
x = x + self.x_offset
|
||||||
|
self.timeline = timeline
|
||||||
|
|
||||||
|
#Check if we're going up or down
|
||||||
|
if y > self.get_y():
|
||||||
|
#Going down
|
||||||
|
y = int(y - selectee.get_menu().get_item_gap()/2)
|
||||||
|
else:
|
||||||
|
#Going up
|
||||||
|
y = int(y - selectee.get_menu().get_item_gap()/2)
|
||||||
|
|
||||||
|
self.move_to(x, y, self.timeline)
|
||||||
|
|
||||||
|
def move_to(self, x, y, timeline):
|
||||||
|
self.timeline = timeline
|
||||||
|
knots = (\
|
||||||
|
(self.get_x(), self.get_y()),\
|
||||||
|
(x, y)\
|
||||||
|
)
|
||||||
|
|
||||||
|
self.alpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
|
||||||
|
self.behaviour = clutter.BehaviourPath(self.alpha, knots)
|
||||||
|
|
||||||
|
self.behaviour.apply(self)
|
||||||
|
|
||||||
|
def set_menu(self, menu):
|
||||||
|
self.menu = menu
|
||||||
|
|
||||||
|
def set_spinner(self, state):
|
||||||
|
if state:
|
||||||
|
self.spinner = Spinner()
|
||||||
|
self.spinner.show()
|
||||||
|
self.menuMgr.get_stage().add(self.spinner)
|
||||||
|
else:
|
||||||
|
self.menuMgr.get_stage().remove(self.spinner)
|
||||||
|
self.spinner = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_x_offset(self):
|
||||||
|
return self.x_offset
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
import pygtk
|
||||||
|
import gtk
|
||||||
|
import clutter
|
||||||
|
import eyeD3
|
||||||
|
|
||||||
|
class MusicPlayer():
|
||||||
|
|
||||||
|
def __init__(self, stage):
|
||||||
|
self.stage = stage
|
||||||
|
self.cover_viewer = coverViewer(self.stage)
|
||||||
|
|
||||||
|
self.is_playing = False
|
||||||
|
|
||||||
|
def on_key_press_event (self, stage, event):
|
||||||
|
if event.keyval == clutter.keysyms.p:
|
||||||
|
if self.paused:
|
||||||
|
self.unpause()
|
||||||
|
else:
|
||||||
|
self.pause()
|
||||||
|
if event.keyval == clutter.keysyms.q:
|
||||||
|
clutter.main_quit()
|
||||||
|
|
||||||
|
def begin(self, MenuMgr):
|
||||||
|
|
||||||
|
#Create a backdrop for the player. In this case we just use the same background as the menus
|
||||||
|
self.backdrop = clutter.CloneTexture(MenuMgr.get_skinMgr().get_Background())
|
||||||
|
self.backdrop.set_size(self.stage.get_width(), self.stage.get_height())
|
||||||
|
self.backdrop.set_opacity(0)
|
||||||
|
self.backdrop.show()
|
||||||
|
self.stage.add(self.backdrop)
|
||||||
|
#Fade the backdrop in
|
||||||
|
timeline_backdrop = clutter.Timeline(10,40)
|
||||||
|
alpha = clutter.Alpha(timeline_backdrop, clutter.ramp_inc_func)
|
||||||
|
backdrop_behaviour = clutter.BehaviourOpacity(alpha, 0, 255)
|
||||||
|
backdrop_behaviour.apply(self.backdrop)
|
||||||
|
timeline_backdrop.start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def unpause(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class coverViewer(clutter.Group):
|
||||||
|
|
||||||
|
def __init__(self, stage):
|
||||||
|
clutter.Group.__init__(self)
|
||||||
|
self.stage = stage
|
||||||
|
self.covers = []
|
||||||
|
self.num_covers = 0
|
||||||
|
self.cover_size = 50 #A cover will be cover_size * cover_size (X * Y)
|
||||||
|
self.cover_gap = 10
|
||||||
|
|
||||||
|
self.num_rows = 2
|
||||||
|
self.num_columns = int(self.stage.get_width() / self.cover_size)
|
||||||
|
|
||||||
|
def add_image(self, imagePath):
|
||||||
|
tempTexture = clutter.Texture()
|
||||||
|
pixbuf = gtk.gdk.pixbuf_new_from_file(imagePath)
|
||||||
|
tempTexture.set_pixbuf(pixbuf)
|
||||||
|
xy_ratio = tempTexture.get_width() / tempTexture.get_height()
|
||||||
|
|
||||||
|
height = int(self.cover_size * xy_ratio)
|
||||||
|
tempTexture.set_width(self.cover_size)
|
||||||
|
tempTexture.set_height(height)
|
||||||
|
|
||||||
|
self.add(tempTexture)
|
||||||
|
self.num_covers = self.num_covers +1
|
||||||
|
|
||||||
|
#Redo positioning on all textures to add new one :(
|
||||||
|
"""for i = 0 to self.num_covers:
|
||||||
|
tempTexture = self.get_nth_child(i)
|
||||||
|
x = (self.cover_gap + self.cover_size) * i
|
||||||
|
y = (i % self.num_rows) * self.cover_size
|
||||||
|
tempTexture.set_position(x, y)"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
import clutter
|
||||||
|
|
||||||
|
"""
|
||||||
|
A Page is like a menu, but without the menu and 'things' placed everywhere
|
||||||
|
instead of menu items
|
||||||
|
"""
|
||||||
|
class Page():
|
||||||
|
|
||||||
|
def __init__():
|
||||||
|
pass
|
|
@ -0,0 +1,29 @@
|
||||||
|
import clutter
|
||||||
|
|
||||||
|
class Texture_Reflection (clutter.Texture):
|
||||||
|
|
||||||
|
def __init__(self, origTexture):
|
||||||
|
clutter.Texture.__init__(self)
|
||||||
|
self.set_pixbuf(origTexture.get_pixbuf())
|
||||||
|
|
||||||
|
self.set_width(origTexture.get_width())
|
||||||
|
self.set_height(origTexture.get_height())
|
||||||
|
|
||||||
|
#Rotate the reflection based on any rotations to the master
|
||||||
|
ang_y = origTexture.get_ryang()
|
||||||
|
self.rotate_y(ang_y,0,0)
|
||||||
|
ang_x = origTexture.get_rxang()
|
||||||
|
self.rotate_x(ang_x,0,0)
|
||||||
|
ang_z = origTexture.get_rzang()
|
||||||
|
self.rotate_z(ang_z,0,0)
|
||||||
|
|
||||||
|
#Get the location for it
|
||||||
|
(x, y) = origTexture.get_abs_position()
|
||||||
|
|
||||||
|
#self.set_clip(0,self.get_height()/2,self.get_width(), (self.get_height()/2))
|
||||||
|
|
||||||
|
#Flip it upside down
|
||||||
|
self.rotate_x(180,origTexture.get_height(),0)
|
||||||
|
self.set_opacity(50)
|
||||||
|
|
||||||
|
self.set_position(x, y)
|
|
@ -0,0 +1,19 @@
|
||||||
|
import clutter
|
||||||
|
import pygtk
|
||||||
|
import gtk
|
||||||
|
|
||||||
|
class SkinMgr:
|
||||||
|
|
||||||
|
def __init__ (self, mainStage):
|
||||||
|
self.stage = mainStage
|
||||||
|
|
||||||
|
def get_Background(self):
|
||||||
|
pixbuf = gtk.gdk.pixbuf_new_from_file("ui/background.png")
|
||||||
|
self.background = clutter.Texture()
|
||||||
|
self.background.set_pixbuf(pixbuf)
|
||||||
|
self.background.set_size(self.stage.get_width(), self.stage.get_height())
|
||||||
|
self.background.show()
|
||||||
|
return self.background
|
||||||
|
|
||||||
|
def get_menu_font(self):
|
||||||
|
return 'Tahoma 40'
|
|
@ -0,0 +1,330 @@
|
||||||
|
import clutter
|
||||||
|
from clutter import cluttergst
|
||||||
|
from Menu import Menu
|
||||||
|
import time
|
||||||
|
import os.path
|
||||||
|
import pygtk
|
||||||
|
import gtk
|
||||||
|
import random
|
||||||
|
import thread
|
||||||
|
|
||||||
|
class Slideshow:
|
||||||
|
image_file_types = ["jpg", "gif", "jpeg", "png", "bmp"]
|
||||||
|
sound_file_types = ["mp3", "wav", "ogg"] #possibly more supported by default?
|
||||||
|
imageDuration = 5 # In seconds
|
||||||
|
effect_FPS = 50
|
||||||
|
|
||||||
|
def __init__(self, MenuMgr, basedir):
|
||||||
|
self.image_texture_group = clutter.Group()
|
||||||
|
self.baseDir = basedir
|
||||||
|
self.MenuMgr = MenuMgr
|
||||||
|
self.currentTexture = clutter.Texture()
|
||||||
|
self.currentSong = None
|
||||||
|
self.paused = False
|
||||||
|
self.textures = []
|
||||||
|
self.music = []
|
||||||
|
self.overlay = clutter.Rectangle()
|
||||||
|
self.backdrop = None
|
||||||
|
|
||||||
|
def on_key_press_event (self, stage, event):
|
||||||
|
#print event.hardware_keycode
|
||||||
|
if event.keyval == clutter.keysyms.p:
|
||||||
|
if self.paused:
|
||||||
|
self.unpause()
|
||||||
|
else:
|
||||||
|
self.pause()
|
||||||
|
if event.keyval == clutter.keysyms.q:
|
||||||
|
clutter.main_quit()
|
||||||
|
|
||||||
|
def loadDir(self, dirPath, recurse):
|
||||||
|
if not os.path.isdir(dirPath):
|
||||||
|
print "ERROR: Invalid path"
|
||||||
|
return None
|
||||||
|
|
||||||
|
new_file_list = os.listdir(dirPath)
|
||||||
|
|
||||||
|
#If recursive sub-dirs is on, loop through any directories
|
||||||
|
if recurse:
|
||||||
|
for fs_object in new_file_list:
|
||||||
|
path = dirPath + "/" + fs_object
|
||||||
|
if os.path.isdir(path):
|
||||||
|
self.loadDir(path, True)
|
||||||
|
|
||||||
|
new_image_list = filter(self.filterImageFile, new_file_list)
|
||||||
|
new_sound_list = filter(self.filterSoundFile, new_file_list)
|
||||||
|
|
||||||
|
#Load pictures into textures array
|
||||||
|
i = len(self.textures)
|
||||||
|
for pic in new_image_list:
|
||||||
|
self.textures.append(clutter.Texture())
|
||||||
|
imgName = dirPath + "/" + pic
|
||||||
|
#print imgName
|
||||||
|
pixbuf = gtk.gdk.pixbuf_new_from_file(imgName)
|
||||||
|
self.textures[i].set_pixbuf(pixbuf)
|
||||||
|
self.textures[i].set_position(0,0)
|
||||||
|
self.image_texture_group.add(self.textures[i])
|
||||||
|
i = i+1
|
||||||
|
|
||||||
|
#Load sound into music array
|
||||||
|
i = len(self.music)
|
||||||
|
for sound in new_sound_list:
|
||||||
|
self.music.append(cluttergst.Audio())
|
||||||
|
sndName = dirPath + "/" + sound
|
||||||
|
self.music[i].set_filename(sndName)
|
||||||
|
i = i+1
|
||||||
|
|
||||||
|
#This makes sure we only take in image files
|
||||||
|
def filterImageFile(self, fileName):
|
||||||
|
extension = fileName[-3:] #Get 3 letter extension
|
||||||
|
if extension in self.image_file_types:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
#This makes sure we only take in sound files
|
||||||
|
def filterSoundFile(self, fileName):
|
||||||
|
extension = fileName[-3:] #Get 3 letter extension
|
||||||
|
if extension in self.sound_file_types:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def begin(self, MenuMgr):
|
||||||
|
self.stage = self.MenuMgr.get_stage()
|
||||||
|
|
||||||
|
self.MenuMgr.get_selector_bar().set_spinner(True)
|
||||||
|
self.stage.queue_redraw()
|
||||||
|
|
||||||
|
|
||||||
|
slideName = self.baseDir + "/" + self.MenuMgr.get_current_menu().get_current_item().get_text()
|
||||||
|
self.loadDir(slideName, True)
|
||||||
|
self.MenuMgr.get_selector_bar().set_spinner(False)
|
||||||
|
|
||||||
|
if self.backdrop == None:
|
||||||
|
#Create a rectangle that serves as the backdrop for the slideshow
|
||||||
|
self.backdrop = clutter.Rectangle()
|
||||||
|
self.backdrop.set_color(clutter.color_parse('Black'))
|
||||||
|
self.backdrop.set_width(self.stage.get_width())
|
||||||
|
self.backdrop.set_height(self.stage.get_height())
|
||||||
|
self.stage.add(self.backdrop)
|
||||||
|
#Fade the backdrop in
|
||||||
|
self.image_texture_group.set_opacity(255)
|
||||||
|
self.backdrop.set_opacity(0)
|
||||||
|
self.backdrop.show()
|
||||||
|
timeline_backdrop = clutter.Timeline(10,30)
|
||||||
|
alpha = clutter.Alpha(timeline_backdrop, clutter.ramp_inc_func)
|
||||||
|
backdrop_behaviour = clutter.BehaviourOpacity(alpha, 0, 255)
|
||||||
|
backdrop_behaviour.apply(self.backdrop)
|
||||||
|
timeline_backdrop.start()
|
||||||
|
|
||||||
|
|
||||||
|
self.stage.add(self.image_texture_group)
|
||||||
|
#print "No of children: " + str(self.image_texture_group.get_n_children())
|
||||||
|
#Get a random texture
|
||||||
|
self.rand1 = random.randint(0, self.image_texture_group.get_n_children()-1)
|
||||||
|
self.currentTexture = self.textures[self.rand1]
|
||||||
|
#Make sure its visible
|
||||||
|
self.currentTexture.set_opacity(255)
|
||||||
|
|
||||||
|
|
||||||
|
#Get a random song (if there's songs available)
|
||||||
|
if not len(self.music) == 0:
|
||||||
|
self.rand1 = random.randint(0, len(self.music)-1)
|
||||||
|
self.currentSong = self.music[self.rand1]
|
||||||
|
self.playNextSong(None)
|
||||||
|
|
||||||
|
#Housekeeping
|
||||||
|
self.image_texture_group.hide_all()
|
||||||
|
self.nextTexture = None
|
||||||
|
self.nextSong = None
|
||||||
|
|
||||||
|
#Begin the show
|
||||||
|
self.currentTexture.show()
|
||||||
|
self.image_texture_group.show()
|
||||||
|
self.nextImage(self.currentTexture)
|
||||||
|
|
||||||
|
def end(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def nextImage(self, currentTexture):
|
||||||
|
#Setup stuff for KEN BURNS EFFECT!!
|
||||||
|
self.timeline_main = clutter.Timeline((self.effect_FPS * self.imageDuration), self.effect_FPS)
|
||||||
|
self.timeline_main.connect('completed', self.image_timeline_end_event)
|
||||||
|
self.alpha = clutter.Alpha(self.timeline_main, clutter.ramp_inc_func)
|
||||||
|
|
||||||
|
#Decide on the next texture to use
|
||||||
|
self.nextTexture = None
|
||||||
|
while (self.nextTexture == None):
|
||||||
|
self.rand1 = random.randint(0, len(self.textures)-1 )
|
||||||
|
self.nextTexture = self.image_texture_group.get_nth_child(self.rand1)
|
||||||
|
#Make sure we don't show the same photo twice
|
||||||
|
if (self.nextTexture == self.currentTexture) and (len(self.textures) > 1):
|
||||||
|
self.nextTexture = None
|
||||||
|
#Make sure its not visible initially (Prevents a nasty flicker the first time a photo is shown)
|
||||||
|
self.nextTexture.set_opacity(0)
|
||||||
|
|
||||||
|
#Zooming stuff
|
||||||
|
rand_zoom = random.uniform(1,1.3) # Zoom somewhere between 1 and 1.3 times
|
||||||
|
self.behaviour1 = clutter.BehaviourScale(self.alpha, 1, rand_zoom, clutter.GRAVITY_CENTER)
|
||||||
|
|
||||||
|
#panning stuff
|
||||||
|
x_pos = self.currentTexture.get_x() + random.randint(-100, 100)
|
||||||
|
y_pos = self.currentTexture.get_y() + random.randint(-100, 100)
|
||||||
|
self.alpha = clutter.Alpha(self.timeline_main, clutter.ramp_inc_func)
|
||||||
|
|
||||||
|
knots = (\
|
||||||
|
(self.currentTexture.get_x(), self.currentTexture.get_y()),\
|
||||||
|
(x_pos, y_pos)\
|
||||||
|
)
|
||||||
|
self.behaviour2 = clutter.BehaviourPath(self.alpha, knots)
|
||||||
|
|
||||||
|
|
||||||
|
#Start and run the Ken Burns effect
|
||||||
|
self.behaviour1.apply(self.currentTexture)
|
||||||
|
self.behaviour2.apply(self.currentTexture)
|
||||||
|
self.timeline_main.start()
|
||||||
|
|
||||||
|
|
||||||
|
def image_timeline_end_event(self, data):
|
||||||
|
#Add the timeline for the dissolve at the end
|
||||||
|
self.timeline_dissolve = clutter.Timeline(30,30)
|
||||||
|
self.alpha_dissolve = clutter.Alpha(self.timeline_dissolve, clutter.ramp_inc_func)
|
||||||
|
|
||||||
|
#Setup the dissolve to the next image
|
||||||
|
self.behaviour3 = clutter.BehaviourOpacity(self.alpha_dissolve, 255, 0)
|
||||||
|
self.behaviour4 = clutter.BehaviourOpacity(self.alpha_dissolve, 0, 255)
|
||||||
|
|
||||||
|
self.behaviour3.apply(self.currentTexture)
|
||||||
|
self.behaviour4.apply(self.nextTexture)
|
||||||
|
|
||||||
|
#Pick a random spot for the next image
|
||||||
|
x_pos = random.randint(0, abs(self.stage.get_width() - self.nextTexture.get_width()) ) #Somewhere between 0 and (stage_width-image_width)
|
||||||
|
y_pos = random.randint(0, abs(self.stage.get_height() - self.nextTexture.get_height()) )
|
||||||
|
self.nextTexture.set_position(x_pos, y_pos)
|
||||||
|
|
||||||
|
self.currentTexture = self.nextTexture
|
||||||
|
self.nextTexture.show()
|
||||||
|
self.timeline_dissolve.start()
|
||||||
|
self.nextImage(self.currentTexture)
|
||||||
|
|
||||||
|
#Begins playing a new song
|
||||||
|
def playNextSong(self, data):
|
||||||
|
self.nextSong = None
|
||||||
|
#Check first that there actually is music
|
||||||
|
if len(self.music) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
#Decide on the next song to play
|
||||||
|
while self.nextSong == None:
|
||||||
|
self.rand1 = random.randint(0, len(self.music)-1)
|
||||||
|
self.nextSong = self.music[self.rand1]
|
||||||
|
#Make sure we don't play the same song twice
|
||||||
|
if (self.nextSong == self.currentSong) and (len(self.music) > 1):
|
||||||
|
self.nextSong = None
|
||||||
|
|
||||||
|
self.currentSong = self.nextSong
|
||||||
|
self.currentSong.set_playing(True)
|
||||||
|
self.currentSong.connect('eos', self.playNextSong)
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
self.paused = True
|
||||||
|
|
||||||
|
#Use the overlay to go over show
|
||||||
|
self.overlay.set_color(clutter.color_parse('Black'))
|
||||||
|
self.overlay.set_width(self.stage.get_width())
|
||||||
|
self.overlay.set_height(self.stage.get_height())
|
||||||
|
self.overlay.set_opacity(0)
|
||||||
|
self.overlay.show()
|
||||||
|
#self.overlay.raise_top()
|
||||||
|
#self.image_texture_group.lower(self.overlay)
|
||||||
|
self.stage.add(self.overlay)
|
||||||
|
#Fade the backdrop in
|
||||||
|
timeline_overlay = clutter.Timeline(10,30)
|
||||||
|
alpha = clutter.Alpha(timeline_overlay, clutter.ramp_inc_func)
|
||||||
|
overlay_behaviour = clutter.BehaviourOpacity(alpha, 0, 100)
|
||||||
|
overlay_behaviour2 = clutter.BehaviourOpacity(alpha, 255, 100) #Used on the backdrop
|
||||||
|
overlay_behaviour3 = clutter.BehaviourOpacity(alpha, 255, 0) #Used on the current texture
|
||||||
|
overlay_behaviour.apply(self.overlay)
|
||||||
|
overlay_behaviour2.apply(self.backdrop)
|
||||||
|
overlay_behaviour3.apply(self.currentTexture)
|
||||||
|
timeline_overlay.start()
|
||||||
|
|
||||||
|
#Pause the main slideshow
|
||||||
|
self.timeline_main.pause()
|
||||||
|
|
||||||
|
#Pause any music
|
||||||
|
if not self.currentSong == None:
|
||||||
|
if self.currentSong.get_playing():
|
||||||
|
self.currentSong.set_playing(False)
|
||||||
|
|
||||||
|
def unpause(self):
|
||||||
|
self.paused = False
|
||||||
|
|
||||||
|
#Fade the backdrop in
|
||||||
|
timeline_overlay = clutter.Timeline(10,30)
|
||||||
|
alpha = clutter.Alpha(timeline_overlay, clutter.ramp_inc_func)
|
||||||
|
overlay_behaviour = clutter.BehaviourOpacity(alpha, 100, 0)
|
||||||
|
overlay_behaviour2 = clutter.BehaviourOpacity(alpha, 100, 255) #Used on the backdrop
|
||||||
|
overlay_behaviour3 = clutter.BehaviourOpacity(alpha, 0, 255) #Used on the current texture
|
||||||
|
overlay_behaviour.apply(self.overlay)
|
||||||
|
overlay_behaviour2.apply(self.backdrop)
|
||||||
|
overlay_behaviour3.apply(self.currentTexture)
|
||||||
|
timeline_overlay.start()
|
||||||
|
|
||||||
|
#Resume the main slideshow
|
||||||
|
self.timeline_main.start()
|
||||||
|
|
||||||
|
#Resume any music
|
||||||
|
if not self.currentSong == None:
|
||||||
|
self.currentSong.set_playing(True)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
#Stop any running timelines
|
||||||
|
self.timeline_main.stop()
|
||||||
|
|
||||||
|
#Fade everything out
|
||||||
|
timeline_stop = clutter.Timeline(10,30)
|
||||||
|
alpha = clutter.Alpha(timeline_stop, clutter.ramp_inc_func)
|
||||||
|
stop_behaviour = clutter.BehaviourOpacity(alpha, 255, 0)
|
||||||
|
stop_behaviour.apply(self.image_texture_group)
|
||||||
|
stop_behaviour.apply(self.backdrop)
|
||||||
|
stop_behaviour.apply(self.overlay)
|
||||||
|
timeline_stop.connect('completed', self.destroySlideshow)
|
||||||
|
timeline_stop.start()
|
||||||
|
|
||||||
|
#Stop any music
|
||||||
|
if not self.currentSong == None:
|
||||||
|
if self.currentSong.get_playing():
|
||||||
|
self.currentSong.set_playing(False)
|
||||||
|
self.currentSong.set_position(0)
|
||||||
|
|
||||||
|
|
||||||
|
def destroySlideshow(self, data):
|
||||||
|
self.stage.remove(self.image_texture_group)
|
||||||
|
self.backdrop.hide()
|
||||||
|
#self.stage.remove(self.overlay)
|
||||||
|
|
||||||
|
self.currentTexture = None
|
||||||
|
self.nextTexture = None
|
||||||
|
self.currentSong = None
|
||||||
|
self.nexttSong = None
|
||||||
|
|
||||||
|
#The following generates a menu with an option for each of the slideshows in the base menu
|
||||||
|
def generateMenu(self):
|
||||||
|
|
||||||
|
tempMenu = Menu(self.MenuMgr)
|
||||||
|
print self.baseDir
|
||||||
|
file_list = os.listdir(self.baseDir)
|
||||||
|
|
||||||
|
for directoryEntry in file_list:
|
||||||
|
subdir = self.baseDir + "/" + directoryEntry
|
||||||
|
if os.path.isdir(subdir):
|
||||||
|
imgPath = subdir + "/" + os.listdir(subdir)[0]
|
||||||
|
print imgPath
|
||||||
|
tempItem = tempMenu.addItem(directoryEntry, "/home/josh/.mythtv/MythVideo/0088763.jpg")
|
||||||
|
tempItem.setAction(self)
|
||||||
|
|
||||||
|
|
||||||
|
return tempMenu
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import clutter
|
||||||
|
import gtk
|
||||||
|
|
||||||
|
class Spinner (clutter.Texture):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
clutter.Texture.__init__ (self)
|
||||||
|
|
||||||
|
#self.texture = clutter.Texture()
|
||||||
|
pixbuf = gtk.gdk.pixbuf_new_from_file("ui/spinner.svg")
|
||||||
|
self.set_pixbuf(pixbuf)
|
||||||
|
|
||||||
|
timeline = clutter.Timeline(40,20)
|
||||||
|
timeline.set_loop(True)
|
||||||
|
alpha = clutter.Alpha(timeline, clutter.ramp_inc_func)
|
||||||
|
spin_behaviour = clutter.BehaviourRotate(alpha, clutter.Z_AXIS, clutter.ROTATE_CW, 0, 359)
|
||||||
|
spin_behaviour.set_center(self.get_width()/2,self.get_height()/2, 0)
|
||||||
|
spin_behaviour.apply(self)
|
||||||
|
|
||||||
|
timeline.start()
|
|
@ -0,0 +1,46 @@
|
||||||
|
from clutter import cluttergst
|
||||||
|
from myth.MythMySQL import mythVideoDB
|
||||||
|
from myth.MythBackendConn import MythBackendConnection
|
||||||
|
|
||||||
|
class TVPlayer:
|
||||||
|
|
||||||
|
def __init__(self, stage):
|
||||||
|
self.video = cluttergst.VideoTexture()
|
||||||
|
self.stage = stage
|
||||||
|
#audio.set_filename('cast1.avi')
|
||||||
|
#audio.show()
|
||||||
|
|
||||||
|
#test = cluttercairo.Cairo()
|
||||||
|
#audio = cluttergst.Audio()
|
||||||
|
#audio.set_filename('test.mp3')
|
||||||
|
|
||||||
|
#stage.add(audio)
|
||||||
|
#audio.set_playing(True)
|
||||||
|
|
||||||
|
#self.db_conn = mythVideoDB()
|
||||||
|
|
||||||
|
def begin(self, menuMgr):
|
||||||
|
self.myConn = MythBackendConnection(self)
|
||||||
|
self.myConn.start()
|
||||||
|
#self.begin_playback()
|
||||||
|
|
||||||
|
|
||||||
|
def begin_playback(self, fd):
|
||||||
|
#self.video.set_filename("test.mpg")
|
||||||
|
print "File Descriptor: " + str(fd)
|
||||||
|
self.video.set_uri("fd://"+str(fd))
|
||||||
|
self.video.show()
|
||||||
|
|
||||||
|
self.stage.add(self.video)
|
||||||
|
self.video.set_playing(True)
|
||||||
|
|
||||||
|
def on_key_press_event (self, stage, event):
|
||||||
|
#print event.hardware_keycode
|
||||||
|
pass
|
||||||
|
"""if event.keyval == clutter.keysyms.p:
|
||||||
|
if self.paused:
|
||||||
|
self.unpause()
|
||||||
|
else:
|
||||||
|
self.pause()
|
||||||
|
if event.keyval == clutter.keysyms.q:
|
||||||
|
clutter.main_quit()"""
|
|
@ -0,0 +1,139 @@
|
||||||
|
import pygtk
|
||||||
|
import gtk
|
||||||
|
import clutter
|
||||||
|
from myth.MythMySQL import mythVideoDB
|
||||||
|
|
||||||
|
class VideoPlayer():
|
||||||
|
|
||||||
|
def __init__(self, stage):
|
||||||
|
self.stage = stage
|
||||||
|
self.cover_viewer = coverViewer(self.stage)
|
||||||
|
self.videoLibrary = []
|
||||||
|
|
||||||
|
self.is_playing = False
|
||||||
|
|
||||||
|
#This block can be moved to begin() but causes a performance hit when loading the module *shrug*
|
||||||
|
dbMgr = mythVideoDB()
|
||||||
|
results = dbMgr.get_videos()
|
||||||
|
|
||||||
|
for record in results:
|
||||||
|
tempVideo = videoItem()
|
||||||
|
tempVideo.importFromMythObject(record)
|
||||||
|
self.videoLibrary.append(tempVideo)
|
||||||
|
self.cover_viewer.add_image(tempVideo.getCoverfile())
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
def on_key_press_event (self, stage, event):
|
||||||
|
if event.keyval == clutter.keysyms.p:
|
||||||
|
if self.paused:
|
||||||
|
self.unpause()
|
||||||
|
else:
|
||||||
|
self.pause()
|
||||||
|
if event.keyval == clutter.keysyms.q:
|
||||||
|
clutter.main_quit()
|
||||||
|
|
||||||
|
def begin(self, MenuMgr):
|
||||||
|
|
||||||
|
#Create a backdrop for the player. In this case we just use the same background as the menus
|
||||||
|
self.backdrop = clutter.CloneTexture(MenuMgr.get_skinMgr().get_Background())
|
||||||
|
self.backdrop.set_size(self.stage.get_width(), self.stage.get_height())
|
||||||
|
self.backdrop.set_opacity(0)
|
||||||
|
self.backdrop.show()
|
||||||
|
self.stage.add(self.backdrop)
|
||||||
|
#Fade the backdrop in
|
||||||
|
timeline_begin = clutter.Timeline(10,40)
|
||||||
|
alpha = clutter.Alpha(timeline_begin, clutter.ramp_inc_func)
|
||||||
|
begin_behaviour = clutter.BehaviourOpacity(alpha, 0, 255)
|
||||||
|
begin_behaviour.apply(self.backdrop)
|
||||||
|
|
||||||
|
self.cover_viewer.set_opacity(0)
|
||||||
|
self.cover_viewer.show_all()
|
||||||
|
self.cover_viewer.show()
|
||||||
|
self.stage.add(self.cover_viewer)
|
||||||
|
begin_behaviour.apply(self.cover_viewer)
|
||||||
|
|
||||||
|
timeline_begin.start()
|
||||||
|
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
class coverViewer(clutter.Group):
|
||||||
|
|
||||||
|
def __init__(self, stage):
|
||||||
|
clutter.Group.__init__(self)
|
||||||
|
self.stage = stage
|
||||||
|
self.covers = []
|
||||||
|
self.num_covers = 0
|
||||||
|
self.cover_size = 200 #A cover will be cover_size * cover_size (X * Y)
|
||||||
|
self.cover_gap = 10
|
||||||
|
|
||||||
|
self.num_rows = 2
|
||||||
|
self.num_columns = int(self.stage.get_width() / self.cover_size)
|
||||||
|
|
||||||
|
def add_image(self, imagePath):
|
||||||
|
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_position( (self.num_covers * self.cover_size), 0)
|
||||||
|
|
||||||
|
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)
|
||||||
|
tempTexture.set_position(x, y)
|
||||||
|
|
||||||
|
self.add(tempTexture)
|
||||||
|
self.num_covers = self.num_covers +1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#Redo positioning on all textures to add new one :(
|
||||||
|
"""for i in range(self.num_covers):
|
||||||
|
tempTexture = self.get_nth_child(i)
|
||||||
|
x = (self.cover_gap + self.cover_size) * i
|
||||||
|
y = (i % self.num_rows) * self.cover_size
|
||||||
|
tempTexture.set_position(x, y)"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
import sys
|
||||||
|
import clutter
|
||||||
|
#import gobject
|
||||||
|
import pygtk
|
||||||
|
import gtk
|
||||||
|
from Menu import Menu
|
||||||
|
from MenuMgr import MenuMgr
|
||||||
|
from Slideshow import Slideshow
|
||||||
|
from VideoPlayer import VideoPlayer
|
||||||
|
from MusicPlayer import MusicPlayer
|
||||||
|
from TVPlayer import TVPlayer
|
||||||
|
|
||||||
|
|
||||||
|
class MainApp:
|
||||||
|
def __init__ (self):
|
||||||
|
gtk.gdk.threads_init()
|
||||||
|
|
||||||
|
self.stage = clutter.stage_get_default()
|
||||||
|
self.stage.set_color(clutter.color_parse('Black'))
|
||||||
|
#self.stage.set_size(800, 600)
|
||||||
|
self.stage.set_property("fullscreen", True)
|
||||||
|
self.stage.connect('button-press-event', self.on_button_press_event)
|
||||||
|
self.stage.show_all()
|
||||||
|
|
||||||
|
|
||||||
|
#color = clutter.Color(0xff, 0xcc, 0xcc, 0xdd)
|
||||||
|
color = clutter.Color(0, 0, 0, 0)
|
||||||
|
|
||||||
|
self.menuMgr = MenuMgr(self.stage)
|
||||||
|
self.stage.connect('key-press-event', self.menuMgr.on_key_press_event)
|
||||||
|
|
||||||
|
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("nothing", "ui/music.png")
|
||||||
|
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.menu1.selectFirst(True)
|
||||||
|
|
||||||
|
|
||||||
|
self.menu1.getItemGroup().show_all()
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
self.mySlideshow = Slideshow(self.menuMgr, "/mythdata/pics")
|
||||||
|
#self.mySlideshow.loadDir("images/", True)
|
||||||
|
|
||||||
|
self.vidPlayer = VideoPlayer(self.stage)
|
||||||
|
self.tvPlayer = TVPlayer(self.stage)
|
||||||
|
self.musicPlayer = 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)
|
||||||
|
|
||||||
|
self.menu2.getItem(1).setAction(self.menu1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def on_button_press_event (self, stage, event):
|
||||||
|
print "mouse button %d pressed at (%d, %d)" % \
|
||||||
|
(event.button, event.x, event.y)
|
||||||
|
if event.button == 1:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def run (self):
|
||||||
|
self.stage.show()
|
||||||
|
#self.timeline.start()
|
||||||
|
clutter.main()
|
||||||
|
|
||||||
|
def main (args):
|
||||||
|
app = MainApp()
|
||||||
|
app.run()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main(sys.argv[1:]))
|
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 382 KiB |
After Width: | Height: | Size: 162 KiB |
After Width: | Height: | Size: 166 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 103 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 108 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 128 KiB |
After Width: | Height: | Size: 84 KiB |
|
@ -0,0 +1,24 @@
|
||||||
|
#python
|
||||||
|
[execution]
|
||||||
|
# project_file_to_execute
|
||||||
|
# The python file to run for this project
|
||||||
|
# default value =
|
||||||
|
project_file_to_execute = myPyToy.py
|
||||||
|
|
||||||
|
# use_python_to_execute
|
||||||
|
# None
|
||||||
|
# default value = True
|
||||||
|
use_python_to_execute = True
|
||||||
|
|
||||||
|
|
||||||
|
[general]
|
||||||
|
# python_binary_location
|
||||||
|
# The location of the python binary
|
||||||
|
# default value = /usr/bin/python
|
||||||
|
python_binary_location = /usr/bin/python
|
||||||
|
|
||||||
|
# source_directory
|
||||||
|
# The directory containing source code.
|
||||||
|
# default value = /home/josh
|
||||||
|
source_directory = /home/josh/clutter/toys/myPyToy
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
import socket
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
|
||||||
|
class MythBackendConnection(threading.Thread):
|
||||||
|
|
||||||
|
def __init__(self, videoPlayer):
|
||||||
|
self.protocolVersion = 31
|
||||||
|
self.localhost_name = "myhost" # Change this later
|
||||||
|
self.server = "192.168.0.8"
|
||||||
|
self.server_port = 6543
|
||||||
|
self.videoPlayer = videoPlayer
|
||||||
|
|
||||||
|
#2 Sockets, 1 for cmds, 1 for data
|
||||||
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
self.data_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
|
||||||
|
#self.sock.connect( ("192.168.0.8", 6543) )
|
||||||
|
self.connected = False
|
||||||
|
self.recorder = None # Mythtv recorder
|
||||||
|
self.connect(self.server, self.server_port)
|
||||||
|
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
|
#def start(self):
|
||||||
|
# threading.Thread.start(self)
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
print "Starting thread"
|
||||||
|
self.setup_recorder()
|
||||||
|
self.spawn_live()
|
||||||
|
#self.disconnect()
|
||||||
|
|
||||||
|
def receive_reply(self, sock):
|
||||||
|
ret = ""
|
||||||
|
tmp = sock.recv(8)
|
||||||
|
count = int(tmp)
|
||||||
|
#debug("REPLY LEN: %d" % count)
|
||||||
|
ret = sock.recv(count)
|
||||||
|
|
||||||
|
#print "read<--" + ret
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def send_cmd(self, sock, base_cmd):
|
||||||
|
cmd = str(len(base_cmd)).ljust(8) + base_cmd
|
||||||
|
sock.send(cmd)
|
||||||
|
#print "write-->" + cmd
|
||||||
|
|
||||||
|
def connect(self, host, port):
|
||||||
|
self.sock.connect((host, port))
|
||||||
|
|
||||||
|
#Do the protocol version check
|
||||||
|
protString = "MYTH_PROTO_VERSION "+ str(self.protocolVersion)
|
||||||
|
self.send_cmd(self.sock, protString)
|
||||||
|
protRecvString = "ACCEPT[]:[]" + str(self.protocolVersion)
|
||||||
|
result = self.receive_reply(self.sock)
|
||||||
|
print result
|
||||||
|
if not result == protRecvString:
|
||||||
|
#Protocol Version check failed
|
||||||
|
raise RuntimeError, "Myth Protocol version failure. Aborting."
|
||||||
|
|
||||||
|
#Perform the mandatory ANN
|
||||||
|
ANNstring = "ANN Playback " + self.localhost_name + " 0"
|
||||||
|
self.send_cmd(self.sock, ANNstring)
|
||||||
|
ANN_recv_string = "OK" #What a successful return should be
|
||||||
|
result = self.receive_reply(self.sock)
|
||||||
|
if not result == ANN_recv_string:
|
||||||
|
raise RuntimeError, "Myth: ANN connection failed"
|
||||||
|
|
||||||
|
#All looks good
|
||||||
|
self.connected = True
|
||||||
|
|
||||||
|
def disconnect(self):
|
||||||
|
self.sock.close()
|
||||||
|
|
||||||
|
def setup_recorder(self):
|
||||||
|
if not self.connected:
|
||||||
|
print "Cannot get recorder, no server connection exists"
|
||||||
|
return None
|
||||||
|
|
||||||
|
recorder_request_string = "GET_NEXT_FREE_RECORDER[]:[]-1"
|
||||||
|
self.send_cmd(self.sock, recorder_request_string)
|
||||||
|
result = self.receive_reply(self.sock)
|
||||||
|
result_list = result.rsplit("[]:[]")
|
||||||
|
if not result_list[0] == -1:
|
||||||
|
#Then everything worked fine
|
||||||
|
self.recorder = result_list[0]
|
||||||
|
else:
|
||||||
|
print "Myth: No recorders available"
|
||||||
|
|
||||||
|
def spawn_live(self):
|
||||||
|
if self.recorder == None:
|
||||||
|
print "Myth: Cannot spawn live tv, no recorder available"
|
||||||
|
|
||||||
|
chainID = "live-" + self.localhost_name + "-2007-08-03T21:54:21"#+str(time.clock())
|
||||||
|
spawn_string = "QUERY_RECORDER "+str(self.recorder)+"[]:[]SPAWN_LIVETV[]:[]"+chainID +"[]:[]0"
|
||||||
|
self.send_cmd(self.sock, spawn_string)
|
||||||
|
spawn_receive_string = "ok"
|
||||||
|
result = self.receive_reply(self.sock)
|
||||||
|
if not result == spawn_receive_string:
|
||||||
|
print "Myth: failed to spawn live tv. Result: "+str(result)
|
||||||
|
|
||||||
|
#Check the recording
|
||||||
|
check_string = "QUERY_RECORDER "+str(self.recorder)+"[]:[]IS_RECORDING"
|
||||||
|
self.send_cmd(self.sock, check_string)
|
||||||
|
is_recording = self.receive_reply(self.sock)
|
||||||
|
if not is_recording == str(1):
|
||||||
|
#Just send the check again
|
||||||
|
self.send_cmd(self.sock, check_string)
|
||||||
|
|
||||||
|
#Create a new data socket
|
||||||
|
self.data_sock.connect( (self.server, self.server_port) )
|
||||||
|
protString = "MYTH_PROTO_VERSION "+ str(self.protocolVersion)
|
||||||
|
self.send_cmd(self.data_sock, protString)
|
||||||
|
protRecvString = "ACCEPT[]:[]" + str(self.protocolVersion)
|
||||||
|
result = self.receive_reply(self.data_sock)
|
||||||
|
|
||||||
|
#This is just a hack to make sure the channel has locked, I'll fix it later
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
#Get the recording filename
|
||||||
|
filename_string = "QUERY_RECORDER "+str(self.recorder)+"[]:[]GET_CURRENT_RECORDING"
|
||||||
|
self.send_cmd(self.sock, filename_string)
|
||||||
|
filedetails = self.receive_reply(self.sock)
|
||||||
|
detail_list = filedetails.rsplit("[]:[]")
|
||||||
|
filename_list = detail_list[8].rsplit("/")
|
||||||
|
filename_list.reverse()
|
||||||
|
filename = "/" + filename_list[0]
|
||||||
|
print filename
|
||||||
|
|
||||||
|
#Announce our intent to read a file
|
||||||
|
announce_cmd = "ANN FileTransfer " + self.localhost_name + "[]:[]" + filename
|
||||||
|
self.send_cmd(self.data_sock, announce_cmd)
|
||||||
|
result = self.receive_reply(self.data_sock)
|
||||||
|
result_list = result.rsplit("[]:[]")
|
||||||
|
data_socket_id = result_list[1]
|
||||||
|
print "Socket ID: " + str(data_socket_id)
|
||||||
|
|
||||||
|
#Do some housekeeping
|
||||||
|
frontend_ready_cmd = "QUERY_RECORDER "+str(self.recorder) +"[]:[]FRONTEND_READY"
|
||||||
|
self.send_cmd(self.sock, frontend_ready_cmd)
|
||||||
|
result = self.receive_reply(self.sock)
|
||||||
|
input_cmd = "QUERY_RECORDER "+ str(self.recorder) +"[]:[]GET_INPUT"
|
||||||
|
self.send_cmd(self.sock, input_cmd)
|
||||||
|
result = self.receive_reply(self.sock)
|
||||||
|
rec_list_cmd = "MESSAGE[]:[]RECORDING_LIST_CHANGE"
|
||||||
|
self.send_cmd(self.sock, rec_list_cmd)
|
||||||
|
result = self.receive_reply(self.sock)
|
||||||
|
|
||||||
|
#Start a recording thread
|
||||||
|
self.buffer_live(self.sock, self.data_sock, data_socket_id)
|
||||||
|
|
||||||
|
def buffer_live(self, cmd_sock, data_sock, socket_id):
|
||||||
|
#Create a buffer file
|
||||||
|
self.buffer_file = open("test.mpg","w")
|
||||||
|
|
||||||
|
print "grunt0"
|
||||||
|
#read some data
|
||||||
|
x=0
|
||||||
|
request_size = 32768
|
||||||
|
|
||||||
|
#Need to create a bit of a buffer so playback will begin
|
||||||
|
while x<80:
|
||||||
|
transfer_cmd = "QUERY_FILETRANSFER "+ str(socket_id) + "[]:[]REQUEST_BLOCK[]:[]"+str(request_size)
|
||||||
|
self.send_cmd(cmd_sock, transfer_cmd)
|
||||||
|
num_bytes = int(self.receive_reply(cmd_sock))
|
||||||
|
data = data_sock.recv(num_bytes)
|
||||||
|
self.buffer_file.write(data)
|
||||||
|
self.buffer_file.flush()
|
||||||
|
x=x+1
|
||||||
|
|
||||||
|
#data_sock.flush()
|
||||||
|
tempfile = data_sock.makefile("r", request_size)
|
||||||
|
tempfile.flush()
|
||||||
|
self.videoPlayer.begin_playback(tempfile.fileno())
|
||||||
|
print "BEGINNING PLAYBACK!"
|
||||||
|
while x<1000:
|
||||||
|
transfer_cmd = "QUERY_FILETRANSFER "+ str(socket_id) + "[]:[]REQUEST_BLOCK[]:[]"+str(request_size)
|
||||||
|
self.send_cmd(cmd_sock, transfer_cmd)
|
||||||
|
num_bytes = int(self.receive_reply(cmd_sock))
|
||||||
|
data_sock.recv(num_bytes)
|
||||||
|
#self.buffer_file.write(data)
|
||||||
|
#self.buffer_file.flush()
|
||||||
|
x=x+1
|
||||||
|
|
||||||
|
print "Ending playback"
|
||||||
|
self.buffer_file.close()
|
||||||
|
|
||||||
|
def end_stream(self):
|
||||||
|
self.stream = False
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import MySQLdb
|
||||||
|
|
||||||
|
class mythVideoDB():
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.server = "127.0.0.1" #"192.168.0.1"
|
||||||
|
self.db = "mythconverg"
|
||||||
|
self.uid = "root"
|
||||||
|
self.passwd = ""
|
||||||
|
|
||||||
|
db = MySQLdb.connect(self.server, self.uid, self.passwd,self.db)
|
||||||
|
|
||||||
|
self.cursor = db.cursor()
|
||||||
|
#cursor.execute("SELECT * FROM videometadatagenre")
|
||||||
|
# get the resultset as a tuple
|
||||||
|
#result = cursor.fetchall()
|
||||||
|
# iterate through resultset
|
||||||
|
#for record in result:
|
||||||
|
#print record[0] , "-->", record[1]
|
||||||
|
|
||||||
|
def get_videos(self):
|
||||||
|
sql = "SELECT * FROM videometadata WHERE coverfile <> 'No Cover'"
|
||||||
|
|
||||||
|
self.cursor.execute(sql)
|
||||||
|
# get the resultset as a tuple
|
||||||
|
result = self.cursor.fetchall()
|
||||||
|
|
||||||
|
return result
|
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 150 KiB |
After Width: | Height: | Size: 147 KiB |
After Width: | Height: | Size: 114 KiB |
After Width: | Height: | Size: 146 KiB |
After Width: | Height: | Size: 71 KiB |
|
@ -0,0 +1,179 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://web.resource.org/cc/"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
id="svg2263"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.45"
|
||||||
|
version="1.0"
|
||||||
|
sodipodi:docbase="/home/njp/o-hand/svn/clutter/trunk/toys/fluttr/data"
|
||||||
|
sodipodi:docname="spinner.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||||
|
sodipodi:modified="true">
|
||||||
|
<defs
|
||||||
|
id="defs2265">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3302">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#dadada;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3304" />
|
||||||
|
<stop
|
||||||
|
id="stop3327"
|
||||||
|
offset="0.73949581"
|
||||||
|
style="stop-color:#d2d2d2;stop-opacity:1;" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0.86974788"
|
||||||
|
id="stop3333" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3306" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3289">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3291" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#474747;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3293" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3275">
|
||||||
|
<stop
|
||||||
|
id="stop3277"
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||||
|
<stop
|
||||||
|
id="stop3279"
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#cfcfcf;stop-opacity:1;" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3133">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#1f2221;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3135" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3137" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3133"
|
||||||
|
id="linearGradient3139"
|
||||||
|
x1="462.85715"
|
||||||
|
y1="0"
|
||||||
|
x2="462.85715"
|
||||||
|
y2="600.20575"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="scale(1,0.7333333)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3273"
|
||||||
|
x1="478.57144"
|
||||||
|
y1="91.428574"
|
||||||
|
x2="478.57144"
|
||||||
|
y2="345.06439"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3133"
|
||||||
|
id="linearGradient3283"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="478.57144"
|
||||||
|
y1="91.428574"
|
||||||
|
x2="478.57144"
|
||||||
|
y2="345.06439"
|
||||||
|
gradientTransform="matrix(0.9328572,0,0,0.8971429,26.857143,22.628568)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3289"
|
||||||
|
id="linearGradient3287"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.9328572,0,0,0.3085715,26.857139,78.54285)"
|
||||||
|
x1="478.57144"
|
||||||
|
y1="91.428574"
|
||||||
|
x2="478.57144"
|
||||||
|
y2="345.06439" />
|
||||||
|
<radialGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3302"
|
||||||
|
id="radialGradient3316"
|
||||||
|
cx="200"
|
||||||
|
cy="125"
|
||||||
|
fx="200"
|
||||||
|
fy="125"
|
||||||
|
r="50"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1,0,0,-1,0,250)" />
|
||||||
|
<radialGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3302"
|
||||||
|
id="radialGradient3331"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.662898,0.7231039,-0.7293767,0.6686485,194.30678,-79.630422)"
|
||||||
|
cx="200"
|
||||||
|
cy="125"
|
||||||
|
fx="200"
|
||||||
|
fy="125"
|
||||||
|
r="50" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#363636"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
gridtolerance="10000"
|
||||||
|
guidetolerance="10"
|
||||||
|
objecttolerance="10"
|
||||||
|
inkscape:pageopacity="0.75686275"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.4"
|
||||||
|
inkscape:cx="152.97332"
|
||||||
|
inkscape:cy="93.594381"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer4"
|
||||||
|
width="800px"
|
||||||
|
height="440px"
|
||||||
|
inkscape:window-width="910"
|
||||||
|
inkscape:window-height="624"
|
||||||
|
inkscape:window-x="4"
|
||||||
|
inkscape:window-y="47" />
|
||||||
|
<metadata
|
||||||
|
id="metadata2268">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer4"
|
||||||
|
transform="translate(-150,-75)">
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:6;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 200,77.857143 C 173.88286,77.857143 152.85714,98.882857 152.85714,125 C 152.85714,151.11714 173.88286,172.14286 200,172.14286 C 226.11714,172.14286 247.14286,151.11714 247.14286,125 C 247.14286,98.882857 226.11714,77.857143 200,77.857143 z M 192.60446,93.532143 L 192.60446,114.275 L 207.39554,114.275 L 207.39554,93.532143 C 221.71682,96.858206 232.32232,109.63693 232.32232,125 C 232.32232,142.9089 217.9089,157.32232 200,157.32232 C 182.0911,157.32233 167.67768,142.9089 167.67768,125 C 167.67768,109.63693 178.28317,96.858206 192.60446,93.532143 z "
|
||||||
|
id="rect3295" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 71 KiB |