diff options
| author | mikeos <mike.osipov@gmail.com> | 2013-07-24 21:07:41 +0400 |
|---|---|---|
| committer | mikeos <mike.osipov@gmail.com> | 2013-07-24 21:07:41 +0400 |
| commit | a14955d8a5741ec382d9b128b69053cf4141f993 (patch) | |
| tree | 9e9fcfc983d05ea794e842c8a29da344bc21f701 | |
| parent | ad7ed713f4a968dbdb7ddc149e56677c6cc5fd2a (diff) | |
replace illegal characters in filename
| -rw-r--r-- | TODO | 2 | ||||
| -rw-r--r-- | config.py | 3 | ||||
| -rwxr-xr-x | cutter | 94 |
3 files changed, 77 insertions, 22 deletions
@@ -4,4 +4,4 @@ OK 3. write tags to the splitted files OK 4. specify output file format including path OK 5. add support of config file with default options OK 6. copy file instead of convert if possible -7. substitute odd symbols in track names +OK 7. substitute odd symbols in track names @@ -50,4 +50,5 @@ SAMPLE_RATE = cfg.getint("output", "sample_rate") CHANNELS = cfg.getint("output", "channels") BITS_PER_SAMPLE = cfg.getint("output", "bits_per_sample") -FILENAME_FORMAT = cfg.get("encoding", "format", DEFAULT_FILENAME_FORMAT) +FILENAME_FORMAT = cfg.get("filename", "format", DEFAULT_FILENAME_FORMAT) +CONVERT_CHARS = cfg.getbool("filename", "convert_chars", False) @@ -13,6 +13,17 @@ import collections 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): @@ -36,7 +47,7 @@ except Exception as err: printerr("import config failed: %s", err) sys.exit(0) -def quote(s, ch = "\""): +def quote(s, ch = '"'): return s if " " not in s else ch + s + ch def msf(ts): @@ -124,10 +135,6 @@ def parse_args(): enc = OptionGroup(parser, "Encoding options") - enc.add_option("--format", - dest="fmt", default=config.FILENAME_FORMAT, - help="the format string for new filenames") - enc.add_option("-d", "--dir", dest="dir", default=config.DIR, help="output directory") @@ -137,6 +144,22 @@ def parse_args(): parser.add_option_group(enc) + fname = OptionGroup(parser, "Filename options") + + fname.add_option("--format", + dest="fmt", default=config.FILENAME_FORMAT, + help="the format string for new filenames") + + fname.add_option("--convert-chars", + dest="convert_chars", action="store_true", + help="replace illegal characters in filename") + + fname.add_option("--no-convert-chars", + dest="convert_chars", action="store_false", + help="do not replace characters in filename") + + parser.add_option_group(fname) + format = OptionGroup(parser, "Output format") format.add_option("-r", "--sample-rate", type="int", @@ -161,17 +184,27 @@ def parse_args(): return parser.parse_args() -def verify_options(opt): +def process_options(opt): if opt.compression is not None and opt.compression < 0 or opt.compression > 8: printerr("invalid compression value %d, must be in range 0 .. 8", opt.compression) sys.exit(1) - opt.dir = u"." if not opt.dir else to_unicode(opt.dir) - opt.fmt = to_unicode(opt.fmt) + if not opt.dir: + opt.dir = u"." + else: + opt.dir = to_unicode(os.path.normpath(opt.dir)) + opt.fmt = to_unicode(opt.fmt) if not os.path.basename(opt.fmt): printerr("invalid format option \"%s\"", opt.fmt) sys.exit(1) + else: + opt.fmt = os.path.normpath(opt.fmt) + if opt.fmt.startswith("/"): + opt.fmt = opt.fmt[1:] + + if opt.convert_chars is None: + opt.convert_chars = config.CONVERT_CHARS def get_encoder_formart(opt, info): cmd = "flac sox - " @@ -196,6 +229,9 @@ def mkdir(path): 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", @@ -238,6 +274,25 @@ class CueSplitter: 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 @@ -255,11 +310,10 @@ class CueSplitter: "albumartist": self.opt.albumartist } - try: - tmp = os.path.dirname(opt.fmt).format(**self.tags) - except KeyError as err: - printerr("invalid format key: %s", err) - sys.exit(1) + 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) @@ -282,15 +336,15 @@ class CueSplitter: "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") }) - try: - name = fmt.format(**tags) + "." + self.TRACK_SUFFIX - except KeyError as err: - printerr("invalid format key: %s", err) - sys.exit(1) + name = self.format_by_tags(fmt, tags).replace("/", "-") + + if self.opt.convert_chars: + name = convert_characters(name) - return self.TrackInfo(name, tags) + return self.TrackInfo(name + "." + self.TRACK_SUFFIX, tags) def find_realfile(self, name): if not name.endswith(".wav"): @@ -494,7 +548,7 @@ class CueSplitter: def main(): options, args = parse_args() - verify_options(options) + process_options(options) if len(args) != 1: printf("Usage: %s [options] cuefile\n", progname) |
