Esempio n. 1
0
def syncImage(img, current, session):
    '''Add or updated the Image.'''
    def _img_str(i):
        return "%s - %s" % (i.type, i.description)

    for db_img in current.images:
        img_info = (img.type, img.md5, img.size)
        db_img_info = (db_img.type, db_img.md5, db_img.size)

        if db_img_info == img_info:
            img = None
            break
        elif (db_img.type == img.type and
                db_img.description == img.description):

            if img.md5 != db_img.md5:
                # Update image
                current.images.remove(db_img)
                current.images.append(img)
                session.add(current)
                print(fg.green("Updating image") + ": " + _img_str(img))
            img = None
            break

    if img:
        # Add image
        current.images.append(img)
        session.add(current)
        print(fg.green("Adding image") + ": " + _img_str(img))
Esempio n. 2
0
    def _getArtist(self, session, name, resolved_artist):
        artist_rows = session.query(Artist).filter_by(name=name).all()
        if artist_rows:
            if len(artist_rows) > 1 and resolved_artist:
                # Use previously resolved artist for this directory.
                artist = resolved_artist
            elif len(artist_rows) > 1:
                # Resolve artist
                try:
                    heading = "Multiple artists names '%s'" % \
                              artist_rows[0].name
                    artist = console.selectArtist(fg.blue(heading),
                                                  choices=artist_rows,
                                                  allow_create=True)
                except PromptExit:
                    log.warn("Duplicate artist requires user "
                             "intervention to resolve.")
                    artist = None
                else:
                    if artist not in artist_rows:
                        session.add(artist)
                        session.flush()
                        print(fg.yellow("Updating artist") + ": " + name)
                    resolved_artist = artist
            else:
                # Artist match
                artist = artist_rows[0]
        else:
            # New artist
            artist = Artist(name=name)
            session.add(artist)
            session.flush()
            print(fg.green("Adding artist") + ": " + name)

        return artist, resolved_artist
Esempio n. 3
0
def promptArtist(text, name=None, default_name=None, default_city=None,
                 default_state=None, default_country=None, artist=None):
    if text:
        print(text)

    if name is None:
        name = prompt(fg.green("Artist name"), default=default_name)

    origin = {}
    for o in ("city", "state", "country"):
        origin["origin_%s" % o] = prompt("   %s" % fg.green(o.title()),
                                         default=locals()["default_%s" % o],
                                         required=False)

    if not artist:
        artist = Artist(name=name, **origin)
    else:
        artist.name = name
        for o in origin:
            setattr(artist, o, origin[o])
    return artist
Esempio n. 4
0
    def handleDirectory(self, d, _):
        audio_files = list(self._file_cache)
        self._file_cache = []

        image_files = self._dir_images
        self._dir_images = []

        if not audio_files:
            return

        d_datetime = datetime.fromtimestamp(getctime(d))

        # This directory of files can be:
        # 1) an album by a single artist (tag.artist, or tag.albun_srtist and
        #    tag.album all equal)
        # 2) a comp (tag.album equal, tag.artist differ)
        # 3) not associated with a collection (tag.artist and tag.album differ)
        artists = set([f.tag.artist for f in audio_files if f.tag])
        album_artists = set([f.tag.album_artist for f in audio_files if f.tag])
        albums = set([f.tag.album for f in audio_files if f.tag])
        for s in artists, album_artists, albums:
            if None in s:
                s.remove(None)

        is_various = (len(artists) > 1 and len(album_artists) == 0 and
                      len(albums) == 1)

        def type_hint():
            hints = set()
            for tag in [f.tag for f in audio_files if f.tag]:
                hint_frame = tag.user_text_frames.get(TXXX_ALBUM_TYPE)
                if hint_frame:
                    hints.add(hint_frame.text)
            if len(hints) > 1:
                log.warn("Inconsistent type hints: %s" % str(hints))
                return None
            else:
                return hints.pop() if hints else None

        album_type = type_hint() or LP_TYPE
        if is_various and album_type not in (None, VARIOUS_TYPE):
            # is_various overrides
            log.warn("Using type various despite files saying %s" % album_type)
        album_type = VARIOUS_TYPE if is_various else album_type

        # Used when a duplicate artist is resolved for the entire directory.
        resolved_artist = None
        resolved_album_artist = None

        album = None
        session = self._db_session
        for audio_file in audio_files:
            path = audio_file.path
            info = audio_file.info
            tag = audio_file.tag

            if not info or not tag:
                log.warn("File missing %s, skipping: %s" %
                         ("audio" if not info else "tag/metadata", path))
                continue
            elif None in (tag.title, tag.artist):
                log.warn("File missing required artist and/or title "
                         "metadata, skipping: %s" % path)
                continue

            try:
                track = session.query(Track).filter_by(path=path).one()
            except NoResultFound:
                track = None
            else:
                if datetime.fromtimestamp(getctime(path)) == track.ctime:
                    # Track is in DB and the file is not modified.
                    # stash the album though, we'll look for artwork
                    # updates later
                    album = track.album
                    continue

            # Either adding the track (track == None)
            # or modifying (track != None)

            artist, resolved_artist = self._getArtist(session, tag.artist,
                                                      resolved_artist)
            if tag.album_type != SINGLE_TYPE:
                if tag.album_artist and tag.artist != tag.album_artist:
                    album_artist, resolved_album_artist = \
                            self._getArtist(session, tag.album_artist,
                                            resolved_album_artist)
                else:
                    album_artist = artist

                if artist is None:
                    # see PromptExit
                    continue

                album_artist_id = album_artist.id if not is_various \
                                                  else VARIOUS_ARTISTS_ID
                album_rows = session.query(Album)\
                                    .filter_by(title=tag.album,
                                               artist_id=album_artist_id)\
                                    .all()
                rel_date = tag.release_date
                rec_date = tag.recording_date
                or_date = tag.original_release_date

                if album_rows:
                    if len(album_rows) > 1:
                        # This artist has more than one album with the same
                        # title.
                        raise NotImplementedError("FIXME")
                    album = album_rows[0]

                    album.type = album_type
                    album.release_date = rel_date
                    album.original_release_date = or_date
                    album.recording_date = rec_date
                    print(fg.yellow("Updating album") + ": " + album.title)
                elif tag.album:
                    album = Album(title=tag.album,
                                  artist_id=album_artist_id,
                                  type=album_type,
                                  release_date=rel_date,
                                  original_release_date=or_date,
                                  recording_date=rec_date,
                                  date_added=d_datetime)
                    session.add(album)
                    print(fg.green("Adding album") + ": " + album.title)

                session.flush()

            if not track:
                track = Track(audio_file=audio_file)
                self._num_added += 1
                print(fg.green("Adding track") + ": " + path)
            else:
                track.update(audio_file)
                self._num_modified += 1
                print(fg.yellow("Updating track") + ": " + path)

            genre = tag.genre
            genre_tag = None
            if genre:
                try:
                    genre_tag = session.query(Tag).filter_by(name=genre.name)\
                                       .one()
                except NoResultFound:
                    genre_tag = Tag(name=genre.name)
                    session.add(genre_tag)
                    session.flush()

            track.artist_id = artist.id
            track.album_id = album.id if album else None
            if genre_tag:
                track.tags.append(genre_tag)
            session.add(track)

            if album:
                # Tag images
                for img in tag.images:
                    for img_type in art.TO_ID3_ART_TYPES:
                        if img.picture_type in \
                                art.TO_ID3_ART_TYPES[img_type]:
                            break
                        img_type = None

                    if img_type is None:
                        log.warn("Skipping unsupported image type: %s" %
                                 img.picture_type)
                        continue

                    new_img = Image.fromTagFrame(img, img_type)
                    if new_img:
                        syncImage(new_img,
                                  album if img_type in IMAGE_TYPES["album"]
                                        else album.artist,
                                  session)
                    else:
                        log.warn("Invalid image in tag")

        if album:
            # Directory images.
            for img_file in image_files:
                img_type = art.matchArtFile(img_file)
                if img_type is None:
                    log.warn("Skipping unrecognized image file: %s" %
                              img_file)
                    continue

                new_img = Image.fromFile(img_file, img_type)
                if new_img:
                    new_img.description = os.path.basename(img_file)
                    syncImage(new_img, album if img_type in IMAGE_TYPES["album"]
                                             else album.artist,
                              session)
                else:
                    log.warn("Invalid image file: " + img_file)