Ejemplo n.º 1
0
        /// <summary>
        /// Keeps the download progress properties of the music items up-to-date
        /// so that the progress can be displayed under each item in the UI.
        ///
        /// The music items in the library and the playlist do not point to the
        /// same object even if it's the same track so we need to update both places separately.
        /// </summary>
        /// <param name="transfer"></param>
        protected override void OnDownloadStatusUpdate(BackgroundTransferRequest transfer)
        {
            base.OnDownloadStatusUpdate(transfer);
            var path          = FileUtilsBase.UnixSeparators(transfer.Tag.Substring(PhoneLocalLibrary.Instance.BaseMusicPath.Length));
            var musicItem     = MusicProvider.SearchItem(path);
            var isDownloading = transfer.TransferStatus == TransferStatus.Transferring;
            var bytesReceived = (ulong)transfer.BytesReceived;

            // updates track in the library
            if (musicItem != null)
            {
                MusicItem.SetDownloadStatus(musicItem, bytesReceived);
                musicItem.IsDownloading = isDownloading;
            }
            // updates the track in the playlist
            var playlistTracks = PimpViewModel.Instance.MusicPlayer.Playlist.Songs
                                 .Where(item => item.Song.Path == path)
                                 .ToList(); // beautiful!!!

            BasePlaylist.SetDownloadStatus(playlistTracks, bytesReceived);
            foreach (var item in playlistTracks)
            {
                item.Song.IsDownloading = isDownloading;
            }
        }
Ejemplo n.º 2
0
 public Task AddToPlaylistRecursively(MusicItem item)
 {
     return(AddToPlaylistRecursively(new List <MusicItem>()
     {
         item
     }));
 }
Ejemplo n.º 3
0
 private Task DeleteLocalItem(MusicItem item)
 {
     return(TryFileDeletion(async() => {
         await LocalLibrary.Delete(item);
         // Updates the UI. Apparently, MusicFolder.MusicItems.Remove(item); does not update the UI.
         await RefreshCurrentFolder();
     }));
 }
Ejemplo n.º 4
0
 public async Task DownloadSong(MusicItem song)
 {
     if (PhoneLibraryManager.Instance.ActiveEndpoint.EndpointType == EndpointTypes.Subsonic &&
         song.Size > 5242880)
     {
         AddMessage("Files over 5MB cannot currently be downloaded from Subsonic due to a technical limitation. The download of " + song.Name + " is likely to fail.");
     }
     await SubmitDownload(song);
 }
Ejemplo n.º 5
0
        public async Task DownloadFolder(MusicItem folder)
        {
            var tracks = await MusicProvider.SongsInFolder(folder);

            foreach (var t in tracks)
            {
                await SubmitDownload(t);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Downloads the song if it is not already available offline.
        /// </summary>
        /// <param name="track"></param>
        /// <returns>the local uri of the downloaded track</returns>
        public async Task <Uri> DownloadAsync(MusicItem track)
        {
            await BeforeDownload(track);

            var maybeLocalUri = await PhoneLocalLibrary.Instance.LocalUriIfExists(track);

            if (maybeLocalUri != null)
            {
                return(maybeLocalUri);
            }
            return(await AddTransferAsync(track.Source, LocalLibrary.AbsolutePathTo(track)));
        }
Ejemplo n.º 7
0
 public async Task <List <MusicItem> > GetSongsRecursively(MusicItem songOrDir)
 {
     if (!songOrDir.IsDir)
     {
         var tracks = new List <MusicItem>();
         tracks.Add(songOrDir);
         return(tracks);
     }
     else
     {
         return(await MusicProvider.SongsInFolder(songOrDir));
     }
 }
Ejemplo n.º 8
0
 protected void Delete(MusicItem song)
 {
     try {
         var shouldRemove = song.IsSourceLocal;
         LocalLibrary.Delete(song.Path);
         // refreshes the items in the current view
         if (shouldRemove)
         {
             MusicFolder.MusicItems.Remove(song);
         }
     } catch (Exception e) {
         Send("Unable to delete. Perhaps the file is in use. " + e.Message);
     }
 }
Ejemplo n.º 9
0
 public async Task ValidateThenSubmitDownload(MusicItem item)
 {
     try {
         if (item.IsDir)
         {
             await DownloadFolder(item);
         }
         else
         {
             await DownloadSong(item);
         }
     } catch (Exception e) {
         AddMessage("Unable to download " + item.Name + ". " + e.Message);
     }
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Downloads the song in the background if it's not already available offline.
        /// </summary>
        /// <param name="track"></param>
        public async Task SubmitDownload(MusicItem track)
        {
            await BeforeDownload(track);

            try {
                var maybeLocalUri = await PhoneLocalLibrary.Instance.LocalUriIfExists(track);

                if (maybeLocalUri == null)
                {
                    // For Subsonic, the response may be transcoded audio, in which case the
                    // path to the track, which has the original file extension as stored on
                    // the server, may be incorrect (example: response is transcoded to .mp3,
                    // path is .flac).

                    // TODO: Ensure that the file is stored locally with the correct extension,
                    // that is, find out whether the response is transcoded.
                    var destination = LocalLibrary.AbsolutePathTo(track);
                    var downloadUri = MusicProvider.DownloadUriFor(track);
                    // Only downloads tracks that are stored as MP3s, because this app does not support other local file formats.
                    if (destination.EndsWith("mp3"))
                    {
                        var downloadable = new Downloadable(downloadUri, destination);
                        if (LoadTransfersCount() < 3)
                        {
                            AddTransfer(downloadUri, destination);
                        }
                        else
                        {
                            // add the download to persistent storage from which it will be taken
                            // later when there are fewer concurrent downloads
                            DownloadDataContext.Add(downloadable);
                        }
                    }
                }
            } catch (PathTooLongException) {
                // Thrown if track.Path is about over 190 characters long, but I'm not sure what
                // the limit is and I don't want to be too defensive with this so I catch and
                // suppress the exception when it occurs.

                // The exception says "The specified path, file name, or both are too long.
                // The fully qualified file name must be less than 260 characters, and the
                // directory name must be less than 248 characters.", however, I don't know
                // the length of the fully qualified path name, so 190 chars is an estimate.
                AddMessage("Download of " + track.Name + " failed. The path is too long: " + track.Path);
            }
        }
Ejemplo n.º 11
0
 private string GroupKeyOf(MusicItem item)
 {
     if (item.IsDir)
     {
         var lowerCase = item.Name.ToLowerInvariant();
         // crashes if item.Name.Length == 0
         if (char.IsDigit(lowerCase, index: 0))
         {
             return(Grouping.DigitGroupHeader);
         }
         else
         {
             return(lowerCase.ToCharArray()[0].ToString());
         }
     }
     else
     {
         return(Grouping.SongGroupHeader);
     }
 }
Ejemplo n.º 12
0
 public async Task OnSingleMusicItemSelected(MusicItem item)
 {
     await WithExceptionEvents(async() => {
         LibraryScrollPositions[MusicFolder.FolderId] = item;
         //MusicFolder.LatestSelection = item;
         if (item.IsDir)
         {
             string folderPath    = MusicFolder.DisplayablePath == String.Empty ? item.Name : MusicFolder.DisplayablePath + "/" + item.Name;
             var folderIdentifier = MusicProvider.DirectoryIdentifier(item);
             var folderJson       = Json.SerializeToString(new FolderMeta(folderIdentifier, folderPath));
             // encode the folder id so we can pass it in a uri query parameter
             var encodedFolderId = Strings.encode(folderJson);
             // user clicked a music directory
             Navigator.NavigateWithinSamePage(encodedFolderId);
         }
         else
         {
             // user clicked a song, let's play!
             await MusicPlayer.PlaySong(item);
         }
     });
 }
Ejemplo n.º 13
0
 public PlaylistMusicItem(MusicItem song, int index)
 {
     Song  = song;
     Index = index;
 }
Ejemplo n.º 14
0
 public static void SetDownloadStatus(MusicItem track, ulong bytesReceived)
 {
     track.IsDownloading = bytesReceived < (ulong)track.Size;
     track.BytesReceived = bytesReceived;
 }
Ejemplo n.º 15
0
 public async Task OnSingleMusicItemSelected(MusicItem item)
 {
     await MusicPlayer.PlaySong(item);
 }
Ejemplo n.º 16
0
 public Task SubmitDownload(MusicItem track, string username, string password)
 {
     return(SubmitDownload(track));
 }
Ejemplo n.º 17
0
 // rely on the credentials in the query string because the background downloader
 // in WP doesn't support custom HTTP headers
 public Task <Uri> DownloadAsync(MusicItem track, string username, string password)
 {
     return(DownloadAsync(track));
 }
Ejemplo n.º 18
0
 // TODO: refactor
 private Task BeforeDownload(MusicItem track)
 {
     return(AsyncTasks.Noop());
 }
Ejemplo n.º 19
0
 public static string DirOnlySortKey(MusicItem item)
 {
     return(item.IsDir ? "a" + item.Name : "b");
 }
Ejemplo n.º 20
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="item"></param>
        /// <returns>a sort key where directories are first, then based on name</returns>
        public static string SortKey(MusicItem item)
        {
            string prefix = item.IsDir ? "a" : "b";

            return(prefix + item.Name);
        }