diff options
| author | LukePulverenti <luke.pulverenti@gmail.com> | 2013-02-23 10:58:08 -0500 |
|---|---|---|
| committer | LukePulverenti <luke.pulverenti@gmail.com> | 2013-02-23 10:58:08 -0500 |
| commit | 17c1fd576057bdd2d6aea517d733fe8af6e6b2ba (patch) | |
| tree | 660f47e816a8599aabdb7ee47f3cde64c72c3f4d /MediaBrowser.UI/Playback | |
| parent | 33ed929b526acbda696f00f5966917ebd6a9ded2 (diff) | |
moved ui to it's own repo
Diffstat (limited to 'MediaBrowser.UI/Playback')
| -rw-r--r-- | MediaBrowser.UI/Playback/BaseMediaPlayer.cs | 747 | ||||
| -rw-r--r-- | MediaBrowser.UI/Playback/ExternalPlayer/BaseExternalPlayer.cs | 243 | ||||
| -rw-r--r-- | MediaBrowser.UI/Playback/ExternalPlayer/GenericExternalPlayer.cs | 35 | ||||
| -rw-r--r-- | MediaBrowser.UI/Playback/InternalPlayer/BaseInternalMediaPlayer.cs | 54 | ||||
| -rw-r--r-- | MediaBrowser.UI/Playback/NVlc/InternalMediaPlayerNVlc.cs | 426 | ||||
| -rw-r--r-- | MediaBrowser.UI/Playback/PlayOptions.cs | 89 | ||||
| -rw-r--r-- | MediaBrowser.UI/Playback/PlayState.cs | 24 | ||||
| -rw-r--r-- | MediaBrowser.UI/Playback/PlaybackEventArgs.cs | 49 | ||||
| -rw-r--r-- | MediaBrowser.UI/Playback/PlaybackManager.cs | 301 |
9 files changed, 0 insertions, 1968 deletions
diff --git a/MediaBrowser.UI/Playback/BaseMediaPlayer.cs b/MediaBrowser.UI/Playback/BaseMediaPlayer.cs deleted file mode 100644 index 6e3324b053..0000000000 --- a/MediaBrowser.UI/Playback/BaseMediaPlayer.cs +++ /dev/null @@ -1,747 +0,0 @@ -using MediaBrowser.Common.Events; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using MediaBrowser.UI.Configuration; -using MediaBrowser.UI.Controller; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.UI.Playback -{ - /// <summary> - /// Class BaseMediaPlayer - /// </summary> - public abstract class BaseMediaPlayer : IDisposable - { - /// <summary> - /// Gets the logger. - /// </summary> - /// <value>The logger.</value> - protected ILogger Logger { get; private set; } - - #region VolumeChanged - /// <summary> - /// Occurs when [volume changed]. - /// </summary> - public event EventHandler VolumeChanged; - protected void OnVolumeChanged() - { - EventHelper.FireEventIfNotNull(VolumeChanged, this, EventArgs.Empty, Logger); - } - #endregion - - #region PlayStateChanged - /// <summary> - /// Occurs when [play state changed]. - /// </summary> - public event EventHandler PlayStateChanged; - protected void OnPlayStateChanged() - { - EventHelper.FireEventIfNotNull(PlayStateChanged, this, EventArgs.Empty, Logger); - } - #endregion - - /// <summary> - /// The null task result - /// </summary> - protected Task<bool> NullTaskResult = Task.FromResult(false); - - /// <summary> - /// Gets a value indicating whether [supports multi file playback]. - /// </summary> - /// <value><c>true</c> if [supports multi file playback]; otherwise, <c>false</c>.</value> - public abstract bool SupportsMultiFilePlayback { get; } - - /// <summary> - /// The currently playing items - /// </summary> - public List<BaseItemDto> Playlist = new List<BaseItemDto>(); - - /// <summary> - /// The _play state - /// </summary> - private PlayState _playState; - /// <summary> - /// Gets or sets the state of the play. - /// </summary> - /// <value>The state of the play.</value> - public PlayState PlayState - { - get - { - return _playState; - } - set - { - _playState = value; - - OnPlayStateChanged(); - } - } - - /// <summary> - /// Gets or sets a value indicating whether this <see cref="BaseMediaPlayer" /> is mute. - /// </summary> - /// <value><c>true</c> if mute; otherwise, <c>false</c>.</value> - public bool Mute - { - get { return IsMuted; } - set - { - SetMute(value); - OnVolumeChanged(); - } - } - - /// <summary> - /// Gets or sets the volume. - /// </summary> - /// <value>The volume.</value> - public int Volume - { - get { return GetVolume(); } - set - { - SetVolume(value); - OnVolumeChanged(); - } - } - - /// <summary> - /// Gets the current player configuration. - /// </summary> - /// <value>The current player configuration.</value> - public PlayerConfiguration CurrentPlayerConfiguration { get; private set; } - - /// <summary> - /// Gets the current play options. - /// </summary> - /// <value>The current play options.</value> - public PlayOptions CurrentPlayOptions { get; private set; } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public abstract string Name { get; } - - /// <summary> - /// Determines whether this instance can play the specified item. - /// </summary> - /// <param name="item">The item.</param> - /// <returns><c>true</c> if this instance can play the specified item; otherwise, <c>false</c>.</returns> - public abstract bool CanPlay(BaseItemDto item); - - /// <summary> - /// Gets a value indicating whether this instance can change volume. - /// </summary> - /// <value><c>true</c> if this instance can change volume; otherwise, <c>false</c>.</value> - public abstract bool CanControlVolume { get; } - - /// <summary> - /// Gets a value indicating whether this instance can mute. - /// </summary> - /// <value><c>true</c> if this instance can mute; otherwise, <c>false</c>.</value> - public abstract bool CanMute { get; } - - /// <summary> - /// Gets a value indicating whether this instance can queue. - /// </summary> - /// <value><c>true</c> if this instance can queue; otherwise, <c>false</c>.</value> - public abstract bool CanQueue { get; } - - /// <summary> - /// Gets a value indicating whether this instance can pause. - /// </summary> - /// <value><c>true</c> if this instance can pause; otherwise, <c>false</c>.</value> - public abstract bool CanPause { get; } - - /// <summary> - /// Gets a value indicating whether this instance can seek. - /// </summary> - /// <value><c>true</c> if this instance can seek; otherwise, <c>false</c>.</value> - public abstract bool CanSeek { get; } - - /// <summary> - /// Gets the index of the current playlist. - /// </summary> - /// <value>The index of the current playlist.</value> - public virtual int CurrentPlaylistIndex - { - get { return 0; } - } - - /// <summary> - /// Gets the current media. - /// </summary> - /// <value>The current media.</value> - public BaseItemDto CurrentMedia - { - get - { - return CurrentPlaylistIndex == -1 ? null : Playlist[CurrentPlaylistIndex]; - } - } - - /// <summary> - /// Gets the current position ticks. - /// </summary> - /// <value>The current position ticks.</value> - public virtual long? CurrentPositionTicks - { - get - { - return null; - } - } - - /// <summary> - /// Gets a value indicating whether this instance is muted. - /// </summary> - /// <value><c>true</c> if this instance is muted; otherwise, <c>false</c>.</value> - protected virtual bool IsMuted - { - get { return false; } - } - - /// <summary> - /// Initializes a new instance of the <see cref="BaseMediaPlayer" /> class. - /// </summary> - protected BaseMediaPlayer(ILogger logger) - { - Logger = logger; - } - - /// <summary> - /// Sets the mute. - /// </summary> - /// <param name="mute">if set to <c>true</c> [mute].</param> - protected virtual void SetMute(bool mute) - { - } - - /// <summary> - /// Sets the volume, on a scale from 0-100 - /// </summary> - /// <param name="value">The value.</param> - protected virtual void SetVolume(int value) - { - } - - /// <summary> - /// Gets the volume. - /// </summary> - /// <returns>System.Int32.</returns> - protected virtual int GetVolume() - { - return 0; - } - - /// <summary> - /// Plays the internal. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="options">The options.</param> - /// <param name="playerConfiguration">The player configuration.</param> - protected abstract void PlayInternal(List<BaseItemDto> items, PlayOptions options, PlayerConfiguration playerConfiguration); - - /// <summary> - /// Queues the internal. - /// </summary> - /// <param name="items">The items.</param> - protected virtual void QueueInternal(List<BaseItemDto> items) - { - } - - /// <summary> - /// Stops the internal. - /// </summary> - /// <returns>Task.</returns> - protected abstract Task StopInternal(); - - /// <summary> - /// The play semaphore - /// </summary> - private readonly SemaphoreSlim PlaySemaphore = new SemaphoreSlim(1, 1); - - /// <summary> - /// Gets or sets the progress update timer. - /// </summary> - /// <value>The progress update timer.</value> - private Timer ProgressUpdateTimer { get; set; } - - /// <summary> - /// Gets a value indicating whether this instance can monitor progress. - /// </summary> - /// <value><c>true</c> if this instance can monitor progress; otherwise, <c>false</c>.</value> - protected virtual bool CanMonitorProgress - { - get - { - return false; - } - } - - /// <summary> - /// Stops this instance. - /// </summary> - /// <returns>Task.</returns> - /// <exception cref="System.InvalidOperationException"></exception> - public Task Stop() - { - var playstate = PlayState; - - if (playstate == PlayState.Playing || playstate == PlayState.Paused) - { - Logger.Info("Stopping"); - - return StopInternal(); - } - - throw new InvalidOperationException(string.Format("{0} is already {1}", Name, playstate)); - } - - /// <summary> - /// Plays the specified item. - /// </summary> - /// <param name="options">The options.</param> - /// <param name="playerConfiguration">The player configuration.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">items</exception> - internal async Task Play(PlayOptions options, PlayerConfiguration playerConfiguration) - { - if (options == null) - { - throw new ArgumentNullException("options"); - } - - await PlaySemaphore.WaitAsync(); - - PlayState = PlayState.Playing; - - lock (Playlist) - { - Playlist.Clear(); - Playlist.AddRange(options.Items); - } - - CurrentPlayerConfiguration = playerConfiguration; - CurrentPlayOptions = options; - - if (options.Items.Count > 1) - { - Logger.Info("Playing {0} items", options.Items.Count); - } - else - { - Logger.Info("Playing {0}", options.Items[0].Name); - } - - try - { - PlayInternal(options.Items, options, playerConfiguration); - } - catch (Exception ex) - { - Logger.Info("Error beginning playback", ex); - - CurrentPlayerConfiguration = null; - CurrentPlayOptions = null; - Playlist.Clear(); - - PlayState = PlayState.Idle; - PlaySemaphore.Release(); - - throw; - } - - SendPlaybackStartCheckIn(options.Items[0]); - - ReloadProgressUpdateTimer(); - } - - /// <summary> - /// Restarts the progress update timer. - /// </summary> - private void ReloadProgressUpdateTimer() - { - ProgressUpdateTimer = new Timer(OnProgressTimerStopped, null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10)); - } - - /// <summary> - /// Called when [progress timer stopped]. - /// </summary> - /// <param name="state">The state.</param> - private void OnProgressTimerStopped(object state) - { - var index = CurrentPlaylistIndex; - - if (index != -1) - { - SendPlaybackProgressCheckIn(Playlist[index], CurrentPositionTicks); - } - } - - /// <summary> - /// Queues the specified items. - /// </summary> - /// <param name="items">The items.</param> - /// <exception cref="System.ArgumentNullException">items</exception> - /// <exception cref="System.InvalidOperationException"></exception> - internal void Queue(List<BaseItemDto> items) - { - if (items == null) - { - throw new ArgumentNullException("items"); - } - - var playstate = PlayState; - - if (playstate != PlayState.Playing && playstate != PlayState.Paused) - { - throw new InvalidOperationException(string.Format("{0} cannot queue from playstate: {1}", Name, playstate)); - } - - lock (Playlist) - { - Playlist.AddRange(items); - } - - QueueInternal(items); - } - - /// <summary> - /// Called when [player stopped]. - /// </summary> - /// <param name="lastPlaylistIndex">Last index of the playlist.</param> - /// <param name="positionTicks">The position ticks.</param> - protected void OnPlayerStopped(int? lastPlaylistIndex, long? positionTicks) - { - Logger.Info("Stopped"); - - if (positionTicks.HasValue && positionTicks.Value == 0) - { - positionTicks = null; - } - - var items = Playlist.ToList(); - - DisposeProgressUpdateTimer(); - - var index = lastPlaylistIndex ?? CurrentPlaylistIndex; - - var lastItem = items[index]; - SendPlaybackStopCheckIn(items[index], positionTicks); - - if (!CanMonitorProgress) - { - if (items.Count > 1) - { - MarkWatched(items.Except(new[] { lastItem })); - } - } - - OnPlayerStoppedInternal(); - - UIKernel.Instance.PlaybackManager.OnPlaybackCompleted(this, Playlist.ToList()); - - CurrentPlayerConfiguration = null; - CurrentPlayOptions = null; - Logger.Info("Clearing Playlist"); - Playlist.Clear(); - - PlayState = PlayState.Idle; - - PlaySemaphore.Release(); - } - - /// <summary> - /// Called when [player stopped internal]. - /// </summary> - protected virtual void OnPlayerStoppedInternal() - { - - } - - /// <summary> - /// Seeks the specified position ticks. - /// </summary> - /// <param name="positionTicks">The position ticks.</param> - /// <returns>Task.</returns> - /// <exception cref="System.InvalidOperationException"></exception> - public async Task Seek(long positionTicks) - { - var playState = PlayState; - - if (playState == PlayState.Playing || playState == PlayState.Paused) - { - await SeekInternal(positionTicks); - } - else - { - throw new InvalidOperationException(string.Format("Cannot seek {0} with playstate {1}", Name, PlayState)); - } - } - - /// <summary> - /// Seeks the internal. - /// </summary> - /// <param name="positionTicks">The position ticks.</param> - /// <returns>Task.</returns> - protected virtual Task SeekInternal(long positionTicks) - { - return NullTaskResult; - } - - /// <summary> - /// The ten seconds - /// </summary> - private static readonly long TenSeconds = TimeSpan.FromSeconds(10).Ticks; - - /// <summary> - /// Goes to next chapter. - /// </summary> - /// <returns>Task.</returns> - public virtual Task GoToNextChapter() - { - var current = CurrentPositionTicks; - - var chapter = CurrentMedia.Chapters.FirstOrDefault(c => c.StartPositionTicks > current); - - return chapter != null ? Seek(chapter.StartPositionTicks) : NullTaskResult; - } - - /// <summary> - /// Goes to previous chapter. - /// </summary> - /// <returns>Task.</returns> - public virtual Task GoToPreviousChapter() - { - var current = CurrentPositionTicks; - - var chapter = CurrentMedia.Chapters.LastOrDefault(c => c.StartPositionTicks < current - TenSeconds); - - return chapter != null ? Seek(chapter.StartPositionTicks) : NullTaskResult; - } - - /// <summary> - /// Pauses this instance. - /// </summary> - /// <returns>Task.</returns> - /// <exception cref="System.InvalidOperationException"></exception> - public async Task Pause() - { - if (PlayState == PlayState.Playing) - { - await PauseInternal(); - - PlayState = PlayState.Paused; - } - else - { - throw new InvalidOperationException(string.Format("Cannot pause {0} with playstate {1}", Name, PlayState)); - } - } - - /// <summary> - /// Pauses the internal. - /// </summary> - /// <returns>Task.</returns> - protected virtual Task PauseInternal() - { - return NullTaskResult; - } - - /// <summary> - /// Uns the pause. - /// </summary> - /// <returns>Task.</returns> - /// <exception cref="System.InvalidOperationException"></exception> - public async Task UnPause() - { - if (PlayState == PlayState.Paused) - { - await UnPauseInternal(); - PlayState = PlayState.Playing; - } - else - { - throw new InvalidOperationException(string.Format("Cannot unpause {0} with playstate {1}", Name, PlayState)); - } - } - - /// <summary> - /// Uns the pause internal. - /// </summary> - /// <returns>Task.</returns> - protected virtual Task UnPauseInternal() - { - return NullTaskResult; - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - Logger.Info("Disposing"); - - DisposeProgressUpdateTimer(); - - if (PlayState == PlayState.Playing || PlayState == PlayState.Paused) - { - var index = CurrentPlaylistIndex; - - if (index != -1) - { - SendPlaybackStopCheckIn(Playlist[index], CurrentPositionTicks); - } - Task.Run(() => Stop()); - Thread.Sleep(1000); - } - - PlaySemaphore.Dispose(); - } - - /// <summary> - /// Disposes the progress update timer. - /// </summary> - private void DisposeProgressUpdateTimer() - { - if (ProgressUpdateTimer != null) - { - ProgressUpdateTimer.Dispose(); - } - } - - /// <summary> - /// Sends the playback start check in. - /// </summary> - /// <param name="item">The item.</param> - protected async void SendPlaybackStartCheckIn(BaseItemDto item) - { - if (string.IsNullOrEmpty(item.Id)) - { - return; - } - - Logger.Info("Sending playback start checkin for {0}", item.Name); - - try - { - await UIKernel.Instance.ApiClient.ReportPlaybackStartAsync(item.Id, App.Instance.CurrentUser.Id); - } - catch (HttpException ex) - { - Logger.ErrorException("Error sending playback start checking for {0}", ex, item.Name); - } - } - - /// <summary> - /// Sends the playback progress check in. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="positionTicks">The position ticks.</param> - protected async void SendPlaybackProgressCheckIn(BaseItemDto item, long? positionTicks) - { - if (string.IsNullOrEmpty(item.Id)) - { - return; - } - var position = positionTicks.HasValue ? TimeSpan.FromTicks(positionTicks.Value).ToString() : "unknown"; - - Logger.Info("Sending playback progress checkin for {0} at position {1}", item.Name, position); - - try - { - await UIKernel.Instance.ApiClient.ReportPlaybackProgressAsync(item.Id, App.Instance.CurrentUser.Id, positionTicks); - } - catch (HttpException ex) - { - Logger.ErrorException("Error sending playback progress checking for {0}", ex, item.Name); - } - } - - /// <summary> - /// Sends the playback stop check in. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="positionTicks">The position ticks.</param> - protected async void SendPlaybackStopCheckIn(BaseItemDto item, long? positionTicks) - { - if (string.IsNullOrEmpty(item.Id)) - { - return; - } - var position = positionTicks.HasValue ? TimeSpan.FromTicks(positionTicks.Value).ToString() : "unknown"; - - Logger.Info("Sending playback stop checkin for {0} at position {1}", item.Name, position); - - try - { - await UIKernel.Instance.ApiClient.ReportPlaybackStoppedAsync(item.Id, App.Instance.CurrentUser.Id, positionTicks); - } - catch (HttpException ex) - { - Logger.ErrorException("Error sending playback stop checking for {0}", ex, item.Name); - } - } - - /// <summary> - /// Marks the watched. - /// </summary> - /// <param name="items">The items.</param> - protected async void MarkWatched(IEnumerable<BaseItemDto> items) - { - var idList = items.Where(i => !string.IsNullOrEmpty(i.Id)).Select(i => i.Id); - - try - { - await UIKernel.Instance.ApiClient.UpdatePlayedStatusAsync(idList.First(), App.Instance.CurrentUser.Id, true); - } - catch (HttpException ex) - { - Logger.ErrorException("Error marking items watched", ex); - } - } - - /// <summary> - /// Called when [media changed]. - /// </summary> - /// <param name="oldPlaylistIndex">Old index of the playlist.</param> - /// <param name="endingPositionTicks">The ending position ticks.</param> - /// <param name="newPlaylistIndex">New index of the playlist.</param> - protected void OnMediaChanged(int oldPlaylistIndex, long? endingPositionTicks, int newPlaylistIndex) - { - DisposeProgressUpdateTimer(); - - Task.Run(() => - { - if (oldPlaylistIndex != -1) - { - SendPlaybackStopCheckIn(Playlist[oldPlaylistIndex], endingPositionTicks); - } - - if (newPlaylistIndex != -1) - { - SendPlaybackStartCheckIn(Playlist[newPlaylistIndex]); - } - }); - - ReloadProgressUpdateTimer(); - } - } -} diff --git a/MediaBrowser.UI/Playback/ExternalPlayer/BaseExternalPlayer.cs b/MediaBrowser.UI/Playback/ExternalPlayer/BaseExternalPlayer.cs deleted file mode 100644 index c50911d71c..0000000000 --- a/MediaBrowser.UI/Playback/ExternalPlayer/BaseExternalPlayer.cs +++ /dev/null @@ -1,243 +0,0 @@ -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 -{ - /// <summary> - /// Class BaseExternalPlayer - /// </summary> - public abstract class BaseExternalPlayer : BaseMediaPlayer - { - protected BaseExternalPlayer(ILogger logger) : base(logger) - { - } - - /// <summary> - /// Gets a value indicating whether this instance can mute. - /// </summary> - /// <value><c>true</c> if this instance can mute; otherwise, <c>false</c>.</value> - public override bool CanMute - { - get { return false; } - } - - /// <summary> - /// Gets a value indicating whether this instance can change volume. - /// </summary> - /// <value><c>true</c> if this instance can change volume; otherwise, <c>false</c>.</value> - public override bool CanControlVolume - { - get { return false; } - } - - /// <summary> - /// Gets a value indicating whether this instance can close automatically. - /// </summary> - /// <value><c>true</c> if this instance can close automatically; otherwise, <c>false</c>.</value> - protected virtual bool CanCloseAutomatically - { - get - { - return false; - } - } - - /// <summary> - /// Gets a value indicating whether [supports multi file playback]. - /// </summary> - /// <value><c>true</c> if [supports multi file playback]; otherwise, <c>false</c>.</value> - public override bool SupportsMultiFilePlayback - { - get - { - return false; - } - } - - /// <summary> - /// Gets the current process. - /// </summary> - /// <value>The current process.</value> - protected Process CurrentProcess { get; private set; } - - /// <summary> - /// Gets the process start info. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="options">The options.</param> - /// <param name="playerConfiguration">The player configuration.</param> - /// <returns>ProcessStartInfo.</returns> - protected virtual ProcessStartInfo GetProcessStartInfo(List<BaseItemDto> items, PlayOptions options, PlayerConfiguration playerConfiguration) - { - return new ProcessStartInfo - { - FileName = playerConfiguration.Command, - Arguments = GetCommandArguments(items, options, playerConfiguration) - }; - } - - /// <summary> - /// Gets the command arguments. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="options">The options.</param> - /// <param name="playerConfiguration">The player configuration.</param> - /// <returns>System.String.</returns> - protected virtual string GetCommandArguments(List<BaseItemDto> items, PlayOptions options, PlayerConfiguration playerConfiguration) - { - var args = playerConfiguration.Args; - - if (string.IsNullOrEmpty(args)) - { - return string.Empty; - } - - return GetCommandArguments(items, args); - } - - /// <summary> - /// Gets the command arguments. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="formatString">The format string.</param> - /// <returns>System.String.</returns> - protected string GetCommandArguments(List<BaseItemDto> items, string formatString) - { - var paths = items.Select(i => "\"" + GetPathForCommandLine(i) + "\""); - - return string.Format(formatString, string.Join(" ", paths.ToArray())); - } - - /// <summary> - /// Gets the path for command line. - /// </summary> - /// <param name="item">The item.</param> - /// <returns>System.String.</returns> - protected virtual string GetPathForCommandLine(BaseItemDto item) - { - return item.Path; - } - - /// <summary> - /// Gets a value indicating whether this instance can queue. - /// </summary> - /// <value><c>true</c> if this instance can queue; otherwise, <c>false</c>.</value> - public override bool CanQueue - { - get { return false; } - } - - /// <summary> - /// Gets a value indicating whether this instance can pause. - /// </summary> - /// <value><c>true</c> if this instance can pause; otherwise, <c>false</c>.</value> - public override bool CanPause - { - get { return false; } - } - - /// <summary> - /// Gets a value indicating whether this instance can seek. - /// </summary> - /// <value><c>true</c> if this instance can seek; otherwise, <c>false</c>.</value> - public override bool CanSeek - { - get { return false; } - } - - /// <summary> - /// Plays the internal. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="options">The options.</param> - /// <param name="playerConfiguration">The player configuration.</param> - protected override void PlayInternal(List<BaseItemDto> 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; - } - - /// <summary> - /// Handles the KeyDown event of the KeyboardListener control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="KeyEventArgs" /> instance containing the event data.</param> - void KeyboardListener_KeyDown(object sender, KeyEventArgs e) - { - if (e.KeyCode == Keys.MediaStop) - { - var playstate = PlayState; - - if (playstate == PlayState.Paused || playstate == PlayState.Playing) - { - Stop(); - } - } - } - - /// <summary> - /// Handles the Exited event of the CurrentProcess control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> - void CurrentProcess_Exited(object sender, EventArgs e) - { - var process = (Process)sender; - - process.Dispose(); - - OnPlayerStopped(CurrentPlaylistIndex, CurrentPositionTicks); - } - - /// <summary> - /// Stops the internal. - /// </summary> - /// <returns>Task.</returns> - protected override Task StopInternal() - { - return Task.Run(() => CurrentProcess.Kill()); - } - - /// <summary> - /// Called when [player stopped internal]. - /// </summary> - protected override void OnPlayerStoppedInternal() - { - KeyboardListener.KeyDown -= KeyboardListener_KeyDown; - - base.OnPlayerStoppedInternal(); - } - - /// <summary> - /// Called when [external player launched]. - /// </summary> - protected virtual void OnExternalPlayerLaunched() - { - - } - } -} diff --git a/MediaBrowser.UI/Playback/ExternalPlayer/GenericExternalPlayer.cs b/MediaBrowser.UI/Playback/ExternalPlayer/GenericExternalPlayer.cs deleted file mode 100644 index 9150280507..0000000000 --- a/MediaBrowser.UI/Playback/ExternalPlayer/GenericExternalPlayer.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.UI.Playback.ExternalPlayer -{ - /// <summary> - /// Class GenericExternalPlayer - /// </summary> - public class GenericExternalPlayer : BaseExternalPlayer - { - public GenericExternalPlayer(ILogger logger) - : base(logger) - { - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "Generic Player"; } - } - - /// <summary> - /// Determines whether this instance can play the specified item. - /// </summary> - /// <param name="item">The item.</param> - /// <returns><c>true</c> if this instance can play the specified item; otherwise, <c>false</c>.</returns> - public override bool CanPlay(BaseItemDto item) - { - return false; - } - } -} diff --git a/MediaBrowser.UI/Playback/InternalPlayer/BaseInternalMediaPlayer.cs b/MediaBrowser.UI/Playback/InternalPlayer/BaseInternalMediaPlayer.cs deleted file mode 100644 index e9178d3f53..0000000000 --- a/MediaBrowser.UI/Playback/InternalPlayer/BaseInternalMediaPlayer.cs +++ /dev/null @@ -1,54 +0,0 @@ -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Logging; -using MediaBrowser.UI.Configuration; -using System.Collections.Generic; -using System.Windows; - -namespace MediaBrowser.UI.Playback.InternalPlayer -{ - /// <summary> - /// Class BaseInternalMediaPlayer - /// </summary> - public abstract class BaseInternalMediaPlayer : BaseMediaPlayer - { - protected BaseInternalMediaPlayer(ILogger logger) : base(logger) - { - } - - /// <summary> - /// Ensures the media player created. - /// </summary> - protected abstract void EnsureMediaPlayerCreated(); - - /// <summary> - /// Plays the internal. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="options">The options.</param> - /// <param name="playerConfiguration">The player configuration.</param> - protected override void PlayInternal(List<BaseItemDto> items, PlayOptions options, PlayerConfiguration playerConfiguration) - { - App.Instance.ApplicationWindow.Dispatcher.Invoke(() => - { - App.Instance.ApplicationWindow.BackdropContainer.Visibility = Visibility.Collapsed; - App.Instance.ApplicationWindow.WindowBackgroundContent.SetResourceReference(FrameworkElement.StyleProperty, "WindowBackgroundContentDuringPlayback"); - }); - - App.Instance.NavigateToInternalPlayerPage(); - } - - /// <summary> - /// Called when [player stopped internal]. - /// </summary> - protected override void OnPlayerStoppedInternal() - { - App.Instance.ApplicationWindow.Dispatcher.Invoke(() => - { - App.Instance.ApplicationWindow.BackdropContainer.Visibility = Visibility.Visible; - App.Instance.ApplicationWindow.WindowBackgroundContent.SetResourceReference(FrameworkElement.StyleProperty, "WindowBackgroundContent"); - }); - - base.OnPlayerStoppedInternal(); - } - } -} diff --git a/MediaBrowser.UI/Playback/NVlc/InternalMediaPlayerNVlc.cs b/MediaBrowser.UI/Playback/NVlc/InternalMediaPlayerNVlc.cs deleted file mode 100644 index 2d596655b5..0000000000 --- a/MediaBrowser.UI/Playback/NVlc/InternalMediaPlayerNVlc.cs +++ /dev/null @@ -1,426 +0,0 @@ -using Declarations.Events; -using Declarations.Media; -using Declarations.Players; -using Implementation; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.UI.Configuration; -using MediaBrowser.UI.Playback.InternalPlayer; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace MediaBrowser.UI.Playback.NVlc -{ - /// <summary> - /// Class InternalMediaPlayer - /// </summary> - public class InternalMediaPlayerNVlc : BaseInternalMediaPlayer - { - public InternalMediaPlayerNVlc(ILogger logger) - : base(logger) - { - } - - /// <summary> - /// Gets or sets the media player factory. - /// </summary> - /// <value>The media player factory.</value> - private MediaPlayerFactory MediaPlayerFactory { get; set; } - - /// <summary> - /// Gets or sets the video player. - /// </summary> - /// <value>The video player.</value> - private IMediaListPlayer VideoPlayer { get; set; } - - /// <summary> - /// Gets or sets the media list. - /// </summary> - /// <value>The media list.</value> - private IMediaList MediaList { get; set; } - - /// <summary> - /// Gets a value indicating whether [supports multi file playback]. - /// </summary> - /// <value><c>true</c> if [supports multi file playback]; otherwise, <c>false</c>.</value> - public override bool SupportsMultiFilePlayback - { - get { return true; } - } - - /// <summary> - /// Gets a value indicating whether this instance can mute. - /// </summary> - /// <value><c>true</c> if this instance can mute; otherwise, <c>false</c>.</value> - public override bool CanMute - { - get { return true; } - } - - /// <summary> - /// Gets a value indicating whether this instance can change volume. - /// </summary> - /// <value><c>true</c> if this instance can change volume; otherwise, <c>false</c>.</value> - public override bool CanControlVolume - { - get { return true; } - } - - /// <summary> - /// Gets a value indicating whether this instance is muted. - /// </summary> - /// <value><c>true</c> if this instance is muted; otherwise, <c>false</c>.</value> - protected override bool IsMuted - { - get { return VideoPlayer != null && VideoPlayer.InnerPlayer.Mute; } - } - - /// <summary> - /// The _current playlist index - /// </summary> - private int _currentPlaylistIndex; - - /// <summary> - /// Gets the index of the current playlist. - /// </summary> - /// <value>The index of the current playlist.</value> - public override int CurrentPlaylistIndex - { - get - { - return _currentPlaylistIndex; - } - } - - /// <summary> - /// Gets the current position ticks. - /// </summary> - /// <value>The current position ticks.</value> - public override long? CurrentPositionTicks - { - get - { - if (VideoPlayer != null) - { - return TimeSpan.FromMilliseconds(VideoPlayer.Time).Ticks; - } - - return base.CurrentPositionTicks; - } - } - - /// <summary> - /// Gets a value indicating whether this instance can monitor progress. - /// </summary> - /// <value><c>true</c> if this instance can monitor progress; otherwise, <c>false</c>.</value> - protected override bool CanMonitorProgress - { - get - { - return true; - } - } - - /// <summary> - /// Gets or sets the windows forms panel. - /// </summary> - /// <value>The windows forms panel.</value> - private Panel WindowsFormsPanel { get; set; } - - /// <summary> - /// Ensures the player. - /// </summary> - protected override void EnsureMediaPlayerCreated() - { - if (MediaPlayerFactory != null) - { - return; - } - - WindowsFormsPanel = new Panel(); - WindowsFormsPanel.BackColor = Color.Black; - - App.Instance.HiddenWindow.WindowsFormsHost.Child = WindowsFormsPanel; - - MediaPlayerFactory = new MediaPlayerFactory(new[] - { - "-I", - "dummy", - "--ignore-config", - "--no-osd", - "--disable-screensaver", - //"--ffmpeg-hw", - "--plugin-path=./plugins" - }); - } - - /// <summary> - /// Events_s the media changed. - /// </summary> - /// <param name="sender">The sender.</param> - /// <param name="e">The e.</param> - void Events_MediaChanged(object sender, MediaPlayerMediaChanged e) - { - //var current = MediaList.FirstOrDefault(i => i.Tag == e.NewMedia.Tag); - - //var newIndex = current != null ? MediaList.IndexOf(current) : -1; - - //var currentIndex = _currentPlaylistIndex; - - //if (newIndex != currentIndex) - //{ - // OnMediaChanged(currentIndex, null, newIndex); - //} - - //_currentPlaylistIndex = newIndex; - } - - /// <summary> - /// Determines whether this instance can play the specified item. - /// </summary> - /// <param name="item">The item.</param> - /// <returns><c>true</c> if this instance can play the specified item; otherwise, <c>false</c>.</returns> - public override bool CanPlay(BaseItemDto item) - { - return item.IsVideo || item.IsAudio; - } - - /// <summary> - /// Gets a value indicating whether this instance can queue. - /// </summary> - /// <value><c>true</c> if this instance can queue; otherwise, <c>false</c>.</value> - public override bool CanQueue - { - get { return true; } - } - - /// <summary> - /// Plays the internal. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="options">The options.</param> - /// <param name="playerConfiguration">The player configuration.</param> - protected override void PlayInternal(List<BaseItemDto> items, PlayOptions options, PlayerConfiguration playerConfiguration) - { - EnsureMediaPlayerCreated(); - - _currentPlaylistIndex = 0; - - MediaList = MediaPlayerFactory.CreateMediaList<IMediaList>(items.Select(GetPlayablePath)); - VideoPlayer = MediaPlayerFactory.CreateMediaListPlayer<IMediaListPlayer>(MediaList); - - VideoPlayer.InnerPlayer.WindowHandle = WindowsFormsPanel.Handle; - - VideoPlayer.InnerPlayer.Events.PlayerStopped += Events_PlayerStopped; - VideoPlayer.Play(); - - var position = options.StartPositionTicks; - - if (position > 0) - { - VideoPlayer.Time = Convert.ToInt64(TimeSpan.FromTicks(position).TotalMilliseconds); - } - - VideoPlayer.MediaListPlayerEvents.MediaListPlayerNextItemSet += MediaListPlayerEvents_MediaListPlayerNextItemSet; - - base.PlayInternal(items, options, playerConfiguration); - } - - /// <summary> - /// Gets the playable path. - /// </summary> - /// <param name="item">The item.</param> - /// <returns>System.String.</returns> - private string GetPlayablePath(BaseItemDto item) - { - if (item.VideoType.HasValue && item.VideoType.Value == VideoType.BluRay) - { - var file = Directory.EnumerateFiles(item.Path, "*.m2ts", SearchOption.AllDirectories).OrderByDescending(f => new FileInfo(f).Length).FirstOrDefault(); - - if (!string.IsNullOrEmpty(file)) - { - return file; - } - } - - return item.Path; - } - - /// <summary> - /// Medias the list player events_ media list player next item set. - /// </summary> - /// <param name="sender">The sender.</param> - /// <param name="e">The e.</param> - void MediaListPlayerEvents_MediaListPlayerNextItemSet(object sender, MediaListPlayerNextItemSet e) - { - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public override string Name - { - get { return "Internal Player"; } - } - - /// <summary> - /// Gets a value indicating whether this instance can pause. - /// </summary> - /// <value><c>true</c> if this instance can pause; otherwise, <c>false</c>.</value> - public override bool CanPause - { - get { return true; } - } - - /// <summary> - /// Gets a value indicating whether this instance can seek. - /// </summary> - /// <value><c>true</c> if this instance can seek; otherwise, <c>false</c>.</value> - public override bool CanSeek - { - get { return true; } - } - - /// <summary> - /// Queues the internal. - /// </summary> - /// <param name="items">The items.</param> - protected override void QueueInternal(List<BaseItemDto> items) - { - } - - /// <summary> - /// Seeks the internal. - /// </summary> - /// <param name="positionTicks">The position ticks.</param> - /// <returns>Task.</returns> - protected override Task SeekInternal(long positionTicks) - { - return Task.Run(() => VideoPlayer.Time = Convert.ToInt64(TimeSpan.FromTicks(positionTicks).TotalMilliseconds)); - } - - /// <summary> - /// Pauses the internal. - /// </summary> - /// <returns>Task.</returns> - protected override Task PauseInternal() - { - return Task.Run(() => VideoPlayer.Pause()); - } - - /// <summary> - /// Uns the pause internal. - /// </summary> - /// <returns>Task.</returns> - protected override Task UnPauseInternal() - { - return Task.Run(() => VideoPlayer.Pause()); - } - - /// <summary> - /// Stops the internal. - /// </summary> - /// <returns>Task.</returns> - protected override Task StopInternal() - { - return Task.Run(() => VideoPlayer.Stop()); - } - - /// <summary> - /// Handles the PlayerStopped event of the Events control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> - void Events_PlayerStopped(object sender, EventArgs e) - { - OnPlayerStopped(CurrentPlaylistIndex, CurrentPositionTicks); - } - - /// <summary> - /// Called when [player stopped]. - /// </summary> - protected override void OnPlayerStoppedInternal() - { - VideoPlayer.MediaListPlayerEvents.MediaListPlayerNextItemSet -= MediaListPlayerEvents_MediaListPlayerNextItemSet; - - MediaList.Dispose(); - - VideoPlayer.InnerPlayer.Events.PlayerStopped -= Events_PlayerStopped; - VideoPlayer.InnerPlayer.Dispose(); - - //VideoPlayer.Dispose(); - VideoPlayer = null; - - _currentPlaylistIndex = 0; - - base.OnPlayerStoppedInternal(); - } - - /// <summary> - /// Gets the volume. - /// </summary> - /// <returns>System.Int32.</returns> - protected override int GetVolume() - { - return VideoPlayer.InnerPlayer.Volume; - } - - /// <summary> - /// Sets the volume, on a scale from 0-100 - /// </summary> - /// <param name="value">The value.</param> - protected override void SetVolume(int value) - { - if (value > 0 && VideoPlayer.InnerPlayer.Mute) - { - VideoPlayer.InnerPlayer.Mute = false; - } - - VideoPlayer.InnerPlayer.Volume = value; - } - - /// <summary> - /// Sets the mute. - /// </summary> - /// <param name="mute">if set to <c>true</c> [mute].</param> - protected override void SetMute(bool mute) - { - VideoPlayer.InnerPlayer.Mute = mute; - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected override void Dispose(bool dispose) - { - base.Dispose(dispose); - - if (dispose) - { - if (MediaList != null) - { - MediaList.Dispose(); - } - if (VideoPlayer != null) - { - if (VideoPlayer.InnerPlayer != null) - { - VideoPlayer.InnerPlayer.Dispose(); - } - } - if (MediaPlayerFactory != null) - { - MediaPlayerFactory.Dispose(); - } - } - } - } -} diff --git a/MediaBrowser.UI/Playback/PlayOptions.cs b/MediaBrowser.UI/Playback/PlayOptions.cs deleted file mode 100644 index 276e611b9c..0000000000 --- a/MediaBrowser.UI/Playback/PlayOptions.cs +++ /dev/null @@ -1,89 +0,0 @@ -using MediaBrowser.Model.Dto; -using System; -using System.Collections.Generic; - -namespace MediaBrowser.UI.Playback -{ - /// <summary> - /// Class PlayOptions - /// </summary> - public class PlayOptions - { - /// <summary> - /// Gets or sets the items. - /// </summary> - /// <value>The items.</value> - public List<BaseItemDto> Items { get; set; } - - /// <summary> - /// If true, the PlayableItems will be shuffled before playback - /// </summary> - /// <value><c>true</c> if shuffle; otherwise, <c>false</c>.</value> - public bool Shuffle { get; set; } - - /// <summary> - /// If true, Playback will be resumed from the last known position - /// </summary> - /// <value><c>true</c> if resume; otherwise, <c>false</c>.</value> - public bool Resume { get; set; } - - private long? _startPositionTicks; - /// <summary> - /// Gets or sets the start position ticks. - /// </summary> - /// <value>The start position ticks.</value> - public long StartPositionTicks - { - get - { - if (_startPositionTicks.HasValue) - { - return _startPositionTicks.Value; - } - - if (Resume && Items.Count > 0) - { - var item = Items[0]; - - if (item.UserData != null) - { - return item.UserData.PlaybackPositionTicks; - } - } - - return 0; - } - set - { - _startPositionTicks = value; - } - } - - /// <summary> - /// Holds the time that playback was started - /// </summary> - /// <value>The playback start time.</value> - public DateTime PlaybackStartTime { get; private set; } - - /// <summary> - /// The _show now playing view - /// </summary> - private bool _showNowPlayingView = true; - /// <summary> - /// Determines whether or not the PlaybackController should show the now playing view during playback - /// Note that this depends on PlaybackController implementation and support - /// </summary> - /// <value><c>true</c> if [show now playing view]; otherwise, <c>false</c>.</value> - public bool ShowNowPlayingView { get { return _showNowPlayingView; } set { _showNowPlayingView = value; } } - - /// <summary> - /// The _go full screen - /// </summary> - private bool _goFullScreen = true; - /// <summary> - /// Determines whether or not the PlaybackController should go full screen upon beginning playback - /// </summary> - /// <value><c>true</c> if [go full screen]; otherwise, <c>false</c>.</value> - public bool GoFullScreen { get { return _goFullScreen; } set { _goFullScreen = value; } } - } -} diff --git a/MediaBrowser.UI/Playback/PlayState.cs b/MediaBrowser.UI/Playback/PlayState.cs deleted file mode 100644 index d166c4a776..0000000000 --- a/MediaBrowser.UI/Playback/PlayState.cs +++ /dev/null @@ -1,24 +0,0 @@ - -namespace MediaBrowser.UI.Playback -{ - /// <summary> - /// Enum PlayState - /// </summary> - public enum PlayState - { - /// <summary> - /// The idle - /// </summary> - Idle, - - /// <summary> - /// The playing - /// </summary> - Playing, - - /// <summary> - /// The paused - /// </summary> - Paused - } -} diff --git a/MediaBrowser.UI/Playback/PlaybackEventArgs.cs b/MediaBrowser.UI/Playback/PlaybackEventArgs.cs deleted file mode 100644 index a2eef782a6..0000000000 --- a/MediaBrowser.UI/Playback/PlaybackEventArgs.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Collections.Generic; -using MediaBrowser.Model.Dto; -using MediaBrowser.UI.Configuration; -using System; - -namespace MediaBrowser.UI.Playback -{ - /// <summary> - /// Class PlaybackEventArgs - /// </summary> - public class PlaybackEventArgs : EventArgs - { - /// <summary> - /// Gets or sets the player. - /// </summary> - /// <value>The player.</value> - public BaseMediaPlayer Player { get; set; } - - /// <summary> - /// Gets or sets the options. - /// </summary> - /// <value>The options.</value> - public PlayOptions Options { get; set; } - - /// <summary> - /// Gets or sets the player configuration. - /// </summary> - /// <value>The player configuration.</value> - public PlayerConfiguration PlayerConfiguration { get; set; } - } - - /// <summary> - /// Class PlaybackStopEventArgs - /// </summary> - public class PlaybackStopEventArgs : EventArgs - { - /// <summary> - /// Gets or sets the player. - /// </summary> - /// <value>The player.</value> - public BaseMediaPlayer Player { get; set; } - - /// <summary> - /// Gets or sets the items. - /// </summary> - /// <value>The items.</value> - public List<BaseItemDto> Items { get; set; } - } -} diff --git a/MediaBrowser.UI/Playback/PlaybackManager.cs b/MediaBrowser.UI/Playback/PlaybackManager.cs deleted file mode 100644 index eedcad9b35..0000000000 --- a/MediaBrowser.UI/Playback/PlaybackManager.cs +++ /dev/null @@ -1,301 +0,0 @@ -using MediaBrowser.Common.Events; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Kernel; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using MediaBrowser.UI.Configuration; -using MediaBrowser.UI.Controller; -using MediaBrowser.UI.Playback.InternalPlayer; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -namespace MediaBrowser.UI.Playback -{ - /// <summary> - /// Class PlaybackManager - /// </summary> - public class PlaybackManager : BaseManager<UIKernel> - { - private readonly ILogger _logger; - - /// <summary> - /// Initializes a new instance of the <see cref="PlaybackManager" /> class. - /// </summary> - /// <param name="kernel">The kernel.</param> - public PlaybackManager(UIKernel kernel, ILogger logger) - : base(kernel) - { - _logger = logger; - } - - #region PlaybackStarted Event - /// <summary> - /// Occurs when [playback started]. - /// </summary> - public event EventHandler<PlaybackEventArgs> PlaybackStarted; - - /// <summary> - /// Called when [playback started]. - /// </summary> - /// <param name="player">The player.</param> - /// <param name="options">The options.</param> - /// <param name="playerConfiguration">The player configuration.</param> - private void OnPlaybackStarted(BaseMediaPlayer player, PlayOptions options, PlayerConfiguration playerConfiguration) - { - EventHelper.QueueEventIfNotNull(PlaybackStarted, this, new PlaybackEventArgs - { - Options = options, - Player = player, - PlayerConfiguration = playerConfiguration - }, _logger); - } - #endregion - - #region PlaybackCompleted Event - /// <summary> - /// Occurs when [playback completed]. - /// </summary> - public event EventHandler<PlaybackStopEventArgs> PlaybackCompleted; - - /// <summary> - /// Called when [playback completed]. - /// </summary> - /// <param name="player">The player.</param> - /// <param name="items">The items.</param> - internal void OnPlaybackCompleted(BaseMediaPlayer player, List<BaseItemDto> items) - { - EventHelper.QueueEventIfNotNull(PlaybackCompleted, this, new PlaybackStopEventArgs - { - Items = items, - Player = player - }, _logger); - } - #endregion - - /// <summary> - /// Gets the active players. - /// </summary> - /// <value>The active players.</value> - public IEnumerable<BaseMediaPlayer> ActivePlayers - { - get - { - return Kernel.MediaPlayers.Where(m => m.PlayState != PlayState.Idle); - } - } - - /// <summary> - /// Gets the active internal players. - /// </summary> - /// <value>The active internal players.</value> - public IEnumerable<BaseMediaPlayer> ActiveInternalPlayers - { - get { return ActivePlayers.Where(p => p is BaseInternalMediaPlayer); } - } - - /// <summary> - /// Plays the specified items. - /// </summary> - /// <param name="options">The options.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentException"></exception> - /// <exception cref="System.InvalidOperationException"></exception> - public async Task Play(PlayOptions options) - { - if (options == null) - { - throw new ArgumentNullException("options"); - } - - if (options.Items == null || options.Items.Count == 0) - { - throw new ArgumentNullException("options"); - } - - var player = GetPlayer(options.Items); - - if (player != null) - { - await StopAllPlayback(); - - await Play(player.Item1, options, player.Item2); - } - else - { - throw new InvalidOperationException(); - } - } - - /// <summary> - /// Plays the specified player. - /// </summary> - /// <param name="player">The player.</param> - /// <param name="options">The options.</param> - /// <param name="playerConfiguration">The player configuration.</param> - /// <returns>Task.</returns> - private async Task Play(BaseMediaPlayer player, PlayOptions options, PlayerConfiguration playerConfiguration) - { - if (options.Shuffle) - { - options.Items = options.Items.Shuffle().ToList(); - } - - var firstItem = options.Items[0]; - - if (options.StartPositionTicks == 0 && player.SupportsMultiFilePlayback && firstItem.IsVideo && firstItem.LocationType == LocationType.FileSystem) - { - try - { - var intros = await UIKernel.Instance.ApiClient.GetIntrosAsync(firstItem.Id, App.Instance.CurrentUser.Id); - - options.Items.InsertRange(0, intros.Select(GetPlayableItem)); - } - catch (HttpException ex) - { - _logger.ErrorException("Error retrieving intros", ex); - } - } - - await player.Play(options, playerConfiguration); - - OnPlaybackStarted(player, options, playerConfiguration); - } - - /// <summary> - /// Gets the playable item. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>BaseItemDto.</returns> - public BaseItemDto GetPlayableItem(string path) - { - return new BaseItemDto - { - Path = path, - Name = Path.GetFileName(path), - Type = "Video", - VideoType = VideoType.VideoFile, - IsFolder = false - }; - } - - /// <summary> - /// Gets the playable item. - /// </summary> - /// <param name="uri">The URI.</param> - /// <param name="name">The name.</param> - /// <returns>BaseItemDto.</returns> - public BaseItemDto GetPlayableItem(Uri uri, string name) - { - return new BaseItemDto - { - Path = uri.ToString(), - Name = name, - Type = "Video", - VideoType = VideoType.VideoFile, - IsFolder = false, - LocationType = LocationType.Remote - }; - } - - /// <summary> - /// Stops all playback. - /// </summary> - /// <returns>Task.</returns> - public async Task StopAllPlayback() - { - var tasks = Kernel.MediaPlayers.Where(p => p.PlayState == PlayState.Playing || p.PlayState == PlayState.Paused).Select(p => p.Stop()); - - await Task.WhenAll(tasks); - } - - /// <summary> - /// Gets the player. - /// </summary> - /// <param name="items">The items.</param> - /// <returns>BaseMediaPlayer.</returns> - private Tuple<BaseMediaPlayer, PlayerConfiguration> GetPlayer(List<BaseItemDto> items) - { - var player = GetConfiguredPlayer(items); - - if (player != null) - { - return player; - } - - // If there's no explicit configuration just find the first matching player - var mediaPlayer = Kernel.MediaPlayers.OfType<BaseInternalMediaPlayer>().FirstOrDefault(p => items.All(p.CanPlay)); - - if (mediaPlayer != null) - { - return new Tuple<BaseMediaPlayer, PlayerConfiguration>(mediaPlayer, null); - } - - return null; - } - - /// <summary> - /// Gets the configured player. - /// </summary> - /// <param name="items">The items.</param> - /// <returns>BaseMediaPlayer.</returns> - private Tuple<BaseMediaPlayer, PlayerConfiguration> GetConfiguredPlayer(List<BaseItemDto> items) - { - if (UIKernel.Instance.Configuration.MediaPlayers == null) - { - return null; - } - - return UIKernel.Instance.Configuration.MediaPlayers.Where(p => IsConfiguredToPlay(p, items)) - .Select(p => new Tuple<BaseMediaPlayer, PlayerConfiguration>(UIKernel.Instance.MediaPlayers.FirstOrDefault(m => m.Name.Equals(p.PlayerName, StringComparison.OrdinalIgnoreCase)), p)) - .FirstOrDefault(p => p.Item1 != null); - } - - /// <summary> - /// Determines whether [is configured to play] [the specified configuration]. - /// </summary> - /// <param name="configuration">The configuration.</param> - /// <param name="items">The items.</param> - /// <returns><c>true</c> if [is configured to play] [the specified configuration]; otherwise, <c>false</c>.</returns> - private bool IsConfiguredToPlay(PlayerConfiguration configuration, List<BaseItemDto> items) - { - if (configuration.ItemTypes != null && configuration.ItemTypes.Length > 0) - { - if (items.Any(i => !configuration.ItemTypes.Contains(i.Type, StringComparer.OrdinalIgnoreCase))) - { - return false; - } - } - - if (configuration.FileExtensions != null && configuration.FileExtensions.Length > 0) - { - if (items.Any(i => !configuration.FileExtensions.Select(ext => ext.TrimStart('.')).Contains((Path.GetExtension(i.Path) ?? string.Empty).TrimStart('.'), StringComparer.OrdinalIgnoreCase))) - { - return false; - } - } - - if (configuration.VideoTypes != null && configuration.VideoTypes.Length > 0) - { - if (items.Any(i => i.VideoType.HasValue && !configuration.VideoTypes.Contains(i.VideoType.Value))) - { - return false; - } - } - - if (configuration.VideoFormats != null && configuration.VideoFormats.Length > 0) - { - if (items.Any(i => i.VideoFormat.HasValue && !configuration.VideoFormats.Contains(i.VideoFormat.Value))) - { - return false; - } - } - - return true; - } - } -} |
