Commit 6bc292d3 authored by Martin Finkel's avatar Martin Finkel

Implemented MediaEventManager and WIP on MediaPlayerEventManager

parent e6bc3674
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using NUnit.Framework;
using VideoLAN.LibVLC;
namespace Bindings.Tests
{
[TestFixture]
public class EventManagerTests
{
[Test]
public void MetaChangedEventSubscribe()
{
var media = new Media(new Instance(), Path.GetTempFileName(), Media.FromType.FromPath);
var eventManager = media.EventManager;
var eventHandlerCalled = false;
const Media.MetadataType description = Media.MetadataType.Description;
eventManager.MetaChanged += (sender, args) =>
{
Assert.AreEqual(description, args.MetadataType);
eventHandlerCalled = true;
};
media.SetMeta(Media.MetadataType.Description, "test");
Assert.True(eventHandlerCalled);
}
[Test]
public void SubItemAdded()
{
var media = new Media(new Instance(), Path.GetTempFileName(), Media.FromType.FromPath);
//media.SubItems.
//TODO: Implement MediaList to test this.
}
string RealMediaPath
{
get
{
var dir = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
var binDir = Path.Combine(dir, "..\\..\\..\\");
var files = Directory.GetFiles(binDir);
return files.First();
}
}
[Test]
public void DurationChanged()
{
var media = new Media(new Instance(), RealMediaPath, Media.FromType.FromPath);
var called = false;
long duration = 0;
media.EventManager.DurationChanged += (sender, args) =>
{
called = true;
duration = args.Duration;
};
media.Parse();
Assert.True(called);
Assert.NotZero(duration);
}
[Test]
public void FreedMedia()
{
var media = new Media(new Instance(), RealMediaPath, Media.FromType.FromPath);
var eventCalled = false;
media.EventManager.MediaFreed += (sender, args) =>
{
eventCalled = true;
};
media.Dispose();
Assert.True(eventCalled);
}
[Test]
public void StateChanged()
{
var media = new Media(new Instance(), RealMediaPath, Media.FromType.FromPath);
var called = false;
media.EventManager.StateChanged += (sender, args) => called = true;
//TODO: implement MediaPlayer.cs
//mediaPlayer.SetMedia(media);
Assert.True(called);
}
[Test]
public void SubItemTreeAdded()
{
var media = new Media(new Instance(), RealMediaPath, Media.FromType.FromPath);
//TODO: Implement MediaList.cs
Assert.Fail();
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;
using VideoLAN.LibVLC;
......@@ -11,20 +12,17 @@ namespace VideoLAN.LibVLC
public struct Internal
{
[SuppressUnmanagedCodeSecurity]
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_event_attach")]
internal static extern int LibVLCEventAttach(IntPtr eventManager, EventType eventType, IntPtr callback,
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "libvlc_event_attach")]
internal static extern int LibVLCEventAttach(IntPtr eventManager, EventType eventType, EventCallback eventCallback,
IntPtr userData);
[SuppressUnmanagedCodeSecurity]
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_event_detach")]
internal static extern void LibVLCEventDetach(IntPtr eventManager, EventType eventType, IntPtr callback,
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "libvlc_event_detach")]
internal static extern void LibVLCEventDetach(IntPtr eventManager, EventType eventType, EventCallback eventCallback,
IntPtr userData);
}
public IntPtr NativeReference;
protected List<EventHandlerBase> Lambdas = new List<EventHandlerBase>();
protected EventManager(IntPtr ptr)
{
......@@ -34,85 +32,693 @@ namespace VideoLAN.LibVLC
NativeReference = ptr;
}
protected virtual void Unregister(EventHandlerBase eventHandler) { }
protected void AttachEvent(EventType eventType, EventCallback eventCallback)
{
if(Internal.LibVLCEventAttach(NativeReference, eventType, eventCallback, IntPtr.Zero) != 0)
throw new VLCException($"Could not attach event {eventType}");
}
protected void DetachEvent(EventType eventType, EventCallback eventCallback)
{
Internal.LibVLCEventDetach(NativeReference, eventType, eventCallback, IntPtr.Zero);
}
protected EventHandler Handle(EventType eventType, EventCallback eventCallback, LibVLCEvent libVLCEvent)
protected LibVLCEvent RetrieveEvent(IntPtr eventPtr)
{
var eventHandler = new EventHandler(this, eventType, eventCallback, libVLCEvent);
Lambdas.Add(eventHandler);
return eventHandler;
return Marshal.PtrToStructure<LibVLCEvent>(eventPtr);
}
}
//protected EventHandler Handle(EventType eventType, EventCallback eventCallback)
//{
//return Handle(eventType, eventCallback, )
//}
public class MediaEventManager : EventManager
{
readonly object _lock = new object();
public abstract class EventHandlerBase
EventHandler<MediaMetaChangedEventArgs> _mediaMetaChanged;
EventHandler<MediaParsedChangedEventArgs> _mediaParsedChanged;
EventHandler<MediaSubItemAddedEventArgs> _mediaSubItemAdded;
EventHandler<MediaDurationChangedEventArgs> _mediaDurationChanged;
EventHandler<MediaFreedEventArgs> _mediaFreed;
EventHandler<MediaStateChangedEventArgs> _mediaStateChanged;
EventHandler<MediaSubItemTreeAddedEventArgs> _mediaSubItemTreeAdded;
public MediaEventManager(IntPtr ptr) : base(ptr)
{
public LibVLCEvent LibVLCEvent { get; protected set; }
protected abstract void Unregister();
}
public class EventHandler : EventHandlerBase
public event EventHandler<MediaMetaChangedEventArgs> MetaChanged
{
add
{
lock (_lock)
{
_mediaMetaChanged += value;
AttachEvent(EventType.MediaMetaChanged, OnMetaChanged);
}
}
remove
{
lock (_lock)
{
_mediaMetaChanged -= value;
DetachEvent(EventType.MediaMetaChanged, OnMetaChanged);
}
}
}
public event EventHandler<MediaParsedChangedEventArgs> ParsedChanged
{
readonly IntPtr _eventCallbackPtr;
readonly EventType _eventType;
readonly EventManager _eventManager;
readonly IntPtr _eventStructPtr;
add
{
lock (_lock)
{
_mediaParsedChanged += value;
AttachEvent(EventType.MediaParsedChanged, OnParsedChanged);
}
}
remove
{
lock (_lock)
{
_mediaParsedChanged -= value;
DetachEvent(EventType.MediaParsedChanged, OnParsedChanged);
}
}
}
public EventHandler(EventManager eventManager, EventType eventType, EventCallback eventCallback, LibVLCEvent libVLCEvent)
public event EventHandler<MediaSubItemAddedEventArgs> SubItemAdded
{
add
{
_eventStructPtr = new IntPtr();
Marshal.StructureToPtr(libVLCEvent, _eventStructPtr, true);
_eventCallbackPtr = Marshal.GetFunctionPointerForDelegate(eventCallback);
lock (_lock)
{
_mediaSubItemAdded += value;
AttachEvent(EventType.MediaSubItemAdded, OnSubItemAdded);
}
}
remove
{
lock (_lock)
{
_mediaSubItemAdded -= value;
DetachEvent(EventType.MediaSubItemAdded, OnSubItemAdded);
}
}
}
if (Internal.LibVLCEventAttach(eventManager.NativeReference, eventType, _eventStructPtr, _eventCallbackPtr) != 0)
throw new VLCException();
public event EventHandler<MediaDurationChangedEventArgs> DurationChanged
{
add
{
lock (_lock)
{
_mediaDurationChanged += value;
AttachEvent(EventType.MediaDurationChanged, OnDurationChanged);
}
}
remove
{
lock (_lock)
{
_mediaDurationChanged -= value;
DetachEvent(EventType.MediaDurationChanged, OnDurationChanged);
}
}
}
_eventManager = eventManager;
_eventType = eventType;
LibVLCEvent = libVLCEvent;
public event EventHandler<MediaFreedEventArgs> MediaFreed
{
add
{
lock (_lock)
{
_mediaFreed += value;
AttachEvent(EventType.MediaFreed, OnMediaFreed);
}
}
remove
{
lock (_lock)
{
_mediaFreed -= value;
DetachEvent(EventType.MediaFreed, OnMediaFreed);
}
}
}
~EventHandler()
public event EventHandler<MediaStateChangedEventArgs> StateChanged
{
add
{
Internal.LibVLCEventDetach(_eventManager.NativeReference, _eventType, _eventStructPtr, _eventCallbackPtr);
lock (_lock)
{
_mediaStateChanged += value;
AttachEvent(EventType.MediaStateChanged, OnMediaStateChanged);
}
}
remove
{
lock (_lock)
{
_mediaStateChanged -= value;
DetachEvent(EventType.MediaStateChanged, OnMediaStateChanged);
}
}
}
protected override void Unregister()
public event EventHandler<MediaSubItemTreeAddedEventArgs> SubItemTreeAdded
{
add
{
_eventManager.Unregister(this);
lock (_lock)
{
_mediaSubItemTreeAdded += value;
AttachEvent(EventType.MediaSubItemTreeAdded, OnSubItemTreeAdded);
}
}
remove
{
lock (_lock)
{
_mediaSubItemTreeAdded -= value;
DetachEvent(EventType.MediaSubItemTreeAdded, OnSubItemTreeAdded);
}
}
}
}
public class MediaEventManager : EventManager
{
public MediaEventManager(IntPtr ptr) : base(ptr)
void OnSubItemTreeAdded(IntPtr ptr)
{
_mediaSubItemTreeAdded?.Invoke(this,
new MediaSubItemTreeAddedEventArgs(RetrieveEvent(ptr).Union.MediaSubItemTreeAdded.MediaInstance));
}
public EventHandler OnMetaChanged(EventCallback cb)
void OnMediaStateChanged(IntPtr ptr)
{
return Handle(EventType.MediaMetaChanged, cb, new LibVLCEvent
{
Type = EventType.MediaMetaChanged,
//Union = new LibVLCEvent.EventUnion
//{
// MediaMetaChanged = new LibVLCEvent.MediaMetaChanged
// {
// }
//}
});
_mediaStateChanged?.Invoke(this,
new MediaStateChangedEventArgs(RetrieveEvent(ptr).Union.MediaStateChanged.NewState));
}
void OnMediaFreed(IntPtr ptr)
{
_mediaFreed?.Invoke(this, new MediaFreedEventArgs(RetrieveEvent(ptr).Union.MediaFreed.MediaInstance));
}
void OnDurationChanged(IntPtr ptr)
{
_mediaDurationChanged?.Invoke(this,
new MediaDurationChangedEventArgs(RetrieveEvent(ptr).Union.MediaDurationChanged.NewDuration));
}
void OnSubItemAdded(IntPtr ptr)
{
_mediaSubItemAdded?.Invoke(this,
new MediaSubItemAddedEventArgs(RetrieveEvent(ptr).Union.MediaSubItemAdded.NewChild));
}
void OnParsedChanged(IntPtr ptr)
{
_mediaParsedChanged?.Invoke(this,
new MediaParsedChangedEventArgs(RetrieveEvent(ptr).Union.MediaParsedChanged.NewStatus));
}
void OnMetaChanged(IntPtr ptr)
{
_mediaMetaChanged?.Invoke(this,
new MediaMetaChangedEventArgs(RetrieveEvent(ptr).Union.MediaMetaChanged.MetaType));
}
}
public class MediaPlayerEventManager : EventManager
{
readonly object _lock = new object();
EventHandler<MediaPlayerMediaChangedEventArgs> _mediaPlayerMediaChanged;
EventHandler<EventArgs> _mediaPlayerNothingSpecial;
EventHandler<EventArgs> _mediaPlayerOpening;
EventHandler<MediaPlayerBufferingEventArgs> _mediaPlayerBuffering;
EventHandler<EventArgs> _mediaPlayerPlaying;
EventHandler<EventArgs> _mediaPlayerPaused;
EventHandler<EventArgs> _mediaPlayerStopped;
EventHandler<EventArgs> _mediaPlayerForward;
EventHandler<EventArgs> _mediaPlayerBackward;
EventHandler<EventArgs> _mediaPlayerEndReached;
EventHandler<EventArgs> _mediaPlayerEncounteredError;
EventHandler<MediaPlayerTimeChangedEventArgs> _mediaPlayerTimeChanged;
EventHandler<MediaPlayerPositionChangedEventArgs> _mediaPlayerPositionChanged;
EventHandler<MediaPlayerSeekableChangedEventArgs> _mediaPlayerSeekableChanged;
EventHandler<MediaPlayerPausableChangedEventArgs> _mediaPlayerPausableChanged;
EventHandler<MediaPlayerTitleChangedEventArgs> _mediaPlayerTitleChanged;
EventHandler<MediaPlayerChapterChangedEventArgs> _mediaPlayerChapterChanged; //vlc 3
EventHandler<MediaPlayerSnapshotTakenEventArgs> _mediaPlayerSnapshotTaken;
EventHandler<MediaPlayerLengthChangedEventArgs> _mediaPlayerLengthChanged;
EventHandler<MediaPlayerVoutEventArgs> _mediaPlayerVout;
EventHandler<MediaPlayerScrambledChangedEventArgs> _mediaPlayerScrambledChanged;
EventHandler<MediaPlayerESAddedEventArgs> _mediaPlayerESAdded; // vlc 3
EventHandler<MediaPlayerESDeletedEventArgs> _mediaPlayerESDeleted; // vlc 3
EventHandler<MediaPlayerESSelectedEventArgs> _mediaPlayerESSelected; // vlc 3
EventHandler<MediaPlayerAudioDeviceEventArgs> _mediaPlayerAudioDevice; // vlc 3
EventHandler<EventArgs> _mediaPlayerCorked; // vlc 2.2
EventHandler<EventArgs> _mediaPlayerUncorked; // vlc 2.2
EventHandler<EventArgs> _mediaPlayerMuted; // vlc 2.2
EventHandler<EventArgs> _mediaPlayerUnmuted; // vlc 2.2
EventHandler<EventArgs> _mediaPlayerAudioVolume; // vlc 2.2
public MediaPlayerEventManager(IntPtr ptr) : base(ptr)
{
}
public event EventHandler<MediaPlayerMediaChangedEventArgs> MediaChanged
{
add
{
lock (_lock)
{
_mediaPlayerMediaChanged += value;
AttachEvent(EventType.MediaPlayerMediaChanged, OnMediaChanged);
}
}
remove
{
lock (_lock)
{
_mediaPlayerMediaChanged -= value;
DetachEvent(EventType.MediaPlayerMediaChanged, OnMediaChanged);
}
}
}
public event EventHandler<EventArgs> NothingSpecial
{
add
{
lock (_lock)
{
_mediaPlayerNothingSpecial += value;
AttachEvent(EventType.MediaPlayerNothingSpecial, OnNothingSpecial);
}
}
remove
{
lock (_lock)
{
_mediaPlayerNothingSpecial -= value;
DetachEvent(EventType.MediaPlayerNothingSpecial, OnNothingSpecial);
}
}
}
public event EventHandler<EventArgs> Opening
{
add
{
lock (_lock)
{
_mediaPlayerOpening += value;
AttachEvent(EventType.MediaPlayerOpening, OnOpening);
}
}
remove
{
lock (_lock)
{
_mediaPlayerOpening -= value;
DetachEvent(EventType.MediaPlayerOpening, OnOpening);
}
}
}
public event EventHandler<MediaPlayerBufferingEventArgs> Buffering
{
add
{
lock (_lock)
{
_mediaPlayerBuffering += value;
AttachEvent(EventType.MediaPlayerBuffering, OnBuffering);
}
}
remove
{
lock (_lock)
{
_mediaPlayerBuffering -= value;
DetachEvent(EventType.MediaPlayerBuffering, OnBuffering);
}
}
}
public event EventHandler<EventArgs> Playing
{
add
{
lock (_lock)
{
_mediaPlayerPlaying += value;
AttachEvent(EventType.MediaPlayerPlaying, OnPlaying);
}
}
remove
{
lock (_lock)
{
_mediaPlayerPlaying -= value;
DetachEvent(EventType.MediaPlayerPlaying, OnPlaying);
}
}
}
public event EventHandler<EventArgs> Paused
{
add
{
lock (_lock)
{
_mediaPlayerPaused += value;
AttachEvent(EventType.MediaPlayerPaused, OnPaused);
}
}
remove
{
lock (_lock)
{
_mediaPlayerPaused -= value;
DetachEvent(EventType.MediaPlayerPaused, OnPaused);
}
}
}
public event EventHandler<EventArgs> Stopped
{
add
{
lock (_lock)
{
_mediaPlayerStopped += value;
AttachEvent(EventType.MediaPlayerStopped, OnStopped);
}
}
remove
{
lock (_lock)
{
_mediaPlayerStopped -= value;
DetachEvent(EventType.MediaPlayerStopped, OnStopped);
}
}
}
public event EventHandler<EventArgs> Forward
{
add
{
lock (_lock)
{
_mediaPlayerForward += value;
AttachEvent(EventType.MediaPlayerForward, OnForward);
}
}
remove
{
lock (_lock)
{
_mediaPlayerForward -= value;
DetachEvent(EventType.MediaPlayerForward, OnForward);
}
}
}
public event EventHandler<EventArgs> Backward
{
add
{
lock (_lock)
{
_mediaPlayerBackward += value;
AttachEvent(EventType.MediaPlayerBackward, OnBackward);
}
}
remove
{
lock (_lock)
{
_mediaPlayerBackward -= value;
DetachEvent(EventType.MediaPlayerBackward, OnBackward);
}
}
}
public event EventHandler<EventArgs> EndReached
{
add
{
lock (_lock)
{
_mediaPlayerEndReached += value;
AttachEvent(EventType.MediaPlayerEndReached, OnEndReached);
}
}
remove
{
lock (_lock)
{
_mediaPlayerEndReached -= value;
DetachEvent(EventType.MediaPlayerEndReached, OnEndReached);
}
}
}
public event EventHandler<EventArgs> EncounteredError
{
add
{
lock (_lock)
{
_mediaPlayerEncounteredError += value;
AttachEvent(EventType.MediaPlayerEncounteredError, OnEncounteredError);
}
}
remove
{
lock (_lock)
{
_mediaPlayerEncounteredError -= value;
DetachEvent(EventType.MediaPlayerEncounteredError, OnEncounteredError);
}
}
}
public event EventHandler<MediaPlayerTimeChangedEventArgs> TimeChanged
{
add
{
lock (_lock)
{
_mediaPlayerTimeChanged += value;
AttachEvent(EventType.MediaPlayerTimeChanged, OnTimeChanged);
}
}
remove
{
lock (_lock)
{
_mediaPlayerTimeChanged -= value;
DetachEvent(EventType.MediaPlayerTimeChanged, OnTimeChanged);
}
}
}
public event EventHandler<MediaPlayerPositionChangedEventArgs> PositionChanged
{
add
{
lock (_lock)
{
_mediaPlayerPositionChanged += value;
AttachEvent(EventType.MediaPlayerPositionChanged, OnPositionChanged);
}
}
remove
{
lock (_lock)
{
_mediaPlayerPositionChanged -= value;
DetachEvent(EventType.MediaPlayerPositionChanged, OnPositionChanged);
}
}
}
public event EventHandler<MediaPlayerSeekableChangedEventArgs> SeekableChanged
{
add
{
lock (_lock)
{
_mediaPlayerSeekableChanged += value;
AttachEvent(EventType.MediaPlayerSeekableChanged, OnSeekableChanged);
}
}
remove
{
lock (_lock)
{
_mediaPlayerSeekableChanged -= value;
DetachEvent(EventType.MediaPlayerSeekableChanged, OnSeekableChanged);
}
}
}
public event EventHandler<MediaPlayerPausableChangedEventArgs> PausableChanged
{
add
{
lock (_lock)
{
_mediaPlayerPausableChanged += value;
AttachEvent(EventType.MediaPlayerPausableChanged, OnPausableChanged);
}
}
remove
{
lock (_lock)
{