2 # -*- coding: utf-8 -*-
4 # Copyright (c) 2010-2015 Jack Kaliko <kaliko@azylum.org>
6 # This file is part of MPD_sima
8 # MPD_sima is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
13 # MPD_sima is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with MPD_sima. If not, see <http://www.gnu.org/licenses/>.
26 from argparse import (ArgumentParser, SUPPRESS)
27 from difflib import get_close_matches
28 from locale import getpreferredencoding
29 from os import (environ, chmod, makedirs)
30 from os.path import (join, isdir, isfile, expanduser)
31 from sys import (exit, stdout, stderr)
33 from sima.lib.track import Track
34 from sima.utils import utils
35 from sima.lib import simadb
36 from musicpd import MPDClient, MPDError
40 simadb_cli helps you to edit entries in your own DB of similarity
45 # pop out 'sw' value before creating ArgumentParser object.
48 'sw':['-d', '--dbfile'],
51 'action': utils.Wfile,
52 'help': 'File to read/write database from/to'},
54 'sw': ['-S', '--host'],
58 'help': 'MPD host, as IP or FQDN (default: localhost|MPD_HOST).'},
60 'sw': ['-P', '--port'],
64 'help': 'Port MPD in listening on (default: 6600|MPD_PORT).'},
73 'action': 'store_true',
75 'help': 'View black list.'},
77 'sw': ['--remove_bl'],
79 'help': 'Suppress a black list entry, by row id. Use --view_bl to get row id.'},
83 'metavar': 'ARTIST_NAME',
84 'help': 'Black list artist.'},
86 'sw': ['--bl_curr_art'],
87 'action': 'store_true',
88 'help': 'Black list currently playing artist.'},
90 'sw': ['--bl_curr_alb'],
91 'action': 'store_true',
92 'help': 'Black list currently playing album.'},
94 'sw': ['--bl_curr_trk'],
95 'action': 'store_true',
96 'help': 'Black list currently playing track.'},
98 'sw':['--purge_hist'],
99 'action': 'store_true',
100 'dest': 'do_purge_hist',
101 'help': 'Purge play history.'}])
104 class SimaDB_CLI(object):
105 """Command line management.
109 self.dbfile = self._get_default_dbfile()
111 self.options = dict({})
112 self.localencoding = 'UTF-8'
116 def _get_encoding(self):
117 """Get local encoding"""
118 localencoding = getpreferredencoding()
120 self.localencoding = localencoding
122 def _get_mpd_env_var(self):
124 MPD host/port environement variables are used if command line does not
125 provide host|port|passwd.
127 host, port, passwd = utils.get_mpd_environ()
128 if self.options.passwd is None and passwd:
129 self.options.passwd = passwd
130 if self.options.mpdhost is None:
132 self.options.mpdhost = host
134 self.options.mpdhost = 'localhost'
135 if self.options.mpdport is None:
137 self.options.mpdport = port
139 self.options.mpdport = 6600
141 def _declare_opts(self):
143 Declare options in ArgumentParser object.
145 self.parser = ArgumentParser(description=DESCRIPTION,
146 usage='%(prog)s [-h|--help] [options]',
148 epilog='Happy Listening',
151 self.parser.add_argument('--version', action='version',
152 version='%(prog)s {0}'.format(__version__))
153 # Add all options declare in OPTS
155 opt_names = opt.pop('sw')
156 self.parser.add_argument(*opt_names, **opt)
158 def _get_default_dbfile(self):
160 Use XDG directory standard if exists
161 else use "HOME/.local/share/mpd_sima/"
162 http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
164 homedir = expanduser('~')
166 if environ.get('XDG_DATA_HOME'):
167 data_dir = join(environ.get('XDG_DATA_HOME'), dirname)
169 data_dir = join(homedir, '.local', 'share', dirname)
170 if not isdir(data_dir):
172 chmod(data_dir, 0o700)
173 return join(data_dir, DB_NAME)
175 def _get_mpd_client(self):
177 host = self.options.mpdhost
178 port = self.options.mpdport
179 passwd = self.options.passwd
182 cli.connect(host, port)
185 except MPDError as err:
186 mess = 'ERROR: fail to connect MPD on %s:%s %s' % (
188 print(mess, file=stderr)
192 def _create_db(self):
193 """Create database if necessary"""
194 if isfile(self.dbfile):
196 print('Creating database!')
197 open(self.dbfile, 'a').close()
198 simadb.SimaDB(db_path=self.dbfile).create_db()
200 def _get_art_from_db(self, art):
201 """Return (id, name, self...) from DB or None is not in DB"""
202 db = simadb.SimaDB(db_path=self.dbfile)
203 art_db = db.get_artist(art, add_not=True)
205 print('ERROR: "%s" not in data base!' % art, file=stderr)
210 """Black list artist"""
211 mpd_cli = self._get_mpd_client()
212 artists_list = mpd_cli.list('artist')
213 # Unicode cli given artist name
214 cli_artist_to_bl = self.options.bl_art
215 if cli_artist_to_bl not in artists_list:
216 print('Artist not found in MPD library.')
217 match = get_close_matches(cli_artist_to_bl, artists_list, 50, 0.78)
219 print('You may be refering to %s' %
220 '/'.join([m_a for m_a in match]))
222 print('Black listing artist: %s' % cli_artist_to_bl)
223 db = simadb.SimaDB(db_path=self.dbfile)
224 db.get_bl_artist(cli_artist_to_bl)
226 def bl_current_artist(self):
227 """Black list current artist"""
228 mpd_cli = self._get_mpd_client()
229 artist = mpd_cli.currentsong().get('artist', '')
231 print('No artist found.')
233 print('Black listing artist: %s' % artist)
234 db = simadb.SimaDB(db_path=self.dbfile)
235 db.get_bl_artist(artist)
237 def bl_current_album(self):
238 """Black list current artist"""
239 mpd_cli = self._get_mpd_client()
240 track = Track(**mpd_cli.currentsong())
242 print('No album set for this track: %s' % track)
244 print('Black listing album: {0}'.format(track.album))
245 db = simadb.SimaDB(db_path=self.dbfile)
246 db.get_bl_album(track)
248 def bl_current_track(self):
249 """Black list current artist"""
250 mpd_cli = self._get_mpd_client()
251 track = Track(**mpd_cli.currentsong())
252 print('Black listing track: %s' % track)
253 db = simadb.SimaDB(db_path=self.dbfile)
254 db.get_bl_track(track)
256 def purge_history(self):
257 """Purge all entries in history"""
258 db = simadb.SimaDB(db_path=self.dbfile)
259 print('Purging history...')
260 db.purge_history(duration=int(0))
262 print('Cleaning database...')
267 """Print out black list."""
268 # TODO: enhance output formating
269 db = simadb.SimaDB(db_path=self.dbfile)
270 for bl_e in db.get_black_list():
271 print('\t# '.join([str(e) for e in bl_e]))
273 def remove_black_list_entry(self):
275 db = simadb.SimaDB(db_path=self.dbfile)
276 db._remove_bl(int(self.options.remove_bl))
280 Parse command line and run actions.
283 self.options = self.parser.parse_args()
284 self._get_mpd_env_var()
285 if self.options.dbfile:
286 self.dbfile = self.options.dbfile
287 print('Using db file: %s' % self.dbfile)
288 if self.options.bl_art:
291 if self.options.bl_curr_art:
292 self.bl_current_artist()
294 if self.options.bl_curr_alb:
295 self.bl_current_album()
297 if self.options.bl_curr_trk:
298 self.bl_current_track()
300 if self.options.view_bl:
303 if self.options.remove_bl:
304 self.remove_black_list_entry()
306 if self.options.do_purge_hist:
312 if __name__ == '__main__':
315 except Exception as err:
320 # vim: ai ts=4 sw=4 sts=4 expandtab