MarshalExtensions.cs 7.29 KB
Newer Older
1
using LibVLCSharp.Shared.Structures;
2
using System;
Martin Finkel's avatar
Martin Finkel committed
3
using System.Collections.Generic;
4 5
using System.Runtime.InteropServices;
using System.Text;
6 7 8 9 10 11

namespace LibVLCSharp.Shared.Helpers
{
    internal static class MarshalExtensions
    {
        /// <summary>
Martin Finkel's avatar
Martin Finkel committed
12
        /// Helper method that creates a user friendly type from the internal interop structure.
13 14 15
        /// </summary>
        /// <param name="s">AudioOutputDescriptionStructure from interop</param>
        /// <returns>public AudioOutputDescription to be consumed by the user</returns>
16
        internal static AudioOutputDescription Build(this AudioOutputDescriptionStructure s) => 
Martin Finkel's avatar
Martin Finkel committed
17
            new AudioOutputDescription(s.Name.FromUtf8(), s.Description.FromUtf8());
18 19

        /// <summary>
Martin Finkel's avatar
Martin Finkel committed
20
        /// Helper method that creates a user friendly type from the internal interop structure.
21 22 23
        /// </summary>
        /// <param name="s">AudioOutputDeviceStructure from interop</param>
        /// <returns>public AudioOutputDevice to be consumed by the user</returns>
24
        internal static AudioOutputDevice Build(this AudioOutputDeviceStructure s) =>
Martin Finkel's avatar
Martin Finkel committed
25
            new AudioOutputDevice(s.DeviceIdentifier.FromUtf8(), s.Description.FromUtf8());
26 27

        /// <summary>
Martin Finkel's avatar
Martin Finkel committed
28
        /// Helper method that creates a user friendly type from the internal interop structure.
29 30 31
        /// </summary>
        /// <param name="s">ModuleDescriptionStructure from interop</param>
        /// <returns>public ModuleDescription to be consumed by the user</returns>
32
        internal static ModuleDescription Build(this ModuleDescriptionStructure s) =>
Martin Finkel's avatar
Martin Finkel committed
33
            new ModuleDescription(s.Name.FromUtf8(), s.ShortName.FromUtf8(), s.LongName.FromUtf8(), s.Help.FromUtf8());
34 35

        /// <summary>
Martin Finkel's avatar
Martin Finkel committed
36
        /// Helper method that creates a user friendly type from the internal interop structure.
37 38 39 40
        /// </summary>
        /// <param name="s">TrackDescriptionStructure from interop</param>
        /// <returns>public TrackDescription to be consumed by the user</returns>
        internal static TrackDescription Build(this TrackDescriptionStructure s) =>
Martin Finkel's avatar
Martin Finkel committed
41
            new TrackDescription(s.Id, s.Name.FromUtf8());
42 43

        /// <summary>
Martin Finkel's avatar
Martin Finkel committed
44
        /// Helper method that creates a user friendly type from the internal interop structure.
45
        /// </summary>
Martin Finkel's avatar
Martin Finkel committed
46 47
        /// <param name="s">MediaSlaveStructure from interop</param>
        /// <returns>public MediaSlave to be consumed by the user</returns>
Martin Finkel's avatar
Martin Finkel committed
48 49
        internal static MediaSlave Build(this MediaSlaveStructure s) => 
            new MediaSlave(s.Uri.FromUtf8(), s.Type, s.Priority);
Martin Finkel's avatar
Martin Finkel committed
50 51

        /// <summary>
Martin Finkel's avatar
Martin Finkel committed
52
        /// Helper method that creates a user friendly type from the internal interop structure.
Martin Finkel's avatar
Martin Finkel committed
53 54 55
        /// </summary>
        /// <param name="s">TrackDescriptionStructure from interop</param>
        /// <returns>public TrackDescription to be consumed by the user</returns>
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
        internal static MediaTrack Build(this MediaTrackStructure s)
        {
            AudioTrack audioTrack = default;
            VideoTrack videoTrack = default;
            SubtitleTrack subtitleTrack = default;

            switch (s.TrackType)
            {
                case TrackType.Audio:
                    audioTrack = MarshalUtils.PtrToStructure<AudioTrack>(s.TrackData);
                    break;
                case TrackType.Video:
                    videoTrack = MarshalUtils.PtrToStructure<VideoTrack>(s.TrackData);
                    break;
                case TrackType.Text:
                    subtitleTrack = MarshalUtils.PtrToStructure<SubtitleTrackStructure>(s.TrackData).Build();
                    break;
                case TrackType.Unknown:
                    break;
            }

            return new MediaTrack(s.Codec, 
                s.OriginalFourcc, 
                s.Id, 
                s.TrackType, 
                s.Profile, 
                s.Level, 
                new MediaTrackData(audioTrack, videoTrack, subtitleTrack), s.Bitrate,
Martin Finkel's avatar
Martin Finkel committed
84 85
                s.Language.FromUtf8(),
                s.Description.FromUtf8());
86 87 88 89 90 91 92
        }
        
        /// <summary>
        /// Helper method that creates a user friendly type from the internal interop structure.
        /// </summary>
        /// <param name="s">SubtitleTrackStructure from interop</param>
        /// <returns>public SubtitleTrack to be consumed by the user</returns>
Martin Finkel's avatar
Martin Finkel committed
93
        internal static SubtitleTrack Build(this SubtitleTrackStructure s) => new SubtitleTrack(s.Encoding.FromUtf8());
Martin Finkel's avatar
Martin Finkel committed
94 95 96 97 98 99 100

        /// <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) =>
Martin Finkel's avatar
Martin Finkel committed
101
            new MediaDiscovererDescription(s.Name.FromUtf8(), s.LongName.FromUtf8(), s.Category);
Martin Finkel's avatar
Martin Finkel committed
102 103 104 105 106 107

        /// <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>
Martin Finkel's avatar
Martin Finkel committed
108 109
        internal static RendererDescription Build(this RendererDescriptionStructure s) => 
            new RendererDescription(s.Name.FromUtf8(), s.LongName.FromUtf8());
110

Martin Finkel's avatar
Martin Finkel committed
111 112 113 114 115
        /// <summary>
        /// Helper method that marshals a UTF16 managed string to a UTF8 native string ptr
        /// </summary>
        /// <param name="str">the managed string to marshal to native</param>
        /// <returns>a ptr to the UTF8 string that needs to be freed after use</returns>
Martin Finkel's avatar
Martin Finkel committed
116 117
        internal static IntPtr ToUtf8(this string str)
        {
Martin Finkel's avatar
Martin Finkel committed
118
            if (str == null)
Martin Finkel's avatar
Martin Finkel committed
119 120
                return IntPtr.Zero;

121 122 123 124 125 126 127 128 129 130 131 132 133 134
            byte[] bytes = Encoding.UTF8.GetBytes(str);
            var nativeString = Marshal.AllocHGlobal(bytes.Length + 1);
            try
            {
                Marshal.Copy(bytes, 0, nativeString, bytes.Length);
                Marshal.WriteByte(nativeString, bytes.Length, 0);
            }
            catch (Exception)
            {
                Marshal.FreeHGlobal(nativeString);
                throw;
            }

            return nativeString;
Martin Finkel's avatar
Martin Finkel committed
135 136
        }

Martin Finkel's avatar
Martin Finkel committed
137 138 139 140 141 142 143
        /// <summary>
        /// Helper method that mashals a UTF8 native string ptr to a UTF16 managed string.
        /// Optionally frees the native string ptr
        /// </summary>
        /// <param name="nativeString">the native string to marshal to managed</param>
        /// <param name="libvlcFree">frees the native pointer of the libvlc string (use only for char*)</param>
        /// <returns>a managed UTF16 string</returns>
Martin Finkel's avatar
Martin Finkel committed
144 145 146 147 148
        internal static string FromUtf8(this IntPtr nativeString, bool libvlcFree = false)
        {
            if (nativeString == IntPtr.Zero)
                return null;

149 150 151
            var length = 0;

            while (Marshal.ReadByte(nativeString, length) != 0)
Martin Finkel's avatar
Martin Finkel committed
152
            {
153
                length++;
Martin Finkel's avatar
Martin Finkel committed
154 155
            }

156 157
            byte[] buffer = new byte[length];
            Marshal.Copy(nativeString, buffer, 0, buffer.Length);
Martin Finkel's avatar
Martin Finkel committed
158 159
            if (libvlcFree)
                MarshalUtils.LibVLCFree(ref nativeString);
160
            return Encoding.UTF8.GetString(buffer, 0, buffer.Length);
Martin Finkel's avatar
Martin Finkel committed
161
        }
162 163
    }
}