diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index ea8510b536..dbc0fc2827 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1651,6 +1651,11 @@ namespace MediaBrowser.Controller.Entities return AddImages(imageType, images.Cast().ToList()); } + public bool AddImages(ImageType imageType, IEnumerable images) + { + return AddImages(imageType, images.ToList()); + } + /// /// Adds the images. /// diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index 8ca16832da..73bc4984c8 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -62,16 +62,22 @@ namespace MediaBrowser.Dlna.Ssdp { if (string.Equals(args.Method, "M-SEARCH", StringComparison.OrdinalIgnoreCase)) { - TimeSpan delay = GetSearchDelay(args.Headers); + var headers = args.Headers; + + TimeSpan delay = GetSearchDelay(headers); if (_config.GetDlnaConfiguration().EnableDebugLogging) { _logger.Debug("Delaying search response by {0} seconds", delay.TotalSeconds); } - await Task.Delay(delay).ConfigureAwait(false); + await Task.Delay(delay).ConfigureAwait(false); - RespondToSearch(args.EndPoint, args.Headers["st"]); + string st; + if (headers.TryGetValue("st", out st)) + { + RespondToSearch(args.EndPoint, st); + } } EventHelper.FireEventIfNotNull(MessageReceived, this, args, _logger); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index c309739d01..0bf0075722 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -75,7 +75,7 @@ namespace MediaBrowser.MediaEncoding.Encoder protected readonly Func SubtitleEncoder; protected readonly Func MediaSourceManager; - private readonly List _runningProcesses = new List(); + private readonly List _runningProcesses = new List(); public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func subtitleEncoder, Func mediaSourceManager) { @@ -197,9 +197,11 @@ namespace MediaBrowser.MediaEncoding.Encoder await _ffProbeResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + var processWrapper = new ProcessWrapper(process, this); + try { - StartProcess(process); + StartProcess(processWrapper); } catch (Exception ex) { @@ -264,7 +266,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch { - StopProcess(process, 100, true); + StopProcess(processWrapper, 100, true); throw; } @@ -303,7 +305,9 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - StartProcess(process); + var processWrapper = new ProcessWrapper(process, this); + + StartProcess(processWrapper); var lines = new List(); var outputCancellationSource = new CancellationTokenSource(4000); @@ -325,7 +329,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } finally { - StopProcess(process, 100, true); + StopProcess(processWrapper, 100, true); } return lines; @@ -382,23 +386,6 @@ namespace MediaBrowser.MediaEncoding.Encoder /// protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - /// - /// Processes the exited. - /// - /// The sender. - /// The instance containing the event data. - private void ProcessExited(object sender, EventArgs e) - { - var process = (Process) sender; - - lock (_runningProcesses) - { - _runningProcesses.Remove(process); - } - - process.Dispose(); - } - public Task ExtractAudioImage(string path, CancellationToken cancellationToken) { return ExtractImage(new[] { path }, MediaProtocol.File, true, null, null, cancellationToken); @@ -423,6 +410,10 @@ namespace MediaBrowser.MediaEncoding.Encoder { return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false); } + catch (ArgumentException) + { + throw; + } catch { _logger.Error("I-frame image extraction failed, will attempt standard way. Input: {0}", inputArgument); @@ -505,7 +496,9 @@ namespace MediaBrowser.MediaEncoding.Encoder await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - StartProcess(process); + var processWrapper = new ProcessWrapper(process, this); + + StartProcess(processWrapper); var memoryStream = new MemoryStream(); @@ -521,12 +514,12 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!ranToCompletion) { - StopProcess(process, 1000, false); + StopProcess(processWrapper, 1000, false); } resourcePool.Release(); - var exitCode = ranToCompletion ? process.ExitCode : -1; + var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; process.Dispose(); @@ -611,9 +604,11 @@ namespace MediaBrowser.MediaEncoding.Encoder bool ranToCompletion; + var processWrapper = new ProcessWrapper(process, this); + try { - StartProcess(process); + StartProcess(processWrapper); // Need to give ffmpeg enough time to make all the thumbnails, which could be a while, // but we still need to detect if the process hangs. @@ -637,7 +632,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!ranToCompletion) { - StopProcess(process, 1000, false); + StopProcess(processWrapper, 1000, false); } } finally @@ -645,7 +640,7 @@ namespace MediaBrowser.MediaEncoding.Encoder resourcePool.Release(); } - var exitCode = ranToCompletion ? process.ExitCode : -1; + var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; process.Dispose(); @@ -699,18 +694,16 @@ namespace MediaBrowser.MediaEncoding.Encoder return job.OutputFilePath; } - private void StartProcess(Process process) + private void StartProcess(ProcessWrapper process) { - process.Exited += ProcessExited; - - process.Start(); + process.Process.Start(); lock (_runningProcesses) { _runningProcesses.Add(process); } } - private void StopProcess(Process process, int waitTimeMs, bool enableForceKill) + private void StopProcess(ProcessWrapper process, int waitTimeMs, bool enableForceKill) { try { @@ -718,7 +711,7 @@ namespace MediaBrowser.MediaEncoding.Encoder try { - process.StandardInput.WriteLine("q"); + process.Process.StandardInput.WriteLine("q"); } catch (Exception) { @@ -727,7 +720,7 @@ namespace MediaBrowser.MediaEncoding.Encoder try { - if (process.WaitForExit(waitTimeMs)) + if (process.Process.WaitForExit(waitTimeMs)) { return; } @@ -739,7 +732,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (enableForceKill) { - process.Kill(); + process.Process .Kill(); } } catch (Exception ex) @@ -750,7 +743,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private void StopProcesses() { - List proceses; + List proceses; lock (_runningProcesses) { proceses = _runningProcesses.ToList(); @@ -782,5 +775,36 @@ namespace MediaBrowser.MediaEncoding.Encoder StopProcesses(); } } + + private class ProcessWrapper + { + public readonly Process Process; + public bool HasExited; + public int? ExitCode; + private readonly MediaEncoder _mediaEncoder; + + public ProcessWrapper(Process process, MediaEncoder mediaEncoder) + { + Process = process; + this._mediaEncoder = mediaEncoder; + Process.Exited += Process_Exited; + } + + void Process_Exited(object sender, EventArgs e) + { + var process = (Process)sender; + + HasExited = true; + + ExitCode = process.ExitCode; + + lock (_mediaEncoder._runningProcesses) + { + _mediaEncoder._runningProcesses.Remove(this); + } + + process.Dispose(); + } + } } } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index b1bc5dbe54..03daa4c2a7 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; @@ -69,7 +70,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// The instance containing the event data. void libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) { - if (e.Item.LocationType == LocationType.Virtual) + if (!FilterItem(e.Item)) { return; } @@ -102,7 +103,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// The instance containing the event data. void libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e) { - if (e.Item.LocationType == LocationType.Virtual) + if (!FilterItem(e.Item)) { return; } @@ -130,7 +131,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// The instance containing the event data. void libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e) { - if (e.Item.LocationType == LocationType.Virtual) + if (!FilterItem(e.Item)) { return; } @@ -257,6 +258,16 @@ namespace MediaBrowser.Server.Implementations.EntryPoints }; } + private bool FilterItem(BaseItem item) + { + if (item.LocationType == LocationType.Virtual) + { + return false; + } + + return !(item is IChannelItem); + } + /// /// Translates the physical item to user library. /// diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs index 56557d6e1d..6b99883a52 100644 --- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -151,8 +151,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder chapter.ImagePath = path; changesMade = true; } - catch + catch (Exception ex) { + _logger.ErrorException("Error extraching chapter images for {0}", ex, string.Join(",", inputPath)); success = false; break; }