From 81564ea0fb7bee590822b30f8f202d1afaf8e69e Mon Sep 17 00:00:00 2001
From: Tristan Roux
Date: Tue, 23 Apr 2019 21:29:47 +0200
Subject: [PATCH] Adding playlists track support for arbitrary song lists.
Reworking home.
---
Opus/Code/Api/LocalManager.cs | 4 +-
Opus/Code/Api/PlaylistManager.cs | 12 +--
Opus/Code/Api/Services/MusicPlayer.cs | 2 +-
Opus/Code/Api/SongManager.cs | 59 +++++++++++++-
Opus/Code/Api/YoutubeManager.cs | 4 +-
Opus/Code/UI/Adapter/HomeAdapter.cs | 2 +-
Opus/Code/UI/Adapter/PlaylistTrackAdapter.cs | 32 +++++---
Opus/Code/UI/Fragments/Home.cs | 84 ++++++++++----------
Opus/Code/UI/Fragments/PlaylistTracks.cs | 42 +++++-----
9 files changed, 155 insertions(+), 86 deletions(-)
diff --git a/Opus/Code/Api/LocalManager.cs b/Opus/Code/Api/LocalManager.cs
index 251e741..f679501 100644
--- a/Opus/Code/Api/LocalManager.cs
+++ b/Opus/Code/Api/LocalManager.cs
@@ -125,7 +125,7 @@ namespace Opus.Api
while (MusicPlayer.instance == null)
await Task.Delay(10);
- MusicPlayer.instance.AddToQueue(songs.ToArray());
+ MusicPlayer.instance.AddToQueue(songs);
}
///
@@ -199,7 +199,7 @@ namespace Opus.Api
MusicPlayer.currentID = startingPosition;
Queue.instance?.RefreshCurrent();
Player.instance?.RefreshPlayer();
- MusicPlayer.instance.AddToQueue(tracks.GetRange(startingPosition, tracks.Count - startingPosition).ToArray());
+ MusicPlayer.instance.AddToQueue(tracks.GetRange(startingPosition, tracks.Count - startingPosition));
}
#endregion
diff --git a/Opus/Code/Api/PlaylistManager.cs b/Opus/Code/Api/PlaylistManager.cs
index 999453e..671a35f 100644
--- a/Opus/Code/Api/PlaylistManager.cs
+++ b/Opus/Code/Api/PlaylistManager.cs
@@ -70,7 +70,7 @@ namespace Opus.Api
MusicPlayer.currentID = startingPosition;
Queue.instance?.RefreshCurrent();
Player.instance?.RefreshPlayer();
- MusicPlayer.instance.AddToQueue(tracks.GetRange(startingPosition, tracks.Count - startingPosition).ToArray());
+ MusicPlayer.instance.AddToQueue(tracks.GetRange(startingPosition, tracks.Count - startingPosition));
}
///
@@ -98,7 +98,7 @@ namespace Opus.Api
MusicPlayer.currentID = startingPosition;
Queue.instance?.RefreshCurrent();
Player.instance?.RefreshPlayer();
- MusicPlayer.instance.AddToQueue(tracks.GetRange(startingPosition, tracks.Count - startingPosition).ToArray());
+ MusicPlayer.instance.AddToQueue(tracks.GetRange(startingPosition, tracks.Count - startingPosition));
}
#endregion
@@ -135,7 +135,7 @@ namespace Opus.Api
while (MusicPlayer.instance == null)
await Task.Delay(10);
- MusicPlayer.instance.AddToQueue(tracks.ToArray());
+ MusicPlayer.instance.AddToQueue(tracks);
}
///
@@ -157,7 +157,7 @@ namespace Opus.Api
tracks.RemoveAt(playPos);
tracks = tracks.OrderBy(x => r.Next()).ToList();
- MusicPlayer.instance.AddToQueue(tracks.ToArray());
+ MusicPlayer.instance.AddToQueue(tracks);
}
#endregion
@@ -187,7 +187,7 @@ namespace Opus.Api
}
List tracks = await GetTracksFromLocalPlaylist(LocalID);
- MusicPlayer.instance.AddToQueue(tracks.ToArray());
+ MusicPlayer.instance.AddToQueue(tracks);
}
///
@@ -202,7 +202,7 @@ namespace Opus.Api
return;
}
- MusicPlayer.instance.AddToQueue((await GetTracksFromYoutubePlaylist(YoutubeID)).ToArray());
+ MusicPlayer.instance.AddToQueue((await GetTracksFromYoutubePlaylist(YoutubeID)));
}
#endregion
diff --git a/Opus/Code/Api/Services/MusicPlayer.cs b/Opus/Code/Api/Services/MusicPlayer.cs
index dc8202e..1769a3b 100644
--- a/Opus/Code/Api/Services/MusicPlayer.cs
+++ b/Opus/Code/Api/Services/MusicPlayer.cs
@@ -868,7 +868,7 @@ namespace Opus.Api.Services
}
}
- public async void AddToQueue(Song[] songs)
+ public async void AddToQueue(IEnumerable songs)
{
queue.AddRange(songs);
Home.instance?.RefreshQueue();
diff --git a/Opus/Code/Api/SongManager.cs b/Opus/Code/Api/SongManager.cs
index c29d52b..2960f1c 100644
--- a/Opus/Code/Api/SongManager.cs
+++ b/Opus/Code/Api/SongManager.cs
@@ -1,4 +1,9 @@
-using Opus.DataStructure;
+using Opus.Api.Services;
+using Opus.DataStructure;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
namespace Opus.Api
{
@@ -39,5 +44,57 @@ namespace Opus.Api
else
YoutubeManager.PlayLast(item);
}
+
+ ///
+ /// Play a list of song in it's default order
+ ///
+ ///
+ public async static void PlayInOrder(List items)
+ {
+ Play(items[0]);
+ items.RemoveAt(0);
+
+ await Task.Delay(1000);
+
+ while (MusicPlayer.instance == null)
+ await Task.Delay(10);
+
+ MusicPlayer.instance.AddToQueue(items);
+ }
+
+ ///
+ /// Play a list of song in a random order
+ ///
+ ///
+ public async static void Shuffle(List items)
+ {
+ Random r = new Random();
+ items = items.OrderBy(x => r.Next()).ToList();
+
+ Play(items[0]);
+ items.RemoveAt(0);
+
+ await Task.Delay(1000);
+
+ while (MusicPlayer.instance == null)
+ await Task.Delay(10);
+
+ MusicPlayer.instance.AddToQueue(items);
+ }
+
+ ///
+ /// Add a list of songs in the queue
+ ///
+ ///
+ public static void AddToQueue(List items)
+ {
+ if(MusicPlayer.instance == null || MusicPlayer.queue == null || MusicPlayer.queue.Count == 0)
+ {
+ PlayInOrder(items);
+ return;
+ }
+
+ MusicPlayer.instance.AddToQueue(items);
+ }
}
}
\ No newline at end of file
diff --git a/Opus/Code/Api/YoutubeManager.cs b/Opus/Code/Api/YoutubeManager.cs
index 49433ef..afef28c 100644
--- a/Opus/Code/Api/YoutubeManager.cs
+++ b/Opus/Code/Api/YoutubeManager.cs
@@ -330,7 +330,7 @@ namespace Opus.Api
while (MusicPlayer.instance == null)
await Task.Delay(100);
- MusicPlayer.instance.AddToQueue(tracks.ToArray());
+ MusicPlayer.instance.AddToQueue(tracks);
MainActivity.instance.ShowPlayer();
Home.instance?.RefreshQueue();
Queue.instance?.Refresh();
@@ -376,7 +376,7 @@ namespace Opus.Api
while (MusicPlayer.instance == null)
await Task.Delay(10);
- MusicPlayer.instance.AddToQueue(songs.ToArray());
+ MusicPlayer.instance.AddToQueue(songs);
}
#endregion
diff --git a/Opus/Code/UI/Adapter/HomeAdapter.cs b/Opus/Code/UI/Adapter/HomeAdapter.cs
index 543f99f..68d3501 100644
--- a/Opus/Code/UI/Adapter/HomeAdapter.cs
+++ b/Opus/Code/UI/Adapter/HomeAdapter.cs
@@ -82,7 +82,7 @@ namespace Opus.Adapter
position = holder.AdapterPosition;
MainActivity.instance.contentRefresh.Refresh -= Home.instance.OnRefresh;
Home.instance = null;
- //MainActivity.instance.SupportFragmentManager.BeginTransaction().Replace(Resource.Id.contentView, PlaylistTracks.NewInstance(items[position].contentValue, items[position].SectionTitle)).AddToBackStack(null).Commit();
+ MainActivity.instance.SupportFragmentManager.BeginTransaction().Replace(Resource.Id.contentView, PlaylistTracks.NewInstance(items[position].contentValue, items[position].SectionTitle)).AddToBackStack(null).Commit();
};
}
diff --git a/Opus/Code/UI/Adapter/PlaylistTrackAdapter.cs b/Opus/Code/UI/Adapter/PlaylistTrackAdapter.cs
index 7c404cd..be94877 100644
--- a/Opus/Code/UI/Adapter/PlaylistTrackAdapter.cs
+++ b/Opus/Code/UI/Adapter/PlaylistTrackAdapter.cs
@@ -53,26 +53,27 @@ namespace Opus.Adapter
public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
{
+ System.Console.WriteLine("&Binding at " + position);
+ System.Console.WriteLine("&ItemCount " + ItemCount);
+ System.Console.WriteLine("&ItemBefore " + ItemBefore);
+ System.Console.WriteLine("&ItemAfter " + ItemAfter);
+
if (position == ItemCount - 1 && !PlaylistTracks.instance.fullyLoadded)
{
int pad = MainActivity.instance.DpToPx(30);
((RecyclerView.LayoutParams)viewHolder.ItemView.LayoutParameters).TopMargin = pad;
((RecyclerView.LayoutParams)viewHolder.ItemView.LayoutParameters).BottomMargin = pad;
}
- else if (BaseCount == 0 && position == 0)
- {
- ((TextView)viewHolder.ItemView).Text = MainActivity.instance.GetString(Resource.String.playlist_empty);
- }
else if (position == 0 && !PlaylistTracks.instance.useHeader)
{
View header = viewHolder.ItemView;
header.FindViewById(Resource.Id.headerNumber).Text = tracks.Count + " " + (tracks.Count < 2 ? MainActivity.instance.GetString(Resource.String.element) : MainActivity.instance.GetString(Resource.String.elements));
if (!header.FindViewById(Resource.Id.headerPlay).HasOnClickListeners)
{
- header.FindViewById(Resource.Id.headerPlay).Click += (sender, e0) => { PlaylistManager.PlayInOrder(PlaylistTracks.instance.item); };
+ header.FindViewById(Resource.Id.headerPlay).Click += (sender, e0) => { SongManager.PlayInOrder(tracks); };
header.FindViewById(Resource.Id.headerShuffle).Click += (sender, e0) =>
{
- PlaylistManager.Shuffle(PlaylistTracks.instance.item);
+ SongManager.Shuffle(tracks);
};
header.FindViewById(Resource.Id.headerMore).Click += (sender, e0) =>
{
@@ -91,6 +92,10 @@ namespace Opus.Adapter
header.FindViewById(Resource.Id.headerMore).ImageTintList = ColorStateList.ValueOf(Color.Black);
}
}
+ else if (BaseCount == 0)
+ {
+ ((TextView)viewHolder.ItemView).Text = MainActivity.instance.GetString(Resource.String.playlist_empty);
+ }
else if (tracks != null)
OnBindViewHolder(viewHolder, tracks[position - ItemBefore]);
else
@@ -151,7 +156,10 @@ namespace Opus.Adapter
public override void Clicked(Song item, int position)
{
- PlaylistManager.PlayInOrder(PlaylistTracks.instance.item, position);
+ if (PlaylistTracks.instance.useHeader)
+ PlaylistManager.PlayInOrder(PlaylistTracks.instance.item, position);
+ else
+ SongManager.Play(item);
}
public override void OnLongClick(int position)
@@ -200,12 +208,12 @@ namespace Opus.Adapter
{
if (position == ItemCount - 1 && !PlaylistTracks.instance.fullyLoadded)
return 1;
- else if (BaseCount == 0 && position == 0)
- return 3;
-
- if (position == 0 && !PlaylistTracks.instance.useHeader)
+ else if (position == 0 && !PlaylistTracks.instance.useHeader)
return 2;
- return 0;
+ else if (BaseCount == 0)
+ return 3;
+ else
+ return 0;
}
diff --git a/Opus/Code/UI/Fragments/Home.cs b/Opus/Code/UI/Fragments/Home.cs
index 0d78d39..2e52ebb 100644
--- a/Opus/Code/UI/Fragments/Home.cs
+++ b/Opus/Code/UI/Fragments/Home.cs
@@ -80,51 +80,57 @@ namespace Opus.Fragments
HomeSection shuffle = new HomeSection(Resources.GetString(Resource.String.shuffle), SectionType.Shuffle);
adapterItems.Add(shuffle);
- if (MainActivity.instance.HasReadPermission())
+ await Task.Run(() =>
{
- Android.Net.Uri musicUri = MediaStore.Audio.Media.ExternalContentUri;
-
- List allSongs = new List();
- CursorLoader cursorLoader = new CursorLoader(MainActivity.instance, musicUri, null, null, null, null);
- ICursor musicCursor = (ICursor)cursorLoader.LoadInBackground();
-
- if (musicCursor != null && musicCursor.MoveToFirst())
+ if (MainActivity.instance.HasReadPermission())
{
- int titleID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Title);
- int artistID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Artist);
- int albumID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Album);
- int thisID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Id);
- int pathID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Data);
- do
+ if (Looper.MyLooper() == null)
+ Looper.Prepare();
+
+ Android.Net.Uri musicUri = MediaStore.Audio.Media.ExternalContentUri;
+
+ List allSongs = new List();
+ CursorLoader cursorLoader = new CursorLoader(MainActivity.instance, musicUri, null, null, null, null);
+ ICursor musicCursor = (ICursor)cursorLoader.LoadInBackground();
+
+ if (musicCursor != null && musicCursor.MoveToFirst())
{
- string Artist = musicCursor.GetString(artistID);
- string Title = musicCursor.GetString(titleID);
- string Album = musicCursor.GetString(albumID);
- long AlbumArt = musicCursor.GetLong(musicCursor.GetColumnIndex(MediaStore.Audio.Albums.InterfaceConsts.AlbumId));
- long id = musicCursor.GetLong(thisID);
- string path = musicCursor.GetString(pathID);
+ int titleID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Title);
+ int artistID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Artist);
+ int albumID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Album);
+ int thisID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Id);
+ int pathID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Data);
+ do
+ {
+ string Artist = musicCursor.GetString(artistID);
+ string Title = musicCursor.GetString(titleID);
+ string Album = musicCursor.GetString(albumID);
+ long AlbumArt = musicCursor.GetLong(musicCursor.GetColumnIndex(MediaStore.Audio.Albums.InterfaceConsts.AlbumId));
+ long id = musicCursor.GetLong(thisID);
+ string path = musicCursor.GetString(pathID);
- if (Title == null)
- Title = "Unknown Title";
- if (Artist == null)
- Artist = "Unknow Artist";
- if (Album == null)
- Album = "Unknow Album";
+ if (Title == null)
+ Title = "Unknown Title";
+ if (Artist == null)
+ Artist = "Unknow Artist";
+ if (Album == null)
+ Album = "Unknow Album";
- allSongs.Add(new Song(Title, Artist, Album, null, AlbumArt, id, path));
+ allSongs.Add(new Song(Title, Artist, Album, null, AlbumArt, id, path));
+ }
+ while (musicCursor.MoveToNext());
+ musicCursor.Close();
}
- while (musicCursor.MoveToNext());
- musicCursor.Close();
- }
- Random r = new Random();
- List songList = allSongs.OrderBy(x => r.Next()).ToList();
+ Random r = new Random();
+ List songList = allSongs.OrderBy(x => r.Next()).ToList();
- if (songList.Count > 0)
- {
- HomeSection featured = new HomeSection(Resources.GetString(Resource.String.featured), SectionType.SinglePlaylist, songList.GetRange(0, songList.Count > 50 ? 50 : songList.Count));
- adapterItems.Add(featured);
+ if (songList.Count > 0)
+ {
+ HomeSection featured = new HomeSection(Resources.GetString(Resource.String.featured), SectionType.SinglePlaylist, songList.GetRange(0, songList.Count > 50 ? 50 : songList.Count));
+ adapterItems.Add(featured);
+ }
}
- }
+ });
view.FindViewById(Resource.Id.loading).Visibility = ViewStates.Gone;
adapter = new HomeAdapter(adapterItems);
@@ -173,10 +179,6 @@ namespace Opus.Fragments
await PopulateView();
}
- public void LoadMore()
- {
- }
-
public void RefreshQueue(bool scroll = true)
{
if (adapterItems.Count > 0)
diff --git a/Opus/Code/UI/Fragments/PlaylistTracks.cs b/Opus/Code/UI/Fragments/PlaylistTracks.cs
index 3536f12..34e03f1 100644
--- a/Opus/Code/UI/Fragments/PlaylistTracks.cs
+++ b/Opus/Code/UI/Fragments/PlaylistTracks.cs
@@ -175,7 +175,10 @@ namespace Opus.Fragments
break;
case Resource.Id.addToQueue:
- PlaylistManager.AddToQueue(item);
+ if (useHeader)
+ PlaylistManager.AddToQueue(item);
+ else
+ SongManager.AddToQueue(adapter.tracks);
break;
case Resource.Id.rename:
@@ -223,16 +226,15 @@ namespace Opus.Fragments
menu.Show();
}
- //public static Fragment NewInstance(List songs, string playlistName)
- //{
- // instance = new PlaylistTracks { Arguments = new Bundle() };
- // instance.tracks = songs;
- // instance.playlistName = playlistName;
- // instance.useHeader = false;
- // instance.fullyLoadded = true;
- // instance.hasWriteAcess = false;
- // return instance;
- //}
+ public static Fragment NewInstance(List songs, string playlistName)
+ {
+ instance = new PlaylistTracks { Arguments = new Bundle() };
+ instance.item = new PlaylistItem() { Name = playlistName, Count = songs.Count, HasWritePermission = false, LocalID = -1, YoutubeID = null };
+ instance.useHeader = false;
+ instance.fullyLoadded = true;
+ instance.adapter = new PlaylistTrackAdapter(new SearchableList(songs));
+ return instance;
+ }
public static Fragment NewInstance(PlaylistItem item, bool forked)
{
@@ -246,7 +248,7 @@ namespace Opus.Fragments
async Task PopulateList()
{
- if (item.LocalID == -1 && item.YoutubeID == ""/* && tracks.Count == 0*/)
+ if (item.LocalID == -1 && item.YoutubeID == null && adapter?.tracks.Count == 0)
return;
if (item.LocalID != -1)
@@ -311,13 +313,10 @@ namespace Opus.Fragments
MainActivity.instance.Timout();
}
}
- //else if(tracks.Count != 0)
- //{
- // adapter = new PlaylistTrackAdapter(tracks);
- // adapter.ItemClick += ListView_ItemClick;
- // adapter.ItemLongClick += ListView_ItemLongClick;
- // ListView.SetAdapter(adapter);
- //}
+ else if (adapter?.tracks.Count != 0)
+ {
+ ListView.SetAdapter(adapter);
+ }
}
public Android.Support.V4.Content.Loader OnCreateLoader(int id, Bundle args)
@@ -464,7 +463,10 @@ namespace Opus.Fragments
{
new BottomSheetAction(Resource.Drawable.Play, Resources.GetString(Resource.String.play), (sender, eventArg) =>
{
- PlaylistManager.PlayInOrder(item, position);
+ if(useHeader)
+ PlaylistManager.PlayInOrder(item, position);
+ else
+ SongManager.Play(song);
bottomSheet.Dismiss();
}),
new BottomSheetAction(Resource.Drawable.PlaylistPlay, Resources.GetString(Resource.String.play_next), (sender, eventArg) =>