Example #1
0
        private IDownloadCancelHandle StartEnqueuedDownload(QueuedDownload download)
        {
            _downloadStartedEvent.OnNext(download);
            App.Engine.StatisticsManager.LogDownloadStart(download);

            Transport.PendingDownload pendingDownload = Transport.StartQueuedDownload(download);

            pendingDownload.Response
            .ObserveOnDispatcher()
            .Subscribe <Transport.RunningDownload>(
                activeDownload =>
            {
                if (activeDownload.Download.DownloadSize == long.MaxValue || activeDownload.Download.DownloadSize == 0)
                {
                    activeDownload.Download.DownloadSize = activeDownload.ContentLength;
                }
                BackgroundWorker worker = new BackgroundWorker()
                {
                    WorkerReportsProgress = true, WorkerSupportsCancellation = true
                };

                // change cancel handle
                startedDownloads[activeDownload.Download] = new ActiveDownloadCancelHandle(worker);

                worker.DoWork += (sender, e) =>
                {
                    Transport.RunningDownload dl = (Transport.RunningDownload)e.Argument;
                    BackgroundWorker bw          = (BackgroundWorker)sender;
                    long bytesRead = dl.Download.DownloadedBytes;

                    // limited number of progress bar updates
                    var uiUpdates       = new Subject <long>();
                    var cancelUiUpdates = uiUpdates
                                          .Take(1)
                                          .Merge(Observable.Empty <long>().Delay(TimeSpan.FromMilliseconds(KProgressUpdateInterval)))
                                          .Repeat()
                                          .Subscribe <long>(progress =>
                    {
                        if (bw.IsBusy)
                        {
                            bw.ReportProgress(0, progress);
                        }
                    });

                    if (dl is Transport.ActiveDownload)
                    {
                        string filePath = Utils.MediaFilePath(App.Engine.LoggedUser, dl.Download);
                        using (Stream writer = new IsolatedStorageFileStream(filePath, FileMode.Append, IsolatedStorageFile.GetUserStoreForApplication()))
                        {
                            using (Stream reader = ((Transport.ActiveDownload)dl).Stream)
                            {
                                byte[] buffer = new byte[16 * 1024];
                                int readCount;
                                while ((readCount = reader.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    bytesRead += readCount;
                                    writer.Write(buffer, 0, readCount);
                                    uiUpdates.OnNext(bytesRead);

                                    if (bw.CancellationPending)
                                    {
                                        pendingDownload.Cancel();
                                        e.Cancel = true;
                                        break;
                                    }
                                }
                                bw.ReportProgress(0, bytesRead);
                                e.Result = activeDownload.Download;
                            }
                        }
                        cancelUiUpdates.Dispose();
                    }
                    if (dl is Transport.BackgroundDownload)
                    {
                        BackgroundTransferRequest downloadRequest = ((Transport.BackgroundDownload)dl).Request;
                        IObservable <IEvent <BackgroundTransferEventArgs> > requestObserver = Observable.FromEvent <BackgroundTransferEventArgs>(downloadRequest, "TransferStatusChanged");
                        if (downloadRequest.TransferStatus != TransferStatus.Completed)
                        {
                            if (downloadRequest.TransferStatus == TransferStatus.None)
                            {
                                downloadRequest.DownloadLocation    = new Uri(Utils.BackgroundFilePath(App.Engine.LoggedUser, dl.Download), UriKind.RelativeOrAbsolute);
                                downloadRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
                                e.Result = activeDownload.Download;
                                BackgroundTransferService.Add(downloadRequest);
                            }
                            downloadRequest.TransferProgressChanged += (senderBackground, eventBackground) =>
                            {
                                if (activeDownload.Download.DownloadSize == long.MaxValue || activeDownload.Download.DownloadSize == 0)
                                {
                                    activeDownload.Download.DownloadSize =
                                        activeDownload.ContentLength == -1 ?
                                        0:
                                        activeDownload.ContentLength;
                                }
                                uiUpdates.OnNext(eventBackground.Request.BytesReceived);
                            };
                            IDisposable cancelOnStop = DownloadStopPendingEvent.Subscribe(stoppedDownload =>
                            {
                                if (dl.Download == stoppedDownload)
                                {
                                    BackgroundTransferService.Remove(downloadRequest);
                                    dl.Download.State           = QueuedDownload.DownloadState.Stopped;
                                    dl.Download.DownloadedBytes = 0;
                                }
                            });
                            bw.ReportProgress(0, requestObserver.First().EventArgs.Request);
                            cancelOnStop.Dispose();
                        }
                        e.Result = activeDownload.Download;
                    }
                };
                worker.ProgressChanged += (sender, e) =>
                {
                    if (e.UserState is BackgroundTransferRequest)
                    {
                        BackgroundTransferRequest request = e.UserState as BackgroundTransferRequest;
                        if (request.TransferStatus != TransferStatus.Completed || request.TransferError is InvalidOperationException)
                        {
                            activeDownload.Download.DownloadedBytes = 0;
                        }
                        else
                        {
                            activeDownload.Download.DownloadedBytes = ((BackgroundTransferRequest)e.UserState).BytesReceived;
                        }
                    }
                    else
                    {
                        activeDownload.Download.DownloadedBytes = (long)e.UserState;
                    }
                };
                worker.RunWorkerCompleted += (sender, e) =>
                {
                    if (activeDownload is Transport.ActiveDownload)
                    {
                        startedDownloads.Remove(activeDownload.Download);

                        if (!IsFileDownloadSuccessfulOrResumed(e, activeDownload.Download))
                        {
                            _downloadStoppedEvent.OnNext(activeDownload.Download);
                        }
                    }
                    else
                    {
                        if (!e.Cancelled && e.Error == null)
                        {
                            startedDownloads.Remove(activeDownload.Download);
                            QueuedDownload result = (QueuedDownload)e.Result;
                            if (IsBackgroundTransferSuccesfull(((Transport.BackgroundDownload)activeDownload).Request, result))
                            {
                                _downloadCompletedEvent.OnNext(activeDownload.Download);
                                App.Engine.StatisticsManager.LogDownloadCompleted(activeDownload.Download, "Completed");
                            }
                            else
                            {
                                _downloadStoppedEvent.OnNext(activeDownload.Download);
                            }
                        }
                        else if (e.Error != null)
                        {
                            startedDownloads.Remove(download);
                            _downloadErrorEvent.OnNext(download);
                        }
                        else
                        {
                            try
                            {
                                BackgroundTransferService.Remove((activeDownload as Transport.BackgroundDownload).Request);
                                _downloadStoppedEvent.OnNext(activeDownload.Download);
                                startedDownloads.Remove(download);
                            }
                            catch (InvalidOperationException)
                            {
                                startedDownloads.Remove(download);
                            }
                        }
                    }
                };
                worker.RunWorkerAsync(activeDownload);
            },
                error =>
            {
                startedDownloads.Remove(download);

                if (IsFileMissingFromServer(error))
                {
                    _downloadErrorEvent.OnNext(download);
                    App.Engine.StatisticsManager.LogDownloadCompleted(download, "Error");
                }
                else
                {
                    _downloadStoppedEvent.OnNext(download);
                }
            }
                );
            return(new PendingDownloadCancelHandle(pendingDownload));
        }