-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for NativeControlHost inside a UserControl #6237
Comments
I'm looking into these same topics to attempt an integration of MPV media player
This wID integration should work in Windows and Linux but may cause troubles under MacOS. Does VLC support the OpenGL Render API that MPV provides? Have you done any attempts with it to see whether it works and see any downsides? Currently, NativeControlHost seems to have many issues and limitations, and at the end of it, it still won't work as expected on MacOS. |
After some investigation it turned out that the problem is caused by API misuse by LibVLCSharp. It tries to create the player before It works for So it's LibVLCSharp's bug. |
The Anyway, closing this for now. Thanks for your investigations. I will have another look and see if the LVS.Avalonia VideoView can be adapted, or if the problem can only be fixed from user code (e.g. the code from the stackoverfow question). Cheers! |
Hi everyone! I was asked to share this piece of code. It's a full replacement of the VideoView that should fix this issue. I've tested it and works acceptably well. using System;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Platform;
using CSharpFunctionalExtensions;
using LibVLCSharp.Shared;
/// <summary>
/// Avalonia VideoView for Windows, Linux and Mac.
/// </summary>
public class VideoView : NativeControlHost
{
public static readonly DirectProperty<VideoView, Maybe<MediaPlayer>> MediaPlayerProperty =
AvaloniaProperty.RegisterDirect<VideoView, Maybe<MediaPlayer>>(
nameof(MediaPlayer),
o => o.MediaPlayer,
(o, v) => o.MediaPlayer = v.GetValueOrDefault(),
defaultBindingMode: BindingMode.TwoWay);
private readonly IDisposable attacher;
private readonly BehaviorSubject<Maybe<MediaPlayer>> mediaPlayers = new(Maybe<MediaPlayer>.None);
private readonly BehaviorSubject<Maybe<IPlatformHandle>> platformHandles = new(Maybe<IPlatformHandle>.None);
public VideoView()
{
attacher = platformHandles.WithLatestFrom(mediaPlayers).Subscribe(x =>
{
var playerAndHandle = from h in x.First
from mp in x.Second
select new {n = h, m = mp};
playerAndHandle.Execute(a => a.m.SetHandle(a.n));
});
}
public MediaPlayer? MediaPlayer
{
get => mediaPlayers.Value.GetValueOrDefault();
set => mediaPlayers.OnNext(value);
}
/// <inheritdoc />
protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent)
{
var handle = base.CreateNativeControlCore(parent);
platformHandles.OnNext(Maybe<IPlatformHandle>.From(handle));
return handle;
}
/// <inheritdoc />
protected override void DestroyNativeControlCore(IPlatformHandle control)
{
attacher.Dispose();
base.DestroyNativeControlCore(control);
mediaPlayers.Value.Execute(MediaPlayerExtensions.DisposeHandle);
}
}
public static class MediaPlayerExtensions
{
public static void DisposeHandle(this MediaPlayer player)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
player.Hwnd = IntPtr.Zero;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
player.XWindow = 0;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) player.NsObject = IntPtr.Zero;
}
public static void SetHandle(this MediaPlayer player, IPlatformHandle handle)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
player.Hwnd = handle.Handle;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
player.XWindow = (uint) handle.Handle;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) player.NsObject = handle.Handle;
}
} Please, be sure the add the CSharpFunctionalExtensions Nuget package. |
About questions on How-To:
you can find my answer here: Here the links to the 2 Proof of Concept repositories: AvaVLCWindow, AvaVLCControl |
Hi @radiolondra, good work! Would you like to contribute this to libvlcsharp so everybody can benefit? |
Hi @mfkl,
I uploaded some old and not used test files by mistake in the LibVLCSharp.Avalonia project in both AvaVLCWindow and AvaVLCControl, where you found the usage of video callbacks. I just uploaded a clean solution for both repos.
Martin, you could add the solutions in the right place better than me, or you could simply add links to the following posts: Anyway remember that this is a POC and maybe it needs a bit of more work. Also it has to be tested on other platforms too (I tested it on Windows 10 only right now). Thanks for your attention. EDIT: EDIT: Successfully tested on MacOS 10.13 (High Sierra) Next step test: Raspberry Pi |
Test on Raspberry Pi (Raspbian Stretch) The generated on-top window has no transparency and opacity is not respected. I tried every possible combinations of Background and TransparencyLevelHint without any success. Maybe Avalonia has some issues for linux-arm or maybe there are some other settings I don't know. Having 926MB of RAM only and just 1 CPU, the video is played in jerks. Anyway, it works BUT the transparency and opacity issues. |
New test on Raspberry Pi (DietPi with MATE or Xfce)It works fine!Transparency and Opacity are fully honored. In my opinion, the problem is not Avalonia vs Raspberry, the problem is what is installed or not in Raspberry. With DietPi OS and MATE (or Xfce) as X, the sample works perfectly. And playback is smooth without jerks, interruptions or whatever. As root, I installed |
For anyone is interested: A sample to apply in the real world the changes I did in LibVLCSharp.Avalonia I created YAMP2 repository (Yet-Another-Media-Player v2) here, which fully uses my new LibVLCSharp.Avalonia.Unofficial lib. To make tests, build it by yourselves and run. Enjoy. |
The new release of the Unofficial Avalonia LibVLCSharp, allows to display multiple draggable controls over the scene of a video played with LibVLCSharp in an Avalonia app. For anyone is interested. output.mp4 |
All the links updated (latest libs and samples versions)Avalonia Unofficial LibVLCSharp LinksVLC video player inside an Avalonia Window/UserControl embedding single static customizable control (e.g.player buttons) VLC video player inside an Avalonia Window/UserControl embedding multiple draggable customizable controls (e.g.player buttons, images,...) LibVLCSharp.Avalonia.Unofficial Samples LibVLCSharp.Avalonia.Unofficial.UCanvas sample YAMP 2 - Open source video player sample using LibVLCSharp.Avalonia.Unofficial library |
Is your feature request related to a problem? Please describe.
https://stackoverflow.com/questions/68292849/avaloniaui-cannot-embed-videoview-control-libvlcsharp-in-a-usercontrol
It seems the native window handle is not surfaced when the
NativeControlHost
is positioned inside aUserControl
.Describe the solution you'd like
Essentially a more advanced version of https://github.com/AvaloniaUI/Avalonia/blob/master/samples/interop/NativeEmbedSample/EmbedSample.cs
Being able to do so would improve the
NativeControlHost
support and help building native-based reusable components.Describe alternatives you've considered
Other than that, the view is working fine on its own https://code.videolan.org/videolan/LibVLCSharp/-/blob/3.x/src/LibVLCSharp.Avalonia/VideoView.cs
Additional context
The text was updated successfully, but these errors were encountered: