NativeLibVlc.cs: Difference between revisions

From VideoLAN Wiki
Jump to navigation Jump to search
Tappen (talk | contribs)
No edit summary
 
m syntaxhighlight
 
(4 intermediate revisions by 2 users not shown)
Line 1: Line 1:
<pre>
{{example code|l=LGPL|for=.Net Interface to VLC}}
<syntaxhighlight lang="csharp">
/*****************************************************************************
/*****************************************************************************
  * NativeLibVlc.cs: NativeLibVlc class definition
  * NativeLibVlc.cs: NativeLibVlc class definition
Line 25: Line 26:
using System.Diagnostics;
using System.Diagnostics;
using System.Drawing;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Text;
Line 202: Line 205:
PLAYLIST_GOTO = 7,      /**< arg1=int                          res=can fail */
PLAYLIST_GOTO = 7,      /**< arg1=int                          res=can fail */
PLAYLIST_VIEWGOTO = 8  /**< arg1=int                          res=can fail */
PLAYLIST_VIEWGOTO = 8  /**< arg1=int                          res=can fail */
}
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,
}
enum input_query_e : int
{
/* input variable "position" */
INPUT_GET_POSITION = 0,        /* arg1= double *      res=    */
INPUT_SET_POSITION,        /* arg1= double        res=can fail    */
/* input variable "length" */
INPUT_GET_LENGTH,          /* arg1= int64_t *      res=can fail    */
/* input variable "time" */
INPUT_GET_TIME,            /* arg1= int64_t *      res=    */
INPUT_SET_TIME,            /* arg1= int64_t        res=can fail    */
/* input variable "rate" (1 is DEFAULT_RATE) */
INPUT_GET_RATE,            /* arg1= int *          res=    */
INPUT_SET_RATE,            /* arg1= int            res=can fail    */
/* input variable "state" */
INPUT_GET_STATE,            /* arg1= int *          res=    */
INPUT_SET_STATE,            /* arg1= int            res=can fail    */
/* input variable "audio-delay" and "sub-delay" */
INPUT_GET_AUDIO_DELAY,      /* arg1 = int* res=can fail */
INPUT_SET_AUDIO_DELAY,      /* arg1 = int  res=can fail */
INPUT_GET_SPU_DELAY,        /* arg1 = int* res=can fail */
INPUT_SET_SPU_DELAY,        /* arg1 = int  res=can fail */
/* Meta datas */
INPUT_ADD_INFO,  /* arg1= char* arg2= char* arg3=...    res=can fail */
INPUT_GET_INFO,  /* arg1= char* arg2= char* arg3= char** res=can fail */
INPUT_DEL_INFO,  /* arg1= char* arg2= char*              res=can fail */
INPUT_SET_NAME,  /* arg1= char* res=can fail    */
/* Input config options */
INPUT_ADD_OPTION,      /* arg1= char * arg2= char *  res=can fail*/
/* Input properties */
INPUT_GET_BYTE_POSITION,    /* arg1= int64_t *      res=    */
INPUT_SET_BYTE_SIZE,        /* arg1= int64_t *      res=    */
/* bookmarks */
INPUT_GET_BOOKMARKS,  /* arg1= seekpoint_t *** arg2= int * res=can fail */
INPUT_CLEAR_BOOKMARKS, /* res=can fail */
INPUT_ADD_BOOKMARK,    /* arg1= seekpoint_t *  res=can fail  */
INPUT_CHANGE_BOOKMARK, /* arg1= seekpoint_t * arg2= int * res=can fail  */
INPUT_DEL_BOOKMARK,    /* arg1= seekpoint_t *  res=can fail  */
INPUT_SET_BOOKMARK,    /* arg1= int  res=can fail    */
/* On the fly input slave */
INPUT_ADD_SLAVE        /* arg1= char * */
}
}


Line 271: Line 336:


[StructLayout(LayoutKind.Sequential)]
[StructLayout(LayoutKind.Sequential)]
struct playlist_t_begin
struct module_config_t
{
{
public Int32 i_index;
public CONFIG_ITEM i_type;
public Int32 i_enabled;
public Int32 i_size;
}
}


Line 281: Line 344:


#region vlc api interop
#region vlc api interop
        [DllImport("libvlc")]
const int AOUT_VOLUME_MAX = 1024;
const int VOLUME_MAX = 200;
const int DEFAULT_CHAN = 1;
const String Playlist_Current = "item-change";
const String Now_Playing = "Now Playing";
const String Meta_information = "Meta-information";
const String Meta_title = "meta-title";
const String Meta_author = "meta-author";
const String Meta_artist = "meta-artist";
const String Meta_genre = "meta-genre";
const String Meta_description = "meta-description";
const String Meta_url = "meta-url";
[DllImport("libvlc")]
         static extern int VLC_Create();
         static extern int VLC_Create();
         [DllImport("libvlc")]
         [DllImport("libvlc")]
Line 307: Line 383:
static extern VlcError __var_Change(IntPtr p_this, String name, VarFlags varFlags,
static extern VlcError __var_Change(IntPtr p_this, String name, VarFlags varFlags,
ref vlc_value_t value, ref vlc_value_t value2);
ref vlc_value_t value, ref vlc_value_t value2);
const int AOUT_VOLUME_MAX = 1024;
const int VOLUME_MAX = 200;


[DllImport("libvlc")]
[DllImport("libvlc")]
Line 328: Line 401:
static extern void libvlc_playlist_play(ref libvlc_instance_t libvlc, Int32 id,  
static extern void libvlc_playlist_play(ref libvlc_instance_t libvlc, Int32 id,  
Int32 optionsCount, IntPtr optionsAlwaysNull, ref libvlc_exception_t p_exception);
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")]
[DllImport("libvlc")]
static extern IntPtr libvlc_playlist_get_input(ref libvlc_instance_t libvlc, ref libvlc_exception_t p_exception);
static extern int VLC_PlaylistIndex(int vlcObject);
[DllImport("libvlc")]
static extern int VLC_PlaylistNumberOfItems(int vlcObject);


[DllImport("libvlc")]
[DllImport("libvlc")]
Line 337: Line 414:
[DllImport("libvlc")]
[DllImport("libvlc")]
static extern int libvlc_video_get_width(IntPtr p_input, ref libvlc_exception_t p_exception);
static extern int libvlc_video_get_width(IntPtr p_input, ref libvlc_exception_t p_exception);
[DllImport("libvlc")]
[DllImport("libvlc")]
static extern int libvlc_video_get_height(IntPtr p_input, ref libvlc_exception_t p_exception);
static extern int libvlc_video_get_height(IntPtr p_input, ref libvlc_exception_t p_exception);
Line 343: Line 419:
[DllImport("libvlc", CallingConvention=CallingConvention.Cdecl)]
[DllImport("libvlc", CallingConvention=CallingConvention.Cdecl)]
static extern VlcError playlist_LockControl(IntPtr p_playlist, playlist_command i_query);
static extern VlcError playlist_LockControl(IntPtr p_playlist, playlist_command i_query);
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
static extern VlcError playlist_LockControl(IntPtr p_playlist, playlist_command i_query, Int32 arg1);
static extern VlcError playlist_LockControl(IntPtr p_playlist, playlist_command i_query, Int32 arg1);
[DllImport("libvlc")]
[DllImport("libvlc")]
static extern VlcError playlist_Clear(IntPtr p_playlist);
static extern VlcError playlist_Clear(IntPtr p_playlist);
[DllImport("libvlc")]
[DllImport("libvlc")]
static extern VlcError playlist_AddExt(IntPtr p_playlist, String mrl, String mrlDuplicate,  
static extern VlcError playlist_AddExt(IntPtr p_playlist, String mrl, String mrlDuplicate,  
Line 356: Line 429:
int OptionsCount);
int OptionsCount);


const int DEFAULT_CHAN = 1;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int VarChangedCallback(IntPtr vlc, String variable, vlc_value_t old_val,
vlc_value_t new_val, IntPtr param);
 
[DllImport("libvlc")]
static extern int __var_AddCallback(IntPtr vlc, String variable, VarChangedCallback cb,
IntPtr param);
[DllImport("libvlc")]
static extern int __var_DelCallback(IntPtr vlc, String variable, VarChangedCallback cb,
IntPtr param);
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, CharSet=CharSet.Ansi)]
static extern VlcError input_Control(IntPtr input_thread_t, input_query_e i_query, String category, String name,
ref IntPtr result);


[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
static extern void __vout_OSDMessage(IntPtr p_input, int i_channel, String message);
static extern void __vout_OSDMessage(IntPtr p_input, int i_channel, String message);
[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);
[DllImport("libvlc")]
static extern int __config_GetInt(IntPtr vlc, String name);
[DllImport("libvlc")]
static extern float __config_GetFloat(IntPtr vlc, String name);
[DllImport("libvlc")]
static extern String __config_GetPsz(IntPtr vlc, String name);


#endregion
#endregion
static NativeLibVlc()
{
NativeLibVlc.vlcInstallDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase).Substring(6);
//NativeLibVlc.vlcInstallDirectory = Environment.CurrentDirectory;
//NativeLibVlc.vlcInstallDirectory = QueryVlcInstallPath();
}


public NativeLibVlc()
public NativeLibVlc()
         {
         {
            vlcInstallDirectory = QueryVlcInstallPath();
         }
         }


Line 375: Line 481:
                 try
                 try
                 {
                 {
if(this.gch.IsAllocated)
{
UnhookPlaylistChanges();
}
VideoOutput = null;
VideoOutput = null;
VLC_CleanUp(vlcHandle);
VLC_CleanUp(this.vlcHandle);
                     VLC_Destroy(vlcHandle);
                     VLC_Destroy(this.vlcHandle);
                 }
                 }
                 catch { }
                 catch { }
Line 792: Line 902:


         #region public Properties
         #region public Properties
         public string VlcInstallDir
         public static string VlcInstallDir
         {
         {
             get{ return vlcInstallDirectory; }
             get{ return vlcInstallDirectory; }
Line 834: Line 944:
             get{return lastErrorMessage;}
             get{return lastErrorMessage;}
         }
         }
public event MetaDataEventHandler NowPlaying;
protected virtual void OnNowPlaying(MetaDataUpdateEventArgs args)
{
if(this.NowPlaying != null)
{
this.NowPlaying(this, args);
}
}
protected delegate void HandleNowPlaying(MetaDataUpdateEventArgs args);
protected virtual void VlcNowPlayingChanged(String newText)
{
// switch out of the Vlc thread to our User Interface thread if possible
if(this.VideoOutput != null)
{
this.VideoOutput.BeginInvoke(new HandleNowPlaying(OnNowPlaying),
new MetaDataUpdateEventArgs(MetaData.NowPlaying, newText));
}
else
{
OnNowPlaying(new MetaDataUpdateEventArgs(MetaData.NowPlaying, newText));
}
}


         public int Length
         public int Length
Line 994: Line 1,130:
try
try
{
{
using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
return VLC_PlaylistIndex(this.vlcHandle);
{
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)
catch(Exception ex)
Line 1,008: Line 1,137:
return -1;
return -1;
}
}
return -1;
}
}
}
}
Line 1,018: Line 1,146:
try
try
{
{
using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
return VLC_PlaylistNumberOfItems(this.vlcHandle);
{
}
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)
catch(Exception ex)
{
{
Line 1,032: Line 1,153:
return -1;
return -1;
}
}
return -1;
}
}
}
}
Line 1,045: Line 1,165:
                 return true;
                 return true;


            // try init
string oldDir = Environment.CurrentDirectory;
            try
// try init
            {
try
                // create instance
{
                vlcHandle = VLC_Create();
// create instance
Environment.CurrentDirectory = NativeLibVlc.vlcInstallDirectory;
this.vlcHandle = VLC_Create();


                if (vlcHandle < 0)
if(this.vlcHandle < 0)
                {
{
                    lastErrorMessage = "Failed to create VLC instance";
lastErrorMessage = "Failed to create VLC instance";
                    return false;
return false;
                }
}


                string[] initOptions = { "vlc",
string[] initOptions = { NativeLibVlc.vlcInstallDirectory,
                                            ":no-one-instance",
":no-one-instance",
                                            ":no-loop",
":no-loop",
                                            ":no-drop-late-frames",
":no-drop-late-frames",
                                            ":disable-screensaver",
":disable-screensaver",
":vout=vout_directx" };
":vout=vout_directx",
                if(vlcInstallDirectory.Length > 0)
"--plugin-path=" + NativeLibVlc.vlcInstallDirectory + @"\plugins",
                    initOptions[0] = vlcInstallDirectory + @"\vlc";
};


                // init libvlc
// init libvlc
                VlcError errVlcLib = VLC_Init(vlcHandle, initOptions.Length, initOptions);
VlcError errVlcLib = VLC_Init(vlcHandle, initOptions.Length, initOptions);
                if (errVlcLib != VlcError.Success)
if(errVlcLib != VlcError.Success)
                {
{
                    VLC_Destroy(vlcHandle);
VLC_Destroy(vlcHandle);
                    lastErrorMessage = "Failed to initialise VLC";
lastErrorMessage = "Failed to initialise VLC";
                    vlcHandle   = -1;
this.vlcHandle = -1;
                    return false;
return false;
                }
}
             
}
            }
catch
            catch
{
            {
lastErrorMessage = "Could not find libvlc";
                lastErrorMessage = "Could not find libvlc";
return false;
                return false;
}
            }          
finally
{
Environment.CurrentDirectory = oldDir;
}


             // check output window
             // check output window
Line 1,092: Line 1,217:
         }
         }


public VlcError AddTarget(string target, ref int itemId)
// there's an overhead to supporting Vlc events, a memory leak, so we need to have them off by default
        {
public bool ProducingEvents
try
{
get { return this.gch.IsAllocated; }
set
{
{
using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
if(value)
{
{
if(vobj.SubObject != IntPtr.Zero)
if(!this.gch.IsAllocated)
{
{
VlcError enmErr = playlist_AddExt(vobj.SubObject, target, target, Mode.Append,
HookPlaylistChanges();
EndOfPlaylist, -1L, null, 0);
if(enmErr >= VlcError.Success)
{
itemId = (int)enmErr;
}
return enmErr;
}
}
else
}
else
{
if(this.gch.IsAllocated)
{
{
return VlcError.NoObj;
UnhookPlaylistChanges();
}
}
}
}
}
catch(Exception ex)
{
this.lastErrorMessage = ex.Message;
return VlcError.Exception;
}
}
}
}


public VlcError AddTarget(string target, string[] options, ref int itemId)
private static String AdjustFilterString(String current, String filter, bool add)
        {
{
            int optionsCount = 0;
String newFilter = null;
if(options != null)
int findFilter = current.IndexOf(filter);
{
if(findFilter == -1)
optionsCount = options.Length;
{
if(add)
{
if(current.Length == 0)
{
newFilter = filter;
}
else
{
newFilter = String.Format("{0}:{1}", current, filter);
}
}
}
}
 
else
try
{
{
using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
if(!add)
{
{
if(vobj.SubObject != IntPtr.Zero)
int colonAfterAdjust = current.IndexOf(':', findFilter + 1);
if(findFilter == 0)
{
{
VlcError enmErr = playlist_AddExt(vobj.SubObject, target, target, Mode.Append,
if(colonAfterAdjust == -1)
EndOfPlaylist, -1L, options, optionsCount);
{
if(enmErr >= VlcError.Success)
newFilter = String.Empty;
}
else
{
{
itemId = (int)enmErr;
newFilter = current.Substring(colonAfterAdjust + 1);
}
}
return enmErr;
}
}
else
else
{
{
return VlcError.NoObj;
if(colonAfterAdjust == -1)
{
newFilter = current.Substring(0, findFilter - 1);
}
else
{
newFilter = current.Substring(0, findFilter - 1) +
current.Substring(colonAfterAdjust);
}
}
}
}
}
}
}
catch(Exception ex)
return newFilter;
{
}
this.lastErrorMessage = ex.Message;
 
return VlcError.Exception;
const String VideoFilterList = "vout-filter";
}
const String AdjustFilter = "adjust";
        }


public Size VideoSize
public bool AllowVideoAdjustments
{
{
get
get
{
{
try
String voutFilter = GetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, VideoFilterList, null);
if(voutFilter == null)
{
GetConfigVariable(VideoFilterList, out voutFilter);
}
if(voutFilter != null)
{
return voutFilter.IndexOf(AdjustFilter) != -1;
}
else
{
return false;
}
}
set
{
bool useConfig = false;
String voutFilter = GetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, VideoFilterList, null);
if(voutFilter == null)
{
using(VlcObject vlc = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_VLC))
{
GetConfigVariable(VideoFilterList, out voutFilter);
useConfig = true;
}
}
if(voutFilter != null)
{
{
using(VlcPlaylistObject vpobj = new VlcPlaylistObject(this.vlcHandle))
String newVoutFilter = AdjustFilterString(voutFilter, AdjustFilter, value);
if(newVoutFilter != null)
{
{
if(vpobj.SubObject != IntPtr.Zero)
if(useConfig)
{
{
IntPtr p_input = libvlc_playlist_get_input(ref vpobj.libvlc, ref vpobj.exception);
SetConfigVariable(VideoFilterList, newVoutFilter);
if(vpobj.exception.WasExceptionRaised())
}
{
else
this.lastErrorMessage = Marshal.PtrToStringAnsi(vpobj.exception.psz_message);
{
}
SetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, VideoFilterList, newVoutFilter);
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)
public VlcError AddTarget(string target, ref int itemId)
{
        {
try
try
{
{
this.artificialLength = 0;
using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
this.timeScaling = 0.0d;
using(VlcPlaylistObject vpobj = new VlcPlaylistObject(this.vlcHandle))
{
{
if(vpobj.SubObject != IntPtr.Zero)
if(vobj.SubObject != IntPtr.Zero)
{
{
libvlc_playlist_play(ref vpobj.libvlc, itemId, 0, IntPtr.Zero,  
VlcError enmErr = playlist_AddExt(vobj.SubObject, target, target, Mode.Append,  
ref vpobj.exception);
EndOfPlaylist, -1L, null, 0);
if(vpobj.exception.WasExceptionRaised())
if(enmErr >= VlcError.Success)
{
{
return VlcError.Generic;
itemId = (int)enmErr;
}
}
return VlcError.Success;
return enmErr;
}
}
}
else
{
return VlcError.NoObj;
}
}
}
}
catch(Exception ex)
catch(Exception ex)
Line 1,226: Line 1,369:
return VlcError.Exception;
return VlcError.Exception;
}
}
return VlcError.NoObj;
}
}


        public VlcError Play()
public VlcError AddTarget(string target, string[] options, ref int itemId)
         {
         {
            int optionsCount = 0;
if(options != null)
{
optionsCount = options.Length;
}
try
try
{
{
Line 1,237: Line 1,385:
if(vobj.SubObject != IntPtr.Zero)
if(vobj.SubObject != IntPtr.Zero)
{
{
return playlist_LockControl(vobj.SubObject, playlist_command.PLAYLIST_PLAY);
VlcError enmErr = playlist_AddExt(vobj.SubObject, target, target, Mode.Append,
EndOfPlaylist, -1L, options, optionsCount);
if(enmErr >= VlcError.Success)
{
itemId = (int)enmErr;
}
return enmErr;
}
}
else
else
Line 1,252: Line 1,406:
         }
         }


        public VlcError Pause()
public Size VideoSize
        {
{
try
get
{
{
using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
try
{
{
if(vobj.SubObject != IntPtr.Zero)
using(VlcPlaylistObject vpobj = new VlcPlaylistObject(this.vlcHandle))
{
{
return playlist_LockControl(vobj.SubObject, playlist_command.PLAYLIST_PAUSE);
if(vpobj.SubObject != IntPtr.Zero)
}
{
else
IntPtr p_input = libvlc_playlist_get_input(ref vpobj.libvlc, ref vpobj.exception);
{
if(vpobj.exception.WasExceptionRaised())
return VlcError.NoObj;
{
}
this.lastErrorMessage = Marshal.PtrToStringAnsi(vpobj.exception.psz_message);
}
}
}
else
catch(Exception ex)
{
{
try
this.lastErrorMessage = ex.Message;
{
return VlcError.Exception;
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 Stop()
public VlcError Play(int itemId)
        {
{
try
try
{
{
using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
this.artificialLength = 0;
this.timeScaling = 0.0d;
using(VlcPlaylistObject vpobj = new VlcPlaylistObject(this.vlcHandle))
{
{
if(vobj.SubObject != IntPtr.Zero)
if(vpobj.SubObject != IntPtr.Zero)
{
{
return playlist_LockControl(vobj.SubObject, playlist_command.PLAYLIST_PAUSE);
libvlc_playlist_play(ref vpobj.libvlc, itemId, 0, IntPtr.Zero,  
}
ref vpobj.exception);
else
if(vpobj.exception.WasExceptionRaised())
{
{
return VlcError.NoObj;
return VlcError.Generic;
}
return VlcError.Success;
}
}
}
}
Line 1,296: Line 1,476:
return VlcError.Exception;
return VlcError.Exception;
}
}
return VlcError.NoObj;
}
}


         public VlcError PlaylistClear()
         public VlcError Play()
         {
         {
try
try
Line 1,306: Line 1,487:
if(vobj.SubObject != IntPtr.Zero)
if(vobj.SubObject != IntPtr.Zero)
{
{
return playlist_Clear(vobj.SubObject);
return playlist_LockControl(vobj.SubObject, playlist_command.PLAYLIST_PLAY);
}
}
else
else
Line 1,321: Line 1,502:
         }
         }


         public VlcError ToggleVolumeMute()
         public VlcError Pause()
         {
         {
IntPtr vlc = vlc_current_object(vlcHandle);
try
if(IntPtr.Zero != vlc)
{
{
try
using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
{
{
return __aout_VolumeMute(vlc, IntPtr.Zero);
if(vobj.SubObject != IntPtr.Zero)
}
{
catch(Exception)
return playlist_LockControl(vobj.SubObject, playlist_command.PLAYLIST_PAUSE);
{
}
}
else
finally
{
{
return VlcError.NoObj;
__vlc_object_release(vlc);
}
}
}
}
}
            return VlcError.NoObj;
catch(Exception ex)
{
this.lastErrorMessage = ex.Message;
return VlcError.Exception;
}
         }
         }


         public VlcError PressKey(string strKey)
         public VlcError Stop()
         {
         {
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
try
{
{
using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_INPUT))
using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
{
{
if(vobj.SubObject != IntPtr.Zero)
if(vobj.SubObject != IntPtr.Zero)
{
{
__vout_OSDMessage(vobj.SubObject, DEFAULT_CHAN, message);
return playlist_LockControl(vobj.SubObject, playlist_command.PLAYLIST_STOP);
return VlcError.Success;
}
}
else
else
Line 1,375: Line 1,548:
}
}


enum CONFIG_ITEM : int
        public VlcError PlaylistClear()
{
        {
CONFIG_ITEM_STRING = 0x0010,
try
CONFIG_ITEM_FILE = 0x0020,
{
CONFIG_ITEM_MODULE = 0x0030,
using(VlcObject vobj = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
CONFIG_ITEM_INTEGER = 0x0040,
{
CONFIG_ITEM_BOOL = 0x0050,
if(vobj.SubObject != IntPtr.Zero)
CONFIG_ITEM_FLOAT = 0x0060,
{
}
return playlist_Clear(vobj.SubObject);
}
else
{
return VlcError.NoObj;
}
}
}
catch(Exception ex)
{
this.lastErrorMessage = ex.Message;
return VlcError.Exception;
}
        }


[StructLayout(LayoutKind.Sequential)]
        public VlcError ToggleVolumeMute()
struct module_config_t
        {
{
IntPtr vlc = vlc_current_object(vlcHandle);
public CONFIG_ITEM i_type;
if(IntPtr.Zero != vlc)
}
 
[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)
try
{
{
return VlcError.NoObj;
return __aout_VolumeMute(vlc, IntPtr.Zero);
}
}
 
catch(Exception)
IntPtr p_item = config_FindConfig(vlc.SubObject, name);
if(IntPtr.Zero == p_item)
{
{
return VlcError.NoVar;
}
}
else
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))
{
{
try
if(vobj.SubObject != IntPtr.Zero)
{
{
module_config_t mod = (module_config_t)Marshal.PtrToStructure(p_item, typeof(module_config_t));
__vout_OSDMessage(vobj.SubObject, DEFAULT_CHAN, message);
switch(mod.i_type)
return VlcError.Success;
{
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)
else
{
{
this.lastErrorMessage = e.Message;
return VlcError.NoObj;
return VlcError.Exception;
}
}
}
}
}
catch(Exception ex)
{
this.lastErrorMessage = ex.Message;
return VlcError.Exception;
}
}
 
public VlcError GetConfigVariable(String name, out String value)
{
value = null;
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;
}
 
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 result = (__config_GetInt(vlc.SubObject, name) == 0);
value = result.ToString();
}
break;
case CONFIG_ITEM.CONFIG_ITEM_INTEGER:
{
int intResult = __config_GetInt(vlc.SubObject, name);
value = intResult.ToString();
}
break;
case CONFIG_ITEM.CONFIG_ITEM_FLOAT:
{
float floatResult = __config_GetFloat(vlc.SubObject, name);
value = floatResult.ToString();
}
break;
case CONFIG_ITEM.CONFIG_ITEM_STRING:
value = __config_GetPsz(vlc.SubObject, name);
break;
default:
return VlcError.BadVar;
}
}
catch(Exception e)
{
this.lastErrorMessage = e.Message;
return VlcError.Exception;
}
}
return VlcError.Success;
}
 
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;
}
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.BadVar;
}
}
catch(Exception e)
{
this.lastErrorMessage = e.Message;
return VlcError.Exception;
}
}
return VlcError.Success;
}
 
        #endregion
 
#region private members, properties and methods
 
private static string vlcInstallDirectory = "";
private int vlcHandle = -1;
private Control outputWindow = null;
private string lastErrorMessage = "";
private int artificialLength;
private double timeScaling;
private GCHandle gch;
private VarChangedCallback currentTrackCallback;
private string previousNowPlaying = String.Empty;
 
        /// -------------------------------------------------------------------
        /// <summary>
        /// Method name      :  QueryVlcInstallPath
        /// Author        :  Odysee
        ///  Date        :  10.11.2006
        /// </summary>
        /// -------------------------------------------------------------------
        private static string QueryVlcInstallPath()
        {
            // open registry
            RegistryKey regkeyVlcInstallPathKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\VideoLAN\VLC");
            if(regkeyVlcInstallPathKey == null)
                return "";
            return (string)regkeyVlcInstallPathKey.GetValue("InstallDir","");
        }
 
private void HookPlaylistChanges()
{
using(VlcObject vlc = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
{
if(vlc.SubObject != IntPtr.Zero)
{
this.gch = GCHandle.Alloc(this);
this.currentTrackCallback = new VarChangedCallback(CurrentTrackChanged);
 
int isSet = __var_AddCallback(vlc.SubObject, Playlist_Current,
this.currentTrackCallback, (IntPtr)this.gch);
//Debug.WriteLine("__var_AddCallback playlistObject = " + isSet.ToString());
}
}
}
 
private void UnhookPlaylistChanges()
{
using(VlcObject vlc = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
{
if(vlc.SubObject != IntPtr.Zero)
{
__var_DelCallback(vlc.SubObject, Playlist_Current,
this.currentTrackCallback, (IntPtr)this.gch);
}
}
this.gch.Free();
}
 
private static int CurrentTrackChanged(IntPtr vlc, String variable, vlc_value_t old_val,
vlc_value_t new_val, IntPtr param)
{
//Debug.WriteLine("CurrentTrackChanged: " + new_val.i_int.ToString());
GCHandle gch = (GCHandle)param;
NativeLibVlc thisVlc = (NativeLibVlc)gch.Target;
try
{
using(VlcObject vobj = new VlcObject(thisVlc.vlcHandle, ObjectType.VLC_OBJECT_INPUT))
{
if(vobj.SubObject != IntPtr.Zero)
{
IntPtr resultString = IntPtr.Zero;
input_Control(vobj.SubObject, input_query_e.INPUT_GET_INFO,
Meta_information, Now_Playing, ref resultString);
String nowPlaying = Marshal.PtrToStringAnsi(resultString);
if(nowPlaying != thisVlc.previousNowPlaying)
{
thisVlc.previousNowPlaying = nowPlaying;
Debug.WriteLine(String.Format("nowPlaying: {0}", nowPlaying));
thisVlc.VlcNowPlayingChanged(nowPlaying);
}
}
}
}
catch(Exception ex)
{
thisVlc.lastErrorMessage = ex.Message;
}
}
return VlcError.Success;
return (int)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
         #endregion
}
}


/* future features
/* 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,
     add_bool( "brightness-threshold", 0, NULL,
Line 1,525: Line 1,854:
*/
*/
}
}
</pre>
</syntaxhighlight>

Latest revision as of 09:35, 29 January 2019

This page contains example code for .Net Interface to VLC.
This code is licensed under the GNU Lesser General public license
/*****************************************************************************
 * 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.IO;
using System.Reflection;
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 */
		}

		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,
		}

		enum input_query_e : int
		{
			/* input variable "position" */
			INPUT_GET_POSITION = 0,         /* arg1= double *       res=    */
			INPUT_SET_POSITION,         /* arg1= double         res=can fail    */

			/* input variable "length" */
			INPUT_GET_LENGTH,           /* arg1= int64_t *      res=can fail    */

			/* input variable "time" */
			INPUT_GET_TIME,             /* arg1= int64_t *      res=    */
			INPUT_SET_TIME,             /* arg1= int64_t        res=can fail    */

			/* input variable "rate" (1 is DEFAULT_RATE) */
			INPUT_GET_RATE,             /* arg1= int *          res=    */
			INPUT_SET_RATE,             /* arg1= int            res=can fail    */

			/* input variable "state" */
			INPUT_GET_STATE,            /* arg1= int *          res=    */
			INPUT_SET_STATE,            /* arg1= int            res=can fail    */

			/* input variable "audio-delay" and "sub-delay" */
			INPUT_GET_AUDIO_DELAY,      /* arg1 = int* res=can fail */
			INPUT_SET_AUDIO_DELAY,      /* arg1 = int  res=can fail */
			INPUT_GET_SPU_DELAY,        /* arg1 = int* res=can fail */
			INPUT_SET_SPU_DELAY,        /* arg1 = int  res=can fail */

			/* Meta datas */
			INPUT_ADD_INFO,   /* arg1= char* arg2= char* arg3=...     res=can fail */
			INPUT_GET_INFO,   /* arg1= char* arg2= char* arg3= char** res=can fail */
			INPUT_DEL_INFO,   /* arg1= char* arg2= char*              res=can fail */
			INPUT_SET_NAME,   /* arg1= char* res=can fail    */

			/* Input config options */
			INPUT_ADD_OPTION,      /* arg1= char * arg2= char *  res=can fail*/

			/* Input properties */
			INPUT_GET_BYTE_POSITION,     /* arg1= int64_t *       res=    */
			INPUT_SET_BYTE_SIZE,         /* arg1= int64_t *       res=    */

			/* bookmarks */
			INPUT_GET_BOOKMARKS,   /* arg1= seekpoint_t *** arg2= int * res=can fail */
			INPUT_CLEAR_BOOKMARKS, /* res=can fail */
			INPUT_ADD_BOOKMARK,    /* arg1= seekpoint_t *  res=can fail   */
			INPUT_CHANGE_BOOKMARK, /* arg1= seekpoint_t * arg2= int * res=can fail   */
			INPUT_DEL_BOOKMARK,    /* arg1= seekpoint_t *  res=can fail   */
			INPUT_SET_BOOKMARK,    /* arg1= int  res=can fail    */

			/* On the fly input slave */
			INPUT_ADD_SLAVE        /* arg1= char * */
		}

        #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 module_config_t
		{
			public CONFIG_ITEM i_type;
		}

		#endregion

		#region vlc api interop
		const int AOUT_VOLUME_MAX = 1024;
		const int VOLUME_MAX = 200;
		const int DEFAULT_CHAN = 1;
		const String Playlist_Current = "item-change";
		const String Now_Playing = "Now Playing";
		const String Meta_information = "Meta-information";
		const String Meta_title = "meta-title";
		const String Meta_author = "meta-author";
		const String Meta_artist = "meta-artist";
		const String Meta_genre = "meta-genre";
		const String Meta_description = "meta-description";
		const String Meta_url = "meta-url";
		
		[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);

		[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 int VLC_PlaylistIndex(int vlcObject);
		[DllImport("libvlc")]
		static extern int VLC_PlaylistNumberOfItems(int vlcObject);

		[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);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		delegate int VarChangedCallback(IntPtr vlc, String variable, vlc_value_t old_val, 
			vlc_value_t new_val, IntPtr param);

		[DllImport("libvlc")]
		static extern int __var_AddCallback(IntPtr vlc, String variable, VarChangedCallback cb, 
			IntPtr param);
		[DllImport("libvlc")]
		static extern int __var_DelCallback(IntPtr vlc, String variable, VarChangedCallback cb, 
			IntPtr param);
		[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, CharSet=CharSet.Ansi)]
		static extern VlcError input_Control(IntPtr input_thread_t, input_query_e i_query, String category, String name,
			ref IntPtr result);

		[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl)]
		static extern void __vout_OSDMessage(IntPtr p_input, int i_channel, String message);
		[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);

		[DllImport("libvlc")]
		static extern int __config_GetInt(IntPtr vlc, String name);
		[DllImport("libvlc")]
		static extern float __config_GetFloat(IntPtr vlc, String name);
		[DllImport("libvlc")]
		static extern String __config_GetPsz(IntPtr vlc, String name);

		#endregion

		static NativeLibVlc()
		{
			NativeLibVlc.vlcInstallDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase).Substring(6);
			//NativeLibVlc.vlcInstallDirectory = Environment.CurrentDirectory;
			//NativeLibVlc.vlcInstallDirectory = QueryVlcInstallPath();
		}

		public NativeLibVlc()
        {
        }

        #region IDisposable
        public void Dispose()
        {
            if(vlcHandle != -1)
            {
                try
                {
					if(this.gch.IsAllocated)
					{
						UnhookPlaylistChanges();
					}
					VideoOutput = null;
					VLC_CleanUp(this.vlcHandle);
                    VLC_Destroy(this.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 static 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 event MetaDataEventHandler NowPlaying;

		protected virtual void OnNowPlaying(MetaDataUpdateEventArgs args)
		{
			if(this.NowPlaying != null)
			{
				this.NowPlaying(this, args);
			}
		}

		protected delegate void HandleNowPlaying(MetaDataUpdateEventArgs args);

		protected virtual void VlcNowPlayingChanged(String newText)
		{
			// switch out of the Vlc thread to our User Interface thread if possible
			if(this.VideoOutput != null)
			{
				this.VideoOutput.BeginInvoke(new HandleNowPlaying(OnNowPlaying),
					new MetaDataUpdateEventArgs(MetaData.NowPlaying, newText));
			}
			else
			{
				OnNowPlaying(new MetaDataUpdateEventArgs(MetaData.NowPlaying, newText));
			}
		}

        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
				{
					return VLC_PlaylistIndex(this.vlcHandle);
				}
				catch(Exception ex)
				{
					this.lastErrorMessage = ex.Message;
					return -1;
				}
			}
		}

		public int PlaylistCount
		{
			get
			{
				try
				{
					return VLC_PlaylistNumberOfItems(this.vlcHandle);
				}
				catch(Exception ex)
				{
					this.lastErrorMessage = ex.Message;
					return -1;
				}
			}
		}

        #endregion

        #region public Methods
        public bool Initialize()
        {
            // check if already initializes
            if(vlcHandle != -1)
                return true;

			string oldDir = Environment.CurrentDirectory;
			// try init
			try
			{
				// create instance
				Environment.CurrentDirectory = NativeLibVlc.vlcInstallDirectory;
				this.vlcHandle = VLC_Create();

				if(this.vlcHandle < 0)
				{
					lastErrorMessage = "Failed to create VLC instance";
					return false;
				}

				string[] initOptions = {	NativeLibVlc.vlcInstallDirectory,
											":no-one-instance",
											":no-loop",
											":no-drop-late-frames",
											":disable-screensaver",
											":vout=vout_directx",
											"--plugin-path=" + NativeLibVlc.vlcInstallDirectory + @"\plugins",
					};

				// init libvlc
				VlcError errVlcLib = VLC_Init(vlcHandle, initOptions.Length, initOptions);
				if(errVlcLib != VlcError.Success)
				{
					VLC_Destroy(vlcHandle);
					lastErrorMessage = "Failed to initialise VLC";
					this.vlcHandle = -1;
					return false;
				}
			}
			catch
			{
				lastErrorMessage = "Could not find libvlc";
				return false;
			}
			finally
			{
				Environment.CurrentDirectory = oldDir;
			}

            // check output window
            if(outputWindow != null)
            {
				SetVlcObjectInt(ObjectType.VLC_OBJECT_VLC, "drawable", outputWindow.Handle.ToInt32());
			}

            return true;
        }

		// there's an overhead to supporting Vlc events, a memory leak, so we need to have them off by default
		public bool ProducingEvents
		{
			get { return this.gch.IsAllocated; }
			set
			{
				if(value)
				{
					if(!this.gch.IsAllocated)
					{
						HookPlaylistChanges();
					}
				}
				else
				{
					if(this.gch.IsAllocated)
					{
						UnhookPlaylistChanges();
					}
				}
			}
		}

		private static String AdjustFilterString(String current, String filter, bool add)
		{
			String newFilter = null;
			int findFilter = current.IndexOf(filter);
			if(findFilter == -1)
			{
				if(add)
				{
					if(current.Length == 0)
					{
						newFilter = filter;
					}
					else
					{
						newFilter = String.Format("{0}:{1}", current, filter);
					}
				}
			}
			else
			{
				if(!add)
				{
					int colonAfterAdjust = current.IndexOf(':', findFilter + 1);
					if(findFilter == 0)
					{
						if(colonAfterAdjust == -1)
						{
							newFilter = String.Empty;
						}
						else
						{
							newFilter = current.Substring(colonAfterAdjust + 1);
						}
					}
					else
					{
						if(colonAfterAdjust == -1)
						{
							newFilter = current.Substring(0, findFilter - 1);
						}
						else
						{
							newFilter = current.Substring(0, findFilter - 1) +
								current.Substring(colonAfterAdjust);
						}
					}
				}
			}
			return newFilter;
		}

		const String VideoFilterList = "vout-filter";
		const String AdjustFilter = "adjust";

		public bool AllowVideoAdjustments
		{
			get
			{
				String voutFilter = GetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, VideoFilterList, null);
				if(voutFilter == null)
				{
					GetConfigVariable(VideoFilterList, out voutFilter);
				}
				if(voutFilter != null)
				{
					return voutFilter.IndexOf(AdjustFilter) != -1;
				}
				else
				{
					return false;
				}
			}
			set
			{
				bool useConfig = false;
				String voutFilter = GetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, VideoFilterList, null);
				if(voutFilter == null)
				{
					using(VlcObject vlc = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_VLC))
					{
						GetConfigVariable(VideoFilterList, out voutFilter);
						useConfig = true;
					}
				}
				if(voutFilter != null)
				{
					String newVoutFilter = AdjustFilterString(voutFilter, AdjustFilter, value);
					if(newVoutFilter != null)
					{
						if(useConfig)
						{
							SetConfigVariable(VideoFilterList, newVoutFilter);
						}
						else
						{
							SetVlcObjectString(ObjectType.VLC_OBJECT_VOUT, VideoFilterList, newVoutFilter);
						}
					}
				}
			}
		}

		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_STOP);
					}
					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;
			}
		}

		public VlcError GetConfigVariable(String name, out String value)
		{
			value = null;
			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;
				}

				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 result = (__config_GetInt(vlc.SubObject, name) == 0);
							value = result.ToString();
						}
						break;
					case CONFIG_ITEM.CONFIG_ITEM_INTEGER:
						{
							int intResult = __config_GetInt(vlc.SubObject, name);
							value = intResult.ToString();
						}
						break;
					case CONFIG_ITEM.CONFIG_ITEM_FLOAT:
						{
							float floatResult = __config_GetFloat(vlc.SubObject, name);
							value = floatResult.ToString();
						}
						break;
					case CONFIG_ITEM.CONFIG_ITEM_STRING:
						value = __config_GetPsz(vlc.SubObject, name);
						break;
					default:
						return VlcError.BadVar;
					}
				}
				catch(Exception e)
				{
					this.lastErrorMessage = e.Message;
					return VlcError.Exception;
				}
			}
			return VlcError.Success;
		}

		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;
				}
				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.BadVar;
					}
				}
				catch(Exception e)
				{
					this.lastErrorMessage = e.Message;
					return VlcError.Exception;
				}
			}
			return VlcError.Success;
		}

        #endregion

		#region private members, properties and methods

		private static string vlcInstallDirectory = "";
		private int vlcHandle = -1;
		private Control outputWindow = null;
		private string lastErrorMessage = "";
		private int artificialLength;
		private double timeScaling;
		private GCHandle gch;
		private VarChangedCallback currentTrackCallback;
		private string previousNowPlaying = String.Empty;

        /// -------------------------------------------------------------------
        /// <summary>
        /// Method name      :   QueryVlcInstallPath
        /// Author         :   Odysee
        ///   Date         :   10.11.2006
        /// </summary>
        /// -------------------------------------------------------------------
        private static string QueryVlcInstallPath()
        {
            // open registry
            RegistryKey regkeyVlcInstallPathKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\VideoLAN\VLC");
            if(regkeyVlcInstallPathKey == null)
                return "";
            return (string)regkeyVlcInstallPathKey.GetValue("InstallDir","");
        }

		private void HookPlaylistChanges()
		{
			using(VlcObject vlc = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
			{
				if(vlc.SubObject != IntPtr.Zero)
				{
					this.gch = GCHandle.Alloc(this);
					this.currentTrackCallback = new VarChangedCallback(CurrentTrackChanged);

					int isSet = __var_AddCallback(vlc.SubObject, Playlist_Current,
						this.currentTrackCallback, (IntPtr)this.gch);
					//Debug.WriteLine("__var_AddCallback playlistObject = " + isSet.ToString());
				}
			}
		}

		private void UnhookPlaylistChanges()
		{
			using(VlcObject vlc = new VlcObject(this.vlcHandle, ObjectType.VLC_OBJECT_PLAYLIST))
			{
				if(vlc.SubObject != IntPtr.Zero)
				{
					__var_DelCallback(vlc.SubObject, Playlist_Current,
						this.currentTrackCallback, (IntPtr)this.gch);
				}
			}
			this.gch.Free();
		}

		private static int CurrentTrackChanged(IntPtr vlc, String variable, vlc_value_t old_val,
			vlc_value_t new_val, IntPtr param)
		{
			//Debug.WriteLine("CurrentTrackChanged: " + new_val.i_int.ToString());
			GCHandle gch = (GCHandle)param;
			NativeLibVlc thisVlc = (NativeLibVlc)gch.Target;
			try
			{
				using(VlcObject vobj = new VlcObject(thisVlc.vlcHandle, ObjectType.VLC_OBJECT_INPUT))
				{
					if(vobj.SubObject != IntPtr.Zero)
					{
						IntPtr resultString = IntPtr.Zero;
						input_Control(vobj.SubObject, input_query_e.INPUT_GET_INFO,
							Meta_information, Now_Playing, ref resultString);
						String nowPlaying = Marshal.PtrToStringAnsi(resultString);
						if(nowPlaying != thisVlc.previousNowPlaying)
						{
							thisVlc.previousNowPlaying = nowPlaying;
							Debug.WriteLine(String.Format("nowPlaying: {0}", nowPlaying));
							thisVlc.VlcNowPlayingChanged(nowPlaying);
						}
					}
				}
			}
			catch(Exception ex)
			{
				thisVlc.lastErrorMessage = ex.Message;
			}
			return (int)VlcError.Success;
		}

        #endregion
	}

	/* future features

    add_bool( "brightness-threshold", 0, NULL,
              THRES_TEXT, THRES_LONGTEXT, VLC_FALSE );
	 */
}