Ejemplo n.º 1
0
        public override async Task <TrackFile> GetDownloadableTrackAsync(Track track)
        {
            var response =
                await
                client.GetStreamUrlAsync(Int32.Parse(track.Id), settings.StreamQuality);

            var result = new TidalTrackFile
            {
                DownloadUri = new Uri(response.Url),
                Track       = track
            };

            // We can assume the MIME type and bitrate from the **returned** sound quality
            // It is unwise to use the stream quality stored in settings as users with lossless
            // subscriptions will get lossy streams simply because lossless streams are unavailable
            switch (response.SoundQuality)
            {
            case StreamingQuality.Low:
                result.BitRate = 96 * 1000;
                break;

            case StreamingQuality.High:
                result.BitRate = 320 * 1000;
                break;

            case StreamingQuality.HiRes:
            case StreamingQuality.Lossless:
                // Bitrate doesn't really matter since it's lossless
                result.BitRate = -1;
                break;

            default:
                result.BitRate = -1;
                break;
            }
            switch (response.Codec)
            {
            case TidalCodec.AAC:
                result.FileType = MediaFileTypes.Mpeg4Audio;
                break;

            case TidalCodec.FLAC:
            case TidalCodec.MQA:
                result.FileType = MediaFileTypes.FreeLosslessAudioCodec;
                break;

            case TidalCodec.MP3:
                result.FileType = MediaFileTypes.Mpeg3Audio;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            if (!string.IsNullOrEmpty(response.EncryptionKey))
            {
                result.FileKey = TidalDecryptor.ParseFileKey(Convert.FromBase64String(response.EncryptionKey));
            }
            return(result);
        }
Ejemplo n.º 2
0
        public async Task DownloadAsyncTask(TrackFile track, string destination)
        {
            var tidalTrack = (TidalTrackFile)track;
            // This is the way to do it as a stream. However this is also really slow.
//            var request = WebRequest.CreateHttp(tidalTrack.DownloadUri);
//            request.Method = "GET";
//            var response = (HttpWebResponse) await request.GetResponseAsync();
//            using (
//                var cryptoStream = TidalDecryptor.CreateDecryptionStream(tidalTrack.FileKey,
//                    response.GetResponseStream()))
//            {
//                using (var destFile = File.OpenWrite(destination))
//                {
//                    var eventArgs = new DownloadEventArgs {State = DownloadState.Downloading};
//                    int bytesRead, bytesReadTotal = 0;
//                    var buffer = new byte[TidalDecryptor.BlockSize];
//                    while ((bytesRead = await cryptoStream.ReadAsync(buffer, 0, TidalDecryptor.BlockSize)) > 0)
//                    {
//                        bytesReadTotal += bytesRead;
//                        await destFile.WriteAsync(buffer, 0, bytesRead);
//                        eventArgs.PercentCompleted = (decimal)bytesReadTotal / response.ContentLength;
//                        Progress?.Invoke(this, eventArgs);
//                    }
//                }
//            }
//            Done?.Invoke(this, EventArgs.Empty);
            var data = await mClient.DownloadDataTaskAsync(tidalTrack.DownloadUri);

            Progress?.Invoke(this, new DownloadEventArgs {
                PercentCompleted = 1m, State = DownloadState.PostProcess
            });
            using (var inputStream = new MemoryStream(data))
            {
                using (
                    var cryptoStream = TidalDecryptor.CreateDecryptionStream(tidalTrack.FileKey, inputStream))
                {
                    using (var destFile = File.OpenWrite(destination))
                    {
                        await cryptoStream.CopyToAsync(destFile, TidalDecryptor.BlockSize);
                    }
                }
            }
            Done?.Invoke(this, EventArgs.Empty);
        }