Skip to content

Commit

Permalink
Make playback more stable
Browse files Browse the repository at this point in the history
  • Loading branch information
cjw1115 committed Jul 20, 2020
1 parent 9020cee commit 0cff65a
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 180 deletions.
63 changes: 20 additions & 43 deletions AilianBT/Services/MusicManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,67 +26,31 @@ public class MusicManager
public MusicManager()
{
_mediaPlaybackList = new MediaPlaybackList();
_mediaPlaybackList.CurrentItemChanged += _mediaPlaybackListCurrentItemChanged;
_mediaPlaybackList.ItemOpened += _mediaPlaybackListItemOpened;
_mediaPlaybackList.ItemFailed += _mediaPlaybackListItemFailed;
_mediaPlaybackList.AutoRepeatEnabled = false;
_mediaPlaybackList.MaxPlayedItemsToKeepOpen = 3;

_mediaPlaybackList.Items.Add(_createPlaceholderItem());
_mediaPlaybackList.Items.Add(_createPlaceholderItem());
_mediaPlaybackList.Items.Add(_createPlaceholderItem());

_mediaPlayer = new MediaPlayer();
_mediaPlayer.AutoPlay = false;
_mediaPlayer.Source = _mediaPlaybackList;
_mediaPlayer.PlaybackSession.PositionChanged += PlaybackSession_PositionChanged;
_mediaPlayer.MediaEnded += _mediaPlayerMediaEnded;
}

private void _mediaPlayerMediaEnded(MediaPlayer sender, object args)
{
MediaEnd?.Invoke();
}

private void PlaybackSession_PositionChanged(MediaPlaybackSession sender, object args)
{
PositionChanged?.Invoke(_mediaPlayer.PlaybackSession.Position, _mediaPlayer.PlaybackSession.NaturalDuration);
}

public event Action<MusicModel> MediaLoaded;
public event Action<MusicModel> MediaEnd;
public event Action<MusicModel> MediaFailed;
public event Action<MusicModel, MusicModel> MediaChanged;
public event Action<MusicModel> MediaLoading;
public event Action<MusicModel> MediaCached;
public event Action<TimeSpan, TimeSpan> PositionChanged;

public event Action MediaEnd;

#region MediaPlaybackList callbacks
private void _mediaPlaybackListCurrentItemChanged(MediaPlaybackList sender, CurrentMediaPlaybackItemChangedEventArgs args)
{
if(args.Reason== MediaPlaybackItemChangedReason.EndOfStream)
{
_mediaPlayer.Pause();
MediaEnd?.Invoke();
return;
}

MusicModel newModel = null;
MusicModel oldModel= null;
if(args.NewItem!=null)
{
var newModelJson = args.NewItem.Source.CustomProperties["model"] as string;
newModel = JsonSerializer.Deserialize<MusicModel>(newModelJson);
}
if (args.OldItem != null)
{
var oldModelJson = args.OldItem.Source.CustomProperties["model"] as string;
oldModel = JsonSerializer.Deserialize<MusicModel>(oldModelJson);
}
MediaChanged?.Invoke(newModel, oldModel);
}

private void _mediaPlaybackListItemOpened(MediaPlaybackList sender, MediaPlaybackItemOpenedEventArgs args)
{
var modelJson = args.Item.Source.CustomProperties["model"] as string;
Expand All @@ -95,15 +59,21 @@ private void _mediaPlaybackListItemOpened(MediaPlaybackList sender, MediaPlaybac
MediaLoaded?.Invoke(model);
}

private void _mediaPlayerMediaEnded(MediaPlayer sender, object args)
{
MediaEnd?.Invoke(null);
}

private void _mediaPlaybackListItemFailed(MediaPlaybackList sender, MediaPlaybackItemFailedEventArgs args)
{
MusicModel model = null;
if(args.Item.Source.CustomProperties.TryGetValue("model", out object value))
{
var modelJson = value as string;
var model = JsonSerializer.Deserialize<MusicModel>(modelJson);
model = JsonSerializer.Deserialize<MusicModel>(modelJson);
_logger.Error($"Play music failed: \n\t{modelJson}\n\t{args.Error.ErrorCode}", args.Error.ExtendedError);
MediaFailed?.Invoke(model);
}
MediaFailed?.Invoke(model);
}
#endregion

Expand Down Expand Up @@ -188,10 +158,17 @@ public async Task Seek(TimeSpan position)
}
private async Task _play(MusicModel model)
{
var playbackItem = await _cacheMusic(model);
var playbackItemIndex = _mediaPlaybackList.Items.IndexOf(playbackItem);
_mediaPlaybackList.MoveTo((uint)playbackItemIndex);
_mediaPlayer.Play();
try
{
var playbackItem = await _cacheMusic(model);
var playbackItemIndex = _mediaPlaybackList.Items.IndexOf(playbackItem);
_mediaPlaybackList.MoveTo((uint)playbackItemIndex);
_mediaPlayer.Play();
}
catch
{
MediaFailed?.Invoke(model);
}
}

private int? _getIndex(MusicModel model)
Expand Down
49 changes: 38 additions & 11 deletions AilianBT/Services/MusicService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Windows.Media.Core;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.WindowManagement;

namespace AilianBT.Services
Expand All @@ -30,6 +31,7 @@ public class MusicService
private StorageService _storageService;

private BackgroundDownloader _backgroundDownloader;
private BackgroundTransferGroup _backgroundDownloaderGroup = BackgroundTransferGroup.CreateGroup(DOWNLOAD_GROUP_NAME);

public MusicService(UtilityHelper utilityHelper,LogService logger, StorageService storageService)
{
Expand Down Expand Up @@ -127,10 +129,11 @@ public async Task CachePlayListAsync(IList<MusicModel> playlist)
}
#endregion


private const string DOWNLOAD_GROUP_NAME = "MusicCaching";
private void _initDownloader()
{
_backgroundDownloader = new BackgroundDownloader();
_backgroundDownloader.TransferGroup = _backgroundDownloaderGroup;
_backgroundDownloader.SetRequestHeader("Referer", KISSSUB_HOST);
}

Expand All @@ -149,21 +152,45 @@ public async Task<MediaSource> RequestMusic(MusicModel model)
}
};

IRandomAccessStreamReference ras = null;
DownloadOperation downloadOperation = null;
var downloadProgress = new Progress<DownloadOperation>();
downloadProgress.ProgressChanged += downloadProgressHandler;

var cacheFile = await _createMusicFile(model);
if (cacheFile == null)
{
_logger.Error($"Create local file for storing music failed");
return null;
var operations = await BackgroundDownloader.GetCurrentDownloadsForTransferGroupAsync(_backgroundDownloaderGroup);
foreach (var item in operations)
{
if (item.ResultFile is StorageFile cachedFile)
{
if (cachedFile.Name == _utilityHelper.CreateMd5HashString(model.Title))
{
downloadOperation = item;
break;
}
}
}
if (downloadOperation != null)
{
ras = downloadOperation.GetResultRandomAccessStreamReference();
downloadOperation.AttachAsync().AsTask(downloadProgress);
}
else
{
_logger.Warning($"Don't find the downloading task for {model.Title}");
return null;
}
}
else
{
downloadOperation = _backgroundDownloader.CreateDownload(model.Uri, cacheFile);
downloadOperation.IsRandomAccessRequired = true;
ras = downloadOperation.GetResultRandomAccessStreamReference();
downloadOperation.StartAsync().AsTask(downloadProgress);
}

var downloadProgress = new Progress<DownloadOperation>();
downloadProgress.ProgressChanged += downloadProgressHandler;

var downloadOperation = _backgroundDownloader.CreateDownload(model.Uri, cacheFile);
downloadOperation.IsRandomAccessRequired = true;
var ras = downloadOperation.GetResultRandomAccessStreamReference();

downloadOperation.StartAsync().AsTask(downloadProgress);
var source = MediaSource.CreateFromStreamReference(ras, "audio/mpeg");
return source;
}
Expand Down
13 changes: 3 additions & 10 deletions AilianBT/ViewModels/MusicVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ public ObservableCollection<MusicModel> MusicList

public async void Load()
{
PlayerVM.SetMusicList(MusicList);
await _preparePlaylist();
PlayerVM.SetMusicList(MusicList);
await _musicService.CheckCachedMusicAsync(MusicList, SynchronizationContext);
}

Expand Down Expand Up @@ -82,26 +82,19 @@ private async Task _preparePlaylist()
{
MusicList.Add(item);
}
PlayerVM.CurrentIndex = 0;
}
catch (Exception e)
{
App.ShowNotification(e.Message);
_logger.Error($"Initilize the playlist failed", e);
return;
}
PlayerVM.CanPreviou = false;
PlayerVM.CanNext = true;
}


public async void ItemClicked(MusicModel model)
public void ItemClicked(MusicModel model)
{
//IsLoading = true;

//_musicManager.Pause(true);
//await _musicManager.Play(model);
//Title = model.Title;
PlayerVM.PlayClicked();
}
}
}
Expand Down
Loading

0 comments on commit 0cff65a

Please sign in to comment.