def __init__(self, version): super().__init__(application_id='com.rafaelmardojai.Blanket', flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE) GLib.set_application_name(_('Blanket')) GLib.setenv('PULSE_PROP_application.icon_name', 'com.rafaelmardojai.Blanket-symbolic', True) # Connect app shutdown signal self.connect('shutdown', self._on_shutdown) # Add --hidden command line option self.add_main_option('hidden', b'h', GLib.OptionFlags.NONE, GLib.OptionArg.NONE, 'Start window hidden', None) # App window self.window = None self.window_hidden = False # App version self.version = version # App main player self.mainplayer = MainPlayer() # Load saved props self.mainplayer.volume = Settings.get().volume self.mainplayer.playing = Settings.get().playing # Start MPRIS server self.mpris = MPRIS(self)
def load_presets(self): presets = Settings.get().get_presets_dict() for index, (preset_id, name) in enumerate(presets.items()): preset = PresetObject(preset_id, self.model) self.model.append(preset) if preset_id == Settings.get().active_preset: self.selected = preset
def _save_settings(self): # Save scroll position Settings.get().scroll_position = self.window.vscroll.get_value() # Save mainplayer volume Settings.get().volume = self.mainplayer.volume # Save mainplayer playing state Settings.get().playing = self.mainplayer.playing # Save presets settings Settings.get().save_presets()
def __init__(self, preset_id, model): super().__init__() self.id = preset_id self.model = model # Bind preset name with settings one Settings.get().get_preset_settings(self.id).bind( 'visible-name', self, 'name', Gio.SettingsBindFlags.DEFAULT)
def _on_rename_preset(self, _button): name = self.__get_name() if name: Settings.get().set_preset_name(self.preset.id, name) else: self.__invalid_name() return self.destroy()
def _on_selected_changed(self, _chooser, _pspec): if self.selected is not None: if Settings.get().active_preset != self.selected.id: Settings.get().active_preset = self.selected.id for row in self.presets_list.get_children(): row.selected = row.preset.id == self.selected.id self.emit('selected', self.selected)
def _on_selected_changed(self, _chooser, _pspec): if self.selected is not None: if Settings.get().active_preset != self.selected.id: Settings.get().active_preset = self.selected.id for i in range(self.model.get_n_items()): row = self.presets_list.get_row_at_index(i) row.selected = row.preset.id == self.selected.id self.emit('selected', self.selected)
def __init__(self, window, **kwargs): super().__init__(**kwargs) self.window = window Settings.get().bind( 'dark-mode', self.dark, 'active', Gio.SettingsBindFlags.DEFAULT ) self.dark.connect('notify::active', self._toggle_dark) self.autostart_failed = False self.autostart_saved = Settings.get().autostart self.autostart.set_active(self.autostart_saved) self.autostart.connect('notify::active', self._toggle_autostart)
def setup(self): # Get volume scale adjustment vol_adjustment = self.volume.get_adjustment() # Bind volume scale value with main player volume vol_adjustment.bind_property('value', self.mainplayer, 'volume', GObject.BindingFlags.BIDIRECTIONAL) # Set volume scale value on first run self.volume.set_value(self.mainplayer.volume) # Wire playpause button self.mainplayer.bind_property('playing', self.playpause_btn, 'playing', GObject.BindingFlags.SYNC_CREATE) # Setup presets widgets self.setup_presets() # Setup included/saved sounds self.setup_sounds() self.setup_custom_sounds() # Get saved scroll position saved_scroll = Settings.get().scroll_position # Get scrolled window vertical adjustment self.vscroll = self.scrolled_window.get_vadjustment() # Set saved scroll to vertical adjustment self.vscroll.set_value(saved_scroll)
def _on_window_close_request(self, window): if Settings.get().background: self._save_settings() # Save settings window.hide() else: self.quit_from_window = True self.quit()
def __init__(self, window, **kwargs): super().__init__(**kwargs) self.window = window Settings.get().bind('dark-mode', self.dark, 'active', Gio.SettingsBindFlags.DEFAULT) self.dark.connect('notify::active', self._toggle_dark) style_manager = Adw.StyleManager.get_default() self.dark_group.props.visible = not style_manager.props.system_supports_color_schemes self.autostart_failed = False self.autostart_saved = Settings.get().autostart self.autostart.set_active(self.autostart_saved) self.autostart.connect('notify::active', self._toggle_autostart)
def _on_window_delete(self, window, _event): if Settings.get().background: self._save_settings() # Save settings return window.hide_on_delete() else: self.quit_from_window = True self.quit()
def update_title(self, preset): if self.name_binding is not None: self.name_binding.unbind() if preset.id != Settings.get().default_preset: self.name_binding = preset.bind_property( 'name', self, 'title', GObject.BindingFlags.SYNC_CREATE) else: self.set_title(_('Blanket'))
def do_startup(self): # Startup application Adw.Application.do_startup(self) style_manager = Adw.StyleManager.get_default() # if the system doesn't support libadwaita color schemes, fall back to our setting if Settings.get( ).dark_mode and not style_manager.props.system_supports_color_schemes: style_manager.props.color_scheme = Adw.ColorScheme.FORCE_DARK self.setup_actions()
def __init__(self, preset): super().__init__() self.preset = preset self.rename_btn.connect('clicked', self._on_show_rename) self.delete_btn.connect('clicked', self._on_delete_preset) self.revealer.props.reveal_child = self.preset.id != Settings.get( ).default_preset preset.bind_property('name', self.name, 'label', GObject.BindingFlags.SYNC_CREATE)
def setup(self): # Load dark theme gtk_settings = Gtk.Settings.get_default() gtk_settings.set_property( 'gtk-application-prefer-dark-theme', Settings.get().dark_mode ) # Get volume scale adjustment vol_adjustment = self.volume.get_adjustment() # Bind volume scale value with main player volume vol_adjustment.bind_property('value', self.mainplayer, 'volume', GObject.BindingFlags.BIDIRECTIONAL) # Set volume scale value on first run self.volume.set_value(self.mainplayer.volume) # Wire playpause button self.mainplayer.bind_property( 'playing', self.playpause_btn, 'playing', GObject.BindingFlags.SYNC_CREATE ) # If background-playback enabled show quit action on menu self.quit_revealer.set_reveal_child(Settings.get().background) # Setup presets widgets self.setup_presets() # Setup included/saved sounds self.setup_sounds() self.setup_custom_sounds() # Show all widgets added to window self.show_all() # Get saved scroll position saved_scroll = Settings.get().scroll_position # Get scrolled window vertical adjustment self.vscroll = self.scrolled_window.get_vadjustment() # Set saved scroll to vertical adjustment self.vscroll.set_value(saved_scroll)
def setup_actions(self): actions = [{ 'name': 'open', 'func': self.on_open, 'accels': ['<Ctl>o'] }, { 'name': 'playpause', 'func': self.on_playpause, 'accels': ['<Ctl>m', 'space'] }, { 'name': 'reset-volumes', 'func': self.on_reset_volumes, }, { 'name': 'add-preset', 'func': self.on_add_preset, }, { 'name': 'background-playback', 'func': self.on_background, 'state': True }, { 'name': 'preferences', 'func': self.on_preferences }, { 'name': 'shortcuts', 'func': self.on_shortcuts }, { 'name': 'about', 'func': self.on_about }, { 'name': 'close', 'func': self.on_close, 'accels': ['<Ctl>w'] }, { 'name': 'quit', 'func': self.on_quit, 'accels': ['<Ctl>q'] }] for a in actions: if 'state' in a: action = Gio.SimpleAction.new_stateful( a['name'], None, Settings.get().get_value(a['name'])) action.connect('change-state', a['func']) else: action = Gio.SimpleAction.new(a['name'], None) action.connect('activate', a['func']) self.add_action(action) if 'accels' in a: self.set_accels_for_action('app.' + a['name'], a['accels'])
def __init__(self, preset): super().__init__() self.preset = preset self.rename_btn.connect('clicked', self._on_show_rename) self.delete_btn.connect('clicked', self._on_delete_preset) if self.preset.id != Settings.get().default_preset: self.rename_btn.set_visible(True) self.delete_btn.set_visible(True) preset.bind_property('name', self.name, 'label', GObject.BindingFlags.SYNC_CREATE)
def _on_delete_preset(self, _button): app = Gio.Application.get_default() window = app.get_active_window() active = self.preset.id == Settings.get().active_preset index = self.preset.remove() if index is not None: chooser = window.presets_chooser chooser.model.remove(index) # Select default preset row if active: chooser.selected = chooser.model.get_item(0)
def setup_custom_sounds(self): # Setup user custom sounds self.custom_sounds = SoundsGroup(_('Custom'), True) self.custom_sounds.connect('add-clicked', self._on_add_sound_clicked) self.box.pack_start(self.custom_sounds, False, True, 0) # Load saved custom audios for name, uri in Settings.get().custom_audios.items(): # Create a new SoundObject sound = SoundObject( name, uri=uri, mainplayer=self.mainplayer, custom=True ) # Add SoundObject to SoundsGroup self.custom_sounds.add(sound)
def do_activate(self): self.window = self.props.active_window if not self.window: self.window = BlanketWindow(self.mainplayer, self.mpris, application=self) self.window.props.hide_on_close = Settings.get().background if self.window_hidden: self.window.hide() self.window_hidden = False else: self.window.present() # Connect window close-request signal to _on_window_close_request self.window.connect('close-request', self._on_window_close_request)
def on_response(_filechooser, _id): gfile = self.filechooser.get_file() if gfile: filename = gfile.get_path() name = os.path.basename(filename).split('.')[0] uri = gfile.get_uri() # Create a new SoundObject sound = SoundObject(name, uri=uri, mainplayer=self.mainplayer, custom=True) # Save to settings GLib.idle_add(Settings.get().add_custom_audio, sound.name, sound.uri) # Add SoundObject to SoundsGroup self.custom_sounds.add(sound)
def _on_create_preset(self, _button): name = self.__get_name() if name: chooser = self.window.presets_chooser preset_id = Settings.get().add_preset(name) # Save new preset # Add preset to model preset = PresetObject(preset_id, chooser.model) chooser.model.append(preset) # Select new preset chooser.selected = preset else: self.__invalid_name() return # Clear name entry self.name_entry.set_text('') self.destroy()
def open_audio(self): filters = { 'Ogg': ['audio/ogg'], 'FLAC': ['audio/flac'], 'WAV': ['audio/x-wav', 'audio/wav'], 'MP3': ['audio/mpeg'], } self.filechooser = Gtk.FileChooserNative.new( _('Open audio'), self, Gtk.FileChooserAction.OPEN, None, None) for f, mts in filters.items(): audio_filter = Gtk.FileFilter() audio_filter.set_name(f) for mt in mts: audio_filter.add_mime_type(mt) self.filechooser.add_filter(audio_filter) response = self.filechooser.run() if response == Gtk.ResponseType.ACCEPT: filename = self.filechooser.get_filename() if filename: name = os.path.basename(filename).split('.')[0] uri = self.filechooser.get_uri() # Create a new SoundObject sound = SoundObject( name, uri=uri, mainplayer=self.mainplayer, custom=True ) # Save to settings GLib.idle_add(Settings.get().add_custom_audio, sound.name, sound.uri) # Add SoundObject to SoundsGroup self.custom_sounds.add(sound) self.custom_sounds.show_all()
def __receive_autostart(self, *args): self.window.present() active = self.autostart.get_active() state = args[5][0] autostart = args[5][1]['autostart'] if state == 0: pass elif state == 1: if active: error_dialog = Gtk.MessageDialog( message_type=Gtk.MessageType.WARNING, buttons=Gtk.ButtonsType.OK, text=_('Authorization failed')) error_dialog.props.transient_for = self error_dialog.props.modal = True error_dialog.props.secondary_text = _( 'Make sure Blanket has permission to run in ' '\nthe background in Settings → Applications → ' '\nBlanket and try again.') error_dialog.connect('response', self.__on_dialog_response) error_dialog.present() elif state == 2: error_dialog = Gtk.MessageDialog( message_type=Gtk.MessageType.WARNING, buttons=Gtk.ButtonsType.OK, text=_('Request error')) error_dialog.props.transient_for = self error_dialog.props.modal = True error_dialog.props.secondary_text = _( 'The autostart request failed.') error_dialog.connect('response', self.__on_dialog_response) error_dialog.present() self.autostart.set_active(autostart) Settings.get().autostart = autostart return
def __receive_autostart(self, *args): self.window.present() active = self.autostart.get_active() state = args[5][0] autostart = args[5][1]['autostart'] if state == 0: pass elif state == 1: if active: error_dialog = Gtk.MessageDialog( self, 0, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, _('Authorization failed') ) error_dialog.format_secondary_text( _('Make sure Blanket has permission to run in ' '\nthe background in Settings → Applications → ' '\nBlanket and try again.')) error_response = error_dialog.run() if error_response == Gtk.ResponseType.OK: error_dialog.destroy() elif state == 2: error_dialog = Gtk.MessageDialog( self, 0, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, _('Request error') ) error_dialog.format_secondary_text( _('The autostart request failed.') ) error_response = error_dialog.run() if error_response == Gtk.ResponseType.OK: error_dialog.destroy() self.autostart.set_active(autostart) Settings.get().autostart = autostart return
def _create_widget(self, preset): widget = PresetRow(preset) if preset.id == Settings.get().active_preset: widget.selected = True return widget
def remove(self): if self.custom: Settings.get().remove_custom_audio(self.name)
def remove(self): if self.id != Settings.get().default_preset: index = Settings.get().remove_preset(self.id) return index # Return the index where the preset where positioned return None
def on_background(self, action, value): action.set_state(value) Settings.get().background = value self.window.props.hide_on_close = value