mirror of
https://github.com/cainan-c/TaikoPythonTools.git
synced 2024-11-23 22:50:59 +01:00
Update and Improve tool
This commit is contained in:
parent
cfe264baf5
commit
c15f9450ad
@ -7,7 +7,7 @@ Nintendo Switch Version / Drum 'n' Fun v1.4.13 (Nintendo Switch)
|
|||||||
Drum Session (Any Update) (PlayStation 4)
|
Drum Session (Any Update) (PlayStation 4)
|
||||||
Pop Tap Beat (Any Update) (iOS/MacOS/Apple TV)
|
Pop Tap Beat (Any Update) (iOS/MacOS/Apple TV)
|
||||||
|
|
||||||
A version of this tool with all song data can be found elsewhere.
|
A version of this tool with all song data can be found elsewhere.
|
||||||
There's 3 options to sort songs by: ID (A-Z), Song Name (A-Z) and Genre
|
There's 3 options to sort songs by: ID (A-Z), Song Name (A-Z) and Genre
|
||||||
|
|
||||||
This is still a work in-progress, so please report any issues found to me, along with suggestions for features or game support.
|
This is still a work in-progress, so please report any issues found to me, along with suggestions for features or game support.
|
||||||
@ -25,6 +25,9 @@ Due to copyright reasons, etc. no song data will be provided with this tool, how
|
|||||||
Currently, due to the nature of this relying on some Windows executables, this tool currently only supports Windows.
|
Currently, due to the nature of this relying on some Windows executables, this tool currently only supports Windows.
|
||||||
I will be looking into getting it running on Unix-based operating systems. (Linux/macOS)
|
I will be looking into getting it running on Unix-based operating systems. (Linux/macOS)
|
||||||
|
|
||||||
|
# Additional Features
|
||||||
|
This tool now supports the ability to load songs from an additional folder. This is designed to allow both Official song data and Custom Song data to be used in-conjunction with eachother.
|
||||||
|
|
||||||
![song conversion tool](https://i.imgur.com/TnRlAxR.png)
|
![song conversion tool](https://i.imgur.com/TnRlAxR.png)
|
||||||
|
|
||||||
## Tools Used
|
## Tools Used
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"max_concurrent": 25
|
"max_concurrent": 25,
|
||||||
|
"custom_songs": false,
|
||||||
|
"custom_song_path": "data_custom/"
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,43 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
from cryptography.hazmat.primitives import padding
|
from cryptography.hazmat.primitives import padding
|
||||||
|
|
||||||
|
# Function to load configuration from file
|
||||||
|
def load_config():
|
||||||
|
config_file = "config.json"
|
||||||
|
default_config = {
|
||||||
|
"max_concurrent": 5, # Default value if not specified in config file
|
||||||
|
"custom_songs": False,
|
||||||
|
"custom_song_path": "data_custom/"
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(config_file, "r") as f:
|
||||||
|
config = json.load(f)
|
||||||
|
# Override default values with values from config file
|
||||||
|
default_config.update(config)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"Config file '{config_file}' not found. Using default configuration.")
|
||||||
|
|
||||||
|
return default_config
|
||||||
|
|
||||||
data_dir = "data/"
|
data_dir = "data/"
|
||||||
musicinfo_path = os.path.join(data_dir, "datatable", "musicinfo.json")
|
musicinfo_path = os.path.join(data_dir, "datatable", "musicinfo.json")
|
||||||
wordlist_path = os.path.join(data_dir, "datatable", "wordlist.json")
|
wordlist_path = os.path.join(data_dir, "datatable", "wordlist.json")
|
||||||
previewpos_path = os.path.join(data_dir, "datatable", "previewpos.json")
|
previewpos_path = os.path.join(data_dir, "datatable", "previewpos.json")
|
||||||
|
|
||||||
|
# Load configuration
|
||||||
|
config = load_config()
|
||||||
|
|
||||||
|
custom_songs = config["custom_songs"]
|
||||||
|
# custom_song_path = config["custom_path"]
|
||||||
|
|
||||||
|
if custom_songs == True:
|
||||||
|
print("Custom Song Loading Enabled")
|
||||||
|
custom_data_dir = config.get('custom_song_path')
|
||||||
|
custom_musicinfo_path = os.path.join(custom_data_dir, "datatable", "musicinfo.json")
|
||||||
|
custom_wordlist_path = os.path.join(custom_data_dir, "datatable", "wordlist.json")
|
||||||
|
custom_previewpos_path = os.path.join(custom_data_dir, "datatable", "previewpos.json")
|
||||||
|
|
||||||
item_selection_state = {}
|
item_selection_state = {}
|
||||||
|
|
||||||
with open(musicinfo_path, "r", encoding="utf-8") as musicinfo_file:
|
with open(musicinfo_path, "r", encoding="utf-8") as musicinfo_file:
|
||||||
@ -24,6 +56,13 @@ with open(musicinfo_path, "r", encoding="utf-8") as musicinfo_file:
|
|||||||
with open(wordlist_path, "r", encoding="utf-8") as wordlist_file:
|
with open(wordlist_path, "r", encoding="utf-8") as wordlist_file:
|
||||||
word_list = json.load(wordlist_file)
|
word_list = json.load(wordlist_file)
|
||||||
|
|
||||||
|
if custom_songs == True:
|
||||||
|
with open(custom_musicinfo_path, "r", encoding="utf-8") as custom_musicinfo_file:
|
||||||
|
custom_music_info = json.load(custom_musicinfo_file)
|
||||||
|
|
||||||
|
with open(custom_wordlist_path, "r", encoding="utf-8") as custom_wordlist_file:
|
||||||
|
custom_word_list = json.load(custom_wordlist_file)
|
||||||
|
|
||||||
genre_map = {
|
genre_map = {
|
||||||
0: ("POP", "light blue"),
|
0: ("POP", "light blue"),
|
||||||
1: ("Anime", "orange"),
|
1: ("Anime", "orange"),
|
||||||
@ -38,6 +77,10 @@ genre_map = {
|
|||||||
song_titles = {item["key"]: item["englishUsText"] for item in word_list["items"]}
|
song_titles = {item["key"]: item["englishUsText"] for item in word_list["items"]}
|
||||||
song_subtitles = {item["key"]: item["englishUsText"] for item in word_list["items"]}
|
song_subtitles = {item["key"]: item["englishUsText"] for item in word_list["items"]}
|
||||||
|
|
||||||
|
if custom_songs == True:
|
||||||
|
custom_song_titles = {item["key"]: item["englishUsText"] for item in custom_word_list["items"]}
|
||||||
|
custom_song_subtitles = {item["key"]: item["englishUsText"] for item in custom_word_list["items"]}
|
||||||
|
|
||||||
window = tk.Tk()
|
window = tk.Tk()
|
||||||
window.title("Taiko no Tatsujin Song Conversion GUI Tool")
|
window.title("Taiko no Tatsujin Song Conversion GUI Tool")
|
||||||
|
|
||||||
@ -73,26 +116,6 @@ vsb.pack(side="left", fill="y", padx=(0, 10), pady=10)
|
|||||||
selection_count = tk.IntVar()
|
selection_count = tk.IntVar()
|
||||||
selection_count.set(0) # Initial selection count
|
selection_count.set(0) # Initial selection count
|
||||||
|
|
||||||
# Function to load configuration from file
|
|
||||||
def load_config():
|
|
||||||
config_file = "config.json"
|
|
||||||
default_config = {
|
|
||||||
"max_concurrent": 5, # Default value if not specified in config file
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(config_file, "r") as f:
|
|
||||||
config = json.load(f)
|
|
||||||
# Override default values with values from config file
|
|
||||||
default_config.update(config)
|
|
||||||
except FileNotFoundError:
|
|
||||||
print(f"Config file '{config_file}' not found. Using default configuration.")
|
|
||||||
|
|
||||||
return default_config
|
|
||||||
|
|
||||||
# Load configuration
|
|
||||||
config = load_config()
|
|
||||||
|
|
||||||
def on_search_keyrelease(event):
|
def on_search_keyrelease(event):
|
||||||
print("Key released:", event.keysym)
|
print("Key released:", event.keysym)
|
||||||
#filter_treeview()
|
#filter_treeview()
|
||||||
@ -170,6 +193,39 @@ def populate_tree():
|
|||||||
item_id = tree.insert("", "end", values=("☐", unique_id, song_id, english_title, english_subtitle, genre_name, difficulty_info))
|
item_id = tree.insert("", "end", values=("☐", unique_id, song_id, english_title, english_subtitle, genre_name, difficulty_info))
|
||||||
tree.tag_configure(genre_name, background=genre_color)
|
tree.tag_configure(genre_name, background=genre_color)
|
||||||
|
|
||||||
|
if custom_songs == True:
|
||||||
|
for song in sorted(custom_music_info["items"], key=lambda x: x["id"]): # Sort by ID
|
||||||
|
unique_id = ""
|
||||||
|
song_id = f"{song['id']}"
|
||||||
|
genre_no = song["genreNo"]
|
||||||
|
genre_name, genre_color = genre_map.get(genre_no, ("Unknown Genre", "white"))
|
||||||
|
english_title = custom_song_titles.get(f"song_{song_id}", "-")
|
||||||
|
english_subtitle = custom_song_subtitles.get(f"song_sub_{song_id}", "-")
|
||||||
|
|
||||||
|
star_easy = song.get("starEasy", "N/A")
|
||||||
|
star_normal = song.get("starNormal", "N/A")
|
||||||
|
star_hard = song.get("starHard", "N/A")
|
||||||
|
star_mania = song.get("starMania", "N/A")
|
||||||
|
star_ura = song.get("starUra", 0)
|
||||||
|
|
||||||
|
difficulty_info_parts = [
|
||||||
|
f"{star_easy}",
|
||||||
|
f"{star_normal}",
|
||||||
|
f"{star_hard}",
|
||||||
|
f"{star_mania}",
|
||||||
|
]
|
||||||
|
|
||||||
|
if star_ura > 0:
|
||||||
|
difficulty_info_parts.append(f"{star_ura}")
|
||||||
|
|
||||||
|
difficulty_info = " | ".join(difficulty_info_parts)
|
||||||
|
|
||||||
|
# Check if the search text matches the song name
|
||||||
|
if search_var.get().strip().lower() in english_title.lower():
|
||||||
|
item_id = tree.insert("", "end", values=("☐", unique_id, song_id, english_title, english_subtitle, genre_name, difficulty_info))
|
||||||
|
tree.tag_configure(genre_name, background=genre_color)
|
||||||
|
|
||||||
|
|
||||||
# Restore original selection after filtering
|
# Restore original selection after filtering
|
||||||
for item in current_selection:
|
for item in current_selection:
|
||||||
if tree.exists(item): # Check if item exists in Treeview
|
if tree.exists(item): # Check if item exists in Treeview
|
||||||
@ -191,12 +247,19 @@ def sort_tree(sort_option):
|
|||||||
selection_count.set(0) # Reset Counter to 0
|
selection_count.set(0) # Reset Counter to 0
|
||||||
for song in sorted(music_info["items"], key=lambda x: song_titles.get(f"song_{x['id']}", "-")):
|
for song in sorted(music_info["items"], key=lambda x: song_titles.get(f"song_{x['id']}", "-")):
|
||||||
populate_song_entry(song)
|
populate_song_entry(song)
|
||||||
|
if custom_songs == True:
|
||||||
|
for song in sorted(custom_music_info["items"], key=lambda x: custom_song_titles.get(f"song_{x['id']}", "-")):
|
||||||
|
populate_song_entry(song)
|
||||||
elif sort_option == "Genre":
|
elif sort_option == "Genre":
|
||||||
selection_count.set(0) # Reset Counter to 0
|
selection_count.set(0) # Reset Counter to 0
|
||||||
for genre_no in sorted(genre_map.keys()):
|
for genre_no in sorted(genre_map.keys()):
|
||||||
for song in sorted(music_info["items"], key=lambda x: x["id"]):
|
for song in sorted(music_info["items"], key=lambda x: x["id"]):
|
||||||
if song["genreNo"] == genre_no:
|
if song["genreNo"] == genre_no:
|
||||||
populate_song_entry(song)
|
populate_song_entry(song)
|
||||||
|
if custom_songs == True:
|
||||||
|
for song in sorted(custom_music_info["items"], key=lambda x: x["id"]):
|
||||||
|
if song["genreNo"] == genre_no:
|
||||||
|
populate_song_entry(song)
|
||||||
|
|
||||||
def populate_song_entry(song):
|
def populate_song_entry(song):
|
||||||
unique_id = ""
|
unique_id = ""
|
||||||
@ -205,6 +268,9 @@ def populate_song_entry(song):
|
|||||||
genre_name, genre_color = genre_map.get(genre_no, ("Unknown Genre", "white"))
|
genre_name, genre_color = genre_map.get(genre_no, ("Unknown Genre", "white"))
|
||||||
english_title = song_titles.get(f"song_{song_id}", "-")
|
english_title = song_titles.get(f"song_{song_id}", "-")
|
||||||
english_subtitle = song_subtitles.get(f"song_sub_{song_id}", "-")
|
english_subtitle = song_subtitles.get(f"song_sub_{song_id}", "-")
|
||||||
|
if custom_songs == True:
|
||||||
|
english_title = custom_song_titles.get(f"song_{song_id}", "-")
|
||||||
|
english_subtitle = custom_song_subtitles.get(f"song_sub_{song_id}", "-")
|
||||||
|
|
||||||
star_easy = song.get("starEasy", "N/A")
|
star_easy = song.get("starEasy", "N/A")
|
||||||
star_normal = song.get("starNormal", "N/A")
|
star_normal = song.get("starNormal", "N/A")
|
||||||
@ -261,17 +327,35 @@ tree.bind("<Button-1>", toggle_checkbox)
|
|||||||
def preview_audio(song_id):
|
def preview_audio(song_id):
|
||||||
preview_pos = get_preview_pos(song_id)
|
preview_pos = get_preview_pos(song_id)
|
||||||
if preview_pos is not None:
|
if preview_pos is not None:
|
||||||
song_filename = f"data/sound/song_{song_id}.mp3"
|
song_filename = os.path.join(data_dir, "sound", f"song_{song_id}.mp3")
|
||||||
subprocess.run(["ffplay", "-autoexit", "-ss", f"{preview_pos / 1000}", song_filename])
|
subprocess.run(["ffplay", "-autoexit", "-ss", f"{preview_pos / 1000}", song_filename])
|
||||||
|
|
||||||
|
if custom_songs:
|
||||||
|
custom_preview_pos = get_preview_pos(song_id)
|
||||||
|
if custom_preview_pos is not None:
|
||||||
|
custom_song_filename = os.path.join(custom_data_dir, "sound", f"song_{song_id}.mp3")
|
||||||
|
subprocess.run(["ffplay", "-autoexit", "-ss", f"{custom_preview_pos / 1000}", custom_song_filename])
|
||||||
|
|
||||||
|
|
||||||
def get_preview_pos(song_id):
|
def get_preview_pos(song_id):
|
||||||
|
# Load previewpos data from the default file
|
||||||
with open(previewpos_path, "r", encoding="utf-8") as previewpos_file:
|
with open(previewpos_path, "r", encoding="utf-8") as previewpos_file:
|
||||||
previewpos_data = json.load(previewpos_file)
|
previewpos_data = json.load(previewpos_file)
|
||||||
for item in previewpos_data:
|
for item in previewpos_data:
|
||||||
if item["id"] == song_id:
|
if item["id"] == song_id:
|
||||||
return item["previewPos"]
|
return item["previewPos"]
|
||||||
|
|
||||||
|
# If use_custom is True, also try to load from the custom file
|
||||||
|
if custom_songs:
|
||||||
|
with open(custom_previewpos_path, "r", encoding="utf-8") as custom_previewpos_file:
|
||||||
|
custom_previewpos_data = json.load(custom_previewpos_file)
|
||||||
|
for item in custom_previewpos_data:
|
||||||
|
if item["id"] == song_id:
|
||||||
|
return item["previewPos"]
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def preview_selected():
|
def preview_selected():
|
||||||
selected_item = tree.selection()
|
selected_item = tree.selection()
|
||||||
if selected_item:
|
if selected_item:
|
||||||
@ -493,6 +577,10 @@ def export_data():
|
|||||||
# Load preview position data
|
# Load preview position data
|
||||||
with open(previewpos_path, "r", encoding="utf-8") as previewpos_file:
|
with open(previewpos_path, "r", encoding="utf-8") as previewpos_file:
|
||||||
previewpos_data = json.load(previewpos_file)
|
previewpos_data = json.load(previewpos_file)
|
||||||
|
|
||||||
|
if custom_songs:
|
||||||
|
with open(custom_previewpos_path, "r", encoding="utf-8") as custom_previewpos_file:
|
||||||
|
custom_previewpos_data = json.load(custom_previewpos_file)
|
||||||
|
|
||||||
# Copy fumen folders for selected songs to output directory
|
# Copy fumen folders for selected songs to output directory
|
||||||
for item_id in selected_items:
|
for item_id in selected_items:
|
||||||
@ -503,9 +591,23 @@ def export_data():
|
|||||||
|
|
||||||
song_info = next((item for item in music_info["items"] if item["id"] == song_id), None)
|
song_info = next((item for item in music_info["items"] if item["id"] == song_id), None)
|
||||||
|
|
||||||
|
if custom_songs:
|
||||||
|
for item_id in selected_items:
|
||||||
|
song_id = tree.item(item_id)["values"][2]
|
||||||
|
custom_fumen_folder_path = os.path.join(custom_data_dir, "fumen", str(song_id))
|
||||||
|
if os.path.exists(custom_fumen_folder_path):
|
||||||
|
shutil.copytree(custom_fumen_folder_path, os.path.join(fumen_output_dir, f"{song_id}"))
|
||||||
|
|
||||||
|
song_info = next((item for item in custom_music_info["items"] if item["id"] == song_id), None)
|
||||||
|
|
||||||
for item_id in selected_items:
|
for item_id in selected_items:
|
||||||
song_id = tree.item(item_id)["values"][2]
|
song_id = tree.item(item_id)["values"][2]
|
||||||
song_info = next((item for item in music_info["items"] if item["id"] == song_id), None)
|
if custom_songs:
|
||||||
|
combined_items = custom_music_info["items"] + music_info["items"]
|
||||||
|
else:
|
||||||
|
combined_items = music_info["items"]
|
||||||
|
|
||||||
|
song_info = next((item for item in combined_items if item["id"] == song_id), None)
|
||||||
|
|
||||||
if song_info:
|
if song_info:
|
||||||
|
|
||||||
@ -703,84 +805,106 @@ def export_data():
|
|||||||
if game_platform == "PS4":
|
if game_platform == "PS4":
|
||||||
# Find the corresponding preview position for the current song_id
|
# Find the corresponding preview position for the current song_id
|
||||||
preview_pos = next((item["previewPos"] for item in previewpos_data if item["id"] == song_id), None)
|
preview_pos = next((item["previewPos"] for item in previewpos_data if item["id"] == song_id), None)
|
||||||
if preview_pos is not None:
|
if custom_songs:
|
||||||
# Run the audio conversion command based on the game platform
|
custom_preview_pos = next((item["previewPos"] for item in custom_previewpos_data if item["id"] == song_id), None)
|
||||||
def convert_song(song_id):
|
|
||||||
preview_pos = get_preview_pos(song_id)
|
def convert_song(song_id, custom_songs):
|
||||||
song_filename = f"data/sound/song_{song_id}.mp3"
|
preview_pos = get_preview_pos(song_id)
|
||||||
output_file = os.path.join(audio_output_dir, f"song_{song_id}.nus3bank")
|
if custom_songs and custom_preview_pos is not None:
|
||||||
command = [
|
song_filename = os.path.join(custom_data_dir, "sound", f"song_{song_id}.mp3")
|
||||||
"python",
|
else:
|
||||||
"conv.py",
|
song_filename = os.path.join(data_dir, "sound", f"song_{song_id}.mp3")
|
||||||
song_filename,
|
|
||||||
"at9",
|
output_file = os.path.join(audio_output_dir, f"song_{song_id}.nus3bank")
|
||||||
platform_tag,
|
command = [
|
||||||
str(preview_pos), # Convert preview_pos to string
|
"python",
|
||||||
song_id
|
"conv.py",
|
||||||
]
|
song_filename,
|
||||||
subprocess.run(command)
|
"at9",
|
||||||
|
platform_tag,
|
||||||
|
str(preview_pos), # Convert preview_pos to string
|
||||||
|
song_id
|
||||||
|
]
|
||||||
|
subprocess.run(command)
|
||||||
|
if os.path.exists(f"song_{song_id}.nus3bank"):
|
||||||
shutil.move(f"song_{song_id}.nus3bank", output_file)
|
shutil.move(f"song_{song_id}.nus3bank", output_file)
|
||||||
|
print(f"Created {output_file} successfully.")
|
||||||
|
else:
|
||||||
|
print(f"Conversion failed for song_{song_id}.")
|
||||||
|
if os.path.exists(f"song_{song_id}.mp3.at9"):
|
||||||
|
os.remove(f"song_{song_id}.mp3.at9")
|
||||||
|
print(f"Deleted song_{song_id}.mp3.at9")
|
||||||
|
else:
|
||||||
|
print(f"Error: File song_{song_id}.mp3.at9 not found.")
|
||||||
|
|
||||||
|
# Check if preview_pos or custom_preview_pos is not None and run conversion
|
||||||
|
if preview_pos is not None or (custom_songs and custom_preview_pos is not None):
|
||||||
|
convert_song(song_id, custom_songs)
|
||||||
|
|
||||||
|
elif game_platform == "PTB":
|
||||||
|
# Find the corresponding preview position for the current song_id
|
||||||
|
preview_pos = next((item["previewPos"] for item in previewpos_data if item["id"] == song_id), None)
|
||||||
|
if custom_songs:
|
||||||
|
custom_preview_pos = next((item["previewPos"] for item in custom_previewpos_data if item["id"] == song_id), None)
|
||||||
|
|
||||||
|
def convert_song(song_id, custom_songs):
|
||||||
|
preview_pos = get_preview_pos(song_id)
|
||||||
|
if custom_songs and custom_preview_pos is not None:
|
||||||
|
song_filename = os.path.join(custom_data_dir, "sound", f"song_{song_id}.mp3")
|
||||||
|
else:
|
||||||
|
song_filename = os.path.join(data_dir, "sound", f"song_{song_id}.mp3")
|
||||||
|
output_file = os.path.join(audio_output_dir, f"song_{song_id}.bin")
|
||||||
|
command = [
|
||||||
|
"python",
|
||||||
|
"script/acb/acb.py",
|
||||||
|
song_filename,
|
||||||
|
song_id
|
||||||
|
]
|
||||||
|
subprocess.run(command)
|
||||||
|
shutil.move(f"song_{song_id}.bin", output_file)
|
||||||
|
|
||||||
|
# Check if preview_pos or custom_preview_pos is not None and run conversion
|
||||||
|
if preview_pos is not None or (custom_songs and custom_preview_pos is not None):
|
||||||
|
convert_song(song_id, custom_songs)
|
||||||
|
|
||||||
elif game_platform == "NS1":
|
elif game_platform == "NS1":
|
||||||
# Find the corresponding preview position for the current song_id
|
# Find the corresponding preview position for the current song_id
|
||||||
preview_pos = next((item["previewPos"] for item in previewpos_data if item["id"] == song_id), None)
|
preview_pos = next((item["previewPos"] for item in previewpos_data if item["id"] == song_id), None)
|
||||||
if preview_pos is not None:
|
if custom_songs:
|
||||||
# Run the audio conversion command based on the game platform
|
custom_preview_pos = next((item["previewPos"] for item in custom_previewpos_data if item["id"] == song_id), None)
|
||||||
def convert_song(song_id):
|
|
||||||
preview_pos = get_preview_pos(song_id)
|
def convert_song(song_id, custom_songs):
|
||||||
song_filename = f"data/sound/song_{song_id}.mp3"
|
preview_pos = get_preview_pos(song_id)
|
||||||
output_file = os.path.join(audio_output_dir, f"song_{song_id}.nus3bank")
|
if custom_songs and custom_preview_pos is not None:
|
||||||
command = [
|
song_filename = os.path.join(custom_data_dir, "sound", f"song_{song_id}.mp3")
|
||||||
"python",
|
else:
|
||||||
"conv.py",
|
song_filename = os.path.join(data_dir, "sound", f"song_{song_id}.mp3")
|
||||||
song_filename,
|
|
||||||
"idsp",
|
output_file = os.path.join(audio_output_dir, f"song_{song_id}.nus3bank")
|
||||||
platform_tag,
|
command = [
|
||||||
str(preview_pos), # Convert preview_pos to string
|
"python",
|
||||||
song_id
|
"conv.py",
|
||||||
]
|
song_filename,
|
||||||
subprocess.run(command)
|
"idsp",
|
||||||
|
platform_tag,
|
||||||
|
str(preview_pos), # Convert preview_pos to string
|
||||||
|
song_id
|
||||||
|
]
|
||||||
|
subprocess.run(command)
|
||||||
|
if os.path.exists(f"song_{song_id}.nus3bank"):
|
||||||
shutil.move(f"song_{song_id}.nus3bank", output_file)
|
shutil.move(f"song_{song_id}.nus3bank", output_file)
|
||||||
|
print(f"Created {output_file} successfully.")
|
||||||
|
else:
|
||||||
|
print(f"Conversion failed for song_{song_id}.")
|
||||||
|
if os.path.exists(f"song_{song_id}.mp3.idsp"):
|
||||||
|
os.remove(f"song_{song_id}.mp3.idsp")
|
||||||
|
print(f"Deleted song_{song_id}.mp3.idsp")
|
||||||
|
else:
|
||||||
|
print(f"Error: File song_{song_id}.mp3.idsp not found.")
|
||||||
|
|
||||||
elif game_platform == "PTB":
|
# Check if preview_pos or custom_preview_pos is not None and run conversion
|
||||||
# Find the corresponding preview position for the current song_id
|
if preview_pos is not None or (custom_songs and custom_preview_pos is not None):
|
||||||
preview_pos = next((item["previewPos"] for item in previewpos_data if item["id"] == song_id), None)
|
convert_song(song_id, custom_songs)
|
||||||
if preview_pos is not None:
|
|
||||||
# Run the audio conversion command based on the game platform
|
|
||||||
def convert_song(song_id):
|
|
||||||
preview_pos = get_preview_pos(song_id)
|
|
||||||
song_filename = f"data/sound/song_{song_id}.mp3"
|
|
||||||
output_file = os.path.join(audio_output_dir, f"song_{song_id}.bin")
|
|
||||||
command = [
|
|
||||||
"python",
|
|
||||||
"script/acb/acb.py",
|
|
||||||
song_filename,
|
|
||||||
song_id
|
|
||||||
]
|
|
||||||
subprocess.run(command)
|
|
||||||
shutil.move(f"song_{song_id}.bin", output_file)
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
if len(selected_items) > 0:
|
|
||||||
with concurrent.futures.ThreadPoolExecutor(max_workers=max_concurrent) as executor:
|
|
||||||
futures = []
|
|
||||||
|
|
||||||
for item_id in selected_items:
|
|
||||||
song_id = tree.item(item_id)["values"][2]
|
|
||||||
|
|
||||||
if song_id not in processed_ids:
|
|
||||||
# Submit conversion task for this song ID
|
|
||||||
futures.append(executor.submit(convert_song, song_id))
|
|
||||||
processed_ids.add(song_id) # Mark as processed
|
|
||||||
|
|
||||||
# Wait for all tasks to complete
|
|
||||||
concurrent.futures.wait(futures)
|
|
||||||
else:
|
|
||||||
messagebox.showinfo("No Songs Selected", "Please select songs to export.")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
messagebox.showerror("Export Error", f"An error occurred during export: {str(e)}")
|
|
||||||
|
|
||||||
# Export selected musicinfo and wordlist
|
# Export selected musicinfo and wordlist
|
||||||
if game_platform == "PTB":
|
if game_platform == "PTB":
|
||||||
|
Loading…
Reference in New Issue
Block a user