summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcutter.py100
-rw-r--r--cutter/splitter.py24
-rw-r--r--cutter/tools.py4
3 files changed, 101 insertions, 27 deletions
diff --git a/cutter.py b/cutter.py
index 6b0cbcd..b11365d 100755
--- a/cutter.py
+++ b/cutter.py
@@ -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":