class ShellPlayer(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="Shell Player") self.set_default_size(640, 360) self.set_position(Gtk.WindowPosition.CENTER) action_group = Gtk.ActionGroup("shell_player_actions") self.add_popup_menu_actions(action_group) self.add_file_menu_actions(action_group) self.add_view_menu_actions(action_group) self.add_video_menu_actions(action_group) self.add_audio_menu_actions(action_group) self.add_subtitles_menu_actions(action_group) self.uimanager = self.create_ui_manager() self.uimanager.insert_action_group(action_group) ui_css = """GtkEventBox { background:black; } """ css_provider = Gtk.CssProvider() screen = Gdk.Screen.get_default() context = Gtk.StyleContext() css_provider.load_from_data(ui_css) context.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) eventbox = Gtk.EventBox() eventbox.connect("draw", self.on_expose_event) eventbox.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.LINK) eventbox.drag_dest_add_uri_targets() self.connect("key-press-event", self.on_key_press_event) self.connect("motion-notify-event", self.on_motion_notify_event) self.connect("scroll-event", self.on_scroll_wheel_event) eventbox.connect("button-press-event", self.on_button_press_event) eventbox.connect("drag-data-received", self.on_drag_data_received) self.set_events(Gdk.EventMask.LEAVE_NOTIFY_MASK | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_HINT_MASK | Gdk.EventMask.SCROLL_MASK) box.pack_start(eventbox, True, True, 0) manager = Gtk.RecentManager.get_default() self.recentchooser = Gtk.RecentChooserMenu() recentfilter = Gtk.RecentFilter() recentfilter.set_name('Video Files') recentfilter.add_mime_type('video/*') self.recentchooser.add_filter(recentfilter) self.recentchooser.connect("item-activated", self.display_info) self.uimanager.get_widget("/PopupMenu/PopupFileMenu/PopupFileRecent").set_submenu(self.recentchooser) self.popup = self.uimanager.get_widget("/PopupMenu") self.add(box) self.mplayer = None self.above = False self.fullscreened = False self.compactness = 0 self.resize_grip = 10 self.playlist = [] self.audio_source_merge_id = None def play_file(self, filename, args=[]): if self.mplayer.is_alive(): self.mplayer.quit() self.mplayer = Player(args=stdargs + args) del self.playlist[:] self.playlist.append(filename) if not self.mplayer.filename: self.mplayer.loadfile(self.playlist[0]) print self.mplayer.info if self.audio_source_merge_id: self.uimanager.remove_ui(self.audio_source_merge_id) AUDIO_INFO = """ <ui> <popup name='PopupMenu'> <menu action='PopupAudioMenu'> <separator /> """ for key in self.mplayer.info['audio']: AUDIO_INFO += "<menuitem action='PopupAudioSource" + key + "'/>" AUDIO_INFO += """ </menu> </popup> </ui> """ action_group = Gtk.ActionGroup("audio_source_actions") self.add_audio_source_actions(action_group) self.uimanager.insert_action_group(action_group) self.audio_source_merge_id = self.uimanager.add_ui_from_string(AUDIO_INFO) self.resize(self.mplayer.width, self.mplayer.height) pass def choose_file(self, mime): dialog = Gtk.FileChooserDialog("Please choose a file", self, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) self.add_filters(dialog, mime) response = dialog.run() filename = None if response == Gtk.ResponseType.OK: filename = dialog.get_filename() elif response == Gtk.ResponseType.CANCEL: pass dialog.destroy() return filename def on_file_clicked(self, widget): filename = self.choose_file({'Media Files':['video/*', 'audio/*'], 'Any Files':['*']}) if filename: self.play_file(filename) else: print 'canceled or wrong filename' def add_filters(self, dialog, mime): filter_text = Gtk.FileFilter() for key in mime: filefilter = Gtk.FileFilter() filefilter.set_name(key) for mime_type in mime[key]: filefilter.add_mime_type(mime_type) dialog.add_filter(filefilter) def on_folder_clicked(self, widget): dialog = Gtk.FileChooserDialog("Please choose a folder", self, Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, "Select", Gtk.ResponseType.OK)) dialog.set_default_size(800, 400) response = dialog.run() if response == Gtk.ResponseType.OK: print "Select clicked" print "Folder selected: " + dialog.get_filename() elif response == Gtk.ResponseType.CANCEL: print "Cancel clicked" dialog.destroy() def add_popup_menu_actions(self, action_group): #settings button action_group.add_actions([ ("PopupMenu", None, "Popup"), ("PopupSettings", Gtk.STOCK_PREFERENCES, None, None, None, self.on_menu_others) ]) #quit button action_filequit = Gtk.Action("PopupQuit", "Quit", None, Gtk.STOCK_QUIT) action_filequit.connect("activate", self.on_menu_file_quit) action_group.add_action_with_accel(action_filequit, "Escape") def add_file_menu_actions(self, action_group): action_group.add_action(Gtk.Action("PopupFileMenu", "File", None, None)) action_group.add_actions([ ("PopupFileOpen", Gtk.STOCK_OPEN, None, None, None, self.on_file_clicked), ("PopupFileClose", Gtk.STOCK_CLOSE, None, None, None, self.on_folder_clicked), ("PopupFileRecent", None, 'Open Recent', None, None, None) ]) def add_view_menu_actions(self, action_group): action_group.add_action(Gtk.Action("PopupViewMenu", "View", None, None)) on_top = Gtk.ToggleAction("PopupViewOnTop", "On Top", None, None) on_top.connect("toggled", self.on_keep_on_top) action_group.add_action(on_top) borderless = Gtk.ToggleAction("PopupViewBorderless", "No Frame", None, None) borderless.set_active(True) borderless.connect("toggled", self.on_border_switch) action_group.add_action(borderless) def add_video_menu_actions(self, action_group): action_group.add_action(Gtk.Action("PopupVideoMenu", "Video", None, None)) action_group.add_actions([ ("PopupVideoSettings", None, "Settings", None, None, self.on_menu_others), ("PopupVideoAspect", None, "Aspect", None, None, self.on_menu_others) ]) def add_audio_menu_actions(self, action_group): action_group.add_action(Gtk.Action("PopupAudioMenu", "Audio", None, None)) action_group.add_actions([ ("PopupAudioExternal", None, "External Audio", None, None, self.on_audio_external), ("PopupAudioUnload", None, "Unload External Audio", None, None, self.on_audio_unload) ]) def add_audio_source_actions(self, action_group): for key in self.mplayer.info['audio']: info = "" lang = "" if 'info' in self.mplayer.info['audio'][key]: info = self.mplayer.info['audio'][key]['info'] if 'lang' in self.mplayer.info['audio'][key]: lang = self.mplayer.info['audio'][key]['lang'] action_group.add_actions([ ("PopupAudioSource" + key, None, 'Audio: ' + key + ' ' + info + ' ' + lang, None, None, self.on_audio_source) ]) pass def add_subtitles_menu_actions(self, action_group): action_group.add_action(Gtk.Action("PopupSubtitlesMenu", "Subtitles", None, None)) action_group.add_actions([ ("PopupSubtitlesExternal", None, "Load External", None, None, self.on_menu_others), ("PopupSubtitlesSource", None, "Select Builtin", None, None, self.on_menu_others) ]) def display_info(self, widget): selected = self.recentchooser.get_current_item().get_uri() path = self.get_file_path_from_dnd_dropped_uri(selected) self.play_file(path) def on_keep_on_top(self, widget): self.set_keep_above(not self.above) self.above = not self.above def on_border_switch(self, widget): self.set_decorated(not self.get_decorated()) def on_audio_external(self, widget): if self.mplayer.is_alive() and self.mplayer.filename: self.mplayer.pause() audiofile = self.choose_file({'Media Files':['audio/*'], 'Any Files':['*']}) if audiofile: filename = self.mplayer.path position = int(self.mplayer.time_pos) self.play_file(None, ['-audiofile', audiofile, '-ss', position, filename]) else: self.mplayer.pause() pass def on_audio_unload(self, widget): if self.mplayer.is_alive() and self.mplayer.filename: filename = self.mplayer.path position = int(self.mplayer.time_pos) self.play_file(None, ['-ss', position, filename]) pass def on_audio_source(self, widget): s = widget.get_name() if s[-2:].isdigit(): idx = s[-2:] else: idx = s[-1] if self.mplayer.switch_audio != idx: self.mplayer.pause() self.mplayer._run_command('switch_audio', idx) self.mplayer.pause() return True def create_ui_manager(self): uimanager = Gtk.UIManager() # Throws exception if something went wrong uimanager.add_ui_from_string(UI_INFO) # Add the accelerator group to the toplevel window accelgroup = uimanager.get_accel_group() self.add_accel_group(accelgroup) return uimanager def on_menu_file_quit(self, widget): if self.mplayer: self.mplayer.quit() Gtk.main_quit() def on_menu_others(self, widget): print "Menu item " + widget.get_name() + " was selected" def on_menu_choices_toggled(self, widget): if widget.get_active(): print widget.get_name() + " activated" else: print widget.get_name() + " deactivated" def on_button_press_event(self, widget, event): # Check if right mouse button was preseed if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3: self.popup.popup(None, None, None, None, event.button, event.time) return True # event has been handled if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 1: some, x, y, mods = self.get_screen().get_root_window().get_pointer() mouse_position = self.get_pointer() window_size = (self.get_window().get_width(), self.get_window().get_height()) if mouse_position[0] < self.resize_grip and mouse_position[1] < self.resize_grip: self.begin_resize_drag(Gdk.WindowEdge.NORTH_WEST, event.button, x, y, event.time) return True if mouse_position[0] > window_size[0] - self.resize_grip and mouse_position[1] > window_size[1] - self.resize_grip: self.begin_resize_drag(Gdk.WindowEdge.SOUTH_EAST, event.button, x, y, event.time) return True if mouse_position[0] < self.resize_grip and mouse_position[1] > window_size[1] - self.resize_grip: self.begin_resize_drag(Gdk.WindowEdge.SOUTH_WEST, event.button, x, y, event.time) return True if mouse_position[0] > window_size[0] - self.resize_grip and mouse_position[1] < self.resize_grip: self.begin_resize_drag(Gdk.WindowEdge.NORTH_EAST, event.button, x, y, event.time) return True if mouse_position[0] < self.resize_grip: self.begin_resize_drag(Gdk.WindowEdge.WEST, event.button, x, y, event.time) return True if mouse_position[0] > window_size[0] - self.resize_grip: self.begin_resize_drag(Gdk.WindowEdge.EAST, event.button, x, y, event.time) return True if mouse_position[1] > window_size[1] - self.resize_grip: self.begin_resize_drag(Gdk.WindowEdge.SOUTH, event.button, x, y, event.time) return True if mouse_position[1] < self.resize_grip: self.begin_resize_drag(Gdk.WindowEdge.NORTH, event.button, x, y, event.time) return True self.begin_move_drag(event.button, x, y, event.time) return True if event.type == Gdk.EventType._2BUTTON_PRESS and event.button == 1: if not self.fullscreened: self.fullscreen() self.fullscreened = True else: self.unfullscreen() self.fullscreened = False return True def on_key_press_event(self, widget, event): if event.keyval == Gdk.KEY_space: if self.mplayer.filename: self.mplayer.pause() else: if len(self.playlist) > 0: self.play_file(self.playlist[0]) return True if event.keyval == Gdk.KEY_r: return True if event.keyval == Gdk.KEY_l: metadata = self.mplayer.metadata or {} print metadata return True if event.state == Gdk.ModifierType.MOD1_MASK and event.keyval == Gdk.KEY_1: if self.mplayer.filename: self.resize(self.mplayer.width / 2, self.mplayer.height / 2) return True if event.state == Gdk.ModifierType.MOD1_MASK and event.keyval == Gdk.KEY_2: if self.mplayer.filename: self.resize(self.mplayer.width / 1.75, self.mplayer.height / 1.75) return True if event.state == Gdk.ModifierType.MOD1_MASK and event.keyval == Gdk.KEY_3: if self.mplayer.filename: self.resize(self.mplayer.width, self.mplayer.height) return True if event.keyval == Gdk.KEY_1: self.compactness = 0 self.set_decorated(False) return True if event.keyval == Gdk.KEY_2: self.compactness = 1 self.set_decorated(True) return True # else pass event to mplayer if self.mplayer.is_alive(): self.mplayer.key_down_event(int(event.keyval)) return True def on_motion_notify_event(self, widget, event): if self.compactness == 0: if event.type == Gdk.EventType.MOTION_NOTIFY: mouse_position = self.get_pointer() window_size = (self.get_window().get_width(), self.get_window().get_height()) if mouse_position[0] < self.resize_grip and mouse_position[1] < self.resize_grip: self.get_window().set_cursor (Gdk.Cursor(Gdk.CursorType.TOP_LEFT_CORNER)) return True if mouse_position[0] > window_size[0] - self.resize_grip and mouse_position[1] > window_size[1] - self.resize_grip: self.get_window().set_cursor (Gdk.Cursor(Gdk.CursorType.BOTTOM_RIGHT_CORNER)) return True if mouse_position[0] < self.resize_grip and mouse_position[1] > window_size[1] - self.resize_grip: self.get_window().set_cursor (Gdk.Cursor(Gdk.CursorType.BOTTOM_LEFT_CORNER)) return True if mouse_position[0] > window_size[0] - self.resize_grip and mouse_position[1] < self.resize_grip: self.get_window().set_cursor (Gdk.Cursor(Gdk.CursorType.TOP_RIGHT_CORNER)) return True if mouse_position[0] < self.resize_grip: self.get_window().set_cursor (Gdk.Cursor(Gdk.CursorType.LEFT_SIDE)) return True if mouse_position[0] > window_size[0] - self.resize_grip: self.get_window().set_cursor (Gdk.Cursor(Gdk.CursorType.RIGHT_SIDE)) return True if mouse_position[1] > window_size[1] - self.resize_grip: self.get_window().set_cursor (Gdk.Cursor(Gdk.CursorType.BOTTOM_SIDE)) return True if mouse_position[1] < self.resize_grip: self.get_window().set_cursor (Gdk.Cursor(Gdk.CursorType.TOP_SIDE)) return True if self.get_window().get_cursor() != None and self.get_window().get_cursor().get_cursor_type() != Gdk.CursorType.ARROW: self.get_window().set_cursor (Gdk.Cursor(Gdk.CursorType.ARROW)) return True # else pass event to mplayer if self.mplayer.is_alive(): self.mplayer.set_mouse_pos(mouse_position[0], mouse_position[1]) return True pass def on_scroll_wheel_event(self, widget, event): if event.direction == Gdk.ScrollDirection.UP: if self.mplayer.filename: vol = self.mplayer.volume + 10 self.mplayer.volume = vol if vol < 100 else 100 return True if event.direction == Gdk.ScrollDirection.DOWN: if self.mplayer.filename: vol = self.mplayer.volume - 10 self.mplayer.volume = vol if vol >= 0 else 0 return True pass def on_drag_data_received(self, widget, drag_context, x, y, data, info, time): del self.playlist[:] for uri in data.get_uris(): path = self.get_file_path_from_dnd_dropped_uri(uri) self.playlist.append(path) if self.mplayer.is_alive(): self.mplayer.quit() self.mplayer = Player(args=stdargs) self.mplayer.loadfile(self.playlist[0]) print self.playlist return True def get_file_path_from_dnd_dropped_uri(self, uri): path = "" if uri.startswith('file:\\\\\\'): # windows path = uri[8:] # 8 is len('file:///') elif uri.startswith('file://'): # nautilus, rox path = uri[7:] # 7 is len('file://') elif uri.startswith('file:'): # xffm path = uri[5:] # 5 is len('file:') path = urllib.url2pathname(path) # escape special chars path = path.strip('\r\n\x00') # remove \r\n and NULL return path def on_expose_event(self, widget, event): # print('kok') # ctx = self.get_window().cairo_create() # Gtk.paint_resize_grip(self.get_default_style(), ctx, Gtk.StateType.NORMAL, self, "", Gdk.WindowEdge.WEST, -10, -10, # 0, 0) pass