[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
+5 -1
View File
@@ -6,13 +6,17 @@
<LangVersion>11.0</LangVersion>
<UseWPF>true</UseWPF>
<ApplicationIcon>Assets\ZuneFluentGem.ico</ApplicationIcon>
<AppConfig>App.config</AppConfig>
<AppConfig>App.config</AppConfig>
</PropertyGroup>
<ItemGroup>
<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" />
+19 -15
View File
@@ -1,21 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net461;net6.0-windows10.0.22000;net6.0;</TargetFrameworks>
<Platforms>AnyCPU;x64;x86;ARM32</Platforms>
<LangVersion>11.0</LangVersion>
<AppConfig>App.config</AppConfig>
</PropertyGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net461;net6.0-windows10.0.22000;net6.0;</TargetFrameworks>
<Platforms>AnyCPU;x64;x86;ARM32</Platforms>
<LangVersion>11.0</LangVersion>
<AppConfig>App.config</AppConfig>
</PropertyGroup>
<ItemGroup>
<Compile Remove="build\**" />
<EmbeddedResource Remove="build\**" />
<None Remove="build\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="build\**" />
<EmbeddedResource Remove="build\**" />
<None Remove="build\**" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ZuneShell\ZuneShell.csproj" />
</ItemGroup>
<ItemGroup>
<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;
}
}
+119 -111
View File
@@ -470,118 +470,7 @@ namespace Microsoft.Zune.Library
}
var stTracks = m_dataRoot.Library.GetTracksAsync(int.MaxValue, 0);
await foreach (var stTrack in stTracks)
{
var stAlbum = stTrack.Album;
var stAlbumArtist = stAlbum != null
? await stAlbum.GetArtistItemsAsync(1, 0).FirstOrDefaultAsync()
: null;
// Handle filters
if (queryType == EQueryType.eQueryTypeTracksForAlbumId)
{
var currentAlbumId = stAlbum?.Id.HashToInt32();
if (currentAlbumId != albumId) continue;
}
else if (queryType == EQueryType.eQueryTypeTracksForAlbumArtistId)
{
var currentAlbumArtistId = stAlbumArtist?.Id.HashToInt32();
if (currentAlbumArtistId != albumArtistId) continue;
}
else if (queryType == EQueryType.eQueryTypeTracksByGenreId)
{
var containsCurrentGenre = await stTrack.GetGenresAsync(int.MaxValue, 0)
.Select(g => g.Name.HashToInt32())
.AnyAsync(g => g == genreId);
if (!containsCurrentGenre && stAlbum != null)
{
// If the track doesn't have the genre, the album might.
containsCurrentGenre = await stAlbum.GetGenresAsync(int.MaxValue, 0)
.Select(g => g.Name.HashToInt32())
.AnyAsync(g => g == genreId);
}
if (!containsCurrentGenre) continue;
}
Schemas.Track track = new(m_dataType)
{
AlbumName = stTrack.Album?.Name,
AlbumLibraryId = stTrack.Album?.Id.HashToInt32() ?? 0,
TitleYomi = stTrack.Name,
ReleaseDate = DateTime.Now,
ZuneMediaId = stTrack.Id.HashToGuid(),
TrackNumber = stTrack.TrackNumber ?? 0,
Duration = stTrack.Duration,
ComponentId = "strix",
FileName = System.IO.Path.GetFileName(stTrack.Id),
FolderName = System.IO.Path.GetDirectoryName(stTrack.Id),
FilePath = stTrack.Id,
NowPlaying = false,
InLibrary = true,
DateLastPlayed = stTrack.LastPlayed ?? DateTime.MinValue,
PlayCount = 0,
FileSize = 0,
ComposerName = null,
ConductorName = null,
IsProtected = 0,
DateAdded = stTrack.AddedAt ?? DateTime.Now,
Bitrate = 0,
MediaType = "track",
DiscNumber = stTrack.DiscNumber ?? 0,
DateAlbumAdded = DateTime.Now,
FileCount = 1L,
DrmState = 0,
DrmStateMask = 0L,
QuickMixState = 0,
LibraryId = stTrack.Id.HashToInt32(),
Title = stTrack.Name,
SyncState = 0,
Type = "track",
DeviceFileSize = 0L,
UserRating = 0,
AlbumArtistName = stAlbumArtist?.Name,
AlbumArtistLibraryId = stAlbumArtist?.Id.HashToInt32() ?? 0
};
var stArtists = stTrack.GetArtistItemsAsync(int.MaxValue, 0);
bool setPrimaryArtist = false;
List<string> contributingArtists = new();
await foreach (var stArtist in stArtists)
{
if (!setPrimaryArtist)
{
track.ArtistLibraryId = stArtist.Id.HashToInt32();
track.ArtistName = stArtist.Name;
track.ArtistNameYomi = stArtist.Name;
setPrimaryArtist = true;
}
else if (!string.IsNullOrEmpty(stArtist.Name))
{
contributingArtists.Add(stArtist.Name);
}
}
track.ContributingArtistCount = contributingArtists.Count;
track.ContributingArtistNames = contributingArtists;
// No artists
if (!setPrimaryArtist)
{
track.ArtistLibraryId = 0;
track.ArtistName = null;
track.ArtistNameYomi = null;
}
var stGenre = await stTrack.GetGenresAsync(1, 0).FirstOrDefaultAsync();
track.Genre = stGenre?.Name;
queryList.Add(track.Item);
}
}
else if (text == "AlbumByTOC")
{
@@ -659,6 +548,8 @@ namespace Microsoft.Zune.Library
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,
@@ -715,6 +606,123 @@ namespace Microsoft.Zune.Library
Result = libraryDataProviderQueryResult;
Status = DataProviderQueryStatus.Complete;
}
private Schemas.Track CreateTrack(ZuneQueryList queryList, )
{
await foreach (var stTrack in stTracks)
{
var stAlbum = stTrack.Album;
var stAlbumArtist = stAlbum != null
? await stAlbum.GetArtistItemsAsync(1, 0).FirstOrDefaultAsync()
: null;
// Handle filters
if (queryType == EQueryType.eQueryTypeTracksForAlbumId)
{
var currentAlbumId = stAlbum?.Id.HashToInt32();
if (currentAlbumId != albumId) continue;
}
else if (queryType == EQueryType.eQueryTypeTracksForAlbumArtistId)
{
var currentAlbumArtistId = stAlbumArtist?.Id.HashToInt32();
if (currentAlbumArtistId != albumArtistId) continue;
}
else if (queryType == EQueryType.eQueryTypeTracksByGenreId)
{
var containsCurrentGenre = await stTrack.GetGenresAsync(int.MaxValue, 0)
.Select(g => g.Name.HashToInt32())
.AnyAsync(g => g == genreId);
if (!containsCurrentGenre && stAlbum != null)
{
// If the track doesn't have the genre, the album might.
containsCurrentGenre = await stAlbum.GetGenresAsync(int.MaxValue, 0)
.Select(g => g.Name.HashToInt32())
.AnyAsync(g => g == genreId);
}
if (!containsCurrentGenre) continue;
}
Schemas.Track track = new(m_dataType)
{
AlbumName = stTrack.Album?.Name,
AlbumLibraryId = stTrack.Album?.Id.HashToInt32() ?? 0,
TitleYomi = stTrack.Name,
ReleaseDate = DateTime.Now,
ZuneMediaId = stTrack.Id.HashToGuid(),
TrackNumber = stTrack.TrackNumber ?? 0,
Duration = stTrack.Duration,
ComponentId = "strix",
FileName = System.IO.Path.GetFileName(stTrack.Id),
FolderName = System.IO.Path.GetDirectoryName(stTrack.Id),
FilePath = stTrack.Id,
NowPlaying = false,
InLibrary = true,
DateLastPlayed = stTrack.LastPlayed ?? DateTime.MinValue,
PlayCount = 0,
FileSize = 0,
ComposerName = null,
ConductorName = null,
IsProtected = 0,
DateAdded = stTrack.AddedAt ?? DateTime.Now,
Bitrate = 0,
MediaType = "track",
DiscNumber = stTrack.DiscNumber ?? 0,
DateAlbumAdded = DateTime.Now,
FileCount = 1L,
DrmState = 0,
DrmStateMask = 0L,
QuickMixState = 0,
LibraryId = stTrack.Id.HashToInt32(),
Title = stTrack.Name,
SyncState = 0,
Type = "track",
DeviceFileSize = 0L,
UserRating = 0,
AlbumArtistName = stAlbumArtist?.Name,
AlbumArtistLibraryId = stAlbumArtist?.Id.HashToInt32() ?? 0
};
var stArtists = stTrack.GetArtistItemsAsync(int.MaxValue, 0);
bool setPrimaryArtist = false;
List<string> contributingArtists = new();
await foreach (var stArtist in stArtists)
{
if (!setPrimaryArtist)
{
track.ArtistLibraryId = stArtist.Id.HashToInt32();
track.ArtistName = stArtist.Name;
track.ArtistNameYomi = stArtist.Name;
setPrimaryArtist = true;
}
else if (!string.IsNullOrEmpty(stArtist.Name))
{
contributingArtists.Add(stArtist.Name);
}
}
track.ContributingArtistCount = contributingArtists.Count;
track.ContributingArtistNames = contributingArtists;
// No artists
if (!setPrimaryArtist)
{
track.ArtistLibraryId = 0;
track.ArtistName = null;
track.ArtistNameYomi = null;
}
var stGenre = await stTrack.GetGenresAsync(1, 0).FirstOrDefaultAsync();
track.Genre = stGenre?.Name;
track.Item.Storage["StrixItem"] = stTrack;
queryList.Add(track.Item);
}
}
}
internal class DeferredSetResultArgs
+22 -3
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);
throw new NotImplementedException();
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,
+10 -1
View File
@@ -465,8 +465,17 @@ 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;
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;
Application.DeferredInvoke(delegate
try
{
if (IsDisposed || myID != _lastKnownSetUriCallID)
return;
var stTrack = ((StrixPlaybackTrack)nextTrack).Track;
PlaybackItem item = ZuneMediaSourceConfig.CreatePlaybackItem(nextTrackUri, track.PlaybackID);
_player.PreloadSync(item);
Application.DeferredInvoke(delegate
{
if (IsDisposed || myID != _lastKnownSetUriCallID)
return;
_tracksSubmittedToPlayer.Remove(nextTrack);
_tracksSubmittedToPlayer.Add(nextTrack);
UpdatePropertiesAndCommands();
}, null);
// Preload track
//AsyncHelper.Run(dataRoot.Library.PlayTrackCollectionAsync(stTrack));
_tracksSubmittedToPlayer.Remove(nextTrack);
_tracksSubmittedToPlayer.Add(nextTrack);
UpdatePropertiesAndCommands();
}, null);
}
catch
{
}
}, null);
}