Linglun-Converter/llc_cli.py

404 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
# 伶伦 开发交流群 861684859
"""
伶伦转换器 命令行
Linglun Converter CLI
版权所有 © 2024 金羿
Copyright © 2024 EillesWan
伶伦转换器命令行版本(“本项目”)的协议颁发者为 金羿
The Licensor of _Linglun Converter CLI_("this project") is Eilles Wan.
本项目根据 第一版 汉钰律许可协议(“本协议”)授权。
任何人皆可从以下地址获得本协议副本https://gitee.com/EillesWan/YulvLicenses。
若非因法律要求或经过了特殊准许,此作品在根据本协议“原样”提供的基础上,不予提供任何形式的担保、任何明示、任何暗示或类似承诺。也就是说,用户将自行承担因此作品的质量或性能问题而产生的全部风险。
详细的准许和限制条款请见原协议文本。
"""
__version__ = "0.0.8"
import os
import random
# import sys
import Musicreater
from Musicreater import DEFAULT_PROGRESSBAR_STYLE
from Musicreater.plugin.addonpack import (
to_addon_pack_in_delay,
to_addon_pack_in_repeater,
to_addon_pack_in_score,
)
from Musicreater.plugin.mcstructfile import (
to_mcstructure_file_in_delay,
to_mcstructure_file_in_repeater,
to_mcstructure_file_in_score,
)
from Musicreater.plugin.bdxfile import to_BDX_file_in_delay, to_BDX_file_in_score
from utils.io import logger, int_str, prt, ipt, isin, bool_str, float_str
from utils.yanlun import yanlun_texts, solar_date
# from Musicreater.plugin.mcstructure import commands_to_structure, commands_to_redstone_delay_structure
logger.console.print(
"[#121110 on #F0F2F4] ",
style="#121110 on #F0F2F4",
justify="center",
)
# osc.project_name = "伶伦转换器"
# osc.version = __version__
# if len(sys.argv) > 0:
# def go_for_args(debugMode: str = "False", logfile: str = "True"):
# global logger
# osc.isRelease = False if debugMode.lower() in ("true", "1") else True
# logger.printing = not osc.isRelease
# logger.writing = True if logfile.lower() in ("true", "1") else False
# go_for_args(*sys.argv)
# 显示大标题
logger.console.rule(
title="[bold #AB70FF]欢迎使用伶伦独立转换器", characters="=", style="#26E2FF"
)
# MainConsole.rule(title="[bold #AB70FF]Welcome to Linglun Converter", characters="-")
logger.console.rule(
title="[#AB70FF]版本{} | 音·创内核版本{}".format(
__version__, Musicreater.__version__
),
characters="-",
style="#26E2FF",
)
if solar_date == (4, 3):
# 诸葛八卦生日
style_ = "#7DB5F0 on #121110"
elif solar_date == (8, 6):
# 金羿生日快乐
style_ = "#0089F2 on #F0F2F4"
elif solar_date == (8, 16):
# 旧梦生日快乐
style_ = "#F0F2F4 on #0089F2" # TODO
else:
style_ = "#121110 on #F0F2F4"
# 显示箴言部分
logger.console.print(
"[{}]{}".format(style_, random.choice(yanlun_texts)),
style=style_,
justify="center",
)
del style_
# prt(f"{_('LangChd')}{_(':')}{_(currentLang)}")
def format_ipt(
notice: str,
fun,
err_note: str = "输入内容有误,请重新输入。",
*extraArg,
):
"""循环输入,以某种格式
notice: 输入时的提示
fun: 格式函数
err_note: 输入不符格式时的提示
*extraArg: 对于函数的其他参数"""
while True:
result = ipt(notice)
try:
fun_result = fun(result, *extraArg)
break
except ValueError:
prt(err_note)
continue
return result, fun_result
# 获取midi列表
while True:
midi_path = ipt(f"MIDI地址或所在目录地址")
try:
if os.path.exists(midi_path):
if os.path.isfile(midi_path):
midis = (midi_path,)
elif os.path.isdir(midi_path):
midis = (
os.path.join(midi_path, i)
for i in os.listdir(midi_path)
if i.lower().endswith(".mid") or i.lower().endswith(".midi")
)
else:
prt("输入内容有误,请重新输入。")
continue
else:
prt("该地址不存在,或无法访问该地址,请重新输入。")
continue
except PermissionError:
prt("无法访问该地址,请检查是否给予程序相关文件的访问权限。")
continue
break
# 获取输出地址
while True:
out_path = ipt(f"文件生成输出地址:")
try:
if not os.path.exists(out_path):
prt("该地址不存在,或无法访问该地址,请重新输入。")
continue
except PermissionError:
prt("无法访问该地址,请检查是否给予程序相关文件的访问权限。")
continue
break
# 选择输出格式
def is_in_bdx_mcpack(sth: str):
return isin(
sth.lower(),
{
1: ("bdx", "1", "币帝查", "币帝·艾克斯", "", ""),
0: ("mcpack", "0", "唉姆西·派克", "", ""),
2: ("MCSTRUCTURE", "2", "", "麦块结构", "MC结构", "", "我的世界结构"),
},
)
def is_in_player(sth: str, in_ok: tuple = (0, 1, 2)):
return isin(
sth.lower(),
dict(
[
(i, v)
for i, v in [
(
0,
("delay", "0", "延迟", "帝蕾"),
),
(
1,
("score", "1", "计分板", "积分", "积分板", "计分", "斯阔尔"),
),
(
2,
("repeater", "2", "中继器", "瑞皮特"),
),
]
if i in in_ok
]
),
)
output_file_format = format_ipt(
"输出文件类型 (mcpack/0|bdx/1|mcstructure/2)",
is_in_bdx_mcpack,
"输入内容有误,请重新输入。",
)[1]
if output_file_format == 1:
player_format = format_ipt(
"播放器类型 (延迟/0|计分板/1)",
lambda a: is_in_player(a, (0, 1)),
"输入内容有误,请重新输入。",
)[1]
else:
player_format = format_ipt(
"播放器类型 (延迟/0|计分板/1|中继器/2)",
is_in_player,
"输入内容有误,请重新输入。",
)[1]
old_exe_enabled = format_ipt(
"启用旧版代行指令 (否/0|是/1)",
bool_str,
"输入内容格式错误,应为 是/1/真/t/y 或 否/0/假/f/n",
)[1]
if os.path.exists("./demo_config.json"):
import json
prompts = json.load(open("./demo_config.json", "r", encoding="utf-8"))
prompts = prompts[:-1]
else:
prompts = []
# 提示语 检测函数 错误提示语
for args in [
(
"速度倍率 (0,+∞)",
float_str,
),
(
"最小音量 (0,1]",
float_str,
),
(
(
"自动生成进度条 (否/0|是/1)",
bool_str,
)
if output_file_format != 2
else ()
),
(
(
"计分板名称:",
str,
)
if player_format == 1
else (
"受播放玩家的选择器:",
str,
)
),
(
(
"自动重置计分板 (否/0|是/1)",
bool_str,
)
if player_format == 1
else ()
),
(
(
"BDX作者署名",
str,
)
if output_file_format == 1
else (
(
"结构延展方向 (x+|z+|x-|z-)",
lambda a: isin(
a,
{
"z+": ["z+", "Z+"],
"x+": ["X+", "x+"],
"z-": ["Z-", "z-"],
"x-": ["x-", "X-"],
},
),
)
if (player_format == 2 and output_file_format == 2)
else ()
)
),
(
(
"基础底部方块 (例concrete)",
str,
)
if (player_format == 2 and output_file_format == 2)
else (
(
"结构生成最大高度 (0,+∞)",
int_str,
)
if player_format == 0 or output_file_format != 0
else ()
)
),
]:
if args:
prompts.append(
format_ipt(
*args, err_note="输入内容格式错误,应符合 {}".format(args[1])
)[1]
)
if output_file_format != 2 and prompts[2]:
style = DEFAULT_PROGRESSBAR_STYLE
costom_pgb_enabled = format_ipt(
"自定义进度条样式 (否/0|是/1)",
bool_str,
"输入内容格式错误,应为 是/1/真/t/y 或 否/0/假/f/n",
)[1]
if costom_pgb_enabled:
base_style = ipt("基本样式组 (留空默认)")
if base_style:
style.set_base_style(base_style)
yet_part = ipt("未播放样式 (留空默认)")
if yet_part:
style.set_to_play_style(yet_part)
done_part = ipt("已播放样式 (留空默认)")
if done_part:
style.set_played_style(done_part)
else:
style = None
if output_file_format == 0:
if player_format == 1:
cvt_method = to_addon_pack_in_score
elif player_format == 0:
cvt_method = to_addon_pack_in_delay
elif player_format == 2:
cvt_method = to_addon_pack_in_repeater
elif output_file_format == 2:
if player_format == 1:
cvt_method = to_mcstructure_file_in_score
if player_format == 0:
cvt_method = to_mcstructure_file_in_delay
elif player_format == 2:
cvt_method = to_mcstructure_file_in_repeater
for singleMidi in midis:
prt("\n" f"正在处理 {singleMidi}")
cvt_mid = Musicreater.MidiConvert.from_midi_file(
midi_file_path=singleMidi,
play_speed=prompts[0],
old_exe_format=old_exe_enabled,
min_volume=prompts[1],
)
conversion_result = (
(cvt_method(cvt_mid, out_path, style, *prompts[3:])) # type: ignore
if output_file_format == 0
else (
(
to_BDX_file_in_score(cvt_mid, out_path, style, *prompts[3:])
if player_format == 1
else to_BDX_file_in_delay(cvt_mid, out_path, style, *prompts[3:])
)
if output_file_format == 1
else (cvt_method(cvt_mid, out_path, *prompts[2:]))
)
)
prt(
"\t{}{},播放刻数:{}{}".format(
"结构大小" if output_file_format == 2 else "指令总长",
conversion_result[0],
conversion_result[1],
(
",结构大小:{},末点坐标:{}".format(*conversion_result[2:])
if output_file_format == 1
else ""
),
)
)
exitSth = ipt("结束。换行以退出程序。")
if exitSth == "record":
import json
with open("./demo_config.json", "w", encoding="utf-8") as f:
json.dump(prompts, f)
elif exitSth == "delrec":
os.remove("./demo_config.json")