-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2010-2015 Jack Kaliko <kaliko@azylum.org>
-#
-# This file is part of MPD_sima
-#
-# MPD_sima 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.
-#
-# MPD_sima 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 MPD_sima. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-
-__version__ = '0.4.1'
-
-# IMPORT#
-from argparse import (ArgumentParser, SUPPRESS)
-from difflib import get_close_matches
-from locale import getpreferredencoding
-from os import (environ, chmod, makedirs)
-from os.path import (join, isdir, isfile, expanduser)
-from sys import (exit, stdout, stderr)
-
-from sima.lib.track import Track
-from sima.utils import utils
-from sima.lib import simadb
-from musicpd import MPDClient, MPDError
-
-
-DESCRIPTION = """
-simadb_cli helps you to edit entries in your own DB of similarity
-between artists."""
-DB_NAME = 'sima.db'
-
-# Options list
-# pop out 'sw' value before creating ArgumentParser object.
-OPTS = list([
- {
- 'sw':['-d', '--dbfile'],
- 'type': str,
- 'dest':'dbfile',
- 'action': utils.Wfile,
- 'help': 'File to read/write database from/to'},
- {
- 'sw': ['-S', '--host'],
- 'type': str,
- 'dest': 'mpdhost',
- 'default': None,
- 'help': 'MPD host, as IP or FQDN (default: localhost|MPD_HOST).'},
- {
- 'sw': ['-P', '--port'],
- 'type': int,
- 'dest': 'mpdport',
- 'default': None,
- 'help': 'Port MPD in listening on (default: 6600|MPD_PORT).'},
- {
- 'sw': ['--password'],
- 'type': str,
- 'dest': 'passwd',
- 'default': None,
- 'help': SUPPRESS},
- {
- 'sw': ['--view_bl'],
- 'action': 'store_true',
- 'dest': 'view_bl',
- 'help': 'View black list.'},
- {
- 'sw': ['--remove_bl'],
- 'type': int,
- 'help': 'Suppress a black list entry, by row id. Use --view_bl to get row id.'},
- {
- 'sw': ['--bl_art'],
- 'type': str,
- 'metavar': 'ARTIST_NAME',
- 'help': 'Black list artist.'},
- {
- 'sw': ['--bl_curr_art'],
- 'action': 'store_true',
- 'help': 'Black list currently playing artist.'},
- {
- 'sw': ['--bl_curr_alb'],
- 'action': 'store_true',
- 'help': 'Black list currently playing album.'},
- {
- 'sw': ['--bl_curr_trk'],
- 'action': 'store_true',
- 'help': 'Black list currently playing track.'},
- {
- 'sw':['--purge_hist'],
- 'action': 'store_true',
- 'dest': 'do_purge_hist',
- 'help': 'Purge play history.'}])
-
-
-class SimaDB_CLI(object):
- """Command line management.
- """
-
- def __init__(self):
- self.dbfile = self._get_default_dbfile()
- self.parser = None
- self.options = dict({})
- self.localencoding = 'UTF-8'
- self._get_encoding()
- self.main()
-
- def _get_encoding(self):
- """Get local encoding"""
- localencoding = getpreferredencoding()
- if localencoding:
- self.localencoding = localencoding
-
- def _get_mpd_env_var(self):
- """
- MPD host/port environement variables are used if command line does not
- provide host|port|passwd.
- """
- host, port, passwd = utils.get_mpd_environ()
- if self.options.passwd is None and passwd:
- self.options.passwd = passwd
- if self.options.mpdhost is None:
- if host:
- self.options.mpdhost = host
- else:
- self.options.mpdhost = 'localhost'
- if self.options.mpdport is None:
- if port:
- self.options.mpdport = port
- else:
- self.options.mpdport = 6600
-
- def _declare_opts(self):
- """
- Declare options in ArgumentParser object.
- """
- self.parser = ArgumentParser(description=DESCRIPTION,
- usage='%(prog)s [-h|--help] [options]',
- prog='simadb_cli',
- epilog='Happy Listening',
- )
-
- self.parser.add_argument('--version', action='version',
- version='%(prog)s {0}'.format(__version__))
- # Add all options declare in OPTS
- for opt in OPTS:
- opt_names = opt.pop('sw')
- self.parser.add_argument(*opt_names, **opt)
-
- def _get_default_dbfile(self):
- """
- Use XDG directory standard if exists
- else use "HOME/.local/share/mpd_sima/"
- http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
- """
- homedir = expanduser('~')
- dirname = 'mpd_sima'
- if environ.get('XDG_DATA_HOME'):
- data_dir = join(environ.get('XDG_DATA_HOME'), dirname)
- else:
- data_dir = join(homedir, '.local', 'share', dirname)
- if not isdir(data_dir):
- makedirs(data_dir)
- chmod(data_dir, 0o700)
- return join(data_dir, DB_NAME)
-
- def _get_mpd_client(self):
- """"""
- host = self.options.mpdhost
- port = self.options.mpdport
- passwd = self.options.passwd
- cli = MPDClient()
- try:
- cli.connect(host, port)
- if passwd:
- cli.password(passwd)
- except MPDError as err:
- mess = 'ERROR: fail to connect MPD on %s:%s %s' % (
- host, port, err)
- print(mess, file=stderr)
- exit(1)
- return cli
-
- def _create_db(self):
- """Create database if necessary"""
- if isfile(self.dbfile):
- return
- print('Creating database!')
- open(self.dbfile, 'a').close()
- simadb.SimaDB(db_path=self.dbfile).create_db()
-
- def _get_art_from_db(self, art):
- """Return (id, name, self...) from DB or None is not in DB"""
- db = simadb.SimaDB(db_path=self.dbfile)
- art_db = db.get_artist(art, add_not=True)
- if not art_db:
- print('ERROR: "%s" not in data base!' % art, file=stderr)
- return None
- return art_db
-
- def bl_artist(self):
- """Black list artist"""
- mpd_cli = self._get_mpd_client()
- artists_list = mpd_cli.list('artist')
- # Unicode cli given artist name
- cli_artist_to_bl = self.options.bl_art
- if cli_artist_to_bl not in artists_list:
- print('Artist not found in MPD library.')
- match = get_close_matches(cli_artist_to_bl, artists_list, 50, 0.78)
- if match:
- print('You may be refering to %s' %
- '/'.join([m_a for m_a in match]))
- return False
- print('Black listing artist: %s' % cli_artist_to_bl)
- db = simadb.SimaDB(db_path=self.dbfile)
- db.get_bl_artist(cli_artist_to_bl)
-
- def bl_current_artist(self):
- """Black list current artist"""
- mpd_cli = self._get_mpd_client()
- artist = mpd_cli.currentsong().get('artist', '')
- if not artist:
- print('No artist found.')
- return False
- print('Black listing artist: %s' % artist)
- db = simadb.SimaDB(db_path=self.dbfile)
- db.get_bl_artist(artist)
-
- def bl_current_album(self):
- """Black list current artist"""
- mpd_cli = self._get_mpd_client()
- track = Track(**mpd_cli.currentsong())
- if not track.album:
- print('No album set for this track: %s' % track)
- return False
- print('Black listing album: {0}'.format(track.album))
- db = simadb.SimaDB(db_path=self.dbfile)
- db.get_bl_album(track)
-
- def bl_current_track(self):
- """Black list current artist"""
- mpd_cli = self._get_mpd_client()
- track = Track(**mpd_cli.currentsong())
- print('Black listing track: %s' % track)
- db = simadb.SimaDB(db_path=self.dbfile)
- db.get_bl_track(track)
-
- def purge_history(self):
- """Purge all entries in history"""
- db = simadb.SimaDB(db_path=self.dbfile)
- print('Purging history...')
- db.purge_history(duration=int(0))
- print('done.')
- print('Cleaning database...')
- db.clean_database()
- print('done.')
-
- def view_bl(self):
- """Print out black list."""
- # TODO: enhance output formating
- db = simadb.SimaDB(db_path=self.dbfile)
- for bl_e in db.get_black_list():
- print('\t# '.join([str(e) for e in bl_e]))
-
- def remove_black_list_entry(self):
- """"""
- db = simadb.SimaDB(db_path=self.dbfile)
- db._remove_bl(int(self.options.remove_bl))
-
- def main(self):
- """
- Parse command line and run actions.
- """
- self._declare_opts()
- self.options = self.parser.parse_args()
- self._get_mpd_env_var()
- if self.options.dbfile:
- self.dbfile = self.options.dbfile
- print('Using db file: %s' % self.dbfile)
- if self.options.bl_art:
- self.bl_artist()
- return
- if self.options.bl_curr_art:
- self.bl_current_artist()
- return
- if self.options.bl_curr_alb:
- self.bl_current_album()
- return
- if self.options.bl_curr_trk:
- self.bl_current_track()
- return
- if self.options.view_bl:
- self.view_bl()
- return
- if self.options.remove_bl:
- self.remove_black_list_entry()
- return
- if self.options.do_purge_hist:
- self.purge_history()
- exit(0)
-
-
-# Script starts here
-if __name__ == '__main__':
- try:
- SimaDB_CLI()
- except Exception as err:
- print(err)
- exit(1)
-
-# VIM MODLINE
-# vim: ai ts=4 sw=4 sts=4 expandtab