private static void UpdateDownloadStoreWithError(Download download, string errorMessage)
		{
			using (var udm = UtilityDataModel.NewContext())
			{
				udm.Attach(download);
				download.ErrorMessage = errorMessage;
				download.LastDownloadUpdate = DateTime.Now;
				udm.SaveAndRefreshDataModel(udm.Downloads);
				udm.Detach(download);
			}
		}
		/// <summary>
		/// Downloads the specified <see cref="AVItem"/> path.
		/// </summary>
		/// <param name="download">A <see cref="tubeCentric.Shared.Download"/> object that can be redownloaded</param>
		public void Download(Download download)
		{
			var path = download.Path;

			Write(string.Format(@"Request {0}: " + path, DateTime.Now.ToShortTimeString()));

			Interrupted = false;

			var downloader = new LaunchMpeg2DvrmsCommandLine(OnPlaybackReady)
			{
				ForStorageOnly = true
			};
			downloader.OnConversionStopped += OnDownloadingStopped;

			using (var udm = UtilityDataModel.NewContext())
			{
				udm.Attach(download);
				var downloadAttempts = download.DownloadAttemptedCount + 1;
				download.Clear();
				download.FilePath = downloader.GetPlaybackFile().FullName;
				download.IsDownloading = true;
				download.DownloadAttemptedCount = downloadAttempts;
				udm.SaveAndRefreshDataModel(udm.Downloads);
				udm.Detach(download);
			}
			DownloadInfo.Download = download;

			var deviceName = Utility.GetDeviceNameFromPath(path);
			var device = OnGetDevice(deviceName);
			if (device == null)
			{
				var error = "Could not find device: " + deviceName;
				Write(error);
				throw new DeviceLocateException(error, deviceName);
			}

			var item = (AVItem)Utility.GetItemFromPath(device, path);
			if (item == null)
			{
				var error = "Could not find path: " + path;
				Write(error);
				throw new PathLocateException(error, path);
			}

			Write(@"Waiting for download to start...");
			if (!downloader.StartConversion(item, download))
			{
				Write(@"Start conversion call failed.");
				throw new tubeCentricException("Could not start the download.");
			}

			var start = DateTime.Now;
			var ts = DateTime.Now - start;
			while (ts.TotalSeconds < 60 && !downloader.IsConversionActive && !Interrupted)
			{
				ts = DateTime.Now - start;
				Thread.Sleep(100);
			}
			if (!Interrupted)
			{
				var status = downloader.GetDownloadedStatus();
				start = DateTime.Now;
				ts = DateTime.Now - start;
				while (ts.TotalSeconds < 60 && status == null)
				{
					ts = DateTime.Now - start;
					Thread.Sleep(100);
					status = downloader.GetDownloadedStatus();
				}
				Write(string.Format("Waited {0} seconds for download status.", ts.TotalSeconds));
				if (status != null)
					Write(@"Starting download: " + path);
				while (downloader.IsConversionActive && !Interrupted)
				{
					status = downloader.GetDownloadedStatus();
					if (status == null)
					{	// download done
						Write(@"Could not get a status on the file. Might have exited with error.", NotificationLevel.Error);
						SyncDownloadInfo(status);
						OnSaveProgress();
						break;
					}
					download.IsDownloading = downloader.IsConversionActive;
					SyncDownloadInfo(status);
					OnSaveProgress();
					Write(string.Format(@"{1}/{0}, {2}%, {3}              ",
										status.DownloadTotal, status.DownloadCurrent,
										status.PercentComplete, status.CurrentFileSize), NotificationLevel.Tip);
					if (status.PercentComplete > 100)
					{
						Logger.TraceWarn("Download of {0} went beyond 100%. Stopping automatically.", download.Path);
						break;
					}
					Thread.Sleep(5000);	// give a chance to read the download queue and for listeners to keep up
				}
				if (Interrupted)
				{
					bool fileDeleted = false;
					try
					{
						File.Delete(downloader.GetPlaybackFile().FullName);
						fileDeleted = true;
					}
					catch (Exception)
					{
						Write(@"Could not delete the file after it was interrupted.");
					}
					finally
					{
						var filePath = DownloadInfo.Download.FilePath;
						if (fileDeleted)
						{
							filePath = string.Empty;
						}
						// clear everything except the number of download attempts
						var downloadAttemptedCount = DownloadInfo.Download.DownloadAttemptedCount;
						DownloadInfo.Download.Clear();
						DownloadInfo.Download.DownloadAttemptedCount = downloadAttemptedCount;
						DownloadInfo.Download.FilePath = filePath;
						DownloadInfo.Download.IsDownloading = false;
						OnSaveProgress();
					}
				}
				else
				{
					OnSaveProgress();
					Write(@"Completed " + path);
				}
			}
			else
			{
				var message = @"Download was interrupted " + path;
				Write(message);
				throw new DownloadInterruptedException(message);
			}
		}
		private void CleanupDownload(Download download)
		{
			using (var udm = UtilityDataModel.NewContext())
			{
				try
				{
					ActiveDownloads.Remove(download.Path);
					udm.Attach(download);
					download.IsDownloading = false;
					udm.SaveAndRefreshDataModel(udm.Downloads);
					udm.Detach(download);
				}
				catch (Exception exception)
				{
					Logger.TraceErr(exception);
				}
			}
		}
		public void ResetDownload(Download download)
		{
			using (var udm = UtilityDataModel.NewContext())
			{
				udm.Attach(download);
				download.IsDownloading = false;
				download.PercentComplete = 0;
				download.DownloadAttemptedCount = 0;
				udm.SaveAndRefreshDataModel(udm.Downloads);
				udm.Detach(download);
			}
		}