From f36a4075b1c1f5b34c4e1236a73d66723fceba41 Mon Sep 17 00:00:00 2001 From: datasone Date: Sat, 12 Mar 2022 18:44:02 +0800 Subject: [PATCH] Add reset SMTC functionality --- MPVMediaControl/MediaController.cs | 55 ++++++++++++++++++++++++------ MPVMediaControl/Program.cs | 29 ++++++++++++++-- 2 files changed, 71 insertions(+), 13 deletions(-) diff --git a/MPVMediaControl/MediaController.cs b/MPVMediaControl/MediaController.cs index 8160275..f4b1bd4 100644 --- a/MPVMediaControl/MediaController.cs +++ b/MPVMediaControl/MediaController.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Linq; using System.Threading; using Windows.Media; using Windows.Media.Playback; @@ -11,9 +10,9 @@ namespace MPVMediaControl { public class MediaController { - private readonly SystemMediaTransportControls _controls; - private readonly SystemMediaTransportControlsDisplayUpdater _updater; - private readonly MediaPlayer _mediaPlayer; + private SystemMediaTransportControls _controls; + private SystemMediaTransportControlsDisplayUpdater _updater; + private MediaPlayer _mediaPlayer; public readonly int Pid; @@ -54,9 +53,14 @@ public void Cleanup() System.IO.File.Delete(ShotPath); } } + + public MCMediaFile Clone() + { + return this.MemberwiseClone() as MCMediaFile; + } } - private readonly MCMediaFile _file = new MCMediaFile(); + private MCMediaFile _file = new MCMediaFile(); public MCMediaFile File { @@ -140,9 +144,8 @@ public PlayState State } } - public MediaController(int pid) + public void InitSMTC() { - this.Pid = pid; _mediaPlayer = new MediaPlayer(); _controls = _mediaPlayer.SystemMediaTransportControls; _mediaPlayer.CommandManager.IsEnabled = false; @@ -155,13 +158,45 @@ public MediaController(int pid) _controls.IsNextEnabled = true; _controls.IsPreviousEnabled = true; - State = PlayState.Stop; + State = _state; + + if (_file.Path != null) + { + File = _file; + } + } + + public MediaController(int pid, bool initSMTC) + { + this.Pid = pid; + _state = PlayState.Stop; + + if (initSMTC) + { + InitSMTC(); + } } - public void Cleanup() + public MediaController DuplicateSelf() { - _file?.Cleanup(); + var newObj = new MediaController(Pid, false); + newObj._file = _file.Clone(); + newObj._state = _state; + return newObj; + } + + public void Cleanup(bool cleanFile) + { + if (cleanFile) + { + _file?.Cleanup(); + } _updater.ClearAll(); + + // Ensure objects collected while "resetting SMTC" + _updater = null; + _controls = null; + _mediaPlayer = null; } public void UpdateShotPath(string path) diff --git a/MPVMediaControl/Program.cs b/MPVMediaControl/Program.cs index cc16031..c579f30 100644 --- a/MPVMediaControl/Program.cs +++ b/MPVMediaControl/Program.cs @@ -3,6 +3,7 @@ using System.Drawing; using System.Linq; using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; namespace MPVMediaControl @@ -47,6 +48,7 @@ public MyAppContext() Icon = new Icon(SystemIcons.Application, 32, 32), ContextMenu = new ContextMenu(new [] { + new MenuItem("Reset SMTC", ResetControllers), new MenuItem("Exit", Exit) }), Visible = true @@ -61,7 +63,7 @@ public MediaController GetController(int pid) { if (_controllers.FindIndex(c => c.Pid == pid) == -1) { - _controllers.Add(new MediaController(pid)); + _controllers.Add(new MediaController(pid, true)); return _controllers.Last(); } @@ -71,17 +73,38 @@ public MediaController GetController(int pid) public void RemoveController(int pid) { var controller = _controllers.Find(c => c.Pid == pid); - controller.Cleanup(); + controller.Cleanup(true); _controllers.Remove(controller); } + private async void ResetControllers(object sender, EventArgs e) + { + var newControllers = _controllers.Select(c => c.DuplicateSelf()).ToList(); + + _controllers.ForEach(c => c.Cleanup(false)); + _controllers.Clear(); + + // We need to manually trigger GC to remove MusicPlayer instances and prevent duplicate SMTC controls + GC.Collect(); + + _controllers.AddRange(newControllers); + + // There is a bug in Windows where the control is not visible (but exists and is able to interact) if the info is updated too fast + // Sleep for a bit to prevent this + foreach (var controller in _controllers) + { + await Task.Delay(400); + controller.InitSMTC(); + } + } + private void Exit(object sender, EventArgs e) { _trayIcon.Visible = false; PipeServer.Cleanup(); - _controllers.ForEach(i => i.Cleanup()); + _controllers.ForEach(i => i.Cleanup(true)); Application.Exit(); Environment.Exit(0);