Jimmy 1 жил өмнө
parent
commit
7546544e72

+ 9 - 0
fis/App.axaml.cs

@@ -29,6 +29,7 @@ using System.Diagnostics;
 using fis.Win.Utilities;
 using System.Collections.Generic;
 using fis.Win.Dev.Managers;
+using AudioRecorder;
 
 namespace fis
 {
@@ -55,6 +56,14 @@ namespace fis
             _appViewModel = new AppViewModel();
             DataContext = new AppViewModel();
             Logger.WriteShellLog("App initialize end");
+            //Task.Run(() => {
+            //    Thread.Sleep(10000);
+            //    var asd=AudioRecorderHelpler.GetAudioDevices(AudioDeviceTypeEnum.Mic);
+            //    var xxx = asd.Last();
+            //    Thread.Sleep(3000);
+            //    AudioRecorderHelpler.SetSystemAudioDevice(xxx);
+            //    ;
+            //});
         }
 
         public override async void OnFrameworkInitializationCompleted()

+ 136 - 0
fis/Utilities/AudioRecorderHelpler.cs

@@ -1,6 +1,12 @@
 using AudioRecorder;
 using fis.Log;
+using NAudio.CoreAudioApi;
+using NAudio.Wave;
 using System;
+using System.Collections.Generic;
+using System.Linq;
+using NAudio.CoreAudioApi;
+using System.Runtime.InteropServices;
 
 namespace fis.Utilities
 {
@@ -64,10 +70,140 @@ namespace fis.Utilities
   
         }
 
+
+        public static void AdjustAudioDevice(AudioDeviceTypeEnum audioTypeEnum, double volume, Action<string> logger)
+        {
+            var audioEnumerator = new MMDeviceEnumerator();
+            var microphone = audioEnumerator.GetDefaultAudioEndpoint(DataFlow.Capture, Role.Communications);
+            var speaker = audioEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
+            
+            if (volume < 0 || volume > 1)
+            {
+                logger($"Invalid volum {volume}");
+                return;
+            }
+            // 设置音量大小 (0.0f 到 1.0f)
+            float micVolume = (float)volume; // 50% 音量
+            float speakerVolume = (float)volume; // 75% 音量
+
+            if (audioTypeEnum == AudioDeviceTypeEnum.Mic)
+            {
+                // 设置麦克风音量
+                if (microphone.AudioEndpointVolume != null)
+                {
+                    microphone.AudioEndpointVolume.MasterVolumeLevelScalar = micVolume;
+                }
+            }
+
+            if (audioTypeEnum == AudioDeviceTypeEnum.Speaker)
+            {
+                // 设置扬声器音量
+                if (speaker.AudioEndpointVolume != null)
+                {
+                    speaker.AudioEndpointVolume.MasterVolumeLevelScalar = speakerVolume;
+                }
+            }
+
+
+        }
+
+        public static List<string> GetAudioDevices(AudioDeviceTypeEnum audioTypeEnum)
+        {
+            var audioEnumerator = new MMDeviceEnumerator();
+            var devices = audioEnumerator.EnumerateAudioEndPoints(audioTypeEnum==AudioDeviceTypeEnum.Speaker?
+                DataFlow.Render:DataFlow.Capture, DeviceState.Active);
+            if (devices == null)
+            {
+                return new List<string>();
+            }
+            return devices.Select(x => x.DeviceFriendlyName).ToList();
+        }
+
+      
+        public static bool SetSystemAudioDevice(string deviceName)
+        {
+            var audioEnumerator = new MMDeviceEnumerator();
+            var devices = audioEnumerator.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active);
+            var selectedDevice = devices.FirstOrDefault(device => device.DeviceFriendlyName == deviceName);
+           
+            if (selectedDevice != null)
+            {
+                AudioDeviceManager.SetDefaultAudioDevice(deviceName);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+       
         private static void WriteLog(string logs)
         {
             Logger.WriteShellLog(logs);
         }
 
     }
+
+    public class AudioDeviceManager
+    {
+        [DllImport("winmm.dll", CharSet = CharSet.Auto)]
+        public static extern int waveOutGetNumDevs();
+
+        [DllImport("winmm.dll", CharSet = CharSet.Auto)]
+        public static extern int waveOutGetDevCaps(IntPtr uDeviceID, out WAVEOUTCAPS pwoc, int cbwoc);
+
+        [DllImport("winmm.dll", CharSet = CharSet.Auto)]
+        public static extern int waveOutSetDev(IntPtr uDeviceID);
+
+        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+        public struct WAVEOUTCAPS
+        {
+            public ushort wMid;
+            public ushort wPid;
+            public uint vDriverVersion;
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+            public string szPname;
+            public uint dwFormats;
+            public ushort wChannels;
+            public ushort wReserved1;
+            public uint dwSupport;
+        }
+
+        public static int GetAudioDeviceID(string deviceName)
+        {
+            int deviceCount = waveOutGetNumDevs();
+
+            for (int i = 0; i < deviceCount; i++)
+            {
+                WAVEOUTCAPS waveOutCaps = new WAVEOUTCAPS();
+                int result = waveOutGetDevCaps(new IntPtr(i), out waveOutCaps, Marshal.SizeOf(waveOutCaps));
+                if (result == 0 && waveOutCaps.szPname == deviceName)
+                {
+                    return i;
+                }
+            }
+
+            return -1; // 设备未找到
+        }
+
+        public static void SetDefaultAudioDevice(string deviceName)
+        {
+            int deviceID = 3;
+
+            if (deviceID != -1)
+            {
+                IntPtr uDeviceID = new IntPtr(2);
+
+                int result = waveOutSetDev(uDeviceID);
+                if (result != 0)
+                {
+                    Console.WriteLine("无法更改系统默认的音频设备");
+                }
+            }
+            else
+            {
+                Console.WriteLine("找不到指定名称的音频设备");
+            }
+        }
+    }
 }

+ 509 - 0
fis_tools_code/FisTools.cs

@@ -0,0 +1,509 @@
+using System;
+using System.Diagnostics;
+using System.IO.Compression;
+
+namespace FisTools
+{
+    public class FFmpegException : Exception
+    {
+        public FFmpegException(int exitCode, Exception innerException = null)
+            : base($"Exit Code: {exitCode}.\nSee FFmpeg Log for more info.", innerException) { }
+    }
+
+    public class FFmpegService
+    {
+        private string _ffmpegPath = "ffmpeg";     
+        public void SetFFmpegPath(string ffmpegPath)
+        {
+            _ffmpegPath = ffmpegPath;
+        }
+
+        public void StartFFmpeg(out Process process, string arguments)
+        {
+            process = new Process
+            {
+                StartInfo =
+                {
+                    FileName = _ffmpegPath,
+                    Arguments = arguments,
+                    UseShellExecute = false,
+                    Verb = "runas",
+                    CreateNoWindow = true,
+                    RedirectStandardError = true,
+                    RedirectStandardInput = true
+                },
+                EnableRaisingEvents = true
+            };
+            process.Start();
+            process.BeginErrorReadLine();
+        }
+        public void ForceCloseFFmpegIfStillAlive()
+        {
+            var fmpegProcess = Process.GetProcessesByName("ffmpeg");
+            foreach (var f in fmpegProcess)
+            {
+                f.Kill();
+            }
+        }
+    }
+
+    public class LoaderCenter
+    {
+        private  string _processName=string.Empty;     
+        public void StartProcessWithFileName(string filePath, string arguments,string processName)
+        {
+            _processName = processName;
+            var process = new Process
+            {
+                StartInfo =
+                {
+                    FileName = filePath,
+                    Arguments = arguments,
+                    UseShellExecute = false,
+                    Verb = "runas",
+                    CreateNoWindow = true,
+                    RedirectStandardError = true,
+                    RedirectStandardInput = true
+                },
+            };
+            process.Start();
+        }
+
+        public void StartProcessWithWorkingDirectory(string filePath,string workingDirectory)
+        {
+            var process = new Process
+            {
+                StartInfo =
+                {
+                    FileName = filePath,
+                    WorkingDirectory = workingDirectory,
+                    UseShellExecute = false,
+                    CreateNoWindow = true,
+                    RedirectStandardOutput = true,
+                    Verb = "runas",
+                },
+            };              
+            process.Start();
+        }
+
+        /// <summary>
+        /// 校验APP是否已存在,已存在则直接唤起
+        /// </summary>
+        /// <returns></returns>
+        public bool CheckAppIsInvalid(Action<string> logger)
+        {
+            var id = Process.GetCurrentProcess().Id;
+            Process[] processesByNames = Process.GetProcessesByName("fis");
+            bool appInvalid=false;
+            foreach (var pn in processesByNames)
+            {
+                //如果存在同名但不同id的进程
+                if (pn.Id != id)
+                {
+                    logger.Invoke("Got another fis process");
+                    var threads = pn.Threads;
+                    foreach (ProcessThread t in threads)
+                    {
+                        logger.Invoke("Exist process status is:");
+                        logger.Invoke(t.ThreadState.ToString());
+                        var appHangup = t.ThreadState == System.Diagnostics.ThreadState.Unknown
+                            || t.ThreadState == System.Diagnostics.ThreadState.Terminated
+                        || t.ThreadState == System.Diagnostics.ThreadState.Wait;
+                        
+                        if (appHangup)
+                        {
+                            logger.Invoke("Kill the existing hang up process");
+                            //如果存在挂起线程,则杀死
+                            KillProcessWithGivenName("fis", false);                          
+                        }
+                        if (t.ThreadState == System.Diagnostics.ThreadState.Running)
+                        {
+                            appInvalid = true;
+                        }
+                    }
+                }
+            }
+            return appInvalid;
+        }
+
+        /// <summary>
+        /// 打开守护进程
+        /// </summary>
+        public void OpenFlyinsonoDaemon()
+        {
+            var process = Process.GetProcessesByName("FlyinsonoDaemon.exe").FirstOrDefault();
+            if (process == null)
+            {
+                var flyinsonoDaemonPath = "C:\\vinno\\daemon\\FlyinsonoDaemon.exe";
+                ToolManager.Instance.LoaderCenter.StartProcessDirectly(flyinsonoDaemonPath);
+            }
+        }
+        public void StartProcessDirectly(string filePath)
+        {
+            var process = new Process
+            {
+                StartInfo =
+                {
+                    FileName = filePath,
+                    UseShellExecute = false,
+                    Verb = "runas",
+                    CreateNoWindow = true,
+                    RedirectStandardError = true,
+                },
+                EnableRaisingEvents = true
+            };
+            process.Start();
+        }
+
+        public void StartProcessWithUI(string filePath)
+        {
+            var process = new Process
+            {
+                StartInfo =
+                {
+                    FileName = filePath,
+                },
+
+            };
+            process.Start();
+        }
+        public void ForceCloseIfStillAlive()
+        {
+            if (!string.IsNullOrEmpty(_processName))
+            {
+                var fmpegProcess = Process.GetProcessesByName(_processName);
+                foreach (var f in fmpegProcess)
+                {
+                    f.Kill();
+                }
+            }
+        }
+        public void KillProcessWithGivenName(string processName,bool killSelf=true)
+        {
+            var processes = Process.GetProcessesByName(processName);
+            foreach (Process process in processes)
+            {
+                if (process.ProcessName == processName)
+                {
+                    if (killSelf)
+                    {
+                        process.Kill();
+                        process.WaitForExit();
+                    }
+                    else if(process.Id != Process.GetCurrentProcess().Id)
+                    {
+                        process.Kill();
+                        process.WaitForExit();
+                    }
+                }
+            }
+        }
+    }
+
+//    public class AutoStartHelper
+//    {
+//        /// <summary>
+//        /// App开机自启动 Reg key
+//        /// </summary>
+//        private const string AppAutoStartRegistryKey = "FisAutoStart";
+
+//        /// <summary>
+//        /// 当前用户注册表开启启动路径
+//        /// </summary>
+//        private const string RegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
+//        /// <summary>
+//        /// 设置APP开机自启动
+//        /// </summary>
+//        /// <returns></returns>
+//        public bool SetAppAutoStart()
+//        {
+//            ///默认选择Release下的loader.exe
+//            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "loader.exe");
+//#if DEBUG
+//            ///Debug模式下启动fis.exe
+//            path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fis.exe");
+//#endif
+//            return SetAutoStartByPath(path, AppAutoStartRegistryKey);
+//        }
+
+//        /// <summary>
+//        /// 取消APP开机自启动
+//        /// </summary>
+//        /// <returns></returns>
+//        public bool AbortAppAutoStart()
+//        {
+//            return AbortAutoByRegKey(AppAutoStartRegistryKey);
+//        }
+
+//        /// <summary>
+//        /// 根据指定的key取消开机自启动
+//        /// </summary>
+//        /// <param name="regkey"></param>
+//        /// <returns></returns>
+//        public bool AbortAutoByRegKey(string regkey)
+//        {
+//            try
+//            {
+//                var currentUserRegKey = Registry.CurrentUser;
+//                var startUpKey = currentUserRegKey.CreateSubKey(RegPath);
+//                startUpKey.DeleteValue(regkey, false);
+//                startUpKey.Close();
+//                currentUserRegKey.Close();
+//                return true;
+
+//            }
+//            catch (Exception ex)
+//            {
+//                return false;
+//            }
+//        }
+//        /// <summary>
+//        /// 根据给定开机自启动文件路径和注册表的key设置开启自启动
+//        /// </summary>
+//        /// <param name="regkey"></param>
+//        /// <returns></returns>
+//        public bool SetAutoStartByPath(string path, string regKey)
+//        {
+//            try
+//            {
+//                var currentUserKey = Registry.CurrentUser;
+//                var startUpKey = currentUserKey.CreateSubKey(RegPath);
+//                startUpKey.SetValue(regKey, path);
+//                startUpKey.Close();
+//                currentUserKey.Close();
+//                return true;
+
+//            }
+//            catch (Exception)
+//            {
+//                return false;
+//            }
+//        }
+
+//    }
+
+    public class UpgradeCenter
+    {
+        private int _totalEntrysCount;
+        private int _finishedCount;
+        private const int ExpirationCount = 90;
+        private Action<double>? _onProgressChanged;
+
+        public void ExecutePartUpgrade(Action<string> logger)
+        {
+            logger.Invoke($"Part upgrade");
+             ToolManager.Instance.LoaderCenter.KillProcessWithGivenName("fis");
+            var currentDir = AppDomain.CurrentDomain.BaseDirectory;
+            var fisDir = Directory.GetParent(currentDir)!.Parent!.FullName;
+            logger($"Fis dir is {fisDir}");
+            var webZipPath = Path.Combine(fisDir, "App", "flyinsono");
+            var updateCacheDir = Path.Combine(fisDir, "UpgradCache");
+            var filesToCopy = Directory.GetFiles(updateCacheDir);
+            foreach (var file in filesToCopy)
+            {
+                var ext = Path.GetExtension(file);
+                if (ext != ".zip")
+                {
+                   logger($"Skipped none zip file for part upgrade");
+                    continue;
+                }
+                var fileName = Path.GetFileName(file);
+                var fileDest = Path.Combine(webZipPath, fileName);
+                File.Copy(file, fileDest, true);
+                File.Delete(file);
+            }
+            var fisFileName = Path.Combine(fisDir, "fis.exe");
+            ToolManager.Instance.LoaderCenter.StartProcessDirectly(fisFileName);
+        }
+
+        public void ExecuteFullUpgrade(Action<string> logger,Action<double>? onProgressChanged = null)
+        {
+            logger.Invoke($"Full upgrade");
+            _onProgressChanged=onProgressChanged;
+            ToolManager.Instance.LoaderCenter.KillProcessWithGivenName("fis");
+            var currentDir = AppDomain.CurrentDomain.BaseDirectory;
+
+
+            var fisDir = Directory.GetParent(currentDir)!.Parent!.FullName;
+            logger($"Fis dir is {fisDir}");
+            var filesToCopy = Directory.GetFiles(currentDir);
+
+            foreach (var file in filesToCopy)
+            {
+                var ext = Path.GetExtension(file);
+                logger($"File name {file}");
+                if (ext != ".zip")
+                {
+                    logger($"None zip file skipped {file}");
+                    continue;
+                }
+
+                var fileName = Path.GetFileName(file);
+                if (!fileName.Contains("fis_package"))
+                {
+                    logger($"Zip file skipped {file}");
+                    continue;
+                }
+                logger($"Do extract {file} begin");
+                var fileNameWithoutExt = Path.GetFileNameWithoutExtension(file);
+                var filePathToSkip = $"{fileNameWithoutExt}/";
+                logger("Begin to extract");
+                Task.Run(() =>
+                {
+                    var waitCount = 0;
+                    while (true)
+                    {
+                        waitCount++;
+                        Thread.Sleep(1000);
+                        if (waitCount == ExpirationCount)
+                        {
+                            _onProgressChanged?.Invoke(2.0);
+                            break;
+                        }
+                        var progress = Math.Round((double)_finishedCount / (double)_totalEntrysCount, 2);
+                        _onProgressChanged?.Invoke(progress);
+                        if (progress == 1)
+                        {
+                            break;
+                        }
+                    }
+                });
+                using (ZipArchive archive = ZipFile.OpenRead(file))
+                {
+                    try
+                    {
+                        var entrys = archive.Entries;
+                        _totalEntrysCount = entrys.Count; 
+                        var fileDirs = entrys.Where(c => c.Name == "");
+                        var filesEntries = entrys.Where(c => c.Name != "");
+                        foreach (var dir in fileDirs)
+                        {
+                            _finishedCount++;
+                            var entrySubPath = dir.FullName.Replace(filePathToSkip, "");
+                            if (string.IsNullOrEmpty(entrySubPath))
+                            {
+                                continue;
+                            }
+                            string entryPath = Path.Combine(fisDir, entrySubPath);
+                            if (!Directory.Exists(entryPath))
+                            {
+                                Directory.CreateDirectory(entryPath);
+                            }
+                        }
+
+                        foreach (ZipArchiveEntry fileEntry in filesEntries)
+                        {
+                            var entrySubPath = fileEntry.FullName.Replace(filePathToSkip, "");
+                            string entryPath = Path.Combine(fisDir, entrySubPath);
+                            if (fileEntry.Name.Contains("libHarfBuzzSharp") || fileEntry.Name.Contains("libSkiaSharp"))
+                            {
+                                _finishedCount++;
+                                continue;
+                            }
+                            try
+                            {
+                                fileEntry.ExtractToFile(entryPath, true);
+                            }
+                            catch (Exception ex)
+                            {
+                                logger($"Extract single file error {ex}");
+                            }
+                            logger($"{fileEntry.FullName} extract success.");
+                            _finishedCount++;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        logger($"Extract error {ex}");
+                    }
+
+                }
+
+                logger("End to extract");
+
+                logger($"Do extract {file} end");
+                logger($"Do delete {file} begin");
+                File.Delete(file);
+                logger($"Do delete {file} end");
+            }
+            logger($"Do restart begin");
+            var fisFileName = Path.Combine(fisDir, "fis.exe");
+            if (_onProgressChanged == null)
+            {
+                ToolManager.Instance.LoaderCenter.StartProcessDirectly(fisFileName);
+            }
+            logger($"Do restart end");
+        }
+  
+    }
+
+    public class ToolManager
+    {
+        private ToolManager()
+        { 
+        }
+        private FFmpegService _ffmpegService;
+        private LoaderCenter _loaderCenter;
+        //private AutoStartHelper _autoStartHelper;
+        private UpgradeCenter _upgradeCenter;
+        static private ToolManager _instance;
+        public static ToolManager Instance
+        {
+            get{
+                if (_instance == null)
+                {
+                    _instance = new ToolManager();
+                }
+                return _instance;
+            }
+        }
+
+
+        public LoaderCenter LoaderCenter
+        {
+            get {
+                if (_loaderCenter == null)
+                {
+                    _loaderCenter = new LoaderCenter();
+                }
+                return _loaderCenter;
+            }
+        }
+
+        public FFmpegService FFmpegService
+        {
+            get
+            {
+                if (_ffmpegService == null)
+                {
+                    _ffmpegService = new FFmpegService();
+                }
+                return _ffmpegService;
+            }
+        }
+        public UpgradeCenter UpgradeCenter
+        {
+            get
+            {
+                if (_upgradeCenter == null)
+                {
+                    _upgradeCenter = new UpgradeCenter();
+                }
+                return _upgradeCenter;
+            }
+        }
+
+        //public AutoStartHelper AutoStartHelper
+        //{
+        //    get {
+        //        if (_autoStartHelper == null)
+        //        {
+        //            _autoStartHelper = new AutoStartHelper();
+        //        }
+        //        return _autoStartHelper;
+        //    }
+        //}
+    }
+
+    
+}

+ 9 - 0
fis_tools_code/FisTools.csproj

@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
+</Project>

+ 6 - 0
fis_tools_code/FisTools.csproj.user

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <_LastSelectedProfileId>C:\Users\vinno\source\repos\ProcessDiganosisWrapper\ProcessDiganosisWrapper\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
+  </PropertyGroup>
+</Project>

+ 17 - 0
fis_tools_code/Properties/PublishProfiles/FolderProfile.pubxml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <Configuration>Release</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>bin\Release\net6.0\publish\win-x64\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <TargetFramework>net6.0</TargetFramework>
+    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
+    <SelfContained>false</SelfContained>
+    <PublishSingleFile>true</PublishSingleFile>
+    <PublishReadyToRun>false</PublishReadyToRun>
+  </PropertyGroup>
+</Project>

+ 9 - 0
fis_tools_code/Properties/PublishProfiles/FolderProfile.pubxml.user

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <History>True|2023-04-21T06:36:42.5851799Z;</History>
+  </PropertyGroup>
+</Project>