VideoTools/scripts/git_converter/lt-gui.sh
Jake P 799102cac7 Attempted to create GUI
Attempted to create GUIs for both lt-convert and lt-gui
2025-12-17 22:50:59 +00:00

618 lines
17 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# ===================================================================
# LT-Convert GUI - VideoTools Style Interface
# Author: LeakTechnologies
# Fyne-based GUI matching VideoTools design
# ===================================================================
# Check if Fyne is available
if ! command -v fyne &> /dev/null; then
echo "❌ Fyne not found. Please install Fyne:"
echo " go install fyne.io/fyne/v2/cmd/fyne@latest"
exit 1
fi
# Get script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/modules/hardware.sh"
source "$SCRIPT_DIR/modules/codec.sh"
source "$SCRIPT_DIR/modules/quality.sh"
source "$SCRIPT_DIR/modules/filters.sh"
source "$SCRIPT_DIR/modules/encode.sh"
# VideoTools-style colors
GRID_COLOR="#2C3E50"
TEXT_COLOR="#FFFFFF"
ACCENT_COLOR="#00BCD4"
SUCCESS_COLOR="#4CAF50"
WARNING_COLOR="#FF9800"
ERROR_COLOR="#F44336"
# Create main GUI
create_main_gui() {
echo "🔨 Building Go GUI application..."
# Create temporary directory for build
mkdir -p /tmp/lt-gui-build
cd /tmp/lt-gui-build
cat > lt_convert_gui.go << 'EOF'
package main
import (
"fmt"
"image/color"
"os"
"path/filepath"
"strings"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
type ConversionConfig struct {
VideoFiles []string
SelectedEncoder string
SelectedQuality string
SelectedResolution string
SelectedFPS string
SelectedColor string
OutputContainer string
}
var config ConversionConfig
func main() {
config = ConversionConfig{
VideoFiles: getVideoFiles(),
SelectedEncoder: "Auto-detect",
SelectedQuality: "High Quality (CRF 18)",
SelectedResolution: "Source",
SelectedFPS: "Original",
SelectedColor: "No color correction",
OutputContainer: "mkv",
}
a := app.New()
w := a.NewWindow("LT-Convert - VideoTools Style")
w.Resize(fyne.NewSize(1000, 700))
w.SetContent(buildMainUI())
w.ShowAndRun()
}
func getVideoFiles() []string {
// Get video files from current directory
files, err := os.ReadDir(".")
if err != nil {
return []string{}
}
var videos []string
for _, file := range files {
if !file.IsDir() && isVideoFile(file.Name()) {
videos = append(videos, file.Name())
}
}
return videos
}
func isVideoFile(filename string) bool {
ext := strings.ToLower(filepath.Ext(filename))
videoExts := []string{".mp4", ".mkv", ".mov", ".avi", ".wmv", ".ts", ".m2ts", ".flv", ".webm", ".m4v"}
for _, ve := range videoExts {
if ext == ve {
return true
}
}
return false
}
func buildMainUI() fyne.CanvasObject {
// Title
title := canvas.NewText("LT-CONVERT", color.White)
title.TextStyle = fyne.TextStyle{Monospace: true, Bold: true}
title.TextSize = 28
// File list
fileLabel := widget.NewLabel("VIDEO FILES")
fileLabel.TextStyle = fyne.TextStyle{Bold: true}
var fileList *widget.List
if len(config.VideoFiles) > 0 {
fileList = widget.NewList([]string{"No video files found"}, func(i widget.ListItemID, o widget.ListItemID, v widget.ListItemID) {})
} else {
fileList = widget.NewList(config.VideoFiles, func(i widget.ListItemID, o widget.ListItemID, v widget.ListItemID) {})
}
// Settings sections
settingsContainer := buildSettingsContainer()
// Action buttons
startBtn := widget.NewButton("START CONVERSION", func() {
startConversion()
})
startBtn.Importance = widget.HighImportance
quitBtn := widget.NewButton("QUIT", func() {
os.Exit(0)
})
quitBtn.Importance = widget.LowImportance
// Layout
header := container.NewHBox(
container.NewCenter(title),
container.NewSpacer(),
quitBtn,
)
content := container.NewVBox(
header,
widget.NewSeparator(),
container.NewHSplit(
container.NewVBox(
fileLabel,
fileList,
),
settingsContainer,
),
widget.NewSeparator(),
container.NewHBox(
container.NewSpacer(),
startBtn,
),
)
return container.NewPadded(content)
}
func buildSettingsContainer() fyne.CanvasObject {
// Encoder selection
encoderLabel := widget.NewLabel("ENCODER")
encoderLabel.TextStyle = fyne.TextStyle{Bold: true}
encoderSelect := widget.NewSelect([]string{
"Auto-detect",
"NVIDIA HEVC NVENC",
"NVIDIA AV1 NVENC",
"AMD HEVC AMF",
"AMD AV1 AMF",
"Intel HEVC QSV",
"Intel AV1 QSV",
"CPU SVT-AV1",
"CPU x265 HEVC",
}, func(selected string) {
config.SelectedEncoder = selected
})
encoderSelect.SetSelected(config.SelectedEncoder)
// Quality selection
qualityLabel := widget.NewLabel("QUALITY")
qualityLabel.TextStyle = fyne.TextStyle{Bold: true}
qualitySelect := widget.NewSelect([]string{
"Source quality (bypass)",
"High Quality (CRF 18)",
"Good Quality (CRF 20)",
"DVD-NTSC Professional",
"DVD-PAL Professional",
"Custom bitrate",
}, func(selected string) {
config.SelectedQuality = selected
})
qualitySelect.SetSelected(config.SelectedQuality)
// Resolution selection
resolutionLabel := widget.NewLabel("RESOLUTION")
resolutionLabel.TextStyle = fyne.TextStyle{Bold: true}
resolutionSelect := widget.NewSelect([]string{
"Source file resolution",
"720p (1280×720)",
"1080p (1920×1080)",
"1440p (2560×1440)",
"4K (3840×2160)",
"2X Upscale",
"4X Upscale",
}, func(selected string) {
config.SelectedResolution = selected
})
resolutionSelect.SetSelected(config.SelectedResolution)
// FPS selection
fpsLabel := widget.NewLabel("FPS")
fpsLabel.TextStyle = fyne.TextStyle{Bold: true}
fpsSelect := widget.NewSelect([]string{
"Original FPS",
"60 FPS",
}, func(selected string) {
config.SelectedFPS = selected
})
fpsSelect.SetSelected(config.SelectedFPS)
// Color correction
colorLabel := widget.NewLabel("COLOR")
colorLabel.TextStyle = fyne.TextStyle{Bold: true}
colorSelect := widget.NewSelect([]string{
"No color correction",
"Fix pink skin tones (Topaz AI)",
"Warm enhancement",
"Cool enhancement",
"2000s DVD Restore",
"90s Quality Restore",
"VHS Quality Restore",
"Anime Preservation",
}, func(selected string) {
config.SelectedColor = selected
})
colorSelect.SetSelected(config.SelectedColor)
// Container selection
containerLabel := widget.NewLabel("CONTAINER")
containerLabel.TextStyle = fyne.TextStyle{Bold: true}
containerSelect := widget.NewSelect([]string{
"MKV (flexible)",
"MP4 (compatible)",
}, func(selected string) {
config.OutputContainer = strings.ToLower(strings.Fields(selected)[0])
})
containerSelect.SetSelected("MKV (flexible)")
// Layout settings in grid
settingsGrid := container.NewGridWithColumns(2,
encoderLabel, encoderSelect,
qualityLabel, qualitySelect,
resolutionLabel, resolutionSelect,
fpsLabel, fpsSelect,
colorLabel, colorSelect,
containerLabel, containerSelect,
)
return container.NewVBox(
widget.NewCard(settingsGrid),
)
}
func startConversion() {
if len(config.VideoFiles) == 0 {
dialog.ShowError("No video files found", "Please add video files to the directory and restart.")
return
}
// Show confirmation dialog
dialog.ShowConfirm("Start Conversion",
fmt.Sprintf("Convert %d file(s) with these settings?\n\nEncoder: %s\nQuality: %s\nResolution: %s\nFPS: %s\nColor: %s\nContainer: %s",
len(config.VideoFiles),
config.SelectedEncoder,
config.SelectedQuality,
config.SelectedResolution,
config.SelectedFPS,
config.SelectedColor,
config.OutputContainer),
func(confirmed bool) {
if confirmed {
runConversion()
}
}, nil)
}
func runConversion() {
// This would call the bash conversion functions
// For now, just show success message
dialog.ShowInformation("Conversion Started",
fmt.Sprintf("Converting %d file(s)...\n\nSettings applied:\n- Encoder: %s\n- Quality: %s\n- Resolution: %s\n- FPS: %s\n- Color: %s\n- Container: %s",
len(config.VideoFiles),
config.SelectedEncoder,
config.SelectedQuality,
config.SelectedResolution,
config.SelectedFPS,
config.SelectedColor,
config.OutputContainer))
}
EOF
# Check if Windows x64
detect_windows_x64() {
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]] && [[ "$(uname -m)" == "x86_64" ]]; then
return 0
fi
return 1
}
# Pre-built Windows x64 GUI
build_windows_exe() {
if detect_windows_x64; then
echo "🎯 Detected Windows x64 - checking for pre-built GUI..."
# Check for pre-built executable
if [[ -f "$SCRIPT_DIR/lt-convert-gui.exe" ]]; then
echo "✅ Found pre-built Windows GUI executable"
return 0
else
echo "⚠️ Pre-built GUI not found, building from source..."
return 1
fi
else
return 1
fi
}
# Build GUI from source (fallback)
build_gui_from_source() {
echo "🔨 Building GUI from source..."
cat > lt_convert_gui.go << 'ENDOFFILE'
package main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func main() {
a := app.New()
w := a.NewWindow("LT-Convert GUI")
w.Resize(fyne.NewSize(800, 600))
content := container.NewVBox(
widget.NewLabelWithStyle("LT-Convert GUI", fyne.TextStyle{Bold: true}),
widget.NewSeparator(),
widget.NewLabel("VideoTools Style Interface v1.0"),
widget.NewSeparator(),
widget.NewButton("Launch Bash Mode", func() {
w.Close()
}),
widget.NewButton("Quit", func() {
a.Quit()
}),
)
w.SetContent(content)
w.ShowAndRun()
}
ENDOFFILE
if go build -o lt-convert-gui lt_convert_gui.go 2>/dev/null; then
echo "✅ GUI built successfully"
return 0
else
echo "❌ Build failed"
return 1
fi
}
# Unified GUI builder
build_gui() {
echo "🔨 Building GUI application..."
# Try Windows x64 pre-built first
if build_windows_exe; then
echo "🚀 Launching pre-built Windows GUI..."
cd "$SCRIPT_DIR"
./lt-convert-gui.exe
return 0
fi
# Fallback to source build
echo "📝 Building from source (fallback)..."
build_gui_from_source
if [[ $? -eq 0 ]]; then
echo "🚀 Launching GUI..."
if [[ -f "./lt-convert-gui" ]] || [[ -f "./lt-convert-gui.exe" ]]; then
echo "✅ GUI executable ready"
return 0
else
echo "❌ GUI executable not found after build"
return 1
fi
else
echo "❌ GUI build failed"
return 1
fi
}
ENDOFFILE
if go build -o lt-convert-gui lt_convert_gui.go 2>/dev/null; then
echo "✅ GUI built successfully"
return 0
else
echo "❌ Build failed"
return 1
fi
}
EOF
# Try to build
echo "Building Go application..."
if go build -o lt-convert-gui lt_convert_gui.go 2>/dev/null; then
echo "✅ GUI built successfully"
return 0
else
echo "❌ Build failed"
return 1
fi
}
GO_EOF
echo "🔨 Building GUI..."
# Build with error handling
if go build -o lt-convert-gui lt_convert_gui.go 2>build.log; then
echo "✅ GUI built successfully"
return 0
else
echo "❌ GUI build failed. Check build.log:"
cat build.log 2>/dev/null || echo "No build log created"
return 1
fi
}
func buildSimpleUI() fyne.CanvasObject {
title := container.NewVBox(
widget.NewLabelWithStyle("LT-CONVERT", fyne.TextStyle{Bold: true, Monospace: true}),
widget.NewLabel("VideoTools Style GUI"),
)
// Encoder selection
encoderSelect := widget.NewSelect([]string{
"Auto-detect",
"NVIDIA HEVC NVENC",
"NVIDIA AV1 NVENC",
"AMD HEVC AMF",
"AMD AV1 AMF",
"Intel HEVC QSV",
"Intel AV1 QSV",
"CPU SVT-AV1",
"CPU x265 HEVC",
}, func(selected string) {
fmt.Printf("Selected encoder: %s\n", selected)
})
// Quality selection
qualitySelect := widget.NewSelect([]string{
"Source quality (bypass)",
"High Quality (CRF 18)",
"Good Quality (CRF 20)",
"DVD-NTSC Professional",
"DVD-PAL Professional",
"Custom bitrate",
}, func(selected string) {
fmt.Printf("Selected quality: %s\n", selected)
})
// Start button
startBtn := widget.NewButton("START CONVERSION WITH BASH", func() {
dialog.ShowConfirm("Start Conversion", "This will launch the bash version with your settings. Continue?", func(confirmed bool) {
if confirmed {
fmt.Println("Starting bash conversion...")
// In real implementation, this would call lt-convert.sh with saved settings
os.Exit(0)
}
}, nil)
})
startBtn.Importance = widget.HighImportance
quitBtn := widget.NewButton("QUIT", func() {
os.Exit(0)
})
return container.NewVBox(
title,
widget.NewSeparator(),
container.NewGridWithColumns(2,
widget.NewLabel("Encoder:"), encoderSelect,
widget.NewLabel("Quality:"), qualitySelect,
),
widget.NewSeparator(),
container.NewHBox(
widget.NewLabel("Click START to run bash version"),
container.NewSpacer(),
startBtn,
quitBtn,
),
)
}
GO_EOF
# Try to build
if go build -o lt-convert-gui lt_convert_gui.go 2>/dev/null; then
echo "✅ GUI built successfully"
return 0
else
echo "❌ GUI build failed"
return 1
fi
}
}
# Check dependencies
check_dependencies() {
echo "🔍 Checking dependencies..."
if ! command -v go &> /dev/null; then
echo "❌ Go not found. Please install Go:"
echo " https://golang.org/dl/"
return 1
fi
if ! command -v fyne &> /dev/null; then
echo "❌ Fyne not found. Installing Fyne..."
go install fyne.io/fyne/v2/cmd/fyne@latest
if [[ $? -ne 0 ]]; then
echo "❌ Failed to install Fyne"
return 1
fi
fi
echo "✅ Dependencies ready"
return 0
}
# Main execution
main() {
clear
cat << "EOF"
╔════════════════════════════════════════════════════════╗
║ LT-Convert GUI Mode ║
(VideoTools Style)
╚══════════════════════════════════════════════════════════════════════════════╝
Launching modern Fyne-based GUI...
EOF
# Check dependencies
if ! check_dependencies; then
echo "❌ Dependency check failed. Falling back to bash mode..."
echo "Press Enter to continue to lt-convert.sh..."
read
bash "$SCRIPT_DIR/lt-convert.sh" "$@"
return
fi
# Try to build and run GUI
if ! build_gui; then
echo "❌ GUI build failed. Falling back to bash mode..."
echo "Press Enter to continue to lt-convert.sh..."
read
bash "$SCRIPT_DIR/lt-convert.sh" "$@"
return
fi
# Run GUI with Windows x64 check
run_gui() {
cd "$SCRIPT_DIR"
if detect_windows_x64; then
# For Windows x64, check for exe
if [[ -f "./lt-convert-gui.exe" ]]; then
echo "🚀 Launching Windows GUI..."
./lt-convert-gui.exe
elif [[ -f "./lt-convert-gui" ]]; then
echo "🚀 Launching GUI..."
./lt-convert-gui
else
echo "❌ GUI executable not found"
return 1
fi
else
# Non-Windows or build failed, run bash version
echo "📋 Running bash version..."
bash "$SCRIPT_DIR/lt-convert.sh" "$@"
fi
}
}
}
# Run main function
main "$@"