* ALL: bumped version number to 0.6.3-cvs
[vlc.git] / modules / control / corba / simpleplayer.py
1 #!/usr/bin/env python
2
3 import sys, time
4
5 # For gtk/glade
6 import pygtk
7 pygtk.require ('2.0')
8 import gtk
9 import gtk.glade
10
11 # For CORBA
12 import ORBit, CORBA
13 # FIXME: How do we make this portable to windows ?
14 ORBit.load_typelib ("./MediaControl.so")
15 import VLC
16
17 class Connect:
18     """Abstract class defining helper functions to interconnect
19     glade XML files and methods of a python class."""    
20     def create_dictionary (self):
21         """Create a (name, function) dictionnary for the current class"""
22         dict = {}
23         self.create_dictionary_for_class (self.__class__, dict)
24         return dict
25     
26     def create_dictionary_for_class (self, a_class, dict):
27         """Create a (name, function) dictionnary for the specified class"""
28         bases = a_class.__bases__
29         for iteration in bases:
30             self.create_dictionary_for_class (iteration, dict)
31         for iteration in dir(a_class):
32             dict[iteration] = getattr(self, iteration)
33
34     def connect (self):
35         """Connects the class methods with the UI"""
36         self.gui.signal_autoconnect(self.create_dictionary ())
37
38     def gtk_widget_hide (self, widget):
39         widget.hide ()
40         return gtk.TRUE
41         
42     def on_exit(self, source=None, event=None):
43         """Generic exit callback"""
44         gtk.main_quit()
45
46 class DVDControl (Connect):
47     def __init__ (self, gladefile):
48         """Initializes the GUI and other attributes"""
49         # Glade init.
50         self.gui = gtk.glade.XML(gladefile)
51         self.connect ()
52         # Frequently used GUI widgets
53         self.gui.logmessages = self.gui.get_widget("logmessages")
54         self.gui.position_label = self.gui.get_widget("position_label")
55         self.gui.fs = gtk.FileSelection ("Select a file")
56         self.gui.fs.ok_button.connect_after ("clicked", lambda win: self.gui.fs.hide ())
57         self.gui.fs.cancel_button.connect ("clicked", lambda win: self.gui.fs.destroy ())
58
59         # CORBA init.
60         self.mc = None
61         self.currentpos = None
62         self.status = None
63         # FIXME: portability
64         self.iorfile = "/tmp/vlc-ior.ref"
65         
66         # Various
67         # Default FF/RW time : 5 seconds
68         self.default_time_increment = 5
69
70     def update_title (self, title):
71         # Update the title of the main window
72         self.gui.get_widget ("win").set_title (title)
73         
74     def launch_player (self):
75         """Launch the VLC corba plugin"""
76         #print "Launching vlc server..."
77         # FIXME: spawn is portable, but how can we make sure that
78         # launch-vlc-corba launches the application in the background ?
79         # FIXME: portability
80         import distutils.spawn
81         distutils.spawn.spawn (["launch-vlc-corba"], True, True)
82         # Wait a little for the server to initialize. We could instead test
83         # on the existence and validity of self.iorfile
84         time.sleep (2)
85         return
86
87     def main (self):
88         """Mainloop : CORBA initalization and Gtk mainloop setup"""
89         self.orb = CORBA.ORB_init(sys.argv)
90
91         errormessage = """Unable to get a MediaControl object
92 Please try to run the following command:
93 vlc --intf corba"""
94         
95         try:
96             ior = open(self.iorfile).readline()
97         except:
98             # The iorfile does not existe : the player is maybe not active
99             self.launch_player ()
100             try:
101                 ior = open(self.iorfile).readline()
102             except:
103                 print errormessage
104                 sys.exit(1)
105
106         self.mc = self.orb.string_to_object(ior)
107
108         if self.mc._non_existent ():
109             # The remote object is not available. Let's run the
110             # VLC server
111             self.launch_player ()
112             try:
113                 ior = open(self.iorfile).readline()
114             except:
115                 print errormessage
116                 sys.exit(1)
117             self.mc = self.orb.string_to_object(ior)
118             if self.mc._non_existent ():
119                 print errormessage
120                 sys.exit(1)
121
122         self.currentpos = VLC.Position ()
123         self.currentpos.value = 0
124         self.currentpos.key = VLC.MediaTime
125         self.currentpos.origin = VLC.RelativePosition
126             
127         gtk.timeout_add (20, self.update_display, self.orb)
128         gtk.main ()
129
130     def log (self, msg):
131         """Adds a new log message to the logmessage window"""
132         buf = self.gui.logmessages.get_buffer ()
133         mes = str(msg) + "\n"
134         buf.insert_at_cursor (mes, len(mes))
135
136         endmark = buf.create_mark ("end",
137                                    buf.get_end_iter (),
138                                    gtk.TRUE)
139         self.gui.logmessages.scroll_mark_onscreen (endmark)
140         return
141         
142     def on_exit (self, source=None, event=None):
143         """General exit callback"""
144         self.status = "Stop"
145         # Terminate the VLC server
146         try:
147             self.mc.exit()
148         except:
149             pass
150         gtk.main_quit ()
151
152     def file_selector (self, callback=None, label="Select a file",
153                        default=""):
154         """Display the file selector"""
155         self.gui.fs.set_property ("title", label)
156         self.gui.fs.set_property ("filename", default)
157         self.gui.fs.set_property ("select-multiple", False)
158         self.gui.fs.set_property ("show-fileops", False)
159
160         if callback:
161             # Disconnecting the old callback
162             try:
163                 self.gui.fs.ok_button.disconnect (self.gui.fs.connect_id)
164             except:
165                 pass
166             # Connecting the new one
167             self.gui.fs.connect_id = self.gui.fs.ok_button.connect ("clicked", callback, self.gui.fs)
168         self.gui.fs.show ()
169         return gtk.TRUE
170
171     def file_selected_cb (self, button, fs):
172         """Open and play the selected movie file"""
173         file = self.gui.fs.get_property ("filename")
174         self.mc.add_to_playlist (file)
175         self.status = "Play"
176         return gtk.TRUE
177
178     def move_position (self, value):
179         """Helper function : fast forward or rewind by value seconds"""
180         print "Moving by %d seconds" % value
181         pos = VLC.Position ()
182         pos.value = value
183         pos.key = VLC.MediaTime
184         pos.origin = VLC.RelativePosition
185         self.mc.set_media_position (pos)
186         return
187
188     def update_display (self, orb):
189         """Update the interface"""
190         if self.status == "Play":
191             pos = self.mc.get_media_position (VLC.AbsolutePosition,
192                                               VLC.ByteCount)
193             self.gui.position_label.set_text (str(pos.value))
194         elif self.status == "Stop":
195             self.gui.position_label.set_text ("N/C")
196         return gtk.TRUE
197
198     # Callbacks function. Skeletons can be generated by glade2py
199     def on_win_key_press_event (self, win=None, event=None):
200         # Navigation keys
201         if event.keyval == gtk.keysyms.Tab:
202             self.on_b_pause_clicked (win, event)
203             return gtk.TRUE
204         elif event.keyval == gtk.keysyms.Right:
205             self.on_b_forward_clicked (win, event)
206             return gtk.TRUE
207         elif event.keyval == gtk.keysyms.Left:
208             self.on_b_rewind_clicked (win, event)
209             return gtk.TRUE
210         elif event.keyval == gtk.keysyms.Home:
211             pos = VLC.Position ()
212             pos.value = 0
213             pos.key = VLC.MediaTime
214             pos.origin = VLC.AbsolutePosition
215             self.mc.set_media_position (pos)
216             return gtk.TRUE
217         elif event.keyval == gtk.keysyms.End:
218             pos = VLC.Position ()
219             pos.value = -self.default_time_increment
220             pos.key = VLC.MediaTime
221             pos.origin = VLC.ModuloPosition
222             self.mc.set_media_position (pos)
223             return gtk.TRUE
224         elif event.keyval == gtk.keysyms.Page_Down:
225             # FIXME: Next chapter
226             return gtk.TRUE
227         elif event.keyval == gtk.keysyms.Page_Up:
228             # FIXME: Previous chapter
229             return gtk.TRUE
230         return gtk.TRUE
231
232     def on_quit1_activate (self, button=None, data=None):
233         """Gtk callback to quit"""
234         self.on_exit (button, data)
235         return gtk.TRUE
236     
237     def on_about1_activate (self, button=None, data=None):
238         self.gui.get_widget("about").show ()
239         return gtk.TRUE
240
241     def about_hide (self, button=None, data=None):
242         self.gui.get_widget("about").hide ()
243         return gtk.TRUE
244         
245     def on_b_rewind_clicked (self, button=None, data=None):
246         if self.status == "Play":
247             self.move_position (-self.default_time_increment)
248         return gtk.TRUE
249
250     def on_b_play_clicked (self, button=None, data=None):
251         if self.status != "Play":
252             self.mc.start (self.currentpos)
253             self.status = "Play"
254         return gtk.TRUE
255
256     def on_b_pause_clicked (self, button=None, data=None):
257         if self.status == "Play":
258             self.mc.pause (self.currentpos)
259             self.status = "Pause"
260         elif self.status == "Pause":
261             self.mc.pause (self.currentpos)
262             self.status = "Play"
263         return gtk.TRUE
264
265     def on_b_stop_clicked (self, button=None, data=None):
266         self.mc.stop (self.currentpos)
267         self.status = "Stop"
268         return gtk.TRUE
269
270     def on_b_forward_clicked (self, button=None, data=None):
271         if self.status == "Play":
272             self.move_position (self.default_time_increment)
273         return gtk.TRUE
274
275     def on_b_addfile_clicked (self, button=None, data=None):
276         self.file_selector (callback=self.file_selected_cb,
277                             label="Play a movie file")
278         return gtk.TRUE
279
280     def on_b_selectdvd_clicked (self, button=None, data=None):
281         """Play a DVD"""
282         self.mc.add_to_playlist ("dvd:///dev/dvd at 1,1")
283         self.mc.start (self.currentpos)
284         self.status = "Play"
285         return gtk.TRUE
286     
287     def on_b_exit_clicked (self, button=None, data=None):
288         self.on_exit (button, data)
289         return gtk.TRUE
290
291     def on_logmessages_insert_at_cursor (self, button=None, data=None):
292         print "on_logmessages_insert_at_cursor activated (%s, %s, %s)" % (self, button, data)
293         # FIXME: faire défiler la scrollmark (cf gtkshell)
294         return gtk.TRUE
295
296 if __name__ == '__main__':
297     v = DVDControl ("simpleplayer.glade")
298     v.main ()