Download playlist now add songs to a local playlist

This commit is contained in:
Anonymous Raccoon
2018-05-20 17:06:04 +02:00
parent 1e17cfd3ba
commit 2a6f1cbeef
7 changed files with 161 additions and 95 deletions
@@ -373,6 +373,57 @@ namespace MusicApp.Resources.Portable_Class
builder.Show();
}
public static long GetPlaylistID(string playlistName)
{
Android.Net.Uri uri = MediaStore.Audio.Playlists.ExternalContentUri;
Looper.Prepare();
CursorLoader loader = new CursorLoader(Android.App.Application.Context, uri, null, null, null, null);
ICursor cursor = (ICursor)loader.LoadInBackground();
if (cursor != null && cursor.MoveToFirst())
{
int nameID = cursor.GetColumnIndex(MediaStore.Audio.Playlists.InterfaceConsts.Name);
int plID = cursor.GetColumnIndex(MediaStore.Audio.Playlists.InterfaceConsts.Id);
do
{
string name = cursor.GetString(nameID);
if (name != playlistName)
continue;
return cursor.GetLong(plID);
}
while (cursor.MoveToNext());
cursor.Close();
}
//Playlist do not exist, create it
ContentResolver resolver = act.ContentResolver;
ContentValues value = new ContentValues();
value.Put(MediaStore.Audio.Playlists.InterfaceConsts.Name, playlistName);
resolver.Insert(uri, value);
CursorLoader loaderBis = new CursorLoader(Android.App.Application.Context, uri, null, null, null, null);
ICursor cursorBis = (ICursor)loader.LoadInBackground();
if (cursorBis != null && cursorBis.MoveToFirst())
{
int nameID = cursorBis.GetColumnIndex(MediaStore.Audio.Playlists.InterfaceConsts.Name);
int getplaylistID = cursorBis.GetColumnIndex(MediaStore.Audio.Playlists.InterfaceConsts.Id);
do
{
string name = cursorBis.GetString(nameID);
long id = cursorBis.GetLong(getplaylistID);
if (playlistName == name)
return id;
}
while (cursorBis.MoveToNext());
cursorBis.Close();
}
return -1;
}
public async static Task CheckWritePermission()
{
const string permission = Manifest.Permission.WriteExternalStorage;
+44 -15
View File
@@ -2,7 +2,12 @@
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Database;
using Android.Media;
using Android.Net;
using Android.OS;
using Android.Provider;
using Android.Support.Design.Widget;
using Android.Support.V4.App;
using MusicApp.Resources.values;
using System.Collections.Generic;
@@ -19,7 +24,7 @@ using File = System.IO.File;
namespace MusicApp.Resources.Portable_Class
{
[Service]
public class Downloader : Service
public class Downloader : Service, MediaScannerConnection.IOnScanCompletedListener
{
public static Downloader instance;
public string downloadPath;
@@ -28,8 +33,8 @@ namespace MusicApp.Resources.Portable_Class
private int currentStrike = 0;
private static bool isDownloading = false;
private NotificationCompat.Builder notification;
private int notificationID = 1001;
private int RequestCode = 5465;
private const int notificationID = 1001;
private const int RequestCode = 5465;
public override IBinder OnBind(Intent intent)
@@ -83,20 +88,31 @@ namespace MusicApp.Resources.Portable_Class
currentStrike++;
CreateNotification(file.name);
if (YoutubeEngine.FileIsAlreadyDownloaded(file.videoID) && !file.skipCheck)
{
Snackbar.Make(MainActivity.instance.FindViewById(Resource.Id.snackBar), file.name + " is already on your device.", Snackbar.LengthShort).SetAction("Download Anyway", (v) =>
{
file.skipCheck = true;
Download(file);
}).Show();
}
YoutubeClient client = new YoutubeClient();
Video videoInfo = await client.GetVideoAsync(file.videoID);
MediaStreamInfoSet mediaStreamInfo = await client.GetVideoMediaStreamInfosAsync(file.videoID);
AudioStreamInfo streamInfo = mediaStreamInfo.Audio.Where(x => x.Container == Container.M4A).OrderBy(s => s.Bitrate).Last();
System.Console.WriteLine("&" + streamInfo.Url);
//With Where container == Container.M4A, output file should be a m4a file, so ffmpeg is usless
string fileExtension = streamInfo.Container.GetFileExtension();
string fileName = $"{videoInfo.Title}.{fileExtension}";
string filePath = Path.Combine(path, fileName);
string outpath = path;
if(file.playlist != null)
{
outpath = Path.Combine(path, file.playlist);
Directory.CreateDirectory(outpath);
}
System.Console.WriteLine("&Client and path created");
string filePath = Path.Combine(outpath, fileName);
MediaStream input = await client.GetMediaStreamAsync(streamInfo);
@@ -104,18 +120,16 @@ namespace MusicApp.Resources.Portable_Class
await input.CopyToAsync(output);
output.Dispose();
System.Console.WriteLine("&Webm Output created");
SetMetaData(filePath, videoInfo.Title, videoInfo.Author, videoInfo.Thumbnails.HighResUrl, file.videoID);
SetMetaData(filePath, videoInfo.Title, videoInfo.Author, videoInfo.Thumbnails.HighResUrl, file.videoID, file.playlist);
isDownloading = false;
if (queue.Count != 0)
DownloadAudio(queue[0], path);
}
private void SetMetaData(string filePath, string title, string artist, string album, string youtubeID)
private void SetMetaData(string filePath, string title, string artist, string album, string youtubeID, string playlist)
{
Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite);
System.IO.Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite);
var meta = TagLib.File.Create(new StreamFileAbstraction(filePath, stream, stream));
meta.Tag.Title = title;
@@ -130,9 +144,24 @@ namespace MusicApp.Resources.Portable_Class
meta.Tag.Pictures = pictures;
meta.Save();
stream.Dispose();
Android.Media.MediaScannerConnection.ScanFile(this, new string[] { filePath }, null, null);
MediaScannerConnection.ScanFile(this, new string[] { filePath }, null, this);
StopForeground(true);
if (queue.Count == 0)
StopForeground(true);
}
public void OnScanCompleted(string path, Uri uri)
{
long id = long.Parse(uri.ToString().Substring(uri.ToString().IndexOf("audio/media/") + 12, uri.ToString().Length - uri.ToString().IndexOf("audio/media/") - 12));
string playlist = path.Substring(downloadPath.Length + 1, path.IndexOf("/", downloadPath.Length) - downloadPath.Length + 1);
Browse.act = MainActivity.instance;
long playlistID = Browse.GetPlaylistID(playlist);
ContentValues value = new ContentValues();
value.Put(MediaStore.Audio.Playlists.Members.AudioId, id);
value.Put(MediaStore.Audio.Playlists.Members.PlayOrder, 0);
ContentResolver.Insert(MediaStore.Audio.Playlists.Members.GetContentUri("external", playlistID), value);
}
void CreateNotification(string title)
@@ -348,8 +348,6 @@ namespace MusicApp.Resources.Portable_Class
CursorLoader cursorLoader = new CursorLoader(Android.App.Application.Context, musicUri, null, null, null, null);
ICursor musicCursor = (ICursor)cursorLoader.LoadInBackground();
System.Console.WriteLine("&Path: " + path + " URI: " + musicUri.ToString());
if (musicCursor != null && musicCursor.MoveToFirst())
{
int thisID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Id);
+15 -22
View File
@@ -21,6 +21,7 @@ namespace MusicApp.Resources.Portable_Class
{
public static Playlist instance;
public RecyclerView ListView;
private bool populated = false;
//Local playlists
private List<string> playList = new List<string>();
@@ -32,7 +33,6 @@ namespace MusicApp.Resources.Portable_Class
private List<Google.Apis.YouTube.v3.Data.Playlist> YtPlaylists = new List<Google.Apis.YouTube.v3.Data.Playlist>();
private PlaylistAdapter adapter;
private bool isEmpty = false;
private View emptyView;
public override void OnActivityCreated(Bundle savedInstanceState)
@@ -43,20 +43,6 @@ namespace MusicApp.Resources.Portable_Class
MainActivity.instance.OnPaddingChanged += OnPaddingChanged;
}
public void AddEmptyView()
{
if (emptyView.Parent != null)
((ViewGroup)emptyView.Parent).RemoveView(emptyView);
Activity.AddContentView(emptyView, View.LayoutParameters);
}
public void RemoveEmptyView()
{
ViewGroup rootView = Activity.FindViewById<ViewGroup>(Android.Resource.Id.Content);
rootView.RemoveView(emptyView);
}
private void OnPaddingChanged(object sender, PaddingChange e)
{
if (MainActivity.paddingBot > e.oldPadding)
@@ -69,8 +55,6 @@ namespace MusicApp.Resources.Portable_Class
{
MainActivity.instance.contentRefresh.Refresh -= OnRefresh;
MainActivity.instance.OnPaddingChanged -= OnPaddingChanged;
if (isEmpty)
RemoveEmptyView();
base.OnDestroy();
instance = null;
@@ -90,6 +74,8 @@ namespace MusicApp.Resources.Portable_Class
public async Task PopulateView()
{
populated = false;
//Local playlists
playList.Clear();
playlistId.Clear();
@@ -145,6 +131,9 @@ namespace MusicApp.Resources.Portable_Class
YouTubeService youtube = YoutubeEngine.youtubeService;
if (instance == null)
return;
PlaylistsResource.ListRequest request = youtube.Playlists.List("snippet,contentDetails");
request.Mine = true;
request.MaxResults = 25;
@@ -185,6 +174,9 @@ namespace MusicApp.Resources.Portable_Class
PlaylistsResource.ListRequest plRequest = youtube.Playlists.List("snippet, contentDetails");
plRequest.Id = section.ContentDetails.Playlists[i];
if (instance == null)
return;
PlaylistListResponse plResponse = await plRequest.ExecuteAsync();
if (instance == null)
@@ -209,6 +201,8 @@ namespace MusicApp.Resources.Portable_Class
adapter.SetYtPlaylists(ytPlaylists, true);
else
adapter.SetYtPlaylists(ytPlaylists, true);
populated = true;
}
public static Fragment NewInstance()
@@ -225,7 +219,8 @@ namespace MusicApp.Resources.Portable_Class
public async Task Refresh()
{
await PopulateView();
if(populated)
await PopulateView();
}
private void ListView_ItemClick(object sender, int Position)
@@ -290,8 +285,6 @@ namespace MusicApp.Resources.Portable_Class
act.SupportActionBar.Title = playlist.GetName();
instance = null;
MainActivity.instance.contentRefresh.Refresh -= OnRefresh;
if (isEmpty)
RemoveEmptyView();
if (local)
MainActivity.instance.Transition(Resource.Id.contentView, PlaylistTracks.NewInstance(playlist.GetID(), playlist.GetName()), true);
@@ -352,7 +345,7 @@ namespace MusicApp.Resources.Portable_Class
RemoveYoutubePlaylist(Position, playlist.GetPath());
break;
case 4:
YoutubeEngine.DownloadPlaylist(playlist.GetPath());
YoutubeEngine.DownloadPlaylist(playlist.GetName(), playlist.GetPath());
break;
default:
break;
@@ -373,7 +366,7 @@ namespace MusicApp.Resources.Portable_Class
Unfork(Position, playlist.GetPath());
break;
case 3:
YoutubeEngine.DownloadPlaylist(playlist.GetPath());
YoutubeEngine.DownloadPlaylist(playlist.GetName(), playlist.GetPath());
break;
default:
break;
@@ -417,19 +417,11 @@ namespace MusicApp.Resources.Portable_Class
parseProgress.Visibility = ViewStates.Gone;
}
public async static void Download(string name, string videoID, bool skipExistVerification = false)
public async static void Download(string name, string videoID)
{
ISharedPreferences prefManager = PreferenceManager.GetDefaultSharedPreferences(Android.App.Application.Context);
if (prefManager.GetString("downloadPath", null) != null)
{
if (FileIsAlreadyDownloaded(videoID) && !skipExistVerification)
{
Snackbar.Make(MainActivity.instance.FindViewById(Resource.Id.snackBar), name + " is already on your device.", Snackbar.LengthShort).SetAction("Download Anyway", (v) =>
{
Download(name, videoID, true);
}).Show();
}
Toast.MakeText(Android.App.Application.Context, "Downloading...", ToastLength.Short).Show();
Context context = Android.App.Application.Context;
Intent intent = new Intent(context, typeof(Downloader));
@@ -439,7 +431,7 @@ namespace MusicApp.Resources.Portable_Class
await Task.Delay(10);
Downloader.instance.downloadPath = prefManager.GetString("downloadPath", null);
Downloader.instance.Download(new DownloadFile(name, videoID));
Downloader.instance.Download(new DownloadFile(name, videoID, null));
}
else
{
@@ -451,56 +443,56 @@ namespace MusicApp.Resources.Portable_Class
}
}
public static async void DownloadFiles(string[] names, string[] videoIDs, bool skipExistVerification = false)
public static async void DownloadFiles(string[] names, string[] videoIDs, string playlist)
{
ISharedPreferences prefManager = PreferenceManager.GetDefaultSharedPreferences(Android.App.Application.Context);
if (prefManager.GetString("downloadPath", null) != null)
{
if (!skipExistVerification)
{
List<string> downloadedName = new List<string>();
List<string> downloadedID = new List<string>();
for (int i = 0; i < names.Length; i++)
{
if (FileIsAlreadyDownloaded(videoIDs[i]))
{
downloadedName.Add(names[i]);
downloadedID.Add(videoIDs[i]);
}
}
//if (!skipExistVerification)
//{
// List<string> downloadedName = new List<string>();
// List<string> downloadedID = new List<string>();
// for (int i = 0; i < names.Length; i++)
// {
// if (FileIsAlreadyDownloaded(videoIDs[i]))
// {
// downloadedName.Add(names[i]);
// downloadedID.Add(videoIDs[i]);
// }
// }
if (downloadedName.Count > 0)
{
List<string> namesList = names.ToList();
List<string> idList = videoIDs.ToList();
// if (downloadedName.Count > 0)
// {
// List<string> namesList = names.ToList();
// List<string> idList = videoIDs.ToList();
for(int i = 0; i < downloadedName.Count; i++)
{
namesList.Remove(downloadedName[i]);
idList.Remove(downloadedID[i]);
}
// for(int i = 0; i < downloadedName.Count; i++)
// {
// namesList.Remove(downloadedName[i]);
// idList.Remove(downloadedID[i]);
// }
names = namesList.ToArray();
videoIDs = idList.ToArray();
// names = namesList.ToArray();
// videoIDs = idList.ToArray();
if (downloadedName.Count == 1)
{
Snackbar.Make(MainActivity.instance.FindViewById(Resource.Id.snackBar), downloadedName[0] + " is already on your device.", Snackbar.LengthShort).SetAction("Download this file anyway", (v) =>
{
Downloader.instance.Download(new DownloadFile(downloadedName[0], downloadedID[0]));
}).Show();
}
else
{
Snackbar.Make(MainActivity.instance.FindViewById(Resource.Id.snackBar), downloadedName.Count + " files are already on your device", Snackbar.LengthShort).SetAction("Download all this files anyway", (v) =>
{
for(int i = 0; i < downloadedName.Count; i++)
Downloader.instance.Download(new DownloadFile(downloadedName[i], downloadedID[i]));
// if (downloadedName.Count == 1)
// {
// Snackbar.Make(MainActivity.instance.FindViewById(Resource.Id.snackBar), downloadedName[0] + " is already on your device.", Snackbar.LengthShort).SetAction("Download this file anyway", (v) =>
// {
// Downloader.instance.Download(new DownloadFile(downloadedName[0], downloadedID[0], playlist));
// }).Show();
// }
// else
// {
// Snackbar.Make(MainActivity.instance.FindViewById(Resource.Id.snackBar), downloadedName.Count + " files are already on your device", Snackbar.LengthShort).SetAction("Download all this files anyway", (v) =>
// {
// for(int i = 0; i < downloadedName.Count; i++)
// Downloader.instance.Download(new DownloadFile(downloadedName[i], downloadedID[i], playlist));
}).Show();
}
}
}
// }).Show();
// }
// }
//}
Toast.MakeText(Android.App.Application.Context, "Downloading...", ToastLength.Short).Show();
Context context = Android.App.Application.Context;
@@ -513,7 +505,7 @@ namespace MusicApp.Resources.Portable_Class
Downloader.instance.downloadPath = prefManager.GetString("downloadPath", null);
for(int i = 0; i < names.Length; i++)
Downloader.instance.Download(new DownloadFile(names[i], videoIDs[i]));
Downloader.instance.Download(new DownloadFile(names[i], videoIDs[i], playlist));
}
else
{
@@ -772,7 +764,7 @@ namespace MusicApp.Resources.Portable_Class
PlayFiles(tracks.ToArray());
}
public static async void DownloadPlaylist(string playlistID)
public static async void DownloadPlaylist(string playlist, string playlistID)
{
List<string> names = new List<string>();
List<string> videoIDs = new List<string>();
@@ -794,7 +786,7 @@ namespace MusicApp.Resources.Portable_Class
nextPageToken = ytPlaylist.NextPageToken;
}
DownloadFiles(names.ToArray(), videoIDs.ToArray());
DownloadFiles(names.ToArray(), videoIDs.ToArray(), playlist);
}
}
}
@@ -106,7 +106,7 @@ namespace MusicApp.Resources.Portable_Class
YoutubeEngine.ForkPlaylist(playlist.GetPath());
break;
case 2:
YoutubeEngine.DownloadPlaylist(playlist.GetPath());
YoutubeEngine.DownloadPlaylist(playlist.GetName(), playlist.GetPath());
break;
default:
break;
+4 -1
View File
@@ -5,11 +5,14 @@
{
public string name;
public string videoID;
public string playlist;
public bool skipCheck = false;
public DownloadFile(string name, string videoID)
public DownloadFile(string name, string videoID, string playlist)
{
this.name = name;
this.videoID = videoID;
this.playlist = playlist;
}
}
}