Client v5: BLE, BLE Hosting, HTTP, Jobs - Linux, MacOS, & Blazor Support! Full AOT, RX on BLE only & MANY other features! Power up!
Getting Started
| GitHub | 👁 GitHub stars for shinyorg/music |
| Downloads | 👁 NuGet downloads for Shiny.Music |
Frameworks
.NET
.NET MAUI
Operating Systems
Android
iOS
Shiny.Music provides a unified API for accessing the device music library on Android and iOS. It supports permission management, querying track metadata, playing music files, and copying tracks (where platform restrictions allow).
Features
Section titled “Features”- Request and check music library permissions on both platforms
- Query all music tracks or search by title, artist, or album
- Browse by genre, year, or decade — each with track counts
- Browse playlists and their tracks
- Filter tracks by any combination of genre, year, decade, and search query via
MusicFilter - Cross-dimensional browsing — genres by decade, years by genre, etc.
- Play, pause, resume, stop, and seek within tracks
- Control playback volume programmatically
- Stream Apple Music subscription tracks via
MPMusicPlayerControlleron iOS - Check for active streaming subscriptions
- Fetch lyrics — plain text and synchronized LRC format via LRCLIB
- Retrieve album artwork as cached file paths
- Copy music files to app storage (non-DRM content only on iOS)
- Event-driven playback state changes and completion notifications
- Manage custom playlists — create, remove, and add tracks via
IMediaLibrary - Track play counts per song via
MusicMetadata.PlayCount
Platform Support
Section titled “Platform Support”| Feature | Android | iOS |
|---|---|---|
| Permission Request | ✅ | ✅ |
| Query Tracks | ✅ | ✅ |
| Search Tracks | ✅ | ✅ |
| Browse by Genre | ✅ | ✅ |
| Browse by Year / Decade | ✅ | ✅ |
| Browse Playlists | ✅ | ✅ |
| Filter by Genre + Year/Decade | ✅ | ✅ |
| Local Playback | ✅ | ✅ (AVAudioPlayer) |
| Streaming Playback | ❌ | ✅ (MPMusicPlayerController via StoreId) |
| Volume Control | ✅ | ✅ |
| Lyrics (Plain + Synced LRC) | ✅ (LRCLIB) | ✅ (LRCLIB + MPMediaItem.Lyrics) |
| Album Art | ✅ (MediaStore) | ✅ (MPMediaItem.Artwork, cached to file) |
| Copy Track | ✅ | ✅ (non-DRM only) |
| Streaming Subscription Check | ❌ (always false) | ✅ (SKCloudServiceController) |
| Explicit Flag | ❌ | ✅ (via MPMediaItem.IsExplicitItem) |
| Custom Playlists | ✅ (local JSON) | ✅ (local JSON) |
| Play Count Tracking | ✅ (local store) | ✅ (MPMediaItem.PlayCount) |
Quick Example
Section titled “Quick Example”publicclassMyPage{readonlyIMediaLibrary_library;readonlyIMusicPlayer_player;readonlyILyricsProvider_lyrics;publicMyPage(IMediaLibrarylibrary, IMusicPlayerplayer, ILyricsProviderlyrics){_library = library;_player = player;_lyrics = lyrics;}asyncTaskPlayFirstTrack(){// 1. Request permissionvarstatus=await _library.RequestPermissionAsync();if (status != PermissionStatus.Granted)return;// 2. Get all tracksvartracks=await _library.GetAllTracksAsync();if (tracks.Count ==0)return;// 3. Play the first trackawait _player.PlayAsync(tracks[0]);// 4. Control volume_player.Volume =0.75f;// 5. Get album artworkvarartPath=await _library.GetAlbumArtPathAsync(tracks[0].Id);// 6. Fetch lyrics (plain or synced LRC)varlyrics=await _lyrics.GetLyricsAsync(tracks[0]);// 7. Listen for completion_player.PlaybackCompleted += (s, e) =>{Console.WriteLine("Track finished!");};}asyncTaskBrowseAndFilter(){// Browse genres with track countsvargenres=await _library.GetGenresAsync();foreach (vargin genres)Console.WriteLine($"{g.Value} ({g.Count} tracks)");// Browse decadesvardecades=await _library.GetDecadesAsync();foreach (vardin decades)Console.WriteLine($"{d.Value}s ({d.Count} tracks)");// Get rock tracks from the 1990svartracks=await _library.GetTracksAsync(newMusicFilter{Genre ="Rock",Decade =1990});// Get genres within the 2000svargenresIn2000s=await _library.GetGenresAsync(newMusicFilter { Decade =2000 });// Browse playlistsvarplaylists=await _library.GetPlaylistsAsync();foreach (varpin playlists)Console.WriteLine($"{p.Name} ({p.SongCount} songs)");// Get tracks in a playlistvarplaylistTracks=await _library.GetPlaylistTracksAsync(playlists[0].Id);}}Samples
Section titled “Samples”AI Coding Assistant
Section titled “AI Coding Assistant”Step 1 — Add the marketplace:
claude plugin marketplace add shinyorg/skills Step 2 — Install the plugin:
claude plugin install shiny-client@shiny Step 1 — Add the marketplace:
copilot plugin marketplace add https://github.com/shinyorg/skills Step 2 — Install the plugin:
copilot plugin install shiny-client@shiny 