原文 http://www.helyar.net/2009/libvlc-media-player-in-c-part-2/

I gave some simplified VLC media player code in part 1 to show how easy it was to do and how most wrapper libraries make a mountain out of a mole hill. In that entry, I briefly touched on using some classes to make it easier and safer to implement actual programs with this.

The first thing to do is write a wrapper for the exceptions, so that they are handled nicely in C#. For a program using the library, exceptions should be completely transparent and should be handled in the normal try/catch blocks without having to do anything like initialise them or check them.

Another thing to do is to move all of the initialisation functions into constructors and all of the release functions into destuctors or use the System.IDisposable interface.

Here is the code listing for the 4 classes used (VlcInstance, VlcMedia, VlcMediaPlayer and VlcException). Note that the first 3 of these are very similar and that the main difference is that the media player class has some extra functions for doing things like playing and pausing the content.

class VlcInstance : IDisposable
{
internal IntPtr Handle;
 
public VlcInstance(string[] args)
{
VlcException ex = new VlcException();
Handle = LibVlc.libvlc_new(args.Length, args, ref ex.Ex);
if (ex.IsRaised) throw ex;
}
 
public void Dispose()
{
LibVlc.libvlc_release(Handle);
}
}
 
class VlcMedia : IDisposable
{
internal IntPtr Handle;
 
public VlcMedia(VlcInstance instance, string url)
{
VlcException ex = new VlcException();
Handle = LibVlc.libvlc_media_new(instance.Handle, url, ref ex.Ex);
if (ex.IsRaised) throw ex;
}
 
public void Dispose()
{
LibVlc.libvlc_media_release(Handle);
}
}
 
class VlcMediaPlayer : IDisposable
{
internal IntPtr Handle;
private IntPtr drawable;
private bool playing, paused;
 
public VlcMediaPlayer(VlcMedia media)
{
VlcException ex = new VlcException();
Handle = LibVlc.libvlc_media_player_new_from_media(media.Handle, ref ex.Ex);
if (ex.IsRaised) throw ex;
}
 
public void Dispose()
{
LibVlc.libvlc_media_player_release(Handle);
}
 
public IntPtr Drawable
{
get
{
return drawable;
}
set
{
VlcException ex = new VlcException();
LibVlc.libvlc_media_player_set_drawable(Handle, value, ref ex.Ex);
if (ex.IsRaised) throw ex;
drawable = value;
}
}
 
public bool IsPlaying { get { return playing && !paused; } }
 
public bool IsPaused { get { return playing && paused; } }
 
public bool IsStopped { get { return !playing; } }
 
public void Play()
{
VlcException ex = new VlcException();
LibVlc.libvlc_media_player_play(Handle, ref ex.Ex);
if (ex.IsRaised) throw ex;
 
playing = true;
paused = false;
}
 
public void Pause()
{
VlcException ex = new VlcException();
LibVlc.libvlc_media_player_pause(Handle, ref ex.Ex);
if (ex.IsRaised) throw ex;
 
if (playing)
paused ^= true;
}
 
public void Stop()
{
VlcException ex = new VlcException();
LibVlc.libvlc_media_player_stop(Handle, ref ex.Ex);
if (ex.IsRaised) throw ex;
 
playing = false;
paused = false;
}
}
 
class VlcException : Exception
{
internal libvlc_exception_t Ex;
 
public VlcException() : base()
{
Ex = new libvlc_exception_t();
LibVlc.libvlc_exception_init(ref Ex);
}
 
public bool IsRaised { get { return LibVlc.libvlc_exception_raised(ref Ex) != 0; } }
 
public override string Message { get { return LibVlc.libvlc_exception_get_message(ref Ex); } }
}

Using these classes is even easier than before, can use proper exception handling (removed for brevity) and cleans up better at the end. In this example, I have added an OpenFileDialog, which is where the file is loaded.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
 
namespace MyLibVLC
{
public partial class Form1 : Form
{
VlcInstance instance;
VlcMediaPlayer player;
 
public Form1()
{
InitializeComponent();
 
openFileDialog1.FileName = "";
openFileDialog1.Filter = "MPEG|*.mpg|AVI|*.avi|All|*.*";
 
string[] args = new string[] {
"-I", "dummy", "--ignore-config",
@"--plugin-path=C:\Program Files (x86)\VideoLAN\VLC\plugins",
"--vout-filter=deinterlace", "--deinterlace-mode=blend"
};
 
instance = new VlcInstance(args);
player = null;
}
 
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if(player != null) player.Dispose();
instance.Dispose();
}
 
private void Open_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() != DialogResult.OK)
return;
 
using (VlcMedia media = new VlcMedia(instance, openFileDialog1.FileName))
{
if (player != null) player.Dispose();
player = new VlcMediaPlayer(media);
}
 
player.Drawable = panel1.Handle;
}
 
private void Play_Click(object sender, EventArgs e)
{
player.Play();
}
 
private void Pause_Click(object sender, EventArgs e)
{
player.Pause();
}
 
private void Stop_Click(object sender, EventArgs e)
{
player.Stop();
}
}
}

Update:

I have just corrected a minor bug (the wrong release function being called on the player handle) and uploaded the full Visual Studio 2005 project. You can download the full project here (or see 1.1.2 version below). It comes with the libvlc.dll and libvlccore.dll for VLC 1.0.1 in the bin\x86\Debug directory so if you have a version other than this, just overwrite those files.

Update for VLC 1.1.2:

You can now download the VLC 1.1.2 compatible version. There were some changes to the way libvlc handles exceptions that needed to be corrected. Other than that, there were a couple of minor function name changes.

Please use these posts as a starting point to use your own code though. These posts are intended to stoppeople from being reliant on the already existing, large, overcomplicated and quickly outdated libraries. They are not intended to be just another library for people to blindly use without understanding how it works. You can use this to learn how to write your own native interop code on a well designed library then adapt it for your own changes and keep it up to date with whichever version of VLC you want. This also means you never have to use the terrible code on pinvoke.net for other libraries, as you can write your own from the original documentation and it will almost always be better.

Bugfix: VlcException should use Marshal.PtrToStringAnsi not Marshal.PtrToStringAuto

最新文章

  1. Ubuntu+Apache+PHP+Mysql环境搭建
  2. [嵌入式开发板]iTOP-4412开发板linux 系统存储空间的修改
  3. -ffunction-sections -Wl,--gc-sections
  4. C# 之 Int16 Int32 Int64 的区别
  5. OpenCV 显示Mat矩阵异常 显示“程序停止工作” 解决办法
  6. Java学习----集合函数
  7. Qt 技巧: 解决未解析的SSL问题
  8. jQuery组织您钞四----jQuery操作DOM
  9. bzoj2628: JZPSTR
  10. flask mega-tutorial 1.0 documentation学习记录
  11. 队列详解及java实现
  12. 航班座位_hihocoder
  13. Linux生成私钥和公钥免密连接
  14. 关于Mac的rootless问题
  15. 网易2018.03.27算法岗,三道编程题100%样例AC题解
  16. bootstrap 3.0 LESS源代码浅析(二)
  17. Maven本地库_remote.repositories文件
  18. subline 自己使用的插件
  19. OSS介绍
  20. Ettercap之ARP+DNS欺骗

热门文章

  1. head first c<11>在根据网络编程
  2. apache本地多域配置(wampserver本地多域配置)
  3. hibernate在地图的方法之一协会
  4. 【Eclipse高速发展-文章插件】google V8,对于调试Nodejs
  5. 它们的定义TextView使之具有跑马灯的效果
  6. Mac周边环境 goBASIC语言HelloWorld
  7. POJ 1252 Euro Efficiency
  8. Linux在device is busy处理
  9. hibernate Disabling contextual LOB creation as connection was null
  10. 【Machine Learning】Mahout基于协同过滤(CF)的用户推荐