[WIP] sync

This commit is contained in:
Yoshi Askharoun
2023-10-08 20:49:37 -05:00
parent a718ad1f48
commit dbf74db8ef
11 changed files with 274 additions and 165 deletions
+4
View File
@@ -13,6 +13,10 @@
<ProjectReference Include="..\ZuneShell\ZuneShell.csproj" />
</ItemGroup>
<ItemGroup Condition=" $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' ">
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.18" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\ZuneFluentGem.ico" />
<Resource Include="Assets\ZuneFluentWordmark.png" />
+4
View File
@@ -18,4 +18,8 @@
<ProjectReference Include="..\ZuneShell\ZuneShell.csproj" />
</ItemGroup>
<ItemGroup Condition=" $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' ">
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.18" />
</ItemGroup>
</Project>
+27
View File
@@ -5,6 +5,8 @@ using System.Net.Http;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.Text;
using System.Diagnostics.CodeAnalysis;
using System.Collections.Generic;
namespace Microsoft.Zune;
@@ -50,4 +52,29 @@ internal static class Extensions
MD5 md5 = MD5.Create();
return md5.ComputeHash(Encoding.Default.GetBytes(id));
}
/// <summary>
/// Returns a value that indicates whether there is an object at the top of the System.Collections.Generic.Stack`1,
/// and if one is present, copies it to the result parameter, and removes it from
/// the System.Collections.Generic.Stack`1.
/// </summary>
/// <param name="result">
/// If present, the object at the top of the System.Collections.Generic.Stack`1;
/// otherwise, the default value of T.
/// </param>
/// <returns>
/// true if there is an object at the top of the System.Collections.Generic.Stack`1;
/// false if the System.Collections.Generic.Stack`1 is empty.
/// </returns>
public static bool TryPop<T>(this Stack<T> stack, [MaybeNullWhen(false)] out T result)
{
if (stack.Count > 0)
{
result = stack.Pop();
return true;
}
result = default;
return false;
}
}
+140 -132
View File
@@ -470,6 +470,145 @@ namespace Microsoft.Zune.Library
}
var stTracks = m_dataRoot.Library.GetTracksAsync(int.MaxValue, 0);
}
else if (text == "AlbumByTOC")
{
queryType = EQueryType.eQueryTypeAlbumsByTOC;
//if (!queryPropertyBag.IsSet("TOC"))
//{
// equeryType = EQueryType.eQueryTypeInvalid;
//}
}
else if (text == "Photo")
{
queryType = (equeryTypeView == EQueryTypeView.eQueryTypeDeviceSyncRuleView)
? EQueryType.eQueryTypeAllPhotos
: EQueryType.eQueryTypePhotosByFolderId;
}
else if (text == "MediaFolder")
{
queryType = EQueryType.eQueryTypeMediaFolders;
}
else if (text == "Video")
{
if (TryGetProperty("CategoryId", out categoryId) && categoryId != -1)
queryType = EQueryType.eQueryTypeVideosByCategoryId;
else
queryType = EQueryType.eQueryTypeAllVideos;
}
else if (text == "PodcastSeries")
{
queryType = EQueryType.eQueryTypeAllPodcastSeries;
}
else if (text == "PodcastEpisode")
{
if (TryGetProperty("SeriesId", out seriesId) && seriesId != -1)
queryType = EQueryType.eQueryTypeEpisodesForSeriesId;
else
queryType = EQueryType.eQueryTypeAllPodcastEpisodes;
}
else if (text == "SyncItem")
{
queryType = EQueryType.eQueryTypeSyncProgress;
}
else if (text == "Playlist")
{
queryType = EQueryType.eQueryTypeAllPlaylists;
}
else if (text == "PlaylistContent")
{
queryType = EQueryType.eQueryTypePlaylistContentByPlaylistId;
}
else if (text == "UserCard")
{
queryType = EQueryType.eQueryTypeUserCards;
}
else if (text == "Person")
{
queryType = EQueryType.eQueryTypePersonsByTypeId;
EMediaTypes personType = EMediaTypes.eMediaTypePersonArtist;
personType = ((string)GetProperty("PersonType") == "Composer")
? EMediaTypes.eMediaTypePersonComposer
: personType;
}
else if (text == "ArtistsRanking")
{
queryType = EQueryType.eQueryTypeArtistsRanking;
}
else if (text == "TVSeries")
{
queryType = EQueryType.eQueryTypeVideoSeriesTitles;
}
else if (text == "Pin")
{
queryType = EQueryType.eQueryTypePinsByPinType;
if (!TryGetProperty("PinType", out EPinType pinType))
pinType = EPinType.ePinTypeGeneric;
var pinnedTracks = m_dataRoot.Library.GetTracksAsync(3, 0);
Schemas.Pin pin = new(m_dataType)
{
PinId = 42,
PinType = 1,
Ordinal = 1,
Description = "An OpenZune pin",
MediaId = 1,
MediaType = 1,
ZuneMediaRef = "ZuneSomethingHehe",
UserId = 0,
DateModified = DateTime.Now,
ZuneMediaType = 0,
};
//queryList.Add(pin.Item);
}
else if (text == "App")
{
queryType = EQueryType.eQueryTypeAllApps;
}
queryList.QueryType = queryType;
DeferredSetResult(new DeferredSetResultArgs(num, queryList, false));// retainedList));
}
}
private void DeferredSetResult(object state)
{
DeferredSetResultArgs deferredSetResultArgs = (DeferredSetResultArgs)state;
bool isEmpty = true;
if (deferredSetResultArgs.QueryList != null)
{
if (!TryGetProperty("AutoRefresh", out bool autoRefresh))
autoRefresh = true;
if (!TryGetProperty("AntialiasImageEdges", out bool antialiasEdges))
antialiasEdges = false;
m_thumbnailFallbackImageUrl = (string)GetProperty("ThumbnailFallbackImageUrl");
(m_virtualListResultSet as IDisposable)?.Dispose();
m_virtualListResultSet = new(this, deferredSetResultArgs.QueryList, autoRefresh, antialiasEdges)
{
VisualReleaseBehavior = deferredSetResultArgs.RetainedList
? ReleaseBehavior.KeepReference
: ReleaseBehavior.ReleaseReference
};
isEmpty = deferredSetResultArgs.QueryList.IsEmpty;
}
StrixLibraryDataProviderQueryResult libraryDataProviderQueryResult = new(this, m_virtualListResultSet, ResultTypeCookie);
libraryDataProviderQueryResult.SetIsEmpty(isEmpty);
Result = libraryDataProviderQueryResult;
Status = DataProviderQueryStatus.Complete;
}
private Schemas.Track CreateTrack(ZuneQueryList queryList, )
{
await foreach (var stTrack in stTracks)
{
var stAlbum = stTrack.Album;
@@ -580,141 +719,10 @@ namespace Microsoft.Zune.Library
var stGenre = await stTrack.GetGenresAsync(1, 0).FirstOrDefaultAsync();
track.Genre = stGenre?.Name;
track.Item.Storage["StrixItem"] = stTrack;
queryList.Add(track.Item);
}
}
else if (text == "AlbumByTOC")
{
queryType = EQueryType.eQueryTypeAlbumsByTOC;
//if (!queryPropertyBag.IsSet("TOC"))
//{
// equeryType = EQueryType.eQueryTypeInvalid;
//}
}
else if (text == "Photo")
{
queryType = (equeryTypeView == EQueryTypeView.eQueryTypeDeviceSyncRuleView)
? EQueryType.eQueryTypeAllPhotos
: EQueryType.eQueryTypePhotosByFolderId;
}
else if (text == "MediaFolder")
{
queryType = EQueryType.eQueryTypeMediaFolders;
}
else if (text == "Video")
{
if (TryGetProperty("CategoryId", out categoryId) && categoryId != -1)
queryType = EQueryType.eQueryTypeVideosByCategoryId;
else
queryType = EQueryType.eQueryTypeAllVideos;
}
else if (text == "PodcastSeries")
{
queryType = EQueryType.eQueryTypeAllPodcastSeries;
}
else if (text == "PodcastEpisode")
{
if (TryGetProperty("SeriesId", out seriesId) && seriesId != -1)
queryType = EQueryType.eQueryTypeEpisodesForSeriesId;
else
queryType = EQueryType.eQueryTypeAllPodcastEpisodes;
}
else if (text == "SyncItem")
{
queryType = EQueryType.eQueryTypeSyncProgress;
}
else if (text == "Playlist")
{
queryType = EQueryType.eQueryTypeAllPlaylists;
}
else if (text == "PlaylistContent")
{
queryType = EQueryType.eQueryTypePlaylistContentByPlaylistId;
}
else if (text == "UserCard")
{
queryType = EQueryType.eQueryTypeUserCards;
}
else if (text == "Person")
{
queryType = EQueryType.eQueryTypePersonsByTypeId;
EMediaTypes personType = EMediaTypes.eMediaTypePersonArtist;
personType = ((string)GetProperty("PersonType") == "Composer")
? EMediaTypes.eMediaTypePersonComposer
: personType;
}
else if (text == "ArtistsRanking")
{
queryType = EQueryType.eQueryTypeArtistsRanking;
}
else if (text == "TVSeries")
{
queryType = EQueryType.eQueryTypeVideoSeriesTitles;
}
else if (text == "Pin")
{
queryType = EQueryType.eQueryTypePinsByPinType;
if (!TryGetProperty("PinType", out EPinType pinType))
pinType = EPinType.ePinTypeGeneric;
Schemas.Pin pin = new(m_dataType)
{
PinId = 42,
PinType = 1,
Ordinal = 1,
Description = "An OpenZune pin",
MediaId = 1,
MediaType = 1,
ZuneMediaRef = "ZuneSomethingHehe",
UserId = 0,
DateModified = DateTime.Now,
ZuneMediaType = 0,
};
//queryList.Add(pin.Item);
}
else if (text == "App")
{
queryType = EQueryType.eQueryTypeAllApps;
}
queryList.QueryType = queryType;
DeferredSetResult(new DeferredSetResultArgs(num, queryList, false));// retainedList));
}
}
private void DeferredSetResult(object state)
{
DeferredSetResultArgs deferredSetResultArgs = (DeferredSetResultArgs)state;
bool isEmpty = true;
if (deferredSetResultArgs.QueryList != null)
{
if (!TryGetProperty("AutoRefresh", out bool autoRefresh))
autoRefresh = true;
if (!TryGetProperty("AntialiasImageEdges", out bool antialiasEdges))
antialiasEdges = false;
m_thumbnailFallbackImageUrl = (string)GetProperty("ThumbnailFallbackImageUrl");
(m_virtualListResultSet as IDisposable)?.Dispose();
m_virtualListResultSet = new(this, deferredSetResultArgs.QueryList, autoRefresh, antialiasEdges)
{
VisualReleaseBehavior = deferredSetResultArgs.RetainedList
? ReleaseBehavior.KeepReference
: ReleaseBehavior.ReleaseReference
};
isEmpty = deferredSetResultArgs.QueryList.IsEmpty;
}
StrixLibraryDataProviderQueryResult libraryDataProviderQueryResult = new(this, m_virtualListResultSet, ResultTypeCookie);
libraryDataProviderQueryResult.SetIsEmpty(isEmpty);
Result = libraryDataProviderQueryResult;
Status = DataProviderQueryStatus.Complete;
}
}
internal class DeferredSetResultArgs
+21 -2
View File
@@ -3,6 +3,7 @@
using LibVLCSharp.Shared;
using StrixMusic.Sdk.MediaPlayback;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -16,6 +17,7 @@ namespace Microsoft.Zune.Playback
readonly LibVLC m_vlc;
readonly MediaPlayer m_player;
private Media m_media, m_nextMedia;
private Stack<IDisposable> m_toDisposeOnEnd = new(2);
private PlaybackItem m_currentSource;
private TimeSpan m_position;
@@ -46,6 +48,11 @@ namespace Microsoft.Zune.Playback
m_player = new(m_vlc);
m_player.TimeChanged += (sender, e) => Position = TimeSpan.FromMilliseconds(e.Time);
m_player.EndReached += (sender, e) =>
{
while (m_toDisposeOnEnd.TryPop(out var item))
item.Dispose();
};
}
public PlaybackItem CurrentSource
@@ -179,12 +186,24 @@ namespace Microsoft.Zune.Playback
var uri = sourceConfig.MediaConfig.MediaSourceUri;
var stream = sourceConfig.MediaConfig.FileStreamSource;
Media media = null;
if (uri != null)
return new(m_vlc, uri);
{
media = new(m_vlc, uri);
}
else if (stream != null)
return new(m_vlc, new StreamMediaInput(stream));
{
StreamMediaInput streamInput = new(stream);
media = new(m_vlc, streamInput);
m_toDisposeOnEnd.Push(streamInput);
}
if (media is null)
throw new NotImplementedException();
m_toDisposeOnEnd.Push(media);
return media;
}
}
}
-4
View File
@@ -21,8 +21,4 @@
<ProjectReference Include="..\libs\MicrosoftIris\UIX\UIX.csproj" />
</ItemGroup>
<ItemGroup Condition=" $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows' ">
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.18" />
</ItemGroup>
</Project>
+4 -4
View File
@@ -83,8 +83,8 @@ Global
{CB2B7609-C7B8-4E2A-82D8-DD631B70B621}.Release|x64.Build.0 = Release|x64
{CB2B7609-C7B8-4E2A-82D8-DD631B70B621}.Release|x86.ActiveCfg = Release|x86
{CB2B7609-C7B8-4E2A-82D8-DD631B70B621}.Release|x86.Build.0 = Release|x86
{4041A91F-EF2A-4C47-9EBE-F4E862532345}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4041A91F-EF2A-4C47-9EBE-F4E862532345}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4041A91F-EF2A-4C47-9EBE-F4E862532345}.Debug|Any CPU.ActiveCfg = Debug|x64
{4041A91F-EF2A-4C47-9EBE-F4E862532345}.Debug|Any CPU.Build.0 = Debug|x64
{4041A91F-EF2A-4C47-9EBE-F4E862532345}.Debug|ARM32.ActiveCfg = Debug|ARM32
{4041A91F-EF2A-4C47-9EBE-F4E862532345}.Debug|ARM32.Build.0 = Debug|ARM32
{4041A91F-EF2A-4C47-9EBE-F4E862532345}.Debug|x64.ActiveCfg = Debug|x64
@@ -99,8 +99,8 @@ Global
{4041A91F-EF2A-4C47-9EBE-F4E862532345}.Release|x64.Build.0 = Release|x64
{4041A91F-EF2A-4C47-9EBE-F4E862532345}.Release|x86.ActiveCfg = Release|x86
{4041A91F-EF2A-4C47-9EBE-F4E862532345}.Release|x86.Build.0 = Release|x86
{1FEAC59B-F012-4ACC-9F11-E7ADF4C77593}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1FEAC59B-F012-4ACC-9F11-E7ADF4C77593}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1FEAC59B-F012-4ACC-9F11-E7ADF4C77593}.Debug|Any CPU.ActiveCfg = Debug|x64
{1FEAC59B-F012-4ACC-9F11-E7ADF4C77593}.Debug|Any CPU.Build.0 = Debug|x64
{1FEAC59B-F012-4ACC-9F11-E7ADF4C77593}.Debug|ARM32.ActiveCfg = Debug|x64
{1FEAC59B-F012-4ACC-9F11-E7ADF4C77593}.Debug|ARM32.Build.0 = Debug|x64
{1FEAC59B-F012-4ACC-9F11-E7ADF4C77593}.Debug|x64.ActiveCfg = Debug|x64
@@ -150,7 +150,7 @@ namespace Microsoft.Zune.Shell
cacheFolderPath.Create();
OwlCore.Storage.SystemIO.SystemFolder cacheFolder = new(cacheFolderPath);
OwlCore.Storage.SystemIO.SystemFolder musicFolder = new(@"D:\Music\Zune\Test");
OwlCore.Storage.SystemIO.SystemFolder musicFolder = new(@"C:\Users\jjask\OneDrive\Music\Rush");
var localCore = new StrixMusic.Cores.Storage.StorageCore(musicFolder, cacheFolder, "Local Test")
{
ScannerWaitBehavior = StrixMusic.Cores.Storage.ScannerWaitBehavior.AlwaysWait,
+9
View File
@@ -465,6 +465,15 @@ namespace ZuneUI
case QuickMixItem _:
AddQuickMixItemToTrackList((QuickMixItem)obj, tracks, containerPlayMarkerOverride);
continue;
#if OPENZUNE
case Microsoft.Iris.UI.Class ozMediaItem:
var stTrack = (StrixMusic.Sdk.AppModels.ITrack)ozMediaItem.Storage["StrixItem"];
var zuneMediaId = (Guid)ozMediaItem.Storage["ZuneMediaId"];
tracks.Add(new Strix.StrixPlaybackTrack(stTrack, zuneMediaId));
break;
#endif
default:
continue;
}
@@ -0,0 +1,37 @@
using Microsoft.Zune;
using StrixMusic.Sdk.AppModels;
using System;
using System.Linq;
namespace ZuneUI.Strix;
public class StrixPlaybackTrack : PlaybackTrack
{
public StrixPlaybackTrack(ITrack stTrack, Guid zuneId)
{
Track = stTrack;
ZuneMediaId = zuneId;
}
public ITrack Track { get; }
public override string Title => Track.Name;
public override TimeSpan Duration => Track.Duration;
public override Guid ZuneMediaId { get; }
public override HRESULT GetURI(out string uri)
{
uri = null;
if (Track.TotalUrlCount <= 0)
return HRESULT._DB_E_NOTFOUND;
var url = AsyncHelper.Run(
() => Track.GetUrlsAsync(1, 0).FirstAsync().AsTask()
);
uri = url.Url.ToString();
return HRESULT._S_OK;
}
}
@@ -24,6 +24,7 @@ using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
using UIXControls;
using ZuneUI.Strix;
namespace ZuneUI
{
@@ -1838,20 +1839,19 @@ namespace ZuneUI
int myID = ++_lastKnownSetUriCallID;
ThreadPool.QueueUserWorkItem(args =>
{
var dataRoot = Microsoft.Zune.Shell.ZuneApplication.DataRoot;
if (track != null)
{
HRESULT hr = track.GetURI(out string trackUri);
if (string.IsNullOrEmpty(trackUri))
trackUri = ".:* INVALID URI *:.";
try
{
var stTrack = ((StrixPlaybackTrack)track).Track;
if (hr.IsSuccess)
Application.DeferredInvoke(delegate
{
if (IsDisposed || myID != _lastKnownSetUriCallID)
return;
PlaybackItem item = ZuneMediaSourceConfig.CreatePlaybackItem(trackUri, track.PlaybackID);
_player.PlaySync(item);
AsyncHelper.Run(dataRoot.Library.PlayTrackCollectionAsync(stTrack));
ReportStreamingAction(PlayerState.Stopped);
_tracksSubmittedToPlayer.Remove(track);
@@ -1862,35 +1862,40 @@ namespace ZuneUI
// TODO: _playbackWrapper.CancelNext();
UpdatePropertiesAndCommands();
}, null);
else
}
catch (Exception ex)
{
OnAlertSent(new Announcement()
{
HResult = hr.Int,
HResult = ex.HResult,
PlaybackID = track.PlaybackID
});
}
}
if (nextTrack == null)
return;
HRESULT nextTrackHr = nextTrack.GetURI(out string nextTrackUri);
if (string.IsNullOrEmpty(nextTrackUri))
nextTrackUri = ".:* INVALID URI *:.";
if (!nextTrackHr.IsSuccess)
return;
try
{
var stTrack = ((StrixPlaybackTrack)nextTrack).Track;
Application.DeferredInvoke(delegate
{
if (IsDisposed || myID != _lastKnownSetUriCallID)
return;
PlaybackItem item = ZuneMediaSourceConfig.CreatePlaybackItem(nextTrackUri, track.PlaybackID);
_player.PreloadSync(item);
// Preload track
//AsyncHelper.Run(dataRoot.Library.PlayTrackCollectionAsync(stTrack));
_tracksSubmittedToPlayer.Remove(nextTrack);
_tracksSubmittedToPlayer.Add(nextTrack);
UpdatePropertiesAndCommands();
}, null);
}
catch
{
}
}, null);
}