コード例 #1
0
ファイル: cli.py プロジェクト: hile/musa
    def run(self, args, skip_targets=False):
        """
        Common argument parsing
        """
        args = super(MusaScriptCommand, self).parse_args(args)

        self.prefixes = TreePrefixes()

        if skip_targets:
            return [], [], []

        trees, tracks, metadata = [], [], []
        for path in args.paths:
            if os.path.isdir(path):
                trees.append(Tree(path))

            else:
                try:
                    tracks.append(Track(path))
                except TreeError:
                    match = match_metadata(path)
                    if match is not None:
                        metadata.append(match)

        tracks_found = False
        for d in trees:
            if not len(d):
                continue
            tracks_found = True
            break

        if not tracks_found and not len(tracks) and not len(metadata):
            return [], [], []

        return trees, tracks, metadata
コード例 #2
0
    def __init__(self, path):
        super(Track, self).__init__(path)

        self.prefixes = TreePrefixes()
        if self.codec is None:
            raise TreeError('Not a music file: {0}'.format(self.path))

        self.tags_loaded = False
        self.file_tags = None
コード例 #3
0
ファイル: tree.py プロジェクト: pombreda/soundforest
 def __init__(self, path, iterable):
     self.log = SoundforestLogger().default_stream
     self.__next = None
     self.__iterable = iterable
     if path in ['.', '']:
         path = os.path.realpath(path)
     self.path = path_string(path)
     self.prefixes = TreePrefixes()
     self.invalid_paths = []
     self.has_been_iterated = False
     setattr(self, iterable, [])
コード例 #4
0
class Track(AudioFileFormat):
    """Track

    Audio file track

    """

    def __init__(self, path):
        super(Track, self).__init__(path)

        self.prefixes = TreePrefixes()
        if self.codec is None:
            raise TreeError('Not a music file: {0}'.format(self.path))

        self.tags_loaded = False
        self.file_tags = None

    @property
    def tags(self):
        if not self.tags_loaded:
            try:
                self.file_tags = Tags(self.path, fileformat=self)
                self.tags_loaded = True
            except TagError as e:
                raise TreeError('Error loading tags: {0}'.format(e))

        return self.file_tags

    def relative_path(self):
        return self.prefixes.relative_path(os.path.realpath(self.path))

    @property
    def filename_no_extension(self):
        return os.path.splitext(os.path.basename(self.path))[0]

    @property
    def extension(self):
        return os.path.splitext(self.path)[1][1:]

    @property
    def album(self):
        return Album(os.path.dirname(self.path))

    @property
    def tracknumber_and_title(self):
        filename = os.path.splitext(os.path.basename(self.path))[0]

        try:
            tracknumber, title = filename.split(None, 1)
            tracknumber = int(tracknumber)
        except ValueError:
            tracknumber = None
            title = filename

        return tracknumber, title

    @property
    def checksum(self):
        with open(self.path, 'rb') as fd:
            m = hashlib.md5()
            m.update(fd.read())
            return m.hexdigest()

    def get_album_tracks(self):
        path = os.path.dirname(self.path)
        extensions = CODECS[self.codec]['extensions']
        tracks = []

        for t in os.listdir(path):
            if os.path.splitext(t)[1][1:] not in extensions:
                continue
            tracks.append(Track(os.path.join(path, t)))

        return tracks

    def get_decoder_command(self, wav_path=None):
        if wav_path is None:
            wav_path = '{0}.wav'.format(os.path.splitext(self.path)[0])
        if wav_path == self.path:
            raise TreeError('Trying to encode to itself')

        try:
            decoder = self.get_available_decoders()[0]
        except IndexError:
            raise TreeError('No available decoders for {0}'.format(self.path))

        decoder = decoder.split()
        decoder[decoder.index('OUTFILE')] = wav_path
        decoder[decoder.index('FILE')] = self.path
        return decoder

    def get_encoder_command(self, wav_path=None):
        if wav_path is None:
            wav_path = '{0}.wav'.format(os.path.splitext(self.path)[0])
        if wav_path == self.path:
            raise TreeError('Trying to encode to itself')

        try:
            encoder = self.get_available_encoders()[0]
        except IndexError:
            raise TreeError('No available encoders for {0}'.format(self.path))

        encoder = encoder.split()
        encoder[encoder.index('OUTFILE')] = self.path
        encoder[encoder.index('FILE')] = wav_path
        return encoder

    def get_tester_command(self, tempfile_path):
        try:
            tester = self.get_available_testers()[0]
        except IndexError:
            raise TreeError('No available testers for {0}'.format(self.path))

        tester = tester.split()
        tester[tester.index('FILE')] = self.path
        if tester.count('OUTFILE') == 1:
            tester[tester.index('OUTFILE')] = tempfile_path

        return tester

    def test(self, callback):
        tempfile_path = self.get_temporary_file(prefix='test', suffix='.wav')
        try:
            cmd = self.get_tester_command(tempfile_path)
        except TreeError:
            callback(self, False, errors='No tester available for {0}'.format(self.extension))
            return

        rv, stdout, stderr = self.execute(cmd)
        if rv == 0:
            callback(self, True, stdout=stdout, stderr=stderr)
        else:
            callback(self, False, stdout=stdout, stderr=stderr)

        if os.path.isfile(tempfile_path):
            try:
                os.unlink(tempfile_path)
            except IOError as e:
                raise TreeError('Error removing temporary file {0}: {1}'.format(tempfile_path, e))
            except OSError as e:
                raise TreeError('Error removing temporary file {0}: {1}'.format(tempfile_path, e))

        return rv
コード例 #5
0
class IterableTrackFolder(object):
    """IterableTrackFolder model

    Abstract class for various iterable music items

    """

    def __init__(self, path, iterable):
        self.log = SoundforestLogger().default_stream
        self.__next = None
        self.__iterable = iterable

        if path in ['.', '']:
            path = os.path.realpath(path)

        self.path = path_string(path)
        self.prefixes = TreePrefixes()
        self.invalid_paths = []
        self.has_been_iterated = False

        setattr(self, iterable, [])

    def __getitem__(self, item):
        if not self.has_been_iterated:
            self.load()
        iterable = getattr(self, self.__iterable)
        return iterable[item]

    def __len__(self):
        iterable = getattr(self, self.__iterable)
        if len(iterable) == 0:
            self.load()
        if len(iterable) - len(self.invalid_paths) >= 0:
            return len(iterable) - len(self.invalid_paths)
        else:
            return 0

    def __iter__(self):
        return self

    def next(self):
        iterable = getattr(self, self.__iterable)
        if self.__next is None:
            self.__next = 0
            self.has_been_iterated = False
            if len(iterable) == 0:
                self.load()
        try:
            entry = iterable[self.__next]
            self.__next += 1
            path = os.path.join(entry[0], entry[1])
            try:
                return Track(path)
            except TreeError:
                if not self.invalid_paths.count(path):
                    self.invalid_paths.append(path)
                return self.next()
        except IndexError:
            self.__next = None
            self.has_been_iterated = True
            raise StopIteration

    def load(self):
        """Lazy loader

        Lazy loader of the iterable item
        """
        iterable = getattr(self, self.__iterable)
        iterable.__delslice__(0, len(iterable))
        self.invalid_paths.__delslice__(0, len(self.invalid_paths))

    def relative_path(self, item=None):
        """Item relative path

        Returns relative path of this iterable item
        """

        if item is not None:
            if isinstance(item, Track):
                return self.prefixes.relative_path(item.path)
            else:
                return self.prefixes.relative_path(item)

        else:
            return self.prefixes.relative_path(self.path)

    def remove_empty_path(self, empty):
        """Remove empty directory

        Remove empty directory and all empty parent directories
        """
        while True:
            if not os.path.isdir(empty):

                # Directory does not exist
                return

            if os.listdir(empty):
                # Directory is not empty
                return

            try:
                os.rmdir(empty)
            except OSError as e:
                raise TreeError('Error removing empty directory {0}: {1}'.format(empty, e))
            except IOError as e:
                raise TreeError('Error removing empty directory {0}: {1}'.format(empty, e))

            # Try to remove parent empty directory
            empty = os.path.dirname(empty)