' Copyright (C) 2023 Andy https://github.com/AAndyProgram ' This program is free software: you can redistribute it and/or modify ' it under the terms of the GNU General Public License as published by ' the Free Software Foundation, either version 3 of the License, or ' (at your option) any later version. ' ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY Imports System.ComponentModel Imports SCrawler.API.YouTube.Objects Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms.Controls Imports PersonalUtilities.Forms.Controls.Base Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.XML.Base Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons Namespace API.YouTube.Controls Friend Class MusicPlaylistsForm : Implements IDesignXMLContainer #Region "Declarations" Private MyView As FormView Friend Property DesignXML As EContainer Implements IDesignXMLContainer.DesignXML Private Property DesignXMLNodes As String() Implements IDesignXMLContainer.DesignXMLNodes Private Property DesignXMLNodeName As String Implements IDesignXMLContainer.DesignXMLNodeName Private ReadOnly MyContainer As IYouTubeMediaContainer Private Initializing As Boolean = True Private ReadOnly Property Current As IYouTubeMediaContainer Get With MyContainer If .ObjectType = Base.YouTubeMediaType.Channel Then If _LatestSelected.ValueBetween(0, .Count - 1) Then Return .Elements(_LatestSelected) Else Return .Self End If End With Return Nothing End Get End Property #End Region #Region "Initializer" Friend Sub New(ByVal Container As IYouTubeMediaContainer) InitializeComponent() MyContainer = Container End Sub #End Region #Region "Form handlers" Private Sub MusicPlaylistsForm_Load(sender As Object, e As EventArgs) Handles Me.Load If Not DesignXML Is Nothing Then MyView = New FormView(Me) MyView.Import() MyView.SetFormSize() End If CMB_FORMATS.Items.AddRange(AvailableAudioFormats) If MyYouTubeSettings.PlaylistFormSplitterDistance > 0 Then SPLITTER_MAIN.SplitterDistancePercentageSet(MyYouTubeSettings.PlaylistFormSplitterDistance) With MyContainer CH_DOWN_LYRICS.Checked = Not .OutputSubtitlesFormat.IsEmptyString Dim i% If Not .OutputAudioCodec.IsEmptyString Then i = AvailableAudioFormats.ListIndexOf(Function(ff) ff.StringToLower = .OutputAudioCodec.StringToLower) If i >= 0 Then CMB_FORMATS.SelectedIndex = i End If If CMB_FORMATS.SelectedIndex = -1 Then Dim oac$ = MyYouTubeSettings.DefaultAudioCodecMusic.Value.IfNullOrEmpty("mp3").StringToLower i = AvailableAudioFormats.ListIndexOf(Function(ff) ff.StringToLower = oac) If i >= 0 Then CMB_FORMATS.SelectedIndex = i Else CMB_FORMATS.SelectedIndex = 0 End If If .ObjectType = Base.YouTubeMediaType.Channel Then If .HasElements Then For Each elem In .Elements : LIST_PLAYLISTS.Items.Add(elem, elem.CheckState) : Next End If ElseIf .ObjectType = Base.YouTubeMediaType.PlayList Then LIST_PLAYLISTS.Items.Add(.Self, .CheckState) Else Throw New InvalidOperationException($"The object type '{ .ObjectType}' is incompatible with 'MusicPlaylistsForm'.") End If LIST_PLAYLISTS.SelectedIndex = 0 TXT_OUTPUT_PATH.Text = MyYouTubeSettings.OutputPath.Value If Not .UserTitle.IsEmptyString Then Text = .UserTitle If .ObjectType = Base.YouTubeMediaType.PlayList Then If Not .PlaylistTitle.IsEmptyString AndAlso Not .PlaylistTitle = .UserTitle Then Text &= $" - { .PlaylistTitle}" ElseIf Not .Title.IsEmptyString AndAlso Not .Title = .UserTitle Then Text &= $" - { .Title}" End If End If If Not TXT_OUTPUT_PATH.IsEmptyString AndAlso Not TXT_OUTPUT_PATH.Text.Contains(.UserTitle) Then TXT_OUTPUT_PATH.Text = $"{TXT_OUTPUT_PATH.Text.TrimEnd("\")}\{ .UserTitle}\" ElseIf Not .PlaylistTitle.IsEmptyString Then Text = .PlaylistTitle End If UpdateSizeText() End With RefillAddit() Initializing = False End Sub Private Sub MusicPlaylistsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing MyYouTubeSettings.PlaylistFormSplitterDistance.Value = SPLITTER_MAIN.SplitterDistancePercentageGet MyView.DisposeIfReady() End Sub #End Region #Region "Form text" Private _InitialFormText As String = String.Empty Private Sub UpdateSizeText() If _InitialFormText.IsEmptyString Then _InitialFormText = Text Text = $"{_InitialFormText} ({MyContainer.SizeStr})" End Sub #End Region #Region "Settings" Private Sub TXT_SUBS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_SUBS.ActionOnButtonClick, TXT_FORMATS_ADDIT.ActionOnButtonClick Dim isLyrics As Boolean = DirectCast(e.AssociatedControl, Control).Tag = "s" With DirectCast(MyContainer, YouTubeMediaContainerBase) Select Case Sender.DefaultButton Case ADB.Open Using f As New SimpleListForm(Of String)(IIf(isLyrics, AvailableSubtitlesFormats, AvailableAudioFormats)) With { .DesignXML = DesignXML, .DesignXMLNodeName = SimpleArraysFormNode, .FormText = DirectCast(e.AssociatedControl, TextBoxExtended).CaptionText, .Icon = My.Resources.SiteYouTube.YouTubeMusicIcon_32, .Mode = SimpleListFormModes.CheckedItems } f.DataSelected.ListAddList(IIf(isLyrics, .PostProcessing_OutputSubtitlesFormats, .PostProcessing_OutputAudioFormats)) If f.ShowDialog = DialogResult.OK Then If isLyrics Then .PostProcessing_OutputSubtitlesFormats.Clear() .PostProcessing_OutputSubtitlesFormats.ListAddList(f.DataResult) Else .PostProcessing_OutputAudioFormats.Clear() .PostProcessing_OutputAudioFormats.ListAddList(f.DataResult) End If RefillAddit() End If End Using Case ADB.Refresh If isLyrics Then .PostProcessing_OutputSubtitlesFormats_Reset() Else .PostProcessing_OutputAudioFormats_Reset() End If RefillAddit() Case ADB.Clear If isLyrics Then .PostProcessing_OutputSubtitlesFormats.Clear() Else .PostProcessing_OutputAudioFormats.Clear() End If RefillAddit() End Select End With End Sub Private Sub RefillAddit() With DirectCast(MyContainer, YouTubeMediaContainerBase) TXT_SUBS.Text = .PostProcessing_OutputSubtitlesFormats.ListToString TXT_FORMATS_ADDIT.Text = .PostProcessing_OutputAudioFormats.ListToString End With End Sub Private Sub TXT_OUTPUT_PATH_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_OUTPUT_PATH.ActionOnButtonClick If Sender.DefaultButton = ADB.Open Then Dim f As SFile = SFile.SelectPath(TXT_OUTPUT_PATH.Text, "Select files destination", EDP.ReturnValue) If Not f.IsEmptyString Then TXT_OUTPUT_PATH.Text = f End If End Sub #End Region #Region "Lists' handlers" Private _LatestSelected As Integer = -1 Private Sub LIST_PLAYLISTS_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_PLAYLISTS.SelectedIndexChanged Dim i% = LIST_PLAYLISTS.SelectedIndex If i >= 0 Then _LatestSelected = i LIST_ITEMS.Items.Clear() With DirectCast(LIST_PLAYLISTS.SelectedItem, IYouTubeMediaContainer) If .HasElements Then For Each elem In .Elements : LIST_ITEMS.Items.Add(elem, elem.Checked) : Next End If End With End If End Sub Private _CheckHandlersSuspended As Boolean = False Private Sub LIST_PLAYLISTS_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles LIST_PLAYLISTS.ItemCheck If Not Initializing And Not _CheckHandlersSuspended Then _CheckHandlersSuspended = True Dim checked As Boolean = Not e.NewValue = CheckState.Unchecked Dim current As IYouTubeMediaContainer = Me.Current If Not current Is Nothing Then With current .Checked = checked If LIST_ITEMS.Items.Count > 0 Then _ListCheckHandlersSuspended = True For i% = 0 To .Count - 1 If i.ValueBetween(0, LIST_ITEMS.Items.Count - 1) Then LIST_ITEMS.SetItemChecked(i, checked) Next _ListCheckHandlersSuspended = False End If If LIST_PLAYLISTS.Items.Count.ValueBetween(0, _LatestSelected) Then LIST_PLAYLISTS.SetItemChecked(_LatestSelected, checked) End With UpdateSizeText() End If _CheckHandlersSuspended = False End If End Sub Private _ListCheckHandlersSuspended As Boolean = False Private Sub LIST_ITEMS_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles LIST_ITEMS.ItemCheck If Not Initializing Then Dim current As IYouTubeMediaContainer = Me.Current If Not current Is Nothing Then With current If e.Index.ValueBetween(0, .Count - 1) Then .Elements(e.Index).Checked = e.NewValue If Not _ListCheckHandlersSuspended And _LatestSelected.ValueBetween(0, LIST_PLAYLISTS.Items.Count - 1) Then Dim checked As Boolean = .Elements(e.Index).Checked _CheckHandlersSuspended = True If .Elements.All(Function(ee) ee.Checked = checked) Then LIST_PLAYLISTS.SetItemChecked(_LatestSelected, checked) Else LIST_PLAYLISTS.SetItemCheckState(_LatestSelected, CheckState.Indeterminate) End If _CheckHandlersSuspended = False LIST_PLAYLISTS.Refresh() UpdateSizeText() End If End If End With End If End If End Sub #End Region #Region "Selection buttons" Private Sub BTT_PLS_Click(sender As Object, e As EventArgs) Handles BTT_PLS_ALL.Click, BTT_PLS_NONE.Click Dim checked As Boolean = DirectCast(sender, Button).Tag = "a" _CheckHandlersSuspended = True If LIST_PLAYLISTS.Items.Count > 0 Then For i% = 0 To LIST_PLAYLISTS.Items.Count - 1 : LIST_PLAYLISTS.SetItemChecked(i, checked) : Next End If MyContainer.Checked = checked If MyContainer.Count > 1 Then MyContainer.Elements.ForEach(Sub(ee) ee.Checked = checked) _CheckHandlersSuspended = False UpdateSizeText() End Sub #End Region #Region "Ok, Cancel" Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click If TXT_OUTPUT_PATH.IsEmptyString Then MsgBoxE({"The output path cannot be null.", "Download music"}, vbCritical) Else With DirectCast(MyContainer, YouTubeMediaContainerBase) .OutputSubtitlesFormat = IIf(CH_DOWN_LYRICS.Checked, "LRC", String.Empty) If Not TXT_SUBS.Checked Then .PostProcessing_OutputSubtitlesFormats.Clear() .OutputAudioCodec = CMB_FORMATS.Text If Not TXT_FORMATS_ADDIT.Checked Then .PostProcessing_OutputAudioFormats.Clear() .File = TXT_OUTPUT_PATH.Text.CSFileP If MyYouTubeSettings.OutputPathAutoChange Then MyYouTubeSettings.OutputPath.Value = .File End With DialogResult = DialogResult.OK Close() End If End Sub Private Sub BTT_CANCEL_Click(sender As Object, e As EventArgs) Handles BTT_CANCEL.Click DialogResult = DialogResult.Cancel Close() End Sub #End Region End Class End Namespace