vgmstream/cli/tools/txtp_segmenter.py

174 lines
6.3 KiB
Python
Raw Normal View History

2019-11-23 20:53:59 +01:00
# !/usr/bin/python
2021-10-10 11:24:03 +02:00
import os, glob, argparse, re
2019-11-23 20:53:59 +01:00
def parse():
description = (
"creates segmented .txtp from a list of files obtained using wildcards"
)
epilog = (
2021-10-10 11:24:03 +02:00
'examples:\n'
'%(prog)s bgm_*.ogg\n'
'- get all files that start with bgm_ and end with .ogg\n'
'%(prog)s bgm_??.* -n bgm_main.txtp -cla\n'
'- get all files that start with bgm_ and end with 2 chars plus any extension + loop\n'
'%(prog)s files/bgm_*_all.ogg -s\n'
'- create single .txtp per every bgm_(something)_all.ogg inside files dir\n'
'%(prog)s **/*.ogg -l\n'
'- list results only\n'
'%(prog)s files/*.ogg -fi .+(00[01])[.]ogg$\n'
'- find all .ogg in files including those that end with 0.ogg or 1.ogg\n'
'%(prog)s files/*.ogg -fe .+(a|all)[.]ogg$\n'
'- find all .ogg in files excluding those that end with a.ogg or all.ogg\n'
2022-02-13 21:18:48 +01:00
'%(prog)s files/*.* -fi "(.+)(_intro|_loop)([.].+)$" -n "\\1_full" -cla\n'
2021-10-10 11:24:03 +02:00
'- makes intro+loop .txtp named (first part without _intro/_loop)_full.txtp + loops\n'
'%(prog)s files/*.* -fe "(.+)(_intro|_loop)([.].+)$" -s\n'
'- makes single .txtp for files that don\'t have intro+loop pairs\n'
2019-11-23 20:53:59 +01:00
)
parser = argparse.ArgumentParser(description=description, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter)
2023-02-26 00:18:01 +01:00
parser.add_argument("files", help="files to match", nargs="+")
2021-10-10 11:24:03 +02:00
parser.add_argument("-n","--name", help="generated txtp name (auto from 'files' by default)\nMay use regex groups like '\\1.ogg' when used with filter-include")
parser.add_argument("-fi","--filter-include", help="include files matched with regex and ignore rest")
parser.add_argument("-fe","--filter-exclude", help="exclude files matched with regex and keep rest")
2019-11-23 20:53:59 +01:00
parser.add_argument("-s","--single", help="generate single files per list match", action='store_true')
2021-10-10 11:24:03 +02:00
parser.add_argument("-l","--list", help="list only results and don't write .txtp", action='store_true')
2023-12-30 17:04:40 +01:00
parser.add_argument("-ml","--mode-layers", help="sets layers", action='store_true')
2021-10-10 11:24:03 +02:00
parser.add_argument("-cla","--command-loop-auto", help="sets auto-loop (last segment)", action='store_true')
parser.add_argument("-clf","--command-loop-force", help="sets auto-loop (last segment) even with 1 segment", action='store_true')
2019-11-23 20:53:59 +01:00
parser.add_argument("-cls","--command-loop-start", help="sets loop start segment")
parser.add_argument("-cle","--command-loop-end", help="sets loop end segment")
parser.add_argument("-cv","--command-volume", help="sets volume")
parser.add_argument("-c","--command", help="sets any command (free text)")
2022-08-06 20:51:54 +02:00
parser.add_argument("-ci","--command-inline", help="sets any inline command (free text)")
2023-02-26 00:18:01 +01:00
parser.add_argument("-m","--multi", help="only write txtp that have multiple results", action='store_true')
2019-11-23 20:53:59 +01:00
return parser.parse_args()
2021-10-10 11:24:03 +02:00
def is_file_ok(args, file):
if not os.path.isfile(file):
2019-11-23 20:53:59 +01:00
return False
2021-10-10 11:24:03 +02:00
if file.endswith(".py"):
2019-11-23 20:53:59 +01:00
return False
2021-10-10 11:24:03 +02:00
file_test = os.path.basename(file)
if args.filter_exclude:
if args.p_exclude.match(file_test) != None:
2019-11-23 20:53:59 +01:00
return False
2021-10-10 11:24:03 +02:00
if args.filter_include:
if args.p_include.match(file_test) == None:
2019-11-23 20:53:59 +01:00
return False
return True
2021-10-10 11:24:03 +02:00
def get_txtp_name(args, file):
2019-11-23 20:53:59 +01:00
txtp_name = ''
2021-10-10 11:24:03 +02:00
if args.filter_include and args.name and '\\' in args.name:
file_test = os.path.basename(file)
txtp_name = args.p_include.sub(args.name, file_test)
elif args.name:
2019-11-23 20:53:59 +01:00
txtp_name = args.name
elif args.single:
2021-10-10 11:24:03 +02:00
txtp_name = os.path.splitext(os.path.basename(file))[0]
2019-11-23 20:53:59 +01:00
else:
2023-04-29 22:43:51 +02:00
txtp_name = os.path.splitext(os.path.basename(file))[0]
2019-11-23 20:53:59 +01:00
txtp_name = txtp_name.replace('*', '')
txtp_name = txtp_name.replace('?', '')
if txtp_name.endswith('_'):
txtp_name = txtp_name[:-1]
2021-10-10 11:24:03 +02:00
if not txtp_name:
txtp_name = 'bgm'
2019-11-23 20:53:59 +01:00
if not txtp_name.endswith(".txtp"):
txtp_name += ".txtp"
2021-10-10 11:24:03 +02:00
2019-11-23 20:53:59 +01:00
return txtp_name
def main():
args = parse()
2021-10-10 11:24:03 +02:00
if args.filter_include:
2022-02-13 21:18:48 +01:00
args.p_include = re.compile(args.filter_include, re.IGNORECASE)
2021-10-10 11:24:03 +02:00
if args.filter_exclude:
2022-02-13 21:18:48 +01:00
args.p_exclude = re.compile(args.filter_exclude, re.IGNORECASE)
2021-10-10 11:24:03 +02:00
2019-11-23 20:53:59 +01:00
# get target files
2023-02-26 00:18:01 +01:00
files = []
for file in args.files:
print(file)
files += glob.glob(file)
2019-11-23 20:53:59 +01:00
# process matches and add to output list
2021-10-10 11:24:03 +02:00
txtps = {}
for file in files:
if not is_file_ok(args, file):
2019-11-23 20:53:59 +01:00
continue
2021-10-10 11:24:03 +02:00
name = get_txtp_name(args, file)
if not name in txtps:
txtps[name] = []
2023-09-30 20:51:24 +02:00
file = file.replace('\\', '/')
2021-10-10 11:24:03 +02:00
txtps[name].append(file)
2019-11-23 20:53:59 +01:00
2021-10-10 11:24:03 +02:00
if not txtps:
2019-11-23 20:53:59 +01:00
print("no files found")
exit()
# list info
2021-10-10 11:24:03 +02:00
for name, segments in txtps.items():
2023-02-26 00:18:01 +01:00
if args.multi and len(segments) <= 1:
continue
2019-11-23 20:53:59 +01:00
print("file: " + name)
for segment in segments:
print(" " + segment)
if args.list:
exit()
# write resulting files
2021-10-10 11:24:03 +02:00
for name, segments in txtps.items():
len_segments = len(segments)
2023-02-26 00:18:01 +01:00
if args.multi and len_segments <= 1:
continue
2019-11-23 20:53:59 +01:00
with open(name,"w+") as ftxtp:
2021-10-10 11:24:03 +02:00
for i, segment in enumerate(segments):
2022-08-06 20:51:54 +02:00
command_inline = ''
if args.command_inline:
command_inline = args.command_inline.replace("\\n", "\n")
2021-10-10 11:24:03 +02:00
if args.command_loop_force and len_segments == 1:
2022-08-06 20:51:54 +02:00
txtp_line = "%s #e%s\n" % (segment, command_inline)
2021-10-10 11:24:03 +02:00
else:
2022-08-06 20:51:54 +02:00
txtp_line = "%s%s\n" % (segment, command_inline)
ftxtp.write(txtp_line)
2021-10-10 11:24:03 +02:00
2023-12-30 17:04:40 +01:00
if args.mode_layers:
ftxtp.write("mode = layers\n")
2021-10-10 11:24:03 +02:00
if args.command_loop_auto or args.command_loop_force and len_segments > 1:
ftxtp.write("loop_mode = auto\n")
2019-11-23 20:53:59 +01:00
if args.command_loop_start:
ftxtp.write("loop_start_segment = " + args.command_loop_start + "\n")
if args.command_loop_end:
ftxtp.write("loop_end_segment = " + args.command_loop_end + "\n")
if args.command_volume:
ftxtp.write("commands = #@volume " + args.command_volume + "\n")
if args.command:
2019-11-23 20:57:32 +01:00
ftxtp.write(args.command.replace("\\n", "\n") + "\n")
2019-11-23 20:53:59 +01:00
if __name__ == "__main__":
main()