]> git.plutz.net Git - viper/blob - player.py
implemeted most basic cropping controls
[viper] / player.py
1 #encoding: utf-8
2 #Copyright 2010 Paul Hänsch
3
4 #This file is part of Viper.
5
6 #Viper is free software: you can redistribute it and/or modify
7 #it under the terms of the GNU General Public License as published by
8 #the Free Software Foundation, either version 3 of the License, or
9 #(at your option) any later version.
10
11 #Viper is distributed in the hope that it will be useful,
12 #but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #GNU General Public License for more details.
15
16 #You should have received a copy of the GNU General Public License
17 #along with Viper.  If not, see <http://www.gnu.org/licenses/>
18
19 from Tkinter import *
20 import os
21 import threading
22
23 class Player():
24     """
25     Video player for inclusion in videoview widget
26     """
27     def __init__(self, parent, surface, callback = None, slider = None):
28         """
29         Constructor
30         
31         surface  - the widget which shall be the parent for 
32                    video playback
33         callback - a function which is called on status change
34                    the function will be called with a string parameter
35                    beeing one of "playing", "paused", or "stopped"
36         slider   - a Tk slider widget which controls and displays
37                    the position in the video
38         """
39         self.parent = parent
40         self.surface = surface
41         self.announce_status = callback
42         self.slider = slider
43         self.slave = (None, None)
44         self.status = 'stopped'
45         self.perc_pos = 0
46         self.time_pos = 0
47
48         if self.slider != None: self.slider.configure(command = self.s_seek)
49         self.get_position()
50
51     def configure(self, surface = None, callback = None, slider = None):
52         if surface != None: self.surface = surface
53         if callback != None: self.announce_status = callback
54         if slider != None:
55             self.slider = slider
56         self.slider.configure(command = self.s_seek)
57
58     def get_position(self):
59         """
60         Command mplayer slave to print position data
61         """
62         if self.slave != (None, None) and self.status == 'playing':
63             self.slave[0].writelines(['get_percent_pos\n'])
64             self.slave[0].writelines(['get_time_pos\n'])
65             self.slave[0].flush()
66         try: self.slider.set(self.perc_pos /100, self.perc_pos /100 + .01)
67         except: pass
68         self.parent.after(20, self.get_position)
69
70     def seek(self, absolute, pos):
71         """
72         Seek in video
73
74         absolute - True for absolute seek
75                    False for relative seek
76         pos      - seek position
77         """
78         if self.slave != (None, None):
79             if absolute:
80                 self.slave[0].writelines(['pausing seek '+ str(pos) + ' 1\n'])
81                 self.status = 'paused'
82                 self.announce_status(self.status)
83             else:
84                 self.slave[0].writelines(['pausing seek '+ str(pos) + ' 0\n'])
85                 self.status = 'paused'
86                 self.announce_status(self.status)
87
88             try:
89                 self.slave[sid][0].writelines(['pausing get_percent_pos\n'])
90                 self.slave[sid][0].writelines(['pausing get_time_pos\n'])
91                 self.slave[sid][0].flush()
92             except:
93                 pass
94
95     def s_seek(self, p1 = None, p2 = None, p3 = None):
96         """
97         Callback for slider bar
98         
99         Specify this function as the callback for a sliderbar
100         and the slider will control the video position
101         """
102         if p1 == 'moveto':
103             self.seek(True, int(p2[2:4]))
104         elif p1 == 'scroll' and p3 == 'units':
105             self.seek(False, int(p2) * 10)
106         elif p1 == 'scroll' and p3 == 'pages':
107             self.seek(False, int(p2) * 60)
108
109     def stop_video(self):
110         """
111         Stop playback of a video
112         """
113         if self.slave != (None, None):
114             self.slave[0].writelines(['stop\n'])
115             self.slave[0].flush()
116             self.status = 'stopped'
117             self.announce_status(self.status)
118
119     def play_video(self, loop = False, params = []):
120         """
121         Start playback
122
123         surface - widget in which the video will be displayed
124         loop    - if True loop the video indefinitely
125         params  - list of playback parameters (filenames, filters, ...)
126         """
127         if self.slave == (None, None):
128             cmd = ['mplayer', '-noconfig', 'all', '-slave', '-fixed-vo', '-osdlevel', '3', '-vo', 'x11',
129                    '-wid', str(self.surface.winfo_id()), '-x','320', '-y','240']
130             if loop: cmd.extend(['-loop', '0'])
131             cmd.extend(params)
132             self.slave = os.popen2(cmd)
133             threading.Thread(target = self.read_slave).start()
134         else:
135             self.slave[0].writelines(['seek 0\n'])
136             self.slave[0].flush()
137         self.status = 'playing'
138         self.announce_status(self.status)
139
140     def pause_video(self):
141         """
142         Pause video allowing resume
143         """
144         self.slave[0].writelines(['pause\n'])
145         self.slave[0].flush()
146         self.status = 'paused'
147         self.announce_status(self.status)
148
149     def read_slave(self):
150         """
151         Read output line of slave and
152         set time positions, etc...
153         """
154         statline = 'start'
155         perc_pos = time_pos = 0.0
156         while statline != '':
157             statline = self.slave[1].readline()
158             if statline.find('ANS_PERCENT_POSITION') != -1:
159                 pos = statline[statline.find('ANS_PERCENT_POSITION'):]
160                 try:
161                     perc_pos = float(pos.split('=')[1])
162                 except:
163                     pass
164             elif statline.find('ANS_TIME_POSITION') == 0:
165                 pos = statline[statline.find('ANS_TIME_POSITION'):]
166                 try:
167                     time_pos = float(pos.split('=')[1])
168                 except:
169                     pass
170             self.perc_pos = perc_pos
171             self.time_pos = time_pos
172
173         self.slave = (None, None)
174         self.status = 'stopped'
175         self.announce_status(self.status)
176         self.perc_pos = self.pre_perc_pos = 0
177         self.time_pos = self.pre_time_pos = 0
178
179     def step_video(self):
180         """
181         Play a single frame
182         """
183         if self.slave != (None, None):
184             self.slave[0].writelines(['pausing frame_step\n'])
185             self.slave[0].flush()
186             self.status = 'paused'
187             self.announce_status(self.status)