Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: MusikPolice/musik
base: 251bbcf7ac
...
head fork: MusikPolice/musik
compare: eb06996896
  • 7 commits
  • 3 files changed
  • 0 commit comments
  • 1 contributor
Commits on Sep 30, 2012
@MusikPolice improved on the debug logging that jbillo added to the importer class 18b6506
@MusikPolice added physical disc searches to importer 7b188c7
@MusikPolice Modified importer to allow for pre-existing tracks to have their meta…
…data updated.
70c2539
@MusikPolice Added support for ASIN and Author metadata tags. Added import for sql…
…alchemy.exc.OperationalError to importer.
d4622b5
@MusikPolice Added support for the remaining EasyID3 metadata tags 8e9ec78
@MusikPolice Added support for playcounts and ratings to the importer f7558ca
Commits on Oct 01, 2012
@MusikPolice Importing now works!
* Added a foreign key from Album to Artist
* Disc number is a string, expressed as <track>/<total_tracks>
* Track objects need to be added to the database when they are being created
* Changed the way that discs are added to albums
* Limited some id3 frames from being processed, as they cause problems - need a better solution for this later.
eb06996
Showing with 359 additions and 62 deletions.
  1. +2 −2 musik.py
  2. +21 −14 musik/db.py
  3. +336 −46 musik/library/importer.py
View
4 musik.py
@@ -35,7 +35,7 @@ def cleanup(signum=None, frame=None):
# application entry - starts the database connection and dev server
if __name__ == '__main__':
global log, importThread, app
-
+
threads = []
# get logging set up
@@ -47,7 +47,7 @@ def cleanup(signum=None, frame=None):
except IOError:
print u"Could not create log directory %s" % log_dir
sys.exit(1)
-
+
log = initLogging(__name__)
# TODO: also register for CherryPy shutdown messages
View
35 musik/db.py
@@ -77,17 +77,21 @@ class Album(Base):
collection of related songs that may or may not have a physical representation.
"""
__tablename__ = 'albums'
- id = Column(Integer, primary_key=True) # unique id
- title = Column(String) # the title of the album
- title_sort = Column(String) # sortable title of the album
- barcode = Column(String) # physical album barcode
- compilation = Column(Boolean) # whether or not this album is a compilation
- media_type = Column(String) # the type of media (CD, etc)
- musicbrainz_albumid = Column(String) # unique 36-digit musicbrainz hex string
- musicbrainz_albumstatus = Column(String)# unique 36-digit musicbrainz hex string
- musicbrainz_albumtype = Column(String) # unique 36-digit musicbrainz hex string
- organization = Column(String) # organization that released the album (usually a record company)
- releasecountry = Column(String) # the country that this album was released in
+ id = Column(Integer, primary_key=True) # unique id
+ title = Column(String) # the title of the album
+ title_sort = Column(String) # sortable title of the album
+ artist_id = Column(Integer, ForeignKey('artists.id')) # the artist that recorded this album
+ asin = Column(String) # amazon standard identification number - only if physical
+ barcode = Column(String) # physical album barcode
+ compilation = Column(Boolean) # whether or not this album is a compilation
+ media_type = Column(String) # the type of media (CD, etc)
+ musicbrainz_albumid = Column(String) # unique 36-digit musicbrainz hex string
+ musicbrainz_albumstatus = Column(String) # unique 36-digit musicbrainz hex string
+ musicbrainz_albumtype = Column(String) # unique 36-digit musicbrainz hex string
+ organization = Column(String) # organization that released the album (usually a record company)
+ releasecountry = Column(String) # the country that this album was released in
+
+ artist = relationship('Artist', backref=backref('albums', order_by=id))
def __init__(self, title):
Base.__init__(self)
@@ -117,19 +121,19 @@ class Disc(Base):
# columns
id = Column(Integer, primary_key=True) # unique id
album_id = Column(Integer, ForeignKey('albums.id')) # the album that this disc belongs to
- discnumber = Column(Integer) # the play order of this disc in the collection
+ discnumber = Column(String) # the play order of this disc in the collection
disc_subtitle = Column(String) # the subtitle (if applicable) of this disc
musicbrainz_discid = Column(String) # unique 36-digit musicbrainz hex string
# relationships
- album = relationship('Album', backref=backref('discs', order_by=discnumber))
+ album = relationship('Album', backref=backref('discs', order_by=discnumber, lazy='dynamic'))
def __init__(self, discnumber):
Base.__init__(self)
self.discnumber = discnumber
def __unicode__(self):
- return u'<Disc(album_id=%i, discnumber=%i)>' % (self.album_id, self.discnumber)
+ return u'<Disc(album=%s, discnumber=%s)>' % (self.album, self.discnumber)
def __str__(self):
return unicode(self).encode('utf-8')
@@ -149,6 +153,7 @@ class Track(Base):
album_id = Column(Integer, ForeignKey('albums.id')) # the album that contains the track
album_artist_id = Column(Integer, ForeignKey('artists.id')) # the artist that released the album
arranger_id = Column(Integer, ForeignKey('artists.id')) # the artist that arranged the track
+ author_id = Column(Integer, ForeignKey('artists.id')) # the author that wrote the track
bpm = Column(Integer) # beats per minute
composer_id = Column(Integer, ForeignKey('artists.id')) # the artist that composed the track
conductor_id = Column(Integer, ForeignKey('artists.id')) # the artist that conducted the track
@@ -170,6 +175,7 @@ class Track(Base):
title_sort = Column(String) # sortable title of the track
tracknumber = Column(Integer) # order of the track on the disc
subtitle = Column(String) # sub title of the track
+ website = Column(String) # a website for the track
playcount = Column(Integer) # number of times the track was played
rating = Column(Integer) # rating of the track (0-255)
@@ -181,6 +187,7 @@ class Track(Base):
conductor = relationship('Artist', primaryjoin='Artist.id == Track.conductor_id')
lyricist = relationship('Artist', primaryjoin='Artist.id == Track.lyricist_id')
performer = relationship('Artist', primaryjoin='Artist.id == Track.performer_id')
+ author = relationship('Artist', primaryjoin='Artist.id == Track.author_id')
album = relationship('Album', backref=backref('tracks', order_by=tracknumber))
disc = relationship('Disc', backref=backref('tracks', order_by=tracknumber))
View
382 musik/library/importer.py
@@ -7,8 +7,10 @@
from mutagen.easyid3 import EasyID3
from mutagen.mp3 import MP3
+from sqlalchemy.exc import OperationalError
+
from musik import initLogging
-from musik.db import DatabaseWrapper, ImportTask, Track, Album, Artist
+from musik.db import DatabaseWrapper, ImportTask, Track, Album, Artist, Disc
from musik.util import EasygoingDictionary
class ImportThread(threading.Thread):
@@ -114,19 +116,30 @@ def isMimeTypeSupported(self, uri):
def importFile(self, uri):
- #TODO: actually import the file
- self.log.info(u'ImportFile called with uri %s', uri)
+ self.log.debug(u'ImportFile called with uri %s', uri)
mtype = mimetypes.guess_type(uri)[0]
if mtype != u'audio/mpeg':
self.log.info(u'Unsupported mime type %s. Ignoring file.', mtype)
# Try to read the metadata appropriately.
- metadata = self.readMp3MetaData(uri)
+ self.createTrack(uri)
+
+ def createTrack(self, uri):
+ """Creates a track object out of the specified URI.
+ Returns a fully populated musik.db.Track object that has already been
+ committed to the database.
+ """
+ self.log.debug(u'createTrack called with uri %s', uri)
- def readMp3MetaData(self, uri):
- # TODO: check that the uri doesn't already exist
+ # check that the uri doesn't already exist in our library
+ track = self.sa_session.query(Track).filter(Track.uri == uri).first()
+ if track == None:
+ track = Track(uri)
+ self.sa_session.add(track)
+ else:
+ self.log.info(u'Track with uri %s is already in the library. Updating metadata...')
# get id3 data from the file
easyid3 = EasyID3(uri)
@@ -138,29 +151,269 @@ def readMp3MetaData(self, uri):
for key in easyid3.keys():
metadata[key] = easyid3[key][0]
- # TODO: handle these keys
- # 'asin', 'author', 'bpm', 'copyright', 'date',
- # 'encodedby', 'genre', 'isrc', 'length', 'mood',
- # 'musicbrainz_trackid', 'musicbrainz_trmid',
- # 'musicip_fingerprint', 'musicip_puid', 'performer:*',
- # 'replaygain_*_gain', 'replaygain_*_peak', 'title', 'titlesort',
- # 'tracknumber', 'version', 'website'
-
- track = Track(uri)
- track.artist = self.findArtist(metadata['artist'], metadata['artistsort'], metadata['musicbrainz_artistid'])
- track.album_artist = self.findArtist(metadata['albumartist'], metadata['albumartistsort'])
- track.arranger = self.findArtist(metadata['arranger'])
- track.composer = self.findArtist(metadata['composer'], metadata['composersort'])
- track.conductor = self.findArtist(metadata['conductor'])
- track.lyricist = self.findArtist(metadata['lyricist'])
- track.performer = self.findArtist(metadata['performer'])
- track.title = metadata['title']
-
- track.album = self.findAlbum(metadata['album'], metadata['albumsort'], metadata['musicbrainz_albumid'], track.artist, metadata)
+ # artist
+ artist = self.findArtist(metadata['artist'], metadata['artistsort'], metadata['musicbrainz_artistid'])
+ if artist != None:
+ if track.artist == None:
+ track.artist = artist
+ elif track.artist.id != artist.id:
+ # TODO: conflict!
+ self.log.warning(u'Artist conflict for track %s: %s != %s', track, track.artist, artist)
+
+ # album artist
+ album_artist = self.findArtist(metadata['albumartist'], metadata['albumartistsort'])
+ if album_artist != None:
+ if track.album_artist == None:
+ track.album_artist = album_artist
+ elif track.album_artist.id != album_artist.id:
+ # TODO: conflict!
+ self.log.warning(u'Album artist conflict for track %s: %s != %s', track, track.album_artist, album_artist)
+
+ # arranger
+ arranger = self.findArtist(metadata['arranger'])
+ if arranger != None:
+ if track.arranger == None:
+ track.arranger = arranger
+ elif track.arranger.id != arranger.id:
+ # TODO: conflict!
+ self.log.warning(u'Arranger conflict for track %s: %s != %s', track, track.arranger, arranger)
+
+ # author
+ author = self.findArtist(metadata['author'])
+ if author != None:
+ if track.author == None:
+ track.author = author
+ elif track.author.id != author.id:
+ # TODO: conflict!
+ self.log.warning(u'Author conflict for track %s: %s != %s', track, track.author, author)
+
+ # composer
+ composer = self.findArtist(metadata['composer'], metadata['composersort'])
+ if composer != None:
+ if track.composer == None:
+ track.composer = composer
+ elif track.composer.id != composer.id:
+ # TODO: conflict!
+ self.log.warning(u'Composer conflict for track %s: %s != %s', track, track.composer, composer)
+
+ # conductor
+ conductor = self.findArtist(metadata['conductor'])
+ if conductor != None:
+ if track.conductor == None:
+ track.conductor = conductor
+ elif track.conductor.id != conductor.id:
+ # TODO: conflict!
+ self.log.warning(u'Conductor conflict for track %s: %s != %s', track, track.conductor, conductor)
+
+ # lyricist
+ lyricist = self.findArtist(metadata['lyricist'])
+ if lyricist != None:
+ if track.lyricist == None:
+ track.lyricist = lyricist
+ elif track.lyricist.id != lyricist.id:
+ # TODO: conflict!
+ self.log.warning(u'Lyricist conflict for track %s: %s != %s', track, track.lyricist, lyricist)
+
+ # performer
+ performer = self.findArtist(metadata['performer'])
+ if performer != None:
+ if track.performer == None:
+ track.performer = performer
+ elif track.performer.id != performer.id:
+ # TODO: conflict!
+ self.log.warning(u'Performer conflict for track %s: %s != %s', track, track.performer, performer)
+
+ # album
+ album = self.findAlbum(metadata['album'], metadata['albumsort'], metadata['musicbrainz_albumid'], track.artist, metadata)
+ if album != None:
+ if track.album == None:
+ track.album = album
+ elif track.album.id != album.id:
+ # TODO: conflict!
+ self.log.warning(u'Album conflict for track %s: %s != %s', track, track.album, album)
+
+ # disc
if track.album != None:
disc = self.findDisc(track.album, metadata['discnumber'], metadata['discsubtitle'], metadata['musicbrainz_discid'])
+ for d in track.album.discs:
+ if d.id == disc.id:
+ # found disc is already linked - don't add it again
+ disc = None
+ if disc != None:
+ track.album.discs.append(disc)
+
+ #bpm
+ if metadata['bpm'] != None:
+ if track.bpm == None:
+ track.bpm = metadata['bpm']
+ elif track.bpm != metadata['bpm']:
+ # TODO: conflict!
+ self.log.warning(u'Track bpm conflict for track %s: %s != %s', track, track.bpm, metadata['bpm'])
+
+ #copyright
+ if metadata['copyright'] != None:
+ if track.copyright == None:
+ track.copyright = metadata['copyright']
+ elif track.copyright != metadata['copyright']:
+ # TODO: conflict!
+ self.log.warning(u'Track copyright conflict for track %s: %s != %s', track, track.copyright, metadata['copyright'])
+
+ #date
+ if metadata['date'] != None:
+ if track.date == None:
+ track.date = metadata['date']
+ elif track.date != metadata['date']:
+ # TODO: conflict!
+ self.log.warning(u'Track date conflict for track %s: %s != %s', track, track.date, metadata['date'])
+
+ #encodedby
+ if metadata['encodedby'] != None:
+ if track.encodedby == None:
+ track.encodedby = metadata['encodedby']
+ elif track.encodedby != metadata['encodedby']:
+ # TODO: conflict!
+ self.log.warning(u'Track encodedby conflict for track %s: %s != %s', track, track.encodedby, metadata['encodedby'])
+
+ #genre
+ if metadata['genre'] != None:
+ if track.genre == None:
+ track.genre = metadata['genre']
+ elif track.genre != metadata['genre']:
+ # TODO: conflict!
+ self.log.warning(u'Track genre conflict for track %s: %s != %s', track, track.genre, metadata['genre'])
+
+ #isrc
+ if metadata['isrc'] != None:
+ if track.isrc == None:
+ track.isrc = metadata['isrc']
+ elif track.isrc != metadata['isrc']:
+ # TODO: conflict!
+ self.log.warning(u'Track isrc conflict for track %s: %s != %s', track, track.isrc, metadata['isrc'])
+
+ #length
+ if metadata['length'] != None:
+ if track.length == None:
+ track.length = metadata['length']
+ elif track.length != metadata['length']:
+ # TODO: conflict!
+ self.log.warning(u'Track length conflict for track %s: %s != %s', track, track.length, metadata['length'])
+
+ #mood
+ if metadata['mood'] != None:
+ if track.mood == None:
+ track.mood = metadata['mood']
+ elif track.mood != metadata['mood']:
+ # TODO: conflict!
+ self.log.warning(u'Track mood conflict for track %s: %s != %s', track, track.mood, metadata['mood'])
+
+ #musicbrainz_trackid
+ if metadata['musicbrainz_trackid'] != None:
+ if track.musicbrainz_trackid == None:
+ track.musicbrainz_trackid = metadata['musicbrainz_trackid']
+ elif track.musicbrainz_trackid != metadata['musicbrainz_trackid']:
+ # TODO: conflict!
+ self.log.warning(u'Track musicbrainz_trackid conflict for track %s: %s != %s', track, track.musicbrainz_trackid, metadata['musicbrainz_trackid'])
+
+ #musicbrainz_trmid
+ if metadata['musicbrainz_trmid'] != None:
+ if track.musicbrainz_trmid == None:
+ track.musicbrainz_trmid = metadata['musicbrainz_trmid']
+ elif track.musicbrainz_trmid != metadata['musicbrainz_trmid']:
+ # TODO: conflict!
+ self.log.warning(u'Track musicbrainz_trmid conflict for track %s: %s != %s', track, track.musicbrainz_trmid, metadata['musicbrainz_trmid'])
+
+ #musicip_fingerprint
+ if metadata['musicip_fingerprint'] != None:
+ if track.musicip_fingerprint == None:
+ track.musicip_fingerprint = metadata['musicip_fingerprint']
+ elif track.musicip_fingerprint != metadata['musicip_fingerprint']:
+ # TODO: conflict!
+ self.log.warning(u'Track musicip_fingerprint conflict for track %s: %s != %s', track, track.musicip_fingerprint, metadata['musicip_fingerprint'])
+
+ #musicip_puid
+ if metadata['musicip_puid'] != None:
+ if track.musicip_puid == None:
+ track.musicip_puid = metadata['musicip_puid']
+ elif track.musicip_puid != metadata['musicip_puid']:
+ # TODO: conflict!
+ self.log.warning(u'Track musicip_puid conflict for track %s: %s != %s', track, track.musicip_puid, metadata['musicip_puid'])
+
+ # title
+ if metadata['title'] != None:
+ if track.title == None:
+ track.title = metadata['title']
+ elif track.title != metadata['title']:
+ # TODO: conflict!
+ self.log.warning(u'Track title conflict for track %s: %s != %s', track, track.title, metadata['title'])
+
+ # titlesort
+ if metadata['titlesort'] != None:
+ if track.title_sort == None:
+ track.title_sort = metadata['titlesort']
+ elif track.title_sort != metadata['titlesort']:
+ # TODO: conflict!
+ self.log.warning(u'Track titlesort conflict for track %s: %s != %s', track, track.title_sort, metadata['titlesort'])
+
+ # tracknumber
+ if metadata['tracknumber'] != None:
+ if track.tracknumber == None:
+ track.tracknumber = metadata['tracknumber']
+ elif track.tracknumber != metadata['tracknumber']:
+ # TODO: conflict!
+ self.log.warning(u'Track tracknumber conflict for track %s: %s != %s', track, track.tracknumber, metadata['tracknumber'])
+
+ # version
+ if metadata['version'] != None:
+ if track.subtitle == None:
+ track.subtitle = metadata['version']
+ elif track.subtitle != metadata['version']:
+ # TODO: conflict!
+ self.log.warning(u'Track version conflict for track %s: %s != %s', track, track.subtitle, metadata['version'])
+
+ # website
+ if metadata['website'] != None:
+ if track.website == None:
+ track.website = metadata['website']
+ elif track.website != metadata['website']:
+ # TODO: conflict!
+ self.log.warning(u'Track website conflict for track %s: %s != %s', track, track.website, metadata['website'])
+
+ # get id3 data from the file
+ id3 = MP3(uri)
- return track
+ # copy data to a new dict that only uses the first value of each key.
+ # technically this is discarding data, but most keys are only allowed
+ # a single value anyway, and it simplifies the following algorithm
+ metadata = EasygoingDictionary()
+ for key in id3.keys():
+ # TODO: these frames are singletons, so we can't use the array
+ # index when accessing them. for now we'll boot out, but we
+ # need a better way to do this.
+ if key.startswith('APIC') or key.startswith('UFID') or key.startswith('USLT'):
+ continue
+ metadata[key] = id3[key][0]
+
+ # play count can be stored in either the PCNT or the POPM frames.
+ # choose the largest of the two values as our official playcount.
+ playcount = 0
+ if metadata['PCNT'] != None and metadata['PCNT'].count != None:
+ playcount = int(metadata['PCNT'].count)
+
+ if metadata['POPM'] != None and metadata['POPM'].count != None:
+ if int(metadata['POPM'].count) > playcount:
+ playcount = int(metadata['POPM'].count)
+
+ # always take the largest playcount
+ if track.playcount == None or track.playcount < playcount:
+ track.playcount = playcount
+
+ # rating is stored in the POPM frame
+ # only ever set the rating if it is currently None - we never want to overwrite a user's rating
+ if metadata['POPM'] != None and metadata['POPM'].rating != None:
+ if track.rating == None:
+ track.rating = int(metadata['POPM'].rating)
+
+ self.log.info(u'Added track %s to the current session.', track)
def findArtist(self, name=None, name_sort=None, musicbrainz_id=None):
@@ -175,6 +428,7 @@ def findArtist(self, name=None, name_sort=None, musicbrainz_id=None):
if artist != None:
# found an existing artist in our db - compare its metadata
# to the new info. Always prefer existing metadata over new.
+ self.log.debug(u'Artist name musicbrainz_artistid search found existing artist %s in database' % artist)
if name != None:
if artist.name == None:
artist.name = name
@@ -193,7 +447,7 @@ def findArtist(self, name=None, name_sort=None, musicbrainz_id=None):
# artist in our db, try to find an existing artist by name
artist = self.sa_session.query(Artist).filter(Artist.name == name).first()
if artist != None:
- self.log.debug(u'Found existing artist %s in database' % name)
+ self.log.debug(u'Artist name search found existing artist %s in database' % artist)
# found an existing artist in our db - compare its metadata
# to the new info. Always prefer existing metadata over new.
if name_sort != None:
@@ -203,19 +457,20 @@ def findArtist(self, name=None, name_sort=None, musicbrainz_id=None):
self.log.warning(u'Artist sort name conflict for artist %s: %s != %s', artist.name, artist.name_sort, name_sort)
else:
# an existing artist could not be found in our db. Make a new one
- self.log.debug(u'Artist not found in database; creating %s' % name)
artist = Artist(name)
if name_sort != None:
artist.name_sort = name_sort
if musicbrainz_id != None:
artist.musicbrainz_artistid = musicbrainz_id
# add the artist object to the DB
+ self.log.debug(u'Artist not found in database. Created new artist %s' % artist)
self.sa_session.add(artist)
# return the artist that we found and/or created
return artist
+ # TODO: Need support for album artist?
def findAlbum(self, title=None, title_sort=None, musicbrainz_id=None, artist=None, metadata=None):
"""Searches the database for an existing album that matches the specified criteria.
If no existing album can be found, a new album is created with the criteria.
@@ -228,6 +483,7 @@ def findAlbum(self, title=None, title_sort=None, musicbrainz_id=None, artist=Non
if album != None:
# found an existing album in our db - compare its metadata
# to the new info. Always prefer existing metadata over new.
+ self.log.debug(u'Album musicbrainz_albumid search found existing album %s in database' % album)
if title != None:
if album.title == None:
album.title = title
@@ -243,18 +499,18 @@ def findAlbum(self, title=None, title_sort=None, musicbrainz_id=None, artist=Non
if artist != None:
if album.artist == None:
album.artist = artist
- elif album.artist.id != artist.id:
+ elif album.artist_id != artist.id:
# TODO: conflict -> schedule musicbrainz task!
self.log.warning(u'Album artist conflict for musicbrainz_albumid %s: %s != %s', album.musicbrainz_albumid, album.artist, artist)
if album == None and title != None and artist != None:
# if we don't have musicbrainz_albumid or there is no matching
# album in our db, try to find an existing album by title and artist
- album = self.sa_session.query(Album).filter(Album.title == title, Album.artist.id == artist.id).first()
+ album = self.sa_session.query(Album).filter(Album.title == title, Album.artist_id == artist.id).first()
if album != None:
# found an existing album in our db - compare its metadata
# to the new info. Always prefer existing metadata over new.
- self.log.debug(u'Found existing album %s in database' % title)
+ self.log.debug(u'Album title/artist search found existing album %s in database' % album)
if title_sort != None:
if album.title_sort == None:
album.title_sort = title_sort
@@ -262,7 +518,6 @@ def findAlbum(self, title=None, title_sort=None, musicbrainz_id=None, artist=Non
self.log.warning(u'Album sort title conflict for album %s: %s != %s', album.title, album.title_sort, title_sort)
else:
# an existing album could not be found in our db. Make a new one
- self.log.debug(u'Album not found in database; creating %s' % title)
album = Album(title)
if title_sort != None:
album.title_sort = title_sort
@@ -270,10 +525,17 @@ def findAlbum(self, title=None, title_sort=None, musicbrainz_id=None, artist=Non
album.musicbrainz_albumid = musicbrainz_id
if artist != None:
album.artist = artist
+ self.log.debug(u'Album not found in database. Created new album %s' % album)
self.sa_session.add(album)
# we either found or created the album. now verify its metadata
if album != None and metadata != None:
+ if metadata['asin'] != None:
+ if album.asin == None:
+ album.asin = metadata['asin']
+ elif album.asin != metadata['asin']:
+ # TODO: conflict -> schedule musicbrainz task!
+ self.log.warning(u'Album ASIN conflict for album %s: %s != %s', album, album.asin, metadata['asin'])
if metadata['barcode'] != None:
if album.barcode == None:
album.barcode = metadata['barcode']
@@ -324,22 +586,48 @@ def findDisc(self, album=None, discnumber=None, discsubtitle=None, musicbrainz_i
"""Tries to find an existing disc that matches the specified criteria.
If an existing disc cannot be found, creates a new disc with the specified criteria.
"""
- # TODO: first, see if there's a disc that's already linked that satisfies the specified criteria
- # if album != None:
- # for disc in album.discs:
- # if musicbrainz_id != None:
- # if disc.musicbrainz_id == musicbrainz_id:
- # if discnumber != None:
- # if disc.discnumber == None:
- # disc.discnumber = discnumber
- # elif
-
+ # first see if there's a disc that's already linked to the album that
+ # has either the specified musicbrainz_discid or discnumber.
disc = None
- if musicbrainz_id != None:
+ if album != None:
+ for d in album.discs:
+ if musicbrainz_id != None:
+ if d.musicbrainz_id == musicbrainz_id:
+ disc = d
+ if discnumber != None:
+ if d.discnumber == discnumber:
+ disc = d
+
+ # if we found a disc in the existing album's collection that matches
+ # the specified criteria, update any missing metadata
+ if disc != None:
+ self.log.debug(u'Disc musicbrainz_discid/discnumber search found existing disc %s in database' % disc)
+ if discnumber != None:
+ if d.discnumber == None:
+ d.discnumber = discnumber
+ elif d.discnumber != discnumber:
+ # TODO: conflict!
+ self.log.warning(u'Disc number conflict for disc %s: %s != %s', disc, disc.discnumber, discnumber)
+ if discsubtitle != None:
+ if d.subtitle == None:
+ d.subtitle = discsubtitle
+ elif d.subtitle != discsubtitle:
+ # TODO: Conflict!
+ self.log.warning(u'Disc subtitle conflict for disc %s: %s != %s', disc, disc.subtitle, discsubtitle)
+ if musicbrainz_id != None:
+ if d.musicbrainz_discid == None:
+ d.musicbrainz_discid = musicbrainz_id
+ elif d.musicbrainz_discid != musicbrainz_id:
+ # TODO: conflict!
+ self.log.warning(u'Disc musicbrainz_discid conflict for disc %s: %s != %s', disc, disc.musicbrainz_discid, musicbrainz_id)
+
+ if disc == None and musicbrainz_id != None:
+ # search for an existing unlinked disc in the database.
# we trust musicbrainz_discid the most because it infers that
# some other tagger has already verified the metadata.
disc = self.sa_session.query(Disc).filter(Disc.musicbrainz_discid == musicbrainz_id).first()
if disc != None:
+ self.log.debug(u'Disc musicbrainz_discid search found existing disc %s in database' % disc)
if album != None:
if disc.album == None:
disc.album = album
@@ -358,11 +646,13 @@ def findDisc(self, album=None, discnumber=None, discsubtitle=None, musicbrainz_i
elif disc.discsubtitle != discsubtitle:
# TODO: conflict -> schedule musicbrainz task!
self.log.warning(u'Disc subtitle conflict for disc %s: %s != %s', disc, disc.discsubtitle, discsubtitle)
- if album != None and discnumber != None:
+
+ if disc == None and album != None and discnumber != None:
# musicbrainz_discid wasn't supplied or didn't yield an existing album.
# try to search with album id and disc number instead.
- disc = self.sa_session.query(Disc).filter(Disc.album_id == album.id, Disc.discnumber == discnumber)
+ disc = self.sa_session.query(Disc).filter(Disc.album_id == album.id, Disc.discnumber == discnumber).first()
if disc != None:
+ self.log.debug(u'Disc album/number search found existing disc %s in database' % disc)
if discsubtitle != None:
if disc.discsubtitle == None:
disc.discsubtitle = discsubtitle
@@ -377,7 +667,6 @@ def findDisc(self, album=None, discnumber=None, discsubtitle=None, musicbrainz_i
self.log.warning(u'Disc musicbrainz_discid conflict for disc %s: %s != %s', disc, disc.musicbrainz_discid, musicbrainz_id)
else:
# could not find the disc in question. Create a new one instead
- self.log.debug(u'Could not find disc in database; creating %s' % discnumber)
disc = Disc(discnumber)
if album != None:
disc.album = album
@@ -385,6 +674,7 @@ def findDisc(self, album=None, discnumber=None, discsubtitle=None, musicbrainz_i
disc.discsubtitle = discsubtitle
if musicbrainz_id != None:
disc.musicbrainz_discid = musicbrainz_id
+ self.log.debug(u'Could not find disc in database. Created new disc %s' % disc)
self.sa_session.add(disc)
return disc

No commit comments for this range

Something went wrong with that request. Please try again.