feat: implement project management and media track handling
- Added domain entities for audio, subtitle, and video tracks. - Created a Project entity to manage media editing sessions. - Implemented value objects for file paths, sync offsets, track IDs, and languages. - Developed infrastructure for asynchronous FFmpeg process execution. - Built a user interface for selecting video files, adding audio and subtitle tracks, and managing output settings. - Integrated error handling and logging for media processing tasks.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
use eframe::egui;
|
||||
|
||||
/// Estado da execução do FFmpeg.
|
||||
#[derive(Default, PartialEq)]
|
||||
pub enum ExecutionState {
|
||||
#[default]
|
||||
Idle,
|
||||
Running,
|
||||
Success,
|
||||
Error(String),
|
||||
}
|
||||
|
||||
/// Painel de execução: botão "Gerar MKV", progresso e erros.
|
||||
pub struct ExecutionPanel {
|
||||
pub state: ExecutionState,
|
||||
pub log_lines: Vec<String>,
|
||||
}
|
||||
|
||||
impl ExecutionPanel {
|
||||
pub fn new() -> Self {
|
||||
ExecutionPanel {
|
||||
state: ExecutionState::Idle,
|
||||
log_lines: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_log(&mut self, line: String) {
|
||||
self.log_lines.push(line);
|
||||
// Limita o histórico de log
|
||||
if self.log_lines.len() > 200 {
|
||||
self.log_lines.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Renderiza o painel. Retorna `true` se o botão "Gerar MKV" foi clicado.
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, can_generate: bool) -> bool {
|
||||
let mut clicked = false;
|
||||
|
||||
ui.group(|ui| {
|
||||
ui.heading("Gerar arquivo");
|
||||
|
||||
let is_running = self.state == ExecutionState::Running;
|
||||
|
||||
if ui
|
||||
.add_enabled(
|
||||
can_generate && !is_running,
|
||||
egui::Button::new(if is_running {
|
||||
"Processando…"
|
||||
} else {
|
||||
"Gerar MKV"
|
||||
}),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
clicked = true;
|
||||
}
|
||||
|
||||
match &self.state {
|
||||
ExecutionState::Idle => {}
|
||||
ExecutionState::Running => {
|
||||
ui.spinner();
|
||||
ui.label("Processando...");
|
||||
}
|
||||
ExecutionState::Success => {
|
||||
ui.colored_label(egui::Color32::GREEN, "✓ Arquivo gerado com sucesso!");
|
||||
}
|
||||
ExecutionState::Error(msg) => {
|
||||
ui.colored_label(egui::Color32::RED, "✗ Erro durante o processamento:");
|
||||
ui.add(
|
||||
egui::TextEdit::multiline(&mut msg.as_str())
|
||||
.desired_rows(4)
|
||||
.desired_width(f32::INFINITY),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Log de progresso
|
||||
if !self.log_lines.is_empty() {
|
||||
ui.collapsing("Log detalhado", |ui| {
|
||||
egui::ScrollArea::vertical()
|
||||
.max_height(150.0)
|
||||
.show(ui, |ui| {
|
||||
for line in &self.log_lines {
|
||||
ui.label(egui::RichText::new(line).monospace().size(11.0));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
clicked
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user