diff --git a/beetsplug/smartplaylist.py b/beetsplug/smartplaylist.py index 254671094..ff8d0ed11 100644 --- a/beetsplug/smartplaylist.py +++ b/beetsplug/smartplaylist.py @@ -27,6 +27,28 @@ import os database_changed = False +def query_from_parameter(lib, playlist, parameter, album=False): + if playlist.has_key(parameter): + # Parse quer(ies). If it's a list, join the queries with OR. + query_strings = playlist[parameter] + if not isinstance(query_strings, (list, tuple)): + query_strings = [query_strings] + model = library.Album if album else library.Item + query = dbcore.OrQuery( + [library.get_query(q, model) for q in query_strings] + ) + # Execute query, depending on type + if album: + result = [] + for album in lib.albums(query): + result.extend(album.items()) + return result + else: + return lib.items(query) + else: + return [] + + def update_playlists(lib): ui.print_("Updating smart playlists...") playlists = config['smartplaylist']['playlists'].get(list) @@ -36,13 +58,9 @@ def update_playlists(lib): relative_to = normpath(relative_to) for playlist in playlists: - # Parse the query. If it's a list, join the queries with OR. - query_strings = playlist['query'] - if not isinstance(query_strings, (list, tuple)): - query_strings = [query_strings] - items = lib.items(dbcore.OrQuery( - [library.get_query(q, library.Item) for q in query_strings] - )) + items = [] + items.extend(query_from_parameter(lib, playlist, 'album_query', True)) + items.extend(query_from_parameter(lib, playlist, 'query', False)) m3us = {} basename = playlist['name'].encode('utf8') @@ -55,7 +73,8 @@ def update_playlists(lib): item_path = item.path if relative_to: item_path = os.path.relpath(item.path, relative_to) - m3us[m3u_name].append(item_path) + if not item_path in m3us[m3u_name]: + m3us[m3u_name].append(item_path) # Now iterate through the m3us that we need to generate for m3u in m3us: m3u_path = normpath(os.path.join(playlist_dir, m3u)) diff --git a/docs/plugins/smartplaylist.rst b/docs/plugins/smartplaylist.rst index 0ee62eb92..05a1c8c7a 100644 --- a/docs/plugins/smartplaylist.rst +++ b/docs/plugins/smartplaylist.rst @@ -15,11 +15,11 @@ following example:: relative_to: ~/Music playlist_dir: ~/.mpd/playlists playlists: - - query: '' - name: all.m3u + - name: all.m3u + query: '' - - query: 'artist:Beatles' - name: beatles.m3u + - name: beatles.m3u + query: 'artist:Beatles' If you intend to use this plugin to generate playlists for MPD, you should set ``relative_to`` to your MPD music directory (by default, ``relative_to`` is @@ -38,8 +38,8 @@ will be overwritten when the plugin runs. For more advanced usage, you can use template syntax (see :doc:`/reference/pathformat/`) in the ``name`` field. For example:: - - query: 'year::201(0|1)' - name: 'ReleasedIn$year.m3u' + - name: 'ReleasedIn$year.m3u' + query: 'year::201(0|1)' This will query all the songs in 2010 and 2011 and generate the two playlist files `ReleasedIn2010.m3u` and `ReleasedIn2011.m3u` using those songs. @@ -47,8 +47,17 @@ files `ReleasedIn2010.m3u` and `ReleasedIn2011.m3u` using those songs. You can also gather the results of several queries by putting them in a list. (Items that match both queries are not included twice.) For example:: - - query: ['artist:beatles', 'genre:"beatles cover"'] - name: 'BeatlesUniverse.m3u' + - name: 'BeatlesUniverse.m3u' + query: ['artist:beatles', 'genre:"beatles cover"'] + +For querying albums instead of items (mainly useful with extensible fields), +use the ``album_query`` field. ``query`` and ``album_query`` can be used at the +same time. The following example gathers single items but also items belonging +to albums that have a ``for_travel`` extensible field set to 1:: + + - name: 'MyTravelPlaylist.m3u' + album_query: 'for_travel:1' + query: 'for_travel:1' By default, all playlists are regenerated after every beets command that changes the library database. To force regeneration, you can invoke it manually