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

net40 compatibility: Rework OS platform checks and expose HWND

parent 6a5f2eab
<Project> <Project>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<DefineConstants>$(DefineConstants);PORTABLE;DESKTOP</DefineConstants> <DefineConstants>$(DefineConstants);PORTABLE;MODERN_DESKTOP</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.1'"> <PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.1'">
<DefineConstants>$(DefineConstants);NETSTANDARD1_1</DefineConstants> <DefineConstants>$(DefineConstants);NETSTANDARD1_1</DefineConstants>
...@@ -29,6 +29,6 @@ ...@@ -29,6 +29,6 @@
<DefineConstants>$(DefineConstants);MONO;ANDROID</DefineConstants> <DefineConstants>$(DefineConstants);MONO;ANDROID</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'"> <PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
<DefineConstants>$(DefineConstants);NETCORE;DESKTOP</DefineConstants> <DefineConstants>$(DefineConstants);NETCORE;MODERN_DESKTOP</DefineConstants>
</PropertyGroup> </PropertyGroup>
</Project> </Project>
\ No newline at end of file
...@@ -28,7 +28,7 @@ namespace LibVLCSharp.Shared ...@@ -28,7 +28,7 @@ namespace LibVLCSharp.Shared
public static void Initialize() public static void Initialize()
{ {
#if DESKTOP #if MODERN_DESKTOP
InitializeDesktop(); InitializeDesktop();
#elif ANDROID #elif ANDROID
InitializeAndroid(); InitializeAndroid();
...@@ -43,7 +43,7 @@ namespace LibVLCSharp.Shared ...@@ -43,7 +43,7 @@ namespace LibVLCSharp.Shared
throw new VLCException("failed to initialize libvlc with JniOnLoad " + throw new VLCException("failed to initialize libvlc with JniOnLoad " +
$"{nameof(JniRuntime.CurrentRuntime.InvocationPointer)}: {JniRuntime.CurrentRuntime.InvocationPointer}"); $"{nameof(JniRuntime.CurrentRuntime.InvocationPointer)}: {JniRuntime.CurrentRuntime.InvocationPointer}");
} }
#elif DESKTOP #elif MODERN_DESKTOP
//TODO: Add Unload library func using handles //TODO: Add Unload library func using handles
static void InitializeDesktop() static void InitializeDesktop()
{ {
...@@ -111,6 +111,10 @@ namespace LibVLCSharp.Shared ...@@ -111,6 +111,10 @@ namespace LibVLCSharp.Shared
/// The name of the folder that contains the per-architecture folders /// The name of the folder that contains the per-architecture folders
/// </summary> /// </summary>
internal const string LibrariesRepositoryFolderName = "libvlc"; internal const string LibrariesRepositoryFolderName = "libvlc";
internal const string Windows = "msvcrt";
internal const string Linux = "libc";
internal const string Mac = "libSystem";
} }
internal static class ArchitectureNames internal static class ArchitectureNames
......
...@@ -141,16 +141,14 @@ namespace LibVLCSharp.Shared ...@@ -141,16 +141,14 @@ namespace LibVLCSharp.Shared
internal static extern void LibVLCMediaPlayerSetAndroidContext(IntPtr mediaPlayer, IntPtr aWindow); internal static extern void LibVLCMediaPlayerSetAndroidContext(IntPtr mediaPlayer, IntPtr aWindow);
#endif #endif
#region Windows
/// <summary> /// <summary>
/// Compute the size required by vsprintf to print the parameters. /// Compute the size required by vsprintf to print the parameters.
/// </summary> /// </summary>
/// <param name="format"></param> /// <param name="format"></param>
/// <param name="ptr"></param> /// <param name="ptr"></param>
/// <returns></returns> /// <returns></returns>
[DllImport(Windows, CallingConvention = CallingConvention.Cdecl)] [DllImport(Constants.Windows, CallingConvention = CallingConvention.Cdecl)]
public static extern int _vscprintf(string format,IntPtr ptr); public static extern int _vscprintf(string format, IntPtr ptr);
/// <summary> /// <summary>
/// Format a string using printf style markers /// Format a string using printf style markers
...@@ -162,44 +160,11 @@ namespace LibVLCSharp.Shared ...@@ -162,44 +160,11 @@ namespace LibVLCSharp.Shared
/// <param name="format">The message format</param> /// <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> /// <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> /// <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( public static extern int vsprintf(
IntPtr buffer, IntPtr buffer,
string format, string format,
IntPtr args); 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 internal static readonly System.Collections.Concurrent.ConcurrentDictionary<IntPtr, LibVLC> NativeToManagedMap
...@@ -384,19 +349,12 @@ namespace LibVLCSharp.Shared ...@@ -384,19 +349,12 @@ namespace LibVLCSharp.Shared
/// <summary> /// <summary>
/// Native close log file handle /// Native close log file handle
/// </summary> /// </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() bool CloseLogFile()
{ {
if (_logFileHandle == IntPtr.Zero) return true; if (_logFileHandle == IntPtr.Zero) return true;
#if DESKTOP
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return MarshalUtils.Close(_logFileHandle);
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;
} }
public void SetLog(LogCallback cb) public void SetLog(LogCallback cb)
...@@ -438,6 +396,7 @@ namespace LibVLCSharp.Shared ...@@ -438,6 +396,7 @@ namespace LibVLCSharp.Shared
/// <summary>Sets up logging to a file. /// <summary>Sets up logging to a file.
/// Watch out: Overwrite contents if file exists! /// Watch out: Overwrite contents if file exists!
/// Potentially throws a VLCException if FILE * cannot be obtained
/// </summary> /// </summary>
/// <para>FILE pointer opened for writing</para> /// <para>FILE pointer opened for writing</para>
/// <para>(the FILE pointer must remain valid until libvlc_log_unset())</para> /// <para>(the FILE pointer must remain valid until libvlc_log_unset())</para>
...@@ -455,25 +414,10 @@ namespace LibVLCSharp.Shared ...@@ -455,25 +414,10 @@ namespace LibVLCSharp.Shared
IntPtr NativeFilePtr(string filename) IntPtr NativeFilePtr(string filename)
{ {
var filePtr = IntPtr.Zero; var result = MarshalUtils.Open(filename, out var filePtr);
#if DESKTOP if (!result)
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)
throw new VLCException("Could not get FILE * for log_set_file"); throw new VLCException("Could not get FILE * for log_set_file");
return IntPtr.Zero;
return filePtr;
} }
/// <summary>Returns a list of audio filters that are available.</summary> /// <summary>Returns a list of audio filters that are available.</summary>
......
...@@ -7,6 +7,42 @@ namespace LibVLCSharp.Shared ...@@ -7,6 +7,42 @@ namespace LibVLCSharp.Shared
{ {
public static class MarshalUtils 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, public static TU[] Retrieve<T, TU>(Func<IntPtr> getRef, Func<IntPtr, T> retrieve,
Func<T, TU> create, Func<TU, TU> next, Action<IntPtr> releaseRef) Func<T, TU> create, Func<TU, TU> next, Action<IntPtr> releaseRef)
{ {
...@@ -60,6 +96,75 @@ namespace LibVLCSharp.Shared ...@@ -60,6 +96,75 @@ namespace LibVLCSharp.Shared
return (T)Marshal.PtrToStructure(ptr, typeof(T)); return (T)Marshal.PtrToStructure(ptr, typeof(T));
#else #else
return Marshal.PtrToStructure<T>(ptr); 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 #endif
} }
} }
......
...@@ -65,12 +65,10 @@ namespace LibVLCSharp.Shared ...@@ -65,12 +65,10 @@ namespace LibVLCSharp.Shared
EntryPoint = "libvlc_media_player_stop")] EntryPoint = "libvlc_media_player_stop")]
internal static extern void LibVLCMediaPlayerStop(IntPtr mediaPlayer); internal static extern void LibVLCMediaPlayerStop(IntPtr mediaPlayer);
#if COCOA #if COCOA
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_player_set_nsobject")] EntryPoint = "libvlc_media_player_set_nsobject")]
internal static extern void LibVLCMediaPlayerSetNsobject(IntPtr mediaPlayer, IntPtr drawable); internal static extern void LibVLCMediaPlayerSetNsobject(IntPtr mediaPlayer, IntPtr drawable);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_player_get_nsobject")] EntryPoint = "libvlc_media_player_get_nsobject")]
internal static extern IntPtr LibVLCMediaPlayerGetNsobject(IntPtr mediaPlayer); internal static extern IntPtr LibVLCMediaPlayerGetNsobject(IntPtr mediaPlayer);
...@@ -80,17 +78,15 @@ namespace LibVLCSharp.Shared ...@@ -80,17 +78,15 @@ namespace LibVLCSharp.Shared
EntryPoint = "libvlc_media_player_set_xwindow")] EntryPoint = "libvlc_media_player_set_xwindow")]
internal static extern void LibVLCMediaPlayerSetXwindow(IntPtr mediaPlayer, uint drawable); internal static extern void LibVLCMediaPlayerSetXwindow(IntPtr mediaPlayer, uint drawable);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_player_get_xwindow")] EntryPoint = "libvlc_media_player_get_xwindow")]
internal static extern uint LibVLCMediaPlayerGetXwindow(IntPtr mediaPlayer); internal static extern uint LibVLCMediaPlayerGetXwindow(IntPtr mediaPlayer);
#if DESKTOP
#if MODERN_DESKTOP || NET40
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_player_set_hwnd")] EntryPoint = "libvlc_media_player_set_hwnd")]
internal static extern void LibVLCMediaPlayerSetHwnd(IntPtr mediaPlayer, IntPtr drawable); internal static extern void LibVLCMediaPlayerSetHwnd(IntPtr mediaPlayer, IntPtr drawable);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_player_get_hwnd")] EntryPoint = "libvlc_media_player_get_hwnd")]
internal static extern IntPtr LibVLCMediaPlayerGetHwnd(IntPtr mediaPlayer); internal static extern IntPtr LibVLCMediaPlayerGetHwnd(IntPtr mediaPlayer);
...@@ -777,7 +773,7 @@ namespace LibVLCSharp.Shared ...@@ -777,7 +773,7 @@ namespace LibVLCSharp.Shared
set => Native.LibVLCMediaPlayerSetXwindow(NativeReference, value); set => Native.LibVLCMediaPlayerSetXwindow(NativeReference, value);
} }
#if DESKTOP #if MODERN_DESKTOP || NET40
/// <summary> /// <summary>
/// Set a Win32/Win64 API window handle (HWND) where the media player /// Set a Win32/Win64 API window handle (HWND) where the media player
/// should render its video output. If LibVLC was built without /// 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