Random track group are now supported in ct_config.json, cup icons can now be named by the cup name, custom track cup now start at 001
|
@ -1805,6 +1805,37 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tracks_list":[
|
"tracks_list":[
|
||||||
|
{
|
||||||
|
"name":"4IT Clown's Road",
|
||||||
|
"author":[
|
||||||
|
"4IT★Lecce",
|
||||||
|
"4IT★Clown"
|
||||||
|
],
|
||||||
|
"special":"T82",
|
||||||
|
"music":"T82",
|
||||||
|
"score":2,
|
||||||
|
"since_version":"0.8",
|
||||||
|
"sha1":"f9dbbaca67b7a26c7986a6e99c2a56cf9fdfa14f",
|
||||||
|
"version":"v1.2",
|
||||||
|
"family":2700,
|
||||||
|
"tags":[
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"8'n Infinite Race",
|
||||||
|
"author":"Bulzeeb",
|
||||||
|
"special":"T11",
|
||||||
|
"music":"T21",
|
||||||
|
"score":2,
|
||||||
|
"since_version":"0.7",
|
||||||
|
"sha1":"3566c3453af382ac13b9db813d8b44286d1e281f",
|
||||||
|
"version":"v1.1",
|
||||||
|
"family":3020,
|
||||||
|
"tags":[
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"4IT Clown's Road",
|
"name":"4IT Clown's Road",
|
||||||
"author":[
|
"author":[
|
||||||
|
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
|
@ -155,6 +155,7 @@
|
||||||
"bmg_patch_dir": "/generated/",
|
"bmg_patch_dir": "/generated/",
|
||||||
"cup_icon_dir": "/cup_icon/",
|
"cup_icon_dir": "/cup_icon/",
|
||||||
"lecode_bin_dir": "/essentials/",
|
"lecode_bin_dir": "/essentials/",
|
||||||
"lpar_dir": "/essentials/"
|
"lpar_dir": "/essentials/",
|
||||||
|
"track_dir": "/Track-WU8/"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,16 +1,16 @@
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image
|
||||||
import math
|
import math
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from source.Cup import Cup
|
from source.Cup import Cup
|
||||||
from source.Track import Track, HiddenTrackAttr
|
from source.Track import Track, get_trackdata_from_json
|
||||||
|
|
||||||
|
|
||||||
class CT_Config:
|
class CT_Config:
|
||||||
def __init__(self, version: str = None, name: str = None, nickname: str = None,
|
def __init__(self, version: str = None, name: str = None, nickname: str = None,
|
||||||
game_variant: str = "01", gui=None, region: int = None, cheat_region: int = None,
|
game_variant: str = "01", gui=None, region: int = None, cheat_region: int = None,
|
||||||
tags_color: dict = {}, prefix_list: list = [], suffix_list: list = [],
|
tags_color: dict = None, prefix_list: list = None, suffix_list: list = None,
|
||||||
tag_retro: str = "Retro", default_track: Track = None, pack_path: str = "",
|
tag_retro: str = "Retro", default_track: Track = None, pack_path: str = "",
|
||||||
file_process: dict = None, file_structure: dict = None):
|
file_process: dict = None, file_structure: dict = None):
|
||||||
|
|
||||||
|
@ -23,12 +23,11 @@ class CT_Config:
|
||||||
|
|
||||||
self.ordered_cups = []
|
self.ordered_cups = []
|
||||||
self.unordered_tracks = []
|
self.unordered_tracks = []
|
||||||
self.all_tracks = []
|
|
||||||
self.all_version = {version}
|
|
||||||
self.gui = gui
|
self.gui = gui
|
||||||
self.tags_color = tags_color
|
|
||||||
self.prefix_list = prefix_list
|
self.tags_color = tags_color if tags_color else {}
|
||||||
self.suffix_list = suffix_list
|
self.prefix_list = prefix_list if tags_color else []
|
||||||
|
self.suffix_list = suffix_list if tags_color else []
|
||||||
self.tag_retro = tag_retro
|
self.tag_retro = tag_retro
|
||||||
self.default_track = default_track
|
self.default_track = default_track
|
||||||
|
|
||||||
|
@ -43,9 +42,6 @@ class CT_Config:
|
||||||
:param cup: a Cup object to add as an ordered cup
|
:param cup: a Cup object to add as an ordered cup
|
||||||
"""
|
"""
|
||||||
self.ordered_cups.append(cup)
|
self.ordered_cups.append(cup)
|
||||||
for track in cup.tracks:
|
|
||||||
self.all_version.add(track.since_version)
|
|
||||||
self.all_tracks.append(track)
|
|
||||||
|
|
||||||
def add_unordered_track(self, track: Track) -> None:
|
def add_unordered_track(self, track: Track) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -53,13 +49,19 @@ class CT_Config:
|
||||||
:param track: a Track object to add as an unordered tracks
|
:param track: a Track object to add as an unordered tracks
|
||||||
"""
|
"""
|
||||||
self.unordered_tracks.append(track)
|
self.unordered_tracks.append(track)
|
||||||
self.all_version.add(track.since_version)
|
|
||||||
self.all_tracks.append(track)
|
|
||||||
|
|
||||||
def create_ctfile(self, directory: str = "./file/", highlight_version: str = None, sort_track_by: str = None) -> None:
|
def unordered_tracks_to_cup(self):
|
||||||
|
track_in_cup: int = 4
|
||||||
|
|
||||||
|
for cup_id, track_id in enumerate(range(0, len(self.unordered_tracks), track_in_cup), start=1):
|
||||||
|
cup = Cup(id=cup_id, name=f"CT{cup_id}")
|
||||||
|
for index, track in enumerate(self.unordered_tracks[track_id:track_id + track_in_cup]):
|
||||||
|
cup.tracks[index] = track
|
||||||
|
yield cup
|
||||||
|
|
||||||
|
def create_ctfile(self, directory: str = "./file/", highlight_version: str = None) -> None:
|
||||||
"""
|
"""
|
||||||
create a ctfile configuration in a directory
|
create a ctfile configuration in a directory
|
||||||
:param sort_track_by: by which property will track be sorted
|
|
||||||
:param highlight_version: highlight a specific version in light blue
|
:param highlight_version: highlight a specific version in light blue
|
||||||
:param directory: create CTFILE.txt and RCTFILE.txt in this directory
|
:param directory: create CTFILE.txt and RCTFILE.txt in this directory
|
||||||
"""
|
"""
|
||||||
|
@ -74,54 +76,31 @@ class CT_Config:
|
||||||
)
|
)
|
||||||
ctfile.write(header); rctfile.write(header)
|
ctfile.write(header); rctfile.write(header)
|
||||||
|
|
||||||
# generate cup for undefined track
|
|
||||||
unordered_cups = []
|
|
||||||
|
|
||||||
star_value = []
|
|
||||||
if not self.gui.boolvar_use_1star_track.get(): star_value.append(1)
|
|
||||||
if not self.gui.boolvar_use_2star_track.get(): star_value.append(2)
|
|
||||||
if not self.gui.boolvar_use_3star_track.get(): star_value.append(3)
|
|
||||||
|
|
||||||
track_list = self.search_tracks(not_value=True, values_list=True,
|
|
||||||
only_unordered_track=True, score=star_value)
|
|
||||||
if sort_track_by:
|
|
||||||
track_list.sort(key=lambda track: getattr(track, sort_track_by, None))
|
|
||||||
|
|
||||||
for i, track in enumerate(track_list):
|
|
||||||
if i % 4 == 0:
|
|
||||||
_actual_cup = Cup(name=f"TL{i // 4}", default_track=self.default_track)
|
|
||||||
unordered_cups.append(_actual_cup)
|
|
||||||
_actual_cup.tracks[i % 4] = track
|
|
||||||
|
|
||||||
# all cups
|
# all cups
|
||||||
for cup in self.ordered_cups + unordered_cups:
|
for cup in self.get_all_cups():
|
||||||
kwargs = {"highlight_version": highlight_version, "ct_config": self}
|
kwargs = {"highlight_version": highlight_version, "ct_config": self}
|
||||||
ctfile.write(cup.get_ctfile_cup(race=False, **kwargs))
|
ctfile.write(cup.get_ctfile(race=False, **kwargs))
|
||||||
rctfile.write(cup.get_ctfile_cup(race=True, **kwargs))
|
rctfile.write(cup.get_ctfile(race=True, **kwargs))
|
||||||
|
|
||||||
def get_cup_icon(self, cup_id: [str, int], font_path: str = "./assets/SuperMario256.ttf") -> Image:
|
def get_tracks(self):
|
||||||
"""
|
for data in self.unordered_tracks + self.ordered_cups:
|
||||||
:param cup_id: id of the cup
|
for track in data.get_tracks(): yield track
|
||||||
:param font_path: path to the font used to generate icon
|
|
||||||
:return: cup icon
|
|
||||||
"""
|
|
||||||
|
|
||||||
dir = self.file_process['placement'].get('cup_icon_dir')
|
def search_tracks(self, **condition):
|
||||||
if not dir: dir = "/ct_icons/"
|
for track in self.get_tracks():
|
||||||
cup_icon_dir = f"{self.pack_path}/file/{dir}/"
|
for property, (possibility, filter_func) in condition.items():
|
||||||
|
if not filter_func: filter_func = lambda a, b: a == b
|
||||||
|
if not filter_func(getattr(track, property, None), possibility):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
yield track
|
||||||
|
|
||||||
if os.path.exists(f"{cup_icon_dir}/{cup_id}.png"):
|
def get_cup_count(self) -> int:
|
||||||
cup_icon = Image.open(f"{cup_icon_dir}/{cup_id}.png").resize((128, 128))
|
return math.ceil(len(self.unordered_tracks) / 4) + len(self.ordered_cups)
|
||||||
|
|
||||||
else:
|
def get_all_cups(self):
|
||||||
cup_icon = Image.new("RGBA", (128, 128))
|
for cup in self.ordered_cups: yield cup
|
||||||
draw = ImageDraw.Draw(cup_icon)
|
for cup in self.unordered_tracks_to_cup(): yield cup
|
||||||
font = ImageFont.truetype(font_path, 90)
|
|
||||||
draw.text((4, 4), "CT", (255, 165, 0), font=font, stroke_width=2, stroke_fill=(0, 0, 0))
|
|
||||||
font = ImageFont.truetype(font_path, 60)
|
|
||||||
draw.text((5, 80), "%03i" % cup_id, (255, 165, 0), font=font, stroke_width=2, stroke_fill=(0, 0, 0))
|
|
||||||
|
|
||||||
return cup_icon
|
|
||||||
|
|
||||||
def get_cticon(self) -> Image:
|
def get_cticon(self) -> Image:
|
||||||
"""
|
"""
|
||||||
|
@ -129,18 +108,27 @@ class CT_Config:
|
||||||
:return: ct_icon image
|
:return: ct_icon image
|
||||||
"""
|
"""
|
||||||
CT_ICON_WIDTH = 128
|
CT_ICON_WIDTH = 128
|
||||||
icon_files = ["left", "right"]
|
|
||||||
|
|
||||||
total_cup_count = math.ceil(len(self.all_tracks) // 4) + 10 # +10 because left, right, start at 0, 8 normal cup
|
default_cups = [
|
||||||
|
"left", "right",
|
||||||
|
|
||||||
|
"mushroom", "shell", "flower", "banana",
|
||||||
|
"star", "leaf", "special", "lightning",
|
||||||
|
|
||||||
|
"random"
|
||||||
|
]
|
||||||
|
|
||||||
|
total_cup_count = self.get_cup_count() + len(default_cups) # +10 because left, right, start at 0, 8 normal cup
|
||||||
ct_icon = Image.new("RGBA", (CT_ICON_WIDTH, CT_ICON_WIDTH * (total_cup_count + 2)))
|
ct_icon = Image.new("RGBA", (CT_ICON_WIDTH, CT_ICON_WIDTH * (total_cup_count + 2)))
|
||||||
# +2 because of left and right arrow
|
# +2 because of left and right arrow
|
||||||
|
|
||||||
icon_files.extend(range(total_cup_count))
|
def icon_cups_generator():
|
||||||
|
for id, name in enumerate(default_cups): yield Cup(name=name, id=-id) # default cup have a negative id
|
||||||
|
for cup in self.get_all_cups(): yield cup
|
||||||
|
|
||||||
for index, cup_id in enumerate(icon_files):
|
for index, cup in enumerate(icon_cups_generator()):
|
||||||
# index is a number, id can be string or number ("left", 0, 12, ...)
|
# index is a number, id can be string or number ("left", 0, 12, ...)
|
||||||
cup_icon = self.get_cup_icon(cup_id)
|
ct_icon.paste(cup.get_icon(), (0, index * CT_ICON_WIDTH))
|
||||||
ct_icon.paste(cup_icon, (0, index * CT_ICON_WIDTH))
|
|
||||||
|
|
||||||
return ct_icon
|
return ct_icon
|
||||||
|
|
||||||
|
@ -167,21 +155,30 @@ class CT_Config:
|
||||||
|
|
||||||
self.pack_path = pack_path
|
self.pack_path = pack_path
|
||||||
|
|
||||||
# default track
|
with open(f"{pack_path}/file_process.json", encoding="utf8") as fp_file:
|
||||||
self.default_track = Track(track_wu8_dir=f"{self.pack_path}/file/Track-WU8/")
|
self.file_process = json.load(fp_file)
|
||||||
if "default_track" in ctconfig_json: self.default_track.load_from_json(ctconfig_json["default_track"])
|
with open(f"{pack_path}/file_structure.json", encoding="utf8") as fs_file:
|
||||||
|
self.file_structure = json.load(fs_file)
|
||||||
|
|
||||||
for cup_json in ctconfig_json["cup"] if "cup" in ctconfig_json else []: # tracks with defined order
|
dir = self.file_process['placement'].get('cup_icon_dir') if 'placement' in self.file_process else None
|
||||||
cup = Cup(default_track=self.default_track)
|
if not dir: dir = "/ct_icons/"
|
||||||
|
Cup.icon_dir = f"{self.pack_path}/file/{dir}/"
|
||||||
|
|
||||||
|
# default track
|
||||||
|
self.default_track = Track()
|
||||||
|
if "default_track" in ctconfig_json: self.default_track.load_from_json(ctconfig_json["default_track"])
|
||||||
|
Cup.default_track = self.default_track
|
||||||
|
|
||||||
|
for id, cup_json in enumerate(ctconfig_json["cup"] if "cup" in ctconfig_json else []):
|
||||||
|
# tracks with defined order
|
||||||
|
cup = Cup(id=id)
|
||||||
cup.load_from_json(cup_json)
|
cup.load_from_json(cup_json)
|
||||||
self.ordered_cups.append(cup)
|
self.ordered_cups.append(cup)
|
||||||
self.all_tracks.extend(cup.tracks)
|
|
||||||
|
|
||||||
for track_json in ctconfig_json["tracks_list"] if "tracks_list" in ctconfig_json else []: # unordered tracks
|
for track_json in ctconfig_json["tracks_list"] if "tracks_list" in ctconfig_json else []:
|
||||||
track = Track(track_wu8_dir=f"{self.pack_path}/file/Track-WU8/")
|
# unordered tracks
|
||||||
track.load_from_json(track_json)
|
track = get_trackdata_from_json(track_json)
|
||||||
self.unordered_tracks.append(track)
|
self.unordered_tracks.append(track)
|
||||||
self.all_tracks.append(track)
|
|
||||||
|
|
||||||
self.version = ctconfig_json.get("version")
|
self.version = ctconfig_json.get("version")
|
||||||
|
|
||||||
|
@ -192,39 +189,23 @@ class CT_Config:
|
||||||
for param in ["region", "cheat_region", "tags_color", "prefix_list", "suffix_list", "tag_retro"]:
|
for param in ["region", "cheat_region", "tags_color", "prefix_list", "suffix_list", "tag_retro"]:
|
||||||
setattr(self, param, ctconfig_json.get(param))
|
setattr(self, param, ctconfig_json.get(param))
|
||||||
|
|
||||||
with open(f"{pack_path}/file_process.json", encoding="utf8") as fp_file:
|
wu8_dirname = self.file_process["track_dir"] if "track_dir" in self.file_process else "/Track-WU8/"
|
||||||
self.file_process = json.load(fp_file)
|
Track._wu8_dir = f"{self.pack_path}/file/{wu8_dirname}/"
|
||||||
with open(f"{pack_path}/file_structure.json", encoding="utf8") as fs_file:
|
Track._szs_dir = "./file/Track/"
|
||||||
self.file_structure = json.load(fs_file)
|
Track.tag_retro = self.tag_retro
|
||||||
|
Track.prefix_list = self.prefix_list
|
||||||
|
Track.suffix_list = self.suffix_list
|
||||||
|
Track.tags_color = self.tags_color
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def search_tracks(self, values_list=False, not_value=False, only_unordered_track=False, **kwargs) -> list:
|
def get_tracks_count(self) -> int:
|
||||||
"""
|
return sum(1 for _ in self.get_tracks())
|
||||||
:param only_unordered_track: only search in unordered track
|
|
||||||
:param values_list: search track with a value list instead of a single value
|
|
||||||
:param not_value: search track that does not have value
|
|
||||||
:param kwargs: any track property = any value
|
|
||||||
:return: track list respecting condition
|
|
||||||
"""
|
|
||||||
track = self.all_tracks.copy() if not only_unordered_track else self.unordered_tracks.copy()
|
|
||||||
|
|
||||||
if values_list:
|
|
||||||
if not_value: filter_func = lambda track: getattr(track, keyword) not in value
|
|
||||||
else: filter_func = lambda track: getattr(track, keyword) in value
|
|
||||||
else:
|
|
||||||
if not_value: filter_func = lambda track: getattr(track, keyword) != value
|
|
||||||
else: filter_func = lambda track: getattr(track, keyword) == value
|
|
||||||
|
|
||||||
for keyword, value in kwargs.items():
|
|
||||||
track = list(filter(filter_func, track))
|
|
||||||
return track
|
|
||||||
|
|
||||||
def get_all_track_possibilities(self) -> dict:
|
def get_all_track_possibilities(self) -> dict:
|
||||||
possibilities = {}
|
possibilities = {}
|
||||||
for track in self.all_tracks:
|
for track in self.get_tracks():
|
||||||
for key, value in track.__dict__.items():
|
for key, value in track.__dict__.items():
|
||||||
if key in HiddenTrackAttr: continue
|
|
||||||
if not key in possibilities: possibilities[key] = []
|
if not key in possibilities: possibilities[key] = []
|
||||||
|
|
||||||
if type(value) == list:
|
if type(value) == list:
|
||||||
|
|
|
@ -1,14 +1,20 @@
|
||||||
from source.Track import Track
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
import os
|
||||||
|
|
||||||
|
from source.Track import Track, TrackGroup, get_trackdata_from_json
|
||||||
|
|
||||||
|
|
||||||
class Cup:
|
class Cup:
|
||||||
|
icon_dir = None
|
||||||
|
default_track = None
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
default_track: Track,
|
|
||||||
name: str = None,
|
name: str = None,
|
||||||
track1: Track = None,
|
id: int = 0,
|
||||||
track2: Track = None,
|
track1: [Track, TrackGroup] = None,
|
||||||
track3: Track = None,
|
track2: [Track, TrackGroup] = None,
|
||||||
track4: Track = None,
|
track3: [Track, TrackGroup] = None,
|
||||||
|
track4: [Track, TrackGroup] = None,
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
"""
|
"""
|
||||||
class of a cup
|
class of a cup
|
||||||
|
@ -22,14 +28,15 @@ class Cup:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.id = id
|
||||||
self.tracks = [
|
self.tracks = [
|
||||||
track1 if track1 else default_track.copy(),
|
track1 if track1 else self.default_track.copy() if self.default_track else None,
|
||||||
track2 if track2 else default_track.copy(),
|
track2 if track2 else self.default_track.copy() if self.default_track else None,
|
||||||
track3 if track3 else default_track.copy(),
|
track3 if track3 else self.default_track.copy() if self.default_track else None,
|
||||||
track4 if track4 else default_track.copy()
|
track4 if track4 else self.default_track.copy() if self.default_track else None,
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_ctfile_cup(self, *args, **kwargs) -> str:
|
def get_ctfile(self, *args, **kwargs) -> str:
|
||||||
"""
|
"""
|
||||||
get the ctfile definition for the cup
|
get the ctfile definition for the cup
|
||||||
:param race: is it a text used for Race_*.szs ?
|
:param race: is it a text used for Race_*.szs ?
|
||||||
|
@ -40,7 +47,7 @@ class Cup:
|
||||||
ctfile_cup += track.get_ctfile(*args, **kwargs)
|
ctfile_cup += track.get_ctfile(*args, **kwargs)
|
||||||
return ctfile_cup
|
return ctfile_cup
|
||||||
|
|
||||||
def load_from_json(self, cup: dict):
|
def load_from_json(self, cup: dict, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
load the cup from a dictionnary
|
load the cup from a dictionnary
|
||||||
:param cup: dictionnary cup
|
:param cup: dictionnary cup
|
||||||
|
@ -48,8 +55,35 @@ class Cup:
|
||||||
for key, value in cup.items(): # load all value in the json as class attribute
|
for key, value in cup.items(): # load all value in the json as class attribute
|
||||||
if key == "tracks": # if the key is tracks
|
if key == "tracks": # if the key is tracks
|
||||||
for i, track_json in enumerate(value): # load all tracks from their json
|
for i, track_json in enumerate(value): # load all tracks from their json
|
||||||
self.tracks[i].load_from_json(track_json)
|
self.tracks[i] = get_trackdata_from_json(track_json)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def get_tracks(self):
|
||||||
|
for trackdata in self.tracks:
|
||||||
|
for track in trackdata.get_tracks():
|
||||||
|
yield track
|
||||||
|
|
||||||
|
def get_icon(self, font_path: str = "./assets/SuperMario256.ttf") -> Image:
|
||||||
|
"""
|
||||||
|
:param font_path: path to the font used to generate icon
|
||||||
|
:return: cup icon
|
||||||
|
"""
|
||||||
|
cup_icon = None
|
||||||
|
|
||||||
|
for name in [self.id, self.name]:
|
||||||
|
if os.path.exists(f"{self.icon_dir}/{name}.png"):
|
||||||
|
cup_icon = Image.open(f"{self.icon_dir}/{name}.png").resize((128, 128))
|
||||||
|
|
||||||
|
if not cup_icon:
|
||||||
|
cup_icon = Image.new("RGBA", (128, 128))
|
||||||
|
draw = ImageDraw.Draw(cup_icon)
|
||||||
|
font = ImageFont.truetype(font_path, 90)
|
||||||
|
draw.text((4, 4), "CT", (255, 165, 0), font=font, stroke_width=2, stroke_fill=(0, 0, 0))
|
||||||
|
font = ImageFont.truetype(font_path, 60)
|
||||||
|
draw.text((5, 80), "%03i" % self.id, (255, 165, 0), font=font, stroke_width=2, stroke_fill=(0, 0, 0))
|
||||||
|
|
||||||
|
return cup_icon
|
||||||
|
|
|
@ -29,11 +29,6 @@ class TooMuchSha1CheckFailed(Exception):
|
||||||
super().__init__("Too much sha1 check failed !")
|
super().__init__("Too much sha1 check failed !")
|
||||||
|
|
||||||
|
|
||||||
class CantConvertTrack(Exception):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__("Can't convert track.")
|
|
||||||
|
|
||||||
|
|
||||||
class NoGui:
|
class NoGui:
|
||||||
"""
|
"""
|
||||||
'fake' gui if no gui are used for compatibility.
|
'fake' gui if no gui are used for compatibility.
|
||||||
|
@ -280,7 +275,7 @@ class Game:
|
||||||
if not lpar_path: f""
|
if not lpar_path: f""
|
||||||
lpar_path = (
|
lpar_path = (
|
||||||
f"{self.ctconfig.pack_path}/file/{lpar_path}/"
|
f"{self.ctconfig.pack_path}/file/{lpar_path}/"
|
||||||
f"lpar-{'debug' if self.gui.boolvar_use_debug_mode.get() else 'normal'}"
|
f"lpar-{'debug' if self.gui.boolvar_use_debug_mode.get() else 'normal'}.txt"
|
||||||
)
|
)
|
||||||
|
|
||||||
lecode_file = self.ctconfig.file_process["placement"].get("lecode_bin_dir")
|
lecode_file = self.ctconfig.file_process["placement"].get("lecode_bin_dir")
|
||||||
|
@ -493,7 +488,6 @@ class Game:
|
||||||
self.gui.progress(statut=self.gui.translate("Configurating LE-CODE"), add=1)
|
self.gui.progress(statut=self.gui.translate("Configurating LE-CODE"), add=1)
|
||||||
self.ctconfig.create_ctfile(
|
self.ctconfig.create_ctfile(
|
||||||
highlight_version=self.gui.stringvar_mark_track_from_version.get(),
|
highlight_version=self.gui.stringvar_mark_track_from_version.get(),
|
||||||
sort_track_by=self.gui.stringvar_sort_track_by.get()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self.generate_cticons()
|
self.generate_cticons()
|
||||||
|
@ -614,16 +608,9 @@ class Game:
|
||||||
"""
|
"""
|
||||||
nonlocal error_count, error_max, thread_list
|
nonlocal error_count, error_max, thread_list
|
||||||
|
|
||||||
if os.path.exists(track.file_szs) and os.path.getsize(track.file_szs) < 1000:
|
try: track.convert_wu8_to_szs()
|
||||||
os.remove(track.file_szs) # File under this size are corrupted
|
except Exception as e:
|
||||||
|
raise e
|
||||||
if not track.check_szs_sha1(): # if sha1 of track's szs is incorrect or track's szs does not exist
|
|
||||||
if os.path.exists(track.file_wu8):
|
|
||||||
track.convert_wu8_to_szs()
|
|
||||||
else:
|
|
||||||
messagebox.showerror(self.gui.translate("Error"),
|
|
||||||
self.gui.translate("Can't convert track.\nEnable track download and retry."))
|
|
||||||
raise CantConvertTrack()
|
|
||||||
|
|
||||||
def clean_process() -> int:
|
def clean_process() -> int:
|
||||||
"""
|
"""
|
||||||
|
@ -639,10 +626,10 @@ class Game:
|
||||||
|
|
||||||
return bool(thread_list)
|
return bool(thread_list)
|
||||||
|
|
||||||
total_track = len(self.ctconfig.all_tracks)
|
total_track = self.ctconfig.get_tracks_count()
|
||||||
self.gui.progress(max=total_track, indeter=False, show=True)
|
self.gui.progress(max=total_track, indeter=False, show=True)
|
||||||
|
|
||||||
for i, track in enumerate(self.ctconfig.all_tracks):
|
for i, track in enumerate(self.ctconfig.get_tracks()):
|
||||||
while error_count <= error_max:
|
while error_count <= error_max:
|
||||||
if len(thread_list) < max_process:
|
if len(thread_list) < max_process:
|
||||||
thread_list[track.sha1] = Thread(target=add_process, args=[track])
|
thread_list[track.sha1] = Thread(target=add_process, args=[track])
|
||||||
|
|
163
source/Track.py
|
@ -2,19 +2,25 @@ from source.definition import *
|
||||||
from source.wszst import *
|
from source.wszst import *
|
||||||
|
|
||||||
|
|
||||||
HiddenTrackAttr = [
|
|
||||||
"file_wu8",
|
|
||||||
"file_szs",
|
|
||||||
"_track_wu8_dir",
|
|
||||||
"_track_szs_dir"
|
|
||||||
] # These attribute shouldn't be used to reference all the possibilities of values
|
|
||||||
|
|
||||||
|
|
||||||
class CantDownloadTrack(Exception):
|
class CantDownloadTrack(Exception):
|
||||||
def __init__(self, track, http_error: [str, int]):
|
def __init__(self, track, http_error: [str, int]):
|
||||||
super().__init__(f"Can't download track {track.name} ({track.sha1}) (error {http_error}) !")
|
super().__init__(f"Can't download track {track.name} ({track.sha1}) (error {http_error}) !")
|
||||||
|
|
||||||
|
|
||||||
|
class CantConvertTrack(Exception):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Can't convert track.")
|
||||||
|
|
||||||
|
|
||||||
|
class MissingTrackWU8(Exception):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("The original wu8 track file is missing !")
|
||||||
|
|
||||||
|
|
||||||
|
def get_trackdata_from_json(track_json, *args, **kwargs):
|
||||||
|
return (TrackGroup if "group" in track_json else Track)(*args, **kwargs).load_from_json(track_json)
|
||||||
|
|
||||||
|
|
||||||
def check_file_sha1(file: str, excepted_sha1: str) -> int:
|
def check_file_sha1(file: str, excepted_sha1: str) -> int:
|
||||||
"""
|
"""
|
||||||
check if track szs sha1 is correct
|
check if track szs sha1 is correct
|
||||||
|
@ -22,17 +28,24 @@ def check_file_sha1(file: str, excepted_sha1: str) -> int:
|
||||||
"""
|
"""
|
||||||
if not os.path.exists(file): return 0
|
if not os.path.exists(file): return 0
|
||||||
calculated_sha1 = szs.sha1(file=file)
|
calculated_sha1 = szs.sha1(file=file)
|
||||||
if calculated_sha1 == excepted_sha1: return 1
|
if calculated_sha1 == excepted_sha1:
|
||||||
|
return 1
|
||||||
else:
|
else:
|
||||||
print(f"incorrect sha1 for {file} {calculated_sha1} : (expected {excepted_sha1})")
|
print(f"incorrect sha1 for {file} {calculated_sha1} : (expected {excepted_sha1})")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
class Track:
|
class Track:
|
||||||
|
_wu8_dir = None
|
||||||
|
_szs_dir = None
|
||||||
|
tag_retro = None
|
||||||
|
prefix_list = None
|
||||||
|
suffix_list = None
|
||||||
|
tags_color = None
|
||||||
|
|
||||||
def __init__(self, name: str = " ", author: str = "Nintendo", special: str = "T11", music: str = "T11",
|
def __init__(self, name: str = " ", author: str = "Nintendo", special: str = "T11", music: str = "T11",
|
||||||
sha1: str = None, since_version: str = None, score: int = -1, warning: int = 0, note: str = "",
|
sha1: str = None, since_version: str = None, score: int = -1, warning: int = 0,
|
||||||
track_wu8_dir: str = "./file/Track-WU8/", track_szs_dir: str = "./file/Track/",
|
version: str = None, tags: list = None, is_in_group: bool = False, *args, **kwargs):
|
||||||
version: str = None, tags: list = [], *args, **kwargs):
|
|
||||||
"""
|
"""
|
||||||
Track class
|
Track class
|
||||||
:param name: track name
|
:param name: track name
|
||||||
|
@ -57,21 +70,19 @@ class Track:
|
||||||
:param kwargs: /
|
:param kwargs: /
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.name = name # Track name
|
self.name = name # Track name
|
||||||
self.author = author # Track author
|
self.author = author # Track author
|
||||||
self.sha1 = sha1 # Track sha1 from wszst SHA1
|
self.sha1 = sha1 # Track sha1 from wszst SHA1
|
||||||
self.special = special # Special slot of the track
|
self.special = special # Special slot of the track
|
||||||
self.music = music # Music of the track
|
self.music = music # Music of the track
|
||||||
self.since_version = since_version # Since which version is this track available
|
self.since_version = since_version # Since which version is this track available
|
||||||
self.score = score # Track score between 1 and 3 stars
|
self.score = score # Track score between 1 and 3 stars
|
||||||
self.warning = warning # Track bug level (1 = minor, 2 = major)
|
self.warning = warning # Track bug level (1 = minor, 2 = major)
|
||||||
self.version = version
|
self.version = version
|
||||||
self.tags = tags
|
self.tags = tags if tags else []
|
||||||
|
self.refresh_filename()
|
||||||
|
|
||||||
self._track_wu8_dir = track_wu8_dir
|
self._is_in_group = is_in_group
|
||||||
self._track_szs_dir = track_szs_dir
|
|
||||||
self.file_wu8 = f"{track_wu8_dir}/{self.sha1}.wu8"
|
|
||||||
self.file_szs = f"{track_szs_dir}/{self.sha1}.szs"
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -85,23 +96,33 @@ class Track:
|
||||||
check if track wu8 sha1 is correct
|
check if track wu8 sha1 is correct
|
||||||
:return: 0 if yes, -1 if no
|
:return: 0 if yes, -1 if no
|
||||||
"""
|
"""
|
||||||
return check_file_sha1(self.file_wu8, self.sha1)
|
return check_file_sha1(self._wu8_file, self.sha1)
|
||||||
|
|
||||||
def check_szs_sha1(self) -> int:
|
def check_szs_sha1(self) -> int:
|
||||||
"""
|
"""
|
||||||
check if track szs sha1 is correct
|
check if track szs sha1 is correct
|
||||||
:return: 0 if yes, -1 if no
|
:return: 0 if yes, -1 if no
|
||||||
"""
|
"""
|
||||||
return check_file_sha1(self.file_szs, self.sha1)
|
return check_file_sha1(self._szs_file, self.sha1)
|
||||||
|
|
||||||
def convert_wu8_to_szs(self) -> None:
|
def convert_wu8_to_szs(self) -> None:
|
||||||
"""
|
"""
|
||||||
convert track to szs
|
convert track to szs
|
||||||
"""
|
"""
|
||||||
szs.normalize(
|
file_wu8 = f"{self._wu8_dir}/{self.sha1}.wu8"
|
||||||
src_file=self.file_wu8,
|
file_szs = f"{self._szs_dir}/{self.sha1}.szs"
|
||||||
dest_dir="./file/Track/"
|
|
||||||
)
|
if os.path.exists(file_szs) and os.path.getsize(file_szs) < 1000:
|
||||||
|
os.remove(file_szs) # File under this size are corrupted
|
||||||
|
|
||||||
|
if not self.check_szs_sha1(): # if sha1 of track's szs is incorrect or track's szs does not exist
|
||||||
|
if os.path.exists(file_wu8):
|
||||||
|
szs.normalize(
|
||||||
|
src_file=file_wu8,
|
||||||
|
dest_file=file_szs
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise MissingTrackWU8()
|
||||||
|
|
||||||
def get_author_str(self) -> str:
|
def get_author_str(self) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -109,39 +130,43 @@ class Track:
|
||||||
"""
|
"""
|
||||||
return self.author if type(self.author) == str else ", ".join(self.author)
|
return self.author if type(self.author) == str else ", ".join(self.author)
|
||||||
|
|
||||||
def get_ctfile(self, ct_config, race=False, *args, **kwargs) -> str:
|
def get_ctfile(self, race=False, *args, **kwargs) -> str:
|
||||||
"""
|
"""
|
||||||
get ctfile text to create CTFILE.txt and RCTFILE.txt
|
get ctfile text to create CTFILE.txt and RCTFILE.txt
|
||||||
:param ct_config: ct_config used to generate the Track
|
|
||||||
:param race: is it a text used for Race_*.szs ?
|
:param race: is it a text used for Race_*.szs ?
|
||||||
:return: ctfile definition for the track
|
:return: ctfile definition for the track
|
||||||
"""
|
"""
|
||||||
ctfile_text = (
|
track_type = "T"
|
||||||
f' T {self.music}; '
|
track_flag = 0x00 if self.tag_retro in self.tags else 0x01
|
||||||
f'{self.special}; '
|
if self._is_in_group:
|
||||||
f'{"0x00" if ct_config.tag_retro in self.tags else "0x01"}; '
|
track_type = "H"
|
||||||
)
|
track_flag |= 0x04
|
||||||
if not race:
|
|
||||||
ctfile_text += (
|
ctfile_track = f' {track_type} {self.music}; {self.special}; {hex(track_flag)}; '
|
||||||
f'"{self.sha1}"; ' # track path
|
|
||||||
f'"{self.get_track_formatted_name(ct_config, *args, **kwargs)}"; ' # track text shown ig
|
if race:
|
||||||
f'"{self.sha1}"\n') # sha1
|
ctfile_track += (
|
||||||
else:
|
|
||||||
ctfile_text += (
|
|
||||||
f'"-"; ' # track path, not used in Race_*.szs, save a bit of space
|
f'"-"; ' # track path, not used in Race_*.szs, save a bit of space
|
||||||
f'"{self.get_track_formatted_name(ct_config, *args, **kwargs)}\\n{self.get_author_str()}"; '
|
f'"{self.get_track_formatted_name(*args, **kwargs)}\\n{self.get_author_str()}"; '
|
||||||
# only in race show author's name
|
# only in race show author's name
|
||||||
f'"-"\n' # sha1, not used in Race_*.szs, save a bit of space
|
f'"-"\n' # sha1, not used in Race_*.szs, save a bit of space
|
||||||
)
|
)
|
||||||
|
|
||||||
return ctfile_text
|
else:
|
||||||
|
ctfile_track += (
|
||||||
|
f'"{self.sha1}"; ' # track path
|
||||||
|
f'"{self.get_track_formatted_name(*args, **kwargs)}"; ' # track text shown ig
|
||||||
|
f'"{self.sha1}"\n' # sha1
|
||||||
|
)
|
||||||
|
|
||||||
|
return ctfile_track
|
||||||
|
|
||||||
def select_tag(self, tag_list: list) -> str:
|
def select_tag(self, tag_list: list) -> str:
|
||||||
for tag in self.tags:
|
for tag in self.tags:
|
||||||
if tag in tag_list: return tag
|
if tag in tag_list: return tag
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def get_track_formatted_name(self, ct_config, highlight_version: str = None, *args, **kwargs) -> str:
|
def get_track_formatted_name(self, highlight_version: str = None, *args, **kwargs) -> str:
|
||||||
"""
|
"""
|
||||||
get the track name with score, color, ...
|
get the track name with score, color, ...
|
||||||
:param ct_config: ct_config for tags configuration
|
:param ct_config: ct_config for tags configuration
|
||||||
|
@ -150,8 +175,8 @@ class Track:
|
||||||
"""
|
"""
|
||||||
hl_prefix = "" # highlight
|
hl_prefix = "" # highlight
|
||||||
hl_suffix = ""
|
hl_suffix = ""
|
||||||
prefix = self.select_tag(ct_config.prefix_list) # tag prefix
|
prefix = self.select_tag(self.prefix_list) # tag prefix
|
||||||
suffix = self.select_tag(ct_config.suffix_list) # tag suffix
|
suffix = self.select_tag(self.suffix_list) # tag suffix
|
||||||
star_prefix = "" # star
|
star_prefix = "" # star
|
||||||
star_suffix = ""
|
star_suffix = ""
|
||||||
star_text = ""
|
star_text = ""
|
||||||
|
@ -166,8 +191,8 @@ class Track:
|
||||||
if self.since_version == highlight_version:
|
if self.since_version == highlight_version:
|
||||||
hl_prefix, hl_suffix = "\\\\c{blue1}", "\\\\c{off}"
|
hl_prefix, hl_suffix = "\\\\c{blue1}", "\\\\c{off}"
|
||||||
|
|
||||||
if prefix: prefix = "\\\\c{"+ct_config.tags_color[prefix]+"}"+prefix+"\\\\c{off} "
|
if prefix: prefix = "\\\\c{" + self.tags_color[prefix] + "}" + prefix + "\\\\c{off} "
|
||||||
if suffix: suffix = " (\\\\c{"+ct_config.tags_color[suffix]+"}"+suffix+"\\\\c{off})"
|
if suffix: suffix = " (\\\\c{" + self.tags_color[suffix] + "}" + suffix + "\\\\c{off})"
|
||||||
|
|
||||||
name = f"{star_prefix}{star_text}{star_suffix}{prefix}{hl_prefix}{self.name}{hl_suffix}{suffix}"
|
name = f"{star_prefix}{star_text}{star_suffix}{prefix}{hl_prefix}{self.name}{hl_suffix}{suffix}"
|
||||||
return name
|
return name
|
||||||
|
@ -179,6 +204,10 @@ class Track:
|
||||||
"""
|
"""
|
||||||
return f"{self.select_tag(ct_config.prefix_list)}{self.name}{self.select_tag(ct_config.suffix_list)}"
|
return f"{self.select_tag(ct_config.prefix_list)}{self.name}{self.select_tag(ct_config.suffix_list)}"
|
||||||
|
|
||||||
|
def refresh_filename(self):
|
||||||
|
self._wu8_file = f"{self._wu8_dir}/{self.sha1}.wu8"
|
||||||
|
self._szs_file = f"{self._szs_dir}/{self.sha1}.szs"
|
||||||
|
|
||||||
def load_from_json(self, track_json: dict):
|
def load_from_json(self, track_json: dict):
|
||||||
"""
|
"""
|
||||||
load the track from a dictionary
|
load the track from a dictionary
|
||||||
|
@ -187,8 +216,7 @@ class Track:
|
||||||
for key, value in track_json.items(): # load all value in the json as class attribute
|
for key, value in track_json.items(): # load all value in the json as class attribute
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
self.file_wu8 = f"{self._track_wu8_dir}/{self.sha1}.wu8"
|
self.refresh_filename()
|
||||||
self.file_szs = f"{self._track_szs_dir}/{self.sha1}.szs"
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -200,3 +228,32 @@ class Track:
|
||||||
for k, v in self.__dict__.items():
|
for k, v in self.__dict__.items():
|
||||||
setattr(new, k, v)
|
setattr(new, k, v)
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
def get_tracks(self): yield self
|
||||||
|
|
||||||
|
|
||||||
|
class TrackGroup(Track):
|
||||||
|
def __init__(self, tracks: list = None, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.tracks = tracks if tracks else []
|
||||||
|
|
||||||
|
def load_from_json(self, group_json: dict, *args, **kwargs):
|
||||||
|
for key, value in group_json.items(): # load all value in the json as class attribute
|
||||||
|
if key == "group":
|
||||||
|
for track_json in value:
|
||||||
|
self.tracks.append(Track(is_in_group=True, *args, **kwargs).load_from_json(track_json))
|
||||||
|
|
||||||
|
else:
|
||||||
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def get_tracks(self):
|
||||||
|
for track in self.tracks: yield track
|
||||||
|
|
||||||
|
def get_ctfile(self, *args, **kwargs):
|
||||||
|
ctfile_group = f' T T11; T11; 0x02; "-"; "{self.get_track_formatted_name()}"; "-"\n'
|
||||||
|
for track in self.tracks:
|
||||||
|
ctfile_group += track.get_ctfile(*args, **kwargs)
|
||||||
|
|
||||||
|
return ctfile_group
|
|
@ -48,17 +48,16 @@ def sha1(file, autoadd_path: str = "./file/auto-add/") -> str:
|
||||||
|
|
||||||
|
|
||||||
@error.better_wszst_error(wszst_tools=WSZST_PATH)
|
@error.better_wszst_error(wszst_tools=WSZST_PATH)
|
||||||
def normalize(src_file: str, dest_dir: str = "./file/Track/", dest_name: str = "%N.szs",
|
def normalize(src_file: str, dest_file: str = "./file/Track/%N.szs",
|
||||||
output_format: str = "szs", autoadd_path: str = "./file/auto-add/") -> None:
|
output_format: str = "szs", autoadd_path: str = "./file/auto-add/") -> None:
|
||||||
"""
|
"""
|
||||||
convert a track into an another format
|
convert a track into an another format
|
||||||
:param src_file: source file
|
:param src_file: source file
|
||||||
:param dest_dir: destination directory
|
:param dest_file: destination filename (%N mean same name as src_file)
|
||||||
:param dest_name: destination filename (%N mean same name as src_file)
|
|
||||||
:param output_format: format of the destination track
|
:param output_format: format of the destination track
|
||||||
:param autoadd_path: path of the auto-add directory
|
:param autoadd_path: path of the auto-add directory
|
||||||
"""
|
"""
|
||||||
subprocess.run([WSZST_PATH, "NORMALIZE", src_file, "--DEST", dest_dir + dest_name, "--" + output_format,
|
subprocess.run([WSZST_PATH, "NORMALIZE", src_file, "--DEST", dest_file, "--" + output_format,
|
||||||
"--overwrite", "--autoadd-path", autoadd_path],
|
"--overwrite", "--autoadd-path", autoadd_path],
|
||||||
creationflags=subprocess.CREATE_NO_WINDOW, stderr=subprocess.PIPE)
|
creationflags=subprocess.CREATE_NO_WINDOW, stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
|