2007-08-26 06:15:05 -07:00
import pygst
import gst
import gobject
2007-09-04 05:19:21 -07:00
import pango
2007-08-14 18:10:53 -07:00
import clutter
2007-12-02 02:18:18 -08:00
import os
2009-01-21 01:51:06 -08:00
import cluttergst
2008-04-14 06:34:29 -07:00
from multimedia . VideoController import VideoController
2008-01-17 04:27:52 -08:00
from modules . video_player . elements . cover_viewer import coverViewer
from modules . video_player . elements . video_details import video_details
from modules . video_player . elements . folder_menu import folderMenu
from modules . video_player . video_object import videoItem
2007-08-14 18:10:53 -07:00
2008-01-06 04:11:17 -08:00
#===============================================================================
#This module displays a basic cover viewer for videos within myth's Mythvideo table
#It defines the following theme elements:
#video_menu_image (Texture): The graphic used on the menu to represent this module
#video_cover_bg_image (Texture): Graphic that serves as the background for the cover viewer grid
#===============================================================================
2007-11-19 03:38:15 -08:00
class Module ( ) :
title = " Videos "
2008-01-15 04:58:09 -08:00
STATE_FOLDERS , STATE_COVERS , STATE_VIDEO = range ( 3 )
2008-01-06 04:11:17 -08:00
2008-01-19 16:18:06 -08:00
#The are just some default values to be used in case of an emergency
2007-12-05 03:49:50 -08:00
coverViewerWidth = 750
2007-12-03 05:19:43 -08:00
coverViewerHeight = 600
2008-01-12 03:46:40 -08:00
coverViewerPosX = 300
coverViewerPosY = 50
2007-12-03 05:19:43 -08:00
coverViewerRows = 3
coverViewerColumns = 4
2008-01-19 16:18:06 -08:00
coverDetailsWidth = 750
foldersPosX = 50
foldersPosX = 50
2007-12-03 05:19:43 -08:00
cover_size = int ( coverViewerWidth / coverViewerColumns )
2008-02-13 15:51:35 -08:00
#Basic UI elements
currentViewer = None
backdrop = None
video_details = None
covers_background = None
2007-08-14 18:10:53 -07:00
2007-12-21 03:39:50 -08:00
def __init__ ( self , glossMgr , dbMgr ) :
self . stage = glossMgr . get_stage ( )
self . glossMgr = glossMgr
2007-12-03 05:19:43 -08:00
self . dbMgr = dbMgr
2008-01-06 04:11:17 -08:00
self . setup_ui ( )
2007-12-03 05:19:43 -08:00
self . viewerLibrary = [ ]
self . folderLibrary = [ ]
2008-01-21 03:09:17 -08:00
self . videoController = VideoController ( glossMgr )
2008-01-06 04:11:17 -08:00
#Setup initial vars
2007-08-14 18:10:53 -07:00
self . is_playing = False
2008-01-15 04:58:09 -08:00
self . controlState = self . STATE_FOLDERS
2008-01-19 16:18:06 -08:00
2007-08-14 18:10:53 -07:00
#This block can be moved to begin() but causes a performance hit when loading the module *shrug*
2008-01-19 16:18:06 -08:00
#All it does is load the initial folders into the viewers
2007-12-02 02:18:18 -08:00
self . baseDir = dbMgr . get_setting ( " VideoStartupDir " )
2008-02-13 15:51:35 -08:00
if self . glossMgr . debug : print " VideoPlayer: Base directory= " + str ( self . baseDir )
2007-12-03 05:19:43 -08:00
self . cwd = self . baseDir
self . folder_level = 0
2008-01-21 05:10:27 -08:00
self . base_folder_menu = folderMenu ( glossMgr , self . coverViewerRows , self . folders_cover_size )
self . base_folder_menu . set_position ( self . foldersPosX , self . foldersPosY )
self . folderLibrary . append ( self . base_folder_menu )
self . load_base_folders ( self . baseDir , self . base_folder_menu )
2008-01-15 04:58:09 -08:00
2008-01-19 16:18:06 -08:00
#Set the current viewer
2008-01-21 05:10:27 -08:00
self . currentViewer = self . base_folder_menu . get_current_viewer ( )
2008-01-28 11:36:43 -08:00
#self.currentViewer.set_depth(self.currentViewer.cover_size)
2008-01-19 16:18:06 -08:00
#Create the details group
self . video_details = video_details ( self . coverDetailsWidth )
self . video_details . set_position ( self . coverDetailsPosX , self . coverDetailsPosY )
2008-01-06 04:11:17 -08:00
def setup_ui ( self ) :
self . menu_image = self . glossMgr . themeMgr . get_texture ( " video_menu_image " , None , None )
2008-01-12 03:46:40 -08:00
#Add the background
self . covers_background = self . glossMgr . themeMgr . get_texture ( " video_covers_background " , self . stage , None )
2008-01-19 16:18:06 -08:00
#Set the number of rows / cols for the viewer (These come from the MythVideo settings in the backend DB)
tmp_rows = self . dbMgr . get_setting ( " VideoGalleryRowsPerPage " )
tmp_cols = self . dbMgr . get_setting ( " VideoGalleryColsPerPage " )
if not tmp_rows is None : self . coverViewerRows = int ( tmp_rows )
if not tmp_cols is None : self . coverViewerColumns = int ( tmp_cols )
#Set the size / position of the cover_viewer
element = self . glossMgr . themeMgr . search_docs ( " video_cover_viewer " , " main " ) . childNodes
( self . coverViewerWidth , self . coverViewerHeight ) = self . glossMgr . themeMgr . get_dimensions ( element , self . stage )
( self . coverViewerPosX , self . coverViewerPosY ) = self . glossMgr . themeMgr . get_position ( element , self . stage )
#Set the all important cover size
self . cover_size = int ( self . coverViewerWidth / self . coverViewerColumns )
#set the size / position of the details group
element = self . glossMgr . themeMgr . search_docs ( " video_cover_details " , " main " ) . childNodes
( self . coverDetailsWidth , self . coverDetailsHeight ) = self . glossMgr . themeMgr . get_dimensions ( element , self . stage )
( self . coverDetailsPosX , self . coverDetailsPosY ) = self . glossMgr . themeMgr . get_position ( element , self . stage )
#set the size / position of the folder menu
element = self . glossMgr . themeMgr . search_docs ( " video_folder_menu " , " main " ) . childNodes
( self . foldersWidth , self . foldersHeight ) = self . glossMgr . themeMgr . get_dimensions ( element , self . stage )
( self . foldersPosX , self . foldersPosY ) = self . glossMgr . themeMgr . get_position ( element , self . stage )
self . folders_cover_size = self . foldersWidth #int(self.foldersWidth / self.coverViewerColumns)
2007-12-03 05:19:43 -08:00
def load_base_folders ( self , dirPath , folder_menu ) :
2007-12-11 02:50:45 -08:00
try :
new_file_list = os . listdir ( dirPath )
except os . error , ( errno , errstr ) :
2008-02-13 15:51:35 -08:00
self . glossMgr . display_msg ( " VideoPlayer File Error " , " Could not load Video directory " )
2007-12-11 02:50:45 -08:00
return
2007-12-03 05:19:43 -08:00
2008-02-13 15:51:35 -08:00
#Videos and Directories
2007-12-03 05:19:43 -08:00
for dir_entry in new_file_list :
tempPath = dirPath + " / " + dir_entry
if os . path . isdir ( tempPath ) and not ( dir_entry [ 0 ] == " . " ) :
2008-01-21 03:09:17 -08:00
tempViewer = coverViewer ( self . glossMgr , self . coverViewerWidth , self . coverViewerHeight , self . coverViewerRows , self . coverViewerColumns )
2007-12-03 05:19:43 -08:00
self . loadDir ( tempPath , tempViewer )
folder_menu . add_base_dir ( dir_entry , tempViewer )
2007-09-03 06:13:34 -07:00
2007-12-03 05:19:43 -08:00
def loadDir ( self , dirPath , cover_viewer ) :
2007-12-02 02:18:18 -08:00
if not os . path . isdir ( dirPath ) :
2008-02-13 15:51:35 -08:00
print " ERROR VideoPlayer: Invalid video path "
2007-12-02 02:18:18 -08:00
return None
final_file_list = [ ]
new_file_list = os . listdir ( dirPath )
2007-12-11 02:50:45 -08:00
2008-02-13 15:51:35 -08:00
#Videos and Directories
2007-12-02 02:18:18 -08:00
for dir_entry in new_file_list :
if os . path . isdir ( dirPath + " / " + dir_entry ) and not ( dir_entry [ 0 ] == " . " ) :
2007-12-03 05:19:43 -08:00
cover_viewer . add_folder ( dir_entry )
2007-12-21 03:39:50 -08:00
#print dir_entry
2007-12-02 02:18:18 -08:00
else :
final_file_list . append ( dir_entry )
2007-12-03 05:19:43 -08:00
#Check if we're empty
if len ( final_file_list ) == 0 :
return
#Make sure the dirPath ends in "/"
if not dirPath [ - 1 ] == " / " :
dirPath = dirPath + " / "
#Generate some SQL to retrieve videos that were in the final_file_list
#Load the videos into the cover viewer
sql = " SELECT * FROM videometadata WHERE filename IN ( "
for filename in final_file_list :
filename = dirPath + filename
sql = sql + " \" " + filename + " \" , "
sqlLength = int ( len ( sql ) - 2 )
sql = sql [ : sqlLength ]
sql = sql + " ) "
2008-02-13 15:51:35 -08:00
if self . glossMgr . debug : print " Video SQL: " + sql
2007-12-03 05:19:43 -08:00
results = self . dbMgr . run_sql ( sql )
#Check for null return
if results == None :
print " VideoPlayer: No connection to DB or no videos found in DB "
return None
#Else add the entries in
for record in results :
tempVideo = videoItem ( )
tempVideo . importFromMythObject ( record )
cover_viewer . add_video ( tempVideo )
2007-12-02 02:18:18 -08:00
2007-11-19 03:38:15 -08:00
#Action to take when menu item is selected
def action ( self ) :
return self
2007-09-03 06:13:34 -07:00
2007-08-14 18:10:53 -07:00
def on_key_press_event ( self , stage , event ) :
2007-12-05 03:49:50 -08:00
up = clutter . keysyms . Up
down = clutter . keysyms . Down
left = clutter . keysyms . Left
right = clutter . keysyms . Right
if event . keyval == clutter . keysyms . q :
clutter . main_quit ( )
#*****************************************************************
#"State based input handling
2008-01-15 04:58:09 -08:00
if self . controlState == self . STATE_FOLDERS :
2007-12-05 03:49:50 -08:00
if event . keyval == clutter . keysyms . Escape :
return True
elif event . keyval == right :
2008-01-15 04:58:09 -08:00
self . controlState = self . STATE_COVERS
2007-12-05 03:49:50 -08:00
self . currentViewer = self . folderLibrary [ self . folder_level ] . get_current_viewer ( )
self . currentViewer . select_first ( )
self . folderLibrary [ self . folder_level ] . on_key_press_event ( event )
2008-01-23 14:21:28 -08:00
self . currentViewer = self . folderLibrary [ self . folder_level ] . get_current_viewer ( )
2007-12-05 03:49:50 -08:00
#**********************************************************
2008-01-15 04:58:09 -08:00
elif self . controlState == self . STATE_VIDEO :
2007-09-05 03:16:17 -07:00
if event . keyval == clutter . keysyms . Escape :
self . videoController . stop_video ( )
self . is_playing = False
2008-01-15 04:58:09 -08:00
self . controlState = self . STATE_COVERS
2007-09-05 03:16:17 -07:00
else :
self . videoController . on_key_press_event ( event )
2007-12-05 03:49:50 -08:00
2007-09-05 03:16:17 -07:00
return False
2007-12-05 03:49:50 -08:00
if event . keyval == clutter . keysyms . p :
if self . paused :
self . unpause ( )
else :
self . pause ( )
#**********************************************************
2008-01-15 04:58:09 -08:00
elif self . controlState == self . STATE_COVERS :
2007-12-05 03:49:50 -08:00
if ( event . keyval == up ) or ( event . keyval == down ) or ( event . keyval == left ) or ( event . keyval == right ) :
2008-01-17 04:27:52 -08:00
timeline = self . currentViewer . on_key_press_event ( event )
video = self . currentViewer . get_current_video ( )
#Do a check to see if the input queue is currently processing
#
if not self . currentViewer . input_queue . is_in_queue ( ) :
2008-01-21 03:09:17 -08:00
if not video is None :
self . video_details . set_video_bare ( video )
self . currentViewer . set_details_update ( False , None )
else :
self . video_details . set_folder ( self . currentViewer . folderLibrary [ ( self . currentViewer . currentSelection - len ( self . currentViewer . folderLibrary ) ) ] )
#self.video_details.clear()
2008-01-17 04:27:52 -08:00
else :
self . currentViewer . set_details_update ( True , self . video_details )
2007-08-29 06:35:13 -07:00
2007-12-05 03:49:50 -08:00
if event . keyval == clutter . keysyms . Return :
#Find whether the current item is a folder or video
item = self . currentViewer . get_current_item ( )
if item . isFolder :
2008-06-25 06:43:15 -07:00
self . glossMgr . display_msg ( " Msg " , " Folders are not yet supported ( %s ) " % item . title . get_text ( ) )
2007-12-05 03:49:50 -08:00
else :
self . play_video ( )
2007-09-05 03:16:17 -07:00
2007-12-05 03:49:50 -08:00
if event . keyval == clutter . keysyms . Escape :
self . currentViewer . select_none ( )
2008-01-15 04:58:09 -08:00
self . controlState = self . STATE_FOLDERS
2007-09-05 03:16:17 -07:00
2007-08-29 06:35:13 -07:00
2007-08-14 18:10:53 -07:00
2007-12-21 03:39:50 -08:00
def begin ( self , glossMgr ) :
2007-11-22 02:41:29 -08:00
#Check that the library actually contains something
2007-12-11 02:50:45 -08:00
#if len(self.currentViewer.textureLibrary) == 0:
if self . currentViewer is None :
2008-02-12 02:23:22 -08:00
self . glossMgr . 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. " )
2008-04-14 06:34:29 -07:00
self . currentViewer = None
2007-11-22 02:41:29 -08:00
self . stop ( )
return
2007-09-03 06:13:34 -07:00
2007-08-14 18:10:53 -07:00
#Create a backdrop for the player. In this case we just use the same background as the menus
2008-06-29 04:11:33 -07:00
self . backdrop = clutter . CloneTexture ( glossMgr . background ) #glossMgr.get_themeMgr().get_texture("background", None, None) #clutter.CloneTexture(glossMgr.get_skinMgr().get_Background())
2007-08-14 18:10:53 -07:00
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 )
2008-01-12 03:46:40 -08:00
#Add the covers background
self . covers_background . set_opacity ( 0 )
self . covers_background . show ( )
self . stage . add ( self . covers_background )
#Add the folders menu
2008-01-17 04:27:52 -08:00
self . folderLibrary [ 0 ] . set_opacity ( 0 )
2007-12-05 03:49:50 -08:00
self . folderLibrary [ 0 ] . show ( )
2008-01-17 04:27:52 -08:00
self . stage . add ( self . folderLibrary [ 0 ] )
2007-12-05 03:49:50 -08:00
2008-01-12 03:46:40 -08:00
#Add the cover viewer
2007-12-03 05:19:43 -08:00
self . currentViewer . set_opacity ( 0 )
self . currentViewer . show_all ( )
self . currentViewer . show ( )
2007-12-05 03:49:50 -08:00
self . currentViewer . set_position ( self . coverViewerPosX , self . coverViewerPosY )
2008-01-15 04:58:09 -08:00
self . stage . add ( self . currentViewer )
2008-01-17 04:27:52 -08:00
#Add the video details
self . video_details . set_opacity ( 0 )
self . video_details . show_all ( )
self . video_details . show ( )
self . stage . add ( self . video_details )
2008-01-12 03:46:40 -08:00
#Fade everything in
timeline_begin = clutter . Timeline ( 10 , 40 )
alpha = clutter . Alpha ( timeline_begin , clutter . ramp_inc_func )
self . begin_behaviour = clutter . BehaviourOpacity ( opacity_start = 0 , opacity_end = 255 , alpha = alpha )
self . begin_behaviour . apply ( self . backdrop )
2008-01-17 04:27:52 -08:00
self . begin_behaviour . apply ( self . folderLibrary [ 0 ] )
2008-01-12 03:46:40 -08:00
self . begin_behaviour . apply ( self . covers_background )
self . begin_behaviour . apply ( self . currentViewer )
2008-01-17 04:27:52 -08:00
self . begin_behaviour . apply ( self . video_details )
2008-01-12 03:46:40 -08:00
2007-12-03 05:19:43 -08:00
#self.viewerLibrary[0].set_position(50, 40)
2008-01-17 04:27:52 -08:00
#self.currentViewer.toggle_details() #Turns the details group on
2007-12-05 03:49:50 -08:00
#self.currentViewer.select_first()
2008-01-12 03:46:40 -08:00
2007-08-14 18:10:53 -07:00
timeline_begin . start ( )
2007-12-05 03:49:50 -08:00
#self.folder_menu = folderMenu(self.stage, self.currentViewer.num_visible_rows, self.currentViewer.cover_size)
#self.folder_menu.set_dir_cover_viewer(self.currentViewer)
2007-12-03 05:19:43 -08:00
2007-08-14 18:10:53 -07:00
def stop ( self ) :
2007-12-21 03:39:50 -08:00
self . glossMgr . currentPlugin = None
2007-12-02 02:18:18 -08:00
2007-08-15 07:23:45 -07:00
#Fade everything out
timeline_stop = clutter . Timeline ( 10 , 30 )
alpha = clutter . Alpha ( timeline_stop , clutter . ramp_inc_func )
2008-01-05 06:29:48 -08:00
self . stop_behaviour = clutter . BehaviourOpacity ( opacity_start = 255 , opacity_end = 0 , alpha = alpha )
2008-02-12 02:23:22 -08:00
if not self . currentViewer is None : self . stop_behaviour . apply ( self . currentViewer )
if not self . backdrop is None : self . stop_behaviour . apply ( self . backdrop )
if not self . folderLibrary [ self . folder_level ] is None : self . stop_behaviour . apply ( self . folderLibrary [ self . folder_level ] )
if not self . video_details is None : self . stop_behaviour . apply ( self . video_details )
if not self . covers_background is None : self . stop_behaviour . apply ( self . covers_background )
2007-08-15 07:23:45 -07:00
timeline_stop . connect ( ' completed ' , self . destroyPlugin )
timeline_stop . start ( )
2007-11-22 02:41:29 -08:00
2007-08-15 07:23:45 -07:00
def destroyPlugin ( self , data ) :
2008-04-14 06:34:29 -07:00
self . stage . remove ( self . backdrop )
2007-12-03 05:19:43 -08:00
self . stage . remove ( self . currentViewer )
2007-12-05 03:49:50 -08:00
self . stage . remove ( self . folderLibrary [ self . folder_level ] )
2008-01-17 04:27:52 -08:00
self . stage . remove ( self . video_details )
self . stage . remove ( self . covers_background )
2007-08-15 07:23:45 -07:00
self . backdrop . hide ( )
#self.stage.remove(self.overlay)
2007-11-15 00:36:01 -08:00
def play_video ( self ) :
2007-12-03 05:19:43 -08:00
vid = self . currentViewer . get_current_item ( ) . video
2007-11-15 00:36:01 -08:00
uri = " file:// " + str ( vid . filename )
self . videoController . play_video ( uri , self )
self . is_playing = True
2008-01-15 04:58:09 -08:00
self . controlState = self . STATE_VIDEO
2007-11-15 00:36:01 -08:00
2007-12-03 05:19:43 -08:00
self . stage . remove ( self . currentViewer )
2008-01-21 05:10:27 -08:00
self . stage . remove ( self . base_folder_menu )
2007-08-15 07:23:45 -07:00
2007-11-13 05:03:39 -08:00
def stop_video ( self ) :
if not self . is_playing :
return
self . is_playing = False
2007-08-14 18:10:53 -07:00
2007-11-19 03:38:15 -08:00
timeline = clutter . Timeline ( 15 , 25 )
2007-12-03 05:19:43 -08:00
self . currentViewer . set_opacity ( 0 )
2008-01-21 05:10:27 -08:00
self . base_folder_menu . set_opacity ( 0 )
2007-11-19 03:38:15 -08:00
alpha = clutter . Alpha ( timeline , clutter . ramp_inc_func )
2008-01-05 06:29:48 -08:00
self . behaviour = clutter . BehaviourOpacity ( opacity_start = 0 , opacity_end = 255 , alpha = alpha )
2007-12-03 05:19:43 -08:00
self . behaviour . apply ( self . currentViewer )
2008-01-21 05:10:27 -08:00
self . behaviour . apply ( self . base_folder_menu )
2007-11-19 03:38:15 -08:00
2008-01-15 04:58:09 -08:00
self . stage . add ( self . currentViewer )
2008-01-21 05:10:27 -08:00
self . stage . add ( self . base_folder_menu )
2007-12-03 05:19:43 -08:00
self . currentViewer . show ( )
2007-11-19 03:38:15 -08:00
timeline . start ( )
2007-08-14 18:10:53 -07:00
def pause ( self ) :
pass
def unpause ( self ) :
2007-08-26 06:15:05 -07:00
pass
2008-01-17 04:27:52 -08:00
2007-08-14 18:10:53 -07:00
2007-11-13 05:03:39 -08:00