Example #1
0
    def __init__(self, name, manager):
        super().__init__(name, manager)

        self.config.access(self.unit_config.CONFIG_EDIT_DIALOG_SIZE,
                           [500, 500])
        new_name = _("<New saved search name>")
        self.ssde_struct = ssde.Dict(
            label=_("Saved search"),
            substructs=[
                ssde.Text(label=_("Saved search name"),
                          name='name',
                          default=new_name,
                          validator=lambda x: x != new_name),
                ssde.List(
                    label=_("Search for one of the following"),
                    name='search',
                    substruct=ssde.TupleAndList(
                        label=_("Search for all of the following"),
                        substructs=[
                            ssde.Boolean(label=_("Exact search")),
                            ssde.Tuple(
                                label=_("Search criterion"),
                                substructs=[
                                    ssde.Choice(label=_("Field"),
                                                choices=self.unit_songlist.
                                                fields.basic_names),
                                    ssde.Text(label=_("Value"),
                                              validator=lambda x: x),
                                ])
                        ])),
                ssde.List(
                    label=_("Sort by"),
                    name='sort',
                    substruct=ssde.Tuple(substructs=[
                        ssde.Choice(label=_("Field"),
                                    choices=self.unit_songlist.fields.names),
                        ssde.Boolean(label=_("Reversed"))
                    ])),
                ssde.Integer(label=_("Separator depth"), name='separator'),
            ])

        self.new_resource_provider(SavedSearch.name +
                                   '.left-context.user-action').add_resources(
                                       resource.UserAction(
                                           'mod.savedsearch-new',
                                           _("New search"), 'edit'),
                                       resource.UserAction(
                                           'mod.savedsearch-edit',
                                           _("Edit search"), 'edit'),
                                       resource.UserAction(
                                           'mod.savedsearch-delete',
                                           _("Delete search"), 'edit'),
                                   )
Example #2
0
    def __init__(self, name, manager):
        super().__init__(name, manager)

        self.new_resource_provider('app.menu').add_resources(
            resource.MenuPath('gampc', _("_GAMPC"), is_submenu=True),
            resource.MenuPath('edit', _("_Edit"), is_submenu=True),
            resource.MenuPath('playback', _("_Playback"), is_submenu=True),
            resource.MenuPath('server', _("_Server"), is_submenu=True),
            resource.MenuPath('components', _("_Components"), is_submenu=True),
            resource.MenuPath('help', _("_Help"), is_submenu=True),

            resource.MenuPath('gampc/window'),
            resource.MenuPath('gampc/persistent'),
            resource.MenuPath('gampc/app'),

            resource.MenuPath('edit/global'),
            resource.MenuPath('edit/component'),

            resource.MenuPath('server/server'),
            resource.MenuPath('server/profiles'),
        )

        self.new_resource_provider('app.user-action').add_resources(
            resource.UserAction('app.new-window', _("New window"), 'gampc/window', ['<Control>n']),
            resource.UserAction('app.close-window', _("Close window"), 'gampc/window', ['<Control>w']),
            resource.UserAction('win.toggle-fullscreen', _("Fullscreen window"), 'gampc/window', ['<Alt>f']),
            resource.UserAction('win.volume-popup', _("Adjust volume"), 'gampc/window', ['<Alt>v']),
            resource.UserAction('app.quit', _("Quit"), 'gampc/app', ['<Control>q']),
            resource.UserAction('app.BAD', "BAD", 'gampc/app', ['<Control><Alt>z']),

            resource.UserAction('app.help', _("Help"), 'help', ['<Control>h', 'F1']),
            resource.UserAction('app.about', _("About"), 'help'),
        )
Example #3
0
    def __init__(self, name, manager):
        super().__init__(name, manager)

        self.new_resource_provider('app.user-action').add_resources(
            resource.UserAction('mod.playlist-saveas(false)', _("Save as playlist"), 'edit/component'),
        )

        self.new_resource_provider('songlist.action').add_resources(
            resource.ActionModel('playlist-add', action_playlist_add_saveas_cb, parameter_type=GLib.VariantType.new('b')),
            resource.ActionModel('playlist-saveas', action_playlist_add_saveas_cb, parameter_type=GLib.VariantType.new('b'))
        )

        self.new_resource_provider('songlist.context.user-action').add_resources(
            resource.UserAction('mod.playlist-add(true)', _("Add to playlist"), 'other'),
        )

        self.new_resource_provider(Playlist.name + '.left-context.user-action').add_resources(
            resource.UserAction('mod.playlist-rename', _("Rename"), 'action'),
            resource.UserAction('mod.playlist-delete', _("Delete"), 'action'),
            resource.UserAction('mod.playlist-update-from-queue', _("Update from play queue"), 'action')
        )
Example #4
0
    def __init__(self, name, manager):
        super().__init__(name, manager)

        self.new_resource_provider('app.menu').add_resources(
            resource.MenuPath('edit/component/stream'), )

        self.new_resource_provider('app.user-action').add_resources(
            resource.UserAction('mod.stream-add', _("Add stream"),
                                'edit/component/stream'),
            resource.UserAction('mod.stream-modify', _("Modify stream"),
                                'edit/component/stream', ['F2']),
        )

        self.new_resource_provider('stream.context.menu').add_resources(
            resource.MenuPath('stream'),
            resource.MenuAction('stream/mod.stream-add', _("Add stream")),
            resource.MenuAction('stream/mod.stream-modify',
                                _("Modify stream")),
        )

        self.fields = data.FieldFamily(self.config.fields)
        self.fields.register_field(data.Field('Name', _("Name")))
        self.fields.register_field(data.Field('file', _("URL")))
        self.fields.register_field(data.Field('Comment', _("Comment")))

        self.db = StreamDatabase(self.fields)

        self.config.access(self.unit_config.CONFIG_EDIT_DIALOG_SIZE,
                           [500, 500])
        self.ssde_struct = ssde.Dict(label=_("Internet stream"),
                                     substructs=[
                                         ssde.Text(label=_("Name"),
                                                   name='Name',
                                                   validator=bool),
                                         ssde.Text(label=_("URL"),
                                                   name='file',
                                                   default='http://'),
                                         ssde.Text(label=_("Comment"),
                                                   name='Comment'),
                                     ])
Example #5
0
 def register_component_class(self, component_class, *args, **kwargs):
     name = component_class.name
     if name in self._component_classes:
         raise RuntimeError
     user_action = resource.UserAction(
         'app.component-start("{name}")'.format(name=name),
         component_class.title, 'components/components', [
             '<Alt>' + component_class.key,
             '<Control><Alt>' + component_class.key
         ])
     self._component_classes[
         name] = component_class, args, kwargs, user_action
     self.user_action_provider.add_resource(user_action)
Example #6
0
    def __init__(self, name, manager):
        super().__init__(name, manager)
        self._component_classes = {}
        self._components = []

        self.new_resource_provider('app.menu').add_resources(
            resource.MenuPath('components/components',
                              _("Press <Ctrl> for a new instance")),
            resource.MenuPath('components/current'),
        )

        self.user_action_provider = self.new_resource_provider(
            'app.user-action')
        self.user_action_provider.add_resources(
            resource.UserAction('app.component-stop', _("Stop component"),
                                'components/current', ['<Control><Shift>w']))
Example #7
0
 def __init__(self, name, manager):
     super().__init__(name, manager)
     self.new_resource_provider('app.user-action').add_resources(
         resource.UserAction('mod.search', _("Search"), 'edit/component',
                             ['<Control><Shift>f']), )
Example #8
0
    def __init__(self, name, manager):
        super().__init__(name, manager)

        actions = [
            resource.UserAction('mod.cut',
                                _("Cut"),
                                'edit/component/base', ['<Control>x'],
                                accels_fragile=True),
            resource.UserAction('mod.copy',
                                _("Copy"),
                                'edit/component/base', ['<Control>c'],
                                accels_fragile=True),
            resource.UserAction('mod.paste',
                                _("Paste"),
                                'edit/component/base', ['<Control>v'],
                                accels_fragile=True),
            resource.UserAction('mod.paste-before', _("Paste before"),
                                'edit/component/base', ['<Control>b']),
            resource.UserAction('mod.delete',
                                _("Delete"),
                                'edit/component/base', ['Delete'],
                                accels_fragile=True),
            resource.UserAction('mod.undelete',
                                _("Undelete"),
                                'edit/component/base', ['<Alt>Delete'],
                                accels_fragile=True),
            resource.UserAction('mod.add-separator', _("Add separator"),
                                'edit/component/special'),
            resource.UserAction('mod.add-url', _("Add URL or filename"),
                                'edit/component/special'),
        ]

        menus = [
            resource.MenuPath('edit/component/base'),
            resource.MenuPath('edit/component/special'),
        ]

        self.new_resource_provider('app.menu').add_resources(*menus)

        self.new_resource_provider('app.user-action').add_resources(
            resource.UserAction('mod.save', _("Save"), 'edit/global',
                                ['<Control>s']),
            resource.UserAction('mod.reset', _("Reset"), 'edit/global',
                                ['<Control>r']),
            resource.UserAction('mod.filter', _("Filter"), 'edit/global',
                                ['<Control><Shift>f']),
            *actions,
        )

        self.new_resource_provider('songlist.context.menu').add_resources(
            resource.MenuPath('action'),
            resource.MenuPath('edit'),
            resource.MenuPath('edit/component'),
            *menus,
            resource.MenuPath('other'),
        )

        self.new_resource_provider(
            'songlist.context.user-action').add_resources(*actions)

        self.new_resource_provider('songlist.left-context.menu').add_resources(
            resource.MenuPath('action'),
            resource.MenuPath('edit'),
            resource.MenuPath('other'),
        )

        self.config.access(
            'music-dir', GLib.get_user_special_dir(GLib.USER_DIRECTORY_MUSIC))

        self.fields = data.FieldFamily(self.config.fields)
        self.fields.register_field(data.Field('Album', _("Album")))
        self.fields.register_field(data.Field('AlbumArtist',
                                              _("Album artist")))
        self.fields.register_field(data.Field('Artist', _("Artist")))
        self.fields.register_field(data.Field('Composer', _("Composer")))
        self.fields.register_field(data.Field('Date', _("Date")))
        self.fields.register_field(data.Field('Disc', _("Disc")))
        self.fields.register_field(data.Field('file', _("File")))
        self.fields.register_field(data.Field('Genre', _("Genre")))
        self.fields.register_field(
            data.Field('Last_Modified', _("Last modified")))
        self.fields.register_field(data.Field('Performer', _("Performer")))
        self.fields.register_field(
            data.Field('Time', _("Seconds"), visible=False))
        self.fields.register_field(
            data.Field('FormattedTime',
                       _("Duration"),
                       get_value=lambda song: data.format_time(song['Time'])
                       if 'Time' in song else ''))
        self.fields.register_field(data.Field('Title', _("Title (partial)")))
        self.fields.register_field(
            data.Field('FullTitle', _("Title"), get_value=self.song_title))
        self.fields.register_field(data.Field('Track', _("Track")))
        self.fields.register_field(
            data.FieldWithTable('Extension',
                                _("Extension"),
                                table=[['file', '^http://', ''],
                                       ['file', '\\.([^.]*)$', '\\1']]))
        self.fields.register_field(
            data.FieldWithTable(
                'agenre',
                visible=False,
                table=[['Genre', '[Mm]ilong', 'b milonga'],
                       ['Genre', '[Cc]andombe', 'b milonga'],
                       ['Genre', '[Tt]ango|Canci[oó]n', 'a tango'],
                       ['Genre', '[Vv]als', 'c vals'],
                       ['Genre', '[Ff]ox ?trot', 'd fox'],
                       ['Genre', '[Pp]aso ?doble', 'e paso'],
                       ['Genre', 'Ranchera', 'f ranchera'], [None, None,
                                                             'z']]))
        self.fields.register_field(
            data.FieldWithTable(
                'ArtistSortName',
                visible=False,
                table=[[
                    'Artist', '(La Típica Sanata|Otros Aires|.* Orquesta)',
                    '\\1'
                ], ['Artist', '^(.* Tango)$', '\\1'],
                       [
                           'Artist', '(.*), dir\. (.*) ([^ ]+)',
                           '\\3, \\2 (\\1)'
                       ],
                       [
                           'Artist',
                           '(Orquesta Típica|Dúo|Cuarteto|Sexteto) (.*)',
                           '\\2, \\1'
                       ], ['Artist', '(.*) ((?:Di|De) *[^ ]+)', '\\2, \\1'],
                       ['Artist', '(.*) ([^ ]+)', '\\2, \\1'],
                       ['Artist', '(.*)', '\\1']]))
        performer_last_name = data.FieldWithTable(
            'PerformerLastName',
            visible=False,
            table=[['Performer', '^(.*) ((?:Di|De|Del) *[^ ]+)$', '\\2'],
                   ['Performer', '^(.*) ([^ ]+)$', '\\2'],
                   ['Performer', '^(.*)$', '\\1']])
        self.fields.register_field(
            data.Field('PerformersLastNames',
                       visible=False,
                       get_value=lambda song: ', '.join(
                           performer_last_name.get_value({'Performer': name})
                           for name in song.get('Performer').split(', '))
                       if song.get('Performer') else None))
Example #9
0
    def __init__(self, name, manager):
        super().__init__(name, manager)

        self.new_resource_provider('app.action').add_resources(
            resource.ActionModel('play-or-pause',
                                 self.play_or_pause_cb,
                                 dangerous=True),
            resource.ActionModel('absolute-jump',
                                 self.absolute_jump_cb,
                                 dangerous=True,
                                 parameter_type=GLib.VariantType.new('i')),
            resource.ActionModel('relative-jump',
                                 self.relative_jump_cb,
                                 dangerous=True,
                                 parameter_type=GLib.VariantType.new('i')),
            *(resource.ActionModel(name, self.mpd_command_cb, dangerous=True)
              for name in ('play', 'stop', 'next', 'previous')),
            *(resource.ActionModel('fade-to-' + name, self.fade_to_action_cb)
              for name in ('next', 'stop')),
        )

        self.new_resource_provider('app.menu').add_resources(
            resource.MenuPath('playback/play'),
            resource.MenuPath('playback/move'),
            resource.MenuPath('playback/jump'),
        )

        self.new_resource_provider('app.user-action').add_resources(
            resource.UserAction('app.play-or-pause',
                                _("_Play/pause"),
                                'playback/play',
                                ['<Control>Up', 'AudioPlay', 'space'],
                                accels_fragile=True),
            resource.UserAction('app.stop',
                                _("_Stop"),
                                'playback/play',
                                ['<Control>Down', 'AudioStop'],
                                accels_fragile=True),
            resource.UserAction('app.fade-to-stop',
                                _("Fade to stop"),
                                'playback/play',
                                ['<Control><Shift>Down', '<Shift>AudioStop'],
                                accels_fragile=True),
            resource.UserAction('app.previous',
                                _("_Previous"),
                                'playback/move',
                                ['<Control>Left', 'AudioPrev'],
                                accels_fragile=True),
            resource.UserAction('app.next',
                                _("_Next"),
                                'playback/move',
                                ['<Control>Right', 'AudioNext'],
                                accels_fragile=True),
            resource.UserAction('app.fade-to-next',
                                _("_Fade to next"),
                                'playback/move', ['<Control><Shift>Right'],
                                accels_fragile=True),
            resource.UserAction('app.absolute-jump(0)',
                                _("Restart playback"),
                                'playback/jump', ['<Alt>Up'],
                                accels_fragile=True),
            resource.UserAction('app.absolute-jump(-15)',
                                _("End of song (-{} seconds)").format(15),
                                'playback/jump', ['<Alt>Down'],
                                accels_fragile=True),
            resource.UserAction('app.relative-jump(-5)',
                                _("Skip backwards ({} seconds)").format(5),
                                'playback/jump', ['<Alt>Left'],
                                accels_fragile=True),
            resource.UserAction('app.relative-jump(5)',
                                _("Skip forwards ({} seconds)").format(5),
                                'playback/jump', ['<Alt>Right'],
                                accels_fragile=True),
        )

        self.fading = None
Example #10
0
    def __init__(self, name, manager):
        super().__init__(name, manager)
        self.ampd_client = ampd.ClientGLib()
        self.ampd_client.connect('client-connected', self.client_connected_cb)
        self.ampd_client.connect('client-disconnected',
                                 self.client_disconnected_cb)

        self.ampd = self.ampd_client.executor.sub_executor()

        self.ampd_server_properties = ampd.ServerPropertiesGLib(
            self.ampd_client.executor)
        self.ampd_server_properties.bind_property(
            'current-song', self, 'current-song',
            GObject.BindingFlags.SYNC_CREATE)
        self.ampd_server_properties.connect('server-error',
                                            self.server_error_cb)
        self.ampd_server_properties.connect('notify::updating-db',
                                            self.set_server_label)
        self.server_options = {
            name: ServerOption()
            for name in ampd.OPTION_NAMES
        }
        for name in ampd.OPTION_NAMES:
            self.ampd_server_properties.bind_property(
                name, self.server_options[name], 'value',
                GObject.BindingFlags.BIDIRECTIONAL
                | GObject.BindingFlags.SYNC_CREATE)

        self.host = self.port = None
        self.want_to_connect = False

        self.server_profile_desired = self.config.server.access(
            'profile-desired', self.unit_profiles.LOCAL_HOST)
        self.server_profile_previous = self.config.access(
            'server-profile-previous', self.server_profile_desired)
        self.server_profile_backup = self.server_profile_desired

        self.connect('notify::server-profile', self.notify_server_profile_cb)
        self.connect('notify::server-partition',
                     self.notify_server_partition_cb)
        self.connect('notify::server-profile-desired',
                     self.notify_server_profile_desired_cb)

        self.unit_profiles.connect('notify::profiles', self.notify_profiles_cb)

        self.separator_song = {'file': self.SEPARATOR_FILE}

        self.new_resource_provider('app.action').add_resources(
            resource.PropertyActionModel('server-profile-desired', self),
            resource.ActionModel('connect', self.ampd_connect),
            resource.ActionModel('disconnect', self.ampd_disconnect),
            resource.ActionModel('connect-to-previous',
                                 self.ampd_connect_to_previous),
            resource.ActionModel('update', self.update_cb),
            *(resource.PropertyActionModel(name,
                                           self.server_options[name],
                                           property_name='value')
              for name in ampd.OPTION_NAMES))

        self.new_resource_provider('app.menu').add_resources(
            resource.MenuPath('server/server/actions'),
            resource.MenuPath('server/server/options'),
            resource.MenuPath('server/server/partition'),
            resource.MenuPath('server/server/connection'),
        )

        self.new_resource_provider('app.user-action').add_resources(
            resource.UserAction('app.update', _("Update database"),
                                'server/server/actions'),
            resource.UserAction('app.random', _("Random mode"),
                                'server/server/options'),
            resource.UserAction('app.repeat', _("Repeat mode"),
                                'server/server/options'),
            resource.UserAction('app.consume', _("Consume mode"),
                                'server/server/options'),
            resource.UserAction('app.single', _("Single mode"),
                                'server/server/options'),
            resource.UserAction('app.connect', _("Connect"),
                                'server/server/connection', ['<Alt><Shift>c']),
            resource.UserAction('app.disconnect', _("Disconnect"),
                                'server/server/connection', ['<Alt><Shift>d']),
            resource.UserAction('app.connect-to-previous',
                                _("Connect to previous"),
                                'server/server/connection',
                                ['<Control><Alt>p']),
        )
Example #11
0
    def __init__(self, name, manager):
        super().__init__(name, manager)

        self.fields = data.FieldFamily(self.config.fields)
        self.fields.register_field(data.Field('Artist', _("Artist")))
        self.fields.register_field(data.Field('Genre', _("Genre")))
        self.fields.register_field(
            data.Field('Years_Min',
                       visible=False,
                       get_value=lambda tanda: min(
                           song.get('Date', '').split('-', 1)[0]
                           for song in tanda['_songs']) or '????'
                       if tanda.get('_songs') else None))
        self.fields.register_field(
            data.Field('Years_Max',
                       visible=False,
                       get_value=lambda tanda: max(
                           song.get('Date', '').split('-', 1)[0]
                           for song in tanda['_songs']) or '????'
                       if tanda.get('_songs') else None))
        self.fields.register_field(
            data.Field(
                'Years',
                _("Years"),
                get_value=lambda tanda:
                ('\'{}'.format(tanda['Years_Min'][2:])
                 if tanda['Years_Min'] == tanda['Years_Max'] else '\'{}-\'{}'.
                 format(tanda['Years_Min'][2:], tanda['Years_Max'][2:]))
                if 'Years_Min' in tanda and 'Years_Max' in tanda else '????'))
        self.fields.register_field(
            data.Field('First_Song',
                       _("First song"),
                       get_value=lambda tanda: tanda['_songs'][0]['Title']
                       if '_songs' in tanda else '???'))
        self.fields.register_field(data.Field('Performer', _("Performer")))
        self.fields.register_field(data.Field('Comment', _("Comment")))
        self.fields.register_field(data.Field('Description', _("Description")))
        self.fields.register_field(data.Field('Note', _("Note"), min_width=30))
        self.fields.register_field(
            data.Field('Rhythm', _("Rhythm"), min_width=30))
        self.fields.register_field(
            data.Field('Energy', _("Energy"), min_width=30))
        self.fields.register_field(
            data.Field('Speed', _("Speed"), min_width=30))
        self.fields.register_field(
            data.Field('Emotion', _("Emotion"), min_width=30))

        self.fields.register_field(
            data.Field('Drama', _("Drama"), min_width=30))
        self.fields.register_field(
            data.Field('Romance', _("Romance"), min_width=30))

        self.fields.register_field(
            data.Field('Last_Modified', _("Last modified")))
        self.fields.register_field(data.Field('Last_Played', _("Last played")))
        self.fields.register_field(
            data.Field('Last_Played_Weeks',
                       _("Weeks since last played"),
                       min_width=30,
                       get_value=get_last_played_weeks))
        self.fields.register_field(
            data.Field('n_songs',
                       _("Number of songs"),
                       min_width=30,
                       get_value=lambda tanda: 0
                       if not tanda.get('_songs') else None
                       if (len(tanda.get('_songs')) == 4 and tanda.get('Genre')
                           .startswith('Tango')) or
                       (len(tanda.get('_songs')) == 3 and tanda.get('Genre') in
                        {'Vals', 'Milonga'}) else len(tanda.get('_songs'))))
        self.fields.register_field(
            data.Field('Duration',
                       _("Duration"),
                       get_value=lambda tanda: data.format_time(
                           sum((int(song['Time']))
                               for song in tanda.get('_songs', [])))))

        self.db = TandaDatabase(self.fields, self)

        self.new_resource_provider('app.action').add_resources(
            resource.ActionModel('tanda-verify',
                                 self.db.action_tanda_verify_cb),
            resource.ActionModel('tanda-cleanup-db',
                                 self.db.action_cleanup_db_cb),
        )

        self.new_resource_provider('app.user-action').add_resources(
            resource.UserAction('mod.tanda-fill-field', _("Fill tanda field"),
                                'edit/component', ['<Control>z']),
            resource.UserAction('mod.tanda-reset-field',
                                _("Reset tanda field"), 'edit/component',
                                ['<Control><Shift>z']),
            resource.UserAction('mod.tanda-reset', _("Reset tanda"),
                                'edit/component', ['<Control><Shift>r']),
            resource.UserAction('mod.tanda-delete', _("Delete tanda"),
                                'edit/component', ['<Control>Delete']),
            resource.UserAction('supermod.tanda-switch-subcomponent',
                                _("Switch tanda view mode"), 'edit/component',
                                ['<Control>Tab']),
            resource.UserAction('supermod.tanda-verify',
                                _("Verify tanda database"), 'edit/component',
                                ['<Control><Shift>d']),
            resource.UserAction('supermod.tanda-cleanup-db',
                                _("Cleanup database"), 'edit/component'))

        self.new_resource_provider('songlist.action').add_resources(
            resource.ActionModel('tanda-define',
                                 self.db.action_tanda_define_cb), )

        self.new_resource_provider(
            'songlist.context.user-action').add_resources(
                resource.UserAction('mod.tanda-define', _("Define tanda"),
                                    'other'))

        self.new_resource_provider(
            'tanda-edit.left-context.user-action').add_resources(
                resource.UserAction('mod.tanda-delete', _("Delete tanda"),
                                    'edit'))

        self.setup_menu('tanda-edit', 'context', ['songlist'])
        self.setup_menu('tanda-edit', 'left-context', ['songlist'])
        self.setup_menu('tanda-view', 'context', ['songlist'])
Example #12
0
    def __init__(self, name, manager):
        super().__init__(name, manager)

        self.new_resource_provider('app.user-action').add_resources(
            resource.UserAction('mod.playqueue-shuffle', _("Shuffle"),
                                'edit/component'),
            resource.UserAction('mod.playqueue-go-to-current',
                                _("Go to current song"), 'edit/component',
                                ['<Control>z']))

        self.new_resource_provider('songlist.action').add_resources(
            resource.ActionModel('playqueue-ext-add-high-priority',
                                 action_playqueue_add_high_priority_cb,
                                 dangerous=True,
                                 parameter_type=GLib.VariantType.new('b')),
            *(resource.ActionModel('playqueue-ext' + verb,
                                   action_playqueue_add_replace_cb,
                                   dangerous=(verb == '-replace'),
                                   parameter_type=GLib.VariantType.new('b'))
              for verb in ('-add', '-replace')),
        )

        for name, parameter in (('context', '(true)'), ('left-context',
                                                        '(false)')):
            self.new_resource_provider(
                'songlist.{name}.user-action'.format(name=name)).add_resources(
                    resource.UserAction('mod.playqueue-ext-add' + parameter,
                                        _("Add to play queue"), 'action'),
                    resource.UserAction(
                        'mod.playqueue-ext-replace' + parameter,
                        _("Replace play queue"), 'action'),
                    resource.UserAction(
                        'mod.playqueue-ext-add-high-priority' + parameter,
                        _("Add to play queue with high priority"), 'action'),
                )

        self.new_resource_provider(PlayQueue.name +
                                   '.context.menu').add_resources(
                                       resource.MenuPath(
                                           'other/playqueue-priority',
                                           _("Priority for random mode"),
                                           is_submenu=True), )

        self.new_resource_provider(PlayQueue.name +
                                   '.context.user-action').add_resources(
                                       resource.UserAction(
                                           'mod.playqueue-high-priority',
                                           _("High"),
                                           'other/playqueue-priority'),
                                       resource.UserAction(
                                           'mod.playqueue-normal-priority',
                                           _("Normal"),
                                           'other/playqueue-priority'),
                                       resource.UserAction(
                                           'mod.playqueue-choose-priority',
                                           _("Choose"),
                                           'other/playqueue-priority'),
                                       resource.UserAction(
                                           'mod.playqueue-shuffle',
                                           _("Shuffle"), 'other'),
                                   )