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)
Exemple #2
0
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)
Exemple #3
0
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
Exemple #4
0
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)