Compare commits

...

6 Commits

3 changed files with 61 additions and 35 deletions

View File

@ -1474,7 +1474,7 @@ func authorDefaultOutputDir(outputType string) string {
if err != nil || home == "" {
home = "."
}
dir := filepath.Join(home, "Videos")
dir := filepath.Join(home, "Videos", "VideoTools")
if strings.EqualFold(outputType, "iso") {
return filepath.Join(dir, "ISO_Convert")
}
@ -1755,6 +1755,28 @@ func (s *appState) runAuthoringPipeline(ctx context.Context, paths []string, reg
mpgPaths = append(mpgPaths, remuxPath)
}
// Generate clips from paths if clips is empty (fallback for when job didn't save clips)
if len(clips) == 0 && len(paths) > 1 {
for i, path := range paths {
src, err := probeVideo(path)
duration := 0.0
displayName := filepath.Base(path)
if err == nil {
duration = src.Duration
displayName = src.DisplayName
}
clips = append(clips, authorClip{
Path: path,
DisplayName: displayName,
Duration: duration,
ChapterTitle: fmt.Sprintf("Chapter %d", i+1),
})
}
if logFn != nil {
logFn(fmt.Sprintf("Generated %d clips from input paths for chapter markers", len(clips)))
}
}
// Generate chapters from clips if available (for professional DVD navigation)
if len(chapters) == 0 && len(clips) > 1 {
chapters = chaptersFromClips(clips)
@ -1841,6 +1863,10 @@ func (s *appState) runAuthoringPipeline(ctx context.Context, paths []string, reg
}
if makeISO {
// Create output directory for ISO file if it doesn't exist
if err := os.MkdirAll(filepath.Dir(outputPath), 0755); err != nil {
return fmt.Errorf("failed to create ISO output directory: %w", err)
}
tool, args, err := buildISOCommand(outputPath, discRoot, title)
if err != nil {
logFn(fmt.Sprintf("ERROR: ISO tool not found: %v", err))
@ -1975,6 +2001,10 @@ func (s *appState) executeAuthorJob(ctx context.Context, job *queue.Job, progres
}
appendLog(fmt.Sprintf("Authoring ISO from VIDEO_TS: %s", videoTSPath))
// Create output directory for ISO file if it doesn't exist
if err := os.MkdirAll(filepath.Dir(outputPath), 0755); err != nil {
return fmt.Errorf("failed to create ISO output directory: %w", err)
}
tool, args, err := buildISOCommand(outputPath, videoTSPath, title)
if err != nil {
return err

47
main.go
View File

@ -6625,9 +6625,13 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
appendSuffixCheck := widget.NewCheck("Append \"-convert\" to filename", func(checked bool) {
state.convert.AppendSuffix = checked
if !state.convert.UseAutoNaming {
applyAutoName(false)
}
// Recalculate and update the output base to reflect the suffix change
// Always pass false for keepExisting to regenerate from source
newBase := state.resolveOutputBase(src, false)
updatingOutput = true
state.convert.OutputBase = newBase
outputEntry.SetText(newBase)
updatingOutput = false
// Update output hint to show the change immediately
if outputHint != nil {
outputHint.SetText(fmt.Sprintf("Output file: %s", state.convert.OutputFile()))
@ -8307,7 +8311,6 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
outputEntry,
outputHintContainer,
appendSuffixCheck,
coverDisplay,
widget.NewSeparator(),
advancedVideoEncodingBlock,
widget.NewSeparator(),
@ -9176,7 +9179,9 @@ Metadata: %s`,
makeRow("Metadata", metadata),
)
info := container.NewHBox(col1, col2)
// Add spacing between the two columns
spacer := layout.NewSpacer()
info := container.NewHBox(col1, spacer, col2)
// Copy metadata button - beside header text
copyBtn := widget.NewButton("📋", func() {
@ -9196,33 +9201,10 @@ Metadata: %s`,
headerRow := container.NewHBox(header, copyBtn)
top = container.NewBorder(nil, nil, nil, clearBtn, headerRow)
// Cover art display area - 40% larger (168x168)
coverImg := canvas.NewImageFromFile("")
coverImg.FillMode = canvas.ImageFillContain
coverImg.SetMinSize(fyne.NewSize(168, 168))
placeholderRect := canvas.NewRectangle(utils.MustHex("#0F1529"))
placeholderRect.SetMinSize(fyne.NewSize(168, 168))
placeholderText := widget.NewLabel("Drop cover\nart here")
placeholderText.Alignment = fyne.TextAlignCenter
placeholderText.TextStyle = fyne.TextStyle{Italic: true}
placeholder := container.NewMax(placeholderRect, container.NewCenter(placeholderText))
// Update cover art when changed
// Cover art support removed - users can add cover art through metadata editor
updateCoverDisplay := func() {
if state.convert.CoverArtPath != "" {
coverImg.File = state.convert.CoverArtPath
coverImg.Refresh()
placeholder.Hide()
coverImg.Show()
} else {
coverImg.Hide()
placeholder.Show()
}
// No-op: cover art display removed from this panel
}
updateCoverDisplay()
coverContainer := container.NewMax(placeholder, coverImg)
// Interlacing Analysis Section
analyzeBtn := widget.NewButton("Analyze Interlacing", func() {
@ -9405,9 +9387,8 @@ Metadata: %s`,
)
}
// Layout: metadata form on left, cover art on right (bottom-aligned)
coverColumn := container.NewVBox(layout.NewSpacer(), coverContainer)
contentArea := container.NewBorder(nil, nil, nil, coverColumn, info)
// Layout: two-column metadata display with spacing
contentArea := info
body := container.NewVBox(
top,

View File

@ -226,6 +226,14 @@ func buildRipView(state *appState) fyne.CanvasObject {
state.persistRipConfig()
})
clearISOBtn := widget.NewButton("Clear ISO", func() {
state.ripSourcePath = ""
state.ripOutputPath = ""
sourceEntry.SetText("")
outputEntry.SetText("")
})
clearISOBtn.Importance = widget.LowImportance
controls := container.NewVBox(
widget.NewLabelWithStyle("Source", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
ui.NewDroppable(sourceEntry, func(items []fyne.URI) {
@ -237,6 +245,7 @@ func buildRipView(state *appState) fyne.CanvasObject {
outputEntry.SetText(state.ripOutputPath)
}
}),
clearISOBtn,
widget.NewLabelWithStyle("Format", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
formatSelect,
widget.NewLabelWithStyle("Output", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
@ -357,6 +366,12 @@ func (s *appState) executeRipJob(ctx context.Context, job *queue.Job, progressCa
}
defer os.Remove(listFile)
// Create output directory if it doesn't exist
outputDir := filepath.Dir(outputPath)
if err := os.MkdirAll(outputDir, 0755); err != nil {
return fmt.Errorf("failed to create output directory: %w", err)
}
args := buildRipFFmpegArgs(listFile, outputPath, format)
appendLog(fmt.Sprintf(">> ffmpeg %s", strings.Join(args, " ")))
updateProgress(10)
@ -376,7 +391,7 @@ func defaultRipOutputPath(sourcePath, format string) string {
if err != nil || home == "" {
home = "."
}
baseDir := filepath.Join(home, "Videos", "DVD_Rips")
baseDir := filepath.Join(home, "Videos", "VideoTools", "DVD_Rips")
name := strings.TrimSuffix(filepath.Base(sourcePath), filepath.Ext(sourcePath))
if strings.EqualFold(name, "video_ts") {
name = filepath.Base(filepath.Dir(sourcePath))