Skip to content

Commit

Permalink
Merge pull request #89 from insomniachi/media_detection_improvements
Browse files Browse the repository at this point in the history
Media detection improvements
  • Loading branch information
insomniachi authored Feb 28, 2024
2 parents fa7ce76 + 494fd9d commit 34778c0
Show file tree
Hide file tree
Showing 52 changed files with 971 additions and 351 deletions.
Binary file modified Plugins Store/Totoro.Plugins.MediaDetection.Generic.dll
Binary file not shown.
Binary file not shown.
Binary file modified Plugins Store/Totoro.Plugins.MediaDetection.Vlc.dll
Binary file not shown.
Binary file modified Plugins Store/Totoro.Plugins.MediaDetection.Win11MediaPlayer.dll
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.ComponentModel;
using Totoro.Plugins.Options;

namespace Totoro.Plugins.MediaDetection.MpcHc;

public class Config : ConfigObject
{
[DisplayName("Path")]
[Description("Path to executable")]
[Glyph(Glyphs.File)]
public string FileName { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"MPC-HC\mpc-hc64.exe");

[Glyph(Glyphs.Website)]
public string Host { get; set; } = "127.0.0.1";

[Glyph(Glyphs.Port)]
[Description("View > Options > Web Interface > Listen on port")]
public int Port { get; set; } = 13579;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.Diagnostics;
using System.Reactive.Linq;
using FlaUI.Core;
using FlaUI.Core.AutomationElements;
using ReactiveUI;
using Totoro.Plugins.MediaDetection.Contracts;
using Totoro.Plugins.Options;

namespace Totoro.Plugins.MediaDetection.MpcHc
{
internal sealed partial class MediaPlayer : ReactiveObject, INativeMediaPlayer, IHavePosition, ICanLaunch
{
private string? _customTitle;
private MpvHcInterface _interface = null!;

public IObservable<TimeSpan> PositionChanged { get; private set; } = null!;
public IObservable<TimeSpan> DurationChanged { get; private set; } = null!;
public IObservable<string> TitleChanged { get; private set; } = null!;
public Process? Process { get; private set; }


public Task Launch(string title, string url)
{
_customTitle = title;
var app = Application.Launch(ConfigManager<Config>.Current.FileName, $"{url} /fullscreen");
InitializeInternal(Process.GetProcessById(app.ProcessId), true);
return Task.CompletedTask;
}

public Task Initialize(Window window)
{
Process = Process.GetProcessById(window.Properties.ProcessId);
InitializeInternal(Process);
return Task.CompletedTask;
}

private void InitializeInternal(Process process, bool hasCustomTitle = false)
{
_interface = new MpvHcInterface(process);

TitleChanged = hasCustomTitle
? Observable.Return(_customTitle!)
: _interface.TitleChanged;

DurationChanged = _interface.DurationChanged;
PositionChanged = _interface.PositionChanged;
}

public void Dispose()
{
_interface.Dispose();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System.Diagnostics;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text.RegularExpressions;
using Flurl;
using Flurl.Http;
using ReactiveUI;
using Totoro.Plugins.Options;

namespace Totoro.Plugins.MediaDetection.MpcHc;

internal sealed partial class MpvHcInterface : IDisposable
{
private readonly string _api;
private readonly CompositeDisposable _disposables = new();
private readonly ReplaySubject<string> _titleChanged = new();
private readonly ReplaySubject<TimeSpan> _durationChanged = new();
private readonly ReplaySubject<TimeSpan> _timeChanged = new();

[GeneratedRegex(@"<p id=""(?<Variable>(file|positionstring|durationstring))"">(?<Value>[^<>]*)")]
private partial Regex VariablesRegex();

public IObservable<string> TitleChanged { get; }
public IObservable<TimeSpan> DurationChanged { get; }
public IObservable<TimeSpan> PositionChanged { get; }

public MpvHcInterface(Process process)
{
var host = ConfigManager<Config>.Current.Host;
var port = ConfigManager<Config>.Current.Port;
_api = $"http://{host}:{port}";

Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1))
.Where(_ => !process.HasExited)
.SelectMany(_ => GetVariables())
.WhereNotNull()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(variables =>
{
if (!string.IsNullOrEmpty(variables.Title))
{
_titleChanged.OnNext(variables.Title);
}
_durationChanged.OnNext(variables.Duration);
_timeChanged.OnNext(variables.Time);
})
.DisposeWith(_disposables);

TitleChanged = _titleChanged.DistinctUntilChanged();
DurationChanged = _durationChanged.DistinctUntilChanged();
PositionChanged = _timeChanged.DistinctUntilChanged();
}

private async Task<Variables?> GetVariables()
{
var result = await _api.AppendPathSegment("variables.html").GetAsync();

if(result.StatusCode >= 300)
{
return null;
}

var html = await result.GetStringAsync();
var variables = new Variables();

foreach (var match in VariablesRegex().Matches(html).OfType<Match>().Where(x => x.Success))
{
var name = match.Groups["Variable"].Value;
var value = match.Groups["Value"].Value;

if (name == "file")
{
variables.Title = Path.GetFileNameWithoutExtension(value);
}
else if(name == "positionstring")
{
variables.Time = TimeSpan.Parse(value);
}
else if(name == "durationstring")
{
variables.Duration = TimeSpan.Parse(value);
}
}

return variables;
}

public void Dispose()
{
_disposables.Dispose();
}

}

internal class Variables
{
public string Title { get; set; } = string.Empty;
public TimeSpan Duration { get; set; }
public TimeSpan Time { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Reflection;
using Totoro.Plugins.Contracts;
using Totoro.Plugins.MediaDetection.Contracts;

namespace Totoro.Plugins.MediaDetection.MpcHc;

public class Plugin : Plugin<INativeMediaPlayer, Config>
{
public override INativeMediaPlayer Create() => new MediaPlayer();

public override PluginInfo GetInfo()
{
return new PluginInfo
{
Name = "mpc-hc64",
DisplayName = "MPC-HC",
Description = "",
Version = Assembly.GetExecutingAssembly().GetName().Version!,
Icon = typeof(Plugin).Assembly.GetManifestResourceStream("Totoro.Plugins.MediaDetection.MpcHc.mpc-hc-logo.png"),
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>x64</Platforms>
<Version>1.0</Version>
<OutputPath Condition="$(Configuration) == Release">..\..\..\Plugins Store\</OutputPath>
<AppendTargetFrameworkToOutputPath Condition="$(Configuration) == Release">false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath Condition="$(Configuration) == Release">false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>

<ItemGroup>
<EmbeddedResource Include="mpc-hc-logo.png" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\Totoro.Plugins.MediaDetection\Totoro.Plugins.MediaDetection.csproj" />
</ItemGroup>

</Project>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
using Totoro.Plugins.Options;
using System.ComponentModel;
using Totoro.Plugins.Options;

namespace Totoro.Plugins.MediaDetection.Generic;

public class MpcConfig : ConfigObject
{
public string FileName { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"MPC-HC\mpc-hc64.exe");
}

public class MpvConfig : ConfigObject
{
[DisplayName("Path")]
[Description("Path to executable")]
[Glyph(Glyphs.File)]
public string FileName { get; set; } = @"";
}
Original file line number Diff line number Diff line change
@@ -1,76 +1,40 @@
using System.Diagnostics;
using FlaUI.Core;
using FlaUI.Core.AutomationElements;
using FlaUI.Core;
using Totoro.Plugins.MediaDetection.Contracts;
using Totoro.Plugins.Options;

namespace Totoro.Plugins.MediaDetection.Generic;

public class Mpv : GenericMediaPlayer, ICanLaunch
public sealed class Mpv : GenericMediaPlayer, ICanLaunch
{
private bool _hasCustomTitle;
private string? _customTitle;
private Application? _application;

protected override string ParseFromWindowTitle(string windowTitle)
protected override Task<string> ParseFromWindowTitle(string windowTitle)
{
return windowTitle.Replace("- mpv", string.Empty);
return Task.FromResult(windowTitle.Replace("- mpv", string.Empty));
}

public override string GetTitle()
public override Task<string> GetTitle()
{
if (_hasCustomTitle)
{
return _customTitle!;
return Task.FromResult(_customTitle!);
}

return base.GetTitle();
}

public void Launch(string title, string url)
public Task Launch(string title, string url)
{
_hasCustomTitle = true;
_customTitle = title;
Application.Launch(ConfigManager<MpvConfig>.Current.FileName, $"{url} --title=\"{title}\" --fs");
}
}

public sealed class MpcHc : INativeMediaPlayer, ICanLaunch
{
private Window? _window;
private bool _hasCustomTitle;
private string? _customTitle;

public Process? Process { get; private set; }

public void Dispose() { }

public string GetTitle()
{
if (_hasCustomTitle)
{
return _customTitle!;
}

var title = _window!.Title;
while (title == "Media Player Classic Home Cinema")
{
title = _window!.Title;
Thread.Sleep(100);
}

return title;
_application = Application.Launch(ConfigManager<MpvConfig>.Current.FileName, $"{url} --title=\"{title}\" --fs");
return Task.CompletedTask;
}

public void Initialize(Window window)
public override void Dispose()
{
_window = window;
Process = Process.GetProcessById(window.Properties.ProcessId);
}

public void Launch(string title, string url)
{
_hasCustomTitle = true;
_customTitle = title;
Application.Launch(ConfigManager<MpcConfig>.Current.FileName, $"{url} /fullscreen");
_application?.Dispose();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,8 @@ public override PluginInfo GetInfo()
Name = "mpv",
DisplayName = "MPV",
Description = "",
Version = Assembly.GetExecutingAssembly().GetName().Version!
};
}
}

public class MpcHcPlugin : GenericPlugin<MpcHc, MpcConfig>
{
public override PluginInfo GetInfo()
{
return new PluginInfo
{
Name = "mpc-hc64",
DisplayName = "MPC-HC",
Description = "",
Version = Assembly.GetExecutingAssembly().GetName().Version!
Version = Assembly.GetExecutingAssembly().GetName().Version!,
Icon = typeof(MpvPlugin).Assembly.GetManifestResourceStream("Totoro.Plugins.MediaDetection.Generic.mpv-icon.png"),
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>x64</Platforms>
<Version>1.4</Version>
<Version>1.5</Version>
<OutputPath Condition="$(Configuration) == Release">..\..\..\Plugins Store\</OutputPath>
<AppendTargetFrameworkToOutputPath Condition="$(Configuration) == Release">false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath Condition="$(Configuration) == Release">false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>

<ItemGroup>
<EmbeddedResource Include="mpv-icon.png" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\Totoro.Plugins.MediaDetection\Totoro.Plugins.MediaDetection.csproj" />
</ItemGroup>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.ComponentModel;
using Totoro.Plugins.Options;

namespace Totoro.Plugins.MediaDetection.Vlc;

public class Config : ConfigObject
{
[DisplayName("Path")]
[Description("Path to executable")]
[Glyph(Glyphs.File)]
public string FileName { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"VideoLAN\VLC\vlc.exe");

[Glyph(Glyphs.Website)]
[Description("Enable web interface Preferences > Interface > Main Interfaces > Web Interface")]
public string Host { get; set; } = "127.0.0.1";

[Glyph(Glyphs.Port)]
public int Port { get; set; } = 8080;

[Glyph(Glyphs.Password)]
[Description("Password set in Preferences > Interface > Main Interfaces > Lua > Lua HTTP password")]
public string Password { get; set; } = "";
}
Loading

0 comments on commit 34778c0

Please sign in to comment.