diff --git a/data/database.db b/data/database.db index cc809d3..c9cae12 100644 Binary files a/data/database.db and b/data/database.db differ diff --git a/database/__pycache__/db_manager.cpython-313.pyc b/database/__pycache__/db_manager.cpython-313.pyc index 651770f..d458632 100644 Binary files a/database/__pycache__/db_manager.cpython-313.pyc and b/database/__pycache__/db_manager.cpython-313.pyc differ diff --git a/database/__pycache__/models.cpython-313.pyc b/database/__pycache__/models.cpython-313.pyc index b51b524..3abf0a6 100644 Binary files a/database/__pycache__/models.cpython-313.pyc and b/database/__pycache__/models.cpython-313.pyc differ diff --git a/database/db_manager.py b/database/db_manager.py index 3d76dde..3f4d7c3 100644 --- a/database/db_manager.py +++ b/database/db_manager.py @@ -14,13 +14,14 @@ class DatabaseManager: app_dir = Path(os.path.dirname(os.path.abspath(__file__))).parent data_dir = app_dir / 'data' db_path = str(data_dir / 'database.db') - + print(f"db_path: {db_path}") cls._instance.db_path = db_path cls._instance._init_database() return cls._instance def __init__(self): - self.init_database() + # self.init_database() + pass def _init_database(self): Path(self.db_path).parent.mkdir(parents=True, exist_ok=True) @@ -30,22 +31,27 @@ class DatabaseManager: CREATE TABLE IF NOT EXISTS configs ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + channel_id INTEGER NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(name, channel_id) ); CREATE TABLE IF NOT EXISTS params ( id INTEGER PRIMARY KEY, config_id INTEGER, + channel_id INTEGER NOT NULL, delay_data1 FLOAT, ENC_volume_data1 FLOAT, ENT_mx_right_data FLOAT, ENT_mix_left_data FLOAT, - FOREIGN KEY (config_id) REFERENCES configs(id) + FOREIGN KEY (config_id) REFERENCES configs(id), + FOREIGN KEY (channel_id) REFERENCES configs(channel_id) ); CREATE TABLE IF NOT EXISTS filters ( id INTEGER PRIMARY KEY, config_id INTEGER, + channel_id INTEGER NOT NULL, filter_type TEXT NOT NULL, freq FLOAT, q FLOAT, @@ -53,7 +59,8 @@ class DatabaseManager: slope FLOAT, enabled BOOLEAN DEFAULT TRUE, position INTEGER, - FOREIGN KEY (config_id) REFERENCES configs(id) + FOREIGN KEY (config_id) REFERENCES configs(id), + FOREIGN KEY (channel_id) REFERENCES configs(channel_id) ); """) @@ -62,51 +69,84 @@ class DatabaseManager: def get_all_configs(self) -> List[ConfigData]: with self.get_connection() as conn: - cursor = conn.execute("SELECT id, name, created_at FROM configs") + cursor = conn.execute("SELECT id, name, channel_id, created_at FROM configs") return [ConfigData(*row) for row in cursor.fetchall()] def load_config(self, config_id: int) -> Tuple[Optional[ParamData], List[FilterData]]: with self.get_connection() as conn: + # 1. 首先加载参数数据 cursor = conn.execute( - "SELECT * FROM params WHERE config_id = ?", + """SELECT config_id, channel_id, delay_data1, ENC_volume_data1, + ENT_mx_right_data, ENT_mix_left_data + FROM params WHERE config_id = ?""", (config_id,) ) param_row = cursor.fetchone() - params = ParamData(*param_row[2:]) if param_row else None + if param_row is None: + return None, [] + # 2. 创建 ParamData 对象 + params = ParamData( + config_id=param_row[0], + channel_id=param_row[1], + delay_data1=param_row[2], + ENC_volume_data1=param_row[3], + ENT_mx_right_data=param_row[4], + ENT_mix_left_data=param_row[5] + ) + + # 3. 加载滤波器数据 cursor = conn.execute( - "SELECT * FROM filters WHERE config_id = ? ORDER BY position", + """SELECT config_id, channel_id, filter_type, freq, q, gain, slope, + enabled, position, id + FROM filters WHERE config_id = ? ORDER BY position""", (config_id,) ) - filters = [FilterData(*row[2:]) for row in cursor.fetchall()] - + filters = [] + for row in cursor.fetchall(): + filters.append(FilterData( + channel_id=row[1], + filter_type=row[2], + freq=row[3], + q=row[4], + gain=row[5], + slope=row[6], + enabled=bool(row[7]), + position=row[8], + config_id=row[0], + id=row[9] + )) + print(f"load_config filters: {filters}") return params, filters - def save_config(self, name: str, params: ParamData, filters: List[FilterData]) -> int: + def save_config(self, name: str, channel_id: int, params: ParamData, filters: List[FilterData]) -> int: with self.get_connection() as conn: cursor = conn.execute( - "INSERT INTO configs (name) VALUES (?)", - (name,) + "INSERT INTO configs (name, channel_id) VALUES (?, ?)", + (name, channel_id) ) config_id = cursor.lastrowid + params.config_id = config_id conn.execute( """INSERT INTO params - (config_id, delay_data1, ENC_volume_data1, ENT_mx_right_data, ENT_mix_left_data) - VALUES (?, ?, ?, ?, ?)""", - (config_id, params.delay_data1, params.ENC_volume_data1, + (config_id, channel_id, delay_data1, ENC_volume_data1, ENT_mx_right_data, ENT_mix_left_data) + VALUES (?, ?, ?, ?, ?, ?)""", + (params.config_id, params.channel_id, params.delay_data1, params.ENC_volume_data1, params.ENT_mx_right_data, params.ENT_mix_left_data) ) for filter_data in filters: - conn.execute( + filter_data.config_id = config_id + cursor = conn.execute( """INSERT INTO filters - (config_id, filter_type, freq, q, gain, slope, enabled, position) - VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", - (config_id, filter_data.filter_type, filter_data.freq, - filter_data.q, filter_data.gain, filter_data.slope, + (config_id, channel_id, filter_type, freq, q, gain, slope, enabled, position) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""", + (filter_data.config_id, filter_data.channel_id, filter_data.filter_type, + filter_data.freq, filter_data.q, filter_data.gain, filter_data.slope, filter_data.enabled, filter_data.position) ) + filter_data.id = cursor.lastrowid conn.commit() return config_id @@ -137,29 +177,37 @@ class DatabaseManager: if not configs: # 创建默认配置 default_params = ParamData( + channel_id=1, delay_data1=0.0, ENC_volume_data1=0.0, ENT_mx_right_data=0.0, - ENT_mix_left_data=0.0 + ENT_mix_left_data=0.0, + config_id=None # 将在 save_config 中设置 ) # 创建一些默认滤波器 default_filters = [ FilterData( + channel_id=1, filter_type="PEQ", freq=1000.0, q=1.0, gain=0.0, - slope=12.0 + slope=12.0, + position=0, + config_id=None # 将在 save_config 中设置 ), FilterData( + channel_id=1, filter_type="HPF", freq=20.0, q=0.707, gain=0.0, - slope=12.0 + slope=12.0, + position=1, + config_id=None # 将在 save_config 中设置 ) ] # 保存默认配置 - self.save_config("Default Config", default_params, default_filters) + self.save_config("Default Config", 1, default_params, default_filters) diff --git a/database/models.py b/database/models.py index 3be871d..8ceb411 100644 --- a/database/models.py +++ b/database/models.py @@ -4,17 +4,21 @@ from datetime import datetime @dataclass class FilterData: + channel_id: int filter_type: str freq: float q: float gain: float slope: float - id: int = None enabled: bool = True position: int = 0 + config_id: Optional[int] = None + id: Optional[int] = None @dataclass class ParamData: + config_id: int + channel_id: int delay_data1: float ENC_volume_data1: float ENT_mx_right_data: float @@ -24,4 +28,5 @@ class ParamData: class ConfigData: id: int name: str + channel_id: int created_at: str diff --git a/widgets/__pycache__/audio_filter_widget.cpython-313.pyc b/widgets/__pycache__/audio_filter_widget.cpython-313.pyc index 3f1011a..4993e0d 100644 Binary files a/widgets/__pycache__/audio_filter_widget.cpython-313.pyc and b/widgets/__pycache__/audio_filter_widget.cpython-313.pyc differ diff --git a/widgets/__pycache__/avas_widget.cpython-313.pyc b/widgets/__pycache__/avas_widget.cpython-313.pyc index 03be399..8df9d26 100644 Binary files a/widgets/__pycache__/avas_widget.cpython-313.pyc and b/widgets/__pycache__/avas_widget.cpython-313.pyc differ diff --git a/widgets/audio_filter_widget.py b/widgets/audio_filter_widget.py index 83b46fb..5b8b5ab 100644 --- a/widgets/audio_filter_widget.py +++ b/widgets/audio_filter_widget.py @@ -8,8 +8,11 @@ class AudioFilterModel: def __init__(self, db_manager: DatabaseManager): self.db_manager = db_manager self.current_config_id: Optional[int] = None + self.current_channel_id: int = 1 # 添加当前通道ID self.filters: List[FilterData] = [] self.params: ParamData = ParamData( + config_id=None, + channel_id=self.current_channel_id, # 设置通道ID delay_data1=0.0, ENC_volume_data1=0.0, ENT_mx_right_data=0.0, @@ -19,15 +22,22 @@ class AudioFilterModel: def load_config(self, config_id: int) -> bool: params, filters = self.db_manager.load_config(config_id) + print(f"load_config filters: {filters}") if params is not None: self.params = params self.filters = filters self.current_config_id = config_id + self.current_channel_id = params.channel_id # 更新当前通道ID return True return False def save_config(self, name: str) -> int: - return self.db_manager.save_config(name, self.params, self.filters) + # 确保所有对象都有正确的channel_id + self.params.channel_id = self.current_channel_id + for filter_data in self.filters: + print(f"save_config filter_data.channel_id: {filter_data.channel_id}") + filter_data.channel_id = self.current_channel_id + return self.db_manager.save_config(name, self.current_channel_id, self.params, self.filters) def update_filter(self, index: int, **kwargs): if 0 <= index < len(self.filters): @@ -162,39 +172,38 @@ class AudioFilterController: return next_number def add_filter(self): - # 检查是否达到最大滤波器数量 - if len(self.model.filters) >= 20: - print("已达到最大滤波器数量限制(20个)") - return - - # 显示滤波器类型选择对话框 + # 1. 用户界面创建 dialog = FilterTypeDialog(self.view) if dialog.exec(): filter_type = dialog.get_selected_type() - - # 获取下一个可用的序号 next_number = self.get_next_available_number(filter_type) - - # 创建新的滤波器名称 new_filter_type = f"{filter_type}_{next_number}" - # 创建新的滤波器,使用默认参数 + # 2. 内存中创建 FilterData 对象 new_filter = FilterData( filter_type=new_filter_type, - freq=1000.0, + freq=10.0, q=1.0, - gain=0.0, - slope=12.0, - position=len(self.model.filters) + gain=1.0, + slope=1.0, + position=len(self.model.filters), + config_id=self.model.current_config_id, + channel_id=self.model.current_channel_id, + enabled=True, + id=None # 初始创建时 id 为 None ) - # 添加到模型中 + # 3. 添加到模型的过滤器列表 self.model.filters.append(new_filter) - # 如果有当前配置,保存到数据库 - if self.model.current_config_id: - self.model.save_config(f"Config {self.model.current_config_id}") - + # 4. 保存到数据库 + if not self.model.current_config_id: + # 创建新配置,使用默认名称 + config_name = f"Channel {self.model.current_channel_id} Config" + self.model.save_config(config_name) + else: + # 更新现有配置 + self.model.save_config(f"Config {self.model.current_config_id}") # 更新视图 self.view.update_table() @@ -231,7 +240,7 @@ class AudioFilterController: pass class AudioFilterWidget(QWidget): - def __init__(self): + def __init__(self, channel_id: int = 1): super().__init__() self.ui = Ui_Widget() self.ui.setupUi(self) @@ -242,38 +251,16 @@ class AudioFilterWidget(QWidget): self.db_manager = DatabaseManager() self.model = AudioFilterModel(self.db_manager) + self.model.current_channel_id = channel_id # 设置当前通道ID - # 加载配置 + # 加载该通道的默认配置 configs = self.db_manager.get_all_configs() if configs: - # 有配置则加载最后一个 - last_config_id = configs[-1].id - self.model.load_config(last_config_id) - else: - # 没有配置则创建默认配置 - default_params = ParamData( - delay_data1=0.0, - ENC_volume_data1=0.0, - ENT_mx_right_data=0.0, - ENT_mix_left_data=0.0 - ) - - # 创建默认滤波器 - self.model.filters = [ - FilterData( - filter_type="PEQ", - freq=1000.0, - q=1.0, - gain=0.0, - slope=12.0 - ) - ] - self.model.params = default_params - - # 保存到数据库 - config_id = self.model.save_config("Default Config") - self.model.current_config_id = config_id - + # 查找当前通道的配置 + channel_config = next((config for config in configs if config.channel_id == channel_id), None) + if channel_config: + self.model.load_config(channel_config.id) + self.controller = AudioFilterController(self.model, self) self.update_view() @@ -287,10 +274,12 @@ class AudioFilterWidget(QWidget): def update_table_row(self, row: int): filter_data = self.model.filters[row] + print(f"filter_data: {filter_data}") # 创建带复选框的滤波器名称项 - filter_item = QTableWidgetItem(filter_data.filter_type) + filter_item = QTableWidgetItem() filter_item.setFlags(filter_item.flags() | Qt.ItemFlag.ItemIsUserCheckable) - filter_item.setCheckState(Qt.CheckState.Checked) # 默认选中 + filter_item.setCheckState(Qt.CheckState.Checked if filter_data.enabled else Qt.CheckState.Unchecked) + filter_item.setText(str(filter_data.filter_type)) # 设置文本,这样文本会和复选框一起显示 # 更新各列的值 self.ui.tableWidget.setItem(row, 0, filter_item) diff --git a/widgets/avas_widget.py b/widgets/avas_widget.py index 02851cc..a0d867e 100644 --- a/widgets/avas_widget.py +++ b/widgets/avas_widget.py @@ -9,6 +9,8 @@ class ChannelButton(QWidget): def __init__(self, channel_num): super().__init__() + self.channel_num = channel_num # 保存通道号 + # Create GroupBox for the channel self.group = QGroupBox(f"CH{channel_num}") layout = QVBoxLayout() @@ -98,8 +100,8 @@ class ChannelButton(QWidget): def show_filter_window(self): if not self.filter_window: - self.filter_window = AudioFilterWidget() - # Set window title to include channel number + # 创建滤波器窗口时传入对应的通道号 + self.filter_window = AudioFilterWidget(channel_id=self.channel_num) self.filter_window.setWindowTitle(f"Channel {self.group.title()} Filter Settings") # Show the window if it's not visible