| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- from dash.dependencies import Input, Output, State, ALL
- from dash import html, callback_context
- from utils.file_utils import list_files_in_directory, save_file, delete_file, is_valid_wav
- from components.hotwords import generate_training_data_table
- import os
- import base64
- TRAINING_HOTWORD_DIR = './training/hotword/'
- def register_manage_data_callbacks(app):
- @app.callback(
- Output('file-preview-list', 'children'),
- [
- Input('upload-training-data', 'contents'),
- Input({'type': 'delete-preview-file', 'index': ALL}, 'n_clicks')
- ],
- [
- State('upload-training-data', 'filename'),
- State('upload-training-data', 'last_modified'),
- State('file-preview-list', 'children')
- ]
- )
- def manage_file_previews(contents, n_clicks, filenames, last_modified, preview_list):
- ctx = callback_context
- if not ctx.triggered:
- return preview_list
- if preview_list is None:
- preview_list = []
- triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
- if 'upload-training-data' in triggered_id and contents:
- files = []
- for content, filename in zip(contents, filenames):
- files.append(html.Div([
- html.Audio(src=f'data:audio/wav;base64,{content.split(",")[1]}', controls=True),
- html.Button("Delete", id={'type': 'delete-preview-file', 'index': filename}),
- html.Div(content, style={'display': 'none'}, id={'type': 'file-content', 'index': filename})
- ], id={'type': 'preview-file', 'index': filename}))
- return preview_list + files
- if 'delete-preview-file' in triggered_id:
- filename_to_delete = ctx.triggered[0]['prop_id'].split('.')[1]
- new_preview_list = [
- item for item in preview_list if item['props']['id']['index'] != filename_to_delete
- ]
- return new_preview_list
- return preview_list
- @app.callback(
- Output('upload-status', 'children'),
- Input('confirm-upload', 'n_clicks'),
- State('file-preview-list', 'children'),
- State('url', 'pathname')
- )
- def upload_files(n_clicks, preview_list, pathname):
- if n_clicks and preview_list:
- model_name = pathname.split('/')[-1]
- for item in preview_list:
- content = item['props']['children'][2]['props']['children']
- filename = item['props']['id']['index']
- data = content.split(",")[1]
- file_path = f'{TRAINING_HOTWORD_DIR}/{model_name}/{filename}'
- save_file(file_path, base64.b64decode(data))
- if not is_valid_wav(file_path):
- os.remove(file_path)
- return f"File {filename} is not a valid WAV file.", True
- training_data = list_files_in_directory(f'{TRAINING_HOTWORD_DIR}/{model_name}')
- return generate_training_data_table(model_name, training_data)
- return html.Div()
- @app.callback(
- Output('hotword-manage-training-data', 'children'),
- [
- Input({"type": "delete-button", "index": ALL}, 'n_clicks'),
- Input({"type": "toggle-button", 'index': ALL}, 'n_clicks')
- ],
- [
- State({"type": "delete-button", "index": ALL}, 'id'),
- State({"type": "toggle-button", "index": ALL}, 'id'),
- State('url', 'pathname')
- ]
- )
- def manage_training_data(n_clicks_delete, n_clicks_toggle, delete_ids, toggle_ids, pathname):
- ctx = callback_context
- if not ctx.triggered:
- return html.Div()
- model_name = pathname.split('/')[-1]
- triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
- if 'delete-button' in triggered_id:
- for item in delete_ids:
- if item['id'] == triggered_id:
- file_path = os.path.join(TRAINING_HOTWORD_DIR, model_name, item['index'])
- delete_file(file_path)
- training_data = list_files_in_directory(f'{TRAINING_HOTWORD_DIR}/{model_name}')
- return generate_training_data_table(model_name, training_data)
- if 'toggle-button' in triggered_id:
- for item in toggle_ids:
- if item['id'] == triggered_id:
- file_path = os.path.join(TRAINING_HOTWORD_DIR, model_name, item['index'])
- new_file_path = os.path.join(TRAINING_HOTWORD_DIR, model_name, '_' + item['index'] if not item['index'].startswith('_') else item['index'][1:])
- os.rename(file_path, new_file_path)
- training_data = list_files_in_directory(f'{TRAINING_HOTWORD_DIR}/{model_name}')
- return generate_training_data_table(model_name, training_data)
- return html.Div()
|