Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

15 better error messages #22

Merged
merged 2 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 20 additions & 21 deletions internal/logic/sync.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package logic

import (
"io"
"bufio"
"context"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
Expand All @@ -15,7 +15,6 @@ import (

"fyne.io/fyne/v2/widget"
"github.com/dhowden/tag"

ff "github.com/dpolakovics/soundscape-sync/internal/ffmpeg"
)

Expand All @@ -40,23 +39,20 @@ func getAudioFiles(folder string) ([]string, error) {
return audioFiles, nil
}

// Add a statusCallback parameter to allow updates on what is happening
func CombineFiles(folder1 string, folder2 string, outputFolder string, progress *widget.ProgressBar, soundscapeVolume float64, statusCallback func(string)) error {
// Adjust volume to range [0.5, 1.0]
func CombineFiles(folder1 string, folder2 string, outputFolder string, progress *widget.ProgressBar, soundscapeVolume float64, debug bool, statusCallback func(string)) error {
soundscapeVolume = 0.5 + (soundscapeVolume / 100.0 * 0.5)

// Get list of audio files from both folders
files1, err := getAudioFiles(folder1)
if err != nil {
return err
return fmt.Errorf("failed to read audio files from folder1 (%s): %w. Check folder permissions or file formats and try again.", folder1, err)
}
files2, err := getAudioFiles(folder2)
if err != nil {
return err
return fmt.Errorf("failed to read audio files from folder2 (%s): %w. Check folder permissions or file formats and try again.", folder2, err)
}

if len(files1) != len(files2) {
return fmt.Errorf("the number of audio files in the two folders must be the same")
return fmt.Errorf("the number of audio files in the two folders does not match: folder1 has %d files, folder2 has %d files. Please ensure both folders contain the same number of audio files and that they are in the correct order before retrying.", len(files1), len(files2))
}

ffmpeg := ff.FFmpegPath()
Expand All @@ -65,7 +61,7 @@ func CombineFiles(folder1 string, folder2 string, outputFolder string, progress
for index, file := range files1 {
statusCallback(fmt.Sprintf("Preparing to combine file %d of %d: %s", index+1, total, filepath.Base(file)))

channel , err := getChannelAmount(file)
channel, err := getChannelAmount(file)
if err != nil {
return err
}
Expand All @@ -79,12 +75,10 @@ func CombineFiles(folder1 string, folder2 string, outputFolder string, progress
return err
}

// Get output file name
ext := filepath.Ext(file)
newFileName := outputFolder + "/" + filepath.Base(files2[index])
newFileName = newFileName[:len(newFileName)-4] + "_synced" + ext

// Construct FFmpeg command
ctx, _ := context.WithCancel(context.Background())
arguments := []string{
"-i", file,
Expand All @@ -95,28 +89,33 @@ func CombineFiles(folder1 string, folder2 string, outputFolder string, progress
if ext == ".mp3" || ext == ".flac" {
arguments = append(arguments, getCoverArtArguments(file, files2[index])...)
}

// If debug mode is enabled, add verbose logging arguments
if debug {
arguments = append(arguments, "-loglevel", "verbose")
}

arguments = append(arguments, newFileName)

cmd := exec.CommandContext(ctx, ffmpeg, arguments...)
cmd.SysProcAttr = getSysProcAttr()
stdout, err := cmd.StdoutPipe()
if err != nil {
// prepend error with text
err = fmt.Errorf("error creating ffmpeg command: %w", err)
err = fmt.Errorf("error creating FFmpeg command pipeline (arguments: %v): %w. Consider running with more detailed logging or contacting the developer if the problem persists.", cmd.Args, err)
return err
}

statusCallback(fmt.Sprintf("Combining file %d of %d...", index+1, total))

// Execute FFmpeg command
if err := cmd.Start(); err != nil {
err = fmt.Errorf("error at ffmpeg command start: %w", err)
err = fmt.Errorf("error starting FFmpeg command with arguments %v: %w. Check that the input files are accessible and not corrupted. If the issue persists, contact the developer.", cmd.Args, err)
return err
}

parseProgress(index, total, progress, stdout, duration)

if err := cmd.Wait(); err != nil {
err = fmt.Errorf("error at ffmpeg command wait: %w", err)
err = fmt.Errorf("FFmpeg encountered an error while processing file %q with arguments %v: %w. Check the input files for issues or consider contacting the developer for further assistance.", newFileName, cmd.Args, err)
return err
}

Expand All @@ -133,11 +132,11 @@ func getChannelAmount(file string) (int, error) {
cmd := exec.Command(ffprobe, "-v", "error", "-select_streams", "a:0", "-count_packets", "-show_entries", "stream=channels", "-of", "csv=p=0", file)
out, err := cmd.Output()
if err != nil {
return 0, err
return 0, fmt.Errorf("failed to determine channel amount for file %q: %w. The file might be corrupted or unsupported.", file, err)
}
channels, err := strconv.Atoi(strings.TrimSuffix(strings.TrimSpace(string(out)), ","))
if err != nil {
return 0, err
return 0, fmt.Errorf("invalid channel information retrieved for file %q: %w. Please ensure the file is a valid audio file and consider reporting this issue if it persists.", file, err)
}
return channels, nil
}
Expand All @@ -148,7 +147,7 @@ func getDuration(filename string) (float64, error) {
cmd := exec.Command(ffprobe, "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", filename)
out, err := cmd.Output()
if err != nil {
return 0, err
return 0, fmt.Errorf("failed to determine duration for file %q: %w. The file might be corrupted or unsupported. If issues persist, consider contacting the developer.", filename, err)
}
return strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
}
Expand Down Expand Up @@ -186,7 +185,7 @@ func getChannelArguments(channels int, volume float64) ([]string, error) {
case 12:
return get7_1_4Arguments(volume), nil
}
return nil, fmt.Errorf("Currently only stereo, 5.1, 7.1.2 and 7.1.4 Soundscapes are supported")
return nil, fmt.Errorf("unsupported soundscape format with %d channels. Currently only stereo (2 channels), 5.1 (6 channels), 7.1.2 (10 channels), and 7.1.4 (12 channels) are supported. Please convert your files or contact the developer for assistance.", channels)
}

func getCoverArtArguments(file1 string, file2 string) []string {
Expand Down
31 changes: 26 additions & 5 deletions internal/ui/windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func showFolderSelection(win fyne.Window, callback func(string)) {

dialog.ShowFolderOpen(func(uri fyne.ListableURI, err error) {
if err != nil {
dialog.ShowError(err, win)
showErrorDialog(win, fmt.Errorf("Failed to open folder selection dialog: %w. If this issue persists, please contact the developer.", err))
return
}
if uri == nil {
Expand Down Expand Up @@ -180,17 +180,18 @@ func CreateMainContent(app fyne.App, window fyne.Window) fyne.CanvasObject {

statusLabel := widget.NewLabel("Idle")

// Add a checkbox for debug mode
debugCheck := widget.NewCheck("Debug Mode", func(checked bool) {})

startButton.OnTapped = func() {
startButton.Disable()
progressBar.Show()
// Run CombineFiles synchronously on the main goroutine
err := logic.CombineFiles(folder1, folder2, folderOutput, progressBar, volumeSlider.Value, func(msg string) {
// Safe to call directly because we're on the main goroutine
err := logic.CombineFiles(folder1, folder2, folderOutput, progressBar, volumeSlider.Value, debugCheck.Checked, func(msg string) {
statusLabel.SetText(msg)
})
progressBar.Hide()
if err != nil {
dialog.ShowError(err, window)
showErrorDialog(window, fmt.Errorf("An error occurred while combining the audio files: %w. Check that the input files are valid and supported. If you continue to encounter this issue, consider seeking help from the developer and providing the details above.", err))
statusLabel.SetText("Error during combination")
} else {
dialog.ShowInformation("Success", "Audio files combined successfully", window)
Expand All @@ -204,6 +205,7 @@ func CreateMainContent(app fyne.App, window fyne.Window) fyne.CanvasObject {
"",
container.NewVBox(
statusLabel,
debugCheck,
startButton,
progressBar,
),
Expand Down Expand Up @@ -250,3 +252,22 @@ func updateStartButton(label1, label2, folderOutputLabel *widget.Label, button *
button.Disable()
}
}

func showErrorDialog(win fyne.Window, err error) {
if err == nil {
return
}

errorStr := err.Error()
copyButton := widget.NewButton("Copy Error", func() {
win.Clipboard().SetContent(errorStr)
})

errorLabel := widget.NewLabel(errorStr)
errorLabel.Wrapping = fyne.TextWrapWord

content := container.NewVBox(errorLabel, copyButton)
d := dialog.NewCustom("Error", "Close", content, win)
d.Resize(fyne.NewSize(700, 500))
d.Show()
}
32 changes: 25 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ package main

import (
"context"
"fmt"
"net/url"
"strconv"
"strings"

"github.com/dpolakovics/soundscape-sync/internal/ui"

"fyne.io/fyne/v2"
Expand All @@ -12,9 +16,6 @@ import (
"fyne.io/fyne/v2/widget"

"github.com/google/go-github/v39/github"
"fmt"
"strings"
"strconv"
)

const (
Expand All @@ -40,7 +41,7 @@ func checkForUpdates(a fyne.App, w fyne.Window) {
client := github.NewClient(nil)
release, _, err := client.Repositories.GetLatestRelease(context.Background(), owner, repo)
if err != nil {
dialog.ShowError(err, w)
showErrorDialog(w, fmt.Errorf("Failed to check for the latest release: %w. Please ensure you have an internet connection, and if the issue persists, reach out to the developer.", err))
return
}

Expand All @@ -61,7 +62,6 @@ func checkForUpdates(a fyne.App, w fyne.Window) {
}

func isNewerVersion(oldVer, newVer string) bool {
// Strip leading 'v'
oldVer = strings.TrimPrefix(oldVer, "v")
newVer = strings.TrimPrefix(newVer, "v")

Expand All @@ -78,6 +78,24 @@ func isNewerVersion(oldVer, newVer string) bool {
}
}

// If all matched so far, then a longer new version means it's newer
return len(newParts) > len(oldParts)
}
}

func showErrorDialog(win fyne.Window, err error) {
if err == nil {
return
}

errorStr := err.Error()
copyButton := widget.NewButton("Copy Error", func() {
win.Clipboard().SetContent(errorStr)
})

errorLabel := widget.NewLabel(errorStr)
errorLabel.Wrapping = fyne.TextWrapWord

content := container.NewVBox(errorLabel, copyButton)
d := dialog.NewCustom("Error", "Close", content, win)
d.Resize(fyne.NewSize(700, 500))
d.Show()
}
Loading