private void MainForm_Load(object sender, EventArgs e) { Application.Idle += Application_Idle; this.ResizeBegin += (s, ee) => { this.SuspendLayout(); }; this.ResizeEnd += (s, ee) => { this.ResumeLayout(true); }; ffmpegPath = Path.Combine(ROOT_DIRECTORY, BIN_FOLDER_NAME, "ffmpeg.exe"); api = new YoutubeDLApi(Path.Combine(ROOT_DIRECTORY, BIN_FOLDER_NAME, "youtube-dl.exe"), new YoutubeDLArguments()); CheckVersion(); cbxFilesizeMaxUnits.DataSource = Enum.GetValues(typeof(FilesizeUnit)); cbxFilesizeMaxUnits.SelectedItem = FilesizeUnit.MB; cbxFilesizeMinUnits.DataSource = Enum.GetValues(typeof(FilesizeUnit)); cbxFilesizeMinUnits.SelectedItem = FilesizeUnit.MB; cbxLimitRateUnits.DataSource = Enum.GetValues(typeof(FilesizeUnit)); cbxLimitRateUnits.SelectedItem = FilesizeUnit.MB; cbxOutputFormat.DataSource = Enum.GetValues(typeof(MergeVideoFormat)); cbxOutputFormat.SelectedItem = MergeVideoFormat.MP4; cbxRecodeFormat.DataSource = Enum.GetValues(typeof(VideoFormatRecode)); cbxRecodeFormat.SelectedItem = VideoFormatRecode.MP4; txtDownloadDirectory.Text = Properties.Settings.Default.DownloadDirectory; txtDownloadArchive.Text = Properties.Settings.Default.DownloadArchive; txtFileTemplate.Text = Properties.Settings.Default.FilenameTemplate; ControlListenGroup clg = ControlListenGroup.New(); clg.OnChanged += () => { string ffmpegLocation = api.Arguments.PostProcessing.FFmpegLocation; api.Arguments.PostProcessing.FFmpegLocation = null; bool preferffmpeg = api.Arguments.PostProcessing.PreferFFmpeg; api.Arguments.PostProcessing.PreferFFmpeg = false; string exe = api.Executable; api.Executable = "youtube-dl"; txtCommand.Text = api.BuildCommandString(); api.Arguments.PostProcessing.FFmpegLocation = ffmpegLocation; api.Arguments.PostProcessing.PreferFFmpeg = preferffmpeg; api.Executable = exe; }; CreateBindings(clg); }
private void CreateBindings(ControlListenGroup clg) { txtUrl.BindValueTo(v => { isYoutube = txtUrl.IsValidUrl() && new Uri(v).Host.Contains("youtube.com"); }); txtUrl.BindValueTo(v => api.Arguments.Url = v).Listen(clg); nudVideoQualityWidth.BindEnableTo(rbVqCustom); nudVideoQualityHeight.BindEnableTo(rbVqCustom); nudFpsCustom.BindEnableTo(rbFpsCustom); gbVideoQuality.BindEnableTo(cbs => !cbs[0].Checked, cbCustomFormatSelector); gbFrameRate.BindEnableTo(cbs => !cbs[0].Checked, cbCustomFormatSelector); #region General cbIgnoreErrors.BindValueTo(v => api.Arguments.General.IgnoreErrors = v).Listen(clg); cbAbortOnErrors.BindValueTo(v => api.Arguments.General.AbortOnError = v).Listen(clg); cbMarkWatched.BindValueTo(v => api.Arguments.General.MarkWatched = isYoutube ? v : false, cbUsernamePassword, clg); #endregion #region Video Selection nudPlaylistStart.BindEnableTo(cbPlaylistStart).BindValueTo(v => api.Arguments.VideoSelection.PlaylistStart = (int?)v, cbPlaylistStart, clg); nudPlaylistEnd.BindEnableTo(cbPlaylistEnd).BindValueTo(v => api.Arguments.VideoSelection.PlaylistEnd = (int?)v, cbPlaylistEnd, clg); txtPlaylistRange.BindEnableTo(cbPlaylistRange).BindValueTo(v => api.Arguments.VideoSelection.PlaylistItems = v, cbPlaylistRange, clg); txtMatchTitle.BindEnableTo(cbMatchTitle).BindValueTo(v => api.Arguments.VideoSelection.MatchTitle = v, cbMatchTitle, clg); txtRejectTitle.BindEnableTo(cbRejectTitle).BindValueTo(v => api.Arguments.VideoSelection.RejectTitle = v, cbRejectTitle, clg); nudMaxDownloads.BindEnableTo(cbMaxDownloads).BindValueTo(v => api.Arguments.VideoSelection.MaxDownloads = (int?)v, cbMaxDownloads, clg); txtMatchFilter.BindEnableTo(cbMatchFilter).BindValueTo(v => api.Arguments.VideoSelection.MatchFilter = v, cbMatchFilter, clg); void filesizeMinEvt(float?v) { api.Arguments.VideoSelection.MinFilesize = (v == null || v == 0) ? (ByteSize?)null : ByteSize.From(v.Value, (FilesizeUnit)cbxFilesizeMinUnits.SelectedItem); } cbxFilesizeMinUnits.BindEnableTo(cbFilesizeMin).BindValueTo(obj => filesizeMinEvt(nudFilesizeMin.GetValueFloat(cbFilesizeMin))).Listen(clg); nudFilesizeMin.BindEnableTo(cbFilesizeMin).BindValueTo(filesizeMinEvt, cbFilesizeMin, clg); void filesizeMaxEvt(float?v) { api.Arguments.VideoSelection.MaxFilesize = (v == null || v == 0) ? (ByteSize?)null : ByteSize.From(v.Value, (FilesizeUnit)cbxFilesizeMaxUnits.SelectedItem); } cbxFilesizeMaxUnits.BindEnableTo(cbFilesizeMax).BindValueTo(obj => filesizeMaxEvt(nudFilesizeMax.GetValueFloat(cbFilesizeMax))).Listen(clg); nudFilesizeMax.BindEnableTo(cbFilesizeMax).BindValueTo(filesizeMaxEvt, cbFilesizeMax, clg); dtpDate.BindEnableTo(cbDate).BindValueTo(v => api.Arguments.VideoSelection.Date = v, cbDate, clg); dtpDateAfter.BindEnableTo(cbDateAfter).BindValueTo(v => api.Arguments.VideoSelection.DateAfter = v, cbDateAfter, clg); dtpDateBefore.BindEnableTo(cbDateBefore).BindValueTo(v => api.Arguments.VideoSelection.DateBefore = v, cbDateBefore, clg); nudViewRangeMin.BindEnableTo(cbMinViews).BindValueTo(v => api.Arguments.VideoSelection.MinViews = (int?)v, cbMinViews, clg); nudViewRangeMax.BindEnableTo(cbMaxViews).BindValueTo(v => api.Arguments.VideoSelection.MaxViews = (int?)v, cbMaxViews, clg); //// api.Arguments.VideoSelection.MatchFilter = rbPlaylistOnly.BindValueTo(v => api.Arguments.VideoSelection.YesPlaylist = v).Listen(clg); rbVideoOnly.BindValueTo(v => api.Arguments.VideoSelection.NoPlaylist = v).Listen(clg); nudAgeLimit.BindEnableTo(cbAgeLimit).BindValueTo(v => api.Arguments.VideoSelection.AgeLimit = (int?)v, cbAgeLimit, clg); btnBrowseDownloadArchive.BindEnableTo(cbDownloadArchive); txtDownloadArchive.BindEnableTo(cbDownloadArchive).BindValueTo(v => { api.Arguments.VideoSelection.DownloadArchive = v; }, cbDownloadArchive, clg); #endregion #region Filesystem txtFileTemplate.BindEnableTo(cbFileTemplate).BindValueTo(v => { api.Arguments.FileSystem.OutputTemplate = v; }, cbFileTemplate, clg); cbRestrictFilenames.BindValueTo(v => api.Arguments.FileSystem.RestrictFilenames = v).Listen(clg); cbNoOverwrites.BindValueTo(v => api.Arguments.FileSystem.NoOverwrites = v).Listen(clg); cbWriteDescription.BindValueTo(v => api.Arguments.FileSystem.WriteDescription = v).Listen(clg); cbWriteAnnotations.BindValueTo(v => api.Arguments.FileSystem.WriteAnnotations = v).Listen(clg); #endregion #region Network txtProxy.BindEnableTo(cbProxy).BindValueTo(v => api.Arguments.Network.Proxy = v, cbProxy, clg); txtSourceAddress.BindEnableTo(cbSourceAddress).BindValueTo(v => api.Arguments.Network.SourceAddress = v, cbSourceAddress, clg); nudSocketTimeout.BindEnableTo(cbSocketTimeout).BindValueTo(v => api.Arguments.Network.SocketTimeout = (int?)v, cbSocketTimeout, clg); rbForceIpv4.BindValueTo(v => api.Arguments.Network.ForceIpv4 = v).Listen(clg); rbForceIpv6.BindValueTo(v => api.Arguments.Network.ForceIpv6 = v).Listen(clg); #endregion #region Download void limitRateEvt(float?v) { api.Arguments.Download.LimitRate = (v == null || v == 0) ? (ByteSize?)null : ByteSize.From(v.Value, (FilesizeUnit)cbxLimitRateUnits.SelectedItem); } cbxLimitRateUnits.BindEnableTo(cbLimitRate).BindValueTo(obj => limitRateEvt(nudLimitRate.GetValueFloat(cbLimitRate))).Listen(clg); nudLimitRate.BindEnableTo(cbLimitRate).BindValueTo(limitRateEvt, cbLimitRate, clg); cbRetriesInf.BindEnableTo(cbRetries); nudRetries.BindEnableTo(cbs => { return(cbs[0].Checked && !cbs[1].Checked); }, cbRetries, cbRetriesInf).BindValueTo(v => api.Arguments.Download.Retries = (v == null) ? null : v >= 0 ? v.ToString() : "infinite", cbRetries, clg); cbFragmentRetriesInf.BindEnableTo(cbFragmentRetries); nudFragmentRetries.BindEnableTo(cbs => { return(cbs[0].Checked && !cbs[1].Checked); }, cbFragmentRetries, cbFragmentRetriesInf).BindValueTo(v => api.Arguments.Download.FragmentRetries = (v == null) ? null : v >= 0 ? v.ToString() : "infinite", cbFragmentRetries, clg); cbPlaylistRandom.BindValueTo(v => api.Arguments.Download.PlaylistRandom = v).Listen(clg); cbPlaylistReversed.BindValueTo(v => api.Arguments.Download.PlaylistReverse = v).Listen(clg); #endregion cbWriteThumbnail.BindValueTo(v => api.Arguments.Thumbnail.WriteThumbnail = v).Listen(clg); #region Workarounds txtReferer.BindEnableTo(cbReferer).BindValueTo(v => api.Arguments.Workarounds.Referer = v, cbReferer, clg); txtUserAgent.BindEnableTo(cbUserAgent).BindValueTo(v => api.Arguments.Workarounds.UserAgent = v, cbUserAgent, clg); dgvHeaders.BindValueTo(v => { api.Arguments.Workarounds.Headers.Clear(); foreach (DataGridViewRow row in v) { string key = row.Cells["cKey"].Value as string; string value = row.Cells["cValue"].Value as string; if (!string.IsNullOrWhiteSpace(key) && !string.IsNullOrWhiteSpace(value)) { api.Arguments.Workarounds.Headers.Add(key, value); } } }).Listen(clg); nudSleepValue.BindEnableTo(rbSleepValue).BindValueTo(v => api.Arguments.Workarounds.SleepInterval = (int?)v, rbSleepValue, clg); nudSleepRangeMin.BindEnableTo(rbSleepRange).BindValueTo(v => api.Arguments.Workarounds.MinSleepInterval = (int?)v, rbSleepRange, clg); nudSleepRangeMax.BindEnableTo(rbSleepRange).BindValueTo(v => api.Arguments.Workarounds.MaxSleepInterval = (int?)v, rbSleepRange, clg); #endregion #region Auth string user = null, pass = null; txtPassword.BindEnableTo(cbUsernamePassword).BindValueTo(v => api.Arguments.Authentication.Password = v, cbUsernamePassword, clg); txtPassword.BindValueTo(v => { pass = v; if (string.IsNullOrWhiteSpace(user) || string.IsNullOrWhiteSpace(pass)) { api.Arguments.Authentication.Username = null; api.Arguments.Authentication.Password = null; } else { api.Arguments.Authentication.Username = user; api.Arguments.Authentication.Password = pass; } clg.Trigger(); }, cbUsernamePassword); txtUsername.BindEnableTo(cbUsernamePassword).BindValueTo(v => { user = v; if (string.IsNullOrWhiteSpace(user) || string.IsNullOrWhiteSpace(pass)) { api.Arguments.Authentication.Username = null; api.Arguments.Authentication.Password = null; } else { api.Arguments.Authentication.Username = user; api.Arguments.Authentication.Password = pass; } clg.Trigger(); }, cbUsernamePassword, clg); txtTwoFactor.BindEnableTo(cbTwoFactor).BindValueTo(v => api.Arguments.Authentication.TwoFactor = v, cbTwoFactor, clg); txtVideoPassword.BindEnableTo(cbVideoPassword).BindValueTo(v => api.Arguments.Authentication.VideoPassword = v, cbVideoPassword, clg); #endregion #region Post Processing api.Arguments.PostProcessing.PreferFFmpeg = true; api.Arguments.PostProcessing.FFmpegLocation = ffmpegPath; cbxRecodeFormat.BindEnableTo(cbRecodeFormat).BindValueTo(v => api.Arguments.PostProcessing.RecodeVideo = (VideoFormatRecode?)v, cbRecodeFormat, clg); #endregion #region Video Format ControlListenGroup formatGroup = ControlListenGroup.New(); txtCustomFormatSelector.BindEnableTo(cbCustomFormatSelector).BindValueTo(v => api.Arguments.VideoFormat.Format = v, cbCustomFormatSelector, formatGroup); cbxOutputFormat.BindEnableTo(cbOutputFormat).BindValueTo(v => api.Arguments.VideoFormat.MergeOutputFormat = (v == null) ? null : (MergeVideoFormat?)v, cbOutputFormat, clg); formatGroup.Listen(rbVq2160p, rbVq1440p, rbVq1080p, rbVq720p, rbVq480p, rbVq360p, rbVq240p, rbVqCustom, rbFps144, rbFps120, rbFps60, rbFps30, rbFps25, rbFpsCustom); formatGroup.Listen(cbVqPreferred, cbFpsPreferred, cbVqFallback, cbFpsFallback); formatGroup.Listen(nudFpsCustom, nudVideoQualityWidth, nudVideoQualityHeight); formatGroup.OnChanged += () => { if (!cbCustomFormatSelector.Checked) { api.Arguments.VideoFormat.Format = GetVideoQuality().FormatSelector; } VideoQuality vq = GetVideoQuality(); if (!rbVqCustom.Checked) { nudVideoQualityWidth.Value = vq.Width; nudVideoQualityHeight.Value = vq.Height; } if (!rbFpsCustom.Checked) { nudFpsCustom.Value = vq.Fps; } if (!cbCustomFormatSelector.Checked) { txtCustomFormatSelector.Text = vq.FormatSelector; } clg.Trigger(); }; formatGroup.Trigger(); #endregion }