diff --git a/src/LibVLCSharp/Shared/Core/Constants.cs b/src/LibVLCSharp/Shared/Core/Constants.cs index 1328de87d..95da85020 100644 --- a/src/LibVLCSharp/Shared/Core/Constants.cs +++ b/src/LibVLCSharp/Shared/Core/Constants.cs @@ -8,10 +8,16 @@ internal static class Constants internal const string LibraryName = "@rpath/DynamicMobileVLCKit.framework/DynamicMobileVLCKit"; #elif TVOS internal const string LibraryName = "@rpath/DynamicTVVLCKit.framework/DynamicTVVLCKit"; +#elif MAC + internal const string LibraryName = "@executable_path/../MonoBundle/lib/libvlc.dylib"; #else internal const string LibraryName = "libvlc"; + // for netcore on mac, this is needed. + // but this case can't be determined at build time, so we might need LibraryName to be a variable + //internal const string LibraryName = "libvlc/osx-x64/lib/libvlc"; #endif - internal const string CoreLibraryName = "libvlccore"; + // TODO: fix + internal const string CoreLibraryName = "@rpath/libvlccore.dylib"; /// /// The name of the folder that contains the per-architecture folders @@ -20,6 +26,7 @@ internal static class Constants internal const string Msvcrt = "msvcrt"; internal const string Libc = "libc"; + internal const string Libdl = "libdl"; internal const string LibSystem = "libSystem"; internal const string Kernel32 = "kernel32"; internal const string LibX11 = "libX11"; @@ -27,6 +34,8 @@ internal static class Constants internal const string MacLibraryExtension = ".dylib"; internal const string Lib = "lib"; internal const string LibVLC = "libvlc"; + internal const string VLCPLUGINPATH = "VLC_PLUGIN_PATH"; + internal const string Plugins = "plugins"; } internal static class ArchitectureNames diff --git a/src/LibVLCSharp/Shared/Core/Core.Apple.cs b/src/LibVLCSharp/Shared/Core/Core.Apple.cs index 932780ee4..f10faf302 100644 --- a/src/LibVLCSharp/Shared/Core/Core.Apple.cs +++ b/src/LibVLCSharp/Shared/Core/Core.Apple.cs @@ -1,5 +1,6 @@ #if APPLE using System; +using System.IO; namespace LibVLCSharp.Shared { @@ -9,6 +10,7 @@ namespace LibVLCSharp.Shared /// public static partial class Core { +#if IOS || TVOS /// /// Load the native libvlc library (if necessary, depending on platform) /// Ensure that you installed the VideoLAN.LibVLC.[YourPlatform] package in your target project @@ -24,6 +26,48 @@ public static void Initialize(string? libvlcDirectoryPath = null) { EnsureVersionsMatch(); } +#elif MAC + static IntPtr LibvlcHandle; + static IntPtr LibvlccoreHandle; + + /// + /// Load the native libvlc library (if necessary, depending on platform) + /// Ensure that you installed the VideoLAN.LibVLC.[YourPlatform] package in your target project + /// This will throw a if the native libvlc libraries cannot be found or loaded. + /// It may also throw a if the LibVLC and LibVLCSharp major versions do not match. + /// See https://code.videolan.org/videolan/LibVLCSharp/-/blob/master/docs/versioning.md for more info about the versioning strategy. + /// + /// The path to the directory that contains libvlc and libvlccore + /// No need to specify unless running netstandard 1.1, or using custom location for libvlc + /// This parameter is NOT supported on Linux, use LD_LIBRARY_PATH instead. + /// + public static void Initialize(string? libvlcDirectoryPath = null) + { + InitializeMac(libvlcDirectoryPath); + + EnsureVersionsMatch(); + } + + // TODO: is this still called? + private static void InitializeMac(string? libvlcDirectoryPath) + { + if (!string.IsNullOrEmpty(libvlcDirectoryPath)) + { + bool loadResult; + + var libvlcPath = LibVLCPath(libvlcDirectoryPath!); + loadResult = LoadNativeLibrary(libvlcPath, out LibvlcHandle); + if (!loadResult) + Log($"Failed to load required native libraries at {libvlcPath}"); + return; + } + + var pluginPath = Path.Combine(Path.GetDirectoryName(typeof(LibVLC).Assembly.Location)); + PluginPath(pluginPath); + + LoadLibVLC(); + } +#endif // MAC } } -#endif +#endif // APPLE \ No newline at end of file diff --git a/src/LibVLCSharp/Shared/Core/Core.Desktop.cs b/src/LibVLCSharp/Shared/Core/Core.Desktop.cs index 82caa2c1d..19bd2f902 100644 --- a/src/LibVLCSharp/Shared/Core/Core.Desktop.cs +++ b/src/LibVLCSharp/Shared/Core/Core.Desktop.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Reflection; using System.Runtime.InteropServices; namespace LibVLCSharp.Shared @@ -85,10 +86,31 @@ static void InitializeDesktop(string? libvlcDirectoryPath = null) return; } + if (PlatformHelper.IsMac) + { +#if !NETSTANDARD1_1 && !NET40 + var pluginPath = string.Empty; + if(PlatformHelper.IsDotNet) + { + pluginPath = Path.Combine(Path.GetDirectoryName(typeof(LibVLC).Assembly.Location), Constants.LibVLC, + ArchitectureNames.MacOS64, Constants.Plugins); + } + else + { + // in this case, we have a real macOS app bundle thanks to Mono integration with cocoa + pluginPath = Path.Combine(Path.GetDirectoryName(typeof(LibVLC).Assembly.Location), Constants.Plugins); + } + + Console.Out.WriteLine("PluginPath: " + pluginPath); + PluginPath(pluginPath); +#endif + + } #if !NETSTANDARD1_1 LoadLibVLC(libvlcDirectoryPath); #endif } } + } #endif // NETFRAMEWORK || NETSTANDARD diff --git a/src/LibVLCSharp/Shared/Core/Core.cs b/src/LibVLCSharp/Shared/Core/Core.cs index 7dd225da9..c02f99b3d 100644 --- a/src/LibVLCSharp/Shared/Core/Core.cs +++ b/src/LibVLCSharp/Shared/Core/Core.cs @@ -25,8 +25,11 @@ partial struct Native [DllImport(Constants.Kernel32, SetLastError = true)] internal static extern IntPtr LoadLibrary(string dllToLoad); - [DllImport(Constants.LibSystem, EntryPoint = "dlopen")] - internal static extern IntPtr Dlopen(string libraryPath, int mode = 1); + [DllImport(Constants.Libdl, EntryPoint = "dlopen")] + internal static extern IntPtr Dlopen(string libraryPath, int mode = 0x002); + + [DllImport(Constants.Libc)] + internal static extern int setenv(string name, string value, int overwrite = 1); } #if !UWP10_0 && !NETSTANDARD1_1 @@ -44,9 +47,12 @@ static void EnsureVersionsMatch() } #endif - static string LibVLCPath(string dir) => Path.Combine(dir, $"{Constants.LibraryName}{LibraryExtension}"); - static string LibVLCCorePath(string dir) => Path.Combine(dir, $"{Constants.CoreLibraryName}{LibraryExtension}"); + static string LibVLCPath(string dir) => Path.Combine(dir, $"{Constants.LibVLC}{LibraryExtension}"); + static string LibVLCCorePath(string dir) => Path.Combine(dir, $"libvlccore{LibraryExtension}"); static string LibraryExtension => PlatformHelper.IsWindows ? Constants.WindowsLibraryExtension : Constants.MacLibraryExtension; +#if !NETSTANDARD1_1 + static void PluginPath(string pluginPath) => Native.setenv(Constants.VLCPLUGINPATH, pluginPath); +#endif static void Log(string message) { #if !UWP10_0 && !NETSTANDARD1_1 @@ -56,7 +62,7 @@ static void Log(string message) #endif } -#if (NETFRAMEWORK || NETSTANDARD) && !NETSTANDARD1_1 +#if (MAC || NETFRAMEWORK || NETSTANDARD) && !NETSTANDARD1_1 static bool Loaded => LibvlcHandle != IntPtr.Zero; static List<(string libvlccore, string libvlc)> ComputeLibVLCSearchPaths() { @@ -144,7 +150,7 @@ static void LoadLibVLC(string? libvlcDirectoryPath = null) { throw new VLCException("Failed to load required native libraries. " + $"{Environment.NewLine}Have you installed the latest LibVLC package from nuget for your target platform?" + - $"{Environment.NewLine}Search paths include {string.Join("; ", paths.Select(p => $"{p.libvlc},{p.libvlccore}"))}"); + $"{Environment.NewLine}Search paths include {string.Join($"; {Environment.NewLine}", paths.Select(p => $"{p.libvlc},{p.libvlccore}"))}"); } } #endif diff --git a/src/LibVLCSharp/Shared/Helpers/PlatformHelper.cs b/src/LibVLCSharp/Shared/Helpers/PlatformHelper.cs index cee99770e..aae4cc9d4 100644 --- a/src/LibVLCSharp/Shared/Helpers/PlatformHelper.cs +++ b/src/LibVLCSharp/Shared/Helpers/PlatformHelper.cs @@ -64,5 +64,12 @@ public static bool IsMac /// Returns true if running in 64bit process, false otherwise /// public static bool IsX64BitProcess => IntPtr.Size == 8; + +#if !NET40 && !UWP10_0 + /// + /// Returns true if running on dotnet, false otherwise (such as on Mono) + /// + public static bool IsDotNet => RuntimeInformation.FrameworkDescription.StartsWith(".NET"); +#endif } }