Beispiel #1
0
def _prompt(prompt, default=None, required=True, Type=unicode):
    yes_no = default is True or default is False

    if yes_no:
        default_str = "Yn" if default is True else "yN"
    else:
        default_str = str(default) if default else None

    if default is not None:
        prompt = "%s [%s]" % (prompt, default_str)
    prompt += ": " if not yes_no else "? "

    resp = None
    while not resp:
        if NEVER_PROMPT:
            print(prompt + "\n--no-prompt in effect, exiting.")
            sys.exit(2)
        resp = raw_input(prompt).decode(LOCAL_ENCODING)
        if not resp:
            resp = default
        elif yes_no:
            resp = True if resp in ("yes", "y", "Y") else False

        if resp is not None:
            if yes_no:
                return bool(resp)
            else:
                try:
                    return Type(resp)
                except Exception as ex:
                    printError(str(ex))
                    resp = None
        elif not required:
            return None
    def handleFile(self, f):
        super().handleFile(f)

        if len(self.args.paths) != 1:
            printError('Autotag operates on only a single album at a time')
            return

        # set album metadata once
        if self.meta is None:
            # ensure args is set in classic plugin
            self.classic.args = self.args

            # handle current directoty notation
            if self.args.paths[0] == '.':
                path = os.getcwd()
            else:
                path = self.args.paths[0]

            try:
                # extract album metadata from directory name
                self.parseDirectoryName(path)

            except AppException as e:
                printError(str(e))
                sys.exit(1)

        if not self.audio_file:
            if os.path.basename(f) != 'folder.jpg':
                printWarning('Unknown type: {}'.format(os.path.basename(f)))
        else:
            track_num, artist, title = self.smart_split(os.path.basename(f))
            self.tagFile(os.path.basename(f), track_num, artist, title)
Beispiel #3
0
    def handleFile(self, f):
        parse_version = self.args.tag_version

        super(ClassicPlugin, self).handleFile(f, tag_version=parse_version)

        if not self.audio_file:
            return

        self.printHeader(f)
        printMsg("-" * 79)

        new_tag = False
        if (not self.audio_file.tag or
                self.handleRemoves(self.audio_file.tag)):
            self.audio_file.initTag(version=parse_version)
            new_tag = True

        save_tag = (self.handleEdits(self.audio_file.tag) or
                    self.args.force_update or self.args.convert_version)

        self.printAudioInfo(self.audio_file.info)

        if not save_tag and new_tag:
            printError("No ID3 %s tag found!" %
                       id3.versionToString(self.args.tag_version))
            return

        self.printTag(self.audio_file.tag)

        if save_tag:
            # Use current tag version unless a convert was supplied
            version = (self.args.convert_version or
                       self.audio_file.tag.version)
            printWarning("Writing ID3 version %s" %
                         id3.versionToString(version))

            self.audio_file.tag.save(
                    version=version, encoding=self.args.text_encoding,
                    backup=self.args.backup,
                    preserve_file_time=self.args.preserve_file_time)

        if self.args.rename_pattern:
            # Handle file renaming.
            from eyed3.id3.tag import TagTemplate
            template = TagTemplate(self.args.rename_pattern)
            name = template.substitute(self.audio_file.tag, zeropad=True)
            orig = self.audio_file.path
            try:
                self.audio_file.rename(name)
                printWarning("Renamed '%s' to '%s'" %
                             (orig, self.audio_file.path))
            except IOError as ex:
                printError(ex.message)

        printMsg("-" * 79)
Beispiel #4
0
    def handleFile(self, f, *args, **kwargs):
        if self.args.pattern_help:
            return
        if self.__return_code != 0:
            return

        super(DisplayPlugin, self).handleFile(f)
        if not self.audio_file:
            return

        try:
            print(self.__pattern.output_for(self.audio_file),
                  end=self.__output_ending)
        except PatternCompileException as e:
            self.__return_code = 1
            console.printError(e.message)
        except DisplayException as e:
            self.__return_code = 1
            console.printError(e.message)
Beispiel #5
0
    def handleFile(self, f, *args, **kwargs):
        '''Loads ``f`` and sets ``self.audio_file`` to an instance of
        :class:`eyed3.core.AudioFile` or ``None`` if an error occurred or the
        file is not a recognized type.

        The ``*args`` and ``**kwargs`` are passed to :func:`eyed3.core.load`.
        '''
        self.audio_file = None

        try:
            self.audio_file = core.load(f, *args, **kwargs)
        except NotImplementedError as ex:
            # Frame decryption, for instance...
            printError(str(ex))
            return

        if self.audio_file:
            self._num_loaded += 1
            if self._file_cache is not None:
                self._file_cache.append(self.audio_file)
Beispiel #6
0
    def start(self, args, config):
        super(DisplayPlugin, self).start(args, config)

        if args.pattern_help:
            self.__print_pattern_help()
            return

        if not _have_grako:
            console.printError(u"Unknown module 'grako'" + os.linesep +
                               u"Please install grako! " +
                               u"E.g. $ pip install grako")
            self.__return_code = 2
            return

        if args.pattern_string is not None:
            self.__pattern = Pattern(args.pattern_string)
        if args.pattern_file is not None:
            pfile = open(args.pattern_file, "r")
            self.__pattern = Pattern(''.join(pfile.read().splitlines()))
            pfile.close()
        self.__output_ending = "" if args.no_newline else os.linesep
Beispiel #7
0
    def _run(self):
        session = self.db_session

        _output = []

        def _addOutput(_k, _v):
            _output.append(tuple((_k, _v)))

        def _printOutput(_format, _olist, key_fg=None):
            k_width = max([len(k) for k, v in _olist if k])
            for k, v in _olist:
                print(_format % (cformat(k.ljust(k_width), key_fg), v)
                        if k else "")
            _olist.clear()

        cprint(figlet_format("``MishMash``", font="graffiti"), Fore.GREEN,
                styles=[Style.BRIGHT])

        _addOutput("Version", version)
        _addOutput("Database URL", self.config.db_url)

        try:
            meta = session.query(Meta).one()
        except (ProgrammingError, OperationalError) as ex:
            printError("\nError querying metadata. Database may not be "
                       "initialized: %s" % str(ex))
            return 1

        _addOutput("Database version", meta.version)
        _addOutput("Last sync", meta.last_sync or "Never")
        _addOutput("Configuration file ", self.args.config.filename or "None")
        _printOutput("%s : %s", _output, key_fg=Fore.BLUE)

        _addOutput(None, None)
        for name, orm_type in [("tracks", Track), ("artists", Artist),
                              ("albums", Album), ("tags", Tag),
                     ]:
            count = session.query(orm_type).count()
            _addOutput(str(count), name)
        _printOutput("%s music %s", _output)
    def handleFile(self, f, *args, **kwargs):
        """Loads ``f`` and sets ``self.audio_file`` to an instance of
        :class:`eyed3.core.AudioFile` or ``None`` if an error occurred or the
        file is not a recognized type.

        The ``*args`` and ``**kwargs`` are passed to :func:`eyed3.core.load`.
        """
        self.audio_file = None

        try:
            self.audio_file = core.load(f, *args, **kwargs)
        except NotImplementedError as ex:
            # Frame decryption, for instance...
            printError(str(ex))
            return

        if self.audio_file:
            self._num_loaded += 1
            if self._file_cache is not None:
                self._file_cache.append(self.audio_file)
        elif self._dir_images is not None:
            mt = guessMimetype(f)
            if mt and mt.startswith("image/"):
                self._dir_images.append(f)
Beispiel #9
0
    def handleFile(self, f, *args, **kwargs):
        '''Loads ``f`` and sets ``self.audio_file`` to an instance of
        :class:`eyed3.core.AudioFile` or ``None`` if an error occurred or the
        file is not a recognized type.

        The ``*args`` and ``**kwargs`` are passed to :func:`eyed3.core.load`.
        '''
        self.audio_file = None

        try:
            self.audio_file = core.load(f, *args, **kwargs)
        except NotImplementedError as ex:
            # Frame decryption, for instance...
            printError(str(ex))
            return

        if self.audio_file:
            self._num_loaded += 1
            if self._file_cache is not None:
                self._file_cache.append(self.audio_file)
        elif self._dir_images is not None:
            mt = guessMimetype(f)
            if mt and mt.startswith("image/"):
                self._dir_images.append(f)
Beispiel #10
0
from __future__ import print_function
import os
import re
import abc

from argparse import ArgumentTypeError

from eyed3 import id3
from eyed3.utils import console, formatSize, formatTime
from eyed3.plugins import LoaderPlugin
try:
    from eyed3.plugins._display_parser import DisplayPatternParser
    _have_grako = True
except ImportError:
    _have_grako = False
    console.printError(u"Unknown module 'grako'" + os.linesep +
                       u"Please install grako! E.g. with $ pip install grako")


class Pattern(object):
    def __init__(self, text=None, sub_patterns=None):
        self.__text = text
        self.__sub_patterns = sub_patterns

    def output_for(self, audio_file):
        output = u""
        for sub_pattern in self.sub_patterns or []:
            output += sub_pattern.output_for(audio_file)
        return output

    def __get_sub_patterns(self):
        if self.__sub_patterns is None and self.__text is not None:
Beispiel #11
0
    def handleEdits(self, tag):
        retval = False

        # --remove-all-*, Handling removes first means later options are still
        # applied
        for what, arg, fid in (("comments", self.args.remove_all_comments,
                                id3.frames.COMMENT_FID),
                               ("lyrics", self.args.remove_all_lyrics,
                                id3.frames.LYRICS_FID),
                               ("images", self.args.remove_all_images,
                                id3.frames.IMAGE_FID),
                               ("objects", self.args.remove_all_objects,
                                id3.frames.OBJECT_FID),
                               ):
            if arg and tag.frame_set[fid]:
                printWarning("Removing all %s..." % what)
                del tag.frame_set[fid]
                retval = True

        # --artist, --title, etc. All common/simple text frames.
        for (what, arg, setFunc) in (
                ("artist", self.args.artist, tag._setArtist),
                ("album", self.args.album, tag._setAlbum),
                ("title", self.args.title, tag._setTitle),
                ("genre", self.args.genre, tag._setGenre),
                ("release date", self.args.release_date, tag._setReleaseDate),
                ("original release date", self.args.orig_release_date,
                 tag._setOrigReleaseDate),
                ("recording date", self.args.recording_date,
                 tag._setRecordingDate),
                ("encoding date", self.args.encoding_date,
                 tag._setEncodingDate),
                ("tagging date", self.args.tagging_date,
                 tag._setTaggingDate),
                ("beats per minute", self.args.bpm, tag._setBpm),
                ("publisher", self.args.publisher, tag._setPublisher),
            ):
            if arg is not None:
                printWarning("Setting %s: %s" % (what, arg))
                setFunc(arg or None)
                retval = True

        def _checkNumberedArgTuples(curr, new):
            n = None
            if new not in [(None, None), curr]:
                n = [None] * 2
                for i in (0, 1):
                    if new[i] == 0:
                        n[i] = None
                    else:
                        n[i] = new[i] or curr[i]
                n = tuple(n)
            # Returing None means do nothing, (None, None) would clear both vals
            return n

        # --track, --track-total
        track_info = _checkNumberedArgTuples(tag.track_num,
                                             (self.args.track,
                                              self.args.track_total))
        if track_info is not None:
            printWarning("Setting track info: %s" % str(track_info))
            tag.track_num = track_info
            retval = True

        # --disc-num, --disc-total
        disc_info = _checkNumberedArgTuples(tag.disc_num,
                                            (self.args.disc_num,
                                             self.args.disc_total))
        if disc_info is not None:
            printWarning("Setting disc info: %s" % str(disc_info))
            tag.disc_num = disc_info
            retval = True

        # -Y, --release-year
        if self.args.release_year is not None:
            # empty string means clean, None means not given
            year = self.args.release_year
            printWarning("Setting release year: %s" % year)
            tag.release_date = int(year) if year else None
            retval = True

        # -c , simple comment
        if self.args.simple_comment:
            # Just add it as if it came in --add-comment
            self.args.comments.append((self.args.simple_comment, u"",
                                       id3.DEFAULT_LANG))

        # --remove-comment, remove-lyrics, --remove-image, --remove-object
        for what, arg, accessor in (("comment", self.args.remove_comment,
                                     tag.comments),
                                    ("lyrics", self.args.remove_lyrics,
                                     tag.lyrics),
                                    ("image", self.args.remove_image,
                                     tag.images),
                                    ("object", self.args.remove_object,
                                     tag.objects),
                                   ):
            for vals in arg:
                frame = accessor.remove(*vals)
                if frame:
                    printWarning("Removed %s %s" % (what, str(vals)))
                    retval = True
                else:
                    printError("Removing %s failed, %s not found" %
                               (what, str(vals)))

        # --add-comment, --add-lyrics
        for what, arg, accessor in (("comment", self.args.comments,
                                     tag.comments),
                                    ("lyrics", self.args.lyrics, tag.lyrics),
                                   ):
            for text, desc, lang in arg:
                printWarning("Setting %s: %s/%s" % (what, desc, lang))
                accessor.set(text, desc, lang)
                retval = True

        # --play-count
        playcount_arg = self.args.play_count
        if playcount_arg:
            increment, pc = playcount_arg
            if increment:
                printWarning("Incrementing play count by %d" % pc)
                tag.play_count += pc
            else:
                printWarning("Setting play count to %d" % pc)
                tag.play_count = pc
            retval = True

        # --add-popularty
        for email, rating, play_count in self.args.popularities:
            tag.popularities.set(email, rating, play_count)
            retval = True

        # --remove-popularity
        for email in self.args.remove_popularity:
            popm = tag.popularities.remove(email)
            if popm:
                retval = True

        # --text-frame, --url-frame
        for what, arg, setter in (
                ("text frame", self.args.text_frames, tag.setTextFrame),
                ("url frame", self.args.url_frames, tag._setUrlFrame),
            ):
            for fid, text in arg:
                if text:
                    printWarning("Setting %s %s to '%s'" % (fid, what, text))
                else:
                    printWarning("Removing %s %s" % (fid, what))
                setter(fid, text)
                retval = True

        # --user-text-frame, --user-url-frame
        for what, arg, accessor in (
                ("user text frame", self.args.user_text_frames,
                 tag.user_text_frames),
                ("user url frame", self.args.user_url_frames,
                 tag.user_url_frames),
            ):
            for desc, text in arg:
                if text:
                    printWarning("Setting '%s' %s to '%s'" % (desc, what, text))
                    accessor.set(text, desc)
                else:
                    printWarning("Removing '%s' %s" % (desc, what))
                    accessor.remove(desc)
                retval = True

        # --add-image
        for img_path, img_type, img_mt, img_desc in self.args.images:
            assert(img_path)
            printWarning("Adding image %s" % img_path)
            if img_mt != ImageFrame.URL_MIME_TYPE:
                with open(img_path, "rb") as img_fp:
                    tag.images.set(img_type, img_fp.read(), img_mt, img_desc)
            else:
                tag.images.set(img_type, None, None, img_desc, img_url=img_path)
            retval = True

        # --add-object
        for obj_path, obj_mt, obj_desc, obj_fname in self.args.objects or []:
            assert(obj_path)
            printWarning("Adding object %s" % obj_path)
            with open(obj_path, "rb") as obj_fp:
                tag.objects.set(obj_fp.read(), obj_mt, obj_desc, obj_fname)
            retval = True

        # --unique-file-id
        for arg in self.args.unique_file_ids:
            owner_id, id = arg
            if not id:
                if tag.unique_file_ids.remove(owner_id):
                    printWarning("Removed unique file ID '%s'" % owner_id)
                    retval = True
                else:
                    printWarning("Unique file ID '%s' not found" % owner_id)
            else:
                tag.unique_file_ids.set(id, owner_id)
                printWarning("Setting unique file ID '%s' to %s" %
                              (owner_id, id))
                retval = True

        # --remove-frame
        for fid in self.args.remove_fids:
            if fid in tag.frame_set:
                del tag.frame_set[fid]
                retval = True

        return retval
Beispiel #12
0
    def handleFile(self, f):
        parse_version = self.args.tag_version

        super(ClassicPlugin, self).handleFile(f, tag_version=parse_version)

        if not self.audio_file:
            return

        self.printHeader(f)
        printMsg("-" * 79)

        new_tag = False
        if not self.audio_file.tag or self.handleRemoves(self.audio_file.tag):
            self.audio_file.initTag(version=parse_version)
            new_tag = True

        save_tag = (
            self.handleEdits(self.audio_file.tag)
            or self.handlePadding(self.audio_file.tag)
            or self.args.force_update
            or self.args.convert_version
        )

        self.printAudioInfo(self.audio_file.info)

        if not save_tag and new_tag:
            printError("No ID3 %s tag found!" % id3.versionToString(self.args.tag_version))
            return

        self.printTag(self.audio_file.tag)

        if save_tag:
            # Use current tag version unless a convert was supplied
            version = self.args.convert_version or self.audio_file.tag.version
            printWarning("Writing ID3 version %s" % id3.versionToString(version))

            # DEFAULT_MAX_PADDING is not set up as argument default,
            # because we don't want to rewrite the file if the user
            # did not trigger that explicitly:
            max_padding = self.args.max_padding
            if max_padding is True:
                max_padding = DEFAULT_MAX_PADDING

            self.audio_file.tag.save(
                version=version,
                encoding=self.args.text_encoding,
                backup=self.args.backup,
                preserve_file_time=self.args.preserve_file_time,
                max_padding=max_padding,
            )

        if self.args.rename_pattern:
            # Handle file renaming.
            from eyed3.id3.tag import TagTemplate

            template = TagTemplate(self.args.rename_pattern)
            name = template.substitute(self.audio_file.tag, zeropad=True)
            orig = self.audio_file.path
            try:
                self.audio_file.rename(name)
                printWarning("Renamed '%s' to '%s'" % (orig, self.audio_file.path))
            except IOError as ex:
                printError(ex.message)

        printMsg("-" * 79)