diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b248083 --- /dev/null +++ b/.gitignore @@ -0,0 +1,349 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd.sln b/YTDLNetFrontEnd/YTDLNetFrontEnd.sln new file mode 100644 index 0000000..6226797 --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YTDLNetFrontEnd", "YTDLNetFrontEnd\YTDLNetFrontEnd.csproj", "{D7470CBA-B4D7-4F7C-B241-EB25B0D2B336}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D7470CBA-B4D7-4F7C-B241-EB25B0D2B336}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D7470CBA-B4D7-4F7C-B241-EB25B0D2B336}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D7470CBA-B4D7-4F7C-B241-EB25B0D2B336}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D7470CBA-B4D7-4F7C-B241-EB25B0D2B336}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd/Main.Designer.cs b/YTDLNetFrontEnd/YTDLNetFrontEnd/Main.Designer.cs new file mode 100644 index 0000000..3eb14cc --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd/Main.Designer.cs @@ -0,0 +1,176 @@ +namespace com.captainalm.YTDLNetFrontEnd +{ + partial class Main + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanelMain = new System.Windows.Forms.TableLayoutPanel(); + this.tableLayoutPanelEntry = new System.Windows.Forms.TableLayoutPanel(); + this.textBoxEntry = new System.Windows.Forms.TextBox(); + this.buttonGo = new System.Windows.Forms.Button(); + this.textBoxOutput = new System.Windows.Forms.TextBox(); + this.buttonInstall = new System.Windows.Forms.Button(); + this.buttonExit = new System.Windows.Forms.Button(); + this.backgroundWorkerMain = new System.ComponentModel.BackgroundWorker(); + this.tableLayoutPanelMain.SuspendLayout(); + this.tableLayoutPanelEntry.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanelMain + // + this.tableLayoutPanelMain.ColumnCount = 2; + this.tableLayoutPanelMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanelMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanelMain.Controls.Add(this.tableLayoutPanelEntry, 0, 0); + this.tableLayoutPanelMain.Controls.Add(this.textBoxOutput, 0, 2); + this.tableLayoutPanelMain.Controls.Add(this.buttonInstall, 0, 1); + this.tableLayoutPanelMain.Controls.Add(this.buttonExit, 1, 1); + this.tableLayoutPanelMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanelMain.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanelMain.Margin = new System.Windows.Forms.Padding(1); + this.tableLayoutPanelMain.Name = "tableLayoutPanelMain"; + this.tableLayoutPanelMain.RowCount = 3; + this.tableLayoutPanelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 15F)); + this.tableLayoutPanelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 15F)); + this.tableLayoutPanelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 70F)); + this.tableLayoutPanelMain.Size = new System.Drawing.Size(284, 161); + this.tableLayoutPanelMain.TabIndex = 0; + // + // tableLayoutPanelEntry + // + this.tableLayoutPanelEntry.ColumnCount = 2; + this.tableLayoutPanelMain.SetColumnSpan(this.tableLayoutPanelEntry, 2); + this.tableLayoutPanelEntry.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 80F)); + this.tableLayoutPanelEntry.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20F)); + this.tableLayoutPanelEntry.Controls.Add(this.textBoxEntry, 0, 0); + this.tableLayoutPanelEntry.Controls.Add(this.buttonGo, 1, 0); + this.tableLayoutPanelEntry.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanelEntry.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanelEntry.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanelEntry.Name = "tableLayoutPanelEntry"; + this.tableLayoutPanelEntry.RowCount = 1; + this.tableLayoutPanelEntry.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanelEntry.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F)); + this.tableLayoutPanelEntry.Size = new System.Drawing.Size(284, 24); + this.tableLayoutPanelEntry.TabIndex = 0; + // + // textBoxEntry + // + this.textBoxEntry.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxEntry.Location = new System.Drawing.Point(0, 2); + this.textBoxEntry.Margin = new System.Windows.Forms.Padding(0); + this.textBoxEntry.Name = "textBoxEntry"; + this.textBoxEntry.Size = new System.Drawing.Size(227, 20); + this.textBoxEntry.TabIndex = 0; + // + // buttonGo + // + this.buttonGo.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonGo.Location = new System.Drawing.Point(227, 0); + this.buttonGo.Margin = new System.Windows.Forms.Padding(0); + this.buttonGo.Name = "buttonGo"; + this.buttonGo.Size = new System.Drawing.Size(57, 24); + this.buttonGo.TabIndex = 1; + this.buttonGo.Text = "Go!"; + this.buttonGo.UseVisualStyleBackColor = true; + this.buttonGo.Click += new System.EventHandler(this.buttonGo_Click); + // + // textBoxOutput + // + this.tableLayoutPanelMain.SetColumnSpan(this.textBoxOutput, 2); + this.textBoxOutput.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBoxOutput.Location = new System.Drawing.Point(1, 49); + this.textBoxOutput.Margin = new System.Windows.Forms.Padding(1); + this.textBoxOutput.Multiline = true; + this.textBoxOutput.Name = "textBoxOutput"; + this.textBoxOutput.ReadOnly = true; + this.textBoxOutput.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBoxOutput.Size = new System.Drawing.Size(282, 111); + this.textBoxOutput.TabIndex = 3; + this.textBoxOutput.WordWrap = false; + // + // buttonInstall + // + this.buttonInstall.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonInstall.Location = new System.Drawing.Point(0, 24); + this.buttonInstall.Margin = new System.Windows.Forms.Padding(0); + this.buttonInstall.Name = "buttonInstall"; + this.buttonInstall.Size = new System.Drawing.Size(142, 24); + this.buttonInstall.TabIndex = 4; + this.buttonInstall.Text = "Install"; + this.buttonInstall.UseVisualStyleBackColor = true; + this.buttonInstall.Click += new System.EventHandler(this.buttonInstall_Click); + // + // buttonExit + // + this.buttonExit.Dock = System.Windows.Forms.DockStyle.Fill; + this.buttonExit.Location = new System.Drawing.Point(142, 24); + this.buttonExit.Margin = new System.Windows.Forms.Padding(0); + this.buttonExit.Name = "buttonExit"; + this.buttonExit.Size = new System.Drawing.Size(142, 24); + this.buttonExit.TabIndex = 5; + this.buttonExit.Text = "Exit"; + this.buttonExit.UseVisualStyleBackColor = true; + this.buttonExit.Click += new System.EventHandler(this.buttonExit_Click); + // + // backgroundWorkerMain + // + this.backgroundWorkerMain.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorkerMain_DoWork); + // + // Main + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(284, 161); + this.Controls.Add(this.tableLayoutPanelMain); + this.MinimumSize = new System.Drawing.Size(300, 200); + this.Name = "Main"; + this.ShowIcon = false; + this.Text = "YT-DL Front End"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.Main_FormClosed); + this.Load += new System.EventHandler(this.Main_Load); + this.tableLayoutPanelMain.ResumeLayout(false); + this.tableLayoutPanelMain.PerformLayout(); + this.tableLayoutPanelEntry.ResumeLayout(false); + this.tableLayoutPanelEntry.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanelMain; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanelEntry; + private System.Windows.Forms.TextBox textBoxEntry; + private System.Windows.Forms.TextBox textBoxOutput; + private System.Windows.Forms.Button buttonGo; + private System.Windows.Forms.Button buttonInstall; + private System.Windows.Forms.Button buttonExit; + private System.ComponentModel.BackgroundWorker backgroundWorkerMain; + } +} + diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd/Main.cs b/YTDLNetFrontEnd/YTDLNetFrontEnd/Main.cs new file mode 100644 index 0000000..232d256 --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd/Main.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.IO; +using System.Threading.Tasks; + +namespace com.captainalm.YTDLNetFrontEnd +{ + public partial class Main : Form + { + private Process theProcess; + + public Main() + { + InitializeComponent(); + } + + private void Main_Load(object sender, EventArgs e) + { + if (YTDL.getInstalled() == ApplicationType.Unavailable) + { + buttonGo.Enabled = false; + } + else + { + buttonInstall.Text = "Update"; + } + Environment.CurrentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos); + } + + private void buttonGo_Click(object sender, EventArgs e) + { + if (!backgroundWorkerMain.IsBusy) backgroundWorkerMain.RunWorkerAsync(BWArg.Go); + + } + + private void buttonInstall_Click(object sender, EventArgs e) + { + if (!backgroundWorkerMain.IsBusy) backgroundWorkerMain.RunWorkerAsync(BWArg.Install); + } + + private void buttonExit_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void Main_FormClosed(object sender, FormClosedEventArgs e) + { + Environment.Exit(0); + } + + private void backgroundWorkerMain_DoWork(object sender, DoWorkEventArgs e) + { + switch ((BWArg)e.Argument) + { + case BWArg.Install: + this.Invoke(new Action(() => { + buttonExit.Enabled = false; + buttonInstall.Enabled = false; + })); + + var loctxt = + YTDL.executeInstall((YTDL.getInstalled() != ApplicationType.Unavailable) ? YTDL.getInstalled() : + (((Control.ModifierKeys & Keys.Shift) == Keys.Shift) ? ApplicationType.YoutubeDL : ApplicationType.YT_DLP), + YTDL.getInstalled() != ApplicationType.Unavailable) + + Environment.NewLine; + this.Invoke(new Action(() => + { + textBoxOutput.Text += loctxt; + })); + if (YTDL.getInstalled() != ApplicationType.Unavailable) + { + this.Invoke(new Action(() => + { + buttonGo.Enabled = true; + buttonInstall.Text = "Update"; + })); + } + this.Invoke(new Action(() => + { + buttonInstall.Enabled = true; + buttonExit.Enabled = true; + })); + break; + case BWArg.Go: + this.Invoke(new Action(() => + { + buttonExit.Enabled = false; + buttonGo.Enabled = false; + })); + + if (theProcess != null) + { + if (!theProcess.HasExited) theProcess.WaitForExit(); + theProcess.Close(); + } + + var theTarget = ""; + + this.Invoke(new Action(() => + { + theTarget = textBoxEntry.Text; + })); + + theProcess = YTDL.executeApplication(theTarget); + if (theProcess != null) + { + theProcess.BeginOutputReadLine(); + theProcess.BeginErrorReadLine(); + theProcess.OutputDataReceived += theProcess_OutputDataReceived; + theProcess.ErrorDataReceived += theProcess_ErrorDataReceived; + theProcess.Exited += theProcess_Exited; + theProcess.EnableRaisingEvents = true; + theProcess.WaitForExit(); + } + this.Invoke(new Action(() => + { + buttonGo.Enabled = true; + buttonExit.Enabled = true; + })); + break; + default: + break; + } + } + + void theProcess_Exited(object sender, EventArgs e) + { + theProcess.CancelOutputRead(); + theProcess.CancelErrorRead(); + } + + void theProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e) + { + if (e.Data.Equals("")) return; + this.Invoke(new Action(() => + { + textBoxOutput.Text += "Error: " + e.Data + Environment.NewLine; + })); + } + + void theProcess_OutputDataReceived(object sender, DataReceivedEventArgs e) + { + this.Invoke(new Action(() => + { + textBoxOutput.Text += e.Data + Environment.NewLine; + })); + } + + private enum BWArg { + Install, + Go + } + } +} diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd/Main.resx b/YTDLNetFrontEnd/YTDLNetFrontEnd/Main.resx new file mode 100644 index 0000000..b4fa3e4 --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd/Main.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd/Program.cs b/YTDLNetFrontEnd/YTDLNetFrontEnd/Program.cs new file mode 100644 index 0000000..69fc159 --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace com.captainalm.YTDLNetFrontEnd +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Main()); + } + } +} diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/AssemblyInfo.cs b/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..60e1b50 --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("YT-DL Frontend")] +[assembly: AssemblyDescription("YT-DL Frontend in .net 4")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Captain ALM")] +[assembly: AssemblyProduct("YTDLNetFrontEnd")] +[assembly: AssemblyCopyright("Copyright © Captain ALM 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2c525461-f259-4b76-b4e9-e5f3bb3b3823")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.0.0.0")] +[assembly: AssemblyFileVersion("0.0.0.0")] diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Resources.Designer.cs b/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Resources.Designer.cs new file mode 100644 index 0000000..7e19fea --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace com.captainalm.YTDLNetFrontEnd.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("com.captainalm.YTDLNetFrontEnd.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Resources.resx b/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Settings.Designer.cs b/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Settings.Designer.cs new file mode 100644 index 0000000..ded7a8f --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace com.captainalm.YTDLNetFrontEnd.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Settings.settings b/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd/YTDL.cs b/YTDLNetFrontEnd/YTDLNetFrontEnd/YTDL.cs new file mode 100644 index 0000000..1791c8e --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd/YTDL.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.IO; +using System.Threading; + +namespace com.captainalm.YTDLNetFrontEnd +{ + static class YTDL + { + private static string[] pathLocs = Environment.GetEnvironmentVariable("PATH").Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + + public static Process executeApplication(string target) + { + var packageName = ""; + switch (getInstalled()) + { + case ApplicationType.YoutubeDL: + packageName = "youtube_dl"; + break; + case ApplicationType.YT_DLP: + packageName = "yt_dlp"; + break; + default: + return null; + } + var pyProSet = new ProcessStartInfo(findExecutableInPath("python"), "-m " + packageName + " --hls-prefer-native " + + ((getInstalled() == ApplicationType.YT_DLP) ? "-N 16 " : "") + "\"" + target + "\"") + { UseShellExecute = false, CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8 }; + return Process.Start(pyProSet); + } + + public static string executeInstall(ApplicationType package, bool update) + { + var packageName = ""; + switch (package) + { + case ApplicationType.YoutubeDL: + packageName = "youtube-dl"; + break; + case ApplicationType.YT_DLP: + packageName = "yt-dlp"; + break; + default: + return "Invalid Package Name"; + } + var pipProSet = new ProcessStartInfo(findExecutableInPath("python"), "-m pip install " + packageName + ((update) ? " --upgrade" : "")) { UseShellExecute = false, CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true }; + using (var pipPro = Process.Start(pipProSet)) + { + using (var errTSR = new ThreadedStreamReader(pipPro.StandardError.BaseStream)) + { + using (var outTSR = new ThreadedStreamReader(pipPro.StandardOutput.BaseStream)) + { + pipPro.WaitForExit(); + try + { + var terr = System.Text.Encoding.UTF8.GetString(errTSR.getData()); + var tout = System.Text.Encoding.UTF8.GetString(outTSR.getData()); + if (terr != "") return terr; else return tout; + } + catch (Exception e) + { + return "Exception:" + e.GetType().FullName + ":" + e.Message; + } + } + } + } + } + + private static ApplicationType installed; + public static ApplicationType getInstalled() + { + if (installed == ApplicationType.Unavailable) + { + try + { + var pipProSet = new ProcessStartInfo(findExecutableInPath("python"), "-m pip freeze") {UseShellExecute = false, CreateNoWindow = true, RedirectStandardOutput = true}; + using (var pipPro = Process.Start(pipProSet)) + { + var theList = pipPro.StandardOutput.ReadToEnd(); + pipPro.WaitForExit(); + if (theList.Contains("yt-dlp")) installed = ApplicationType.YT_DLP; + else if (theList.Contains("youtube-dl")) installed = ApplicationType.YoutubeDL; + else installed = ApplicationType.Unavailable; + } + } + catch (Exception) + { + installed = ApplicationType.Unavailable; + } + } + return installed; + } + + private static String findExecutableInPath(string target) + { + if (target.Equals("")) return null; + target = Path.GetFileNameWithoutExtension(target) + ".exe"; + foreach (var c in pathLocs) + { + if (Path.GetFileNameWithoutExtension(c).Equals(target) && File.Exists(c)) return c; + if (File.Exists(Path.Combine(c, target))) return Path.Combine(c, target); + } + return null; + } + } + + enum ApplicationType : int + { + Unavailable = 0, + YoutubeDL = 1, + YT_DLP = 2 + } + + class ThreadedStreamReader : IDisposable + { + Thread theThread; + MemoryStream msToRet; + Stream theStream; + public ThreadedStreamReader(Stream streamIn) + { + theStream = streamIn; + msToRet = new MemoryStream(); + theThread = new Thread(thread_execute); + theThread.IsBackground = true; + theThread.Start(); + } + + void thread_execute() + { + try + { + int b; + while ((b = theStream.ReadByte()) != -1) msToRet.WriteByte((byte)b); + } + catch (Exception e) + { + var msg = System.Text.Encoding.UTF8.GetBytes("Exception:" + e.GetType().FullName + ":" + e.Message); + msToRet.Write(msg, 0, msg.Length); + } + } + + public byte[] getData() + { + theThread.Join(); + return msToRet.ToArray(); + } + + public void Dispose() + { + theThread.Join(); + msToRet.Close(); + } + } +} diff --git a/YTDLNetFrontEnd/YTDLNetFrontEnd/YTDLNetFrontEnd.csproj b/YTDLNetFrontEnd/YTDLNetFrontEnd/YTDLNetFrontEnd.csproj new file mode 100644 index 0000000..a059135 --- /dev/null +++ b/YTDLNetFrontEnd/YTDLNetFrontEnd/YTDLNetFrontEnd.csproj @@ -0,0 +1,90 @@ + + + + + Debug + AnyCPU + {D7470CBA-B4D7-4F7C-B241-EB25B0D2B336} + WinExe + Properties + com.captainalm.YTDLNetFrontEnd + YTDLNetFrontEnd + v4.0 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + com.captainalm.YTDLNetFrontEnd.Program + + + + + + + + + + + + + + + + Form + + + Main.cs + + + + + + Main.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + \ No newline at end of file