Player.py :  » Media-Sound-Audio » Christine-Media-Player » christine-0.6.1 » libchristine » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Media Sound Audio » Christine Media Player 
Christine Media Player » christine 0.6.1 » libchristine » Player.py
# This file is part of the Christine project
#
# Copyright (c) 2006-2007 Marco Antonio Islas Cruz
#
# Christine is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Christine is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
#
# @category  libchristine
# @package   Player
# @author    Marco Antonio Islas Cruz <markuz@islascruz.org>
# @author    Miguel Vazquez Gocobachi <demrit@gnu.org>
# @copyright 2006-2007 Christine Development Group
# @license   http://www.gnu.org/licenses/gpl.txt
from libchristine.christineConf import christineConf
from libchristine.Events import christineEvents
from libchristine.Validator import isFile
from globalvars import CHRISTINE_VIDEO_EXT
from libchristine.Logger import LoggerManager
from libchristine.ui import interface
import gst
import gtk
import gobject
import os


BORDER_WIDTH = 0

#
# Player for manager play files
#
class Player(gtk.DrawingArea, object):
  """
  Player for manage play files
  """
  __gsignals__= {
        'player-play' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                tuple()),
        'player-pause' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                tuple()),
        'player-stop' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                tuple()),
        'set-location' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                (gobject.TYPE_PYOBJECT, 
                  gobject.TYPE_PYOBJECT))
        }
  #
  # Constructor
  #
  def __init__(self):
    """
     Constructor
    """
    gtk.DrawingArea.__init__(self)
    self.christineConf   = christineConf()
    self.set_events(gtk.gdk.POINTER_MOTION_MASK |
        gtk.gdk.POINTER_MOTION_HINT_MASK |
        gtk.gdk.EXPOSURE_MASK |
        gtk.gdk.KEY_PRESS_MASK |
        gtk.gdk.KEY_RELEASE_MASK) 
    self.unset_flags(gtk.DOUBLE_BUFFERED)
    self.set_flags(gtk.APP_PAINTABLE)
    self.set_size_request(100,100)
    self.interface = interface()
    self.interface.Player = self
    self.__Logger = LoggerManager().getLogger('Player')
    self.__Logger.info('Starting player')
    self.__Text = ''
    self.location = None
    self.config = christineConf(self)
    self.events = christineEvents()
    self.__ShouldShow = False
    self.__createPlaybin()
    self.connect('expose-event', self.exposeCallback)
    
  def __createPlaybin(self):
    """
    Create the playbin
    """
    self.__Logger.info("Creating the Player")
    self.__PlayBin = self.__elementFactoryMake('playbin')
    self.__elementSetProperty(self.__PlayBin,'delay',
                self.config.getInt('backend/gst_delay'))
    self.play = self.__PlayBin
    self.bus  = self.__PlayBin.get_bus()
    self.getState = self.__PlayBin.get_state
    self.__updateAudioSink()
    self.__updateVideoSink()
    self.__updateAspectRatio()
    self.config.notifyAdd('backend/audiosink',    self.__updateAudioSink)
    self.config.notifyAdd('backend/videosink',    self.__updateVideoSink)
    self.config.notifyAdd('backend/aspect-ratio', self.__updateAspectRatio)
    self.__updateAudioSink()
    self.__updateVideoSink()
    active = self.config.getBool("ui/visualization")
    if active: self.setVisualization(False)
    self.setVisualization(active)
    self.__connectSinks()
    self.query_duration = self.__PlayBin.query_duration
    self.query_position = self.__PlayBin.query_position

  def __connectSinks(self):
    """
    Connect the sinks to tye playbin by setting the sinks as elements in the
    playbin
    """
    self.__Logger.info("Connecting sinks")
    self.__elementSetProperty(self.__PlayBin,'audio-sink', self.__AudioSinkPack)
    self.__elementSetProperty(self.__PlayBin,'video-sink', self.VideoSink)

  def __updateAudioSink(self, *args):
    """
    Updates audio sink
    """
    self.__Logger.info("__updateAudioSink")
    state = self.getState()[1]
    self.__AudioSinkPack = self.__elementFactoryMake('bin')
    if not self.getLocation() == None:
      self.pause()
    asink = self.config.getString('backend/audiosink')
    self.__AudioSink = self.__elementFactoryMake(asink)
    self.__AudioSinkPack.add(self.__AudioSink)
    self.audio_ghost = gst.GhostPad('sink', self.__AudioSink.get_pad('sink'))
    self.__AudioSinkPack.add_pad(self.audio_ghost)
    self.__elementSetProperty(self.__PlayBin,'audio-sink', self.__AudioSinkPack)
    if asink == 'alsasink':
      self.__AudioSink.set_property('device', 'default')
    if gst.State(gst.STATE_PLAYING) == state:
      self.playIt()

  def __updateVideoSink(self, *args):
    """
    Updates video sink
    """
    state = self.getState()[1]
    if self.getLocation() != None:
      self.pause()
    vsink = self.config.getString('backend/videosink')
    self.VideoSink = self.__elementFactoryMake(vsink, 'vsink')
    self.__elementSetProperty(self.__PlayBin,'video-sink', self.VideoSink)
    self.__elementSetProperty(self.VideoSink,'force-aspect-ratio', True)
    self.__elementSetProperty(self.VideoSink,'draw-borders', True)
    if gst.State(gst.STATE_PLAYING) == state:
      self.playIt()

  def __updateAspectRatio(self, client = '', cnx_id = '', entry = '', userdata = ''):
    """
    Updates aspect ratio
    """
    aspect_ratio = self.config.getString('backend/aspect-ratio')
    if not aspect_ratio == None:
      self.__elementSetProperty(self.VideoSink, 'pixel-aspect-ratio',
                  aspect_ratio)

  def __elementFactoryMake(self,element, type= ''):
    '''
    Wrap the gst.element_factory_make, but add logging capabilities

    @param element: element to be created (str)
    '''
    self.__Logger.info("creatign a gst element %s"%element)
    return gst.element_factory_make(element, type)

  def __elementSetProperty(self,element,property,value):
    ''' 
    Wrap the self.(element).set_property, but add logging capabilities

    @parame element: gst.Element
    @param property: string Property
    @param value: property value
    '''
    self.__Logger.info("setting property '%s' with value '%s", property,str(value))
    try:
      element.set_property(property,value)
      return True
    except Exception, e:
      self.__Logger.exception(e)

  def exposeCallback(self, window, event):
    """
    Draw the visualization widget.
    """
    # Drawing a black background because some
    # GTK themes (clearlooks) don't draw it
    
    if not self.window:
      return False
    w, h = (self.allocation.width, self.allocation.height)
    try:
      self.VideoSink.set_xwindow_id(self.window.xid)
    except:
      pass
    self.__Context = self.window.cairo_create()
    self.__Context.rectangle(BORDER_WIDTH, BORDER_WIDTH,
                             w - 2 * BORDER_WIDTH,
                             h - 2 * BORDER_WIDTH)
    self.__Context.clip_preserve()

    self.__Context.set_source_rgba(0,0,0)
    self.__Context.fill_preserve()
    self.__Context.stroke()
    if self.__ShouldShow:
      width = self.getTag('width')
      height = self.getTag('height')
      if not width or not height:
        width, height = 400,200
      self.set_size_request(width, height)
      self.show()
  
  def setLocation(self, file):
    self.Tags = {}
    last_location = self.getLocation()
    self.location = file
    if getattr(self, 'visualizationPlugin', None) != None:
      self.__elementSetProperty(self.__PlayBin,'vis-plugin', self.visualizationPlugin)
    if (isFile(file)):
      self.__setState(gst.STATE_READY)
      if os.name == 'nt':
        p = file.split("\\")
        file = "/" + "/".join(p)
      nfile = 'file://' + file
      self.__elementSetProperty(self.__PlayBin,'uri', nfile)
      self.__elementSetProperty(self.__PlayBin, 'suburi', None)
      self.__elementSetProperty(self.__PlayBin, 'subtitle-font-desc', None)
      self.__elementSetProperty(self.__PlayBin, 'subtitle-encoding', None)
      if self.isVideo():
        self.__ShouldShow = True
        self.__elementSetProperty(self.VideoSink,'force-aspect-ratio', True)
        subtitle = '.'.join(file.split('.')[:-1]) + '.srt'
        if os.path.exists(subtitle):
          self.__elementSetProperty(self.__PlayBin, 'suburi', 'file://'+subtitle)
          self.__elementSetProperty(self.__PlayBin, 'subtitle-font-desc', self.config.getString('backend/subtitle_font_desc'))
          self.__elementSetProperty(self.__PlayBin, 'subtitle-encoding', self.config.getString('backend/subtitle_encoding'))
          
    else:
      file = file.replace( "\\'", r"'\''" )
      if file:
        self.__elementSetProperty(self.__PlayBin,'uri', file)
    self.emit('set-location',last_location, self.location)
    self.christineConf.setValue('backend/last_played', self.location)
    self.show()
    self.getType()
    self.exposeCallback(self.window, gtk.gdk.Event(gtk.gdk.EXPOSE))

  def getLocation(self):
    """
    Gets location
    """
    return self.location    

  def playIt(self):
    """
    Play the current song
    """
    self.__setState(gst.STATE_PLAYING)
    self.emit('player-play')
    self.events.executeEvent('onPlay')

  def pause(self):
    """
    Pause the current song
    """
    self.__setState(gst.STATE_PAUSED)
    self.emit('player-pause')

  def stop(self):
    """
    Stop the current song
    """
    self.__setState(gst.STATE_NULL)
    self.emit('player-stop')

  def __setState(self,state):
    '''
    Sets the state of the playtin to the state in
    the state param.
    Add loggin capabilites

    @param: state: gst.STATE
    '''
    self.__Logger.info("Setting the state of the Playbin to %s"%repr(state))
    self.__PlayBin.set_state(state)

  def setVisualization(self, active = False):
    """
    Sets visualization active or desactive
    """
    self.__Logger.info("Setting visualization to %s"%repr(active))
    if active:
      self.visualizationPlugin = self.__elementFactoryMake(self.config.getString('backend/vis-plugin'))
      self.__elementSetProperty(self.VideoSink,'force-aspect-ratio', self.isVideo())
      self.__ShouldShow = True
      self.__elementSetProperty(self.__PlayBin,'vis-plugin', 
                  self.visualizationPlugin)
      self.show()
    else:
      if gst.STATE_PLAYING in self.getState():
        location = self.getLocation()
        sec = self.query_duration(gst.FORMAT_TIME)[0]
        self.stop()
        gobject.timeout_add(500, self.__replay, location, sec)
      self.__elementSetProperty(self.__PlayBin,'vis-plugin', None)
      #self.visualizationPlugin = None
      self.__elementSetProperty(self.VideoSink,'force-aspect-ratio', True)
      self.__ShouldShow = False
    return True
  
  def  __replay(self, location, sec):
    self.setLocation(location)
    sec = (sec / gst.SECOND)
    self.playIt()
    self.seekTo(sec)
    return False

  def __do_quit_visualization(self, sec):
    
    return True

  def setVolume(self, volume):
    if (volume < 0):
      volume = 0.0
    elif (volume > 1):
      volume = 1.0
    self.__elementSetProperty(self.__PlayBin,'volume', volume)

  def getTag(self, key):
    """
    Gets a specific tag
    """
    try:
      return self.Tags[key]
    except:
      return ""

  def foundTagCallback(self, tags):
    """
    Callback to found tags
    """
    if len(tags.keys()):
      for i in tags.keys():
        if tags[i] != None:
          self.Tags[i] = tags[i]
    self.getType()

  def getType(self):
    """
    Sets file type
    """
    if self.isVideo():
      result =  'video'
    elif self.isSound():
      result =  'sound'
    else:
      result = 'Unknown'
    return result
      

  def nano2str(self,nanos):
    """
    Returns a string like 00:00:00.000000
    """
    ts = (nanos / gst.SECOND)
    str = '%02d:%02d:%02d.%06d' % ((ts / 3600), 
                  (ts / 60), (ts % 60), 
                  (nanos % gst.SECOND))
    return str

  def seekTo(self, sec):
    """
    Seek to secs
    """
    sec = (long(sec) * gst.SECOND)
    self.__PlayBin.seek(1.0,
            gst.FORMAT_TIME,    gst.SEEK_FLAG_FLUSH,
        gst.SEEK_TYPE_SET,  sec,
        gst.SEEK_TYPE_NONE, -1)

  def isVideo(self):
    """
    Check if it is video or not
    """
    if not self.getLocation():
      return False
    ext = self.getLocation().split('.').pop().lower()
    if self.Tags.has_key('video-codec') or ext in CHRISTINE_VIDEO_EXT:
      self.__ShouldShow = True
      return True
    return False

  def isSound(self):
    """
    Check if it is sound or not
    """
    if not self.getLocation():
      return False
    ext = self.getLocation().split('.').pop().lower()
    if self.Tags.has_key('audio-codec') or \
      ext in self.config.get('backend/allowed_files'):
      return True
    else:
      return False
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.