''' SVPlayer player backend objects (c) 2011-2014 Jan ONDREJ (SAL) This program 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. Update of vlc.py from videolan sources: URL=http://git.videolan.org wget -O vlc.py \ "$URL/?p=vlc/bindings/python.git;a=blob_plain;f=generated/vlc.py;hb=HEAD" ''' import sys, os, time, glob from urllib import pathname2url #from config import * from sgtk import * from base import BasePlayerWidget import vlc ### VLC Player ### class VLCWidget(Gtk.DrawingArea, BasePlayerWidget): """ VLC widget player """ name = 'vlc' max_volume = 100 audio_tracks = [] def __init__(self, media=None, subtitles=[], options={}, events=True): Gtk.DrawingArea.__init__(self) self.instance = vlc.Instance( '--no-xlib', *["--%s" % x for x in self.to_list(options) if not (x.startswith("program=") or x.startswith(":"))] ) self.player = self.instance.media_player_new() self.modify_bg(Gtk.STATE_NORMAL, COLOR_BLACK) # minimal size self.set_size_request(320, 200) self.player.video_set_mouse_input(True) # function aliases self.toggle_mute = self.player.audio_toggle_mute self.set_deinterlace = self.player.video_set_deinterlace self.get_crop = self.player.video_get_crop_geometry self.set_crop = self.player.video_set_crop_geometry self.get_aspect = self.player.video_get_aspect_ratio self.set_aspect = self.player.video_set_aspect_ratio self.stop = self.player.stop self.add_subtitle = self.player.video_set_subtitle_file if media and type(media)!=int: if media.startswith("dvd://"): events = False if os.path.isdir(os.path.join(media, "VIDEO_TS")): events = False self.handle_events = events if events: print "Setting events", events self.set_events( Gtk.gdk.BUTTON_PRESS_MASK |Gtk.gdk.BUTTON_RELEASE_MASK |Gtk.gdk.SCROLL_MASK |Gtk.gdk.POINTER_MOTION_MASK ) if media: self.set_media(media, options) # events self.em = self.player.event_manager() self.em.event_attach( vlc.EventType.MediaPlayerPlaying, self.event_play) self.em.event_attach( vlc.EventType.MediaPlayerTimeChanged, self.event_timechange) self.em.event_attach( vlc.EventType.MediaPlayerTitleChanged, self.event_title) self.em.event_attach( vlc.EventType.MediaPlayerEncounteredError, self.event_error) def destroy(self): self.stop() self.instance.release() Gtk.DrawingArea.destroy(self) def to_list(self, options): def toeq(x): if x[1] is None: return x[0] return str(x[0]) + "=" + str(x[1]) return [toeq(x) for x in options.items()] def show_all(self): super(VLCWidget, self).show_all() self.player.set_xwindow(self.get_property('window').get_xid()) def play(self): self.player.play() os = '' for i in range(30): s = self.get_state() if os!=s and s!="NothingSpecial": print "Waiting for play ...", s os = s if s=='Playing': break time.sleep(0.1) # change to subtitle 1 if present self.next_sub(1) def pause(self, state=None): if state is None: self.player.pause() self.paused = not self.paused elif self.paused!=state: self.player.pause() self.paused = state def event_play(self, event): # change audio track to preffered language self.audio_tracks = self.get_tracks(self._language_priority) if self._language_priority and self.audio_tracks: self.set_track(self.audio_tracks[1][0]) print "Languages:", self.audio_tracks self.audio_track = self.player.audio_get_track() self.subtitle = self.player.video_get_spu() def event_timechange(self, event): # change audio track to preffered language if not self.audio_tracks: self.audio_tracks = self.get_tracks(self._language_priority) if self._language_priority and self.audio_tracks: self.set_track(self.audio_tracks[1][0]) print "Languages:", self.audio_tracks def event_title(self, event): print "EVENT: TITLE CHANGED", self.player.get_title() def event_error(self, event): print "EVENT: ERROR", event def decode_errors(self): mstats = vlc.MediaStats() self.media.get_stats(mstats) return mstats.demux_corrupted def read_bytes(self): mstats = vlc.MediaStats() self.media.get_stats(mstats) return mstats.read_bytes+mstats.demux_read_bytes def get_state(self): return str(self.player.get_state()).replace("State.", "") def set_media(self, url, options): if type(url)==int: self.media = self.instance.media_new_fd(url) self.media.add_options(self.to_list(options)) else: if '://' not in url: # local file url = "file://" + pathname2url(os.path.abspath(url)) print options, self.to_list(options) self.media = self.instance.media_new(url, *self.to_list(options)) self.player.set_media(self.media) self.start_time = time.time() self.paused = False def get_size(self): return ( vlc.dll.libvlc_video_get_width(self.player), vlc.dll.libvlc_video_get_height(self.player) ) def was_ended(self): return self.player.get_state()==vlc.State.Ended def get_volume(self): return self.player.audio_get_volume()/2 def set_volume(self, value): self.player.audio_set_volume(value*2) def get_mute(self): return bool(self.player.audio_get_mute()) def set_mute(self, value): self.player.audio_set_mute(int(value)) def get_tracks(self, priority=[]): ptracks = self.player.audio_get_track_description() if not ptracks: self.audio_tracks = [] return self.audio_tracks self.audio_tracks = [ptracks[0]] tracks = ptracks[1:] for p in priority+['']: for track in list(tracks): if p in track[1]: self.audio_tracks.append((ptracks.index(track), track[1])) tracks.remove(track) print "Tracks:", self.audio_tracks return self.audio_tracks def set_track(self, track): if track==-1: self.player.audio_set_track(-1) else: ptracks = self.player.audio_get_track_description() if ptracks: self.player.audio_set_track(ptracks[track][0]) def print_info(self): mstats = vlc.MediaStats() print "Stats:", self.media.get_stats(mstats), mstats print "State:", self.player.get_state() print "Time:", self.player.get_time(), self.player.get_position() print "Length:", self.player.get_length() print "Size:", self.get_size() print "Aspect:", self.player.video_get_aspect_ratio() print "Sub: count=%d, current=%d" % ( self.player.video_get_spu_count(), self.player.video_get_spu() ) for id, name in self.sub_list(): print "%10d %s" % (id, name) print "Audio track: count=%d, current=%d" % ( self.player.audio_get_track_count(), self.player.audio_get_track() ) for id, name in self.player.audio_get_track_description(): print "%10d %s" % (id, name) print "Audio channel:", self.player.audio_get_channel() def get_position(self): return self.player.get_position()*100.0, \ self.player.get_time()/1000.0, \ self.player.get_length()/1000.0 def forward(self, seconds=10): if self.player.get_time()==0: # Workaround for "infinite" videos, # which always returns zero time position. self.player.set_position(self.player.get_position()+seconds/6000.0) else: self.player.set_time(self.player.get_time() + 1000*seconds) def seek(self, position): self.player.set_time(int(self.player.get_length()*position/100.0)) # subtitle functions def sub_list(self): return self.player.video_get_spu_description() def get_sub(self): return self.player.video_get_spu() def next_sub(self, idx=None, increment=1): subids = [x[0] for x in self.sub_list()] if not subids: return False if idx is None: idx = subids.index(self.player.video_get_spu())+increment if idx>=len(subids): idx = subids[0] elif idx<0: idx = subids[-1] else: idx = subids[idx] if not idx in subids: return False print "Select subtitle:", idx, subids ret = self.player.video_set_spu(idx) else: print "Select subtitle:", idx, subids ret = self.player.video_set_spu(subids[idx]) if ret==0: self.subtitle = idx return True return False def set_rate(self, rate=1.0, inc=None): if inc is not None: rate = self.player.get_rate() print "Setting rate: %f" % rate self.player.set_rate(rate*inc) else: self.player.set_rate(rate) def snapshot(self, path=None): # TODO: direct snapshot sending not implemented return self.player.video_take_snapshot(0, path, 0, 0)==0