Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mac libvlc loading refactoring #163

Draft
wants to merge 10 commits into
base: 3.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/LibVLCSharp/Shared/Core/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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";

/// <summary>
/// The name of the folder that contains the per-architecture folders
Expand All @@ -20,13 +26,16 @@ 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";
internal const string WindowsLibraryExtension = ".dll";
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
Expand Down
46 changes: 45 additions & 1 deletion src/LibVLCSharp/Shared/Core/Core.Apple.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#if APPLE
using System;
using System.IO;

namespace LibVLCSharp.Shared
{
Expand All @@ -9,6 +10,7 @@ namespace LibVLCSharp.Shared
/// </summary>
public static partial class Core
{
#if IOS || TVOS
/// <summary>
/// Load the native libvlc library (if necessary, depending on platform)
/// <para/> Ensure that you installed the VideoLAN.LibVLC.[YourPlatform] package in your target project
Expand All @@ -24,6 +26,48 @@ public static void Initialize(string? libvlcDirectoryPath = null)
{
EnsureVersionsMatch();
}
#elif MAC
static IntPtr LibvlcHandle;
static IntPtr LibvlccoreHandle;

/// <summary>
/// Load the native libvlc library (if necessary, depending on platform)
/// <para/> Ensure that you installed the VideoLAN.LibVLC.[YourPlatform] package in your target project
/// <para/> This will throw a <see cref="VLCException"/> if the native libvlc libraries cannot be found or loaded.
/// <para/> It may also throw a <see cref="VLCException"/> 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.
/// </summary>
/// <param name="libvlcDirectoryPath">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
/// <para/> This parameter is NOT supported on Linux, use LD_LIBRARY_PATH instead.
/// </param>
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
22 changes: 22 additions & 0 deletions src/LibVLCSharp/Shared/Core/Core.Desktop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;

namespace LibVLCSharp.Shared
Expand Down Expand Up @@ -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
18 changes: 12 additions & 6 deletions src/LibVLCSharp/Shared/Core/Core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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()
{
Expand Down Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions src/LibVLCSharp/Shared/Helpers/PlatformHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,12 @@ public static bool IsMac
/// Returns true if running in 64bit process, false otherwise
/// </summary>
public static bool IsX64BitProcess => IntPtr.Size == 8;

#if !NET40 && !UWP10_0
/// <summary>
/// Returns true if running on dotnet, false otherwise (such as on Mono)
/// </summary>
public static bool IsDotNet => RuntimeInformation.FrameworkDescription.StartsWith(".NET");
#endif
}
}