Thanks folks. I've written this helper class for locating the VLC installation and plugins folder, and for adding them to the path environment variable without messing about with .bat files.
Code: Select all
using System;
using Microsoft.Win32; // for registry access
using System.IO; // for Path
namespace Simon
{
/// <summary>
/// Static class containing methods and properties which are useful when
/// using libvlc from a .net application.
/// </summary>
public static class VlcHelpers
{
private static string _vlcInstallationFolder;
#region AddVlcToPath method
/// <summary>
/// Looks in the registry to see where VLC is installed, and temporarily
/// adds that folder to the PATH environment variable, so that the
/// runtime is able to locate libvlc.dll and other libraries that it
/// depends on, without needing to copy them all to the folder where
/// your application is.
/// </summary>
public static void AddVlcToPath()
{
// Get the current value of the PATH environment variable
string currentPath = Environment.GetEnvironmentVariable( "PATH" );
System.Diagnostics.Debug.WriteLine( "Current path: " + currentPath );
// Concatenate the VLC installation and plugins folders onto the
// current path
string newPath = VlcInstallationFolder + ";"
+ VlcPluginsFolder + ";"
+ currentPath;
System.Diagnostics.Debug.WriteLine( "New path: " + newPath );
// Update the PATH environment variable
Environment.SetEnvironmentVariable( "PATH", newPath );
}
#endregion
#region VlcInstallationFolder property
/// <summary>
/// Gets the location of the folder where VLC is installed, from the
/// registry.
/// </summary>
public static string VlcInstallationFolder
{
get
{
if( _vlcInstallationFolder == null )
{
RegistryKey vlcKey = Registry.LocalMachine.CreateSubKey( @"SOFTWARE\VideoLAN\VLC" );
_vlcInstallationFolder = (string) vlcKey.GetValue( "InstallDir" )
+ Path.DirectorySeparatorChar;
vlcKey.Close();
}
return _vlcInstallationFolder;
}
}
#endregion
#region VlcPluginsFolder property
/// <summary>
/// Gets the location of the VLC plugins folder.
/// </summary>
public static string VlcPluginsFolder
{
get
{
return VlcInstallationFolder
+ "plugins"
+ Path.DirectorySeparatorChar;
}
}
#endregion
}
}
And now all three wrappers seem to be quite happily referencing libvlc.dll from it's home in the VLC installation folder without having to copy it anywhere, provided I add a call to that AddVlcToPath method before any attempt is made to call any of the libvlc code (I've put it right at the beginning of the Main method in Program.cs in each case).
But I don't seem to be able to reference the plugins folder the same way. The VlcUserControl seems to be OK without its own copy of that folder (subject to another issue - see below), but the Meedios and Marx wrappers seem to need their own copies.
If I run the Meedios wrapper without its own copy of the plugins folder, I get the following:
[00000001] main libvlc debug: VLC media player - version 0.9.6 Grishenko - (c) 1
996-2008 the VideoLAN team
[00000001] main libvlc debug: libvlc was configured with ./configure '--host=i5
86-mingw32msvc' '--build=i386-linux' '--enable-mkv' '--enable-release' '--withou
t-contrib' '--enable-nls' '--enable-shared-libvlc' '--enable-update-check' '--en
able-lua' '--enable-faad' '--enable-flac' '--enable-theora' '--enable-twolame' '
--enable-quicktime' '--enable-real' '--enable-realrtsp' '--enable-ffmpeg' '--wit
h-ffmpeg-mp3lame' '--with-ffmpeg-faac' '--with-ffmpeg-config-path=/usr/win32/bin
' '--with-ffmpeg-zlib' '--enable-live555' '--with-live555-tree=/usr/win32/live.c
om' '--ena
[00000001] main libvlc debug: translation test: code is "C"
[00000001] main libvlc error: no memcpy module matched "any"
[00000007] main access error: no access module matched "file"
[00000006] main input error: open of `file/xspf-open://I:\Documents and Settings
\simon\Application Data\vlc\ml.xspf' failed: could not create access: no access
module matched "file"
[00000010] main interface error: no interface module matched "hotkeys,none"
[00000010] main interface error: no suitable interface module
[00000001] main libvlc error: interface "hotkeys,none" initialization failed
State: Opening
[00000013] main access error: no access module matched "dvb"
[00000011] main input error: open of `dvb://' failed: could not create access: n
o access module matched "dvb"
State: Error
Followed by a
System.Exception: No active video output
at VideoLan.libvlc_exception_t.CheckException() in i:\Documents and Settings\simon\My Documents\SharpDevelop Projects\VlcWrapper\VideoLan.Interop\InteropMethods.cs:line 49
at VideoLan.VlcVideo.set_FullScreen(Boolean value) in i:\Documents and Settings\simon\My Documents\SharpDevelop Projects\VlcWrapper\VideoLan.Interop\VLC\VlcVideo.cs:line 56
at DVBsharp.MainClass.Main(String[] args) in i:\Documents and Settings\simon\My Documents\SharpDevelop Projects\VlcWrapper\VideoLan.Interop.Example\Program.cs:line 87
... whereas if I run it with its own copy of the plugins folder, I get
[00000001] main libvlc debug: VLC media player - version 0.9.6 Grishenko - (c) 1
996-2008 the VideoLAN team
[00000001] main libvlc debug: libvlc was configured with ./configure '--host=i5
86-mingw32msvc' '--build=i386-linux' '--enable-mkv' '--enable-release' '--withou
t-contrib' '--enable-nls' '--enable-shared-libvlc' '--enable-update-check' '--en
able-lua' '--enable-faad' '--enable-flac' '--enable-theora' '--enable-twolame' '
--enable-quicktime' '--enable-real' '--enable-realrtsp' '--enable-ffmpeg' '--wit
h-ffmpeg-mp3lame' '--with-ffmpeg-faac' '--with-ffmpeg-config-path=/usr/win32/bin
' '--with-ffmpeg-zlib' '--enable-live555' '--with-live555-tree=/usr/win32/live.c
om' '--ena
[00000001] main libvlc debug: translation test: code is "C"
State: Opening
[00000740] main input error: open of `dvb://' failed: could not create access
State: Error
... followed by the same "No active video output" exception.
(OK, it's still not working, but I'm guessing that's a separate issue to the problem of calling the unmanaged code).
Meanwhile if I run the Marx wrapper without its own copy of the plugins folder, I get
[00000001] main libvlc debug: VLC media player - version 0.9.6 Grishenko - (c) 1
996-2008 the VideoLAN team
[00000001] main libvlc debug: libvlc was configured with ./configure '--host=i5
86-mingw32msvc' '--build=i386-linux' '--enable-mkv' '--enable-release' '--withou
t-contrib' '--enable-nls' '--enable-shared-libvlc' '--enable-update-check' '--en
able-lua' '--enable-faad' '--enable-flac' '--enable-theora' '--enable-twolame' '
--enable-quicktime' '--enable-real' '--enable-realrtsp' '--enable-ffmpeg' '--wit
h-ffmpeg-mp3lame' '--with-ffmpeg-faac' '--with-ffmpeg-config-path=/usr/win32/bin
' '--with-ffmpeg-zlib' '--enable-live555' '--with-live555-tree=/usr/win32/live.c
om' '--ena
[00000001] main libvlc debug: translation test: code is "C"
[00000001] main libvlc error: no memcpy module matched "any"
[00000359] main access error: no access module matched "file"
[00000358] main input error: open of `file/xspf-open://I:\Documents and Settings
\simon\Application Data\vlc\ml.xspf' failed: could not create access: no access
module matched "file"
[00000362] main interface error: no interface module matched "hotkeys,none"
[00000362] main interface error: no suitable interface module
[00000001] main libvlc error: interface "hotkeys,none" initialization failed
*** LibVLC Exception not handled: No active input
Set a breakpoint in 'libvlc_exception_not_handled' to debug.
[00000365] main access error: no access module matched "http"
[00000363] main input error: open of `
http://160.79.128.61:7244' failed: could n
ot create access: no access module matched "http"
... and if I run it with its own copy of the plugins folder, I get
[00000001] main libvlc debug: VLC media player - version 0.9.6 Grishenko - (c) 1
996-2008 the VideoLAN team
[00000001] main libvlc debug: libvlc was configured with ./configure '--host=i5
86-mingw32msvc' '--build=i386-linux' '--enable-mkv' '--enable-release' '--withou
t-contrib' '--enable-nls' '--enable-shared-libvlc' '--enable-update-check' '--en
able-lua' '--enable-faad' '--enable-flac' '--enable-theora' '--enable-twolame' '
--enable-quicktime' '--enable-real' '--enable-realrtsp' '--enable-ffmpeg' '--wit
h-ffmpeg-mp3lame' '--with-ffmpeg-faac' '--with-ffmpeg-config-path=/usr/win32/bin
' '--with-ffmpeg-zlib' '--enable-live555' '--with-live555-tree=/usr/win32/live.c
om' '--ena
[00000001] main libvlc debug: translation test: code is "C"
*** LibVLC Exception not handled: No active input
Set a breakpoint in 'libvlc_exception_not_handled' to debug.
[00000379] access_http access: Raw-audio server found, mp3 demuxer selected
and music streamed to me across the internet
These results are the same, regardless of whether or not my AddVlcToPath method adds the plugins folder to the path environment variable or not.
See
my post regarding the wrapper from the Medios link.
You shouldn't have to copy any dll's or plugins anywhere if you pass the VLC installation folder path as the argument of the VideoLanClient constructor. You should be able to get this path from the registry. On one XP computer I checked it was located at HKEY_LOCAL_MACHINE\SOFTWARE\VideoLAN\VLC with the name InstallDir. Visual Studio C# has functions that make this easy. This means your software doesn't require any configuration or file copying as long as VLC player is installed.
I've done just that, and I've found the Meedios wrapper works just fine with or without its own copy of the plugins folder, as long as I pass the result of my VlcInstallationFolder property to the VideoLanClient constructor.
This is what I'm getting from that wrapper now:
[00000001] main libvlc debug: VLC media player - version 0.9.6 Grishenko - (c) 1
996-2008 the VideoLAN team
[00000001] main libvlc debug: libvlc was configured with ./configure '--host=i5
86-mingw32msvc' '--build=i386-linux' '--enable-mkv' '--enable-release' '--withou
t-contrib' '--enable-nls' '--enable-shared-libvlc' '--enable-update-check' '--en
able-lua' '--enable-faad' '--enable-flac' '--enable-theora' '--enable-twolame' '
--enable-quicktime' '--enable-real' '--enable-realrtsp' '--enable-ffmpeg' '--wit
h-ffmpeg-mp3lame' '--with-ffmpeg-faac' '--with-ffmpeg-config-path=/usr/win32/bin
' '--with-ffmpeg-zlib' '--enable-live555' '--with-live555-tree=/usr/win32/live.c
om' '--ena
[00000001] main libvlc debug: translation test: code is "C"
State: Opening
[00001092] main input error: open of `dvb://' failed: could not create access
State: Error
(I'm using the code posted by BexX at
viewtopic.php?f=32&t=47385&start=90#p173109 to do this)
I guess this means my unmanaged DLL resolution issues are resolved now for the Meedios wrapper, and I just need to do some more reading to find out what dvb:// is and what tweaks I need to make to BexX's code to point it at media files from my local disk.
Back to the VlcUserControl...
I now find that, when I call the AddVlcToPath method from the Main method of Program.cs in the windows forms app which contains this control, I get the following written to the Debug stream:
System.EntryPointNotFoundException: Unable to find an entry point named 'vlc_current_object' in DLL 'libvlc'.
at VLanControl.NativeLibVlc.vlc_current_object(Int32 i_object)
at VLanControl.NativeLibVlc.set_Volume(Int32 value) in i:\Documents and Settings\simon\My Documents\SharpDevelop Projects\VlcWrapper\VLanControl\NativeLibVlc.cs:line 1087
at VLanControl.VlcUserControl.set_Volume(Int32 value) in i:\Documents and Settings\simon\My Documents\SharpDevelop Projects\VlcWrapper\VLanControl\VlcUserControl.cs:line 379
at VlcWrapper.MainForm..ctor() in i:\Documents and Settings\simon\My Documents\SharpDevelop Projects\VlcWrapper\VlcWrapper\MainForm.cs:line 49
And this happens regardless of whether or not it has its own copy of the plugins folder. I guess this exception has been caught and handled, but does it mean I'm still missing a reference to part of libvlc or its dependents?