From dc5640157f0a108bfe671b7652241460dfd0b78e Mon Sep 17 00:00:00 2001 From: kaliko Date: Thu, 16 May 2019 18:41:39 +0200 Subject: [PATCH] Add mlast --- README.md | 4 +- bin/mlast | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 2 deletions(-) create mode 100755 bin/mlast diff --git a/README.md b/README.md index 43aa84d..6be0ecf 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # MPD-GOODIES -A collection of small commands to play with MusicPlayerDaemon: +A collection of small commands to play with [MusicPlayerDaemon]: * Fading in/out over a specified time * Jumping to next album en queue. - * Last modified artist/album + * Last modified artist/album/tracks * Crop the queue [MusicPlayerDaemon]: https://www.musicpd.org/ diff --git a/bin/mlast b/bin/mlast new file mode 100755 index 0000000..b664aeb --- /dev/null +++ b/bin/mlast @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Copyright (c) 2009,2010,2012,2019 kaliko +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import argparse +import sys + +from os.path import basename + +import musicpd + +VERSION = '0.1' + + +def unic(li): + my_set = set() + res = [] + for _ in li: + if _ not in my_set: + res.append(_) + my_set.add(_) + return res + + +class MLast(musicpd.MPDClient): + script_info = dict({ + 'prog': basename(__file__), + 'description': 'Show last music library changes.', + 'epilog': 'Set MPD host/port in env. var' + }) + + def __init__(self): + """""" + musicpd.MPDClient.__init__(self) + self.args = self._get_args() + self._run() + + def _get_args(self): + """""" + parser = argparse.ArgumentParser(**self.__class__.script_info) + parser.add_argument('--version', action='version', + version='v%s' % VERSION) + parser.add_argument('n', type=int, nargs='?', default=5, + help='how many items to fetch (defaults to 5)') + parser.add_argument('--add', action="store_true", default=False, + help='Add items found to the queue') + group = parser.add_mutually_exclusive_group() + group.add_argument('-A', '--album', action="store_true", default=False, + help='Look for lastest modified artists') + group.add_argument('-a', '--artist', action="store_true", default=False, + help='Look for lastest modified albums') + group.add_argument('-t', '--track', action="store_true", default=False, + help='Look for lastest modified tracks') + args = parser.parse_args() + if not (args.track or args.artist or args.album): + args.album = True + if args.track or args.artist: + self.offset = args.n + if args.album: + self.offset = 5*args.n + return args + + def _filter_files(self, files): + filtered = [] + manda_tags = ('album', 'artist', 'title') + for f in files: + if not all(k in f for k in manda_tags): + print('Missing tags for {file}'.format(**f)) + continue + filtered.append(f) + return filtered + + def _run(self): + """""" + bucket = [] + self.connect() + version = self.mpd_version + if version[:4] not in ['0.21', '0.22']: + print('MPD version might be < 0.21, need filter') + sys.exit(1) + # Total number of tracks in library + nb_files = int(self.stats()['songs']) + upper_lim = nb_files + for i in range(self.offset, min(30*10, nb_files), self.offset): + # print('%d:%d' % (nb_files-i,upper_lim)) + files = self.search('file', '', 'sort', + 'Last-Modified', 'window', (nb_files-i, upper_lim)) + upper_lim = nb_files-i + # print([f.get('file') for f in files]) + # filter files with no tags + files = self._filter_files(files) + if self.args.album: + # bucket = unic(bucket + [(f.get('artist'), f.get('album')) for f in files]) + _ = [(f.get('artist'), f.get('album')) for f in files] + bucket = unic(bucket + _) + elif self.args.artist: + _ = [(f.get('artist'),) for f in files] + bucket = unic(bucket + _) + elif self.args.track: + _ = [(f.get('artist'), f.get('album'), f.get('title')) for f in files] + # bucket = unic(bucket + _) + bucket = unic(_ + bucket) + if len(bucket) >= self.args.n: + break + self.disconnect() + self.show(bucket) + sys.exit(0) + + def show(self, results): + if self.args.artist: + tpl = '{}' + elif self.args.album: + tpl = '{} : {}' + elif self.args.track: + tpl = '{} : {} - {}' + for elem in results: + print(tpl.format(*elem)) + + +# Script starts here +if __name__ == '__main__': + try: + MLast() + except KeyboardInterrupt: + sys.stdout.write('exit') + +# VIM MODLINE +# vim: ai ts=4 sw=4 sts=4 expandtab -- 2.39.2