|
@@ -15,7 +15,6 @@ using MediaBrowser.Model.Events;
|
|
using MediaBrowser.Model.LiveTv;
|
|
using MediaBrowser.Model.LiveTv;
|
|
using MediaBrowser.Model.Logging;
|
|
using MediaBrowser.Model.Logging;
|
|
using MediaBrowser.Model.Serialization;
|
|
using MediaBrowser.Model.Serialization;
|
|
-using MediaBrowser.Server.Implementations.FileOrganization;
|
|
|
|
using System;
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
@@ -35,10 +34,12 @@ using MediaBrowser.Controller.Entities;
|
|
using MediaBrowser.Controller.Entities.TV;
|
|
using MediaBrowser.Controller.Entities.TV;
|
|
using MediaBrowser.Controller.IO;
|
|
using MediaBrowser.Controller.IO;
|
|
using MediaBrowser.Model.Configuration;
|
|
using MediaBrowser.Model.Configuration;
|
|
|
|
+using MediaBrowser.Model.Diagnostics;
|
|
using MediaBrowser.Model.FileOrganization;
|
|
using MediaBrowser.Model.FileOrganization;
|
|
-using Microsoft.Win32;
|
|
|
|
|
|
+using MediaBrowser.Model.System;
|
|
|
|
+using MediaBrowser.Model.Threading;
|
|
|
|
|
|
-namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
|
|
|
|
+namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|
{
|
|
{
|
|
public class EmbyTV : ILiveTvService, ISupportsDirectStreamProvider, ISupportsNewTimerIds, IDisposable
|
|
public class EmbyTV : ILiveTvService, ISupportsDirectStreamProvider, ISupportsNewTimerIds, IDisposable
|
|
{
|
|
{
|
|
@@ -59,6 +60,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
private readonly IProviderManager _providerManager;
|
|
private readonly IProviderManager _providerManager;
|
|
private readonly IFileOrganizationService _organizationService;
|
|
private readonly IFileOrganizationService _organizationService;
|
|
private readonly IMediaEncoder _mediaEncoder;
|
|
private readonly IMediaEncoder _mediaEncoder;
|
|
|
|
+ private readonly IProcessFactory _processFactory;
|
|
|
|
+ private readonly ISystemEvents _systemEvents;
|
|
|
|
|
|
public static EmbyTV Current;
|
|
public static EmbyTV Current;
|
|
|
|
|
|
@@ -68,7 +71,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
private readonly ConcurrentDictionary<string, ActiveRecordingInfo> _activeRecordings =
|
|
private readonly ConcurrentDictionary<string, ActiveRecordingInfo> _activeRecordings =
|
|
new ConcurrentDictionary<string, ActiveRecordingInfo>(StringComparer.OrdinalIgnoreCase);
|
|
new ConcurrentDictionary<string, ActiveRecordingInfo>(StringComparer.OrdinalIgnoreCase);
|
|
|
|
|
|
- public EmbyTV(IServerApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder)
|
|
|
|
|
|
+ public EmbyTV(IServerApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder, ITimerFactory timerFactory, IProcessFactory processFactory, ISystemEvents systemEvents)
|
|
{
|
|
{
|
|
Current = this;
|
|
Current = this;
|
|
|
|
|
|
@@ -82,11 +85,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
_providerManager = providerManager;
|
|
_providerManager = providerManager;
|
|
_organizationService = organizationService;
|
|
_organizationService = organizationService;
|
|
_mediaEncoder = mediaEncoder;
|
|
_mediaEncoder = mediaEncoder;
|
|
|
|
+ _processFactory = processFactory;
|
|
|
|
+ _systemEvents = systemEvents;
|
|
_liveTvManager = (LiveTvManager)liveTvManager;
|
|
_liveTvManager = (LiveTvManager)liveTvManager;
|
|
_jsonSerializer = jsonSerializer;
|
|
_jsonSerializer = jsonSerializer;
|
|
|
|
|
|
_seriesTimerProvider = new SeriesTimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers"));
|
|
_seriesTimerProvider = new SeriesTimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers"));
|
|
- _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger);
|
|
|
|
|
|
+ _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger, timerFactory);
|
|
_timerProvider.TimerFired += _timerProvider_TimerFired;
|
|
_timerProvider.TimerFired += _timerProvider_TimerFired;
|
|
|
|
|
|
_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
|
|
_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
|
|
@@ -104,10 +109,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
{
|
|
{
|
|
_timerProvider.RestartTimers();
|
|
_timerProvider.RestartTimers();
|
|
|
|
|
|
- SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
|
|
|
|
|
|
+ _systemEvents.Resume += _systemEvents_Resume;
|
|
CreateRecordingFolders();
|
|
CreateRecordingFolders();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private void _systemEvents_Resume(object sender, EventArgs e)
|
|
|
|
+ {
|
|
|
|
+ _timerProvider.RestartTimers();
|
|
|
|
+ }
|
|
|
|
+
|
|
private void OnRecordingFoldersChanged()
|
|
private void OnRecordingFoldersChanged()
|
|
{
|
|
{
|
|
CreateRecordingFolders();
|
|
CreateRecordingFolders();
|
|
@@ -231,16 +241,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
|
|
|
- {
|
|
|
|
- _logger.Info("Power mode changed to {0}", e.Mode);
|
|
|
|
-
|
|
|
|
- if (e.Mode == PowerModes.Resume)
|
|
|
|
- {
|
|
|
|
- _timerProvider.RestartTimers();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
public string Name
|
|
public string Name
|
|
{
|
|
{
|
|
get { return "Emby"; }
|
|
get { return "Emby"; }
|
|
@@ -988,7 +988,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
_liveStreamsSemaphore.Release();
|
|
_liveStreamsSemaphore.Release();
|
|
}
|
|
}
|
|
|
|
|
|
- throw new ApplicationException("Tuner not found.");
|
|
|
|
|
|
+ throw new Exception("Tuner not found.");
|
|
}
|
|
}
|
|
|
|
|
|
public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken)
|
|
public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken)
|
|
@@ -1031,7 +1031,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
IsInfiniteStream = true,
|
|
IsInfiniteStream = true,
|
|
RequiresOpening = false,
|
|
RequiresOpening = false,
|
|
RequiresClosing = false,
|
|
RequiresClosing = false,
|
|
- Protocol = Model.MediaInfo.MediaProtocol.Http,
|
|
|
|
|
|
+ Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http,
|
|
BufferMs = 0
|
|
BufferMs = 0
|
|
};
|
|
};
|
|
|
|
|
|
@@ -1353,7 +1353,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
timer.StartDate = DateTime.UtcNow.AddSeconds(retryIntervalSeconds);
|
|
timer.StartDate = DateTime.UtcNow.AddSeconds(retryIntervalSeconds);
|
|
_timerProvider.AddOrUpdate(timer);
|
|
_timerProvider.AddOrUpdate(timer);
|
|
}
|
|
}
|
|
- else if (File.Exists(recordPath))
|
|
|
|
|
|
+ else if (_fileSystem.FileExists(recordPath))
|
|
{
|
|
{
|
|
timer.RecordingPath = recordPath;
|
|
timer.RecordingPath = recordPath;
|
|
timer.Status = RecordingStatus.Completed;
|
|
timer.Status = RecordingStatus.Completed;
|
|
@@ -1409,7 +1409,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
.Where(i => i.Status == RecordingStatus.Completed && !string.IsNullOrWhiteSpace(i.RecordingPath))
|
|
.Where(i => i.Status == RecordingStatus.Completed && !string.IsNullOrWhiteSpace(i.RecordingPath))
|
|
.Where(i => string.Equals(i.SeriesTimerId, seriesTimerId, StringComparison.OrdinalIgnoreCase))
|
|
.Where(i => string.Equals(i.SeriesTimerId, seriesTimerId, StringComparison.OrdinalIgnoreCase))
|
|
.OrderByDescending(i => i.EndDate)
|
|
.OrderByDescending(i => i.EndDate)
|
|
- .Where(i => File.Exists(i.RecordingPath))
|
|
|
|
|
|
+ .Where(i => _fileSystem.FileExists(i.RecordingPath))
|
|
.Skip(seriesTimer.KeepUpTo - 1)
|
|
.Skip(seriesTimer.KeepUpTo - 1)
|
|
.ToList();
|
|
.ToList();
|
|
|
|
|
|
@@ -1457,13 +1457,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
{
|
|
{
|
|
try
|
|
try
|
|
{
|
|
{
|
|
- File.Delete(timer.RecordingPath);
|
|
|
|
|
|
+ _fileSystem.DeleteFile(timer.RecordingPath);
|
|
}
|
|
}
|
|
- catch (DirectoryNotFoundException)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
- catch (FileNotFoundException)
|
|
|
|
|
|
+ catch (IOException)
|
|
{
|
|
{
|
|
|
|
|
|
}
|
|
}
|
|
@@ -1519,7 +1515,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
|
|
|
|
if (regInfo.IsValid)
|
|
if (regInfo.IsValid)
|
|
{
|
|
{
|
|
- return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config, _httpClient);
|
|
|
|
|
|
+ return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config, _httpClient, _processFactory);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1528,28 +1524,28 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
|
|
|
|
private async void OnSuccessfulRecording(TimerInfo timer, string path)
|
|
private async void OnSuccessfulRecording(TimerInfo timer, string path)
|
|
{
|
|
{
|
|
- if (timer.IsProgramSeries && GetConfiguration().EnableAutoOrganize)
|
|
|
|
- {
|
|
|
|
- try
|
|
|
|
- {
|
|
|
|
- // this is to account for the library monitor holding a lock for additional time after the change is complete.
|
|
|
|
- // ideally this shouldn't be hard-coded
|
|
|
|
- await Task.Delay(30000).ConfigureAwait(false);
|
|
|
|
-
|
|
|
|
- var organize = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager);
|
|
|
|
-
|
|
|
|
- var result = await organize.OrganizeEpisodeFile(path, _config.GetAutoOrganizeOptions(), false, CancellationToken.None).ConfigureAwait(false);
|
|
|
|
-
|
|
|
|
- if (result.Status == FileSortingStatus.Success)
|
|
|
|
- {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- catch (Exception ex)
|
|
|
|
- {
|
|
|
|
- _logger.ErrorException("Error processing new recording", ex);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ //if (timer.IsProgramSeries && GetConfiguration().EnableAutoOrganize)
|
|
|
|
+ //{
|
|
|
|
+ // try
|
|
|
|
+ // {
|
|
|
|
+ // // this is to account for the library monitor holding a lock for additional time after the change is complete.
|
|
|
|
+ // // ideally this shouldn't be hard-coded
|
|
|
|
+ // await Task.Delay(30000).ConfigureAwait(false);
|
|
|
|
+
|
|
|
|
+ // var organize = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager);
|
|
|
|
+
|
|
|
|
+ // var result = await organize.OrganizeEpisodeFile(path, _config.GetAutoOrganizeOptions(), false, CancellationToken.None).ConfigureAwait(false);
|
|
|
|
+
|
|
|
|
+ // if (result.Status == FileSortingStatus.Success)
|
|
|
|
+ // {
|
|
|
|
+ // return;
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // catch (Exception ex)
|
|
|
|
+ // {
|
|
|
|
+ // _logger.ErrorException("Error processing new recording", ex);
|
|
|
|
+ // }
|
|
|
|
+ //}
|
|
}
|
|
}
|
|
|
|
|
|
private void SaveNfo(TimerInfo timer, string recordingPath, string seriesPath)
|
|
private void SaveNfo(TimerInfo timer, string recordingPath, string seriesPath)
|
|
@@ -1575,7 +1571,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
{
|
|
{
|
|
var nfoPath = Path.Combine(seriesPath, "tvshow.nfo");
|
|
var nfoPath = Path.Combine(seriesPath, "tvshow.nfo");
|
|
|
|
|
|
- if (File.Exists(nfoPath))
|
|
|
|
|
|
+ if (_fileSystem.FileExists(nfoPath))
|
|
{
|
|
{
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -1610,7 +1606,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
{
|
|
{
|
|
var nfoPath = Path.ChangeExtension(recordingPath, ".nfo");
|
|
var nfoPath = Path.ChangeExtension(recordingPath, ".nfo");
|
|
|
|
|
|
- if (File.Exists(nfoPath))
|
|
|
|
|
|
+ if (_fileSystem.FileExists(nfoPath))
|
|
{
|
|
{
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -1931,7 +1927,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
var defaultFolder = RecordingPath;
|
|
var defaultFolder = RecordingPath;
|
|
var defaultName = "Recordings";
|
|
var defaultName = "Recordings";
|
|
|
|
|
|
- if (Directory.Exists(defaultFolder))
|
|
|
|
|
|
+ if (_fileSystem.DirectoryExists(defaultFolder))
|
|
{
|
|
{
|
|
list.Add(new VirtualFolderInfo
|
|
list.Add(new VirtualFolderInfo
|
|
{
|
|
{
|
|
@@ -1941,7 +1937,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
}
|
|
}
|
|
|
|
|
|
var customPath = GetConfiguration().MovieRecordingPath;
|
|
var customPath = GetConfiguration().MovieRecordingPath;
|
|
- if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && Directory.Exists(customPath))
|
|
|
|
|
|
+ if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && _fileSystem.DirectoryExists(customPath))
|
|
{
|
|
{
|
|
list.Add(new VirtualFolderInfo
|
|
list.Add(new VirtualFolderInfo
|
|
{
|
|
{
|
|
@@ -1952,7 +1948,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|
}
|
|
}
|
|
|
|
|
|
customPath = GetConfiguration().SeriesRecordingPath;
|
|
customPath = GetConfiguration().SeriesRecordingPath;
|
|
- if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && Directory.Exists(customPath))
|
|
|
|
|
|
+ if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && _fileSystem.DirectoryExists(customPath))
|
|
{
|
|
{
|
|
list.Add(new VirtualFolderInfo
|
|
list.Add(new VirtualFolderInfo
|
|
{
|
|
{
|