diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index bb9d2b8645..7c5f7cde40 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -192,13 +192,13 @@ namespace MediaBrowser.Api _activeTranscodingJobs.Add(job); - ReportTranscodingProgress(job, state, null, null, null, null); + ReportTranscodingProgress(job, state, null, null, null, null, null); return job; } } - public void ReportTranscodingProgress(TranscodingJob job, StreamState state, TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded) + public void ReportTranscodingProgress(TranscodingJob job, StreamState state, TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate) { var ticks = transcodingPosition.HasValue ? transcodingPosition.Value.Ticks : (long?)null; @@ -208,6 +208,7 @@ namespace MediaBrowser.Api job.CompletionPercentage = percentComplete; job.TranscodingPositionTicks = ticks; job.BytesTranscoded = bytesTranscoded; + job.BitRate = bitRate; } var deviceId = state.Request.DeviceId; @@ -219,7 +220,7 @@ namespace MediaBrowser.Api _sessionManager.ReportTranscodingInfo(deviceId, new TranscodingInfo { - Bitrate = state.TotalOutputBitrate, + Bitrate = bitRate ?? state.TotalOutputBitrate, AudioCodec = audioCodec, VideoCodec = videoCodec, Container = state.OutputContainer, @@ -694,6 +695,7 @@ namespace MediaBrowser.Api public long? BytesDownloaded { get; set; } public long? BytesTranscoded { get; set; } + public int? BitRate { get; set; } public long? TranscodingPositionTicks { get; set; } public long? DownloadPositionTicks { get; set; } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index a8992ccbb5..fa4be8fc24 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1178,6 +1178,7 @@ namespace MediaBrowser.Api.Playback double? percent = null; TimeSpan? transcodingPosition = null; long? bytesTranscoded = null; + int? bitRate = null; var parts = line.Split(' '); @@ -1241,11 +1242,32 @@ namespace MediaBrowser.Api.Playback } } } + else if (part.StartsWith("bitrate=", StringComparison.OrdinalIgnoreCase)) + { + var rate = part.Split(new[] { '=' }, 2).Last(); + + int? scale = null; + if (rate.IndexOf("kbits/s", StringComparison.OrdinalIgnoreCase) != -1) + { + scale = 1024; + rate = rate.Replace("kbits/s", string.Empty, StringComparison.OrdinalIgnoreCase); + } + + if (scale.HasValue) + { + float val; + + if (float.TryParse(rate, NumberStyles.Any, UsCulture, out val)) + { + bitRate = (int)Math.Ceiling(val * scale.Value); + } + } + } } if (framerate.HasValue || percent.HasValue) { - ApiEntryPoint.Instance.ReportTranscodingProgress(transcodingJob, state, transcodingPosition, framerate, percent, bytesTranscoded); + ApiEntryPoint.Instance.ReportTranscodingProgress(transcodingJob, state, transcodingPosition, framerate, percent, bytesTranscoded, bitRate); } } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index 2109f8d59e..39992b65dd 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -43,13 +43,6 @@ namespace MediaBrowser.Server.Implementations.FileOrganization _providerManager = providerManager; } - public Task OrganizeEpisodeFile(string path, CancellationToken cancellationToken) - { - var options = _config.GetAutoOrganizeOptions(); - - return OrganizeEpisodeFile(path, options, false, cancellationToken); - } - public async Task OrganizeEpisodeFile(string path, AutoOrganizeOptions options, bool overwriteExisting, CancellationToken cancellationToken) { _logger.Info("Sorting file {0}", path); @@ -63,6 +56,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization FileSize = new FileInfo(path).Length }; + try + { if (_libraryMonitor.IsPathLocked(path)) { result.Status = FileSortingStatus.Failure; @@ -148,6 +143,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false); + } + catch (Exception ex) + { + result.Status = FileSortingStatus.Failure; + result.StatusMessage = ex.Message; + } return result; } @@ -156,6 +157,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization { var result = _organizationService.GetResult(request.ResultId); + try + { Series series = null; if (request.NewSeriesProviderIds.Count > 0) @@ -207,6 +210,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization cancellationToken).ConfigureAwait(false); await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false); + } + catch (Exception ex) + { + result.Status = FileSortingStatus.Failure; + result.StatusMessage = ex.Message; + } return result; } @@ -263,16 +272,15 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var originalExtractedSeriesString = result.ExtractedName; + try + { // Proceed to sort the file var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options.TvOptions, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(newPath)) { var msg = string.Format("Unable to sort {0} because target path could not be determined.", sourcePath); - result.Status = FileSortingStatus.Failure; - result.StatusMessage = msg; - _logger.Warn(msg); - return; + throw new Exception(msg); } _logger.Info("Sorting file {0} to new path {1}", sourcePath, newPath); @@ -347,6 +355,14 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } } } + } + catch (Exception ex) + { + result.Status = FileSortingStatus.Failure; + result.StatusMessage = ex.Message; + _logger.Warn(ex.Message); + return; + } if (rememberCorrection) { @@ -505,7 +521,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } catch (Exception ex) { - var errorMsg = string.Format("Failed to move file from {0} to {1}", result.OriginalPath, result.TargetPath); + var errorMsg = string.Format("Failed to move file from {0} to {1}: {2}", result.OriginalPath, result.TargetPath, ex.Message); result.Status = FileSortingStatus.Failure; result.StatusMessage = errorMsg; @@ -616,7 +632,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization { var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber); _logger.Warn(msg); - return null; + throw new Exception(msg); } var episodeName = episode.Name; @@ -715,6 +731,11 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var pattern = endingEpisodeNumber.HasValue ? options.MultiEpisodeNamePattern : options.EpisodeNamePattern; + if (string.IsNullOrWhiteSpace(pattern)) + { + throw new Exception("GetEpisodeFileName: Configured episode name pattern is empty!"); + } + var result = pattern.Replace("%sn", seriesName) .Replace("%s.n", seriesName.Replace(" ", ".")) .Replace("%s_n", seriesName.Replace(" ", "_")) @@ -759,8 +780,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization // There may be cases where reducing the title length may still not be sufficient to // stay below maxLength var msg = string.Format("Unable to generate an episode file name shorter than {0} characters to constrain to the max path limit", maxLength); - _logger.Warn(msg); - return string.Empty; + throw new Exception(msg); } return result; diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs index 60d515e120..9e16613e62 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs @@ -112,8 +112,13 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); - await organizer.OrganizeEpisodeFile(result.OriginalPath, GetAutoOrganizeOptions(), true, CancellationToken.None) + var organizeResult = await organizer.OrganizeEpisodeFile(result.OriginalPath, GetAutoOrganizeOptions(), true, CancellationToken.None) .ConfigureAwait(false); + + if (organizeResult.Status != FileSortingStatus.Success) + { + throw new Exception(result.StatusMessage); + } } public Task ClearLog() @@ -126,7 +131,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); - await organizer.OrganizeWithCorrection(request, GetAutoOrganizeOptions(), CancellationToken.None).ConfigureAwait(false); + var result = await organizer.OrganizeWithCorrection(request, GetAutoOrganizeOptions(), CancellationToken.None).ConfigureAwait(false); + + if (result.Status != FileSortingStatus.Success) + { + throw new Exception(result.StatusMessage); + } } public QueryResult GetSmartMatchInfos(FileOrganizationResultQuery query) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 3d8e7a3d6d..6acb0783eb 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1139,7 +1139,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV var organize = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); - var result = await organize.OrganizeEpisodeFile(path, CancellationToken.None).ConfigureAwait(false); + var result = await organize.OrganizeEpisodeFile(path, _config.GetAutoOrganizeOptions(), false, CancellationToken.None).ConfigureAwait(false); } catch (Exception ex) {