Imports Stax
Imports Stax.UI
Imports Stax.AppFramework

<Serializable()> _
Public MustInherit Class AudioProfile
    Inherits Profile

    Public MustOverride Sub ShowDialog()
    Public MustOverride Sub Encode()
    Public MustOverride Function HandlesDelay() As Boolean

    Public Sub New(ByVal name As String, ByVal streamName As String, ByVal typeName As String, ByVal audioSettings As AudioSettings, ByVal bitrate As Integer, ByVal input As List(Of String), ByVal type As StreamType)
        MyBase.New(name, typeName)
        Me.StreamName = streamName
        Me.AudioSettings = audioSettings
        Me.Bitrate = bitrate
        Me.SupportedInputFileTypes = input
        Me.StreamType = type
    End Sub

    <NonSerialized()> _
    Private AudioSettingsValue As AudioSettings

    Public Property AudioSettings() As AudioSettings
        Get
            Return AudioSettingsValue
        End Get
        Set(ByVal Value As AudioSettings)
            AudioSettingsValue = Value
        End Set
    End Property

    Private SupportedInputFileTypesValue As List(Of String)

    Public Property SupportedInputFileTypes() As List(Of String)
        Get
            Return SupportedInputFileTypesValue
        End Get
        Set(ByVal value As List(Of String))
            SupportedInputFileTypesValue = value
        End Set
    End Property

    Private BitrateValue As Double

    Public Overridable Property Bitrate() As Double
        Get
            Return BitrateValue
        End Get
        Set(ByVal Value As Double)
            BitrateValue = Value
        End Set
    End Property

    Private StreamNameValue As String = ""

    Public Property StreamName() As String
        Get
            Return StreamNameValue
        End Get
        Set(ByVal Value As String)
            StreamNameValue = Value
        End Set
    End Property

    Private StreamTypeValue As StreamType

    Public Property StreamType() As StreamType
        Get
            Return StreamTypeValue
        End Get
        Set(ByVal Value As StreamType)
            StreamTypeValue = Value
        End Set
    End Property

    Public Function SolveMacros(ByVal value As String) As String
        value = value.Replace("%input%", AudioSettings.File)
        value = value.Replace("%output%", Filepath.GetDirAndNameNoExt(AudioSettings.File) + "_AudioOutput" + GetExtension())
        value = value.Replace("%language_native%", AudioSettings.Language.CultureInfo.NativeName)
        value = value.Replace("%language_english%", AudioSettings.Language.Name)
        value = value.Replace("%delay%", AudioSettings.Delay.ToString)
        Return Macro.Solve(value)
    End Function

    Public Function GetExtension() As String
        Return StreamTypeUtils.GetExtension(StreamType)
    End Function

    Public Shared Function GetProfile(ByVal name As String) As AudioProfile
        For Each i As AudioProfile In AudioProfile.GetDefaults(False)
            If i.Name = name Then
                Return i
            End If
        Next

        Throw New Exception("Unknown profile: " + name)
    End Function

    Public Shared Function GetDefaults(ByVal advanced As Boolean) As List(Of AudioProfile)
        Dim ret As New List(Of AudioProfile)

        ret.Add(New CommandLineAudioProfile( _
            "MP3 - VBR 110-150 kbps", _
            "%language_english% (MP3)", _
            Nothing, _
            128, _
            New List(Of String)(New String() {"ac3", "mp2", "mpa", "wav"}), _
            StreamType.MP3VBR, _
            """%application:BeSweet%"" -core( -input ""%input%"" -output ""%output%"" ) -azid( -c normal -L -3db ) -ota( -d %delay% -hybridgain ) -lame( -v --vbr-new -V 5 )"))

        ret.Add(New MuxAudioProfile( _
            "MP3 - Add Existing VBR File", _
            "%language_english% (MP3)", _
            Nothing, _
            0, _
            New List(Of String)(New String() {"mp3"}), _
            StreamType.MP3VBR))

        ret.Add(New CommandLineAudioProfile( _
            "MP3 - CBR 160 kbps", _
            "%language_english% (MP3)", _
            Nothing, _
            160, _
            New List(Of String)(New String() {"ac3", "mp2", "mpa", "wav"}), _
            StreamType.MP3CBR, _
            """%application:BeSweet%"" -core( -input ""%input%"" -output ""%output%"" ) -azid( -c normal -L -3db ) -ota( -d %delay% -hybridgain ) -lame( --alt-preset cbr 160 )"))

        ret.Add(New CommandLineAudioProfile( _
            "MP3 - CBR 128 kbps", _
            "%language_english% (MP3)", _
            Nothing, _
            128, _
            New List(Of String)(New String() {"ac3", "mp2", "mpa", "wav"}), _
            StreamType.MP3CBR, _
            """%application:BeSweet%"" -core( -input ""%input%"" -output ""%output%"" ) -azid( -c normal -L -3db ) -ota( -d %delay% -hybridgain ) -lame( --alt-preset cbr 128 )"))

        'name is referenced
        ret.Add(New CommandLineAudioProfile( _
            "MP3 - CBR 128 kbps 44100 Khz", _
            "%language_english% (MP3)", _
            Nothing, _
            128, _
            New List(Of String)(New String() {"ac3", "mp2", "mpa", "wav"}), _
            StreamType.MP3CBR, _
            """%application:BeSweet%"" -core( -input ""%input%"" -output ""%output%"" ) -azid( -c normal -L -3db ) -ota( -d %delay% -hybridgain ) -lame( --alt-preset cbr 128 --resample 44.1)"))


        ret.Add(New MuxAudioProfile( _
            "MP3 - Add Existing CBR File", _
            "%language_english% (MP3)", _
            Nothing, _
            0, _
            New List(Of String)(New String() {"mp3"}), _
            StreamType.MP3CBR))

        'name is referenced
        ret.Add(New CommandLineAudioProfile( _
            "AAC - HE VBR 50-70 kbps", _
            "%language_english%", _
            Nothing, _
            60, _
            New List(Of String)(New String() {"ac3", "mp2", "mpa", "wav"}), _
            StreamType.AAC_HE_MP4, _
            """%application:BeSweet%"" -core( -input ""%input%"" -output ""%output%"" ) -azid( -c normal -L -3db ) -ota( -d %delay% -g max ) -bsn( -2ch -vbr_streaming -codecquality_high -aacprofile_he )"))

        ret.Add(New CommandLineAudioProfile( _
            "AAC - HE 5.1 VBR 200-250 kbps", _
            "%language_english% (5.1)", _
            Nothing, _
            225, _
            New List(Of String)(New String() {"ac3"}), _
            StreamType.AAC_HE_MP4, _
            """%application:BeSweet%"" -core( -input ""%input%"" -output ""%output%"" ) -azid( -c normal ) -ota( -d %delay% -g max ) -bsn( -6chnew -vbr_streaming -codecquality_high -aacprofile_he )"))

        ret.Add(New MuxAudioProfile( _
            "AAC - Add Existing HE File", _
            "%language_english%", _
            Nothing, _
            0, _
            New List(Of String)(New String() {"mp4", "aac"}), _
            StreamType.AAC_HE_MP4))

        ret.Add(New CommandLineAudioProfile( _
            "AAC - LC VBR 110-150 kbps", _
            "%language_english%", _
            Nothing, _
            130, _
            New List(Of String)(New String() {"ac3", "mp2", "mpa", "wav"}), _
            StreamType.AAC_LC_MP4, _
            """%application:BeSweet%"" -core( -input ""%input%"" -output ""%output%"" ) -azid( -c normal -L -3db ) -ota( -d %delay% -g max ) -bsn( -2ch -vbr_normal -codecquality_high -aacprofile_lc )"))

        ret.Add(New MuxAudioProfile( _
            "AAC - Add Existing LC File", _
            "%language_english%", _
            Nothing, _
            0, _
            New List(Of String)(New String() {"mp4", "aac"}), _
            StreamType.AAC_LC_MP4))

        ret.Add(New MuxAudioProfile( _
            "AC3 - Add Existing File", _
            "%language_english% (AC3)", _
            Nothing, _
            0, _
            New List(Of String)(New String() {"ac3"}), _
            StreamType.AC3))

        ret.Add(New MuxAudioProfile( _
            "DTS - Add Existing File", _
            "%language_english% (DTS)", _
            Nothing, _
            0, _
            New List(Of String)(New String() {"dts"}), _
            StreamType.DTS))

        ret.Add(New CommandLineAudioProfile( _
            "Vorbis - 80-100 kbps", _
            "%language_english% (Vorbis)", _
            Nothing, _
            90, _
            New List(Of String)(New String() {"ac3", "mp2", "mpa", "wav"}), _
            StreamType.Vorbis, _
            """%application:BeSweet%"" -core( -input ""%input%"" -output ""%output%"" ) -azid( -c normal -L -3db ) -ota( -d %delay% -hybridgain ) -ogg( -q 0.200 )"))

        ret.Add(New MuxAudioProfile( _
            "Vorbis - Add Existing File", _
            "%language_english% (Vorbis)", _
            Nothing, _
            0, _
            New List(Of String)(New String() {"ogg"}), _
            StreamType.Vorbis))

        ret.Add(New CommandLineAudioProfile( _
            "Vorbis - 5.1 200-300 kbps", _
            "%language_english% (Vorbis 5.1)", _
           Nothing, _
            300, _
            New List(Of String)(New String() {"ac3", "mp2", "mpa", "wav"}), _
            StreamType.Vorbis, _
            """%application:BeSweet%"" -core( -input ""%input%"" -output ""%output%"" ) -azid( -c normal ) -ota( -d %delay% -hybridgain ) -ogg( -q 0.200 -6ch 1 )"))

        ret.Add(New MuxAudioProfile( _
            "Calculate Size Only", _
            "", _
            Nothing, _
            0, _
            New List(Of String)(New String() {"mp3", "mp4", "ac3", "mp2", "mpa"}), _
            StreamType.Ignore))

        ret.Add(New NullAudioProfile())

        Return ret
    End Function

    Public Overrides Function GetInfoValues() As Dictionary(Of String, String)
        Dim ret As New Dictionary(Of String, String)

        ret("Audio Profile Type") = TypeName
        ret("Supported Input File Extensions") = String.Join(", ", SupportedInputFileTypes.ToArray)
        ret("Bitrate") = Bitrate.ToString
        ret("Output Format") = StreamTypeUtils.GetName(StreamType)
        ret("Output File Extension") = GetExtension()

        Return ret
    End Function
End Class

<Serializable()> _
Public Class CommandLineAudioProfile
    Inherits AudioProfile

    Public Sub New(ByVal name As String, ByVal streamName As String, ByVal audioSettings As AudioSettings, ByVal bitrate As Integer, ByVal input As List(Of String), ByVal type As StreamType, ByVal commandLines As String)
        MyBase.New(name, streamName, "Command Line Audio Profile", audioSettings, bitrate, input, type)
        Me.CommandLines = commandLines
        CanEditValue = True
    End Sub

    Private CommandValue As String

    Public Property CommandLines() As String
        Get
            Return CommandValue
        End Get
        Set(ByVal Value As String)
            CommandValue = Value
        End Set
    End Property

    Private HelpFileValue As String = ""

    Public Property HelpFile() As String
        Get
            Return HelpFileValue
        End Get
        Set(ByVal Value As String)
            HelpFileValue = Value
        End Set
    End Property

    Public Overrides Function Edit() As DialogResult
        Using f As New CommandLineAudioSettingsForm(Me, New AudioSettings(Me, New Language()))
            f.cbLanguage.Visible = False
            f.lLanguage.Visible = False
            f.tbDelay.Visible = False
            f.lDelay.Visible = False
            Return f.ShowDialog()
        End Using
    End Function

    Public Overrides Sub ShowDialog()
        Dim f As New CommandLineAudioSettingsForm(Me, AudioSettings)
        f.ShowDialog()
        f.Dispose()
    End Sub

    Public Overrides Function GetInfoValues() As Dictionary(Of String, String)
        Dim ret As Dictionary(Of String, String) = MyBase.GetInfoValues
        ret("Command Lines") = CommandLines
        Return ret
    End Function

    Public Overrides Sub Encode()
        If AudioSettings.File <> "" Then
            Dim bitrateBefore As Integer = p.VideoBitrate
            Dim targetPath As String = Filepath.GetDirAndNameNoExt(AudioSettings.File) + "_AudioOutput" + GetExtension()

            For Each i As String In StringHelp.SplitLines(SolveMacros(CommandLines))
                Log.WriteHeader("Audio Encoding")

                Dim start As DateTime = DateTime.Now
                Dim pw As New ProcessWrapper
                ProcessForm.ProcessWrapper = pw

                pw.CommandLine = i

                Log.WriteLine("Command Line: " + i)

                pw.Minimized = s.RunAppsMinimized.Value
                pw.Directory = Filepath.GetDir(pw.File)
                pw.Wait = True
                pw.Priority = s.ProcessPriority.Value
                pw.Start()

                AudioSettings.File = targetPath

                Bitrate = Calc.GetBitrateFromFile(AudioSettings.File, p.TargetSeconds)
                p.VideoBitrate = CInt(Calc.GetTotalBitrate - Calc.GetAudioBitrate())

                Log.WriteHeader("Audio Encoding Statistics")
                Log.WriteStats(start, p.TargetAVSDoc.GetFrames)
                Log.WriteLine("Size: " + (Calc.GetKBytes(AudioSettings.File) / 1024).ToString("f1") + " MB")
                Log.WriteLine("Bitrate: " + Bitrate.ToString("f2") + " kbps")
                Log.WriteLine("Video Bitrate: " + bitrateBefore.ToString() + " -> " + p.VideoBitrate.ToString)
            Next
        End If
    End Sub

    Public Overrides Function HandlesDelay() As Boolean
        Return CommandLines.Contains("%delay%")
    End Function
End Class

<Serializable()> _
Public Class MuxAudioProfile
    Inherits AudioProfile

    Public Sub New(ByVal name As String, ByVal streamName As String, ByVal audioSettings As AudioSettings, ByVal bitrate As Integer, ByVal input As List(Of String), ByVal type As StreamType)
        MyBase.New(name, streamName, "Mux Audio Profile", audioSettings, bitrate, input, type)
    End Sub

    Public Overrides Sub Encode()
    End Sub

    Public Overrides Sub ShowDialog()
        Using f As New SettingTreeViewForm("Audio Mux Options", "The Audio [[glossary.htm#muxing|Mux]] Options allow to include a audio file.", Strings.ProjectAudioSettingsHelp)
            f.SettingTreeView.AddSetting(New TextBoxTreeNodeSetting("Stream Name", "Audio Mux Options", New BindingSettingBag(Of String)(AudioSettings.Profile, "StreamName"), "Stream name used by the muxer. The stream name may contain macros."))
            f.SettingTreeView.AddSetting(New ComboboxTreeNodeSetting(Of Language)("Language", "Audio Mux Options", New BindingSettingBag(Of Language)(AudioSettings, "Language"), "Language of the audio track.", Language.Languages))
            f.SettingTreeView.AddSetting(New NumericTreeNodeSetting(Of Integer)("Delay", "Audio Mux Options", New BindingSettingBag(Of Integer)(AudioSettings, "Delay"), "Delay used by the muxer."))

            f.SettingTreeView.Nodes(0).ExpandAll()
            f.ShowDialog()
        End Using
    End Sub

    Public Overrides Function HandlesDelay() As Boolean
        Return False
    End Function
End Class

<Serializable()> _
Public Class NullAudioProfile
    Inherits AudioProfile

    Public Sub New()
        MyBase.New("No Audio", "", "Null Audio Profile", Nothing, 0, New List(Of String)(New String() {}), StaxRip.StreamType.Ignore)
    End Sub

    Public Overrides Sub Encode()
    End Sub

    Public Overrides Function HandlesDelay() As Boolean
    End Function

    Public Overrides Sub ShowDialog()
    End Sub
End Class