class Window(Gtk.ApplicationWindow, Container): """ Main window """ def __init__(self, app): """ Init window """ Container.__init__(self) self._app = app self._signal1 = None self._signal2 = None Gtk.ApplicationWindow.__init__(self, application=app, title="Lollypop") self._nullwidget = Gtk.Label() # Use to get selected background color self._timeout_configure = None seek_action = Gio.SimpleAction.new('seek', GLib.VariantType.new('i')) seek_action.connect('activate', self._on_seek_action) app.add_action(seek_action) player_action = Gio.SimpleAction.new('player', GLib.VariantType.new('s')) player_action.connect('activate', self._on_player_action) app.add_action(player_action) self._setup_content() self._setup_window() self._setup_media_keys() self.enable_global_shorcuts(True) self.connect('destroy', self._on_destroyed_window) self.connect('realize', self._on_realize) def setup_menu(self, menu): """ Add an application menu to window @parma: menu as Gio.Menu """ self._toolbar.setup_menu_btn(menu) def get_selected_color(self): """ Return selected color """ return self._nullwidget.get_style_context().\ get_background_color(Gtk.StateFlags.SELECTED) def enable_global_shorcuts(self, enable): """ Setup global shortcuts @param enable as bool """ if enable: if Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL: self._app.set_accels_for_action("app.seek(10)", ["Left"]) self._app.set_accels_for_action("app.seek(20)", ["<Control>Left"]) self._app.set_accels_for_action("app.seek(-10)", ["Right"]) self._app.set_accels_for_action("app.seek(-20)", ["<Control>Right"]) else: self._app.set_accels_for_action("app.seek(10)", ["Right"]) self._app.set_accels_for_action("app.seek(20)", ["<Control>Right"]) self._app.set_accels_for_action("app.seek(-10)", ["Left"]) self._app.set_accels_for_action("app.seek(-20)", ["<Control>Left"]) self._app.set_accels_for_action("app.player::play_pause", ["space", "c"]) self._app.set_accels_for_action("app.player::play", ["x"]) self._app.set_accels_for_action("app.player::stop", ["v"]) self._app.set_accels_for_action("app.player::next", ["n"]) self._app.set_accels_for_action("app.player::next_album", ["<Control>n"]) self._app.set_accels_for_action("app.player::prev", ["p"]) else: self._app.set_accels_for_action("app.seek(10)", [None]) self._app.set_accels_for_action("app.seek(20)", [None]) self._app.set_accels_for_action("app.seek(-10)", [None]) self._app.set_accels_for_action("app.seek(-20)", [None]) self._app.set_accels_for_action("app.player::play_pause", [None]) self._app.set_accels_for_action("app.player::play", [None]) self._app.set_accels_for_action("app.player::stop", [None]) self._app.set_accels_for_action("app.player::play_pause", [None]) self._app.set_accels_for_action("app.player::play", [None]) self._app.set_accels_for_action("app.player::stop", [None]) self._app.set_accels_for_action("app.player::next", [None]) self._app.set_accels_for_action("app.player::next_album", [None]) self._app.set_accels_for_action("app.player::prev", [None]) def do_hide(self): """ Remove callbacks (we don't want to save an invalid value on hide """ if self._signal1 is not None: self.disconnect(self._signal1) if self._signal2 is not None: self.disconnect(self._signal2) Gtk.ApplicationWindow.do_hide(self) ############ # Private # ############ def _setup_media_keys(self): """ Setup media player keys """ self._proxy = Gio.DBusProxy.new_sync(Gio.bus_get_sync(Gio.BusType. SESSION, None), Gio.DBusProxyFlags.NONE, None, 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/' 'MediaKeys', 'org.gnome.SettingsDaemon.' 'MediaKeys', None) self._grab_media_player_keys() try: self._proxy.connect('g-signal', self._handle_media_keys) except GLib.GError: # We cannot grab media keys if no settings daemon is running pass def _grab_media_player_keys(self): """ Do key grabbing """ try: self._proxy.call_sync('GrabMediaPlayerKeys', GLib.Variant('(su)', ('Lollypop', 0)), Gio.DBusCallFlags.NONE, -1, None) except GLib.GError: # We cannot grab media keys if no settings daemon is running pass def _handle_media_keys(self, proxy, sender, signal, parameters): """ Do player actions in response to media key pressed """ if signal != 'MediaPlayerKeyPressed': print('Received an unexpected signal\ \'%s\' from media player'.format(signal)) return response = parameters.get_child_value(1).get_string() if 'Play' in response: Lp.player.play_pause() elif 'Stop' in response: Lp.player.stop() elif 'Next' in response: Lp.player.next() elif 'Previous' in response: Lp.player.prev() def _setup_content(self): """ Setup window content """ self.set_icon_name('lollypop') self._toolbar = Toolbar(self.get_application()) self._toolbar.show() if Lp.settings.get_value('disable-csd'): vgrid = Gtk.Grid() vgrid.set_orientation(Gtk.Orientation.VERTICAL) vgrid.add(self._toolbar) vgrid.add(self.main_widget()) vgrid.show() self.add(vgrid) else: self.set_titlebar(self._toolbar) self._toolbar.set_show_close_button(True) self.add(self.main_widget()) def _setup_window(self): """ Setup window position and size, callbacks """ size_setting = Lp.settings.get_value('window-size') if isinstance(size_setting[0], int) and\ isinstance(size_setting[1], int): self.resize(size_setting[0], size_setting[1]) else: self.set_size_request(800, 600) position_setting = Lp.settings.get_value('window-position') if len(position_setting) == 2 and\ isinstance(position_setting[0], int) and\ isinstance(position_setting[1], int): self.move(position_setting[0], position_setting[1]) if Lp.settings.get_value('window-maximized'): self.maximize() self._signal1 = self.connect("window-state-event", self._on_window_state_event) self._signal2 = self.connect("configure-event", self._on_configure_event) def _on_configure_event(self, widget, event): """ Delay event @param: widget as Gtk.Window @param: event as Gdk.Event """ self._toolbar.set_progress_width(widget.get_size()[0]/4) if self._timeout_configure: GLib.source_remove(self._timeout_configure) self._timeout_configure = GLib.timeout_add(500, self._save_size_position, widget) def _save_size_position(self, widget): """ Save window state, update current view content size @param: widget as Gtk.Window """ self._timeout_configure = None size = widget.get_size() Lp.settings.set_value('window-size', GLib.Variant('ai', [size[0], size[1]])) position = widget.get_position() Lp.settings.set_value('window-position', GLib.Variant('ai', [position[0], position[1]])) def _on_window_state_event(self, widget, event): """ Save maximised state """ Lp.settings.set_boolean('window-maximized', 'GDK_WINDOW_STATE_MAXIMIZED' in event.new_window_state.value_names) def _on_destroyed_window(self, widget): """ Save paned widget width @param widget as unused, data as unused """ Lp.settings.set_value('paned-mainlist-width', GLib.Variant('i', self._paned_main_list. get_position())) Lp.settings.set_value('paned-listview-width', GLib.Variant('i', self._paned_list_view. get_position())) def _on_seek_action(self, action, param): """ Seek in stream @param action as Gio.SimpleAction @param param as GLib.Variant """ seconds = param.get_int32() position = Lp.player.get_position_in_track() seek = position/1000000/60+seconds if seek < 0: seek = 0 if seek > Lp.player.current_track.duration: seek = Lp.player.current_track.duration - 2 Lp.player.seek(seek) self._toolbar.update_position(seek*60) def _on_player_action(self, action, param): """ Change player state @param action as Gio.SimpleAction @param param as GLib.Variant """ string = param.get_string() if string == "play_pause": Lp.player.play_pause() elif string == "play": Lp.player.play() elif string == "stop": Lp.player.stop() elif string == "next": Lp.player.next() elif string == "next_album": # In party or shuffle, just update next track if Lp.player.is_party() or\ Lp.settings.get_enum('shuffle') == Shuffle.TRACKS: Lp.player.set_next() # We send this signal to update next popover Lp.player.emit("queue-changed") else: Lp.player.context.next = NextContext.START_NEW_ALBUM Lp.player.set_next() Lp.player.next() elif string == "prev": Lp.player.prev() def _on_realize(self, widget): """ Run scanner on realize @param widget as Gtk.Widget """ if Lp.settings.get_value('auto-update') or Lp.tracks.is_empty(): # Delayed, make python segfault on sys.exit() otherwise # No idea why, maybe scanner using Gstpbutils before Gstreamer # initialisation is finished... GLib.timeout_add(2000, self.update_db)
class Window(Gtk.ApplicationWindow, Container): """ Init window objects """ def __init__(self, app): Container.__init__(self) self._app = app Gtk.ApplicationWindow.__init__(self, application=app, title="Lollypop") self._nullwidget = Gtk.Label() # Use to get selected background color self._timeout_configure = None seek_action = Gio.SimpleAction.new('seek', GLib.VariantType.new('i')) seek_action.connect('activate', self._on_seek_action) app.add_action(seek_action) player_action = Gio.SimpleAction.new('player', GLib.VariantType.new('s')) player_action.connect('activate', self._on_player_action) app.add_action(player_action) self._setup_window() self._setup_media_keys() self.enable_global_shorcuts(True) self.connect("destroy", self._on_destroyed_window) """ Add an application menu to window @parma: menu as Gio.Menu """ def setup_menu(self, menu): self._toolbar.setup_menu_btn(menu) """ Return selected color """ def get_selected_color(self): return self._nullwidget.get_style_context().get_background_color( Gtk.StateFlags.SELECTED) """ Setup global shortcuts @param enable as bool """ def enable_global_shorcuts(self, enable): if enable: if Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL: self._app.set_accels_for_action("app.seek(10)", ["Left"]) self._app.set_accels_for_action("app.seek(20)", ["<Control>Left"]) self._app.set_accels_for_action("app.seek(-10)", ["Right"]) self._app.set_accels_for_action("app.seek(-20)", ["<Control>Right"]) else: self._app.set_accels_for_action("app.seek(10)", ["Right"]) self._app.set_accels_for_action("app.seek(20)", ["<Control>Right"]) self._app.set_accels_for_action("app.seek(-10)", ["Left"]) self._app.set_accels_for_action("app.seek(-20)", ["<Control>Left"]) self._app.set_accels_for_action("app.player::play_pause", ["space", "c"]) self._app.set_accels_for_action("app.player::play", ["x"]) self._app.set_accels_for_action("app.player::stop", ["v"]) else: self._app.set_accels_for_action("app.seek(10)", [None]) self._app.set_accels_for_action("app.seek(20)", [None]) self._app.set_accels_for_action("app.seek(-10)", [None]) self._app.set_accels_for_action("app.seek(-20)", [None]) self._app.set_accels_for_action("app.player::play_pause", [None]) self._app.set_accels_for_action("app.player::play", [None]) self._app.set_accels_for_action("app.player::stop", [None]) ############ # Private # ############ """ Setup media player keys """ def _setup_media_keys(self): self._proxy = Gio.DBusProxy.new_sync( Gio.bus_get_sync(Gio.BusType.SESSION, None), Gio.DBusProxyFlags.NONE, None, 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/MediaKeys', 'org.gnome.SettingsDaemon.MediaKeys', None) self._grab_media_player_keys() try: self._proxy.connect('g-signal', self._handle_media_keys) except GLib.GError: # We cannot grab media keys if no settings daemon is running pass """ Do key grabbing """ def _grab_media_player_keys(self): try: self._proxy.call_sync('GrabMediaPlayerKeys', GLib.Variant('(su)', ('Lollypop', 0)), Gio.DBusCallFlags.NONE, -1, None) except GLib.GError: # We cannot grab media keys if no settings daemon is running pass """ Do player actions in response to media key pressed """ def _handle_media_keys(self, proxy, sender, signal, parameters): if signal != 'MediaPlayerKeyPressed': print('Received an unexpected signal\ \'%s\' from media player'.format(signal)) return response = parameters.get_child_value(1).get_string() if 'Play' in response: Objects.player.play_pause() elif 'Stop' in response: Objects.player.stop() elif 'Next' in response: Objects.player.next() elif 'Previous' in response: Objects.player.prev() """ Setup window icon, position and size, callback for updating this values """ def _setup_window(self): self.set_icon_name('lollypop') size_setting = Objects.settings.get_value('window-size') if isinstance(size_setting[0], int) and\ isinstance(size_setting[1], int): self.resize(size_setting[0], size_setting[1]) else: self.set_size_request(800, 600) position_setting = Objects.settings.get_value('window-position') if len(position_setting) == 2 and\ isinstance(position_setting[0], int) and\ isinstance(position_setting[1], int): self.move(position_setting[0], position_setting[1]) if Objects.settings.get_value('window-maximized'): self.maximize() self.connect("window-state-event", self._on_window_state_event) self.connect("configure-event", self._on_configure_event) self._toolbar = Toolbar(self.get_application()) self._toolbar.show() # Only set headerbar if according DE detected or forced manually if use_csd(): self.set_titlebar(self._toolbar) self._toolbar.set_show_close_button(True) self.add(self.main_widget()) else: hgrid = Gtk.Grid() hgrid.set_orientation(Gtk.Orientation.VERTICAL) hgrid.add(self._toolbar) hgrid.add(self.main_widget()) hgrid.show() self.add(hgrid) """ Delay event @param: widget as Gtk.Window @param: event as Gdk.Event """ def _on_configure_event(self, widget, event): self._toolbar.set_progress_width(widget.get_size()[0] / 4) if self._timeout_configure: GLib.source_remove(self._timeout_configure) self._timeout_configure = GLib.timeout_add(500, self._save_size_position, widget) """ Save window state, update current view content size @param: widget as Gtk.Window """ def _save_size_position(self, widget): self._timeout_configure = None size = widget.get_size() Objects.settings.set_value('window-size', GLib.Variant('ai', [size[0], size[1]])) position = widget.get_position() Objects.settings.set_value( 'window-position', GLib.Variant('ai', [position[0], position[1]])) """ Save maximised state """ def _on_window_state_event(self, widget, event): Objects.settings.set_boolean( 'window-maximized', 'GDK_WINDOW_STATE_MAXIMIZED' in event.new_window_state.value_names) """ Save paned widget width @param widget as unused, data as unused """ def _on_destroyed_window(self, widget): Objects.settings.set_value( "paned-mainlist-width", GLib.Variant('i', self._paned_main_list.get_position())) Objects.settings.set_value( "paned-listview-width", GLib.Variant('i', self._paned_list_view.get_position())) """ Seek in stream @param action as Gio.SimpleAction @param param as GLib.Variant """ def _on_seek_action(self, action, param): seconds = param.get_int32() position = Objects.player.get_position_in_track() seek = position / 1000000 / 60 + seconds if seek < 0: seek = 0 if seek > Objects.player.current.duration: seek = Objects.player.current.duration - 2 Objects.player.seek(seek) self._toolbar.update_position(seek * 60) """ Change player state @param action as Gio.SimpleAction @param param as GLib.Variant """ def _on_player_action(self, action, param): string = param.get_string() if string == "play_pause": Objects.player.play_pause() elif string == "play": Objects.player.play() elif string == "stop": Objects.player.stop()
class Window(Gtk.ApplicationWindow, Container): """ Main window """ def __init__(self, app): """ Init window """ Container.__init__(self) self._app = app self._signal1 = None self._signal2 = None Gtk.ApplicationWindow.__init__(self, application=app, title="Lollypop") self._nullwidget = Gtk.Label() # Use to get selected background color self._timeout_configure = None seek_action = Gio.SimpleAction.new('seek', GLib.VariantType.new('i')) seek_action.connect('activate', self._on_seek_action) app.add_action(seek_action) player_action = Gio.SimpleAction.new('player', GLib.VariantType.new('s')) player_action.connect('activate', self._on_player_action) app.add_action(player_action) self._setup_content() self._setup_window() self._setup_media_keys() self.enable_global_shorcuts(True) self.connect('destroy', self._on_destroyed_window) self.connect('realize', self._on_realize) def setup_menu(self, menu): """ Add an application menu to window @parma: menu as Gio.Menu """ self._toolbar.setup_menu_btn(menu) def get_selected_color(self): """ Return selected color """ return self._nullwidget.get_style_context().\ get_background_color(Gtk.StateFlags.SELECTED) def enable_global_shorcuts(self, enable): """ Setup global shortcuts @param enable as bool """ if enable: if Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL: self._app.set_accels_for_action("app.seek(10)", ["Left"]) self._app.set_accels_for_action("app.seek(20)", ["<Control>Left"]) self._app.set_accels_for_action("app.seek(-10)", ["Right"]) self._app.set_accels_for_action("app.seek(-20)", ["<Control>Right"]) else: self._app.set_accels_for_action("app.seek(10)", ["Right"]) self._app.set_accels_for_action("app.seek(20)", ["<Control>Right"]) self._app.set_accels_for_action("app.seek(-10)", ["Left"]) self._app.set_accels_for_action("app.seek(-20)", ["<Control>Left"]) self._app.set_accels_for_action("app.player::play_pause", ["space", "c"]) self._app.set_accels_for_action("app.player::play", ["x"]) self._app.set_accels_for_action("app.player::stop", ["v"]) self._app.set_accels_for_action("app.player::next", ["n"]) self._app.set_accels_for_action("app.player::next_album", ["<Control>n"]) self._app.set_accels_for_action("app.player::prev", ["p"]) else: self._app.set_accels_for_action("app.seek(10)", [None]) self._app.set_accels_for_action("app.seek(20)", [None]) self._app.set_accels_for_action("app.seek(-10)", [None]) self._app.set_accels_for_action("app.seek(-20)", [None]) self._app.set_accels_for_action("app.player::play_pause", [None]) self._app.set_accels_for_action("app.player::play", [None]) self._app.set_accels_for_action("app.player::stop", [None]) self._app.set_accels_for_action("app.player::play_pause", [None]) self._app.set_accels_for_action("app.player::play", [None]) self._app.set_accels_for_action("app.player::stop", [None]) self._app.set_accels_for_action("app.player::next", [None]) self._app.set_accels_for_action("app.player::next_album", [None]) self._app.set_accels_for_action("app.player::prev", [None]) def do_hide(self): """ Remove callbacks (we don't want to save an invalid value on hide """ if self._signal1 is not None: self.disconnect(self._signal1) if self._signal2 is not None: self.disconnect(self._signal2) Gtk.ApplicationWindow.do_hide(self) ############ # Private # ############ def _setup_media_keys(self): """ Setup media player keys """ self._proxy = Gio.DBusProxy.new_sync( Gio.bus_get_sync(Gio.BusType.SESSION, None), Gio.DBusProxyFlags.NONE, None, 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/' 'MediaKeys', 'org.gnome.SettingsDaemon.' 'MediaKeys', None) self._grab_media_player_keys() try: self._proxy.connect('g-signal', self._handle_media_keys) except GLib.GError: # We cannot grab media keys if no settings daemon is running pass def _grab_media_player_keys(self): """ Do key grabbing """ try: self._proxy.call_sync('GrabMediaPlayerKeys', GLib.Variant('(su)', ('Lollypop', 0)), Gio.DBusCallFlags.NONE, -1, None) except GLib.GError: # We cannot grab media keys if no settings daemon is running pass def _handle_media_keys(self, proxy, sender, signal, parameters): """ Do player actions in response to media key pressed """ if signal != 'MediaPlayerKeyPressed': print('Received an unexpected signal\ \'%s\' from media player'.format(signal)) return response = parameters.get_child_value(1).get_string() if 'Play' in response: Lp.player.play_pause() elif 'Stop' in response: Lp.player.stop() elif 'Next' in response: Lp.player.next() elif 'Previous' in response: Lp.player.prev() def _setup_content(self): """ Setup window content """ self.set_icon_name('lollypop') self._toolbar = Toolbar(self.get_application()) self._toolbar.show() if Lp.settings.get_value('disable-csd'): vgrid = Gtk.Grid() vgrid.set_orientation(Gtk.Orientation.VERTICAL) vgrid.add(self._toolbar) vgrid.add(self.main_widget()) vgrid.show() self.add(vgrid) else: self.set_titlebar(self._toolbar) self._toolbar.set_show_close_button(True) self.add(self.main_widget()) def _setup_window(self): """ Setup window position and size, callbacks """ size_setting = Lp.settings.get_value('window-size') if isinstance(size_setting[0], int) and\ isinstance(size_setting[1], int): self.resize(size_setting[0], size_setting[1]) else: self.set_size_request(800, 600) position_setting = Lp.settings.get_value('window-position') if len(position_setting) == 2 and\ isinstance(position_setting[0], int) and\ isinstance(position_setting[1], int): self.move(position_setting[0], position_setting[1]) if Lp.settings.get_value('window-maximized'): self.maximize() self._signal1 = self.connect("window-state-event", self._on_window_state_event) self._signal2 = self.connect("configure-event", self._on_configure_event) def _on_configure_event(self, widget, event): """ Delay event @param: widget as Gtk.Window @param: event as Gdk.Event """ self._toolbar.set_progress_width(widget.get_size()[0] / 4) if self._timeout_configure: GLib.source_remove(self._timeout_configure) self._timeout_configure = GLib.timeout_add(500, self._save_size_position, widget) def _save_size_position(self, widget): """ Save window state, update current view content size @param: widget as Gtk.Window """ self._timeout_configure = None size = widget.get_size() Lp.settings.set_value('window-size', GLib.Variant('ai', [size[0], size[1]])) position = widget.get_position() Lp.settings.set_value('window-position', GLib.Variant('ai', [position[0], position[1]])) def _on_window_state_event(self, widget, event): """ Save maximised state """ Lp.settings.set_boolean( 'window-maximized', 'GDK_WINDOW_STATE_MAXIMIZED' in event.new_window_state.value_names) def _on_destroyed_window(self, widget): """ Save paned widget width @param widget as unused, data as unused """ Lp.settings.set_value( 'paned-mainlist-width', GLib.Variant('i', self._paned_main_list.get_position())) Lp.settings.set_value( 'paned-listview-width', GLib.Variant('i', self._paned_list_view.get_position())) def _on_seek_action(self, action, param): """ Seek in stream @param action as Gio.SimpleAction @param param as GLib.Variant """ seconds = param.get_int32() position = Lp.player.get_position_in_track() seek = position / 1000000 / 60 + seconds if seek < 0: seek = 0 if seek > Lp.player.current_track.duration: seek = Lp.player.current_track.duration - 2 Lp.player.seek(seek) self._toolbar.update_position(seek * 60) def _on_player_action(self, action, param): """ Change player state @param action as Gio.SimpleAction @param param as GLib.Variant """ string = param.get_string() if string == "play_pause": Lp.player.play_pause() elif string == "play": Lp.player.play() elif string == "stop": Lp.player.stop() elif string == "next": Lp.player.next() elif string == "next_album": # In party or shuffle, just update next track if Lp.player.is_party() or\ Lp.settings.get_enum('shuffle') == Shuffle.TRACKS: Lp.player.set_next() # We send this signal to update next popover Lp.player.emit("queue-changed") else: Lp.player.context.next = NextContext.START_NEW_ALBUM Lp.player.set_next() Lp.player.next() elif string == "prev": Lp.player.prev() def _on_realize(self, widget): """ Run scanner on realize @param widget as Gtk.Widget """ if Lp.settings.get_value('auto-update') or Lp.tracks.is_empty(): # Delayed, make python segfault on sys.exit() otherwise # No idea why, maybe scanner using Gstpbutils before Gstreamer # initialisation is finished... GLib.timeout_add(2000, self.update_db)
class Window(Gtk.ApplicationWindow, Container): """ Init window objects """ def __init__(self, app): Container.__init__(self) self._app = app Gtk.ApplicationWindow.__init__(self, application=app, title="Lollypop") self._nullwidget = Gtk.Label() # Use to get selected background color self._timeout_configure = None seek_action = Gio.SimpleAction.new('seek', GLib.VariantType.new('i')) seek_action.connect('activate', self._on_seek_action) app.add_action(seek_action) player_action = Gio.SimpleAction.new('player', GLib.VariantType.new('s')) player_action.connect('activate', self._on_player_action) app.add_action(player_action) self._setup_window() self._setup_media_keys() self.enable_global_shorcuts(True) self.connect("destroy", self._on_destroyed_window) """ Add an application menu to window @parma: menu as Gio.Menu """ def setup_menu(self, menu): self._toolbar.setup_menu_btn(menu) """ Return selected color """ def get_selected_color(self): return self._nullwidget.get_style_context( ).get_background_color(Gtk.StateFlags.SELECTED) """ Setup global shortcuts @param enable as bool """ def enable_global_shorcuts(self, enable): if enable: if Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL: self._app.set_accels_for_action("app.seek(10)", ["Left"]) self._app.set_accels_for_action("app.seek(20)", ["<Control>Left"]) self._app.set_accels_for_action("app.seek(-10)", ["Right"]) self._app.set_accels_for_action("app.seek(-20)", ["<Control>Right"]) else: self._app.set_accels_for_action("app.seek(10)", ["Right"]) self._app.set_accels_for_action("app.seek(20)", ["<Control>Right"]) self._app.set_accels_for_action("app.seek(-10)", ["Left"]) self._app.set_accels_for_action("app.seek(-20)", ["<Control>Left"]) self._app.set_accels_for_action("app.player::play_pause", ["space", "c"]) self._app.set_accels_for_action("app.player::play", ["x"]) self._app.set_accels_for_action("app.player::stop", ["v"]) else: self._app.set_accels_for_action("app.seek(10)", [None]) self._app.set_accels_for_action("app.seek(20)", [None]) self._app.set_accels_for_action("app.seek(-10)", [None]) self._app.set_accels_for_action("app.seek(-20)", [None]) self._app.set_accels_for_action("app.player::play_pause", [None]) self._app.set_accels_for_action("app.player::play", [None]) self._app.set_accels_for_action("app.player::stop", [None]) ############ # Private # ############ """ Setup media player keys """ def _setup_media_keys(self): self._proxy = Gio.DBusProxy.new_sync( Gio.bus_get_sync(Gio.BusType.SESSION, None), Gio.DBusProxyFlags.NONE, None, 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/MediaKeys', 'org.gnome.SettingsDaemon.MediaKeys', None) self._grab_media_player_keys() try: self._proxy.connect('g-signal', self._handle_media_keys) except GLib.GError: # We cannot grab media keys if no settings daemon is running pass """ Do key grabbing """ def _grab_media_player_keys(self): try: self._proxy.call_sync('GrabMediaPlayerKeys', GLib.Variant('(su)', ('Lollypop', 0)), Gio.DBusCallFlags.NONE, -1, None) except GLib.GError: # We cannot grab media keys if no settings daemon is running pass """ Do player actions in response to media key pressed """ def _handle_media_keys(self, proxy, sender, signal, parameters): if signal != 'MediaPlayerKeyPressed': print('Received an unexpected signal\ \'%s\' from media player'.format(signal)) return response = parameters.get_child_value(1).get_string() if 'Play' in response: Objects.player.play_pause() elif 'Stop' in response: Objects.player.stop() elif 'Next' in response: Objects.player.next() elif 'Previous' in response: Objects.player.prev() """ Setup window icon, position and size, callback for updating this values """ def _setup_window(self): self.set_icon_name('lollypop') size_setting = Objects.settings.get_value('window-size') if isinstance(size_setting[0], int) and\ isinstance(size_setting[1], int): self.resize(size_setting[0], size_setting[1]) else: self.set_size_request(800, 600) position_setting = Objects.settings.get_value('window-position') if len(position_setting) == 2 and\ isinstance(position_setting[0], int) and\ isinstance(position_setting[1], int): self.move(position_setting[0], position_setting[1]) if Objects.settings.get_value('window-maximized'): self.maximize() self.connect("window-state-event", self._on_window_state_event) self.connect("configure-event", self._on_configure_event) self._toolbar = Toolbar(self.get_application()) self._toolbar.show() # Only set headerbar if according DE detected or forced manually if use_csd(): self.set_titlebar(self._toolbar) self._toolbar.set_show_close_button(True) self.add(self.main_widget()) else: hgrid = Gtk.Grid() hgrid.set_orientation(Gtk.Orientation.VERTICAL) hgrid.add(self._toolbar) hgrid.add(self.main_widget()) hgrid.show() self.add(hgrid) """ Delay event @param: widget as Gtk.Window @param: event as Gdk.Event """ def _on_configure_event(self, widget, event): self._toolbar.set_progress_width(widget.get_size()[0]/4) if self._timeout_configure: GLib.source_remove(self._timeout_configure) self._timeout_configure = GLib.timeout_add(500, self._save_size_position, widget) """ Save window state, update current view content size @param: widget as Gtk.Window """ def _save_size_position(self, widget): self._timeout_configure = None size = widget.get_size() Objects.settings.set_value('window-size', GLib.Variant('ai', [size[0], size[1]])) position = widget.get_position() Objects.settings.set_value('window-position', GLib.Variant('ai', [position[0], position[1]])) """ Save maximised state """ def _on_window_state_event(self, widget, event): Objects.settings.set_boolean('window-maximized', 'GDK_WINDOW_STATE_MAXIMIZED' in event.new_window_state.value_names) """ Save paned widget width @param widget as unused, data as unused """ def _on_destroyed_window(self, widget): Objects.settings.set_value("paned-mainlist-width", GLib.Variant( 'i', self._paned_main_list.get_position())) Objects.settings.set_value("paned-listview-width", GLib.Variant( 'i', self._paned_list_view.get_position())) """ Seek in stream @param action as Gio.SimpleAction @param param as GLib.Variant """ def _on_seek_action(self, action, param): seconds = param.get_int32() position = Objects.player.get_position_in_track() seek = position/1000000/60+seconds if seek < 0: seek = 0 if seek > Objects.player.current.duration: seek = Objects.player.current.duration - 2 Objects.player.seek(seek) self._toolbar.update_position(seek*60) """ Change player state @param action as Gio.SimpleAction @param param as GLib.Variant """ def _on_player_action(self, action, param): string = param.get_string() if string == "play_pause": Objects.player.play_pause() elif string == "play": Objects.player.play() elif string == "stop": Objects.player.stop()