diff options
| author | mykmo <mike.osipov@gmail.com> | 2013-11-14 11:46:33 +0300 |
|---|---|---|
| committer | Mikhail Osipov <mike.osipov@gmail.com> | 2013-11-15 00:43:44 +0400 |
| commit | 62314b65546b4597031851a6decd34b6a6c61605 (patch) | |
| tree | b7a841cc48eab5ea07782337da334b6a904e9840 | |
| parent | c5d5b09048864dd5878d44a419880149aa1ff8d5 (diff) | |
new options: --export-titles-to, --import-titles-from
| -rwxr-xr-x | cutter.py | 100 | ||||
| -rw-r--r-- | cutter/splitter.py | 24 | ||||
| -rw-r--r-- | cutter/tools.py | 4 |
3 files changed, 101 insertions, 27 deletions
@@ -17,8 +17,7 @@ re_range = re.compile("^(\d+)-(\d+)$") try: from cutter import config except Exception as err: - printerr("import config failed: %s", err) - sys.exit(0) + fatal("import config failed: %s", err) def print_cue(cue): for k, v in cue.attrs(): @@ -95,8 +94,7 @@ def parse_fmt(string): def parse_type(string): if string == "help": - printerr("supported formats: " + " ".join(formats.supported())) - sys.exit(1) + fatal("supported formats: " + " ".join(formats.supported())) if not formats.issupported(string): msg = "type %r is not supported" % string @@ -104,6 +102,18 @@ def parse_type(string): return string +def read_titles(filename): + if filename == "-": + fp = sys.stdin + else: + try: + fp = open(filename) + except IOError as err: + msg = "open %s: %s" % (err.filename, err.strerror) + raise argparse.ArgumentTypeError(msg) + + return list(filter(None, [s.strip() for s in fp.readlines()])) + class HelpFormatter(argparse.HelpFormatter): def __init__(self, *args, **kwargs): kwargs["max_help_position"] = 40 @@ -210,6 +220,10 @@ def parse_args(): tag.add_argument("--track-total", type=int, dest="tracktotal", metavar="TOTAL") tag.add_argument("--track-start", type=int, dest="trackstart", metavar="START") + tag.add_argument("--export-titles-to", dest="export_titles", metavar="FILE") + tag.add_argument("--import-titles-from", type=read_titles, + dest="titles", metavar="FILE") + parser.set_defaults(**defaults) return parser.parse_args() @@ -244,6 +258,10 @@ def process_options(opt): if not os.isatty(sys.stdout.fileno()): opt.show_progress = False + if opt.dump and opt.export_titles != None: + printerr("--dump and --export-titles-to cannot be used together") + return False + return True def find_cuefile(path): @@ -252,15 +270,55 @@ def find_cuefile(path): if os.path.isfile(fullname) and file.endswith(".cue"): return os.path.normpath(fullname) - printerr("no cue file") - sys.exit(1) + fatal("no cue file") def switch(value, opts): opts.get(value, lambda: None)() def sigint_handler(sig, frame): - printf("\n") - sys.exit(1) + fatal("\n") + +def fall_on_exception(func): + def safe_method(self, *args): + try: + func(self, *args) + except Exception as exc: + if hasattr(exc, "strerror"): + msg = exc.strerror + else: + msg = str(exc) + + name = func.__name__ + fatal(name + " %s: %s", quote(self.filename), msg) + + return safe_method + +class File: + def __init__(self, filename, mode): + self.filename = filename + self.mode = mode + self.open() + + @fall_on_exception + def open(self): + self.fp = open(self.filename, self.mode) + + @fall_on_exception + def write(self, data): + self.fp.write(data) + + @fall_on_exception + def close(self): + self.fp.close() + +def write_titles(splitter, filename): + fp = File(filename, "w") if filename != "-" else sys.stdout + + for name in splitter.get_titles(): + fp.write(name + "\n") + + if fp != sys.stdout: + fp.close() def main(): signal.signal(signal.SIGINT, sigint_handler) @@ -281,25 +339,31 @@ def main(): try: cuesheet = cue.read(cuepath, options.coding, cue_error, options.ignore) except IOError as err: - printerr("open %s: %s", err.filename, err.strerror) + fatal("open %s: %s", err.filename, err.strerror) except Exception as err: msg = "%s (%s)" % (err, err.__class__.__name__) if hasattr(err, "filename"): - printerr("%s: %s: %s\n", err.filename, msg) + fatal("%s: %s: %s\n", err.filename, msg) else: - printerr("%s\n", msg) - - if not cuesheet: - return 1 + fatal("%s\n", msg) cuesheet.dir = os.path.dirname(cuepath) + if options.dump == "cue": + print_cue(cuesheet) + return 0 + + splitter = Splitter(cuesheet, options) + + if options.export_titles != None: + write_titles(splitter, options.export_titles) + return 0 + switch(options.dump, { - "cue": lambda: print_cue(cuesheet), - "tags": lambda: Splitter(cuesheet, options).dump_tags(), - "tracks": lambda: Splitter(cuesheet, options).dump_tracks(), - None: lambda: Splitter(cuesheet, options).split() + "tags": lambda: splitter.dump_tags(), + "tracks": lambda: splitter.dump_tracks(), + None: lambda: splitter.split() }) return 0 diff --git a/cutter/splitter.py b/cutter/splitter.py index 14c2097..789cb1e 100644 --- a/cutter/splitter.py +++ b/cutter/splitter.py @@ -112,7 +112,7 @@ class Splitter: sys.exit(1) def init_tags(self): - self.tracktotal = self.opt.tracktotal or len(list(self.all_tracks())) + self.tracktotal = self.opt.tracktotal or len(self.all_tracks()) self.tags = { "album": self.opt.album or self.cue.get("title"), @@ -134,12 +134,13 @@ class Splitter: self.dest = os.path.join(self.opt.dir, tmp) track_fmt = os.path.basename(self.opt.fmt) + self.titles = list(self.opt.titles) if self.opt.titles else None + tracknumber = self.opt.trackstart or 1 self.track_info = {} for track in self.all_tracks(): - self.track_info[track] = self.get_track_info( - track, tracknumber, track_fmt - ) + info = self.get_track_info(track, tracknumber, track_fmt) + self.track_info[track] = info tracknumber += 1 def __init__(self, cue, opt): @@ -153,12 +154,14 @@ class Splitter: self.init_tags() def get_track_info(self, track, tracknumber, fmt): + title = self.titles.pop(0) if self.titles else None + tags = dict(self.tags) tags.update({ "tracknumber": tracknumber, "tracktotal": self.tracktotal, - "title": track.get("title") or "track", + "title": title or 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") @@ -387,8 +390,7 @@ class Splitter: 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) + fatal("track names are duplicated: %s", " ".join(dup)) def transfer_files(self, source, dest): for file in sorted(os.listdir(source)): @@ -432,8 +434,7 @@ class Splitter: try: shutil.rmtree(self.dest) except Exception as err: - printerr("rm %s failed: %s\n", self.dest, err) - sys.exit(1) + fatal("rm %s failed: %s\n", self.dest, err) def tag_files(self): for track in self.all_tracks(): @@ -453,6 +454,11 @@ class Splitter: return self.tracks + def get_titles(self): + for track in self.all_tracks(): + tags = self.track_tags(track) + yield tags["title"] + def dump_tags(self): add_line = False for track in self.all_tracks(): diff --git a/cutter/tools.py b/cutter/tools.py index 8afbaa4..c516b49 100644 --- a/cutter/tools.py +++ b/cutter/tools.py @@ -19,6 +19,10 @@ def printerr(fmt, *args): msg += "\n" sys.stderr.write("** " + progname + ": " + msg) +def fatal(fmt, *args): + printerr(fmt, *args) + sys.exit(1) + def debug(fmt, *args): msg = fmt % args if msg[-1] != "\n": |
