Replace original code with .NET 5
@@ -10,34 +10,39 @@ echo.
|
||||
set "ver=16"
|
||||
set /p ver="Enter the version number: "
|
||||
|
||||
cd ..\Code\bin\x64\Release
|
||||
cd ..
|
||||
|
||||
dotnet publish -c Release -o "Release/Build" "Code5"
|
||||
|
||||
cd Release
|
||||
|
||||
rmdir /s/q FlowframesApp%ver%
|
||||
mkdir "FlowframesApp%ver%"
|
||||
mkdir "FlowframesApp%ver%/FlowframesData"
|
||||
mkdir "FlowframesApp%ver%/FlowframesData/pkgs"
|
||||
|
||||
rem xcopy "../../../../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E
|
||||
xcopy "../../../../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I
|
||||
xcopy "../../../../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I
|
||||
xcopy "../../../../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I
|
||||
xcopy "../../../../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I
|
||||
xcopy "../../../../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I
|
||||
rem xcopy "../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E
|
||||
xcopy "../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I
|
||||
xcopy "../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I
|
||||
xcopy "../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I
|
||||
xcopy "../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I
|
||||
xcopy "../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I
|
||||
|
||||
echo %ver% >> "FlowframesApp%ver%/FlowframesData/ver.ini"
|
||||
|
||||
xcopy Flowframes.exe "FlowframesApp%ver%"
|
||||
xcopy /E "Build" "FlowframesApp%ver%"
|
||||
|
||||
cd ../../../../Build
|
||||
cd ..\Build5
|
||||
|
||||
rmdir /s/q ..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\logs
|
||||
del ..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\config.ini
|
||||
rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\logs
|
||||
del ..\Release\FlowframesApp%ver%\FlowframesData\config.ini
|
||||
|
||||
|
||||
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Code\bin\x64\Release\FlowframesApp%ver%"
|
||||
del FF-%ver%-Slim.7z
|
||||
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Release\FlowframesApp%ver%"
|
||||
|
||||
|
||||
rmdir /s/q ..\Code\bin\x64\Release\FlowframesApp%ver%
|
||||
rmdir /s/q ..\Release\FlowframesApp%ver%
|
||||
|
||||
|
||||
rem pause
|
||||
@@ -10,41 +10,48 @@ echo.
|
||||
set "ver=16"
|
||||
set /p ver="Enter the version number: "
|
||||
|
||||
cd ..\Code\bin\x64\Release
|
||||
cd ..
|
||||
|
||||
dotnet publish -c Release -o "Release/Build" "Code5"
|
||||
|
||||
cd Release
|
||||
|
||||
rmdir /s/q FlowframesApp%ver%
|
||||
mkdir "FlowframesApp%ver%"
|
||||
mkdir "FlowframesApp%ver%/FlowframesData"
|
||||
mkdir "FlowframesApp%ver%/FlowframesData/pkgs"
|
||||
|
||||
rem xcopy "../../../../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E
|
||||
xcopy "../../../../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I
|
||||
xcopy "../../../../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I
|
||||
xcopy "../../../../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I
|
||||
xcopy "../../../../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I
|
||||
xcopy "../../../../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I
|
||||
rem xcopy "../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E
|
||||
xcopy "../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I
|
||||
xcopy "../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I
|
||||
xcopy "../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I
|
||||
xcopy "../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I
|
||||
xcopy "../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I
|
||||
|
||||
echo %ver% >> "FlowframesApp%ver%/FlowframesData/ver.ini"
|
||||
|
||||
xcopy Flowframes.exe "FlowframesApp%ver%"
|
||||
xcopy /E "Build" "FlowframesApp%ver%"
|
||||
|
||||
cd ../../../../Build
|
||||
cd ..\Build5
|
||||
|
||||
rmdir /s/q ..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\logs
|
||||
del ..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\config.ini
|
||||
rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\logs
|
||||
del ..\Release\FlowframesApp%ver%\FlowframesData\config.ini
|
||||
|
||||
|
||||
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Code\bin\x64\Release\FlowframesApp%ver%"
|
||||
del FF-%ver%-Slim.7z
|
||||
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Release\FlowframesApp%ver%"
|
||||
|
||||
xcopy "../pkgs/py-tu" "..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu" /E /I
|
||||
7za.exe a FF-%ver%-Full.7z -m0=flzma2 -mx7 "..\Code\bin\x64\Release\FlowframesApp%ver%"
|
||||
xcopy "../pkgs/py-tu" "..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu" /E /I
|
||||
del FF-%ver%-Full.7z
|
||||
7za.exe a FF-%ver%-Full.7z -m0=flzma2 -mx7 "..\Release\FlowframesApp%ver%"
|
||||
|
||||
rmdir /s/q ..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu
|
||||
xcopy "../pkgs/py-amp" "..\Code\bin\x64\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-amp" /E /I
|
||||
7za.exe a FF-%ver%-Full-RTX3000.7z -m0=flzma2 -mx7 "..\Code\bin\x64\Release\FlowframesApp%ver%"
|
||||
rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu
|
||||
xcopy "../pkgs/py-amp" "..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-amp" /E /I
|
||||
del FF-%ver%-Full-RTX3000.7z
|
||||
7za.exe a FF-%ver%-Full-RTX3000.7z -m0=flzma2 -mx7 "..\Release\FlowframesApp%ver%"
|
||||
|
||||
|
||||
rmdir /s/q ..\Code\bin\x64\Release\FlowframesApp%ver%
|
||||
rmdir /s/q ..\Release\FlowframesApp%ver%
|
||||
|
||||
|
||||
rem pause
|
||||
BIN
Build5/7za.dll
BIN
Build5/7za.exe
@@ -1,48 +0,0 @@
|
||||
@echo off
|
||||
|
||||
echo ===============================
|
||||
echo == NMKD'S FLOWFRAMES BUILDER ==
|
||||
echo ===============================
|
||||
echo.
|
||||
echo This script makes a build ready for distribution by creating three 7z archives, without python, with pytorch for Turing, and with pytorch for Ampere.
|
||||
echo.
|
||||
|
||||
set "ver=16"
|
||||
set /p ver="Enter the version number: "
|
||||
|
||||
cd ..
|
||||
|
||||
dotnet publish -c Release -o "Release/Build" "Code5"
|
||||
|
||||
cd Release
|
||||
|
||||
rmdir /s/q FlowframesApp%ver%
|
||||
mkdir "FlowframesApp%ver%"
|
||||
mkdir "FlowframesApp%ver%/FlowframesData"
|
||||
mkdir "FlowframesApp%ver%/FlowframesData/pkgs"
|
||||
|
||||
rem xcopy "../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E
|
||||
xcopy "../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I
|
||||
xcopy "../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I
|
||||
xcopy "../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I
|
||||
xcopy "../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I
|
||||
xcopy "../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I
|
||||
|
||||
echo %ver% >> "FlowframesApp%ver%/FlowframesData/ver.ini"
|
||||
|
||||
xcopy /E "Build" "FlowframesApp%ver%"
|
||||
|
||||
cd ..\Build5
|
||||
|
||||
rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\logs
|
||||
del ..\Release\FlowframesApp%ver%\FlowframesData\config.ini
|
||||
|
||||
|
||||
del FF-%ver%-Slim.7z
|
||||
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Release\FlowframesApp%ver%"
|
||||
|
||||
|
||||
rmdir /s/q ..\Release\FlowframesApp%ver%
|
||||
|
||||
|
||||
rem pause
|
||||
@@ -1,57 +0,0 @@
|
||||
@echo off
|
||||
|
||||
echo ===============================
|
||||
echo == NMKD'S FLOWFRAMES BUILDER ==
|
||||
echo ===============================
|
||||
echo.
|
||||
echo This script makes a build ready for distribution by creating three 7z archives, without python, with pytorch for Turing, and with pytorch for Ampere.
|
||||
echo.
|
||||
|
||||
set "ver=16"
|
||||
set /p ver="Enter the version number: "
|
||||
|
||||
cd ..
|
||||
|
||||
dotnet publish -c Release -o "Release/Build" "Code5"
|
||||
|
||||
cd Release
|
||||
|
||||
rmdir /s/q FlowframesApp%ver%
|
||||
mkdir "FlowframesApp%ver%"
|
||||
mkdir "FlowframesApp%ver%/FlowframesData"
|
||||
mkdir "FlowframesApp%ver%/FlowframesData/pkgs"
|
||||
|
||||
rem xcopy "../pkgs" "FlowframesApp%ver%/FlowframesData\pkgs\" /E
|
||||
xcopy "../pkgs/av" "FlowframesApp%ver%/FlowframesData\pkgs\av" /E /I
|
||||
xcopy "../pkgs/dain-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\dain-ncnn" /E /I
|
||||
xcopy "../pkgs/licenses" "FlowframesApp%ver%/FlowframesData\pkgs\licenses" /E /I
|
||||
xcopy "../pkgs/rife-cuda" "FlowframesApp%ver%/FlowframesData\pkgs\rife-cuda" /E /I
|
||||
xcopy "../pkgs/rife-ncnn" "FlowframesApp%ver%/FlowframesData\pkgs\rife-ncnn" /E /I
|
||||
|
||||
echo %ver% >> "FlowframesApp%ver%/FlowframesData/ver.ini"
|
||||
|
||||
xcopy /E "Build" "FlowframesApp%ver%"
|
||||
|
||||
cd ..\Build5
|
||||
|
||||
rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\logs
|
||||
del ..\Release\FlowframesApp%ver%\FlowframesData\config.ini
|
||||
|
||||
|
||||
del FF-%ver%-Slim.7z
|
||||
7za.exe a FF-%ver%-Slim.7z -m0=flzma2 -mx5 "..\Release\FlowframesApp%ver%"
|
||||
|
||||
xcopy "../pkgs/py-tu" "..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu" /E /I
|
||||
del FF-%ver%-Full.7z
|
||||
7za.exe a FF-%ver%-Full.7z -m0=flzma2 -mx7 "..\Release\FlowframesApp%ver%"
|
||||
|
||||
rmdir /s/q ..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-tu
|
||||
xcopy "../pkgs/py-amp" "..\Release\FlowframesApp%ver%\FlowframesData\pkgs\py-amp" /E /I
|
||||
del FF-%ver%-Full-RTX3000.7z
|
||||
7za.exe a FF-%ver%-Full-RTX3000.7z -m0=flzma2 -mx7 "..\Release\FlowframesApp%ver%"
|
||||
|
||||
|
||||
rmdir /s/q ..\Release\FlowframesApp%ver%
|
||||
|
||||
|
||||
rem pause
|
||||
@@ -1,17 +0,0 @@
|
||||
1) Download...
|
||||
- FF-Slim if you have an AMD/Intel GPU, or if you have an Nvidia GPU and Pytorch already installed
|
||||
- FF-Full if you have an Nvidia Turing (RTX 2000) or older GPU
|
||||
- FF-Full-RTX3000 if you have an Nvidia Ampere (RTX 3000) GPU. Also compatible with older GPUs, but has bigger filesize.
|
||||
|
||||
2) Extract the 7z file using 7zip or any other program that supports it
|
||||
|
||||
3) Run Flowframes.exe
|
||||
|
||||
|
||||
|
||||
|
||||
If you updated from an older version, you can optionally copy "FlowframesData/config.ini" to your new installation if you want to keep your settings.
|
||||
You can delete your old installation after updating.
|
||||
|
||||
IT IS NOT RECOMMENDED TO OVERWRITE YOUR OLD INSTALLATION!
|
||||
Instead, delete it first or install the new one to a different/empty folder.
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Syncfusion.Licensing" publicKeyToken="632609b4d040f6b4" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-18.2460.0.56" newVersion="18.2460.0.56" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Security.Principal.Windows" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -1,369 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{389E42DD-A163-49D7-9E0A-AE41090A07B3}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>Flowframes</RootNamespace>
|
||||
<AssemblyName>Flowframes</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0-windows</TargetFramework>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
|
||||
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
|
||||
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
|
||||
<ApplicationIcon>flowframesIcoNew.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="7z.NET, Version=1.0.3.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\7z.NET.1.0.3\lib\net463\7z.NET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CircularProgressBar, Version=2.8.0.16, Culture=neutral, PublicKeyToken=310fd07b25df79b3, processorArchitecture=MSIL">
|
||||
<HintPath>packages\CircularProgressBar.2.8.0.16\lib\net40\CircularProgressBar.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Costura, Version=4.1.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Costura.Fody.4.1.0\lib\net40\Costura.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Crc32.NET, Version=1.0.0.0, Culture=neutral, PublicKeyToken=dc0b95cf99bf4e99, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Crc32.NET.1.2.0\lib\net20\Crc32.NET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CustomMarshalers" />
|
||||
<Reference Include="Cyotek.Windows.Forms.TabList, Version=2.0.0.0, Culture=neutral, PublicKeyToken=58daa28b0b2de221, processorArchitecture=MSIL">
|
||||
<HintPath>packages\CyotekTabList.2.0.0\lib\net35\Cyotek.Windows.Forms.TabList.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DiskDetector, Version=0.3.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\diskdetector-net.0.3.2\lib\netstandard2.0\DiskDetector.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HTAlt WinForms, Version=0.1.6.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\HTAlt.WinForms.0.1.6\lib\net461\HTAlt WinForms.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HTAlt.Standart, Version=0.1.6.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\HTAlt.Standart.0.1.6\lib\netstandard2.0\HTAlt.Standart.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Magick.NET-Q16-AnyCPU, Version=7.21.1.0, Culture=neutral, PublicKeyToken=2004825badfa91ec, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Magick.NET-Q16-AnyCPU.7.21.1\lib\net40\Magick.NET-Q16-AnyCPU.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Magick.NET.Core, Version=4.1.0.0, Culture=neutral, PublicKeyToken=2004825badfa91ec, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Magick.NET.Core.4.1.0\lib\net40\Magick.NET.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="Microsoft.WindowsAPICodePack, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\WindowsAPICodePack-Core.1.1.1\lib\Microsoft.WindowsAPICodePack.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAPICodePack.Shell, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\WindowsAPICodePack-Shell.1.1.1\lib\Microsoft.WindowsAPICodePack.Shell.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NvAPIWrapper, Version=0.8.0.98, Culture=neutral, PublicKeyToken=310fd07b25df79b3, processorArchitecture=MSIL">
|
||||
<HintPath>packages\NvAPIWrapper.Net.0.8.0.98\lib\net45\NvAPIWrapper.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PagedControl, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\PagedControl.2.2.0\lib\net35\PagedControl.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="Standart.Hash.xxHash, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Standart.Hash.xxHash.3.1.0\lib\netstandard2.0\Standart.Hash.xxHash.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.HashFunction.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=80c9288e394c1322, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Data.HashFunction.Core.2.0.0\lib\net45\System.Data.HashFunction.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.HashFunction.Interfaces, Version=2.0.0.0, Culture=neutral, PublicKeyToken=80c9288e394c1322, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Data.HashFunction.Interfaces.2.0.0\lib\net45\System.Data.HashFunction.Interfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Design" />
|
||||
<Reference Include="System.Drawing.Common, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Drawing.Common.5.0.0\lib\net461\System.Drawing.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Claims, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Security.Claims.4.3.0\lib\net46\System.Security.Claims.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Principal.Windows, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Security.Principal.Windows.4.3.0\lib\net46\System.Security.Principal.Windows.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="TabControl, Version=2.1.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\TabControl.2.1.2\lib\net35\TabControl.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Win32Interop.Dwmapi, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Win32Interop.Dwmapi.1.0.1\lib\Win32Interop.Dwmapi.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Win32Interop.Gdi32, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Win32Interop.Gdi32.1.0.1\lib\Win32Interop.Gdi32.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Win32Interop.Kernel32, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Win32Interop.Kernel32.1.0.1\lib\Win32Interop.Kernel32.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Win32Interop.User32, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Win32Interop.User32.1.0.1\lib\Win32Interop.User32.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Win32Interop.Uxtheme, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Win32Interop.Uxtheme.1.0.1\lib\Win32Interop.Uxtheme.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="WindowsFormsIntegration" />
|
||||
<Reference Include="WinFormAnimation, Version=1.6.0.4, Culture=neutral, PublicKeyToken=310fd07b25df79b3, processorArchitecture=MSIL">
|
||||
<HintPath>packages\WinFormAnimation.1.6.0.4\lib\net40\WinFormAnimation.dll</HintPath>
|
||||
</Reference>
|
||||
<PackageReference Include="CircularProgressBar" Version="2.8.0.16" />
|
||||
<PackageReference Include="Crc32.NET" Version="1.2.0" />
|
||||
<PackageReference Include="CyotekTabList" Version="2.2.0" />
|
||||
<PackageReference Include="diskdetector-net" Version="0.3.2" />
|
||||
<PackageReference Include="HTAlt.Standart" Version="0.1.6" />
|
||||
<PackageReference Include="HTAlt.WinForms" Version="0.1.6" />
|
||||
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.23.1" />
|
||||
<PackageReference Include="Magick.NET.Core" Version="6.1.0" />
|
||||
<PackageReference Include="NvAPIWrapper.Net" Version="0.8.1.101" />
|
||||
<PackageReference Include="Standart.Hash.xxHash" Version="3.1.0" />
|
||||
<PackageReference Include="System.Management" Version="5.0.0" />
|
||||
<PackageReference Include="WindowsAPICodePack-Core" Version="1.1.2" />
|
||||
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
|
||||
<PackageReference Include="WinFormAnimation" Version="1.6.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Data\AI.cs" />
|
||||
<Compile Include="Data\InterpSettings.cs" />
|
||||
<Compile Include="Data\Networks.cs" />
|
||||
<Compile Include="Data\Padding.cs" />
|
||||
<Compile Include="Data\ResumeState.cs" />
|
||||
<Compile Include="Data\SubtitleTrack.cs" />
|
||||
<Compile Include="Forms\BatchForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Forms\BatchForm.Designer.cs">
|
||||
<DependentUpon>BatchForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Forms\BigPreviewForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Forms\BigPreviewForm.Designer.cs">
|
||||
<DependentUpon>BigPreviewForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Forms\SettingsForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Forms\SettingsForm.Designer.cs">
|
||||
<DependentUpon>SettingsForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Forms\UpdaterForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Forms\UpdaterForm.Designer.cs">
|
||||
<DependentUpon>UpdaterForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="IO\ConfigParser.cs" />
|
||||
<Compile Include="Data\FlowPackage.cs" />
|
||||
<Compile Include="IO\ModelDownloader.cs" />
|
||||
<Compile Include="Data\Packages.cs" />
|
||||
<Compile Include="IO\PkgUtils.cs" />
|
||||
<Compile Include="Main\AutoEncode.cs" />
|
||||
<Compile Include="Main\BatchProcessing.cs" />
|
||||
<Compile Include="Main\CreateVideo.cs" />
|
||||
<Compile Include="Main\InterpolateSteps.cs" />
|
||||
<Compile Include="Main\InterpolateUtils.cs" />
|
||||
<Compile Include="Main\FrameOrder.cs" />
|
||||
<Compile Include="Main\ResumeUtils.cs" />
|
||||
<Compile Include="Media\AvProcess.cs" />
|
||||
<Compile Include="Media\FfmpegAlpha.cs" />
|
||||
<Compile Include="Media\FfmpegAudioAndMetadata.cs" />
|
||||
<Compile Include="Media\FfmpegCommands.cs" />
|
||||
<Compile Include="Media\FfmpegEncode.cs" />
|
||||
<Compile Include="Media\FfmpegExtract.cs" />
|
||||
<Compile Include="Media\FFmpegUtils.cs" />
|
||||
<Compile Include="MiscUtils\Benchmarker.cs" />
|
||||
<Compile Include="OS\AiProcess.cs" />
|
||||
<Compile Include="ExtensionMethods.cs" />
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form1.Designer.cs">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Main\Interpolate.cs" />
|
||||
<Compile Include="IO\CfgStrings.cs" />
|
||||
<Compile Include="IO\Config.cs" />
|
||||
<Compile Include="IO\IOUtils.cs" />
|
||||
<Compile Include="Data\Paths.cs" />
|
||||
<Compile Include="IO\Logger.cs" />
|
||||
<Compile Include="Magick\Converter.cs" />
|
||||
<Compile Include="Magick\Dedupe.cs" />
|
||||
<Compile Include="OS\NvApi.cs" />
|
||||
<Compile Include="OS\OSUtils.cs" />
|
||||
<Compile Include="OS\Python.cs" />
|
||||
<Compile Include="OS\Updater.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="MiscUtils\FormatUtils.cs" />
|
||||
<Compile Include="UI\GetWebInfo.cs" />
|
||||
<Compile Include="UI\MainUiFunctions.cs" />
|
||||
<Compile Include="UI\UIUtils.cs" />
|
||||
<Compile Include="UI\UtilsTab.cs" />
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\BatchForm.resx">
|
||||
<DependentUpon>BatchForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\BigPreviewForm.resx">
|
||||
<DependentUpon>BigPreviewForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\SettingsForm.resx">
|
||||
<DependentUpon>SettingsForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\UpdaterForm.resx">
|
||||
<DependentUpon>UpdaterForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.7.2 %28x86 and x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="FlowFramesFunkyLogo1.ico" />
|
||||
<Content Include="FlowFramesFunkyLogo2.ico" />
|
||||
<None Include="Resources\flowframesIcoNew-512px.png" />
|
||||
<None Include="Resources\flowframesIcoNew.png" />
|
||||
<None Include="Resources\questmark-72px-bordeer.png" />
|
||||
<None Include="Resources\7za.exe" />
|
||||
<None Include="Resources\baseline_fact_check_white_48dp.png" />
|
||||
<None Include="Resources\discordIco.png" />
|
||||
<None Include="Resources\paypal256px.png" />
|
||||
<None Include="Resources\patreon256px.png" />
|
||||
<None Include="Resources\baseline_settings_white_48dp.png" />
|
||||
<None Include="Resources\baseline_image_white_48dp.png" />
|
||||
<None Include="Resources\baseline_image_white_48dp-4x.png" />
|
||||
<None Include="Resources\baseline_image_white_48dp-4x-25pcAlpha.png" />
|
||||
<None Include="Resources\baseline_queue_white_48dp.png" />
|
||||
<None Include="Resources\separatorTest1.png" />
|
||||
<None Include="Resources\discordIcoColored.png" />
|
||||
<None Include="Resources\patreon256pxColored.png" />
|
||||
<None Include="Resources\baseline_create_white_18dp.png" />
|
||||
<None Include="Resources\baseline_create_white_18dp-semiTransparent.png" />
|
||||
<Content Include="flowframesIcoNew.ico" />
|
||||
<None Include="Resources\baseline_system_update_alt_white_48dp.png" />
|
||||
<None Include="Resources\baseline_system_update_alt_white_48dp1.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" />
|
||||
<Error Condition="!Exists('packages\7z.NET.1.0.3\build\7z.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\7z.NET.1.0.3\build\7z.NET.targets'))" />
|
||||
<Error Condition="!Exists('packages\Fody.6.3.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.3.0\build\Fody.targets'))" />
|
||||
</Target>
|
||||
<Import Project="packages\7z.NET.1.0.3\build\7z.NET.targets" Condition="Exists('packages\7z.NET.1.0.3\build\7z.NET.targets')" />
|
||||
<Import Project="packages\Fody.6.3.0\build\Fody.targets" Condition="Exists('packages\Fody.6.3.0\build\Fody.targets')" />
|
||||
|
||||
</Project>
|
||||
@@ -1,31 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30413.136
|
||||
VisualStudioVersion = 16.0.30907.101
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flowframes", "Flowframes.csproj", "{389E42DD-A163-49D7-9E0A-AE41090A07B3}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flowframes", "Flowframes.csproj", "{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Debug|x64.Build.0 = Debug|x64
|
||||
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Release|x64.ActiveCfg = Release|x64
|
||||
{389E42DD-A163-49D7-9E0A-AE41090A07B3}.Release|x64.Build.0 = Release|x64
|
||||
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {4622DEE4-C34E-4439-A743-7B534210FDFA}
|
||||
SolutionGuid = {62B981E7-6590-4960-BDF4-3439D25D3840}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="7z.NET" version="1.0.3" targetFramework="net472" />
|
||||
<package id="CircularProgressBar" version="2.8.0.16" targetFramework="net472" />
|
||||
<package id="Costura.Fody" version="4.1.0" targetFramework="net472" />
|
||||
<package id="Crc32.NET" version="1.2.0" targetFramework="net472" />
|
||||
<package id="CyotekTabList" version="2.0.0" targetFramework="net472" />
|
||||
<package id="diskdetector-net" version="0.3.2" targetFramework="net472" />
|
||||
<package id="Fody" version="6.3.0" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="HTAlt.Standart" version="0.1.6" targetFramework="net472" />
|
||||
<package id="HTAlt.WinForms" version="0.1.6" targetFramework="net472" />
|
||||
<package id="Magick.NET.Core" version="4.1.0" targetFramework="net472" />
|
||||
<package id="Magick.NET-Q16-AnyCPU" version="7.21.1" targetFramework="net472" />
|
||||
<package id="Microsoft-WindowsAPICodePack-Core" version="1.1.4" targetFramework="net472" />
|
||||
<package id="Microsoft-WindowsAPICodePack-Shell" version="1.1.4" targetFramework="net472" />
|
||||
<package id="NvAPIWrapper.Net" version="0.8.0.98" targetFramework="net472" />
|
||||
<package id="PagedControl" version="2.2.0" targetFramework="net472" />
|
||||
<package id="Standart.Hash.xxHash" version="3.1.0" targetFramework="net472" />
|
||||
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
|
||||
<package id="System.Data.HashFunction.Core" version="2.0.0" targetFramework="net472" />
|
||||
<package id="System.Data.HashFunction.Interfaces" version="2.0.0" targetFramework="net472" />
|
||||
<package id="System.Drawing.Common" version="5.0.0" targetFramework="net472" />
|
||||
<package id="System.Management" version="5.0.0" targetFramework="net472" />
|
||||
<package id="System.Memory" version="4.5.4" targetFramework="net472" />
|
||||
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
|
||||
<package id="System.Runtime.CompilerServices.Unsafe" version="4.7.1" targetFramework="net472" />
|
||||
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Security.Claims" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Security.Principal.Windows" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.5.3" targetFramework="net472" />
|
||||
<package id="TabControl" version="2.1.2" targetFramework="net472" />
|
||||
<package id="Win32Interop.Dwmapi" version="1.0.1" targetFramework="net472" />
|
||||
<package id="Win32Interop.Gdi32" version="1.0.1" targetFramework="net472" />
|
||||
<package id="Win32Interop.Kernel32" version="1.0.1" targetFramework="net472" />
|
||||
<package id="Win32Interop.User32" version="1.0.1" targetFramework="net472" />
|
||||
<package id="Win32Interop.Uxtheme" version="1.0.1" targetFramework="net472" />
|
||||
<package id="WindowsAPICodePack-Core" version="1.1.1" targetFramework="net472" />
|
||||
<package id="WindowsAPICodePack-Shell" version="1.1.1" targetFramework="net472" />
|
||||
<package id="WinFormAnimation" version="1.6.0.4" targetFramework="net472" />
|
||||
</packages>
|
||||
442
Code5/.gitignore
vendored
@@ -1,442 +0,0 @@
|
||||
## 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/
|
||||
[Ll]ogs/
|
||||
|
||||
# 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
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*[.json, .xml, .info]
|
||||
|
||||
# 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/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
##
|
||||
## Visual studio for Mac
|
||||
##
|
||||
|
||||
|
||||
# globs
|
||||
Makefile.in
|
||||
*.userprefs
|
||||
*.usertasks
|
||||
config.make
|
||||
config.status
|
||||
aclocal.m4
|
||||
install-sh
|
||||
autom4te.cache/
|
||||
*.tar.gz
|
||||
tarballs/
|
||||
test-results/
|
||||
|
||||
# Mac bundle stuff
|
||||
*.dmg
|
||||
*.app
|
||||
|
||||
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
##
|
||||
## Visual Studio Code
|
||||
##
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
@@ -1,29 +0,0 @@
|
||||
using Flowframes.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.Data
|
||||
{
|
||||
public struct AI
|
||||
{
|
||||
public string aiName;
|
||||
public string aiNameShort;
|
||||
public string friendlyName;
|
||||
public string description;
|
||||
public FlowPackage pkg;
|
||||
public bool supportsAnyExp;
|
||||
|
||||
public AI(string aiNameArg, string friendlyNameArg, string descArg, FlowPackage pkgArg, bool supportsAnyExpArg)
|
||||
{
|
||||
aiName = aiNameArg;
|
||||
aiNameShort = aiNameArg.Split(' ')[0].Split('_')[0];
|
||||
friendlyName = friendlyNameArg;
|
||||
description = descArg;
|
||||
pkg = pkgArg;
|
||||
supportsAnyExp = supportsAnyExpArg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.IO
|
||||
{
|
||||
public struct FlowPackage
|
||||
{
|
||||
public string friendlyName;
|
||||
public string fileName;
|
||||
public int downloadSizeMb;
|
||||
public string desc;
|
||||
|
||||
public FlowPackage(string friendlyNameStr, string fileNameStr, int downloadSizeMbInt, string description)
|
||||
{
|
||||
friendlyName = friendlyNameStr;
|
||||
fileName = fileNameStr;
|
||||
downloadSizeMb = downloadSizeMbInt;
|
||||
desc = description;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
using Flowframes.Media;
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.MiscUtils;
|
||||
using Flowframes.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes
|
||||
{
|
||||
public struct InterpSettings
|
||||
{
|
||||
public string inPath;
|
||||
public string outPath;
|
||||
public AI ai;
|
||||
public float inFps;
|
||||
public float outFps;
|
||||
public float interpFactor;
|
||||
public Interpolate.OutMode outMode;
|
||||
public string model;
|
||||
|
||||
public string tempFolder;
|
||||
public string framesFolder;
|
||||
public string interpFolder;
|
||||
public bool inputIsFrames;
|
||||
public string outFilename;
|
||||
public Size inputResolution;
|
||||
public Size scaledResolution;
|
||||
|
||||
public bool alpha;
|
||||
public bool stepByStep;
|
||||
|
||||
public InterpSettings(string inPathArg, string outPathArg, AI aiArg, float inFpsArg, int interpFactorArg, Interpolate.OutMode outModeArg, string modelArg)
|
||||
{
|
||||
inPath = inPathArg;
|
||||
outPath = outPathArg;
|
||||
ai = aiArg;
|
||||
inFps = inFpsArg;
|
||||
interpFactor = interpFactorArg;
|
||||
outFps = inFpsArg * interpFactorArg;
|
||||
outMode = outModeArg;
|
||||
model = modelArg;
|
||||
|
||||
alpha = false;
|
||||
stepByStep = false;
|
||||
|
||||
try
|
||||
{
|
||||
tempFolder = InterpolateUtils.GetTempFolderLoc(inPath, outPath);
|
||||
framesFolder = Path.Combine(tempFolder, Paths.framesDir);
|
||||
interpFolder = Path.Combine(tempFolder, Paths.interpDir);
|
||||
inputIsFrames = IOUtils.IsPathDirectory(inPath);
|
||||
outFilename = Path.Combine(outPath, Path.GetFileNameWithoutExtension(inPath) + IOUtils.GetExportSuffix(interpFactor, ai, model) + FFmpegUtils.GetExt(outMode));
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.Log("Tried to create InterpSettings struct without an inpath. Can't set tempFolder, framesFolder and interpFolder.", true);
|
||||
tempFolder = "";
|
||||
framesFolder = "";
|
||||
interpFolder = "";
|
||||
inputIsFrames = false;
|
||||
outFilename = "";
|
||||
}
|
||||
|
||||
inputResolution = new Size(0, 0);
|
||||
scaledResolution = new Size(0, 0);
|
||||
}
|
||||
|
||||
public InterpSettings (string serializedData)
|
||||
{
|
||||
inPath = "";
|
||||
outPath = "";
|
||||
ai = Networks.networks[0];
|
||||
inFps = 0;
|
||||
interpFactor = 0;
|
||||
outFps = 0;
|
||||
outMode = Interpolate.OutMode.VidMp4;
|
||||
model = "";
|
||||
alpha = false;
|
||||
stepByStep = false;
|
||||
inputResolution = new Size(0, 0);
|
||||
scaledResolution = new Size(0, 0);
|
||||
|
||||
Dictionary<string, string> entries = new Dictionary<string, string>();
|
||||
|
||||
foreach(string line in serializedData.SplitIntoLines())
|
||||
{
|
||||
if (line.Length < 3) continue;
|
||||
string[] keyValuePair = line.Split('|');
|
||||
entries.Add(keyValuePair[0], keyValuePair[1]);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, string> entry in entries)
|
||||
{
|
||||
switch (entry.Key)
|
||||
{
|
||||
case "INPATH": inPath = entry.Value; break;
|
||||
case "OUTPATH": outPath = entry.Value; break;
|
||||
case "AI": ai = Networks.GetAi(entry.Value); break;
|
||||
case "INFPS": inFps = float.Parse(entry.Value); break;
|
||||
case "OUTFPS": outFps = float.Parse(entry.Value); break;
|
||||
case "INTERPFACTOR": interpFactor = float.Parse(entry.Value); break;
|
||||
case "OUTMODE": outMode = (Interpolate.OutMode)Enum.Parse(typeof(Interpolate.OutMode), entry.Value); break;
|
||||
case "MODEL": model = entry.Value; break;
|
||||
case "INPUTRES": inputResolution = FormatUtils.ParseSize(entry.Value); break;
|
||||
case "OUTPUTRES": scaledResolution = FormatUtils.ParseSize(entry.Value); break;
|
||||
case "ALPHA": alpha = bool.Parse(entry.Value); break;
|
||||
case "STEPBYSTEP": stepByStep = bool.Parse(entry.Value); break;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
tempFolder = InterpolateUtils.GetTempFolderLoc(inPath, outPath);
|
||||
framesFolder = Path.Combine(tempFolder, Paths.framesDir);
|
||||
interpFolder = Path.Combine(tempFolder, Paths.interpDir);
|
||||
inputIsFrames = IOUtils.IsPathDirectory(inPath);
|
||||
outFilename = Path.Combine(outPath, Path.GetFileNameWithoutExtension(inPath) + IOUtils.GetExportSuffix(interpFactor, ai, model) + FFmpegUtils.GetExt(outMode));
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.Log("Tried to create InterpSettings struct without an inpath. Can't set tempFolder, framesFolder and interpFolder.", true);
|
||||
tempFolder = "";
|
||||
framesFolder = "";
|
||||
interpFolder = "";
|
||||
inputIsFrames = false;
|
||||
outFilename = "";
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdatePaths (string inPathArg, string outPathArg)
|
||||
{
|
||||
inPath = inPathArg;
|
||||
outPath = outPathArg;
|
||||
tempFolder = InterpolateUtils.GetTempFolderLoc(inPath, outPath);
|
||||
framesFolder = Path.Combine(tempFolder, Paths.framesDir);
|
||||
interpFolder = Path.Combine(tempFolder, Paths.interpDir);
|
||||
inputIsFrames = IOUtils.IsPathDirectory(inPath);
|
||||
outFilename = Path.Combine(outPath, Path.GetFileNameWithoutExtension(inPath) + IOUtils.GetExportSuffix(interpFactor, ai, model) + FFmpegUtils.GetExt(outMode));
|
||||
}
|
||||
|
||||
public async Task<Size> GetInputRes()
|
||||
{
|
||||
await RefreshResolutions();
|
||||
return inputResolution;
|
||||
}
|
||||
|
||||
public async Task<Size> GetScaledRes()
|
||||
{
|
||||
await RefreshResolutions();
|
||||
return scaledResolution;
|
||||
}
|
||||
|
||||
async Task RefreshResolutions ()
|
||||
{
|
||||
if (inputResolution.IsEmpty || scaledResolution.IsEmpty)
|
||||
{
|
||||
inputResolution = await IOUtils.GetVideoOrFramesRes(inPath);
|
||||
scaledResolution = InterpolateUtils.GetOutputResolution(inputResolution, false);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetTargetFrameCount(string overrideInputDir = "", float overrideFactor = -1)
|
||||
{
|
||||
if (framesFolder == null || !Directory.Exists(framesFolder))
|
||||
return 0;
|
||||
|
||||
string framesDir = (!string.IsNullOrWhiteSpace(overrideInputDir)) ? overrideInputDir : framesFolder;
|
||||
int frames = IOUtils.GetAmountOfFiles(framesDir, false, "*.png");
|
||||
float factor = (overrideFactor > 0) ? overrideFactor : interpFactor;
|
||||
int targetFrameCount = ((frames * factor) - (interpFactor - 1)).RoundToInt();
|
||||
return targetFrameCount;
|
||||
}
|
||||
|
||||
public void RefreshAlpha ()
|
||||
{
|
||||
try
|
||||
{
|
||||
bool alphaEnabled = Config.GetBool("enableAlpha", false);
|
||||
bool outputSupportsAlpha = (outMode == Interpolate.OutMode.ImgPng || outMode == Interpolate.OutMode.VidGif);
|
||||
string ext = inputIsFrames ? Path.GetExtension(IOUtils.GetFilesSorted(inPath).First()).ToLower() : Path.GetExtension(inPath).ToLower();
|
||||
alpha = (alphaEnabled && outputSupportsAlpha && (ext == ".gif" || ext == ".png" || ext == ".apng"));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("RefreshAlpha Error: " + e.Message, true);
|
||||
alpha = false;
|
||||
}
|
||||
}
|
||||
|
||||
public string Serialize ()
|
||||
{
|
||||
string s = $"INPATH|{inPath}\n";
|
||||
s += $"OUTPATH|{outPath}\n";
|
||||
s += $"AI|{ai.aiName}\n";
|
||||
s += $"INFPS|{inFps.ToStringDot()}\n";
|
||||
s += $"OUTFPS|{outFps.ToStringDot()}\n";
|
||||
s += $"INTERPFACTOR|{interpFactor}\n";
|
||||
s += $"OUTMODE|{outMode}\n";
|
||||
s += $"MODEL|{model}\n";
|
||||
s += $"INPUTRES|{inputResolution.Width}x{inputResolution.Height}\n";
|
||||
s += $"OUTPUTRES|{scaledResolution.Width}x{scaledResolution.Height}\n";
|
||||
s += $"ALPHA|{alpha}\n";
|
||||
s += $"STEPBYSTEP|{stepByStep}\n";
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using Flowframes.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Flowframes.Data
|
||||
{
|
||||
class Networks
|
||||
{
|
||||
public static AI rifeCuda = new AI("RIFE_CUDA", "RIFE", "CUDA/Pytorch Implementation of RIFE", Packages.rifeCuda, true);
|
||||
public static AI rifeNcnn = new AI("RIFE_NCNN", "RIFE (NCNN)", "Vulkan/NCNN Implementation of RIFE", Packages.rifeNcnn, false);
|
||||
public static AI dainNcnn = new AI("DAIN_NCNN", "DAIN (NCNN)", "Vulkan/NCNN Implementation of DAIN", Packages.dainNcnn, true);
|
||||
|
||||
public static List<AI> networks = new List<AI>();
|
||||
|
||||
public static void Init ()
|
||||
{
|
||||
networks.Clear();
|
||||
networks.Add(rifeCuda);
|
||||
networks.Add(rifeNcnn);
|
||||
networks.Add(dainNcnn);
|
||||
}
|
||||
|
||||
public static AI GetAi (string aiName)
|
||||
{
|
||||
foreach(AI ai in networks)
|
||||
{
|
||||
if (ai.aiName == aiName)
|
||||
return ai;
|
||||
}
|
||||
|
||||
return networks[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
|
||||
namespace Flowframes.IO
|
||||
{
|
||||
class Packages
|
||||
{
|
||||
public static FlowPackage dainNcnn = new FlowPackage("DAIN-NCNN (AMD/Nvidia)", "dain-ncnn.7z", 40, "NCNN/Vulkan implementation of DAIN. Very slow and VRAM-hungry.");
|
||||
//public static FlowPackage cainNcnn = new FlowPackage("CAIN-NCNN (AMD/Nvidia)", "cain-ncnn.7z", 75, "NCNN/Vulkan implementation of CAIN. About 8x faster than DAIN and very lightweight on VRAM.");
|
||||
public static FlowPackage rifeCuda = new FlowPackage("RIFE (Nvidia)", "rife-cuda.7z", 50, "Pytorch implementation of RIFE. Very fast (~2x CAIN, >16x DAIN) and not too VRAM-heavy.");
|
||||
public static FlowPackage rifeNcnn = new FlowPackage("RIFE-NCNN (AMD/Nvidia) [EXPERIMENTAL]", "rife-ncnn.7z", 25, "NCNN/Vulkan implementation of RIFE. Similar speed and VRAM usage as CAIN, but can have better quality.");
|
||||
//public static FlowPackage python = new FlowPackage("Python Runtime", "py.7z", 640, "Embedded Python runtime including Pytorch and all other dependencies. Install this if you don't have system Python.");
|
||||
public static FlowPackage audioVideo = new FlowPackage("Audio/Video Tools (Required)", "av.7z", 10, "Utilities for extracting frames, analysing videos, encoding videos and GIFs.");
|
||||
public static FlowPackage licenses = new FlowPackage("Licenses (Required)", "licenses.7z", 1, "License files for redistributed software.");
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.Data
|
||||
{
|
||||
class Padding
|
||||
{
|
||||
public const int inputFrames = 9;
|
||||
public const int inputFramesRenamed = 8;
|
||||
public const int interpFrames = 8;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Flowframes.IO
|
||||
{
|
||||
class Paths
|
||||
{
|
||||
public const string framesDir = "frames";
|
||||
public const string interpDir = "interp";
|
||||
public const string chunksDir = "vchunks";
|
||||
public const string resumeDir = "resumedata";
|
||||
public const string scenesDir = "scenes";
|
||||
|
||||
public const string alphaSuffix = "-a";
|
||||
public const string prevSuffix = "-previous";
|
||||
|
||||
public const string frameOrderPrefix = "frames";
|
||||
|
||||
public static string GetFrameOrderFilename(float factor)
|
||||
{
|
||||
return $"{frameOrderPrefix}-{factor.ToStringDot()}x.ini";
|
||||
}
|
||||
|
||||
public static string GetFrameOrderFilenameChunk (int from, int to)
|
||||
{
|
||||
return $"{frameOrderPrefix}-chunk-{from}-{to}.ini";
|
||||
}
|
||||
|
||||
public static string GetVerPath()
|
||||
{
|
||||
return Path.Combine(GetDataPath(), "ver.ini");
|
||||
}
|
||||
|
||||
public static string GetDataPath ()
|
||||
{
|
||||
string path = Path.Combine(IOUtils.GetExeDir(), "FlowframesData");
|
||||
Directory.CreateDirectory(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
public static string GetPkgPath()
|
||||
{
|
||||
string path = Path.Combine(GetDataPath(), "pkgs");
|
||||
Directory.CreateDirectory(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
public static string GetLogPath()
|
||||
{
|
||||
string path = Path.Combine(GetDataPath(), "logs");
|
||||
Directory.CreateDirectory(path);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.Data
|
||||
{
|
||||
public struct ResumeState
|
||||
{
|
||||
public bool autoEncode;
|
||||
public int interpolatedInputFrames;
|
||||
|
||||
public ResumeState (bool autoEncArg, int lastInterpInFrameArg)
|
||||
{
|
||||
autoEncode = autoEncArg;
|
||||
interpolatedInputFrames = lastInterpInFrameArg;
|
||||
}
|
||||
|
||||
public ResumeState(string serializedData)
|
||||
{
|
||||
autoEncode = false;
|
||||
interpolatedInputFrames = 0;
|
||||
|
||||
Dictionary<string, string> entries = new Dictionary<string, string>();
|
||||
|
||||
foreach (string line in serializedData.SplitIntoLines())
|
||||
{
|
||||
if (line.Length < 3) continue;
|
||||
string[] keyValuePair = line.Split('|');
|
||||
entries.Add(keyValuePair[0], keyValuePair[1]);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, string> entry in entries)
|
||||
{
|
||||
switch (entry.Key)
|
||||
{
|
||||
case "AUTOENC": autoEncode = bool.Parse(entry.Value); break;
|
||||
case "INTERPOLATEDINPUTFRAMES": interpolatedInputFrames = entry.Value.GetInt(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
string s = $"AUTOENC|{autoEncode}\n";
|
||||
|
||||
if (!autoEncode)
|
||||
{
|
||||
s += $"INTERPOLATEDINPUTFRAMES|{interpolatedInputFrames}";
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace Flowframes.Data
|
||||
{
|
||||
class SubtitleTrack
|
||||
{
|
||||
public int streamIndex;
|
||||
public string lang;
|
||||
public string langFriendly;
|
||||
public string encoding;
|
||||
|
||||
public SubtitleTrack (int streamNum, string langStr, string encodingStr)
|
||||
{
|
||||
streamIndex = streamNum;
|
||||
lang = langStr;
|
||||
langFriendly = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(langStr.ToLower());
|
||||
encoding = encodingStr.Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes
|
||||
{
|
||||
public static class ExtensionMethods
|
||||
{
|
||||
public static string TrimNumbers(this string s, bool allowDotComma = false)
|
||||
{
|
||||
if (!allowDotComma)
|
||||
s = Regex.Replace(s, "[^0-9]", "");
|
||||
else
|
||||
s = Regex.Replace(s, "[^.,0-9]", "");
|
||||
return s.Trim();
|
||||
}
|
||||
|
||||
public static int GetInt(this TextBox textbox)
|
||||
{
|
||||
return GetInt(textbox.Text);
|
||||
}
|
||||
|
||||
public static int GetInt(this ComboBox combobox)
|
||||
{
|
||||
return GetInt(combobox.Text);
|
||||
}
|
||||
|
||||
public static int GetInt(this string str)
|
||||
{
|
||||
if (str.Length < 1 || str == null)
|
||||
return 0;
|
||||
try { return int.Parse(str.TrimNumbers()); }
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Failed to parse \"" + str + "\" to int: " + e.Message, true);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetFloat(this TextBox textbox)
|
||||
{
|
||||
return GetFloat(textbox.Text);
|
||||
}
|
||||
|
||||
public static float GetFloat(this ComboBox combobox)
|
||||
{
|
||||
return GetFloat(combobox.Text);
|
||||
}
|
||||
|
||||
public static float GetFloat(this string str)
|
||||
{
|
||||
if (str.Length < 1 || str == null)
|
||||
return 0f;
|
||||
string num = str.TrimNumbers(true).Replace(",", ".");
|
||||
float value;
|
||||
float.TryParse(num, NumberStyles.Any, CultureInfo.InvariantCulture, out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static string Wrap(this string path, bool addSpaceFront = false, bool addSpaceEnd = false)
|
||||
{
|
||||
string s = "\"" + path + "\"";
|
||||
if (addSpaceFront)
|
||||
s = " " + s;
|
||||
if (addSpaceEnd)
|
||||
s = s + " ";
|
||||
return s;
|
||||
}
|
||||
|
||||
public static string GetParentDir(this string path)
|
||||
{
|
||||
return Directory.GetParent(path).FullName;
|
||||
}
|
||||
|
||||
public static int RoundToInt(this float f)
|
||||
{
|
||||
return (int)Math.Round(f);
|
||||
}
|
||||
|
||||
public static int Clamp(this int i, int min, int max)
|
||||
{
|
||||
if (i < min)
|
||||
i = min;
|
||||
if (i > max)
|
||||
i = max;
|
||||
return i;
|
||||
}
|
||||
|
||||
public static string[] SplitIntoLines(this string str)
|
||||
{
|
||||
return Regex.Split(str, "\r\n|\r|\n");
|
||||
}
|
||||
|
||||
public static string Trunc(this string inStr, int maxChars, bool addEllipsis = true)
|
||||
{
|
||||
string str = inStr.Length <= maxChars ? inStr : inStr.Substring(0, maxChars);
|
||||
if(addEllipsis && inStr.Length > maxChars)
|
||||
str += "…";
|
||||
return str;
|
||||
}
|
||||
|
||||
public static string StripBadChars(this string str)
|
||||
{
|
||||
string outStr = Regex.Replace(str, @"[^\u0020-\u007E]", string.Empty);
|
||||
outStr = outStr.Remove("(").Remove(")").Remove("[").Remove("]").Remove("{").Remove("}").Remove("%").Remove("'").Remove("~");
|
||||
return outStr;
|
||||
}
|
||||
|
||||
public static string StripNumbers(this string str)
|
||||
{
|
||||
return new string(str.Where(c => c != '-' && (c < '0' || c > '9')).ToArray());
|
||||
}
|
||||
|
||||
public static string Remove(this string str, string stringToRemove)
|
||||
{
|
||||
if (str == null || stringToRemove == null)
|
||||
return str;
|
||||
return str.Replace(stringToRemove, "");
|
||||
}
|
||||
|
||||
public static string TrimWhitespaces(this string str)
|
||||
{
|
||||
if (str == null) return str;
|
||||
var newString = new StringBuilder();
|
||||
bool previousIsWhitespace = false;
|
||||
for (int i = 0; i < str.Length; i++)
|
||||
{
|
||||
if (Char.IsWhiteSpace(str[i]))
|
||||
{
|
||||
if (previousIsWhitespace)
|
||||
continue;
|
||||
previousIsWhitespace = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
previousIsWhitespace = false;
|
||||
}
|
||||
newString.Append(str[i]);
|
||||
}
|
||||
return newString.ToString();
|
||||
}
|
||||
|
||||
public static string ReplaceLast (this string str, string stringToReplace, string replaceWith)
|
||||
{
|
||||
int place = str.LastIndexOf(stringToReplace);
|
||||
|
||||
if (place == -1)
|
||||
return str;
|
||||
|
||||
return str.Remove(place, stringToReplace.Length).Insert(place, replaceWith);
|
||||
}
|
||||
|
||||
public static string[] SplitBy (this string str, string splitBy)
|
||||
{
|
||||
return str.Split(new string[] { splitBy }, StringSplitOptions.None);
|
||||
}
|
||||
|
||||
public static string RemoveComments (this string str)
|
||||
{
|
||||
return str.Split('#')[0].SplitBy("//")[0];
|
||||
}
|
||||
|
||||
public static string FilenameSuffix(this string path, string suffix)
|
||||
{
|
||||
string filename = Path.ChangeExtension(path, null);
|
||||
string ext = Path.GetExtension(path);
|
||||
return filename + suffix + ext;
|
||||
}
|
||||
|
||||
public static string ToStringDot (this float f, string format = "")
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(format))
|
||||
return f.ToString().Replace(",", ".");
|
||||
else
|
||||
return f.ToString(format).Replace(",", ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 196 KiB |
@@ -1,50 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net5.0-windows</TargetFramework>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
|
||||
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
|
||||
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
|
||||
<ApplicationIcon>flowframesIcoNew.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CircularProgressBar" Version="2.8.0.16" />
|
||||
<PackageReference Include="Crc32.NET" Version="1.2.0" />
|
||||
<PackageReference Include="CyotekTabList" Version="2.2.0" />
|
||||
<PackageReference Include="diskdetector-net" Version="0.3.2" />
|
||||
<PackageReference Include="HTAlt.Standart" Version="0.1.6" />
|
||||
<PackageReference Include="HTAlt.WinForms" Version="0.1.6" />
|
||||
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.23.1" />
|
||||
<PackageReference Include="Magick.NET.Core" Version="6.1.0" />
|
||||
<PackageReference Include="NvAPIWrapper.Net" Version="0.8.1.101" />
|
||||
<PackageReference Include="Standart.Hash.xxHash" Version="3.1.0" />
|
||||
<PackageReference Include="System.Management" Version="5.0.0" />
|
||||
<PackageReference Include="WindowsAPICodePack-Core" Version="1.1.2" />
|
||||
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
|
||||
<PackageReference Include="WinFormAnimation" Version="1.6.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30907.101
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flowframes", "Flowframes.csproj", "{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A7E45FC0-5BE5-40FC-BCB6-48096F57AF73}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {62B981E7-6590-4960-BDF4-3439D25D3840}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,3 +0,0 @@
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<Costura />
|
||||
</Weavers>
|
||||
@@ -1,111 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
|
||||
<xs:element name="Weavers">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Costura" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="DisableCompression" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="DisableCleanup" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="LoadAtModuleInit" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="ExcludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Unmanaged64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="PreloadOrder" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="VerifyAssembly" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="GenerateXsd" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
1415
Code5/Form1.Designer.cs
generated
453
Code5/Form1.cs
@@ -1,453 +0,0 @@
|
||||
using Flowframes.Forms;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Magick;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.OS;
|
||||
using Flowframes.UI;
|
||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using HTAlt.WinForms;
|
||||
using Flowframes.Data;
|
||||
using Microsoft.WindowsAPICodePack.Taskbar;
|
||||
using System.Threading.Tasks;
|
||||
using Flowframes.MiscUtils;
|
||||
|
||||
namespace Flowframes
|
||||
{
|
||||
public partial class Form1 : Form
|
||||
{
|
||||
public bool initialized = false;
|
||||
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Form1_Load(object sender, EventArgs e)
|
||||
{
|
||||
CheckForIllegalCrossThreadCalls = false;
|
||||
AutoScaleMode = AutoScaleMode.None;
|
||||
Text = $"Flowframes {Updater.GetInstalledVer()}";
|
||||
|
||||
// Main Tab
|
||||
UIUtils.InitCombox(interpFactorCombox, 0);
|
||||
UIUtils.InitCombox(outModeCombox, 0);
|
||||
UIUtils.InitCombox(aiModel, 2);
|
||||
// Video Utils
|
||||
UIUtils.InitCombox(utilsLoopTimesCombox, 0);
|
||||
UIUtils.InitCombox(utilsSpeedCombox, 0);
|
||||
UIUtils.InitCombox(utilsConvCrf, 0);
|
||||
|
||||
Program.mainForm = this;
|
||||
Logger.textbox = logBox;
|
||||
|
||||
InitAis();
|
||||
InterpolateUtils.preview = previewPicturebox;
|
||||
|
||||
UpdateStepByStepControls(true);
|
||||
|
||||
Initialized();
|
||||
Checks();
|
||||
}
|
||||
|
||||
void Checks()
|
||||
{
|
||||
try
|
||||
{
|
||||
GetWebInfo.LoadNews(newsLabel);
|
||||
GetWebInfo.LoadPatronListCsv(patronsLabel);
|
||||
Updater.AsyncUpdateCheck();
|
||||
Python.CheckCompression();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Non-critical error while performing online checks. See logs for details.");
|
||||
Logger.Log(e.Message + "\n" + e.StackTrace, true);
|
||||
}
|
||||
}
|
||||
|
||||
public HTTabControl GetMainTabControl() { return mainTabControl; }
|
||||
|
||||
public bool IsInFocus() { return (ActiveForm == this); }
|
||||
|
||||
public void SetTab(string tabName)
|
||||
{
|
||||
foreach (TabPage tab in mainTabControl.TabPages)
|
||||
{
|
||||
if (tab.Text.ToLower() == tabName.ToLower())
|
||||
mainTabControl.SelectedTab = tab;
|
||||
}
|
||||
mainTabControl.Refresh();
|
||||
mainTabControl.Update();
|
||||
}
|
||||
|
||||
public InterpSettings GetCurrentSettings()
|
||||
{
|
||||
SetTab("interpolate");
|
||||
return new InterpSettings(inputTbox.Text.Trim(), outputTbox.Text.Trim(), GetAi(), fpsInTbox.GetFloat(), interpFactorCombox.GetInt(), GetOutMode(), GetModel());
|
||||
}
|
||||
|
||||
public void LoadBatchEntry(InterpSettings entry)
|
||||
{
|
||||
inputTbox.Text = entry.inPath;
|
||||
outputTbox.Text = entry.outPath;
|
||||
interpFactorCombox.Text = entry.interpFactor.ToString();
|
||||
aiCombox.SelectedIndex = Networks.networks.IndexOf(entry.ai);
|
||||
SetOutMode(entry.outMode);
|
||||
}
|
||||
|
||||
public void SetStatus(string str)
|
||||
{
|
||||
Logger.Log(str, true);
|
||||
statusLabel.Text = str;
|
||||
}
|
||||
|
||||
public void SetProgress(int percent)
|
||||
{
|
||||
percent = percent.Clamp(0, 100);
|
||||
TaskbarManager.Instance.SetProgressValue(percent, 100);
|
||||
longProgBar.Value = percent;
|
||||
longProgBar.Refresh();
|
||||
}
|
||||
|
||||
public Size currInRes;
|
||||
public float currInFps;
|
||||
public int currInFrames;
|
||||
public long currInDuration;
|
||||
public void UpdateInputInfo ()
|
||||
{
|
||||
string str = $"Resolution: {(!currInRes.IsEmpty ? $"{currInRes.Width}x{currInRes.Height}" : "Unknown")} - ";
|
||||
str += $"Framerate: {(currInFps > 0f ? $"{currInFps.ToStringDot()} FPS" : "Unknown")} - ";
|
||||
str += $"Frame Count: {(currInFrames > 0 ? $"{currInFrames}" : "Unknown")} - ";
|
||||
str += $"Duration: {(currInDuration > 0 ? $"{FormatUtils.MsToTimestamp(currInDuration)}" : "Unknown")}";
|
||||
inputInfo.Text = str;
|
||||
}
|
||||
|
||||
public void ResetInputInfo ()
|
||||
{
|
||||
currInRes = new Size();
|
||||
currInFps = 0;
|
||||
currInFrames = 0;
|
||||
currInDuration = 0;
|
||||
UpdateInputInfo();
|
||||
}
|
||||
|
||||
void InitAis()
|
||||
{
|
||||
foreach (AI ai in Networks.networks)
|
||||
aiCombox.Items.Add(ai.friendlyName + " - " + ai.description);
|
||||
ConfigParser.LoadComboxIndex(aiCombox);
|
||||
}
|
||||
|
||||
public void Initialized()
|
||||
{
|
||||
initialized = true;
|
||||
runBtn.Enabled = true;
|
||||
}
|
||||
|
||||
private void browseInputBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
|
||||
dialog.InitialDirectory = inputTbox.Text.Trim();
|
||||
dialog.IsFolderPicker = true;
|
||||
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
|
||||
DragDropHandler(new string[] { dialog.FileName });
|
||||
}
|
||||
|
||||
private void browseInputFileBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
|
||||
dialog.InitialDirectory = inputTbox.Text.Trim();
|
||||
dialog.IsFolderPicker = false;
|
||||
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
|
||||
DragDropHandler(new string[] { dialog.FileName });
|
||||
}
|
||||
|
||||
private void browseOutBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
|
||||
dialog.InitialDirectory = inputTbox.Text.Trim();
|
||||
dialog.IsFolderPicker = true;
|
||||
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
|
||||
outputTbox.Text = dialog.FileName;
|
||||
}
|
||||
|
||||
public void runBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!BatchProcessing.busy) // Don't load values from gui if batch processing is used
|
||||
Interpolate.current = GetCurrentSettings();
|
||||
|
||||
Interpolate.Start();
|
||||
}
|
||||
|
||||
public string GetModel()
|
||||
{
|
||||
return aiModel.Text.Split('-')[0].Remove(" ").Remove(".");
|
||||
}
|
||||
|
||||
Interpolate.OutMode GetOutMode()
|
||||
{
|
||||
Interpolate.OutMode outMode = Interpolate.OutMode.VidMp4;
|
||||
if (outModeCombox.Text.ToLower().Contains("mkv")) outMode = Interpolate.OutMode.VidMkv;
|
||||
if (outModeCombox.Text.ToLower().Contains("webm")) outMode = Interpolate.OutMode.VidWebm;
|
||||
if (outModeCombox.Text.ToLower().Contains("prores")) outMode = Interpolate.OutMode.VidProRes;
|
||||
if (outModeCombox.Text.ToLower().Contains("avi")) outMode = Interpolate.OutMode.VidAvi;
|
||||
if (outModeCombox.Text.ToLower().Contains("gif")) outMode = Interpolate.OutMode.VidGif;
|
||||
if (outModeCombox.Text.ToLower().Contains("image")) outMode = Interpolate.OutMode.ImgPng;
|
||||
return outMode;
|
||||
}
|
||||
|
||||
public void SetOutMode(Interpolate.OutMode mode)
|
||||
{
|
||||
int theIndex = 0;
|
||||
for(int i = 0; i < outModeCombox.Items.Count; i++)
|
||||
{
|
||||
string currentItem = outModeCombox.Items[i].ToString().ToLower();
|
||||
if (mode == Interpolate.OutMode.VidMkv && currentItem.Contains("mkv")) theIndex = i;
|
||||
if (mode == Interpolate.OutMode.VidWebm && currentItem.Contains("webm")) theIndex = i;
|
||||
if (mode == Interpolate.OutMode.VidProRes && currentItem.Contains("prores")) theIndex = i;
|
||||
if (mode == Interpolate.OutMode.VidAvi && currentItem.Contains("avi")) theIndex = i;
|
||||
if (mode == Interpolate.OutMode.VidGif && currentItem.Contains("gif")) theIndex = i;
|
||||
if (mode == Interpolate.OutMode.ImgPng && currentItem.Contains("image")) theIndex = i;
|
||||
}
|
||||
outModeCombox.SelectedIndex = theIndex;
|
||||
}
|
||||
|
||||
AI GetAi()
|
||||
{
|
||||
return Networks.networks[aiCombox.SelectedIndex];
|
||||
}
|
||||
|
||||
void inputTbox_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Copy; }
|
||||
|
||||
private void inputTbox_DragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
DragDropHandler((string[])e.Data.GetData(DataFormats.FileDrop));
|
||||
}
|
||||
|
||||
void outputTbox_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Copy; }
|
||||
|
||||
private void outputTbox_DragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
if (Program.busy) return;
|
||||
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
outputTbox.Text = files[0];
|
||||
}
|
||||
|
||||
private void fpsInTbox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
fpsInTbox.Text = fpsInTbox.Text.TrimNumbers(true);
|
||||
UpdateOutputFPS();
|
||||
}
|
||||
|
||||
public void UpdateOutputFPS()
|
||||
{
|
||||
float fpsOut = fpsInTbox.GetFloat() * interpFactorCombox.GetFloat();
|
||||
fpsOutTbox.Text = fpsOut.ToString();
|
||||
}
|
||||
|
||||
private void interpFactorCombox_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
UpdateOutputFPS();
|
||||
int guiInterpFactor = interpFactorCombox.GetInt();
|
||||
if (!initialized)
|
||||
return;
|
||||
string aiName = GetAi().aiName.Replace("_", "-");
|
||||
if (!Program.busy && guiInterpFactor > 2 && !GetAi().supportsAnyExp && Config.GetInt("autoEncMode") > 0 && !Logger.GetLastLine().Contains(aiName))
|
||||
Logger.Log($"Warning: {aiName} doesn't natively support 4x/8x and will run multiple times for {guiInterpFactor}x. Auto-Encode will only work on the last run.");
|
||||
}
|
||||
|
||||
public void SetWorking(bool state, bool allowCancel = true)
|
||||
{
|
||||
Logger.Log($"SetWorking({state})", true);
|
||||
SetProgress(-1);
|
||||
Control[] controlsToDisable = new Control[] { runBtn, runStepBtn, stepSelector, settingsBtn };
|
||||
Control[] controlsToHide = new Control[] { runBtn, runStepBtn, stepSelector };
|
||||
progressCircle.Visible = state;
|
||||
cancelBtn.Visible = state;
|
||||
foreach (Control c in controlsToDisable)
|
||||
c.Enabled = !state;
|
||||
foreach (Control c in controlsToHide)
|
||||
c.Visible = !state;
|
||||
cancelBtn.Enabled = allowCancel;
|
||||
Program.busy = state;
|
||||
Program.mainForm.UpdateStepByStepControls(false);
|
||||
}
|
||||
|
||||
string lastAiComboxStr = "";
|
||||
private void aiCombox_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(aiCombox.Text) || aiCombox.Text == lastAiComboxStr) return;
|
||||
lastAiComboxStr = aiCombox.Text;
|
||||
aiModel = UIUtils.FillAiModelsCombox(aiModel, GetAi());
|
||||
if(initialized)
|
||||
ConfigParser.SaveComboxIndex(aiCombox);
|
||||
interpFactorCombox_SelectedIndexChanged(null, null);
|
||||
}
|
||||
|
||||
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
Logger.Log("Closing main form.", true);
|
||||
}
|
||||
|
||||
private async void debugExtractFramesBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
await UtilsTab.ExtractVideo(inputTbox.Text.Trim(), utilsExtractAudioCbox.Checked);
|
||||
}
|
||||
|
||||
private void licenseBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
Process.Start("explorer.exe", Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.licenses.fileName)));
|
||||
}
|
||||
|
||||
private async void utilsLoopVidBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
await UtilsTab.LoopVideo(inputTbox.Text.Trim(), utilsLoopTimesCombox);
|
||||
}
|
||||
|
||||
private async void utilsChangeSpeedBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
await UtilsTab.ChangeSpeed(inputTbox.Text.Trim(), utilsSpeedCombox);
|
||||
}
|
||||
|
||||
private void Form1_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Copy; }
|
||||
|
||||
private void Form1_DragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
DragDropHandler((string[])e.Data.GetData(DataFormats.FileDrop));
|
||||
}
|
||||
|
||||
public void DragDropHandler(string[] files)
|
||||
{
|
||||
if (Program.busy) return;
|
||||
|
||||
if (files.Length > 1)
|
||||
{
|
||||
queueBtn_Click(null, null);
|
||||
if (BatchProcessing.currentBatchForm != null)
|
||||
BatchProcessing.currentBatchForm.LoadDroppedPaths(files);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetTab("interpolation");
|
||||
Logger.Log("Selected video/directory: " + Path.GetFileName(files[0]));
|
||||
inputTbox.Text = files[0];
|
||||
|
||||
bool resume = (IOUtils.GetAmountOfFiles(Path.Combine(files[0], Paths.resumeDir), true) > 0);
|
||||
ResumeUtils.resumeNextRun = resume;
|
||||
|
||||
if (resume)
|
||||
ResumeUtils.LoadTempFolder(files[0]);
|
||||
|
||||
MainUiFunctions.InitInput(outputTbox, inputTbox, fpsInTbox);
|
||||
}
|
||||
}
|
||||
|
||||
private async void utilsConvertMp4Btn_Click(object sender, EventArgs e)
|
||||
{
|
||||
await UtilsTab.Convert(inputTbox.Text.Trim(), utilsConvCrf);
|
||||
}
|
||||
|
||||
private void utilsDedupBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
UtilsTab.Dedupe(inputTbox.Text.Trim(), false);
|
||||
}
|
||||
|
||||
private void utilsDedupTestBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
UtilsTab.Dedupe(inputTbox.Text.Trim(), true);
|
||||
}
|
||||
|
||||
private void cancelBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetTab("interpolation");
|
||||
Interpolate.Cancel();
|
||||
}
|
||||
|
||||
private void discordBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
Process.Start("https://discord.gg/eJHD2NSJRe");
|
||||
}
|
||||
|
||||
private void paypalBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
Process.Start("https://www.paypal.com/paypalme/nmkd/10");
|
||||
}
|
||||
|
||||
private void patreonBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
Process.Start("https://patreon.com/n00mkrad");
|
||||
}
|
||||
|
||||
private void settingsBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
new SettingsForm().ShowDialog();
|
||||
}
|
||||
|
||||
private void queueBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (BatchProcessing.currentBatchForm != null)
|
||||
{
|
||||
BatchProcessing.currentBatchForm.WindowState = FormWindowState.Normal;
|
||||
BatchProcessing.currentBatchForm.BringToFront();
|
||||
}
|
||||
else
|
||||
{
|
||||
new BatchForm().Show();
|
||||
}
|
||||
}
|
||||
|
||||
private void previewPicturebox_MouseClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (InterpolateUtils.bigPreviewForm == null)
|
||||
{
|
||||
InterpolateUtils.bigPreviewForm = new BigPreviewForm();
|
||||
InterpolateUtils.bigPreviewForm.Show();
|
||||
InterpolateUtils.bigPreviewForm.SetImage(previewPicturebox.Image);
|
||||
}
|
||||
}
|
||||
|
||||
private async void updateBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
new UpdaterForm().ShowDialog();
|
||||
}
|
||||
|
||||
private void welcomeLabel2_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetTab("interpolation");
|
||||
}
|
||||
|
||||
public void UpdateStepByStepControls(bool settingsMayHaveChanged)
|
||||
{
|
||||
if (settingsMayHaveChanged)
|
||||
{
|
||||
stepSelector.Items.Clear();
|
||||
if (Config.GetBool("scnDetect"))
|
||||
stepSelector.Items.AddRange(new string[] { "1) Extract Scene Changes", "2) Import/Extract Frames", "3) Run Interpolation", "4) Export", "5) Cleanup & Reset" });
|
||||
else
|
||||
stepSelector.Items.AddRange(new string[] { "1) Import/Extract Frames", "2) Run Interpolation", "3) Export", "4) Cleanup & Reset" });
|
||||
stepSelector.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
bool stepByStep = Config.GetInt("processingMode") == 1;
|
||||
runBtn.Visible = !stepByStep && !Program.busy;
|
||||
}
|
||||
|
||||
private async void runStepBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetTab("interpolate");
|
||||
await InterpolateSteps.Run(stepSelector.Text);
|
||||
}
|
||||
|
||||
private void mainTabControl_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!initialized) return;
|
||||
aiCombox_SelectedIndexChanged(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
2465
Code5/Form1.resx
226
Code5/Forms/BatchForm.Designer.cs
generated
@@ -1,226 +0,0 @@
|
||||
namespace Flowframes.Forms
|
||||
{
|
||||
partial class BatchForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BatchForm));
|
||||
this.titleLabel = new System.Windows.Forms.Label();
|
||||
this.stopBtn = new System.Windows.Forms.Button();
|
||||
this.runBtn = new System.Windows.Forms.Button();
|
||||
this.addToQueue = new System.Windows.Forms.Button();
|
||||
this.forceStopBtn = new System.Windows.Forms.Button();
|
||||
this.clearBtn = new System.Windows.Forms.Button();
|
||||
this.taskList = new System.Windows.Forms.ListBox();
|
||||
this.clearSelectedBtn = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.panel1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// titleLabel
|
||||
//
|
||||
this.titleLabel.AutoSize = true;
|
||||
this.titleLabel.Font = new System.Drawing.Font("Yu Gothic UI", 21.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.titleLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.titleLabel.Location = new System.Drawing.Point(12, 9);
|
||||
this.titleLabel.Margin = new System.Windows.Forms.Padding(3, 0, 3, 10);
|
||||
this.titleLabel.Name = "titleLabel";
|
||||
this.titleLabel.Size = new System.Drawing.Size(323, 40);
|
||||
this.titleLabel.TabIndex = 1;
|
||||
this.titleLabel.Text = "Batch Processing Queue";
|
||||
//
|
||||
// stopBtn
|
||||
//
|
||||
this.stopBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.stopBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
|
||||
this.stopBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.stopBtn.ForeColor = System.Drawing.Color.White;
|
||||
this.stopBtn.Location = new System.Drawing.Point(682, 351);
|
||||
this.stopBtn.Name = "stopBtn";
|
||||
this.stopBtn.Size = new System.Drawing.Size(250, 40);
|
||||
this.stopBtn.TabIndex = 35;
|
||||
this.stopBtn.Text = "Stop After Current Task";
|
||||
this.stopBtn.UseVisualStyleBackColor = false;
|
||||
this.stopBtn.Visible = false;
|
||||
this.stopBtn.Click += new System.EventHandler(this.stopBtn_Click);
|
||||
//
|
||||
// runBtn
|
||||
//
|
||||
this.runBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.runBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
|
||||
this.runBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.runBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.runBtn.ForeColor = System.Drawing.Color.White;
|
||||
this.runBtn.Location = new System.Drawing.Point(682, 443);
|
||||
this.runBtn.Name = "runBtn";
|
||||
this.runBtn.Size = new System.Drawing.Size(250, 40);
|
||||
this.runBtn.TabIndex = 36;
|
||||
this.runBtn.Text = "Start";
|
||||
this.runBtn.UseVisualStyleBackColor = false;
|
||||
this.runBtn.Click += new System.EventHandler(this.runBtn_Click);
|
||||
//
|
||||
// addToQueue
|
||||
//
|
||||
this.addToQueue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.addToQueue.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
|
||||
this.addToQueue.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.addToQueue.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.addToQueue.ForeColor = System.Drawing.Color.White;
|
||||
this.addToQueue.Location = new System.Drawing.Point(682, 65);
|
||||
this.addToQueue.Name = "addToQueue";
|
||||
this.addToQueue.Size = new System.Drawing.Size(250, 40);
|
||||
this.addToQueue.TabIndex = 39;
|
||||
this.addToQueue.Text = "Add Current Configuration To Queue";
|
||||
this.addToQueue.UseVisualStyleBackColor = false;
|
||||
this.addToQueue.Click += new System.EventHandler(this.addToQueue_Click);
|
||||
//
|
||||
// forceStopBtn
|
||||
//
|
||||
this.forceStopBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.forceStopBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
|
||||
this.forceStopBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.forceStopBtn.ForeColor = System.Drawing.Color.White;
|
||||
this.forceStopBtn.Location = new System.Drawing.Point(682, 397);
|
||||
this.forceStopBtn.Name = "forceStopBtn";
|
||||
this.forceStopBtn.Size = new System.Drawing.Size(250, 40);
|
||||
this.forceStopBtn.TabIndex = 40;
|
||||
this.forceStopBtn.Text = "Force Stop Now";
|
||||
this.forceStopBtn.UseVisualStyleBackColor = false;
|
||||
this.forceStopBtn.Visible = false;
|
||||
this.forceStopBtn.Click += new System.EventHandler(this.forceStopBtn_Click);
|
||||
//
|
||||
// clearBtn
|
||||
//
|
||||
this.clearBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.clearBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
|
||||
this.clearBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.clearBtn.ForeColor = System.Drawing.Color.White;
|
||||
this.clearBtn.Location = new System.Drawing.Point(682, 157);
|
||||
this.clearBtn.Name = "clearBtn";
|
||||
this.clearBtn.Size = new System.Drawing.Size(250, 40);
|
||||
this.clearBtn.TabIndex = 41;
|
||||
this.clearBtn.Text = "Clear All Queue Entries";
|
||||
this.clearBtn.UseVisualStyleBackColor = false;
|
||||
this.clearBtn.Click += new System.EventHandler(this.clearBtn_Click);
|
||||
//
|
||||
// taskList
|
||||
//
|
||||
this.taskList.AllowDrop = true;
|
||||
this.taskList.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
|
||||
this.taskList.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.taskList.ForeColor = System.Drawing.Color.White;
|
||||
this.taskList.FormattingEnabled = true;
|
||||
this.taskList.ItemHeight = 18;
|
||||
this.taskList.Location = new System.Drawing.Point(12, 65);
|
||||
this.taskList.Name = "taskList";
|
||||
this.taskList.Size = new System.Drawing.Size(664, 418);
|
||||
this.taskList.TabIndex = 43;
|
||||
this.taskList.SelectedIndexChanged += new System.EventHandler(this.taskList_SelectedIndexChanged);
|
||||
this.taskList.DragDrop += new System.Windows.Forms.DragEventHandler(this.taskList_DragDrop);
|
||||
this.taskList.DragEnter += new System.Windows.Forms.DragEventHandler(this.taskList_DragEnter);
|
||||
//
|
||||
// clearSelectedBtn
|
||||
//
|
||||
this.clearSelectedBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.clearSelectedBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
|
||||
this.clearSelectedBtn.Enabled = false;
|
||||
this.clearSelectedBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.clearSelectedBtn.ForeColor = System.Drawing.Color.White;
|
||||
this.clearSelectedBtn.Location = new System.Drawing.Point(682, 111);
|
||||
this.clearSelectedBtn.Name = "clearSelectedBtn";
|
||||
this.clearSelectedBtn.Size = new System.Drawing.Size(250, 40);
|
||||
this.clearSelectedBtn.TabIndex = 44;
|
||||
this.clearSelectedBtn.Text = "Clear Selected Queue Entry";
|
||||
this.clearSelectedBtn.UseVisualStyleBackColor = false;
|
||||
this.clearSelectedBtn.Click += new System.EventHandler(this.clearSelectedBtn_Click);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.ForeColor = System.Drawing.Color.White;
|
||||
this.label1.Location = new System.Drawing.Point(6, 6);
|
||||
this.label1.Margin = new System.Windows.Forms.Padding(6);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(238, 111);
|
||||
this.label1.TabIndex = 45;
|
||||
this.label1.Text = "Tip:\r\nYou can also drag and drop multiple videos into the list.\r\nThey will be add" +
|
||||
"ed to the queue using the interpolation settings set in the GUI.";
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
this.panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
|
||||
this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.panel1.Controls.Add(this.label1);
|
||||
this.panel1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.panel1.Location = new System.Drawing.Point(682, 203);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(250, 142);
|
||||
this.panel1.TabIndex = 46;
|
||||
//
|
||||
// BatchForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
|
||||
this.ClientSize = new System.Drawing.Size(944, 501);
|
||||
this.Controls.Add(this.panel1);
|
||||
this.Controls.Add(this.clearSelectedBtn);
|
||||
this.Controls.Add(this.taskList);
|
||||
this.Controls.Add(this.clearBtn);
|
||||
this.Controls.Add(this.forceStopBtn);
|
||||
this.Controls.Add(this.addToQueue);
|
||||
this.Controls.Add(this.runBtn);
|
||||
this.Controls.Add(this.stopBtn);
|
||||
this.Controls.Add(this.titleLabel);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.Name = "BatchForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Batch Processing";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BatchForm_FormClosing);
|
||||
this.Load += new System.EventHandler(this.BatchForm_Load);
|
||||
this.panel1.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label titleLabel;
|
||||
private System.Windows.Forms.Button stopBtn;
|
||||
private System.Windows.Forms.Button runBtn;
|
||||
private System.Windows.Forms.Button addToQueue;
|
||||
private System.Windows.Forms.Button forceStopBtn;
|
||||
private System.Windows.Forms.Button clearBtn;
|
||||
private System.Windows.Forms.ListBox taskList;
|
||||
private System.Windows.Forms.Button clearSelectedBtn;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Main;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.Forms
|
||||
{
|
||||
public partial class BatchForm : Form
|
||||
{
|
||||
public BatchForm()
|
||||
{
|
||||
AutoScaleMode = AutoScaleMode.None;
|
||||
InitializeComponent();
|
||||
BatchProcessing.currentBatchForm = this;
|
||||
}
|
||||
|
||||
private void addToQueue_Click(object sender, EventArgs e)
|
||||
{
|
||||
Program.batchQueue.Enqueue(Program.mainForm.GetCurrentSettings());
|
||||
RefreshGui();
|
||||
}
|
||||
|
||||
public void RefreshGui ()
|
||||
{
|
||||
taskList.Items.Clear();
|
||||
string nl = Environment.NewLine;
|
||||
for (int i = 0; i < Program.batchQueue.Count; i++)
|
||||
{
|
||||
InterpSettings entry = Program.batchQueue.ElementAt(i);
|
||||
string niceOutMode = entry.outMode.ToString().ToUpper().Replace("VID", "").Replace("IMG", "");
|
||||
string str = $"#{i}: {Path.GetFileName(entry.inPath).Trunc(45)} - {entry.inFps} FPS => {entry.interpFactor}x{nl} {entry.ai.aiNameShort} => {niceOutMode}";
|
||||
taskList.Items.Add(str);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetWorking (bool working)
|
||||
{
|
||||
runBtn.Enabled = !working;
|
||||
addToQueue.Enabled = !working;
|
||||
stopBtn.Visible = working;
|
||||
forceStopBtn.Visible = working;
|
||||
stopBtn.Enabled = working;
|
||||
}
|
||||
|
||||
private void BatchForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
SetWorking(BatchProcessing.busy);
|
||||
RefreshGui();
|
||||
}
|
||||
|
||||
private void runBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
stopBtn.Enabled = true;
|
||||
BatchProcessing.Start();
|
||||
//WindowState = FormWindowState.Minimized;
|
||||
Program.mainForm.WindowState = FormWindowState.Normal;
|
||||
Program.mainForm.BringToFront();
|
||||
}
|
||||
|
||||
private void clearBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
Program.batchQueue.Clear();
|
||||
RefreshGui();
|
||||
}
|
||||
|
||||
private void stopBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
stopBtn.Enabled = false;
|
||||
BatchProcessing.stopped = true;
|
||||
}
|
||||
|
||||
private void forceStopBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
Interpolate.Cancel("Force stopped by user.");
|
||||
BatchProcessing.stopped = true;
|
||||
}
|
||||
|
||||
private void BatchForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
BatchProcessing.currentBatchForm = null;
|
||||
}
|
||||
|
||||
private void clearSelectedBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (taskList.SelectedItem == null) return;
|
||||
|
||||
Queue<InterpSettings> temp = new Queue<InterpSettings>();
|
||||
|
||||
for(int i = 0; i < Program.batchQueue.Count; i++)
|
||||
{
|
||||
if (i != taskList.SelectedIndex)
|
||||
temp.Enqueue(Program.batchQueue.ElementAt(i));
|
||||
}
|
||||
|
||||
Program.batchQueue = temp;
|
||||
|
||||
RefreshGui();
|
||||
}
|
||||
|
||||
private void taskList_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
clearSelectedBtn.Enabled = taskList.SelectedItem != null;
|
||||
}
|
||||
|
||||
private void taskList_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Copy; }
|
||||
|
||||
private async void taskList_DragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
string[] droppedPaths = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
await LoadDroppedPaths(droppedPaths);
|
||||
}
|
||||
|
||||
public async Task LoadDroppedPaths (string[] droppedPaths)
|
||||
{
|
||||
foreach (string path in droppedPaths)
|
||||
{
|
||||
Logger.Log($"Dropped file: '{path}'", true);
|
||||
string frame1 = Path.Combine(path, "00000001.png");
|
||||
if (IOUtils.IsPathDirectory(path) && !File.Exists(frame1))
|
||||
{
|
||||
InterpolateUtils.ShowMessage($"Can't find frames in this folder:\n\n{frame1} does not exist.", "Error");
|
||||
continue;
|
||||
}
|
||||
|
||||
InterpSettings current = Program.mainForm.GetCurrentSettings();
|
||||
current.UpdatePaths(path, path.GetParentDir());
|
||||
current.inFps = await GetFramerate(path);
|
||||
current.outFps = current.inFps * current.interpFactor;
|
||||
Program.batchQueue.Enqueue(current);
|
||||
RefreshGui();
|
||||
await Task.Delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
async Task<float> GetFramerate (string path)
|
||||
{
|
||||
float fps = Interpolate.current.inFps;
|
||||
float fpsFromFile = await IOUtils.GetFpsFolderOrVideo(path);
|
||||
if (fpsFromFile > 0)
|
||||
return fpsFromFile;
|
||||
|
||||
return fps;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
Code5/Forms/BigPreviewForm.Designer.cs
generated
@@ -1,70 +0,0 @@
|
||||
namespace Flowframes.Forms
|
||||
{
|
||||
partial class BigPreviewForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BigPreviewForm));
|
||||
this.picBox = new System.Windows.Forms.PictureBox();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picBox)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// picBox
|
||||
//
|
||||
this.picBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.picBox.Image = global::Flowframes.Properties.Resources.baseline_image_white_48dp_4x_25pcAlpha;
|
||||
this.picBox.Location = new System.Drawing.Point(0, 0);
|
||||
this.picBox.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.picBox.Name = "picBox";
|
||||
this.picBox.Size = new System.Drawing.Size(704, 601);
|
||||
this.picBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.picBox.TabIndex = 0;
|
||||
this.picBox.TabStop = false;
|
||||
//
|
||||
// BigPreviewForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
|
||||
this.ClientSize = new System.Drawing.Size(704, 601);
|
||||
this.Controls.Add(this.picBox);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Name = "BigPreviewForm";
|
||||
this.Text = "Resizable Preview";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BigPreviewForm_FormClosing);
|
||||
this.Load += new System.EventHandler(this.BigPreviewForm_Load);
|
||||
((System.ComponentModel.ISupportInitialize)(this.picBox)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.PictureBox picBox;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using Flowframes.Main;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.Forms
|
||||
{
|
||||
public partial class BigPreviewForm : Form
|
||||
{
|
||||
public BigPreviewForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void BigPreviewForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SetImage (Image img)
|
||||
{
|
||||
picBox.Image = img;
|
||||
}
|
||||
|
||||
private void BigPreviewForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
InterpolateUtils.bigPreviewForm = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
2062
Code5/Forms/SettingsForm.Designer.cs
generated
@@ -1,199 +0,0 @@
|
||||
using Flowframes.IO;
|
||||
using Flowframes.MiscUtils;
|
||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.Forms
|
||||
{
|
||||
public partial class SettingsForm : Form
|
||||
{
|
||||
bool initialized = false;
|
||||
|
||||
public SettingsForm()
|
||||
{
|
||||
AutoScaleMode = AutoScaleMode.None;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void SettingsForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
LoadSettings();
|
||||
initialized = true;
|
||||
CheckModelCacheSize();
|
||||
}
|
||||
|
||||
public async Task CheckModelCacheSize ()
|
||||
{
|
||||
long modelFoldersBytes = 0;
|
||||
|
||||
foreach (string modelFolder in ModelDownloader.GetAllModelFolders())
|
||||
modelFoldersBytes += IOUtils.GetDirSize(modelFolder, true);
|
||||
|
||||
if (modelFoldersBytes > 1024 * 1024)
|
||||
clearModelCacheBtn.Text = $"Clear Model Cache ({FormatUtils.Bytes(modelFoldersBytes)})";
|
||||
else
|
||||
clearModelCacheBtn.Enabled = false;
|
||||
}
|
||||
|
||||
private void SettingsForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
SaveSettings();
|
||||
Program.mainForm.UpdateStepByStepControls(true);
|
||||
}
|
||||
|
||||
void SaveSettings ()
|
||||
{
|
||||
// Clamp...
|
||||
h264Crf.Text = h264Crf.GetInt().Clamp(0, 51).ToString();
|
||||
h265Crf.Text = h265Crf.GetInt().Clamp(0, 51).ToString();
|
||||
vp9Crf.Text = vp9Crf.GetInt().Clamp(0, 63).ToString();
|
||||
// Remove spaces...
|
||||
torchGpus.Text = torchGpus.Text.Replace(" ", "");
|
||||
ncnnGpus.Text = ncnnGpus.Text.Replace(" ", "");
|
||||
|
||||
// General
|
||||
ConfigParser.SaveComboxIndex(processingMode);
|
||||
ConfigParser.SaveGuiElement(maxVidHeight, ConfigParser.StringMode.Int);
|
||||
ConfigParser.SaveGuiElement(enableAlpha);
|
||||
ConfigParser.SaveComboxIndex(tempFolderLoc);
|
||||
ConfigParser.SaveGuiElement(keepTempFolder);
|
||||
ConfigParser.SaveGuiElement(delLogsOnStartup);
|
||||
ConfigParser.SaveGuiElement(clearLogOnInput);
|
||||
ConfigParser.SaveGuiElement(modelSuffix);
|
||||
// Interpolation
|
||||
ConfigParser.SaveGuiElement(keepAudio);
|
||||
ConfigParser.SaveGuiElement(keepSubs);
|
||||
ConfigParser.SaveComboxIndex(dedupMode);
|
||||
ConfigParser.SaveComboxIndex(mpdecimateMode);
|
||||
ConfigParser.SaveGuiElement(dedupThresh);
|
||||
ConfigParser.SaveGuiElement(enableLoop);
|
||||
ConfigParser.SaveGuiElement(scnDetect);
|
||||
ConfigParser.SaveGuiElement(scnDetectValue);
|
||||
ConfigParser.SaveComboxIndex(autoEncMode);
|
||||
ConfigParser.SaveGuiElement(sbsAllowAutoEnc);
|
||||
// AI
|
||||
ConfigParser.SaveGuiElement(torchGpus);
|
||||
ConfigParser.SaveGuiElement(ncnnGpus);
|
||||
ConfigParser.SaveGuiElement(ncnnThreads);
|
||||
ConfigParser.SaveGuiElement(uhdThresh);
|
||||
ConfigParser.SaveGuiElement(dainNcnnTilesize, ConfigParser.StringMode.Int);
|
||||
// Video Export
|
||||
ConfigParser.SaveGuiElement(minOutVidLength, ConfigParser.StringMode.Int);
|
||||
ConfigParser.SaveComboxIndex(mp4Enc);
|
||||
ConfigParser.SaveGuiElement(h264Crf);
|
||||
ConfigParser.SaveGuiElement(h265Crf);
|
||||
ConfigParser.SaveGuiElement(vp9Crf);
|
||||
ConfigParser.SaveComboxIndex(proResProfile);
|
||||
ConfigParser.SaveGuiElement(gifColors);
|
||||
ConfigParser.SaveGuiElement(aviCodec);
|
||||
ConfigParser.SaveGuiElement(aviColors);
|
||||
ConfigParser.SaveGuiElement(maxFps);
|
||||
ConfigParser.SaveComboxIndex(maxFpsMode);
|
||||
ConfigParser.SaveComboxIndex(loopMode);
|
||||
// Debugging
|
||||
ConfigParser.SaveComboxIndex(cmdDebugMode);
|
||||
ConfigParser.SaveGuiElement(autoDedupFrames);
|
||||
ConfigParser.SaveGuiElement(modelsBaseUrl);
|
||||
ConfigParser.SaveGuiElement(ffEncThreads, ConfigParser.StringMode.Int);
|
||||
ConfigParser.SaveGuiElement(ffEncPreset);
|
||||
ConfigParser.SaveGuiElement(ffEncArgs);
|
||||
ConfigParser.SaveGuiElement(ffprobeCountFrames);
|
||||
}
|
||||
|
||||
void LoadSettings()
|
||||
{
|
||||
// General
|
||||
ConfigParser.LoadComboxIndex(processingMode);
|
||||
ConfigParser.LoadGuiElement(maxVidHeight);
|
||||
ConfigParser.LoadGuiElement(enableAlpha);
|
||||
ConfigParser.LoadComboxIndex(tempFolderLoc); ConfigParser.LoadGuiElement(tempDirCustom);
|
||||
ConfigParser.LoadGuiElement(delLogsOnStartup);
|
||||
ConfigParser.LoadGuiElement(keepTempFolder);
|
||||
ConfigParser.LoadGuiElement(clearLogOnInput);
|
||||
ConfigParser.LoadGuiElement(modelSuffix);
|
||||
// Interpolation
|
||||
ConfigParser.LoadGuiElement(keepAudio);
|
||||
ConfigParser.LoadGuiElement(keepSubs);
|
||||
ConfigParser.LoadComboxIndex(dedupMode);
|
||||
ConfigParser.LoadComboxIndex(mpdecimateMode);
|
||||
ConfigParser.LoadGuiElement(dedupThresh);
|
||||
ConfigParser.LoadGuiElement(enableLoop);
|
||||
ConfigParser.LoadGuiElement(scnDetect);
|
||||
ConfigParser.LoadGuiElement(scnDetectValue);
|
||||
ConfigParser.LoadComboxIndex(autoEncMode);
|
||||
ConfigParser.LoadGuiElement(sbsAllowAutoEnc);
|
||||
// AI
|
||||
ConfigParser.LoadGuiElement(torchGpus);
|
||||
ConfigParser.LoadGuiElement(ncnnGpus);
|
||||
ConfigParser.LoadGuiElement(ncnnThreads);
|
||||
ConfigParser.LoadGuiElement(uhdThresh);
|
||||
ConfigParser.LoadGuiElement(dainNcnnTilesize);
|
||||
// Video Export
|
||||
ConfigParser.LoadGuiElement(minOutVidLength);
|
||||
ConfigParser.LoadComboxIndex(mp4Enc);
|
||||
ConfigParser.LoadGuiElement(h264Crf);
|
||||
ConfigParser.LoadGuiElement(h265Crf);
|
||||
ConfigParser.LoadGuiElement(vp9Crf);
|
||||
ConfigParser.LoadComboxIndex(proResProfile);
|
||||
ConfigParser.LoadGuiElement(gifColors);
|
||||
ConfigParser.LoadGuiElement(aviCodec);
|
||||
ConfigParser.LoadGuiElement(aviColors);
|
||||
ConfigParser.LoadGuiElement(maxFps);
|
||||
ConfigParser.LoadComboxIndex(maxFpsMode);
|
||||
ConfigParser.LoadComboxIndex(loopMode);
|
||||
// Debugging
|
||||
ConfigParser.LoadComboxIndex(cmdDebugMode);
|
||||
ConfigParser.LoadGuiElement(autoDedupFrames);
|
||||
ConfigParser.LoadGuiElement(modelsBaseUrl);
|
||||
ConfigParser.LoadGuiElement(ffEncThreads);
|
||||
ConfigParser.LoadGuiElement(ffEncPreset);
|
||||
ConfigParser.LoadGuiElement(ffEncArgs);
|
||||
ConfigParser.LoadGuiElement(ffprobeCountFrames);
|
||||
}
|
||||
|
||||
private void tempFolderLoc_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
tempDirBrowseBtn.Visible = tempFolderLoc.SelectedIndex == 4;
|
||||
tempDirCustom.Visible = tempFolderLoc.SelectedIndex == 4;
|
||||
}
|
||||
|
||||
private void tempDirBrowseBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
|
||||
dialog.InitialDirectory = tempDirCustom.Text.Trim();
|
||||
dialog.IsFolderPicker = true;
|
||||
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
|
||||
tempDirCustom.Text = dialog.FileName;
|
||||
|
||||
ConfigParser.SaveGuiElement(tempDirCustom);
|
||||
}
|
||||
|
||||
private void cmdDebugMode_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (initialized && cmdDebugMode.SelectedIndex == 2)
|
||||
MessageBox.Show("If you enable this, you need to close the CMD window manually after the process has finished, otherwise processing will be paused!", "Notice");
|
||||
}
|
||||
|
||||
private void dedupMode_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
dedupeSensLabel.Visible = dedupMode.SelectedIndex != 0;
|
||||
magickDedupePanel.Visible = dedupMode.SelectedIndex == 1;
|
||||
mpDedupePanel.Visible = dedupMode.SelectedIndex == 2;
|
||||
}
|
||||
|
||||
private void clearModelCacheBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
ModelDownloader.DeleteAllModels();
|
||||
clearModelCacheBtn.Text = "Clear Model Cache";
|
||||
CheckModelCacheSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
208
Code5/Forms/UpdaterForm.Designer.cs
generated
@@ -1,208 +0,0 @@
|
||||
namespace Flowframes.Forms
|
||||
{
|
||||
partial class UpdaterForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UpdaterForm));
|
||||
this.titleLabel = new System.Windows.Forms.Label();
|
||||
this.label13 = new System.Windows.Forms.Label();
|
||||
this.updatePatreonBtn = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.installedLabel = new System.Windows.Forms.Label();
|
||||
this.latestLabel = new System.Windows.Forms.Label();
|
||||
this.statusLabel = new System.Windows.Forms.Label();
|
||||
this.downloadingLabel = new System.Windows.Forms.Label();
|
||||
this.updateFreeBtn = new System.Windows.Forms.Button();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// titleLabel
|
||||
//
|
||||
this.titleLabel.AutoSize = true;
|
||||
this.titleLabel.Font = new System.Drawing.Font("Yu Gothic UI", 21.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.titleLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.titleLabel.Location = new System.Drawing.Point(12, 9);
|
||||
this.titleLabel.Margin = new System.Windows.Forms.Padding(3, 0, 3, 10);
|
||||
this.titleLabel.Name = "titleLabel";
|
||||
this.titleLabel.Size = new System.Drawing.Size(121, 40);
|
||||
this.titleLabel.TabIndex = 2;
|
||||
this.titleLabel.Text = "Updater";
|
||||
//
|
||||
// label13
|
||||
//
|
||||
this.label13.AutoSize = true;
|
||||
this.label13.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label13.ForeColor = System.Drawing.Color.White;
|
||||
this.label13.Location = new System.Drawing.Point(17, 67);
|
||||
this.label13.Margin = new System.Windows.Forms.Padding(8, 8, 3, 0);
|
||||
this.label13.Name = "label13";
|
||||
this.label13.Size = new System.Drawing.Size(110, 16);
|
||||
this.label13.TabIndex = 35;
|
||||
this.label13.Text = "Installed Version:";
|
||||
//
|
||||
// updatePatreonBtn
|
||||
//
|
||||
this.updatePatreonBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.updatePatreonBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
|
||||
this.updatePatreonBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.updatePatreonBtn.ForeColor = System.Drawing.Color.White;
|
||||
this.updatePatreonBtn.Location = new System.Drawing.Point(12, 229);
|
||||
this.updatePatreonBtn.Name = "updatePatreonBtn";
|
||||
this.updatePatreonBtn.Size = new System.Drawing.Size(203, 40);
|
||||
this.updatePatreonBtn.TabIndex = 36;
|
||||
this.updatePatreonBtn.Text = "Download Patreon Version";
|
||||
this.updatePatreonBtn.UseVisualStyleBackColor = true;
|
||||
this.updatePatreonBtn.Click += new System.EventHandler(this.updatePatreonBtn_Click);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label1.ForeColor = System.Drawing.Color.White;
|
||||
this.label1.Location = new System.Drawing.Point(16, 93);
|
||||
this.label1.Margin = new System.Windows.Forms.Padding(8, 10, 3, 0);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(96, 16);
|
||||
this.label1.TabIndex = 37;
|
||||
this.label1.Text = "Latest Version:";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label2.ForeColor = System.Drawing.Color.White;
|
||||
this.label2.Location = new System.Drawing.Point(16, 119);
|
||||
this.label2.Margin = new System.Windows.Forms.Padding(8, 10, 3, 0);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(48, 16);
|
||||
this.label2.TabIndex = 38;
|
||||
this.label2.Text = "Status:";
|
||||
//
|
||||
// installedLabel
|
||||
//
|
||||
this.installedLabel.AutoSize = true;
|
||||
this.installedLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.installedLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.installedLabel.Location = new System.Drawing.Point(170, 67);
|
||||
this.installedLabel.Margin = new System.Windows.Forms.Padding(8, 8, 3, 0);
|
||||
this.installedLabel.Name = "installedLabel";
|
||||
this.installedLabel.Size = new System.Drawing.Size(76, 16);
|
||||
this.installedLabel.TabIndex = 39;
|
||||
this.installedLabel.Text = "Loading...";
|
||||
//
|
||||
// latestLabel
|
||||
//
|
||||
this.latestLabel.AutoSize = true;
|
||||
this.latestLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.latestLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.latestLabel.Location = new System.Drawing.Point(170, 93);
|
||||
this.latestLabel.Margin = new System.Windows.Forms.Padding(8, 8, 3, 0);
|
||||
this.latestLabel.Name = "latestLabel";
|
||||
this.latestLabel.Size = new System.Drawing.Size(76, 16);
|
||||
this.latestLabel.TabIndex = 40;
|
||||
this.latestLabel.Text = "Loading...";
|
||||
//
|
||||
// statusLabel
|
||||
//
|
||||
this.statusLabel.AutoSize = true;
|
||||
this.statusLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.statusLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.statusLabel.Location = new System.Drawing.Point(170, 119);
|
||||
this.statusLabel.Margin = new System.Windows.Forms.Padding(8, 8, 3, 0);
|
||||
this.statusLabel.Name = "statusLabel";
|
||||
this.statusLabel.Size = new System.Drawing.Size(76, 16);
|
||||
this.statusLabel.TabIndex = 41;
|
||||
this.statusLabel.Text = "Loading...";
|
||||
//
|
||||
// downloadingLabel
|
||||
//
|
||||
this.downloadingLabel.AutoSize = true;
|
||||
this.downloadingLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.downloadingLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.downloadingLabel.Location = new System.Drawing.Point(226, 241);
|
||||
this.downloadingLabel.Margin = new System.Windows.Forms.Padding(8, 10, 3, 0);
|
||||
this.downloadingLabel.Name = "downloadingLabel";
|
||||
this.downloadingLabel.Size = new System.Drawing.Size(0, 16);
|
||||
this.downloadingLabel.TabIndex = 42;
|
||||
//
|
||||
// updateFreeBtn
|
||||
//
|
||||
this.updateFreeBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.updateFreeBtn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(48)))), ((int)(((byte)(48)))), ((int)(((byte)(48)))));
|
||||
this.updateFreeBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.updateFreeBtn.ForeColor = System.Drawing.Color.White;
|
||||
this.updateFreeBtn.Location = new System.Drawing.Point(221, 229);
|
||||
this.updateFreeBtn.Name = "updateFreeBtn";
|
||||
this.updateFreeBtn.Size = new System.Drawing.Size(203, 40);
|
||||
this.updateFreeBtn.TabIndex = 43;
|
||||
this.updateFreeBtn.Text = "Download Free Version";
|
||||
this.updateFreeBtn.UseVisualStyleBackColor = true;
|
||||
this.updateFreeBtn.Click += new System.EventHandler(this.updateFreeBtn_Click);
|
||||
//
|
||||
// UpdaterForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
|
||||
this.ClientSize = new System.Drawing.Size(624, 281);
|
||||
this.Controls.Add(this.updateFreeBtn);
|
||||
this.Controls.Add(this.downloadingLabel);
|
||||
this.Controls.Add(this.statusLabel);
|
||||
this.Controls.Add(this.latestLabel);
|
||||
this.Controls.Add(this.installedLabel);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.updatePatreonBtn);
|
||||
this.Controls.Add(this.label13);
|
||||
this.Controls.Add(this.titleLabel);
|
||||
this.ForeColor = System.Drawing.Color.White;
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Name = "UpdaterForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Updater";
|
||||
this.Load += new System.EventHandler(this.UpdaterForm_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label titleLabel;
|
||||
private System.Windows.Forms.Label label13;
|
||||
private System.Windows.Forms.Button updatePatreonBtn;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Label installedLabel;
|
||||
private System.Windows.Forms.Label latestLabel;
|
||||
private System.Windows.Forms.Label statusLabel;
|
||||
private System.Windows.Forms.Label downloadingLabel;
|
||||
private System.Windows.Forms.Button updateFreeBtn;
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.OS;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.Forms
|
||||
{
|
||||
public partial class UpdaterForm : Form
|
||||
{
|
||||
Version installed;
|
||||
Version latestPat;
|
||||
Version latestFree;
|
||||
|
||||
public UpdaterForm()
|
||||
{
|
||||
AutoScaleMode = AutoScaleMode.None;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void UpdaterForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
installed = Updater.GetInstalledVer();
|
||||
latestPat = Updater.GetLatestVer(true);
|
||||
latestFree = Updater.GetLatestVer(false);
|
||||
|
||||
installedLabel.Text = installed.ToString();
|
||||
await Task.Delay(100);
|
||||
latestLabel.Text = $"{latestPat} (Patreon/Beta) - {latestFree} (Free/Stable)";
|
||||
|
||||
if (Updater.CompareVersions(installed, latestFree) == Updater.VersionCompareResult.Equal)
|
||||
{
|
||||
statusLabel.Text = "Latest Free Version Is Installed.";
|
||||
|
||||
if (Updater.CompareVersions(installed, latestPat) == Updater.VersionCompareResult.Newer)
|
||||
statusLabel.Text += "\nBeta Update Available On Patreon.";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Updater.CompareVersions(installed, latestPat) == Updater.VersionCompareResult.Equal)
|
||||
{
|
||||
statusLabel.Text = "Latest Patreon/Beta Version Is Installed.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (Updater.CompareVersions(installed, latestPat) == Updater.VersionCompareResult.Newer)
|
||||
{
|
||||
statusLabel.Text = "Update available on Patreon!";
|
||||
|
||||
if (Updater.CompareVersions(installed, latestFree) == Updater.VersionCompareResult.Newer)
|
||||
statusLabel.Text = $"Beta Updates Available On Patreon and Itch.io.";
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float lastProg = -1f;
|
||||
public void SetProgLabel (float prog, string str)
|
||||
{
|
||||
if (prog == lastProg) return;
|
||||
lastProg = prog;
|
||||
downloadingLabel.Text = str;
|
||||
}
|
||||
|
||||
private void updatePatreonBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
string link = Updater.GetLatestVerLink(true);
|
||||
if(!string.IsNullOrWhiteSpace(link))
|
||||
Process.Start(link);
|
||||
}
|
||||
|
||||
private void updateFreeBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
string link = Updater.GetLatestVerLink(false);
|
||||
if (!string.IsNullOrWhiteSpace(link))
|
||||
Process.Start(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.IO
|
||||
{
|
||||
class CfgStrings
|
||||
{
|
||||
// public static string dedupMode = "dedupMode";
|
||||
// public static string dedupThresh = "dedupThresh";
|
||||
// public static string keepFrames = "keepFrames";
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
using Flowframes.OS;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.IO
|
||||
{
|
||||
internal class Config
|
||||
{
|
||||
private static string configPath;
|
||||
|
||||
private static string[] cachedLines;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
configPath = Path.Combine(Paths.GetDataPath(), "config.ini");
|
||||
IOUtils.CreateFileIfNotExists(configPath);
|
||||
Reload();
|
||||
}
|
||||
|
||||
public static void Set(string key, string value)
|
||||
{
|
||||
string[] lines = new string[1];
|
||||
try
|
||||
{
|
||||
lines = File.ReadAllLines(configPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
MessageBox.Show("Failed to read config file!\nFlowframes will try to re-create the file if it does not exist.", "Error");
|
||||
if(!File.Exists(configPath))
|
||||
Init();
|
||||
}
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
if (lines[i].Split('|')[0] == key)
|
||||
{
|
||||
lines[i] = key + "|" + value;
|
||||
File.WriteAllLines(configPath, lines);
|
||||
cachedLines = lines;
|
||||
return;
|
||||
}
|
||||
}
|
||||
List<string> list = lines.ToList();
|
||||
list.Add(key + "|" + value);
|
||||
list = list.OrderBy(p => p).ToList();
|
||||
|
||||
string newFileContent = "";
|
||||
foreach(string line in list)
|
||||
newFileContent += line + "\n";
|
||||
|
||||
File.WriteAllText(configPath, newFileContent.Trim());
|
||||
|
||||
cachedLines = list.ToArray();
|
||||
}
|
||||
|
||||
public static string Get(string key, string defaultVal)
|
||||
{
|
||||
WriteIfDoesntExist(key, defaultVal);
|
||||
return Get(key);
|
||||
}
|
||||
|
||||
public static string Get(string key, Type type = Type.String)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < cachedLines.Length; i++)
|
||||
{
|
||||
string[] keyValuePair = cachedLines[i].Split('|');
|
||||
if (keyValuePair[0] == key && !string.IsNullOrWhiteSpace(keyValuePair[1]))
|
||||
return keyValuePair[1];
|
||||
}
|
||||
return WriteDefaultValIfExists(key, type);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Failed to get {key.Wrap()} from config! {e.Message}");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool GetBool(string key)
|
||||
{
|
||||
return bool.Parse(Get(key, Type.Bool));
|
||||
}
|
||||
|
||||
public static bool GetBool(string key, bool defaultVal)
|
||||
{
|
||||
WriteIfDoesntExist(key, (defaultVal ? "True" : "False"));
|
||||
return bool.Parse(Get(key, Type.Bool));
|
||||
}
|
||||
|
||||
public static int GetInt(string key)
|
||||
{
|
||||
return Get(key, Type.Int).GetInt();
|
||||
}
|
||||
|
||||
public static int GetInt(string key, int defaultVal)
|
||||
{
|
||||
WriteIfDoesntExist(key, defaultVal.ToString());
|
||||
return GetInt(key);
|
||||
}
|
||||
|
||||
public static float GetFloat(string key)
|
||||
{
|
||||
return float.Parse(Get(key, Type.Float), CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public static string GetFloatString (string key)
|
||||
{
|
||||
return Get(key, Type.Float).Replace(",", ".");
|
||||
}
|
||||
|
||||
static void WriteIfDoesntExist (string key, string val)
|
||||
{
|
||||
foreach (string line in cachedLines)
|
||||
if (line.Contains(key + "|"))
|
||||
return;
|
||||
Set(key, val);
|
||||
}
|
||||
|
||||
public enum Type { String, Int, Float, Bool }
|
||||
private static string WriteDefaultValIfExists(string key, Type type)
|
||||
{
|
||||
if (key == "maxVidHeight") return WriteDefault(key, "2160");
|
||||
if (key == "delLogsOnStartup") return WriteDefault(key, "True");
|
||||
if (key == "clearLogOnInput") return WriteDefault(key, "True");
|
||||
if (key == "tempDirCustom") return WriteDefault(key, "C:/");
|
||||
// Interpolation
|
||||
if (key == "dedupMode") return WriteDefault(key, "2");
|
||||
if (key == "dedupThresh") return WriteDefault(key, "2");
|
||||
if (key == "keepAudio") return WriteDefault(key, "True");
|
||||
if (key == "keepSubs") return WriteDefault(key, "True");
|
||||
if (key == "autoDedupFrames") return WriteDefault(key, "100");
|
||||
if (key == "scnDetectValue") return WriteDefault(key, "0.2");
|
||||
if (key == "autoEncMode") return WriteDefault(key, "2");
|
||||
// Video Export
|
||||
if (key == "minOutVidLength") return WriteDefault(key, "5");
|
||||
if (key == "h264Crf") return WriteDefault(key, "20");
|
||||
if (key == "h265Crf") return WriteDefault(key, "24");
|
||||
if (key == "vp9Crf") return WriteDefault(key, "32");
|
||||
if (key == "proResProfile") return WriteDefault(key, "2");
|
||||
if (key == "aviCodec") return WriteDefault(key, "ffv1");
|
||||
if (key == "aviColors") return WriteDefault(key, "yuv420p");
|
||||
if (key == "gifColors") return WriteDefault(key, "128 (High)");
|
||||
if (key == "minVidLength") return WriteDefault(key, "2");
|
||||
// AI
|
||||
if (key == "uhdThresh") return WriteDefault(key, "1440");
|
||||
if (key == "ncnnThreads") return WriteDefault(key, "1");
|
||||
if (key == "dainNcnnTilesize") return WriteDefault(key, "768");
|
||||
// Debug / Other / Experimental
|
||||
if (key == "modelsBaseUrl") return WriteDefault(key, "https://dl.nmkd.de/flowframes/mdl/");
|
||||
if (key == "ffEncPreset") return WriteDefault(key, "medium");
|
||||
if (key == "ffEncArgs") return WriteDefault(key, "");
|
||||
|
||||
if (type == Type.Int || type == Type.Float) return WriteDefault(key, "0"); // Write default int/float (0)
|
||||
if (type == Type.Bool) return WriteDefault(key, "False"); // Write default bool (False)
|
||||
return WriteDefault(key, "0");
|
||||
}
|
||||
|
||||
private static string WriteDefault(string key, string def)
|
||||
{
|
||||
Set(key, def);
|
||||
return def;
|
||||
}
|
||||
|
||||
private static void Reload()
|
||||
{
|
||||
List<string> validLines = new List<string>();
|
||||
string[] lines = File.ReadAllLines(configPath);
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if(line != null && !string.IsNullOrWhiteSpace(line) && line.Length > 3)
|
||||
validLines.Add(line);
|
||||
}
|
||||
cachedLines = validLines.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.IO
|
||||
{
|
||||
class ConfigParser
|
||||
{
|
||||
|
||||
public enum StringMode { Any, Int, Float }
|
||||
|
||||
public static void SaveGuiElement(TextBox textbox, StringMode stringMode = StringMode.Any)
|
||||
{
|
||||
switch (stringMode)
|
||||
{
|
||||
case StringMode.Any: Config.Set(textbox.Name, textbox.Text); break;
|
||||
case StringMode.Int: Config.Set(textbox.Name, textbox.Text.GetInt().ToString()); break;
|
||||
case StringMode.Float: Config.Set(textbox.Name, textbox.Text.GetFloat().ToString()); break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveGuiElement(ComboBox comboBox, StringMode stringMode = StringMode.Any)
|
||||
{
|
||||
switch (stringMode)
|
||||
{
|
||||
case StringMode.Any: Config.Set(comboBox.Name, comboBox.Text); break;
|
||||
case StringMode.Int: Config.Set(comboBox.Name, comboBox.Text.GetInt().ToString()); break;
|
||||
case StringMode.Float: Config.Set(comboBox.Name, comboBox.Text.GetFloat().ToString().Replace(",", ".")); break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveGuiElement(CheckBox checkbox)
|
||||
{
|
||||
Config.Set(checkbox.Name, checkbox.Checked.ToString());
|
||||
}
|
||||
|
||||
public static void SaveGuiElement(NumericUpDown upDown, StringMode stringMode = StringMode.Any)
|
||||
{
|
||||
switch (stringMode)
|
||||
{
|
||||
case StringMode.Any: Config.Set(upDown.Name, ((float)upDown.Value).ToString().Replace(",", ".")); break;
|
||||
case StringMode.Int: Config.Set(upDown.Name, ((int)upDown.Value).ToString()); break;
|
||||
case StringMode.Float: Config.Set(upDown.Name, ((float)upDown.Value).ToString().Replace(",", ".")); ; break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveComboxIndex(ComboBox comboBox)
|
||||
{
|
||||
Config.Set(comboBox.Name, comboBox.SelectedIndex.ToString());
|
||||
}
|
||||
|
||||
public static void LoadGuiElement(ComboBox comboBox, string suffix = "")
|
||||
{
|
||||
comboBox.Text = Config.Get(comboBox.Name) + suffix;
|
||||
}
|
||||
|
||||
public static void LoadGuiElement(TextBox textbox, string suffix = "")
|
||||
{
|
||||
textbox.Text = Config.Get(textbox.Name) + suffix; ;
|
||||
}
|
||||
|
||||
public static void LoadGuiElement(CheckBox checkbox)
|
||||
{
|
||||
checkbox.Checked = Config.GetBool(checkbox.Name);
|
||||
}
|
||||
|
||||
public static void LoadGuiElement(NumericUpDown upDown)
|
||||
{
|
||||
upDown.Value = Convert.ToDecimal(Config.GetFloat(upDown.Name));
|
||||
}
|
||||
|
||||
public static void LoadComboxIndex(ComboBox comboBox)
|
||||
{
|
||||
comboBox.SelectedIndex = Config.GetInt(comboBox.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,795 +0,0 @@
|
||||
|
||||
using Flowframes.Data;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.MiscUtils;
|
||||
using Flowframes.UI;
|
||||
using Force.Crc32;
|
||||
using Microsoft.WindowsAPICodePack.Shell;
|
||||
using Standart.Hash.xxHash;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.IO
|
||||
{
|
||||
class IOUtils
|
||||
{
|
||||
public static string GetExe()
|
||||
{
|
||||
return System.Reflection.Assembly.GetEntryAssembly().GetName().CodeBase.Replace("file:///", "");
|
||||
}
|
||||
|
||||
public static string GetExeDir()
|
||||
{
|
||||
return AppDomain.CurrentDomain.BaseDirectory;
|
||||
}
|
||||
|
||||
public static Image GetImage(string path)
|
||||
{
|
||||
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
|
||||
return Image.FromStream(stream);
|
||||
}
|
||||
|
||||
public static string[] ReadLines(string path)
|
||||
{
|
||||
List<string> lines = new List<string>();
|
||||
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 0x1000, FileOptions.SequentialScan))
|
||||
using (var sr = new StreamReader(fs, Encoding.UTF8))
|
||||
{
|
||||
string line;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
lines.Add(line);
|
||||
}
|
||||
return lines.ToArray();
|
||||
}
|
||||
|
||||
public static bool IsPathDirectory(string path)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException("path");
|
||||
}
|
||||
path = path.Trim();
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (File.Exists(path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (new string[2]
|
||||
{
|
||||
"\\",
|
||||
"/"
|
||||
}.Any((string x) => path.EndsWith(x)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return string.IsNullOrWhiteSpace(Path.GetExtension(path));
|
||||
}
|
||||
|
||||
public static bool IsFileValid(string path)
|
||||
{
|
||||
if (path == null)
|
||||
return false;
|
||||
|
||||
if (!File.Exists(path))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool IsDirValid(string path)
|
||||
{
|
||||
if (path == null)
|
||||
return false;
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Copy(string sourceDirectoryName, string targetDirectoryName, bool move = false)
|
||||
{
|
||||
Directory.CreateDirectory(targetDirectoryName);
|
||||
DirectoryInfo source = new DirectoryInfo(sourceDirectoryName);
|
||||
DirectoryInfo target = new DirectoryInfo(targetDirectoryName);
|
||||
CopyWork(source, target, move);
|
||||
}
|
||||
|
||||
private static void CopyWork(DirectoryInfo source, DirectoryInfo target, bool move)
|
||||
{
|
||||
DirectoryInfo[] directories = source.GetDirectories();
|
||||
foreach (DirectoryInfo directoryInfo in directories)
|
||||
{
|
||||
CopyWork(directoryInfo, target.CreateSubdirectory(directoryInfo.Name), move);
|
||||
}
|
||||
FileInfo[] files = source.GetFiles();
|
||||
foreach (FileInfo fileInfo in files)
|
||||
{
|
||||
if (move)
|
||||
fileInfo.MoveTo(Path.Combine(target.FullName, fileInfo.Name));
|
||||
else
|
||||
fileInfo.CopyTo(Path.Combine(target.FullName, fileInfo.Name), overwrite: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteContentsOfDir(string path)
|
||||
{
|
||||
DirectoryInfo directoryInfo = new DirectoryInfo(path);
|
||||
FileInfo[] files = directoryInfo.GetFiles();
|
||||
foreach (FileInfo fileInfo in files)
|
||||
{
|
||||
fileInfo.Delete();
|
||||
}
|
||||
DirectoryInfo[] directories = directoryInfo.GetDirectories();
|
||||
foreach (DirectoryInfo directoryInfo2 in directories)
|
||||
{
|
||||
directoryInfo2.Delete(recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReplaceInFilenamesDir(string dir, string textToFind, string textToReplace, bool recursive = true, string wildcard = "*")
|
||||
{
|
||||
int counter = 1;
|
||||
DirectoryInfo d = new DirectoryInfo(dir);
|
||||
FileInfo[] files = null;
|
||||
if (recursive)
|
||||
files = d.GetFiles(wildcard, SearchOption.AllDirectories);
|
||||
else
|
||||
files = d.GetFiles(wildcard, SearchOption.TopDirectoryOnly);
|
||||
foreach (FileInfo file in files)
|
||||
{
|
||||
ReplaceInFilename(file.FullName, textToFind, textToReplace);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReplaceInFilename(string path, string textToFind, string textToReplace)
|
||||
{
|
||||
string ext = Path.GetExtension(path);
|
||||
string newFilename = Path.GetFileNameWithoutExtension(path).Replace(textToFind, textToReplace);
|
||||
string targetPath = Path.Combine(Path.GetDirectoryName(path), newFilename + ext);
|
||||
if (File.Exists(targetPath))
|
||||
{
|
||||
//Program.Print("Skipped " + path + " because a file with the target name already exists.");
|
||||
return;
|
||||
}
|
||||
File.Move(path, targetPath);
|
||||
}
|
||||
|
||||
public static int GetFilenameCounterLength(string file, string prefixToRemove = "")
|
||||
{
|
||||
string filenameNoExt = Path.GetFileNameWithoutExtension(file);
|
||||
if (!string.IsNullOrEmpty(prefixToRemove))
|
||||
filenameNoExt = filenameNoExt.Replace(prefixToRemove, "");
|
||||
string onlyNumbersFilename = Regex.Replace(filenameNoExt, "[^.0-9]", "");
|
||||
return onlyNumbersFilename.Length;
|
||||
}
|
||||
|
||||
public static int GetAmountOfFiles (string path, bool recursive, string wildcard = "*")
|
||||
{
|
||||
try
|
||||
{
|
||||
DirectoryInfo d = new DirectoryInfo(path);
|
||||
FileInfo[] files = null;
|
||||
if (recursive)
|
||||
files = d.GetFiles(wildcard, SearchOption.AllDirectories);
|
||||
else
|
||||
files = d.GetFiles(wildcard, SearchOption.TopDirectoryOnly);
|
||||
return files.Length;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool TryCopy(string source, string target, bool overwrite = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Copy(source, target, overwrite);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Failed to move '{source}' to '{target}' (Overwrite: {overwrite}): {e.Message}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryMove(string source, string target, bool overwrite = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (overwrite && File.Exists(target))
|
||||
File.Delete(target);
|
||||
|
||||
File.Move(source, target);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Failed to move '{source}' to '{target}' (Overwrite: {overwrite}): {e.Message}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void RenameCounterDir(string path, bool inverse = false)
|
||||
{
|
||||
int counter = 1;
|
||||
DirectoryInfo d = new DirectoryInfo(path);
|
||||
FileInfo[] files = d.GetFiles();
|
||||
var filesSorted = files.OrderBy(n => n);
|
||||
if (inverse)
|
||||
filesSorted.Reverse();
|
||||
foreach (FileInfo file in files)
|
||||
{
|
||||
string dir = new DirectoryInfo(file.FullName).Parent.FullName;
|
||||
int filesDigits = (int)Math.Floor(Math.Log10((double)files.Length) + 1);
|
||||
File.Move(file.FullName, Path.Combine(dir, counter.ToString().PadLeft(filesDigits, '0') + Path.GetExtension(file.FullName)));
|
||||
counter++;
|
||||
//if (counter % 100 == 0) Program.Print("Renamed " + counter + " files...");
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<Dictionary<string, string>> RenameCounterDirReversibleAsync(string path, string ext, int startAt, int padding = 0)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Restart();
|
||||
Dictionary<string, string> oldNewNamesMap = new Dictionary<string, string>();
|
||||
|
||||
int counter = startAt;
|
||||
FileInfo[] files = new DirectoryInfo(path).GetFiles($"*.{ext}", SearchOption.TopDirectoryOnly);
|
||||
var filesSorted = files.OrderBy(n => n);
|
||||
|
||||
foreach (FileInfo file in files)
|
||||
{
|
||||
string dir = new DirectoryInfo(file.FullName).Parent.FullName;
|
||||
int filesDigits = (int)Math.Floor(Math.Log10((double)files.Length) + 1);
|
||||
string newFilename = (padding > 0) ? counter.ToString().PadLeft(padding, '0') : counter.ToString();
|
||||
string outpath = outpath = Path.Combine(dir, newFilename + Path.GetExtension(file.FullName));
|
||||
File.Move(file.FullName, outpath);
|
||||
oldNewNamesMap.Add(file.FullName, outpath);
|
||||
counter++;
|
||||
|
||||
if(sw.ElapsedMilliseconds > 100)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
sw.Restart();
|
||||
}
|
||||
}
|
||||
|
||||
return oldNewNamesMap;
|
||||
}
|
||||
|
||||
public static async Task ReverseRenaming(string basePath, Dictionary<string, string> oldNewMap) // Relative -> absolute paths
|
||||
{
|
||||
Dictionary<string, string> absPaths = oldNewMap.ToDictionary(x => Path.Combine(basePath, x.Key), x => Path.Combine(basePath, x.Value));
|
||||
await ReverseRenaming(absPaths);
|
||||
}
|
||||
|
||||
public static async Task ReverseRenaming(Dictionary<string, string> oldNewMap) // Takes absolute paths only
|
||||
{
|
||||
if (oldNewMap == null || oldNewMap.Count < 1) return;
|
||||
int counter = 0;
|
||||
int failCount = 0;
|
||||
|
||||
foreach (KeyValuePair<string, string> pair in oldNewMap)
|
||||
{
|
||||
bool success = TryMove(pair.Value, pair.Key);
|
||||
|
||||
if (!success)
|
||||
failCount++;
|
||||
|
||||
if (failCount >= 100)
|
||||
break;
|
||||
|
||||
counter++;
|
||||
|
||||
if (counter % 1000 == 0)
|
||||
await Task.Delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<float> GetVideoFramerate (string path)
|
||||
{
|
||||
float fps = 0;
|
||||
try
|
||||
{
|
||||
ShellFile shellFile = ShellFile.FromFilePath(path);
|
||||
fps = (float)shellFile.Properties.System.Video.FrameRate.Value / 1000f;
|
||||
Logger.Log("Detected FPS of " + Path.GetFileName(path) + " as " + fps + " FPS", true);
|
||||
if (fps <= 0)
|
||||
throw new Exception("FPS is 0.");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.Log("Failed to read FPS - Trying alternative method...", true);
|
||||
try
|
||||
{
|
||||
fps = await FfmpegCommands.GetFramerate(path);
|
||||
Logger.Log("Detected FPS of " + Path.GetFileName(path) + " as " + fps + " FPS", true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.Log("Failed to read FPS - Please enter it manually.");
|
||||
}
|
||||
}
|
||||
return fps;
|
||||
}
|
||||
|
||||
public static float GetVideoFramerateForDir(string path)
|
||||
{
|
||||
float fps = 0;
|
||||
try
|
||||
{
|
||||
string parentDir = path.GetParentDir();
|
||||
string fpsFile = Path.Combine(parentDir, "fps.ini");
|
||||
fps = float.Parse(ReadLines(fpsFile)[0]);
|
||||
Logger.Log($"Got {fps} FPS from file: " + fpsFile);
|
||||
|
||||
float guiFps = Program.mainForm.GetCurrentSettings().inFps;
|
||||
|
||||
DialogResult dialogResult = MessageBox.Show("A frame rate file has been found in the parent directory.\n\n" +
|
||||
$"Click \"Yes\" to use frame rate from the file ({fps}) or \"No\" to use current FPS set in GUI ({guiFps})", "Load Frame Rate From fps.ini?", MessageBoxButtons.YesNo);
|
||||
if (dialogResult == DialogResult.Yes)
|
||||
return fps;
|
||||
else if (dialogResult == DialogResult.No)
|
||||
return guiFps;
|
||||
}
|
||||
catch { }
|
||||
return fps;
|
||||
}
|
||||
|
||||
public static async Task<Size> GetVideoOrFramesRes (string path)
|
||||
{
|
||||
Size res = new Size();
|
||||
if (!IsPathDirectory(path)) // If path is video
|
||||
{
|
||||
res = GetVideoRes(path);
|
||||
}
|
||||
else // Path is frame folder
|
||||
{
|
||||
Image thumb = await MainUiFunctions.GetThumbnail(path);
|
||||
res = new Size(thumb.Width, thumb.Height);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static Size GetVideoRes (string path)
|
||||
{
|
||||
Size size = new Size(0, 0);
|
||||
try
|
||||
{
|
||||
ShellFile shellFile = ShellFile.FromFilePath(path);
|
||||
int w = (int)shellFile.Properties.System.Video.FrameWidth.Value;
|
||||
int h = (int)shellFile.Properties.System.Video.FrameHeight.Value;
|
||||
return new Size(w, h);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Failed to read video size ({e.Message}) - Trying alternative method...", true);
|
||||
try
|
||||
{
|
||||
size = FfmpegCommands.GetSize(path);
|
||||
Logger.Log($"Detected video size of {Path.GetFileName(path)} as {size.Width}x{size.Height}", true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.Log("Failed to read video size!");
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public static bool TryDeleteIfExists(string path) // Returns true if no exception occurs
|
||||
{
|
||||
try
|
||||
{
|
||||
if (path == null)
|
||||
return false;
|
||||
DeleteIfExists(path);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"TryDeleteIfExists: Error trying to delete {path}: {e.Message}", true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool DeleteIfExists (string path) // Returns true if the file/dir exists
|
||||
{
|
||||
if (!IsPathDirectory(path) && File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
return true;
|
||||
}
|
||||
if (IsPathDirectory(path) && Directory.Exists(path))
|
||||
{
|
||||
Directory.Delete(path, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static string GetCurrentExportSuffix ()
|
||||
{
|
||||
return GetExportSuffix(Interpolate.current.interpFactor, Interpolate.current.ai, Interpolate.current.model);
|
||||
}
|
||||
|
||||
public static string GetExportSuffix(float factor, AI ai, string mdl)
|
||||
{
|
||||
string suffix = $"-{factor.ToStringDot()}x-{ai.aiNameShort.ToUpper()}";
|
||||
if (Config.GetBool("modelSuffix"))
|
||||
suffix += $"-{mdl}";
|
||||
return suffix;
|
||||
}
|
||||
|
||||
public static string GetHighestFrameNumPath (string path)
|
||||
{
|
||||
FileInfo highest = null;
|
||||
int highestInt = -1;
|
||||
foreach(FileInfo frame in new DirectoryInfo(path).GetFiles("*.*", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
int num = frame.Name.GetInt();
|
||||
if (num > highestInt)
|
||||
{
|
||||
highest = frame;
|
||||
highestInt = frame.Name.GetInt();
|
||||
}
|
||||
}
|
||||
return highest.FullName;
|
||||
}
|
||||
|
||||
public static string FilenameSuffix (string path, string suffix)
|
||||
{
|
||||
try
|
||||
{
|
||||
string ext = Path.GetExtension(path);
|
||||
return Path.Combine(path.GetParentDir(), $"{Path.GetFileNameWithoutExtension(path)}{suffix}{ext}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetAudioFile (string basePath)
|
||||
{
|
||||
string[] exts = new string[] { "m4a", "wav", "ogg", "mp2", "mp3" };
|
||||
|
||||
foreach(string ext in exts)
|
||||
{
|
||||
string filename = Path.ChangeExtension(basePath, ext);
|
||||
if (File.Exists(filename))
|
||||
return filename;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static async Task<float> GetFpsFolderOrVideo(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (IsPathDirectory(path))
|
||||
{
|
||||
float dirFps = GetVideoFramerateForDir(path);
|
||||
|
||||
if (dirFps > 0)
|
||||
return dirFps;
|
||||
}
|
||||
else
|
||||
{
|
||||
float vidFps = await GetVideoFramerate(path);
|
||||
|
||||
if (vidFps > 0)
|
||||
return vidFps;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("GetFpsFolderOrVideo() Error: " + e.Message);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public enum ErrorMode { HiddenLog, VisibleLog, Messagebox }
|
||||
public static bool CanWriteToDir (string dir, ErrorMode errMode)
|
||||
{
|
||||
string tempFile = Path.Combine(dir, "flowframes-testfile.tmp");
|
||||
try
|
||||
{
|
||||
File.Create(tempFile);
|
||||
File.Delete(tempFile);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Can't write to {dir}! {e.Message}", errMode == ErrorMode.HiddenLog);
|
||||
if (errMode == ErrorMode.Messagebox && !BatchProcessing.busy)
|
||||
MessageBox.Show($"Can't write to {dir}!\n\n{e.Message}", "Error");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CopyTo (string file, string targetFolder, bool overwrite = true)
|
||||
{
|
||||
string targetPath = Path.Combine(targetFolder, Path.GetFileName(file));
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(targetFolder))
|
||||
Directory.CreateDirectory(targetFolder);
|
||||
File.Copy(file, targetPath, overwrite);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Failed to copy {file} to {targetFolder}: {e.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool MoveTo(string file, string targetFolder, bool overwrite = true)
|
||||
{
|
||||
string targetPath = Path.Combine(targetFolder, Path.GetFileName(file));
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(targetFolder))
|
||||
Directory.CreateDirectory(targetFolder);
|
||||
if (overwrite)
|
||||
DeleteIfExists(targetPath);
|
||||
File.Move(file, targetPath);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Failed to move {file} to {targetFolder}: {e.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Hash { MD5, CRC32, xxHash }
|
||||
public static string GetHash (string path, Hash hashType, bool log = true, bool quick = true)
|
||||
{
|
||||
Benchmarker.Start();
|
||||
string hashStr = "";
|
||||
if (IsPathDirectory(path))
|
||||
{
|
||||
Logger.Log($"Path '{path}' is directory! Returning empty hash.", true);
|
||||
return hashStr;
|
||||
}
|
||||
try
|
||||
{
|
||||
var stream = File.OpenRead(path);
|
||||
|
||||
if (hashType == Hash.MD5)
|
||||
{
|
||||
MD5 md5 = MD5.Create();
|
||||
var hash = md5.ComputeHash(stream);
|
||||
hashStr = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
|
||||
}
|
||||
|
||||
if (hashType == Hash.CRC32)
|
||||
{
|
||||
var crc = new Crc32Algorithm();
|
||||
var crc32bytes = crc.ComputeHash(stream);
|
||||
hashStr = BitConverter.ToUInt32(crc32bytes, 0).ToString();
|
||||
}
|
||||
|
||||
if (hashType == Hash.xxHash)
|
||||
{
|
||||
ulong xxh64 = xxHash64.ComputeHash(stream, 8192, (ulong)GetFilesize(path));
|
||||
hashStr = xxh64.ToString();
|
||||
}
|
||||
|
||||
stream.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Error getting file hash for {Path.GetFileName(path)}: {e.Message}", true);
|
||||
return "";
|
||||
}
|
||||
if (log)
|
||||
Logger.Log($"Computed {hashType} for '{Path.GetFileNameWithoutExtension(path).Trunc(40) + Path.GetExtension(path)}' ({GetFilesizeStr(path)}) in {Benchmarker.GetTimeStr(true)}: {hashStr}", true);
|
||||
return hashStr;
|
||||
}
|
||||
|
||||
public static async Task<string> GetHashAsync(string path, Hash hashType, bool log = true, bool quick = true)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
return GetHash(path, hashType, log, quick);
|
||||
}
|
||||
|
||||
public static bool CreateDir (string path) // Returns whether the dir already existed
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void ZeroPadDir(string path, string ext, int targetLength, bool recursive = false)
|
||||
{
|
||||
FileInfo[] files;
|
||||
if (recursive)
|
||||
files = new DirectoryInfo(path).GetFiles($"*.{ext}", SearchOption.AllDirectories);
|
||||
else
|
||||
files = new DirectoryInfo(path).GetFiles($"*.{ext}", SearchOption.TopDirectoryOnly);
|
||||
|
||||
ZeroPadDir(files.Select(x => x.FullName).ToList(), targetLength);
|
||||
}
|
||||
|
||||
public static void ZeroPadDir(List<string> files, int targetLength, List<string> exclude = null, bool noLog = true)
|
||||
{
|
||||
if(exclude != null)
|
||||
files = files.Except(exclude).ToList();
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
string fname = Path.GetFileNameWithoutExtension(file);
|
||||
string targetFilename = Path.Combine(Path.GetDirectoryName(file), fname.PadLeft(targetLength, '0') + Path.GetExtension(file));
|
||||
try
|
||||
{
|
||||
if (targetFilename != file)
|
||||
File.Move(file, targetFilename);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if(!noLog)
|
||||
Logger.Log($"Failed to zero-pad {file} => {targetFilename}: {e.Message}", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CheckImageValid (string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
Image img = GetImage(path);
|
||||
if (img.Width > 1 && img.Height > 1)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static string[] GetFilesSorted (string path, bool recursive = false, string pattern = "*")
|
||||
{
|
||||
SearchOption opt = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||
return Directory.GetFiles(path, pattern, opt).OrderBy(x => Path.GetFileName(x)).ToArray();
|
||||
}
|
||||
|
||||
public static string[] GetFilesSorted(string path, string pattern = "*")
|
||||
{
|
||||
return GetFilesSorted(path, false, pattern);
|
||||
}
|
||||
|
||||
public static string[] GetFilesSorted(string path)
|
||||
{
|
||||
return GetFilesSorted(path, false, "*");
|
||||
}
|
||||
|
||||
public static FileInfo[] GetFileInfosSorted(string path, bool recursive = false, string pattern = "*")
|
||||
{
|
||||
SearchOption opt = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||
DirectoryInfo dir = new DirectoryInfo(path);
|
||||
return dir.GetFiles(pattern, opt).OrderBy(x => x.Name).ToArray();
|
||||
}
|
||||
|
||||
public static bool CreateFileIfNotExists (string path)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
File.Create(path).Close();
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Failed to create file at '{path}': {e.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static long GetDirSize(string path, bool recursive, string[] includedExtensions = null)
|
||||
{
|
||||
long size = 0;
|
||||
// Add file sizes.
|
||||
string[] files;
|
||||
StringComparison ignCase = StringComparison.OrdinalIgnoreCase;
|
||||
if (includedExtensions == null)
|
||||
files = Directory.GetFiles(path);
|
||||
else
|
||||
files = Directory.GetFiles(path).Where(file => includedExtensions.Any(x => file.EndsWith(x, ignCase))).ToArray();
|
||||
|
||||
foreach (string file in files)
|
||||
size += new FileInfo(file).Length;
|
||||
|
||||
if (!recursive)
|
||||
return size;
|
||||
|
||||
// Add subdirectory sizes.
|
||||
DirectoryInfo[] dis = new DirectoryInfo(path).GetDirectories();
|
||||
foreach (DirectoryInfo di in dis)
|
||||
size += GetDirSize(di.FullName, true, includedExtensions);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public static long GetFilesize(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new FileInfo(path).Length;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetFilesizeStr (string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return FormatUtils.Bytes(GetFilesize(path));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] GetLastBytes (string path, int startAt, int bytesAmount)
|
||||
{
|
||||
byte[] buffer = new byte[bytesAmount];
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(path, FileMode.Open)))
|
||||
{
|
||||
reader.BaseStream.Seek(startAt, SeekOrigin.Begin);
|
||||
reader.Read(buffer, 0, bytesAmount);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static bool HasBadChars(string str)
|
||||
{
|
||||
return str != str.StripBadChars();
|
||||
}
|
||||
|
||||
public static void OverwriteFileWithText (string path, string text = "THIS IS A DUMMY FILE - DO NOT DELETE ME")
|
||||
{
|
||||
try
|
||||
{
|
||||
File.WriteAllText(path, text);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"OverwriteWithText failed for '{path}': {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
using Flowframes.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using DT = System.DateTime;
|
||||
|
||||
namespace Flowframes
|
||||
{
|
||||
class Logger
|
||||
{
|
||||
public static TextBox textbox;
|
||||
static string file;
|
||||
public const string defaultLogName = "sessionlog";
|
||||
public static long id;
|
||||
|
||||
public static void Log(string s, bool hidden = false, bool replaceLastLine = false, string filename = "")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(s))
|
||||
return;
|
||||
|
||||
Console.WriteLine(s);
|
||||
|
||||
try
|
||||
{
|
||||
if (replaceLastLine)
|
||||
textbox.Text = textbox.Text.Remove(textbox.Text.LastIndexOf(Environment.NewLine));
|
||||
}
|
||||
catch { }
|
||||
|
||||
s = s.Replace("\n", Environment.NewLine);
|
||||
|
||||
if (!hidden && textbox != null)
|
||||
textbox.AppendText((textbox.Text.Length > 1 ? Environment.NewLine : "") + s);
|
||||
|
||||
LogToFile(s, false, filename);
|
||||
}
|
||||
|
||||
public static void LogToFile(string logStr, bool noLineBreak, string filename)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(filename))
|
||||
filename = defaultLogName;
|
||||
|
||||
if (Path.GetExtension(filename) != ".txt")
|
||||
filename = Path.ChangeExtension(filename, "txt");
|
||||
file = Path.Combine(Paths.GetLogPath(), filename);
|
||||
logStr = logStr.Replace(Environment.NewLine, " ").TrimWhitespaces();
|
||||
string time = DT.Now.Month + "-" + DT.Now.Day + "-" + DT.Now.Year + " " + DT.Now.Hour + ":" + DT.Now.Minute + ":" + DT.Now.Second;
|
||||
|
||||
try
|
||||
{
|
||||
if (!noLineBreak)
|
||||
File.AppendAllText(file, $"{Environment.NewLine}[{id}] [{time}]: {logStr}");
|
||||
else
|
||||
File.AppendAllText(file, " " + logStr);
|
||||
id++;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// this if fine, i forgot why
|
||||
}
|
||||
}
|
||||
|
||||
public static void LogIfLastLineDoesNotContainMsg (string s, bool hidden = false, bool replaceLastLine = false, string filename = "")
|
||||
{
|
||||
if (!GetLastLine().Contains(s))
|
||||
Log(s, hidden, replaceLastLine, filename);
|
||||
}
|
||||
|
||||
public static void WriteToFile (string content, bool append, string filename)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(filename))
|
||||
filename = defaultLogName;
|
||||
|
||||
if (Path.GetExtension(filename) != ".txt")
|
||||
filename = Path.ChangeExtension(filename, "txt");
|
||||
|
||||
file = Path.Combine(Paths.GetLogPath(), filename);
|
||||
|
||||
string time = DT.Now.Month + "-" + DT.Now.Day + "-" + DT.Now.Year + " " + DT.Now.Hour + ":" + DT.Now.Minute + ":" + DT.Now.Second;
|
||||
|
||||
try
|
||||
{
|
||||
if (append)
|
||||
File.AppendAllText(file, Environment.NewLine + time + ":" + Environment.NewLine + content);
|
||||
else
|
||||
File.WriteAllText(file, Environment.NewLine + time + ":" + Environment.NewLine + content);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearLogBox ()
|
||||
{
|
||||
textbox.Text = "";
|
||||
}
|
||||
|
||||
public static string GetLastLine ()
|
||||
{
|
||||
string[] lines = textbox.Text.SplitIntoLines();
|
||||
if (lines.Length < 1)
|
||||
return "";
|
||||
return lines.Last();
|
||||
}
|
||||
|
||||
public static void RemoveLastLine ()
|
||||
{
|
||||
textbox.Text = textbox.Text.Remove(textbox.Text.LastIndexOf(Environment.NewLine));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.MiscUtils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.IO
|
||||
{
|
||||
class ModelDownloader
|
||||
{
|
||||
public static async Task<Dictionary<string, string>> GetFilelist (string ai, string model)
|
||||
{
|
||||
var client = new WebClient();
|
||||
string[] fileLines = client.DownloadString(GetMdlFileUrl(ai, model, "md5.txt")).SplitIntoLines();
|
||||
Dictionary<string, string> filesDict = GetDict(fileLines);
|
||||
return filesDict;
|
||||
}
|
||||
|
||||
static string GetMdlUrl (string ai, string model)
|
||||
{
|
||||
string baseUrl = Config.Get("modelsBaseUrl");
|
||||
return Path.Combine(baseUrl, ai.ToLower(), model);
|
||||
}
|
||||
|
||||
static string GetMdlFileUrl(string ai, string model, string file)
|
||||
{
|
||||
return Path.Combine(GetMdlUrl(ai, model), file);
|
||||
}
|
||||
|
||||
static string GetLocalPath(string ai, string model)
|
||||
{
|
||||
return Path.Combine(Paths.GetPkgPath(), ai, model);
|
||||
}
|
||||
|
||||
static async Task DownloadTo (string url, string saveDir, int retries = 3)
|
||||
{
|
||||
string savePath = Path.Combine(saveDir, Path.GetFileName(url));
|
||||
IOUtils.TryDeleteIfExists(savePath);
|
||||
Logger.Log($"Downloading '{url}' to '{savePath}'", true);
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Restart();
|
||||
bool completed = false;
|
||||
int lastProgPercentage = -1;
|
||||
var client = new WebClient();
|
||||
client.DownloadProgressChanged += (sender, args) =>
|
||||
{
|
||||
if (sw.ElapsedMilliseconds > 200 && args.ProgressPercentage != lastProgPercentage)
|
||||
{
|
||||
sw.Restart();
|
||||
lastProgPercentage = args.ProgressPercentage;
|
||||
Logger.Log($"Downloading model file '{Path.GetFileName(url)}'... {args.ProgressPercentage}%", false, true);
|
||||
}
|
||||
};
|
||||
client.DownloadFileCompleted += (sender, args) =>
|
||||
{
|
||||
if (args.Error != null)
|
||||
Logger.Log("Download failed: " + args.Error.Message);
|
||||
completed = true;
|
||||
};
|
||||
client.DownloadFileTaskAsync(url, savePath).ConfigureAwait(false);
|
||||
while (!completed)
|
||||
{
|
||||
if (Interpolate.canceled)
|
||||
{
|
||||
client.CancelAsync();
|
||||
client.Dispose();
|
||||
return;
|
||||
}
|
||||
if (sw.ElapsedMilliseconds > 6000)
|
||||
{
|
||||
client.CancelAsync();
|
||||
if(retries > 0)
|
||||
{
|
||||
await DownloadTo(url, saveDir, retries--);
|
||||
}
|
||||
else
|
||||
{
|
||||
Interpolate.Cancel("Model download failed.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
await Task.Delay(500);
|
||||
}
|
||||
Logger.Log($"Downloaded '{Path.GetFileName(url)}' ({IOUtils.GetFilesize(savePath) / 1024} KB)", true);
|
||||
}
|
||||
|
||||
public static async Task DownloadModelFiles (string ai, string model)
|
||||
{
|
||||
model = model.ToUpper();
|
||||
Logger.Log($"DownloadModelFiles(string ai = {ai}, string model = {model})", true);
|
||||
|
||||
try
|
||||
{
|
||||
string mdlDir = GetLocalPath(ai, model);
|
||||
|
||||
if (AreFilesValid(ai, model))
|
||||
return;
|
||||
|
||||
Logger.Log($"Downloading '{model}' model files...");
|
||||
Directory.CreateDirectory(mdlDir);
|
||||
await DownloadTo(GetMdlFileUrl(ai, model, "md5.txt"), mdlDir);
|
||||
Dictionary<string, string> fileList = await GetFilelist(ai, model);
|
||||
|
||||
foreach (KeyValuePair<string, string> modelFile in fileList)
|
||||
await DownloadTo(GetMdlFileUrl(ai, model, modelFile.Key), mdlDir);
|
||||
|
||||
Logger.Log($"Downloaded \"{model}\" model files.", false, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"DownloadModelFiles Error: {e.Message}\nStack Trace:\n{e.StackTrace}");
|
||||
Interpolate.Cancel($"Error downloading model files: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteAllModels ()
|
||||
{
|
||||
foreach(string modelFolder in GetAllModelFolders())
|
||||
{
|
||||
string size = FormatUtils.Bytes(IOUtils.GetDirSize(modelFolder, true));
|
||||
if (IOUtils.TryDeleteIfExists(modelFolder))
|
||||
Logger.Log($"Deleted cached model '{Path.GetFileName(modelFolder.GetParentDir())}/{Path.GetFileName(modelFolder)}' ({size})");
|
||||
}
|
||||
}
|
||||
|
||||
public static List<string> GetAllModelFolders()
|
||||
{
|
||||
List<string> modelPaths = new List<string>();
|
||||
|
||||
foreach (AI ai in Networks.networks)
|
||||
{
|
||||
string aiPkgFolder = PkgUtils.GetPkgFolder(ai.pkg);
|
||||
string modelsFile = Path.Combine(aiPkgFolder, "models.txt");
|
||||
if (!File.Exists(modelsFile)) continue;
|
||||
|
||||
foreach (string mdl in IOUtils.ReadLines(modelsFile))
|
||||
{
|
||||
string modelName = mdl.Split('-')[0].Remove(" ").Remove(".");
|
||||
string mdlFolder = Path.Combine(aiPkgFolder, modelName);
|
||||
if (!Directory.Exists(mdlFolder)) continue;
|
||||
modelPaths.Add(mdlFolder);
|
||||
}
|
||||
}
|
||||
|
||||
return modelPaths;
|
||||
}
|
||||
|
||||
public static bool AreFilesValid (string ai, string model)
|
||||
{
|
||||
string mdlDir = GetLocalPath(ai, model);
|
||||
|
||||
if (!Directory.Exists(mdlDir))
|
||||
{
|
||||
Logger.Log($"Files for model {model} not valid: {mdlDir} does not exist.", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
string md5FilePath = Path.Combine(mdlDir, "md5.txt");
|
||||
|
||||
if (!File.Exists(md5FilePath) || IOUtils.GetFilesize(md5FilePath) < 32)
|
||||
{
|
||||
Logger.Log($"Files for model {model} not valid: {mdlDir} does not exist or is incomplete.", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
string[] md5Lines = IOUtils.ReadLines(md5FilePath);
|
||||
Dictionary<string, string> filesDict = GetDict(md5Lines);
|
||||
|
||||
foreach(KeyValuePair<string, string> file in filesDict)
|
||||
{
|
||||
string md5 = IOUtils.GetHash(Path.Combine(mdlDir, file.Key), IOUtils.Hash.MD5);
|
||||
if (md5.Trim() != file.Value.Trim())
|
||||
{
|
||||
Logger.Log($"Files for model {model} not valid: MD5 of {file.Key} ({md5.Trim()}) does not equal validation MD5 ({file.Value.Trim()}).", true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static Dictionary<string, string> GetDict (string[] lines, char sep = ':')
|
||||
{
|
||||
Dictionary<string, string> dict = new Dictionary<string, string>();
|
||||
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.Length < 3) continue;
|
||||
string[] keyValuePair = line.Split(':');
|
||||
dict.Add(keyValuePair[0], keyValuePair[1]);
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.IO
|
||||
{
|
||||
class PkgUtils
|
||||
{
|
||||
|
||||
public static string GetPkgFolder (FlowPackage pkg)
|
||||
{
|
||||
return Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(pkg.fileName));
|
||||
}
|
||||
|
||||
public static bool IsInstalled(FlowPackage pkg)
|
||||
{
|
||||
string path = GetPkgFolder(pkg);
|
||||
return (Directory.Exists(path) && IOUtils.GetAmountOfFiles(path, true) > 0);
|
||||
}
|
||||
|
||||
public static bool IsUpToDate(FlowPackage pkg, int minVersion)
|
||||
{
|
||||
return (GetVersion(pkg) >= minVersion);
|
||||
}
|
||||
|
||||
public static int GetVersion (FlowPackage pkg)
|
||||
{
|
||||
string versionFilePath = Path.Combine(GetPkgFolder(pkg), "ver.ini");
|
||||
if (!File.Exists(versionFilePath))
|
||||
return 0;
|
||||
return IOUtils.ReadLines(versionFilePath)[0].Split('#')[0].GetInt();
|
||||
}
|
||||
|
||||
public static bool IsAiAvailable(AI ai, bool msg = true)
|
||||
{
|
||||
Logger.Log("PkgInstaller.IsAiAvailable - Checking for AI " + ai.aiName, true);
|
||||
return IsInstalled(ai.pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
using Flowframes;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.UI;
|
||||
using ImageMagick;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.Magick
|
||||
{
|
||||
|
||||
class Converter
|
||||
{
|
||||
public static async Task Convert (string dir, MagickFormat format, int quality, string ext = "", bool print = true, bool setProgress = true)
|
||||
{
|
||||
var files = IOUtils.GetFilesSorted(dir);
|
||||
if(print) Logger.Log($"Converting {files.Length} files in {dir}");
|
||||
int counter = 0;
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (print) Logger.Log("Converting " + Path.GetFileName(file) + " to " + format.ToString().StripNumbers().ToUpper(), false, true);
|
||||
MagickImage img = new MagickImage(file);
|
||||
img.Format = format;
|
||||
img.Quality = quality;
|
||||
string outpath = file;
|
||||
if (!string.IsNullOrWhiteSpace(ext)) outpath = Path.ChangeExtension(outpath, ext);
|
||||
img.Write(outpath);
|
||||
counter++;
|
||||
if(setProgress)
|
||||
Program.mainForm.SetProgress((int)Math.Round(((float)counter / files.Length) * 100f));
|
||||
await Task.Delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task MakeBinary (string inputDir, string outputDir, bool print = true, bool setProgress = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var files = IOUtils.GetFilesSorted(inputDir);
|
||||
if (print) Logger.Log($"Processing alpha channel...");
|
||||
Directory.CreateDirectory(outputDir);
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Restart();
|
||||
int counter = 0;
|
||||
foreach (string file in files)
|
||||
{
|
||||
MagickImage img = new MagickImage(file);
|
||||
img.Format = MagickFormat.Png24;
|
||||
img.Quality = 10;
|
||||
img.Threshold(new Percentage(75));
|
||||
|
||||
string outPath = Path.Combine(outputDir, Path.GetFileName(file));
|
||||
img.Write(outPath);
|
||||
counter++;
|
||||
if (sw.ElapsedMilliseconds > 250)
|
||||
{
|
||||
if (setProgress)
|
||||
Program.mainForm.SetProgress((int)Math.Round(((float)counter / files.Length) * 100f));
|
||||
await Task.Delay(1);
|
||||
sw.Restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("MakeBinary Error: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ExtractAlpha (string inputDir, string outputDir, bool print = true, bool setProgress = true, bool removeInputAlpha = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var files = IOUtils.GetFilesSorted(inputDir);
|
||||
if (print) Logger.Log($"Extracting alpha channel from images...");
|
||||
Directory.CreateDirectory(outputDir);
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Restart();
|
||||
int counter = 0;
|
||||
foreach (string file in files)
|
||||
{
|
||||
MagickImage alphaImg = new MagickImage(file);
|
||||
|
||||
if (removeInputAlpha)
|
||||
{
|
||||
MagickImage rgbImg = alphaImg;
|
||||
rgbImg.Format = MagickFormat.Png24;
|
||||
rgbImg.Quality = 10;
|
||||
MagickImage bg = new MagickImage(MagickColors.Black, rgbImg.Width, rgbImg.Height);
|
||||
bg.Composite(rgbImg, CompositeOperator.Over);
|
||||
rgbImg = bg;
|
||||
rgbImg.Write(file);
|
||||
}
|
||||
|
||||
alphaImg.Format = MagickFormat.Png24;
|
||||
alphaImg.Quality = 10;
|
||||
|
||||
alphaImg.FloodFill(MagickColors.None, 0, 0); // Fill the image with a transparent background
|
||||
alphaImg.InverseOpaque(MagickColors.None, MagickColors.White); // Change all the pixels that are not transparent to white.
|
||||
alphaImg.ColorAlpha(MagickColors.Black); // Change the transparent pixels to black.
|
||||
|
||||
string outPath = Path.Combine(outputDir, Path.GetFileName(file));
|
||||
alphaImg.Write(outPath);
|
||||
counter++;
|
||||
if (sw.ElapsedMilliseconds > 250)
|
||||
{
|
||||
if (setProgress)
|
||||
Program.mainForm.SetProgress((int)Math.Round(((float)counter / files.Length) * 100f));
|
||||
await Task.Delay(1);
|
||||
sw.Restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("ExtractAlpha Error: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task Preprocess (string dir, bool setProgress = true)
|
||||
{
|
||||
var files = IOUtils.GetFilesSorted(dir);
|
||||
Logger.Log($"Preprocessing {files} files in {dir}");
|
||||
int counter = 0;
|
||||
foreach (string file in files)
|
||||
{
|
||||
//Logger.Log("Converting " + Path.GetFileName(file) + " to " + format, false, true);
|
||||
MagickImage img = new MagickImage(file);
|
||||
//img.Format = MagickFormat.Bmp;
|
||||
//img.Write(file);
|
||||
//img = new MagickImage(file);
|
||||
img.Format = MagickFormat.Png24;
|
||||
img.Quality = 10;
|
||||
counter++;
|
||||
if (setProgress)
|
||||
Program.mainForm.SetProgress((int)Math.Round(((float)counter / files.Length) * 100f));
|
||||
await Task.Delay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Flowframes.IO;
|
||||
using ImageMagick;
|
||||
using Flowframes.OS;
|
||||
using Flowframes.Data;
|
||||
using System.Drawing;
|
||||
using Paths = Flowframes.IO.Paths;
|
||||
|
||||
namespace Flowframes.Magick
|
||||
{
|
||||
class Dedupe
|
||||
{
|
||||
public enum Mode { None, Info, Enabled, Auto }
|
||||
public static Mode currentMode;
|
||||
public static float currentThreshold;
|
||||
|
||||
public static async Task Run(string path, bool testRun = false, bool setStatus = true)
|
||||
{
|
||||
if (path == null || !Directory.Exists(path) || Interpolate.canceled)
|
||||
return;
|
||||
|
||||
currentMode = Mode.Auto;
|
||||
|
||||
if(setStatus)
|
||||
Program.mainForm.SetStatus("Running frame de-duplication");
|
||||
|
||||
currentThreshold = Config.GetFloat("dedupThresh");
|
||||
Logger.Log("Running accurate frame de-duplication...");
|
||||
|
||||
if (currentMode == Mode.Enabled || currentMode == Mode.Auto)
|
||||
await RemoveDupeFrames(path, currentThreshold, "png", testRun, false, (currentMode == Mode.Auto));
|
||||
}
|
||||
|
||||
public static Dictionary<string, MagickImage> imageCache = new Dictionary<string, MagickImage>();
|
||||
static MagickImage GetImage(string path)
|
||||
{
|
||||
bool allowCaching = true;
|
||||
|
||||
if (!allowCaching)
|
||||
return new MagickImage(path);
|
||||
|
||||
if (!imageCache.ContainsKey(path))
|
||||
imageCache.Add(path, new MagickImage(path));
|
||||
|
||||
return imageCache[path];
|
||||
}
|
||||
|
||||
public static void ClearCache ()
|
||||
{
|
||||
imageCache.Clear();
|
||||
}
|
||||
|
||||
public static async Task RemoveDupeFrames(string path, float threshold, string ext, bool testRun = false, bool debugLog = false, bool skipIfNoDupes = false)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Restart();
|
||||
Logger.Log("Removing duplicate frames - Threshold: " + threshold.ToString("0.00"));
|
||||
|
||||
FileInfo[] framePaths = IOUtils.GetFileInfosSorted(path, false, "*." + ext);
|
||||
List<string> framesToDelete = new List<string>();
|
||||
|
||||
int bufferSize = await GetBufferSize();
|
||||
|
||||
int currentOutFrame = 1;
|
||||
int currentDupeCount = 0;
|
||||
|
||||
int statsFramesKept = 0;
|
||||
int statsFramesDeleted = 0;
|
||||
|
||||
int skipAfterNoDupesFrames = Config.GetInt("autoDedupFrames");
|
||||
bool hasEncounteredAnyDupes = false;
|
||||
bool skipped = false;
|
||||
|
||||
bool hasReachedEnd = false;
|
||||
|
||||
string fileContent = "";
|
||||
|
||||
for (int i = 0; i < framePaths.Length; i++) // Loop through frames
|
||||
{
|
||||
if (hasReachedEnd)
|
||||
break;
|
||||
|
||||
string frame1 = framePaths[i].FullName;
|
||||
|
||||
int compareWithIndex = i + 1;
|
||||
|
||||
while (true) // Loop dupes
|
||||
{
|
||||
//compareWithIndex++;
|
||||
if (compareWithIndex >= framePaths.Length)
|
||||
{
|
||||
hasReachedEnd = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (framesToDelete.Contains(framePaths[compareWithIndex].FullName) || !File.Exists(framePaths[compareWithIndex].FullName))
|
||||
{
|
||||
//Logger.Log($"Frame {compareWithIndex} was already deleted - skipping");
|
||||
compareWithIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
string frame2 = framePaths[compareWithIndex].FullName;
|
||||
float diff = GetDifference(frame1, frame2);
|
||||
|
||||
if (diff < threshold) // Is a duped frame.
|
||||
{
|
||||
if (!testRun)
|
||||
{
|
||||
framesToDelete.Add(frame2);
|
||||
if (debugLog) Logger.Log("[Deduplication] Deleted " + Path.GetFileName(frame2));
|
||||
hasEncounteredAnyDupes = true;
|
||||
}
|
||||
statsFramesDeleted++;
|
||||
currentDupeCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fileContent += $"{Path.GetFileNameWithoutExtension(framePaths[i].Name)}:{currentDupeCount}\n";
|
||||
statsFramesKept++;
|
||||
currentOutFrame++;
|
||||
currentDupeCount = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sw.ElapsedMilliseconds >= 500 || (i+1) == framePaths.Length) // Print every 0.5s (or when done)
|
||||
{
|
||||
sw.Restart();
|
||||
Logger.Log($"[Deduplication] Running de-duplication ({i}/{framePaths.Length}), deleted {statsFramesDeleted} ({(((float)statsFramesDeleted / framePaths.Length) * 100f).ToString("0")}%) duplicate frames so far...", false, true);
|
||||
Program.mainForm.SetProgress((int)Math.Round(((float)i / framePaths.Length) * 100f));
|
||||
if (imageCache.Count > bufferSize || (imageCache.Count > 50 && OSUtils.GetFreeRamMb() < 3500))
|
||||
ClearCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// int oldIndex = -1; // TODO: Compare with 1st to fix loops?
|
||||
// if (i >= framePaths.Length) // If this is the last frame, compare with 1st to avoid OutOfRange error
|
||||
// {
|
||||
// oldIndex = i;
|
||||
// i = 0;
|
||||
// }
|
||||
|
||||
if(i % 3 == 0)
|
||||
await Task.Delay(1);
|
||||
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
if (!testRun && skipIfNoDupes && !hasEncounteredAnyDupes && skipAfterNoDupesFrames > 0 && i >= skipAfterNoDupesFrames)
|
||||
{
|
||||
skipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string frame in framesToDelete)
|
||||
IOUtils.TryDeleteIfExists(frame);
|
||||
|
||||
string testStr = testRun ? " [TestRun]" : "";
|
||||
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
int framesLeft = IOUtils.GetAmountOfFiles(path, false, $"*.png");
|
||||
int framesDeleted = framePaths.Length - framesLeft;
|
||||
float percentDeleted = ((float)framesDeleted / framePaths.Length) * 100f;
|
||||
string keptPercent = $"{(100f - percentDeleted).ToString("0.0")}%";
|
||||
|
||||
if (skipped)
|
||||
Logger.Log($"[Deduplication] First {skipAfterNoDupesFrames} frames did not have any duplicates - Skipping the rest!", false, true);
|
||||
else
|
||||
Logger.Log($"[Deduplication]{testStr} Done. Kept {framesLeft} ({keptPercent}) frames, deleted {framesDeleted} frames.", false, true);
|
||||
|
||||
if (statsFramesKept <= 0)
|
||||
Interpolate.Cancel("No frames were left after de-duplication!\n\nTry decreasing the de-duplication threshold.");
|
||||
}
|
||||
|
||||
static float GetDifference (string img1Path, string img2Path)
|
||||
{
|
||||
MagickImage img2 = GetImage(img2Path);
|
||||
MagickImage img1 = GetImage(img1Path);
|
||||
|
||||
double err = img1.Compare(img2, ErrorMetric.Fuzz);
|
||||
float errPercent = (float)err * 100f;
|
||||
return errPercent;
|
||||
}
|
||||
|
||||
static async Task<int> GetBufferSize ()
|
||||
{
|
||||
Size res = await Interpolate.current.GetScaledRes();
|
||||
long pixels = res.Width * res.Height; // 4K = 8294400, 1440p = 3686400, 1080p = 2073600, 720p = 921600, 540p = 518400, 360p = 230400
|
||||
int bufferSize = 100;
|
||||
if (pixels < 518400) bufferSize = 1800;
|
||||
if (pixels >= 518400) bufferSize = 1400;
|
||||
if (pixels >= 921600) bufferSize = 800;
|
||||
if (pixels >= 2073600) bufferSize = 400;
|
||||
if (pixels >= 3686400) bufferSize = 200;
|
||||
if (pixels >= 8294400) bufferSize = 100;
|
||||
if (pixels == 0) bufferSize = 100;
|
||||
Logger.Log($"Using magick dedupe buffer size {bufferSize} for frame resolution {res.Width}x{res.Height}", true);
|
||||
return bufferSize;
|
||||
}
|
||||
|
||||
public static async Task CreateDupesFile (string framesPath, int lastFrameNum)
|
||||
{
|
||||
string infoFile = Path.Combine(framesPath.GetParentDir(), $"dupes.ini");
|
||||
string fileContent = "";
|
||||
|
||||
FileInfo[] frameFiles = IOUtils.GetFileInfosSorted(framesPath, false, "*.png");
|
||||
|
||||
for(int i = 0; i < frameFiles.Length; i++)
|
||||
{
|
||||
bool isLastItem = (i + 1) == frameFiles.Length;
|
||||
|
||||
int frameNum1 = frameFiles[i].Name.GetInt();
|
||||
int frameNum2 = isLastItem ? lastFrameNum : frameFiles[i+1].Name.GetInt();
|
||||
|
||||
int diff = frameNum2 - frameNum1;
|
||||
int dupes = diff - 1;
|
||||
|
||||
//if (File.Exists(Path.Combine(framesPath.GetParentDir(), Paths.scenesDir, frameFiles[i].Name)))
|
||||
// dupes = 0;
|
||||
|
||||
fileContent += $"{Path.GetFileNameWithoutExtension(frameFiles[i].Name)}:{dupes}\n";
|
||||
}
|
||||
|
||||
File.WriteAllText(infoFile, fileContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
using Flowframes.Media;
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.MiscUtils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.Main
|
||||
{
|
||||
class AutoEncode
|
||||
{
|
||||
static string interpFramesFolder;
|
||||
static string videoChunksFolder;
|
||||
public static int chunkSize = 125; // Encode every n frames
|
||||
public static int safetyBufferFrames = 90; // Ignore latest n frames to avoid using images that haven't been fully encoded yet
|
||||
public static string[] interpFramesLines;
|
||||
public static List<int> encodedFrameLines = new List<int>();
|
||||
public static List<int> unencodedFrameLines = new List<int>();
|
||||
|
||||
public static bool busy;
|
||||
|
||||
public static bool paused;
|
||||
|
||||
public static void UpdateChunkAndBufferSizes ()
|
||||
{
|
||||
chunkSize = GetChunkSize((IOUtils.GetAmountOfFiles(Interpolate.current.framesFolder, false, "*.png") * Interpolate.current.interpFactor).RoundToInt());
|
||||
bool isNcnn = Interpolate.current.ai.aiName.ToUpper().Contains("NCNN");
|
||||
safetyBufferFrames = isNcnn ? Config.GetInt("autoEncSafeBufferNcnn", 90) : Config.GetInt("autoEncSafeBufferCuda", 30); // Use bigger safety buffer for NCNN
|
||||
}
|
||||
|
||||
public static async Task MainLoop(string interpFramesPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
UpdateChunkAndBufferSizes();
|
||||
|
||||
interpFramesFolder = interpFramesPath;
|
||||
videoChunksFolder = Path.Combine(interpFramesPath.GetParentDir(), Paths.chunksDir);
|
||||
if (Interpolate.currentlyUsingAutoEnc)
|
||||
Directory.CreateDirectory(videoChunksFolder);
|
||||
|
||||
encodedFrameLines.Clear();
|
||||
unencodedFrameLines.Clear();
|
||||
|
||||
Logger.Log($"[AutoEnc] Starting AutoEncode MainLoop - Chunk Size: {chunkSize} Frames - Safety Buffer: {safetyBufferFrames} Frames", true);
|
||||
int videoIndex = 1;
|
||||
string encFile = Path.Combine(interpFramesPath.GetParentDir(), Paths.GetFrameOrderFilename(Interpolate.current.interpFactor));
|
||||
interpFramesLines = IOUtils.ReadLines(encFile).Select(x => x.Split('/').Last().Remove("'").Split('#').First()).ToArray(); // Array with frame filenames
|
||||
|
||||
while (!Interpolate.canceled && GetInterpFramesAmount() < 2)
|
||||
await Task.Delay(2000);
|
||||
|
||||
int lastEncodedFrameNum = 0;
|
||||
|
||||
while (HasWorkToDo()) // Loop while proc is running and not all frames have been encoded
|
||||
{
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
if (paused)
|
||||
{
|
||||
//Logger.Log("autoenc paused");
|
||||
await Task.Delay(200);
|
||||
continue;
|
||||
}
|
||||
|
||||
unencodedFrameLines.Clear();
|
||||
|
||||
for (int vfrLine = lastEncodedFrameNum; vfrLine < interpFramesLines.Length; vfrLine++)
|
||||
unencodedFrameLines.Add(vfrLine);
|
||||
|
||||
bool aiRunning = !AiProcess.currentAiProcess.HasExited;
|
||||
|
||||
if (unencodedFrameLines.Count > 0 && (unencodedFrameLines.Count >= (chunkSize + safetyBufferFrames) || !aiRunning)) // Encode every n frames, or after process has exited
|
||||
{
|
||||
List<int> frameLinesToEncode = aiRunning ? unencodedFrameLines.Take(chunkSize).ToList() : unencodedFrameLines; // Take all remaining frames if process is done
|
||||
|
||||
string lastOfChunk = Path.Combine(interpFramesPath, interpFramesLines[frameLinesToEncode.Last()]);
|
||||
|
||||
if (!File.Exists(lastOfChunk))
|
||||
{
|
||||
await Task.Delay(500);
|
||||
continue;
|
||||
}
|
||||
|
||||
busy = true;
|
||||
string outpath = Path.Combine(videoChunksFolder, "chunks", $"{videoIndex.ToString().PadLeft(4, '0')}{FFmpegUtils.GetExt(Interpolate.current.outMode)}");
|
||||
int firstLineNum = frameLinesToEncode.First();
|
||||
int lastLineNum = frameLinesToEncode.Last();
|
||||
Logger.Log($"[AutoEnc] Encoding Chunk #{videoIndex} to '{outpath}' using line {firstLineNum} ({Path.GetFileName(interpFramesLines[firstLineNum])}) through {lastLineNum} ({Path.GetFileName(Path.GetFileName(interpFramesLines[frameLinesToEncode.Last()]))})", true, false, "ffmpeg");
|
||||
|
||||
await CreateVideo.EncodeChunk(outpath, Interpolate.current.outMode, firstLineNum, frameLinesToEncode.Count);
|
||||
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
if (aiRunning && Config.GetInt("autoEncMode") == 2)
|
||||
Task.Run(() => DeleteOldFramesAsync(interpFramesPath, frameLinesToEncode));
|
||||
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
encodedFrameLines.AddRange(frameLinesToEncode);
|
||||
|
||||
Logger.Log("Done Encoding Chunk #" + videoIndex, true, false, "ffmpeg");
|
||||
lastEncodedFrameNum = (frameLinesToEncode.Last() + 1 );
|
||||
|
||||
videoIndex++;
|
||||
busy = false;
|
||||
}
|
||||
await Task.Delay(50);
|
||||
}
|
||||
|
||||
if (Interpolate.canceled) return;
|
||||
await CreateVideo.ChunksToVideos(Interpolate.current.tempFolder, videoChunksFolder, Interpolate.current.outFilename);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"AutoEnc Error: {e.Message}. Stack Trace:\n{e.StackTrace}");
|
||||
Interpolate.Cancel("Auto-Encode encountered an error.");
|
||||
}
|
||||
}
|
||||
|
||||
static async Task DeleteOldFramesAsync (string interpFramesPath, List<int> frameLinesToEncode)
|
||||
{
|
||||
Logger.Log("[AutoEnc] Starting DeleteOldFramesAsync.", true, false, "ffmpeg");
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Restart();
|
||||
int counter = 0;
|
||||
|
||||
foreach (int frame in frameLinesToEncode)
|
||||
{
|
||||
if (!FrameIsStillNeeded(interpFramesLines[frame], frame)) // Make sure frames are no longer needed (for dupes) before deleting!
|
||||
{
|
||||
string framePath = Path.Combine(interpFramesPath, interpFramesLines[frame]);
|
||||
IOUtils.OverwriteFileWithText(framePath); // Overwrite to save space without breaking progress counter
|
||||
}
|
||||
|
||||
if(counter % 1000 == 0)
|
||||
await Task.Delay(1);
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
Logger.Log("[AutoEnc] DeleteOldFramesAsync finished in " + FormatUtils.TimeSw(sw), true, false, "ffmpeg");
|
||||
}
|
||||
|
||||
static bool FrameIsStillNeeded (string frameName, int frameIndex)
|
||||
{
|
||||
if ((frameIndex + 1) < interpFramesLines.Length && interpFramesLines[frameIndex+1].Contains(frameName))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool HasWorkToDo ()
|
||||
{
|
||||
if (Interpolate.canceled || interpFramesFolder == null) return false;
|
||||
// Logger.Log($"HasWorkToDo - Process Running: {(AiProcess.currentAiProcess != null && !AiProcess.currentAiProcess.HasExited)} - encodedFrameLines.Count: {encodedFrameLines.Count} - interpFramesLines.Length: {interpFramesLines.Length}");
|
||||
return ((AiProcess.currentAiProcess != null && !AiProcess.currentAiProcess.HasExited) || encodedFrameLines.Count < interpFramesLines.Length);
|
||||
}
|
||||
|
||||
static int GetChunkSize(int targetFramesAmount)
|
||||
{
|
||||
if (targetFramesAmount > 50000) return 2400;
|
||||
if (targetFramesAmount > 20000) return 1200;
|
||||
if (targetFramesAmount > 5000) return 600;
|
||||
if (targetFramesAmount > 1000) return 300;
|
||||
return 150;
|
||||
}
|
||||
|
||||
static int GetInterpFramesAmount()
|
||||
{
|
||||
return IOUtils.GetAmountOfFiles(interpFramesFolder, false, $"*.{InterpolateUtils.GetOutExt()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
using Flowframes.Forms;
|
||||
using Flowframes.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.Main
|
||||
{
|
||||
class BatchProcessing
|
||||
{
|
||||
public static bool stopped = false;
|
||||
|
||||
public static BatchForm currentBatchForm;
|
||||
public static bool busy = false;
|
||||
|
||||
public static async void Start()
|
||||
{
|
||||
if (Config.GetBool("clearLogOnInput"))
|
||||
Logger.ClearLogBox();
|
||||
|
||||
stopped = false;
|
||||
Program.mainForm.SetTab("preview");
|
||||
int initTaskCount = Program.batchQueue.Count;
|
||||
|
||||
for (int i = 0; i < initTaskCount; i++)
|
||||
{
|
||||
if (!stopped && Program.batchQueue.Count > 0)
|
||||
{
|
||||
Logger.Log($"[Queue] Running queue task {i + 1}/{initTaskCount}, {Program.batchQueue.Count} tasks left.");
|
||||
await RunEntry(Program.batchQueue.Peek());
|
||||
if (currentBatchForm != null)
|
||||
currentBatchForm.RefreshGui();
|
||||
}
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
Logger.Log("[Queue] Finished queue processing.");
|
||||
SetBusy(false);
|
||||
Program.mainForm.SetTab("interpolation");
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
static async Task RunEntry(InterpSettings entry)
|
||||
{
|
||||
if (!EntryIsValid(entry))
|
||||
{
|
||||
Logger.Log("[Queue] Skipping entry because it's invalid.");
|
||||
Program.batchQueue.Dequeue();
|
||||
return;
|
||||
}
|
||||
|
||||
string fname = Path.GetFileName(entry.inPath);
|
||||
if (IOUtils.IsPathDirectory(entry.inPath)) fname = Path.GetDirectoryName(entry.inPath);
|
||||
Logger.Log($"[Queue] Processing {fname} ({entry.interpFactor}x {entry.ai.aiNameShort}).");
|
||||
|
||||
SetBusy(true);
|
||||
Program.mainForm.LoadBatchEntry(entry); // Load entry into GUI
|
||||
Interpolate.current = entry;
|
||||
Program.mainForm.runBtn_Click(null, null);
|
||||
|
||||
await Task.Delay(2000);
|
||||
while (Program.busy)
|
||||
await Task.Delay(1000);
|
||||
|
||||
SetBusy(false);
|
||||
|
||||
Program.batchQueue.Dequeue();
|
||||
Logger.Log($"[Queue] Done processing {fname} ({entry.interpFactor}x {entry.ai.aiNameShort}).");
|
||||
}
|
||||
|
||||
static void SetBusy(bool state)
|
||||
{
|
||||
busy = state;
|
||||
if (currentBatchForm != null)
|
||||
currentBatchForm.SetWorking(state);
|
||||
Program.mainForm.SetWorking(state);
|
||||
Program.mainForm.GetMainTabControl().Enabled = !state; // Lock GUI
|
||||
}
|
||||
|
||||
static bool EntryIsValid(InterpSettings entry)
|
||||
{
|
||||
|
||||
if (entry.inPath == null || (IOUtils.IsPathDirectory(entry.inPath) && !Directory.Exists(entry.inPath)) || (!IOUtils.IsPathDirectory(entry.inPath) && !File.Exists(entry.inPath)))
|
||||
{
|
||||
Logger.Log("[Queue] Can't process queue entry: Input path is invalid.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry.outPath == null || !Directory.Exists(entry.outPath))
|
||||
{
|
||||
Logger.Log("[Queue] Can't process queue entry: Output path is invalid.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PkgUtils.IsAiAvailable(entry.ai))
|
||||
{
|
||||
Logger.Log("[Queue] Can't process queue entry: Selected AI is not available.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
using Flowframes;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Magick;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.OS;
|
||||
using Flowframes.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Padding = Flowframes.Data.Padding;
|
||||
using i = Flowframes.Interpolate;
|
||||
using System.Diagnostics;
|
||||
using Flowframes.Media;
|
||||
|
||||
namespace Flowframes.Main
|
||||
{
|
||||
class CreateVideo
|
||||
{
|
||||
static string currentOutFile; // Keeps track of the out file, in case it gets renamed (FPS limiting, looping, etc) before finishing export
|
||||
|
||||
public static async Task Export(string path, string outPath, i.OutMode mode, bool stepByStep)
|
||||
{
|
||||
if (!mode.ToString().ToLower().Contains("vid")) // Copy interp frames out of temp folder and skip video export for image seq export
|
||||
{
|
||||
try
|
||||
{
|
||||
await CopyOutputFrames(path, Path.GetFileNameWithoutExtension(outPath), stepByStep);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.Log("Failed to move interp frames folder: " + e.Message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (IOUtils.GetAmountOfFiles(path, false, $"*.{InterpolateUtils.GetOutExt()}") <= 1)
|
||||
{
|
||||
i.Cancel("Output folder does not contain frames - An error must have occured during interpolation!", AiProcess.hasShownError);
|
||||
return;
|
||||
}
|
||||
await Task.Delay(10);
|
||||
Program.mainForm.SetStatus("Creating output video from frames...");
|
||||
try
|
||||
{
|
||||
float maxFps = Config.GetFloat("maxFps");
|
||||
bool fpsLimit = maxFps != 0 && i.current.outFps > maxFps;
|
||||
|
||||
bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt("maxFpsMode") == 0;
|
||||
|
||||
if(!dontEncodeFullFpsVid)
|
||||
await Encode(mode, path, outPath, i.current.outFps);
|
||||
|
||||
if (fpsLimit)
|
||||
await Encode(mode, path, outPath.FilenameSuffix($"-{maxFps.ToStringDot("0.00")}fps"), i.current.outFps, maxFps);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("FramesToVideo Error: " + e.Message, false);
|
||||
MessageBox.Show("An error occured while trying to convert the interpolated frames to a video.\nCheck the log for details.");
|
||||
}
|
||||
}
|
||||
|
||||
static async Task CopyOutputFrames (string framesPath, string folderName, bool dontMove)
|
||||
{
|
||||
Program.mainForm.SetStatus("Copying output frames...");
|
||||
string copyPath = Path.Combine(i.current.outPath, folderName);
|
||||
Logger.Log($"Moving output frames to '{copyPath}'");
|
||||
IOUtils.TryDeleteIfExists(copyPath);
|
||||
IOUtils.CreateDir(copyPath);
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Restart();
|
||||
|
||||
string vfrFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(i.current.interpFactor));
|
||||
string[] vfrLines = IOUtils.ReadLines(vfrFile);
|
||||
|
||||
for (int idx = 1; idx <= vfrLines.Length; idx++)
|
||||
{
|
||||
string line = vfrLines[idx-1];
|
||||
string inFilename = line.Split('/').Last().Remove("'").RemoveComments();
|
||||
string framePath = Path.Combine(framesPath, inFilename);
|
||||
string outFilename = Path.Combine(copyPath, idx.ToString().PadLeft(Padding.interpFrames, '0')) + Path.GetExtension(framePath);
|
||||
|
||||
if (dontMove || ((idx < vfrLines.Length) && vfrLines[idx].Contains(inFilename))) // If file is re-used in the next line, copy instead of move
|
||||
File.Copy(framePath, outFilename);
|
||||
else
|
||||
File.Move(framePath, outFilename);
|
||||
|
||||
if (sw.ElapsedMilliseconds >= 500 || idx == vfrLines.Length)
|
||||
{
|
||||
sw.Restart();
|
||||
Logger.Log($"Moving output frames to '{Path.GetFileName(copyPath)}' - {idx}/{vfrLines.Length}", false, true);
|
||||
await Task.Delay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async Task Encode(i.OutMode mode, string framesPath, string outPath, float fps, float resampleFps = -1)
|
||||
{
|
||||
currentOutFile = outPath;
|
||||
string vfrFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(i.current.interpFactor));
|
||||
|
||||
if (mode == i.OutMode.VidGif)
|
||||
{
|
||||
await FfmpegEncode.FramesToGifConcat(vfrFile, outPath, fps, true, Config.GetInt("gifColors"), resampleFps);
|
||||
}
|
||||
else
|
||||
{
|
||||
await FfmpegEncode.FramesToVideoConcat(vfrFile, outPath, mode, fps, resampleFps);
|
||||
await MergeAudio(i.current.inPath, outPath);
|
||||
await Loop(currentOutFile, GetLoopTimes());
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ChunksToVideos(string tempFolder, string chunksFolder, string baseOutPath)
|
||||
{
|
||||
if (IOUtils.GetAmountOfFiles(chunksFolder, true, $"*{FFmpegUtils.GetExt(i.current.outMode)}") < 1)
|
||||
{
|
||||
i.Cancel("No video chunks found - An error must have occured during chunk encoding!", AiProcess.hasShownError);
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Delay(10);
|
||||
Program.mainForm.SetStatus("Merging video chunks...");
|
||||
try
|
||||
{
|
||||
DirectoryInfo chunksDir = new DirectoryInfo(chunksFolder);
|
||||
foreach(DirectoryInfo dir in chunksDir.GetDirectories())
|
||||
{
|
||||
string suffix = dir.Name.Replace("chunks", "");
|
||||
string tempConcatFile = Path.Combine(tempFolder, $"chunks-concat{suffix}.ini");
|
||||
string concatFileContent = "";
|
||||
foreach (string vid in IOUtils.GetFilesSorted(dir.FullName))
|
||||
concatFileContent += $"file '{Paths.chunksDir}/{dir.Name}/{Path.GetFileName(vid)}'\n";
|
||||
File.WriteAllText(tempConcatFile, concatFileContent);
|
||||
|
||||
Logger.Log($"CreateVideo: Running MergeChunks() for vfrFile '{Path.GetFileName(tempConcatFile)}'", true);
|
||||
await MergeChunks(tempConcatFile, baseOutPath.FilenameSuffix(suffix));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("ChunksToVideo Error: " + e.Message, false);
|
||||
MessageBox.Show("An error occured while trying to merge the video chunks.\nCheck the log for details.");
|
||||
}
|
||||
}
|
||||
|
||||
static async Task MergeChunks(string vfrFile, string outPath)
|
||||
{
|
||||
await FfmpegCommands.ConcatVideos(vfrFile, outPath, -1);
|
||||
await MergeAudio(i.current.inPath, outPath);
|
||||
await Loop(outPath, GetLoopTimes());
|
||||
}
|
||||
|
||||
public static async Task EncodeChunk(string outPath, i.OutMode mode, int firstFrameNum, int framesAmount)
|
||||
{
|
||||
string vfrFileOriginal = Path.Combine(i.current.tempFolder, Paths.GetFrameOrderFilename(i.current.interpFactor));
|
||||
string vfrFile = Path.Combine(i.current.tempFolder, Paths.GetFrameOrderFilenameChunk(firstFrameNum, firstFrameNum + framesAmount));
|
||||
File.WriteAllLines(vfrFile, IOUtils.ReadLines(vfrFileOriginal).Skip(firstFrameNum).Take(framesAmount));
|
||||
|
||||
float maxFps = Config.GetFloat("maxFps");
|
||||
bool fpsLimit = maxFps != 0 && i.current.outFps > maxFps;
|
||||
|
||||
bool dontEncodeFullFpsVid = fpsLimit && Config.GetInt("maxFpsMode") == 0;
|
||||
|
||||
if(!dontEncodeFullFpsVid)
|
||||
await FfmpegEncode.FramesToVideoConcat(vfrFile, outPath, mode, i.current.outFps, AvProcess.LogMode.Hidden, true); // Encode
|
||||
|
||||
if (fpsLimit)
|
||||
{
|
||||
string filename = Path.GetFileName(outPath);
|
||||
string newParentDir = outPath.GetParentDir() + "-" + maxFps.ToStringDot("0.00") + "fps";
|
||||
outPath = Path.Combine(newParentDir, filename);
|
||||
await FfmpegEncode.FramesToVideoConcat(vfrFile, outPath, mode, i.current.outFps, maxFps, AvProcess.LogMode.Hidden, true); // Encode with limited fps
|
||||
}
|
||||
}
|
||||
|
||||
static async Task Loop(string outPath, int looptimes)
|
||||
{
|
||||
if (looptimes < 1 || !Config.GetBool("enableLoop")) return;
|
||||
Logger.Log($"Looping {looptimes} {(looptimes == 1 ? "time" : "times")} to reach target length of {Config.GetInt("minOutVidLength")}s...");
|
||||
await FfmpegCommands.LoopVideo(outPath, looptimes, Config.GetInt("loopMode") == 0);
|
||||
}
|
||||
|
||||
static int GetLoopTimes()
|
||||
{
|
||||
int times = -1;
|
||||
int minLength = Config.GetInt("minOutVidLength");
|
||||
int minFrameCount = (minLength * i.current.outFps).RoundToInt();
|
||||
int outFrames = (i.currentInputFrameCount * i.current.interpFactor).RoundToInt();
|
||||
if (outFrames / i.current.outFps < minLength)
|
||||
times = (int)Math.Ceiling((double)minFrameCount / (double)outFrames);
|
||||
times--; // Not counting the 1st play (0 loops)
|
||||
if (times <= 0) return -1; // Never try to loop 0 times, idk what would happen, probably nothing
|
||||
return times;
|
||||
}
|
||||
|
||||
public static async Task MergeAudio(string inputPath, string outVideo, int looptimes = -1)
|
||||
{
|
||||
if (!Config.GetBool("keepAudio")) return;
|
||||
try
|
||||
{
|
||||
string audioFileBasePath = Path.Combine(i.current.tempFolder, "audio");
|
||||
|
||||
if (inputPath != null && IOUtils.IsPathDirectory(inputPath) && !File.Exists(IOUtils.GetAudioFile(audioFileBasePath))) // Try loading out of same folder as input if input is a folder
|
||||
audioFileBasePath = Path.Combine(i.current.tempFolder.GetParentDir(), "audio");
|
||||
|
||||
if (!File.Exists(IOUtils.GetAudioFile(audioFileBasePath)))
|
||||
await FfmpegAudioAndMetadata.ExtractAudio(inputPath, audioFileBasePath); // Extract from sourceVideo to audioFile unless it already exists
|
||||
|
||||
if (!File.Exists(IOUtils.GetAudioFile(audioFileBasePath)) || new FileInfo(IOUtils.GetAudioFile(audioFileBasePath)).Length < 4096)
|
||||
{
|
||||
Logger.Log("No compatible audio stream found.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
await FfmpegAudioAndMetadata.MergeAudioAndSubs(outVideo, IOUtils.GetAudioFile(audioFileBasePath), i.current.tempFolder); // Merge from audioFile into outVideo
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Failed to copy audio!");
|
||||
Logger.Log("MergeAudio() Exception: " + e.Message, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.Main
|
||||
{
|
||||
class FrameOrder
|
||||
{
|
||||
static Stopwatch benchmark = new Stopwatch();
|
||||
|
||||
public static async Task CreateFrameOrderFile(string framesPath, bool loopEnabled, float times)
|
||||
{
|
||||
Logger.Log("Generating frame order information...");
|
||||
try
|
||||
{
|
||||
benchmark.Restart();
|
||||
await CreateEncFile(framesPath, loopEnabled, times, false);
|
||||
Logger.Log($"Generating frame order information... Done.", false, true);
|
||||
Logger.Log($"Generated frame order info file in {benchmark.ElapsedMilliseconds} ms", true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Error generating frame order information: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
static Dictionary<string, int> dupesDict = new Dictionary<string, int>();
|
||||
|
||||
static void LoadDupesFile (string path)
|
||||
{
|
||||
dupesDict.Clear();
|
||||
if (!File.Exists(path)) return;
|
||||
string[] dupesFileLines = IOUtils.ReadLines(path);
|
||||
foreach(string line in dupesFileLines)
|
||||
{
|
||||
string[] values = line.Split(':');
|
||||
dupesDict.Add(values[0], values[1].GetInt());
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task CreateEncFile (string framesPath, bool loopEnabled, float interpFactor, bool notFirstRun)
|
||||
{
|
||||
if (Interpolate.canceled) return;
|
||||
Logger.Log($"Generating frame order information for {interpFactor}x...", false, true);
|
||||
|
||||
bool loop = Config.GetBool("enableLoop");
|
||||
bool sceneDetection = true;
|
||||
string ext = InterpolateUtils.GetOutExt();
|
||||
|
||||
FileInfo[] frameFiles = new DirectoryInfo(framesPath).GetFiles($"*.png");
|
||||
string vfrFile = Path.Combine(framesPath.GetParentDir(), Paths.GetFrameOrderFilename(interpFactor));
|
||||
string fileContent = "";
|
||||
string dupesFile = Path.Combine(framesPath.GetParentDir(), $"dupes.ini");
|
||||
LoadDupesFile(dupesFile);
|
||||
|
||||
string scnFramesPath = Path.Combine(framesPath.GetParentDir(), Paths.scenesDir);
|
||||
string interpPath = Paths.interpDir;
|
||||
|
||||
List<string> sceneFrames = new List<string>();
|
||||
if (Directory.Exists(scnFramesPath))
|
||||
sceneFrames = Directory.GetFiles(scnFramesPath).Select(file => Path.GetFileNameWithoutExtension(file)).ToList();
|
||||
|
||||
bool debug = Config.GetBool("frameOrderDebug", false);
|
||||
|
||||
int interpFramesAmount = (int)interpFactor; // TODO: This code won't work with fractional factors
|
||||
int totalFileCount = 0;
|
||||
|
||||
for (int i = 0; i < (frameFiles.Length - 1); i++)
|
||||
{
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
string inputFilenameNoExt = Path.GetFileNameWithoutExtension(frameFiles[i].Name);
|
||||
int dupesAmount = dupesDict.ContainsKey(inputFilenameNoExt) ? dupesDict[inputFilenameNoExt] : 0;
|
||||
bool discardThisFrame = (sceneDetection && (i + 2) < frameFiles.Length && sceneFrames.Contains(Path.GetFileNameWithoutExtension(frameFiles[i + 1].Name))); // i+2 is in scene detection folder, means i+1 is ugly interp frame
|
||||
|
||||
// If loop is enabled, account for the extra frame added to the end for loop continuity
|
||||
if (loopEnabled && i == (frameFiles.Length - 2))
|
||||
interpFramesAmount = interpFramesAmount * 2;
|
||||
|
||||
for (int frm = 0; frm < interpFramesAmount; frm++) // Generate frames file lines
|
||||
{
|
||||
if (discardThisFrame) // If frame is scene cut frame
|
||||
{
|
||||
totalFileCount++;
|
||||
int lastNum = totalFileCount;
|
||||
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, interpPath, ext, debug, $"[In: {inputFilenameNoExt}] [{((frm == 0) ? " Source " : $"Interp {frm}")}] [DiscardNext]");
|
||||
|
||||
for (int dupeCount = 1; dupeCount < interpFramesAmount; dupeCount++)
|
||||
{
|
||||
totalFileCount++;
|
||||
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, lastNum, interpPath, ext, debug, $"[In: {inputFilenameNoExt}] [DISCARDED]");
|
||||
}
|
||||
|
||||
frm = interpFramesAmount;
|
||||
}
|
||||
else
|
||||
{
|
||||
totalFileCount++;
|
||||
fileContent = WriteFrameWithDupes(dupesAmount, fileContent, totalFileCount, interpPath, ext, debug, $"[In: {inputFilenameNoExt}] [{((frm == 0) ? " Source " : $"Interp {frm}")}]");
|
||||
}
|
||||
}
|
||||
|
||||
if (i % 250 == 0)
|
||||
{
|
||||
if (i % 1000 == 0)
|
||||
Logger.Log($"Generating frame order information... {i}/{frameFiles.Length}.", false, true);
|
||||
await Task.Delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
totalFileCount++;
|
||||
fileContent += $"file '{interpPath}/{totalFileCount.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'\n";
|
||||
|
||||
if(loop)
|
||||
fileContent = fileContent.Remove(fileContent.LastIndexOf("\n"));
|
||||
|
||||
File.WriteAllText(vfrFile, fileContent);
|
||||
|
||||
if (notFirstRun) return; // Skip all steps that only need to be done once
|
||||
|
||||
if (loop)
|
||||
{
|
||||
int lastFileNumber = frameFiles.Last().Name.GetInt() + 1;
|
||||
string loopFrameTargetPath = Path.Combine(frameFiles.First().FullName.GetParentDir(), lastFileNumber.ToString().PadLeft(Padding.inputFrames, '0') + $".png");
|
||||
if (File.Exists(loopFrameTargetPath))
|
||||
{
|
||||
if (debug) Logger.Log($"Won't copy loop frame - {Path.GetFileName(loopFrameTargetPath)} already exists.", true);
|
||||
return;
|
||||
}
|
||||
File.Copy(frameFiles.First().FullName, loopFrameTargetPath);
|
||||
if (debug) Logger.Log($"Copied loop frame to {loopFrameTargetPath}.", true);
|
||||
}
|
||||
}
|
||||
|
||||
static string WriteFrameWithDupes (int dupesAmount, string fileContent, int frameNum, string interpPath, string ext, bool debug, string note = "")
|
||||
{
|
||||
for (int writtenDupes = -1; writtenDupes < dupesAmount; writtenDupes++) // Write duplicates
|
||||
{
|
||||
if (debug) Logger.Log($"Writing frame {frameNum} (writtenDupes {writtenDupes})", true, false);
|
||||
fileContent += $"file '{interpPath}/{frameNum.ToString().PadLeft(Padding.interpFrames, '0')}.{ext}'{(debug ? ($" # Dupe {(writtenDupes+1).ToString("000")} {note}").Replace("Dupe 000", " ") : "" )}\n";
|
||||
}
|
||||
return fileContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,254 +0,0 @@
|
||||
using Flowframes;
|
||||
using Flowframes.Media;
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Magick;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.MiscUtils;
|
||||
using Flowframes.OS;
|
||||
using Flowframes.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Padding = Flowframes.Data.Padding;
|
||||
using Utils = Flowframes.Main.InterpolateUtils;
|
||||
|
||||
namespace Flowframes
|
||||
{
|
||||
public class Interpolate
|
||||
{
|
||||
public enum OutMode { VidMp4, VidMkv, VidWebm, VidProRes, VidAvi, VidGif, ImgPng }
|
||||
|
||||
public static int currentInputFrameCount;
|
||||
public static bool currentlyUsingAutoEnc;
|
||||
public static InterpSettings current;
|
||||
public static bool canceled = false;
|
||||
static Stopwatch sw = new Stopwatch();
|
||||
|
||||
public static async Task Start()
|
||||
{
|
||||
if (!BatchProcessing.busy && Program.busy) return;
|
||||
canceled = false;
|
||||
if (!Utils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.outMode)) return; // General input checks
|
||||
if (!Utils.CheckAiAvailable(current.ai)) return; // Check if selected AI pkg is installed
|
||||
if (!ResumeUtils.resumeNextRun && !Utils.CheckDeleteOldTempFolder()) return; // Try to delete temp folder if an old one exists
|
||||
if (!Utils.CheckPathValid(current.inPath)) return; // Check if input path/file is valid
|
||||
Utils.PathAsciiCheck(current.outPath, "output path");
|
||||
currentInputFrameCount = await Utils.GetInputFrameCountAsync(current.inPath);
|
||||
current.stepByStep = false;
|
||||
Program.mainForm.SetStatus("Starting...");
|
||||
Program.mainForm.SetWorking(true);
|
||||
|
||||
if (!ResumeUtils.resumeNextRun)
|
||||
{
|
||||
await GetFrames();
|
||||
if (canceled) return;
|
||||
sw.Restart();
|
||||
await PostProcessFrames(false);
|
||||
}
|
||||
|
||||
if (canceled) return;
|
||||
await ResumeUtils.PrepareResumedRun();
|
||||
//Task.Run(() => Utils.DeleteInterpolatedInputFrames());
|
||||
await RunAi(current.interpFolder, current.ai);
|
||||
if (canceled) return;
|
||||
Program.mainForm.SetProgress(100);
|
||||
if(!currentlyUsingAutoEnc)
|
||||
await CreateVideo.Export(current.interpFolder, current.outFilename, current.outMode, false);
|
||||
await IOUtils.ReverseRenaming(current.framesFolder, AiProcess.filenameMap); // Get timestamps back
|
||||
AiProcess.filenameMap.Clear();
|
||||
await Cleanup();
|
||||
Program.mainForm.SetWorking(false);
|
||||
Logger.Log("Total processing time: " + FormatUtils.Time(sw.Elapsed));
|
||||
sw.Stop();
|
||||
Program.mainForm.SetStatus("Done interpolating!");
|
||||
}
|
||||
|
||||
public static async Task GetFrames (bool stepByStep = false)
|
||||
{
|
||||
current.RefreshAlpha();
|
||||
|
||||
if (!current.inputIsFrames) // Extract if input is video, import if image sequence
|
||||
await ExtractFrames(current.inPath, current.framesFolder, current.alpha, !stepByStep);
|
||||
else
|
||||
await FfmpegExtract.ImportImages(current.inPath, current.framesFolder, current.alpha, await Utils.GetOutputResolution(current.inPath, true));
|
||||
|
||||
if (current.alpha)
|
||||
{
|
||||
Program.mainForm.SetStatus("Extracting transparency...");
|
||||
Logger.Log("Extracting transparency... (1/2)");
|
||||
await FfmpegAlpha.ExtractAlphaDir(current.framesFolder, current.framesFolder + Paths.alphaSuffix);
|
||||
Logger.Log("Extracting transparency... (2/2)", false, true);
|
||||
await FfmpegAlpha.RemoveAlpha(current.framesFolder, current.framesFolder);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ExtractFrames(string inPath, string outPath, bool alpha, bool sceneDetect)
|
||||
{
|
||||
if (sceneDetect && Config.GetBool("scnDetect"))
|
||||
{
|
||||
Program.mainForm.SetStatus("Extracting scenes from video...");
|
||||
await FfmpegExtract.ExtractSceneChanges(inPath, Path.Combine(current.tempFolder, Paths.scenesDir), current.inFps);
|
||||
await Task.Delay(10);
|
||||
}
|
||||
|
||||
if (canceled) return;
|
||||
Program.mainForm.SetStatus("Extracting frames from video...");
|
||||
bool mpdecimate = Config.GetInt("dedupMode") == 2;
|
||||
await FfmpegExtract.VideoToFrames(inPath, outPath, alpha, current.inFps, mpdecimate, false, await Utils.GetOutputResolution(inPath, true, true));
|
||||
|
||||
if (mpdecimate)
|
||||
{
|
||||
int framesLeft = IOUtils.GetAmountOfFiles(outPath, false, $"*.png");
|
||||
int framesDeleted = currentInputFrameCount - framesLeft;
|
||||
float percentDeleted = ((float)framesDeleted / currentInputFrameCount) * 100f;
|
||||
string keptPercent = $"{(100f - percentDeleted).ToString("0.0")}%";
|
||||
Logger.Log($"[Deduplication] Kept {framesLeft} ({keptPercent}) frames, deleted {framesDeleted} frames.");
|
||||
}
|
||||
|
||||
if(!Config.GetBool("allowConsecutiveSceneChanges", true))
|
||||
Utils.FixConsecutiveSceneFrames(Path.Combine(current.tempFolder, Paths.scenesDir), current.framesFolder);
|
||||
|
||||
if (canceled) return;
|
||||
Program.mainForm.SetStatus("Extracting audio from video...");
|
||||
string audioFile = Path.Combine(current.tempFolder, "audio");
|
||||
|
||||
if (audioFile != null && !File.Exists(audioFile))
|
||||
await FfmpegAudioAndMetadata.ExtractAudio(inPath, audioFile);
|
||||
|
||||
if (canceled) return;
|
||||
Program.mainForm.SetStatus("Extracting subtitles from video...");
|
||||
await FfmpegAudioAndMetadata.ExtractSubtitles(inPath, current.tempFolder, current.outMode);
|
||||
}
|
||||
|
||||
public static async Task PostProcessFrames (bool stepByStep)
|
||||
{
|
||||
if (canceled) return;
|
||||
|
||||
int extractedFrames = IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png");
|
||||
if (!Directory.Exists(current.framesFolder) || currentInputFrameCount <= 0 || extractedFrames < 2)
|
||||
{
|
||||
if(extractedFrames == 1)
|
||||
Cancel("Only a single frame was extracted from your input file!\n\nPossibly your input is an image, not a video?");
|
||||
else
|
||||
Cancel("Frame extraction failed!\n\nYour input file might be incompatible.");
|
||||
}
|
||||
|
||||
if (Config.GetInt("dedupMode") == 1)
|
||||
await Dedupe.Run(current.framesFolder);
|
||||
else
|
||||
Dedupe.ClearCache();
|
||||
|
||||
if(!Config.GetBool("enableLoop"))
|
||||
await Utils.CopyLastFrame(currentInputFrameCount);
|
||||
|
||||
if (Config.GetInt("dedupMode") > 0)
|
||||
await Dedupe.CreateDupesFile(current.framesFolder, currentInputFrameCount);
|
||||
|
||||
if (canceled) return;
|
||||
|
||||
await FrameOrder.CreateFrameOrderFile(current.framesFolder, Config.GetBool("enableLoop"), current.interpFactor);
|
||||
|
||||
if (canceled) return;
|
||||
|
||||
try
|
||||
{
|
||||
Dictionary<string, string> renamedFilesDict = await IOUtils.RenameCounterDirReversibleAsync(current.framesFolder, "png", 1, Padding.inputFramesRenamed);
|
||||
|
||||
if(stepByStep)
|
||||
AiProcess.filenameMap = renamedFilesDict.ToDictionary(x => Path.GetFileName(x.Key), x => Path.GetFileName(x.Value)); // Save rel paths
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Error renaming frame files: {e.Message}");
|
||||
Cancel("Error renaming frame files. Check the log for details.");
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task RunAi(string outpath, AI ai, bool stepByStep = false)
|
||||
{
|
||||
Program.mainForm.SetStatus("Downloading models...");
|
||||
await ModelDownloader.DownloadModelFiles(Path.GetFileNameWithoutExtension(ai.pkg.fileName), current.model);
|
||||
if (canceled) return;
|
||||
|
||||
currentlyUsingAutoEnc = Utils.CanUseAutoEnc(stepByStep, current);
|
||||
|
||||
IOUtils.CreateDir(outpath);
|
||||
|
||||
List<Task> tasks = new List<Task>();
|
||||
|
||||
if (ai.aiName == Networks.rifeCuda.aiName)
|
||||
tasks.Add(AiProcess.RunRifeCuda(current.framesFolder, current.interpFactor, current.model));
|
||||
|
||||
if (ai.aiName == Networks.rifeNcnn.aiName)
|
||||
tasks.Add(AiProcess.RunRifeNcnn(current.framesFolder, outpath, (int)current.interpFactor, current.model));
|
||||
|
||||
if (ai.aiName == Networks.dainNcnn.aiName)
|
||||
tasks.Add(AiProcess.RunDainNcnn(current.framesFolder, outpath, current.interpFactor, current.model, Config.GetInt("dainNcnnTilesize", 512)));
|
||||
|
||||
if (currentlyUsingAutoEnc)
|
||||
{
|
||||
Logger.Log($"{Logger.GetLastLine()} (Using Auto-Encode)", true);
|
||||
tasks.Add(AutoEncode.MainLoop(outpath));
|
||||
}
|
||||
|
||||
Program.mainForm.SetStatus("Running AI...");
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
public static void Cancel(string reason = "", bool noMsgBox = false)
|
||||
{
|
||||
if (AiProcess.currentAiProcess != null && !AiProcess.currentAiProcess.HasExited)
|
||||
OSUtils.KillProcessTree(AiProcess.currentAiProcess.Id);
|
||||
if (AvProcess.lastProcess != null && !AvProcess.lastProcess.HasExited)
|
||||
OSUtils.KillProcessTree(AvProcess.lastProcess.Id);
|
||||
canceled = true;
|
||||
Program.mainForm.SetStatus("Canceled.");
|
||||
Program.mainForm.SetProgress(0);
|
||||
if (!current.stepByStep && !Config.GetBool("keepTempFolder"))
|
||||
{
|
||||
if(false /* IOUtils.GetAmountOfFiles(Path.Combine(current.tempFolder, Paths.resumeDir), true) > 0 */) // TODO: Uncomment for 1.23
|
||||
{
|
||||
DialogResult dialogResult = MessageBox.Show($"Delete the temp folder (Yes) or keep it for resuming later (No)?", "Delete temporary files?", MessageBoxButtons.YesNo);
|
||||
if (dialogResult == DialogResult.Yes)
|
||||
IOUtils.TryDeleteIfExists(current.tempFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
IOUtils.TryDeleteIfExists(current.tempFolder);
|
||||
}
|
||||
}
|
||||
AutoEncode.busy = false;
|
||||
Program.mainForm.SetWorking(false);
|
||||
Program.mainForm.SetTab("interpolation");
|
||||
Logger.LogIfLastLineDoesNotContainMsg("Canceled interpolation.");
|
||||
if (!string.IsNullOrWhiteSpace(reason) && !noMsgBox)
|
||||
Utils.ShowMessage($"Canceled:\n\n{reason}");
|
||||
}
|
||||
|
||||
public static async Task Cleanup(bool ignoreKeepSetting = false, int retriesLeft = 3, bool isRetry = false)
|
||||
{
|
||||
if ((!ignoreKeepSetting && Config.GetBool("keepTempFolder")) || !Program.busy) return;
|
||||
if (!isRetry)
|
||||
Logger.Log("Deleting temporary files...");
|
||||
try
|
||||
{
|
||||
Directory.Delete(current.tempFolder, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Cleanup Error: " + e.Message, true);
|
||||
if(retriesLeft > 0)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
await Cleanup(ignoreKeepSetting, retriesLeft - 1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
using Flowframes.Media;
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.Main
|
||||
{
|
||||
using static Interpolate;
|
||||
|
||||
class InterpolateSteps
|
||||
{
|
||||
public enum Step { ExtractScnChanges, ExtractFrames, Interpolate, CreateVid, Reset }
|
||||
|
||||
public static async Task Run(string step)
|
||||
{
|
||||
Logger.Log($"[SBS] Running step '{step}'", true);
|
||||
canceled = false;
|
||||
Program.mainForm.SetWorking(true);
|
||||
current = Program.mainForm.GetCurrentSettings();
|
||||
current.RefreshAlpha();
|
||||
current.stepByStep = false;
|
||||
|
||||
if (!InterpolateUtils.InputIsValid(current.inPath, current.outPath, current.outFps, current.interpFactor, current.outMode)) return; // General input checks
|
||||
|
||||
if (step.Contains("Extract Scene Changes"))
|
||||
{
|
||||
if (!current.inputIsFrames) // Input is video - extract frames first
|
||||
await ExtractSceneChanges();
|
||||
else
|
||||
InterpolateUtils.ShowMessage("Scene changes can only be extracted from videos, not frames!", "Error");
|
||||
}
|
||||
|
||||
if (step.Contains("Extract Frames"))
|
||||
await ExtractFramesStep();
|
||||
|
||||
if (step.Contains("Run Interpolation"))
|
||||
await DoInterpolate();
|
||||
|
||||
if (step.Contains("Export"))
|
||||
await CreateOutputVid();
|
||||
|
||||
if (step.Contains("Cleanup"))
|
||||
await Reset();
|
||||
|
||||
Program.mainForm.SetWorking(false);
|
||||
Program.mainForm.SetStatus("Done running step.");
|
||||
Logger.Log("Done running this step.");
|
||||
}
|
||||
|
||||
public static async Task ExtractSceneChanges()
|
||||
{
|
||||
string scenesPath = Path.Combine(current.tempFolder, Paths.scenesDir);
|
||||
if (!IOUtils.TryDeleteIfExists(scenesPath))
|
||||
{
|
||||
InterpolateUtils.ShowMessage("Failed to delete existing scenes folder - Make sure no file is opened in another program!", "Error");
|
||||
return;
|
||||
}
|
||||
Program.mainForm.SetStatus("Extracting scenes from video...");
|
||||
await FfmpegExtract.ExtractSceneChanges(current.inPath, scenesPath, current.inFps);
|
||||
await Task.Delay(10);
|
||||
}
|
||||
|
||||
public static async Task ExtractFramesStep()
|
||||
{
|
||||
if (!IOUtils.TryDeleteIfExists(current.framesFolder))
|
||||
{
|
||||
InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error");
|
||||
return;
|
||||
}
|
||||
|
||||
currentInputFrameCount = await InterpolateUtils.GetInputFrameCountAsync(current.inPath);
|
||||
AiProcess.filenameMap.Clear();
|
||||
|
||||
await GetFrames(true);
|
||||
}
|
||||
|
||||
public static async Task DoInterpolate()
|
||||
{
|
||||
current.framesFolder = Path.Combine(current.tempFolder, Paths.framesDir);
|
||||
|
||||
if (!Directory.Exists(current.framesFolder) || IOUtils.GetAmountOfFiles(current.framesFolder, false, "*.png") < 2)
|
||||
{
|
||||
InterpolateUtils.ShowMessage("There are no extracted frames that can be interpolated!\nDid you run the extraction step?", "Error");
|
||||
return;
|
||||
}
|
||||
if (!IOUtils.TryDeleteIfExists(current.interpFolder))
|
||||
{
|
||||
InterpolateUtils.ShowMessage("Failed to delete existing frames folder - Make sure no file is opened in another program!", "Error");
|
||||
return;
|
||||
}
|
||||
|
||||
currentInputFrameCount = await InterpolateUtils.GetInputFrameCountAsync(current.inPath);
|
||||
|
||||
// TODO: Check if this works lol, remove if it does
|
||||
//if (Config.GetBool("sbsAllowAutoEnc"))
|
||||
// nextOutPath = Path.Combine(currentOutPath, Path.GetFileNameWithoutExtension(current.inPath) + IOUtils.GetAiSuffix(current.ai, current.interpFactor) + InterpolateUtils.GetExt(current.outMode));
|
||||
|
||||
await PostProcessFrames(true);
|
||||
|
||||
if (canceled) return;
|
||||
Program.mainForm.SetStatus("Running AI...");
|
||||
await RunAi(current.interpFolder, current.ai, true);
|
||||
await IOUtils.ReverseRenaming(current.framesFolder, AiProcess.filenameMap); // Get timestamps back
|
||||
AiProcess.filenameMap.Clear();
|
||||
Program.mainForm.SetProgress(0);
|
||||
}
|
||||
|
||||
public static async Task CreateOutputVid()
|
||||
{
|
||||
string[] outFrames = IOUtils.GetFilesSorted(current.interpFolder, $"*.{InterpolateUtils.GetOutExt()}");
|
||||
|
||||
if (outFrames.Length > 0 && !IOUtils.CheckImageValid(outFrames[0]))
|
||||
{
|
||||
InterpolateUtils.ShowMessage("Invalid frame files detected!\n\nIf you used Auto-Encode, this is normal, and you don't need to run " +
|
||||
"this step as the video was already created in the \"Interpolate\" step.", "Error");
|
||||
return;
|
||||
}
|
||||
|
||||
string outPath = Path.Combine(current.outPath, Path.GetFileNameWithoutExtension(current.inPath) + IOUtils.GetCurrentExportSuffix() + FFmpegUtils.GetExt(current.outMode));
|
||||
await CreateVideo.Export(current.interpFolder, outPath, current.outMode, true);
|
||||
}
|
||||
|
||||
public static async Task Reset()
|
||||
{
|
||||
await Cleanup(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,467 +0,0 @@
|
||||
using Flowframes.Media;
|
||||
using Flowframes.Data;
|
||||
using Flowframes.Forms;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.MiscUtils;
|
||||
using Flowframes.OS;
|
||||
using Flowframes.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using i = Flowframes.Interpolate;
|
||||
using Padding = Flowframes.Data.Padding;
|
||||
|
||||
namespace Flowframes.Main
|
||||
{
|
||||
class InterpolateUtils
|
||||
{
|
||||
public static PictureBox preview;
|
||||
public static BigPreviewForm bigPreviewForm;
|
||||
|
||||
public static async Task CopyLastFrame (int lastFrameNum)
|
||||
{
|
||||
try
|
||||
{
|
||||
lastFrameNum--; // We have to do this as extracted frames start at 0, not 1
|
||||
bool frameFolderInput = IOUtils.IsPathDirectory(i.current.inPath);
|
||||
string targetPath = Path.Combine(i.current.framesFolder, lastFrameNum.ToString().PadLeft(Padding.inputFrames, '0') + ".png");
|
||||
if (File.Exists(targetPath)) return;
|
||||
|
||||
Size res = IOUtils.GetImage(IOUtils.GetFilesSorted(i.current.framesFolder, false).First()).Size;
|
||||
|
||||
if (frameFolderInput)
|
||||
{
|
||||
string lastFramePath = IOUtils.GetFilesSorted(i.current.inPath, false).Last();
|
||||
await FfmpegExtract.ExtractLastFrame(lastFramePath, targetPath, res);
|
||||
}
|
||||
else
|
||||
{
|
||||
await FfmpegExtract.ExtractLastFrame(i.current.inPath, targetPath, res);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("CopyLastFrame Error: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetOutExt (bool withDot = false)
|
||||
{
|
||||
string dotStr = withDot ? "." : "";
|
||||
if (Config.GetBool("jpegInterp"))
|
||||
return dotStr + "jpg";
|
||||
return dotStr + "png";
|
||||
}
|
||||
|
||||
public static int targetFrames;
|
||||
public static string currentOutdir;
|
||||
public static float currentFactor;
|
||||
public static bool progressPaused = false;
|
||||
public static bool progCheckRunning = false;
|
||||
public static async void GetProgressByFrameAmount(string outdir, int target)
|
||||
{
|
||||
progCheckRunning = true;
|
||||
targetFrames = target;
|
||||
currentOutdir = outdir;
|
||||
Logger.Log($"Starting GetProgressByFrameAmount() loop for outdir '{currentOutdir}', target is {target} frames", true);
|
||||
bool firstProgUpd = true;
|
||||
Program.mainForm.SetProgress(0);
|
||||
while (Program.busy)
|
||||
{
|
||||
if (!progressPaused && AiProcess.processTime.IsRunning && Directory.Exists(currentOutdir))
|
||||
{
|
||||
if (firstProgUpd && Program.mainForm.IsInFocus())
|
||||
Program.mainForm.SetTab("preview");
|
||||
firstProgUpd = false;
|
||||
string[] frames = IOUtils.GetFilesSorted(currentOutdir, $"*.{GetOutExt()}");
|
||||
if (frames.Length > 1)
|
||||
UpdateInterpProgress(frames.Length, targetFrames, frames[frames.Length - 1]);
|
||||
if (frames.Length >= targetFrames)
|
||||
break;
|
||||
await Task.Delay(GetProgressWaitTime(frames.Length));
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.Delay(200);
|
||||
}
|
||||
}
|
||||
progCheckRunning = false;
|
||||
if (i.canceled)
|
||||
Program.mainForm.SetProgress(0);
|
||||
}
|
||||
|
||||
public static int interpolatedInputFramesCount;
|
||||
|
||||
public static void UpdateInterpProgress(int frames, int target, string latestFramePath = "")
|
||||
{
|
||||
if (i.canceled) return;
|
||||
interpolatedInputFramesCount = ((frames / i.current.interpFactor).RoundToInt() - 1);
|
||||
ResumeUtils.Save();
|
||||
frames = frames.Clamp(0, target);
|
||||
int percent = (int)Math.Round(((float)frames / target) * 100f);
|
||||
Program.mainForm.SetProgress(percent);
|
||||
|
||||
float generousTime = ((AiProcess.processTime.ElapsedMilliseconds - AiProcess.lastStartupTimeMs) / 1000f);
|
||||
float fps = (float)frames / generousTime;
|
||||
string fpsIn = (fps / currentFactor).ToString("0.00");
|
||||
string fpsOut = fps.ToString("0.00");
|
||||
|
||||
float secondsPerFrame = generousTime / (float)frames;
|
||||
int framesLeft = target - frames;
|
||||
float eta = framesLeft * secondsPerFrame;
|
||||
string etaStr = FormatUtils.Time(new TimeSpan(0, 0, eta.RoundToInt()), false);
|
||||
|
||||
bool replaceLine = Regex.Split(Logger.textbox.Text, "\r\n|\r|\n").Last().Contains("Average Speed: ");
|
||||
|
||||
string logStr = $"Interpolated {frames}/{target} frames ({percent}%) - Average Speed: {fpsIn} FPS In / {fpsOut} FPS Out - ";
|
||||
logStr += $"Time: {FormatUtils.Time(AiProcess.processTime.Elapsed)} - ETA: {etaStr}";
|
||||
if (AutoEncode.busy) logStr += " - Encoding...";
|
||||
Logger.Log(logStr, false, replaceLine);
|
||||
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(latestFramePath) && frames > currentFactor)
|
||||
{
|
||||
if (bigPreviewForm == null && !preview.Visible /* ||Program.mainForm.WindowState != FormWindowState.Minimized */ /* || !Program.mainForm.IsInFocus()*/) return; // Skip if the preview is not visible or the form is not in focus
|
||||
Image img = IOUtils.GetImage(latestFramePath);
|
||||
SetPreviewImg(img);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public static async Task DeleteInterpolatedInputFrames ()
|
||||
{
|
||||
interpolatedInputFramesCount = 0;
|
||||
string[] inputFrames = IOUtils.GetFilesSorted(i.current.framesFolder);
|
||||
|
||||
for (int i = 0; i < inputFrames.Length; i++)
|
||||
{
|
||||
while (Program.busy && (i + 10) > interpolatedInputFramesCount) await Task.Delay(1000);
|
||||
if (!Program.busy) break;
|
||||
if(i != 0 && i != inputFrames.Length - 1)
|
||||
IOUtils.OverwriteFileWithText(inputFrames[i]);
|
||||
if (i % 10 == 0) await Task.Delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetPreviewImg (Image img)
|
||||
{
|
||||
if (img == null)
|
||||
return;
|
||||
|
||||
preview.Image = img;
|
||||
|
||||
if (bigPreviewForm != null)
|
||||
bigPreviewForm.SetImage(img);
|
||||
}
|
||||
|
||||
public static Dictionary<string, int> frameCountCache = new Dictionary<string, int>();
|
||||
public static async Task<int> GetInputFrameCountAsync (string path)
|
||||
{
|
||||
int maxMb = Config.GetInt("storeHashedFramecountMaxSizeMb", 256);
|
||||
string hash = "";
|
||||
|
||||
if (IOUtils.GetFilesize(path) >= 0 && IOUtils.GetFilesize(path) < maxMb * 1024 * 1024)
|
||||
hash = await IOUtils.GetHashAsync(path, IOUtils.Hash.xxHash); // Get checksum for caching
|
||||
else
|
||||
Logger.Log($"GetInputFrameCountAsync: File bigger than {maxMb}mb, won't hash.", true);
|
||||
|
||||
if (hash.Length > 1 && frameCountCache.ContainsKey(hash))
|
||||
{
|
||||
Logger.Log($"FrameCountCache contains this hash ({hash}), using cached frame count.", true);
|
||||
return frameCountCache[hash];
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log($"Hash ({hash}) not cached, reading frame count.", true);
|
||||
}
|
||||
|
||||
int frameCount = 0;
|
||||
|
||||
if (IOUtils.IsPathDirectory(path))
|
||||
frameCount = IOUtils.GetAmountOfFiles(path, false);
|
||||
else
|
||||
frameCount = await FfmpegCommands.GetFrameCountAsync(path);
|
||||
|
||||
if (hash.Length > 1 && frameCount > 5000) // Cache if >5k frames to avoid re-reading it every single time
|
||||
{
|
||||
Logger.Log($"Adding hash ({hash}) with frame count {frameCount} to cache.", true);
|
||||
frameCountCache[hash] = frameCount; // Use CRC32 instead of path to avoid using cached value if file was changed
|
||||
}
|
||||
|
||||
return frameCount;
|
||||
}
|
||||
|
||||
public static int GetProgressWaitTime(int numFrames)
|
||||
{
|
||||
float hddMultiplier = !Program.lastInputPathIsSsd ? 2f : 1f;
|
||||
|
||||
int waitMs = 200;
|
||||
|
||||
if (numFrames > 100)
|
||||
waitMs = 500;
|
||||
|
||||
if (numFrames > 1000)
|
||||
waitMs = 1000;
|
||||
|
||||
if (numFrames > 2500)
|
||||
waitMs = 1500;
|
||||
|
||||
if (numFrames > 5000)
|
||||
waitMs = 2500;
|
||||
|
||||
return (waitMs * hddMultiplier).RoundToInt();
|
||||
}
|
||||
|
||||
public static string GetTempFolderLoc (string inPath, string outPath)
|
||||
{
|
||||
string basePath = inPath.GetParentDir();
|
||||
|
||||
if(Config.GetInt("tempFolderLoc") == 1)
|
||||
basePath = outPath.GetParentDir();
|
||||
|
||||
if (Config.GetInt("tempFolderLoc") == 2)
|
||||
basePath = outPath;
|
||||
|
||||
if (Config.GetInt("tempFolderLoc") == 3)
|
||||
basePath = IOUtils.GetExeDir();
|
||||
|
||||
if (Config.GetInt("tempFolderLoc") == 4)
|
||||
{
|
||||
string custPath = Config.Get("tempDirCustom");
|
||||
if(IOUtils.IsDirValid(custPath))
|
||||
basePath = custPath;
|
||||
}
|
||||
|
||||
return Path.Combine(basePath, Path.GetFileNameWithoutExtension(inPath).StripBadChars().Remove(" ").Trunc(30, false) + "-temp");
|
||||
}
|
||||
|
||||
public static bool InputIsValid(string inDir, string outDir, float fpsOut, float factor, Interpolate.OutMode outMode)
|
||||
{
|
||||
bool passes = true;
|
||||
|
||||
bool isFile = !IOUtils.IsPathDirectory(inDir);
|
||||
|
||||
if ((passes && isFile && !IOUtils.IsFileValid(inDir)) || (!isFile && !IOUtils.IsDirValid(inDir)))
|
||||
{
|
||||
ShowMessage("Input path is not valid!");
|
||||
passes = false;
|
||||
}
|
||||
if (passes && !IOUtils.IsDirValid(outDir))
|
||||
{
|
||||
ShowMessage("Output path is not valid!");
|
||||
passes = false;
|
||||
}
|
||||
if (passes && /*factor != 2 && factor != 4 && factor != 8*/ factor > 16)
|
||||
{
|
||||
ShowMessage("Interpolation factor is not valid!");
|
||||
passes = false;
|
||||
}
|
||||
if (passes && outMode == i.OutMode.VidGif && fpsOut > 50)
|
||||
{
|
||||
ShowMessage("Invalid output frame rate!\nGIF does not properly support frame rates above 40 FPS.\nPlease use MP4, WEBM or another video format.");
|
||||
passes = false;
|
||||
}
|
||||
if (passes && fpsOut < 1 || fpsOut > 1000)
|
||||
{
|
||||
ShowMessage("Invalid output frame rate - Must be 1-1000.");
|
||||
passes = false;
|
||||
}
|
||||
if (!passes)
|
||||
i.Cancel("Invalid settings detected.", true);
|
||||
return passes;
|
||||
}
|
||||
|
||||
public static void PathAsciiCheck (string path, string pathTitle)
|
||||
{
|
||||
if (IOUtils.HasBadChars(path) || OSUtils.HasNonAsciiChars(path))
|
||||
ShowMessage($"Warning: Your {pathTitle} includes special characters. This might cause problems.");
|
||||
}
|
||||
|
||||
public static void GifCompatCheck (Interpolate.OutMode outMode, float fpsOut, int targetFrameCount)
|
||||
{
|
||||
if (outMode != Interpolate.OutMode.VidGif)
|
||||
return;
|
||||
|
||||
if(fpsOut >= 50f)
|
||||
Logger.Log("Warning: GIFs above 50 FPS might play slower on certain software/hardware! MP4 is recommended for higher frame rates.");
|
||||
|
||||
int maxGifFrames = 200;
|
||||
if (targetFrameCount > maxGifFrames)
|
||||
{
|
||||
ShowMessage($"You can't use GIF with more than {maxGifFrames} output frames!\nPlease use MP4 for this.", "Error");
|
||||
i.Cancel($"Can't use GIF encoding with more than {maxGifFrames} frames!");
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CheckAiAvailable (AI ai)
|
||||
{
|
||||
if (!PkgUtils.IsAiAvailable(ai))
|
||||
{
|
||||
ShowMessage("The selected AI is not installed!\nYou can download it from the Package Installer.", "Error");
|
||||
i.Cancel("Selected AI not available.", true);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool CheckDeleteOldTempFolder ()
|
||||
{
|
||||
if (!IOUtils.TryDeleteIfExists(i.current.tempFolder))
|
||||
{
|
||||
ShowMessage("Failed to remove an existing temp folder of this video!\nMake sure you didn't open any frames in an editor.", "Error");
|
||||
i.Cancel();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool CheckPathValid (string path)
|
||||
{
|
||||
if (IOUtils.IsPathDirectory(path))
|
||||
{
|
||||
if (!IOUtils.IsDirValid(path))
|
||||
{
|
||||
ShowMessage("Input directory is not valid.");
|
||||
i.Cancel();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsVideoValid(path))
|
||||
{
|
||||
ShowMessage("Input video file is not valid.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool IsVideoValid(string videoPath)
|
||||
{
|
||||
if (videoPath == null || !IOUtils.IsFileValid(videoPath))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void ShowMessage(string msg, string title = "Message")
|
||||
{
|
||||
if (!BatchProcessing.busy)
|
||||
MessageBox.Show(msg, title);
|
||||
Logger.Log("Message: " + msg, true);
|
||||
}
|
||||
|
||||
public static async Task<Size> GetOutputResolution (string inputPath, bool print, bool returnZeroIfUnchanged = false)
|
||||
{
|
||||
Size resolution = await IOUtils.GetVideoOrFramesRes(inputPath);
|
||||
return GetOutputResolution(resolution, print, returnZeroIfUnchanged);
|
||||
}
|
||||
|
||||
public static Size GetOutputResolution(Size inputRes, bool print = false, bool returnZeroIfUnchanged = false)
|
||||
{
|
||||
int maxHeight = RoundDiv2(Config.GetInt("maxVidHeight"));
|
||||
if (inputRes.Height > maxHeight)
|
||||
{
|
||||
float factor = (float)maxHeight / inputRes.Height;
|
||||
Logger.Log($"Un-rounded downscaled size: {(inputRes.Width * factor).ToString("0.00")}x{Config.GetInt("maxVidHeight")}", true);
|
||||
int width = RoundDiv2((inputRes.Width * factor).RoundToInt());
|
||||
if (print)
|
||||
Logger.Log($"Video is bigger than the maximum - Downscaling to {width}x{maxHeight}.");
|
||||
return new Size(width, maxHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
//return new Size(RoundDiv2(inputRes.Width), RoundDiv2(inputRes.Height));
|
||||
if (returnZeroIfUnchanged)
|
||||
return new Size();
|
||||
else
|
||||
return inputRes;
|
||||
}
|
||||
}
|
||||
|
||||
public static int RoundDiv2(int n) // Round to a number that's divisible by 2 (for h264 etc)
|
||||
{
|
||||
int a = (n / 2) * 2; // Smaller multiple
|
||||
int b = a + 2; // Larger multiple
|
||||
return (n - a > b - n) ? b : a; // Return of closest of two
|
||||
}
|
||||
|
||||
public static bool CanUseAutoEnc (bool stepByStep, InterpSettings current)
|
||||
{
|
||||
AutoEncode.UpdateChunkAndBufferSizes();
|
||||
|
||||
if (current.alpha)
|
||||
{
|
||||
Logger.Log($"Not Using AutoEnc: Alpha mode is enabled.", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!current.outMode.ToString().ToLower().Contains("vid") || current.outMode.ToString().ToLower().Contains("gif"))
|
||||
{
|
||||
Logger.Log($"Not Using AutoEnc: Out Mode is not video ({current.outMode.ToString()})", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(stepByStep && !Config.GetBool("sbsAllowAutoEnc"))
|
||||
{
|
||||
Logger.Log($"Not Using AutoEnc: Using step-by-step mode, but 'sbsAllowAutoEnc' is false.", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!stepByStep && Config.GetInt("autoEncMode") == 0)
|
||||
{
|
||||
Logger.Log($"Not Using AutoEnc: 'autoEncMode' is 0.", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
int inFrames = IOUtils.GetAmountOfFiles(current.framesFolder, false);
|
||||
if (inFrames * current.interpFactor < (AutoEncode.chunkSize + AutoEncode.safetyBufferFrames) * 1.2f)
|
||||
{
|
||||
Logger.Log($"Not Using AutoEnc: Input frames ({inFrames}) * factor ({current.interpFactor}) is smaller than (chunkSize ({AutoEncode.chunkSize}) + safetyBufferFrames ({AutoEncode.safetyBufferFrames}) * 1.2f)", true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async Task<bool> UseUHD ()
|
||||
{
|
||||
return (await GetOutputResolution(i.current.inPath, false)).Height >= Config.GetInt("uhdThresh");
|
||||
}
|
||||
|
||||
public static void FixConsecutiveSceneFrames (string sceneFramesPath, string sourceFramesPath)
|
||||
{
|
||||
if (!Directory.Exists(sceneFramesPath) || IOUtils.GetAmountOfFiles(sceneFramesPath, false) < 1)
|
||||
return;
|
||||
|
||||
List<string> sceneFrames = IOUtils.GetFilesSorted(sceneFramesPath).Select(x => Path.GetFileNameWithoutExtension(x)).ToList();
|
||||
List<string> sourceFrames = IOUtils.GetFilesSorted(sourceFramesPath).Select(x => Path.GetFileNameWithoutExtension(x)).ToList();
|
||||
List<string> sceneFramesToDelete = new List<string>();
|
||||
|
||||
foreach(string scnFrame in sceneFrames)
|
||||
{
|
||||
if (sceneFramesToDelete.Contains(scnFrame))
|
||||
continue;
|
||||
|
||||
int sourceIndexForScnFrame = sourceFrames.IndexOf(scnFrame); // Get source index of scene frame
|
||||
if ((sourceIndexForScnFrame + 1) == sourceFrames.Count)
|
||||
continue;
|
||||
string followingFrame = sourceFrames[sourceIndexForScnFrame + 1]; // Get filename/timestamp of the next source frame
|
||||
|
||||
if (sceneFrames.Contains(followingFrame)) // If next source frame is in scene folder, add to deletion list
|
||||
sceneFramesToDelete.Add(followingFrame);
|
||||
}
|
||||
|
||||
foreach (string frame in sceneFramesToDelete)
|
||||
IOUtils.TryDeleteIfExists(Path.Combine(sceneFramesPath, frame + ".png"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using I = Flowframes.Interpolate;
|
||||
|
||||
namespace Flowframes.Main
|
||||
{
|
||||
|
||||
class ResumeUtils
|
||||
{
|
||||
public static bool resumeNextRun;
|
||||
|
||||
public static float timeBetweenSaves = 10;
|
||||
public static int minFrames = 100;
|
||||
public static int safetyDelayFrames = 50;
|
||||
public static string resumeFilename = "resume.ini";
|
||||
public static string interpSettingsFilename = "interpSettings.ini";
|
||||
public static string filenameMapFilename = "frameFilenames.ini";
|
||||
|
||||
public static Stopwatch timeSinceLastSave = new Stopwatch();
|
||||
|
||||
public static void Save ()
|
||||
{
|
||||
if (timeSinceLastSave.IsRunning && timeSinceLastSave.ElapsedMilliseconds < (timeBetweenSaves * 1000f).RoundToInt()) return;
|
||||
int frames = (int)Math.Round((float)InterpolateUtils.interpolatedInputFramesCount / I.current.interpFactor) - safetyDelayFrames;
|
||||
if (frames < 1) return;
|
||||
timeSinceLastSave.Restart();
|
||||
Directory.CreateDirectory(Path.Combine(I.current.tempFolder, Paths.resumeDir));
|
||||
SaveState(frames);
|
||||
SaveInterpSettings();
|
||||
SaveFilenameMap();
|
||||
}
|
||||
|
||||
static void SaveState (int frames)
|
||||
{
|
||||
ResumeState state = new ResumeState(I.currentlyUsingAutoEnc, frames);
|
||||
string filePath = Path.Combine(I.current.tempFolder, Paths.resumeDir, resumeFilename);
|
||||
File.WriteAllText(filePath, state.ToString());
|
||||
}
|
||||
|
||||
static async Task SaveFilenameMap ()
|
||||
{
|
||||
string filePath = Path.Combine(I.current.tempFolder, Paths.resumeDir, filenameMapFilename);
|
||||
|
||||
if (File.Exists(filePath) && IOUtils.GetFilesize(filePath) > 0)
|
||||
return;
|
||||
|
||||
string fileContent = "";
|
||||
int counter = 0;
|
||||
|
||||
foreach (KeyValuePair<string, string> entry in AiProcess.filenameMap)
|
||||
{
|
||||
if (counter % 1000 == 0) await Task.Delay(1);
|
||||
fileContent += $"{entry.Key}|{entry.Value}\n";
|
||||
counter++;
|
||||
}
|
||||
|
||||
File.WriteAllText(filePath, fileContent);
|
||||
}
|
||||
|
||||
static void SaveInterpSettings ()
|
||||
{
|
||||
string filepath = Path.Combine(I.current.tempFolder, Paths.resumeDir, interpSettingsFilename);
|
||||
File.WriteAllText(filepath, I.current.Serialize());
|
||||
}
|
||||
|
||||
public static void LoadTempFolder (string tempFolderPath)
|
||||
{
|
||||
string resumeFolderPath = Path.Combine(tempFolderPath, Paths.resumeDir);
|
||||
string interpSettingsPath = Path.Combine(resumeFolderPath, interpSettingsFilename);
|
||||
InterpSettings interpSettings = new InterpSettings(File.ReadAllText(interpSettingsPath));
|
||||
Program.mainForm.LoadBatchEntry(interpSettings);
|
||||
}
|
||||
|
||||
public static async Task PrepareResumedRun ()
|
||||
{
|
||||
if (!resumeNextRun) return;
|
||||
|
||||
string stateFilepath = Path.Combine(I.current.tempFolder, Paths.resumeDir, resumeFilename);
|
||||
ResumeState state = new ResumeState(File.ReadAllText(stateFilepath));
|
||||
|
||||
string fileMapFilepath = Path.Combine(I.current.tempFolder, Paths.resumeDir, filenameMapFilename);
|
||||
List<string> inputFrameLines = File.ReadAllLines(fileMapFilepath).Where(l => l.Trim().Length > 3).ToList();
|
||||
List<string> inputFrames = inputFrameLines.Select(l => Path.Combine(I.current.framesFolder, l.Split('|')[1])).ToList();
|
||||
|
||||
for (int i = 0; i < state.interpolatedInputFrames; i++)
|
||||
{
|
||||
IOUtils.TryDeleteIfExists(inputFrames[i]);
|
||||
if (i % 1000 == 0) await Task.Delay(1);
|
||||
}
|
||||
|
||||
Directory.Move(I.current.interpFolder, I.current.interpFolder + Paths.prevSuffix); // Move existing interp frames
|
||||
Directory.CreateDirectory(I.current.interpFolder); // Re-create empty interp folder
|
||||
|
||||
LoadFilenameMap();
|
||||
}
|
||||
|
||||
static void LoadFilenameMap()
|
||||
{
|
||||
Dictionary<string, string> dict = new Dictionary<string, string>();
|
||||
string filePath = Path.Combine(I.current.tempFolder, Paths.resumeDir, filenameMapFilename);
|
||||
string[] dictLines = File.ReadAllLines(filePath);
|
||||
|
||||
foreach (string line in dictLines)
|
||||
{
|
||||
if (line.Length < 5) continue;
|
||||
string[] keyValuePair = line.Split('|');
|
||||
dict.Add(keyValuePair[0].Trim(), keyValuePair[1].Trim());
|
||||
}
|
||||
|
||||
AiProcess.filenameMap = dict;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
using Flowframes.IO;
|
||||
using Flowframes.OS;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Flowframes.MiscUtils;
|
||||
|
||||
namespace Flowframes
|
||||
{
|
||||
class AvProcess
|
||||
{
|
||||
public static Process lastProcess;
|
||||
public static Stopwatch timeSinceLastOutput = new Stopwatch();
|
||||
public enum TaskType { ExtractFrames, Encode, GetInfo, Merge, Other };
|
||||
public static TaskType lastTask = TaskType.Other;
|
||||
|
||||
public static string lastOutputFfmpeg;
|
||||
public static string lastOutputGifski;
|
||||
|
||||
public enum LogMode { Visible, OnlyLastLine, Hidden }
|
||||
static LogMode currentLogMode;
|
||||
static bool showProgressBar;
|
||||
|
||||
public static async Task RunFfmpeg(string args, LogMode logMode, TaskType taskType = TaskType.Other, bool progressBar = false)
|
||||
{
|
||||
await RunFfmpeg(args, "", logMode, taskType, progressBar);
|
||||
}
|
||||
|
||||
public static async Task RunFfmpeg(string args, string workingDir, LogMode logMode, TaskType taskType = TaskType.Other, bool progressBar = false)
|
||||
{
|
||||
lastOutputFfmpeg = "";
|
||||
currentLogMode = logMode;
|
||||
showProgressBar = progressBar;
|
||||
Process ffmpeg = OSUtils.NewProcess(true);
|
||||
timeSinceLastOutput.Restart();
|
||||
lastProcess = ffmpeg;
|
||||
lastTask = taskType;
|
||||
if(!string.IsNullOrWhiteSpace(workingDir))
|
||||
ffmpeg.StartInfo.Arguments = $"{GetCmdArg()} cd /D {workingDir.Wrap()} & {Path.Combine(GetAvDir(), "ffmpeg.exe").Wrap()} -hide_banner -loglevel warning -y -stats {args}";
|
||||
else
|
||||
ffmpeg.StartInfo.Arguments = $"{GetCmdArg()} cd /D {GetAvDir().Wrap()} & ffmpeg.exe -hide_banner -loglevel warning -y -stats {args}";
|
||||
if (logMode != LogMode.Hidden) Logger.Log("Running ffmpeg...", false);
|
||||
Logger.Log("cmd.exe " + ffmpeg.StartInfo.Arguments, true, false, "ffmpeg");
|
||||
ffmpeg.OutputDataReceived += new DataReceivedEventHandler(FfmpegOutputHandler);
|
||||
ffmpeg.ErrorDataReceived += new DataReceivedEventHandler(FfmpegOutputHandler);
|
||||
ffmpeg.Start();
|
||||
ffmpeg.BeginOutputReadLine();
|
||||
ffmpeg.BeginErrorReadLine();
|
||||
|
||||
while (!ffmpeg.HasExited)
|
||||
await Task.Delay(1);
|
||||
|
||||
if(progressBar)
|
||||
Program.mainForm.SetProgress(0);
|
||||
}
|
||||
|
||||
static void FfmpegOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
|
||||
{
|
||||
timeSinceLastOutput.Restart();
|
||||
if (outLine == null || outLine.Data == null)
|
||||
return;
|
||||
string line = outLine.Data;
|
||||
lastOutputFfmpeg = lastOutputFfmpeg + "\n" + line;
|
||||
bool hidden = currentLogMode == LogMode.Hidden;
|
||||
bool replaceLastLine = currentLogMode == LogMode.OnlyLastLine;
|
||||
string trimmedLine = line.Remove("q=-0.0").Remove("size=N/A").Remove("bitrate=N/A").TrimWhitespaces();
|
||||
Logger.Log(trimmedLine, hidden, replaceLastLine, "ffmpeg");
|
||||
|
||||
if(line.Contains("Could not open file"))
|
||||
Interpolate.Cancel($"FFmpeg Error: {line}");
|
||||
|
||||
if (line.Contains("No NVENC capable devices found"))
|
||||
Interpolate.Cancel($"FFmpeg Error: {line}\nMake sure you have an NVENC-capable Nvidia GPU.");
|
||||
|
||||
if (!hidden && showProgressBar && line.Contains("time="))
|
||||
{
|
||||
Regex timeRegex = new Regex("(?<=time=).*(?= )");
|
||||
UpdateFfmpegProgress(timeRegex.Match(line).Value);
|
||||
}
|
||||
}
|
||||
|
||||
static void FfmpegOutputHandlerSilent (object sendingProcess, DataReceivedEventArgs outLine)
|
||||
{
|
||||
timeSinceLastOutput.Restart();
|
||||
if (outLine == null || outLine.Data == null || outLine.Data.Trim().Length < 2)
|
||||
return;
|
||||
string line = outLine.Data;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(lastOutputFfmpeg))
|
||||
lastOutputFfmpeg += "\n";
|
||||
lastOutputFfmpeg = lastOutputFfmpeg + line;
|
||||
Logger.Log(line, true, false, "ffmpeg");
|
||||
|
||||
if (showProgressBar && line.Contains("time="))
|
||||
{
|
||||
Logger.Log($"showProgressBar, contains: {line.Contains("time=")}", true, false, "ffmpeg");
|
||||
Regex timeRegex = new Regex("(?<=time=).*(?= )");
|
||||
UpdateFfmpegProgress(timeRegex.Match(line).Value);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetFfmpegOutput (string args)
|
||||
{
|
||||
Process ffmpeg = OSUtils.NewProcess(true);
|
||||
lastProcess = ffmpeg;
|
||||
ffmpeg.StartInfo.Arguments = $"{GetCmdArg()} cd /D {GetAvDir().Wrap()} & ffmpeg.exe -hide_banner -y -stats {args}";
|
||||
Logger.Log("cmd.exe " + ffmpeg.StartInfo.Arguments, true, false, "ffmpeg");
|
||||
ffmpeg.Start();
|
||||
ffmpeg.WaitForExit();
|
||||
string output = ffmpeg.StandardOutput.ReadToEnd();
|
||||
string err = ffmpeg.StandardError.ReadToEnd();
|
||||
if (!string.IsNullOrWhiteSpace(err)) output += "\n" + err;
|
||||
return output;
|
||||
}
|
||||
|
||||
public static async Task<string> GetFfmpegOutputAsync(string args, bool setBusy = false, bool progressBar = false)
|
||||
{
|
||||
timeSinceLastOutput.Restart();
|
||||
if (Program.busy) setBusy = false;
|
||||
lastOutputFfmpeg = "";
|
||||
showProgressBar = progressBar;
|
||||
Process ffmpeg = OSUtils.NewProcess(true);
|
||||
lastProcess = ffmpeg;
|
||||
ffmpeg.StartInfo.Arguments = $"{GetCmdArg()} cd /D {GetAvDir().Wrap()} & ffmpeg.exe -hide_banner -y -stats {args}";
|
||||
Logger.Log("cmd.exe " + ffmpeg.StartInfo.Arguments, true, false, "ffmpeg");
|
||||
if (setBusy) Program.mainForm.SetWorking(true);
|
||||
ffmpeg.OutputDataReceived += new DataReceivedEventHandler(FfmpegOutputHandlerSilent);
|
||||
ffmpeg.ErrorDataReceived += new DataReceivedEventHandler(FfmpegOutputHandlerSilent);
|
||||
ffmpeg.Start();
|
||||
ffmpeg.BeginOutputReadLine();
|
||||
ffmpeg.BeginErrorReadLine();
|
||||
while (!ffmpeg.HasExited) await Task.Delay(50);
|
||||
while(timeSinceLastOutput.ElapsedMilliseconds < 200) await Task.Delay(50);
|
||||
if (setBusy) Program.mainForm.SetWorking(false);
|
||||
return lastOutputFfmpeg;
|
||||
}
|
||||
|
||||
public static string GetFfprobeOutput (string args)
|
||||
{
|
||||
Process ffprobe = OSUtils.NewProcess(true);
|
||||
ffprobe.StartInfo.Arguments = $"{GetCmdArg()} cd /D {GetAvDir().Wrap()} & ffprobe.exe {args}";
|
||||
Logger.Log("cmd.exe " + ffprobe.StartInfo.Arguments, true, false, "ffmpeg");
|
||||
ffprobe.Start();
|
||||
ffprobe.WaitForExit();
|
||||
string output = ffprobe.StandardOutput.ReadToEnd();
|
||||
string err = ffprobe.StandardError.ReadToEnd();
|
||||
if (!string.IsNullOrWhiteSpace(err)) output += "\n" + err;
|
||||
return output;
|
||||
}
|
||||
|
||||
public static void UpdateFfmpegProgress(string ffmpegTime)
|
||||
{
|
||||
if (Program.mainForm.currInDuration < 1)
|
||||
{
|
||||
Program.mainForm.SetProgress(0);
|
||||
return;
|
||||
}
|
||||
|
||||
long total = Program.mainForm.currInDuration / 100;
|
||||
long current = FormatUtils.MsFromTimestamp(ffmpegTime);
|
||||
int progress = Convert.ToInt32(current / total);
|
||||
Program.mainForm.SetProgress(progress);
|
||||
}
|
||||
|
||||
static string GetAvDir ()
|
||||
{
|
||||
return Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.audioVideo.fileName));
|
||||
}
|
||||
|
||||
static string GetCmdArg ()
|
||||
{
|
||||
return "/C";
|
||||
}
|
||||
|
||||
public static async Task SetBusyWhileRunning ()
|
||||
{
|
||||
if (Program.busy) return;
|
||||
|
||||
await Task.Delay(100);
|
||||
while(!lastProcess.HasExited)
|
||||
await Task.Delay(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
using Flowframes.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.Media
|
||||
{
|
||||
class FFmpegUtils
|
||||
{
|
||||
public enum Codec { H264, H265, NVENC264, NVENC265, VP9, ProRes, AviRaw }
|
||||
|
||||
|
||||
public static Codec GetCodec(Interpolate.OutMode mode)
|
||||
{
|
||||
if (mode == Interpolate.OutMode.VidMp4 || mode == Interpolate.OutMode.VidMkv)
|
||||
{
|
||||
int mp4Enc = Config.GetInt("mp4Enc");
|
||||
if (mp4Enc == 0) return Codec.H264;
|
||||
if (mp4Enc == 1) return Codec.H265;
|
||||
if (mp4Enc == 2) return Codec.NVENC264;
|
||||
if (mp4Enc == 3) return Codec.NVENC265;
|
||||
}
|
||||
|
||||
if (mode == Interpolate.OutMode.VidWebm)
|
||||
return Codec.VP9;
|
||||
|
||||
if (mode == Interpolate.OutMode.VidProRes)
|
||||
return Codec.ProRes;
|
||||
|
||||
if (mode == Interpolate.OutMode.VidAvi)
|
||||
return Codec.AviRaw;
|
||||
|
||||
return Codec.H264;
|
||||
}
|
||||
|
||||
public static string GetEnc(Codec codec)
|
||||
{
|
||||
switch (codec)
|
||||
{
|
||||
case Codec.H264: return "libx264";
|
||||
case Codec.H265: return "libx265";
|
||||
case Codec.NVENC264: return "h264_nvenc";
|
||||
case Codec.NVENC265: return "hevc_nvenc";
|
||||
case Codec.VP9: return "libvpx-vp9";
|
||||
case Codec.ProRes: return "prores_ks";
|
||||
case Codec.AviRaw: return Config.Get("aviCodec");
|
||||
}
|
||||
return "libx264";
|
||||
}
|
||||
|
||||
public static string GetEncArgs (Codec codec)
|
||||
{
|
||||
string args = $"-c:v { GetEnc(codec)} ";
|
||||
|
||||
if(codec == Codec.H264)
|
||||
{
|
||||
args += $"-crf {Config.GetInt("h264Crf")} -preset {Config.Get("ffEncPreset")} -pix_fmt yuv420p";
|
||||
}
|
||||
|
||||
if (codec == Codec.H265)
|
||||
{
|
||||
args += $"-crf {Config.GetInt("h265Crf")} -preset {Config.Get("ffEncPreset")} -pix_fmt yuv420p";
|
||||
}
|
||||
|
||||
if (codec == Codec.NVENC264)
|
||||
{
|
||||
args += $"-cq {Config.GetInt("h264Crf")} -preset slow -pix_fmt yuv420p";
|
||||
}
|
||||
|
||||
if (codec == Codec.NVENC265)
|
||||
{
|
||||
args += $"-cq {Config.GetInt("h265Crf")} -preset slow -pix_fmt yuv420p";
|
||||
}
|
||||
|
||||
if (codec == Codec.VP9)
|
||||
{
|
||||
int crf = Config.GetInt("vp9Crf");
|
||||
string qualityStr = (crf > 0) ? $"-crf {crf}" : "-lossless 1";
|
||||
string cpuUsed = Config.GetInt("vp9Speed", 3).ToString();
|
||||
args += $"{qualityStr} -cpu-used {cpuUsed} -tile-columns 2 -tile-rows 2 -row-mt 1 -pix_fmt yuv420p";
|
||||
}
|
||||
|
||||
if(codec == Codec.ProRes)
|
||||
{
|
||||
args += $"-profile:v {Config.GetInt("proResProfile")} -pix_fmt yuv420p";
|
||||
}
|
||||
|
||||
if (codec == Codec.AviRaw)
|
||||
{
|
||||
args += $"-pix_fmt {Config.Get("aviColors")}";
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
public static string GetAudioEnc(Codec codec)
|
||||
{
|
||||
switch (codec)
|
||||
{
|
||||
case Codec.VP9: return "libopus";
|
||||
}
|
||||
return "aac";
|
||||
}
|
||||
|
||||
public static string GetExt(Interpolate.OutMode outMode, bool dot = true)
|
||||
{
|
||||
string ext = dot ? "." : "";
|
||||
|
||||
switch (outMode)
|
||||
{
|
||||
case Interpolate.OutMode.VidMp4: ext += "mp4"; break;
|
||||
case Interpolate.OutMode.VidMkv: ext += "mkv"; break;
|
||||
case Interpolate.OutMode.VidWebm: ext += "webm"; break;
|
||||
case Interpolate.OutMode.VidProRes: ext += "mov"; break;
|
||||
case Interpolate.OutMode.VidAvi: ext += "avi"; break;
|
||||
case Interpolate.OutMode.VidGif: ext += "gif"; break;
|
||||
}
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
public static string GetAudioExt(string videoFile)
|
||||
{
|
||||
switch (FfmpegCommands.GetAudioCodec(videoFile))
|
||||
{
|
||||
case "vorbis": return "ogg";
|
||||
case "opus": return "ogg";
|
||||
case "mp2": return "mp2";
|
||||
case "aac": return "m4a";
|
||||
default: return "wav";
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetAudioFallbackArgs (string containerExt)
|
||||
{
|
||||
containerExt = containerExt.Remove(".");
|
||||
string codec = "aac";
|
||||
string bitrate = $"{Config.GetInt("aacBitrate", 160)}";
|
||||
|
||||
if(containerExt == "webm" || containerExt == "mkv")
|
||||
{
|
||||
codec = "libopus";
|
||||
bitrate = $"{Config.GetInt("opusBitrate", 128)}";
|
||||
}
|
||||
|
||||
return $"-c:a {codec} -b:a {bitrate}k -ac 2";
|
||||
}
|
||||
|
||||
public static string GetAudioExtForContainer(string containerExt)
|
||||
{
|
||||
containerExt = containerExt.Remove(".");
|
||||
string ext = "m4a";
|
||||
|
||||
if (containerExt == "webm" || containerExt == "mkv")
|
||||
ext = "ogg";
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
public static string GetSubCodecForContainer(string containerExt)
|
||||
{
|
||||
containerExt = containerExt.Remove(".");
|
||||
|
||||
if (containerExt == "mp4") return "mov_text";
|
||||
if (containerExt == "webm") return "webvtt";
|
||||
|
||||
return "copy"; // Default: Copy SRT subs
|
||||
}
|
||||
|
||||
public static bool ContainerSupportsSubs(string containerExt, bool showWarningIfNotSupported = true)
|
||||
{
|
||||
containerExt = containerExt.Remove(".");
|
||||
bool supported = (containerExt == "mp4" || containerExt == "mkv" || containerExt == "webm" || containerExt == "mov");
|
||||
Logger.Log($"Subtitles {(supported ? "are supported" : "not supported")} by {containerExt.ToUpper()}", true);
|
||||
if (Config.GetBool("keepSubs") && !supported)
|
||||
Logger.Log($"Warning: Subtitles are enabled, but {containerExt.ToUpper()} does not support them. MKV is recommended instead.");
|
||||
return supported;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.MiscUtils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static Flowframes.AvProcess;
|
||||
|
||||
namespace Flowframes.Media
|
||||
{
|
||||
class FfmpegAlpha
|
||||
{
|
||||
public static async Task ExtractAlphaDir(string rgbDir, string alphaDir)
|
||||
{
|
||||
Directory.CreateDirectory(alphaDir);
|
||||
foreach (FileInfo file in IOUtils.GetFileInfosSorted(rgbDir))
|
||||
{
|
||||
string args = $"-i {file.FullName.Wrap()} -vf format=yuva444p16le,alphaextract,format=yuv420p {Path.Combine(alphaDir, file.Name).Wrap()}";
|
||||
await RunFfmpeg(args, LogMode.Hidden);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task RemoveAlpha(string inputDir, string outputDir, string fillColor = "black")
|
||||
{
|
||||
Directory.CreateDirectory(outputDir);
|
||||
foreach (FileInfo file in IOUtils.GetFileInfosSorted(inputDir))
|
||||
{
|
||||
string outFilename = Path.Combine(outputDir, "_" + file.Name);
|
||||
Size res = IOUtils.GetImage(file.FullName).Size;
|
||||
string args = $" -f lavfi -i color={fillColor}:s={res.Width}x{res.Height} -i {file.FullName.Wrap()} " +
|
||||
$"-filter_complex overlay=0:0:shortest=1 -pix_fmt rgb24 {outFilename.Wrap()}";
|
||||
await RunFfmpeg(args, LogMode.Hidden);
|
||||
file.Delete();
|
||||
File.Move(outFilename, file.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task MergeAlphaIntoRgb(string rgbDir, int rgbPad, string alphaDir, int aPad, bool deleteAlphaDir)
|
||||
{
|
||||
string filter = "-filter_complex [0:v:0][1:v:0]alphamerge[out] -map [out]";
|
||||
string args = $"-i \"{rgbDir}/%{rgbPad}d.png\" -i \"{alphaDir}/%{aPad}d.png\" {filter} \"{rgbDir}/%{rgbPad}d.png\"";
|
||||
await RunFfmpeg(args, LogMode.Hidden);
|
||||
if (deleteAlphaDir)
|
||||
IOUtils.TryDeleteIfExists(alphaDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.MiscUtils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static Flowframes.AvProcess;
|
||||
using Utils = Flowframes.Media.FFmpegUtils;
|
||||
|
||||
namespace Flowframes.Media
|
||||
{
|
||||
partial class FfmpegAudioAndMetadata : FfmpegCommands
|
||||
{
|
||||
public static async Task ExtractAudio(string inputFile, string outFile) // https://stackoverflow.com/a/27413824/14274419
|
||||
{
|
||||
try
|
||||
{
|
||||
string audioExt = Utils.GetAudioExt(inputFile);
|
||||
outFile = Path.ChangeExtension(outFile, audioExt);
|
||||
Logger.Log($"[FFCmds] Extracting audio from {inputFile} to {outFile}", true);
|
||||
string args = $" -loglevel panic -i {inputFile.Wrap()} -vn -c:a copy {outFile.Wrap()}";
|
||||
await RunFfmpeg(args, LogMode.Hidden);
|
||||
if (File.Exists(outFile) && IOUtils.GetFilesize(outFile) < 512)
|
||||
{
|
||||
Logger.Log("Failed to extract audio losslessly! Trying to re-encode.");
|
||||
File.Delete(outFile);
|
||||
|
||||
outFile = Path.ChangeExtension(outFile, Utils.GetAudioExtForContainer(Path.GetExtension(inputFile)));
|
||||
args = $" -loglevel panic -i {inputFile.Wrap()} -vn {Utils.GetAudioFallbackArgs(Path.GetExtension(inputFile))} {outFile.Wrap()}";
|
||||
await RunFfmpeg(args, LogMode.Hidden);
|
||||
|
||||
if ((File.Exists(outFile) && IOUtils.GetFilesize(outFile) < 512) || lastOutputFfmpeg.Contains("Invalid data"))
|
||||
{
|
||||
Logger.Log("Failed to extract audio, even with re-encoding. Output will not have audio.");
|
||||
IOUtils.TryDeleteIfExists(outFile);
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Log($"Source audio has been re-encoded as it can't be extracted losslessly. This may decrease the quality slightly.", false, true);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Error extracting audio: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ExtractSubtitles(string inputFile, string outFolder, Interpolate.OutMode outMode,bool showMsg = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
string msg = "Extracting subtitles from video...";
|
||||
if (showMsg) Logger.Log(msg);
|
||||
|
||||
List<SubtitleTrack> subtitleTracks = await GetSubtitleTracks(inputFile);
|
||||
int counter = 1;
|
||||
|
||||
foreach (SubtitleTrack subTrack in subtitleTracks)
|
||||
{
|
||||
string outPath = Path.Combine(outFolder, $"{subTrack.streamIndex}_{subTrack.langFriendly}_{subTrack.encoding}.srt");
|
||||
string args = $" -loglevel error -sub_charenc {subTrack.encoding} -i {inputFile.Wrap()} -map 0:s:{subTrack.streamIndex} {outPath.Wrap()}";
|
||||
await RunFfmpeg(args, LogMode.Hidden);
|
||||
if (subtitleTracks.Count > 4) Program.mainForm.SetProgress(FormatUtils.RatioInt(counter, subtitleTracks.Count));
|
||||
Logger.Log($"[FFCmds] Extracted subtitle track {subTrack.streamIndex} to {outPath} ({FormatUtils.Bytes(IOUtils.GetFilesize(outPath))})", true, false, "ffmpeg");
|
||||
counter++;
|
||||
}
|
||||
|
||||
if (subtitleTracks.Count > 0)
|
||||
Utils.ContainerSupportsSubs(Utils.GetExt(outMode), true);
|
||||
|
||||
Logger.Log($"Extracted {subtitleTracks.Count} subtitle tracks from the input video.".Replace(" 0 ", " no "), false, Logger.GetLastLine().Contains(msg));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Error extracting subtitles: " + e.Message);
|
||||
}
|
||||
|
||||
Program.mainForm.SetProgress(0);
|
||||
}
|
||||
|
||||
public static async Task<List<SubtitleTrack>> GetSubtitleTracks(string inputFile)
|
||||
{
|
||||
List<SubtitleTrack> subtitleTracks = new List<SubtitleTrack>();
|
||||
string args = $"-i {inputFile.Wrap()}";
|
||||
Logger.Log("GetSubtitleTracks()", true, false, "ffmpeg");
|
||||
string[] outputLines = (await GetFfmpegOutputAsync(args)).SplitIntoLines();
|
||||
int idx = 0;
|
||||
|
||||
for (int i = 0; i < outputLines.Length; i++)
|
||||
{
|
||||
string line = outputLines[i];
|
||||
if (!line.Contains(" Subtitle: ")) continue;
|
||||
|
||||
string lang = "unknown";
|
||||
string subEnc = "UTF-8";
|
||||
|
||||
if (line.Contains("(") && line.Contains("): Subtitle: ")) // Lang code in stream name, like "Stream #0:2(eng): Subtitle: ..."
|
||||
lang = line.Split('(')[1].Split(')')[0];
|
||||
|
||||
if ((i + 2 < outputLines.Length) && outputLines[i + 1].Contains("Metadata:") && outputLines[i + 2].Contains("SUB_CHARENC")) // Subtitle encoding is in metadata!
|
||||
subEnc = outputLines[i + 2].Remove("SUB_CHARENC").Remove(":").TrimWhitespaces();
|
||||
|
||||
Logger.Log($"Found subtitle track #{idx} with language '{lang}' and encoding '{subEnc}'", true, false, "ffmpeg");
|
||||
subtitleTracks.Add(new SubtitleTrack(idx, lang, subEnc));
|
||||
idx++;
|
||||
}
|
||||
|
||||
return subtitleTracks;
|
||||
}
|
||||
|
||||
public static async Task MergeAudioAndSubs(string inputFile, string audioPath, string tempFolder, int looptimes = -1) // https://superuser.com/a/277667
|
||||
{
|
||||
Logger.Log($"[FFCmds] Merging audio from {audioPath} into {inputFile}", true);
|
||||
string containerExt = Path.GetExtension(inputFile);
|
||||
string tempPath = Path.Combine(tempFolder, $"vid{containerExt}"); // inputFile + "-temp" + Path.GetExtension(inputFile);
|
||||
string outPath = Path.Combine(tempFolder, $"muxed{containerExt}"); // inputFile + "-temp" + Path.GetExtension(inputFile);
|
||||
File.Move(inputFile, tempPath);
|
||||
string inName = Path.GetFileName(tempPath);
|
||||
string audioName = Path.GetFileName(audioPath);
|
||||
string outName = Path.GetFileName(outPath);
|
||||
|
||||
bool subs = Utils.ContainerSupportsSubs(containerExt, false) && Config.GetBool("keepSubs");
|
||||
string subInputArgs = "";
|
||||
string subMapArgs = "";
|
||||
string subMetaArgs = "";
|
||||
string[] subTracks = subs ? IOUtils.GetFilesSorted(tempFolder, false, "*.srt") : new string[0];
|
||||
|
||||
for (int subTrack = 0; subTrack < subTracks.Length; subTrack++)
|
||||
{
|
||||
subInputArgs += $" -i {Path.GetFileName(subTracks[subTrack])}";
|
||||
subMapArgs += $" -map {subTrack + 2}";
|
||||
subMetaArgs += $" -metadata:s:s:{subTrack} language={Path.GetFileNameWithoutExtension(subTracks[subTrack]).Split('_')[1]}";
|
||||
}
|
||||
|
||||
string subCodec = Utils.GetSubCodecForContainer(containerExt);
|
||||
string args = $" -i {inName} -stream_loop {looptimes} -i {audioName.Wrap()}" +
|
||||
$"{subInputArgs} -map 0:v -map 1:a {subMapArgs} -c:v copy -c:a copy -c:s {subCodec} {subMetaArgs} -shortest {outName}";
|
||||
|
||||
await RunFfmpeg(args, tempFolder, LogMode.Hidden);
|
||||
|
||||
if ((File.Exists(outPath) && IOUtils.GetFilesize(outPath) < 1024) || lastOutputFfmpeg.Contains("Invalid data") || lastOutputFfmpeg.Contains("Error initializing output stream"))
|
||||
{
|
||||
Logger.Log("Failed to merge audio losslessly! Trying to re-encode.", false, false, "ffmpeg");
|
||||
|
||||
args = $" -i {inName} -stream_loop {looptimes} -i {audioName.Wrap()}" +
|
||||
$"{subInputArgs} -map 0:v -map 1:a {subMapArgs} -c:v copy {Utils.GetAudioFallbackArgs(Path.GetExtension(inputFile))} -c:s {subCodec} {subMetaArgs} -shortest {outName}";
|
||||
|
||||
await RunFfmpeg(args, tempFolder, LogMode.Hidden);
|
||||
|
||||
if ((File.Exists(outPath) && IOUtils.GetFilesize(outPath) < 1024) || lastOutputFfmpeg.Contains("Invalid data") || lastOutputFfmpeg.Contains("Error initializing output stream"))
|
||||
{
|
||||
Logger.Log("Failed to merge audio, even with re-encoding. Output will not have audio.", false, false, "ffmpeg");
|
||||
IOUtils.TryMove(tempPath, inputFile); // Move temp file back
|
||||
IOUtils.TryDeleteIfExists(tempPath);
|
||||
return;
|
||||
}
|
||||
|
||||
string audioExt = Path.GetExtension(audioPath).Remove(".").ToUpper();
|
||||
Logger.Log($"Source audio ({audioExt}) has been re-encoded to fit into the target container ({containerExt.Remove(".").ToUpper()}). This may decrease the quality slightly.", false, true, "ffmpeg");
|
||||
}
|
||||
|
||||
if (File.Exists(outPath) && IOUtils.GetFilesize(outPath) > 512)
|
||||
{
|
||||
File.Delete(tempPath);
|
||||
File.Move(outPath, inputFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.Move(tempPath, inputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
using Flowframes.Media;
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.MiscUtils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static Flowframes.AvProcess;
|
||||
using Utils = Flowframes.Media.FFmpegUtils;
|
||||
|
||||
namespace Flowframes
|
||||
{
|
||||
class FfmpegCommands
|
||||
{
|
||||
public static string divisionFilter = "pad=width=ceil(iw/2)*2:height=ceil(ih/2)*2:color=black@0";
|
||||
public static string pngComprArg = "-compression_level 3";
|
||||
public static string mpDecDef = "\"mpdecimate\"";
|
||||
public static string mpDecAggr = "\"mpdecimate=hi=64*32:lo=64*32:frac=0.1\"";
|
||||
|
||||
public static async Task ConcatVideos(string concatFile, string outPath, int looptimes = -1)
|
||||
{
|
||||
Logger.Log($"Merging videos...", false, Logger.GetLastLine().Contains("frame"));
|
||||
string loopStr = (looptimes > 0) ? $"-stream_loop {looptimes}" : "";
|
||||
string vfrFilename = Path.GetFileName(concatFile);
|
||||
string args = $" {loopStr} -vsync 1 -f concat -i {vfrFilename} -c copy -movflags +faststart {outPath.Wrap()}";
|
||||
await RunFfmpeg(args, concatFile.GetParentDir(), LogMode.Hidden, TaskType.Merge);
|
||||
}
|
||||
|
||||
public static async Task LoopVideo(string inputFile, int times, bool delSrc = false)
|
||||
{
|
||||
string pathNoExt = Path.ChangeExtension(inputFile, null);
|
||||
string ext = Path.GetExtension(inputFile);
|
||||
string args = $" -stream_loop {times} -i {inputFile.Wrap()} -c copy \"{pathNoExt}-Loop{times}{ext}\"";
|
||||
await RunFfmpeg(args, LogMode.Hidden);
|
||||
if (delSrc)
|
||||
DeleteSource(inputFile);
|
||||
}
|
||||
|
||||
public static async Task ChangeSpeed(string inputFile, float newSpeedPercent, bool delSrc = false)
|
||||
{
|
||||
string pathNoExt = Path.ChangeExtension(inputFile, null);
|
||||
string ext = Path.GetExtension(inputFile);
|
||||
float val = newSpeedPercent / 100f;
|
||||
string speedVal = (1f / val).ToString("0.0000").Replace(",", ".");
|
||||
string args = " -itsscale " + speedVal + " -i \"" + inputFile + "\" -c copy \"" + pathNoExt + "-" + newSpeedPercent + "pcSpeed" + ext + "\"";
|
||||
await RunFfmpeg(args, LogMode.OnlyLastLine);
|
||||
if (delSrc)
|
||||
DeleteSource(inputFile);
|
||||
}
|
||||
|
||||
public static long GetDuration(string inputFile)
|
||||
{
|
||||
Logger.Log($"GetDuration({inputFile}) - Reading Duration using ffprobe.", true, false, "ffmpeg");
|
||||
string args = $" -v panic -select_streams v:0 -show_entries format=duration -of csv=s=x:p=0 -sexagesimal {inputFile.Wrap()}";
|
||||
string info = GetFfprobeOutput(args);
|
||||
return FormatUtils.MsFromTimestamp(info);
|
||||
}
|
||||
|
||||
public static async Task<float> GetFramerate(string inputFile)
|
||||
{
|
||||
Logger.Log($"GetFramerate('{inputFile}')", true, false, "ffmpeg");
|
||||
|
||||
try
|
||||
{
|
||||
string args = $" -i {inputFile.Wrap()}";
|
||||
string output = await GetFfmpegOutputAsync(args);
|
||||
string[] entries = output.Split(',');
|
||||
|
||||
foreach (string entry in entries)
|
||||
{
|
||||
if (entry.Contains(" fps") && !entry.Contains("Input ")) // Avoid reading FPS from the filename, in case filename contains "fps"
|
||||
{
|
||||
string num = entry.Replace(" fps", "").Trim().Replace(",", ".");
|
||||
float value;
|
||||
float.TryParse(num, NumberStyles.Any, CultureInfo.InvariantCulture, out value);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.Log("GetFramerate Error: " + e.Message, true, false);
|
||||
}
|
||||
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public static Size GetSize(string inputFile)
|
||||
{
|
||||
string args = $" -v panic -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 {inputFile.Wrap()}";
|
||||
string output = GetFfprobeOutput(args);
|
||||
|
||||
if (output.Length > 4 && output.Contains("x"))
|
||||
{
|
||||
string[] numbers = output.Split('x');
|
||||
return new Size(numbers[0].GetInt(), numbers[1].GetInt());
|
||||
}
|
||||
return new Size(0, 0);
|
||||
}
|
||||
|
||||
public static async Task<int> GetFrameCountAsync(string inputFile)
|
||||
{
|
||||
Logger.Log($"GetFrameCountAsync('{inputFile}') - Trying ffprobe first.", true, false, "ffmpeg");
|
||||
int frames = 0;
|
||||
|
||||
frames = await ReadFrameCountFfprobeAsync(inputFile, Config.GetBool("ffprobeCountFrames")); // Try reading frame count with ffprobe
|
||||
if (frames > 0) return frames;
|
||||
|
||||
Logger.Log($"Failed to get frame count using ffprobe (frames = {frames}). Trying to calculate with duration * fps.", true, false, "ffmpeg");
|
||||
frames = await ReadFrameCountFfmpegAsync(inputFile); // Try reading frame count with ffmpeg
|
||||
if (frames > 0) return frames;
|
||||
|
||||
Logger.Log("Failed to get total frame count of video.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ReadFrameCountFromDuration (string inputFile, long durationMs, float fps)
|
||||
{
|
||||
float durationSeconds = durationMs / 1000f;
|
||||
float frameCount = durationSeconds * fps;
|
||||
int frameCountRounded = frameCount.RoundToInt();
|
||||
Logger.Log($"ReadFrameCountFromDuration: Got frame count of {frameCount}, rounded to {frameCountRounded}");
|
||||
return frameCountRounded;
|
||||
}
|
||||
|
||||
static async Task<int> ReadFrameCountFfprobeAsync(string inputFile, bool readFramesSlow)
|
||||
{
|
||||
string args = $" -v panic -select_streams v:0 -show_entries stream=nb_frames -of default=noprint_wrappers=1 {inputFile.Wrap()}";
|
||||
if (readFramesSlow)
|
||||
{
|
||||
Logger.Log("Counting total frames using FFprobe. This can take a moment...");
|
||||
await Task.Delay(10);
|
||||
args = $" -v panic -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 {inputFile.Wrap()}";
|
||||
}
|
||||
string info = GetFfprobeOutput(args);
|
||||
string[] entries = info.SplitIntoLines();
|
||||
try
|
||||
{
|
||||
if (readFramesSlow)
|
||||
return info.GetInt();
|
||||
foreach (string entry in entries)
|
||||
{
|
||||
if (entry.Contains("nb_frames="))
|
||||
return entry.GetInt();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return -1;
|
||||
}
|
||||
|
||||
static async Task<int> ReadFrameCountFfmpegAsync (string inputFile)
|
||||
{
|
||||
string args = $" -loglevel panic -i {inputFile.Wrap()} -map 0:v:0 -c copy -f null - ";
|
||||
string info = await GetFfmpegOutputAsync(args, true, true);
|
||||
try
|
||||
{
|
||||
string[] lines = info.SplitIntoLines();
|
||||
string lastLine = lines.Last();
|
||||
return lastLine.Substring(0, lastLine.IndexOf("fps")).GetInt();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetAudioCodec(string path)
|
||||
{
|
||||
string args = $" -v panic -show_streams -select_streams a -show_entries stream=codec_name {path.Wrap()}";
|
||||
string info = GetFfprobeOutput(args);
|
||||
string[] entries = info.SplitIntoLines();
|
||||
foreach (string entry in entries)
|
||||
{
|
||||
if (entry.Contains("codec_name="))
|
||||
return entry.Split('=')[1];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void DeleteSource(string path)
|
||||
{
|
||||
Logger.Log("[FFCmds] Deleting input file/dir: " + path, true);
|
||||
|
||||
if (IOUtils.IsPathDirectory(path) && Directory.Exists(path))
|
||||
Directory.Delete(path, true);
|
||||
|
||||
if (!IOUtils.IsPathDirectory(path) && File.Exists(path))
|
||||
File.Delete(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.MiscUtils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static Flowframes.AvProcess;
|
||||
using Utils = Flowframes.Media.FFmpegUtils;
|
||||
|
||||
namespace Flowframes.Media
|
||||
{
|
||||
partial class FfmpegEncode : FfmpegCommands
|
||||
{
|
||||
public static async Task FramesToVideoConcat(string framesFile, string outPath, Interpolate.OutMode outMode, float fps, LogMode logMode = LogMode.OnlyLastLine, bool isChunk = false)
|
||||
{
|
||||
await FramesToVideoConcat(framesFile, outPath, outMode, fps, 0, logMode, isChunk);
|
||||
}
|
||||
|
||||
public static async Task FramesToVideoConcat(string framesFile, string outPath, Interpolate.OutMode outMode, float fps, float resampleFps, LogMode logMode = LogMode.OnlyLastLine, bool isChunk = false)
|
||||
{
|
||||
if (logMode != LogMode.Hidden)
|
||||
Logger.Log((resampleFps <= 0) ? $"Encoding video..." : $"Encoding video resampled to {resampleFps.ToString().Replace(",", ".")} FPS...");
|
||||
Directory.CreateDirectory(outPath.GetParentDir());
|
||||
string encArgs = Utils.GetEncArgs(Utils.GetCodec(outMode));
|
||||
if (!isChunk) encArgs += $" -movflags +faststart";
|
||||
string vfrFilename = Path.GetFileName(framesFile);
|
||||
string rate = fps.ToString().Replace(",", ".");
|
||||
string vf = (resampleFps <= 0) ? "" : $"-vf fps=fps={resampleFps.ToStringDot()}";
|
||||
string extraArgs = Config.Get("ffEncArgs");
|
||||
string args = $"-loglevel error -vsync 0 -f concat -r {rate} -i {vfrFilename} {encArgs} {vf} {extraArgs} -threads {Config.GetInt("ffEncThreads")} {outPath.Wrap()}";
|
||||
await RunFfmpeg(args, framesFile.GetParentDir(), logMode, TaskType.Encode, !isChunk);
|
||||
}
|
||||
|
||||
public static async Task FramesToGifConcat(string framesFile, string outPath, float fps, bool palette, int colors = 64, float resampleFps = -1, LogMode logMode = LogMode.OnlyLastLine)
|
||||
{
|
||||
if (logMode != LogMode.Hidden)
|
||||
Logger.Log((resampleFps <= 0) ? $"Encoding GIF..." : $"Encoding GIF resampled to {resampleFps.ToString().Replace(",", ".")} FPS...");
|
||||
string vfrFilename = Path.GetFileName(framesFile);
|
||||
string paletteFilter = palette ? $"-vf \"split[s0][s1];[s0]palettegen={colors}[p];[s1][p]paletteuse=dither=floyd_steinberg:diff_mode=rectangle\"" : "";
|
||||
string fpsFilter = (resampleFps <= 0) ? "" : $"fps=fps={resampleFps.ToStringDot()}";
|
||||
string vf = FormatUtils.ConcatStrings(new string[] { paletteFilter, fpsFilter });
|
||||
string rate = fps.ToStringDot();
|
||||
string args = $"-loglevel error -f concat -r {rate} -i {vfrFilename.Wrap()} -f gif {vf} {outPath.Wrap()}";
|
||||
await RunFfmpeg(args, framesFile.GetParentDir(), LogMode.OnlyLastLine, TaskType.Encode);
|
||||
}
|
||||
|
||||
public static async Task Encode(string inputFile, string vcodec, string acodec, int crf, int audioKbps = 0, bool delSrc = false)
|
||||
{
|
||||
string outPath = Path.ChangeExtension(inputFile, null) + "-convert.mp4";
|
||||
string args = $" -i {inputFile.Wrap()} -c:v {vcodec} -crf {crf} -pix_fmt yuv420p -c:a {acodec} -b:a {audioKbps}k -vf {divisionFilter} {outPath.Wrap()}";
|
||||
if (string.IsNullOrWhiteSpace(acodec))
|
||||
args = args.Replace("-c:a", "-an");
|
||||
if (audioKbps < 0)
|
||||
args = args.Replace($" -b:a {audioKbps}", "");
|
||||
await RunFfmpeg(args, LogMode.OnlyLastLine, TaskType.Encode, true);
|
||||
if (delSrc)
|
||||
DeleteSource(inputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.MiscUtils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using static Flowframes.AvProcess;
|
||||
|
||||
namespace Flowframes.Media
|
||||
{
|
||||
partial class FfmpegExtract : FfmpegCommands
|
||||
{
|
||||
public static async Task ExtractSceneChanges(string inputFile, string frameFolderPath, float rate)
|
||||
{
|
||||
Logger.Log("Extracting scene changes...");
|
||||
await VideoToFrames(inputFile, frameFolderPath, false, rate, false, false, new Size(320, 180), true);
|
||||
bool hiddenLog = Interpolate.currentInputFrameCount <= 50;
|
||||
int amount = IOUtils.GetAmountOfFiles(frameFolderPath, false);
|
||||
Logger.Log($"Detected {amount} scene {(amount == 1 ? "change" : "changes")}.".Replace(" 0 ", " no "), false, !hiddenLog);
|
||||
}
|
||||
|
||||
public static async Task VideoToFrames(string inputFile, string framesDir, bool alpha, float rate, bool deDupe, bool delSrc)
|
||||
{
|
||||
await VideoToFrames(inputFile, framesDir, alpha, rate, deDupe, delSrc, new Size());
|
||||
}
|
||||
|
||||
public static async Task VideoToFrames(string inputFile, string framesDir, bool alpha, float rate, bool deDupe, bool delSrc, Size size, bool sceneDetect = false)
|
||||
{
|
||||
if (!sceneDetect) Logger.Log("Extracting video frames from input video...");
|
||||
string sizeStr = (size.Width > 1 && size.Height > 1) ? $"-s {size.Width}x{size.Height}" : "";
|
||||
IOUtils.CreateDir(framesDir);
|
||||
string timecodeStr = /* timecodes ? $"-copyts -r {FrameOrder.timebase} -frame_pts true" : */ "-copyts -frame_pts true";
|
||||
string scnDetect = sceneDetect ? $"\"select='gt(scene,{Config.GetFloatString("scnDetectValue")})'\"" : "";
|
||||
string mpStr = deDupe ? ((Config.GetInt("mpdecimateMode") == 0) ? mpDecDef : mpDecAggr) : "";
|
||||
string filters = FormatUtils.ConcatStrings(new string[] { divisionFilter, scnDetect, mpStr });
|
||||
string vf = filters.Length > 2 ? $"-vf {filters}" : "";
|
||||
string rateArg = (rate > 0) ? $" -r {rate.ToStringDot()}" : "";
|
||||
string pixFmt = alpha ? "-pix_fmt rgba" : "-pix_fmt rgb24"; // Use RGBA for GIF for alpha support
|
||||
string args = $"{rateArg} -i {inputFile.Wrap()} {pngComprArg} -vsync 0 {pixFmt} {timecodeStr} {vf} {sizeStr} \"{framesDir}/%{Padding.inputFrames}d.png\"";
|
||||
LogMode logMode = Interpolate.currentInputFrameCount > 50 ? LogMode.OnlyLastLine : LogMode.Hidden;
|
||||
await AvProcess.RunFfmpeg(args, logMode, TaskType.ExtractFrames, true);
|
||||
int amount = IOUtils.GetAmountOfFiles(framesDir, false, "*.png");
|
||||
if (!sceneDetect) Logger.Log($"Extracted {amount} {(amount == 1 ? "frame" : "frames")} from input.", false, true);
|
||||
await Task.Delay(1);
|
||||
if (delSrc)
|
||||
DeleteSource(inputFile);
|
||||
}
|
||||
|
||||
public static async Task ImportImages(string inpath, string outpath, bool alpha, Size size, bool delSrc = false, bool showLog = true)
|
||||
{
|
||||
if (showLog) Logger.Log("Importing images...");
|
||||
Logger.Log($"Importing images from {inpath} to {outpath}.", true);
|
||||
IOUtils.CreateDir(outpath);
|
||||
string concatFile = Path.Combine(Paths.GetDataPath(), "png-concat-temp.ini");
|
||||
string concatFileContent = "";
|
||||
string[] files = IOUtils.GetFilesSorted(inpath);
|
||||
foreach (string img in files)
|
||||
concatFileContent += $"file '{img.Replace(@"\", "/")}'\n";
|
||||
File.WriteAllText(concatFile, concatFileContent);
|
||||
|
||||
string sizeStr = (size.Width > 1 && size.Height > 1) ? $"-s {size.Width}x{size.Height}" : "";
|
||||
string pixFmt = alpha ? "-pix_fmt rgba" : "-pix_fmt rgb24"; // Use RGBA for GIF for alpha support
|
||||
string vf = alpha ? $"-filter_complex \"[0:v]{divisionFilter},split[a][b];[a]palettegen=reserve_transparent=on:transparency_color=ffffff[p];[b][p]paletteuse\"" : $"-vf {divisionFilter}";
|
||||
string args = $" -loglevel panic -f concat -safe 0 -i {concatFile.Wrap()} {pngComprArg} {sizeStr} {pixFmt} -vsync 0 {vf} \"{outpath}/%{Padding.inputFrames}d.png\"";
|
||||
LogMode logMode = IOUtils.GetAmountOfFiles(inpath, false) > 50 ? LogMode.OnlyLastLine : LogMode.Hidden;
|
||||
await AvProcess.RunFfmpeg(args, logMode, TaskType.ExtractFrames);
|
||||
if (delSrc)
|
||||
DeleteSource(inpath);
|
||||
}
|
||||
|
||||
public static async Task ImportSingleImage(string inputFile, string outPath, Size size)
|
||||
{
|
||||
string sizeStr = (size.Width > 1 && size.Height > 1) ? $"-s {size.Width}x{size.Height}" : "";
|
||||
bool isPng = (Path.GetExtension(outPath).ToLower() == ".png");
|
||||
string comprArg = isPng ? pngComprArg : "";
|
||||
string pixFmt = "-pix_fmt " + (isPng ? $"rgb24 {comprArg}" : "yuvj420p");
|
||||
string args = $"-i {inputFile.Wrap()} {comprArg} {sizeStr} {pixFmt} -vf {divisionFilter} {outPath.Wrap()}";
|
||||
await AvProcess.RunFfmpeg(args, LogMode.Hidden, TaskType.ExtractFrames);
|
||||
}
|
||||
|
||||
public static async Task ExtractSingleFrame(string inputFile, string outputPath, int frameNum)
|
||||
{
|
||||
bool isPng = (Path.GetExtension(outputPath).ToLower() == ".png");
|
||||
string comprArg = isPng ? pngComprArg : "";
|
||||
string pixFmt = "-pix_fmt " + (isPng ? $"rgb24 {comprArg}" : "yuvj420p");
|
||||
string args = $"-i {inputFile.Wrap()} -vf \"select=eq(n\\,{frameNum})\" -vframes 1 {pixFmt} {outputPath.Wrap()}";
|
||||
await AvProcess.RunFfmpeg(args, LogMode.Hidden, TaskType.ExtractFrames);
|
||||
}
|
||||
|
||||
public static async Task ExtractLastFrame(string inputFile, string outputPath, Size size)
|
||||
{
|
||||
if (IOUtils.IsPathDirectory(outputPath))
|
||||
outputPath = Path.Combine(outputPath, "last.png");
|
||||
bool isPng = (Path.GetExtension(outputPath).ToLower() == ".png");
|
||||
string comprArg = isPng ? pngComprArg : "";
|
||||
string pixFmt = "-pix_fmt " + (isPng ? $"rgb24 {comprArg}" : "yuvj420p");
|
||||
string sizeStr = (size.Width > 1 && size.Height > 1) ? $"-s {size.Width}x{size.Height}" : "";
|
||||
string args = $"-sseof -1 -i {inputFile.Wrap()} -update 1 {pixFmt} {sizeStr} {outputPath.Wrap()}";
|
||||
await AvProcess.RunFfmpeg(args, LogMode.Hidden, TaskType.ExtractFrames);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.MiscUtils
|
||||
{
|
||||
class Benchmarker
|
||||
{
|
||||
static Stopwatch sw = new Stopwatch();
|
||||
|
||||
public static void Start ()
|
||||
{
|
||||
sw.Restart();
|
||||
}
|
||||
|
||||
public static string GetTimeStr (bool stop)
|
||||
{
|
||||
if (stop)
|
||||
sw.Stop();
|
||||
|
||||
return FormatUtils.TimeSw(sw);
|
||||
}
|
||||
|
||||
public static TimeSpan GetTime(bool stop)
|
||||
{
|
||||
if (stop)
|
||||
sw.Stop();
|
||||
|
||||
return sw.Elapsed;
|
||||
}
|
||||
|
||||
public static long GetTimeMs(bool stop)
|
||||
{
|
||||
if (stop)
|
||||
sw.Stop();
|
||||
|
||||
return sw.ElapsedMilliseconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flowframes.MiscUtils
|
||||
{
|
||||
class FormatUtils
|
||||
{
|
||||
public static string Bytes(long sizeBytes)
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
|
||||
if (sizeBytes == 0)
|
||||
return "0" + suf[0];
|
||||
long bytes = Math.Abs(sizeBytes);
|
||||
int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
|
||||
double num = Math.Round(bytes / Math.Pow(1024, place), 1);
|
||||
return ($"{Math.Sign(sizeBytes) * num} {suf[place]}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "N/A B";
|
||||
}
|
||||
}
|
||||
|
||||
public static string Time(long milliseconds)
|
||||
{
|
||||
double secs = (milliseconds / 1000f);
|
||||
if (milliseconds <= 1000)
|
||||
{
|
||||
return milliseconds + "ms";
|
||||
}
|
||||
return secs.ToString("0.00") + "s";
|
||||
}
|
||||
|
||||
public static string Time (TimeSpan span, bool allowMs = true)
|
||||
{
|
||||
if(span.TotalHours >= 1f)
|
||||
return span.ToString(@"hh\:mm\:ss");
|
||||
|
||||
if (span.TotalMinutes >= 1f)
|
||||
return span.ToString(@"mm\:ss");
|
||||
|
||||
if (span.TotalSeconds >= 1f || !allowMs)
|
||||
return span.ToString(@"ss".TrimStart('0').PadLeft(1, '0')) + "s";
|
||||
|
||||
return span.ToString(@"fff").TrimStart('0').PadLeft(1, '0') + "ms";
|
||||
}
|
||||
|
||||
public static string TimeSw(Stopwatch sw)
|
||||
{
|
||||
long elapsedMs = sw.ElapsedMilliseconds;
|
||||
return Time(elapsedMs);
|
||||
}
|
||||
|
||||
public static long MsFromTimestamp(string timestamp)
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] values = timestamp.Split(':');
|
||||
int hours = int.Parse(values[0]);
|
||||
int minutes = int.Parse(values[1]);
|
||||
int seconds = int.Parse(values[2].Split('.')[0]);
|
||||
int milliseconds = int.Parse(values[2].Split('.')[1].Substring(0, 2)) * 10;
|
||||
long ms = hours * 3600000 + minutes * 60000 + seconds * 1000 + milliseconds;
|
||||
return ms;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"MsFromTimeStamp({timestamp}) Exception: {e.Message}", true);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static string MsToTimestamp(long milliseconds)
|
||||
{
|
||||
return (new DateTime(1970, 1, 1)).AddMilliseconds(milliseconds).ToString("HH:mm:ss");
|
||||
}
|
||||
|
||||
public static string Ratio(long numFrom, long numTo)
|
||||
{
|
||||
float ratio = ((float)numFrom / (float)numTo) * 100f;
|
||||
return ratio.ToString("0.00") + "%";
|
||||
}
|
||||
|
||||
public static int RatioInt(long numFrom, long numTo)
|
||||
{
|
||||
double ratio = Math.Round(((float)numFrom / (float)numTo) * 100f);
|
||||
return (int)ratio;
|
||||
}
|
||||
|
||||
public static string RatioIntStr(long numFrom, long numTo)
|
||||
{
|
||||
double ratio = Math.Round(((float)numFrom / (float)numTo) * 100f);
|
||||
return ratio + "%";
|
||||
}
|
||||
|
||||
public static string ConcatStrings(string[] strings, char delimiter = ',', bool distinct = false)
|
||||
{
|
||||
string outStr = "";
|
||||
|
||||
strings = strings.Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
|
||||
if(distinct)
|
||||
strings = strings.Distinct().ToArray();
|
||||
|
||||
for (int i = 0; i < strings.Length; i++)
|
||||
{
|
||||
outStr += strings[i];
|
||||
if (i + 1 != strings.Length)
|
||||
outStr += delimiter;
|
||||
}
|
||||
|
||||
return outStr;
|
||||
}
|
||||
|
||||
public static System.Drawing.Size ParseSize (string str)
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] values = str.Split('x');
|
||||
return new System.Drawing.Size(values[0].GetInt(), values[1].GetInt());
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new System.Drawing.Size();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,359 +0,0 @@
|
||||
using Flowframes.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Flowframes.OS;
|
||||
using Flowframes.UI;
|
||||
using Flowframes.Main;
|
||||
using Flowframes.Data;
|
||||
using Flowframes.MiscUtils;
|
||||
using Flowframes.Magick;
|
||||
using Flowframes.Media;
|
||||
|
||||
namespace Flowframes
|
||||
{
|
||||
class AiProcess
|
||||
{
|
||||
public static bool hasShownError;
|
||||
|
||||
public static Process currentAiProcess;
|
||||
public static Stopwatch processTime = new Stopwatch();
|
||||
public static Stopwatch processTimeMulti = new Stopwatch();
|
||||
|
||||
public static int lastStartupTimeMs = 1000;
|
||||
static string lastInPath;
|
||||
|
||||
public static Dictionary<string, string> filenameMap = new Dictionary<string, string>(); // TODO: Store on disk instead for crashes?
|
||||
|
||||
static void AiStarted (Process proc, int startupTimeMs, string inPath = "")
|
||||
{
|
||||
lastStartupTimeMs = startupTimeMs;
|
||||
processTime.Restart();
|
||||
currentAiProcess = proc;
|
||||
lastInPath = string.IsNullOrWhiteSpace(inPath) ? Interpolate.current.framesFolder : inPath;
|
||||
hasShownError = false;
|
||||
}
|
||||
|
||||
static void SetProgressCheck(string interpPath, float factor)
|
||||
{
|
||||
int frames = IOUtils.GetAmountOfFiles(lastInPath, false, "*.png");
|
||||
int target = ((frames * factor) - (factor - 1)).RoundToInt();
|
||||
InterpolateUtils.progressPaused = false;
|
||||
InterpolateUtils.currentFactor = factor;
|
||||
|
||||
if (InterpolateUtils.progCheckRunning)
|
||||
InterpolateUtils.targetFrames = target;
|
||||
else
|
||||
InterpolateUtils.GetProgressByFrameAmount(interpPath, target);
|
||||
}
|
||||
|
||||
static async Task AiFinished (string aiName)
|
||||
{
|
||||
if (Interpolate.canceled) return;
|
||||
Program.mainForm.SetProgress(100);
|
||||
InterpolateUtils.UpdateInterpProgress(IOUtils.GetAmountOfFiles(Interpolate.current.interpFolder, false, "*.png"), InterpolateUtils.targetFrames);
|
||||
string logStr = $"Done running {aiName} - Interpolation took {FormatUtils.Time(processTime.Elapsed)}";
|
||||
if (Interpolate.currentlyUsingAutoEnc && AutoEncode.HasWorkToDo())
|
||||
logStr += " - Waiting for encoding to finish...";
|
||||
Logger.Log(logStr);
|
||||
processTime.Stop();
|
||||
|
||||
while (Interpolate.currentlyUsingAutoEnc && Program.busy)
|
||||
{
|
||||
if (AvProcess.lastProcess != null && !AvProcess.lastProcess.HasExited && AvProcess.lastTask == AvProcess.TaskType.Encode)
|
||||
{
|
||||
string lastLine = AvProcess.lastOutputFfmpeg.SplitIntoLines().Last();
|
||||
Logger.Log(lastLine.Trim().TrimWhitespaces(), false, Logger.GetLastLine().Contains("frame"));
|
||||
}
|
||||
|
||||
if (AvProcess.timeSinceLastOutput.IsRunning && AvProcess.timeSinceLastOutput.ElapsedMilliseconds > 2500)
|
||||
break;
|
||||
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
if (!Interpolate.canceled && Interpolate.current.alpha)
|
||||
{
|
||||
Logger.Log("Processing alpha...");
|
||||
string rgbInterpDir = Path.Combine(Interpolate.current.tempFolder, Paths.interpDir);
|
||||
string alphaInterpDir = Path.Combine(Interpolate.current.tempFolder, Paths.interpDir + Paths.alphaSuffix);
|
||||
if (!Directory.Exists(alphaInterpDir)) return;
|
||||
await FfmpegAlpha.MergeAlphaIntoRgb(rgbInterpDir, Padding.interpFrames, alphaInterpDir, Padding.interpFrames, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task RunRifeCuda(string framesPath, float interpFactor, string mdl)
|
||||
{
|
||||
string rifeDir = Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.rifeCuda.fileName));
|
||||
string script = "rife.py";
|
||||
|
||||
if (!File.Exists(Path.Combine(rifeDir, script)))
|
||||
{
|
||||
Interpolate.Cancel("RIFE script not found! Make sure you didn't modify any files.");
|
||||
return;
|
||||
}
|
||||
|
||||
await RunRifeCudaProcess(framesPath, Paths.interpDir, script, interpFactor, mdl);
|
||||
|
||||
if (!Interpolate.canceled && Interpolate.current.alpha)
|
||||
{
|
||||
InterpolateUtils.progressPaused = true;
|
||||
Logger.Log("Interpolating alpha channel...");
|
||||
await RunRifeCudaProcess(framesPath + Paths.alphaSuffix, Paths.interpDir + Paths.alphaSuffix, script, interpFactor, mdl);
|
||||
}
|
||||
|
||||
await AiFinished("RIFE");
|
||||
}
|
||||
|
||||
public static async Task RunRifeCudaProcess (string inPath, string outDir, string script, float interpFactor, string mdl)
|
||||
{
|
||||
bool parallel = false;
|
||||
string uhdStr = await InterpolateUtils.UseUHD() ? "--UHD" : "";
|
||||
string outPath = Path.Combine(inPath.GetParentDir(), outDir);
|
||||
string args = $" --input {inPath.Wrap()} --output {outDir} --model {mdl} --exp {(int)Math.Log(interpFactor, 2)} ";
|
||||
if (parallel) args = $" --input {inPath.Wrap()} --output {outPath} --model {mdl} --factor {interpFactor}";
|
||||
if (parallel) script = "rife-parallel.py";
|
||||
|
||||
Process rifePy = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
|
||||
AiStarted(rifePy, 3500);
|
||||
SetProgressCheck(Path.Combine(Interpolate.current.tempFolder, outDir), interpFactor);
|
||||
rifePy.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {PkgUtils.GetPkgFolder(Packages.rifeCuda).Wrap()} & " +
|
||||
$"set CUDA_VISIBLE_DEVICES={Config.Get("torchGpus")} & {Python.GetPyCmd()} {script} {args}";
|
||||
Logger.Log($"Running RIFE {(await InterpolateUtils.UseUHD() ? "(UHD Mode)" : "")} ({script})...".TrimWhitespaces(), false);
|
||||
Logger.Log("cmd.exe " + rifePy.StartInfo.Arguments, true);
|
||||
|
||||
if (!OSUtils.ShowHiddenCmd())
|
||||
{
|
||||
rifePy.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, "rife-cuda-log"); };
|
||||
rifePy.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "rife-cuda-log", true); };
|
||||
}
|
||||
rifePy.Start();
|
||||
if (!OSUtils.ShowHiddenCmd())
|
||||
{
|
||||
rifePy.BeginOutputReadLine();
|
||||
rifePy.BeginErrorReadLine();
|
||||
}
|
||||
|
||||
while (!rifePy.HasExited) await Task.Delay(1);
|
||||
}
|
||||
|
||||
public static async Task RunRifeNcnn (string framesPath, string outPath, int factor, string mdl)
|
||||
{
|
||||
processTimeMulti.Restart();
|
||||
Logger.Log($"Running RIFE{(await InterpolateUtils.UseUHD() ? " (UHD Mode)" : "")}...", false);
|
||||
|
||||
await RunRifeNcnnMulti(framesPath, outPath, factor, mdl);
|
||||
|
||||
if (!Interpolate.canceled && Interpolate.current.alpha)
|
||||
{
|
||||
InterpolateUtils.progressPaused = true;
|
||||
Logger.Log("Interpolating alpha channel...");
|
||||
await RunRifeNcnnMulti(framesPath + Paths.alphaSuffix, outPath + Paths.alphaSuffix, factor, mdl);
|
||||
}
|
||||
|
||||
await AiFinished("RIFE");
|
||||
}
|
||||
|
||||
static async Task RunRifeNcnnMulti(string framesPath, string outPath, int factor, string mdl)
|
||||
{
|
||||
int times = (int)Math.Log(factor, 2);
|
||||
|
||||
if (times > 1)
|
||||
AutoEncode.paused = true; // Disable autoenc until the last iteration
|
||||
|
||||
for (int iteration = 1; iteration <= times; iteration++)
|
||||
{
|
||||
if (Interpolate.canceled) return;
|
||||
|
||||
if (Interpolate.currentlyUsingAutoEnc && iteration == times) // Enable autoenc if this is the last iteration
|
||||
AutoEncode.paused = false;
|
||||
|
||||
if (iteration > 1)
|
||||
{
|
||||
Logger.Log($"Re-Running RIFE for {Math.Pow(2, iteration)}x interpolation...", false);
|
||||
string lastInterpPath = outPath + $"-run{iteration - 1}";
|
||||
Directory.Move(outPath, lastInterpPath); // Rename last interp folder
|
||||
await RunRifeNcnnProcess(lastInterpPath, outPath, mdl);
|
||||
IOUtils.TryDeleteIfExists(lastInterpPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
await RunRifeNcnnProcess(framesPath, outPath, mdl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async Task RunRifeNcnnProcess(string inPath, string outPath, string mdl)
|
||||
{
|
||||
Directory.CreateDirectory(outPath);
|
||||
Process rifeNcnn = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
|
||||
AiStarted(rifeNcnn, 1500, inPath);
|
||||
SetProgressCheck(outPath, 2);
|
||||
|
||||
string uhdStr = await InterpolateUtils.UseUHD() ? "-u" : "";
|
||||
string ttaStr = Config.GetBool("rifeNcnnUseTta", false) ? "-x" : "";
|
||||
|
||||
rifeNcnn.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {PkgUtils.GetPkgFolder(Packages.rifeNcnn).Wrap()} & rife-ncnn-vulkan.exe " +
|
||||
$" -v -i {inPath.Wrap()} -o {outPath.Wrap()} -m {mdl.ToLower()} {ttaStr} {uhdStr} -g {Config.Get("ncnnGpus")} -f {GetNcnnPattern()} -j {GetNcnnThreads()}";
|
||||
|
||||
Logger.Log("cmd.exe " + rifeNcnn.StartInfo.Arguments, true);
|
||||
|
||||
if (!OSUtils.ShowHiddenCmd())
|
||||
{
|
||||
rifeNcnn.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, "rife-ncnn-log"); };
|
||||
rifeNcnn.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "rife-ncnn-log", true); };
|
||||
}
|
||||
|
||||
rifeNcnn.Start();
|
||||
|
||||
if (!OSUtils.ShowHiddenCmd())
|
||||
{
|
||||
rifeNcnn.BeginOutputReadLine();
|
||||
rifeNcnn.BeginErrorReadLine();
|
||||
}
|
||||
|
||||
while (!rifeNcnn.HasExited) await Task.Delay(1);
|
||||
}
|
||||
|
||||
public static async Task RunDainNcnn(string framesPath, string outPath, float factor, string mdl, int tilesize)
|
||||
{
|
||||
await RunDainNcnnProcess(framesPath, outPath, factor, mdl, tilesize);
|
||||
|
||||
if (!Interpolate.canceled && Interpolate.current.alpha)
|
||||
{
|
||||
InterpolateUtils.progressPaused = true;
|
||||
Logger.Log("Interpolating alpha channel...");
|
||||
await RunDainNcnnProcess(framesPath + Paths.alphaSuffix, outPath + Paths.alphaSuffix, factor, mdl, tilesize);
|
||||
}
|
||||
|
||||
await AiFinished("DAIN");
|
||||
}
|
||||
|
||||
public static async Task RunDainNcnnProcess (string framesPath, string outPath, float factor, string mdl, int tilesize)
|
||||
{
|
||||
string dainDir = Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.dainNcnn.fileName));
|
||||
Directory.CreateDirectory(outPath);
|
||||
Process dain = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
|
||||
AiStarted(dain, 1500);
|
||||
SetProgressCheck(outPath, factor);
|
||||
int targetFrames = ((IOUtils.GetAmountOfFiles(lastInPath, false, "*.png") * factor).RoundToInt()) - (factor.RoundToInt() - 1); // TODO: Won't work with fractional factors
|
||||
|
||||
string args = $" -v -i {framesPath.Wrap()} -o {outPath.Wrap()} -n {targetFrames} -m {mdl.ToLower()}" +
|
||||
$" -t {GetNcnnTilesize(tilesize)} -g {Config.Get("ncnnGpus")} -f {GetNcnnPattern()} -j 2:1:2";
|
||||
|
||||
dain.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {dainDir.Wrap()} & dain-ncnn-vulkan.exe {args}";
|
||||
Logger.Log("Running DAIN...", false);
|
||||
Logger.Log("cmd.exe " + dain.StartInfo.Arguments, true);
|
||||
|
||||
if (!OSUtils.ShowHiddenCmd())
|
||||
{
|
||||
dain.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, "dain-ncnn-log"); };
|
||||
dain.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "dain-ncnn-log", true); };
|
||||
}
|
||||
|
||||
dain.Start();
|
||||
if (!OSUtils.ShowHiddenCmd())
|
||||
{
|
||||
dain.BeginOutputReadLine();
|
||||
dain.BeginErrorReadLine();
|
||||
}
|
||||
|
||||
while (!dain.HasExited)
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
static void LogOutput (string line, string logFilename, bool err = false)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line) || line.Length < 6)
|
||||
return;
|
||||
|
||||
Logger.LogToFile(line, false, logFilename);
|
||||
|
||||
if (line.Contains("ff:nocuda-cpu"))
|
||||
Logger.Log("WARNING: CUDA-capable GPU device is not available, running on CPU instead!");
|
||||
|
||||
if (!hasShownError && err && line.ToLower().Contains("out of memory"))
|
||||
{
|
||||
hasShownError = true;
|
||||
InterpolateUtils.ShowMessage($"Your GPU ran out of VRAM! Please try a video with a lower resolution or use the Max Video Size option in the settings.\n\n{line}", "Error");
|
||||
}
|
||||
|
||||
if (!hasShownError && err && line.ToLower().Contains("modulenotfounderror"))
|
||||
{
|
||||
hasShownError = true;
|
||||
InterpolateUtils.ShowMessage($"A python module is missing.\nCheck {logFilename} for details.\n\n{line}", "Error");
|
||||
if(!Python.HasEmbeddedPyFolder())
|
||||
Process.Start("https://github.com/n00mkrad/flowframes/blob/main/PythonDependencies.md");
|
||||
}
|
||||
|
||||
if (!hasShownError && line.ToLower().Contains("no longer supports this gpu"))
|
||||
{
|
||||
hasShownError = true;
|
||||
InterpolateUtils.ShowMessage($"Your GPU seems to be outdated and is not supported!\n\n{line}", "Error");
|
||||
}
|
||||
|
||||
if (!hasShownError && err && (line.Contains("RuntimeError") || line.Contains("ImportError") || line.Contains("OSError")))
|
||||
{
|
||||
hasShownError = true;
|
||||
InterpolateUtils.ShowMessage($"A python error occured during interpolation!\nCheck {logFilename} for details.\n\n{line}", "Error");
|
||||
}
|
||||
|
||||
if (!hasShownError && err && line.Contains("vk") && line.Contains(" failed"))
|
||||
{
|
||||
hasShownError = true;
|
||||
string dain = (Interpolate.current.ai.aiName == Networks.dainNcnn.aiName) ? "\n\nTry reducing the tile size in the AI settings." : "";
|
||||
InterpolateUtils.ShowMessage($"A Vulkan error occured during interpolation!\n\n{line}{dain}", "Error");
|
||||
}
|
||||
|
||||
if (!hasShownError && err && line.Contains("vkAllocateMemory failed"))
|
||||
{
|
||||
hasShownError = true;
|
||||
bool usingDain = (Interpolate.current.ai.aiName == Networks.dainNcnn.aiName);
|
||||
string msg = usingDain ? "\n\nTry reducing the tile size in the AI settings." : "Try a lower resolution (Settings -> Max Video Size).";
|
||||
InterpolateUtils.ShowMessage($"Vulkan ran out of memory!\n\n{line}{msg}", "Error");
|
||||
}
|
||||
|
||||
if (!hasShownError && err && line.Contains("invalid gpu device"))
|
||||
{
|
||||
hasShownError = true;
|
||||
InterpolateUtils.ShowMessage($"A Vulkan error occured during interpolation!\n\n{line}\n\nAre your GPU IDs set correctly?", "Error");
|
||||
}
|
||||
|
||||
if (hasShownError)
|
||||
Interpolate.Cancel();
|
||||
}
|
||||
|
||||
static string GetNcnnPattern ()
|
||||
{
|
||||
return $"%0{Padding.interpFrames}d.{InterpolateUtils.GetOutExt()}";
|
||||
}
|
||||
|
||||
static string GetNcnnTilesize(int tilesize)
|
||||
{
|
||||
int gpusAmount = Config.Get("ncnnGpus").Split(',').Length;
|
||||
string tilesizeStr = $"{tilesize}";
|
||||
|
||||
for (int i = 1; i < gpusAmount; i++)
|
||||
tilesizeStr += $",{tilesize}";
|
||||
|
||||
return tilesizeStr;
|
||||
}
|
||||
|
||||
static string GetNcnnThreads ()
|
||||
{
|
||||
int gpusAmount = Config.Get("ncnnGpus").Split(',').Length;
|
||||
int procThreads = Config.GetInt("ncnnThreads");
|
||||
string progThreadsStr = $"{procThreads}";
|
||||
|
||||
for (int i = 1; i < gpusAmount; i++)
|
||||
progThreadsStr += $",{procThreads}";
|
||||
|
||||
return $"4:{progThreadsStr}:4"; ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
using NvAPIWrapper;
|
||||
using NvAPIWrapper.GPU;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.OS
|
||||
{
|
||||
class NvApi
|
||||
{
|
||||
static PhysicalGPU gpu;
|
||||
|
||||
public static async void Init()
|
||||
{
|
||||
try
|
||||
{
|
||||
NVIDIA.Initialize();
|
||||
PhysicalGPU[] gpus = PhysicalGPU.GetPhysicalGPUs();
|
||||
if (gpus.Length == 0)
|
||||
return;
|
||||
gpu = gpus[0];
|
||||
|
||||
Logger.Log($"Initialized NvApi. GPU: {gpu.FullName}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Failed to initialize NvApi: {e.Message}\nIgnore this if you don't have an Nvidia GPU.");
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetVramGb ()
|
||||
{
|
||||
try
|
||||
{
|
||||
return (gpu.MemoryInformation.AvailableDedicatedVideoMemoryInkB / 1000f / 1024f);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetFreeVramGb()
|
||||
{
|
||||
try
|
||||
{
|
||||
return (gpu.MemoryInformation.CurrentAvailableDedicatedVideoMemoryInkB / 1000f / 1024f);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetGpuName()
|
||||
{
|
||||
try
|
||||
{
|
||||
NVIDIA.Initialize();
|
||||
PhysicalGPU[] gpus = PhysicalGPU.GetPhysicalGPUs();
|
||||
if (gpus.Length == 0)
|
||||
return "";
|
||||
|
||||
return gpus[0].FullName;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Security.Principal;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Management;
|
||||
using Flowframes.IO;
|
||||
using DiskDetector;
|
||||
using DiskDetector.Models;
|
||||
using Microsoft.VisualBasic.Devices;
|
||||
|
||||
namespace Flowframes.OS
|
||||
{
|
||||
class OSUtils
|
||||
{
|
||||
public static bool IsUserAdministrator()
|
||||
{
|
||||
//bool value to hold our return value
|
||||
bool isAdmin;
|
||||
WindowsIdentity user = null;
|
||||
try
|
||||
{
|
||||
//get the currently logged in user
|
||||
user = WindowsIdentity.GetCurrent();
|
||||
WindowsPrincipal principal = new WindowsPrincipal(user);
|
||||
isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
isAdmin = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
isAdmin = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (user != null)
|
||||
user.Dispose();
|
||||
}
|
||||
return isAdmin;
|
||||
}
|
||||
|
||||
public static Process SetStartInfo(Process proc, bool hidden, string filename = "cmd.exe")
|
||||
{
|
||||
proc.StartInfo.UseShellExecute = !hidden;
|
||||
proc.StartInfo.RedirectStandardOutput = hidden;
|
||||
proc.StartInfo.RedirectStandardError = hidden;
|
||||
proc.StartInfo.CreateNoWindow = hidden;
|
||||
proc.StartInfo.FileName = filename;
|
||||
return proc;
|
||||
}
|
||||
|
||||
public static Process NewProcess(bool hidden, string filename = "cmd.exe")
|
||||
{
|
||||
Process proc = new Process();
|
||||
return SetStartInfo(proc, hidden, filename);
|
||||
}
|
||||
|
||||
public static void KillProcessTree(int pid)
|
||||
{
|
||||
ManagementObjectSearcher processSearcher = new ManagementObjectSearcher
|
||||
("Select * From Win32_Process Where ParentProcessID=" + pid);
|
||||
ManagementObjectCollection processCollection = processSearcher.Get();
|
||||
|
||||
try
|
||||
{
|
||||
Process proc = Process.GetProcessById(pid);
|
||||
if (!proc.HasExited) proc.Kill();
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// Process already exited.
|
||||
}
|
||||
|
||||
if (processCollection != null)
|
||||
{
|
||||
foreach (ManagementObject mo in processCollection)
|
||||
{
|
||||
KillProcessTree(Convert.ToInt32(mo["ProcessID"])); //kill child processes(also kills childrens of childrens etc.)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetCmdArg()
|
||||
{
|
||||
bool stayOpen = Config.GetInt("cmdDebugMode") == 2;
|
||||
if (stayOpen)
|
||||
return "/K";
|
||||
else
|
||||
return "/C";
|
||||
}
|
||||
|
||||
public static bool ShowHiddenCmd()
|
||||
{
|
||||
return Config.GetInt("cmdDebugMode") > 0;
|
||||
}
|
||||
|
||||
public static bool DriveIsSSD(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
var detectedDrives = Detector.DetectFixedDrives(QueryType.SeekPenalty);
|
||||
if (detectedDrives.Count != 0)
|
||||
{
|
||||
char pathDriveLetter = (path[0].ToString().ToUpper())[0];
|
||||
foreach (var detectedDrive in detectedDrives)
|
||||
{
|
||||
if (detectedDrive.DriveLetter == pathDriveLetter && detectedDrive.HardwareType.ToString().ToLower().Trim() == "ssd")
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Failed to detect drive type: " + e.Message);
|
||||
return true; // Default to SSD on fail
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool HasNonAsciiChars(string str)
|
||||
{
|
||||
return (Encoding.UTF8.GetByteCount(str) != str.Length);
|
||||
}
|
||||
|
||||
public static int GetFreeRamMb ()
|
||||
{
|
||||
try
|
||||
{
|
||||
return (int)(new ComputerInfo().AvailablePhysicalMemory / 1048576);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
using Flowframes.IO;
|
||||
using Flowframes.MiscUtils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.OS
|
||||
{
|
||||
class Python
|
||||
{
|
||||
static bool hasCheckedSysPy = false;
|
||||
static bool sysPyInstalled = false;
|
||||
|
||||
public static string compactOutput;
|
||||
|
||||
public static async Task CheckCompression ()
|
||||
{
|
||||
if(HasEmbeddedPyFolder() && (Config.Get("compressedPyVersion") != Updater.GetInstalledVer().ToString()))
|
||||
{
|
||||
Program.mainForm.SetWorking(true, false);
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Restart();
|
||||
try
|
||||
{
|
||||
bool shownPatienceMsg = false;
|
||||
Logger.Log("Compressing python runtime. This only needs to be done once.");
|
||||
compactOutput = "";
|
||||
Process compact = OSUtils.NewProcess(true);
|
||||
compact.StartInfo.Arguments = $"/C compact /C /S:{GetPyFolder().Wrap()} /EXE:LZX";
|
||||
compact.OutputDataReceived += new DataReceivedEventHandler(CompactOutputHandler);
|
||||
compact.ErrorDataReceived += new DataReceivedEventHandler(CompactOutputHandler);
|
||||
compact.Start();
|
||||
compact.BeginOutputReadLine();
|
||||
compact.BeginErrorReadLine();
|
||||
while (!compact.HasExited)
|
||||
{
|
||||
await Task.Delay(500);
|
||||
if(sw.ElapsedMilliseconds > 10000)
|
||||
{
|
||||
Logger.Log($"This can take up to a few minutes... (Elapsed: {FormatUtils.Time(sw.Elapsed)})", false, shownPatienceMsg);
|
||||
shownPatienceMsg = true;
|
||||
await Task.Delay(500);
|
||||
}
|
||||
}
|
||||
Config.Set("compressedPyVersion", Updater.GetInstalledVer().ToString());
|
||||
Logger.Log("Done compressing python runtime.");
|
||||
Logger.WriteToFile(compactOutput, true, "compact");
|
||||
}
|
||||
catch { }
|
||||
Program.mainForm.SetWorking(false);
|
||||
}
|
||||
}
|
||||
|
||||
static void CompactOutputHandler (object sendingProcess, DataReceivedEventArgs outLine)
|
||||
{
|
||||
if (outLine == null || outLine.Data == null)
|
||||
return;
|
||||
string line = outLine.Data;
|
||||
compactOutput = compactOutput + line + "\n";
|
||||
}
|
||||
|
||||
public static string GetPyCmd ()
|
||||
{
|
||||
if (HasEmbeddedPyFolder())
|
||||
{
|
||||
Logger.Log("Using embedded Python runtime.");
|
||||
return Path.Combine(GetPyFolder(), "python.exe").Wrap();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsSysPyInstalled())
|
||||
{
|
||||
return "python";
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("System python installation not found!\nPlease install Python or download the package from the package installer.");
|
||||
Interpolate.Cancel("Neither the Flowframes Python Runtime nor System Python installation could be found!");
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static bool HasEmbeddedPyFolder ()
|
||||
{
|
||||
return (Directory.Exists(GetPyFolder()) && IOUtils.GetDirSize(GetPyFolder(), false) > 1024 * 1024 * 5);
|
||||
}
|
||||
|
||||
public static string GetPyFolder ()
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(Paths.GetPkgPath(), "py-amp")))
|
||||
return Path.Combine(Paths.GetPkgPath(), "py-amp");
|
||||
|
||||
if (Directory.Exists(Path.Combine(Paths.GetPkgPath(), "py-tu")))
|
||||
return Path.Combine(Paths.GetPkgPath(), "py-tu");
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static bool IsPytorchReady ()
|
||||
{
|
||||
string torchVer = GetPytorchVer();
|
||||
if (!string.IsNullOrWhiteSpace(torchVer) && torchVer.Length <= 35)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static string GetPytorchVer()
|
||||
{
|
||||
try
|
||||
{
|
||||
Process py = OSUtils.NewProcess(true);
|
||||
py.StartInfo.Arguments = "\"/C\" " + GetPyCmd() + " -c \"import torch; print(torch.__version__)\"";
|
||||
Logger.Log("[DepCheck] CMD: " + py.StartInfo.Arguments);
|
||||
py.Start();
|
||||
py.WaitForExit();
|
||||
string output = py.StandardOutput.ReadToEnd();
|
||||
string err = py.StandardError.ReadToEnd();
|
||||
if (!string.IsNullOrWhiteSpace(err)) output += "\n" + err;
|
||||
Logger.Log("[DepCheck] Pytorch Check Output: " + output.Trim());
|
||||
return output;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsSysPyInstalled ()
|
||||
{
|
||||
if (hasCheckedSysPy)
|
||||
return sysPyInstalled;
|
||||
|
||||
bool isInstalled = false;
|
||||
|
||||
Logger.Log("Checking if system Python is available...", true);
|
||||
string sysPyVer = GetSysPyVersion();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(sysPyVer) && !sysPyVer.ToLower().Contains("not found") && sysPyVer.Length <= 35)
|
||||
{
|
||||
isInstalled = true;
|
||||
Logger.Log("Using Python installation: " + sysPyVer, true);
|
||||
}
|
||||
|
||||
hasCheckedSysPy = true;
|
||||
sysPyInstalled = isInstalled;
|
||||
return sysPyInstalled;
|
||||
}
|
||||
|
||||
static string GetSysPyVersion()
|
||||
{
|
||||
string pythonOut = GetSysPythonOutput();
|
||||
Logger.Log("[DepCheck] System Python Check Output: " + pythonOut.Trim(), true);
|
||||
try
|
||||
{
|
||||
string ver = pythonOut.Split('(')[0].Trim();
|
||||
Logger.Log("[DepCheck] Sys Python Ver: " + ver, true);
|
||||
return ver;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static string GetSysPythonOutput()
|
||||
{
|
||||
Process py = OSUtils.NewProcess(true);
|
||||
py.StartInfo.Arguments = "/C python -V";
|
||||
Logger.Log("[DepCheck] CMD: " + py.StartInfo.Arguments, true);
|
||||
py.Start();
|
||||
py.WaitForExit();
|
||||
string output = py.StandardOutput.ReadToEnd();
|
||||
string err = py.StandardError.ReadToEnd();
|
||||
return output + "\n" + err;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.Forms;
|
||||
using Flowframes.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.OS
|
||||
{
|
||||
class Updater
|
||||
{
|
||||
public enum VersionCompareResult { Older, Newer, Equal };
|
||||
public static string latestVerUrl = "https://dl.nmkd.de/flowframes/exe/ver.ini";
|
||||
|
||||
public static Version GetInstalledVer()
|
||||
{
|
||||
try
|
||||
{
|
||||
string verStr = IOUtils.ReadLines(Paths.GetVerPath())[0];
|
||||
return new Version(verStr);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Error getting installed version: " + e.Message);
|
||||
return new Version(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static VersionCompareResult CompareVersions (Version currentVersion, Version newVersion)
|
||||
{
|
||||
Logger.Log($"Checking if {newVersion} > {currentVersion}", true);
|
||||
int result = newVersion.CompareTo(currentVersion);
|
||||
|
||||
if (result > 0)
|
||||
{
|
||||
Logger.Log($"{newVersion} is newer than {currentVersion}.", true);
|
||||
return VersionCompareResult.Newer;
|
||||
}
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
Logger.Log($"{newVersion} is older than {currentVersion}.", true);
|
||||
return VersionCompareResult.Older;
|
||||
}
|
||||
|
||||
Logger.Log($"{newVersion} is equal to {currentVersion}.", true);
|
||||
return VersionCompareResult.Equal;
|
||||
}
|
||||
|
||||
public static Version GetLatestVer (bool patreon)
|
||||
{
|
||||
var client = new WebClient();
|
||||
int line = patreon ? 0 : 2;
|
||||
return new Version(client.DownloadString(latestVerUrl).SplitIntoLines()[line]);
|
||||
}
|
||||
|
||||
public static string GetLatestVerLink(bool patreon)
|
||||
{
|
||||
int line = patreon ? 1 : 3;
|
||||
var client = new WebClient();
|
||||
try
|
||||
{
|
||||
return client.DownloadString(latestVerUrl).SplitIntoLines()[line].Trim();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.Log("Failed to get latest version link from ver.ini!", true);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task UpdateTo (int version, UpdaterForm form = null)
|
||||
{
|
||||
Logger.Log("Updating to " + version, true);
|
||||
string savePath = Path.Combine(IOUtils.GetExeDir(), $"FlowframesV{version}");
|
||||
try
|
||||
{
|
||||
var client = new WebClient();
|
||||
client.DownloadProgressChanged += async (sender, args) =>
|
||||
{
|
||||
if (form != null && (args.ProgressPercentage % 5 == 0))
|
||||
{
|
||||
Logger.Log("Downloading update... " + args.ProgressPercentage, true);
|
||||
form.SetProgLabel(args.ProgressPercentage, $"Downloading latest version... {args.ProgressPercentage}%");
|
||||
await Task.Delay(20);
|
||||
}
|
||||
};
|
||||
client.DownloadFileCompleted += (sender, args) =>
|
||||
{
|
||||
form.SetProgLabel(100f, $"Downloading latest version... 100%");
|
||||
};
|
||||
await client.DownloadFileTaskAsync(new Uri($"https://dl.nmkd.de/flowframes/exe/{version}/Flowframes.exe"), savePath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show("Error: Failed to download update.\n\n" + e.Message, "Error");
|
||||
Logger.Log("Updater Error during download: " + e.Message, true);
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
Logger.Log("Installing v" + version, true);
|
||||
string runningExePath = IOUtils.GetExe();
|
||||
string oldExePath = runningExePath + ".old";
|
||||
IOUtils.TryDeleteIfExists(oldExePath);
|
||||
File.Move(runningExePath, oldExePath);
|
||||
File.Move(savePath, runningExePath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show("Error: Failed to install update.\n\n" + e.Message, "Error");
|
||||
Logger.Log("Updater Error during install: " + e.Message, true);
|
||||
return;
|
||||
}
|
||||
form.SetProgLabel(101f, $"Update downloaded.");
|
||||
await Task.Delay(20);
|
||||
MessageBox.Show("Update was installed!\nFlowframes will now close. Restart it to use the new version.", "Message");
|
||||
Application.Exit();
|
||||
}
|
||||
|
||||
public static async Task AsyncUpdateCheck ()
|
||||
{
|
||||
Version installed = GetInstalledVer();
|
||||
Version latestPat = GetLatestVer(true);
|
||||
Version latestFree = GetLatestVer(false);
|
||||
|
||||
Logger.Log($"You are running Flowframes {installed}. The latest Patreon version is {latestPat}, the latest free version is {latestFree}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using Flowframes.Data;
|
||||
using Flowframes.IO;
|
||||
using Flowframes.OS;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
public static Form1 mainForm;
|
||||
|
||||
public static bool busy = false;
|
||||
|
||||
public static string lastInputPath;
|
||||
public static bool lastInputPathIsSsd;
|
||||
|
||||
public static Queue<InterpSettings> batchQueue = new Queue<InterpSettings>();
|
||||
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Config.Init();
|
||||
|
||||
if (Config.GetBool("delLogsOnStartup"))
|
||||
IOUtils.DeleteContentsOfDir(Paths.GetLogPath()); // Clear out older logs not from this session
|
||||
|
||||
string oldExePath = IOUtils.GetExe() + ".old";
|
||||
IOUtils.TryDeleteIfExists(oldExePath);
|
||||
|
||||
Networks.Init();
|
||||
NvApi.Init();
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
mainForm = new Form1();
|
||||
Application.Run(mainForm);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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("Flowframes")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Flowframes")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: System.Resources.NeutralResourcesLanguage("en-US")]
|
||||
|
||||
|
||||
// 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("389e42dd-a163-49d7-9e0a-ae41090a07b3")]
|
||||
|
||||
// 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("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
243
Code5/Properties/Resources.Designer.cs
generated
@@ -1,243 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 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.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Flowframes.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// 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", "16.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() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[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("Flowframes.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap baseline_create_white_18dp {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("baseline_create_white_18dp", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap baseline_create_white_18dp_semiTransparent {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("baseline_create_white_18dp-semiTransparent", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap baseline_fact_check_white_48dp {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("baseline_fact_check_white_48dp", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap baseline_image_white_48dp {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("baseline_image_white_48dp", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap baseline_image_white_48dp_4x {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("baseline_image_white_48dp-4x", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap baseline_image_white_48dp_4x_25pcAlpha {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("baseline_image_white_48dp-4x-25pcAlpha", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap baseline_queue_white_48dp {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("baseline_queue_white_48dp", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap baseline_settings_white_48dp {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("baseline_settings_white_48dp", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap baseline_system_update_alt_white_48dp {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("baseline_system_update_alt_white_48dp", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap discordIco {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("discordIco", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap discordIcoColored {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("discordIcoColored", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap flowframesIcoNew_512px {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("flowframesIcoNew_512px", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap patreon256px {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("patreon256px", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap patreon256pxColored {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("patreon256pxColored", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap paypal256px {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("paypal256px", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap questmark_72px_bordeer {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("questmark-72px-bordeer", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap separatorTest1 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("separatorTest1", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] x64_7za {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("x64_7za", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="baseline_image_white_48dp-4x" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\baseline_image_white_48dp-4x.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="baseline_queue_white_48dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\baseline_queue_white_48dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="x64_7za" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\7za.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="baseline_fact_check_white_48dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\baseline_fact_check_white_48dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="paypal256px" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\paypal256px.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="baseline_system_update_alt_white_48dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\baseline_system_update_alt_white_48dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="patreon256px" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\patreon256px.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="questmark-72px-bordeer" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\questmark-72px-bordeer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="baseline_create_white_18dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\baseline_create_white_18dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="discordIco" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\discordIco.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="patreon256pxColored" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\patreon256pxColored.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="discordIcoColored" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\discordIcoColored.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="separatorTest1" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\separatorTest1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="baseline_image_white_48dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\baseline_image_white_48dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="baseline_create_white_18dp-semiTransparent" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\baseline_create_white_18dp-semiTransparent.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="baseline_settings_white_48dp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\baseline_settings_white_48dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="baseline_image_white_48dp-4x-25pcAlpha" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\baseline_image_white_48dp-4x-25pcAlpha.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="flowframesIcoNew_512px" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\flowframesIcoNew-512px.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
26
Code5/Properties/Settings.Designer.cs
generated
@@ -1,26 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 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.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Flowframes.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
|
Before Width: | Height: | Size: 431 B |
|
Before Width: | Height: | Size: 206 B |
|
Before Width: | Height: | Size: 485 B |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 597 B |
|
Before Width: | Height: | Size: 371 B |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 334 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1,78 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Flowframes.UI
|
||||
{
|
||||
class GetWebInfo
|
||||
{
|
||||
public static async Task LoadNews (Label newsLabel)
|
||||
{
|
||||
string url = $"http://dl.nmkd.de/flowframes/changelog.txt";
|
||||
var client = new WebClient();
|
||||
var str = await client.DownloadStringTaskAsync(new Uri(url));
|
||||
newsLabel.Text = str;
|
||||
}
|
||||
|
||||
public static async Task LoadPatronList(Label patronsLabel)
|
||||
{
|
||||
string url = $"http://dl.nmkd.de/flowframes/patreon.txt";
|
||||
var client = new WebClient();
|
||||
var str = await client.DownloadStringTaskAsync(new Uri(url));
|
||||
patronsLabel.Text = str;
|
||||
}
|
||||
|
||||
public static async Task LoadPatronListCsv(Label patronsLabel)
|
||||
{
|
||||
string url = $"http://dl.nmkd.de/flowframes/patrons.csv";
|
||||
var client = new WebClient();
|
||||
var csvData = await client.DownloadStringTaskAsync(new Uri(url));
|
||||
patronsLabel.Text = ParsePatreonCsv(csvData);
|
||||
}
|
||||
|
||||
public static string ParsePatreonCsv(string csvData)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<string> goldPatrons = new List<string>();
|
||||
List<string> silverPatrons = new List<string>();
|
||||
string str = "Gold:\n";
|
||||
string[] lines = csvData.SplitIntoLines();
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
string line = lines[i].Replace(";", ",");
|
||||
string[] values = line.Split(',');
|
||||
if (i == 0 || line.Length < 10 || values.Length < 5) continue;
|
||||
string name = values[0];
|
||||
float amount = float.Parse(values[7], System.Globalization.CultureInfo.InvariantCulture);
|
||||
if (amount >= 4.5f)
|
||||
{
|
||||
if (amount >= 11f)
|
||||
goldPatrons.Add(name);
|
||||
else
|
||||
silverPatrons.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string pat in goldPatrons)
|
||||
str += pat + "\n";
|
||||
|
||||
str += "\nSilver:\n";
|
||||
|
||||
foreach (string pat in silverPatrons)
|
||||
str += pat + "\n";
|
||||
|
||||
return str;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Failed to parse Patreon CSV: " + e.Message, true);
|
||||
return "Failed to load patron list.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||