Added gui msg within MenuMgr

Converted TV player to read directly from the socket file descriptor. I think the GST buffer is too small however as it jerks.
This commit is contained in:
noisymime 2007-11-22 10:41:29 +00:00
parent 1593e437b5
commit a3351b2c66
7 changed files with 166 additions and 48 deletions

View File

@ -3,6 +3,7 @@ from SkinMgr import SkinMgr
from Spinner import Spinner
import pygtk
import gtk
import pango
class MenuMgr:
@ -11,6 +12,7 @@ class MenuMgr:
self.menus = []
self.menuHistory = [] #A list that contains menus in the order that they've been viewed
self.currentMenu = None
self.uiMsg = message(stage)
self.skinMgr = SkinMgr(self.stage)
background = self.skinMgr.get_Background()
@ -108,21 +110,30 @@ class MenuMgr:
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)
#Firstly check whether any messages are currently displayed
if self.uiMsg.active:
self.uiMsg.on_key_press_event(stage, event)
return
#Secondly, 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 none of these things, the menu needs to do something
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)
if event.keyval == clutter.keysyms.Return: #return button pressed
# Need to decide what action to take
# Options are:
# 1) Switch to a new menu
# 2) Launch a module
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)
@ -131,6 +142,7 @@ class MenuMgr:
#We have a plugin and need to start it
self.currentPlugin = action
action.begin( self )
# This is tres bodge
if event.keyval == clutter.keysyms.Escape:
#If there's a plugin running then end it
if not self.currentPlugin == None:
@ -153,6 +165,9 @@ class MenuMgr:
if len(self.menuHistory)>1:
self.transition_fade_zoom(self.menuHistory.pop(), self.menuHistory[-1])
self.currentMenu = self.menuHistory[-1]
def display_msg(self, title, msg):
self.uiMsg.display_msg(title, msg)
class MenuSelector(clutter.Texture):
x_offset = -50
@ -243,3 +258,93 @@ class MenuSelector(clutter.Texture):
def get_width(self):
return self.width
class message():
font = "Lucida Grande "
message_font_size = 30
detail_font_size = 22
def __init__(self, stage):
self.stage = stage
self.active = False
self.backdrop = clutter.Rectangle()
self.backdrop.set_color(clutter.color_parse('Black'))
#self.backdrop.set_opacity(240)
self.backdrop.set_width(self.stage.get_width())
self.backdrop.set_height(self.stage.get_height())
self.main_group = clutter.Group()
pixbuf = gtk.gdk.pixbuf_new_from_file("ui/splash_box.png")
self.box = clutter.Texture()
self.box.set_pixbuf(pixbuf)
self.box.set_opacity(int(255 * 0.75))
self.box.set_height(int(self.stage.get_height()* 0.3))
self.main_group.add(self.box)
self.message = clutter.Label()
self.message.set_font_name(self.font + str(self.message_font_size))
self.message.set_color(clutter.color_parse('White'))
pos_x = int(self.box.get_width() * 0.10)
pos_y = int(self.box.get_height() * 0.10)
self.message.set_position(pos_x, pos_y)
width = int(self.box.get_width() * 0.80) #Width is 80% of the box, giving 10% gap each side
self.message.set_width(width)
self.message.set_ellipsize(pango.ELLIPSIZE_END)
self.message.set_text("")
self.main_group.add(self.message)
self.detail = clutter.Label()
self.detail.set_font_name(self.font + str(self.detail_font_size))
self.detail.set_color(clutter.color_parse('White'))
pos_x = self.message.get_x()
pos_y = self.message.get_y() + self.message.get_height()
self.detail.set_position(pos_x, pos_y)
height = self.box.get_height() - pos_y
self.detail.set_height(height)
#self.detail.set_ellipsize(pango.ELLIPSIZE_END)
self.main_group.add(self.detail)
self.detail.set_line_wrap(True)
group_x = (self.stage.get_width()/2) - (self.box.get_width()/2)
group_y = (self.stage.get_height()/2) - (self.box.get_height()/2)
self.main_group.set_position(group_x, group_y)
def display_msg(self, title, text):
self.active = True
self.message.set_text(title)
self.detail.set_text(text)
width = int(self.box.get_width() * 0.80) #Width is 80% of the box, giving 10% gap each side
self.detail.set_width(width)
self.message.set_width(width)
self.main_group.set_opacity(0)
self.backdrop.set_opacity(0)
self.stage.add(self.backdrop)
self.stage.add(self.main_group)
self.main_group.show_all()
self.backdrop.show()
self.timeline = clutter.Timeline(10,30)
alpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
self.behaviour_group = clutter.BehaviourOpacity(alpha, 0, 255)
self.behaviour_backdrop = clutter.BehaviourOpacity(alpha, 0, 180)
self.behaviour_group.apply(self.main_group)
self.behaviour_backdrop.apply(self.backdrop)
self.timeline.start()
def hide_msg(self):
self.active = False
self.timeline = clutter.Timeline(10,30)
alpha = clutter.Alpha(self.timeline, clutter.ramp_inc_func)
self.behaviour_group = clutter.BehaviourOpacity(alpha, 255, 0)
self.behaviour_backdrop = clutter.BehaviourOpacity(alpha, 180, 0)
self.behaviour_group.apply(self.main_group)
self.behaviour_backdrop.apply(self.backdrop)
self.timeline.start()
def on_key_press_event (self, stage, event):
self.hide_msg()

Binary file not shown.

View File

@ -1,5 +1,6 @@
import sys, clutter, clutter.cluttergst, gst, pygst, gtk, pygtk, gobject
import threading
import os
class VideoController:
@ -35,29 +36,38 @@ class VideoController:
def play_video(self, uri, player):
self.player = player
self.stage.add(self.video_texture)
#f = open("/home/josh/eclipse/gloss-mc/test.mpg",'r')
#fd = os.dup(f.fileno())
#uri = "fd://" + str(fd)
#print "New URI: " + uri
self.video_texture.set_uri(uri)
self.video_texture.set_position(0, 0)
self.video_texture.show()
#We need to connect to the message queue on the playbin to watch for any message (ie codec or file not found errors)
self.bin = self.video_texture.get_playbin()
bus = self.video_texture.get_playbin().get_bus()
bus.add_signal_watch()
bus.connect('message', self.on_bus_message)
#Now we can start the video
self.video_texture.set_playing(True)
self.bin.set_state(gst.STATE_PAUSED)
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"
#Currently this is checking two types of msgs:
# 1) A "codec not found" warning, at which stage playback is stopped
# 2) A Buffering msg. This pauses the video until the buffer is at 100%
def on_bus_message(self, bus, message):
t = message.type
print "message type: " + str(t)
if t == gst.MESSAGE_ELEMENT:
#This occurs when an invalid codec is attempted to be played
#Need to insert some form of message to the user here
#print "Element: " + message.structure.to_string()
struc = message.structure
if struc is None:
return
@ -66,8 +76,20 @@ class VideoController:
self.isPlaying = False
self.video_texture.set_playing(False)
self.player.stop_video()
if t == gst.MESSAGE_BUFFERING:
percent = message.parse_buffering()
print "Buffer: " + str(percent)
if percent < 100:
self.bin.set_state(gst.STATE_PAUSED)
else:
self.bin.set_state(gst.STATE_PLAYING)
if t == gst.MESSAGE_STATE_CHANGED:
prev, current, next = message.parse_state_changed()
print "State Changed. Previous state: " + str(prev)
print "State Changed. Current state: " + str(current)
elif t == gst.STREAM_ERROR:
print "OHH NOES!"
#print "OHH NOES!"
print "GST Message: " + message.structure.to_string()
def stop_video(self):
if self.video_texture.get_playing():
@ -92,9 +114,9 @@ class VideoController:
self.stage.remove(self.blackdrop)
self.blackdrop = None
def customBin(self):
self.src = gst.element_factory_make("filesrc", "src");
self.src.set_property("location", "/home/josh/clutter/toys/gloss/test.mpg")
def customBin(self, fd):
self.src = gst.element_factory_make("fdsrc", "src");
self.src.set_property("fd", fd)
self.demux = gst.element_factory_make("ffdemux_mpegts", "demux")
self.queue1 = gst.element_factory_make("queue", "queue1")
self.queue2 = gst.element_factory_make("queue", "queue2")

View File

@ -167,24 +167,28 @@ class MythBackendConnection(threading.Thread):
def buffer_live(self, cmd_sock, data_sock, socket_id):
#Create a buffer file
buffer_file_name = "test.mpg"
self.buffer_file = open(buffer_file_name,"w")
#buffer_file_name = "test.mpg"
#self.buffer_file = open(buffer_file_name,"w")
request_size = 32768
max_request_size = 135000
#max_request_size = 135000
max_request_size = 270000
request_size_step = 16384
#Need to create a bit of a buffer so playback will begin
"""
x=0
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.write(data)
x=x+1
self.buffer_file.flush()
self.videoPlayer.begin_playback(buffer_file_name)
#self.videoPlayer.begin_playback(self.data_sock.fileno())
#self.buffer_file.flush()
"""
#self.videoPlayer.begin_playback(buffer_file_name)
reader_fd = os.dup(data_sock.fileno())
self.videoPlayer.begin_playback(reader_fd)
print "BEGINNING PLAYBACK!"
self.Playing = True
@ -192,8 +196,8 @@ class MythBackendConnection(threading.Thread):
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)
data_sock.recv(num_bytes)
#self.buffer_file.write(data)
#This tries to optimise the request size
#print "Received: " + str(num_bytes)
@ -201,12 +205,12 @@ class MythBackendConnection(threading.Thread):
request_size = request_size + request_size_step
if request_size > max_request_size:
request_size = max_request_size
elif (request_size > request_size_step):
elif (request_size > request_size_step) and (num_bytes != request_size):
request_size = request_size - request_size_step
print "Ending playback"
self.buffer_file.close()
#self.buffer_file.close()
def message_socket_mgr(self, msg_socket):
#Do the protocol version check

View File

@ -34,35 +34,14 @@ class Module:
self.isRunning = True
def begin_playback(self, buffer_file):
def begin_playback(self, fd):#buffer_file):
self.menuMgr.get_selector_bar().set_spinner(False)
uri = "file://" + os.getcwd() +"/" + buffer_file
#uri = "file://" + os.getcwd() +"/" + buffer_file
#f = open(os.getcwd() +"/" + buffer_file, 'r')
uri = "fd://" + str(fd)
#print uri
self.videoController.play_video(uri, self)
"""
timeline = clutter.Timeline(15, 25)
alpha = clutter.Alpha(timeline, clutter.ramp_inc_func)
behaviour = clutter.BehaviourOpacity(alpha, 0,255)
behaviour.apply(self.video)
self.stage.add(self.video)
self.video.set_playing(True)
timeline.start()
#return None
"""
def video_size_change(self, texture, width, height):
self.video.set_property("sync-size", False)
self.video.set_position(0, 0)
xy_ratio = float(width / height)
print "XY Ratio: " + str(xy_ratio)
width = int(self.stage.get_width())
height = int (width / xy_ratio)
height = 768
self.video.set_size(width, height)
def stop(self):
self.videoController.stop_video()
self.myConn.stop() # Stops the backend / frontend streaming

View File

@ -131,7 +131,7 @@ class coverViewer(clutter.Group):
self.timeline.start()
def select_first(self):
def select_first(self):
self.timeline = clutter.Timeline(20,80)
self.current_video_details.set_video(self.videoLibrary[0], self.timeline)

View File

@ -15,6 +15,7 @@ class Module():
def __init__(self, MenuMgr, dbMgr):
self.stage = MenuMgr.get_stage()
self.MenuMgr = MenuMgr
self.cover_viewer = coverViewer(self.stage, 800, 600)
self.videoController = VideoController(self.stage)
self.is_playing = False
@ -69,6 +70,11 @@ class Module():
def begin(self, MenuMgr):
#Check that the library actually contains something
if self.cover_viewer.num_covers == 0:
self.MenuMgr.display_msg("Error: No videos", "There are no videos available in the library. This maybe caused by an empty library or a failed connection to the server.")
self.stop()
return
#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())
@ -105,6 +111,8 @@ class Module():
self.stop_behaviour.apply(self.backdrop)
timeline_stop.connect('completed', self.destroyPlugin)
timeline_stop.start()
self.MenuMgr.currentPlugin = None
def destroyPlugin(self, data):
self.stage.remove(self.cover_viewer)