Skip to content

Commit

Permalink
修复bug
Browse files Browse the repository at this point in the history
  • Loading branch information
SK-la committed Nov 3, 2024
1 parent 0fa1ce9 commit b48277e
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 144 deletions.
4 changes: 2 additions & 2 deletions bin/Dispatch_data.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#Dispatch_data.py
from mod.SV import get_sv
from bin.Samples import get_samples
from bin.config import get_config
from bin.conv_bmson import bms
from bin.utils import setup_custom_logger
from bin.get_info import get_info
from bin.osu import generate_osu_file
from bin.utils import setup_custom_logger
from mod.SV import get_sv
from mod.clm_no_empty import remove_empty_columns
from mod.lock_cs import lock_cs

Expand Down
69 changes: 24 additions & 45 deletions bin/Dispatch_file.py
Original file line number Diff line number Diff line change
@@ -1,55 +1,41 @@
import asyncio
import hashlib
import json
import os
import pathlib
import re
from pathlib import Path

import aiofiles

from bin.Dispatch_data import dispatch
from bin.utils import setup_custom_logger, load_hash_cache, save_hash_cache
from bin.utils import setup_custom_logger

logger = setup_custom_logger(__name__)
BATCH_SIZE = 2000
semaphore = asyncio.Semaphore(2000)
semaphore = asyncio.Semaphore(5000)

async def process_file(bmson_file, output_folder, settings, error_list, cache_folder):
async def process_file(bmson_file, output_folder, settings, error_list):
try:
bmson_file = pathlib.Path(bmson_file)
cache_folder = cache_folder / bmson_file.parent.name
hash_cache = await load_hash_cache(cache_folder)
bmson_file = Path(bmson_file)

async with aiofiles.open(bmson_file, 'r', encoding='utf-8') as file:
data = json.loads(await file.read())
content = await file.read()
data = json.loads(content) # 尝试解析 JSON
data['input_file_path'] = str(bmson_file)

osu_content, info, audio_data = await dispatch(data, settings)
logger.info(f"Main audio: {audio_data.main_audio}")
new_md5 = hashlib.md5(osu_content.encode('utf-8')).hexdigest()

# 检查文件夹名称是否带后缀
parent_name_suffix = extract_parent_name_suffix(bmson_file.parent.name)
if parent_name_suffix:
# 如果存在后缀,则将其添加到 info.new_folder 后面
info.new_folder += parent_name_suffix

song_folder = pathlib.Path(output_folder / info.new_folder )
song_folder = Path(output_folder / info.new_folder )
song_folder.mkdir(parents=True, exist_ok=True)
sub_folder = pathlib.Path(song_folder / info.sub_folder)
sub_folder = Path(song_folder / info.sub_folder)
sub_folder.mkdir(parents=True, exist_ok=True)

osu_file_path = pathlib.Path(song_folder / f"{info.osu_filename}.osu")

if osu_file_path.exists():
existing_md5 = hash_cache.get(str(osu_file_path))
if not existing_md5:
async with aiofiles.open(osu_file_path, 'rb') as f:
existing_md5 = hashlib.md5(await f.read()).hexdigest()
hash_cache[str(osu_file_path)] = existing_md5
if existing_md5 == new_md5:
logger.info(f"File {osu_file_path} already exists and is identical. Skipping.")
return
osu_file_path = Path(song_folder / f"{info.osu_filename}.osu")

async with aiofiles.open(osu_file_path, 'w', encoding='utf-8') as file:
await file.write(osu_content)
Expand All @@ -61,7 +47,6 @@ async def process_file(bmson_file, output_folder, settings, error_list, cache_fo
files = await scan_folder(bmson_file.parent)
await process_batches(files, existing_file_names_song, existing_file_names_sub, settings, song_folder, sub_folder, info, audio_data)

await save_hash_cache(cache_folder, hash_cache)
return info

except Exception as e:
Expand All @@ -79,23 +64,21 @@ async def process_batches(files, existing_file_names_song, existing_file_names_s
batch = files[i:i + BATCH_SIZE]
tasks = []
for file_path in batch:
file_path = pathlib.Path(file_path)
if settings.include_images and file_path.suffix in {'.jpg', '.png'} and file_path.stem == pathlib.Path(info.image).stem:
tasks.append(
copy_if_not_exists(file_path, song_folder / f"{info.img_filename}", existing_file_names_song))
file_path = Path(file_path)
if settings.include_images and file_path.suffix in {'.jpg', '.png'} and file_path.stem == Path(info.image).stem:
await copy_if_not_exists(file_path, song_folder / f"{info.img_filename}", existing_file_names_song)

if settings.include_audio:
if file_path.suffix in {'.mp3', '.wav', '.ogg'} and file_path.stem == pathlib.Path(audio_data.main_audio).stem:
if file_path.suffix in {'.mp3', '.wav', '.ogg'} and file_path.stem == Path(audio_data.main_audio).stem:
logger.info(f"匹配的主音频: {file_path}")
tasks.append(
copy_if_not_exists(file_path, song_folder / f"{info.song}", existing_file_names_song))
tasks.append(
copy_if_not_exists(file_path, sub_folder / file_path.name, existing_file_names_sub))
elif file_path.suffix in {'.mp3', '.wav', '.ogg'} and file_path.stem != pathlib.Path(audio_data.main_audio).stem:
elif file_path.suffix in {'.mp3', '.wav', '.ogg'} and file_path.stem != Path(audio_data.main_audio).stem:
if not await compare_file_names(existing_file_names_sub, (sub_folder / file_path.name).name):
tasks.append(
copy_if_not_exists(file_path, sub_folder / file_path.name, existing_file_names_sub))
elif file_path.suffix in {'.wmv', '.mp4', '.avi'} and file_path.stem == pathlib.Path(info.vdo).stem:
await copy_if_not_exists(file_path, sub_folder / file_path.name, existing_file_names_sub)
elif file_path.suffix in {'.wmv', '.mp4', '.avi'} and file_path.stem == Path(info.vdo).stem:
tasks.append(
copy_if_not_exists(file_path, song_folder / f"{info.vdo}", existing_file_names_song))

Expand All @@ -104,18 +87,18 @@ async def process_batches(files, existing_file_names_song, existing_file_names_s

# 先进行所有文件的对比和忽略操作
# for file_path in files:
# file_path = pathlib.Path(file_path)
# if settings.include_images and file_path.suffix in {'.jpg', '.png'} and file_path.stem == pathlib.Path(info.image).stem:
# file_path = Path(file_path)
# if settings.include_images and file_path.suffix in {'.jpg', '.png'} and file_path.stem == Path(info.image).stem:
# tasks.append(copy_if_not_exists(file_path, song_folder / f"{info.img_filename}", existing_file_names_song))
#
# if settings.include_audio:
# if file_path.suffix in {'.mp3', '.wav', '.ogg'} and file_path.stem == pathlib.Path(audio_data.main_audio).stem:
# if file_path.suffix in {'.mp3', '.wav', '.ogg'} and file_path.stem == Path(audio_data.main_audio).stem:
# tasks.append(copy_if_not_exists(file_path, song_folder / f"{info.song}", existing_file_names_song))
# tasks.append(copy_if_not_exists(file_path, sub_folder / file_path.name, existing_file_names_sub))
# elif file_path.suffix in {'.mp3', '.wav', '.ogg'} and file_path.stem != pathlib.Path(audio_data.main_audio).stem:
# elif file_path.suffix in {'.mp3', '.wav', '.ogg'} and file_path.stem != Path(audio_data.main_audio).stem:
# if not await compare_file_names(existing_file_names_sub, (sub_folder / file_path.name).name):
# tasks.append(copy_if_not_exists(file_path, sub_folder / file_path.name, existing_file_names_sub))
# elif file_path.suffix in {'.wmv', '.mp4', '.avi'} and file_path.stem == pathlib.Path(info.vdo).stem:
# elif file_path.suffix in {'.wmv', '.mp4', '.avi'} and file_path.stem == Path(info.vdo).stem:
# tasks.append(copy_if_not_exists(file_path, song_folder / f"{info.vdo}", existing_file_names_song))
#
async def copy_if_not_exists(file_path, destination_path, existing_file_names):
Expand All @@ -140,12 +123,8 @@ async def compare_file_names(existing_file_names, file_name):
return file_name in existing_file_names

async def scan_folder(folder_path):
files = []
for root, _, filenames in os.walk(folder_path):
for filename in filenames:
file_path = os.path.join(root, filename)
if os.path.isfile(file_path):
files.append(file_path)
folder_path = Path(folder_path)
files = [str(file) for file in folder_path.rglob('*') if file.is_file()]
return files

def extract_parent_name_suffix(parent_name):
Expand Down
37 changes: 16 additions & 21 deletions bin/Samples.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,23 @@ def get_samples(data, info, settings):
y_start, y_end, y_min, all_notes = get_y_values(data)

main_audio = ''
for channel in data['sound_channels']:
for note in channel['notes']:
if 'y' in note and note['y'] == y_start:
main_audio = channel.get('name', '')
break
if main_audio:
for note in all_notes:
if note['y'] == y_start and not (1 <= note['x'] <= 16):
main_audio = note['name']
break

song_lg = round((y_end - y_start) * info.MpB)
offset = round((y_min - y_start) * info.MpB)

samples = []
if hasattr(settings, 'convert_sample_bg') and settings.convert_sample_bg:
invalid_notes = [note for note in all_notes if not (1 <= note['x'] <= 16)]
invalid_notes.sort(key=lambda notes: notes['y'])
reset_invalid_notes = [
{'x': note['x'], 'y': note['y'] - invalid_notes[0]['y'], 'name': note.get('name', 'unknown')} for note in
invalid_notes]

for note in reset_invalid_notes:
if settings.convert_sample_bg:
reset_notes = [{'x': note['x'], 'y': note['y'] - all_notes[0]['y'], 'name': note.get('name', '')} for note in all_notes]
invalid_notes = [note for note in reset_notes if not (1 <= note['x'] <= 16)]
for note in invalid_notes:
hs = note['name'].replace("sound\\", f"{info.sub_folder}/")
note_time = calculate_pulse_time(note['y'], info) + offset
samples.append(f"5,{note_time},0,\"{hs}\"")
if note['name'] != main_audio:
note_time = calculate_pulse_time(note['y'], info)
samples.append(f"5,{note_time},0,\"{hs}\"")

audio_data = AudioData(
samples=samples,
Expand All @@ -50,7 +44,6 @@ def get_samples(data, info, settings):
return audio_data



def calculate_pulse_time(y, info):
return round(y * info.MpB)

Expand All @@ -59,11 +52,13 @@ def get_y_values(data):
valid_notes = []

for channel in data['sound_channels']:
channel_name = channel.get('name', '')
for note in channel['notes']:
if 'x' in note and 'y' in note:
all_notes.append(note)
if 1 <= note['x'] <= 16:
valid_notes.append(note)
note['name'] = channel_name # 将 channel 的 name 属性添加到 note 中
all_notes.append(note)
if 1 <= note['x'] <= 16:
valid_notes.append(note)
logger.debug(f"Processed note: {note}")

all_notes.sort(key=lambda notes: notes['y'])
valid_notes.sort(key=lambda notes: notes['y'])
Expand Down
11 changes: 5 additions & 6 deletions bin/aio.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,28 @@
from bin.utils import setup_custom_logger

logger = setup_custom_logger(__name__)
semaphore = asyncio.Semaphore(200) # 限制并发任务数量
semaphore = asyncio.Semaphore(2000) # 限制并发任务数量

async def process_folder(folder_path, output_folder_path, settings, error_list, cache_folder):
async def process_folder(folder_path, output_folder_path, settings, error_list):
folder_path = Path(folder_path)
output_folder_path = Path(output_folder_path)
cache_folder = Path(cache_folder)
for bmson_file in folder_path.glob("*.bmson"):
async with semaphore:
try:
await process_file(bmson_file, output_folder_path, settings, error_list, cache_folder)
await process_file(bmson_file, output_folder_path, settings, error_list)
except Exception as e:
error_list.append((bmson_file, str(e)))
logger.error(f"Error processing file {bmson_file}: {e}")

async def start_conversion(input_folder_path, output_folder_path, settings, cache_folder):
async def start_conversion(input_folder_path, output_folder_path, settings):
input_folder_path = Path(input_folder_path)
output_folder_path = Path(output_folder_path)
error_list = []

tasks = []
for folder in input_folder_path.iterdir():
if folder.is_dir():
tasks.append(process_folder(folder, output_folder_path, settings, error_list, cache_folder))
tasks.append(process_folder(folder, output_folder_path, settings, error_list))

await asyncio.gather(*tasks)

Expand Down
2 changes: 1 addition & 1 deletion config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
creator = SK_la
hp = 7
od = 7
source = EZ2AC_AE
source = EZ2DJ_7th_CV
tags =
nos = N
nop = N
Expand Down
55 changes: 17 additions & 38 deletions ui/MainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
from PyQt6 import QtWidgets, QtCore
from PyQt6.QtWidgets import QMessageBox, QMainWindow

from bin.aio import start_conversion
from bin.config import get_config
from ui.layouts import setup_main_layout
from ui.osu_path import get_osu_songs_path
from ui.settings import ConversionSettings, ConversionWorker
from ui.settings import ConversionSettings
from ui.styling import set_window_icon, set_background_image
from ui.translations import load_translations, get_system_language

Expand Down Expand Up @@ -59,12 +60,6 @@ def initUI(self):
self.auto_create_output_folder.stateChanged.connect(self.handle_auto_create_output_folder)
self.setStatusBar(self.status_bar) # 添加状态栏

# 准备回调字典
callbacks = {
"select_input": self.select_input,
"select_output": self.select_output,
"handle_auto_create_output_folder": self.handle_auto_create_output_folder,
}
def delayed_initialization(self):
pass
def show_notification(self, message):
Expand Down Expand Up @@ -100,48 +95,32 @@ def handle_auto_create_output_folder(self, state):
QMessageBox.warning(self, "错误", "未选择 osu! 安装路径,请手动设置输出文件夹。")
self.auto_create_output_folder.setChecked(False)

def start_conversion_thread(self):
def start_conversion(self):
self.update_status("运行中,请勿关闭")
self.worker = ConversionWorker(
input_path=urllib.parse.unquote_plus(self.input_path.text()),
output_path=self.output_path.text(),
settings=self.get_conversion_settings(),
cache_folder=pathlib.Path("hash_cache"),
)
self.worker_thread = QtCore.QThread() # 每次创建新的线程
self.worker.moveToThread(self.worker_thread)
# 连接信号和槽
self.worker.conversion_finished.connect(self.conversion_finished_handler)
self.worker_thread.started.connect(self.worker.run_conversion)

# 开始线程
self.worker_thread.start()

def conversion_finished_handler(self):
"""处理转换完成的槽函数"""
self.show_conversion_complete_notification()
# 清理工作,例如删除 worker 和 thread
self.worker.deleteLater()
self.worker_thread.quit()
self.worker_thread.wait()
self.worker_thread.deleteLater()
self.worker_thread = None

def start_conversion(self):
# 自动创建输出文件夹
if self.auto_create_output_folder.isChecked():
osu_songs_path = pathlib.Path(self.settings.value("osu_songs_path"))
output_path = self.create_output_folder(osu_songs_path)
self.output_path.setText(str(output_path))
else:
output_path = self.output_path.text()
output_path = pathlib.Path(self.output_path.text())

# 确保使用self.input_path来访问属性
input_path = urllib.parse.unquote_plus(self.input_path.text())
input_path = pathlib.Path(urllib.parse.unquote_plus(self.input_path.text()))

# 直接运行异步转换
loop = asyncio.get_event_loop()
loop.create_task(self.run_async_conversion(input_path, output_path))

# 使用多线程启动转换
self.start_conversion_thread()
self.update_file_trees(pathlib.Path(input_path), pathlib.Path(output_path))
# 更新文件树
self.update_file_trees(input_path, output_path)

async def run_async_conversion(self, input_path, output_path):
settings = self.get_conversion_settings()
# cache_folder = pathlib.Path("hash_cache")
await start_conversion(input_path, output_path, settings)
self.show_conversion_complete_notification()

def show_conversion_complete_notification(self):
QMessageBox.information(self, "Message", "程序结束")
Expand Down
19 changes: 9 additions & 10 deletions ui/home_tab.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from PyQt6 import QtWidgets

from bin.Dispatch_file import process_file
from bin.aio import start_conversion


class HomeTab(QtWidgets.QWidget):
Expand All @@ -29,13 +28,14 @@ def initUI(self):
layout.addLayout(tree_layout)
self.setLayout(layout)

def start_conversion(self):
input_path = urllib.parse.unquote_plus(self.parent.input_path.text())
output_path = self.parent.output_path.text()
settings = self.parent.get_conversion_settings()
cache_folder = pathlib.Path("hash_cache")

asyncio.create_task(start_conversion(input_path, output_path, settings, cache_folder))
# async def start_conversion(self):
# input_path = urllib.parse.unquote_plus(self.parent.input_path.text())
# output_path = self.parent.output_path.text()
# settings = self.parent.get_conversion_settings()
# cache_folder = pathlib.Path("hash_cache")
#
# await start_conversion(input_path, output_path, settings, cache_folder)
# self.parent.show_conversion_complete_notification()

class FileTreeWidget(QtWidgets.QTreeWidget):
def __init__(self, parent, tree_type, main_window):
Expand Down Expand Up @@ -96,9 +96,8 @@ async def convert_file(self, item):
file_path = pathlib.Path(item.text(0))
if file_path.exists() and file_path.is_file():
output_path = pathlib.Path(self.main_window.output_path.text())
cache_folder = pathlib.Path("hash_cache")
await process_file(
file_path, output_path, self.main_window.settings, [], cache_folder)
file_path, output_path, self.main_window.settings, [])
self.main_window.show_notification(f"文件 {file_path} 转换完成")

def delete_file(self, item):
Expand Down
Loading

0 comments on commit b48277e

Please sign in to comment.