Commit 7bd17acc authored by Martin Finkel's avatar Martin Finkel

net40 compatibility: Rework OS platform checks and expose HWND

parent 6a5f2eab
<Project>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<DefineConstants>$(DefineConstants);PORTABLE;DESKTOP</DefineConstants>
<DefineConstants>$(DefineConstants);PORTABLE;MODERN_DESKTOP</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.1'">
<DefineConstants>$(DefineConstants);NETSTANDARD1_1</DefineConstants>
......@@ -29,6 +29,6 @@
<DefineConstants>$(DefineConstants);MONO;ANDROID</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
<DefineConstants>$(DefineConstants);NETCORE;DESKTOP</DefineConstants>
<DefineConstants>$(DefineConstants);NETCORE;MODERN_DESKTOP</DefineConstants>
</PropertyGroup>
</Project>
\ No newline at end of file
......@@ -28,7 +28,7 @@ namespace LibVLCSharp.Shared
public static void Initialize()
{
#if DESKTOP
#if MODERN_DESKTOP
InitializeDesktop();
#elif ANDROID
InitializeAndroid();
......@@ -43,7 +43,7 @@ namespace LibVLCSharp.Shared
throw new VLCException("failed to initialize libvlc with JniOnLoad " +
$"{nameof(JniRuntime.CurrentRuntime.InvocationPointer)}: {JniRuntime.CurrentRuntime.InvocationPointer}");
}
#elif DESKTOP
#elif MODERN_DESKTOP
//TODO: Add Unload library func using handles
static void InitializeDesktop()
{
......@@ -111,6 +111,10 @@ namespace LibVLCSharp.Shared
/// The name of the folder that contains the per-architecture folders
/// </summary>
internal const string LibrariesRepositoryFolderName = "libvlc";
internal const string Windows = "msvcrt";
internal const string Linux = "libc";
internal const string Mac = "libSystem";
}
internal static class ArchitectureNames
......
......@@ -141,16 +141,14 @@ namespace LibVLCSharp.Shared
internal static extern void LibVLCMediaPlayerSetAndroidContext(IntPtr mediaPlayer, IntPtr aWindow);
#endif
#region Windows
/// <summary>
/// Compute the size required by vsprintf to print the parameters.
/// </summary>
/// <param name="format"></param>
/// <param name="ptr"></param>
/// <returns></returns>
[DllImport(Windows, CallingConvention = CallingConvention.Cdecl)]
public static extern int _vscprintf(string format,IntPtr ptr);
[DllImport(Constants.Windows, CallingConvention = CallingConvention.Cdecl)]
public static extern int _vscprintf(string format, IntPtr ptr);
/// <summary>
/// Format a string using printf style markers
......@@ -162,44 +160,11 @@ namespace LibVLCSharp.Shared
/// <param name="format">The message format</param>
/// <param name="args">The variable arguments list pointer. We do not know what it is, but the pointer must be given as-is from C back to sprintf.</param>
/// <returns>A negative value on failure, the number of characters written otherwise.</returns>
[DllImport(Windows, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
[DllImport(Constants.Windows, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int vsprintf(
IntPtr buffer,
string format,
IntPtr args);
[DllImport(Windows, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int _wfopen_s(out IntPtr pFile, string filename, string mode = Write);
[DllImport(Windows, CallingConvention = CallingConvention.Cdecl, EntryPoint = "fclose", SetLastError = true)]
public static extern int fcloseWindows(IntPtr stream);
#endregion
#region Linux
[DllImport(Linux, CallingConvention = CallingConvention.Cdecl, EntryPoint = "fopen", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr fopenLinux(string filename, string mode = Write);
[DllImport(Linux, CallingConvention = CallingConvention.Cdecl, EntryPoint = "fclose", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern int fcloseLinux(IntPtr file);
#endregion
#region Mac
[DllImport(Mac, CallingConvention = CallingConvention.Cdecl, EntryPoint = "fopen", SetLastError = true)]
public static extern IntPtr fopenMac(string path, string mode = Write);
[DllImport(Mac, CallingConvention = CallingConvention.Cdecl, EntryPoint = "fclose", SetLastError = true)]
public static extern int fcloseMac(IntPtr file);
#endregion
const string Windows = "msvcrt";
const string Linux = "libc";
const string Mac = "libSystem";
const string Write = "w";
}
internal static readonly System.Collections.Concurrent.ConcurrentDictionary<IntPtr, LibVLC> NativeToManagedMap
......@@ -384,19 +349,12 @@ namespace LibVLCSharp.Shared
/// <summary>
/// Native close log file handle
/// </summary>
/// <returns>true if no file to close or closed successful, false otherwise</returns>
/// <returns>true if no file to close or close operation successful, false otherwise</returns>
bool CloseLogFile()
{
if (_logFileHandle == IntPtr.Zero) return true;
#if DESKTOP
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return Native.fcloseWindows(_logFileHandle) == 0;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return Native.fcloseLinux(_logFileHandle) == 0;
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return Native.fcloseMac(_logFileHandle) == 0;
#endif
return false;
return MarshalUtils.Close(_logFileHandle);
}
public void SetLog(LogCallback cb)
......@@ -438,6 +396,7 @@ namespace LibVLCSharp.Shared
/// <summary>Sets up logging to a file.
/// Watch out: Overwrite contents if file exists!
/// Potentially throws a VLCException if FILE * cannot be obtained
/// </summary>
/// <para>FILE pointer opened for writing</para>
/// <para>(the FILE pointer must remain valid until libvlc_log_unset())</para>
......@@ -455,25 +414,10 @@ namespace LibVLCSharp.Shared
IntPtr NativeFilePtr(string filename)
{
var filePtr = IntPtr.Zero;
#if DESKTOP
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Native._wfopen_s(out filePtr, filename);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
filePtr = Native.fopenLinux(filename);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
filePtr = Native.fopenMac(filename);
}
#endif
if (filePtr == IntPtr.Zero)
var result = MarshalUtils.Open(filename, out var filePtr);
if (!result)
throw new VLCException("Could not get FILE * for log_set_file");
return filePtr;
return IntPtr.Zero;
}
/// <summary>Returns a list of audio filters that are available.</summary>
......
......@@ -7,6 +7,42 @@ namespace LibVLCSharp.Shared
{
public static class MarshalUtils
{
internal struct Native
{
#region Windows
[DllImport(Constants.Windows, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int _wfopen_s(out IntPtr pFile, string filename, string mode = Write);
[DllImport(Constants.Windows, CallingConvention = CallingConvention.Cdecl, EntryPoint = "fclose", SetLastError = true)]
public static extern int fcloseWindows(IntPtr stream);
#endregion
#region Linux
[DllImport(Constants.Linux, CallingConvention = CallingConvention.Cdecl, EntryPoint = "fopen", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr fopenLinux(string filename, string mode = Write);
[DllImport(Constants.Linux, CallingConvention = CallingConvention.Cdecl, EntryPoint = "fclose", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern int fcloseLinux(IntPtr file);
#endregion
#region Mac
[DllImport(Constants.Mac, CallingConvention = CallingConvention.Cdecl, EntryPoint = "fopen", SetLastError = true)]
public static extern IntPtr fopenMac(string path, string mode = Write);
[DllImport(Constants.Mac, CallingConvention = CallingConvention.Cdecl, EntryPoint = "fclose", SetLastError = true)]
public static extern int fcloseMac(IntPtr file);
#endregion
const string Write = "w";
}
public static TU[] Retrieve<T, TU>(Func<IntPtr> getRef, Func<IntPtr, T> retrieve,
Func<T, TU> create, Func<TU, TU> next, Action<IntPtr> releaseRef)
{
......@@ -60,6 +96,75 @@ namespace LibVLCSharp.Shared
return (T)Marshal.PtrToStructure(ptr, typeof(T));
#else
return Marshal.PtrToStructure<T>(ptr);
#endif
}
/// <summary>
/// Crossplatform dlopen
/// </summary>
/// <returns>true if successful</returns>
public static bool Open(string filename, out IntPtr fileHandle)
{
fileHandle = IntPtr.Zero;
#if NET40
switch (Environment.OSVersion.Platform)
{
case PlatformID.MacOSX:
fileHandle = Native.fopenMac(filename);
return fileHandle != IntPtr.Zero;
case PlatformID.Unix:
fileHandle = Native.fopenLinux(filename);
return fileHandle != IntPtr.Zero;
default:
return Native._wfopen_s(out fileHandle, filename) == 0;
}
#else
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if(Native._wfopen_s(out fileHandle, filename) != 0) return false;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
fileHandle = Native.fopenLinux(filename);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
fileHandle = Native.fopenMac(filename);
}
#endif
return fileHandle != IntPtr.Zero;
}
/// <summary>
/// Crossplatform fclose
/// </summary>
/// <param name="file handle"></param>
/// <returns>true if successful</returns>
public static bool Close(IntPtr fileHandle)
{
#if NET40
switch (Environment.OSVersion.Platform)
{
case PlatformID.MacOSX:
return Native.fcloseMac(fileHandle) == 0;
case PlatformID.Unix:
return Native.fcloseLinux(fileHandle) == 0;
default:
return Native.fcloseWindows(fileHandle) == 0;
}
#else
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return Native.fcloseMac(fileHandle) == 0;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return Native.fcloseLinux(fileHandle) == 0;
}
else
{
return Native.fcloseWindows(fileHandle) == 0;
}
#endif
}
}
......
......@@ -65,12 +65,10 @@ namespace LibVLCSharp.Shared
EntryPoint = "libvlc_media_player_stop")]
internal static extern void LibVLCMediaPlayerStop(IntPtr mediaPlayer);
#if COCOA
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_player_set_nsobject")]
internal static extern void LibVLCMediaPlayerSetNsobject(IntPtr mediaPlayer, IntPtr drawable);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_player_get_nsobject")]
internal static extern IntPtr LibVLCMediaPlayerGetNsobject(IntPtr mediaPlayer);
......@@ -80,17 +78,15 @@ namespace LibVLCSharp.Shared
EntryPoint = "libvlc_media_player_set_xwindow")]
internal static extern void LibVLCMediaPlayerSetXwindow(IntPtr mediaPlayer, uint drawable);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_player_get_xwindow")]
internal static extern uint LibVLCMediaPlayerGetXwindow(IntPtr mediaPlayer);
#if DESKTOP
#if MODERN_DESKTOP || NET40
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_player_set_hwnd")]
internal static extern void LibVLCMediaPlayerSetHwnd(IntPtr mediaPlayer, IntPtr drawable);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_player_get_hwnd")]
internal static extern IntPtr LibVLCMediaPlayerGetHwnd(IntPtr mediaPlayer);
......@@ -777,7 +773,7 @@ namespace LibVLCSharp.Shared
set => Native.LibVLCMediaPlayerSetXwindow(NativeReference, value);
}
#if DESKTOP
#if MODERN_DESKTOP || NET40
/// <summary>
/// Set a Win32/Win64 API window handle (HWND) where the media player
/// should render its video output. If LibVLC was built without
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment