Console logging improvements, implement Equals/GetHashCode for QueryInfo

This commit is contained in:
n00mkrad
2025-12-20 23:13:26 +01:00
parent 4c0202edb2
commit 8a0e181f8d
10 changed files with 109 additions and 89 deletions

View File

@@ -101,7 +101,7 @@ namespace Flowframes.Data
public async Task Initialize(bool progressBar = true, bool countFrames = true)
{
Logger.Log($"MediaFile {Name}: Initializing", true);
Logger.Log($"Analyzing media '{Name}'", true);
try
{
@@ -116,11 +116,10 @@ namespace Flowframes.Data
DataStreams = AllStreams.Where(x => x.Type == Stream.StreamType.Data).Select(x => (DataStream)x).ToList();
AttachmentStreams = AllStreams.Where(x => x.Type == Stream.StreamType.Attachment).Select(x => (AttachmentStream)x).ToList();
MayHaveAlpha = VideoStreams.Any(vs => vs.CanHaveAlpha);
Logger.Log($"Loaded and sorted streams for {Name}", true);
}
catch (Exception e)
{
Logger.Log($"Failed to initialized MediaFile: {e.Message}", true);
Logger.Log($"Failed to initialize MediaFile: {e.Message}", true);
}
Initialized = true;

View File

@@ -2,15 +2,33 @@
{
class QueryInfo
{
public string path;
public long filesize;
public string cmd = null;
public string Path;
public long SizeBytes;
public string Command = "";
public QueryInfo(string path, long filesize, string cmd = null)
public QueryInfo(string path, long filesize = 0, string cmd = "")
{
this.path = path;
this.filesize = filesize;
this.cmd = cmd;
Path = path;
SizeBytes = filesize;
Command = cmd;
}
public override bool Equals(object obj)
{
if (obj is QueryInfo other)
return Path == other.Path && SizeBytes == other.SizeBytes;
return false;
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 31 + (Path?.GetHashCode() ?? 0);
hash = hash * 31 + SizeBytes.GetHashCode();
return hash;
}
}
}
}

View File

@@ -18,13 +18,13 @@ namespace Flowframes.IO
public static bool SymlinksAllowed()
{
string origFile = Paths.GetExe();
string linkPath = Paths.GetExe() + "lnktest";
bool success = CreateSymbolicLink(linkPath, origFile, Flag.Unprivileged);
string testLinkPath = Paths.GetExe() + "lnktest";
bool success = CreateSymbolicLink(testLinkPath, origFile, Flag.Unprivileged);
if (!success)
return false;
File.Delete(linkPath);
File.Delete(testLinkPath);
return true;
}

View File

@@ -114,7 +114,7 @@ namespace Flowframes
if (allowDurationFromMetadata)
{
Logger.Log($"GetDuration({inputFile}) - Reading duration by checking metadata.", true, false, "ffmpeg");
Logger.Log($"[{nameof(GetDurationMs)}] Reading duration by checking metadata", true, false, "ffmpeg");
string argsMeta = $"ffprobe -v quiet -show_streams -select_streams v:0 -show_entries stream=duration {inputFile.Wrap()}";
var outputLinesMeta = NUtilsTemp.OsUtils.RunCommand($"cd /D {GetAvDir().Wrap()} && {argsMeta}").SplitIntoLines();
@@ -144,7 +144,7 @@ namespace Flowframes
if (demuxInsteadOfPacketTs)
{
Logger.Log($"GetDuration({inputFile}) - Reading duration by demuxing.", true, false, "ffmpeg");
Logger.Log($"[{nameof(GetDurationMs)}] Reading duration by demuxing", true, false, "ffmpeg");
string argsDemux = $"ffmpeg -loglevel panic -stats -i {inputFile.Wrap()} -map 0:v:0 -c copy -f null NUL";
var outputLinesDemux = NUtilsTemp.OsUtils.RunCommand($"cd /D {GetAvDir().Wrap()} && {argsDemux}").SplitIntoLines().Where(l => l.IsNotEmpty() && l.MatchesWildcard("*time=* *"));
@@ -156,7 +156,7 @@ namespace Flowframes
}
else
{
Logger.Log($"GetDuration({inputFile}) - Reading duration using packet timestamps.", true, false, "ffmpeg");
Logger.Log($"[{nameof(GetDurationMs)}] Reading duration using packet timestamps", true, false, "ffmpeg");
string argsPackets = $"ffprobe -v error -select_streams v:0 -show_packets -show_entries packet=pts_time -of csv=p=0 {inputFile.Wrap()}";
var outputLinesPackets = NUtilsTemp.OsUtils.RunCommand($"cd /D {GetAvDir().Wrap()} && {argsPackets}").SplitIntoLines().Where(l => l.IsNotEmpty()).ToList();
@@ -405,10 +405,12 @@ namespace Flowframes
public static async Task<bool> IsEncoderCompatible(string enc)
{
Logger.Log($"IsEncoderCompatible('{enc}')", true, false, "ffmpeg");
Logger.Log($"Running ffmpeg to check if encoder '{enc}' is available...", true, false, "ffmpeg");
string args = $"-loglevel error -f lavfi -i color=black:s=1920x1080 -vframes 1 -c:v {enc} -f null -";
string output = await RunFfmpeg(args, LogMode.Hidden);
return !output.SplitIntoLines().Where(l => !l.Lower().StartsWith("frame") && l.IsNotEmpty()).Any();
bool compat = !output.SplitIntoLines().Where(l => !l.Lower().StartsWith("frame") && l.IsNotEmpty()).Any();
Logger.Log($"Encoder '{enc}' is {(compat ? "available!" : "not available.")}", true, false, "ffmpeg");
return compat;
}
public static List<string> GetAudioCodecs(string path, int streamIndex = -1)

View File

@@ -19,19 +19,15 @@ namespace Flowframes.Media
public static async Task<int> GetFrameCountAsync(string path, int retryCount = 3)
{
Logger.Log($"Getting frame count ({path})", true);
Logger.Log($"Getting frame count ({path})...", true);
long filesize = IoUtils.GetPathSize(path);
QueryInfo hash = new QueryInfo(path, filesize);
if (filesize > 0 && CacheContains(hash))
if (filesize > 0 && cache.ContainsKey(hash))
{
Logger.Log($"Cache contains this hash, using cached value.", true);
return GetFromCache(hash);
}
else
{
Logger.Log($"Hash not cached, reading frame count.", true);
Logger.Log($"Using cached frame count value.", true);
return cache[hash];
}
int frameCount;
@@ -54,7 +50,7 @@ namespace Flowframes.Media
if (frameCount > 0)
{
Logger.Log($"Adding hash with value {frameCount} to cache.", true);
Logger.Log($"Caching frame count ({frameCount}).", true);
cache.Add(hash, frameCount);
}
else
@@ -74,24 +70,6 @@ namespace Flowframes.Media
return frameCount;
}
private static bool CacheContains(QueryInfo hash)
{
foreach (KeyValuePair<QueryInfo, int> entry in cache)
if (entry.Key.path == hash.path && entry.Key.filesize == hash.filesize)
return true;
return false;
}
private static int GetFromCache(QueryInfo hash)
{
foreach (KeyValuePair<QueryInfo, int> entry in cache)
if (entry.Key.path == hash.path && entry.Key.filesize == hash.filesize)
return entry.Value;
return 0;
}
public static void Clear()
{
cache.Clear();

View File

@@ -38,12 +38,12 @@ namespace Flowframes.Media
private static bool CacheContains(QueryInfo hash)
{
return cache.Any(entry => entry.Key.path == hash.path && entry.Key.filesize == hash.filesize);
return cache.Any(entry => entry.Key.Path == hash.Path && entry.Key.SizeBytes == hash.SizeBytes);
}
private static Size GetFromCache(QueryInfo hash)
{
return cache.Where(entry => entry.Key.path == hash.path && entry.Key.filesize == hash.filesize).Select(entry => entry.Value).FirstOrDefault();
return cache.Where(entry => entry.Key.Path == hash.Path && entry.Key.SizeBytes == hash.SizeBytes).Select(entry => entry.Value).FirstOrDefault();
}
public static void Clear()

View File

@@ -30,7 +30,7 @@ namespace Flowframes.Media
public static async Task<string> GetFfmpegOutputAsync(string path, string argsIn, string argsOut, string lineFilter = "", bool noCache = false)
{
Process process = OsUtils.NewProcess(true);
process.StartInfo.Arguments = $"/C cd /D {GetAvPath().Wrap()} & " +
process.StartInfo.Arguments = $"/C cd /D {AvProcess.GetAvDir().Wrap()} & " +
$"ffmpeg.exe -hide_banner -y {argsIn} {path.GetConcStr()} -i {path.Wrap()} {argsOut}";
return await GetInfoAsync(path, process, lineFilter, noCache);
}
@@ -41,7 +41,7 @@ namespace Flowframes.Media
string showFormat = mode == FfprobeMode.ShowBoth || mode == FfprobeMode.ShowFormat ? "-show_format" : "";
string showStreams = mode == FfprobeMode.ShowBoth || mode == FfprobeMode.ShowStreams ? "-show_streams" : "";
process.StartInfo.Arguments = $"/C cd /D {GetAvPath().Wrap()} & " +
process.StartInfo.Arguments = $"/C cd /D {AvProcess.GetAvDir().Wrap()} & " +
$"ffprobe -v quiet {path.GetConcStr()} {showFormat} {showStreams} {path.Wrap()}";
string output = await GetInfoAsync(path, process, lineFilter, streamIndex, stripKeyName);
@@ -112,7 +112,7 @@ namespace Flowframes.Media
private static bool CacheContains(QueryInfo hash, ref Dictionary<QueryInfo, string> cacheDict)
{
foreach (KeyValuePair<QueryInfo, string> entry in cacheDict)
if (entry.Key.path == hash.path && entry.Key.filesize == hash.filesize && entry.Key.cmd == hash.cmd)
if (entry.Key.Path == hash.Path && entry.Key.SizeBytes == hash.SizeBytes && entry.Key.Command == hash.Command)
return true;
return false;
@@ -121,7 +121,7 @@ namespace Flowframes.Media
private static string GetFromCache(QueryInfo hash, ref Dictionary<QueryInfo, string> cacheDict)
{
foreach (KeyValuePair<QueryInfo, string> entry in cacheDict)
if (entry.Key.path == hash.path && entry.Key.filesize == hash.filesize && entry.Key.cmd == hash.cmd)
if (entry.Key.Path == hash.Path && entry.Key.SizeBytes == hash.SizeBytes && entry.Key.Command == hash.Command)
return entry.Value;
return "";
@@ -131,10 +131,5 @@ namespace Flowframes.Media
{
cmdCache.Clear();
}
private static string GetAvPath()
{
return Path.Combine(Paths.GetPkgPath(), Paths.audioVideoDir);
}
}
}

View File

@@ -29,13 +29,13 @@ namespace Flowframes.Os
{
float vramGb = gpu.GetVramGb();
vramGb = (float)(Math.Round(vramGb * 2, MidpointRounding.AwayFromZero) / 2); // Round to nearest 0.5 GB
Logger.Log($"Nvidia GPU: {gpu.FullName} ({vramGb.ToString("0.#")} GB) {GetArch(gpu)} Architecture", true);
Logger.Log($"[NvAPI] Nvidia GPU: {gpu.FullName} ({vramGb.ToString("0.#")} GB) {GetArch(gpu)} Architecture", true);
GpuVram[gpu] = vramGb;
}
NvGpus = gpus.OrderByDescending(g => GpuVram[g]).ThenBy(g => g.FullName).ToList();
string mostVramGpu = gpus.Length > 1 ? $" Most VRAM: {GpuWithMostVram.FullName} ({GpuVram[GpuWithMostVram].ToString("0.#")} GB)" : "";
Logger.Log($"Initialized Nvidia API in {sw.ElapsedMs} ms. GPU{(gpus.Length > 1 ? "s" : "")}: {string.Join(", ", gpus.Select(g => g.FullName))}.{mostVramGpu}", true);
Logger.Log($"[NvAPI] Initialized Nvidia API in {sw.ElapsedMs} ms. GPU{(gpus.Length > 1 ? "s" : "")}: {string.Join(", ", gpus.Select(g => g.FullName))}.{mostVramGpu}", true);
}
catch (Exception e)
{

View File

@@ -1,19 +1,19 @@
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using DiskDetector;
using DiskDetector.Models;
using Flowframes.MiscUtils;
using Microsoft.VisualBasic.Devices;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Flowframes.IO;
using DiskDetector;
using DiskDetector.Models;
using Microsoft.VisualBasic.Devices;
using Flowframes.MiscUtils;
using System.Linq;
using Tulpep.NotificationWindow;
using System.Runtime.InteropServices;
namespace Flowframes.Os
{
@@ -50,8 +50,7 @@ namespace Flowframes.Os
}
finally
{
if (user != null)
user.Dispose();
user?.Dispose();
}
return isAdmin;
}
@@ -167,28 +166,29 @@ namespace Flowframes.Os
}
}
public static string GetWindowsVer()
public static string GetWindowsVer() => GetWindowsVerVerbose(out _);
public static string GetWindowsVerVerbose(out string osDesc)
{
string os = RuntimeInformation.OSDescription;
osDesc = RuntimeInformation.OSDescription.Replace("Microsoft ", "").Trim();
if (os.StartsWith("Microsoft Windows 6.1"))
return "Windows 7";
if (os.StartsWith("Microsoft Windows 6.2"))
return "Windows 8";
if (os.StartsWith("Microsoft Windows 6.3"))
return "Windows 8.1";
if (os.StartsWith("Microsoft Windows 10.0"))
if (osDesc.StartsWith("Windows 10.0"))
{
int buildNum = os.Split("Microsoft Windows 10.0").Last().GetInt();
int buildNum = osDesc.Split("Windows 10.0").Last().GetInt();
// Assuming build numbers for distinguishing Windows 10 and 11 - Windows 10: Builds 10240 to 19044 - Windows 11: Builds 22000 and above
return buildNum >= 22000 ? "Windows 11" : "Windows 10";
}
return "";
// return os.Replace("Microsoft ", ""); // Fallback to raw description without "Microsoft "
if (osDesc.StartsWith("Windows 6.1"))
return "Windows 7";
if (osDesc.StartsWith("Windows 6.2"))
return "Windows 8";
if (osDesc.StartsWith("Windows 6.3"))
return "Windows 8.1";
return "???";
}
public static IEnumerable<Process> GetChildProcesses(Process process)
@@ -347,5 +347,31 @@ namespace Flowframes.Os
return false;
}
}
public enum DevModeState { Disabled, Enabled, Unknown }
public static DevModeState GetDeveloperModeState()
{
const string subKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock";
const string valueName = "AllowDevelopmentWithoutDevLicense";
foreach (var view in new[] { RegistryView.Registry64, RegistryView.Registry32 })
{
try
{
using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view))
using (var key = baseKey.OpenSubKey(subKey, writable: false))
{
if(key != null && key.GetValue(valueName) is int val)
{
return val == 1 ? DevModeState.Enabled : DevModeState.Disabled;
}
}
}
catch { }
}
return DevModeState.Unknown;
}
}
}

View File

@@ -11,11 +11,13 @@ namespace Flowframes.Os
{
class StartupChecks
{
public static bool IsAdmin = OsUtils.IsUserAdministrator();
static bool IsWin10Or11()
{
string winVer = OsUtils.GetWindowsVer();
if (winVer.IsEmpty())
if (winVer.Trim('?').IsEmpty())
return true; // If it fails, return true for future-proofing
return winVer.Lower().Contains("windows 10") || winVer.Lower().Contains("windows 11");
@@ -43,8 +45,8 @@ namespace Flowframes.Os
Application.Exit();
}
string winVer = OsUtils.GetWindowsVer();
Logger.Log($"Running {winVer}", true);
string winVer = OsUtils.GetWindowsVerVerbose(out string winVerDesc);
Logger.Log($"[OS] Running {winVer} ({winVerDesc.Replace("Windows ", "")}) [{(IsAdmin ? "Admin" : "User")}]", true);
if (!Environment.Is64BitOperatingSystem && !Config.GetBool("allow32Bit", false))
{
@@ -70,7 +72,7 @@ namespace Flowframes.Os
bool silent = Config.GetBool("silentDevmodeCheck", true);
string ver = Updater.GetInstalledVer().ToString();
bool symlinksAllowed = Symlinks.SymlinksAllowed();
Logger.Log($"Symlinks allowed: {symlinksAllowed}", true);
Logger.Log($"Symlink creation is {(symlinksAllowed ? "allowed." : $"not allowed!")} (Admin: {IsAdmin} - Dev Mode: {OsUtils.GetDeveloperModeState()})", true);
if (!symlinksAllowed && Config.Get(Config.Key.askedForDevModeVersion) != ver)
{