diff --git a/README.md b/README.md index a07d1ad..5715c7a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ Kleines macOS-SwiftUI-Tool zum Vorbereiten von Hörspielordnern für TonUINO/DFP ## Werkzeuge - `Datenumwandlung`: Schreibt die TonUINO-Ordnerstruktur. MP3-Dateien je Folge können zu `001.mp3` zusammengeführt oder getrennt als `001.mp3`, `002.mp3`, ... exportiert werden. -- `SD-Karte`: Prüft eine ausgewählte TonUINO-SD-Karte, führt `dot_clean` aus und kann MP3Gain mit `-r -k -d 4` auf alle MP3-Dateien anwenden. +- `SD-Karte`: Prüft eine ausgewählte TonUINO-SD-Karte und führt `dot_clean` aus. +- `MP3Gain`: Wendet MP3Gain mit `-r -k -d 4` rekursiv auf alle MP3-Dateien in einem gewählten Ordner an. - `ID3-Tags`: Bearbeitet MP3-Tags rekursiv auf einer SD-Karte oder in einem ausgewählten Ordner. ## Erwartete Input-Struktur diff --git a/Sources/ContentView.swift b/Sources/ContentView.swift index d8841a7..9649688 100644 --- a/Sources/ContentView.swift +++ b/Sources/ContentView.swift @@ -14,6 +14,11 @@ struct ContentView: View { Label("SD-Karte", systemImage: "sdcard") } + MP3GainToolView() + .tabItem { + Label("MP3Gain", systemImage: "waveform") + } + ID3TagToolView() .tabItem { Label("ID3-Tags", systemImage: "tag") @@ -301,13 +306,6 @@ private struct SDCardToolView: View { } .disabled(!canRun) - Button { - normalizeMP3Gain() - } label: { - Label("MP3Gain", systemImage: "waveform") - } - .disabled(!canRun) - Button { cleanSDCard() } label: { @@ -394,15 +392,73 @@ private struct SDCardToolView: View { } } +} + +private struct MP3GainToolView: View { + @State private var targetURL: URL? + @State private var messages: [ExportMessage] = [] + @State private var isWorking = false + + private var canRun: Bool { + targetURL != nil && !isWorking + } + + var body: some View { + VStack(spacing: 0) { + HStack(spacing: 10) { + Button { + chooseFolder(title: "Ordner für MP3Gain wählen") { url in + targetURL = url + messages = [] + } + } label: { + Label("Ordner", systemImage: "folder") + } + + Spacer() + + Button { + normalizeMP3Gain() + } label: { + Label("MP3Gain ausführen", systemImage: "waveform") + } + .buttonStyle(.borderedProminent) + .disabled(!canRun) + } + .padding(12) + + Divider() + + VStack(alignment: .leading, spacing: 16) { + VStack(alignment: .leading, spacing: 8) { + Text("MP3Gain Normalisierung") + .font(.title2.weight(.semibold)) + PathRow(label: "Ordner", url: targetURL) + Text("Verwendet rekursiv: mp3gain -r -k -d 4") + .foregroundStyle(.secondary) + } + + VStack(alignment: .leading, spacing: 10) { + Text("Protokoll") + .font(.headline) + MessageList(messages: messages, emptyText: "Noch keine MP3-Dateien normalisiert.") + } + + Spacer(minLength: 0) + } + .padding(16) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + } + } + private func normalizeMP3Gain() { - guard let sdCardURL else { return } + guard let targetURL else { return } isWorking = true messages = [.info("MP3Gain gestartet: -r -k -d 4")] DispatchQueue.global(qos: .userInitiated).async { - var result = MP3GainNormalizer(fileManager: .default).normalize(rootURL: sdCardURL) - result.append(contentsOf: SDCardValidator(fileManager: .default).validate(rootURL: sdCardURL)) + let result = MP3GainNormalizer(fileManager: .default).normalize(rootURL: targetURL) DispatchQueue.main.async { messages = result