Пример #1
0
    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)
Пример #2
0
    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
Пример #3
0
 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()
Пример #4
0
    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)
Пример #5
0
    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()
Пример #6
0
    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)
Пример #7
0
    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)
Пример #8
0
    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)
Пример #9
0
    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)
Пример #10
0
 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()
Пример #11
0
    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)
Пример #12
0
 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()
Пример #13
0
    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'))
Пример #14
0
    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()
Пример #15
0
    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)
Пример #16
0
    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)
Пример #17
0
    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'])
Пример #18
0
    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)
Пример #19
0
    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)
Пример #20
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)
Пример #21
0
    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)
Пример #22
0
        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)
Пример #23
0
    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()
Пример #24
0
    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()
Пример #25
0
    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
Пример #26
0
    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
Пример #27
0
 def _create_widget(self, preset):
     widget = PresetRow(preset)
     if preset.id == Settings.get().active_preset:
         widget.selected = True
     return widget
Пример #28
0
 def remove(self):
     if self.custom:
         Settings.get().remove_custom_audio(self.name)
Пример #29
0
 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
Пример #30
0
 def on_background(self, action, value):
     action.set_state(value)
     Settings.get().background = value
     self.window.props.hide_on_close = value