using System.Diagnostics; using System.Runtime.InteropServices; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.FFmpeg; using ErsatzTV.Core.Interfaces.Repositories; namespace ErsatzTV.Core.FFmpeg; public class FFmpegLocator : IFFmpegLocator { private readonly IConfigElementRepository _configElementRepository; public FFmpegLocator(IConfigElementRepository configElementRepository) => _configElementRepository = configElementRepository; public async Task> ValidatePath(string executableBase, ConfigElementKey key) { Option setting = await _configElementRepository.GetConfigElement(key); return await setting.MatchAsync( async ce => { if (File.Exists(ce.Value)) { return ce.Value; } // configured path was incorrect await _configElementRepository.Delete(ce); return await LocateExecutableAsync(executableBase, key); }, async () => await LocateExecutableAsync(executableBase, key)); } private async Task> LocateExecutableAsync(string executableBase, ConfigElementKey key) { Option maybePath = await LocateExecutableOnPathAsync(executableBase); return await maybePath.MatchAsync( async path => { await _configElementRepository.Upsert(key, path); return Some(path); }, () => None); } private static async Task> LocateExecutableOnPathAsync(string executableBase) { string executable = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? $"{executableBase}.exe" : executableBase; string processFileName = Environment.ProcessPath ?? string.Empty; if (!string.IsNullOrWhiteSpace(processFileName)) { string localFileName = Path.Combine(Path.GetDirectoryName(processFileName) ?? string.Empty, executable); if (File.Exists(localFileName)) { return localFileName; } } string locateCommand = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "where" : "which"; using var p = new Process(); p.StartInfo = new ProcessStartInfo { UseShellExecute = false, FileName = locateCommand, Arguments = executable, RedirectStandardOutput = true }; p.Start(); string path = (await p.StandardOutput.ReadToEndAsync()).Trim(); await p.WaitForExitAsync(); return p.ExitCode == 0 ? Some(path) : None; } }