diff options
| author | mikeos <mike.osipov@gmail.com> | 2013-09-30 04:36:57 +0400 |
|---|---|---|
| committer | mikeos <mike.osipov@gmail.com> | 2013-09-30 04:36:57 +0400 |
| commit | 0ae5a430e4f92ee7bf9e458cf584a0a12fd5c25a (patch) | |
| tree | da2f685caf97a8c51991360b97b852466f7ca765 | |
| parent | 5fb3e2f167ba4a742dc84ed58ddd68c8374a1195 (diff) | |
refactoring
| -rw-r--r-- | coding.py (renamed from utils.py) | 0 | ||||
| -rw-r--r-- | config.py | 2 | ||||
| -rw-r--r-- | cue.py | 2 | ||||
| -rw-r--r-- | cuedump.py | 8 | ||||
| -rwxr-xr-x | cutter | 439 | ||||
| -rw-r--r-- | formats/flac.py | 2 | ||||
| -rw-r--r-- | formats/mp3.py | 2 | ||||
| -rw-r--r-- | formats/ogg.py | 2 | ||||
| -rw-r--r-- | splitter.py | 403 | ||||
| -rw-r--r-- | tools.py | 26 |
10 files changed, 449 insertions, 437 deletions
@@ -1,4 +1,4 @@ -from utils import is_python_v2, to_unicode +from coding import is_python_v2, to_unicode import os try: @@ -319,7 +319,7 @@ def __read_file(filename, coding = None): return encoded -def read_cue(filename, coding = None, on_error = None): +def read(filename, coding = None, on_error = None): if on_error: def msg(fmt, *args): err = CueParserError(fmt % args) @@ -1,7 +1,7 @@ from os.path import basename import sys -from cue import read_cue +import cue if sys.version_info.major == 2: class Encoded: @@ -35,7 +35,7 @@ if len(sys.argv) != 2: sys.exit(1) try: - cue = read_cue(sys.argv[1], on_error = lambda err:\ + cuesheet = cue.read(sys.argv[1], on_error = lambda err:\ sys.stderr.write("** %s:%d: %s\n" % (progname, err.line, err)) ) except Exception as err: @@ -43,10 +43,10 @@ except Exception as err: sys.exit(1) printf("Cue attributes:\n") -for k, v in cue.attrs(): +for k, v in cuesheet.attrs(): printf("\t%s = %s\n", k, quote(v)) -for file in cue.files(filter_audio=False): +for file in cuesheet.files(filter_audio=False): printf("File %s %s\n", quote(file.name), file.type) for track in file.tracks(filter_audio=False): printf("\tTrack %d\n", track.number) @@ -1,61 +1,23 @@ #!/usr/bin/python -from utils import to_unicode, to_bytes -from cue import read_cue +from coding import to_unicode, to_bytes +from splitter import Splitter +from tools import * import formats +import cue from optparse import OptionParser, OptionGroup -from tempfile import mkdtemp -from itertools import chain -import collections -import subprocess -import shutil import sys import os -ILLEGAL_CHARACTERS_MAP = { - u"\\": u"-", - u":": u"-", - u"*": u"+", - u"?": u"_", - u'"': u"'", - u"<": u"(", - u">": u")", - u"|": u"-" -} - -progname = os.path.basename(sys.argv[0]) - -def printf(fmt, *args): - out = fmt % args - sys.stdout.write(out) - - if out[-1] != '\n': - sys.stdout.flush() - -def printerr(fmt, *args): - msg = fmt % args - if msg[-1] != "\n": - msg += "\n" - sys.stderr.write("** " + progname + ": " + msg) - -def debug(fmt, *args): - msg = fmt % args - if msg[-1] != "\n": - msg += "\n" - sys.stderr.write("-- " + msg) - try: import config except Exception as err: printerr("import config failed: %s", err) sys.exit(0) -def quote(s, ch = '"'): - return s if " " not in s else ch + s + ch - def msf(ts): m = ts / (60 * 75) s = ts / 75 % 60 @@ -63,33 +25,6 @@ def msf(ts): return "%d:%02d:%02d" % (m, s, f) -class TempLink: - def __init__(self, path, name): - self.tmpdir = mkdtemp(prefix = "temp-") - self.linkpath = "%s/%s" % (self.tmpdir, name) - - try: - os.symlink(path, self.tmpdir + "/" + name) - except Exception as err: - os.rmdir(self.tmpdir) - raise err - - def remove(self): - os.unlink(self.linkpath) - os.rmdir(self.tmpdir) - - def __repr__(self): - return "TempLink('%s')" % self.linkpath - - def __str__(self): - return self.linkpath - - def __enter__(self): - return self - - def __exit__(self, *args): - self.remove() - def print_cue(cue): for k, v in cue.attrs(): printf("%s: %s\n", k.upper(), quote(v)) @@ -271,358 +206,6 @@ def process_options(opt): return True -def filterdir(dir, prefix): - return sorted(filter(lambda f: f.startswith(prefix), os.listdir(dir))) - -def mkdir(path): - if not os.path.exists(path): - try: - os.makedirs(path) - except OSError as err: - printerr("make dir %s failed: %s", quote(path), err) - sys.exit(1) - -def convert_characters(path): - return "".join([ILLEGAL_CHARACTERS_MAP.get(ch, ch) for ch in path]) - -class StreamInfo: - __mapping = { - b"Channels:": "channels", - b"Bits/sample:": "bits_per_sample", - b"Samples/sec:": "sample_rate" - } - - @staticmethod - def get(name): - info = StreamInfo() - proc = subprocess.Popen(["shninfo", name], stdout = subprocess.PIPE) - for line in proc.stdout.readlines(): - data = line.split() - attr = StreamInfo.__mapping.get(data[0]) - if attr: - setattr(info, attr, int(data[1])) - elif line.startswith(b"Handled by:"): - info.type = to_unicode(data[2]) - - if proc.wait(): - return None - - return info - -class CueSplitter: - EXT = ["ape", "flac", "wv"] - - class File: - def __init__(self, fileobj, name, info): - self.fileobj = fileobj - self.name = name - self.info = info - - def __getattr__(self, attr): - return getattr(self.fileobj, attr) - - class TrackInfo: - def __init__(self, name, tags): - self.name = name - self.tags = tags - - @staticmethod - def format_by_tags(fmt, tags, replace=False): - if replace: - def conv(var): - if isinstance(var, str): - return var.replace("/", "-") - return var - - tags = {k: conv(v) for k, v in tags.items()} - - try: - return fmt.format(year=tags["date"], **tags) - except KeyError as err: - printerr("invalid format key: %s", err) - sys.exit(1) - except ValueError as err: - printerr("invalid format option: %s", err) - sys.exit(1) - - def __init__(self, cue, opt): - self.cue = cue - self.opt = opt - self.tracktotal = len(list(self.all_tracks())) - - self.enctype = formats.handler(opt.type, logger=printf) - self.tag_supported = self.enctype.is_tag_supported() - - self.tags = { - "album": self.opt.album or self.cue.get("title"), - "date": self.opt.date or self.cue.get("date"), - "genre": self.opt.genre or self.cue.get("genre"), - "comment": self.opt.comment or self.cue.get("comment"), - "composer": self.opt.composer - or self.cue.get("songwriter"), - "artist": self.opt.albumartist or self.opt.artist - or self.cue.get("performer"), - "albumartist": self.opt.albumartist - } - - tmp = self.format_by_tags(os.path.dirname(opt.fmt), self.tags, True) - - if opt.convert_chars: - tmp = convert_characters(tmp) - - self.dest = os.path.join(opt.dir, tmp) - track_fmt = os.path.basename(opt.fmt) - - tracknumber = 0 - self.track_info = {} - for track in self.all_tracks(): - tracknumber += 1 - self.track_info[track] = self.get_track_info( - track, tracknumber, track_fmt - ) - - def get_track_info(self, track, tracknumber, fmt): - tags = dict(self.tags) - tags.update({ - "tracknumber": tracknumber, - "tracktotal": self.tracktotal, - - "title": track.get("title") or "track", - "artist": self.opt.artist or track.get("performer") - or self.cue.get("performer"), - "composer": self.opt.composer or track.get("songwriter") - or self.cue.get("songwriter") - }) - - name = self.format_by_tags(fmt, tags).replace("/", "-") - - if self.opt.convert_chars: - name = convert_characters(name) - - return self.TrackInfo(name + "." + self.enctype.ext, tags) - - def find_realfile(self, name): - if not name.endswith(".wav"): - return None - - orig = name.rpartition(".")[0] - for file in filterdir(self.cue.dir or ".", orig): - head, _, ext = file.rpartition(".") - if head == orig and ext in self.EXT: - return file - - return None - - def open_files(self): - lst = [] - - for file in self.cue.files(): - if not file.has_audio_tracks(): - debug("skip file %s: no tracks", quote(file.name)) - continue - - name = self.cue.dir + file.name - if not os.path.exists(name): - real = self.find_realfile(file.name) - if not real: - printerr("no such file %s", quote(file.name)) - sys.exit(1) - name = self.cue.dir + real - - info = StreamInfo.get(name) - if info is None: - printerr("%s: unknown type", quote(file.name)) - sys.exit(1) - - lst.append(self.File(file, name, info)) - - return lst - - def shntool_args(self, tool, info): - encode = self.enctype.encode(self.opt, info) - return [tool, "-w", "-d", self.dest, "-o", encode] - - def track_name(self, track): - return self.track_info[track].name - - def track_tags(self, track): - return self.track_info[track].tags - - def tag(self, track, path): - if not self.tag_supported: - return - - printf("Tag [%s] : ", path) - if not self.enctype.tag(path, self.track_tags(track)): - printf("FAILED\n") - sys.exit(1) - - printf("OK\n") - - def copy_file(self, file): - noteq = lambda a, b: a and a != b - - if file.info.type != self.encode.name: - return False - if noteq(self.opt.sample_rate, file.info.sample_rate): - return False - if noteq(self.opt.bits_per_sample, file.info.bits_per_sample): - return False - if noteq(self.opt.channels, file.info.channels): - return False - - track = list(file.tracks())[0] - trackname = self.track_name(track) - path = os.path.join(self.dest, trackname) - - if self.opt.dry_run: - printf("Copy [%s] --> [%s]\n", file.name, path) - return True - - printf("Copy [%s] --> [%s] : ", file.name, path) - - try: - shutil.copyfile(file.name, path) - except Exception as err: - printf("FAILED: %s\n", err) - sys.exit(1) - else: - printf("OK\n") - - self.tag(track, path) - - return True - - def convert_file(self, file): - track = list(file.tracks())[0] - trackname = self.track_name(track) - - args = self.shntool_args("shnconv", file.info) - - if self.opt.dry_run: - name = "link to " + quote(file.name, "'") - debug("run %s", " ".join(map(quote, args + [name]))) - return - - try: - link = TempLink(os.path.abspath(file.name), trackname) - except OSError as err: - printerr("create symlink %s failed: %s", quote(trackname), err) - sys.exit(1) - - ret = subprocess.call(args + [str(link)]) - link.remove() - - if ret: - printerr("shnconv failed: exit code %d", ret); - sys.exit(1) - - self.tag(track, os.path.join(self.dest, trackname)) - - def split_file(self, file, points): - args = self.shntool_args("shnsplit", file.info) + [file.name] - - if self.opt.dry_run: - debug("run %s", " ".join(map(quote, args))) - return - - proc = subprocess.Popen(args, stdin = subprocess.PIPE) - proc.stdin.write(to_bytes("\n".join(map(str, points)))) - proc.stdin.close() - - if proc.wait(): - printerr("shnsplit failed: exit code %d", proc.returncode) - sys.exit(1) - - splitted = filterdir(self.dest, "split-track") - for track, filename in zip(file.tracks(), splitted): - trackname = self.track_name(track) - path = os.path.join(self.dest, trackname) - - printf("Rename [%s] --> [%s] : ", filename, trackname) - try: - os.rename(os.path.join(self.dest, filename), path) - except OSError as err: - printf("FAILED: %s\n", err) - sys.exit(1) - else: - printf("OK\n") - - self.tag(track, path) - - def check_duplicates(self): - names = [x.name for x in self.track_info.values()] - dup = [k for k, v in collections.Counter(names).items() if v > 1] - if dup: - printerr("track names are duplicated: %s", " ".join(dup)) - sys.exit(1) - - def transfer_files(self, source, dest): - for file in sorted(os.listdir(source)): - path = os.path.join(source, file) - if not os.path.isfile(path): - debug("skip non file %s", quote(file)) - continue - - printf("Copy [%s] into [%s] : ", file, dest) - - try: - shutil.copy(path, dest) - except Exception as err: - printf("FAILED: %s\n", err) - sys.exit(1) - else: - printf("OK\n") - - def split(self): - self.check_duplicates() - - files = self.open_files() - - self.realpath = None - if not self.opt.dry_run: - mkdir(self.dest) - if self.opt.use_tempdir: - self.realpath = self.dest - tempdir = mkdtemp(prefix="cutter-") - self.dest = to_unicode(tempdir) - - for file in files: - points = list(file.split_points(file.info)) - if not points: - if not self.copy_file(file): - self.convert_file(file) - else: - self.split_file(file, points) - - if self.realpath: - self.transfer_files(self.dest, self.realpath) - try: - shutil.rmtree(self.dest) - except Exception as err: - printerr("rm %s failed: %s\n", self.dest, err) - sys.exit(1) - - def all_tracks(self): - return chain(*[f.tracks() for f in self.cue.files()]) - - def dump_tags(self): - add_line = False - for track in self.all_tracks(): - if add_line: - printf("\n") - add_line = True - - tags = self.track_tags(track) - for k, v in sorted(tags.items()): - if v is not "": - printf("%s=%s\n", k.upper(), v) - - def dump_tracks(self): - for track in self.all_tracks(): - trackname = self.track_name(track) - printf("%s\n", os.path.join(self.dest, trackname)) - def find_cuefile(path): for file in os.listdir(path): fullname = os.path.join(path, file) @@ -653,7 +236,7 @@ def main(): debug("use cue file %s", quote(cuepath)) try: - cue = read_cue(cuepath, options.coding, on_error=on_error) + cuesheet = cue.read(cuepath, options.coding, on_error=on_error) except StopIteration: return 1 except IOError as err: @@ -669,15 +252,15 @@ def main(): return 1 - cue.dir = os.path.dirname(cuepath) - if cue.dir: - cue.dir += "/" + cuesheet.dir = os.path.dirname(cuepath) + if cuesheet.dir: + cuesheet.dir += "/" { "cue": lambda: print_cue(cue), - "tags": lambda: CueSplitter(cue, options).dump_tags(), - "tracks": lambda: CueSplitter(cue, options).dump_tracks(), - None: lambda: CueSplitter(cue, options).split() + "tags": lambda: Splitter(cuesheet, options).dump_tags(), + "tracks": lambda: Splitter(cuesheet, options).dump_tracks(), + None: lambda: Splitter(cuesheet, options).split() }[options.dump]() return 0 diff --git a/formats/flac.py b/formats/flac.py index 35db1e4..542aba2 100644 --- a/formats/flac.py +++ b/formats/flac.py @@ -1,5 +1,5 @@ from formats.__base__ import * -from utils import to_bytes +from coding import to_bytes import subprocess diff --git a/formats/mp3.py b/formats/mp3.py index cbd912f..67019cc 100644 --- a/formats/mp3.py +++ b/formats/mp3.py @@ -1,5 +1,5 @@ from formats.__base__ import * -from utils import to_bytes +from coding import to_bytes import subprocess import struct diff --git a/formats/ogg.py b/formats/ogg.py index c7352c2..464ba8b 100644 --- a/formats/ogg.py +++ b/formats/ogg.py @@ -1,5 +1,5 @@ from formats.__base__ import * -from utils import to_bytes +from coding import to_bytes import subprocess diff --git a/splitter.py b/splitter.py new file mode 100644 index 0000000..fbbafff --- /dev/null +++ b/splitter.py @@ -0,0 +1,403 @@ +from coding import to_unicode, to_bytes +from tools import * + +import formats + +from tempfile import mkdtemp +from itertools import chain + +import collections +import subprocess +import shutil +import sys +import os + +ILLEGAL_CHARACTERS_MAP = { + u"\\": u"-", + u":": u"-", + u"*": u"+", + u"?": u"_", + u'"': u"'", + u"<": u"(", + u">": u")", + u"|": u"-" +} + +def filterdir(dir, prefix): + return sorted(filter(lambda f: f.startswith(prefix), os.listdir(dir))) + +def mkdir(path): + if not os.path.exists(path): + try: + os.makedirs(path) + except OSError as err: + printerr("make dir %s failed: %s", quote(path), err) + sys.exit(1) + +def convert_characters(path): + return "".join([ILLEGAL_CHARACTERS_MAP.get(ch, ch) for ch in path]) + +class TempLink: + def __init__(self, path, name): + self.tmpdir = mkdtemp(prefix = "temp-") + self.linkpath = "%s/%s" % (self.tmpdir, name) + + try: + os.symlink(path, self.tmpdir + "/" + name) + except Exception as err: + os.rmdir(self.tmpdir) + raise err + + def remove(self): + os.unlink(self.linkpath) + os.rmdir(self.tmpdir) + + def __repr__(self): + return "TempLink('%s')" % self.linkpath + + def __str__(self): + return self.linkpath + + def __enter__(self): + return self + + def __exit__(self, *args): + self.remove() + +class StreamInfo: + __mapping = { + b"Channels:": "channels", + b"Bits/sample:": "bits_per_sample", + b"Samples/sec:": "sample_rate" + } + + @staticmethod + def get(name): + info = StreamInfo() + proc = subprocess.Popen(["shninfo", name], stdout = subprocess.PIPE) + for line in proc.stdout.readlines(): + data = line.split() + attr = StreamInfo.__mapping.get(data[0]) + if attr: + setattr(info, attr, int(data[1])) + elif line.startswith(b"Handled by:"): + info.type = to_unicode(data[2]) + + if proc.wait(): + return None + + return info + +class Splitter: + EXT = ["ape", "flac", "wv"] + + class File: + def __init__(self, fileobj, name, info): + self.fileobj = fileobj + self.name = name + self.info = info + + def __getattr__(self, attr): + return getattr(self.fileobj, attr) + + class TrackInfo: + def __init__(self, name, tags): + self.name = name + self.tags = tags + + @staticmethod + def format_by_tags(fmt, tags, replace=False): + if replace: + def conv(var): + if isinstance(var, str): + return var.replace("/", "-") + return var + + tags = {k: conv(v) for k, v in tags.items()} + + try: + return fmt.format(year=tags["date"], **tags) + except KeyError as err: + printerr("invalid format key: %s", err) + sys.exit(1) + except ValueError as err: + printerr("invalid format option: %s", err) + sys.exit(1) + + def __init__(self, cue, opt): + self.cue = cue + self.opt = opt + self.tracktotal = len(list(self.all_tracks())) + + self.enctype = formats.handler(opt.type, logger=printf) + self.tag_supported = self.enctype.is_tag_supported() + + self.tags = { + "album": self.opt.album or self.cue.get("title"), + "date": self.opt.date or self.cue.get("date"), + "genre": self.opt.genre or self.cue.get("genre"), + "comment": self.opt.comment or self.cue.get("comment"), + "composer": self.opt.composer + or self.cue.get("songwriter"), + "artist": self.opt.albumartist or self.opt.artist + or self.cue.get("performer"), + "albumartist": self.opt.albumartist + } + + tmp = self.format_by_tags(os.path.dirname(opt.fmt), self.tags, True) + + if opt.convert_chars: + tmp = convert_characters(tmp) + + self.dest = os.path.join(opt.dir, tmp) + track_fmt = os.path.basename(opt.fmt) + + tracknumber = 0 + self.track_info = {} + for track in self.all_tracks(): + tracknumber += 1 + self.track_info[track] = self.get_track_info( + track, tracknumber, track_fmt + ) + + def get_track_info(self, track, tracknumber, fmt): + tags = dict(self.tags) + tags.update({ + "tracknumber": tracknumber, + "tracktotal": self.tracktotal, + + "title": track.get("title") or "track", + "artist": self.opt.artist or track.get("performer") + or self.cue.get("performer"), + "composer": self.opt.composer or track.get("songwriter") + or self.cue.get("songwriter") + }) + + name = self.format_by_tags(fmt, tags).replace("/", "-") + + if self.opt.convert_chars: + name = convert_characters(name) + + return self.TrackInfo(name + "." + self.enctype.ext, tags) + + def find_realfile(self, name): + if not name.endswith(".wav"): + return None + + orig = name.rpartition(".")[0] + for file in filterdir(self.cue.dir or ".", orig): + head, _, ext = file.rpartition(".") + if head == orig and ext in self.EXT: + return file + + return None + + def open_files(self): + lst = [] + + for file in self.cue.files(): + if not file.has_audio_tracks(): + debug("skip file %s: no tracks", quote(file.name)) + continue + + name = self.cue.dir + file.name + if not os.path.exists(name): + real = self.find_realfile(file.name) + if not real: + printerr("no such file %s", quote(file.name)) + sys.exit(1) + name = self.cue.dir + real + + info = StreamInfo.get(name) + if info is None: + printerr("%s: unknown type", quote(file.name)) + sys.exit(1) + + lst.append(self.File(file, name, info)) + + return lst + + def shntool_args(self, tool, info): + encode = self.enctype.encode(self.opt, info) + return [tool, "-w", "-d", self.dest, "-o", encode] + + def track_name(self, track): + return self.track_info[track].name + + def track_tags(self, track): + return self.track_info[track].tags + + def tag(self, track, path): + if not self.tag_supported: + return + + printf("Tag [%s] : ", path) + if not self.enctype.tag(path, self.track_tags(track)): + printf("FAILED\n") + sys.exit(1) + + printf("OK\n") + + def copy_file(self, file): + noteq = lambda a, b: a and a != b + + if file.info.type != self.encode.name: + return False + if noteq(self.opt.sample_rate, file.info.sample_rate): + return False + if noteq(self.opt.bits_per_sample, file.info.bits_per_sample): + return False + if noteq(self.opt.channels, file.info.channels): + return False + + track = list(file.tracks())[0] + trackname = self.track_name(track) + path = os.path.join(self.dest, trackname) + + if self.opt.dry_run: + printf("Copy [%s] --> [%s]\n", file.name, path) + return True + + printf("Copy [%s] --> [%s] : ", file.name, path) + + try: + shutil.copyfile(file.name, path) + except Exception as err: + printf("FAILED: %s\n", err) + sys.exit(1) + else: + printf("OK\n") + + self.tag(track, path) + + return True + + def convert_file(self, file): + track = list(file.tracks())[0] + trackname = self.track_name(track) + + args = self.shntool_args("shnconv", file.info) + + if self.opt.dry_run: + name = "link to " + quote(file.name, "'") + debug("run %s", " ".join(map(quote, args + [name]))) + return + + try: + link = TempLink(os.path.abspath(file.name), trackname) + except OSError as err: + printerr("create symlink %s failed: %s", quote(trackname), err) + sys.exit(1) + + ret = subprocess.call(args + [str(link)]) + link.remove() + + if ret: + printerr("shnconv failed: exit code %d", ret); + sys.exit(1) + + self.tag(track, os.path.join(self.dest, trackname)) + + def split_file(self, file, points): + args = self.shntool_args("shnsplit", file.info) + [file.name] + + if self.opt.dry_run: + debug("run %s", " ".join(map(quote, args))) + return + + proc = subprocess.Popen(args, stdin = subprocess.PIPE) + proc.stdin.write(to_bytes("\n".join(map(str, points)))) + proc.stdin.close() + + if proc.wait(): + printerr("shnsplit failed: exit code %d", proc.returncode) + sys.exit(1) + + splitted = filterdir(self.dest, "split-track") + for track, filename in zip(file.tracks(), splitted): + trackname = self.track_name(track) + path = os.path.join(self.dest, trackname) + + printf("Rename [%s] --> [%s] : ", filename, trackname) + try: + os.rename(os.path.join(self.dest, filename), path) + except OSError as err: + printf("FAILED: %s\n", err) + sys.exit(1) + else: + printf("OK\n") + + self.tag(track, path) + + def check_duplicates(self): + names = [x.name for x in self.track_info.values()] + dup = [k for k, v in collections.Counter(names).items() if v > 1] + if dup: + printerr("track names are duplicated: %s", " ".join(dup)) + sys.exit(1) + + def transfer_files(self, source, dest): + for file in sorted(os.listdir(source)): + path = os.path.join(source, file) + if not os.path.isfile(path): + debug("skip non file %s", quote(file)) + continue + + printf("Copy [%s] into [%s] : ", file, dest) + + try: + shutil.copy(path, dest) + except Exception as err: + printf("FAILED: %s\n", err) + sys.exit(1) + else: + printf("OK\n") + + def split(self): + self.check_duplicates() + + files = self.open_files() + + self.realpath = None + if not self.opt.dry_run: + mkdir(self.dest) + if self.opt.use_tempdir: + self.realpath = self.dest + tempdir = mkdtemp(prefix="cutter-") + self.dest = to_unicode(tempdir) + + for file in files: + points = list(file.split_points(file.info)) + if not points: + if not self.copy_file(file): + self.convert_file(file) + else: + self.split_file(file, points) + + if self.realpath: + self.transfer_files(self.dest, self.realpath) + try: + shutil.rmtree(self.dest) + except Exception as err: + printerr("rm %s failed: %s\n", self.dest, err) + sys.exit(1) + + def all_tracks(self): + return chain(*[f.tracks() for f in self.cue.files()]) + + def dump_tags(self): + add_line = False + for track in self.all_tracks(): + if add_line: + printf("\n") + add_line = True + + tags = self.track_tags(track) + for k, v in sorted(tags.items()): + if v is not "": + printf("%s=%s\n", k.upper(), v) + + def dump_tracks(self): + for track in self.all_tracks(): + trackname = self.track_name(track) + printf("%s\n", os.path.join(self.dest, trackname)) diff --git a/tools.py b/tools.py new file mode 100644 index 0000000..69d8bdb --- /dev/null +++ b/tools.py @@ -0,0 +1,26 @@ +import sys +import os + +progname = os.path.basename(sys.argv[0]) + +def quote(s, ch = '"'): + return s if " " not in s else ch + s + ch + +def printf(fmt, *args): + out = fmt % args + sys.stdout.write(out) + + if out[-1] != '\n': + sys.stdout.flush() + +def printerr(fmt, *args): + msg = fmt % args + if msg[-1] != "\n": + msg += "\n" + sys.stderr.write("** " + progname + ": " + msg) + +def debug(fmt, *args): + msg = fmt % args + if msg[-1] != "\n": + msg += "\n" + sys.stderr.write("-- " + msg) |
