mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-21 18:52:36 +01:00
MPV support for linux first imlementation.
This commit is contained in:
parent
a091491c35
commit
13d870bdd3
1
.gitignore
vendored
1
.gitignore
vendored
@ -32,3 +32,4 @@ SubtitleEdit-*-setup.exe
|
|||||||
/src/SubtitleEdit.VC.opendb
|
/src/SubtitleEdit.VC.opendb
|
||||||
/src/SubtitleEdit.VC.VC.opendb
|
/src/SubtitleEdit.VC.VC.opendb
|
||||||
/src/SubtitleEdit.VC.db
|
/src/SubtitleEdit.VC.db
|
||||||
|
/src/SubtitleEdit.userprefs
|
@ -668,7 +668,7 @@ namespace Nikse.SubtitleEdit.Core
|
|||||||
OpenSubtitleExtraExtensions = "*.mp4;*.m4v;*.mkv;*.ts"; // matroska/mp4/m4v files (can contain subtitles)
|
OpenSubtitleExtraExtensions = "*.mp4;*.m4v;*.mkv;*.ts"; // matroska/mp4/m4v files (can contain subtitles)
|
||||||
ListViewColumnsRememberSize = true;
|
ListViewColumnsRememberSize = true;
|
||||||
VlcWaveTranscodeSettings = "acodec=s16l"; // "acodec=s16l,channels=1,ab=64,samplerate=8000";
|
VlcWaveTranscodeSettings = "acodec=s16l"; // "acodec=s16l,channels=1,ab=64,samplerate=8000";
|
||||||
MpvVideoOutput = "direct3d_shaders"; // mpv "vo" option
|
MpvVideoOutput = "vaapi"; // mpv "vo" option
|
||||||
UseTimeFormatHHMMSSFF = false;
|
UseTimeFormatHHMMSSFF = false;
|
||||||
ClearStatusBarAfterSeconds = 10;
|
ClearStatusBarAfterSeconds = 10;
|
||||||
MoveVideo100Or500MsPlaySmallSample = false;
|
MoveVideo100Or500MsPlaySmallSample = false;
|
||||||
|
@ -2327,7 +2327,10 @@ namespace Nikse.SubtitleEdit.Forms
|
|||||||
private void RefreshMpvSettings()
|
private void RefreshMpvSettings()
|
||||||
{
|
{
|
||||||
radioButtonVideoPlayerMPV.Enabled = LibMpvDynamic.IsInstalled;
|
radioButtonVideoPlayerMPV.Enabled = LibMpvDynamic.IsInstalled;
|
||||||
labelMpvSettings.Text = "--vo=" + Configuration.Settings.General.MpvVideoOutput;
|
if (!Configuration.IsRunningOnLinux())
|
||||||
|
labelMpvSettings.Text = "--vo=" + Configuration.Settings.General.MpvVideoOutput;
|
||||||
|
else
|
||||||
|
labelMpvSettings.Text = "--vo=vaapi";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void linkLabelBingSubscribe_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
private void linkLabelBingSubscribe_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||||
|
45
src/Forms/SettingsMpv.Designer.cs
generated
45
src/Forms/SettingsMpv.Designer.cs
generated
@ -1,5 +1,7 @@
|
|||||||
namespace Nikse.SubtitleEdit.Forms
|
namespace Nikse.SubtitleEdit.Forms
|
||||||
{
|
{
|
||||||
|
using Nikse.SubtitleEdit.Core;
|
||||||
|
|
||||||
sealed partial class SettingsMpv
|
sealed partial class SettingsMpv
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -38,23 +40,37 @@
|
|||||||
//
|
//
|
||||||
// buttonDownload
|
// buttonDownload
|
||||||
//
|
//
|
||||||
this.buttonDownload.Location = new System.Drawing.Point(12, 24);
|
if (!Configuration.IsRunningOnLinux())
|
||||||
this.buttonDownload.Name = "buttonDownload";
|
{
|
||||||
this.buttonDownload.Size = new System.Drawing.Size(186, 23);
|
this.buttonDownload.Location = new System.Drawing.Point(12, 24);
|
||||||
this.buttonDownload.TabIndex = 0;
|
this.buttonDownload.Name = "buttonDownload";
|
||||||
this.buttonDownload.Text = "Download mpv dll";
|
this.buttonDownload.Size = new System.Drawing.Size(186, 23);
|
||||||
this.buttonDownload.UseVisualStyleBackColor = true;
|
this.buttonDownload.TabIndex = 0;
|
||||||
this.buttonDownload.Click += new System.EventHandler(this.buttonDownload_Click_1);
|
this.buttonDownload.Text = "Download mpv dll";
|
||||||
|
this.buttonDownload.UseVisualStyleBackColor = true;
|
||||||
|
this.buttonDownload.Click += new System.EventHandler(this.buttonDownload_Click_1);
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// comboBoxVideoOutput
|
// comboBoxVideoOutput
|
||||||
//
|
//
|
||||||
this.comboBoxVideoOutput.FormattingEnabled = true;
|
this.comboBoxVideoOutput.FormattingEnabled = true;
|
||||||
this.comboBoxVideoOutput.Items.AddRange(new object[] {
|
if (Configuration.IsRunningOnLinux())
|
||||||
"direct3d_shaders",
|
{
|
||||||
"direct3d ",
|
this.comboBoxVideoOutput.Items.AddRange(new object[] {
|
||||||
"sdl",
|
"sdl",
|
||||||
"vaapi",
|
"vaapi",
|
||||||
"vdpau"});
|
"vdpau"});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.comboBoxVideoOutput.Items.AddRange(new object[] {
|
||||||
|
"direct3d_shaders",
|
||||||
|
"direct3d ",
|
||||||
|
"sdl",
|
||||||
|
"vaapi",
|
||||||
|
"vdpau"});
|
||||||
|
}
|
||||||
|
|
||||||
this.comboBoxVideoOutput.Location = new System.Drawing.Point(12, 109);
|
this.comboBoxVideoOutput.Location = new System.Drawing.Point(12, 109);
|
||||||
this.comboBoxVideoOutput.Name = "comboBoxVideoOutput";
|
this.comboBoxVideoOutput.Name = "comboBoxVideoOutput";
|
||||||
this.comboBoxVideoOutput.Size = new System.Drawing.Size(186, 21);
|
this.comboBoxVideoOutput.Size = new System.Drawing.Size(186, 21);
|
||||||
@ -113,7 +129,8 @@
|
|||||||
this.Controls.Add(this.buttonCancel);
|
this.Controls.Add(this.buttonCancel);
|
||||||
this.Controls.Add(this.label1);
|
this.Controls.Add(this.label1);
|
||||||
this.Controls.Add(this.comboBoxVideoOutput);
|
this.Controls.Add(this.comboBoxVideoOutput);
|
||||||
this.Controls.Add(this.buttonDownload);
|
if (!Configuration.IsRunningOnLinux())
|
||||||
|
this.Controls.Add(this.buttonDownload);
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||||
this.KeyPreview = true;
|
this.KeyPreview = true;
|
||||||
this.MaximizeBox = false;
|
this.MaximizeBox = false;
|
||||||
|
@ -13,11 +13,15 @@ namespace Nikse.SubtitleEdit.Forms
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
labelPleaseWait.Text = string.Empty;
|
labelPleaseWait.Text = string.Empty;
|
||||||
comboBoxVideoOutput.Text = Configuration.Settings.General.MpvVideoOutput;
|
if (!Configuration.IsRunningOnLinux())
|
||||||
|
comboBoxVideoOutput.Text = Configuration.Settings.General.MpvVideoOutput;
|
||||||
|
else
|
||||||
|
comboBoxVideoOutput.Text = "vaapi";
|
||||||
buttonCancel.Text = Configuration.Settings.Language.General.Cancel;
|
buttonCancel.Text = Configuration.Settings.Language.General.Cancel;
|
||||||
buttonOK.Text = Configuration.Settings.Language.General.Ok;
|
buttonOK.Text = Configuration.Settings.Language.General.Ok;
|
||||||
Text = Configuration.Settings.Language.SettingsMpv.Title;
|
Text = Configuration.Settings.Language.SettingsMpv.Title;
|
||||||
buttonDownload.Text = Configuration.Settings.Language.SettingsMpv.DownloadMpv;
|
if (!Configuration.IsRunningOnLinux())
|
||||||
|
buttonDownload.Text = Configuration.Settings.Language.SettingsMpv.DownloadMpv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
|
private void wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
|
||||||
@ -27,7 +31,8 @@ namespace Nikse.SubtitleEdit.Forms
|
|||||||
MessageBox.Show(Configuration.Settings.Language.SettingsMpv.DownloadMpvFailed);
|
MessageBox.Show(Configuration.Settings.Language.SettingsMpv.DownloadMpvFailed);
|
||||||
labelPleaseWait.Text = string.Empty;
|
labelPleaseWait.Text = string.Empty;
|
||||||
buttonOK.Enabled = true;
|
buttonOK.Enabled = true;
|
||||||
buttonDownload.Enabled = true;
|
if (!Configuration.IsRunningOnLinux())
|
||||||
|
buttonDownload.Enabled = true;
|
||||||
Cursor = Cursors.Default;
|
Cursor = Cursors.Default;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -53,7 +58,8 @@ namespace Nikse.SubtitleEdit.Forms
|
|||||||
Cursor = Cursors.Default;
|
Cursor = Cursors.Default;
|
||||||
labelPleaseWait.Text = string.Empty;
|
labelPleaseWait.Text = string.Empty;
|
||||||
buttonOK.Enabled = true;
|
buttonOK.Enabled = true;
|
||||||
buttonDownload.Enabled = true;
|
if (!Configuration.IsRunningOnLinux())
|
||||||
|
buttonDownload.Enabled = true;
|
||||||
MessageBox.Show(Configuration.Settings.Language.SettingsMpv.DownloadMpvOk);
|
MessageBox.Show(Configuration.Settings.Language.SettingsMpv.DownloadMpvOk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +69,8 @@ namespace Nikse.SubtitleEdit.Forms
|
|||||||
{
|
{
|
||||||
labelPleaseWait.Text = Configuration.Settings.Language.General.PleaseWait;
|
labelPleaseWait.Text = Configuration.Settings.Language.General.PleaseWait;
|
||||||
buttonOK.Enabled = false;
|
buttonOK.Enabled = false;
|
||||||
buttonDownload.Enabled = false;
|
if (!Configuration.IsRunningOnLinux())
|
||||||
|
buttonDownload.Enabled = false;
|
||||||
Refresh();
|
Refresh();
|
||||||
Cursor = Cursors.WaitCursor;
|
Cursor = Cursors.WaitCursor;
|
||||||
|
|
||||||
@ -80,7 +87,8 @@ namespace Nikse.SubtitleEdit.Forms
|
|||||||
{
|
{
|
||||||
labelPleaseWait.Text = string.Empty;
|
labelPleaseWait.Text = string.Empty;
|
||||||
buttonOK.Enabled = true;
|
buttonOK.Enabled = true;
|
||||||
buttonDownload.Enabled = true;
|
if (!Configuration.IsRunningOnLinux())
|
||||||
|
buttonDownload.Enabled = true;
|
||||||
Cursor = Cursors.Default;
|
Cursor = Cursors.Default;
|
||||||
MessageBox.Show(exception.Message + Environment.NewLine + Environment.NewLine + exception.StackTrace);
|
MessageBox.Show(exception.Message + Environment.NewLine + Environment.NewLine + exception.StackTrace);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ namespace Nikse.SubtitleEdit.Logic
|
|||||||
GeneralSettings gs = Configuration.Settings.General;
|
GeneralSettings gs = Configuration.Settings.General;
|
||||||
|
|
||||||
if (Configuration.IsRunningOnLinux())
|
if (Configuration.IsRunningOnLinux())
|
||||||
return new MPlayer();
|
return new LibMpvMono();
|
||||||
|
|
||||||
// Mono on OS X is 32 bit and thus requires 32 bit VLC. Place VLC in the same
|
// Mono on OS X is 32 bit and thus requires 32 bit VLC. Place VLC in the same
|
||||||
// folder as Subtitle Edit and add this to the app.config inside the
|
// folder as Subtitle Edit and add this to the app.config inside the
|
||||||
|
431
src/Logic/VideoPlayers/LibMpvMono.cs
Normal file
431
src/Logic/VideoPlayers/LibMpvMono.cs
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
using Nikse.SubtitleEdit.Core;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Nikse.SubtitleEdit.Core.SubtitleFormats;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Nikse.SubtitleEdit.Logic.VideoPlayers
|
||||||
|
{
|
||||||
|
public class LibMpvMono : VideoPlayer, IDisposable
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
#region mpv dll methods
|
||||||
|
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern IntPtr mpv_create();
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern int mpv_initialize(IntPtr mpvHandle);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern int mpv_command(IntPtr mpvHandle, IntPtr utf8Strings);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern int mpv_terminate_destroy(IntPtr mpvHandle);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern IntPtr mpv_wait_event(IntPtr mpvHandle, double wait);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern int mpv_set_option(IntPtr mpvHandle, byte[] name, int format, ref long data);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern int mpv_set_option_string(IntPtr mpvHandle, byte[] name, byte[] value);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern IntPtr mpv_get_property_string(IntPtr mpvHandle, byte[] name);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern int mpv_get_property(IntPtr mpvHandle, byte[] name, int format, ref double data);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern int mpv_set_property(IntPtr mpvHandle, byte[] name, int format, ref byte[] data);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("mpv", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern int mpv_free(IntPtr data);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private IntPtr _libMpvDll;
|
||||||
|
private IntPtr _mpvHandle;
|
||||||
|
private Timer _videoLoadedTimer;
|
||||||
|
// private Timer _videoEndedTimer;
|
||||||
|
|
||||||
|
public override event EventHandler OnVideoLoaded;
|
||||||
|
public override event EventHandler OnVideoEnded;
|
||||||
|
|
||||||
|
private const int MpvFormatString = 1;
|
||||||
|
|
||||||
|
private object GetDllType(Type type, string name)
|
||||||
|
{
|
||||||
|
IntPtr address = NativeMethods.GetProcAddress(_libMpvDll, name);
|
||||||
|
if (address != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return Marshal.GetDelegateForFunctionPointer(address, type);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static byte[] GetUtf8Bytes(string s)
|
||||||
|
{
|
||||||
|
return Encoding.UTF8.GetBytes(s + "\0");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPtr AllocateUtf8IntPtrArrayWithSentinel(string[] arr, out IntPtr[] byteArrayPointers)
|
||||||
|
{
|
||||||
|
int numberOfStrings = arr.Length + 1; // add extra element for extra null pointer last (sentinel)
|
||||||
|
byteArrayPointers = new IntPtr[numberOfStrings];
|
||||||
|
IntPtr rootPointer = Marshal.AllocCoTaskMem(IntPtr.Size * numberOfStrings);
|
||||||
|
for (int index = 0; index < arr.Length; index++)
|
||||||
|
{
|
||||||
|
var bytes = GetUtf8Bytes(arr[index]);
|
||||||
|
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
|
||||||
|
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
|
||||||
|
byteArrayPointers[index] = unmanagedPointer;
|
||||||
|
}
|
||||||
|
Marshal.Copy(byteArrayPointers, 0, rootPointer, numberOfStrings);
|
||||||
|
return rootPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DoMpvCommand(params string[] args)
|
||||||
|
{
|
||||||
|
if (_mpvHandle == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IntPtr[] byteArrayPointers;
|
||||||
|
var mainPtr = AllocateUtf8IntPtrArrayWithSentinel(args, out byteArrayPointers);
|
||||||
|
mpv_command(_mpvHandle, mainPtr);
|
||||||
|
foreach (var ptr in byteArrayPointers)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(ptr);
|
||||||
|
}
|
||||||
|
Marshal.FreeHGlobal(mainPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string PlayerName
|
||||||
|
{
|
||||||
|
get { return "MPV Player"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _volume = 75;
|
||||||
|
public override int Volume
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _volume;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
DoMpvCommand("set", "volume", value.ToString());
|
||||||
|
_volume = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override double Duration
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_mpvHandle == IntPtr.Zero)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int mpvFormatDouble = 5;
|
||||||
|
double d = 0;
|
||||||
|
mpv_get_property(_mpvHandle, GetUtf8Bytes("duration"), mpvFormatDouble, ref d);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override double CurrentPosition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_mpvHandle == IntPtr.Zero)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int mpvFormatDouble = 5;
|
||||||
|
double d = 0;
|
||||||
|
mpv_get_property(_mpvHandle, GetUtf8Bytes("time-pos"), mpvFormatDouble, ref d);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_mpvHandle == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DoMpvCommand("seek", value.ToString(CultureInfo.InvariantCulture), "absolute");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _playRate = 2.0;
|
||||||
|
public override double PlayRate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _playRate;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
DoMpvCommand("set", "speed", value.ToString(CultureInfo.InvariantCulture));
|
||||||
|
_playRate = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetNextFrame()
|
||||||
|
{
|
||||||
|
if (_mpvHandle == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DoMpvCommand("frame-step");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetPreviousFrame()
|
||||||
|
{
|
||||||
|
if (_mpvHandle == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DoMpvCommand("frame-back-step");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Play()
|
||||||
|
{
|
||||||
|
if (_mpvHandle == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var bytes = GetUtf8Bytes("no");
|
||||||
|
mpv_set_property(_mpvHandle, GetUtf8Bytes("pause"), MpvFormatString, ref bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Pause()
|
||||||
|
{
|
||||||
|
if (_mpvHandle == IntPtr.Zero)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var bytes = GetUtf8Bytes("yes");
|
||||||
|
mpv_set_property(_mpvHandle, GetUtf8Bytes("pause"), MpvFormatString, ref bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Stop()
|
||||||
|
{
|
||||||
|
Pause();
|
||||||
|
CurrentPosition = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsPaused
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_mpvHandle == IntPtr.Zero)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var lpBuffer = mpv_get_property_string(_mpvHandle, GetUtf8Bytes("pause"));
|
||||||
|
string s = Marshal.PtrToStringAnsi(lpBuffer);
|
||||||
|
bool isPaused = s == "yes";
|
||||||
|
mpv_free(lpBuffer);
|
||||||
|
return isPaused;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsPlaying
|
||||||
|
{
|
||||||
|
get { return !IsPaused; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<string> _audioTrackIds;
|
||||||
|
public int AudioTrackCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_audioTrackIds == null)
|
||||||
|
{
|
||||||
|
_audioTrackIds = new List<string>();
|
||||||
|
var lpBuffer = mpv_get_property_string(_mpvHandle, GetUtf8Bytes("track-list"));
|
||||||
|
string trackListJson = Marshal.PtrToStringAnsi(lpBuffer);
|
||||||
|
foreach (var json in Json.ReadObjectArray(trackListJson))
|
||||||
|
{
|
||||||
|
string trackType = Json.ReadTag(json, "type");
|
||||||
|
string id = Json.ReadTag(json, "id");
|
||||||
|
if (trackType == "audio")
|
||||||
|
{
|
||||||
|
_audioTrackIds.Add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mpv_free(lpBuffer);
|
||||||
|
}
|
||||||
|
return _audioTrackIds.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int AudioTrackNumber
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var lpBuffer = mpv_get_property_string(_mpvHandle, GetUtf8Bytes("aid"));
|
||||||
|
string str = Marshal.PtrToStringAnsi(lpBuffer);
|
||||||
|
int number = 0;
|
||||||
|
if (AudioTrackCount > 1 && _audioTrackIds.Contains(str))
|
||||||
|
{
|
||||||
|
number = _audioTrackIds.IndexOf(str);
|
||||||
|
}
|
||||||
|
mpv_free(lpBuffer);
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
string id = "1";
|
||||||
|
if (AudioTrackCount > 1 && value >= 0 && value < _audioTrackIds.Count)
|
||||||
|
{
|
||||||
|
id = _audioTrackIds[value];
|
||||||
|
}
|
||||||
|
DoMpvCommand("set", "aid", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsInstalled
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetMpvPath(string fileName)
|
||||||
|
{
|
||||||
|
var path = Path.Combine(Configuration.DataDirectory, fileName);
|
||||||
|
if (File.Exists(path))
|
||||||
|
return path;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Initialize(Control ownerControl, string videoFileName, EventHandler onVideoLoaded, EventHandler onVideoEnded)
|
||||||
|
{
|
||||||
|
_mpvHandle = mpv_create();
|
||||||
|
OnVideoLoaded = onVideoLoaded;
|
||||||
|
OnVideoEnded = onVideoEnded;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(videoFileName))
|
||||||
|
{
|
||||||
|
//Mono.Unix.
|
||||||
|
mpv_initialize(_mpvHandle);
|
||||||
|
|
||||||
|
string videoOutput = "vaapi";
|
||||||
|
if (!string.IsNullOrWhiteSpace(Configuration.Settings.General.MpvVideoOutput))
|
||||||
|
videoOutput = Configuration.Settings.General.MpvVideoOutput;
|
||||||
|
mpv_set_option_string(_mpvHandle, GetUtf8Bytes("vo"), GetUtf8Bytes(videoOutput)); // "direct3d_shaders" is default, "direct3d" could be used for compabality with old systems
|
||||||
|
|
||||||
|
mpv_set_option_string(_mpvHandle, GetUtf8Bytes("keep-open"), GetUtf8Bytes("always")); // don't auto close video
|
||||||
|
mpv_set_option_string(_mpvHandle, GetUtf8Bytes("no-sub"), GetUtf8Bytes("")); // don't load subtitles
|
||||||
|
if (ownerControl != null)
|
||||||
|
{
|
||||||
|
int mpvFormatInt64 = 4;
|
||||||
|
var windowId = ownerControl.Handle.ToInt64();
|
||||||
|
mpv_set_option(_mpvHandle, GetUtf8Bytes("wid"), mpvFormatInt64, ref windowId);
|
||||||
|
}
|
||||||
|
DoMpvCommand("loadfile", videoFileName);
|
||||||
|
|
||||||
|
_videoLoadedTimer = new Timer { Interval = 50 };
|
||||||
|
_videoLoadedTimer.Tick += VideoLoadedTimer_Tick;
|
||||||
|
_videoLoadedTimer.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VideoLoadedTimer_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_videoLoadedTimer.Stop();
|
||||||
|
const int mpvEventFileLoaded = 8;
|
||||||
|
int l = 0;
|
||||||
|
while (l < 10000)
|
||||||
|
{
|
||||||
|
Application.DoEvents();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_mpvHandle != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
var eventIdHandle = mpv_wait_event(_mpvHandle, 0);
|
||||||
|
var eventId = Convert.ToInt64(Marshal.PtrToStructure(eventIdHandle, typeof(int)));
|
||||||
|
if (eventId == mpvEventFileLoaded)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Application.DoEvents();
|
||||||
|
if (OnVideoLoaded != null)
|
||||||
|
OnVideoLoaded.Invoke(this, null);
|
||||||
|
Application.DoEvents();
|
||||||
|
Pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void DisposeVideoPlayer()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReleaseUnmangedResources()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
if (_mpvHandle != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
mpv_terminate_destroy(_mpvHandle);
|
||||||
|
_mpvHandle = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_libMpvDll != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
NativeMethods.FreeLibrary(_libMpvDll);
|
||||||
|
_libMpvDll = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~LibMpvMono()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (_mpvHandle != IntPtr.Zero)
|
||||||
|
DoMpvCommand("quit");
|
||||||
|
ReleaseUnmangedResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -378,7 +378,7 @@ namespace Nikse.SubtitleEdit.Logic.VideoPlayers
|
|||||||
{
|
{
|
||||||
_mpvInitialize.Invoke(_mpvHandle);
|
_mpvInitialize.Invoke(_mpvHandle);
|
||||||
|
|
||||||
string videoOutput = "direct3d_shaders";
|
string videoOutput = "vaapi";
|
||||||
if (!string.IsNullOrWhiteSpace(Configuration.Settings.General.MpvVideoOutput))
|
if (!string.IsNullOrWhiteSpace(Configuration.Settings.General.MpvVideoOutput))
|
||||||
videoOutput = Configuration.Settings.General.MpvVideoOutput;
|
videoOutput = Configuration.Settings.General.MpvVideoOutput;
|
||||||
_mpvSetOptionString(_mpvHandle, GetUtf8Bytes("vo"), GetUtf8Bytes(videoOutput)); // "direct3d_shaders" is default, "direct3d" could be used for compabality with old systems
|
_mpvSetOptionString(_mpvHandle, GetUtf8Bytes("vo"), GetUtf8Bytes(videoOutput)); // "direct3d_shaders" is default, "direct3d" could be used for compabality with old systems
|
||||||
|
@ -866,6 +866,7 @@
|
|||||||
<Compile Include="Logic\UiGetPacEncoding.cs" />
|
<Compile Include="Logic\UiGetPacEncoding.cs" />
|
||||||
<Compile Include="Logic\UiGetYouTubeAnnotationStyles.cs" />
|
<Compile Include="Logic\UiGetYouTubeAnnotationStyles.cs" />
|
||||||
<Compile Include="Logic\UiUtil.cs" />
|
<Compile Include="Logic\UiUtil.cs" />
|
||||||
|
<Compile Include="Logic\VideoPlayers\LibMpvMono.cs" />
|
||||||
<Compile Include="Logic\VideoPlayers\LibMpvDynamic.cs" />
|
<Compile Include="Logic\VideoPlayers\LibMpvDynamic.cs" />
|
||||||
<Compile Include="Logic\VideoPlayers\LibVlcDynamic.cs" />
|
<Compile Include="Logic\VideoPlayers\LibVlcDynamic.cs" />
|
||||||
<Compile Include="Logic\VideoPlayers\LibVlcMono.cs" />
|
<Compile Include="Logic\VideoPlayers\LibVlcMono.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user