...
 
Commits (60)
<!---
Please read this!
Before opening a new issue, make sure to search for keywords in the issues
filtered by "bug" label and verify the issue you're about to submit isn't a duplicate.
If this is a question please ask on StackOverflow: https://stackoverflow.com/questions/tagged/libvlcsharp.
--->
### Summary
<!-- Summarize the bug encountered concisely -->
### Minimal project and steps to reproduce
<!-- How one can reproduce the issue - this is very important
Provide a Minimal, Complete, and Verifiable example (https://stackoverflow.com/help/mcve) through a git hosting platform
and post the URL here. If you don't provide this, we may not be able to help and may close the issue.
Please also provide the functional steps to reproduce the behavior (if necessary):
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
-->
### What is the current *bug* behavior?
<!-- What actually happens -->
### What is the expected *correct* behavior?
<!-- What you should see instead -->
### Relevant logs and/or screenshots
<!-- Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it's very hard to read otherwise. -->
### Environment
<!-- Please complete the following information. -->
- OS: <!-- [e.g. iOS] -->
- Version <!-- [e.g. 22] -->
- Device: <!-- [e.g. iPhone6] -->
- LibVLC version and architecture <!-- [e.g. 3.0.6, x64] -->
- LibVLCSharp version <!-- [e.g. 0.7.0] -->
### Possible fixes
<!-- If you can, link to the line of code that might be responsible for the problem -->
\ No newline at end of file
### Problem to solve
<!-- What problem do we solve? -->
### Intended users
<!-- Who will use this feature? -->
### Proposal
<!-- How are we going to solve the problem? -->
<!-- Include use cases, benefits, and/or goals -->
### Documentation
<!-- What kind of documentation is needed for this feature? -->
\ No newline at end of file
Please follow the VideoLAN Code of Conduct: https://wiki.videolan.org/Code_of_Conduct/
\ No newline at end of file
......@@ -23,4 +23,7 @@
<PropertyGroup Condition="$(TargetFramework.StartsWith('MonoAndroid'))">
<DefineConstants>$(DefineConstants);MONO;ANDROID</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="$(TargetFramework.StartsWith('uap'))">
<DefineConstants>$(DefineConstants);UWP;NET</DefineConstants>
</PropertyGroup>
</Project>
\ No newline at end of file
# Requirements
Make sure you have the proper SDK installed for your target platform. The **Xamarin** workloads, the .NET desktop components, the GTK# one, etc. depending on your needs.
# Getting started
Clone https://code.videolan.org/mfkl/libvlcsharp-samples to get started and explore the samples.
The `MinimalPlayback` one provides a simple approach to getting video on the screen quickly.
The steps are:
1. Instantiate a `VideoView` and add it to your main View.
2. Call `Core.Initialize()` to load the `libvlc` native libraries, depending on your host platform.
3. The `VideoView` offers a `MediaPlayer` object (with data-binding support) which you should create and set on the `VideoView`. The `MediaPlayer` allows you to control playback with APIs such as `Play`, `Pause`, set a new media or listen for playback events.
4. In case you are using `LibVLCSharp.Forms`, make sure to call `LibVLCSharpFormsRenderer.Init()` in your platform specific project [*before*](https://forums.xamarin.com/discussion/comment/57605/#Comment_57605) `Xamarin.Forms.Forms.Init` is called. See the [Forms sample](https://github.com/videolan/libvlcsharp/tree/master/Samples/Forms).
# Platform-specific caveats
When building LibVLCSharp, we tried really hard to provide a unified experience to all developpers.
Despite our efforts, there are some cases where we had no choice but to make some hacks.
Sometimes, the hacks are hidden into LibVLCSharp's code, but sometimes, you'll need to write extra code.
## WPF
### The airspace issue
*This issue also occurs in LVS.Forms.WPF, but no mitigation technique has been implemented yet.*
tl;dr : If you need to put content over your video, place it inside the control, like this:
```xml
<lvs:VideoView>
<Grid>
<TextBlock>This content will be rendered over the video</TextBlock>
</Grid>
</lvs:VideoView>
```
It will be rendered in a separate transparent window which is rendered over the video view.
Detailed explanation:
To display a Video in WPF, you don't have many solutions:
- Use `D3DImage` : This seems like a good idea to use DirectX to accelerate the rendering on screen. However, libvlc doesn't expose a way to use DirectX9 from an application, and even if it did, it wouldn't work. D3DImage tells you when it's ready for rendering, but libvlc has its own clock and wants to "push" content to the view.
- Use an `InteropBitmap`, as [Vlc.DotNet.Wpf](https://github.com/ZeBobo5/Vlc.DotNet/). With this, you have a real WPF `ImageSource` that you can use to make nice things in WPF (Blur effects, transformations...). However, copying a decoded image from libvlc to the .net buffer, and displaying it many times per second is really slow and uses too much CPU, especially for 4K videos...
- Use a `WindowsFormsHost`, which creates a Win32 window. The nice thing is that libvlc can use a Win32 window directly and use DirectX to draw the video on it directly, using the hardware acceleration.
We decided to implement the WPF control with the third solution. However, integrating a `WindowsFormsHost` inside a WPF application creates a window over the WPF content, meaning that the WPF content you write will never be above the WinForms content, here, the video.
This is a problem for many people because they want to display the play/pause controls over the video. This is why LibVLCSharp.WPF comes with its own wrapper to help users to mitigate this issue.
The idea is simple: since WinForms is a window over the WPF content, let's create another window over the WinForms window.
The content you place inside the `VideoView` is used for the window, like this:
```xml
<lvs:VideoView>
<Grid>
<TextBlock>This content will be rendered over the video</TextBlock>
</Grid>
</lvs:VideoView>
```
## UWP
These issues are issues of libvlc 3, that we hope to get fixed for libvlc 4
### LibVLC additionnal parameters
tl;dr : If you want to play a video with UWP, integrate the `VideoView` in your control, handle the `Loaded` event and then initialize your player with:
```cs
new LibVLC(VideoView.GetSwapChainOptions());
```
Detailed explanation:
In UWP here are mandatory options to be given to the LibVLC constructor. These options tells libvlc (and more precisely the DirectX plugin) where to output the video, using a so-called "swap chain".
This initialization step will disappear in libvlc 4, but for now, you will need to have a code similar to [this one](Samples/LibVLCSharp.UWP.Sample/MainPage.xaml.cs)
### Automatic audio output module selection
tl;dr : You don't have anything to do. This section explains how things work internally
Detailed explanation:
When you create a `new LibVLC()` in UWP, the `--aout=winstore` is automatically added. This means that you can't specify another `--aout` option in that constructor.
# Documentation
For usage of the API, you should check out the `libvlc` [C API documentation](https://www.videolan.org/developers/vlc/doc/doxygen/html/group__libvlc.html) which this wrapper follows closely.
\ No newline at end of file
# LibVLCSharp.Android.AWindow
This project is an implementation detail for LibVLCSharp on the android platform.
libvlc for android needs the AWindow class, which is provided by the Jars/org.videolan.libvlc.aar file.
This project generates Xamarin bindings for this java classes.
\ No newline at end of file
......@@ -26,8 +26,8 @@ Features:
- DVD playback and menu navigation.
</Description>
<TargetFramework>net47</TargetFramework>
<RootNamespace>LibVLCSharp.Forms.GTK</RootNamespace>
<PackageVersion>0.0.1</PackageVersion>
<RootNamespace>LibVLCSharp.Forms.Platforms.GTK</RootNamespace>
<PackageVersion>0.8.1</PackageVersion>
<PackageId>LibVLCSharp.Forms.GTK</PackageId>
<Authors>VideoLAN</Authors>
<Owners>VideoLAN</Owners>
......
# LibVLCSharp.Forms.GTK
[![NuGet Stats](https://img.shields.io/nuget/v/LibVLCSharp.Forms.GTK.svg)](https://www.nuget.org/packages/LibVLCSharp.Forms.GTK)
[![NuGet Stats](https://img.shields.io/nuget/dt/LibVLCSharp.Forms.GTK.svg)](https://www.nuget.org/packages/LibVLCSharp.Forms.GTK)
This package provides Xamarin.Forms support for GTK# apps that use LibVLCSharp.
## Why should I reference this package in my project?
If you are in this situation, this package is made for you:
- You want to have a native GTK app on Windows or Linux that makes use of your shared Xamarin.Forms XAML code.
For other platforms, see the [main documentation](../README.md)
\ No newline at end of file
......@@ -23,16 +23,20 @@ namespace LibVLCSharp.Forms.Platforms.GTK
if (e.OldElement != null)
{
e.OldElement.MediaPlayerChanged -= OnMediaPlayerChanged;
e.OldElement.MediaPlayerChanging -= OnMediaPlayerChanging;
}
if (e.NewElement != null)
{
e.NewElement.MediaPlayerChanged += OnMediaPlayerChanged;
e.NewElement.MediaPlayerChanging += OnMediaPlayerChanging;
if (Control.MediaPlayer != e.NewElement.MediaPlayer)
{
OnMediaPlayerChanging(this, new MediaPlayerChangingEventArgs(Control.MediaPlayer, e.NewElement.MediaPlayer));
}
}
}
private void OnMediaPlayerChanged(object sender, MediaPlayerChangedEventArgs e)
private void OnMediaPlayerChanging(object sender, MediaPlayerChangingEventArgs e)
{
if (Control == null)
{
......
......@@ -26,8 +26,8 @@ Features:
- DVD playback and menu navigation.
</Description>
<TargetFramework>net47</TargetFramework>
<RootNamespace>LibVLCSharp.Forms.WPF</RootNamespace>
<PackageVersion>0.3.0</PackageVersion>
<RootNamespace>LibVLCSharp.Forms.Platforms.WPF</RootNamespace>
<PackageVersion>0.8.1</PackageVersion>
<PackageId>LibVLCSharp.Forms.WPF</PackageId>
<Authors>VideoLAN</Authors>
<Owners>VideoLAN</Owners>
......
# LibVLCSharp.Forms.WPF
[![NuGet Stats](https://img.shields.io/nuget/v/LibVLCSharp.Forms.WPF.svg)](https://www.nuget.org/packages/LibVLCSharp.Forms.WPF)
[![NuGet Stats](https://img.shields.io/nuget/dt/LibVLCSharp.Forms.WPF.svg)](https://www.nuget.org/packages/LibVLCSharp.Forms.WPF)
This package provides Xamarin.Forms support for WPF Windows apps that use LibVLCSharp.
## Why should I reference this package in my project?
If you are in this situation, this package is made for you:
- You want to have a native WPF app on Windows that makes use of your shared Xamarin.Forms XAML code.
For other platforms, see the [main documentation](../README.md)
\ No newline at end of file
using LibVLCSharp.Shared;
using LibVLCSharp.Forms.Platforms.WPF;
using LibVLCSharp.Forms.Platforms.WPF;
using LibVLCSharp.Forms.Shared;
using LibVLCSharp.Shared;
using Xamarin.Forms.Platform.WPF;
[assembly: ExportRenderer(typeof(VideoView), typeof(VideoViewRenderer))]
......@@ -19,16 +19,20 @@ namespace LibVLCSharp.Forms.Platforms.WPF
if (e.OldElement != null)
{
e.OldElement.MediaPlayerChanged -= OnMediaPlayerChanged;
e.OldElement.MediaPlayerChanging -= OnMediaPlayerChanging;
}
if (e.NewElement != null)
{
e.NewElement.MediaPlayerChanged += OnMediaPlayerChanged;
e.NewElement.MediaPlayerChanging += OnMediaPlayerChanging;
if (Control.MediaPlayer != e.NewElement.MediaPlayer)
{
OnMediaPlayerChanging(this, new MediaPlayerChangingEventArgs(Control.MediaPlayer, e.NewElement.MediaPlayer));
}
}
}
private void OnMediaPlayerChanged(object sender, MediaPlayerChangedEventArgs e)
private void OnMediaPlayerChanging(object sender, MediaPlayerChangingEventArgs e)
{
Control.MediaPlayer = e.NewMediaPlayer;
}
......
<Project Sdk="MSBuild.Sdk.Extras/1.6.46">
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<Title>LibVLCSharp.Forms</Title>
<Summary>Xamarin.Forms integration for LibVLCSharp</Summary>
......@@ -30,7 +30,7 @@ Features:
<RootNamespace>LibVLCSharp.Forms</RootNamespace>
<NeutralLanguage>en</NeutralLanguage>
<LangVersion>7.3</LangVersion>
<Version>0.5.0</Version>
<Version>0.8.1</Version>
<PackageId>LibVLCSharp.Forms</PackageId>
<Authors>VideoLAN</Authors>
<Owners>VideoLAN</Owners>
......
......@@ -27,16 +27,20 @@ namespace LibVLCSharp.Forms.Platforms.Android
if (e.OldElement != null)
{
e.OldElement.MediaPlayerChanged -= OnMediaPlayerChanged;
e.OldElement.MediaPlayerChanging -= OnMediaPlayerChanging;
}
if (e.NewElement != null)
{
e.NewElement.MediaPlayerChanged += OnMediaPlayerChanged;
e.NewElement.MediaPlayerChanging += OnMediaPlayerChanging;
if (Control.MediaPlayer != e.NewElement.MediaPlayer)
{
OnMediaPlayerChanging(this, new MediaPlayerChangingEventArgs(Control.MediaPlayer, e.NewElement.MediaPlayer));
}
}
}
private void OnMediaPlayerChanged(object sender, MediaPlayerChangedEventArgs e)
private void OnMediaPlayerChanging(object sender, MediaPlayerChangingEventArgs e)
{
Control.MediaPlayer = e.NewMediaPlayer;
Control.TriggerLayoutChangeListener();
......
......@@ -22,16 +22,20 @@ namespace LibVLCSharp.Forms.Platforms.Mac
if (e.OldElement != null)
{
e.OldElement.MediaPlayerChanged -= OnMediaPlayerChanged;
e.OldElement.MediaPlayerChanging -= OnMediaPlayerChanging;
}
if (e.NewElement != null)
{
e.NewElement.MediaPlayerChanged += OnMediaPlayerChanged;
e.NewElement.MediaPlayerChanging += OnMediaPlayerChanging;
if (Control.MediaPlayer != e.NewElement.MediaPlayer)
{
OnMediaPlayerChanging(this, new MediaPlayerChangingEventArgs(Control.MediaPlayer, e.NewElement.MediaPlayer));
}
}
}
private void OnMediaPlayerChanged(object sender, MediaPlayerChangedEventArgs e)
private void OnMediaPlayerChanging(object sender, MediaPlayerChangingEventArgs e)
{
Control.MediaPlayer = e.NewMediaPlayer;
}
......
......@@ -24,16 +24,20 @@ namespace LibVLCSharp.Forms.Platforms.iOS
if (e.OldElement != null)
{
e.OldElement.MediaPlayerChanged -= OnMediaPlayerChanged;
e.OldElement.MediaPlayerChanging -= OnMediaPlayerChanging;
}
if (e.NewElement != null)
{
e.NewElement.MediaPlayerChanged += OnMediaPlayerChanged;
e.NewElement.MediaPlayerChanging += OnMediaPlayerChanging;
if (Control.MediaPlayer != e.NewElement.MediaPlayer)
{
OnMediaPlayerChanging(this, new MediaPlayerChangingEventArgs(Control.MediaPlayer, e.NewElement.MediaPlayer));
}
}
}
private void OnMediaPlayerChanged(object sender, MediaPlayerChangedEventArgs e)
private void OnMediaPlayerChanging(object sender, MediaPlayerChangingEventArgs e)
{
Control.MediaPlayer = e.NewMediaPlayer;
}
......
# LibVLCSharp.Forms
[![NuGet Stats](https://img.shields.io/nuget/v/LibVLCSharp.Forms.svg)](https://www.nuget.org/packages/LibVLCSharp.Forms)
[![NuGet Stats](https://img.shields.io/nuget/dt/LibVLCSharp.Forms.svg)](https://www.nuget.org/packages/LibVLCSharp.Forms)
This package provides Xamarin.Forms support for LibVLCSharp.
This package also contains the views for the following platforms:
- Android
- iOS
- Mac
[GTK](../LibVLCSharp.Forms.Platforms.GTK/README.md) and [WPF](../LibVLCSharp.Forms.Platforms.WPF/README.md) Forms support are in separate packages due to multi-targetting limitations.
This package has multiple target frameworks, which means it will pick the right features for your project (you will only get the mac view if you are building a mac project).
BE CAREFUL: This project does not include **LibVLC** itself! You will need to install it separately!
See the [Installation](../README.md#installation) documentation for more info.
## Why should I reference this package in my project?
If you are in this situation, this package is made for you:
- You want to build a Xamarin.Forms application (no matter on which platform) using LibVLCSharp.
For other platforms, see the [main documentation](../README.md)
\ No newline at end of file
......@@ -8,20 +8,19 @@ namespace LibVLCSharp.Forms.Shared
public class VideoView : View
{
/// <summary>
/// Raised when a new MediaPlayer is set and attached to the view
/// Raised when a new MediaPlayer is set and will be attached to the view
/// </summary>
public event EventHandler<MediaPlayerChangedEventArgs> MediaPlayerChanged;
public event EventHandler<MediaPlayerChangingEventArgs> MediaPlayerChanging;
/// <summary>
/// Raised after the first mediaplayer has been set.
/// This is mostly needed with LibVLCSharp.Forms.WPF to prevent timing issues regarding HWND creation.
/// It is safe to call Play() when Loaded has been raised.
/// Raised when a new MediaPlayer is set and attached to the view
/// </summary>
public event EventHandler Loaded;
public event EventHandler<MediaPlayerChangedEventArgs> MediaPlayerChanged;
public static readonly BindableProperty MediaPlayerProperty = BindableProperty.Create(nameof(MediaPlayer),
typeof(LibVLCSharp.Shared.MediaPlayer),
public static readonly BindableProperty MediaPlayerProperty = BindableProperty.Create(nameof(MediaPlayer),
typeof(LibVLCSharp.Shared.MediaPlayer),
typeof(VideoView),
propertyChanging: OnMediaPlayerChanging,
propertyChanged: OnMediaPlayerChanged);
/// <summary>
......@@ -33,14 +32,18 @@ namespace LibVLCSharp.Forms.Shared
set { SetValue(MediaPlayerProperty, value); }
}
private static void OnMediaPlayerChanging(BindableObject bindable, object oldValue, object newValue)
{
var videoView = (VideoView)bindable;
Debug.WriteLine("OnMediaPlayerChanging");
videoView.MediaPlayerChanging?.Invoke(videoView, new MediaPlayerChangingEventArgs(oldValue as LibVLCSharp.Shared.MediaPlayer, newValue as LibVLCSharp.Shared.MediaPlayer));
}
private static void OnMediaPlayerChanged(BindableObject bindable, object oldValue, object newValue)
{
var videoView = (VideoView)bindable;
Trace.WriteLine("OnMediaPlayerChanged");
Debug.WriteLine("OnMediaPlayerChanged");
videoView.MediaPlayerChanged?.Invoke(videoView, new MediaPlayerChangedEventArgs(oldValue as LibVLCSharp.Shared.MediaPlayer, newValue as LibVLCSharp.Shared.MediaPlayer));
if(oldValue == null && newValue != null) // assuming this is the first MediaPlayer set
videoView.Loaded?.Invoke(videoView, EventArgs.Empty);
}
}
}
\ No newline at end of file
......@@ -2,32 +2,20 @@
<PropertyGroup>
<Title>LibVLCSharp.GTK</Title>
<Summary>GTK integration for LibVLCSharp</Summary>
<Description>LibVLCSharp is a cross-platform audio and video API for .NET platforms based on VideoLAN's LibVLC Library.
It provides a comprehensive multimedia API that can be used across mobile, server and desktop to render video and output audio. Mono, .NET Framework and .NET Core runtimes are supported.
<Description>The official GTK# (mono/gtk-sharp) views for LibVLCSharp.
Supported platforms:
- Xamarin.Android
- Xamarin.iOS
- Xamarin.Mac
- Windows (WPF/WinForms)
- Xamarin.Forms
- .NET Standard 1.1
- .NET Core
This package contains the views that allows to display a video played with LibVLCSharp
in a GTK# app.
Features:
- Network browsing for distant filesystems (SMB, FTP, SFTP, NFS...).
- HDMI passthrough for Audio HD codecs, like E-AC3, TrueHD or DTS-HD.
- Stream to distant renderers, like Chromecast.
- 360 video and 3D audio playback with viewpoint change.
- Support for Ambisonics audio and more than 8 audio channels.
- Subtitles size modification live.
- Hardware decoding and display on all platforms.
- DVD playback and menu navigation.
LibVLCSharp.Forms.Platforms.GTK depends on this package.
This package depends on LibVLCSharp.
libvlc needs to be installed separately.
</Description>
<TargetFramework>net47</TargetFramework>
<RootNamespace>LibVLCSharp.GTK</RootNamespace>
<Version>0.0.1</Version>
<Version>0.8.1</Version>
<PackageId>LibVLCSharp.GTK</PackageId>
<Authors>VideoLAN</Authors>
<Owners>VideoLAN</Owners>
......@@ -36,10 +24,10 @@ Features:
<UseFullSemVerForNuGet>false</UseFullSemVerForNuGet>
<PackageLicenseExpression>LGPL-2.1-or-later</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://code.videolan.org/videolan/LibVLCSharp</RepositoryUrl>
<RepositoryUrl>https://code.videolan.org/videolan/LibVLCSharp/tree/master/LibVLCSharp.GTK</RepositoryUrl>
<PackageIconUrl>https://code.videolan.org/videolan/LibVLCSharp/raw/master/Assets/icon.png</PackageIconUrl>
<PackageReleaseNotes>https://code.videolan.org/videolan/LibVLCSharp/blob/master/NEWS</PackageReleaseNotes>
<PackageTags>libvlc;vlc;videolan;native;c/c++;video;audio;player;media;mediaplayer;codec;ffmpeg;xamarin;graphics;ios;android;linux;windows;macos;cross-platform</PackageTags>
<PackageTags>libvlc;vlc;videolan;video;audio;player;media;mediaplayer;gtk-sharp;linux;windows;cross-platform</PackageTags>
</PropertyGroup>
<ItemGroup>
<Reference Include="gdk-sharp">
......
# LibVLCSharp.GTK
[![NuGet Stats](https://img.shields.io/nuget/v/LibVLCSharp.GTK.svg)](https://www.nuget.org/packages/LibVLCSharp.GTK)
[![NuGet Stats](https://img.shields.io/nuget/dt/LibVLCSharp.GTK.svg)](https://www.nuget.org/packages/LibVLCSharp.GTK)
The official [GTK#](https://github.com/mono/gtk-sharp) views for [LibVLCSharp](../LibVLCSharp/README.md).
This package contains the views that allows to display a video played with [LibVLCSharp](../LibVLCSharp/README.md)
in a GTK# app (the mono/gtk-sharp one, [see below](#note-on-gtk-sharp)).
[LibVLCSharp.Forms.Platforms.GTK](../LibVLCSharp.Forms.Platforms.GTK) depends on this package.
This package depends on [LibVLCSharp](../LibVLCSharp/README.md).
Supported frameworks:
- net47 (on mono)
Supported platforms:
- Windows
- Linux
NOTE: This package does not currently support macOS! See [this issue](https://code.videolan.org/videolan/LibVLCSharp/issues/92)
WARNING: To create a GTK# program and run the samples, you will need mono and GTK# installed on the machine you build AND
on the machine you run.
## <a name="note-on-gtk-sharp"></a> A note on mono/gtk-sharp vs GtkSharp/GtkSharp
Let's face it, mono/gtk-sharp has a lot of drawbacks:
- It is based on GTK 2 (GTK 3 was released in 2011... but no stable version of GTK# for GTK3 as of now)
- Requires mono and GTK# installed on both the build and the target machine. (aka no nuget package)
On the other hand, [GtkSharp/GtkSharp](https://github.com/GtkSharp/GtkSharp) fixes this issues by providing a
.NET Standard 2.0 package for GTK 3.0 and NuGet packages for the GTK# libraries.
Unfortunately, Xamarin.Forms.GTK is only implemented using the former, which means that in order to support Xamarin.Forms.GTK, our views needs to support mono/gtk-sharp, hence this package.
## Why should I reference this package in my project?
If you want to create a video application using GTK# and C# with mono, this package is made for you.
You can also create a true cross-platform application with Xamarin.Forms, and use the GTK# backend to target linux and windows.
In that case, you would need the [LibVLCSharp.Forms.Platforms.GTK](../LibVLCSharp.Forms.Platforms.GTK) package instead,
which internally references this one.
For other platforms, see the [main documentation](../README.md)
\ No newline at end of file
using LibVLCSharp.Shared;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
namespace LibVLCSharp.Tests
{
[TestFixture]
public class LibVLCAPICoverage
{
const string LibVLCSym3URL = "https://raw.githubusercontent.com/videolan/vlc-3.0/3.0.0/lib/libvlc.sym";
const string LibVLCDeprecatedSymUrl = "https://raw.githubusercontent.com/videolan/vlc-3.0/master/include/vlc/deprecated.h";
[Test]
public async Task CheckLibVLCCoverage()
{
string[] libvlc3Symbols;
string[] libvlc3deprecatedSym;
using (var httpClient = new HttpClient())
{
libvlc3Symbols = (await httpClient.GetStringAsync(LibVLCSym3URL)).Split(new[] { '\r', '\n' }).Where(s => !string.IsNullOrEmpty(s)).ToArray();
libvlc3deprecatedSym = (await httpClient.GetStringAsync(LibVLCDeprecatedSymUrl)).Split(new[] { '\r', '\n' }).Where(s => !string.IsNullOrEmpty(s)).ToArray();
}
List<string> dllImports = new List<string>();
// retrieving EventManager using reflection because the type is internal
var eventManager = typeof(MediaPlayer).GetRuntimeProperties()
.First(n => n.Name.Equals("EventManager"))
.PropertyType
.BaseType;
List<Type> libvlcTypes = new List<Type>
{
typeof(LibVLC),
typeof(MediaPlayer),
typeof(Media),
typeof(MediaDiscoverer),
typeof(RendererDiscoverer),
typeof(RendererItem),
typeof(Dialog),
typeof(MediaList),
typeof(Equalizer),
eventManager
};
var deprecatedSymbolsLine = new List<string>();
for (var i = 0; i < libvlc3deprecatedSym.Count(); i++)
{
var currentLine = libvlc3deprecatedSym[i];
if(currentLine.StartsWith("LIBVLC_DEPRECATED"))
{
deprecatedSymbolsLine.Add(libvlc3deprecatedSym[i + 1]);
}
}
var deprecatedSymbols = new List<string>();
foreach (var symLine in deprecatedSymbolsLine)
{
var libvlcIndexStart = symLine.IndexOf("libvlc");
var sym1 = symLine.Substring(libvlcIndexStart);
var finalSymbol = new string(sym1.TakeWhile(c => c != '(').ToArray());
if (finalSymbol.Contains('*'))
{
finalSymbol = finalSymbol.Substring(finalSymbol.IndexOf('*') + 1);
}
deprecatedSymbols.Add(finalSymbol.Trim());
}
List<string> implementedButHidden = new List<string>
{
"libvlc_media_player_set_android_context", // android build only
"libvlc_free" // hidden in internal type
};
// these symbols are internal, should not be in libvlc.sym and have been removed in libvlc 4+
List<string> internalSymbolsThatShouldNotBeThere = new List<string>
{
"libvlc_get_input_thread", "libvlc_media_new_from_input_item", "libvlc_media_set_state"
};
// not implemented symbols for lack of use case or user interest
List<string> notImplementedOnPurpose = new List<string>
{
"libvlc_printerr", "libvlc_vprinterr", "libvlc_clock", "libvlc_dialog_get_context", "libvlc_dialog_set_context",
"libvlc_event_type_name", "libvlc_log_get_object", "libvlc_vlm", "libvlc_media_list_player", "libvlc_media_library"
};
List<string> exclude = new List<string>();
exclude.AddRange(implementedButHidden);
exclude.AddRange(internalSymbolsThatShouldNotBeThere);
exclude.AddRange(notImplementedOnPurpose);
foreach (var libvlcType in libvlcTypes)
{
var r = libvlcType.GetNestedType("Native", BindingFlags.NonPublic);
if (r == null) continue;
foreach (var method in r.GetRuntimeMethods())
{
foreach (var attr in method.CustomAttributes)
{
if (attr.AttributeType.Name.Equals("DllImportAttribute"))
{
var arg = attr.NamedArguments.FirstOrDefault(a => a.MemberName.Equals("EntryPoint"));
if (arg == null) continue;
var sym = (string)arg.TypedValue.Value;
dllImports.Add(sym);
}
}
}
}
var missingApis = libvlc3Symbols
.Where(symbol => !exclude.Any(excludeSymbol => symbol.StartsWith(excludeSymbol))) // Filters out excluded symbols
.Except(dllImports)
.Except(deprecatedSymbols);
var missingApisCount = missingApis.Count();
Debug.WriteLine($"we have {dllImports.Count} dll import statements");
Debug.WriteLine($"{missingApisCount} missing APIs implementation");
foreach (var miss in missingApis)
{
Debug.WriteLine(miss);
}
Assert.Zero(missingApisCount);
}
}
}
\ No newline at end of file
......@@ -105,28 +105,12 @@ namespace LibVLCSharp.Tests
Assert.IsTrue(called);
}
[Test]
public async Task SetLogCallback()
{
var logCallbackCalled = false;
void LogCallback(object sender, LogEventArgs args) => logCallbackCalled = true;
_libVLC.Log += LogCallback;
await Task.Delay(1000);
_libVLC.Log -= LogCallback;
Assert.IsTrue(logCallbackCalled);
}
[Test]
public void SetLogFile()
{
var path = Path.GetTempFileName();
_libVLC.SetLogFile(path);
_libVLC.UnsetLog();
_libVLC.CloseLogFile();
var logs = File.ReadAllText(path);
Assert.True(logs.StartsWith("VLC media player"));
}
......@@ -134,7 +118,6 @@ namespace LibVLCSharp.Tests
[Test]
public void DisposeLibVLC()
{
_libVLC.SetLog((data, logLevel, logContext, format, args) => { });
_libVLC.SetDialogHandlers((title, text) => Task.CompletedTask,
(dialog, title, text, defaultUsername, askStore, token) => Task.CompletedTask,
(dialog, title, text, type, cancelText, firstActionText, secondActonText, token) => Task.CompletedTask,
......
......@@ -24,7 +24,7 @@ namespace LibVLCSharp.Tests
public void OutputDeviceEnum()
{
var mp = new MediaPlayer(_libVLC);
var t = mp.OutputDeviceEnum;
var t = mp.AudioOutputDeviceEnum;
Debug.WriteLine(t);
}
......
......@@ -103,7 +103,6 @@ namespace LibVLCSharp.Tests
[Test]
public async Task CreateRealMediaSpecialCharacters()
{
_libVLC.Log += LibVLC_Log;
using (var media = new Media(_libVLC, RealMp3PathSpecialCharacter, FromType.FromPath))
{
Assert.False(media.IsParsed);
......@@ -119,7 +118,6 @@ namespace LibVLCSharp.Tests
mp.Stop();
}
}
_libVLC.Log -= LibVLC_Log;
}
[Test]
......
......@@ -38,7 +38,7 @@ namespace LibVLCSharp.WPF
void Background_Unloaded(object sender, RoutedEventArgs e)
{
_wndhost.Closing -= Wndhost_Closing;
_wndhost.SizeChanged -= Wndhost_SizeChanged;
_bckgnd.SizeChanged -= Wndhost_SizeChanged;
_wndhost.LocationChanged -= Wndhost_LocationChanged;
Hide();
......@@ -52,7 +52,7 @@ namespace LibVLCSharp.WPF
Owner = _wndhost;
_wndhost.Closing += Wndhost_Closing;
_wndhost.SizeChanged += Wndhost_SizeChanged;
_bckgnd.SizeChanged += Wndhost_SizeChanged;
_wndhost.LocationChanged += Wndhost_LocationChanged;
try
......@@ -62,7 +62,7 @@ namespace LibVLCSharp.WPF
var targetPoints = source.CompositionTarget.TransformFromDevice.Transform(locationFromScreen);
Left = targetPoints.X;
Top = targetPoints.Y;
var size = _bckgnd.PointToScreen(new Point(_bckgnd.ActualWidth, _bckgnd.ActualHeight)) - _bckgnd.PointToScreen(_zeroPoint);
var size = new Point(_bckgnd.ActualWidth, _bckgnd.ActualHeight);
Height = size.Y;
Width = size.X;
Show();
......@@ -91,7 +91,7 @@ namespace LibVLCSharp.WPF
var targetPoints = source.CompositionTarget.TransformFromDevice.Transform(locationFromScreen);
Left = targetPoints.X;
Top = targetPoints.Y;
var size = _bckgnd.PointToScreen(new Point(_bckgnd.ActualWidth, _bckgnd.ActualHeight)) - _bckgnd.PointToScreen(_zeroPoint);
var size = new Point(_bckgnd.ActualWidth, _bckgnd.ActualHeight);
Height = size.Y;
Width = size.X;
}
......
<Project Sdk="MSBuild.Sdk.Extras/1.6.46">
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<Title>LibVLCSharp.WPF</Title>
<Summary>WPF integration for LibVLCSharp</Summary>
......@@ -29,9 +29,9 @@ Features:
<RootNamespace>LibVLCSharp.WPF</RootNamespace>
<NeutralLanguage>en</NeutralLanguage>
<LangVersion>7.3</LangVersion>
<Version>0.3.0</Version>
<Version>0.8.1</Version>
<PackageId>LibVLCSharp.WPF</PackageId>
<ExtrasEnableWpfProjectSetup>true</ExtrasEnableWpfProjectSetup>
<UseWPF>true</UseWPF>
<Authors>VideoLAN</Authors>
<Owners>VideoLAN</Owners>
<GeneratePackageOnBuild Condition=" '$(Configuration)' == 'Release' ">true</GeneratePackageOnBuild>
......@@ -47,8 +47,22 @@ Features:
<ItemGroup>
<Reference Include="WindowsFormsIntegration" />
<Reference Include="System.Windows.Forms" />
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LibVLCSharp\LibVLCSharp.csproj" />
</ItemGroup>
<!-- Workaround https://github.com/onovotny/MSBuildSdkExtras/issues/158 -->
<ItemGroup Condition=" '$(UseWpf)' == 'true'">
<None Remove="**\*.xaml" />
<Page Remove="**\*.xaml" />
<Page Include="**\*.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Remove="**\App.xaml" />
<ApplicationDefinition Include="**\App.xaml" />
<Reference Include="System.Xaml" />
</ItemGroup>
</Project>
\ No newline at end of file
......@@ -19,7 +19,7 @@ namespace LibVLCSharp.WPF
{
DefaultStyleKey = typeof(VideoView);
}
public static readonly DependencyProperty MediaPlayerProperty = DependencyProperty.Register(nameof(MediaPlayer),
typeof(MediaPlayer),
typeof(VideoView),
......@@ -63,7 +63,7 @@ namespace LibVLCSharp.WPF
Content = ViewContent
};
}
Hwnd = (Template.FindName(PART_PlayerView, this) as System.Windows.Forms.Panel)?.Handle ?? IntPtr.Zero;
if (Hwnd == null)
{
......@@ -116,8 +116,8 @@ namespace LibVLCSharp.WPF
{
if (disposing)
{
if(MediaPlayer != null)
{
if (MediaPlayer != null)
{
MediaPlayer.Hwnd = IntPtr.Zero;
}
}
......
......@@ -21,7 +21,7 @@
</Description>
<TargetFrameworks>net40</TargetFrameworks>
<RootNamespace>LibVLCSharp.WinForms</RootNamespace>
<Version>0.0.1</Version>
<Version>0.8.1</Version>
<PackageId>LibVLCSharp.WinForms</PackageId>
<Authors>VideoLAN</Authors>
<Owners>VideoLAN</Owners>
......
This diff is collapsed.
<Project Sdk="MSBuild.Sdk.Extras/1.6.46">
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<Title>LibVLCSharp</Title>
<Summary>LibVLCSharp is a crossplatform multimedia framework for all .NET languages and runtimes</Summary>
<Description>LibVLCSharp is a cross-platform audio and video API for .NET platforms based on VideoLAN's LibVLC Library.
It provides a comprehensive multimedia API that can be used across mobile, server and desktop to render video and output audio. Mono, .NET Framework and .NET Core runtimes are supported.
<Summary>The official .NET wrapper around LibVLC.</Summary>
<Description>
LibVLCSharp is a cross-platform audio and video API for .NET platforms based on VideoLAN's LibVLC Library.
It provides a comprehensive multimedia API that can be used across mobile, server and desktop to render video and output audio. Mono, .NET Framework and .NET Core runtimes are supported.
This package contains the core features of LibVLCSharp (libvlc loading and initialization, .NET-friendly classes to ease the use of libvlc...). All other `LibVLCSharp.*` packages depend on this one.
Supported platforms:
- Xamarin.Android
- Xamarin.iOS
- Xamarin.Mac
- Windows (WPF/WinForms)
- Xamarin.Forms
- .NET Standard 1.1
- .NET Core
This package also contains the views for the following platforms:
Features:
- Network browsing for distant filesystems (SMB, FTP, SFTP, NFS...).
- HDMI passthrough for Audio HD codecs, like E-AC3, TrueHD or DTS-HD.
- Stream to distant renderers, like Chromecast.
- 360 video and 3D audio playback with viewpoint change.
- Support for Ambisonics audio and more than 8 audio channels.
- Subtitles size modification live.
- Hardware decoding and display on all platforms.
- DVD playback and menu navigation.
- Android
- iOS
- Mac
- tvOS
- UWP
libvlc needs to be installed separately. See VideoLAN.LibVLC.* packages.
</Description>
<TargetFrameworks>netstandard2.0;netstandard1.1;net40;net471</TargetFrameworks>
<TargetFrameworks Condition="!$([MSBuild]::IsOsPlatform('Linux'))">$(TargetFrameworks);MonoAndroid81;Xamarin.iOS10;Xamarin.Mac20;Xamarin.TVOS10</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);uap10.0</TargetFrameworks>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeAWindow</TargetsForTfmSpecificBuildOutput>
<RootNamespace>LibVLCSharp</RootNamespace>
<NeutralLanguage>en</NeutralLanguage>
<LangVersion>7.3</LangVersion>
<PackageVersion>0.5.0</PackageVersion>
<PackageVersion>0.8.1</PackageVersion>
<PackageId>LibVLCSharp</PackageId>
<Authors>VideoLAN</Authors>
<Owners>VideoLAN</Owners>
......@@ -40,7 +35,7 @@ Features:
<UseFullSemVerForNuGet>false</UseFullSemVerForNuGet>
<PackageLicenseExpression>LGPL-2.1-or-later</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://code.videolan.org/videolan/LibVLCSharp</RepositoryUrl>
<RepositoryUrl>https://code.videolan.org/videolan/LibVLCSharp/tree/master/LibVLCSharp</RepositoryUrl>
<PackageIconUrl>https://code.videolan.org/videolan/LibVLCSharp/raw/master/Assets/icon.png</PackageIconUrl>
<PackageReleaseNotes>https://code.videolan.org/videolan/LibVLCSharp/blob/master/NEWS</PackageReleaseNotes>
<PackageTags>libvlc;vlc;videolan;native;c/c++;video;audio;player;media;mediaplayer;codec;ffmpeg;xamarin;graphics;ios;android;linux;windows;macos;cross-platform</PackageTags>
......@@ -70,9 +65,14 @@ Features:
<Compile Include="Platforms\tvOS\**\*.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
<PackageReference Include="System.ValueTuple" Version="4.5.0"/>
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Microsoft.Bcl.Async" Version="1.0.168" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('uap'))">
<Compile Include="Platforms\UWP\**\*.cs" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" />
</ItemGroup>
<Target Name="IncludeAWindow" Condition="$(TargetFramework.StartsWith('MonoAndroid'))">
<ItemGroup>
<BuildOutputInPackage Include="$(OutputPath)LibVLCSharp.Android.AWindow.dll" />
......
namespace LibVLCSharp.Platforms.UWP
{
using LibVLCSharp.Shared;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using SharpDX.Mathematics.Interop;
using System;
using System.Runtime.InteropServices;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
/// <summary>
/// The VideoView implementation for UWP applications
/// </summary>
public class VideoView : UserControl, IVideoView
{
SwapChainPanel _panel;
SharpDX.Direct3D11.Device _d3D11Device;
SharpDX.DXGI.Device1 _device;
SharpDX.DXGI.Device3 _device3;
SwapChain2 _swapChain2;
SwapChain1 _swapChain;
const string Mobile = "Windows.Mobile";
bool _loaded;
/// <summary>
/// The constructor
/// </summary>
public VideoView()
{
_panel = new SwapChainPanel();
Content = _panel;
Loaded += (s, e) => CreateSwapChain();
Unloaded += (s, e) => DestroySwapChain();
Application.Current.Suspending += (s, e) => { Trim(); };
_panel.SizeChanged += (s, eventArgs) =>
{
if (_loaded)
{
UpdateSize();
}
};
_panel.CompositionScaleChanged += (s, eventArgs) =>
{
if (_loaded)
{
UpdateScale();
}
};
}
/// <summary>
/// Gets the swapchain parameters to pass to the <see cref="LibVLC"/> constructor.
/// If you don't pass them to the <see cref="LibVLC"/> constructor, the video won't
/// be displayed in your application.
/// Calling this property will throw an <see cref="InvalidOperationException"/> if the VideoView is not yet full Loaded.
/// </summary>
/// <returns>The list of arguments to be given to the <see cref="LibVLC"/> constructor.</returns>
public string[] SwapChainOptions
{
get
{
if (!_loaded)
{
throw new InvalidOperationException("You must wait for the VideoView to be loaded before calling GetSwapChainOptions()");
}
return new string[]
{
$"--winrt-d3dcontext=0x{_d3D11Device.ImmediateContext.NativePointer.ToString("x")}",
$"--winrt-swapchain=0x{_swapChain.NativePointer.ToString("x")}"
};
}
}
/// <summary>
/// Initializes the SwapChain for use with LibVLC
/// </summary>
void CreateSwapChain()
{
SharpDX.DXGI.Factory2 dxgiFactory = null;
try
{
DeviceCreationFlags deviceCreationFlags =
DeviceCreationFlags.BgraSupport | DeviceCreationFlags.VideoSupport;
#if DEBUG
if (Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily != Mobile)
deviceCreationFlags |= DeviceCreationFlags.Debug;
try
{
dxgiFactory = new SharpDX.DXGI.Factory2(true);
}
catch (SharpDXException)
{
dxgiFactory = new SharpDX.DXGI.Factory2(false);
}
#else
dxgiFactory = new SharpDX.DXGI.Factory2(false);
#endif
_d3D11Device = null;
foreach (var adapter in dxgiFactory.Adapters)
{
try
{
_d3D11Device = new SharpDX.Direct3D11.Device(adapter, deviceCreationFlags);
break;
}
catch (SharpDXException)
{
}
}
if (_d3D11Device is null)
{
throw new VLCException("Could not create Direct3D11 device : No compatible adapter found.");
}
_device = _d3D11Device.QueryInterface<SharpDX.DXGI.Device1>();
//Create the swapchain
var swapChainDescription = new SharpDX.DXGI.SwapChainDescription1
{
Width = (int) (_panel.ActualWidth * _panel.CompositionScaleX),
Height = (int) (_panel.ActualHeight * _panel.CompositionScaleY),
Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
Stereo = false,
SampleDescription =
{
Count = 1,
Quality = 0
},
Usage = Usage.RenderTargetOutput,
BufferCount = 2,
SwapEffect = SwapEffect.FlipSequential,
Flags = SwapChainFlags.None,
AlphaMode = AlphaMode.Unspecified
};
_swapChain = new SharpDX.DXGI.SwapChain1(dxgiFactory, _d3D11Device, ref swapChainDescription);
_device.MaximumFrameLatency = 1;
using (var panelNative = ComObject.As<ISwapChainPanelNative>(_panel))
{
panelNative.SwapChain = _swapChain;
}
// This is necessary so we can call Trim() on suspend
_device3 = _device.QueryInterface<SharpDX.DXGI.Device3>();
if (_device3 == null)
{
throw new VLCException("Failed to query interface \"Device3\"");
}
_swapChain2 = _swapChain.QueryInterface<SharpDX.DXGI.SwapChain2>();
if (_swapChain2 == null)
{
throw new VLCException("Failed to query interface \"SwapChain2\"");
}
UpdateScale();
UpdateSize();
_loaded = true;
}
catch (Exception ex)
{
DestroySwapChain();
if (ex is SharpDXException)
{
throw new VLCException("SharpDX operation failed, see InnerException for details", ex);
}
throw;
}
finally
{
dxgiFactory?.Dispose();
}
}
/// <summary>
/// Destroys the SwapChain and all related instances.
/// </summary>
void DestroySwapChain()
{
_swapChain2?.Dispose();
_swapChain2 = null;
_device3?.Dispose();
_device3 = null;
_swapChain?.Dispose();
_swapChain = null;
_device?.Dispose();
_device = null;
_d3D11Device?.Dispose();
_d3D11Device = null;
}
readonly Guid SWAPCHAIN_WIDTH = new Guid(0xf1b59347, 0x1643, 0x411a, 0xad, 0x6b, 0xc7, 0x80, 0x17, 0x7a, 0x6, 0xb6);
readonly Guid SWAPCHAIN_HEIGHT = new Guid(0x6ea976a0, 0x9d60, 0x4bb7, 0xa5, 0xa9, 0x7d, 0xd1, 0x18, 0x7f, 0xc9, 0xbd);
/// <summary>
/// Associates width/height private data into the SwapChain, so that VLC knows at which size to render its video.
/// </summary>
void UpdateSize()
{
IntPtr width = Marshal.AllocHGlobal(sizeof(int));
IntPtr height = Marshal.AllocHGlobal(sizeof(int));
try
{
var w = (int)(_panel.ActualWidth * _panel.CompositionScaleX);
var h = (int)(_panel.ActualHeight * _panel.CompositionScaleY);
Marshal.WriteInt32(width, w);
Marshal.WriteInt32(height, h);
_swapChain.SetPrivateData(SWAPCHAIN_WIDTH, sizeof(int), width);
_swapChain.SetPrivateData(SWAPCHAIN_HEIGHT, sizeof(int), height);
}
finally
{
Marshal.FreeHGlobal(width);
Marshal.FreeHGlobal(height);
}
}
/// <summary>
/// Updates the MatrixTransform of the SwapChain.
/// </summary>
void UpdateScale()
{
_swapChain2.MatrixTransform = new RawMatrix3x2 { M11 = 1.0f / _panel.CompositionScaleX, M22 = 1.0f / _panel.CompositionScaleY };
}
/// <summary>
/// When the app is suspended, UWP apps should call Trim so that the DirectX data is cleaned.
/// </summary>
void Trim()
{
_device3?.Trim();
}
/// <summary>
/// When the media player is attached to the view.
/// </summary>
void Attach()
{
}
/// <summary>
/// When the media player is detached from the view.
/// </summary>
void Detach()
{
}
MediaPlayer _mediaPlayer;
/// <summary>
/// MediaPlayer object connected to the view
/// </summary>
public MediaPlayer MediaPlayer
{
get => _mediaPlayer;
set
{
if (_mediaPlayer != value)
{
Detach();
_mediaPlayer = value;
if (_mediaPlayer != null)
{
Attach();
}
}
}
}
}
}
# LibVLCSharp
[![NuGet Stats](https://img.shields.io/nuget/v/LibVLCSharp.svg)](https://www.nuget.org/packages/LibVLCSharp)
[![NuGet Stats](https://img.shields.io/nuget/dt/LibVLCSharp.svg)](https://www.nuget.org/packages/LibVLCSharp)
The official .NET wrapper around LibVLC.
This package contains the core features of LibVLCSharp (libvlc loading and initialization, .NET-friendly classes to ease the use of libvlc...).
All other `LibVLCSharp.*` packages depend on this one.
This package also contains the views for the following platforms:
- Android
- iOS
- Mac
- tvOS
- UWP
This package has multiple target frameworks, which means it will pick the right features for your project (you will only get the mac view if you are building a mac project).
BE CAREFUL: This project does not include **LibVLC** itself! You will need to install it separately!
See the [Installation](../README.md#installation) documentation for more info.
## Why should I reference this package in my project?
If you are in one of these situation, this package is made for you.
- You want to build a console application that leverages the power of VLC for transcoding/streaming/recording/playing audio... without displaying the video anywhere
- You want to build a Xamarin.iOS/Android/Mac/tvOS/UWP app (not Xamarin.Forms, for that, see [LibVLCSharp.Forms](../LibVLCSharp.Forms/README.md) )
For other platforms, see the [main documentation](../README.md)
\ No newline at end of file
......@@ -15,10 +15,10 @@ namespace LibVLCSharp.Shared
{
struct Native
{
#if NET || NETSTANDARD
[DllImport(Constants.Kernel32, SetLastError = true)]
internal static extern IntPtr LoadPackagedLibrary(string dllToLoad);
#if UWP
[DllImport(Constants.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr LoadPackagedLibrary(string dllToLoad, uint reserved = 0);
#elif NET || NETSTANDARD
[DllImport(Constants.Kernel32, SetLastError = true)]
internal static extern IntPtr LoadLibrary(string dllToLoad);
......@@ -40,9 +40,12 @@ namespace LibVLCSharp.Shared
}
#if NET || NETSTANDARD
#if !UWP
static IntPtr _libvlccoreHandle;
#endif // !UWP
static IntPtr _libvlcHandle;
#endif
#endif // NET || NETSTANDARD
/// <summary>
/// Load the native libvlc library (if necessary, depending on platform)
/// <para/> Ensure that you installed the VideoLAN.LibVLC.[YourPlatform] package in your target project
......@@ -56,6 +59,8 @@ namespace LibVLCSharp.Shared
{
#if ANDROID
InitializeAndroid();
#elif UWP
InitializeUWP();
#elif NET || NETSTANDARD
InitializeDesktop(libvlcDirectoryPath);
#endif
......@@ -69,6 +74,16 @@ namespace LibVLCSharp.Shared
throw new VLCException("failed to initialize libvlc with JniOnLoad " +
$"{nameof(JniRuntime.CurrentRuntime.InvocationPointer)}: {JniRuntime.CurrentRuntime.InvocationPointer}");