]> kaliko git repositories - mpd-goodies.git/blob - bin/mlast
Add mlast
[mpd-goodies.git] / bin / mlast
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3
4 # Copyright (c) 2009,2010,2012,2019 kaliko <kaliko@azylum.org>
5 #
6 #   This program is free software: you can redistribute it and/or modify
7 #   it under the terms of the GNU General Public License as published by
8 #   the Free Software Foundation, either version 3 of the License, or
9 #   (at your option) any later version.
10 #
11 #   This program is distributed in the hope that it will be useful,
12 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #   GNU General Public License for more details.
15 #
16 #   You should have received a copy of the GNU General Public License
17 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19
20 import argparse
21 import sys
22
23 from os.path import basename
24
25 import musicpd
26
27 VERSION = '0.1'
28
29
30 def unic(li):
31     my_set = set()
32     res = []
33     for _ in li:
34         if _ not in my_set:
35             res.append(_)
36             my_set.add(_)
37     return res
38
39
40 class MLast(musicpd.MPDClient):
41     script_info = dict({
42         'prog': basename(__file__),
43         'description': 'Show last music library changes.',
44         'epilog': 'Set MPD host/port in env. var'
45     })
46
47     def __init__(self):
48         """"""
49         musicpd.MPDClient.__init__(self)
50         self.args = self._get_args()
51         self._run()
52
53     def _get_args(self):
54         """"""
55         parser = argparse.ArgumentParser(**self.__class__.script_info)
56         parser.add_argument('--version', action='version',
57                             version='v%s' % VERSION)
58         parser.add_argument('n', type=int, nargs='?', default=5,
59                             help='how many items to fetch (defaults to 5)')
60         parser.add_argument('--add', action="store_true", default=False,
61                             help='Add items found to the queue')
62         group = parser.add_mutually_exclusive_group()
63         group.add_argument('-A', '--album', action="store_true", default=False,
64                            help='Look for lastest modified artists')
65         group.add_argument('-a', '--artist', action="store_true", default=False,
66                            help='Look for lastest modified albums')
67         group.add_argument('-t', '--track', action="store_true", default=False,
68                            help='Look for lastest modified tracks')
69         args = parser.parse_args()
70         if not (args.track or args.artist or args.album):
71             args.album = True
72         if args.track or args.artist:
73             self.offset = args.n
74         if args.album:
75             self.offset = 5*args.n
76         return args
77
78     def _filter_files(self, files):
79         filtered = []
80         manda_tags = ('album', 'artist', 'title')
81         for f in files:
82             if not all(k in f for k in manda_tags):
83                 print('Missing tags for {file}'.format(**f))
84                 continue
85             filtered.append(f)
86         return filtered
87
88     def _run(self):
89         """"""
90         bucket = []
91         self.connect()
92         version = self.mpd_version
93         if version[:4] not in ['0.21', '0.22']:
94             print('MPD version might be < 0.21, need filter')
95             sys.exit(1)
96         # Total number of tracks in library
97         nb_files = int(self.stats()['songs'])
98         upper_lim = nb_files
99         for i in range(self.offset, min(30*10, nb_files), self.offset):
100             # print('%d:%d' % (nb_files-i,upper_lim))
101             files = self.search('file', '', 'sort',
102                                 'Last-Modified', 'window', (nb_files-i, upper_lim))
103             upper_lim = nb_files-i
104             # print([f.get('file') for f in files])
105             # filter files with no tags
106             files = self._filter_files(files)
107             if self.args.album:
108                 # bucket = unic(bucket + [(f.get('artist'), f.get('album')) for f in files])
109                 _ = [(f.get('artist'), f.get('album')) for f in files]
110                 bucket = unic(bucket + _)
111             elif self.args.artist:
112                 _ = [(f.get('artist'),) for f in files]
113                 bucket = unic(bucket + _)
114             elif self.args.track:
115                 _ = [(f.get('artist'), f.get('album'), f.get('title')) for f in files]
116                 # bucket = unic(bucket + _)
117                 bucket = unic(_ + bucket)
118             if len(bucket) >= self.args.n:
119                 break
120         self.disconnect()
121         self.show(bucket)
122         sys.exit(0)
123
124     def show(self, results):
125         if self.args.artist:
126             tpl = '{}'
127         elif self.args.album:
128             tpl = '{} : {}'
129         elif self.args.track:
130             tpl = '{} : {} - {}'
131         for elem in results:
132             print(tpl.format(*elem))
133
134
135 # Script starts here
136 if __name__ == '__main__':
137     try:
138         MLast()
139     except KeyboardInterrupt:
140         sys.stdout.write('exit')
141
142 # VIM MODLINE
143 # vim: ai ts=4 sw=4 sts=4 expandtab