using MediaBrowser.Model.Dto; using MediaBrowser.Model.Logging; using MediaBrowser.UI.Configuration; using MediaBrowser.UI.UserInput; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; namespace MediaBrowser.UI.Playback.ExternalPlayer { /// /// Class BaseExternalPlayer /// public abstract class BaseExternalPlayer : BaseMediaPlayer { protected BaseExternalPlayer(ILogger logger) : base(logger) { } /// /// Gets a value indicating whether this instance can mute. /// /// true if this instance can mute; otherwise, false. public override bool CanMute { get { return false; } } /// /// Gets a value indicating whether this instance can change volume. /// /// true if this instance can change volume; otherwise, false. public override bool CanControlVolume { get { return false; } } /// /// Gets a value indicating whether this instance can close automatically. /// /// true if this instance can close automatically; otherwise, false. protected virtual bool CanCloseAutomatically { get { return false; } } /// /// Gets a value indicating whether [supports multi file playback]. /// /// true if [supports multi file playback]; otherwise, false. public override bool SupportsMultiFilePlayback { get { return false; } } /// /// Gets the current process. /// /// The current process. protected Process CurrentProcess { get; private set; } /// /// Gets the process start info. /// /// The items. /// The options. /// The player configuration. /// ProcessStartInfo. protected virtual ProcessStartInfo GetProcessStartInfo(List items, PlayOptions options, PlayerConfiguration playerConfiguration) { return new ProcessStartInfo { FileName = playerConfiguration.Command, Arguments = GetCommandArguments(items, options, playerConfiguration) }; } /// /// Gets the command arguments. /// /// The items. /// The options. /// The player configuration. /// System.String. protected virtual string GetCommandArguments(List items, PlayOptions options, PlayerConfiguration playerConfiguration) { var args = playerConfiguration.Args; if (string.IsNullOrEmpty(args)) { return string.Empty; } return GetCommandArguments(items, args); } /// /// Gets the command arguments. /// /// The items. /// The format string. /// System.String. protected string GetCommandArguments(List items, string formatString) { var paths = items.Select(i => "\"" + GetPathForCommandLine(i) + "\""); return string.Format(formatString, string.Join(" ", paths.ToArray())); } /// /// Gets the path for command line. /// /// The item. /// System.String. protected virtual string GetPathForCommandLine(BaseItemDto item) { return item.Path; } /// /// Gets a value indicating whether this instance can queue. /// /// true if this instance can queue; otherwise, false. public override bool CanQueue { get { return false; } } /// /// Gets a value indicating whether this instance can pause. /// /// true if this instance can pause; otherwise, false. public override bool CanPause { get { return false; } } /// /// Gets a value indicating whether this instance can seek. /// /// true if this instance can seek; otherwise, false. public override bool CanSeek { get { return false; } } /// /// Plays the internal. /// /// The items. /// The options. /// The player configuration. protected override void PlayInternal(List items, PlayOptions options, PlayerConfiguration playerConfiguration) { CurrentProcess = new Process { EnableRaisingEvents = true, StartInfo = GetProcessStartInfo(items, options, playerConfiguration) }; Logger.Info("{0} {1}", CurrentProcess.StartInfo.FileName, CurrentProcess.StartInfo.Arguments); CurrentProcess.Start(); OnExternalPlayerLaunched(); if (!CanCloseAutomatically) { KeyboardListener.KeyDown += KeyboardListener_KeyDown; } CurrentProcess.Exited += CurrentProcess_Exited; } /// /// Handles the KeyDown event of the KeyboardListener control. /// /// The source of the event. /// The instance containing the event data. void KeyboardListener_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.MediaStop) { var playstate = PlayState; if (playstate == PlayState.Paused || playstate == PlayState.Playing) { Stop(); } } } /// /// Handles the Exited event of the CurrentProcess control. /// /// The source of the event. /// The instance containing the event data. void CurrentProcess_Exited(object sender, EventArgs e) { var process = (Process)sender; process.Dispose(); OnPlayerStopped(CurrentPlaylistIndex, CurrentPositionTicks); } /// /// Stops the internal. /// /// Task. protected override Task StopInternal() { return Task.Run(() => CurrentProcess.Kill()); } /// /// Called when [player stopped internal]. /// protected override void OnPlayerStoppedInternal() { KeyboardListener.KeyDown -= KeyboardListener_KeyDown; base.OnPlayerStoppedInternal(); } /// /// Called when [external player launched]. /// protected virtual void OnExternalPlayerLaunched() { } } }