NativeLibVlc.cs
Jump to navigation
Jump to search
/***************************************************************************** * NativeLibVlc.cs: NativeLibVlc class definition ***************************************************************************** * Copyright (C) 2006 Chris Meadowcroft * * Authors: Chris Meadowcroft * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using Microsoft.Win32; namespace VLanControl { internal enum ObjectType : int { VLC_OBJECT_ROOT = (-1), VLC_OBJECT_VLC = (-2), VLC_OBJECT_MODULE = (-3), VLC_OBJECT_INTF = (-4), VLC_OBJECT_PLAYLIST = (-5), VLC_OBJECT_ITEM = (-6), VLC_OBJECT_INPUT = (-7), VLC_OBJECT_DECODER = (-8), VLC_OBJECT_VOUT = (-9), VLC_OBJECT_AOUT = (-10), VLC_OBJECT_SOUT = (-11), VLC_OBJECT_HTTPD = (-12), VLC_OBJECT_PACKETIZER = (-13), VLC_OBJECT_ENCODER = (-14), VLC_OBJECT_DIALOGS = (-15), VLC_OBJECT_VLM = (-16), VLC_OBJECT_ANNOUNCE = (-17), VLC_OBJECT_DEMUX = (-18), VLC_OBJECT_ACCESS = (-19), VLC_OBJECT_STREAM = (-20), VLC_OBJECT_OPENGL = (-21), VLC_OBJECT_FILTER = (-22), VLC_OBJECT_VOD = (-23), VLC_OBJECT_SPU = (-24), VLC_OBJECT_TLS = (-25), VLC_OBJECT_SD = (-26), VLC_OBJECT_XML = (-27), VLC_OBJECT_OSDMENU = (-28), VLC_OBJECT_STATS = (-29), VLC_OBJECT_HTTPD_HOST = (-30), VLC_OBJECT_GENERIC = (-666), } internal enum VlcError : int { Success = -0, NoMem = -1, Thread = -2, Timeout = -3, NoMod = -10, NoObj = -20, BadObj = -21, NoVar = -30, BadVar = -31, Exit = -255, Generic = -666, Exception = -998, NoInit = -999, }; internal enum InputState : int { INIT_S = 0, OPENING_S = 1, BUFFERING_S = 2, PLAYING_S = 3, PAUSE_S = 4, END_S = 5, ERROR_S = 6, } internal class NativeLibVlc : IDisposable { #region private vlc enums enum Mode : int { Insert = 0x01, Replace = 0x02, Append = 0x04, Go = 0x08, CheckInsert = 0x10 }; public const Int32 EndOfPlaylist = -666; [Flags] enum ObjectSearchMode : int { FIND_PARENT = 0x0001, FIND_CHILD = 0x0002, FIND_ANYWHERE = 0x0003, FIND_STRICT = 0x0010, } [Flags] enum VarFlags : int { /** \defgroup var_flags Additive flags * These flags are added to the type field of the variable. Most as a result of * a __var_Change() call, but some may be added at creation time * @{ */ VLC_VAR_HASCHOICE = 0x0100, VLC_VAR_HASMIN = 0x0200, VLC_VAR_HASMAX = 0x0400, VLC_VAR_HASSTEP = 0x0800, VLC_VAR_ISLIST = 0x1000, VLC_VAR_ISCOMMAND = 0x2000, VLC_VAR_ISCONFIG = 0x2000, /** Creation flag */ VLC_VAR_DOINHERIT = 0x8000, /** * \defgroup var_action Variable actions * These are the different actions that can be used with __var_Change(). * The parameters given are the meaning of the two last parameters of * __var_Change() when this action is being used. * @{ */ /** * Set the minimum value of this variable * \param p_val The new minimum value * \param p_val2 Unused */ VLC_VAR_SETMIN = 0x0010, /** * Set the maximum value of this variable * \param p_val The new maximum value * \param p_val2 Unused */ VLC_VAR_SETMAX = 0x0011, VLC_VAR_SETSTEP = 0x0012, /** * Set the value of this variable without triggering any callbacks * \param p_val The new value * \param p_val2 Unused */ VLC_VAR_SETVALUE = 0x0013, VLC_VAR_SETTEXT = 0x0014, VLC_VAR_GETTEXT = 0x0015, VLC_VAR_ADDCHOICE = 0x0020, VLC_VAR_DELCHOICE = 0x0021, VLC_VAR_CLEARCHOICES = 0x0022, VLC_VAR_SETDEFAULT = 0x0023, VLC_VAR_GETCHOICES = 0x0024, VLC_VAR_FREECHOICES = 0x0025, VLC_VAR_GETLIST = 0x0026, VLC_VAR_FREELIST = 0x0027, VLC_VAR_CHOICESCOUNT = 0x0028, VLC_VAR_INHERITVALUE = 0x0030, VLC_VAR_TRIGGER_CALLBACKS = 0x0035, } enum playlist_command : int { PLAYLIST_PLAY = 0, /**< No arg. res=can fail*/ PLAYLIST_AUTOPLAY = 1, /**< No arg. res=cant fail*/ PLAYLIST_VIEWPLAY = 2, /**< arg1= int, arg2= playlist_item_t*,*/ /** arg3 = playlist_item_t* , res=can fail */ PLAYLIST_ITEMPLAY = 3, /** <arg1 = playlist_item_t * , res=can fail */ PLAYLIST_PAUSE = 4, /**< No arg res=can fail*/ PLAYLIST_STOP = 5, /**< No arg res=can fail*/ PLAYLIST_SKIP = 6, /**< arg1=int, res=can fail*/ PLAYLIST_GOTO = 7, /**< arg1=int res=can fail */ PLAYLIST_VIEWGOTO = 8 /**< arg1=int res=can fail */ } #endregion #region private vlc structs [StructLayout(LayoutKind.Sequential)] struct libvlc_exception_t { public Int32 b_raised; public IntPtr psz_message; public void Init() { libvlc_exception_init(out this); } public bool WasExceptionRaised() { if(0 != libvlc_exception_raised(ref this)) { libvlc_exception_clear(ref this); return true; } return false; } } [StructLayout(LayoutKind.Sequential)] struct libvlc_instance_t { public IntPtr p_vlc; public IntPtr p_playlist; public IntPtr p_vlm; public Int32 i_vlc_id; public libvlc_instance_t(IntPtr vlc, IntPtr playlist, int vlcHandle) { this.p_vlc = vlc; this.p_playlist = playlist; this.p_vlm = IntPtr.Zero; this.i_vlc_id = vlcHandle; } } [StructLayout(LayoutKind.Sequential)] struct vlc_list_t { public Int32 i_count; public IntPtr p_values; public IntPtr pi_types; } [StructLayout( LayoutKind.Explicit )] struct vlc_value_t { [FieldOffset( 0 )] public Int32 i_int; [FieldOffset( 0 )] public Int32 b_bool; [FieldOffset( 0 )][MarshalAs(UnmanagedType.R4)] public float f_float; [FieldOffset( 0 )] public IntPtr psz_string; [FieldOffset( 0 )] public IntPtr p_address; [FieldOffset( 0 )] public IntPtr p_object; [FieldOffset( 0 )] public IntPtr p_list; [FieldOffset( 0 )][MarshalAs(UnmanagedType.I8)] public Int64 i_time; [FieldOffset( 0 )] public IntPtr psz_name; [FieldOffset( 4 )] public Int32 i_object_id; } [StructLayout(LayoutKind.Sequential)] struct playlist_t_begin { public Int32 i_index; public Int32 i_enabled; public Int32 i_size; } #endregion #region vlc api interop [DllImport("libvlc")] static extern int VLC_Create(); [DllImport("libvlc")] static extern VlcError VLC_Init(int iVLC, int Argc, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)]string[] Argv); [DllImport("libvlc")] static extern string VLC_Version(); [DllImport("libvlc")] static extern VlcError VLC_CleanUp(int iVLC); [DllImport("libvlc")] static extern VlcError VLC_Destroy(int iVLC); [DllImport("libvlc")] static extern string VLC_Error(int i_err); [DllImport("libvlc")] static extern IntPtr vlc_current_object(int i_object); [DllImport("libvlc")] static extern IntPtr __vlc_object_find(IntPtr p_vlc, ObjectType objectType, ObjectSearchMode mode); [DllImport("libvlc")] static extern void __vlc_object_release(IntPtr p_vlc); [DllImport("libvlc")] static extern VlcError __var_Set(IntPtr p_vlc, String name, vlc_value_t value); [DllImport("libvlc")] static extern VlcError __var_Get(IntPtr p_this, String name, ref vlc_value_t value); [DllImport("libvlc")] static extern VlcError __var_Change(IntPtr p_this, String name, VarFlags varFlags, ref vlc_value_t value, ref vlc_value_t value2); const int AOUT_VOLUME_MAX = 1024; const int VOLUME_MAX = 200; [DllImport("libvlc")] static extern VlcError __aout_VolumeGet(IntPtr p_vlc, ref Int16 volume); [DllImport("libvlc")] static extern VlcError __aout_VolumeSet(IntPtr p_vlc, Int16 volume); [DllImport("libvlc")] static extern VlcError __aout_VolumeMute(IntPtr p_vlc, IntPtr alwaysNull); [DllImport("libvlc")] static extern void libvlc_exception_init(out libvlc_exception_t p_exception); [DllImport("libvlc")] static extern Int32 libvlc_exception_raised(ref libvlc_exception_t p_exception); [DllImport("libvlc")] static extern void libvlc_exception_clear(ref libvlc_exception_t p_exception); [DllImport("libvlc")] static extern void libvlc_playlist_play(ref libvlc_instance_t libvlc, Int32 id, Int32 optionsCount, IntPtr optionsAlwaysNull, ref libvlc_exception_t p_exception); [DllImport("libvlc")] static extern IntPtr libvlc_playlist_get_input(ref libvlc_instance_t libvlc, ref libvlc_exception_t p_exception); [DllImport("libvlc")] static extern void libvlc_input_free(IntPtr p_input); [DllImport("libvlc")] static extern int libvlc_video_get_width(IntPtr p_input, ref libvlc_exception_t p_exception); [DllImport("libvlc")] static extern int libvlc_video_get_height(IntPtr p_input, ref libvlc_exception_t p_exception); [DllImport("libvlc", CallingConvention=CallingConvention.Cdecl)] static extern VlcError playlist_LockControl(IntPtr p_playlist, playlist_command i_query); [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)] static extern VlcError playlist_LockControl(IntPtr p_playlist, playlist_command i_query, Int32 arg1); [DllImport("libvlc")] static extern VlcError playlist_Clear(IntPtr p_playlist); [DllImport("libvlc")] static extern VlcError playlist_AddExt(IntPtr p_playlist, String mrl, String mrlDuplicate, Mode mode, Int32 pos, Int64 mtime_t, [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)]string[] Options, int OptionsCount); const int DEFAULT_CHAN = 1; [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)] static extern void __vout_OSDMessage(IntPtr p_input, int i_channel, String message); #endregion public NativeLibVlc() { vlcInstallDirectory = QueryVlcInstallPath(); } #region IDisposable public void Dispose() { if(vlcHandle != -1) { try { VideoOutput = null; VLC_CleanUp(vlcHandle); VLC_Destroy(vlcHandle); } catch { } } vlcHandle = -1; } #endregion #region internal Vlc interop helper classes internal class VlcObject : IDisposable { IntPtr vlc = IntPtr.Zero; IntPtr subObject = IntPtr.Zero; bool isDisposed; public VlcObject(int vlcHandle, ObjectType objectType) { vlc = vlc_current_object(vlcHandle); if(IntPtr.Zero != vlc) { if(objectType == ObjectType.VLC_OBJECT_VLC) { subObject = vlc; } else { subObject = __vlc_object_find(vlc, objectType, ObjectSearchMode.FIND_CHILD); } } } public IntPtr Vlc { get { return this.vlc; } } public IntPtr SubObject { get { return this.subObject; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if(!this.isDisposed) { this.isDisposed = true; if((IntPtr.Zero != subObject) && (subObject != vlc)) { __vlc_object_release(subObject); } if(IntPtr.Zero != vlc) { __vlc_object_release(vlc); } } } protected bool IsDisposed { get { return this.isDisposed; } } ~VlcObject() { Dispose(false); } } private class VlcPlaylistObject : VlcObject { public libvlc_instance_t libvlc; public libvlc_exception_t exception; public VlcPlaylistObject(int vlcHandle) : base(vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST) { if(this.SubObject != IntPtr.Zero) { this.libvlc = new libvlc_instance_t(this.Vlc, this.SubObject, vlcHandle); this.exception.Init(); } } } #endregion #region public Vlc interop helper functions public VlcObject OpenVlcObject(ObjectType objectType) { return new VlcObject(this.vlcHandle, objectType); } public int GetVlcObjectInt(ObjectType objectType, String propertyName, int errorReturn) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, objectType)) { vlc_value_t intValue = new vlc_value_t(); if((vobj.SubObject != IntPtr.Zero) && (VlcError.Success == __var_Get(vobj.SubObject, propertyName, ref intValue))) { return intValue.i_int; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; } return errorReturn; } public VlcError SetVlcObjectInt(ObjectType objectType, String propertyName, int value) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, objectType)) { if(vobj.SubObject != IntPtr.Zero) { vlc_value_t intValue = new vlc_value_t(); intValue.i_int = value; return __var_Set(vobj.SubObject, propertyName, intValue); } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; } return VlcError.NoObj; } public long GetVlcObjectLong(ObjectType objectType, String propertyName, long errorReturn) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, objectType)) { vlc_value_t longValue = new vlc_value_t(); if((vobj.SubObject != IntPtr.Zero) && (VlcError.Success == __var_Get(vobj.SubObject, propertyName, ref longValue))) { return longValue.i_time; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; } return errorReturn; } public VlcError SetVlcObjectLong(ObjectType objectType, String propertyName, long value) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, objectType)) { if(vobj.SubObject != IntPtr.Zero) { vlc_value_t longValue = new vlc_value_t(); longValue.i_time = value; return __var_Set(vobj.SubObject, propertyName, longValue); } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; } return VlcError.NoObj; } public float GetVlcObjectFloat(ObjectType objectType, String propertyName, float errorReturn) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, objectType)) { vlc_value_t floatValue = new vlc_value_t(); if((vobj.SubObject != IntPtr.Zero) && (VlcError.Success == __var_Get(vobj.SubObject, propertyName, ref floatValue))) { return floatValue.f_float; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; } return errorReturn; } public VlcError SetVlcObjectFloat(ObjectType objectType, String propertyName, float value) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, objectType)) { if(vobj.SubObject != IntPtr.Zero) { vlc_value_t floatValue = new vlc_value_t(); floatValue.f_float = value; return __var_Set(vobj.SubObject, propertyName, floatValue); } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; } return VlcError.NoObj; } public String GetVlcObjectString(ObjectType objectType, String propertyName, String errorReturn) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, objectType)) { vlc_value_t stringValue = new vlc_value_t(); if((vobj.SubObject != IntPtr.Zero) && (VlcError.Success == __var_Get(vobj.SubObject, propertyName, ref stringValue))) { return Marshal.PtrToStringAnsi(stringValue.psz_string); } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; } return errorReturn; } public VlcError SetVlcObjectString(ObjectType objectType, String propertyName, String value) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, objectType)) { if(vobj.SubObject != IntPtr.Zero) { vlc_value_t stringValue = new vlc_value_t(); IntPtr valuePtr = Marshal.StringToCoTaskMemAnsi(value); stringValue.psz_string = valuePtr; VlcError ret = __var_Set(vobj.SubObject, propertyName, stringValue); Marshal.ZeroFreeCoTaskMemAnsi(valuePtr); return ret; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; } return VlcError.NoObj; } public VlcError GetVlcVariableChoiceList(ObjectType objectType, String propertyName, out int[] choiceIds, out String[] choiceText) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, objectType)) { if(vobj.SubObject != IntPtr.Zero) { vlc_value_t idValues = new vlc_value_t(); vlc_value_t textValues = new vlc_value_t(); if(VlcError.Success == __var_Change(vobj.SubObject, propertyName, VarFlags.VLC_VAR_GETLIST, ref idValues, ref textValues)) { try { vlc_list_t idList = (vlc_list_t)Marshal.PtrToStructure( idValues.p_list, typeof(vlc_list_t)); vlc_list_t textList = (vlc_list_t)Marshal.PtrToStructure( textValues.p_list, typeof(vlc_list_t)); int choiceCount = idList.i_count; choiceIds = new Int32[choiceCount]; choiceText = new String[choiceCount]; for(int index = 0; index < choiceCount; index++) { IntPtr idPtr = new IntPtr(idList.p_values.ToInt32() + index * Marshal.SizeOf(typeof(vlc_value_t))); vlc_value_t idValue = (vlc_value_t)Marshal.PtrToStructure( idPtr, typeof(vlc_value_t)); choiceIds[index] = idValue.i_int; IntPtr textPtr = new IntPtr(textList.p_values.ToInt32() + index * Marshal.SizeOf(typeof(vlc_value_t))); vlc_value_t textValue = (vlc_value_t)Marshal.PtrToStructure( textPtr, typeof(vlc_value_t)); choiceText[index] = Marshal.PtrToStringAnsi(textValue.psz_string); } return VlcError.Success; } finally { __var_Change(vobj.SubObject, propertyName, VarFlags.VLC_VAR_FREELIST, ref idValues, ref textValues); } } } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; } choiceIds = new int[0]; choiceText = new string[0]; return VlcError.NoObj; } public VlcError GetVlcVariableChoiceList(ObjectType objectType, String propertyName, out String[] choices, out String[] choiceText) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, objectType)) { if(vobj.SubObject != IntPtr.Zero) { vlc_value_t idValues = new vlc_value_t(); vlc_value_t textValues = new vlc_value_t(); if(VlcError.Success == __var_Change(vobj.SubObject, propertyName, VarFlags.VLC_VAR_GETLIST, ref idValues, ref textValues)) { try { vlc_list_t idList = (vlc_list_t)Marshal.PtrToStructure( idValues.p_list, typeof(vlc_list_t)); vlc_list_t textList = (vlc_list_t)Marshal.PtrToStructure( textValues.p_list, typeof(vlc_list_t)); int choiceCount = idList.i_count; List<String> choiceList = new List<string>(choiceCount); List<String> choiceTextList = new List<string>(choiceCount); Dictionary<String, int> choiceDict = new Dictionary<string, int>(choiceCount); for(int index = 0; index < choiceCount; index++) { IntPtr idPtr = new IntPtr(idList.p_values.ToInt32() + index * Marshal.SizeOf(typeof(vlc_value_t))); vlc_value_t idValue = (vlc_value_t)Marshal.PtrToStructure( idPtr, typeof(vlc_value_t)); String choice = Marshal.PtrToStringAnsi(idValue.psz_name); choiceList.Add(choice); if(choiceDict.ContainsKey(choice)) { choiceDict[choice] = choiceDict[choice] + 1; } else { choiceDict[choice] = 1; } IntPtr textPtr = new IntPtr(textList.p_values.ToInt32() + index * Marshal.SizeOf(typeof(vlc_value_t))); vlc_value_t textValue = (vlc_value_t)Marshal.PtrToStructure( textPtr, typeof(vlc_value_t)); choiceTextList.Add(Marshal.PtrToStringAnsi(textValue.psz_string)); } int listIndex = 0; for(int index = 0; index < choiceCount; index++) { String choice = choiceList[listIndex]; if((choiceDict[choice] > 1) && (choiceTextList[listIndex] == null)) { choiceList.RemoveAt(listIndex); choiceTextList.RemoveAt(listIndex); choiceDict[choice] = choiceDict[choice] - 1; } else { listIndex++; } } for(int index = 0; index < choiceList.Count; index++) { if(choiceTextList[index] == null) { choiceTextList[index] = choiceList[index]; } } choices = choiceList.ToArray(); choiceText = choiceTextList.ToArray(); return VlcError.Success; } finally { __var_Change(vobj.SubObject, propertyName, VarFlags.VLC_VAR_FREELIST, ref idValues, ref textValues); } } } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; } choices = new string[0]; choiceText = new string[0]; return VlcError.NoObj; } #endregion #region public Properties public string VlcInstallDir { get{ return vlcInstallDirectory; } set{ vlcInstallDirectory = value; } } public bool IsInitialized { get{return (vlcHandle != -1);} } public Control VideoOutput { get { return outputWindow; } set { if(value == null) { if(outputWindow != null) { outputWindow = null; if(vlcHandle != -1) { SetVlcObjectInt(ObjectType.VLC_OBJECT_VLC, "drawable", 0); } } } else { outputWindow = value; if(vlcHandle != -1) { SetVlcObjectInt(ObjectType.VLC_OBJECT_VLC, "drawable", outputWindow.Handle.ToInt32()); } } } } public string LastError { get{return lastErrorMessage;} } public int Length { get { if(this.artificialLength != 0) { return this.artificialLength; } else { return Convert.ToInt32(GetVlcObjectLong(ObjectType.VLC_OBJECT_INPUT, "length", 0) / 1000000L); } } } public void SetArtificialLength(int newLength) { this.artificialLength = newLength; } public int Time { get { int time = Convert.ToInt32(GetVlcObjectLong(ObjectType.VLC_OBJECT_INPUT, "time", 0) / 1000000L); if((time == 0) && (this.artificialLength != 0)) { time = Convert.ToInt32(Position * this.artificialLength + .5d); } if(this.timeScaling != 0.0d) { time = Convert.ToInt32(time / this.timeScaling); } return time; } set { if(this.artificialLength != 0) { float position = Convert.ToSingle(value) / Convert.ToSingle(this.artificialLength); if(this.timeScaling != 0.0d) { position = Convert.ToSingle(position * this.timeScaling); } Debug.WriteLine(String.Format("Set Position {0}", position)); SetVlcObjectFloat(ObjectType.VLC_OBJECT_INPUT, "position", position); } else { long time = Convert.ToInt64(value) * 1000000L; if(this.timeScaling != 0.0d) { time = Convert.ToInt64(time * this.timeScaling); } Debug.WriteLine(String.Format("Set Time {0}", time)); SetVlcObjectLong(ObjectType.VLC_OBJECT_INPUT, "time", time); } } } public double TimeScaling { get { return this.timeScaling; } set { this.timeScaling = value; } } public double Position { get { double position = GetVlcObjectFloat(ObjectType.VLC_OBJECT_INPUT, "position", 0.0f); if(this.timeScaling != 0.0d) { position = position / this.timeScaling; } return position; } set { double position = value; if(this.timeScaling != 0.0d) { position = position * this.timeScaling; } Debug.WriteLine(String.Format("Set Position {0}", position)); SetVlcObjectFloat(ObjectType.VLC_OBJECT_INPUT, "position", Convert.ToSingle(position)); } } public int Volume { get { IntPtr vlc = vlc_current_object(vlcHandle); if(IntPtr.Zero != vlc) { try { Int16 aoutVol = 0; if(__aout_VolumeGet(vlc, ref aoutVol) == VlcError.Success) { return (aoutVol * VOLUME_MAX + AOUT_VOLUME_MAX / 2) / AOUT_VOLUME_MAX; } } catch(Exception) { } finally { __vlc_object_release(vlc); } } return 0; } set { IntPtr vlc = vlc_current_object(vlcHandle); if(IntPtr.Zero != vlc) { try { Int16 aoutVol = Convert.ToInt16((value * AOUT_VOLUME_MAX + VOLUME_MAX / 2) / VOLUME_MAX); __aout_VolumeSet(vlc, aoutVol); } catch(Exception) { } finally { __vlc_object_release(vlc); } } } } public bool Fullscreen { get { int isFullScreen = GetVlcObjectInt(ObjectType.VLC_OBJECT_VLC, "fullscreen", -666); if((isFullScreen != -666) && (isFullScreen != 0)) { return true; } return false; } set { SetVlcObjectInt(ObjectType.VLC_OBJECT_VLC, "fullscreen", value ? 1 : 0); } } public int PlaylistIndex { get { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST)) { if(vobj.SubObject != IntPtr.Zero) { playlist_t_begin playlist = (playlist_t_begin)Marshal.PtrToStructure(vobj.SubObject, typeof(playlist_t_begin)); return playlist.i_index; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; return -1; } return -1; } } public int PlaylistCount { get { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST)) { if(vobj.SubObject != IntPtr.Zero) { playlist_t_begin playlist = (playlist_t_begin)Marshal.PtrToStructure(vobj.SubObject, typeof(playlist_t_begin)); return playlist.i_size; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; return -1; } return -1; } } #endregion #region public Methods public bool Initialize() { // check if already initializes if(vlcHandle != -1) return true; // try init try { // create instance vlcHandle = VLC_Create(); if (vlcHandle < 0) { lastErrorMessage = "Failed to create VLC instance"; return false; } string[] initOptions = { "vlc", ":no-one-instance", ":no-loop", ":no-drop-late-frames", ":disable-screensaver", ":vout=vout_directx" }; if(vlcInstallDirectory.Length > 0) initOptions[0] = vlcInstallDirectory + @"\vlc"; // init libvlc VlcError errVlcLib = VLC_Init(vlcHandle, initOptions.Length, initOptions); if (errVlcLib != VlcError.Success) { VLC_Destroy(vlcHandle); lastErrorMessage = "Failed to initialise VLC"; vlcHandle = -1; return false; } } catch { lastErrorMessage = "Could not find libvlc"; return false; } // check output window if(outputWindow != null) { SetVlcObjectInt(ObjectType.VLC_OBJECT_VLC, "drawable", outputWindow.Handle.ToInt32()); } return true; } public VlcError AddTarget(string target, ref int itemId) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST)) { if(vobj.SubObject != IntPtr.Zero) { VlcError enmErr = playlist_AddExt(vobj.SubObject, target, target, Mode.Append, EndOfPlaylist, -1L, null, 0); if(enmErr >= VlcError.Success) { itemId = (int)enmErr; } return enmErr; } else { return VlcError.NoObj; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; return VlcError.Exception; } } public VlcError AddTarget(string target, string[] options, ref int itemId) { int optionsCount = 0; if(options != null) { optionsCount = options.Length; } try { using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST)) { if(vobj.SubObject != IntPtr.Zero) { VlcError enmErr = playlist_AddExt(vobj.SubObject, target, target, Mode.Append, EndOfPlaylist, -1L, options, optionsCount); if(enmErr >= VlcError.Success) { itemId = (int)enmErr; } return enmErr; } else { return VlcError.NoObj; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; return VlcError.Exception; } } public Size VideoSize { get { try { using(VlcPlaylistObject vpobj = new VlcPlaylistObject(this.vlcHandle)) { if(vpobj.SubObject != IntPtr.Zero) { IntPtr p_input = libvlc_playlist_get_input(ref vpobj.libvlc, ref vpobj.exception); if(vpobj.exception.WasExceptionRaised()) { this.lastErrorMessage = Marshal.PtrToStringAnsi(vpobj.exception.psz_message); } else { try { int width = libvlc_video_get_width(p_input, ref vpobj.exception); if(!vpobj.exception.WasExceptionRaised()) { int height = libvlc_video_get_height(p_input, ref vpobj.exception); if(!vpobj.exception.WasExceptionRaised()) { return new Size(width, height); } } } finally { libvlc_input_free(p_input); } } } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; } return new Size(); } } public VlcError Play(int itemId) { try { this.artificialLength = 0; this.timeScaling = 0.0d; using(VlcPlaylistObject vpobj = new VlcPlaylistObject(this.vlcHandle)) { if(vpobj.SubObject != IntPtr.Zero) { libvlc_playlist_play(ref vpobj.libvlc, itemId, 0, IntPtr.Zero, ref vpobj.exception); if(vpobj.exception.WasExceptionRaised()) { return VlcError.Generic; } return VlcError.Success; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; return VlcError.Exception; } return VlcError.NoObj; } public VlcError Play() { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST)) { if(vobj.SubObject != IntPtr.Zero) { return playlist_LockControl(vobj.SubObject, playlist_command.PLAYLIST_PLAY); } else { return VlcError.NoObj; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; return VlcError.Exception; } } public VlcError Pause() { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST)) { if(vobj.SubObject != IntPtr.Zero) { return playlist_LockControl(vobj.SubObject, playlist_command.PLAYLIST_PAUSE); } else { return VlcError.NoObj; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; return VlcError.Exception; } } public VlcError Stop() { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST)) { if(vobj.SubObject != IntPtr.Zero) { return playlist_LockControl(vobj.SubObject, playlist_command.PLAYLIST_PAUSE); } else { return VlcError.NoObj; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; return VlcError.Exception; } } public VlcError PlaylistClear() { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST)) { if(vobj.SubObject != IntPtr.Zero) { return playlist_Clear(vobj.SubObject); } else { return VlcError.NoObj; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; return VlcError.Exception; } } public VlcError ToggleVolumeMute() { IntPtr vlc = vlc_current_object(vlcHandle); if(IntPtr.Zero != vlc) { try { return __aout_VolumeMute(vlc, IntPtr.Zero); } catch(Exception) { } finally { __vlc_object_release(vlc); } } return VlcError.NoObj; } public VlcError PressKey(string strKey) { int key = GetVlcObjectInt(ObjectType.VLC_OBJECT_VLC, strKey, -666); if(key != -666) { return SetVlcObjectInt(ObjectType.VLC_OBJECT_VLC, "key-pressed", key); } return VlcError.NoVar; } public VlcError ShowMessage(String message) { try { using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_INPUT)) { if(vobj.SubObject != IntPtr.Zero) { __vout_OSDMessage(vobj.SubObject, DEFAULT_CHAN, message); return VlcError.Success; } else { return VlcError.NoObj; } } } catch(Exception ex) { this.lastErrorMessage = ex.Message; return VlcError.Exception; } } enum CONFIG_ITEM : int { CONFIG_ITEM_STRING = 0x0010, CONFIG_ITEM_FILE = 0x0020, CONFIG_ITEM_MODULE = 0x0030, CONFIG_ITEM_INTEGER = 0x0040, CONFIG_ITEM_BOOL = 0x0050, CONFIG_ITEM_FLOAT = 0x0060, } [StructLayout(LayoutKind.Sequential)] struct module_config_t { public CONFIG_ITEM i_type; } [DllImport("libvlc")] static extern IntPtr config_FindConfig(IntPtr vlc, String name); [DllImport("libvlc")] static extern void __config_PutInt(IntPtr vlc, String name, int value); [DllImport("libvlc")] static extern void __config_PutFloat(IntPtr vlc, String name, float value); [DllImport("libvlc")] static extern void __config_PutPsz(IntPtr vlc, String name, String value); public VlcError SetConfigVariable(String name, String value) { using(VlcObject vlc = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_VLC)) { if(IntPtr.Zero == vlc.SubObject) { return VlcError.NoObj; } IntPtr p_item = config_FindConfig(vlc.SubObject, name); if(IntPtr.Zero == p_item) { return VlcError.NoVar; } else { try { module_config_t mod = (module_config_t)Marshal.PtrToStructure(p_item, typeof(module_config_t)); switch(mod.i_type) { case CONFIG_ITEM.CONFIG_ITEM_BOOL: { bool boolResult; if(Boolean.TryParse(value, out boolResult)) { __config_PutInt(vlc.SubObject, name, boolResult ? 1 : 0); } else { return VlcError.BadVar; } } break; case CONFIG_ITEM.CONFIG_ITEM_INTEGER: { int intResult; if(Int32.TryParse(value, out intResult)) { __config_PutInt(vlc.SubObject, name, intResult); } else { return VlcError.BadVar; } } break; case CONFIG_ITEM.CONFIG_ITEM_FLOAT: { float floatResult; if(Single.TryParse(value, out floatResult)) { __config_PutFloat(vlc.SubObject, name, floatResult); } else { return VlcError.BadVar; } } break; case CONFIG_ITEM.CONFIG_ITEM_STRING: __config_PutPsz(vlc.SubObject, name, value); break; default: return VlcError.NoVar; } } catch(Exception e) { this.lastErrorMessage = e.Message; return VlcError.Exception; } } } return VlcError.Success; } #endregion #region private members, properties and methods private int vlcHandle = -1; private Control outputWindow = null; private string vlcInstallDirectory = ""; private string lastErrorMessage = ""; private int artificialLength; private double timeScaling; /// ------------------------------------------------------------------- /// <summary> /// Method name : QueryVlcInstallPath /// Author : Odysee /// Date : 10.11.2006 /// </summary> /// ------------------------------------------------------------------- private string QueryVlcInstallPath() { // open registry RegistryKey regkeyVlcInstallPathKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\VideoLAN\VLC"); if(regkeyVlcInstallPathKey == null) return ""; return (string)regkeyVlcInstallPathKey.GetValue("InstallDir",""); } #endregion } /* future features add_float_with_range( "contrast", 1.0, 0.0, 2.0, NULL, CONT_TEXT, CONT_LONGTEXT, VLC_FALSE ); add_float_with_range( "brightness", 1.0, 0.0, 2.0, NULL, LUM_TEXT, LUM_LONGTEXT, VLC_FALSE ); add_integer_with_range( "hue", 0, 0, 360, NULL, HUE_TEXT, HUE_LONGTEXT, VLC_FALSE ); add_float_with_range( "saturation", 1.0, 0.0, 3.0, NULL, SAT_TEXT, SAT_LONGTEXT, VLC_FALSE ); add_float_with_range( "gamma", 1.0, 0.01, 10.0, NULL, GAMMA_TEXT, GAMMA_LONGTEXT, VLC_FALSE ); add_bool( "brightness-threshold", 0, NULL, THRES_TEXT, THRES_LONGTEXT, VLC_FALSE ); */ }