Commit f26e019d authored by Martin Finkel's avatar Martin Finkel

More marshal refactoring

parent 3af87979
......@@ -91,9 +91,9 @@ namespace LibVLCSharp.Tests
public void Categories()
{
var libVLC = new LibVLC();
var md1 = libVLC.MediaDiscoverers(MediaDiscoverer.Category.Devices);
var md2 = libVLC.MediaDiscoverers(MediaDiscoverer.Category.Lan);
var md3 = libVLC.MediaDiscoverers(MediaDiscoverer.Category.Localdirs);
var md1 = libVLC.MediaDiscoverers(MediaDiscovererCategory.Devices);
var md2 = libVLC.MediaDiscoverers(MediaDiscovererCategory.Lan);
var md3 = libVLC.MediaDiscoverers(MediaDiscovererCategory.Localdirs);
}
[Test]
......
......@@ -12,7 +12,7 @@ namespace LibVLCSharp.Tests
public void CreateStartAndStopDiscoverer()
{
var libVLC = new LibVLC();
var mds = libVLC.MediaDiscoverers(MediaDiscoverer.Category.Lan);
var mds = libVLC.MediaDiscoverers(MediaDiscovererCategory.Lan);
var md = new MediaDiscoverer(libVLC, mds.First().Name);
Assert.True(md.Start());
Assert.True(md.IsRunning);
......@@ -24,7 +24,7 @@ namespace LibVLCSharp.Tests
public void DisposeMediaDiscoverer()
{
var libVLC = new LibVLC();
var mds = libVLC.MediaDiscoverers(MediaDiscoverer.Category.Lan);
var mds = libVLC.MediaDiscoverers(MediaDiscovererCategory.Lan);
var md = new MediaDiscoverer(libVLC, mds.First().Name);
Assert.True(md.Start());
Assert.True(md.IsRunning);
......
......@@ -5,7 +5,7 @@ namespace LibVLCSharp.Shared.Helpers
internal static class MarshalExtensions
{
/// <summary>
/// Helper method that creates a managed type from the internal interop structure.
/// Helper method that creates a user friendly type from the internal interop structure.
/// </summary>
/// <param name="s">AudioOutputDescriptionStructure from interop</param>
/// <returns>public AudioOutputDescription to be consumed by the user</returns>
......@@ -14,7 +14,7 @@ namespace LibVLCSharp.Shared.Helpers
Utf8StringMarshaler.GetInstance().MarshalNativeToManaged(s.Description) as string);
/// <summary>
/// Helper method that creates a managed type from the internal interop structure.
/// Helper method that creates a user friendly type from the internal interop structure.
/// </summary>
/// <param name="s">AudioOutputDeviceStructure from interop</param>
/// <returns>public AudioOutputDevice to be consumed by the user</returns>
......@@ -23,7 +23,7 @@ namespace LibVLCSharp.Shared.Helpers
Utf8StringMarshaler.GetInstance().MarshalNativeToManaged(s.Description) as string);
/// <summary>
/// Helper method that creates a managed type from the internal interop structure.
/// Helper method that creates a user friendly type from the internal interop structure.
/// </summary>
/// <param name="s">ModuleDescriptionStructure from interop</param>
/// <returns>public ModuleDescription to be consumed by the user</returns>
......@@ -34,7 +34,7 @@ namespace LibVLCSharp.Shared.Helpers
Utf8StringMarshaler.GetInstance().MarshalNativeToManaged(s.Help) as string);
/// <summary>
/// Helper method that creates a managed type from the internal interop structure.
/// Helper method that creates a user friendly type from the internal interop structure.
/// </summary>
/// <param name="s">TrackDescriptionStructure from interop</param>
/// <returns>public TrackDescription to be consumed by the user</returns>
......@@ -42,7 +42,7 @@ namespace LibVLCSharp.Shared.Helpers
new TrackDescription(s.Id, Utf8StringMarshaler.GetInstance().MarshalNativeToManaged(s.Name) as string);
/// <summary>
/// Helper method that creates a managed type from the internal interop structure.
/// Helper method that creates a user friendly type from the internal interop structure.
/// </summary>
/// <param name="s">MediaSlaveStructure from interop</param>
/// <returns>public MediaSlave to be consumed by the user</returns>
......@@ -50,7 +50,7 @@ namespace LibVLCSharp.Shared.Helpers
new MediaSlave(Utf8StringMarshaler.GetInstance().MarshalNativeToManaged(s.Uri) as string, s.Type, s.Priority);
/// <summary>
/// Helper method that creates a managed type from the internal interop structure.
/// Helper method that creates a user friendly type from the internal interop structure.
/// </summary>
/// <param name="s">TrackDescriptionStructure from interop</param>
/// <returns>public TrackDescription to be consumed by the user</returns>
......@@ -58,5 +58,24 @@ namespace LibVLCSharp.Shared.Helpers
new MediaTrack(s.Codec, s.OriginalFourcc, s.Id, s.TrackType, s.Profile, s.Level, s.Data, s.Bitrate,
Utf8StringMarshaler.GetInstance().MarshalNativeToManaged(s.Language) as string,
Utf8StringMarshaler.GetInstance().MarshalNativeToManaged(s.Description) as string);
/// <summary>
/// Helper method that creates a user friendly type from the internal interop structure.
/// </summary>
/// <param name="s">MediaDiscovererDescriptionStructure from interop</param>
/// <returns>public MediaDiscovererDescription to be consumed by the user</returns>
internal static MediaDiscovererDescription Build(this MediaDiscovererDescriptionStructure s) =>
new MediaDiscovererDescription(Utf8StringMarshaler.GetInstance().MarshalNativeToManaged(s.Name) as string,
Utf8StringMarshaler.GetInstance().MarshalNativeToManaged(s.LongName) as string,
s.Category);
/// <summary>
/// Helper method that creates a user friendly type from the internal interop structure.
/// </summary>
/// <param name="s">RendererDescriptionStructure from interop</param>
/// <returns>public RendererDescription to be consumed by the user</returns>
internal static RendererDescription Build(this RendererDescriptionStructure s) =>
new RendererDescription(Utf8StringMarshaler.GetInstance().MarshalNativeToManaged(s.Name) as string,
Utf8StringMarshaler.GetInstance().MarshalNativeToManaged(s.LongName) as string);
}
}
\ No newline at end of file
......@@ -44,7 +44,9 @@ namespace LibVLCSharp.Shared.Helpers
}
internal 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<T, IntPtr> next, Action<IntPtr> releaseRef)
where T : struct
where TU : struct
{
var nativeRef = getRef();
if (nativeRef == IntPtr.Zero)
......@@ -55,25 +57,31 @@ namespace LibVLCSharp.Shared.Helpers
return Array.Empty<TU>();
#endif
}
var structure = retrieve(nativeRef);
var obj = create(structure);
var resultList = new List<TU>();
while (obj != null)
IntPtr nextRef = nativeRef;
T structure;
TU obj;
while (nextRef != IntPtr.Zero)
{
structure = retrieve(nextRef);
obj = create(structure);
resultList.Add(obj);
obj = next(obj);
nextRef = next(structure);
}
releaseRef(nativeRef);
return resultList.ToArray();
}
internal static TU[] Retrieve<T, TU>(Func<IntPtr> getRef, Func<IntPtr, T> retrieve,
Func<T, TU> create, Func<T, IntPtr> next, Action<IntPtr> releaseRef)
internal static TU[] Retrieve<T, TU>(IntPtr nativeRef, Func<IntPtr, IntPtr, uint> getRef, Func<IntPtr, T> retrieve,
Func<T, TU> create, Action<IntPtr, uint> releaseRef)
where T : struct
where TU : struct
{
var nativeRef = getRef();
if (nativeRef == IntPtr.Zero)
var arrayPtr = IntPtr.Zero;
var count = getRef(nativeRef, arrayPtr);
if(count == 0)
{
#if NETSTANDARD1_1 || NET40
return new TU[0];
......@@ -83,28 +91,32 @@ namespace LibVLCSharp.Shared.Helpers
}
var resultList = new List<TU>();
IntPtr nextRef = nativeRef;
T structure;
TU obj;
while (nextRef != IntPtr.Zero)
for (var i = 0; i < count; i++)
{
structure = retrieve(nextRef);
obj = create(structure);
resultList.Add(obj);
nextRef = next(structure);
var ptr = Marshal.ReadIntPtr(arrayPtr, i * IntPtr.Size);
structure = retrieve(ptr);
var managedStruct = create(structure);
resultList.Add(managedStruct);
}
releaseRef(nativeRef);
releaseRef(arrayPtr, count);
arrayPtr = IntPtr.Zero;
return resultList.ToArray();
}
// ulong or uint?
internal static TU[] Retrieve<T, TU>(IntPtr nativeRef, Func<IntPtr, IntPtr, uint> getRef, Func<IntPtr, T> retrieve,
Func<T, TU> create, Action<IntPtr, uint> releaseRef)
internal static TU[] Retrieve<T, TU>(IntPtr nativeRef, Func<IntPtr, IntPtr, ulong> getRef, Func<IntPtr, T> retrieve,
Func<T, TU> create, Action<IntPtr, ulong> releaseRef)
where T : struct
where TU : struct
{
var arrayPtr = IntPtr.Zero;
var count = getRef(nativeRef, arrayPtr);
if(count == 0)
var countLong = getRef(nativeRef, arrayPtr);
var count = (int)countLong;
if (count == 0)
{
#if NETSTANDARD1_1 || NET40
return new TU[0];
......@@ -124,7 +136,42 @@ namespace LibVLCSharp.Shared.Helpers
resultList.Add(managedStruct);
}
releaseRef(arrayPtr, count);
releaseRef(arrayPtr, countLong);
arrayPtr = IntPtr.Zero;
return resultList.ToArray();
}
internal static TU[] Retrieve<T, TU, TE>(IntPtr nativeRef, TE extraParam, Func<IntPtr, TE, IntPtr, ulong> getRef, Func<IntPtr, T> retrieve,
Func<T, TU> create, Action<IntPtr, ulong> releaseRef)
where TE : Enum
where T : struct
where TU : struct
{
var arrayPtr = IntPtr.Zero;
var countLong = getRef(nativeRef, extraParam, arrayPtr);
var count = (int)countLong;
if (count == 0)
{
#if NETSTANDARD1_1 || NET40
return new TU[0];
#else
return Array.Empty<TU>();
#endif
}
var resultList = new List<TU>();
T structure;
for (var i = 0; i < count; i++)
{
var ptr = Marshal.ReadIntPtr(arrayPtr, i * IntPtr.Size);
structure = retrieve(ptr);
var managedStruct = create(structure);
resultList.Add(managedStruct);
}
releaseRef(arrayPtr, countLong);
arrayPtr = IntPtr.Zero;
return resultList.ToArray();
......
......@@ -117,7 +117,7 @@ namespace LibVLCSharp.Shared
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_discoverer_list_get")]
internal static extern ulong LibVLCMediaDiscovererListGet(IntPtr libVLC, MediaDiscoverer.Category category, ref IntPtr pppServices);
internal static extern ulong LibVLCMediaDiscovererListGet(IntPtr libVLC, MediaDiscovererCategory category, ref IntPtr pppServices);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_discoverer_list_release")]
......@@ -497,34 +497,29 @@ namespace LibVLCSharp.Shared
Native.LibVLCAudioOutputDeviceListRelease);
/// <summary>Get media discoverer services by category</summary>
/// <param name="category">category of services to fetch</param>
/// <param name="discovererCategory">category of services to fetch</param>
/// <returns>the number of media discoverer services (0 on error)</returns>
/// <remarks>LibVLC 3.0.0 and later.</remarks>
public MediaDiscoverer.Description[] MediaDiscoverers(MediaDiscoverer.Category category)
{
var arrayResultPtr = IntPtr.Zero;
var count = Native.LibVLCMediaDiscovererListGet(NativeReference, category, ref arrayResultPtr);
#if NETSTANDARD1_1 || NET40
if (count == 0) return new MediaDiscoverer.Description[0];
#else
if (count == 0) return Array.Empty<MediaDiscoverer.Description>();
#endif
var mediaDiscovererDescription = new MediaDiscoverer.Description[(int)count];
for (var i = 0; i < (int)count; i++)
{
var ptr = Marshal.ReadIntPtr(arrayResultPtr, i * IntPtr.Size);
var managedStruct = (MediaDiscoverer.Description)Marshal.PtrToStructure(ptr, typeof(MediaDiscoverer.Description));
mediaDiscovererDescription[i] = managedStruct;
}
Native.LibVLCMediaDiscovererListRelease(arrayResultPtr, count);
return mediaDiscovererDescription;
}
public MediaDiscovererDescription[] MediaDiscoverers(MediaDiscovererCategory discovererCategory) =>
MarshalUtils.Retrieve(NativeReference, discovererCategory,
(nativeRef, category, arrayPtr) => Native.LibVLCMediaDiscovererListGet(nativeRef, category, ref arrayPtr),
MarshalUtils.PtrToStructure<MediaDiscovererDescriptionStructure>,
m => m.Build(),
Native.LibVLCMediaDiscovererListRelease);
readonly Dictionary<IntPtr, CancellationTokenSource> _cts = new Dictionary<IntPtr, CancellationTokenSource>();
/// <summary>
/// Register callbacks in order to handle VLC dialogs.
/// LibVLC 3.0.0 and later.
/// </summary>
/// <param name="error">Called when an error message needs to be displayed.</param>
/// <param name="login">Called when a login dialog needs to be displayed.
/// You can interact with this dialog by calling Dialog.PostLogin() to post an answer or Dialog.Dismiss() to cancel this dialog.</param>
/// <param name="question">Called when a question dialog needs to be displayed.
/// You can interact with this dialog by calling Dialog.PostLogin() to post an answer or Dialog.Dismiss() to cancel this dialog.</param>
/// <param name="displayProgress">Called when a progress dialog needs to be displayed.</param>
/// <param name="updateProgress">Called when a progress dialog needs to be updated.</param>
public void SetDialogHandlers(DisplayError error, DisplayLogin login, DisplayQuestion question,
DisplayProgress displayProgress, UpdateProgress updateProgress)
{
......@@ -576,49 +571,18 @@ namespace LibVLCSharp.Shared
Native.LibVLCDialogSetCallbacks(NativeReference, _dialogCbsPtr, IntPtr.Zero);
}
/// <summary>
/// True if dialog handlers are set
/// </summary>
public bool DialogHandlersSet => _dialogCbsPtr != IntPtr.Zero;
public RendererDescription[] RendererList
{
get
{
// TODO: Move marshalling logic to generic MarshalUtils func
var discoverList = IntPtr.Zero;
var count = Native.LibVLCRendererDiscovererGetList(NativeReference, ref discoverList);
if (count == 0)
#if NETSTANDARD1_1 || NET40
return new RendererDescription[0];
#else
return Array.Empty<RendererDescription>();
#endif
var rendererDiscovererDescription = new RendererDescription[(int)count];
for (var i = 0; i < (int)count; i++)
{
var ptr = Marshal.ReadIntPtr(discoverList, i * IntPtr.Size);
var managedStruct = (RendererDescription)Marshal.PtrToStructure(ptr, typeof(RendererDescription));
rendererDiscovererDescription[i] = managedStruct;
}
Native.LibVLCRendererDiscovererReleaseList(discoverList, count);
return rendererDiscovererDescription;
}
}
public readonly struct RendererDescription
{
public string Name { get; }
public string LongName { get; }
public RendererDescription(string name, string longName)
{
Name = name;
LongName = longName;
}
}
/// <summary>
/// List of available renderers used to create RendererDiscoverer objects
/// </summary>
public RendererDescription[] RendererList => MarshalUtils.Retrieve(NativeReference, (nativeRef, arrayPtr) => Native.LibVLCRendererDiscovererGetList(nativeRef, ref arrayPtr),
MarshalUtils.PtrToStructure<RendererDescriptionStructure>,
m => m.Build(),
Native.LibVLCRendererDiscovererReleaseList);
/// <summary>
/// Code taken from Vlc.DotNet
......
......@@ -7,82 +7,46 @@ namespace LibVLCSharp.Shared
/// <summary>
/// libvlc v3 check
/// </summary>
public class MediaDiscoverer : Internal
public partial class MediaDiscoverer : Internal
{
MediaDiscovererEventManager _eventManager;
MediaList _mediaList;
readonly struct Native
{
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_discoverer_new")]
internal static extern IntPtr LibVLCMediaDiscovererNew(IntPtr libvlc, [MarshalAs(UnmanagedType.LPStr)] string name);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_discoverer_start")]
internal static extern int LibVLCMediaDiscovererStart(IntPtr mediaDiscoverer);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_discoverer_stop")]
internal static extern void LibVLCMediaDiscovererStop(IntPtr mediaDiscoverer);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_discoverer_release")]
internal static extern void LibVLCMediaDiscovererRelease(IntPtr mediaDiscoverer);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_discoverer_localized_name")]
internal static extern IntPtr LibVLCMediaDiscovererLocalizedName(IntPtr mediaDiscoverer);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_discoverer_event_manager")]
internal static extern IntPtr LibVLCMediaDiscovererEventManager(IntPtr mediaDiscoverer);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_discoverer_is_running")]
internal static extern int LibVLCMediaDiscovererIsRunning(IntPtr mediaDiscoverer);
[DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_media_discoverer_media_list")]
internal static extern IntPtr LibVLCMediaDiscovererMediaList(IntPtr discovererMediaList);
}
/// <summary>Category of a media discoverer</summary>
/// <remarks>libvlc_media_discoverer_list_get()</remarks>
public enum Category
{
/// <summary>devices, like portable music player</summary>
Devices = 0,
/// <summary>LAN/WAN services, like Upnp, SMB, or SAP</summary>
Lan = 1,
/// <summary>Podcasts</summary>
Podcasts = 2,
/// <summary>Local directories, like Video, Music or Pictures directories</summary>
Localdirs = 3
}
public readonly struct Description
{
internal Description(string name, string longName, Category category)
{
Name = name;
LongName = longName;
Category = category;
}
public string Name { get; }
public string LongName { get; }
public Category Category { get; }
}
public MediaDiscoverer(LibVLC libVLC, string name)
//v3 check. differen ctors
: base(() => Native.LibVLCMediaDiscovererNew(libVLC.NativeReference, name), Native.LibVLCMediaDiscovererRelease)
......@@ -190,4 +154,18 @@ namespace LibVLCSharp.Shared
base.Dispose(disposing);
}
}
/// <summary>Category of a media discoverer</summary>
/// <remarks>libvlc_media_discoverer_list_get()</remarks>
public enum MediaDiscovererCategory
{
/// <summary>devices, like portable music player</summary>
Devices = 0,
/// <summary>LAN/WAN services, like Upnp, SMB, or SAP</summary>
Lan = 1,
/// <summary>Podcasts</summary>
Podcasts = 2,
/// <summary>Local directories, like Video, Music or Pictures directories</summary>
Localdirs = 3
}
}
\ No newline at end of file
using System;
namespace LibVLCSharp.Shared
{
internal readonly struct MediaDiscovererDescriptionStructure
{
internal readonly IntPtr Name;
internal readonly IntPtr LongName;
internal readonly MediaDiscovererCategory Category;
}
/// <summary>
/// Description of a media discoverer
/// </summary>
public readonly struct MediaDiscovererDescription
{
internal MediaDiscovererDescription(string name, string longName, MediaDiscovererCategory category)
{
Name = name;
LongName = longName;
Category = category;
}
/// <summary>
/// Media discoverer description name
/// </summary>
public string Name { get; }
/// <summary>
/// Media discoverer description long name
/// </summary>
public string LongName { get; }
/// <summary>
/// Media discoverer category
/// </summary>
public MediaDiscovererCategory Category { get; }
}
}
\ No newline at end of file
using System;
namespace LibVLCSharp.Shared
{
internal readonly struct RendererDescriptionStructure
{
internal readonly IntPtr Name;
internal readonly IntPtr LongName;
}
/// <summary>
/// Renderer description
/// </summary>
public readonly struct RendererDescription
{
/// <summary>
/// Renderer Name
/// </summary>
public string Name { get; }
/// <summary>
/// Renderer long name
/// </summary>
public string LongName { get; }
internal RendererDescription(string name, string longName)
{
Name = name;
LongName = longName;
}
}
}
\ No newline at end of file
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