Skip to content
SuRGeoNix edited this page Nov 1, 2024 · 15 revisions

Welcome to Flyleaf Wiki !



Development Requirements

Flyleaf's solution is developed on Visual Studio 2022 with .NET 8 and it supports / requires .NET 8 SDK.

Flyleaf's main NuGet package is FlyleafLib. For WinUI you will need FlyleafLib.Controls.WinUI NuGet package. If you use WPF you might want to have look on FlyleafME, an existing media element control based on FlyleafLib which can be customized to your needs and save you from coding a control from scratch.

You will need to ensure that your projects are targeting windows desktop frameworks, e.g. :-

<TargetFramework>net8.0-windows</TargetFramework>

Video Acceleration, Decoding & Rendering is based on Direct3D 11 through Vortice bindings and even if it supports older Direct3D features, it might not properly work on old systems. For Windows 7, you might require to install the KB36805 windows update and ensure you have the latest GPU drivers as well.

Flyleaf is based on FFmpeg media framework for demuxing and decoding through Flyleaf.FFmpeg.Bindings so you will need to make sure that you properly link FFmpeg's shared libraries through the Flyleaf's Engine configuration.

NOTE 1: FFmpeg libraries platform (x86/x64) must match with your applications platform
NOTE 2: It is highly recommended to use Flyeaf's FFmpeg shared libraries as they are patched and compiled (x64) with FFmpeg-Builds docker for a critical HLS issue).
NOTE 3: Mingw has currently an issue for creating FFmpeg shared libraries that could cause a crash during thread naming (see https://github.com/BtbN/FFmpeg-Builds/issues/412)

Quick Player Setup (WinUI 3)

  • Install-Package FlyleafLib.Controls.WinUI
  1. App.xaml.cs
using FlyleafLib;
using Microsoft.UI.Xaml;

namespace FlyleafSample;

public partial class App : Application
{
    public App()
    {
        InitializeComponent();

        Engine.Start(new EngineConfig()
        {
            FFmpegPath          = @"C:\Flyleaf\FFmpeg",
            FFmpegDevices       = false,    // Prevents loading avdevice/avfilter dll files. Enable it only if you plan to use dshow/gdigrab etc.

            #if RELEASE
            FFmpegLogLevel      = Flyleaf.FFmpeg.LogLevel.Quiet,
            LogLevel            = LogLevel.Quiet,

            #else
            FFmpegLogLevel      = Flyleaf.FFmpeg.LogLevel.Warn,
            LogLevel            = LogLevel.Debug,
            LogOutput           = ":debug",
            //LogOutput         = ":console",
            //LogOutput         = @"C:\Flyleaf\Logs\flyleaf.log",                
            #endif

            //PluginsPath       = @"C:\Flyleaf\Plugins",

            UIRefresh           = false,    // Required for Activity, BufferedDuration, Stats in combination with Config.Player.Stats = true
            UIRefreshInterval   = 250,      // How often (in ms) to notify the UI
            UICurTimePerSecond  = true,     // Whether to notify UI for CurTime only when it's second changed or by UIRefreshInterval
        });
    }
    protected override void OnLaunched(LaunchActivatedEventArgs args)
    {
        m_window = new MainWindow();
        m_window.Activate();
    }

    private Window m_window;
}
  1. MainWindow.xaml.cs
using FlyleafLib;
using FlyleafLib.MediaPlayer;
using Microsoft.UI.Xaml;
using System.Threading.Tasks;
using System.Threading;

namespace FlyleafSample;

public sealed partial class MainWindow : Window
{
    public Player Player { get; set; }
    public Config Config { get; set; }

    public MainWindow()
    {
        Config = new Config();
        Config.Video.BackgroundColor = System.Windows.Media.Colors.DarkGray;

        Player = new Player(Config);

        InitializeComponent();
        rootGrid.DataContext = this;

        // Keyboard focus fix
        FSC.FullScreenEnter += (o, e) => flyleafHost.KFC.Focus(FocusState.Keyboard);
        FSC.FullScreenExit += (o, e) => Task.Run(() => 
            { Thread.Sleep(10); Utils.UIInvoke(() => flyleafHost.KFC.Focus(FocusState.Keyboard)); });
    }
}
  1. MainWindow.xaml
<Window
    x:Class="FlyleafSample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:FlyleafSample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:fl="using:FlyleafLib.Controls.WinUI"
    mc:Ignorable="d">

    <Grid x:Name="rootGrid">
        <fl:FullScreenContainer x:Name="FSC">
            <fl:FlyleafHost x:Name="flyleafHost" Player="{Binding Player}">
                <TextBlock Text="Hello Flyleaf!" Foreground="DarkOrange" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="50"/>
            </fl:FlyleafHost>
        </fl:FullScreenContainer>
    </Grid>
</Window>

Quick Player Setup (WPF)

  • Install-Package FlyleafLib
  1. App.xaml.cs
using FlyleafLib;
using System.Windows;

namespace FlyleafSample
{
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            Engine.Start(new EngineConfig()
            {
                FFmpegPath          = @"C:\Flyleaf\FFmpeg",
                FFmpegDevices       = false,    // Prevents loading avdevice/avfilter dll files. Enable it only if you plan to use dshow/gdigrab etc.

                #if RELEASE
                FFmpegLogLevel      = Flyleaf.FFmpeg.LogLevel.Quiet,
                LogLevel            = LogLevel.Quiet,

                #else
                FFmpegLogLevel      = Flyleaf.FFmpeg.LogLevel.Warn,
                LogLevel            = LogLevel.Debug,
                LogOutput           = ":debug",
                //LogOutput         = ":console",
                //LogOutput         = @"C:\Flyleaf\Logs\flyleaf.log",                
                #endif

                //PluginsPath       = @"C:\Flyleaf\Plugins",

                UIRefresh           = false,    // Required for Activity, BufferedDuration, Stats in combination with Config.Player.Stats = true
                UIRefreshInterval   = 250,      // How often (in ms) to notify the UI
                UICurTimePerSecond  = true,     // Whether to notify UI for CurTime only when it's second changed or by UIRefreshInterval
            });
        }
    }
}
  1. MainWindow.xaml.cs
using System.Windows;
using System.Windows.Media;

using FlyleafLib;
using FlyleafLib.MediaPlayer;

namespace FlyleafSample
{
    public partial class MainWindow : Window
    {
        public Player Player { get; set; }
        public Config Config { get; set; }

        public MainWindow()
        {
            Config = new Config();
            Config.Video.BackgroundColor = Colors.DarkGray;

            Player = new Player(Config);

            InitializeComponent();
            
            DataContext = this;
        }
    }
}
  1. MainWindow.xaml
<Window x:Class="FlyleafSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:FlyleafSample"
        xmlns:fl="clr-namespace:FlyleafLib.Controls.WPF;assembly=FlyleafLib"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <fl:FlyleafHost Player="{Binding Player}" AttachedDragMove="Both" KeyBindings="Both">
            <Viewbox>
                <TextBlock Text="Hello Flyleaf Overlay!" Foreground="DarkOrange"/>
            </Viewbox>
        </fl:FlyleafHost>
    </Grid>
</Window>

Quick Player Setup (WinForms)

  • Install-Package FlyleafLib
  • Add FlyleafHost from your toolbox to the Form
  1. Program.cs
using FlyleafLib;

namespace FlyleafSample
{
    internal static class Program
    {
        [STAThread]
        static void Main()
        {
            Engine.Start(new EngineConfig()
            {
                FFmpegPath          = @"C:\Flyleaf\FFmpeg",
                FFmpegDevices       = false,    // Prevents loading avdevice/avfilter dll files. Enable it only if you plan to use dshow/gdigrab etc.

                #if RELEASE
                FFmpegLogLevel      = Flyleaf.FFmpeg.LogLevel.Quiet,
                LogLevel            = LogLevel.Quiet,

                #else
                FFmpegLogLevel      = Flyleaf.FFmpeg.LogLevel.Warn,
                LogLevel            = LogLevel.Debug,
                LogOutput           = ":debug",
                //LogOutput         = ":console",
                //LogOutput         = @"C:\Flyleaf\Logs\flyleaf.log",                
                #endif

                //PluginsPath       = @"C:\Flyleaf\Plugins",

                UIRefresh           = false,    // Required for Activity, BufferedDuration, Stats in combination with Config.Player.Stats = true
                UIRefreshInterval   = 250,      // How often (in ms) to notify the UI
                UICurTimePerSecond  = true,     // Whether to notify UI for CurTime only when it's second changed or by UIRefreshInterval
            });

            ApplicationConfiguration.Initialize();
            Application.Run(new Form1());
        }
    }
}
  1. Form1.cs
using FlyleafLib;
using FlyleafLib.MediaPlayer;

namespace FlyleafSample
{
    public partial class Form1 : Form
    {
        public Player Player { get; set; }
        public Config Config { get; set; }

        public Form1()
        {
            Config = new Config();
            Config.Video.BackgroundColor = System.Windows.Media.Colors.DarkGray;

            Player = new Player(Config);

            InitializeComponent();

            // flyleafHost1 has been added from toolbox
            flyleafHost1.Player = Player;
        }
    }
}