repo creation with initial code after cloning public repo
This commit is contained in:
@@ -0,0 +1,550 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Model.SyncPlay;
|
||||
|
||||
namespace MediaBrowser.Controller.SyncPlay.Queue
|
||||
{
|
||||
/// <summary>
|
||||
/// Class PlayQueueManager.
|
||||
/// </summary>
|
||||
public class PlayQueueManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Placeholder index for when no item is playing.
|
||||
/// </summary>
|
||||
/// <value>The no-playing item index.</value>
|
||||
private const int NoPlayingItemIndex = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The sorted playlist.
|
||||
/// </summary>
|
||||
/// <value>The sorted playlist, or play queue of the group.</value>
|
||||
private List<SyncPlayQueueItem> _sortedPlaylist = new List<SyncPlayQueueItem>();
|
||||
|
||||
/// <summary>
|
||||
/// The shuffled playlist.
|
||||
/// </summary>
|
||||
/// <value>The shuffled playlist, or play queue of the group.</value>
|
||||
private List<SyncPlayQueueItem> _shuffledPlaylist = new List<SyncPlayQueueItem>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlayQueueManager" /> class.
|
||||
/// </summary>
|
||||
public PlayQueueManager()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the playing item index.
|
||||
/// </summary>
|
||||
/// <value>The playing item index.</value>
|
||||
public int PlayingItemIndex { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last time the queue has been changed.
|
||||
/// </summary>
|
||||
/// <value>The last time the queue has been changed.</value>
|
||||
public DateTime LastChange { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the shuffle mode.
|
||||
/// </summary>
|
||||
/// <value>The shuffle mode.</value>
|
||||
public GroupShuffleMode ShuffleMode { get; private set; } = GroupShuffleMode.Sorted;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the repeat mode.
|
||||
/// </summary>
|
||||
/// <value>The repeat mode.</value>
|
||||
public GroupRepeatMode RepeatMode { get; private set; } = GroupRepeatMode.RepeatNone;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if an item is playing.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if an item is playing; <c>false</c> otherwise.</returns>
|
||||
public bool IsItemPlaying()
|
||||
{
|
||||
return PlayingItemIndex != NoPlayingItemIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current playlist considering the shuffle mode.
|
||||
/// </summary>
|
||||
/// <returns>The playlist.</returns>
|
||||
public IReadOnlyList<SyncPlayQueueItem> GetPlaylist()
|
||||
{
|
||||
return GetPlaylistInternal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a new playlist. Playing item is reset.
|
||||
/// </summary>
|
||||
/// <param name="items">The new items of the playlist.</param>
|
||||
public void SetPlaylist(IReadOnlyList<Guid> items)
|
||||
{
|
||||
_sortedPlaylist.Clear();
|
||||
_shuffledPlaylist.Clear();
|
||||
|
||||
_sortedPlaylist = CreateQueueItemsFromArray(items);
|
||||
if (ShuffleMode.Equals(GroupShuffleMode.Shuffle))
|
||||
{
|
||||
_shuffledPlaylist = new List<SyncPlayQueueItem>(_sortedPlaylist);
|
||||
_shuffledPlaylist.Shuffle();
|
||||
}
|
||||
|
||||
PlayingItemIndex = NoPlayingItemIndex;
|
||||
LastChange = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends new items to the playlist. The specified order is maintained.
|
||||
/// </summary>
|
||||
/// <param name="items">The items to add to the playlist.</param>
|
||||
public void Queue(IReadOnlyList<Guid> items)
|
||||
{
|
||||
var newItems = CreateQueueItemsFromArray(items);
|
||||
|
||||
_sortedPlaylist.AddRange(newItems);
|
||||
if (ShuffleMode.Equals(GroupShuffleMode.Shuffle))
|
||||
{
|
||||
_shuffledPlaylist.AddRange(newItems);
|
||||
}
|
||||
|
||||
LastChange = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuffles the playlist. Shuffle mode is changed. The playlist gets re-shuffled if already shuffled.
|
||||
/// </summary>
|
||||
public void ShufflePlaylist()
|
||||
{
|
||||
if (PlayingItemIndex == NoPlayingItemIndex)
|
||||
{
|
||||
_shuffledPlaylist = new List<SyncPlayQueueItem>(_sortedPlaylist);
|
||||
_shuffledPlaylist.Shuffle();
|
||||
}
|
||||
else if (ShuffleMode.Equals(GroupShuffleMode.Sorted))
|
||||
{
|
||||
// First time shuffle.
|
||||
var playingItem = _sortedPlaylist[PlayingItemIndex];
|
||||
_shuffledPlaylist = new List<SyncPlayQueueItem>(_sortedPlaylist);
|
||||
_shuffledPlaylist.RemoveAt(PlayingItemIndex);
|
||||
_shuffledPlaylist.Shuffle();
|
||||
_shuffledPlaylist.Insert(0, playingItem);
|
||||
PlayingItemIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Re-shuffle playlist.
|
||||
var playingItem = _shuffledPlaylist[PlayingItemIndex];
|
||||
_shuffledPlaylist.RemoveAt(PlayingItemIndex);
|
||||
_shuffledPlaylist.Shuffle();
|
||||
_shuffledPlaylist.Insert(0, playingItem);
|
||||
PlayingItemIndex = 0;
|
||||
}
|
||||
|
||||
ShuffleMode = GroupShuffleMode.Shuffle;
|
||||
LastChange = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the playlist to sorted mode. Shuffle mode is changed.
|
||||
/// </summary>
|
||||
public void RestoreSortedPlaylist()
|
||||
{
|
||||
if (PlayingItemIndex != NoPlayingItemIndex)
|
||||
{
|
||||
var playingItem = _shuffledPlaylist[PlayingItemIndex];
|
||||
PlayingItemIndex = _sortedPlaylist.IndexOf(playingItem);
|
||||
}
|
||||
|
||||
_shuffledPlaylist.Clear();
|
||||
|
||||
ShuffleMode = GroupShuffleMode.Sorted;
|
||||
LastChange = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the playlist. Shuffle mode is preserved.
|
||||
/// </summary>
|
||||
/// <param name="clearPlayingItem">Whether to remove the playing item as well.</param>
|
||||
public void ClearPlaylist(bool clearPlayingItem)
|
||||
{
|
||||
var playingItem = GetPlayingItem();
|
||||
_sortedPlaylist.Clear();
|
||||
_shuffledPlaylist.Clear();
|
||||
LastChange = DateTime.UtcNow;
|
||||
|
||||
if (!clearPlayingItem && playingItem is not null)
|
||||
{
|
||||
_sortedPlaylist.Add(playingItem);
|
||||
if (ShuffleMode.Equals(GroupShuffleMode.Shuffle))
|
||||
{
|
||||
_shuffledPlaylist.Add(playingItem);
|
||||
}
|
||||
|
||||
PlayingItemIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayingItemIndex = NoPlayingItemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds new items to the playlist right after the playing item. The specified order is maintained.
|
||||
/// </summary>
|
||||
/// <param name="items">The items to add to the playlist.</param>
|
||||
public void QueueNext(IReadOnlyList<Guid> items)
|
||||
{
|
||||
var newItems = CreateQueueItemsFromArray(items);
|
||||
|
||||
if (ShuffleMode.Equals(GroupShuffleMode.Shuffle))
|
||||
{
|
||||
var playingItem = GetPlayingItem();
|
||||
var sortedPlayingItemIndex = _sortedPlaylist.IndexOf(playingItem);
|
||||
// Append items to sorted and shuffled playlist as they are.
|
||||
_sortedPlaylist.InsertRange(sortedPlayingItemIndex + 1, newItems);
|
||||
_shuffledPlaylist.InsertRange(PlayingItemIndex + 1, newItems);
|
||||
}
|
||||
else
|
||||
{
|
||||
_sortedPlaylist.InsertRange(PlayingItemIndex + 1, newItems);
|
||||
}
|
||||
|
||||
LastChange = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets playlist identifier of the playing item, if any.
|
||||
/// </summary>
|
||||
/// <returns>The playlist identifier of the playing item.</returns>
|
||||
public Guid GetPlayingItemPlaylistId()
|
||||
{
|
||||
var playingItem = GetPlayingItem();
|
||||
return playingItem?.PlaylistItemId ?? Guid.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the playing item identifier, if any.
|
||||
/// </summary>
|
||||
/// <returns>The playing item identifier.</returns>
|
||||
public Guid GetPlayingItemId()
|
||||
{
|
||||
var playingItem = GetPlayingItem();
|
||||
return playingItem?.ItemId ?? Guid.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the playing item using its identifier. If not in the playlist, the playing item is reset.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The new playing item identifier.</param>
|
||||
public void SetPlayingItemById(Guid itemId)
|
||||
{
|
||||
var playlist = GetPlaylistInternal();
|
||||
PlayingItemIndex = playlist.FindIndex(item => item.ItemId.Equals(itemId));
|
||||
LastChange = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the playing item using its playlist identifier. If not in the playlist, the playing item is reset.
|
||||
/// </summary>
|
||||
/// <param name="playlistItemId">The new playing item identifier.</param>
|
||||
/// <returns><c>true</c> if playing item has been set; <c>false</c> if item is not in the playlist.</returns>
|
||||
public bool SetPlayingItemByPlaylistId(Guid playlistItemId)
|
||||
{
|
||||
var playlist = GetPlaylistInternal();
|
||||
PlayingItemIndex = playlist.FindIndex(item => item.PlaylistItemId.Equals(playlistItemId));
|
||||
LastChange = DateTime.UtcNow;
|
||||
|
||||
return PlayingItemIndex != NoPlayingItemIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the playing item using its position. If not in range, the playing item is reset.
|
||||
/// </summary>
|
||||
/// <param name="playlistIndex">The new playing item index.</param>
|
||||
public void SetPlayingItemByIndex(int playlistIndex)
|
||||
{
|
||||
var playlist = GetPlaylistInternal();
|
||||
if (playlistIndex < 0 || playlistIndex > playlist.Count)
|
||||
{
|
||||
PlayingItemIndex = NoPlayingItemIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayingItemIndex = playlistIndex;
|
||||
}
|
||||
|
||||
LastChange = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes items from the playlist. If not removed, the playing item is preserved.
|
||||
/// </summary>
|
||||
/// <param name="playlistItemIds">The items to remove.</param>
|
||||
/// <returns><c>true</c> if playing item got removed; <c>false</c> otherwise.</returns>
|
||||
public bool RemoveFromPlaylist(IReadOnlyList<Guid> playlistItemIds)
|
||||
{
|
||||
var playingItem = GetPlayingItem();
|
||||
|
||||
_sortedPlaylist.RemoveAll(item => playlistItemIds.Contains(item.PlaylistItemId));
|
||||
_shuffledPlaylist.RemoveAll(item => playlistItemIds.Contains(item.PlaylistItemId));
|
||||
|
||||
LastChange = DateTime.UtcNow;
|
||||
|
||||
if (playingItem is not null)
|
||||
{
|
||||
if (playlistItemIds.Contains(playingItem.PlaylistItemId))
|
||||
{
|
||||
// Playing item has been removed, picking previous item.
|
||||
PlayingItemIndex--;
|
||||
if (PlayingItemIndex < 0)
|
||||
{
|
||||
// Was first element, picking next if available.
|
||||
// Default to no playing item otherwise.
|
||||
PlayingItemIndex = _sortedPlaylist.Count > 0 ? 0 : NoPlayingItemIndex;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Restoring playing item.
|
||||
SetPlayingItemByPlaylistId(playingItem.PlaylistItemId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves an item in the playlist to another position.
|
||||
/// </summary>
|
||||
/// <param name="playlistItemId">The item to move.</param>
|
||||
/// <param name="newIndex">The new position.</param>
|
||||
/// <returns><c>true</c> if the item has been moved; <c>false</c> otherwise.</returns>
|
||||
public bool MovePlaylistItem(Guid playlistItemId, int newIndex)
|
||||
{
|
||||
var playlist = GetPlaylistInternal();
|
||||
var playingItem = GetPlayingItem();
|
||||
|
||||
var oldIndex = playlist.FindIndex(item => item.PlaylistItemId.Equals(playlistItemId));
|
||||
if (oldIndex < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var queueItem = playlist[oldIndex];
|
||||
playlist.RemoveAt(oldIndex);
|
||||
newIndex = Math.Clamp(newIndex, 0, playlist.Count);
|
||||
playlist.Insert(newIndex, queueItem);
|
||||
|
||||
LastChange = DateTime.UtcNow;
|
||||
PlayingItemIndex = playlist.IndexOf(playingItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the playlist to its initial state.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
_sortedPlaylist.Clear();
|
||||
_shuffledPlaylist.Clear();
|
||||
PlayingItemIndex = NoPlayingItemIndex;
|
||||
ShuffleMode = GroupShuffleMode.Sorted;
|
||||
RepeatMode = GroupRepeatMode.RepeatNone;
|
||||
LastChange = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the repeat mode.
|
||||
/// </summary>
|
||||
/// <param name="mode">The new mode.</param>
|
||||
public void SetRepeatMode(GroupRepeatMode mode)
|
||||
{
|
||||
RepeatMode = mode;
|
||||
LastChange = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the shuffle mode.
|
||||
/// </summary>
|
||||
/// <param name="mode">The new mode.</param>
|
||||
public void SetShuffleMode(GroupShuffleMode mode)
|
||||
{
|
||||
if (mode.Equals(GroupShuffleMode.Shuffle))
|
||||
{
|
||||
ShufflePlaylist();
|
||||
}
|
||||
else
|
||||
{
|
||||
RestoreSortedPlaylist();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the shuffle mode between sorted and shuffled.
|
||||
/// </summary>
|
||||
public void ToggleShuffleMode()
|
||||
{
|
||||
if (ShuffleMode.Equals(GroupShuffleMode.Sorted))
|
||||
{
|
||||
ShufflePlaylist();
|
||||
}
|
||||
else
|
||||
{
|
||||
RestoreSortedPlaylist();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next item in the playlist considering repeat mode and shuffle mode.
|
||||
/// </summary>
|
||||
/// <returns>The next item in the playlist.</returns>
|
||||
public SyncPlayQueueItem GetNextItemPlaylistId()
|
||||
{
|
||||
int newIndex;
|
||||
var playlist = GetPlaylistInternal();
|
||||
|
||||
switch (RepeatMode)
|
||||
{
|
||||
case GroupRepeatMode.RepeatOne:
|
||||
newIndex = PlayingItemIndex;
|
||||
break;
|
||||
case GroupRepeatMode.RepeatAll:
|
||||
newIndex = PlayingItemIndex + 1;
|
||||
if (newIndex >= playlist.Count)
|
||||
{
|
||||
newIndex = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
newIndex = PlayingItemIndex + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (newIndex < 0 || newIndex >= playlist.Count)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return playlist[newIndex];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the next item in the queue as playing item.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if the playing item changed; <c>false</c> otherwise.</returns>
|
||||
public bool Next()
|
||||
{
|
||||
if (RepeatMode.Equals(GroupRepeatMode.RepeatOne))
|
||||
{
|
||||
LastChange = DateTime.UtcNow;
|
||||
return true;
|
||||
}
|
||||
|
||||
PlayingItemIndex++;
|
||||
if (PlayingItemIndex >= _sortedPlaylist.Count)
|
||||
{
|
||||
if (RepeatMode.Equals(GroupRepeatMode.RepeatAll))
|
||||
{
|
||||
PlayingItemIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayingItemIndex = _sortedPlaylist.Count - 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LastChange = DateTime.UtcNow;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the previous item in the queue as playing item.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if the playing item changed; <c>false</c> otherwise.</returns>
|
||||
public bool Previous()
|
||||
{
|
||||
if (RepeatMode.Equals(GroupRepeatMode.RepeatOne))
|
||||
{
|
||||
LastChange = DateTime.UtcNow;
|
||||
return true;
|
||||
}
|
||||
|
||||
PlayingItemIndex--;
|
||||
if (PlayingItemIndex < 0)
|
||||
{
|
||||
if (RepeatMode.Equals(GroupRepeatMode.RepeatAll))
|
||||
{
|
||||
PlayingItemIndex = _sortedPlaylist.Count - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayingItemIndex = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LastChange = DateTime.UtcNow;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a list from the array of items. Each item is given an unique playlist identifier.
|
||||
/// </summary>
|
||||
/// <returns>The list of queue items.</returns>
|
||||
private List<SyncPlayQueueItem> CreateQueueItemsFromArray(IReadOnlyList<Guid> items)
|
||||
{
|
||||
var list = new List<SyncPlayQueueItem>();
|
||||
foreach (var item in items)
|
||||
{
|
||||
var queueItem = new SyncPlayQueueItem(item);
|
||||
list.Add(queueItem);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current playlist considering the shuffle mode.
|
||||
/// </summary>
|
||||
/// <returns>The playlist.</returns>
|
||||
private List<SyncPlayQueueItem> GetPlaylistInternal()
|
||||
{
|
||||
if (ShuffleMode.Equals(GroupShuffleMode.Shuffle))
|
||||
{
|
||||
return _shuffledPlaylist;
|
||||
}
|
||||
|
||||
return _sortedPlaylist;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current playing item, depending on the shuffle mode.
|
||||
/// </summary>
|
||||
/// <returns>The playing item.</returns>
|
||||
private SyncPlayQueueItem GetPlayingItem()
|
||||
{
|
||||
if (PlayingItemIndex == NoPlayingItemIndex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ShuffleMode.Equals(GroupShuffleMode.Shuffle))
|
||||
{
|
||||
return _shuffledPlaylist[PlayingItemIndex];
|
||||
}
|
||||
|
||||
return _sortedPlaylist[PlayingItemIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user