internal T GetInteropDelegate <T>() { string vlcFunctionName = null; try { #if NETSTANDARD1_3 var attrs = typeof(T).GetTypeInfo().GetCustomAttributes(typeof(LibVlcFunctionAttribute), false).ToArray(); #else var attrs = typeof(T).GetCustomAttributes(typeof(LibVlcFunctionAttribute), false); #endif if (attrs.Length == 0) { throw new Exception("Could not find the LibVlcFunctionAttribute."); } var attr = (LibVlcFunctionAttribute)attrs[0]; vlcFunctionName = attr.FunctionName; lock (this._myInteropDelegatesLockObject) { if (myInteropDelegates.ContainsKey(vlcFunctionName)) { return((T)myInteropDelegates[attr.FunctionName]); } var procAddress = Win32Interops.GetProcAddress(myLibVlcDllHandle, attr.FunctionName); if (procAddress == IntPtr.Zero) { throw new Win32Exception(); } var delegateForFunctionPointer = MarshalHelper.GetDelegateForFunctionPointer <T>(procAddress); myInteropDelegates[attr.FunctionName] = delegateForFunctionPointer; return(delegateForFunctionPointer); } } catch (Win32Exception e) { throw new MissingMethodException(string.Format("The address of the function '{0}' does not exist in libvlc library.", vlcFunctionName), e); } }
/// <summary> /// Register callbacks in order to handle VLC dialogs. LibVLC 3.0.0 and later. /// </summary> public void SetDialogCallbacks(DialogCallbacks?callbacks, IntPtr data) { if (VlcVersionNumber.Major < 3) { throw new InvalidOperationException($"You need VLC version 3.0 or higher to be able to use {nameof(SetDialogCallbacks)}"); } if (this.dialogCallbacks.HasValue) { Marshal.FreeHGlobal(this.dialogCallbacksPointer); this.dialogCallbacksPointer = IntPtr.Zero; } this.dialogCallbacks = callbacks; if (this.dialogCallbacks.HasValue) { this.dialogCallbacksPointer = Marshal.AllocHGlobal(MarshalHelper.SizeOf <DialogCallbacks>()); Marshal.StructureToPtr(this.dialogCallbacks.Value, this.dialogCallbacksPointer, false); } myLibraryLoader.GetInteropDelegate <SetDialogCallbacks>().Invoke(this.myVlcInstance, this.dialogCallbacksPointer, data); }
public MediaTrack[] GetMediaTracks(VlcMediaInstance mediaInstance) { if (mediaInstance == IntPtr.Zero) { throw new ArgumentException("Media instance is not initialized."); } var cpt = GetInteropDelegate <GetMediaTracks>().Invoke(mediaInstance, out var fullBuffer); if (cpt <= 0) { return(new MediaTrack[0]); } try { var result = new MediaTrack[cpt]; for (int index = 0; index < cpt; index++) { var current = MarshalHelper.PtrToStructure <LibvlcMediaTrackT>(Marshal.ReadIntPtr(fullBuffer, index * MarshalHelper.SizeOf <IntPtr>())); TrackInfo trackInfo = null; switch (current.Type) { case MediaTrackTypes.Audio: var audio = MarshalHelper.PtrToStructure <LibvlcAudioTrackT>(current.TypedTrack); trackInfo = new AudioTrack { Channels = audio.Channels, Rate = audio.Rate }; break; case MediaTrackTypes.Video: var video = MarshalHelper.PtrToStructure <LibvlcVideoTrackT>(current.TypedTrack); trackInfo = new VideoTrack { Height = video.Height, Width = video.Width, SarNum = video.SarNum, SarDen = video.SarDen, FrameRateNum = video.FrameRateNum, FrameRateDen = video.FrameRateDen, Orientation = video.Orientation, Projection = video.Projection, Pose = video.Pose }; break; case MediaTrackTypes.Text: var text = MarshalHelper.PtrToStructure <LibvlcSubtitleTrackT>(current.TypedTrack); trackInfo = new SubtitleTrack { Encoding = Utf8InteropStringConverter.Utf8InteropToString(text.Encoding) }; break; } result[index] = new MediaTrack { CodecFourcc = current.Codec, OriginalFourcc = current.OriginalFourCC, Id = current.Id, Type = current.Type, Profile = current.Profile, Level = current.Level, TrackInfo = trackInfo, Bitrate = current.Bitrate, Language = Utf8InteropStringConverter.Utf8InteropToString(current.Language), Description = Utf8InteropStringConverter.Utf8InteropToString(current.Description) }; } return(result); } finally { GetInteropDelegate <ReleaseMediaTracks>().Invoke(fullBuffer, cpt); } }