def add_track(trackpath, source=str(datetime.date.today()), gordonDir=DEF_GORDON_DIR, tag_dict=None, artist=None, album=None, fast_import=False, import_md=False): """Add track with given filename <trackpath> to database @param source: audio files data source (string) @param gordonDir: main Gordon directory @param tag_dict: dictionary of key,val tag pairs - See add_album(...). @param artist: The artist for this track. An instance of Artist. None if not present @param album: The album for this track. An instance of Album. None if not present @param fast_import: If true, do not calculate strip_zero length. Defaults to False @param import_md: use True to try to extract all metadata tags embedded in the auudio-file. Defaults to False """ (path, filename) = os.path.split(trackpath) (fname, ext) = os.path.splitext(filename) if tag_dict is None: tag_dict = {} log.debug('Adding file "%s" of "%s" album by %s', filename, album, artist) # validations if 'album' not in tag_dict: #todo: currently cannot add singleton files. Need an album which is defined in tag_dict log.error('Cannot add "%s" because it is not part of an album', filename) return -1 # didn't add if not os.path.isfile(trackpath): log.info('Skipping %s because it is not a file', filename) return -1 # not a file # FIXME: 2014-01-10 21:42:48 by Brian McFee <*****@*****.**> # gordon's AudioFile code doesn't handle unicode filenames correctly # try: # AudioFile(trackpath).read(tlen_sec=0.01) # except: # log.error('Skipping "%s" because it is not a valid audio file', filename) # return -1 # not an audio file # required data bytes = os.stat(trackpath)[stat.ST_SIZE] # First look for dupes if track_exists(filename, bytes): log.debug('Skipping "%s" because it has already been indexed', filename) return -1 # Already exists # prepare data if tag_dict[u'compilation'] not in [True, False, 'True', 'False'] : tag_dict[u'compilation'] = False track = Track(title = tag_dict[u'title'], artist = tag_dict[u'artist'], album = tag_dict[u'album'], tracknum = tag_dict[u'tracknum'], compilation = tag_dict[u'compilation'], otitle = tag_dict[u'title'], oartist = tag_dict[u'artist'], oalbum = tag_dict[u'album'], otracknum = tag_dict[u'tracknum'], ofilename = unicode(filename, 'utf-8', errors='ignore'), source = unicode(source), bytes = bytes) # add data add(track) # needed to get a track id commit() #to get our track id we need to write this record log.debug('Wrote track record %s to database', track.id) if fast_import : track.secs = -1 track.zsecs = -1 else : a = AudioFile(trackpath) [track.secs, track.zsecs] = a.get_secs_zsecs() track.path = u'%s' % get_tidfilename(track.id, ext[1:]) # links track to artist & album in DB if artist: log.debug('Linking %s to artist %s', track, artist) track.artist = artist.name track.artists.append(artist) if album: log.debug('Linking %s to album %s', track, album) track.album = album.name track.albums.append(album) log.debug('Wrote album and artist additions to track into database') # copy the file to the Gordon audio/feature data directory tgt = os.path.join(gordonDir, 'audio', 'main', track.path) make_subdirs_and_copy(trackpath, tgt) log.debug('Copied "%s" to %s', trackpath, tgt) # add annotations del(tag_dict[u'title']) del(tag_dict[u'artist']) del(tag_dict[u'album']) del(tag_dict[u'tracknum']) del(tag_dict[u'compilation']) for tagkey, tagval in tag_dict.iteritems(): # create remaining annotations track.annotations.append(Annotation(type='text', name=tagkey, value=tagval)) if import_md: #check if file is mp3. if so: if isValidMP3(trackpath): #extract all ID3 tags, store each tag value as an annotation type id3.[tagname] for tag in getAllTags(trackpath): track.annotations.append(Annotation(type='id3', name=tag[0], value=tag[1])) #todo: work with more metadata formats (use tagpy?) # Link the track to the collection object track.collections.append(get_or_create_collection(source)) commit() # store the annotations log.debug('Added "%s"', trackpath)
def add_mp3(mp3, source=str(datetime.date.today()), gordonDir=DEF_GORDON_DIR, id3_dict=dict(), artist=None, album=None, fast_import=False, import_id3=False): '''Add mp3 with filename <mp3> to database @param source: audio files data source @param gordonDir: main Gordon directory @param tag_dict: dictionary of key,val ID3 tags pairs - See add_album(...). @param artist: The artist for this track. An instance of Artist. None if not present @param album: The album for this track. An instance of Album. None if not present @param fast_import: If true, do not calculate strip_zero length. Defaults to False @param import_id3: Specifies if we want to get the id3 tags from the file. Defaults to True ''' (filepath, filename) = os.path.split(mp3) log.debug(' Adding mp3 file "%s" of "%s" album by %s - add_mp3()', filename, album, artist) # validations if len(id3_dict) == 0 : #todo: currently cannot add singleton mp3s. Need an album which is defined in id3_dict log.error(' Cannot add "%s" because it is not part of an album', filename) return -1 # didn't add if not os.path.isfile(mp3) : log.debug(' Skipping %s because it is not a file', filename) return -1 # not a file # required data bytes = os.stat(mp3)[stat.ST_SIZE] # try: #get track length # eyed3_secs = int(id3.mp3_gettime(mp3)) #from mp3_eyed3 # except : # log.error(' Could not read time from mp3 %s', mp3) # eyed3_secs = -1 #we get odd filenames that cannot be easily encoded. This seems to come #from times when a latin-1 filesystem named files and then those filenames #are brought over to a utf filesystem. try: fn_recoded = filename.decode('utf-8') except : try : fn_recoded = filename.decode('latin1') except : fn_recoded = 'unknown' # prepare data if id3_dict['compilation'] not in [True, False, 'True', 'False'] : id3_dict['compilation'] = False track = Track(title = id3_dict[u'title'], artist = id3_dict[u'artist'], album = id3_dict[u'album'], tracknum = id3_dict[u'tracknum'], compilation = id3_dict[u'compilation'], otitle = id3_dict[u'title'], oartist = id3_dict[u'artist'], oalbum = id3_dict[u'album'], otracknum = id3_dict[u'tracknum'], ofilename = os.path.join(filepath,fn_recoded), source = unicode(source), bytes = bytes) # add data add(track) commit() #to get our track id we need to write this record log.debug(' Wrote track record %s to database', track.id) if fast_import : #try to get the seconds from ffmpeg track.zsecs = -1 track.secs= -1 try : a = AudioFile(filename) [ignore_fs,ignore_chans,track.secs] = a.read_stats() except : log.warn(" Could not read stats from", filename) else : a = AudioFile(filename) [track.secs, track.zsecs] = a.get_secs_zsecs() track.path = u"%s" % get_tidfilename(track.id) #This is a bit confusing. For backwards compat #todo: clean up DB relationships if artist: log.debug(' Linking to artist %s', artist) track.artist = artist.name track.artists.append(artist) if album: log.debug(' Linking to album %s', album) track.album = album.name track.albums.append(album) commit() # save (again) the track record (this time) log.debug(' * Wrote album and artist additions to track into database') #copy the file to the Gordon instal audio/feature data directory tgt = os.path.join(gordonDir, 'audio', 'main', track.path) make_subdirs_and_copy(filename, tgt) log.debug(' Copied mp3 "%s" to %s', filename, tgt) #stamp the file ("TID n" as an ID3v2 commment) id3.id3v2_putval(tgt, 'tid', 'T%i' % track.id) # writes on new audio file (the copy) # We update id3 tags in mp3 if necessary (from local MusicBrainz DB, when no info found) #todo: try this when Gordon has no write access to the files, does the script handle the error? (can't roll back saved tracks now) if track.otitle <> track.title or track.oartist <> track.artist or track.oalbum <> track.album or track.otracknum <> track.tracknum : log.debug(' (NOT) Trying to update_mp3_from_db %s %s', track.id, os.path.join(gordonDir, 'audio', 'main')) try: from gordon.db.mbrainz_resolver import GordonResolver gordonResolver = GordonResolver() try: if not gordonResolver.update_mp3_from_db(track.id, audioDir = os.path.join(gordonDir, 'audio', 'main'), doit = True) : pass # if file not found ... except Exception: # except for file access crashes? pass except: log.warning(' MusicBrainz interface is not installed. Refer to Gordon INSTALL notes.') #search for other annotations and store them in the database _store_annotations(mp3, track, import_id3)
def add_track(trackpath, source=str(datetime.date.today()), gordonDir=DEF_GORDON_DIR, tag_dict=dict(), artist=None, album=None, fast_import=False, import_md=False): """Add track with given filename <trackpath> to database @param source: audio files data source (string) @param gordonDir: main Gordon directory @param tag_dict: dictionary of key,val tag pairs - See add_album(...). @param artist: The artist for this track. An instance of Artist. None if not present @param album: The album for this track. An instance of Album. None if not present @param fast_import: If true, do not calculate strip_zero length. Defaults to False @param import_md: use True to try to extract all metadata tags embedded in the auudio-file. Defaults to False """ (path, filename) = os.path.split(trackpath) (fname, ext) = os.path.splitext(filename) log.debug('Adding file "%s" of "%s" album by %s', filename, album, artist) # validations if 'album' not in tag_dict: #todo: currently cannot add singleton files. Need an album which is defined in tag_dict log.error('Cannot add "%s" because it is not part of an album', filename) return -1 # didn't add if not os.path.isfile(trackpath): log.info('Skipping %s because it is not a file', filename) return -1 # not a file try: AudioFile(trackpath).read(tlen_sec=0.01) except: log.error('Skipping "%s" because it is not a valid audio file', filename) return -1 # not an audio file # required data bytes = os.stat(trackpath)[stat.ST_SIZE] # reencode name to latin1 !!! try: fn_recoded = filename.decode('utf-8') except: try: fn_recoded = filename.decode('latin1') except: fn_recoded = 'unknown' # prepare data if tag_dict[u'compilation'] not in [True, False, 'True', 'False']: tag_dict[u'compilation'] = False track = Track(title=tag_dict[u'title'], artist=tag_dict[u'artist'], album=tag_dict[u'album'], tracknum=tag_dict[u'tracknum'], compilation=tag_dict[u'compilation'], otitle=tag_dict[u'title'], oartist=tag_dict[u'artist'], oalbum=tag_dict[u'album'], otracknum=tag_dict[u'tracknum'], ofilename=fn_recoded, source=unicode(source), bytes=bytes) # add data add(track) # needed to get a track id commit() #to get our track id we need to write this record log.debug('Wrote track record %s to database', track.id) if fast_import: track.secs = -1 track.zsecs = -1 else: a = AudioFile(trackpath) [track.secs, track.zsecs] = a.get_secs_zsecs() track.path = u'%s' % get_tidfilename(track.id, ext[1:]) # links track to artist & album in DB if artist: log.debug('Linking %s to artist %s', track, artist) track.artist = artist.name track.artists.append(artist) if album: log.debug('Linking %s to album %s', track, album) track.album = album.name track.albums.append(album) log.debug('Wrote album and artist additions to track into database') # copy the file to the Gordon audio/feature data directory tgt = os.path.join(gordonDir, 'audio', 'main', track.path) make_subdirs_and_copy(trackpath, tgt) log.debug('Copied "%s" to %s', trackpath, tgt) # add annotations del (tag_dict[u'title']) del (tag_dict[u'artist']) del (tag_dict[u'album']) del (tag_dict[u'tracknum']) del (tag_dict[u'compilation']) for tagkey, tagval in tag_dict.iteritems(): # create remaining annotations track.annotations.append( Annotation(type='text', name=tagkey, value=tagval)) if import_md: #check if file is mp3. if so: if isValidMP3(trackpath): #extract all ID3 tags, store each tag value as an annotation type id3.[tagname] for tag in getAllTags(trackpath): track.annotations.append( Annotation(type='id3', name=tag[0], value=tag[1])) #todo: work with more metadata formats (use tagpy?) # Link the track to the collection object track.collections.append(get_or_create_collection(source)) commit() # store the annotations
def add_uncomp(wav, source=str(datetime.date.today()), gordonDir=DEF_GORDON_DIR, tag_dict=dict(), artist=None, album=None, fast_import=False, import_md=False): """Add uncompressed wav/aif with filename <wav> to database @param source: audio files data source - Collection object @param gordonDir: main Gordon directory @param tag_dict: dictionary of key,val tag pairs - See add_album(...). @param artist: The artist for this track. An instance of Artist. None if not present @param album: The album for this track. An instance of Album. None if not present @param fast_import: If true, do not calculate strip_zero length. Defaults to False @param import_md: Specifies if we want to get the metadata tags from the file. Defaults to True """ (xxx, filename) = os.path.split(wav) (xxx, ext) = os.path.splitext(filename) log.debug(' Adding uncompressed file "%s" of "%s" album by %s - add_uncomp()', filename, album, artist) # validations if len(tag_dict) == 0 : #todo: currently cannot add singleton files. Need an album which is defined in tag_dict log.error(' Cannot add "%s" because it is not part of an album', filename) return -1 # didn't add if not os.path.isfile(wav) : log.debug(' Skipping %s because it is not a file', filename) return -1 # not a file # required data bytes = os.stat(wav)[stat.ST_SIZE] # reencode name to latin1 try: fn_recoded = filename.decode('utf-8') except : try : fn_recoded = filename.decode('latin1') except : fn_recoded = 'unknown' # prepare data if tag_dict['compilation'] not in [True, False, 'True', 'False'] : tag_dict['compilation'] = False track = Track(title = tag_dict[u'title'], artist = tag_dict[u'artist'], album = tag_dict[u'album'], tracknum = tag_dict[u'tracknum'], compilation = tag_dict[u'compilation'], otitle = tag_dict[u'title'], oartist = tag_dict[u'artist'], oalbum = tag_dict[u'album'], otracknum = tag_dict[u'tracknum'], ofilename = fn_recoded, source = unicode(source), bytes = bytes) # add data add(track) # needed to get a track id commit() #to get our track id we need to write this record log.debug(' Wrote track record %s to database', track.id) if fast_import : track.secs = -1 track.zsecs = -1 else : a = AudioFile(filename) [track.secs, track.zsecs] = a.get_secs_zsecs() track.path = u'%s' % get_tidfilename(track.id, ext[1:]) # creates path to insert in track # links track to artist & album in DB if artist: log.debug(' Attaching artist %s', artist) track.artist = artist.name track.artists.append(artist) if album: log.debug(' Attaching album %s', album) track.album = album.name track.albums.append(album) commit() # save (again) the track record (this time having the track id) log.debug(' * Wrote album and artist additions to track into database') #copy the file to the Gordon instal audio/feature data directory tgt = os.path.join(gordonDir, 'audio', 'main', track.path) make_subdirs_and_copy(filename, tgt) log.debug(' Copied uncompressed "%s" to %s', filename, tgt) #search for other annotations and store them in the database _store_annotations(wav, track, import_md)