arlodotexe / strix-music Goto Github PK
View Code? Open in Web Editor NEWCombine any music sources into a single library. It's your music. Play it your way.
Home Page: http://www.strixmusic.com
Combine any music sources into a single library. It's your music. Play it your way.
Home Page: http://www.strixmusic.com
The Zune settings created very early in development, before we had a good handle on architecture. We've learned the hard way to just put View code in the control code-behind, instead of trying to put View code in a ViewModel.
In StrixMusic.Shells.ZuneDesktop.Controls.Views.Settings
, the SettingsView
is doing a couple of strange things that need to be cleaned up or removed:
ZuneDesktopSettingsViewModel
and move code into the SettingsView
control.ZuneDesktopSettings
directly. This uses OwlCore's SettingsBase
, which implements INPC for settings already, so we can just bind to the properties.SaveAsync
in property setters.SaveClicked
event handler, call SaveAsync()
on ZuneDesktopSettingsCancelClicked
event handler, call the LoadAsync()
method on ZuneDesktopSettings to reload the persisted values into memory and overwrite unsaved changes.I just cloned the repo and installed the app for the first time, but whenever I go through the OOBE and set up a new core, the core remains unloaded and the app remains on its splash screen indefinitely. Checking the logs and stepping through with a debugger reveals that the SDK version compatibility check fails on a freshly created core.
The check is performed by MergedCore
's constructor:
strix-music/src/Sdk/StrixMusic.Sdk/AdapterModels/MergedCore.cs
Lines 42 to 43 in 5663129
Somehow the core metadata's SdkVer
is set to 0.0.0.0
, while the current SDK version is 0.0.2.0
.
No response
1. Install and launch app
2. Set up local files core
3. Relaunch app
4. Observe that app gets stuck on loading screen, with local files core on "Unloaded"
No response
The SDK version specified in core metadata should match the version of the SDK it is dependent on.
No response
Yes, but only if others can assist.
The AdapterModel layer is where we merge many CoreModel instances into a single AppModel instance.
To decide the order of sources that we pull data from for merged collections, we use the CoreRanking, which is an ordered list of the instance IDs for all possible sources.
The first item in the list is the most preferred, the last item in the least.
The ranking is non-configurable. It's decided by the order which a core was registered - with no way for the user to rearrange it.
We need to:
CoreManagementService
.
InitializeCoreRankingAsync
out of AppLoadingView.xaml.cs
.AppSettings
.I've recently upgraded to Window 11, and after trying to load the app and test out a PR, I was met with an UnauthorizedAccessException
for my personal music library, which was stored on a hard drive. Unblocking the files had no effect.
No response
Since I'm not sure what caused this, I'm not sure how to reproduce it on another machine. Since it's my own machine, I can fix it myself.
No response
App should not crash when it encounters a file it can't read.
No response
Yes, I'd like to be assigned to work on this item.
Currently there is no way to handle the DP property changed events on the Collection/Item dependency property on the following essential SDK classes (there maybe more classes with similar situations):
Since DPs cannot be virtual they cannot be overridden like normal properties , to achieve this currently we are (kind of) overriding the existing DP properties using the new
keyboard which hides the parent DP and is not an ideal way to do it.
To fix this each base class DP should provide virtual callback of the Dependency property, in this way this callback can be overriden by shells without hiding the base class DPs using the new
keyword
No response
No response
No response
When you scan an album with multiple discs to it, they appear in the UI sorted by track number, but not grouped by disc number.
No response
1. Setup a file based core
2. Point it to an album with multiple discs
3. When the data is output to the UI, it's sorted by track number with no regard to disc number.
Track order should be grouped by disc number
No response
The PlaybackHandlerService
requires an implementation of IAudioPlayerService
to do local playback. In the App, we have an implementation called AudioPlayerService
which is built to wrap around a MediaPlayerElement
.
IAudioPlayerService
should support preloading track data to allow for instant playback.
This hasn't been implemented but should be possible via MediaSource.OpenAsync()
.
Make sure to test that this method actually works, and find a different way if not.
The Basic Usage docs are missing a required step for using MergedCore
.
The user needs to initialize the CoreRanking
property on the MergedCollectionConfig
before they can use it. This doesn't seem to be documented anywhere.
From Discord:
The FileMetadataManager
and AudioMetadataScanner
currently have a dependency on INotificationService
.
This forces all file-based core to also have a dependency on it, which is inconvenient for consumers of file-based cores to have to implement.
For all classes in the StrixMusic.Sdk.FileMetadata
namespace, remove any dependencies on INotificationService
and trade it for normal events where needed.
Since the project started, a number of TODO comments were left around the app.
Issues have been filed for all TODOs that are still valid, but there's a number of TODOs which are outdated or no long applicable.
Find and remove the invalid TODO comments.
When the CI compiles the Strix Music app in release mode, there's a high chance that release mode will fail and need to be rerun. The error message is:
Generating native code
Launching 'C:\Users\VssAdministrator.nuget\packages\runtime.win10-arm.microsoft.net.native.compiler\2.2.7-rel-27913-00\tools\ARM\ilc\Tools64\nutc_driver.exe @"D:\a\1\s\src\Platforms\StrixMusic.UWP\obj\ARM\Release\ilc\intermediate\MDIL\StrixMusic.rsp"'##[error]C:\Users\VssAdministrator.nuget\packages\microsoft.net.native.compiler\2.2.7-rel-27913-00\tools\Microsoft.NetNative.targets(801,5): Error : Internal Compiler Error
C:\Users\VssAdministrator.nuget\packages\microsoft.net.native.compiler\2.2.7-rel-27913-00\tools\Microsoft.NetNative.targets(801,5): error : Internal Compiler Error [D:\a\1\s\src\Platforms\StrixMusic.UWP\StrixMusic.UWP.csproj]
##[error]C:\Users\VssAdministrator.nuget\packages\microsoft.net.native.compiler\2.2.7-rel-27913-00\tools\Microsoft.NetNative.targets(801,5): Error : ILT0005: 'C:\Users\VssAdministrator.nuget\packages\runtime.win10-arm.microsoft.net.native.compiler\2.2.7-rel-27913-00\tools\ARM\ilc\Tools64\nutc_driver.exe @"D:\a\1\s\src\Platforms\StrixMusic.UWP\obj\ARM\Release\ilc\intermediate\MDIL\StrixMusic.rsp"' returned exit code 1
1>C:\Users\VssAdministrator.nuget\packages\microsoft.net.native.compiler\2.2.7-rel-27913-00\tools\Microsoft.NetNative.targets(801,5): error : ILT0005: 'C:\Users\VssAdministrator.nuget\packages\runtime.win10-arm.microsoft.net.native.compiler\2.2.7-rel-27913-00\tools\ARM\ilc\Tools64\nutc_driver.exe @"D:\a\1\s\src\Platforms\StrixMusic.UWP\obj\ARM\Release\ilc\intermediate\MDIL\StrixMusic.rsp"' returned exit code 1 [D:\a\1\s\src\Platforms\StrixMusic.UWP\StrixMusic.UWP.csproj]
Done Building Project "D:\a\1\s\src\Platforms\StrixMusic.UWP\StrixMusic.UWP.csproj" (default targets) -- FAILED.
Build locally in release mode and find/fix the cause of the build error. Use Visual Studio and set the build output level to at least "Detailed" to get the most useful information.
Cores that are based on StrixMusic.Cores.Storage
do not fully handle when files are added / removed while the app is running.
FileMetadataManager
and handle the changes appropriatelyWhen we created the model plugins, we wrote a ton of unit tests. I mean an overkill number of tests, in the unit of thousands of tests after all combinations were run.
The testing of all the different possible combinations for plugin models was done by using enum flags, allowing us to feed every combination to the same unit test method.
We made sure the correct underlying plugin was accessed using a bit of reflection to get the relevant properties, throwing an AccessedException{T}
, catching it and making sure the T
(which is always the containing class) was what we expected.
I created the model plugins on a single machine, running Windows 10 21H2 (Build 19044) and Visual Studio 2022 17.1.6.
For some reason, a select number of these tests simply fail when using other machines.
The reason why isn't clear, but it's something we need to fix
Most playlist formats specify a list of URIs to music streams. In most cases, these URIs will be to local files the core already has in its track repository, but some formats allow links to external resources. For example, the HLS streaming extension for M3U/M3U8 uses https://
URIs to link to segments of a streamed track on the web. This feature is essential for supporting certain streaming services, such as Soundcloud.
The initial implementation of PlaylistScanner
used helper methods designed to handle this transparently and gracefully, but it appears that at some point the code was refactored incompletely. The initial design used a few helper methods in PlaylistMetadataScanner
, exposed by ResolveFilePath(string path, string currentPath)
. The sole purpose of this method was to get a full, absolute path given the current path. This was necessary because playlists often specify paths relative to the playlist file's location, so the path would have to expanded in order for the file to be played. At some point, the TryGetHashFromExistingTracks(Uri path, IEnumerable<Models.FileMetadata?> files)
helper was added, which checks the list of files for one with a matching path. This means that all external/web resources will be rejected, because the audio metadata scanner could not have found it. (The same applies to local audio files outside the directory specified by the local files core, though that is a much more complicated issue because the core does not have immediate access to the file, unlike web resources that can easily be acquired.)
The new checks also have been applied inconsistently. For example, some parser methods use only TryGetHashFromExistingTracks
, others use the old ResolveFilePath
, while still others use the result of ResolveFilePath
and pass that to TryGetHashFromExistingTracks
.
pre-alpha
I don't think a specific repro is useful here, but in general any `https://` URLs in a playlist will be considered invalid and ignored.
No response
PlaylistMetadataScanner
should be able to recognize and handle external but still accessible resources, not only local and already scanned files.
No response
Yes, I'd like to be assigned to work on this item.
The recent feature implemented in #101 has caused a styling issue in the app. Track names get cut off at some window sizes.
0.0.4
1. Set up the app with any core that has tracks
2. Using the Zune Desktop shell, navigate to the Collection.
3. Resize the window and observe that the track names only take up 50% of their respective column.
The track name should be visible.
No response
No, I'm unable to contribute a solution.
In the Zune Desktop skin, we have a custom ZuneAlbumCollection
that takes an IAlbumCollectionViewModel
and displays them to the user.
There's also a button on each album that play the album when clicked. This button is on the ZuneAlbumItem
, and when clicked, the control emits a AlbumPlaybackTriggered
event.
The ZuneAlbumCollection
listens for this event on each album, and when fired, plays the clicked album in the context of the IAlbumCollectionViewModel
.
We're listening for the AlbumPlaybackTriggered
event in a way that doesn't play nicely with the UI framework.
When the control is loaded, and again as needed when the Albums
collection is changed, we're getting the ZuneAlbumItem
control directly from the templated ItemsControl using the index, then attaching to the AlbumPlaybackTriggered
event.
This results in the following issues:
The proposed solution uses loose data coupling by wrapping each templated model in a custom ViewModel and wiring the events together.
This approach means events can be set up for every item in the ZuneAlbumCollection
, and invoked by the ZuneAlbumItem
only when/if the control is loaded and the button is clicked.
The "Artists" section in Zune Desktop is the default view when opening the Collection tab.
Implementation of this view in Strix is incomplete.
Finish implementing this view, making sure it's faithfully matches the original app.
If you don't have the original app, the installer that we use is available here.
The AudioMetadataScanner performs image processing as part of its scan, taking care of linking and re-emitting image IDs to known metadata.
When processing is complete, image files are stored in an AbstractStorage folder, the CacheFolder
property. When using the scanner, it will crash if you don't set this property, and we don't provide a way to set it without using a FileMetadataManager
.
ImageOutputFolder
.All classes used internally in the PlaybackHandlerPlugin
should be marked as internal
, but StrixDataRootPlaybackHandlerPlugin
is marked as public
.
The result is that this type is visible in docs when it doesn't need to be (permalink):
No response
N/a
No response
All classes used internally in the PlaybackHandlerPlugin
should be marked as internal
No response
Yes, I'd like to be assigned to work on this item.
In Zune shell there is a feature where an additional artists column is shown alongside track list which actually includes all the artists involved in the making of the tracks.
If the whole collection has only 1 artist the column isn't shown at all, but if it has more than one artists on the TrackCollection an additional column is shown with all the artists.
Currently its not happening, no matter what AlbumCollection you select it doesn't display any additional artists because the AlbumCollection doesn't have more than one artist to show against a track.
Helping Info:
The shell has also subscribed the ArtistItemsCountChanged
on the track but SDK doesn't notify about any new artists during scan.
No response
1. Launch the app.
2. Go to the collections
3. Select an album collection whom you think has should have more than one artists.
The list of artists should be shown.
No response
No, I'm unable to contribute a solution.
Needs to match IAppModel
, as well as mapping with our AppModel/CoreModel architecture labels.
Right now, when the app is starting up, we display "Quips". These are witty remarks that change depending on language, time of day or year, region, etc., and are meant to entertain the user briefly while the app loads.
Seasonable quips are based on the current date, but these are based on the dates seasons stop and start for the northern hemisphere. In the sourthern hemisphere, the dates that seasons start and stop are different, meaning anyone using the app in the southern hemisphere will see quips for the wrong season.
The changelogs are adding all previous release tags under the title.
From here:
We need to:
The AdapterModel layer is where we merge many CoreModel instances into a single AppModel instance.
There are 2 major parts to this:
Right now, we're simply selecting the first source in the CoreRanking. This ranking is used to decide the order we pull items from for sources in merged collections.
However, we've also been using it to assume that the first source is the preferred source, and we've been using that for property values in models that have been merged.
We can do better.
There's a few ways we could improve this:
For now, let's use option 1. Option 2 will need separate issue and discussion to fully flesh out, as it could bleed into the conversation about customizing how sources are merged.
MergedCollectionConfig
should contain:
ICore
for the preferred source.To understand this issue, you'll need an understanding of how we structure data in the SDK.
By default, the data from databases, APIs (like Spotify or Deezer), file systems, and backends in general, are always:
These properties are intrinsic of every object-oriented data structure, spanning from JSON to SQL to XML to C# objects.
Far too often, one or more of these things are lost due to limitations of the architecture built to interact with it.
In order to maintain these things throughout the entire SDK and all apps built on it, we had to conceptualize a new architectural pattern:
This concept can be applied to any application which is powered by a structured graph of data.
In the Strix SDK, our AppModels are much more complicated than this, as we're doing some complicated things. Our model layers include:
The PluginModels
and ViewModels
wrap around implementations of AdapterModels
The AdapterModels
wrap around one or more implementations of CoreModels
.
The CoreModels
wrap whatever code is needed to interact with the music source.
When we created the model plugins, we wrote a ton of unit tests. I mean an overkill number of tests, in the unit of thousands of tests after all combinations were run.
The testing of all the different possible combinations for plugin models was done by using enum flags, allowing us to feed every combination to the same unit test method.
We made sure the correct underlying plugin was accessed using a bit of reflection to get the relevant properties, throwing an AccessedException{T}
, catching it and making sure the T
(which is always the containing class) was what we expected.
An understanding of our data layers and model plugins is required to solve this issue.
At some point after we implemented model plugins in the app, the DisposeAsync()
method began to hang when a model plugin was between us and the AdapterModels.
When we tried to "disconnect" the core from the UI, it was unregistered, removed as a source where needed in the AdapterModels layer, and the DisposeAsync()
method was called to clean up unmanaged resources used by the core (such as open network connections)
After brief debugging, I found that it was still calling the underlying methods, making it all the way to the relevant cores, but the task still just kinda hangs there.
We had trouble consistently reproducing it, but we modified the DisposeAsync() logic slightly and added more unit tests. But though it briefly worked and the tests passed, the issue wasn't actually fixed.
Here's what needs to be done:
In our Pledges, we promised:
The entire project (docs, website, build process, dependencies, SDK, app, etc) are perpetually preserved in every released binary and on our website, all hosted on IPFS. If anyone has these things, you'll be able to access it over IPFS
In order to do this, we need to create build scripts that can perform all of our CI standalone, and put them in the repo.
Create powershell scripts that can
An InvalidCastException
is thrown when loading the Zune Desktop shell with the debugger attached.
This issue occurs on startup. To the user, there is no regression as a result of the exception, and it does not take down the app when thrown.
Steps to repro
Attempting to cancel the setup of a new core during the OOBE causes the app to crash with a TaskCanceledException
.
No response
1. Open a fresh install of Strix Music
2. In the Services tab of the OOBE, add a OneDrive core
3. Click "OK"
4. Click "Cancel"
5. Observe app crash
No response
The OOBE should gracefully cancel setup of the selected core.
No response
Yes, but only if others can assist.
The MergedSearch
, MergedSearchResults
, MergedSearchQuery
, and MergedSearchHistory
classes are all of our Search components in the AdapterModels layer.
These models are implemented, but have some lingering TODOs and needs both unit tests and to be tested with real data from multiple cores.
If you have multiple cores, you cannot disconnect any of them.
0.0.2
1. Open the strix music app
2. Set up multiple cores
3. Try to remove one by disconnecting it
4. Observe the missing disconnect button
Should be able to disconnect
No response
Yes, I'd like to be assigned to work on this item.
There's a lot of async methods in the SDK's ViewModel that uses SynchronizationContext.Post()
. This method only supports an Action, and does not wait for an async lambda to complete. The result is that the public SDK method's Task completes before execution is actually finished.
No response
Run an async method such as LibraryViewModel.InitTrackCollectionAsync(). When the task completes, the tracks will not be populated.
No response
The task should not complete until all code has finished running.
No response
Yes, I'd like to be assigned to work on this item.
The PlaybackHandlerService
is a class which
IAudioPlayerService
for playback, or the source core for remote playback.StrixDevice
, an IDevice
which turns the playback handler into a useable SDK device.When implementing this, most of our testing was done against the PreviousAsync
and NextAsync
methods. The PlayFromPrevious
and PlayFromNext
methods were largely neglected.
In both methods, we need to
CurrentItemChanged
, NextItemsChanged
, etc)The AudioMetadataScanner
is responsible for scanning a folder for audio files, then scanning those files for audio metadata.
The PlaylistMetadataScanner
is responsible for scanning a folder for playlist files, then scanning those files for playlist metadata.
The FileMetadataManager
is responsible for managing the metadata scans of both audio and playlist files, then holding the data in memory and persisted to disk in "repositories".
These things have a pretty clear separation of concerns. FileMetadataManager
internally uses AudioMetadataScanner
and PlaylistMetadataScanner
to scan files.
However, the scanners also take on a dependency of FileMetadataManager
. It appears that this is currently being used to get scan type settings and update the number of files or folders scanned.
These are trivial things that don't require a full dependency on FileMetadataManager
. Instead, let's:
In the Strix Music SDK, all image (interfaces inheriting from IImageBase
) uses a Uri to provide images.
Unlike most of the data in the SDK, images are not raw data. Similar to an audio stream, it is a resource.
As part of the standard, with the exception of things that self-classify as an external resource (UriCollection
), all data should be provided directly from the cores as data, instead of using Uris to point to the resource elsewhere.
There's a number of reasons for not using Uris:
Change IImageBase to use Stream
instead of Uri
.
OpenStreamAsync
method that returns a Task<Stream>
The Strix Music SDK, while well architectured, is no simple thing. We have several explainers for the most essential things devs should know about in our documentation.
There's plenty of code and screenshots in the docs, but no visual aids to help simplify things.
A couple of charts helping explain some of the hard parts would go a long way for new devs who are just onboarding and getting a feel for things.
In the docs, particularly in places where it gets complicated - paragraphs of text, sets of bullet points - we should create a graph explaining the relations between all the things being discussed.
The How it works section is a good example of this.
The Home page is another that could make great use of this.
Ideally, charts should be exported as SVGs and stored somewhere we can edit it, if needed.
LucidChart should be able to do one or both of these
The PlaylistMetadataScanner
is used to scan files for playlist metadata, and link the tracks to known audio metadata found by AudioMetadataScanner
.
This is implemented, but has some lingering TODOs, needs unit tests, and needs to be tested with real data.
The scanner is built to work with a lot of different playlist types, and we need to make sure they all work as expected.
The SuperShell is a UI that sits on top of all other shells, and is where the user configures shells, services, and more. The SuperShell allows for configuring that app, so it was used as a temporary OOBE.
The SuperShell is not designed to provide a cohesive first-time experience for new users.
We need to design and implement a new out of box experience.
No work has been done on this yet, but we can easily lay some guidelines to follow:
Audio files usually have 2 different kinds of artists:
In #106, we added support for returning multiple artists from a scanned files, but we didn't properly distinguish between Album Artist and Performer. Instead, they're mashed together and all listed as Album artists.
0.0.2-app-alpha
1. Set up a files core (either local files or OneDrive, anything that uses AudioMetadataScanner)
2. Make sure to add audio files where songs have different song artists than the album artist
3. Open the app and let it scan the files
4. Observe the bug as the artist list loads. Performers show as album artists.
Visually, the bug manifests as this:
Song artists should only exist on tracks, not as individual artists who have released entire albums.
No response
In large part, the metadata scanners in the namespace StrixMusic.Sdk.FileMetadata.Scanners
were created by many devs collectively, with loose coordination from @Arlodotexe.
Because of the way we developed this, we ran into a few unexpected problems in our first pass, namely that events were firing so quickly and so often that it overloaded the GC and caused the UI to be unresponsive when the debugger was attached, even when running in a background thread (all threads pause before GC can do cleanup).
We solve this by batching results on an event handler, then returning all the scanned metadata as an IEnumerable.
This API surface can be dramatically improved. Instead of using a Task that contains an IEnumerable of all the metadata, we should be using IAsyncEnumerable and returning the metadata as it's scanned.
This applies to both PlaylistMetadataScanner and AudioMetadataScanner.
We'll also need to evaluate what this means for file-based cores, and if it can be applied throughout the codebase so that each song appears in the UI as it's scanned, without overloading the GC.
Right now, when the app is starting up, we display "Quips". These are witty remarks that change depending on language, time of day or year, region, etc., and are meant to entertain the user briefly while the app loads.
The startup process in the app is a rather complicated one. It would be useful, or at least more entertaining to our advanced users, to have a debug mode which displays log messages while starting up.
AppLoadingView.xaml
, display output from the logger either alongside or instead of quips.Designs can be proposed and discussed below or in the PR, if needed ๐
This issue is reserved for future use
The MergedCollectionMap
is a class which contains all of our logic for merging collections together.
It's a very important part of the AdapterModel layer, where we merge many CoreModel instances into a single AppModel instance.
The existing code for this was created in Nov 2020, and while it mostly works, after using it for a while we've found some improvements that need to be made.
ITrackCollection
, IAlbumCollection
, IImageCollection
, etc.ILibrary
, IArtist
or ITrack
implement more than one collection interface.The follow are notes from a brainstorm session between @Arlodotexe and @amaid on how to best handle the issues that arise from merging multiple collections into one collection.
CoreModels and AppModels were split into 2 clearly distinct API surfaces early in development. Though the data structure is nearly identical, AppModels have some inherent differences that required them to be separate from CoreModels.
The reasons for this boil down to:
In AppModels, interfaces like IAlbum
, IArtist
, IPlaylist
, ISearch
, and ITrack
all contain some property that is nullable, such as SearchHistory or RelatedItems.
This matches what's found in the CoreModels. Cores either do or do not supply this information, so there is no need for events to know if these properties change in CoreModels.
This data may not change in a core, but since AppModels are merged, the data can change there if you add a new source with a non-null value.
We don't have any events in the AppModels that help us propagate changes for these nullable properties. We need to add them to the interfaces and all implementations (AdapterModels, PluginModels, ViewModels)
In the original Zune app that the Zune Desktop skin was based on (version 4.8), pressing the back button would navigate you back to the most recent top-level component (Quickplay, Collection & collection tabs, Settings & settings tabs).
The Zune Desktop skin only closes the settings view and does not do any dynamic back navigation
Implement dynamic back navigation on the Zune Desktop skin to match the behavior of the original app.
If you don't have the original app, the installer that we use is available here.
OwlCore.Remoting is a lightweight RPC framework that works anywhere .NET Standard 2.0 is supported.
The framework was originally created for 2 purposes: Synchronizing UI between devices and enabling remote execution of code that is sideloaded in another application, in another process or running on another machine.
Work on this was started here, but had to be paused to focus on other parts of the SDK so we could open source on time. This includes both implementation and unit tests.
Since cores have all the members needed to know when data is changed, we can create a super clean API surface that looks roughly like this:
// Machine/Process 1- "Host" who has the running code
var core = new LocalFilesCore(folderData, config);
var host = new RemoteCore("myUniqueId", core, messageHandler);
// Machine/Process 2 - "Client" who doesn't have the running code
var client = new RemoteCore("myUniqueId", messageHandler);
// When calling a method on the client, it uses RPC calls to get the data from the host core.
var items = await client.Library.GetTracksAsync(5, 5).ToListAsync();
// The host uses RPC calls to notify the client about events and property changes.
client.Library.TotalTrackCountChanged += (s, e) => { ... };
Todo list
RemoteNotificationsService
)Cores that are based on StrixMusic.Cores.Files
do not fully handle removing music from your library when the underlying files are removed from disk.
FilesCore
that mock the data and allow us to test that this works (may need to create a new test project)M3U playlists containing empty lines throw an IndexOutOfRangeException
at the following line when attempting to parse.
This should be a simple fix, there just needs to be a case for skipping the current line if it has zero length or is empty/whitespace.
I suspect there's a larger issue with error handling, as currently the problematic playlist causes the playlist scanner to halt as well, even if there are other valid playlists to scan.
No response
1. Create an M3U playlist and add an empty line anywhere in the file
2. Attempt to load said playlist into Strix Music
3. Observe an `IndexOutOfRangeException` in the log output, and the playlist scanner halting
No response
Playlist parses ignores empty lines.
No response
Yes, I'd like to be assigned to work on this item.
The StrixDevice
is an IDevice
which turns the information in a playback handler into a useable SDK device. This is largely used for controlling local audio playback.
There are 2 types of queues in the SDK:
IDevice
, which is a standard ITrackCollection
.While StrixDevice
is mostly implemented, the PlaybackQueue isn't. That means the user can neither see the actual queue nor modify it when playback is local.
We need to:
ITrackCollection
, call it something like StrixPlaybackQueueCollection
.PlaybackHandlerService
.Sources
property contains references to cores for all items in the collection.
SourceChanged
event when this list is changed (as needed)Right now, when you call InitAsync()
on a file-based core (OneDrive, LocalFilesCore), the task completes before the core has a chance to scan audio files for metadata, meaning the core appears to not have any data.
Worse, even if a dev knows this, there's no reliable way for them to know when data becomes available, short of hooking into every event in the ILibrary
.
We need to fix this in a way to doesn't break the CoreModel standard. Waiting for this shouldn't require locating an extra property, or subscribing to some event, that doesn't exist on the ICore
interface.
Instead, we can add a FileScanBehavior
enum:
namespace StrixMusic.Cores.Files;
/// <summary>
/// The wait behavior of <see cref="IAsyncInit.InitAsync"> on a file-based <see cref="ICore"/> relative to the metadata scanner.
/// </summary>
public enum InitAsyncScannerBehavior
{
/// <summary>
/// <see cref="IAsyncInit.InitAsync"> will only wait for the scanner to complete if it there's no cached scan data.
/// </summary>
WaitIfNoData,
/// <summary>
/// <see cref="IAsyncInit.InitAsync"> will always wait for the scanner to complete.
/// </summary>
AlwaysWait,
/// <summary>
/// <see cref="IAsyncInit.InitAsync"> will never wait for the scanner to complete.
/// </summary>
NeverWait
}
This should be exposed as a property or on the constructor, with WaitIfNoData
as the default value, and InitAsync on each file-based core respecting the option.
No response
No response
No response
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.