Beispiel #1
0
  def Metadata(self) -> Metadata:
    # prefer adapter's metadata to building our own
    metadata: DbusMetadata = self._dbus_metadata()

    if metadata:
      return metadata

    # build metadata if no metadata supplied by adapter
    self.log_trace(f"Building {self.INTERFACE}.Metadata")
    track = self.adapter.get_current_track()
    stream_title = self.adapter.get_stream_title()

    if track is None:
      return DEFAULT_METADATA

    track_id = track.track_id
    res = {"mpris:trackid": Variant("o", track_id)}

    if track.length:
      res["mpris:length"] = Variant("x", track.length)

    if track.uri:
      res["xesam:url"] = Variant("s", track.uri)

    if stream_title or track.name:
      res["xesam:title"] = Variant("s", stream_title or track.name)

    if track.artists:
      artists = list(track.artists)
      artists.sort(key=lambda a: a.name or "")
      res["xesam:artist"] = Variant("as", [a.name for a in artists if a.name])

    if track.album and track.album.name:
      res["xesam:album"] = Variant("s", track.album.name)

    if track.album and track.album.artists:
      artists = list(track.album.artists)
      artists.sort(key=lambda a: a.name or "")
      res["xesam:albumArtist"] = Variant(
        "as", [a.name for a in artists if a.name]
      )

    art_url = self._get_art_url(track)

    if art_url:
      res["mpris:artUrl"] = Variant("s", art_url)

    if track.disc_no:
      res["xesam:discNumber"] = Variant("i", track.disc_no)

    if track.track_no:
      res["xesam:trackNumber"] = Variant("i", track.track_no)

    return res
Beispiel #2
0
def get_variant(type_hint, value):
    """Return a variant data type.

    The type of a variant is specified with
    a type hint.

    Example:

    .. code-block:: python

         v1 = get_variant(Bool, True)
         v2 = get_variant(List[Int], [1,2,3])

    :param type_hint: a type hint or a type string
    :param value: a value of the variant
    :return: an instance of Variant
    """
    if type(type_hint) == str:
        type_string = type_hint
    else:
        type_string = get_dbus_type(type_hint)

    if value is None:
        raise TypeError("Invalid DBus value 'None'.")

    return Variant(type_string, value)
Beispiel #3
0
    def do_activate(self):
        self.shell = self.object

        self.__action = Gio.SimpleAction(name='open')
        self.__action.connect('activate', self.apply_command)

        app = Gio.Application.get_default()
        app.add_action(self.__action)

        # Receive fourth submenu
        menu = self.shell.props.application.get_menubar()
        assert menu.get_n_items() > 3, 'But I need fourth submenu'
        it = menu.iterate_item_links(3)
        it.next()
        self.menu = it.get_value()

        item = Gio.MenuItem()
        if locale.getlocale()[0] == 'ru_RU':
            item.set_label("Открыть...")
        else:
            item.set_label(_("Open..."))
        item.set_detailed_action('app.open')
        item.set_attribute_value('accel', Variant('s', '<Ctrl>L'))
        self.menu.append_item(item)
        app.add_plugin_menu_item('edit', 'open', item)
        app.add_plugin_menu_item('browser-popup', 'open', item)
        app.add_plugin_menu_item('playlist-popup', 'open', item)
        app.add_plugin_menu_item('queue-popup', 'open', item)
Beispiel #4
0
 def get_source_data(self):
     if self.source:
         views = self.source.get_property_views()
         browser_values_list = []
         for view in views:
             browser_values_list.append(view.get_selection())
         self.browser_values_list = Variant('aas', browser_values_list)
         self.settings.set_value(KEY_BROWSER_VALUES, self.browser_values_list)
Beispiel #5
0
    def __call__(
        self, instance, call_done_cb, call_error_cb, user_data, *args, **kwargs
    ):
        argdiff = len(args) - len(self._inargs)
        if argdiff != 0:
            dbg_args = {
                "instance": instance,
                "call_done_cb": call_done_cb,
                "call_error_cb": call_error_cb,
                "user_data": user_data,
                "args": args,
                "kwargs": kwargs,
            }
        if argdiff < 0:
            raise TypeError(
                self.__qualname__
                + " missing {} required positional argument(s), expected: {}, given: {}".format(
                    -argdiff, len(self._inargs), dbg_args
                )
            )

        elif argdiff > 0:
            raise TypeError(
                self.__qualname__
                + " takes {} positional argument(s) but {} was/were given: {}".format(
                    len(self._inargs), len(args), dbg_args
                )
            )

        timeout = kwargs.get("timeout", None)

        def done_cb(obj, res, data):
            try:
                ret = obj.call_finish(res)
                if call_done_cb:
                    call_done_cb(instance, ret, data)
            except Exception as e:
                if call_error_cb:
                    call_error_cb(instance, e, data)

        ret = instance._bus.con.call(
            instance._bus_name,
            instance._path,
            self._iface_name,
            self.__name__[0 : -len("Async")],
            Variant(self._sinargs, args),
            VariantType.new(self._soutargs),
            0,
            timeout_to_glib(timeout),
            None,
            done_cb,
            user_data,
        )

        return ret
Beispiel #6
0
 def Metadata(self):
     self.log_trace("Getting %s.Metadata", self.INTERFACE)
     current_tl_track = self.core.playback.get_current_tl_track().get()
     stream_title = self.core.playback.get_stream_title().get()
     if current_tl_track is None:
         return {}
     else:
         (tlid, track) = current_tl_track
         track_id = get_track_id(tlid)
         res = {"mpris:trackid": Variant("o", track_id)}
         if track.length:
             res["mpris:length"] = Variant("x", track.length * 1000)
         if track.uri:
             res["xesam:url"] = Variant("s", track.uri)
         if stream_title or track.name:
             res["xesam:title"] = Variant("s", stream_title or track.name)
         if track.artists:
             artists = list(track.artists)
             artists.sort(key=lambda a: a.name or "")
             res["xesam:artist"] = Variant(
                 "as", [a.name for a in artists if a.name])
         if track.album and track.album.name:
             res["xesam:album"] = Variant("s", track.album.name)
         if track.album and track.album.artists:
             artists = list(track.album.artists)
             artists.sort(key=lambda a: a.name or "")
             res["xesam:albumArtist"] = Variant(
                 "as", [a.name for a in artists if a.name])
         art_url = self._get_art_url(track)
         if art_url:
             res["mpris:artUrl"] = Variant("s", art_url)
         if track.disc_no:
             res["xesam:discNumber"] = Variant("i", track.disc_no)
         if track.track_no:
             res["xesam:trackNumber"] = Variant("i", track.track_no)
         return res
    def do_deactivate(self):
        self.first_run = True
        self.settings.set_string('playlist', self.playlist)
        self.settings.set_string('source', self.source_name)
        if self.location:

            self.settings.set_string(KEY_LOCATION, self.location)
            self.settings.set_uint(KEY_PLAYBACK_TIME, self.playback_time)
        self.settings.set_boolean(KEY_PLAY_STATE, self.play_state)
        if self.source:
            views = self.source.get_property_views()
            browser_values_list = []
            for view in views:
                browser_values_list.append(view.get_selection())
            self.browser_values_list = Variant('aas', browser_values_list)
            self.settings.set_value(KEY_BROWSER_VALUES, self.browser_values_list)
    def save_rhythm(self, pb_time=None):
        """
        This actually saves info into gsettings
        :param pb_time:
        :return:
        """
        if self.location:
            pb_time = pb_time is None and self.playback_time or pb_time is None
            self.settings.set_uint(KEY_PLAYBACK_TIME, pb_time)
            self.settings.set_string(KEY_LOCATION, self.location)
            #logger.debug("last location %s" % self.location)
        self.settings.set_boolean(KEY_PLAY_STATE, self.play_state)

        if self.source:
            views = self.source.get_property_views()
            browser_values_list = []
            for view in views:
                browser_values_list.append(view.get_selection())
            self.browser_values_list = Variant('aas', browser_values_list)
            self.settings.set_value(KEY_BROWSER_VALUES, self.browser_values_list)
Beispiel #9
0
def get_variant(type_hint, value):
    """Return a variant data type.

    The type of a variant is specified with
    a type hint.

    Example:
         v1 = get_variant(Bool, True)
         v2 = get_variant(List[Int], [1,2,3])

    :param type_hint: a type hint or a type string
    :param value: a value of the variant
    :return: an instance of Variant
    """
    if type(type_hint) == str:
        type_string = type_hint
    else:
        type_string = get_dbus_type(type_hint)

    return Variant(type_string, value)
Beispiel #10
0
async def on_workspace_focus(i3, event):
    """Show the appfinder when an empty workspace receives focus"""

    # Close any open appfinder window
    await i3.command('[class="Xfce4-appfinder"] kill')

    # Do nothing if this workspace isn't empty
    if event.current.focus:
        return

    if event.current.num in WORKSPACE_CATEGORIES:
        # Switch appfinder category to the one configured for this workspace
        category = Variant("s", WORKSPACE_CATEGORIES[event.current.num])
        xfconf.SetProperty("xfce4-appfinder", "/last/category", category)

        try:
            # Open a new appfinder window in the new category
            bus.get("org.xfce.Appfinder").OpenWindow(True, 'such_fast')
        except:
            # The xfce4-appfinder service isn't running. Start it up.
            await i3.command("exec --no-startup-id xfce4-appfinder")
Beispiel #11
0
 def on_language_changed(self, spellchecker, language):
     action, go = self.get_action_owner()
     if go:
         action_target = Variant("s", language)
         go.activate_action(action, action_target)
Beispiel #12
0
 def create_stateful_action(self, name, _type, default_value, method):
     action = SimpleAction.new_stateful(name, VariantType.new(_type),
                                        Variant(_type, default_value))
     action.connect("change-state", method)
     self.add_action(action)
Beispiel #13
0
def dbus_prepare(obj,
                 variant: bool = False,
                 camel_keys: bool = False) -> tuple:
    """
    Recursively walks obj and builds a D-Bus signature
    by inspecting types. Variant types are created as
    necessary, and the returned obj may have changed.

    :param obj: An arbitrary primitive or container type
    :param variant: Force wrapping contained objects with variants
    :param camel_keys: Convert dict keys to CamelCase
    """
    sig = ''
    use_variant = variant

    try:
        if isinstance(obj, Variant):
            sig = 'v'

        elif isinstance(obj, bool):
            sig = 'b'

        elif isinstance(obj, str):
            sig = 's'

        elif isinstance(obj, int):
            if obj < pow(2, 16):
                sig = 'n'
            elif obj < pow(2, 32):
                sig = 'i'
            else:
                sig = 'x'

        elif isinstance(obj, float):
            sig = 'd'

        elif isinstance(obj, Color):
            sig = 's'
            obj = obj.html

        elif isinstance(obj, TraitType):
            obj, sig = dbus_prepare(trait_as_dict(obj), variant=True)

        elif isinstance(obj, HasTraits):
            obj, sig = dbus_prepare(class_traits_as_dict(obj), variant=True)

        elif hasattr(obj, '_asdict') and hasattr(obj, '_field_types'):
            # typing.NamedTuple
            obj, sig = dbus_prepare(obj._asdict(), variant=True)

        elif isinstance(obj, type) and issubclass(obj, enum.Enum):
            # top level enum, tuple of string keys
            obj = tuple(obj.__members__.keys())
            sig = '(%s)' % ('s' * len(obj))

        elif isinstance(obj, enum.Enum):
            obj = obj.name
            sig = 's'

        elif isinstance(obj, np.ndarray):
            dtype = obj.dtype.kind
            if dtype == 'f':
                dtype = 'd'
            sig = 'a' * obj.ndim + dtype
            obj = obj.tolist()

        elif isinstance(obj, tuple):
            tmp = []
            sig = '('

            for item in obj:
                if item is None and use_variant:
                    continue
                # struct of all items
                r_obj, r_sig = dbus_prepare(item)
                if r_obj is None:
                    continue
                sig += r_sig
                tmp.append(r_obj)
            if len(tmp) > 0:
                sig += ')'
                obj = tuple(tmp)
            else:
                sig = ''
                obj = None

        elif isinstance(obj, list):
            tmp = []
            sig = 'a'
            is_variant = use_variant or _check_variance(obj)

            for item in obj:
                if item is None and is_variant:
                    continue
                r_obj, r_sig = dbus_prepare(item, variant=is_variant)
                if r_obj is None:
                    continue

                tmp.append(r_obj)

            if is_variant:
                sig += 'v'
            else:
                sig += dbus_prepare(tmp[0])[1]

            obj = tmp

        elif isinstance(obj, (dict, frozendict)):
            if isinstance(obj, frozendict):
                tmp = {}
            else:
                tmp = obj.__class__()
            sig = 'a{s'
            vals = [x for x in obj.values() if x is not None]
            is_variant = use_variant or _check_variance(vals)

            for k, v in obj.items():
                if v is None:
                    continue
                r_obj, r_sig = dbus_prepare(v)
                if r_obj is None:
                    continue
                if camel_keys:
                    k = snake_to_camel(k)
                if is_variant:
                    tmp[k] = Variant(r_sig, r_obj)
                else:
                    tmp[k] = r_obj

            if is_variant:
                sig += 'v'
            else:
                sig += dbus_prepare(vals[0])[1]

            obj = tmp
            sig += '}'

        elif isinstance(obj, type):
            obj = obj.__name__
            sig = 's'

    except Exception as err:
        logger.exception('obj: %s  sig: %s variant: %s',
                         obj,
                         sig,
                         variant,
                         exc_info=err)
        raise

    return obj, sig
Beispiel #14
0
    def test_python_to_dbus_translations(self):
        from pydbus.translator import PydbusCPythonTranslator
        c = PydbusCPythonTranslator(True,
                                    'pydbus.unittest',
                                    unit_test_dictname='pydbus_python_to_dbus')

        argspec = c.translate('who.knows.what', 'testkey',
                              (1, 4, 100, 'never see it', 'no changes'), 0,
                              False, 'uui', None, None)
        self.assertEqual(argspec[0], 1)
        self.assertEqual(argspec[1], 4)
        self.assertEqual(argspec[3], 'never see it')

        argspec = c.translate('pydbus.unittest', 'leave_me_alone',
                              (1, 4, 100, 100000), 0, False, 'uui', None, None)
        self.assertEqual(argspec[0], 1)
        self.assertEqual(argspec[1], 4)

        argspec = c.translate(
            'pydbus.unittest', 'testkey',
            ('value_should_be_one', 'Test Case Matching on 4',
             'value should be thirty', (1, 2, 3, "won't see me"), 'no changes',
             ('bit 1 off', 'bit 2 on', 'bit 0 on'), {
                 'bit 1 off': True,
                 'bit 2 on': True,
                 'bit 0 on': True
             }), 0, False, 'uiussii', None, None)
        self.assertEqual(argspec[0], 1)
        self.assertEqual(argspec[1], 4)
        self.assertEqual(argspec[2], 30)
        self.assertEqual(argspec[3], 'forced replacement item')
        self.assertEqual(argspec[4], 'no changes')
        self.assertEqual(argspec[5], 5)
        self.assertEqual(argspec[6], 5)

        argspec = c.translate(
            'pydbus.unittest',
            'fromDbusNamedBitFormats',
            (
                ('bit 0 on', 'bit 2 off'),
                ('bit 2 off', ['zero_to_sixteen', 9
                               ], 'left two of nibble2 is one'),
                100,  # oass ints along as they come
                'never see it',
                'no changes'),
            0,
            False,
            'uuiss',
            None,
            None)
        self.assertEqual(argspec[0], 1)
        self.assertEqual(argspec[1], 0x910)
        self.assertEqual(argspec[2], 100)

        self.assertRaises(ValueError, c.translate, 'pydbus.unittest',
                          'singletest', ('should fail', 6), 0, False, 'uui',
                          None, None)
        argspec = c.translate('pydbus.unittest', 'singletest', 'bit 0 ON', 0,
                              False, 'u', None, None)
        self.assertTrue(argspec, 1)

        argspec = c.translate(
            'pydbus.unittest', 'prettydicttest', {
                'the first three bits if not the fourth': 5,
                'solo True, seldom seen': True
            }, 0, False, 'i', None, None)
        # print(str(argspec))
        self.assertEqual(argspec[0], 5 + 16)
        self.assertTrue(len(argspec) == 1)

        argspec = c.translate('pydbus.unittest', 'prettylisttest', ((
            'solo True, seldom seen',
            ('the first three bits if not the fifth', 3),
        ), ), 0, False, 'i', None, None)

        # print(str(argspec))
        self.assertEqual(argspec[0], 0x13)

        argspec = c.translate('pydbus.unittest', 'simplematchfunction',
                              ("The answer should be five", ), 0, False, 'i',
                              None, None)
        # print(str(argspec))
        self.assertTrue(argspec[0] == 5)

        argspec = c.translate('pydbus.unittest', 'allargsin1matchfunction',
                              ("The answer should be seven", "Hi Mom"), 0,
                              False, 'i', None, None)
        # print(str(argspec))
        self.assertTrue(argspec[0] == 7)

        argspec = c.translate('pydbus.unittest', 'pytodbusvariants',
                              (('label for 0', 1, 2, 'two', 'strings'),
                               ['some', 'more', 'strings']), 0, False, 'vv',
                              None, None)
        self.assertEqual(argspec[0],
                         Variant('(iiiss)', (0, 1, 2, 'two', 'strings')))
        self.assertEqual(argspec[1], Variant('as',
                                             ['some', 'more', 'strings']))

        argspec = c.translate('pydbus.unittest', 'pytodbusvariants2', (
            ('label for 0', 1, 2, 'two', 'strings'),
            ['label for 10', 'who', 'knows'],
            ('label for 10', 'who', 'knows'),
        ), 0, False, 'vvv', None, None)
        self.assertEqual(argspec[0],
                         Variant('(iiiss)', (0, 1, 2, 'two', 'strings')))
        self.assertEqual(argspec[1], Variant('ai', [10, -101, -101]))
        self.assertEqual(argspec[2], Variant(
            '(iss)',
            (10, 'who', 'knows'),
        ))
        self.assertTrue(len(argspec) == 3)

        argspec = c.translate('pydbus.unittest', 'dictionary_test',
                              ({
                                  0: 'label for 1',
                                  1: 10
                              }, {
                                  0: 'label for 1',
                                  20: 'label for 20',
                                  99: 99,
                                  42: "who knows",
                                  100: "label for 1"
                              }), 0, False, 'a{ii}a{ii}', None, None)

        self.assertEqual(argspec, ({
            0: 1,
            1: 10
        }, {
            0: 1,
            20: 20,
            99: 99,
            42: -101,
            100: -101
        }))

        argspec = c.translate('pydbus.unittest', 'dictionary_keys', (
            {
                'label for 1': 'is 1',
                2: 'is 2'
            },
            {
                'label for 1': 'is 1',
                2: 'is 2'
            },
        ), 0, False, 'a{is}a{ii}', None, None)
        # print(str(argspec))
        self.assertEqual(argspec[0], {1: 'is 1', 2: 'is 2'})
        self.assertEqual(argspec[1], {1: 1, 2: 2})

        t = BlankObject()
        t.arg0 = 'zero'
        t.arg1 = 'one'
        t.arg2 = 2
        argspec = c.translate('pydbus.unittest', 'named_arguments', t, 0,
                              False, 'ssi', None, None)
        self.assertEqual(argspec, ('zero', 'one', 2))

        d = {'arg0': 'zero', 'arg1': 'one', 'arg2': 2}
        argspec = c.translate('pydbus.unittest', 'named_arguments2', d, 0,
                              False, 'ssi', None, None)
        self.assertEqual(argspec, ('zero', 'one', 2))
Beispiel #15
0
    def __init__(self, user_preferences):
        super(Preferences, self).__init__(border_width=20)
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        self.add(vbox)

        self.vert_btn = Gtk.RadioButton(label="Vertical preview",
                                        action_name="win.change-preview",
                                        action_target=Variant(
                                            'q', Gtk.Orientation.VERTICAL))
        if user_preferences.preview == Gtk.Orientation.VERTICAL:
            self.vert_btn.set_active(True)
        vbox.pack_start(self.vert_btn, True, True, 0)
        self.hori_btn = Gtk.RadioButton(group=self.vert_btn,
                                        label="Horizontal preview",
                                        action_name="win.change-preview",
                                        action_target=Variant(
                                            'q', Gtk.Orientation.HORIZONTAL))
        if user_preferences.preview == Gtk.Orientation.HORIZONTAL:
            self.hori_btn.set_active(True)
        vbox.pack_start(self.hori_btn, True, True, 0)

        self.auto_scroll_btn = Gtk.CheckButton(
            label='Auto scroll',
            action_name="win.auto-scroll-toggle",
            action_target=Variant('b', True))
        self.auto_scroll_btn.set_active(user_preferences.auto_scroll)
        vbox.pack_start(self.auto_scroll_btn, True, True, 0)

        vbox.pack_start(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL),
                        True, True, 0)

        group = None
        for key, val in sorted(PARSERS.items()):
            enabled = val['class'] is not None
            item = Gtk.RadioButton(
                label=val['title'],
                group=group,
                sensitive=enabled,
                action_name=("win.change-parser" if enabled else None),
                action_target=Variant('s', key))
            if user_preferences.parser == key:
                item.set_active(True)
            item.parser = key
            if group is None:
                group = item
            vbox.pack_start(item, True, True, 0)
        self.parser_group = group.get_group()

        vbox.pack_start(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL),
                        True, True, 0)
        group = None
        for key, val in sorted(WRITERS.items()):
            enabled = val['class'] is not None
            item = Gtk.RadioButton(
                label=val['title'],
                group=group,
                sensitive=enabled,
                action_name=("win.change-writer" if enabled else None),
                action_target=Variant('s', key))
            if user_preferences.writer == key:
                item.set_active(True)
            item.writer = key
            if group is None:
                group = item
            vbox.pack_start(item, True, True, 0)
        self.writer_group = group.get_group()

        vbox.pack_start(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL),
                        True, True, 0)

        self.custom_btn = Gtk.CheckButton(
            label='Custom style',
            action_name="win.custom-style-toggle",
            action_target=Variant('b', True))
        self.custom_btn.set_active(user_preferences.custom_style)
        self.custom_btn.connect("toggled", self.on_custom_style_toggle)
        vbox.pack_start(self.custom_btn, True, True, 0)

        self.style_btn = ActionableFileChooserButton(
            sensitive=user_preferences.custom_style,
            action_name="win.change-style")
        vbox.pack_start(self.style_btn, True, True, 0)

        vbox.show_all()
Beispiel #16
0
 def do_file_set(self):
     self.action_target = Variant("s", self.get_filename() or '')
     action, go = self.get_action_owner()
     if go:
         go.activate_action(action, self.action_target)
Beispiel #17
0
def get_dbus_metadata(metadata: Metadata) -> DbusMetadata:
    return {
        key: Variant(METADATA_TYPES[key], val)
        for key, val in metadata.items() if is_valid_metadata(key, val)
    }
Beispiel #18
0
WORKSPACE_CATEGORIES = {
    1: "Accesssories",
    2: "Chromium Apps",
    3: "Office",
    4: "Bookmarks",
    5: "Development",
    6: "Games",
    7: "Internet",
    8: "Settings",
    9: "System",
}

# Tweak xfce4-appfinder over D-Bus
bus = SessionBus()
xfconf = bus.get("org.xfce.Xfconf")
xfconf.SetProperty("xfce4-appfinder", "/enable-service", Variant("b", True))
xfconf.SetProperty("xfce4-appfinder", "/single-window", Variant("b", True))


async def on_workspace_focus(i3, event):
    """Show the appfinder when an empty workspace receives focus"""

    # Close any open appfinder window
    await i3.command('[class="Xfce4-appfinder"] kill')

    # Do nothing if this workspace isn't empty
    if event.current.focus:
        return

    if event.current.num in WORKSPACE_CATEGORIES:
        # Switch appfinder category to the one configured for this workspace