[SCM] morituri/master: * morituri/rip/debug.py: * morituri/common/musicbrainzngs.py (added): Rewrite using python-musicbrainz-ngs. Add rip debug musicbrainzngs command for testing, seems to work on Weezer - Blue Album - disc 2

js at users.alioth.debian.org js at users.alioth.debian.org
Sun Oct 19 20:09:36 UTC 2014


The following commit has been merged in the master branch:
commit 83d212a20e8e829a1d421a79314eca89a43a6e1a
Author: Thomas Vander Stichele <thomas (at) apestaart (dot) org>
Date:   Wed Oct 19 22:37:37 2011 +0000

    	* morituri/rip/debug.py:
    	* morituri/common/musicbrainzngs.py (added):
    	  Rewrite using python-musicbrainz-ngs.
    	  Add rip debug musicbrainzngs command for testing,
    	  seems to work on Weezer - Blue Album - disc 2

diff --git a/ChangeLog b/ChangeLog
index 3a41451..2187f1c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2011-10-20  Thomas Vander Stichele  <thomas at apestaart dot org>
+
+	* morituri/rip/debug.py:
+	* morituri/common/musicbrainzngs.py (added):
+	  Rewrite using python-musicbrainz-ngs.
+	  Add rip debug musicbrainzngs command for testing,
+	  seems to work on Weezer - Blue Album - disc 2
+
 2011-10-19  Thomas Vander Stichele  <thomas at apestaart dot org>
 
 	* morituri/extern/Makefile.am:
diff --git a/morituri/common/musicbrainzngs.py b/morituri/common/musicbrainzngs.py
new file mode 100644
index 0000000..951db55
--- /dev/null
+++ b/morituri/common/musicbrainzngs.py
@@ -0,0 +1,210 @@
+# -*- Mode: Python; test-case-name: morituri.test.test_common_musicbrainzngs -*-
+# vi:si:et:sw=4:sts=4:ts=4
+
+# Morituri - for those about to RIP
+
+# Copyright (C) 2009, 2010, 2011 Thomas Vander Stichele
+
+# This file is part of morituri.
+#
+# morituri 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.
+#
+# morituri 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 morituri.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Handles communication with the musicbrainz server using NGS.
+"""
+
+import urlparse
+
+from morituri.common import log
+
+
+VA_ID = "89ad4ac3-39f7-470e-963a-56509c546377" # Various Artists
+
+class MusicBrainzException(Exception):
+    def __init__(self, exc):
+        self.args = (exc, )
+        self.exception = exc
+
+
+class TrackMetadata(object):
+    artist = None
+    title = None
+    duration = None # in ms
+    mbid = None
+    sortName = None
+    mbidArtist = None
+
+
+class DiscMetadata(object):
+    """
+    @param release: earliest release date, in YYYY-MM-DD
+    @type  release: unicode
+    """
+    artist = None
+    sortName = None
+    title = None
+    various = False
+    tracks = None
+    release = None
+
+    mbid = None
+    mbidArtist = None
+
+    def __init__(self):
+        self.tracks = []
+
+
+def _getMetadata(release, discid):
+    """
+    @type  release: L{musicbrainz2.model.Release}
+
+    @rtype: L{DiscMetadata} or None
+    """
+    log.debug('program', 'getMetadata for release id %r',
+        release['id'])
+    if not release['id']:
+        log.warning('program', 'No id for release %r', release)
+        return None
+
+    assert release['id'], 'Release does not have an id'
+
+    metadata = DiscMetadata()
+
+    if len(release['artist-credit']) > 1:
+        log.warning('musicbrainzngs', 'artist-credit more than 1: %r',
+            release['artist-credit'])
+
+    artist = release['artist-credit'][0]['artist']
+
+    # FIXME: is there a better way to check for VA
+    metadata.various = False
+    if artist['id'] == VA_ID:
+        metadata.various = True
+    isSingleArtist = not metadata.various
+
+    # getUniqueName gets disambiguating names like Muse (UK rock band)
+    metadata.artist = artist['name']
+    metadata.sortName = artist['sort-name']
+    # FIXME: is format str ?
+    metadata.release = release['date']
+
+    metadata.mbid = release['id']
+    metadata.mbidArtist = artist['id']
+    metadata.url = 'http://musicbrainz.org/release/' + release['id']
+
+    tainted = False
+    duration = 0
+
+    # only show discs from medium-list->disc-list with matching discid
+    for medium in release['medium-list']:
+        for disc in medium['disc-list']:
+            if disc['id'] == discid:
+                title = release['title']
+                if release.has_key('disambiguation'):
+                    title += " (%s)" % release['disambiguation']
+                count = len(release['medium-list'])
+                if count > 1:
+                    title += ' - Disc %d of %d' % (
+                        int(medium['position']), count)
+                if medium.has_key('title'):
+                    title += " - %s" % medium['title']
+                metadata.title = title
+                for t in medium['track-list']:
+                    track = TrackMetadata()
+
+                    if isSingleArtist or not t['recording'].has_key('artist-credit'):
+                        track.artist = metadata.artist
+                        track.sortName = metadata.sortName
+                        track.mbidArtist = metadata.mbidArtist
+                    else:
+                        # various artists discs can have tracks with no artist
+                        if len(t['recording']['artist-credit']) > 1:
+                            log.warning('musicbrainzngs', 'artist-credit more than 1: %r',
+                                t['recording']['artist-credit'])
+                        artist = t['recording']['artist-credit'][0]['artist']
+                        track.artist = artist and artist['name'] or metadata.artist.name
+                        track.sortName = artist and artist['sort-name'] or metadata.artist.sortName
+                        track.mbidArtist = artist and artist['id'] or metadata.artist.mbid
+
+                    track.title = t['recording']['title']
+                    track.mbid = t['recording']['id']
+
+                    # FIXME: unit of duration ?
+                    track.duration = int(t['recording']['length'])
+                    if not track.duration:
+                        log.warning('getMetadata',
+                            'track %r (%r) does not have duration' % (
+                                track.title, track.mbid))
+                        tainted = True
+                    else:
+                        duration += track.duration
+
+                    metadata.tracks.append(track)
+
+                if not tainted:
+                    metadata.duration = duration
+                else:
+                    metadata.duration = 0
+
+    return metadata
+
+
+# see http://bugs.musicbrainz.org/browser/python-musicbrainz2/trunk/examples/ripper.py
+def musicbrainz(discid):
+    """
+    Based on a MusicBrainz disc id, get a list of DiscMetadata objects
+    for the given disc id.
+
+    Example disc id: Mj48G109whzEmAbPBoGvd4KyCS4-
+
+    @type  discid: str
+
+    @rtype: list of L{DiscMetadata}
+    """
+    log.debug('musicbrainz', 'looking up results for discid %r', discid)
+    from morituri.extern.musicbrainzngs import musicbrainz
+
+    results = []
+
+    result = musicbrainz.get_releases_by_discid(discid,
+        includes=["artists", "recordings", "release-groups"])
+
+    # No disc matching this DiscID has been found.
+    if len(result) == 0:
+        return None
+
+    log.debug('musicbrainz', 'found %d releases for discid %r',
+        len(result['disc']['release-list']),
+        discid)
+
+    # Display the returned results to the user.
+    ret = []
+
+    for release in result['disc']['release-list']:
+        log.debug('program', 'result %r: artist %r, title %r' % (
+            release, release['artist-credit-phrase'], release['title']))
+
+        # to get titles of recordings, we need to query the release with
+        # artist-credits
+
+        res = musicbrainz.get_release_by_id(release['id'],
+            includes=["artists", "artist-credits", "recordings", "discids"])
+        release = res['release']
+
+        md = _getMetadata(release, discid)
+        if md:
+            log.debug('program', 'duration %r', md.duration)
+            ret.append(md)
+
+    return ret
diff --git a/morituri/rip/debug.py b/morituri/rip/debug.py
index e64572a..3225003 100644
--- a/morituri/rip/debug.py
+++ b/morituri/rip/debug.py
@@ -108,7 +108,33 @@ class MusicBrainz(logcommand.LogCommand):
                 self.stdout.write('      Track %2d: %r - %r\n' % (
                     j + 1, track.artist, track.title))
 
+class MusicBrainzNGS(logcommand.LogCommand):
+
+    summary = "examine MusicBrainz NGS info"
+
+
+    def do(self, args):
+        try:
+            discId = unicode(args[0])
+        except IndexError:
+            self.stdout.write('Please specify a MusicBrainz disc id.\n')
+            return 3
+
+        from morituri.common import musicbrainzngs
+        metadatas = musicbrainzngs.musicbrainz(discId)
+
+        self.stdout.write('%d releases\n' % len(metadatas))
+        for i, md in enumerate(metadatas):
+            self.stdout.write('- Release %d:\n' % (i + 1, ))
+            self.stdout.write('    Artist: %r\n' % md.artist)
+            self.stdout.write('    Title:  %r\n' % md.title)
+            self.stdout.write('    URL: %r\n' % md.url)
+            self.stdout.write('    Tracks: %r\n' % len(md.tracks))
+            for j, track in enumerate(md.tracks):
+                self.stdout.write('      Track %2d: %r - %r\n' % (
+                    j + 1, track.artist, track.title))
+
 class Debug(logcommand.LogCommand):
     summary = "debug internals"
 
-    subCommandClasses = [Checksum, Encode, MusicBrainz, ]
+    subCommandClasses = [Checksum, Encode, MusicBrainz, MusicBrainzNGS]

-- 
morituri packaging



More information about the pkg-multimedia-commits mailing list