aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs8
-rw-r--r--Emby.Server.Implementations/Channels/ChannelManager.cs2
-rw-r--r--Emby.Server.Implementations/Connect/ConnectEntryPoint.cs27
-rw-r--r--Emby.Server.Implementations/Connect/ConnectManager.cs9
-rw-r--r--Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs8
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs120
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs8
-rw-r--r--Emby.Server.Implementations/Emby.Server.Implementations.csproj1
-rw-r--r--Emby.Server.Implementations/EntryPoints/SystemEvents.cs5
-rw-r--r--Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs5
-rw-r--r--Emby.Server.Implementations/EntryPoints/UsageReporter.cs5
-rw-r--r--Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs334
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs29
-rw-r--r--Emby.Server.Implementations/IO/FileRefresher.cs7
-rw-r--r--Emby.Server.Implementations/Intros/DefaultIntroProvider.cs18
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs41
-rw-r--r--Emby.Server.Implementations/Library/MediaSourceManager.cs2
-rw-r--r--Emby.Server.Implementations/Library/MusicManager.cs3
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs12
-rw-r--r--Emby.Server.Implementations/Library/SearchEngine.cs4
-rw-r--r--Emby.Server.Implementations/Library/UserManager.cs60
-rw-r--r--Emby.Server.Implementations/Library/UserViewManager.cs10
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs15
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs39
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs5
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveStreamHelper.cs10
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs12
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs10
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs1
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs10
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs1
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs14
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs85
-rw-r--r--Emby.Server.Implementations/Localization/iso6392.txt1
-rw-r--r--Emby.Server.Implementations/Migrations/GuideMigration.cs47
-rw-r--r--Emby.Server.Implementations/Migrations/LibraryScanMigration.cs2
-rw-r--r--Emby.Server.Implementations/Notifications/Notifications.cs17
-rw-r--r--Emby.Server.Implementations/Playlists/PlaylistManager.cs2
-rw-r--r--Emby.Server.Implementations/Sync/SyncHelper.cs2
-rw-r--r--Emby.Server.Implementations/Sync/SyncJobProcessor.cs20
-rw-r--r--Emby.Server.Implementations/Sync/SyncManager.cs8
-rw-r--r--Emby.Server.Implementations/Sync/TargetDataProvider.cs32
-rw-r--r--Emby.Server.Implementations/UserViews/DynamicImageProvider.cs4
43 files changed, 623 insertions, 432 deletions
diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
index 11fd3a872..d3b2ef7ef 100644
--- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
+++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
@@ -138,7 +138,7 @@ namespace Emby.Server.Implementations.Activity
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), user.Name, item.Name),
+ Name = string.Format(_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), user.Name, Notifications.Notifications.GetItemName(item)),
Type = "PlaybackStopped",
ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName),
UserId = user.Id.ToString("N")
@@ -170,7 +170,7 @@ namespace Emby.Server.Implementations.Activity
CreateLogEntry(new ActivityLogEntry
{
- Name = string.Format(_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), user.Name, item.Name),
+ Name = string.Format(_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), user.Name, Notifications.Notifications.GetItemName(item)),
Type = "PlaybackStart",
ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName),
UserId = user.Id.ToString("N")
@@ -235,10 +235,6 @@ namespace Emby.Server.Implementations.Activity
});
}
- void _logManager_LoggerLoaded(object sender, EventArgs e)
- {
- }
-
void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
{
CreateLogEntry(new ActivityLogEntry
diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs
index f7dc93009..8f03fa7a4 100644
--- a/Emby.Server.Implementations/Channels/ChannelManager.cs
+++ b/Emby.Server.Implementations/Channels/ChannelManager.cs
@@ -343,7 +343,7 @@ namespace Emby.Server.Implementations.Channels
private MediaSourceInfo GetMediaSource(BaseItem item, ChannelMediaInfo info)
{
- var source = info.ToMediaSource();
+ var source = info.ToMediaSource(item.Id);
source.RunTimeTicks = source.RunTimeTicks ?? item.RunTimeTicks;
diff --git a/Emby.Server.Implementations/Connect/ConnectEntryPoint.cs b/Emby.Server.Implementations/Connect/ConnectEntryPoint.cs
index 170ef07f3..b5639773b 100644
--- a/Emby.Server.Implementations/Connect/ConnectEntryPoint.cs
+++ b/Emby.Server.Implementations/Connect/ConnectEntryPoint.cs
@@ -9,6 +9,7 @@ using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
+using MediaBrowser.Controller.Security;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Threading;
@@ -17,6 +18,7 @@ namespace Emby.Server.Implementations.Connect
public class ConnectEntryPoint : IServerEntryPoint
{
private ITimer _timer;
+ private IpAddressInfo _cachedIpAddress;
private readonly IHttpClient _httpClient;
private readonly IApplicationPaths _appPaths;
private readonly ILogger _logger;
@@ -26,8 +28,9 @@ namespace Emby.Server.Implementations.Connect
private readonly IApplicationHost _appHost;
private readonly IFileSystem _fileSystem;
private readonly ITimerFactory _timerFactory;
+ private readonly IEncryptionManager _encryption;
- public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost, IFileSystem fileSystem, ITimerFactory timerFactory)
+ public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost, IFileSystem fileSystem, ITimerFactory timerFactory, IEncryptionManager encryption)
{
_httpClient = httpClient;
_appPaths = appPaths;
@@ -37,6 +40,7 @@ namespace Emby.Server.Implementations.Connect
_appHost = appHost;
_fileSystem = fileSystem;
_timerFactory = timerFactory;
+ _encryption = encryption;
}
public void Run()
@@ -143,17 +147,31 @@ namespace Emby.Server.Implementations.Connect
private string CacheFilePath
{
- get { return Path.Combine(_appPaths.DataPath, "wan.txt"); }
+ get { return Path.Combine(_appPaths.DataPath, "wan.dat"); }
}
private void CacheAddress(IpAddressInfo address)
{
+ if (_cachedIpAddress != null && _cachedIpAddress.Equals(address))
+ {
+ // no need to update the file if the address has not changed
+ return;
+ }
+
var path = CacheFilePath;
try
{
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
- _fileSystem.WriteAllText(path, address.ToString(), Encoding.UTF8);
+ }
+ catch (Exception ex)
+ {
+ }
+
+ try
+ {
+ _fileSystem.WriteAllText(path, _encryption.EncryptString(address.ToString()), Encoding.UTF8);
+ _cachedIpAddress = address;
}
catch (Exception ex)
{
@@ -169,11 +187,12 @@ namespace Emby.Server.Implementations.Connect
try
{
- var endpoint = _fileSystem.ReadAllText(path, Encoding.UTF8);
+ var endpoint = _encryption.DecryptString(_fileSystem.ReadAllText(path, Encoding.UTF8));
IpAddressInfo ipAddress;
if (_networkManager.TryParseIpAddress(endpoint, out ipAddress))
{
+ _cachedIpAddress = ipAddress;
((ConnectManager)_connectManager).OnWanAddressResolved(ipAddress);
}
}
diff --git a/Emby.Server.Implementations/Connect/ConnectManager.cs b/Emby.Server.Implementations/Connect/ConnectManager.cs
index 8c8b7b026..7e6755f6a 100644
--- a/Emby.Server.Implementations/Connect/ConnectManager.cs
+++ b/Emby.Server.Implementations/Connect/ConnectManager.cs
@@ -925,7 +925,11 @@ namespace Emby.Server.Implementations.Connect
}
_data.PendingAuthorizations = newPendingList;
- CacheData();
+
+ if (!newPendingList.Select(i => i.Id).SequenceEqual(currentPendingList.Select(i => i.Id), StringComparer.Ordinal))
+ {
+ CacheData();
+ }
await RefreshGuestNames(list, refreshImages).ConfigureAwait(false);
}
@@ -1118,7 +1122,7 @@ namespace Emby.Server.Implementations.Connect
}
}
- public async Task Authenticate(string username, string passwordMd5)
+ public async Task<ConnectAuthenticationResult> Authenticate(string username, string passwordMd5)
{
if (string.IsNullOrWhiteSpace(username))
{
@@ -1147,6 +1151,7 @@ namespace Emby.Server.Implementations.Connect
// No need to examine the response
using (var response = (await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)).Content)
{
+ return _json.DeserializeFromStream<ConnectAuthenticationResult>(response);
}
}
diff --git a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
index 5bc3a625f..2819a249f 100644
--- a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
+++ b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
@@ -137,6 +137,11 @@ namespace Emby.Server.Implementations.Data
var numComplete = 0;
var numItems = result.Count;
+ var allLibraryPaths = _libraryManager
+ .GetVirtualFolders()
+ .SelectMany(i => i.Locations)
+ .ToList();
+
foreach (var item in result)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -170,9 +175,8 @@ namespace Emby.Server.Implementations.Data
continue;
}
- if (Folder.IsPathOffline(path))
+ if (Folder.IsPathOffline(path, allLibraryPaths))
{
- await libraryItem.UpdateIsOffline(true).ConfigureAwait(false);
continue;
}
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index 8c16216b9..c158f2e51 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -372,7 +372,7 @@ namespace Emby.Server.Implementations.Data
userDataRepo.Initialize(WriteLock, _connection);
- _shrinkMemoryTimer = _timerFactory.Create(OnShrinkMemoryTimerCallback, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(15));
+ _shrinkMemoryTimer = _timerFactory.Create(OnShrinkMemoryTimerCallback, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(30));
}
private void OnShrinkMemoryTimerCallback(object state)
@@ -2384,8 +2384,17 @@ namespace Emby.Server.Implementations.Data
var excludeIds = query.ExcludeItemIds.ToList();
excludeIds.Add(item.Id.ToString("N"));
- query.ExcludeItemIds = excludeIds.ToArray();
+ if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Trailer).Name))
+ {
+ var hasTrailers = item as IHasTrailers;
+ if (hasTrailers != null)
+ {
+ excludeIds.AddRange(hasTrailers.GetTrailerIds().Select(i => i.ToString("N")));
+ }
+ }
+
+ query.ExcludeItemIds = excludeIds.ToArray();
query.ExcludeProviderIds = item.ProviderIds;
}
@@ -2548,57 +2557,53 @@ namespace Emby.Server.Implementations.Data
{
using (var connection = CreateConnection(true))
{
- return connection.RunInTransaction(db =>
- {
- var list = new List<BaseItem>();
+ var list = new List<BaseItem>();
- using (var statement = PrepareStatementSafe(db, commandText))
+ using (var statement = PrepareStatementSafe(connection, commandText))
+ {
+ if (EnableJoinUserData(query))
{
- if (EnableJoinUserData(query))
- {
- statement.TryBind("@UserId", query.User.Id);
- }
+ statement.TryBind("@UserId", query.User.Id);
+ }
- BindSimilarParams(query, statement);
+ BindSimilarParams(query, statement);
- // Running this again will bind the params
- GetWhereClauses(query, statement);
+ // Running this again will bind the params
+ GetWhereClauses(query, statement);
- foreach (var row in statement.ExecuteQuery())
+ foreach (var row in statement.ExecuteQuery())
+ {
+ var item = GetItem(row, query);
+ if (item != null)
{
- var item = GetItem(row, query);
- if (item != null)
- {
- list.Add(item);
- }
+ list.Add(item);
}
}
+ }
- // Hack for right now since we currently don't support filtering out these duplicates within a query
- if (query.EnableGroupByMetadataKey)
+ // Hack for right now since we currently don't support filtering out these duplicates within a query
+ if (query.EnableGroupByMetadataKey)
+ {
+ var limit = query.Limit ?? int.MaxValue;
+ limit -= 4;
+ var newList = new List<BaseItem>();
+
+ foreach (var item in list)
{
- var limit = query.Limit ?? int.MaxValue;
- limit -= 4;
- var newList = new List<BaseItem>();
+ AddItem(newList, item);
- foreach (var item in list)
+ if (newList.Count >= limit)
{
- AddItem(newList, item);
-
- if (newList.Count >= limit)
- {
- break;
- }
+ break;
}
-
- list = newList;
}
- LogQueryTime("GetItemList", commandText, now);
+ list = newList;
+ }
- return list;
+ LogQueryTime("GetItemList", commandText, now);
- }, ReadTransactionMode);
+ return list;
}
}
}
@@ -2652,7 +2657,7 @@ namespace Emby.Server.Implementations.Data
{
//Logger.Debug("{2} query time: {0}ms. Query: {1}",
// Convert.ToInt32(elapsed),
- // cmd.CommandText,
+ // commandText,
// methodName);
}
}
@@ -2825,8 +2830,9 @@ namespace Emby.Server.Implementations.Data
{
if (orderBy.Count == 0)
{
- 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>("SimilarityScore", SortOrder.Descending));
+ //orderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending));
query.SortOrder = SortOrder.Descending;
enableOrderInversion = false;
}
@@ -3212,6 +3218,11 @@ namespace Emby.Server.Implementations.Data
private List<string> GetWhereClauses(InternalItemsQuery query, IStatement statement, string paramSuffix = "")
{
+ if (query.IsResumable ?? false)
+ {
+ query.IsVirtualItem = false;
+ }
+
var whereClauses = new List<string>();
if (EnableJoinUserData(query))
@@ -3372,9 +3383,9 @@ namespace Emby.Server.Implementations.Data
}
}
- if (query.SimilarTo != null)
+ if (query.SimilarTo != null && query.MinSimilarityScore > 0)
{
- whereClauses.Add("SimilarityScore > 0");
+ whereClauses.Add("SimilarityScore > " + (query.MinSimilarityScore - 1).ToString(CultureInfo.InvariantCulture));
}
if (query.IsFolder.HasValue)
@@ -3616,10 +3627,12 @@ namespace Emby.Server.Implementations.Data
var index = 0;
foreach (var type in query.TrailerTypes)
{
- clauses.Add("TrailerTypes like @TrailerTypes" + index);
+ var paramName = "@TrailerTypes" + index;
+
+ clauses.Add("TrailerTypes like " + paramName);
if (statement != null)
{
- statement.TryBind("@TrailerTypes" + index, "%" + type + "%");
+ statement.TryBind(paramName, "%" + type + "%");
}
index++;
}
@@ -4085,27 +4098,6 @@ namespace Emby.Server.Implementations.Data
whereClauses.Add("LocationType in (" + val + ")");
}
- if (query.ExcludeLocationTypes.Length == 1)
- {
- if (query.ExcludeLocationTypes[0] == LocationType.Virtual && _config.Configuration.SchemaVersion >= 90)
- {
- query.IsVirtualItem = false;
- }
- else
- {
- whereClauses.Add("LocationType<>@ExcludeLocationTypes");
- if (statement != null)
- {
- statement.TryBind("@ExcludeLocationTypes", query.ExcludeLocationTypes[0].ToString());
- }
- }
- }
- else if (query.ExcludeLocationTypes.Length > 1)
- {
- var val = string.Join(",", query.ExcludeLocationTypes.Select(i => "'" + i + "'").ToArray());
-
- whereClauses.Add("LocationType not in (" + val + ")");
- }
if (query.IsVirtualItem.HasValue)
{
whereClauses.Add("IsVirtualItem=@IsVirtualItem");
@@ -4221,7 +4213,7 @@ namespace Emby.Server.Implementations.Data
var paramName = "@ExcludeProviderId" + index;
//excludeIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")");
- excludeIds.Add("ProviderIds not like " + paramName);
+ excludeIds.Add("(ProviderIds is null or ProviderIds not like " + paramName + ")");
if (statement != null)
{
statement.TryBind(paramName, "%" + pair.Key + "=" + pair.Value + "%");
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index 8e6c1263d..f866c34de 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -361,10 +361,7 @@ namespace Emby.Server.Implementations.Dto
if (collectionFolder != null)
{
dto.OriginalCollectionType = collectionFolder.CollectionType;
-
- dto.CollectionType = user == null ?
- collectionFolder.CollectionType :
- collectionFolder.GetViewType(user);
+ dto.CollectionType = collectionFolder.CollectionType;
}
if (fields.Contains(ItemFields.CanDelete))
@@ -1515,7 +1512,8 @@ namespace Emby.Server.Implementations.Dto
return artist;
}
}
- return item.GetParent();
+
+ return item.DisplayParent ?? item.GetParent();
}
private void AddInheritedImages(BaseItemDto dto, BaseItem item, DtoOptions options, BaseItem owner)
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index 7ee0c566f..e3cd96894 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -182,6 +182,7 @@
<Compile Include="MediaEncoder\EncodingManager.cs" />
<Compile Include="Migrations\IVersionMigration.cs" />
<Compile Include="Migrations\LibraryScanMigration.cs" />
+ <Compile Include="Migrations\GuideMigration.cs" />
<Compile Include="Migrations\UpdateLevelMigration.cs" />
<Compile Include="News\NewsEntryPoint.cs" />
<Compile Include="News\NewsService.cs" />
diff --git a/Emby.Server.Implementations/EntryPoints/SystemEvents.cs b/Emby.Server.Implementations/EntryPoints/SystemEvents.cs
index 021ae47ec..4ab6d32f3 100644
--- a/Emby.Server.Implementations/EntryPoints/SystemEvents.cs
+++ b/Emby.Server.Implementations/EntryPoints/SystemEvents.cs
@@ -6,15 +6,16 @@ using System.Threading.Tasks;
using MediaBrowser.Model.System;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Common;
+using MediaBrowser.Controller;
namespace Emby.Server.Implementations.EntryPoints
{
public class SystemEvents : IServerEntryPoint
{
private readonly ISystemEvents _systemEvents;
- private readonly IApplicationHost _appHost;
+ private readonly IServerApplicationHost _appHost;
- public SystemEvents(ISystemEvents systemEvents, IApplicationHost appHost)
+ public SystemEvents(ISystemEvents systemEvents, IServerApplicationHost appHost)
{
_systemEvents = systemEvents;
_appHost = appHost;
diff --git a/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs
index 1b897ca29..9fbe06673 100644
--- a/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs
+++ b/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs
@@ -10,6 +10,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
namespace Emby.Server.Implementations.EntryPoints
@@ -19,7 +20,7 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary>
public class UsageEntryPoint : IServerEntryPoint
{
- private readonly IApplicationHost _applicationHost;
+ private readonly IServerApplicationHost _applicationHost;
private readonly IHttpClient _httpClient;
private readonly ILogger _logger;
private readonly ISessionManager _sessionManager;
@@ -28,7 +29,7 @@ namespace Emby.Server.Implementations.EntryPoints
private readonly ConcurrentDictionary<Guid, ClientInfo> _apps = new ConcurrentDictionary<Guid, ClientInfo>();
- public UsageEntryPoint(ILogger logger, IApplicationHost applicationHost, IHttpClient httpClient, ISessionManager sessionManager, IUserManager userManager, IServerConfigurationManager config)
+ public UsageEntryPoint(ILogger logger, IServerApplicationHost applicationHost, IHttpClient httpClient, ISessionManager sessionManager, IUserManager userManager, IServerConfigurationManager config)
{
_logger = logger;
_applicationHost = applicationHost;
diff --git a/Emby.Server.Implementations/EntryPoints/UsageReporter.cs b/Emby.Server.Implementations/EntryPoints/UsageReporter.cs
index be848acb7..31254c6c2 100644
--- a/Emby.Server.Implementations/EntryPoints/UsageReporter.cs
+++ b/Emby.Server.Implementations/EntryPoints/UsageReporter.cs
@@ -8,19 +8,20 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Controller;
using MediaBrowser.Model.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
public class UsageReporter
{
- private readonly IApplicationHost _applicationHost;
+ private readonly IServerApplicationHost _applicationHost;
private readonly IHttpClient _httpClient;
private readonly IUserManager _userManager;
private readonly ILogger _logger;
private const string MbAdminUrl = "https://www.mb3admin.com/admin/";
- public UsageReporter(IApplicationHost applicationHost, IHttpClient httpClient, IUserManager userManager, ILogger logger)
+ public UsageReporter(IServerApplicationHost applicationHost, IHttpClient httpClient, IUserManager userManager, ILogger logger)
{
_applicationHost = applicationHost;
_httpClient = httpClient;
diff --git a/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
index 5bb21d02a..f841b8b6b 100644
--- a/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
+++ b/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
@@ -61,92 +61,92 @@ namespace Emby.Server.Implementations.FileOrganization
};
try
- {
- if (_libraryMonitor.IsPathLocked(path))
{
- result.Status = FileSortingStatus.Failure;
- result.StatusMessage = "Path is locked by other processes. Please try again later.";
- return result;
- }
+ if (_libraryMonitor.IsPathLocked(path))
+ {
+ result.Status = FileSortingStatus.Failure;
+ result.StatusMessage = "Path is locked by other processes. Please try again later.";
+ return result;
+ }
- var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
- var resolver = new EpisodeResolver(namingOptions, new NullLogger());
+ var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
+ var resolver = new EpisodeResolver(namingOptions, new NullLogger());
- var episodeInfo = resolver.Resolve(path, false) ??
- new MediaBrowser.Naming.TV.EpisodeInfo();
+ var episodeInfo = resolver.Resolve(path, false) ??
+ new MediaBrowser.Naming.TV.EpisodeInfo();
- var seriesName = episodeInfo.SeriesName;
+ var seriesName = episodeInfo.SeriesName;
- if (!string.IsNullOrEmpty(seriesName))
- {
- var seasonNumber = episodeInfo.SeasonNumber;
+ if (!string.IsNullOrEmpty(seriesName))
+ {
+ var seasonNumber = episodeInfo.SeasonNumber;
- result.ExtractedSeasonNumber = seasonNumber;
+ result.ExtractedSeasonNumber = seasonNumber;
- // Passing in true will include a few extra regex's
- var episodeNumber = episodeInfo.EpisodeNumber;
+ // Passing in true will include a few extra regex's
+ var episodeNumber = episodeInfo.EpisodeNumber;
- result.ExtractedEpisodeNumber = episodeNumber;
+ result.ExtractedEpisodeNumber = episodeNumber;
- var premiereDate = episodeInfo.IsByDate ?
- new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value) :
- (DateTime?)null;
+ var premiereDate = episodeInfo.IsByDate ?
+ new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value) :
+ (DateTime?)null;
- if (episodeInfo.IsByDate || (seasonNumber.HasValue && episodeNumber.HasValue))
- {
- if (episodeInfo.IsByDate)
+ if (episodeInfo.IsByDate || (seasonNumber.HasValue && episodeNumber.HasValue))
{
- _logger.Debug("Extracted information from {0}. Series name {1}, Date {2}", path, seriesName, premiereDate.Value);
+ if (episodeInfo.IsByDate)
+ {
+ _logger.Debug("Extracted information from {0}. Series name {1}, Date {2}", path, seriesName, premiereDate.Value);
+ }
+ else
+ {
+ _logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, seasonNumber, episodeNumber);
+ }
+
+ var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber;
+
+ result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;
+
+ await OrganizeEpisode(path,
+ seriesName,
+ seasonNumber,
+ episodeNumber,
+ endingEpisodeNumber,
+ premiereDate,
+ options,
+ overwriteExisting,
+ false,
+ result,
+ cancellationToken).ConfigureAwait(false);
}
else
{
- _logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, seasonNumber, episodeNumber);
+ var msg = string.Format("Unable to determine episode number from {0}", path);
+ result.Status = FileSortingStatus.Failure;
+ result.StatusMessage = msg;
+ _logger.Warn(msg);
}
-
- var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber;
-
- result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;
-
- await OrganizeEpisode(path,
- seriesName,
- seasonNumber,
- episodeNumber,
- endingEpisodeNumber,
- premiereDate,
- options,
- overwriteExisting,
- false,
- result,
- cancellationToken).ConfigureAwait(false);
}
else
{
- var msg = string.Format("Unable to determine episode number from {0}", path);
+ var msg = string.Format("Unable to determine series name from {0}", path);
result.Status = FileSortingStatus.Failure;
result.StatusMessage = msg;
_logger.Warn(msg);
}
- }
- else
- {
- var msg = string.Format("Unable to determine series name from {0}", path);
- result.Status = FileSortingStatus.Failure;
- result.StatusMessage = msg;
- _logger.Warn(msg);
- }
- var previousResult = _organizationService.GetResultBySourcePath(path);
+ var previousResult = _organizationService.GetResultBySourcePath(path);
- if (previousResult != null)
- {
- // Don't keep saving the same result over and over if nothing has changed
- if (previousResult.Status == result.Status && previousResult.StatusMessage == result.StatusMessage && result.Status != FileSortingStatus.Success)
+ if (previousResult != null)
{
- return previousResult;
+ // Don't keep saving the same result over and over if nothing has changed
+ if (previousResult.Status == result.Status && previousResult.StatusMessage == result.StatusMessage && result.Status != FileSortingStatus.Success)
+ {
+ return previousResult;
+ }
}
- }
- await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
+ await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -162,58 +162,60 @@ namespace Emby.Server.Implementations.FileOrganization
var result = _organizationService.GetResult(request.ResultId);
try
- {
- Series series = null;
-
- if (request.NewSeriesProviderIds.Count > 0)
{
- // We're having a new series here
- SeriesInfo seriesRequest = new SeriesInfo();
- seriesRequest.ProviderIds = request.NewSeriesProviderIds;
-
- var refreshOptions = new MetadataRefreshOptions(_fileSystem);
- series = new Series();
- series.Id = Guid.NewGuid();
- series.Name = request.NewSeriesName;
+ Series series = null;
- int year;
- if (int.TryParse(request.NewSeriesYear, out year))
+ if (request.NewSeriesProviderIds.Count > 0)
{
- series.ProductionYear = year;
- }
+ // We're having a new series here
+ SeriesInfo seriesRequest = new SeriesInfo();
+ seriesRequest.ProviderIds = request.NewSeriesProviderIds;
- var seriesFolderName = series.Name;
- if (series.ProductionYear.HasValue)
- {
- seriesFolderName = string.Format("{0} ({1})", seriesFolderName, series.ProductionYear);
- }
+ var refreshOptions = new MetadataRefreshOptions(_fileSystem);
+ series = new Series();
+ series.Id = Guid.NewGuid();
+ series.Name = request.NewSeriesName;
+
+ int year;
+ if (int.TryParse(request.NewSeriesYear, out year))
+ {
+ series.ProductionYear = year;
+ }
- series.Path = Path.Combine(request.TargetFolder, seriesFolderName);
+ var seriesFolderName = series.Name;
+ if (series.ProductionYear.HasValue)
+ {
+ seriesFolderName = string.Format("{0} ({1})", seriesFolderName, series.ProductionYear);
+ }
- series.ProviderIds = request.NewSeriesProviderIds;
+ seriesFolderName = _fileSystem.GetValidFilename(seriesFolderName);
- await series.RefreshMetadata(refreshOptions, cancellationToken);
- }
+ series.Path = Path.Combine(request.TargetFolder, seriesFolderName);
- if (series == null)
- {
- // Existing Series
- series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId));
- }
+ series.ProviderIds = request.NewSeriesProviderIds;
- await OrganizeEpisode(result.OriginalPath,
- series,
- request.SeasonNumber,
- request.EpisodeNumber,
- request.EndingEpisodeNumber,
- null,
- options,
- true,
- request.RememberCorrection,
- result,
- cancellationToken).ConfigureAwait(false);
+ await series.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
+ }
+
+ if (series == null)
+ {
+ // Existing Series
+ series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId));
+ }
+
+ await OrganizeEpisode(result.OriginalPath,
+ series,
+ request.SeasonNumber,
+ request.EpisodeNumber,
+ request.EndingEpisodeNumber,
+ null,
+ options,
+ true,
+ request.RememberCorrection,
+ result,
+ cancellationToken).ConfigureAwait(false);
- await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
+ await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -287,91 +289,91 @@ namespace Emby.Server.Implementations.FileOrganization
{
throw new Exception("File is currently processed otherwise. Please try again later.");
}
-
- 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);
- throw new Exception(msg);
- }
-
- _logger.Info("Sorting file {0} to new path {1}", sourcePath, newPath);
- result.TargetPath = newPath;
-
- var fileExists = _fileSystem.FileExists(result.TargetPath);
- var otherDuplicatePaths = GetOtherDuplicatePaths(result.TargetPath, series, seasonNumber, episodeNumber, endingEpiosdeNumber);
- if (!overwriteExisting)
+ try
{
- if (options.TvOptions.CopyOriginalFile && fileExists && IsSameEpisode(sourcePath, newPath))
- {
- var msg = string.Format("File '{0}' already copied to new path '{1}', stopping organization", sourcePath, newPath);
- _logger.Info(msg);
- result.Status = FileSortingStatus.SkippedExisting;
- result.StatusMessage = msg;
- return;
- }
+ // Proceed to sort the file
+ var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options.TvOptions, cancellationToken).ConfigureAwait(false);
- if (fileExists)
+ if (string.IsNullOrEmpty(newPath))
{
- var msg = string.Format("File '{0}' already exists as '{1}', stopping organization", sourcePath, newPath);
- _logger.Info(msg);
- result.Status = FileSortingStatus.SkippedExisting;
- result.StatusMessage = msg;
- result.TargetPath = newPath;
- return;
+ var msg = string.Format("Unable to sort {0} because target path could not be determined.", sourcePath);
+ throw new Exception(msg);
}
- if (otherDuplicatePaths.Count > 0)
- {
- var msg = string.Format("File '{0}' already exists as these:'{1}'. Stopping organization", sourcePath, string.Join("', '", otherDuplicatePaths));
- _logger.Info(msg);
- result.Status = FileSortingStatus.SkippedExisting;
- result.StatusMessage = msg;
- result.DuplicatePaths = otherDuplicatePaths;
- return;
- }
- }
+ _logger.Info("Sorting file {0} to new path {1}", sourcePath, newPath);
+ result.TargetPath = newPath;
- PerformFileSorting(options.TvOptions, result);
-
- if (overwriteExisting)
- {
- var hasRenamedFiles = false;
+ var fileExists = _fileSystem.FileExists(result.TargetPath);
+ var otherDuplicatePaths = GetOtherDuplicatePaths(result.TargetPath, series, seasonNumber, episodeNumber, endingEpiosdeNumber);
- foreach (var path in otherDuplicatePaths)
+ if (!overwriteExisting)
{
- _logger.Debug("Removing duplicate episode {0}", path);
-
- _libraryMonitor.ReportFileSystemChangeBeginning(path);
-
- var renameRelatedFiles = !hasRenamedFiles &&
- string.Equals(Path.GetDirectoryName(path), Path.GetDirectoryName(result.TargetPath), StringComparison.OrdinalIgnoreCase);
-
- if (renameRelatedFiles)
+ if (options.TvOptions.CopyOriginalFile && fileExists && IsSameEpisode(sourcePath, newPath))
{
- hasRenamedFiles = true;
+ var msg = string.Format("File '{0}' already copied to new path '{1}', stopping organization", sourcePath, newPath);
+ _logger.Info(msg);
+ result.Status = FileSortingStatus.SkippedExisting;
+ result.StatusMessage = msg;
+ return;
}
- try
+ if (fileExists)
{
- DeleteLibraryFile(path, renameRelatedFiles, result.TargetPath);
+ var msg = string.Format("File '{0}' already exists as '{1}', stopping organization", sourcePath, newPath);
+ _logger.Info(msg);
+ result.Status = FileSortingStatus.SkippedExisting;
+ result.StatusMessage = msg;
+ result.TargetPath = newPath;
+ return;
}
- catch (IOException ex)
+
+ if (otherDuplicatePaths.Count > 0)
{
- _logger.ErrorException("Error removing duplicate episode", ex, path);
+ var msg = string.Format("File '{0}' already exists as these:'{1}'. Stopping organization", sourcePath, string.Join("', '", otherDuplicatePaths));
+ _logger.Info(msg);
+ result.Status = FileSortingStatus.SkippedExisting;
+ result.StatusMessage = msg;
+ result.DuplicatePaths = otherDuplicatePaths;
+ return;
}
- finally
+ }
+
+ PerformFileSorting(options.TvOptions, result);
+
+ if (overwriteExisting)
+ {
+ var hasRenamedFiles = false;
+
+ foreach (var path in otherDuplicatePaths)
{
- _libraryMonitor.ReportFileSystemChangeComplete(path, true);
+ _logger.Debug("Removing duplicate episode {0}", path);
+
+ _libraryMonitor.ReportFileSystemChangeBeginning(path);
+
+ var renameRelatedFiles = !hasRenamedFiles &&
+ string.Equals(Path.GetDirectoryName(path), Path.GetDirectoryName(result.TargetPath), StringComparison.OrdinalIgnoreCase);
+
+ if (renameRelatedFiles)
+ {
+ hasRenamedFiles = true;
+ }
+
+ try
+ {
+ DeleteLibraryFile(path, renameRelatedFiles, result.TargetPath);
+ }
+ catch (IOException ex)
+ {
+ _logger.ErrorException("Error removing duplicate episode", ex, path);
+ }
+ finally
+ {
+ _libraryMonitor.ReportFileSystemChangeComplete(path, true);
+ }
}
}
}
- }
catch (Exception ex)
{
result.Status = FileSortingStatus.Failure;
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
index ec3dfeb60..ede85fb67 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
@@ -49,6 +49,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
string device = null;
string client = null;
string version = null;
+ string token = null;
if (auth != null)
{
@@ -56,9 +57,13 @@ namespace Emby.Server.Implementations.HttpServer.Security
auth.TryGetValue("Device", out device);
auth.TryGetValue("Client", out client);
auth.TryGetValue("Version", out version);
+ auth.TryGetValue("Token", out token);
}
- var token = httpReq.Headers["X-Emby-Token"];
+ if (string.IsNullOrWhiteSpace(token))
+ {
+ token = httpReq.Headers["X-Emby-Token"];
+ }
if (string.IsNullOrWhiteSpace(token))
{
@@ -156,8 +161,10 @@ namespace Emby.Server.Implementations.HttpServer.Security
// There should be at least to parts
if (parts.Length != 2) return null;
+ var acceptedNames = new[] { "MediaBrowser", "Emby"};
+
// It has to be a digest request
- if (!string.Equals(parts[0], "MediaBrowser", StringComparison.OrdinalIgnoreCase))
+ if (!acceptedNames.Contains(parts[0] ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{
return null;
}
@@ -174,7 +181,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
if (param.Length == 2)
{
- var value = NormalizeValue (param[1].Trim(new[] { '"' }));
+ var value = NormalizeValue(param[1].Trim(new[] { '"' }));
result.Add(param[0], value);
}
}
@@ -182,14 +189,14 @@ namespace Emby.Server.Implementations.HttpServer.Security
return result;
}
- private string NormalizeValue(string value)
- {
- if (string.IsNullOrWhiteSpace (value))
- {
- return value;
- }
+ private string NormalizeValue(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ return value;
+ }
- return System.Net.WebUtility.HtmlEncode(value);
- }
+ return System.Net.WebUtility.HtmlEncode(value);
+ }
}
}
diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs
index 39033249f..d7f2ffa43 100644
--- a/Emby.Server.Implementations/IO/FileRefresher.cs
+++ b/Emby.Server.Implementations/IO/FileRefresher.cs
@@ -261,10 +261,11 @@ namespace Emby.Server.Implementations.IO
// In order to determine if the file is being written to, we have to request write access
// But if the server only has readonly access, this is going to cause this entire algorithm to fail
// So we'll take a best guess about our access level
- var requestedFileAccess = ConfigurationManager.Configuration.SaveLocalMeta
- ? FileAccessMode.ReadWrite
- : FileAccessMode.Read;
+ //var requestedFileAccess = ConfigurationManager.Configuration.SaveLocalMeta
+ // ? FileAccessMode.ReadWrite
+ // : FileAccessMode.Read;
+ var requestedFileAccess = FileAccessMode.Read;
try
{
using (_fileSystem.GetFileStream(path, FileOpenMode.Open, requestedFileAccess, FileShareMode.ReadWrite))
diff --git a/Emby.Server.Implementations/Intros/DefaultIntroProvider.cs b/Emby.Server.Implementations/Intros/DefaultIntroProvider.cs
index 180f6aba7..4d19a0e9b 100644
--- a/Emby.Server.Implementations/Intros/DefaultIntroProvider.cs
+++ b/Emby.Server.Implementations/Intros/DefaultIntroProvider.cs
@@ -100,20 +100,30 @@ namespace Emby.Server.Implementations.Intros
if (trailerTypes.Count > 0)
{
+ if (trailerTypes.Count >= 5)
+ {
+ trailerTypes.Clear();
+ }
+
+ // hack - can't filter by user library because local trailers get TopParentId =null in the db.
+ // for now we have to use a post-query filter afterwards to solve that
var trailerResult = _libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(Trailer).Name },
TrailerTypes = trailerTypes.ToArray(),
SimilarTo = item,
- IsPlayed = config.EnableIntrosForWatchedContent ? (bool?)null : false,
+ //IsPlayed = config.EnableIntrosForWatchedContent ? (bool?)null : false,
MaxParentalRating = config.EnableIntrosParentalControl ? ratingLevel : null,
BlockUnratedItems = config.EnableIntrosParentalControl ? new[] { UnratedItem.Trailer } : new UnratedItem[] { },
// Account for duplicates by imdb id, since the database doesn't support this yet
- Limit = config.TrailerLimit * 2,
+ Limit = config.TrailerLimit * 4,
SourceTypes = sourceTypes.ToArray()
-
- }).Where(i => string.IsNullOrWhiteSpace(i.GetProviderId(MetadataProviders.Imdb)) || !string.Equals(i.GetProviderId(MetadataProviders.Imdb), item.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase)).Take(config.TrailerLimit);
+ })
+ .Where(i => string.IsNullOrWhiteSpace(i.GetProviderId(MetadataProviders.Imdb)) || !string.Equals(i.GetProviderId(MetadataProviders.Imdb), item.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase))
+ .Where(i => i.IsVisibleStandalone(user))
+ .Where(i => config.EnableIntrosForWatchedContent || !i.IsPlayed(user))
+ .Take(config.TrailerLimit);
candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer
{
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 4c788a2ab..c59a22884 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -1956,30 +1956,6 @@ namespace Emby.Server.Implementations.Library
var options = collectionFolder == null ? new LibraryOptions() : collectionFolder.GetLibraryOptions();
- if (options.SchemaVersion < 3)
- {
- options.SaveLocalMetadata = ConfigurationManager.Configuration.SaveLocalMeta;
- options.EnableInternetProviders = ConfigurationManager.Configuration.EnableInternetProviders;
- }
-
- if (options.SchemaVersion < 2)
- {
- var chapterOptions = ConfigurationManager.GetConfiguration<ChapterOptions>("chapters");
- options.ExtractChapterImagesDuringLibraryScan = chapterOptions.ExtractDuringLibraryScan;
-
- if (collectionFolder != null)
- {
- if (string.Equals(collectionFolder.CollectionType, "movies", StringComparison.OrdinalIgnoreCase))
- {
- options.EnableChapterImageExtraction = chapterOptions.EnableMovieChapterImageExtraction;
- }
- else if (string.Equals(collectionFolder.CollectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
- {
- options.EnableChapterImageExtraction = chapterOptions.EnableEpisodeChapterImageExtraction;
- }
- }
- }
-
return options;
}
@@ -2034,7 +2010,7 @@ namespace Emby.Server.Implementations.Library
private string GetContentTypeOverride(string path, bool inherit)
{
- var nameValuePair = ConfigurationManager.Configuration.ContentTypes.FirstOrDefault(i => string.Equals(i.Name, path, StringComparison.OrdinalIgnoreCase) || (inherit && !string.IsNullOrWhiteSpace(i.Name) && _fileSystem.ContainsSubPath(i.Name, path)));
+ var nameValuePair = ConfigurationManager.Configuration.ContentTypes.FirstOrDefault(i => _fileSystem.AreEqual(i.Name, path) || (inherit && !string.IsNullOrWhiteSpace(i.Name) && _fileSystem.ContainsSubPath(i.Name, path)));
if (nameValuePair != null)
{
return nameValuePair.Value;
@@ -2505,6 +2481,8 @@ namespace Emby.Server.Implementations.Library
options.VideoFileExtensions.Remove(".zip");
}
+ options.VideoFileExtensions.Add(".tp");
+
return options;
}
@@ -2615,7 +2593,7 @@ namespace Emby.Server.Implementations.Library
{
foreach (var pathInfo in libraryOptions.PathInfos)
{
- if (string.IsNullOrWhiteSpace(pathInfo.NetworkPath))
+ if (string.IsNullOrWhiteSpace(pathInfo.Path) || string.IsNullOrWhiteSpace(pathInfo.NetworkPath))
{
continue;
}
@@ -2643,10 +2621,13 @@ namespace Emby.Server.Implementations.Library
foreach (var map in ConfigurationManager.Configuration.PathSubstitutions)
{
- var substitutionResult = SubstitutePathInternal(path, map.From, map.To);
- if (substitutionResult.Item2)
+ if (!string.IsNullOrWhiteSpace(map.From))
{
- return substitutionResult.Item1;
+ var substitutionResult = SubstitutePathInternal(path, map.From, map.To);
+ if (substitutionResult.Item2)
+ {
+ return substitutionResult.Item1;
+ }
}
}
@@ -3088,7 +3069,7 @@ namespace Emby.Server.Implementations.Library
{
removeList.Add(contentType);
}
- else if (string.Equals(path, contentType.Name, StringComparison.OrdinalIgnoreCase)
+ else if (_fileSystem.AreEqual(path, contentType.Name)
|| _fileSystem.ContainsSubPath(path, contentType.Name))
{
removeList.Add(contentType);
diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs
index 93c406ebc..c1bd8fe91 100644
--- a/Emby.Server.Implementations/Library/MediaSourceManager.cs
+++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs
@@ -199,6 +199,8 @@ namespace Emby.Server.Implementations.Library
foreach (var mediaSource in list)
{
+ mediaSource.InferTotalBitrate();
+
SetKeyProperties(provider, mediaSource);
}
diff --git a/Emby.Server.Implementations/Library/MusicManager.cs b/Emby.Server.Implementations/Library/MusicManager.cs
index 7669dd0bf..9d07837c6 100644
--- a/Emby.Server.Implementations/Library/MusicManager.cs
+++ b/Emby.Server.Implementations/Library/MusicManager.cs
@@ -105,11 +105,10 @@ namespace Emby.Server.Implementations.Library
return inputItems
.Cast<Audio>()
.Select(i => new Tuple<Audio, int>(i, i.Genres.Count(genresDictionary.ContainsKey)))
- .Where(i => i.Item2 > 0)
.OrderByDescending(i => i.Item2)
.ThenBy(i => Guid.NewGuid())
.Select(i => i.Item1)
- .Take(100)
+ .Take(200)
.OrderBy(i => Guid.NewGuid());
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
index 871b2d46d..b3d6d4ad7 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
@@ -142,12 +142,14 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
}
}
}
-
- var fullName = fileSystemInfo.FullName;
-
- if (libraryManager.IsAudioFile(fullName, libraryOptions))
+ else
{
- return true;
+ var fullName = fileSystemInfo.FullName;
+
+ if (libraryManager.IsAudioFile(fullName, libraryOptions))
+ {
+ return true;
+ }
}
}
diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs
index afdf65c06..e6c88aa1a 100644
--- a/Emby.Server.Implementations/Library/SearchEngine.cs
+++ b/Emby.Server.Implementations/Library/SearchEngine.cs
@@ -157,6 +157,7 @@ namespace Emby.Server.Implementations.Library
}
AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name);
+ AddIfMissing(excludeItemTypes, typeof(Folder).Name);
var mediaItems = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
@@ -164,8 +165,7 @@ namespace Emby.Server.Implementations.Library
ExcludeItemTypes = excludeItemTypes.ToArray(),
IncludeItemTypes = includeItemTypes.ToArray(),
Limit = query.Limit,
- IncludeItemsByName = true,
- IsVirtualItem = false
+ IncludeItemsByName = true
});
// Add search hints based on item name
diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs
index 2a5706b3b..eb0d0cf9b 100644
--- a/Emby.Server.Implementations/Library/UserManager.cs
+++ b/Emby.Server.Implementations/Library/UserManager.cs
@@ -236,29 +236,63 @@ namespace Emby.Server.Implementations.Library
var user = Users
.FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
- if (user == null)
- {
- throw new SecurityException("Invalid username or password entered.");
- }
+ var success = false;
- if (user.Policy.IsDisabled)
+ if (user != null)
{
- throw new SecurityException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
- }
+ // Authenticate using local credentials if not a guest
+ if (!user.ConnectLinkType.HasValue || user.ConnectLinkType.Value != UserLinkType.Guest)
+ {
+ success = string.Equals(GetPasswordHash(user), passwordSha1.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
- var success = false;
+ if (!success && _networkManager.IsInLocalNetwork(remoteEndPoint) && user.Configuration.EnableLocalPassword)
+ {
+ success = string.Equals(GetLocalPasswordHash(user), passwordSha1.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
+ }
+ }
- // Authenticate using local credentials if not a guest
- if (!user.ConnectLinkType.HasValue || user.ConnectLinkType.Value != UserLinkType.Guest)
+ // Maybe user accidently entered connect credentials. let's be flexible
+ if (!success && user.ConnectLinkType.HasValue && !string.IsNullOrWhiteSpace(passwordMd5) && !string.IsNullOrWhiteSpace(user.ConnectUserName))
+ {
+ try
+ {
+ await _connectFactory().Authenticate(user.ConnectUserName, passwordMd5).ConfigureAwait(false);
+ success = true;
+ }
+ catch
+ {
+
+ }
+ }
+ }
+
+ // Try originally entered username
+ if (!success && (user == null || !string.Equals(user.ConnectUserName, username, StringComparison.OrdinalIgnoreCase)))
{
- success = string.Equals(GetPasswordHash(user), passwordSha1.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
+ try
+ {
+ var connectAuthResult = await _connectFactory().Authenticate(username, passwordMd5).ConfigureAwait(false);
- if (!success && _networkManager.IsInLocalNetwork(remoteEndPoint) && user.Configuration.EnableLocalPassword)
+ user = Users.FirstOrDefault(i => string.Equals(i.ConnectUserId, connectAuthResult.User.Id, StringComparison.OrdinalIgnoreCase));
+
+ success = user != null;
+ }
+ catch
{
- success = string.Equals(GetLocalPasswordHash(user), passwordSha1.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
+
}
}
+ if (user == null)
+ {
+ throw new SecurityException("Invalid username or password entered.");
+ }
+
+ if (user.Policy.IsDisabled)
+ {
+ throw new SecurityException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
+ }
+
// Update LastActivityDate and LastLoginDate, then save
if (success)
{
diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs
index f7cc8bb73..f11cbd498 100644
--- a/Emby.Server.Implementations/Library/UserViewManager.cs
+++ b/Emby.Server.Implementations/Library/UserViewManager.cs
@@ -55,8 +55,6 @@ namespace Emby.Server.Implementations.Library
}).ToList();
}
- var plainFolderIds = user.Configuration.PlainFolderViews.Select(i => new Guid(i)).ToList();
-
var groupedFolders = new List<ICollectionFolder>();
var list = new List<Folder>();
@@ -72,12 +70,6 @@ namespace Emby.Server.Implementations.Library
continue;
}
- if (plainFolderIds.Contains(folder.Id) && UserView.IsEligibleForEnhancedView(folderViewType))
- {
- list.Add(folder);
- continue;
- }
-
if (collectionFolder != null && UserView.IsEligibleForGrouping(folder) && user.IsFolderGrouped(folder.Id))
{
groupedFolders.Add(collectionFolder);
@@ -287,7 +279,7 @@ namespace Emby.Server.Implementations.Library
SortBy = new[] { ItemSortBy.DateCreated },
IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null,
ExcludeItemTypes = excludeItemTypes,
- ExcludeLocationTypes = new[] { LocationType.Virtual },
+ IsVirtualItem = false,
Limit = limit * 5,
SourceTypes = parents.Count == 0 ? new[] { SourceType.Library } : new SourceType[] { },
IsPlayed = request.IsPlayed
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 2e591711b..5e0b4ff34 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -150,7 +150,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
foreach (var recordingFolder in recordingFolders)
{
var pathsToCreate = recordingFolder.Locations
- .Where(i => !allExistingPaths.Contains(i, StringComparer.OrdinalIgnoreCase))
+ .Where(i => !allExistingPaths.Any(p => _fileSystem.AreEqual(p, i)))
.ToList();
if (pathsToCreate.Count == 0)
@@ -1370,13 +1370,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
ActiveRecordingInfo removed;
_activeRecordings.TryRemove(timer.Id, out removed);
- if (recordingStatus != RecordingStatus.Completed && DateTime.UtcNow < timer.EndDate)
+ if (recordingStatus != RecordingStatus.Completed && DateTime.UtcNow < timer.EndDate && timer.RetryCount < 10)
{
const int retryIntervalSeconds = 60;
_logger.Info("Retrying recording in {0} seconds.", retryIntervalSeconds);
timer.Status = RecordingStatus.New;
timer.StartDate = DateTime.UtcNow.AddSeconds(retryIntervalSeconds);
+ timer.RetryCount++;
_timerProvider.AddOrUpdate(timer);
}
else if (_fileSystem.FileExists(recordPath))
@@ -2106,13 +2107,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
return true;
}
-
- if (!seriesTimer.Days.Contains(timer.StartDate.ToLocalTime().DayOfWeek))
- {
- return true;
- }
}
+ //if (!seriesTimer.Days.Contains(timer.StartDate.ToLocalTime().DayOfWeek))
+ //{
+ // return true;
+ //}
+
if (seriesTimer.RecordNewOnly && timer.IsRepeat)
{
return true;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index 5e55b893f..beb08cc25 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -240,14 +240,49 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
try
{
- _logger.Info("Killing ffmpeg recording process for {0}", _targetPath);
+ _logger.Info("Stopping ffmpeg recording process for {0}", _targetPath);
//process.Kill();
_process.StandardInput.WriteLine("q");
}
catch (Exception ex)
{
- _logger.ErrorException("Error killing transcoding job for {0}", ex, _targetPath);
+ _logger.ErrorException("Error stopping recording transcoding job for {0}", ex, _targetPath);
+ }
+
+ if (_hasExited)
+ {
+ return;
+ }
+
+ try
+ {
+ _logger.Info("Calling recording process.WaitForExit for {0}", _targetPath);
+
+ if (_process.WaitForExit(5000))
+ {
+ return;
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error waiting for recording process to exit for {0}", ex, _targetPath);
+ }
+
+ if (_hasExited)
+ {
+ return;
+ }
+
+ try
+ {
+ _logger.Info("Killing ffmpeg recording process for {0}", _targetPath);
+
+ _process.Kill();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error killing recording transcoding job for {0}", ex, _targetPath);
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
index e2446b16f..46b914232 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
@@ -182,7 +182,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
programsInfo.Add(GetProgram(channelNumber, schedule, programDict[schedule.programID]));
}
- _logger.Info("Finished with EPGData");
}
}
@@ -322,8 +321,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
using (var response = await Get(httpOptions, true, info).ConfigureAwait(false))
{
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response);
- _logger.Info("Found " + root.map.Count + " channels on the lineup on ScheduleDirect");
- _logger.Info("Mapping Stations to Channel");
+
foreach (ScheduleDirect.Map map in root.map)
{
var channelNumber = map.logicalChannelNumber;
@@ -353,7 +351,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
});
}
}
- _logger.Info("Added " + GetChannelPairCacheCount(listingsId) + " channels to the dictionary");
foreach (ChannelInfo channel in channels)
{
diff --git a/Emby.Server.Implementations/LiveTv/LiveStreamHelper.cs b/Emby.Server.Implementations/LiveTv/LiveStreamHelper.cs
index a338ae23a..0313e6fde 100644
--- a/Emby.Server.Implementations/LiveTv/LiveStreamHelper.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveStreamHelper.cs
@@ -96,15 +96,7 @@ namespace Emby.Server.Implementations.LiveTv
}
// Try to estimate this
- if (!mediaSource.Bitrate.HasValue)
- {
- var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
-
- if (total > 0)
- {
- mediaSource.Bitrate = total;
- }
- }
+ mediaSource.InferTotalBitrate(true);
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index 62a0738c7..ff76f6bef 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -459,15 +459,7 @@ namespace Emby.Server.Implementations.LiveTv
}
// Set the total bitrate if not already supplied
- if (!mediaSource.Bitrate.HasValue)
- {
- var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
-
- if (total > 0)
- {
- mediaSource.Bitrate = total;
- }
- }
+ mediaSource.InferTotalBitrate();
if (!(service is EmbyTV.EmbyTV))
{
@@ -1602,7 +1594,7 @@ namespace Emby.Server.Implementations.LiveTv
Recursive = true,
AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(),
IsFolder = false,
- ExcludeLocationTypes = new[] { LocationType.Virtual },
+ IsVirtualItem = false,
Limit = query.Limit,
SortBy = new[] { ItemSortBy.DateCreated },
SortOrder = SortOrder.Descending,
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
index e0a35686e..dd95660c7 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
@@ -200,15 +200,7 @@ namespace Emby.Server.Implementations.LiveTv
}
// Try to estimate this
- if (!mediaSource.Bitrate.HasValue)
- {
- var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
-
- if (total > 0)
- {
- mediaSource.Bitrate = total;
- }
- }
+ mediaSource.InferTotalBitrate();
}
public Task CloseMediaSource(string liveStreamId)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs
index f2e48fbc0..336469c50 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs
@@ -104,7 +104,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
Type = HdHomerunHost.DeviceType,
Url = url,
- DataVersion = 1,
DeviceId = response.DeviceID
}).ConfigureAwait(false);
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
index 77efe8585..1c7c0828c 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
@@ -61,10 +61,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
var id = ChannelIdPrefix + i.GuideNumber;
- if (info.DataVersion >= 1)
- {
- id += '_' + (i.GuideName ?? string.Empty).GetMD5().ToString("N");
- }
+ id += '_' + (i.GuideName ?? string.Empty).GetMD5().ToString("N");
return id;
}
@@ -103,7 +100,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
TunerHostId = info.Id,
IsHD = i.HD == 1,
AudioCodec = i.AudioCodec,
- VideoCodec = i.VideoCodec
+ VideoCodec = i.VideoCodec,
+ ChannelType = ChannelType.TV
});
}
@@ -430,6 +428,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
IsInfiniteStream = true
};
+ mediaSource.InferTotalBitrate();
+
return mediaSource;
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs
index 4852270d5..625e4457d 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs
@@ -25,7 +25,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private readonly TaskCompletionSource<bool> _liveStreamTaskCompletionSource = new TaskCompletionSource<bool>();
private readonly MulticastStream _multicastStream;
-
public HdHomerunLiveStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost)
: base(mediaSource)
{
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
index 8027ce2dd..601cb2666 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
@@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
protected override async Task<IEnumerable<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken)
{
- return await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).Parse(info.Url, ChannelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false);
+ return await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).Parse(info.Url, ChannelIdPrefix, info.Id, !info.EnableTvgId, cancellationToken).ConfigureAwait(false);
}
public Task<List<LiveTvTunerInfo>> GetTunerInfos(CancellationToken cancellationToken)
@@ -127,6 +127,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
{
protocol = MediaProtocol.Udp;
}
+ else if (path.StartsWith("rtp", StringComparison.OrdinalIgnoreCase))
+ {
+ protocol = MediaProtocol.Rtmp;
+ }
var mediaSource = new MediaSourceInfo
{
@@ -155,9 +159,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
ReadAtNativeFramerate = false,
Id = channel.Path.GetMD5().ToString("N"),
- IsInfiniteStream = true
+ IsInfiniteStream = true,
+ SupportsDirectStream = false,
+ IsRemote = true
};
+ mediaSource.InferTotalBitrate();
+
return new List<MediaSourceInfo> { mediaSource };
}
return new List<MediaSourceInfo>();
@@ -168,4 +176,4 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return Task.FromResult(true);
}
}
-}
+} \ No newline at end of file
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
index e0f040281..5e191ada9 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
@@ -14,6 +14,7 @@ using MediaBrowser.Controller;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Extensions;
namespace Emby.Server.Implementations.LiveTv.TunerHosts
{
@@ -32,14 +33,25 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
_appHost = appHost;
}
- public async Task<List<M3UChannel>> Parse(string url, string channelIdPrefix, string tunerHostId, CancellationToken cancellationToken)
+ public async Task<List<M3UChannel>> Parse(string url, string channelIdPrefix, string tunerHostId, bool enableStreamUrlAsIdentifier, CancellationToken cancellationToken)
{
var urlHash = url.GetMD5().ToString("N");
// Read the file and display it line by line.
using (var reader = new StreamReader(await GetListingsStream(url, cancellationToken).ConfigureAwait(false)))
{
- return GetChannels(reader, urlHash, channelIdPrefix, tunerHostId);
+ return GetChannels(reader, urlHash, channelIdPrefix, tunerHostId, enableStreamUrlAsIdentifier);
+ }
+ }
+
+ public List<M3UChannel> ParseString(string text, string channelIdPrefix, string tunerHostId)
+ {
+ var urlHash = "text".GetMD5().ToString("N");
+
+ // Read the file and display it line by line.
+ using (var reader = new StringReader(text))
+ {
+ return GetChannels(reader, urlHash, channelIdPrefix, tunerHostId, false);
}
}
@@ -59,7 +71,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
}
const string ExtInfPrefix = "#EXTINF:";
- private List<M3UChannel> GetChannels(StreamReader reader, string urlHash, string channelIdPrefix, string tunerHostId)
+ private List<M3UChannel> GetChannels(TextReader reader, string urlHash, string channelIdPrefix, string tunerHostId, bool enableStreamUrlAsIdentifier)
{
var channels = new List<M3UChannel>();
string line;
@@ -85,7 +97,15 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
else if (!string.IsNullOrWhiteSpace(extInf) && !line.StartsWith("#", StringComparison.OrdinalIgnoreCase))
{
var channel = GetChannelnfo(extInf, tunerHostId, line);
- channel.Id = channelIdPrefix + urlHash + line.GetMD5().ToString("N");
+ if (string.IsNullOrWhiteSpace(channel.Id) || enableStreamUrlAsIdentifier)
+ {
+ channel.Id = channelIdPrefix + urlHash + line.GetMD5().ToString("N");
+ }
+ else
+ {
+ channel.Id = channelIdPrefix + urlHash + channel.Id.GetMD5().ToString("N");
+ }
+
channel.Path = line;
channels.Add(channel);
extInf = "";
@@ -114,6 +134,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
channel.Name = GetChannelName(extInf, attributes);
channel.Number = GetChannelNumber(extInf, attributes, mediaUrl);
+ if (attributes.TryGetValue("tvg-id", out value))
+ {
+ channel.Id = value;
+ }
+
return channel;
}
@@ -122,18 +147,22 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null;
- var numberString = nameParts[0];
+ string numberString = null;
- //Check for channel number with the format from SatIp
- int number;
+ // Check for channel number with the format from SatIp
+ // #EXTINF:0,84. VOX Schweiz
+ // #EXTINF:0,84.0 - VOX Schweiz
if (!string.IsNullOrWhiteSpace(nameInExtInf))
{
- var numberIndex = nameInExtInf.IndexOf('.');
+ var numberIndex = nameInExtInf.IndexOf(' ');
if (numberIndex > 0)
{
- if (int.TryParse(nameInExtInf.Substring(0, numberIndex), out number))
+ var numberPart = nameInExtInf.Substring(0, numberIndex).Trim(new[] { ' ', '.' });
+
+ double number;
+ if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out number))
{
- numberString = number.ToString();
+ numberString = numberPart;
}
}
}
@@ -150,7 +179,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
string value;
if (attributes.TryGetValue("tvg-id", out value))
{
- numberString = value;
+ double doubleValue;
+ if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue))
+ {
+ numberString = value;
+ }
}
}
@@ -208,17 +241,21 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null;
- //Check for channel number with the format from SatIp
- int number;
+ // Check for channel number with the format from SatIp
+ // #EXTINF:0,84. VOX Schweiz
+ // #EXTINF:0,84.0 - VOX Schweiz
if (!string.IsNullOrWhiteSpace(nameInExtInf))
{
- var numberIndex = nameInExtInf.IndexOf('.');
+ var numberIndex = nameInExtInf.IndexOf(' ');
if (numberIndex > 0)
{
- if (int.TryParse(nameInExtInf.Substring(0, numberIndex), out number))
+ var numberPart = nameInExtInf.Substring(0, numberIndex).Trim(new[] { ' ', '.' });
+
+ double number;
+ if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out number))
{
//channel.Number = number.ToString();
- nameInExtInf = nameInExtInf.Substring(numberIndex + 1);
+ nameInExtInf = nameInExtInf.Substring(numberIndex + 1).Trim(new[] { ' ', '-' });
}
}
}
@@ -250,20 +287,18 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
var reg = new Regex(@"([a-z0-9\-_]+)=\""([^""]+)\""", RegexOptions.IgnoreCase);
var matches = reg.Matches(line);
- var minIndex = int.MaxValue;
+
+ remaining = line;
+
foreach (Match match in matches)
{
- dict[match.Groups[1].Value] = match.Groups[2].Value;
- minIndex = Math.Min(minIndex, match.Index);
- }
+ var key = match.Groups[1].Value;
+ var value = match.Groups[2].Value;
- if (minIndex > 0 && minIndex < line.Length)
- {
- line = line.Substring(0, minIndex);
+ dict[match.Groups[1].Value] = match.Groups[2].Value;
+ remaining = remaining.Replace(key + "=\"" + value + "\"", string.Empty, StringComparison.OrdinalIgnoreCase);
}
- remaining = line;
-
return dict;
}
}
diff --git a/Emby.Server.Implementations/Localization/iso6392.txt b/Emby.Server.Implementations/Localization/iso6392.txt
index 665a5375e..5616d41bc 100644
--- a/Emby.Server.Implementations/Localization/iso6392.txt
+++ b/Emby.Server.Implementations/Localization/iso6392.txt
@@ -137,6 +137,7 @@ fon|||Fon|fon
fre|fra|fr|French|français
frm|||French, Middle (ca.1400-1600)|français moyen (1400-1600)
fro|||French, Old (842-ca.1400)|français ancien (842-ca.1400)
+frc||fr-ca|French (Canada)|french
frr|||Northern Frisian|frison septentrional
frs|||Eastern Frisian|frison oriental
fry||fy|Western Frisian|frison occidental
diff --git a/Emby.Server.Implementations/Migrations/GuideMigration.cs b/Emby.Server.Implementations/Migrations/GuideMigration.cs
new file mode 100644
index 000000000..71286b282
--- /dev/null
+++ b/Emby.Server.Implementations/Migrations/GuideMigration.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Updates;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.Tasks;
+using MediaBrowser.Model.Updates;
+using System.Linq;
+
+namespace Emby.Server.Implementations.Migrations
+{
+ public class GuideMigration : IVersionMigration
+ {
+ private readonly IServerConfigurationManager _config;
+ private readonly ITaskManager _taskManager;
+
+ public GuideMigration(IServerConfigurationManager config, ITaskManager taskManager)
+ {
+ _config = config;
+ _taskManager = taskManager;
+ }
+
+ public async Task Run()
+ {
+ var name = "GuideRefresh2";
+
+ if (!_config.Configuration.Migrations.Contains(name, StringComparer.OrdinalIgnoreCase))
+ {
+ Task.Run(() =>
+ {
+ _taskManager.QueueScheduledTask(_taskManager.ScheduledTasks.Select(i => i.ScheduledTask)
+ .First(i => string.Equals(i.Key, "RefreshGuide", StringComparison.OrdinalIgnoreCase)));
+ });
+
+ var list = _config.Configuration.Migrations.ToList();
+ list.Add(name);
+ _config.Configuration.Migrations = list.ToArray();
+ _config.SaveConfiguration();
+ }
+ }
+ }
+}
diff --git a/Emby.Server.Implementations/Migrations/LibraryScanMigration.cs b/Emby.Server.Implementations/Migrations/LibraryScanMigration.cs
index 600dd8033..bd185bc9c 100644
--- a/Emby.Server.Implementations/Migrations/LibraryScanMigration.cs
+++ b/Emby.Server.Implementations/Migrations/LibraryScanMigration.cs
@@ -35,8 +35,6 @@ namespace Emby.Server.Implementations.Migrations
{
_taskManager.QueueScheduledTask(_taskManager.ScheduledTasks.Select(i => i.ScheduledTask)
.First(i => string.Equals(i.Key, "RefreshLibrary", StringComparison.OrdinalIgnoreCase)));
- _taskManager.QueueScheduledTask(_taskManager.ScheduledTasks.Select(i => i.ScheduledTask)
- .First(i => string.Equals(i.Key, "RefreshGuide", StringComparison.OrdinalIgnoreCase)));
});
var list = _config.Configuration.Migrations.ToList();
diff --git a/Emby.Server.Implementations/Notifications/Notifications.cs b/Emby.Server.Implementations/Notifications/Notifications.cs
index 2d441c18c..8f24dfe1a 100644
--- a/Emby.Server.Implementations/Notifications/Notifications.cs
+++ b/Emby.Server.Implementations/Notifications/Notifications.cs
@@ -430,6 +430,23 @@ namespace Emby.Server.Implementations.Notifications
return name;
}
+ public static string GetItemName(BaseItemInfo item)
+ {
+ var name = item.Name;
+
+ if (!string.IsNullOrWhiteSpace(item.SeriesName))
+ {
+ name = item.SeriesName + " - " + name;
+ }
+
+ if (item.Artists != null && item.Artists.Count > 0)
+ {
+ name = item.Artists[0] + " - " + name;
+ }
+
+ return name;
+ }
+
async void _userManager_UserCreated(object sender, GenericEventArgs<User> e)
{
var notification = new NotificationRequest
diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
index 9583141e0..386da73c6 100644
--- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs
+++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
@@ -100,7 +100,7 @@ namespace Emby.Server.Implementations.Playlists
if (string.IsNullOrWhiteSpace(options.MediaType))
{
- throw new ArgumentException("A playlist media type is required.");
+ options.MediaType = "Audio";
}
var user = _userManager.GetUserById(options.UserId);
diff --git a/Emby.Server.Implementations/Sync/SyncHelper.cs b/Emby.Server.Implementations/Sync/SyncHelper.cs
index da475f003..7fe703796 100644
--- a/Emby.Server.Implementations/Sync/SyncHelper.cs
+++ b/Emby.Server.Implementations/Sync/SyncHelper.cs
@@ -4,7 +4,7 @@ namespace Emby.Server.Implementations.Sync
{
public class SyncHelper
{
- public static int? AdjustBitrate(int? profileBitrate, string quality)
+ public static long? AdjustBitrate(long? profileBitrate, string quality)
{
if (profileBitrate.HasValue)
{
diff --git a/Emby.Server.Implementations/Sync/SyncJobProcessor.cs b/Emby.Server.Implementations/Sync/SyncJobProcessor.cs
index b1adc64df..17cdef5fc 100644
--- a/Emby.Server.Implementations/Sync/SyncJobProcessor.cs
+++ b/Emby.Server.Implementations/Sync/SyncJobProcessor.cs
@@ -59,15 +59,8 @@ namespace Emby.Server.Implementations.Sync
_mediaSourceManager = mediaSourceManager;
}
- public async Task EnsureJobItems(SyncJob job)
+ public async Task EnsureJobItems(SyncJob job, User user)
{
- var user = _userManager.GetUserById(job.UserId);
-
- if (user == null)
- {
- throw new InvalidOperationException("Cannot proceed with sync because user no longer exists.");
- }
-
var items = (await GetItemsForSync(job.Category, job.ParentId, job.RequestedItemIds, user, job.UnwatchedOnly).ConfigureAwait(false))
.ToList();
@@ -385,7 +378,16 @@ namespace Emby.Server.Implementations.Sync
if (job.SyncNewContent)
{
- await EnsureJobItems(job).ConfigureAwait(false);
+ var user = _userManager.GetUserById(job.UserId);
+
+ if (user == null)
+ {
+ await _syncManager.CancelJob(job.Id).ConfigureAwait(false);
+ }
+ else
+ {
+ await EnsureJobItems(job, user).ConfigureAwait(false);
+ }
}
}
}
diff --git a/Emby.Server.Implementations/Sync/SyncManager.cs b/Emby.Server.Implementations/Sync/SyncManager.cs
index 310b35afe..418d42c9a 100644
--- a/Emby.Server.Implementations/Sync/SyncManager.cs
+++ b/Emby.Server.Implementations/Sync/SyncManager.cs
@@ -181,7 +181,7 @@ namespace Emby.Server.Implementations.Sync
await _repo.Create(job).ConfigureAwait(false);
- await processor.EnsureJobItems(job).ConfigureAwait(false);
+ await processor.EnsureJobItems(job, user).ConfigureAwait(false);
// If it already has a converting status then is must have been aborted during conversion
var jobItemsResult = GetJobItems(new SyncJobItemQuery
@@ -560,6 +560,12 @@ namespace Emby.Server.Implementations.Sync
{
var jobItem = _repo.GetJobItem(id);
+ if (jobItem == null)
+ {
+ _logger.Debug("ReportSyncJobItemTransferred: SyncJobItem {0} doesn't exist anymore", id);
+ return;
+ }
+
jobItem.Status = SyncJobItemStatus.Synced;
jobItem.Progress = 100;
diff --git a/Emby.Server.Implementations/Sync/TargetDataProvider.cs b/Emby.Server.Implementations/Sync/TargetDataProvider.cs
index fbd82aa7a..cac8f0cd8 100644
--- a/Emby.Server.Implementations/Sync/TargetDataProvider.cs
+++ b/Emby.Server.Implementations/Sync/TargetDataProvider.cs
@@ -19,6 +19,7 @@ namespace Emby.Server.Implementations.Sync
private readonly IServerSyncProvider _provider;
private readonly SemaphoreSlim _dataLock = new SemaphoreSlim(1, 1);
+ private readonly SemaphoreSlim _remoteDataLock = new SemaphoreSlim(1, 1);
private List<LocalItem> _items;
private readonly ILogger _logger;
@@ -63,15 +64,24 @@ namespace Emby.Server.Implementations.Sync
{
_logger.Debug("Getting {0} from {1}", string.Join(MediaSync.PathSeparatorString, GetRemotePath().ToArray()), _provider.Name);
- var fileResult = await _provider.GetFiles(GetRemotePath().ToArray(), _target, cancellationToken).ConfigureAwait(false);
+ await _remoteDataLock.WaitAsync(cancellationToken).ConfigureAwait(false);
- if (fileResult.Items.Length > 0)
+ try
{
- using (var stream = await _provider.GetFile(fileResult.Items[0].FullName, _target, new Progress<double>(), cancellationToken))
+ var fileResult = await _provider.GetFiles(GetRemotePath().ToArray(), _target, cancellationToken).ConfigureAwait(false);
+
+ if (fileResult.Items.Length > 0)
{
- return _json.DeserializeFromStream<List<LocalItem>>(stream);
+ using (var stream = await _provider.GetFile(fileResult.Items[0].FullName, _target, new Progress<double>(), cancellationToken))
+ {
+ return _json.DeserializeFromStream<List<LocalItem>>(stream);
+ }
}
}
+ finally
+ {
+ _remoteDataLock.Release();
+ }
return new List<LocalItem>();
}
@@ -93,9 +103,19 @@ namespace Emby.Server.Implementations.Sync
// Save to sync provider
stream.Position = 0;
var remotePath = GetRemotePath();
- _logger.Debug("Saving data.json to {0}. Remote path: {1}", _provider.Name, string.Join("/", remotePath));
- await _provider.SendFile(stream, remotePath, _target, new Progress<double>(), cancellationToken).ConfigureAwait(false);
+ await _remoteDataLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ try
+ {
+ _logger.Debug("Saving data.json to {0}. Remote path: {1}", _provider.Name, string.Join("/", remotePath));
+
+ await _provider.SendFile(stream, remotePath, _target, new Progress<double>(), cancellationToken).ConfigureAwait(false);
+ }
+ finally
+ {
+ _remoteDataLock.Release();
+ }
}
}
diff --git a/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs b/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs
index bef964c6f..b8d03db3d 100644
--- a/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs
+++ b/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs
@@ -151,7 +151,9 @@ namespace Emby.Server.Implementations.UserViews
string[] collectionStripViewTypes =
{
CollectionType.Movies,
- CollectionType.TvShows
+ CollectionType.TvShows,
+ CollectionType.Playlists,
+ CollectionType.Photos
};
return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty);