|
| 1 | +using System; |
| 2 | +using System.Collections.Generic; |
| 3 | +using HarmonyLib; |
| 4 | +using ResoniteModLoader; |
| 5 | +using FrooxEngine; |
| 6 | +using UnityFrooxEngineRunner; |
| 7 | +using System.IO; |
| 8 | +using System.Linq; |
| 9 | +using System.Reflection; |
| 10 | +using UMP; |
| 11 | +using NYoutubeDL; |
| 12 | +namespace VideoPlayerFix; |
| 13 | + |
| 14 | +public enum PlayerMode |
| 15 | +{ |
| 16 | + DisableNone, |
| 17 | + DisableUnityNative, |
| 18 | + DisableLibVLC, |
| 19 | + DisableAll |
| 20 | +} |
| 21 | +public class VideoPlayerFix : ResoniteMod |
| 22 | +{ |
| 23 | + public override string Name => "ResoniteVideoPlayerFix"; |
| 24 | + public override string Author => "Fro Zen"; |
| 25 | + public override string Version => "1.0.0"; |
| 26 | + private static string YoutubeDLPath = ""; |
| 27 | + |
| 28 | + [AutoRegisterConfigKey] |
| 29 | + public readonly ModConfigurationKey<PlayerMode> VideoPlayerMode = new("VideoPlayerMode", "Video Player Mode (Requires Restart)", |
| 30 | + () => Engine.Current.IsWine || Engine.Current.Platform != Platform.Windows |
| 31 | + ? PlayerMode.DisableUnityNative |
| 32 | + : PlayerMode.DisableLibVLC); |
| 33 | + |
| 34 | + public override void OnEngineInit() |
| 35 | + { |
| 36 | + var harmony = new Harmony("ResoniteVideoPlayerFixHarmony"); |
| 37 | + var config = GetConfiguration(); |
| 38 | + var mode = config!.GetValue(VideoPlayerMode); |
| 39 | + if (mode is not PlayerMode.DisableNone) |
| 40 | + { |
| 41 | + var engines = PlaybackEngine.PlaybackEngines; |
| 42 | + if (mode is PlayerMode.DisableAll) |
| 43 | + { |
| 44 | + engines.Clear(); |
| 45 | + //patch internal setupprepare method to disable youtubedl |
| 46 | + var ydlClassRemove = AccessTools.AllTypes().First(i => i.ToString().EndsWith("Services.PreparationService")); |
| 47 | + var ydlMethodRemove = ydlClassRemove.GetMethod("SetupPrepare", BindingFlags.NonPublic | BindingFlags.Static); |
| 48 | + harmony.Patch(ydlMethodRemove, new HarmonyMethod(typeof(YoutubeDLPatch).GetMethod(nameof(YoutubeDLPatch.SetupPrepareRemovePatch)))); |
| 49 | + Msg("Removed all valid playback engines and disabled YoutubeDL"); |
| 50 | + Msg("Disabling YoutubeDL reduces network strain, but will cause more errors in logs"); |
| 51 | + return; |
| 52 | + } |
| 53 | + var disable = mode == PlayerMode.DisableUnityNative ? "Unity Native" : "libVLC"; |
| 54 | + var disablePlayer = engines.Find(i => i.Name == disable); |
| 55 | + if (disablePlayer != default) |
| 56 | + { |
| 57 | + engines.Remove(disablePlayer); |
| 58 | + Msg($"Removed {disable} from valid playback engines."); |
| 59 | + } |
| 60 | + } |
| 61 | + if (Engine.Current.Platform != Platform.Linux) return; |
| 62 | + |
| 63 | + harmony.Patch(typeof(UMPSettings).GetMethod("get_LibrariesPath"), |
| 64 | + new HarmonyMethod(typeof(WrapperPatch).GetMethod(nameof(WrapperPatch.WrapperLibraryPatch)))); |
| 65 | + |
| 66 | + //patch internal setupprepare method |
| 67 | + var ydlClass = AccessTools.AllTypes().First(i => i.ToString().EndsWith("Services.PreparationService")); |
| 68 | + var ydlMethod = ydlClass.GetMethod("SetupPrepare", BindingFlags.NonPublic | BindingFlags.Static); |
| 69 | + harmony.Patch(ydlMethod, new HarmonyMethod(typeof(YoutubeDLPatch).GetMethod(nameof(YoutubeDLPatch.SetupPreparePatch)))); |
| 70 | + |
| 71 | + //find valid YTDL locations |
| 72 | + var path = Environment.GetEnvironmentVariable("PATH") ?? ""; |
| 73 | + //var paths = path.Split(Path.PathSeparator).Append(Engine.Current.AppPath).ToList(); |
| 74 | + var paths = new List<string>{ Engine.Current.AppPath }; |
| 75 | + paths.AddRange(path.Split(Path.PathSeparator)); |
| 76 | + var programs = new [] {"yt-dlp", "youtube-dl"}; |
| 77 | + foreach (var p in programs) |
| 78 | + { |
| 79 | + var test = paths.Select(i => Path.Combine(i, p)).FirstOrDefault(File.Exists); |
| 80 | + if (string.IsNullOrWhiteSpace(test)) continue; |
| 81 | + YoutubeDLPath = test; |
| 82 | + Msg($"Patched NYoutubeDL with {p}: {test}"); |
| 83 | + return; |
| 84 | + } |
| 85 | + Msg("Could not find a valid program to patch NYoutubeDL with"); |
| 86 | + } |
| 87 | + |
| 88 | + private class WrapperPatch |
| 89 | + { |
| 90 | + public static bool WrapperLibraryPatch(ref string __result) |
| 91 | + { |
| 92 | + //Fix video players by setting the library path properly |
| 93 | + __result = Path.Combine(Engine.Current.AppPath, "Resonite_Data", "Plugins"); |
| 94 | + Msg("Patched library path: " + __result); |
| 95 | + return false; |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + private class YoutubeDLPatch |
| 100 | + { |
| 101 | + public static void SetupPreparePatch(YoutubeDL ydl) => |
| 102 | + //NYoutubeDL has logic to set the youtube-dl path according to the environment PATH, |
| 103 | + //but this doesn't work because it's set to an invalid path when initialized |
| 104 | + //this will set it to a valid youtube-dl location |
| 105 | + ydl.YoutubeDlPath = YoutubeDLPath; |
| 106 | + public static bool SetupPrepareRemovePatch(YoutubeDL ydl) => throw new Exception(); |
| 107 | + } |
| 108 | +} |
0 commit comments