public async Task <Episode> Build(SonarrSharp.Models.Episode episode) { var mediaFileId = new MediaFileId { Provider = Providers.Sonarr, MediaId = episode.SeriesId, FileId = episode.EpisodeFileId, }; var sessionRepo = await _sessionRepoFactory.GetRepo(); var allSessionsForCurrentEpisode = (await sessionRepo.GetAll()) .Where(session => session.MediaId == mediaFileId.ToString()) .ToList(); var lastSession = allSessionsForCurrentEpisode.OrderByDescending(session => session.EndUTC).FirstOrDefault(); return(new Episode { Title = GrpcStringParser.Parse(episode.Title), Overview = GrpcStringParser.Parse(episode.Overview), SeriesId = episode.SeriesId, SeasonNumber = episode.SeasonNumber, EpisideNumber = episode.EpisodeNumber, EpisodeFileId = episode.EpisodeFileId, PlayableId = mediaFileId.ToString(), Progress = new Progress { LastWatchedUtc = lastSession?.EndUTC ?? 0, WatchedInSec = lastSession?.Duration.EndPostionInSec ?? 0, Lenght = lastSession?.MediaLenghtInSec ?? 0 }, }); }
public MediaServer.Storage.ProtoGenerated.Session CreateNewSession ( MediaFileId mediaFileId, TimeSpan mediaDuration, TimeSpan?startPosition = null ) { var timeWatched = new Duration { EndPostionInSec = 0, StartPostionInSec = 0 }; if (startPosition.HasValue) { timeWatched.StartPostionInSec = startPosition.Value.TotalSeconds; timeWatched.EndPostionInSec = startPosition.Value.TotalSeconds; } var session = new MediaServer.Storage.ProtoGenerated.Session { Id = Guid.NewGuid().ToString("N"), MediaId = mediaFileId.ToString(), Duration = timeWatched, StartUTC = _timeService.GetCurrentTimeAsUnixSeconds(), EndUTC = _timeService.GetCurrentTimeAsUnixSeconds(), MediaLenghtInSec = mediaDuration.TotalSeconds, }; return(session); }
public async Task <ActionResult> DownloadFile(string mediaFileIdStr) { if (!MediaFileId.TryParse(mediaFileIdStr, out var mediaFileId)) { return(BadRequest($"{nameof(mediaFileIdStr)} is invalid")); } await _fileDownloadService.DownloadFile(mediaFileId); return(StatusCode(202)); }
public async Task <ActionResult> PlayMedia(string mediaFileIdStr, double startPositionInSec) { if (!MediaFileId.TryParse(mediaFileIdStr, out var mediaFileId)) { return(BadRequest($"{nameof(mediaFileIdStr)} is invalid")); } if (startPositionInSec < 0) { return(BadRequest($"{nameof(startPositionInSec)} must be > 0")); } var settings = _settingsService.Get(); if (string.IsNullOrWhiteSpace(settings.System.MpvPath)) { return(BadRequest("mpv path must be set in the settings tab")); } if (!_processManager.IsMpvRunning()) { var arguments = new[] { $"--input-ipc-server={NamedPipeFactory.GetPipeNameForCurrentOs()}" }; _processManager.StartProcess(settings.System.MpvPath, arguments); } if (!_processManager.IsSvpRunning() && !string.IsNullOrWhiteSpace(settings.System.SvpPath)) { _processManager.StartProcess(settings.System.SvpPath); } var fileInfo = await _fileLookupProvider.GetFileInfoForId(mediaFileId.FileId); _queue.AddToQueue(new Item { Path = fileInfo.Path, MediaFileId = mediaFileId, StartPosition = TimeSpan.FromSeconds(startPositionInSec), }); return(StatusCode(202)); }
public override async Task Download ( DownloadFileRequest request, IServerStreamWriter <ResponseDownloadFile> responseStream, ServerCallContext context ) { if (!MediaFileId.TryParse(request.MediaFileId, out var mediaFileId)) { throw new Exception("Invalid mediaFileId"); } var info = await _episodeFileLookupProvider.GetFileInfoForId(mediaFileId.FileId); var backSlashIndex = info.Path.LastIndexOf("\\", StringComparison.CurrentCultureIgnoreCase); var index = backSlashIndex > -1 ? backSlashIndex : info.Path.LastIndexOf("/", StringComparison.CurrentCultureIgnoreCase); var fileName = info.Path.Substring(index + 1); var chunkSize = 2048; using (Stream source = File.OpenRead(info.Path)) { byte[] buffer = new byte[chunkSize]; int bytesRead; await responseStream.WriteAsync(new ResponseDownloadFile { Started = new Started { FileName = fileName, Lenght = source.Length, SizePerChunk = chunkSize, } }); while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0) { await responseStream.WriteAsync(new ResponseDownloadFile { Progress = new Chunk { Content = ByteString.CopyFrom(buffer, 0, bytesRead) } }); } source.Seek(0, SeekOrigin.Begin); string hash; using (var md5 = MD5.Create()) { var byteHash = md5.ComputeHash(source); hash = BitConverter.ToString(byteHash).Replace("-", "").ToLowerInvariant(); } await responseStream.WriteAsync(new ResponseDownloadFile { Done = new Done { Hash = hash } }); } }
public async Task DownloadFile(MediaFileId id) { var streamingCall = _client.Download(new DownloadFileRequest { MediaFileId = id.ToString(), }); var settings = _settingsService.Get(); double nrOfChunks = 0; var currentChunk = 0; var currentTempFileIndex = 0; FileStream fileStream = null; const int tempFileSize = 1024 * 10 * 10; var fileName = ""; _logger.LogInformation($"Starting to download file"); var stopwatch = Stopwatch.StartNew(); while (await streamingCall.ResponseStream.MoveNext(CancellationToken.None)) { var res = streamingCall.ResponseStream.Current; switch (res.TypeCase) { case ResponseDownloadFile.TypeOneofCase.Started: fileName = res.Started.FileName; nrOfChunks = (int)Math.Ceiling(res.Started.Lenght / res.Started.SizePerChunk); _logger.LogTrace($"Length is {res.Started.Lenght}"); _logger.LogTrace($"ChunkSize is {res.Started.SizePerChunk}"); _logger.LogTrace($"Nr of chunks should be {nrOfChunks}"); break; case ResponseDownloadFile.TypeOneofCase.Progress: if (currentChunk % tempFileSize == 0) { if (fileStream != null) { fileStream.Close(); fileStream.Dispose(); } fileStream = File.Create(settings.System.TempFileDir + $"{fileName}.{currentTempFileIndex}.temp"); currentTempFileIndex++; } var byteArray = res.Progress.Content.ToByteArray(); await fileStream.WriteAsync(byteArray, 0, byteArray.Length); if (currentChunk % 1000 == 0) { _logger.LogTrace($"Progress {currentChunk / nrOfChunks:P}"); } currentChunk++; break; case ResponseDownloadFile.TypeOneofCase.Done: _logger.LogDebug($"Downloaded chunks in {stopwatch.Elapsed:g}"); fileStream.Close(); fileStream.Dispose(); var sw = Stopwatch.StartNew(); var filePattern = $"{fileName}.*.temp"; await _fileService.CombineMultipleFilesIntoSingleFile(settings.System.TempFileDir, filePattern, settings.System.FileDir + fileName); string hash; using (Stream source = File.OpenRead(settings.System.FileDir + fileName)) using (var md5 = MD5.Create()) { var byteHash = md5.ComputeHash(source); hash = BitConverter.ToString(byteHash).Replace("-", "").ToLowerInvariant(); } // TODO //This needs to be the zip:ed file, else there will be a missmatch. // if (hash != res.Done.Hash) // { // throw new HashMismatchException(res.Done.Hash, hash); // } _logger.LogDebug($"Combined files in {sw.Elapsed:g}"); sw.Stop(); break; case ResponseDownloadFile.TypeOneofCase.None: default: throw new ArgumentOutOfRangeException(); } } stopwatch.Stop(); _logger.LogInformation($"It took {stopwatch.Elapsed:g}"); }