aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Photos/PhotoProvider.cs16
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs13
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs2
-rw-r--r--Emby.Server.Implementations/Devices/DeviceManager.cs27
-rw-r--r--Emby.Server.Implementations/Devices/DeviceRepository.cs212
-rw-r--r--Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs451
-rw-r--r--Emby.Server.Implementations/Emby.Server.Implementations.csproj2
-rw-r--r--Emby.Server.Implementations/HttpClientManager/HttpClientInfo.cs2
-rw-r--r--Emby.Server.Implementations/Library/MediaSourceManager.cs16
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs13
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs7
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs34
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs12
-rw-r--r--MediaBrowser.Api/Devices/DeviceService.cs8
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs4
-rw-r--r--MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs13
-rw-r--r--MediaBrowser.Controller/Devices/IDeviceManager.cs13
-rw-r--r--MediaBrowser.Controller/Devices/IDeviceRepository.cs13
-rw-r--r--MediaBrowser.Controller/Entities/AudioBook.cs6
-rw-r--r--MediaBrowser.Controller/Entities/Book.cs6
-rw-r--r--MediaBrowser.Controller/Entities/Game.cs6
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvChannel.cs3
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj1
-rw-r--r--MediaBrowser.Controller/Providers/IHasChangeMonitor.cs17
-rw-r--r--MediaBrowser.Model/Devices/DeviceInfo.cs12
-rw-r--r--MediaBrowser.Model/Dlna/StreamBuilder.cs29
-rw-r--r--MediaBrowser.Model/Dlna/StreamInfo.cs4
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs66
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs16
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs27
-rw-r--r--MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs16
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbSearch.cs6
-rw-r--r--MediaBrowser.Providers/TV/MissingEpisodeProvider.cs4
-rw-r--r--SharedVersion.cs2
34 files changed, 618 insertions, 461 deletions
diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs
index b2d6ecdcb..3a29b86a5 100644
--- a/Emby.Photos/PhotoProvider.cs
+++ b/Emby.Photos/PhotoProvider.cs
@@ -17,7 +17,7 @@ using TagLib.IFD.Tags;
namespace Emby.Photos
{
- public class PhotoProvider : ICustomMetadataProvider<Photo>, IHasItemChangeMonitor, IForcedProvider
+ public class PhotoProvider : ICustomMetadataProvider<Photo>, IForcedProvider
{
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
@@ -177,19 +177,5 @@ namespace Emby.Photos
{
get { return "Embedded Information"; }
}
-
- public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
- {
- if (item.EnableRefreshOnDateModifiedChange && !string.IsNullOrWhiteSpace(item.Path) && item.LocationType == LocationType.FileSystem)
- {
- var file = directoryService.GetFile(item.Path);
- if (file != null && file.LastWriteTimeUtc != item.DateModified)
- {
- return true;
- }
- }
-
- return false;
- }
}
}
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 57c509923..91493cf53 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -792,6 +792,11 @@ namespace Emby.Server.Implementations
protected abstract IConnectManager CreateConnectManager();
protected abstract ISyncManager CreateSyncManager();
+
+ protected virtual IHttpClient CreateHttpClient()
+ {
+ return new HttpClientManager.HttpClientManager(ApplicationPaths, LogManager.GetLogger("HttpClient"), FileSystemManager, MemoryStreamFactory, GetDefaultUserAgent);
+ }
/// <summary>
/// Registers resources that classes will depend on
@@ -814,7 +819,7 @@ namespace Emby.Server.Implementations
RegisterSingleInstance(FileSystemManager);
- HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, LogManager.GetLogger("HttpClient"), FileSystemManager, MemoryStreamFactory, GetDefaultUserAgent);
+ HttpClient = CreateHttpClient();
RegisterSingleInstance(HttpClient);
RegisterSingleInstance(NetworkManager);
@@ -938,7 +943,9 @@ namespace Emby.Server.Implementations
ConnectManager = CreateConnectManager();
RegisterSingleInstance(ConnectManager);
- DeviceManager = new DeviceManager(new DeviceRepository(ApplicationPaths, JsonSerializer, LogManager.GetLogger("DeviceManager"), FileSystemManager), UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager, LogManager.GetLogger("DeviceManager"), NetworkManager);
+ var deviceRepo = new SqliteDeviceRepository(LogManager.GetLogger("DeviceManager"), ServerConfigurationManager, FileSystemManager, JsonSerializer);
+ deviceRepo.Initialize();
+ DeviceManager = new DeviceManager(deviceRepo, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager, LogManager.GetLogger("DeviceManager"), NetworkManager);
RegisterSingleInstance(DeviceManager);
var newsService = new Emby.Server.Implementations.News.NewsService(ApplicationPaths, JsonSerializer);
@@ -1116,7 +1123,7 @@ namespace Emby.Server.Implementations
IsoManager.AddParts(list);
}
- private string GetDefaultUserAgent()
+ protected string GetDefaultUserAgent()
{
var name = FormatAttribute(Name);
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index bc4ab8315..a6c7150da 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -3038,8 +3038,8 @@ namespace Emby.Server.Implementations.Data
{
if (orderBy.Count == 0)
{
- orderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending));
orderBy.Add(new Tuple<string, SortOrder>("SimilarityScore", SortOrder.Descending));
+ orderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending));
//orderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending));
}
}
diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs
index 027a55516..ee4c4bb26 100644
--- a/Emby.Server.Implementations/Devices/DeviceManager.cs
+++ b/Emby.Server.Implementations/Devices/DeviceManager.cs
@@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.Devices
_network = network;
}
- public async Task<DeviceInfo> RegisterDevice(string reportedId, string name, string appName, string appVersion, string usedByUserId)
+ public DeviceInfo RegisterDevice(string reportedId, string name, string appName, string appVersion, string usedByUserId)
{
if (string.IsNullOrWhiteSpace(reportedId))
{
@@ -76,14 +76,16 @@ namespace Emby.Server.Implementations.Devices
device.DateLastModified = DateTime.UtcNow;
- await _repo.SaveDevice(device).ConfigureAwait(false);
+ device.Name = string.IsNullOrWhiteSpace(device.CustomName) ? device.ReportedName : device.CustomName;
+
+ _repo.SaveDevice(device);
return device;
}
- public Task SaveCapabilities(string reportedId, ClientCapabilities capabilities)
+ public void SaveCapabilities(string reportedId, ClientCapabilities capabilities)
{
- return _repo.SaveCapabilities(reportedId, capabilities);
+ _repo.SaveCapabilities(reportedId, capabilities);
}
public ClientCapabilities GetCapabilities(string reportedId)
@@ -98,13 +100,13 @@ namespace Emby.Server.Implementations.Devices
public QueryResult<DeviceInfo> GetDevices(DeviceQuery query)
{
- IEnumerable<DeviceInfo> devices = _repo.GetDevices().OrderByDescending(i => i.DateLastModified);
+ IEnumerable<DeviceInfo> devices = _repo.GetDevices();
if (query.SupportsSync.HasValue)
{
var val = query.SupportsSync.Value;
- devices = devices.Where(i => GetCapabilities(i.Id).SupportsSync == val);
+ devices = devices.Where(i => i.Capabilities.SupportsSync == val);
}
if (query.SupportsPersistentIdentifier.HasValue)
@@ -113,8 +115,7 @@ namespace Emby.Server.Implementations.Devices
devices = devices.Where(i =>
{
- var caps = GetCapabilities(i.Id);
- var deviceVal = caps.SupportsPersistentIdentifier;
+ var deviceVal = i.Capabilities.SupportsPersistentIdentifier;
return deviceVal == val;
});
}
@@ -132,9 +133,9 @@ namespace Emby.Server.Implementations.Devices
};
}
- public Task DeleteDevice(string id)
+ public void DeleteDevice(string id)
{
- return _repo.DeleteDevice(id);
+ _repo.DeleteDevice(id);
}
public ContentUploadHistory GetCameraUploadHistory(string deviceId)
@@ -213,14 +214,16 @@ namespace Emby.Server.Implementations.Devices
get { return Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads"); }
}
- public async Task UpdateDeviceInfo(string id, DeviceOptions options)
+ public void UpdateDeviceInfo(string id, DeviceOptions options)
{
var device = GetDevice(id);
device.CustomName = options.CustomName;
device.CameraUploadPath = options.CameraUploadPath;
- await _repo.SaveDevice(device).ConfigureAwait(false);
+ device.Name = string.IsNullOrWhiteSpace(device.CustomName) ? device.ReportedName : device.CustomName;
+
+ _repo.SaveDevice(device);
EventHelper.FireEventIfNotNull(DeviceOptionsUpdated, this, new GenericEventArgs<DeviceInfo>(device), _logger);
}
diff --git a/Emby.Server.Implementations/Devices/DeviceRepository.cs b/Emby.Server.Implementations/Devices/DeviceRepository.cs
deleted file mode 100644
index b286a3bb0..000000000
--- a/Emby.Server.Implementations/Devices/DeviceRepository.cs
+++ /dev/null
@@ -1,212 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Devices;
-using MediaBrowser.Model.Devices;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Session;
-using MediaBrowser.Model.Extensions;
-
-namespace Emby.Server.Implementations.Devices
-{
- public class DeviceRepository : IDeviceRepository
- {
- private readonly object _syncLock = new object();
-
- private readonly IApplicationPaths _appPaths;
- private readonly IJsonSerializer _json;
- private readonly ILogger _logger;
- private readonly IFileSystem _fileSystem;
-
- private Dictionary<string, DeviceInfo> _devices;
-
- public DeviceRepository(IApplicationPaths appPaths, IJsonSerializer json, ILogger logger, IFileSystem fileSystem)
- {
- _appPaths = appPaths;
- _json = json;
- _logger = logger;
- _fileSystem = fileSystem;
- }
-
- private string GetDevicesPath()
- {
- return Path.Combine(_appPaths.DataPath, "devices");
- }
-
- private string GetDevicePath(string id)
- {
- return Path.Combine(GetDevicesPath(), id.GetMD5().ToString("N"));
- }
-
- public Task SaveDevice(DeviceInfo device)
- {
- var path = Path.Combine(GetDevicePath(device.Id), "device.json");
- _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
-
- lock (_syncLock)
- {
- _json.SerializeToFile(device, path);
- _devices[device.Id] = device;
- }
- return Task.FromResult(true);
- }
-
- public Task SaveCapabilities(string reportedId, ClientCapabilities capabilities)
- {
- var device = GetDevice(reportedId);
-
- if (device == null)
- {
- throw new ArgumentException("No device has been registed with id " + reportedId);
- }
-
- device.Capabilities = capabilities;
- SaveDevice(device);
-
- return Task.FromResult(true);
- }
-
- public ClientCapabilities GetCapabilities(string reportedId)
- {
- var device = GetDevice(reportedId);
-
- return device == null ? null : device.Capabilities;
- }
-
- public DeviceInfo GetDevice(string id)
- {
- if (string.IsNullOrWhiteSpace(id))
- {
- throw new ArgumentNullException("id");
- }
-
- return GetDevices()
- .FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase));
- }
-
- public IEnumerable<DeviceInfo> GetDevices()
- {
- lock (_syncLock)
- {
- if (_devices == null)
- {
- _devices = new Dictionary<string, DeviceInfo>(StringComparer.OrdinalIgnoreCase);
-
- var devices = LoadDevices().ToList();
- foreach (var device in devices)
- {
- _devices[device.Id] = device;
- }
- }
- return _devices.Values.ToList();
- }
- }
-
- private IEnumerable<DeviceInfo> LoadDevices()
- {
- var path = GetDevicesPath();
-
- try
- {
- return _fileSystem
- .GetFilePaths(path, true)
- .Where(i => string.Equals(Path.GetFileName(i), "device.json", StringComparison.OrdinalIgnoreCase))
- .ToList()
- .Select(i =>
- {
- try
- {
- return _json.DeserializeFromFile<DeviceInfo>(i);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error reading {0}", ex, i);
- return null;
- }
- })
- .Where(i => i != null);
- }
- catch (IOException)
- {
- return new List<DeviceInfo>();
- }
- }
-
- public Task DeleteDevice(string id)
- {
- var path = GetDevicePath(id);
-
- lock (_syncLock)
- {
- try
- {
- _fileSystem.DeleteDirectory(path, true);
- }
- catch (IOException)
- {
- }
-
- _devices = null;
- }
-
- return Task.FromResult(true);
- }
-
- public ContentUploadHistory GetCameraUploadHistory(string deviceId)
- {
- var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
-
- lock (_syncLock)
- {
- try
- {
- return _json.DeserializeFromFile<ContentUploadHistory>(path);
- }
- catch (IOException)
- {
- return new ContentUploadHistory
- {
- DeviceId = deviceId
- };
- }
- }
- }
-
- public void AddCameraUpload(string deviceId, LocalFileInfo file)
- {
- var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
- _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
-
- lock (_syncLock)
- {
- ContentUploadHistory history;
-
- try
- {
- history = _json.DeserializeFromFile<ContentUploadHistory>(path);
- }
- catch (IOException)
- {
- history = new ContentUploadHistory
- {
- DeviceId = deviceId
- };
- }
-
- history.DeviceId = deviceId;
-
- var list = history.FilesUploaded.ToList();
- list.Add(file);
- history.FilesUploaded = list.ToArray(list.Count);
-
- _json.SerializeToFile(history, path);
- }
- }
- }
-}
diff --git a/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs
new file mode 100644
index 000000000..a15eb3558
--- /dev/null
+++ b/Emby.Server.Implementations/Devices/SqliteDeviceRepository.cs
@@ -0,0 +1,451 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using Emby.Server.Implementations.Data;
+using MediaBrowser.Controller;
+using MediaBrowser.Model.Logging;
+using SQLitePCL.pretty;
+using MediaBrowser.Model.Extensions;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Devices;
+using MediaBrowser.Model.Devices;
+using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.Session;
+using MediaBrowser.Controller.Configuration;
+
+namespace Emby.Server.Implementations.Devices
+{
+ public class SqliteDeviceRepository : BaseSqliteRepository, IDeviceRepository
+ {
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+ protected IFileSystem FileSystem { get; private set; }
+ private readonly object _syncLock = new object();
+ private readonly IJsonSerializer _json;
+ private IServerApplicationPaths _appPaths;
+
+ public SqliteDeviceRepository(ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IJsonSerializer json)
+ : base(logger)
+ {
+ var appPaths = config.ApplicationPaths;
+
+ DbFilePath = Path.Combine(appPaths.DataPath, "devices.db");
+ FileSystem = fileSystem;
+ _json = json;
+ _appPaths = appPaths;
+ }
+
+ public void Initialize()
+ {
+ try
+ {
+ InitializeInternal();
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error loading database file. Will reset and retry.", ex);
+
+ FileSystem.DeleteFile(DbFilePath);
+
+ InitializeInternal();
+ }
+ }
+
+ private void InitializeInternal()
+ {
+ using (var connection = CreateConnection())
+ {
+ RunDefaultInitialization(connection);
+
+ string[] queries = {
+ "create table if not exists Devices (Id TEXT PRIMARY KEY, Name TEXT, ReportedName TEXT, CustomName TEXT, CameraUploadPath TEXT, LastUserName TEXT, AppName TEXT, AppVersion TEXT, LastUserId TEXT, DateLastModified DATETIME, Capabilities TEXT)",
+ "create index if not exists idx_id on Devices(Id)"
+ };
+
+ connection.RunQueries(queries);
+
+ MigrateDevices();
+ }
+ }
+
+ private void MigrateDevices()
+ {
+ List<string> files;
+ try
+ {
+ files = FileSystem
+ .GetFilePaths(GetDevicesPath(), true)
+ .Where(i => string.Equals(Path.GetFileName(i), "device.json", StringComparison.OrdinalIgnoreCase))
+ .ToList();
+ }
+ catch (IOException)
+ {
+ return;
+ }
+
+ foreach (var file in files)
+ {
+ try
+ {
+ var device = _json.DeserializeFromFile<DeviceInfo>(file);
+
+ device.Name = string.IsNullOrWhiteSpace(device.CustomName) ? device.ReportedName : device.CustomName;
+
+ SaveDevice(device);
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error reading {0}", ex, file);
+ }
+ finally
+ {
+ try
+ {
+ FileSystem.DeleteFile(file);
+ }
+ catch (IOException)
+ {
+ try
+ {
+ FileSystem.MoveFile(file, Path.ChangeExtension(file, ".old"));
+ }
+ catch (IOException)
+ {
+ }
+ }
+ }
+ }
+ }
+
+ private const string BaseSelectText = "select Id, Name, ReportedName, CustomName, CameraUploadPath, LastUserName, AppName, AppVersion, LastUserId, DateLastModified, Capabilities from Devices";
+
+ public void SaveCapabilities(string deviceId, ClientCapabilities capabilities)
+ {
+ using (WriteLock.Write())
+ {
+ using (var connection = CreateConnection())
+ {
+ connection.RunInTransaction(db =>
+ {
+ using (var statement = db.PrepareStatement("update devices set Capabilities=@Capabilities where Id=@Id"))
+ {
+ statement.TryBind("@Id", deviceId);
+
+ if (capabilities == null)
+ {
+ statement.TryBindNull("@Capabilities");
+ }
+ else
+ {
+ statement.TryBind("@Capabilities", _json.SerializeToString(capabilities));
+ }
+
+ statement.MoveNext();
+ }
+ }, TransactionMode);
+ }
+ }
+ }
+
+ public void SaveDevice(DeviceInfo entry)
+ {
+ if (entry == null)
+ {
+ throw new ArgumentNullException("entry");
+ }
+
+ using (WriteLock.Write())
+ {
+ using (var connection = CreateConnection())
+ {
+ connection.RunInTransaction(db =>
+ {
+ using (var statement = db.PrepareStatement("replace into Devices (Id, Name, ReportedName, CustomName, CameraUploadPath, LastUserName, AppName, AppVersion, LastUserId, DateLastModified, Capabilities) values (@Id, @Name, @ReportedName, @CustomName, @CameraUploadPath, @LastUserName, @AppName, @AppVersion, @LastUserId, @DateLastModified, @Capabilities)"))
+ {
+ statement.TryBind("@Id", entry.Id);
+ statement.TryBind("@Name", entry.Name);
+ statement.TryBind("@ReportedName", entry.ReportedName);
+ statement.TryBind("@CustomName", entry.CustomName);
+ statement.TryBind("@CameraUploadPath", entry.CameraUploadPath);
+ statement.TryBind("@LastUserName", entry.LastUserName);
+ statement.TryBind("@AppName", entry.AppName);
+ statement.TryBind("@AppVersion", entry.AppVersion);
+ statement.TryBind("@DateLastModified", entry.DateLastModified);
+
+ if (entry.Capabilities == null)
+ {
+ statement.TryBindNull("@Capabilities");
+ }
+ else
+ {
+ statement.TryBind("@Capabilities", _json.SerializeToString(entry.Capabilities));
+ }
+
+ statement.MoveNext();
+ }
+ }, TransactionMode);
+ }
+ }
+ }
+
+ public DeviceInfo GetDevice(string id)
+ {
+ using (WriteLock.Read())
+ {
+ using (var connection = CreateConnection(true))
+ {
+ var statementTexts = new List<string>();
+ statementTexts.Add(BaseSelectText + " where Id=@Id");
+
+ return connection.RunInTransaction(db =>
+ {
+ var statements = PrepareAllSafe(db, statementTexts).ToList();
+
+ using (var statement = statements[0])
+ {
+ statement.TryBind("@Id", id);
+
+ foreach (var row in statement.ExecuteQuery())
+ {
+ return GetEntry(row);
+ }
+ }
+
+ return null;
+
+ }, ReadTransactionMode);
+ }
+ }
+ }
+
+ public List<DeviceInfo> GetDevices()
+ {
+ using (WriteLock.Read())
+ {
+ using (var connection = CreateConnection(true))
+ {
+ var statementTexts = new List<string>();
+ statementTexts.Add(BaseSelectText + " order by DateLastModified desc");
+
+ return connection.RunInTransaction(db =>
+ {
+ var list = new List<DeviceInfo>();
+
+ var statements = PrepareAllSafe(db, statementTexts).ToList();
+
+ using (var statement = statements[0])
+ {
+ foreach (var row in statement.ExecuteQuery())
+ {
+ list.Add(GetEntry(row));
+ }
+ }
+
+ return list;
+
+ }, ReadTransactionMode);
+ }
+ }
+ }
+
+ public ClientCapabilities GetCapabilities(string id)
+ {
+ using (WriteLock.Read())
+ {
+ using (var connection = CreateConnection(true))
+ {
+ var statementTexts = new List<string>();
+ statementTexts.Add("Select Capabilities from Devices where Id=@Id");
+
+ return connection.RunInTransaction(db =>
+ {
+ var statements = PrepareAllSafe(db, statementTexts).ToList();
+
+ using (var statement = statements[0])
+ {
+ statement.TryBind("@Id", id);
+
+ foreach (var row in statement.ExecuteQuery())
+ {
+ if (row[0].SQLiteType != SQLiteType.Null)
+ {
+ return _json.DeserializeFromString<ClientCapabilities>(row.GetString(0));
+ }
+ }
+ }
+
+ return null;
+
+ }, ReadTransactionMode);
+ }
+ }
+ }
+
+ private DeviceInfo GetEntry(IReadOnlyList<IResultSetValue> reader)
+ {
+ var index = 0;
+
+ var info = new DeviceInfo
+ {
+ Id = reader.GetString(index)
+ };
+
+ index++;
+ if (reader[index].SQLiteType != SQLiteType.Null)
+ {
+ info.Name = reader.GetString(index);
+ }
+
+ index++;
+ if (reader[index].SQLiteType != SQLiteType.Null)
+ {
+ info.ReportedName = reader.GetString(index);
+ }
+
+ index++;
+ if (reader[index].SQLiteType != SQLiteType.Null)
+ {
+ info.CustomName = reader.GetString(index);
+ }
+
+ index++;
+ if (reader[index].SQLiteType != SQLiteType.Null)
+ {
+ info.CameraUploadPath = reader.GetString(index);
+ }
+
+ index++;
+ if (reader[index].SQLiteType != SQLiteType.Null)
+ {
+ info.LastUserName = reader.GetString(index);
+ }
+
+ index++;
+ if (reader[index].SQLiteType != SQLiteType.Null)
+ {
+ info.AppName = reader.GetString(index);
+ }
+
+ index++;
+ if (reader[index].SQLiteType != SQLiteType.Null)
+ {
+ info.AppVersion = reader.GetString(index);
+ }
+
+ index++;
+ if (reader[index].SQLiteType != SQLiteType.Null)
+ {
+ info.LastUserId = reader.GetString(index);
+ }
+
+ index++;
+ if (reader[index].SQLiteType != SQLiteType.Null)
+ {
+ info.DateLastModified = reader[index].ReadDateTime();
+ }
+
+ index++;
+ if (reader[index].SQLiteType != SQLiteType.Null)
+ {
+ info.Capabilities = _json.DeserializeFromString<ClientCapabilities>(reader.GetString(index));
+ }
+
+ return info;
+ }
+
+ private string GetDevicesPath()
+ {
+ return Path.Combine(_appPaths.DataPath, "devices");
+ }
+
+ private string GetDevicePath(string id)
+ {
+ return Path.Combine(GetDevicesPath(), id.GetMD5().ToString("N"));
+ }
+
+ public ContentUploadHistory GetCameraUploadHistory(string deviceId)
+ {
+ var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
+
+ lock (_syncLock)
+ {
+ try
+ {
+ return _json.DeserializeFromFile<ContentUploadHistory>(path);
+ }
+ catch (IOException)
+ {
+ return new ContentUploadHistory
+ {
+ DeviceId = deviceId
+ };
+ }
+ }
+ }
+
+ public void AddCameraUpload(string deviceId, LocalFileInfo file)
+ {
+ var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path));
+
+ lock (_syncLock)
+ {
+ ContentUploadHistory history;
+
+ try
+ {
+ history = _json.DeserializeFromFile<ContentUploadHistory>(path);
+ }
+ catch (IOException)
+ {
+ history = new ContentUploadHistory
+ {
+ DeviceId = deviceId
+ };
+ }
+
+ history.DeviceId = deviceId;
+
+ var list = history.FilesUploaded.ToList();
+ list.Add(file);
+ history.FilesUploaded = list.ToArray(list.Count);
+
+ _json.SerializeToFile(history, path);
+ }
+ }
+
+ public void DeleteDevice(string id)
+ {
+ using (WriteLock.Write())
+ {
+ using (var connection = CreateConnection())
+ {
+ connection.RunInTransaction(db =>
+ {
+ using (var statement = db.PrepareStatement("delete from devices where Id=@Id"))
+ {
+ statement.TryBind("@Id", id);
+
+ statement.MoveNext();
+ }
+ }, TransactionMode);
+ }
+ }
+
+ var path = GetDevicePath(id);
+
+ lock (_syncLock)
+ {
+ try
+ {
+ FileSystem.DeleteDirectory(path, true);
+ }
+ catch (IOException)
+ {
+ }
+ }
+ }
+ }
+}
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index 4f5471bc3..083a14788 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -67,7 +67,7 @@
<Compile Include="Devices\CameraUploadsFolder.cs" />
<Compile Include="Devices\DeviceId.cs" />
<Compile Include="Devices\DeviceManager.cs" />
- <Compile Include="Devices\DeviceRepository.cs" />
+ <Compile Include="Devices\SqliteDeviceRepository.cs" />
<Compile Include="Diagnostics\CommonProcess.cs" />
<Compile Include="Diagnostics\ProcessFactory.cs" />
<Compile Include="Dto\DtoService.cs" />
diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientInfo.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientInfo.cs
index 6d17bf94d..21cec9d2b 100644
--- a/Emby.Server.Implementations/HttpClientManager/HttpClientInfo.cs
+++ b/Emby.Server.Implementations/HttpClientManager/HttpClientInfo.cs
@@ -1,4 +1,5 @@
using System;
+using System.Net.Http;
namespace Emby.Server.Implementations.HttpClientManager
{
@@ -12,5 +13,6 @@ namespace Emby.Server.Implementations.HttpClientManager
/// </summary>
/// <value>The last timeout.</value>
public DateTime LastTimeout { get; set; }
+ public HttpClient HttpClient { get; set; }
}
}
diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs
index d60a04353..688da5764 100644
--- a/Emby.Server.Implementations/Library/MediaSourceManager.cs
+++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs
@@ -96,23 +96,17 @@ namespace Emby.Server.Implementations.Library
return GetMediaStreamsForItem(list);
}
- private List<MediaStream> GetMediaStreamsForItem(IEnumerable<MediaStream> streams)
+ private List<MediaStream> GetMediaStreamsForItem(List<MediaStream> streams)
{
- var list = streams.ToList();
-
- var subtitleStreams = list
- .Where(i => i.Type == MediaStreamType.Subtitle)
- .ToList();
-
- if (subtitleStreams.Count > 0)
+ foreach (var stream in streams)
{
- foreach (var subStream in subtitleStreams)
+ if (stream.Type == MediaStreamType.Subtitle)
{
- subStream.SupportsExternalStream = StreamSupportsExternalStream(subStream);
+ stream.SupportsExternalStream = StreamSupportsExternalStream(stream);
}
}
- return list;
+ return streams;
}
public async Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, string[] supportedLiveMediaTypes, CancellationToken cancellationToken)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs
index 5e3923972..ad9c0d894 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs
@@ -22,7 +22,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private readonly IHttpClient _httpClient;
private readonly IServerApplicationHost _appHost;
- private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource();
private readonly TaskCompletionSource<bool> _liveStreamTaskCompletionSource = new TaskCompletionSource<bool>();
public HdHomerunHttpStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, IEnvironmentInfo environment)
@@ -35,7 +34,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
protected override Task OpenInternal(CancellationToken openCancellationToken)
{
- _liveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested();
+ LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested();
var mediaSource = OriginalMediaSource;
@@ -45,7 +44,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
var taskCompletionSource = new TaskCompletionSource<bool>();
- StartStreaming(url, taskCompletionSource, _liveStreamCancellationTokenSource.Token);
+ StartStreaming(url, taskCompletionSource, LiveStreamCancellationTokenSource.Token);
//OpenedMediaSource.Protocol = MediaProtocol.File;
//OpenedMediaSource.Path = tempFile;
@@ -65,12 +64,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
//await Task.Delay(5000).ConfigureAwait(false);
}
- public override Task Close()
+ public override async Task Close()
{
Logger.Info("Closing HDHR live stream");
- _liveStreamCancellationTokenSource.Cancel();
+ LiveStreamCancellationTokenSource.Cancel();
- return _liveStreamTaskCompletionSource.Task;
+ await _liveStreamTaskCompletionSource.Task.ConfigureAwait(false);
+ await DeleteTempFile(TempFilePath).ConfigureAwait(false);
}
private Task StartStreaming(string url, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
@@ -112,7 +112,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
}
_liveStreamTaskCompletionSource.TrySetResult(true);
- await DeleteTempFile(TempFilePath).ConfigureAwait(false);
});
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
index ff8fd1bc4..4187fcd8f 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
@@ -26,7 +26,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private readonly IServerApplicationHost _appHost;
private readonly ISocketFactory _socketFactory;
- private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource();
private readonly TaskCompletionSource<bool> _liveStreamTaskCompletionSource = new TaskCompletionSource<bool>();
private readonly IHdHomerunChannelCommands _channelCommands;
private readonly int _numTuners;
@@ -45,7 +44,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
protected override Task OpenInternal(CancellationToken openCancellationToken)
{
- _liveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested();
+ LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested();
var mediaSource = OriginalMediaSource;
@@ -56,7 +55,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
var taskCompletionSource = new TaskCompletionSource<bool>();
- StartStreaming(uri.Host, localPort, taskCompletionSource, _liveStreamCancellationTokenSource.Token);
+ StartStreaming(uri.Host, localPort, taskCompletionSource, LiveStreamCancellationTokenSource.Token);
//OpenedMediaSource.Protocol = MediaProtocol.File;
//OpenedMediaSource.Path = tempFile;
@@ -76,7 +75,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
public override Task Close()
{
Logger.Info("Closing HDHR UDP live stream");
- _liveStreamCancellationTokenSource.Cancel();
+ LiveStreamCancellationTokenSource.Cancel();
return _liveStreamTaskCompletionSource.Task;
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
index 5be91c6c1..685f794fd 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
@@ -32,6 +32,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
protected readonly string TempFilePath;
protected readonly ILogger Logger;
+ protected readonly CancellationTokenSource LiveStreamCancellationTokenSource = new CancellationTokenSource();
public LiveStream(MediaSourceInfo mediaSource, IEnvironmentInfo environment, IFileSystem fileSystem, ILogger logger, IServerApplicationPaths appPaths)
{
@@ -80,6 +81,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
FileSystem.DeleteFile(path);
return;
}
+ catch (DirectoryNotFoundException)
+ {
+ return;
+ }
+ catch (FileNotFoundException)
+ {
+ return;
+ }
catch
{
@@ -96,6 +105,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
public async Task CopyToAsync(Stream stream, CancellationToken cancellationToken)
{
+ cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, LiveStreamCancellationTokenSource.Token).Token;
+
var allowAsync = false;//Environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows;
// use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
@@ -110,16 +121,27 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
private static async Task CopyTo(Stream source, Stream destination, int bufferSize, Action onStarted, CancellationToken cancellationToken)
{
byte[] buffer = new byte[bufferSize];
- while (true)
+
+ var eofCount = 0;
+ var emptyReadLimit = 1000;
+
+ while (eofCount < emptyReadLimit)
{
cancellationToken.ThrowIfCancellationRequested();
- var read = source.Read(buffer, 0, buffer.Length);
+ var bytesRead = source.Read(buffer, 0, buffer.Length);
- if (read > 0)
+ if (bytesRead == 0)
+ {
+ eofCount++;
+ await Task.Delay(10, cancellationToken).ConfigureAwait(false);
+ }
+ else
{
+ eofCount = 0;
+
//await destination.WriteAsync(buffer, 0, read).ConfigureAwait(false);
- destination.Write(buffer, 0, read);
+ destination.Write(buffer, 0, bytesRead);
if (onStarted != null)
{
@@ -127,10 +149,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
onStarted = null;
}
}
- else
- {
- await Task.Delay(10).ConfigureAwait(false);
- }
}
}
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index 97506cdef..2c1535165 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -437,7 +437,7 @@ namespace Emby.Server.Implementations.Session
if (!string.IsNullOrEmpty(deviceId))
{
var userIdString = userId.HasValue ? userId.Value.ToString("N") : null;
- device = await _deviceManager.RegisterDevice(deviceId, deviceName, appName, appVersion, userIdString).ConfigureAwait(false);
+ device = _deviceManager.RegisterDevice(deviceId, deviceName, appName, appVersion, userIdString);
}
}
@@ -446,7 +446,7 @@ namespace Emby.Server.Implementations.Session
if (device == null)
{
var userIdString = userId.HasValue ? userId.Value.ToString("N") : null;
- device = await _deviceManager.RegisterDevice(deviceId, deviceName, appName, appVersion, userIdString).ConfigureAwait(false);
+ device = _deviceManager.RegisterDevice(deviceId, deviceName, appName, appVersion, userIdString);
}
if (device != null)
@@ -1567,7 +1567,7 @@ namespace Emby.Server.Implementations.Session
ReportCapabilities(session, capabilities, true);
}
- private async void ReportCapabilities(SessionInfo session,
+ private void ReportCapabilities(SessionInfo session,
ClientCapabilities capabilities,
bool saveCapabilities)
{
@@ -1593,7 +1593,7 @@ namespace Emby.Server.Implementations.Session
{
try
{
- await SaveCapabilities(session.DeviceId, capabilities).ConfigureAwait(false);
+ SaveCapabilities(session.DeviceId, capabilities);
}
catch (Exception ex)
{
@@ -1607,9 +1607,9 @@ namespace Emby.Server.Implementations.Session
return _deviceManager.GetCapabilities(deviceId);
}
- private Task SaveCapabilities(string deviceId, ClientCapabilities capabilities)
+ private void SaveCapabilities(string deviceId, ClientCapabilities capabilities)
{
- return _deviceManager.SaveCapabilities(deviceId, capabilities);
+ _deviceManager.SaveCapabilities(deviceId, capabilities);
}
public SessionInfoDto GetSessionInfoDto(SessionInfo session)
diff --git a/MediaBrowser.Api/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs
index 012f0ddb2..c375e272a 100644
--- a/MediaBrowser.Api/Devices/DeviceService.cs
+++ b/MediaBrowser.Api/Devices/DeviceService.cs
@@ -85,13 +85,11 @@ namespace MediaBrowser.Api.Devices
public void Post(PostDeviceOptions request)
{
- var task = _deviceManager.UpdateDeviceInfo(request.Id, new DeviceOptions
+ _deviceManager.UpdateDeviceInfo(request.Id, new DeviceOptions
{
CustomName = request.CustomName,
CameraUploadPath = request.CameraUploadPath
});
-
- Task.WaitAll(task);
}
public object Get(GetDeviceInfo request)
@@ -116,9 +114,7 @@ namespace MediaBrowser.Api.Devices
public void Delete(DeleteDevice request)
{
- var task = _deviceManager.DeleteDevice(request.Id);
-
- Task.WaitAll(task);
+ _deviceManager.DeleteDevice(request.Id);
}
public void Post(PostCameraUpload request)
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index 1ae7323dc..703c96e0c 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -734,7 +734,7 @@ namespace MediaBrowser.Api.LiveTv
outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType(path);
- return new ProgressiveFileCopier(_fileSystem, path, outputHeaders, Logger, _environment, CancellationToken.None)
+ return new ProgressiveFileCopier(_fileSystem, path, outputHeaders, Logger, _environment)
{
AllowEndOfFile = false
};
@@ -753,7 +753,7 @@ namespace MediaBrowser.Api.LiveTv
outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType("file." + request.Container);
- return new ProgressiveFileCopier(directStreamProvider, outputHeaders, Logger, _environment, CancellationToken.None)
+ return new ProgressiveFileCopier(directStreamProvider, outputHeaders, Logger, _environment)
{
AllowEndOfFile = false
};
diff --git a/MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs b/MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs
index 9ce109fc4..74293ccd9 100644
--- a/MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs
+++ b/MediaBrowser.Api/LiveTv/ProgressiveFileCopier.cs
@@ -16,7 +16,6 @@ namespace MediaBrowser.Api.LiveTv
private readonly IFileSystem _fileSystem;
private readonly ILogger _logger;
private readonly string _path;
- private readonly CancellationToken _cancellationToken;
private readonly Dictionary<string, string> _outputHeaders;
const int StreamCopyToBufferSize = 81920;
@@ -28,22 +27,20 @@ namespace MediaBrowser.Api.LiveTv
private readonly IDirectStreamProvider _directStreamProvider;
private readonly IEnvironmentInfo _environment;
- public ProgressiveFileCopier(IFileSystem fileSystem, string path, Dictionary<string, string> outputHeaders, ILogger logger, IEnvironmentInfo environment, CancellationToken cancellationToken)
+ public ProgressiveFileCopier(IFileSystem fileSystem, string path, Dictionary<string, string> outputHeaders, ILogger logger, IEnvironmentInfo environment)
{
_fileSystem = fileSystem;
_path = path;
_outputHeaders = outputHeaders;
_logger = logger;
- _cancellationToken = cancellationToken;
_environment = environment;
}
- public ProgressiveFileCopier(IDirectStreamProvider directStreamProvider, Dictionary<string, string> outputHeaders, ILogger logger, IEnvironmentInfo environment, CancellationToken cancellationToken)
+ public ProgressiveFileCopier(IDirectStreamProvider directStreamProvider, Dictionary<string, string> outputHeaders, ILogger logger, IEnvironmentInfo environment)
{
_directStreamProvider = directStreamProvider;
_outputHeaders = outputHeaders;
_logger = logger;
- _cancellationToken = cancellationToken;
_environment = environment;
}
@@ -69,8 +66,6 @@ namespace MediaBrowser.Api.LiveTv
public async Task WriteToAsync(Stream outputStream, CancellationToken cancellationToken)
{
- cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationToken).Token;
-
if (_directStreamProvider != null)
{
await _directStreamProvider.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false);
@@ -89,7 +84,9 @@ namespace MediaBrowser.Api.LiveTv
inputStream.Position = StartPosition;
}
- while (eofCount < 20 || !AllowEndOfFile)
+ var emptyReadLimit = AllowEndOfFile ? 20 : 100;
+
+ while (eofCount < emptyReadLimit)
{
int bytesRead;
if (allowAsyncFileRead)
diff --git a/MediaBrowser.Controller/Devices/IDeviceManager.cs b/MediaBrowser.Controller/Devices/IDeviceManager.cs
index 2846bcfc6..676db09aa 100644
--- a/MediaBrowser.Controller/Devices/IDeviceManager.cs
+++ b/MediaBrowser.Controller/Devices/IDeviceManager.cs
@@ -28,7 +28,7 @@ namespace MediaBrowser.Controller.Devices
/// <param name="appVersion">The application version.</param>
/// <param name="usedByUserId">The used by user identifier.</param>
/// <returns>Task.</returns>
- Task<DeviceInfo> RegisterDevice(string reportedId, string name, string appName, string appVersion, string usedByUserId);
+ DeviceInfo RegisterDevice(string reportedId, string name, string appName, string appVersion, string usedByUserId);
/// <summary>
/// Saves the capabilities.
@@ -36,7 +36,7 @@ namespace MediaBrowser.Controller.Devices
/// <param name="reportedId">The reported identifier.</param>
/// <param name="capabilities">The capabilities.</param>
/// <returns>Task.</returns>
- Task SaveCapabilities(string reportedId, ClientCapabilities capabilities);
+ void SaveCapabilities(string reportedId, ClientCapabilities capabilities);
/// <summary>
/// Gets the capabilities.
@@ -58,7 +58,7 @@ namespace MediaBrowser.Controller.Devices
/// <param name="id">The identifier.</param>
/// <param name="options">The options.</param>
/// <returns>Task.</returns>
- Task UpdateDeviceInfo(string id, DeviceOptions options);
+ void UpdateDeviceInfo(string id, DeviceOptions options);
/// <summary>
/// Gets the devices.
@@ -67,12 +67,7 @@ namespace MediaBrowser.Controller.Devices
/// <returns>IEnumerable&lt;DeviceInfo&gt;.</returns>
QueryResult<DeviceInfo> GetDevices(DeviceQuery query);
- /// <summary>
- /// Deletes the device.
- /// </summary>
- /// <param name="id">The identifier.</param>
- /// <returns>Task.</returns>
- Task DeleteDevice(string id);
+ void DeleteDevice(string id);
/// <summary>
/// Gets the upload history.
diff --git a/MediaBrowser.Controller/Devices/IDeviceRepository.cs b/MediaBrowser.Controller/Devices/IDeviceRepository.cs
index 736504da3..b9ebbb6c7 100644
--- a/MediaBrowser.Controller/Devices/IDeviceRepository.cs
+++ b/MediaBrowser.Controller/Devices/IDeviceRepository.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Session;
using System.Collections.Generic;
-using System.Threading.Tasks;
namespace MediaBrowser.Controller.Devices
{
@@ -12,7 +11,7 @@ namespace MediaBrowser.Controller.Devices
/// </summary>
/// <param name="device">The device.</param>
/// <returns>Task.</returns>
- Task SaveDevice(DeviceInfo device);
+ void SaveDevice(DeviceInfo device);
/// <summary>
/// Saves the capabilities.
@@ -20,7 +19,7 @@ namespace MediaBrowser.Controller.Devices
/// <param name="id">The identifier.</param>
/// <param name="capabilities">The capabilities.</param>
/// <returns>Task.</returns>
- Task SaveCapabilities(string id, ClientCapabilities capabilities);
+ void SaveCapabilities(string id, ClientCapabilities capabilities);
/// <summary>
/// Gets the capabilities.
@@ -36,18 +35,14 @@ namespace MediaBrowser.Controller.Devices
/// <returns>DeviceInfo.</returns>
DeviceInfo GetDevice(string id);
- /// <summary>
- /// Gets the devices.
- /// </summary>
- /// <returns>IEnumerable&lt;DeviceInfo&gt;.</returns>
- IEnumerable<DeviceInfo> GetDevices();
+ List<DeviceInfo> GetDevices();
/// <summary>
/// Deletes the device.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>Task.</returns>
- Task DeleteDevice(string id);
+ void DeleteDevice(string id);
/// <summary>
/// Gets the upload history.
diff --git a/MediaBrowser.Controller/Entities/AudioBook.cs b/MediaBrowser.Controller/Entities/AudioBook.cs
index 78fb10253..374bb21f7 100644
--- a/MediaBrowser.Controller/Entities/AudioBook.cs
+++ b/MediaBrowser.Controller/Entities/AudioBook.cs
@@ -51,12 +51,6 @@ namespace MediaBrowser.Controller.Entities
return null;
}
- [IgnoreDataMember]
- public override bool EnableRefreshOnDateModifiedChange
- {
- get { return true; }
- }
-
public Guid? FindSeriesId()
{
return SeriesId;
diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs
index 9b1a52f83..45e3915ce 100644
--- a/MediaBrowser.Controller/Entities/Book.cs
+++ b/MediaBrowser.Controller/Entities/Book.cs
@@ -38,12 +38,6 @@ namespace MediaBrowser.Controller.Entities
return SeriesPresentationUniqueKey;
}
- [IgnoreDataMember]
- public override bool EnableRefreshOnDateModifiedChange
- {
- get { return true; }
- }
-
public Guid? FindSeriesId()
{
return SeriesId;
diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs
index a99058925..fd45f7c82 100644
--- a/MediaBrowser.Controller/Entities/Game.cs
+++ b/MediaBrowser.Controller/Entities/Game.cs
@@ -29,12 +29,6 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
- public override bool EnableRefreshOnDateModifiedChange
- {
- get { return true; }
- }
-
- [IgnoreDataMember]
public override bool SupportsThemeMedia
{
get { return true; }
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
index 4a93d0399..16010b7f5 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
@@ -136,7 +136,8 @@ namespace MediaBrowser.Controller.LiveTv
Name = Name,
Path = Path,
RunTimeTicks = RunTimeTicks,
- Type = MediaSourceType.Placeholder
+ Type = MediaSourceType.Placeholder,
+ IsInfiniteStream = RunTimeTicks == null
};
list.Add(info);
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 960ff0aa7..dafca0598 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -220,7 +220,6 @@
<Compile Include="Providers\IExternalId.cs" />
<Compile Include="Providers\IExtrasProvider.cs" />
<Compile Include="Providers\IForcedProvider.cs" />
- <Compile Include="Providers\IHasChangeMonitor.cs" />
<Compile Include="Entities\IHasMetadata.cs" />
<Compile Include="Providers\IHasItemChangeMonitor.cs" />
<Compile Include="Providers\IHasLookupInfo.cs" />
diff --git a/MediaBrowser.Controller/Providers/IHasChangeMonitor.cs b/MediaBrowser.Controller/Providers/IHasChangeMonitor.cs
deleted file mode 100644
index aa0b0e3c9..000000000
--- a/MediaBrowser.Controller/Providers/IHasChangeMonitor.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using MediaBrowser.Controller.Entities;
-using System;
-
-namespace MediaBrowser.Controller.Providers
-{
- public interface IHasChangeMonitor
- {
- /// <summary>
- /// Determines whether the specified item has changed.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="directoryService">The directory service.</param>
- /// <param name="date">The date.</param>
- /// <returns><c>true</c> if the specified item has changed; otherwise, <c>false</c>.</returns>
- bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date);
- }
-}
diff --git a/MediaBrowser.Model/Devices/DeviceInfo.cs b/MediaBrowser.Model/Devices/DeviceInfo.cs
index d8358977e..d2ee3fdcc 100644
--- a/MediaBrowser.Model/Devices/DeviceInfo.cs
+++ b/MediaBrowser.Model/Devices/DeviceInfo.cs
@@ -21,17 +21,7 @@ namespace MediaBrowser.Model.Devices
/// <value>The camera upload path.</value>
public string CameraUploadPath { get; set; }
- /// <summary>
- /// Gets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name
- {
- get
- {
- return string.IsNullOrEmpty(CustomName) ? ReportedName : CustomName;
- }
- }
+ public string Name { get; set; }
/// <summary>
/// Gets or sets the identifier.
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index 95a80c34c..a11c88697 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -686,7 +686,7 @@ namespace MediaBrowser.Model.Dlna
if (subtitleStream != null)
{
- SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, directPlay.Value, _transcoderSupport, null, null);
+ SubtitleProfile subtitleProfile = GetSubtitleProfile(item, subtitleStream, options.Profile.SubtitleProfiles, directPlay.Value, _transcoderSupport, null, null);
playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method;
playlistItem.SubtitleFormat = subtitleProfile.Format;
@@ -728,7 +728,7 @@ namespace MediaBrowser.Model.Dlna
if (subtitleStream != null)
{
- SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode, _transcoderSupport, transcodingProfile.Protocol, transcodingProfile.Container);
+ SubtitleProfile subtitleProfile = GetSubtitleProfile(item, subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode, _transcoderSupport, transcodingProfile.Protocol, transcodingProfile.Container);
playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method;
playlistItem.SubtitleFormat = subtitleProfile.Format;
@@ -1054,15 +1054,6 @@ namespace MediaBrowser.Model.Dlna
string videoCodec = videoStream == null ? null : videoStream.Codec;
- if (string.IsNullOrEmpty(videoCodec))
- {
- _logger.Info("Profile: {0}, DirectPlay=false. Reason=Unknown video codec. Path: {1}",
- profile.Name ?? "Unknown Profile",
- mediaSource.Path ?? "Unknown path");
-
- return new Tuple<PlayMethod?, List<TranscodeReason>>(null, new List<TranscodeReason> { TranscodeReason.UnknownVideoStreamInfo });
- }
-
conditions = new List<ProfileCondition>();
foreach (CodecProfile i in profile.CodecProfiles)
{
@@ -1189,7 +1180,7 @@ namespace MediaBrowser.Model.Dlna
{
if (subtitleStream != null)
{
- SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, playMethod, _transcoderSupport, null, null);
+ SubtitleProfile subtitleProfile = GetSubtitleProfile(item, subtitleStream, options.Profile.SubtitleProfiles, playMethod, _transcoderSupport, null, null);
if (subtitleProfile.Method != SubtitleDeliveryMethod.External && subtitleProfile.Method != SubtitleDeliveryMethod.Embed)
{
@@ -1208,7 +1199,7 @@ namespace MediaBrowser.Model.Dlna
return new Tuple<bool, TranscodeReason?>(result, TranscodeReason.ContainerBitrateExceedsLimit);
}
- public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, ITranscoderSupport transcoderSupport, string transcodingSubProtocol, string transcodingContainer)
+ public static SubtitleProfile GetSubtitleProfile(MediaSourceInfo mediaSource, MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, ITranscoderSupport transcoderSupport, string transcodingSubProtocol, string transcodingContainer)
{
if (!subtitleStream.IsExternal && (playMethod != PlayMethod.Transcode || !string.Equals(transcodingSubProtocol, "hls", StringComparison.OrdinalIgnoreCase)))
{
@@ -1262,8 +1253,8 @@ namespace MediaBrowser.Model.Dlna
}
// Look for an external or hls profile that matches the stream type (text/graphical) and doesn't require conversion
- return GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, transcoderSupport, false) ??
- GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, transcoderSupport, true) ??
+ return GetExternalSubtitleProfile(mediaSource, subtitleStream, subtitleProfiles, playMethod, transcoderSupport, false) ??
+ GetExternalSubtitleProfile(mediaSource, subtitleStream, subtitleProfiles, playMethod, transcoderSupport, true) ??
new SubtitleProfile
{
Method = SubtitleDeliveryMethod.Encode,
@@ -1299,7 +1290,7 @@ namespace MediaBrowser.Model.Dlna
return false;
}
- private static SubtitleProfile GetExternalSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, ITranscoderSupport transcoderSupport, bool allowConversion)
+ private static SubtitleProfile GetExternalSubtitleProfile(MediaSourceInfo mediaSource, MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, ITranscoderSupport transcoderSupport, bool allowConversion)
{
foreach (SubtitleProfile profile in subtitleProfiles)
{
@@ -1338,6 +1329,12 @@ namespace MediaBrowser.Model.Dlna
continue;
}
+ // TODO: Build this into subtitleStream.SupportsExternalStream
+ if (mediaSource.IsInfiniteStream)
+ {
+ continue;
+ }
+
if (subtitleStream.IsTextSubtitleStream && subtitleStream.SupportsExternalStream && subtitleStream.SupportsSubtitleConversionTo(profile.Format))
{
return profile;
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index 5a059e91d..93a46aaf4 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -466,7 +466,7 @@ namespace MediaBrowser.Model.Dlna
private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles, ITranscoderSupport transcoderSupport)
{
- SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, subtitleProfiles, PlayMethod, transcoderSupport, SubProtocol, Container);
+ SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(MediaSource, stream, subtitleProfiles, PlayMethod, transcoderSupport, SubProtocol, Container);
SubtitleStreamInfo info = new SubtitleStreamInfo
{
IsForced = stream.IsForced,
@@ -480,7 +480,7 @@ namespace MediaBrowser.Model.Dlna
if (info.DeliveryMethod == SubtitleDeliveryMethod.External)
{
- if (MediaSource.Protocol == MediaProtocol.File || !StringHelper.EqualsIgnoreCase(stream.Codec, subtitleProfile.Format))
+ if (MediaSource.Protocol == MediaProtocol.File || !StringHelper.EqualsIgnoreCase(stream.Codec, subtitleProfile.Format) || !stream.IsExternal)
{
info.Url = string.Format("{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}",
baseUrl,
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index c37e05d95..3759670d4 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -13,6 +13,7 @@ using System.Threading.Tasks;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.MediaInfo;
namespace MediaBrowser.Providers.Manager
{
@@ -37,6 +38,28 @@ namespace MediaBrowser.Providers.Manager
LibraryManager = libraryManager;
}
+ private bool RequiresRefresh(IHasMetadata item, IDirectoryService directoryService)
+ {
+ if (item.RequiresRefresh())
+ {
+ return true;
+ }
+
+ if (item.SupportsLocalMetadata)
+ {
+ var video = item as Video;
+
+ if (video != null && !video.IsPlaceHolder)
+ {
+ return !video.SubtitleFiles
+ .SequenceEqual(SubtitleResolver.GetSubtitleFiles(video, directoryService, FileSystem, false)
+ .OrderBy(i => i), StringComparer.OrdinalIgnoreCase);
+ }
+ }
+
+ return false;
+ }
+
public async Task<ItemUpdateType> RefreshMetadata(IHasMetadata item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken)
{
var itemOfType = (TItemType)item;
@@ -47,19 +70,35 @@ namespace MediaBrowser.Providers.Manager
var libraryOptions = LibraryManager.GetLibraryOptions((BaseItem)item);
- if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
+ DateTime? newDateModified = null;
+ if (item.LocationType == LocationType.FileSystem)
{
- // TODO: If this returns true, should we instead just change metadata refresh mode to Full?
- requiresRefresh = item.RequiresRefresh();
+ var file = refreshOptions.DirectoryService.GetFile(item.Path);
+ if (file != null)
+ {
+ newDateModified = file.LastWriteTimeUtc;
+ if (item.EnableRefreshOnDateModifiedChange)
+ {
+ if (newDateModified != item.DateModified)
+ {
+ Logger.Debug("Date modified for {0}. Old date {1} new date {2} Id {3}", item.Path, item.DateModified, newDateModified, item.Id);
+ requiresRefresh = true;
+ }
+ }
+ }
}
- if (!requiresRefresh &&
- libraryOptions.AutomaticRefreshIntervalDays > 0 &&
- (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= libraryOptions.AutomaticRefreshIntervalDays)
+ if (!requiresRefresh && libraryOptions.AutomaticRefreshIntervalDays > 0 && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= libraryOptions.AutomaticRefreshIntervalDays)
{
requiresRefresh = true;
}
+ if (!requiresRefresh && refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
+ {
+ // TODO: If this returns true, should we instead just change metadata refresh mode to Full?
+ requiresRefresh = RequiresRefresh(item, refreshOptions.DirectoryService);
+ }
+
var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager, FileSystem);
var localImagesFailed = false;
@@ -145,20 +184,9 @@ namespace MediaBrowser.Providers.Manager
var beforeSaveResult = BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh, updateType);
updateType = updateType | beforeSaveResult;
- if (item.LocationType == LocationType.FileSystem)
+ if (newDateModified.HasValue)
{
- var file = refreshOptions.DirectoryService.GetFile(item.Path);
- if (file != null)
- {
- var fileLastWriteTime = file.LastWriteTimeUtc;
- if (item.EnableRefreshOnDateModifiedChange && fileLastWriteTime != item.DateModified)
- {
- Logger.Debug("Date modified for {0}. Old date {1} new date {2} Id {3}", item.Path, item.DateModified, fileLastWriteTime, item.Id);
- requiresRefresh = true;
- }
-
- item.DateModified = fileLastWriteTime;
- }
+ item.DateModified = newDateModified.Value;
}
// Save if changes were made, or it's never been saved before
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index a4f2053a9..3499d5d3f 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
@@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.MediaInfo
/// <summary>
/// Uses ffmpeg to create video images
/// </summary>
- public class AudioImageProvider : IDynamicImageProvider, IHasItemChangeMonitor
+ public class AudioImageProvider : IDynamicImageProvider
{
private readonly IMediaEncoder _mediaEncoder;
private readonly IServerConfigurationManager _config;
@@ -134,19 +134,5 @@ namespace MediaBrowser.Providers.MediaInfo
return item.LocationType == LocationType.FileSystem && audio != null;
}
-
- public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
- {
- if (item.EnableRefreshOnDateModifiedChange && !string.IsNullOrWhiteSpace(item.Path) && item.LocationType == LocationType.FileSystem)
- {
- var file = directoryService.GetFile(item.Path);
- if (file != null && file.LastWriteTimeUtc != item.DateModified)
- {
- return true;
- }
- }
-
- return false;
- }
}
}
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
index a9aa71bfa..bce421901 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
@@ -34,7 +34,6 @@ namespace MediaBrowser.Providers.MediaInfo
ICustomMetadataProvider<Audio>,
ICustomMetadataProvider<AudioPodcast>,
ICustomMetadataProvider<AudioBook>,
- IHasItemChangeMonitor,
IHasOrder,
IForcedProvider,
IPreRefreshProvider
@@ -180,32 +179,6 @@ namespace MediaBrowser.Providers.MediaInfo
return prober.Probe(item, cancellationToken);
}
- public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
- {
- if (item.EnableRefreshOnDateModifiedChange && !string.IsNullOrWhiteSpace(item.Path) && item.LocationType == LocationType.FileSystem)
- {
- var file = directoryService.GetFile(item.Path);
- if (file != null && file.LastWriteTimeUtc != item.DateModified)
- {
- return true;
- }
- }
-
- if (item.SupportsLocalMetadata)
- {
- var video = item as Video;
-
- if (video != null && !video.IsPlaceHolder)
- {
- return !video.SubtitleFiles
- .SequenceEqual(SubtitleResolver.GetSubtitleFiles(video, directoryService, _fileSystem, false)
- .OrderBy(i => i), StringComparer.OrdinalIgnoreCase);
- }
- }
-
- return false;
- }
-
public int Order
{
get
diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
index 9b0d29cf0..9fde9c70f 100644
--- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
@@ -16,7 +16,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.MediaInfo
{
- public class VideoImageProvider : IDynamicImageProvider, IHasItemChangeMonitor, IHasOrder
+ public class VideoImageProvider : IDynamicImageProvider, IHasOrder
{
private readonly IMediaEncoder _mediaEncoder;
private readonly ILogger _logger;
@@ -149,19 +149,5 @@ namespace MediaBrowser.Providers.MediaInfo
return 100;
}
}
-
- public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
- {
- if (item.EnableRefreshOnDateModifiedChange && !string.IsNullOrWhiteSpace(item.Path) && item.LocationType == LocationType.FileSystem)
- {
- var file = directoryService.GetFile(item.Path);
- if (file != null && file.LastWriteTimeUtc != item.DateModified)
- {
- return true;
- }
- }
-
- return false;
- }
}
}
diff --git a/MediaBrowser.Providers/Movies/MovieDbSearch.cs b/MediaBrowser.Providers/Movies/MovieDbSearch.cs
index 1c6157c03..595c0249f 100644
--- a/MediaBrowser.Providers/Movies/MovieDbSearch.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbSearch.cs
@@ -100,6 +100,12 @@ namespace MediaBrowser.Providers.Movies
name = name.Replace("!", " ");
name = name.Replace("?", " ");
+ var parenthIndex = name.IndexOf('(');
+ if (parenthIndex != -1)
+ {
+ name = name.Substring(0, parenthIndex);
+ }
+
name = name.Trim();
// Search again if the new name is different
diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
index 44e3cff6a..b68e6e4a9 100644
--- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
@@ -350,8 +350,6 @@ namespace MediaBrowser.Providers.TV
foreach (var episodeToRemove in episodesToRemove.Select(e => e.Episode))
{
- _logger.Info("Removing missing/unaired episode {0} {1}x{2}", episodeToRemove.Series.Name, episodeToRemove.ParentIndexNumber, episodeToRemove.IndexNumber);
-
await episodeToRemove.Delete(new DeleteOptions
{
DeleteFileLocation = true
@@ -418,8 +416,6 @@ namespace MediaBrowser.Providers.TV
foreach (var seasonToRemove in seasonsToRemove)
{
- _logger.Info("Removing virtual season {0} {1}", seasonToRemove.Series.Name, seasonToRemove.IndexNumber);
-
await seasonToRemove.Delete(new DeleteOptions
{
DeleteFileLocation = true
diff --git a/SharedVersion.cs b/SharedVersion.cs
index 617d9cf04..881dbe03c 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,3 +1,3 @@
using System.Reflection;
-[assembly: AssemblyVersion("3.2.33.7")]
+[assembly: AssemblyVersion("3.2.33.8")]