From ace038170d81f7e330b7b8067c3e1cdce0de7c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Sun, 5 Mar 2017 13:25:38 +0100 Subject: [PATCH 1/2] project: drop dependency to python-cddb --- .travis.yml | 2 +- README.md | 1 - whipper/command/cd.py | 12 ++- whipper/common/program.py | 23 ----- whipper/common/simplefreedb.py | 148 +++++++++++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 28 deletions(-) create mode 100755 whipper/common/simplefreedb.py diff --git a/.travis.yml b/.travis.yml index befcb768..152a1fb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ install: # Dependencies - sudo apt-get -qq update - sudo pip install --upgrade -qq pip - - sudo apt-get -qq install cdparanoia cdrdao flac libcdio-dev libiso9660-dev libsndfile1-dev python-cddb python-gobject python-musicbrainzngs python-mutagen python-setuptools sox swig + - sudo apt-get -qq install cdparanoia cdrdao flac libcdio-dev libiso9660-dev libsndfile1-dev python-gobject python-musicbrainzngs python-mutagen python-setuptools sox swig - sudo pip install pycdio requests # Testing dependencies diff --git a/README.md b/README.md index 8c7db111..95d4486f 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,6 @@ Whipper relies on the following packages in order to run correctly and provide a - [python-musicbrainzngs](https://github.com/alastair/python-musicbrainzngs), for metadata lookup - [python-mutagen](https://pypi.python.org/pypi/mutagen), for tagging support - [python-setuptools](https://pypi.python.org/pypi/setuptools), for installation, plugins support -- [python-cddb](http://cddb-py.sourceforge.net/), for showing but not using metadata if disc not available in the MusicBrainz DB - [pycdio](https://pypi.python.org/pypi/pycdio/) (to avoid bugs please use `pycdio` **0.20** & `libcdio` >= **0.90** or, with previous `libcdio` versions, `pycdio` **0.17**), for drive identification - Required for drive offset and caching behavior to be stored in the configuration file - [requests](https://pypi.python.org/pypi/requests) for retrieving AccurateRip database entries diff --git a/whipper/command/cd.py b/whipper/command/cd.py index d7b11ec8..4edfc31a 100644 --- a/whipper/command/cd.py +++ b/whipper/command/cd.py @@ -27,7 +27,7 @@ import gobject from whipper.command.basecommand import BaseCommand from whipper.common import ( - accurip, config, drive, program, task + accurip, config, drive, program, task, simplefreedb ) from whipper.program import cdrdao, cdparanoia, utils from whipper.result import result @@ -126,8 +126,14 @@ def do(self): if not self.program.metadata: # fall back to FreeDB for lookup cddbid = self.ittoc.getCDDBValues() - cddbmd = self.program.getCDDB(cddbid) - if cddbmd: + + sfdb = simplefreedb.SimpleFreeDB() + discid, ntrks = cddbid[0], cddbid[1] + offsets, nsecs = cddbid[2:-1], cddbid[-1] + matches = sfdb.query(discid, ntrks, offsets, nsecs) + if matches: + match = matches[0] + cddbmd = match['artist_title'] sys.stdout.write('FreeDB identifies disc as %s\n' % cddbmd) # also used by rip cd info diff --git a/whipper/common/program.py b/whipper/common/program.py index 1537229f..9ba3d4c2 100644 --- a/whipper/common/program.py +++ b/whipper/common/program.py @@ -248,29 +248,6 @@ def getPath(self, outdir, template, mbdiscid, metadata, track_number=None): template = re.sub(r'%(\w)', r'%(\1)s', template) return os.path.join(outdir, template % v) - def getCDDB(self, cddbdiscid): - """ - @param cddbdiscid: list of id, tracks, offsets, seconds - - @rtype: str - """ - # FIXME: convert to nonblocking? - import CDDB - try: - code, md = CDDB.query(cddbdiscid) - logger.debug('CDDB query result: %r, %r', code, md) - if code == 200: - return md['title'] - - except IOError, e: - # FIXME: for some reason errno is a str ? - if e.errno == 'socket error': - self._stdout.write("Warning: network error: %r\n" % (e, )) - else: - raise - - return None - def getMusicBrainz(self, ittoc, mbdiscid, release=None, country=None, prompt=False): """ diff --git a/whipper/common/simplefreedb.py b/whipper/common/simplefreedb.py new file mode 100755 index 00000000..a703d5fe --- /dev/null +++ b/whipper/common/simplefreedb.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 + +# Copyright (C) 2017 Clément Bœsch + +# This file is part of whipper. +# +# whipper 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. +# +# whipper 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 whipper. If not, see . + +import re +import socket +import getpass +import urllib +import whipper + + +class SimpleFreeDB: + + URL = 'http://freedb.freedb.org/~cddb/cddb.cgi' + PROTO = 6 + + def __init__(self): + user = getpass.getuser() + host = socket.gethostname() + client = 'whipper' + hello = '%s %s %s %s' % (user, host, client, whipper.__version__) + self._hello = urllib.quote_plus(hello) + self._slash_split_regex = re.compile(r'(? Date: Sun, 5 Mar 2017 13:26:10 +0100 Subject: [PATCH 2/2] cd: add --allow-freedb option --- whipper/command/cd.py | 18 +++++++++++++++++- whipper/common/program.py | 24 +++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/whipper/command/cd.py b/whipper/command/cd.py index 4edfc31a..92c279c5 100644 --- a/whipper/command/cd.py +++ b/whipper/command/cd.py @@ -132,10 +132,21 @@ def do(self): offsets, nsecs = cddbid[2:-1], cddbid[-1] matches = sfdb.query(discid, ntrks, offsets, nsecs) if matches: - match = matches[0] + match = matches[0] # TODO: honor --prompt cddbmd = match['artist_title'] sys.stdout.write('FreeDB identifies disc as %s\n' % cddbmd) + if self.options.allow_freedb: + logger.warning('Using FreeDB metadata, which is not ' + 'recommended due to its very low quality ' + 'standards.') + logger.warning('You are strongly encouraged to submit CD ' + 'information to the MusicBrainz database.') + fdb_data = sfdb.read(match['category'], match['discid']) + self.program.metadata = \ + self.program.craftMusicBrainzFromFreeDB(fdb_data) + + if not self.program.metadata: # also used by rip cd info if not getattr(self.options, 'unknown', False): logger.critical("unable to retrieve disc metadata, " @@ -288,6 +299,11 @@ def add_arguments(self): action="store_true", dest="unknown", help="whether to continue ripping if " "the CD is unknown", default=False) + self.parser.add_argument('--allow-freedb', + action="store_true", dest="allow_freedb", + help="whether to allow relying on low " + "quality CDDB/FreeDB metadata if nothing " + "else is available", default=False) self.parser.add_argument('--cdr', action="store_true", dest="cdr", help="whether to continue ripping if " diff --git a/whipper/common/program.py b/whipper/common/program.py index 9ba3d4c2..a126cd21 100644 --- a/whipper/common/program.py +++ b/whipper/common/program.py @@ -248,6 +248,26 @@ def getPath(self, outdir, template, mbdiscid, metadata, track_number=None): template = re.sub(r'%(\w)', r'%(\1)s', template) return os.path.join(outdir, template % v) + def craftMusicBrainzFromFreeDB(self, freedb_data): + """ + Create MusicBrainz-sytle metadata from a FreeDB entry. + """ + disc = mbngs.DiscMetadata() + + disc.artist = disc.sortName = freedb_data.get('artist') + disc.release = str(freedb_data.get('year', '0000')) + disc.title = disc.releaseTitle = freedb_data.get('title') + + tracks = [] + for track_title in freedb_data.get('tracks', []): + track = mbngs.TrackMetadata() + track.artist = track.sortName = disc.artist + track.title = track_title + tracks.append(track) + disc.tracks = tracks + + return disc + def getMusicBrainz(self, ittoc, mbdiscid, release=None, country=None, prompt=False): """ @@ -432,7 +452,9 @@ def getTagList(self, number): if self.metadata.release is not None: tags['DATE'] = self.metadata.release - if number > 0: + has_mbinfo = (mbidTrack and mbidTrackArtist and mbidAlbum + and mbidTrackAlbum and mbDiscId) + if number > 0 and has_mbinfo: tags['MUSICBRAINZ_TRACKID'] = mbidTrack tags['MUSICBRAINZ_ARTISTID'] = mbidTrackArtist tags['MUSICBRAINZ_ALBUMID'] = mbidAlbum