Imports Stax
Imports Stax.UI
Imports Stax.AppFramework

<Serializable()> _
Public MustInherit Class Preparer
    Public Input As New List(Of String)
    Public VideoOutput As New List(Of String)
    Public AudioOutput As New List(Of String)

    Public MustOverride Function ShowConfigDialog() As DialogResult
    Public MustOverride Sub Run()

    Private NameValue As String = ""

    Public Property Name() As String
        Get
            Return NameValue
        End Get
        Set(ByVal Value As String)
            NameValue = Value
        End Set
    End Property

    Private ActiveValue As Boolean = True

    Public Property Active() As Boolean
        Get
            Return ActiveValue
        End Get
        Set(ByVal Value As Boolean)
            ActiveValue = Value
        End Set
    End Property

    Protected HasConfigDialogValue As Boolean

    Public ReadOnly Property HasConfigDialog() As Boolean
        Get
            Return HasConfigDialogValue
        End Get
    End Property

    Private Shared ActivePreparerValue As Preparer

    Public Shared Property ActivePreparer() As Preparer
        Get
            Return ActivePreparerValue
        End Get
        Set(ByVal Value As Preparer)
            ActivePreparerValue = Value
        End Set
    End Property

    Public Overrides Function ToString() As String
        Return Name
    End Function

    Public Shared Function GetDefaults(ByVal all As Boolean) As List(Of Preparer)
        Dim ret As New List(Of Preparer)

        ret.Add(New AVIPreparer)

        Dim projectX As New CommanLinePreparer
        projectX.Name = "Extract audio from MPEG-2 using ProjectX"
        projectX.Input = New List(Of String)(New String() {"mpg", "ts", "pva"})
        projectX.VideoOutput = New List(Of String)(New String() {"m2v"})
        projectX.AudioOutput = New List(Of String)(New String() {"ac3", "mpa"})
        projectX.CommandLines.Value = """%application:Java%"" -jar ""%application:ProjectX%"" %source_files_blank%"
        ret.Add(projectX)

        Dim dgindex As New CommanLinePreparer
        dgindex.Name = "Extract audio and index MPEG-2 using DGIndex"
        dgindex.Input = New List(Of String)(New String() {"mpg", "vob", "mpv", "m2v", "ts", "pva", "dat"})
        dgindex.VideoOutput = New List(Of String)(New String() {"d2v"})
        dgindex.AudioOutput = New List(Of String)(New String() {"ac3", "mpa"})
        dgindex.CommandLines.Value = """%application:DGIndex%"" -IF[%source_files_comma_no_quotes%] -IA=2 -FO=0 -YR=1 -TN=1 -OM=2 -DRC=2 -DSD=0 -DSA=0 -OF=[%source_dir%\%source_name%] -exit"
        ret.Add(dgindex)

        ret.Add(New DirectShowDecoderPreparer("Extract audio from Windows Media (WMV)", "wmv"))
        ret.Add(New DirectShowDecoderPreparer("Extract audio from Real Media (RMVB)", "rmvb"))

        If all Then
            Dim cliPreparer As New CommanLinePreparer
            cliPreparer.Name = "Command Line Preparer"
            ret.Add(cliPreparer)

            ret.Add(New DirectShowDecoderPreparer("Decode using DirectShow filters"))
        End If

        Return ret
    End Function
End Class

<Serializable()> _
Public Class CommanLinePreparer
    Inherits Preparer

    Public CommandLines As New SettingBag(Of String)("")

    Public Sub New()
        HasConfigDialogValue = True
    End Sub

    Public Overrides Function ShowConfigDialog() As DialogResult
        Dim t As New SettingTreeViewForm("Command Line Preparer", "A command line preparer can be used to perform different tasks with source files like extracting audio to a separate file.")

        Dim inputBag As New SettingBag(Of String)(String.Join(", ", Input.ToArray))
        t.SettingTreeView.AddSetting(New TextBoxTreeNodeSetting("Input", "General", inputBag, "The file types the application should handle separated by comma e.g.: mpg, vob"))
        Dim outputVideoBag As New SettingBag(Of String)(String.Join(", ", VideoOutput.ToArray))
        t.SettingTreeView.AddSetting(New TextBoxTreeNodeSetting("Output Video", "General", outputVideoBag, "The video output file types the application creates separated by comma e.g.: m2v, d2v"))
        Dim outputAudioBag As New SettingBag(Of String)(String.Join(", ", AudioOutput.ToArray))
        t.SettingTreeView.AddSetting(New TextBoxTreeNodeSetting("Output Audio", "General", outputAudioBag, "The audio output file types the application creates separated by comma e.g.: mpa, mp2"))
        t.SettingTreeView.AddSetting(New CmdlEditorTreeNodeSetting("Command Lines", "General", CommandLines, "Multiple command lines may be executed using a new line as separator. The command lines may contain macros."))

        t.Document.WriteTable("Macros", Macro.GetTips)

        t.SettingTreeView.Nodes(0).ExpandAll()

        Dim ret As DialogResult = t.ShowDialog

        If ret = DialogResult.OK Then
            Input = New List(Of String)(StringHelp.Split(inputBag.Value.Replace(" ", ""), ","))
            VideoOutput = New List(Of String)(StringHelp.Split(outputVideoBag.Value.Replace(" ", ""), ","))
            AudioOutput = New List(Of String)(StringHelp.Split(outputAudioBag.Value.Replace(" ", ""), ","))
        End If

        Return ret
    End Function

    Public Overrides Sub Run()
        For Each i As String In StringHelp.SplitLines(Macro.Solve(CommandLines.Value))
            Dim pw As New ProcessWrapper

            ProcessForm.ProcessWrapper = pw
            ProcessForm.ShowForm(False)

            Log.WriteHeader("Preparing")
            Log.WriteLine(Name)

            pw.CommandLine = i
            pw.Minimized = s.RunAppsMinimized.Value
            pw.Priority = s.ProcessPriority.Value
            pw.Directory = Filepath.GetDir(pw.File)
            pw.Wait = True
            pw.Start()
        Next
    End Sub
End Class

<Serializable()> _
Public Class AVIPreparer
    Inherits Preparer

    Public Sub New()
        Name = "Extract audio from AVI using VirtualDubMod"
        Input = New List(Of String)(New String() {"avi"})
        VideoOutput = New List(Of String)(New String() {"avi"})
        AudioOutput = New List(Of String)(New String() {"mp3", "ac3", "wav"})
        HasConfigDialogValue = False
    End Sub

    Public Overrides Sub Run()
        Try
            Paths.MediaInfo.Active = True

            If Not Paths.VerifyRequirements Then
                Exit Sub
            End If

            Dim script As New VirtualDubScript
            script.Open(p.SourceFile)

            Using mi As New MediaInfo(p.SourceFile)
                Dim found As Boolean

                If mi.AudioTracks.Count > 0 Then
                    For x As Integer = 0 To mi.AudioTracks.Count - 1
                        Dim track As MediaInfoAudioTrack = mi.AudioTracks(x)

                        If track.AudioType = MediaInfoAudioType.WAV Then
                            script.SaveWAV(Filepath.GetChangeExt(p.SourceFile, track.Extension))
                            found = True
                        ElseIf track.AudioType <> MediaInfoAudioType.NotImplemented Then
                            script.StreamDemux(x, Filepath.GetChangeExt(p.SourceFile, track.Extension))
                            found = True
                        End If
                    Next
                End If

                If Not found Then Exit Sub
            End Using

            script.SaveScript(Paths.GetTempDir + Filepath.GetNameNoExt(p.SourceFile) + "_Demux.vcf")

            Dim pw As New ProcessWrapper
            ProcessForm.ProcessWrapper = pw
            ProcessForm.ShowForm(False)

            pw.File = Paths.VirtualDubMod.GetPath(False)
            pw.Arguments = "/s""" + Paths.GetTempDir + Filepath.GetNameNoExt(p.SourceFile) + "_Demux.vcf"" /x"
            pw.Minimized = s.RunAppsMinimized.Value
            pw.Wait = True
            pw.Priority = s.ProcessPriority.Value
            pw.Start()
        Finally
            Paths.MediaInfo.Active = False
        End Try
    End Sub

    Public Overrides Function ShowConfigDialog() As DialogResult
        Return DialogResult.OK
    End Function
End Class

<Serializable()> _
Public Class DirectShowDecoderPreparer
    Inherits Preparer

    Public Sub New(ByVal name As String, ByVal ParamArray extensions As String())
        Me.Name = name
        Input = New List(Of String)(extensions)
        VideoOutput = New List(Of String)(extensions)
        AudioOutput = New List(Of String)(New String() {"wav"})
        HasConfigDialogValue = True
    End Sub

    Public Overrides Sub Run()
        Dim start As DateTime = DateTime.Now

        Dim doc As New AviSynthDocument
        doc.Filters.Add(New AviSynthFilter("Source", "DirectShow", "DirectShowSource(""%source_file%"")", True))
        doc.Path = Paths.GetTempDir + Filepath.GetNameNoExt(p.SourceFile) + "_DirectShowDecode.avs"
        doc.Synchronize()

        Dim script As New VirtualDubScript
        script.Open(doc.Path)
        script.SaveWAV(Filepath.GetChangeExt(p.SourceFile, ".wav"))
        script.SaveScript(Paths.GetTempDir + Filepath.GetNameNoExt(p.SourceFile) + "_DirectShowDecode.vcf")

        Dim pw As New ProcessWrapper
        ProcessForm.ProcessWrapper = pw

        pw.File = Paths.VirtualDubMod.GetPath(False)
        pw.Arguments = "/s""" + Paths.GetTempDir + Filepath.GetNameNoExt(p.SourceFile) + "_DirectShowDecode.vcf"" /x"
        pw.Minimized = s.RunAppsMinimized.Value
        pw.Wait = True
        pw.Priority = s.ProcessPriority.Value

        Log.WriteHeader("Audio Decoding")
        Log.WriteLine(p.SourceFile)

        pw.Start()

        Log.WriteHeader("Audio Decoding Statistics")
        Log.WriteStats(start, doc.GetFrames)
    End Sub

    Public Overrides Function ShowConfigDialog() As DialogResult
        Using t As New SettingTreeViewForm("DirectShow Audio Decoding Preparer", "The DirectShow Audio Decoding Preparer extracts the audio as wav file using DirectShow filters.")
            Dim inputBag As New SettingBag(Of String)(String.Join(", ", Input.ToArray))
            t.SettingTreeView.AddSetting(New TextBoxTreeNodeSetting("Input", "General", inputBag, "The file types from which audio should be extracted separated by comma e.g.: wmv, rmvb, avi"))

            t.SettingTreeView.Nodes(0).ExpandAll()

            Dim ret As DialogResult = t.ShowDialog

            If ret = DialogResult.OK Then
                Input = New List(Of String)(StringHelp.Split(inputBag.Value.Replace(" ", ""), ","))
            End If

            Return ret
        End Using
    End Function
End Class