diff options
| author | Luke <luke.pulverenti@gmail.com> | 2016-12-18 00:44:33 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-12-18 00:44:33 -0500 |
| commit | e7cebb91a73354dc3e0d0b6340c9fbd6511f4406 (patch) | |
| tree | 6f1c368c766c17b7514fe749c0e92e69cd89194a /MediaBrowser.Server.Implementations | |
| parent | 025905a3e4d50b9a2e07fbf4ff0a203af6604ced (diff) | |
| parent | aaa027f3229073e9a40756c3157d41af2a442922 (diff) | |
Merge pull request #2350 from MediaBrowser/beta
Beta
Diffstat (limited to 'MediaBrowser.Server.Implementations')
488 files changed, 36 insertions, 79215 deletions
diff --git a/MediaBrowser.Server.Implementations/Activity/ActivityManager.cs b/MediaBrowser.Server.Implementations/Activity/ActivityManager.cs deleted file mode 100644 index 0904c92f1c..0000000000 --- a/MediaBrowser.Server.Implementations/Activity/ActivityManager.cs +++ /dev/null @@ -1,57 +0,0 @@ -using MediaBrowser.Common.Events; -using MediaBrowser.Controller.Activity; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using System; -using System.Linq; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Activity -{ - public class ActivityManager : IActivityManager - { - public event EventHandler<GenericEventArgs<ActivityLogEntry>> EntryCreated; - - private readonly IActivityRepository _repo; - private readonly ILogger _logger; - private readonly IUserManager _userManager; - - public ActivityManager(ILogger logger, IActivityRepository repo, IUserManager userManager) - { - _logger = logger; - _repo = repo; - _userManager = userManager; - } - - public async Task Create(ActivityLogEntry entry) - { - entry.Id = Guid.NewGuid().ToString("N"); - entry.Date = DateTime.UtcNow; - - await _repo.Create(entry).ConfigureAwait(false); - - EventHelper.FireEventIfNotNull(EntryCreated, this, new GenericEventArgs<ActivityLogEntry>(entry), _logger); - } - - public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit) - { - var result = _repo.GetActivityLogEntries(minDate, startIndex, limit); - - foreach (var item in result.Items.Where(i => !string.IsNullOrWhiteSpace(i.UserId))) - { - var user = _userManager.GetUserById(item.UserId); - - if (user != null) - { - var dto = _userManager.GetUserDto(user); - item.UserPrimaryImageTag = dto.PrimaryImageTag; - } - } - - return result; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs deleted file mode 100644 index c992def39d..0000000000 --- a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs +++ /dev/null @@ -1,253 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Activity; -using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using MediaBrowser.Server.Implementations.Persistence; -using System; -using System.Collections.Generic; -using System.Data; -using System.Globalization; -using System.IO; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Activity -{ - public class ActivityRepository : BaseSqliteRepository, IActivityRepository - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - public ActivityRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector connector) - : base(logManager, connector) - { - DbFilePath = Path.Combine(appPaths.DataPath, "activitylog.db"); - } - - public async Task Initialize() - { - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - string[] queries = { - - "create table if not exists ActivityLogEntries (Id GUID PRIMARY KEY, Name TEXT, Overview TEXT, ShortOverview TEXT, Type TEXT, ItemId TEXT, UserId TEXT, DateCreated DATETIME, LogSeverity TEXT)", - "create index if not exists idx_ActivityLogEntries on ActivityLogEntries(Id)" - }; - - connection.RunQueries(queries, Logger); - } - } - - private const string BaseActivitySelectText = "select Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity from ActivityLogEntries"; - - public Task Create(ActivityLogEntry entry) - { - return Update(entry); - } - - public async Task Update(ActivityLogEntry entry) - { - if (entry == null) - { - throw new ArgumentNullException("entry"); - } - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var saveActivityCommand = connection.CreateCommand()) - { - saveActivityCommand.CommandText = "replace into ActivityLogEntries (Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) values (@Id, @Name, @Overview, @ShortOverview, @Type, @ItemId, @UserId, @DateCreated, @LogSeverity)"; - - saveActivityCommand.Parameters.Add(saveActivityCommand, "@Id"); - saveActivityCommand.Parameters.Add(saveActivityCommand, "@Name"); - saveActivityCommand.Parameters.Add(saveActivityCommand, "@Overview"); - saveActivityCommand.Parameters.Add(saveActivityCommand, "@ShortOverview"); - saveActivityCommand.Parameters.Add(saveActivityCommand, "@Type"); - saveActivityCommand.Parameters.Add(saveActivityCommand, "@ItemId"); - saveActivityCommand.Parameters.Add(saveActivityCommand, "@UserId"); - saveActivityCommand.Parameters.Add(saveActivityCommand, "@DateCreated"); - saveActivityCommand.Parameters.Add(saveActivityCommand, "@LogSeverity"); - - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - var index = 0; - - saveActivityCommand.GetParameter(index++).Value = new Guid(entry.Id); - saveActivityCommand.GetParameter(index++).Value = entry.Name; - saveActivityCommand.GetParameter(index++).Value = entry.Overview; - saveActivityCommand.GetParameter(index++).Value = entry.ShortOverview; - saveActivityCommand.GetParameter(index++).Value = entry.Type; - saveActivityCommand.GetParameter(index++).Value = entry.ItemId; - saveActivityCommand.GetParameter(index++).Value = entry.UserId; - saveActivityCommand.GetParameter(index++).Value = entry.Date; - saveActivityCommand.GetParameter(index++).Value = entry.Severity.ToString(); - - saveActivityCommand.Transaction = transaction; - - saveActivityCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save record:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - - public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit) - { - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = BaseActivitySelectText; - - var whereClauses = new List<string>(); - - if (minDate.HasValue) - { - whereClauses.Add("DateCreated>=@DateCreated"); - cmd.Parameters.Add(cmd, "@DateCreated", DbType.Date).Value = minDate.Value; - } - - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - if (startIndex.HasValue && startIndex.Value > 0) - { - var pagingWhereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLogEntries {0} ORDER BY DateCreated DESC LIMIT {1})", - pagingWhereText, - startIndex.Value.ToString(_usCulture))); - } - - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - cmd.CommandText += whereText; - - cmd.CommandText += " ORDER BY DateCreated DESC"; - - if (limit.HasValue) - { - cmd.CommandText += " LIMIT " + limit.Value.ToString(_usCulture); - } - - cmd.CommandText += "; select count (Id) from ActivityLogEntries" + whereTextWithoutPaging; - - var list = new List<ActivityLogEntry>(); - var count = 0; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (reader.Read()) - { - list.Add(GetEntry(reader)); - } - - if (reader.NextResult() && reader.Read()) - { - count = reader.GetInt32(0); - } - } - - return new QueryResult<ActivityLogEntry>() - { - Items = list.ToArray(), - TotalRecordCount = count - }; - } - } - } - - private ActivityLogEntry GetEntry(IDataReader reader) - { - var index = 0; - - var info = new ActivityLogEntry - { - Id = reader.GetGuid(index).ToString("N") - }; - - index++; - if (!reader.IsDBNull(index)) - { - info.Name = reader.GetString(index); - } - - index++; - if (!reader.IsDBNull(index)) - { - info.Overview = reader.GetString(index); - } - - index++; - if (!reader.IsDBNull(index)) - { - info.ShortOverview = reader.GetString(index); - } - - index++; - if (!reader.IsDBNull(index)) - { - info.Type = reader.GetString(index); - } - - index++; - if (!reader.IsDBNull(index)) - { - info.ItemId = reader.GetString(index); - } - - index++; - if (!reader.IsDBNull(index)) - { - info.UserId = reader.GetString(index); - } - - index++; - info.Date = reader.GetDateTime(index).ToUniversalTime(); - - index++; - if (!reader.IsDBNull(index)) - { - info.Severity = (LogSeverity)Enum.Parse(typeof(LogSeverity), reader.GetString(index), true); - } - - return info; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Branding/BrandingConfigurationFactory.cs b/MediaBrowser.Server.Implementations/Branding/BrandingConfigurationFactory.cs deleted file mode 100644 index d6cd3424b1..0000000000 --- a/MediaBrowser.Server.Implementations/Branding/BrandingConfigurationFactory.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Branding; -using System.Collections.Generic; - -namespace MediaBrowser.Server.Implementations.Branding -{ - public class BrandingConfigurationFactory : IConfigurationFactory - { - public IEnumerable<ConfigurationStore> GetConfigurations() - { - return new[] - { - new ConfigurationStore - { - ConfigurationType = typeof(BrandingOptions), - Key = "branding" - } - }; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs b/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs deleted file mode 100644 index 9dfb0404e0..0000000000 --- a/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs +++ /dev/null @@ -1,29 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Configuration; -using System.Collections.Generic; - -namespace MediaBrowser.Server.Implementations.Channels -{ - public static class ChannelConfigurationExtension - { - public static ChannelOptions GetChannelsConfiguration(this IConfigurationManager manager) - { - return manager.GetConfiguration<ChannelOptions>("channels"); - } - } - - public class ChannelConfigurationFactory : IConfigurationFactory - { - public IEnumerable<ConfigurationStore> GetConfigurations() - { - return new List<ConfigurationStore> - { - new ConfigurationStore - { - Key = "channels", - ConfigurationType = typeof (ChannelOptions) - } - }; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelDynamicMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/Channels/ChannelDynamicMediaSourceProvider.cs deleted file mode 100644 index fae78b9bc0..0000000000 --- a/MediaBrowser.Server.Implementations/Channels/ChannelDynamicMediaSourceProvider.cs +++ /dev/null @@ -1,43 +0,0 @@ -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Dto; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Channels -{ - public class ChannelDynamicMediaSourceProvider : IMediaSourceProvider - { - private readonly ChannelManager _channelManager; - - public ChannelDynamicMediaSourceProvider(IChannelManager channelManager) - { - _channelManager = (ChannelManager)channelManager; - } - - public Task<IEnumerable<MediaSourceInfo>> GetMediaSources(IHasMediaSources item, CancellationToken cancellationToken) - { - var baseItem = (BaseItem) item; - - if (baseItem.SourceType == SourceType.Channel) - { - return _channelManager.GetDynamicMediaSources(baseItem, cancellationToken); - } - - return Task.FromResult<IEnumerable<MediaSourceInfo>>(new List<MediaSourceInfo>()); - } - - public Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> OpenMediaSource(string openToken, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public Task CloseMediaSource(string liveStreamId) - { - throw new NotImplementedException(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs deleted file mode 100644 index c98f71ce2a..0000000000 --- a/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs +++ /dev/null @@ -1,55 +0,0 @@ -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Channels -{ - public class ChannelImageProvider : IDynamicImageProvider, IHasItemChangeMonitor - { - private readonly IChannelManager _channelManager; - - public ChannelImageProvider(IChannelManager channelManager) - { - _channelManager = channelManager; - } - - public IEnumerable<ImageType> GetSupportedImages(IHasImages item) - { - return GetChannel(item).GetSupportedChannelImages(); - } - - public Task<DynamicImageResponse> GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken) - { - var channel = GetChannel(item); - - return channel.GetChannelImage(type, cancellationToken); - } - - public string Name - { - get { return "Channel Image Provider"; } - } - - public bool Supports(IHasImages item) - { - return item is Channel; - } - - private IChannel GetChannel(IHasImages item) - { - var channel = (Channel)item; - - return ((ChannelManager)_channelManager).GetChannelProvider(channel); - } - - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) - { - return GetSupportedImages(item).Any(i => !item.HasImage(i)); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs deleted file mode 100644 index 1369efae1b..0000000000 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ /dev/null @@ -1,1581 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Localization; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; - -namespace MediaBrowser.Server.Implementations.Channels -{ - public class ChannelManager : IChannelManager - { - private IChannel[] _channels; - - private readonly IUserManager _userManager; - private readonly IUserDataManager _userDataManager; - private readonly IDtoService _dtoService; - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IServerConfigurationManager _config; - private readonly IFileSystem _fileSystem; - private readonly IJsonSerializer _jsonSerializer; - private readonly IHttpClient _httpClient; - private readonly IProviderManager _providerManager; - - private readonly ILocalizationManager _localization; - private readonly ConcurrentDictionary<Guid, bool> _refreshedItems = new ConcurrentDictionary<Guid, bool>(); - - public ChannelManager(IUserManager userManager, IDtoService dtoService, ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IUserDataManager userDataManager, IJsonSerializer jsonSerializer, ILocalizationManager localization, IHttpClient httpClient, IProviderManager providerManager) - { - _userManager = userManager; - _dtoService = dtoService; - _libraryManager = libraryManager; - _logger = logger; - _config = config; - _fileSystem = fileSystem; - _userDataManager = userDataManager; - _jsonSerializer = jsonSerializer; - _localization = localization; - _httpClient = httpClient; - _providerManager = providerManager; - } - - private TimeSpan CacheLength - { - get - { - return TimeSpan.FromHours(6); - } - } - - public void AddParts(IEnumerable<IChannel> channels) - { - _channels = channels.ToArray(); - } - - public string ChannelDownloadPath - { - get - { - var options = _config.GetChannelsConfiguration(); - - if (!string.IsNullOrWhiteSpace(options.DownloadPath)) - { - return options.DownloadPath; - } - - return Path.Combine(_config.ApplicationPaths.ProgramDataPath, "channels"); - } - } - - private IEnumerable<IChannel> GetAllChannels() - { - return _channels - .OrderBy(i => i.Name); - } - - public IEnumerable<Guid> GetInstalledChannelIds() - { - return GetAllChannels().Select(i => GetInternalChannelId(i.Name)); - } - - public Task<QueryResult<Channel>> GetChannelsInternal(ChannelQuery query, CancellationToken cancellationToken) - { - var user = string.IsNullOrWhiteSpace(query.UserId) - ? null - : _userManager.GetUserById(query.UserId); - - var channels = GetAllChannels() - .Select(GetChannelEntity) - .OrderBy(i => i.SortName) - .ToList(); - - if (query.SupportsLatestItems.HasValue) - { - var val = query.SupportsLatestItems.Value; - channels = channels.Where(i => - { - try - { - return GetChannelProvider(i) is ISupportsLatestMedia == val; - } - catch - { - return false; - } - - }).ToList(); - } - if (query.IsFavorite.HasValue) - { - var val = query.IsFavorite.Value; - channels = channels.Where(i => _userDataManager.GetUserData(user, i).IsFavorite == val) - .ToList(); - } - - if (user != null) - { - channels = channels.Where(i => - { - if (!i.IsVisible(user)) - { - return false; - } - - try - { - return GetChannelProvider(i).IsEnabledFor(user.Id.ToString("N")); - } - catch - { - return false; - } - - }).ToList(); - } - - var all = channels; - var totalCount = all.Count; - - if (query.StartIndex.HasValue) - { - all = all.Skip(query.StartIndex.Value).ToList(); - } - if (query.Limit.HasValue) - { - all = all.Take(query.Limit.Value).ToList(); - } - - var returnItems = all.ToArray(); - - var result = new QueryResult<Channel> - { - Items = returnItems, - TotalRecordCount = totalCount - }; - - return Task.FromResult(result); - } - - public async Task<QueryResult<BaseItemDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken) - { - var user = string.IsNullOrWhiteSpace(query.UserId) - ? null - : _userManager.GetUserById(query.UserId); - - var internalResult = await GetChannelsInternal(query, cancellationToken).ConfigureAwait(false); - - var dtoOptions = new DtoOptions(); - - var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user).ConfigureAwait(false)) - .ToArray(); - - var result = new QueryResult<BaseItemDto> - { - Items = returnItems, - TotalRecordCount = internalResult.TotalRecordCount - }; - - return result; - } - - public async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken) - { - _refreshedItems.Clear(); - - var allChannelsList = GetAllChannels().ToList(); - - var numComplete = 0; - - foreach (var channelInfo in allChannelsList) - { - cancellationToken.ThrowIfCancellationRequested(); - - try - { - await GetChannel(channelInfo, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error getting channel information for {0}", ex, channelInfo.Name); - } - - numComplete++; - double percent = numComplete; - percent /= allChannelsList.Count; - - progress.Report(100 * percent); - } - - progress.Report(100); - } - - private Channel GetChannelEntity(IChannel channel) - { - var item = GetChannel(GetInternalChannelId(channel.Name).ToString("N")); - - if (item == null) - { - item = GetChannel(channel, CancellationToken.None).Result; - } - - return item; - } - - public async Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, bool includeCachedVersions, CancellationToken cancellationToken) - { - IEnumerable<ChannelMediaInfo> results = new List<ChannelMediaInfo>(); - var video = item as Video; - if (video != null) - { - results = video.ChannelMediaSources; - } - var audio = item as Audio; - if (audio != null) - { - results = audio.ChannelMediaSources ?? new List<ChannelMediaInfo>(); - } - - var sources = SortMediaInfoResults(results) - .Select(i => GetMediaSource(item, i)) - .ToList(); - - if (includeCachedVersions) - { - var cachedVersions = GetCachedChannelItemMediaSources(item); - sources.InsertRange(0, cachedVersions); - } - - return sources; - } - - public async Task<IEnumerable<MediaSourceInfo>> GetDynamicMediaSources(BaseItem item, CancellationToken cancellationToken) - { - var channel = GetChannel(item.ChannelId); - var channelPlugin = GetChannelProvider(channel); - - var requiresCallback = channelPlugin as IRequiresMediaInfoCallback; - - IEnumerable<ChannelMediaInfo> results; - - if (requiresCallback != null) - { - results = await GetChannelItemMediaSourcesInternal(requiresCallback, item.ExternalId, cancellationToken) - .ConfigureAwait(false); - } - else - { - results = new List<ChannelMediaInfo>(); - } - - var list = SortMediaInfoResults(results) - .Select(i => GetMediaSource(item, i)) - .ToList(); - - var cachedVersions = GetCachedChannelItemMediaSources(item); - list.InsertRange(0, cachedVersions); - - return list; - } - - private readonly ConcurrentDictionary<string, Tuple<DateTime, List<ChannelMediaInfo>>> _channelItemMediaInfo = - new ConcurrentDictionary<string, Tuple<DateTime, List<ChannelMediaInfo>>>(); - - private async Task<IEnumerable<ChannelMediaInfo>> GetChannelItemMediaSourcesInternal(IRequiresMediaInfoCallback channel, string id, CancellationToken cancellationToken) - { - Tuple<DateTime, List<ChannelMediaInfo>> cachedInfo; - - if (_channelItemMediaInfo.TryGetValue(id, out cachedInfo)) - { - if ((DateTime.UtcNow - cachedInfo.Item1).TotalMinutes < 5) - { - return cachedInfo.Item2; - } - } - - var mediaInfo = await channel.GetChannelItemMediaInfo(id, cancellationToken) - .ConfigureAwait(false); - var list = mediaInfo.ToList(); - - var item2 = new Tuple<DateTime, List<ChannelMediaInfo>>(DateTime.UtcNow, list); - _channelItemMediaInfo.AddOrUpdate(id, item2, (key, oldValue) => item2); - - return list; - } - - private IEnumerable<MediaSourceInfo> GetCachedChannelItemMediaSources(BaseItem item) - { - var filenamePrefix = item.Id.ToString("N"); - var parentPath = Path.Combine(ChannelDownloadPath, item.ChannelId); - - try - { - var files = _fileSystem.GetFiles(parentPath); - - if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) - { - files = files.Where(i => _libraryManager.IsVideoFile(i.FullName)); - } - else - { - files = files.Where(i => _libraryManager.IsAudioFile(i.FullName)); - } - - var file = files - .FirstOrDefault(i => i.Name.StartsWith(filenamePrefix, StringComparison.OrdinalIgnoreCase)); - - if (file != null) - { - var cachedItem = _libraryManager.ResolvePath(file); - - if (cachedItem != null) - { - var hasMediaSources = _libraryManager.GetItemById(cachedItem.Id) as IHasMediaSources; - - if (hasMediaSources != null) - { - var source = hasMediaSources.GetMediaSources(true).FirstOrDefault(); - - if (source != null) - { - return new[] { source }; - } - } - } - } - } - catch (DirectoryNotFoundException) - { - - } - - return new List<MediaSourceInfo>(); - } - - private MediaSourceInfo GetMediaSource(BaseItem item, ChannelMediaInfo info) - { - var source = info.ToMediaSource(); - - source.RunTimeTicks = source.RunTimeTicks ?? item.RunTimeTicks; - - return source; - } - - private IEnumerable<ChannelMediaInfo> SortMediaInfoResults(IEnumerable<ChannelMediaInfo> channelMediaSources) - { - var list = channelMediaSources.ToList(); - - var options = _config.GetChannelsConfiguration(); - - var width = options.PreferredStreamingWidth; - - if (width.HasValue) - { - var val = width.Value; - - var res = list - .OrderBy(i => i.Width.HasValue && i.Width.Value <= val ? 0 : 1) - .ThenBy(i => Math.Abs((i.Width ?? 0) - val)) - .ThenByDescending(i => i.Width ?? 0) - .ThenBy(list.IndexOf) - .ToList(); - - - return res; - } - - return list - .OrderByDescending(i => i.Width ?? 0) - .ThenBy(list.IndexOf); - } - - private async Task<Channel> GetChannel(IChannel channelInfo, CancellationToken cancellationToken) - { - var parentFolder = await GetInternalChannelFolder(cancellationToken).ConfigureAwait(false); - var parentFolderId = parentFolder.Id; - - var id = GetInternalChannelId(channelInfo.Name); - var idString = id.ToString("N"); - - var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id); - - var isNew = false; - var forceUpdate = false; - - var item = _libraryManager.GetItemById(id) as Channel; - - if (item == null) - { - item = new Channel - { - Name = channelInfo.Name, - Id = id, - DateCreated = _fileSystem.GetCreationTimeUtc(path), - DateModified = _fileSystem.GetLastWriteTimeUtc(path) - }; - - isNew = true; - } - - if (!string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase)) - { - isNew = true; - } - item.Path = path; - - if (!string.Equals(item.ChannelId, idString, StringComparison.OrdinalIgnoreCase)) - { - forceUpdate = true; - } - item.ChannelId = idString; - - if (item.ParentId != parentFolderId) - { - forceUpdate = true; - } - item.ParentId = parentFolderId; - - item.OfficialRating = GetOfficialRating(channelInfo.ParentalRating); - item.Overview = channelInfo.Description; - item.HomePageUrl = channelInfo.HomePageUrl; - - if (string.IsNullOrWhiteSpace(item.Name)) - { - item.Name = channelInfo.Name; - } - - if (isNew) - { - await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); - } - else if (forceUpdate) - { - await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false); - } - - await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), cancellationToken); - return item; - } - - private string GetOfficialRating(ChannelParentalRating rating) - { - switch (rating) - { - case ChannelParentalRating.Adult: - return "XXX"; - case ChannelParentalRating.UsR: - return "R"; - case ChannelParentalRating.UsPG13: - return "PG-13"; - case ChannelParentalRating.UsPG: - return "PG"; - default: - return null; - } - } - - public Channel GetChannel(string id) - { - return _libraryManager.GetItemById(id) as Channel; - } - - public IEnumerable<ChannelFeatures> GetAllChannelFeatures() - { - return _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Channel).Name }, - SortBy = new[] { ItemSortBy.SortName } - - }).Select(i => GetChannelFeatures(i.Id.ToString("N"))); - } - - public ChannelFeatures GetChannelFeatures(string id) - { - if (string.IsNullOrWhiteSpace(id)) - { - throw new ArgumentNullException("id"); - } - - var channel = GetChannel(id); - var channelProvider = GetChannelProvider(channel); - - return GetChannelFeaturesDto(channel, channelProvider, channelProvider.GetChannelFeatures()); - } - - public bool SupportsSync(string channelId) - { - if (string.IsNullOrWhiteSpace(channelId)) - { - throw new ArgumentNullException("channelId"); - } - - //var channel = GetChannel(channelId); - var channelProvider = GetChannelProvider(channelId); - - return channelProvider.GetChannelFeatures().SupportsContentDownloading; - } - - public ChannelFeatures GetChannelFeaturesDto(Channel channel, - IChannel provider, - InternalChannelFeatures features) - { - var isIndexable = provider is IIndexableChannel; - var supportsLatest = provider is ISupportsLatestMedia; - - return new ChannelFeatures - { - CanFilter = !features.MaxPageSize.HasValue, - CanSearch = provider is ISearchableChannel, - ContentTypes = features.ContentTypes, - DefaultSortFields = features.DefaultSortFields, - MaxPageSize = features.MaxPageSize, - MediaTypes = features.MediaTypes, - SupportsSortOrderToggle = features.SupportsSortOrderToggle, - SupportsLatestMedia = supportsLatest, - Name = channel.Name, - Id = channel.Id.ToString("N"), - SupportsContentDownloading = features.SupportsContentDownloading && (isIndexable || supportsLatest), - AutoRefreshLevels = features.AutoRefreshLevels - }; - } - - private Guid GetInternalChannelId(string name) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - return _libraryManager.GetNewItemId("Channel " + name, typeof(Channel)); - } - - public async Task<QueryResult<BaseItemDto>> GetLatestChannelItems(AllChannelMediaQuery query, CancellationToken cancellationToken) - { - var user = string.IsNullOrWhiteSpace(query.UserId) - ? null - : _userManager.GetUserById(query.UserId); - - var limit = query.Limit; - - // See below about parental control - if (user != null) - { - query.StartIndex = null; - query.Limit = null; - } - - var internalResult = await GetLatestChannelItemsInternal(query, cancellationToken).ConfigureAwait(false); - - var items = internalResult.Items; - var totalRecordCount = internalResult.TotalRecordCount; - - // Supporting parental control is a hack because it has to be done after querying the remote data source - // This will get screwy if apps try to page, so limit to 10 results in an attempt to always keep them on the first page - if (user != null) - { - items = items.Where(i => i.IsVisible(user)) - .Take(limit ?? 10) - .ToArray(); - - totalRecordCount = items.Length; - } - - var dtoOptions = new DtoOptions(); - - var returnItems = (await _dtoService.GetBaseItemDtos(items, dtoOptions, user).ConfigureAwait(false)) - .ToArray(); - - var result = new QueryResult<BaseItemDto> - { - Items = returnItems, - TotalRecordCount = totalRecordCount - }; - - return result; - } - - public async Task<QueryResult<BaseItem>> GetLatestChannelItemsInternal(AllChannelMediaQuery query, CancellationToken cancellationToken) - { - var user = string.IsNullOrWhiteSpace(query.UserId) - ? null - : _userManager.GetUserById(query.UserId); - - if (!string.IsNullOrWhiteSpace(query.UserId) && user == null) - { - throw new ArgumentException("User not found."); - } - - var channels = GetAllChannels(); - - if (query.ChannelIds.Length > 0) - { - // Avoid implicitly captured closure - var ids = query.ChannelIds; - channels = channels - .Where(i => ids.Contains(GetInternalChannelId(i.Name).ToString("N"))) - .ToArray(); - } - - // Avoid implicitly captured closure - var userId = query.UserId; - - var tasks = channels - .Select(async i => - { - var indexable = i as ISupportsLatestMedia; - - if (indexable != null) - { - try - { - var result = await GetLatestItems(indexable, i, userId, cancellationToken).ConfigureAwait(false); - - var resultItems = result.ToList(); - - return new Tuple<IChannel, ChannelItemResult>(i, new ChannelItemResult - { - Items = resultItems, - TotalRecordCount = resultItems.Count - }); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting all media from {0}", ex, i.Name); - } - } - return new Tuple<IChannel, ChannelItemResult>(i, new ChannelItemResult()); - }); - - var results = await Task.WhenAll(tasks).ConfigureAwait(false); - - var totalCount = results.Length; - - IEnumerable<Tuple<IChannel, ChannelItemInfo>> items = results - .SelectMany(i => i.Item2.Items.Select(m => new Tuple<IChannel, ChannelItemInfo>(i.Item1, m))); - - if (query.ContentTypes.Length > 0) - { - // Avoid implicitly captured closure - var contentTypes = query.ContentTypes; - - items = items.Where(i => contentTypes.Contains(i.Item2.ContentType)); - } - if (query.ExtraTypes.Length > 0) - { - // Avoid implicitly captured closure - var contentTypes = query.ExtraTypes; - - items = items.Where(i => contentTypes.Contains(i.Item2.ExtraType)); - } - - // Avoid implicitly captured closure - var token = cancellationToken; - var itemTasks = items.Select(i => - { - var channelProvider = i.Item1; - var internalChannelId = GetInternalChannelId(channelProvider.Name); - return GetChannelItemEntity(i.Item2, channelProvider, internalChannelId, token); - }); - - var internalItems = await Task.WhenAll(itemTasks).ConfigureAwait(false); - - internalItems = ApplyFilters(internalItems, query.Filters, user).ToArray(); - RefreshIfNeeded(internalItems); - - if (query.StartIndex.HasValue) - { - internalItems = internalItems.Skip(query.StartIndex.Value).ToArray(); - } - if (query.Limit.HasValue) - { - internalItems = internalItems.Take(query.Limit.Value).ToArray(); - } - - var returnItemArray = internalItems.ToArray(); - - return new QueryResult<BaseItem> - { - TotalRecordCount = totalCount, - Items = returnItemArray - }; - } - - private async Task<IEnumerable<ChannelItemInfo>> GetLatestItems(ISupportsLatestMedia indexable, IChannel channel, string userId, CancellationToken cancellationToken) - { - var cacheLength = CacheLength; - var cachePath = GetChannelDataCachePath(channel, userId, "channelmanager-latest", null, false); - - try - { - if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow) - { - return _jsonSerializer.DeserializeFromFile<List<ChannelItemInfo>>(cachePath); - } - } - catch (FileNotFoundException) - { - - } - catch (DirectoryNotFoundException) - { - - } - - await _resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - try - { - if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow) - { - return _jsonSerializer.DeserializeFromFile<List<ChannelItemInfo>>(cachePath); - } - } - catch (FileNotFoundException) - { - - } - catch (DirectoryNotFoundException) - { - - } - - var result = await indexable.GetLatestMedia(new ChannelLatestMediaSearch - { - UserId = userId - - }, cancellationToken).ConfigureAwait(false); - - var resultItems = result.ToList(); - - CacheResponse(resultItems, cachePath); - - return resultItems; - } - finally - { - _resourcePool.Release(); - } - } - - public async Task<QueryResult<BaseItem>> GetAllMediaInternal(AllChannelMediaQuery query, CancellationToken cancellationToken) - { - var channels = GetAllChannels(); - - if (query.ChannelIds.Length > 0) - { - // Avoid implicitly captured closure - var ids = query.ChannelIds; - channels = channels - .Where(i => ids.Contains(GetInternalChannelId(i.Name).ToString("N"))) - .ToArray(); - } - - var tasks = channels - .Select(async i => - { - var indexable = i as IIndexableChannel; - - if (indexable != null) - { - try - { - var result = await GetAllItems(indexable, i, new InternalAllChannelMediaQuery - { - UserId = query.UserId, - ContentTypes = query.ContentTypes, - ExtraTypes = query.ExtraTypes, - TrailerTypes = query.TrailerTypes - - }, cancellationToken).ConfigureAwait(false); - - return new Tuple<IChannel, ChannelItemResult>(i, result); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting all media from {0}", ex, i.Name); - } - } - return new Tuple<IChannel, ChannelItemResult>(i, new ChannelItemResult()); - }); - - var results = await Task.WhenAll(tasks).ConfigureAwait(false); - - var totalCount = results.Length; - - IEnumerable<Tuple<IChannel, ChannelItemInfo>> items = results - .SelectMany(i => i.Item2.Items.Select(m => new Tuple<IChannel, ChannelItemInfo>(i.Item1, m))) - .OrderBy(i => i.Item2.Name); - - if (query.StartIndex.HasValue) - { - items = items.Skip(query.StartIndex.Value); - } - if (query.Limit.HasValue) - { - items = items.Take(query.Limit.Value); - } - - // Avoid implicitly captured closure - var token = cancellationToken; - var itemTasks = items.Select(i => - { - var channelProvider = i.Item1; - var internalChannelId = GetInternalChannelId(channelProvider.Name); - return GetChannelItemEntity(i.Item2, channelProvider, internalChannelId, token); - }); - - var internalItems = await Task.WhenAll(itemTasks).ConfigureAwait(false); - - var returnItemArray = internalItems.ToArray(); - - return new QueryResult<BaseItem> - { - TotalRecordCount = totalCount, - Items = returnItemArray - }; - } - - public async Task<QueryResult<BaseItemDto>> GetAllMedia(AllChannelMediaQuery query, CancellationToken cancellationToken) - { - var user = string.IsNullOrWhiteSpace(query.UserId) - ? null - : _userManager.GetUserById(query.UserId); - - var internalResult = await GetAllMediaInternal(query, cancellationToken).ConfigureAwait(false); - - RefreshIfNeeded(internalResult.Items); - - var dtoOptions = new DtoOptions(); - - var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user).ConfigureAwait(false)) - .ToArray(); - - var result = new QueryResult<BaseItemDto> - { - Items = returnItems, - TotalRecordCount = internalResult.TotalRecordCount - }; - - return result; - } - - private async Task<ChannelItemResult> GetAllItems(IIndexableChannel indexable, IChannel channel, InternalAllChannelMediaQuery query, CancellationToken cancellationToken) - { - var cacheLength = CacheLength; - var folderId = _jsonSerializer.SerializeToString(query).GetMD5().ToString("N"); - var cachePath = GetChannelDataCachePath(channel, query.UserId, folderId, null, false); - - try - { - if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow) - { - return _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath); - } - } - catch (FileNotFoundException) - { - - } - catch (DirectoryNotFoundException) - { - - } - - await _resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - try - { - if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow) - { - return _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath); - } - } - catch (FileNotFoundException) - { - - } - catch (DirectoryNotFoundException) - { - - } - - var result = await indexable.GetAllMedia(query, cancellationToken).ConfigureAwait(false); - - CacheResponse(result, cachePath); - - return result; - } - finally - { - _resourcePool.Release(); - } - } - - public async Task<QueryResult<BaseItem>> GetChannelItemsInternal(ChannelItemQuery query, IProgress<double> progress, CancellationToken cancellationToken) - { - // Get the internal channel entity - var channel = GetChannel(query.ChannelId); - - // Find the corresponding channel provider plugin - var channelProvider = GetChannelProvider(channel); - - var channelInfo = channelProvider.GetChannelFeatures(); - - int? providerStartIndex = null; - int? providerLimit = null; - - if (channelInfo.MaxPageSize.HasValue) - { - providerStartIndex = query.StartIndex; - - if (query.Limit.HasValue && query.Limit.Value > channelInfo.MaxPageSize.Value) - { - query.Limit = Math.Min(query.Limit.Value, channelInfo.MaxPageSize.Value); - } - providerLimit = query.Limit; - - // This will cause some providers to fail - if (providerLimit == 0) - { - providerLimit = 1; - } - } - - var user = string.IsNullOrWhiteSpace(query.UserId) - ? null - : _userManager.GetUserById(query.UserId); - - ChannelItemSortField? sortField = null; - ChannelItemSortField parsedField; - if (query.SortBy.Length == 1 && - Enum.TryParse(query.SortBy[0], true, out parsedField)) - { - sortField = parsedField; - } - - var sortDescending = query.SortOrder.HasValue && query.SortOrder.Value == SortOrder.Descending; - - var itemsResult = await GetChannelItems(channelProvider, - user, - query.FolderId, - providerStartIndex, - providerLimit, - sortField, - sortDescending, - cancellationToken) - .ConfigureAwait(false); - - var providerTotalRecordCount = providerLimit.HasValue ? itemsResult.TotalRecordCount : null; - - var tasks = itemsResult.Items.Select(i => GetChannelItemEntity(i, channelProvider, channel.Id, cancellationToken)); - - var internalItems = await Task.WhenAll(tasks).ConfigureAwait(false); - - if (user != null) - { - internalItems = internalItems.Where(i => i.IsVisible(user)).ToArray(); - - if (providerTotalRecordCount.HasValue) - { - providerTotalRecordCount = providerTotalRecordCount.Value; - } - } - - return await GetReturnItems(internalItems, providerTotalRecordCount, user, query).ConfigureAwait(false); - } - - public async Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken) - { - var user = string.IsNullOrWhiteSpace(query.UserId) - ? null - : _userManager.GetUserById(query.UserId); - - var internalResult = await GetChannelItemsInternal(query, new Progress<double>(), cancellationToken).ConfigureAwait(false); - - var dtoOptions = new DtoOptions(); - - var returnItems = (await _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user).ConfigureAwait(false)) - .ToArray(); - - var result = new QueryResult<BaseItemDto> - { - Items = returnItems, - TotalRecordCount = internalResult.TotalRecordCount - }; - - return result; - } - - private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1); - private async Task<ChannelItemResult> GetChannelItems(IChannel channel, - User user, - string folderId, - int? startIndex, - int? limit, - ChannelItemSortField? sortField, - bool sortDescending, - CancellationToken cancellationToken) - { - var userId = user.Id.ToString("N"); - - var cacheLength = CacheLength; - var cachePath = GetChannelDataCachePath(channel, userId, folderId, sortField, sortDescending); - - try - { - if (!startIndex.HasValue && !limit.HasValue) - { - if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow) - { - return _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath); - } - } - } - catch (FileNotFoundException) - { - - } - catch (DirectoryNotFoundException) - { - - } - - await _resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - try - { - if (!startIndex.HasValue && !limit.HasValue) - { - if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow) - { - return _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath); - } - } - } - catch (FileNotFoundException) - { - - } - catch (DirectoryNotFoundException) - { - - } - - var query = new InternalChannelItemQuery - { - UserId = userId, - StartIndex = startIndex, - Limit = limit, - SortBy = sortField, - SortDescending = sortDescending - }; - - if (!string.IsNullOrWhiteSpace(folderId)) - { - var categoryItem = _libraryManager.GetItemById(new Guid(folderId)); - - query.FolderId = categoryItem.ExternalId; - } - - var result = await channel.GetChannelItems(query, cancellationToken).ConfigureAwait(false); - - if (!startIndex.HasValue && !limit.HasValue) - { - CacheResponse(result, cachePath); - } - - return result; - } - finally - { - _resourcePool.Release(); - } - } - - private void CacheResponse(object result, string path) - { - try - { - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - - _jsonSerializer.SerializeToFile(result, path); - } - catch (Exception ex) - { - _logger.ErrorException("Error writing to channel cache file: {0}", ex, path); - } - } - - private string GetChannelDataCachePath(IChannel channel, - string userId, - string folderId, - ChannelItemSortField? sortField, - bool sortDescending) - { - var channelId = GetInternalChannelId(channel.Name).ToString("N"); - - var userCacheKey = string.Empty; - - var hasCacheKey = channel as IHasCacheKey; - if (hasCacheKey != null) - { - userCacheKey = hasCacheKey.GetCacheKey(userId) ?? string.Empty; - } - - var filename = string.IsNullOrWhiteSpace(folderId) ? "root" : folderId; - filename += userCacheKey; - - var version = (channel.DataVersion ?? string.Empty).GetMD5().ToString("N"); - - if (sortField.HasValue) - { - filename += "-sortField-" + sortField.Value; - } - if (sortDescending) - { - filename += "-sortDescending"; - } - - filename = filename.GetMD5().ToString("N"); - - return Path.Combine(_config.ApplicationPaths.CachePath, - "channels", - channelId, - version, - filename + ".json"); - } - - private async Task<QueryResult<BaseItem>> GetReturnItems(IEnumerable<BaseItem> items, - int? totalCountFromProvider, - User user, - ChannelItemQuery query) - { - items = ApplyFilters(items, query.Filters, user); - - items = _libraryManager.Sort(items, user, query.SortBy, query.SortOrder ?? SortOrder.Ascending); - - var all = items.ToList(); - var totalCount = totalCountFromProvider ?? all.Count; - - if (!totalCountFromProvider.HasValue) - { - if (query.StartIndex.HasValue) - { - all = all.Skip(query.StartIndex.Value).ToList(); - } - if (query.Limit.HasValue) - { - all = all.Take(query.Limit.Value).ToList(); - } - } - - var returnItemArray = all.ToArray(); - RefreshIfNeeded(returnItemArray); - - return new QueryResult<BaseItem> - { - Items = returnItemArray, - TotalRecordCount = totalCount - }; - } - - private string GetIdToHash(string externalId, string channelName) - { - // Increment this as needed to force new downloads - // Incorporate Name because it's being used to convert channel entity to provider - return externalId + (channelName ?? string.Empty) + "16"; - } - - private T GetItemById<T>(string idString, string channelName, string channnelDataVersion, out bool isNew) - where T : BaseItem, new() - { - var id = GetIdToHash(idString, channelName).GetMBId(typeof(T)); - - T item = null; - - try - { - item = _libraryManager.GetItemById(id) as T; - } - catch (Exception ex) - { - _logger.ErrorException("Error retrieving channel item from database", ex); - } - - if (item == null || !string.Equals(item.ExternalEtag, channnelDataVersion, StringComparison.Ordinal)) - { - item = new T(); - isNew = true; - } - else - { - isNew = false; - } - - item.ExternalEtag = channnelDataVersion; - item.Id = id; - return item; - } - - private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, CancellationToken cancellationToken) - { - BaseItem item; - bool isNew; - bool forceUpdate = false; - - if (info.Type == ChannelItemType.Folder) - { - if (info.FolderType == ChannelFolderType.MusicAlbum) - { - item = GetItemById<MusicAlbum>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - else if (info.FolderType == ChannelFolderType.MusicArtist) - { - item = GetItemById<MusicArtist>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - else if (info.FolderType == ChannelFolderType.PhotoAlbum) - { - item = GetItemById<PhotoAlbum>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - else if (info.FolderType == ChannelFolderType.Series) - { - item = GetItemById<Series>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - else if (info.FolderType == ChannelFolderType.Season) - { - item = GetItemById<Season>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - else - { - item = GetItemById<Folder>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - } - else if (info.MediaType == ChannelMediaType.Audio) - { - if (info.ContentType == ChannelMediaContentType.Podcast) - { - item = GetItemById<AudioPodcast>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - else - { - item = GetItemById<Audio>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - } - else - { - if (info.ContentType == ChannelMediaContentType.Episode) - { - item = GetItemById<Episode>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - else if (info.ContentType == ChannelMediaContentType.Movie) - { - item = GetItemById<Movie>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - else if (info.ContentType == ChannelMediaContentType.Trailer || info.ExtraType == ExtraType.Trailer) - { - item = GetItemById<Trailer>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - else - { - item = GetItemById<Video>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); - } - } - - item.RunTimeTicks = info.RunTimeTicks; - - if (isNew) - { - item.Name = info.Name; - item.Genres = info.Genres; - item.Studios = info.Studios; - item.CommunityRating = info.CommunityRating; - item.Overview = info.Overview; - item.IndexNumber = info.IndexNumber; - item.ParentIndexNumber = info.ParentIndexNumber; - item.PremiereDate = info.PremiereDate; - item.ProductionYear = info.ProductionYear; - item.ProviderIds = info.ProviderIds; - item.OfficialRating = info.OfficialRating; - item.DateCreated = info.DateCreated ?? DateTime.UtcNow; - item.Tags = info.Tags; - item.HomePageUrl = info.HomePageUrl; - } - else if (info.Type == ChannelItemType.Folder && info.FolderType == ChannelFolderType.Container) - { - // At least update names of container folders - if (item.Name != info.Name) - { - item.Name = info.Name; - forceUpdate = true; - } - } - - var hasArtists = item as IHasArtist; - if (hasArtists != null) - { - hasArtists.Artists = info.Artists; - } - - var hasAlbumArtists = item as IHasAlbumArtist; - if (hasAlbumArtists != null) - { - hasAlbumArtists.AlbumArtists = info.AlbumArtists; - } - - var trailer = item as Trailer; - if (trailer != null) - { - if (!info.TrailerTypes.SequenceEqual(trailer.TrailerTypes)) - { - forceUpdate = true; - } - trailer.TrailerTypes = info.TrailerTypes; - } - - item.ChannelId = internalChannelId.ToString("N"); - - if (item.ParentId != internalChannelId) - { - forceUpdate = true; - } - item.ParentId = internalChannelId; - - if (!string.Equals(item.ExternalId, info.Id, StringComparison.OrdinalIgnoreCase)) - { - forceUpdate = true; - } - item.ExternalId = info.Id; - - var channelAudioItem = item as Audio; - if (channelAudioItem != null) - { - channelAudioItem.ExtraType = info.ExtraType; - channelAudioItem.ChannelMediaSources = info.MediaSources; - - var mediaSource = info.MediaSources.FirstOrDefault(); - item.Path = mediaSource == null ? null : mediaSource.Path; - } - - var channelVideoItem = item as Video; - if (channelVideoItem != null) - { - channelVideoItem.ExtraType = info.ExtraType; - channelVideoItem.ChannelMediaSources = info.MediaSources; - - var mediaSource = info.MediaSources.FirstOrDefault(); - item.Path = mediaSource == null ? null : mediaSource.Path; - } - - if (!string.IsNullOrWhiteSpace(info.ImageUrl) && !item.HasImage(ImageType.Primary)) - { - item.SetImagePath(ImageType.Primary, info.ImageUrl); - } - - if (item.SourceType != SourceType.Channel) - { - item.SourceType = SourceType.Channel; - forceUpdate = true; - } - - if (isNew) - { - await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); - - if (info.People != null && info.People.Count > 0) - { - await _libraryManager.UpdatePeople(item, info.People ?? new List<PersonInfo>()).ConfigureAwait(false); - } - } - else if (forceUpdate) - { - await item.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false); - } - - return item; - } - - private void RefreshIfNeeded(BaseItem[] programs) - { - foreach (var program in programs) - { - RefreshIfNeeded(program); - } - } - - private void RefreshIfNeeded(BaseItem program) - { - if (!_refreshedItems.ContainsKey(program.Id)) - { - _refreshedItems.TryAdd(program.Id, true); - _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem)); - } - - } - - internal IChannel GetChannelProvider(Channel channel) - { - if (channel == null) - { - throw new ArgumentNullException("channel"); - } - - var result = GetAllChannels() - .FirstOrDefault(i => string.Equals(GetInternalChannelId(i.Name).ToString("N"), channel.ChannelId, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase)); - - if (result == null) - { - throw new ResourceNotFoundException("No channel provider found for channel " + channel.Name); - } - - return result; - } - - internal IChannel GetChannelProvider(string internalChannelId) - { - if (internalChannelId == null) - { - throw new ArgumentNullException("internalChannelId"); - } - - var result = GetAllChannels() - .FirstOrDefault(i => string.Equals(GetInternalChannelId(i.Name).ToString("N"), internalChannelId, StringComparison.OrdinalIgnoreCase)); - - if (result == null) - { - throw new ResourceNotFoundException("No channel provider found for channel id " + internalChannelId); - } - - return result; - } - - private IEnumerable<BaseItem> ApplyFilters(IEnumerable<BaseItem> items, IEnumerable<ItemFilter> filters, User user) - { - foreach (var filter in filters.OrderByDescending(f => (int)f)) - { - items = ApplyFilter(items, filter, user); - } - - return items; - } - - private IEnumerable<BaseItem> ApplyFilter(IEnumerable<BaseItem> items, ItemFilter filter, User user) - { - // Avoid implicitly captured closure - var currentUser = user; - - switch (filter) - { - case ItemFilter.IsFavoriteOrLikes: - return items.Where(item => - { - var userdata = _userDataManager.GetUserData(user, item); - - if (userdata == null) - { - return false; - } - - var likes = userdata.Likes ?? false; - var favorite = userdata.IsFavorite; - - return likes || favorite; - }); - - case ItemFilter.Likes: - return items.Where(item => - { - var userdata = _userDataManager.GetUserData(user, item); - - return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value; - }); - - case ItemFilter.Dislikes: - return items.Where(item => - { - var userdata = _userDataManager.GetUserData(user, item); - - return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value; - }); - - case ItemFilter.IsFavorite: - return items.Where(item => - { - var userdata = _userDataManager.GetUserData(user, item); - - return userdata != null && userdata.IsFavorite; - }); - - case ItemFilter.IsResumable: - return items.Where(item => - { - var userdata = _userDataManager.GetUserData(user, item); - - return userdata != null && userdata.PlaybackPositionTicks > 0; - }); - - case ItemFilter.IsPlayed: - return items.Where(item => item.IsPlayed(currentUser)); - - case ItemFilter.IsUnplayed: - return items.Where(item => item.IsUnplayed(currentUser)); - - case ItemFilter.IsFolder: - return items.Where(item => item.IsFolder); - - case ItemFilter.IsNotFolder: - return items.Where(item => !item.IsFolder); - } - - return items; - } - - public async Task<BaseItemDto> GetChannelFolder(string userId, CancellationToken cancellationToken) - { - var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(userId); - - var folder = await GetInternalChannelFolder(cancellationToken).ConfigureAwait(false); - - return _dtoService.GetBaseItemDto(folder, new DtoOptions(), user); - } - - public async Task<Folder> GetInternalChannelFolder(CancellationToken cancellationToken) - { - var name = _localization.GetLocalizedString("ViewTypeChannels"); - - return await _libraryManager.GetNamedView(name, "channels", "zz_" + name, cancellationToken).ConfigureAwait(false); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs deleted file mode 100644 index b25c9c8180..0000000000 --- a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs +++ /dev/null @@ -1,257 +0,0 @@ -using MediaBrowser.Common.Progress; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Logging; -using MoreLinq; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Channels -{ - public class ChannelPostScanTask - { - private readonly IChannelManager _channelManager; - private readonly IUserManager _userManager; - private readonly ILogger _logger; - private readonly ILibraryManager _libraryManager; - - public ChannelPostScanTask(IChannelManager channelManager, IUserManager userManager, ILogger logger, ILibraryManager libraryManager) - { - _channelManager = channelManager; - _userManager = userManager; - _logger = logger; - _libraryManager = libraryManager; - } - - public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - var users = _userManager.Users - .DistinctBy(GetUserDistinctValue) - .Select(i => i.Id.ToString("N")) - .ToList(); - - var numComplete = 0; - - foreach (var user in users) - { - double percentPerUser = 1; - percentPerUser /= users.Count; - var startingPercent = numComplete * percentPerUser * 100; - - var innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(p => progress.Report(startingPercent + percentPerUser * p)); - - await DownloadContent(user, cancellationToken, innerProgress).ConfigureAwait(false); - - numComplete++; - double percent = numComplete; - percent /= users.Count; - progress.Report(percent * 100); - } - - await CleanDatabase(cancellationToken).ConfigureAwait(false); - - progress.Report(100); - } - - public static string GetUserDistinctValue(User user) - { - var channels = user.Policy.EnabledChannels - .OrderBy(i => i) - .ToList(); - - return string.Join("|", channels.ToArray()); - } - - private async Task DownloadContent(string user, CancellationToken cancellationToken, IProgress<double> progress) - { - var channels = await _channelManager.GetChannelsInternal(new ChannelQuery - { - UserId = user - - }, cancellationToken); - - var numComplete = 0; - var numItems = channels.Items.Length; - - foreach (var channel in channels.Items) - { - var channelId = channel.Id.ToString("N"); - - var features = _channelManager.GetChannelFeatures(channelId); - - const int currentRefreshLevel = 1; - var maxRefreshLevel = features.AutoRefreshLevels ?? 0; - maxRefreshLevel = Math.Max(maxRefreshLevel, 2); - - if (maxRefreshLevel > 0) - { - var innerProgress = new ActionableProgress<double>(); - - var startingNumberComplete = numComplete; - innerProgress.RegisterAction(p => - { - double innerPercent = startingNumberComplete; - innerPercent += p / 100; - innerPercent /= numItems; - progress.Report(innerPercent * 100); - }); - - try - { - await GetAllItems(user, channelId, null, currentRefreshLevel, maxRefreshLevel, innerProgress, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting channel content", ex); - } - } - - numComplete++; - double percent = numComplete; - percent /= numItems; - progress.Report(percent * 100); - } - - progress.Report(100); - } - - private async Task CleanDatabase(CancellationToken cancellationToken) - { - var installedChannelIds = ((ChannelManager)_channelManager).GetInstalledChannelIds(); - - var databaseIds = _libraryManager.GetItemIds(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Channel).Name } - }); - - var invalidIds = databaseIds - .Except(installedChannelIds) - .ToList(); - - foreach (var id in invalidIds) - { - cancellationToken.ThrowIfCancellationRequested(); - - await CleanChannel(id, cancellationToken).ConfigureAwait(false); - } - } - - private async Task CleanChannel(Guid id, CancellationToken cancellationToken) - { - _logger.Info("Cleaning channel {0} from database", id); - - // Delete all channel items - var allIds = _libraryManager.GetItemIds(new InternalItemsQuery - { - ChannelIds = new[] { id.ToString("N") } - }); - - foreach (var deleteId in allIds) - { - cancellationToken.ThrowIfCancellationRequested(); - - await DeleteItem(deleteId).ConfigureAwait(false); - } - - // Finally, delete the channel itself - await DeleteItem(id).ConfigureAwait(false); - } - - private Task DeleteItem(Guid id) - { - var item = _libraryManager.GetItemById(id); - - if (item == null) - { - return Task.FromResult(true); - } - - return _libraryManager.DeleteItem(item, new DeleteOptions - { - DeleteFileLocation = false - }); - } - - private async Task GetAllItems(string user, string channelId, string folderId, int currentRefreshLevel, int maxRefreshLevel, IProgress<double> progress, CancellationToken cancellationToken) - { - var folderItems = new List<string>(); - - var innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(p => progress.Report(p / 2)); - - var result = await _channelManager.GetChannelItemsInternal(new ChannelItemQuery - { - ChannelId = channelId, - UserId = user, - FolderId = folderId - - }, innerProgress, cancellationToken); - - folderItems.AddRange(result.Items.Where(i => i.IsFolder).Select(i => i.Id.ToString("N"))); - - var totalRetrieved = result.Items.Length; - var totalCount = result.TotalRecordCount; - - while (totalRetrieved < totalCount) - { - result = await _channelManager.GetChannelItemsInternal(new ChannelItemQuery - { - ChannelId = channelId, - UserId = user, - StartIndex = totalRetrieved, - FolderId = folderId - - }, new Progress<double>(), cancellationToken); - - folderItems.AddRange(result.Items.Where(i => i.IsFolder).Select(i => i.Id.ToString("N"))); - - totalRetrieved += result.Items.Length; - totalCount = result.TotalRecordCount; - } - - progress.Report(50); - - if (currentRefreshLevel < maxRefreshLevel) - { - var numComplete = 0; - var numItems = folderItems.Count; - - foreach (var folder in folderItems) - { - try - { - innerProgress = new ActionableProgress<double>(); - - var startingNumberComplete = numComplete; - innerProgress.RegisterAction(p => - { - double innerPercent = startingNumberComplete; - innerPercent += p / 100; - innerPercent /= numItems; - progress.Report(innerPercent * 50 + 50); - }); - - await GetAllItems(user, channelId, folder, currentRefreshLevel + 1, maxRefreshLevel, innerProgress, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting channel content", ex); - } - - numComplete++; - double percent = numComplete; - percent /= numItems; - progress.Report(percent * 50 + 50); - } - } - - progress.Report(100); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs deleted file mode 100644 index 5ac3da3db6..0000000000 --- a/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs +++ /dev/null @@ -1,69 +0,0 @@ -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Channels -{ - class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask - { - private readonly IChannelManager _channelManager; - private readonly IUserManager _userManager; - private readonly ILogger _logger; - private readonly ILibraryManager _libraryManager; - - public RefreshChannelsScheduledTask(IChannelManager channelManager, IUserManager userManager, ILogger logger, ILibraryManager libraryManager) - { - _channelManager = channelManager; - _userManager = userManager; - _logger = logger; - _libraryManager = libraryManager; - } - - public string Name - { - get { return "Refresh Channels"; } - } - - public string Description - { - get { return "Refreshes internet channel information."; } - } - - public string Category - { - get { return "Internet Channels"; } - } - - public async Task Execute(System.Threading.CancellationToken cancellationToken, IProgress<double> progress) - { - var manager = (ChannelManager)_channelManager; - - await manager.RefreshChannels(new Progress<double>(), cancellationToken).ConfigureAwait(false); - - await new ChannelPostScanTask(_channelManager, _userManager, _logger, _libraryManager).Run(progress, cancellationToken) - .ConfigureAwait(false); - } - - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - return new ITaskTrigger[] - { - new IntervalTrigger{ Interval = TimeSpan.FromHours(24)} - }; - } - - public bool IsHidden - { - get { return false; } - } - - public bool IsEnabled - { - get { return true; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs deleted file mode 100644 index 25393d30f6..0000000000 --- a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs +++ /dev/null @@ -1,84 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Server.Implementations.Photos; -using MoreLinq; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Collections -{ - public class CollectionImageProvider : BaseDynamicImageProvider<BoxSet> - { - public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - } - - protected override bool Supports(IHasImages item) - { - // Right now this is the only way to prevent this image from getting created ahead of internet image providers - if (!item.IsLocked) - { - return false; - } - - return base.Supports(item); - } - - protected override Task<List<BaseItem>> GetItemsWithImages(IHasImages item) - { - var playlist = (BoxSet)item; - - var items = playlist.Children.Concat(playlist.GetLinkedChildren()) - .Select(i => - { - var subItem = i; - - var episode = subItem as Episode; - - if (episode != null) - { - var series = episode.Series; - if (series != null && series.HasImage(ImageType.Primary)) - { - return series; - } - } - - if (subItem.HasImage(ImageType.Primary)) - { - return subItem; - } - - var parent = subItem.GetParent(); - - if (parent != null && parent.HasImage(ImageType.Primary)) - { - if (parent is MusicAlbum) - { - return parent; - } - } - - return null; - }) - .Where(i => i != null) - .DistinctBy(i => i.Id) - .ToList(); - - return Task.FromResult(GetFinalItems(items, 2)); - } - - protected override Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) - { - return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs deleted file mode 100644 index cb2bd645dd..0000000000 --- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs +++ /dev/null @@ -1,296 +0,0 @@ -using MediaBrowser.Common.Events; -using MediaBrowser.Controller.Collections; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Collections -{ - public class CollectionManager : ICollectionManager - { - private readonly ILibraryManager _libraryManager; - private readonly IFileSystem _fileSystem; - private readonly ILibraryMonitor _iLibraryMonitor; - private readonly ILogger _logger; - private readonly IProviderManager _providerManager; - - public event EventHandler<CollectionCreatedEventArgs> CollectionCreated; - public event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection; - public event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection; - - public CollectionManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor, ILogger logger, IProviderManager providerManager) - { - _libraryManager = libraryManager; - _fileSystem = fileSystem; - _iLibraryMonitor = iLibraryMonitor; - _logger = logger; - _providerManager = providerManager; - } - - public Folder GetCollectionsFolder(string userId) - { - return _libraryManager.RootFolder.Children.OfType<ManualCollectionsFolder>() - .FirstOrDefault() ?? _libraryManager.GetUserRootFolder().Children.OfType<ManualCollectionsFolder>() - .FirstOrDefault(); - } - - public IEnumerable<BoxSet> GetCollections(User user) - { - var folder = GetCollectionsFolder(user.Id.ToString("N")); - return folder == null ? - new List<BoxSet>() : - folder.GetChildren(user, true).OfType<BoxSet>(); - } - - public async Task<BoxSet> CreateCollection(CollectionCreationOptions options) - { - var name = options.Name; - - // Need to use the [boxset] suffix - // If internet metadata is not found, or if xml saving is off there will be no collection.xml - // This could cause it to get re-resolved as a plain folder - var folderName = _fileSystem.GetValidFilename(name) + " [boxset]"; - - var parentFolder = GetParentFolder(options.ParentId); - - if (parentFolder == null) - { - throw new ArgumentException(); - } - - var path = Path.Combine(parentFolder.Path, folderName); - - _iLibraryMonitor.ReportFileSystemChangeBeginning(path); - - try - { - _fileSystem.CreateDirectory(path); - - var collection = new BoxSet - { - Name = name, - Path = path, - IsLocked = options.IsLocked, - ProviderIds = options.ProviderIds, - Shares = options.UserIds.Select(i => new Share - { - UserId = i.ToString("N"), - CanEdit = true - - }).ToList() - }; - - await parentFolder.AddChild(collection, CancellationToken.None).ConfigureAwait(false); - - if (options.ItemIdList.Count > 0) - { - await AddToCollection(collection.Id, options.ItemIdList, false, new MetadataRefreshOptions(_fileSystem) - { - // The initial adding of items is going to create a local metadata file - // This will cause internet metadata to be skipped as a result - MetadataRefreshMode = MetadataRefreshMode.FullRefresh - }); - } - else - { - _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem)); - } - - EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs - { - Collection = collection, - Options = options - - }, _logger); - - return collection; - } - finally - { - // Refresh handled internally - _iLibraryMonitor.ReportFileSystemChangeComplete(path, false); - } - } - - private Folder GetParentFolder(Guid? parentId) - { - if (parentId.HasValue) - { - if (parentId.Value == Guid.Empty) - { - throw new ArgumentNullException("parentId"); - } - - var folder = _libraryManager.GetItemById(parentId.Value) as Folder; - - // Find an actual physical folder - if (folder is CollectionFolder) - { - var child = _libraryManager.RootFolder.Children.OfType<Folder>() - .FirstOrDefault(i => folder.PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase)); - - if (child != null) - { - return child; - } - } - } - - return GetCollectionsFolder(string.Empty); - } - - public Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids) - { - return AddToCollection(collectionId, ids, true, new MetadataRefreshOptions(_fileSystem)); - } - - private async Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent, MetadataRefreshOptions refreshOptions) - { - var collection = _libraryManager.GetItemById(collectionId) as BoxSet; - - if (collection == null) - { - throw new ArgumentException("No collection exists with the supplied Id"); - } - - var list = new List<LinkedChild>(); - var itemList = new List<BaseItem>(); - var currentLinkedChildren = collection.GetLinkedChildren().ToList(); - - foreach (var itemId in ids) - { - var item = _libraryManager.GetItemById(itemId); - - if (item == null) - { - throw new ArgumentException("No item exists with the supplied Id"); - } - - itemList.Add(item); - - if (currentLinkedChildren.All(i => i.Id != itemId)) - { - list.Add(LinkedChild.Create(item)); - } - } - - if (list.Count > 0) - { - collection.LinkedChildren.AddRange(list); - - collection.UpdateRatingToContent(); - - await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - - _providerManager.QueueRefresh(collection.Id, refreshOptions); - - if (fireEvent) - { - EventHelper.FireEventIfNotNull(ItemsAddedToCollection, this, new CollectionModifiedEventArgs - { - Collection = collection, - ItemsChanged = itemList - - }, _logger); - } - } - } - - public async Task RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds) - { - var collection = _libraryManager.GetItemById(collectionId) as BoxSet; - - if (collection == null) - { - throw new ArgumentException("No collection exists with the supplied Id"); - } - - var list = new List<LinkedChild>(); - var itemList = new List<BaseItem>(); - - foreach (var itemId in itemIds) - { - var childItem = _libraryManager.GetItemById(itemId); - - var child = collection.LinkedChildren.FirstOrDefault(i => (i.ItemId.HasValue && i.ItemId.Value == itemId) || (childItem != null && string.Equals(childItem.Path, i.Path, StringComparison.OrdinalIgnoreCase))); - - if (child == null) - { - throw new ArgumentException("No collection title exists with the supplied Id"); - } - - list.Add(child); - - if (childItem != null) - { - itemList.Add(childItem); - } - } - - foreach (var child in list) - { - collection.LinkedChildren.Remove(child); - } - - collection.UpdateRatingToContent(); - - await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem)); - - EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs - { - Collection = collection, - ItemsChanged = itemList - - }, _logger); - } - - public IEnumerable<BaseItem> CollapseItemsWithinBoxSets(IEnumerable<BaseItem> items, User user) - { - var results = new Dictionary<Guid, BaseItem>(); - - var allBoxsets = GetCollections(user).ToList(); - - foreach (var item in items) - { - var grouping = item as ISupportsBoxSetGrouping; - - if (grouping == null) - { - results[item.Id] = item; - } - else - { - var itemId = item.Id; - - var currentBoxSets = allBoxsets - .Where(i => i.GetLinkedChildren().Any(j => j.Id == itemId)) - .ToList(); - - if (currentBoxSets.Count > 0) - { - foreach (var boxset in currentBoxSets) - { - results[boxset.Id] = boxset; - } - } - else - { - results[item.Id] = item; - } - } - } - - return results.Values; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs b/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs deleted file mode 100644 index 50bb6c5592..0000000000 --- a/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Entities; -using System.IO; -using CommonIO; -using MediaBrowser.Controller.Collections; - -namespace MediaBrowser.Server.Implementations.Collections -{ - public class CollectionsDynamicFolder : IVirtualFolderCreator - { - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - - public CollectionsDynamicFolder(IApplicationPaths appPaths, IFileSystem fileSystem) - { - _appPaths = appPaths; - _fileSystem = fileSystem; - } - - public BasePluginFolder GetFolder() - { - var path = Path.Combine(_appPaths.DataPath, "collections"); - - _fileSystem.CreateDirectory(path); - - return new ManualCollectionsFolder - { - Path = path - }; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs deleted file mode 100644 index e8669bbc2c..0000000000 --- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ /dev/null @@ -1,257 +0,0 @@ -using System.Collections.Generic; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Events; -using MediaBrowser.Common.Implementations.Configuration; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.IO; -using System.Linq; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Configuration -{ - /// <summary> - /// Class ServerConfigurationManager - /// </summary> - public class ServerConfigurationManager : BaseConfigurationManager, IServerConfigurationManager - { - - /// <summary> - /// Initializes a new instance of the <see cref="ServerConfigurationManager" /> class. - /// </summary> - /// <param name="applicationPaths">The application paths.</param> - /// <param name="logManager">The log manager.</param> - /// <param name="xmlSerializer">The XML serializer.</param> - /// <param name="fileSystem">The file system.</param> - public ServerConfigurationManager(IApplicationPaths applicationPaths, ILogManager logManager, IXmlSerializer xmlSerializer, IFileSystem fileSystem) - : base(applicationPaths, logManager, xmlSerializer, fileSystem) - { - UpdateMetadataPath(); - } - - public event EventHandler<GenericEventArgs<ServerConfiguration>> ConfigurationUpdating; - - /// <summary> - /// Gets the type of the configuration. - /// </summary> - /// <value>The type of the configuration.</value> - protected override Type ConfigurationType - { - get { return typeof(ServerConfiguration); } - } - - /// <summary> - /// Gets the application paths. - /// </summary> - /// <value>The application paths.</value> - public IServerApplicationPaths ApplicationPaths - { - get { return (IServerApplicationPaths)CommonApplicationPaths; } - } - - /// <summary> - /// Gets the configuration. - /// </summary> - /// <value>The configuration.</value> - public ServerConfiguration Configuration - { - get { return (ServerConfiguration)CommonConfiguration; } - } - - /// <summary> - /// Called when [configuration updated]. - /// </summary> - protected override void OnConfigurationUpdated() - { - UpdateMetadataPath(); - - base.OnConfigurationUpdated(); - } - - public override void AddParts(IEnumerable<IConfigurationFactory> factories) - { - base.AddParts(factories); - - UpdateTranscodingTempPath(); - } - - /// <summary> - /// Updates the metadata path. - /// </summary> - private void UpdateMetadataPath() - { - string metadataPath; - - if (string.IsNullOrWhiteSpace(Configuration.MetadataPath)) - { - metadataPath = GetInternalMetadataPath(); - } - else - { - metadataPath = Path.Combine(Configuration.MetadataPath, "metadata"); - } - - ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = metadataPath; - - ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath; - } - - private string GetInternalMetadataPath() - { - return Path.Combine(ApplicationPaths.ProgramDataPath, "metadata"); - } - - /// <summary> - /// Updates the transcoding temporary path. - /// </summary> - private void UpdateTranscodingTempPath() - { - var encodingConfig = this.GetConfiguration<EncodingOptions>("encoding"); - - ((ServerApplicationPaths)ApplicationPaths).TranscodingTempPath = string.IsNullOrEmpty(encodingConfig.TranscodingTempPath) ? - null : - Path.Combine(encodingConfig.TranscodingTempPath, "transcoding-temp"); - } - - protected override void OnNamedConfigurationUpdated(string key, object configuration) - { - base.OnNamedConfigurationUpdated(key, configuration); - - if (string.Equals(key, "encoding", StringComparison.OrdinalIgnoreCase)) - { - UpdateTranscodingTempPath(); - } - } - - /// <summary> - /// Replaces the configuration. - /// </summary> - /// <param name="newConfiguration">The new configuration.</param> - /// <exception cref="System.IO.DirectoryNotFoundException"></exception> - public override void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration) - { - var newConfig = (ServerConfiguration)newConfiguration; - - ValidatePathSubstitutions(newConfig); - ValidateMetadataPath(newConfig); - ValidateSslCertificate(newConfig); - - EventHelper.FireEventIfNotNull(ConfigurationUpdating, this, new GenericEventArgs<ServerConfiguration> { Argument = newConfig }, Logger); - - base.ReplaceConfiguration(newConfiguration); - } - - - /// <summary> - /// Validates the SSL certificate. - /// </summary> - /// <param name="newConfig">The new configuration.</param> - /// <exception cref="System.IO.DirectoryNotFoundException"></exception> - private void ValidateSslCertificate(BaseApplicationConfiguration newConfig) - { - var serverConfig = (ServerConfiguration)newConfig; - - var newPath = serverConfig.CertificatePath; - - if (!string.IsNullOrWhiteSpace(newPath) - && !string.Equals(Configuration.CertificatePath ?? string.Empty, newPath)) - { - // Validate - if (!FileSystem.FileExists(newPath)) - { - throw new FileNotFoundException(string.Format("Certificate file '{0}' does not exist.", newPath)); - } - } - } - - private void ValidatePathSubstitutions(ServerConfiguration newConfig) - { - foreach (var map in newConfig.PathSubstitutions) - { - if (string.IsNullOrWhiteSpace(map.From) || string.IsNullOrWhiteSpace(map.To)) - { - throw new ArgumentException("Invalid path substitution"); - } - } - } - - /// <summary> - /// Validates the metadata path. - /// </summary> - /// <param name="newConfig">The new configuration.</param> - /// <exception cref="System.IO.DirectoryNotFoundException"></exception> - private void ValidateMetadataPath(ServerConfiguration newConfig) - { - var newPath = newConfig.MetadataPath; - - if (!string.IsNullOrWhiteSpace(newPath) - && !string.Equals(Configuration.MetadataPath ?? string.Empty, newPath)) - { - // Validate - if (!FileSystem.DirectoryExists(newPath)) - { - throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath)); - } - - EnsureWriteAccess(newPath); - } - } - - public void DisableMetadataService(string service) - { - DisableMetadataService(typeof(Movie), Configuration, service); - DisableMetadataService(typeof(Episode), Configuration, service); - DisableMetadataService(typeof(Series), Configuration, service); - DisableMetadataService(typeof(Season), Configuration, service); - DisableMetadataService(typeof(MusicArtist), Configuration, service); - DisableMetadataService(typeof(MusicAlbum), Configuration, service); - DisableMetadataService(typeof(MusicVideo), Configuration, service); - DisableMetadataService(typeof(Video), Configuration, service); - } - - private void DisableMetadataService(Type type, ServerConfiguration config, string service) - { - var options = GetMetadataOptions(type, config); - - if (!options.DisabledMetadataSavers.Contains(service, StringComparer.OrdinalIgnoreCase)) - { - var list = options.DisabledMetadataSavers.ToList(); - - list.Add(service); - - options.DisabledMetadataSavers = list.ToArray(); - } - } - - private MetadataOptions GetMetadataOptions(Type type, ServerConfiguration config) - { - var options = config.MetadataOptions - .FirstOrDefault(i => string.Equals(i.ItemType, type.Name, StringComparison.OrdinalIgnoreCase)); - - if (options == null) - { - var list = config.MetadataOptions.ToList(); - - options = new MetadataOptions - { - ItemType = type.Name - }; - - list.Add(options); - - config.MetadataOptions = list.ToArray(); - } - - return options; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs b/MediaBrowser.Server.Implementations/Connect/ConnectData.cs deleted file mode 100644 index 5ec0bea22c..0000000000 --- a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Server.Implementations.Connect -{ - public class ConnectData - { - /// <summary> - /// Gets or sets the server identifier. - /// </summary> - /// <value>The server identifier.</value> - public string ServerId { get; set; } - /// <summary> - /// Gets or sets the access key. - /// </summary> - /// <value>The access key.</value> - public string AccessKey { get; set; } - - /// <summary> - /// Gets or sets the authorizations. - /// </summary> - /// <value>The authorizations.</value> - public List<ConnectAuthorizationInternal> PendingAuthorizations { get; set; } - - /// <summary> - /// Gets or sets the last authorizations refresh. - /// </summary> - /// <value>The last authorizations refresh.</value> - public DateTime LastAuthorizationsRefresh { get; set; } - - public ConnectData() - { - PendingAuthorizations = new List<ConnectAuthorizationInternal>(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs deleted file mode 100644 index f9eff3c92f..0000000000 --- a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs +++ /dev/null @@ -1,199 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Connect; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using System; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.Threading; - -namespace MediaBrowser.Server.Implementations.Connect -{ - public class ConnectEntryPoint : IServerEntryPoint - { - private PeriodicTimer _timer; - private readonly IHttpClient _httpClient; - private readonly IApplicationPaths _appPaths; - private readonly ILogger _logger; - private readonly IConnectManager _connectManager; - - private readonly INetworkManager _networkManager; - private readonly IApplicationHost _appHost; - private readonly IFileSystem _fileSystem; - - public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost, IFileSystem fileSystem) - { - _httpClient = httpClient; - _appPaths = appPaths; - _logger = logger; - _networkManager = networkManager; - _connectManager = connectManager; - _appHost = appHost; - _fileSystem = fileSystem; - } - - public void Run() - { - LoadCachedAddress(); - - _timer = new PeriodicTimer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(1)); - ((ConnectManager)_connectManager).Start(); - } - - private readonly string[] _ipLookups = - { - "http://bot.whatismyipaddress.com", - "https://connect.emby.media/service/ip" - }; - - private async void TimerCallback(object state) - { - IPAddress validIpAddress = null; - - foreach (var ipLookupUrl in _ipLookups) - { - try - { - validIpAddress = await GetIpAddress(ipLookupUrl).ConfigureAwait(false); - - // Try to find the ipv4 address, if present - if (validIpAddress.AddressFamily == AddressFamily.InterNetwork) - { - break; - } - } - catch (HttpException) - { - } - catch (Exception ex) - { - _logger.ErrorException("Error getting connection info", ex); - } - } - - // If this produced an ipv6 address, try again - if (validIpAddress != null && validIpAddress.AddressFamily == AddressFamily.InterNetworkV6) - { - foreach (var ipLookupUrl in _ipLookups) - { - try - { - var newAddress = await GetIpAddress(ipLookupUrl, true).ConfigureAwait(false); - - // Try to find the ipv4 address, if present - if (newAddress.AddressFamily == AddressFamily.InterNetwork) - { - validIpAddress = newAddress; - break; - } - } - catch (HttpException) - { - } - catch (Exception ex) - { - _logger.ErrorException("Error getting connection info", ex); - } - } - } - - if (validIpAddress != null) - { - ((ConnectManager)_connectManager).OnWanAddressResolved(validIpAddress); - CacheAddress(validIpAddress); - } - } - - private async Task<IPAddress> GetIpAddress(string lookupUrl, bool preferIpv4 = false) - { - // Sometimes whatismyipaddress might fail, but it won't do us any good having users raise alarms over it. - var logErrors = false; - -#if DEBUG - logErrors = true; -#endif - using (var stream = await _httpClient.Get(new HttpRequestOptions - { - Url = lookupUrl, - UserAgent = "Emby/" + _appHost.ApplicationVersion, - LogErrors = logErrors, - - // Seeing block length errors with our server - EnableHttpCompression = false, - PreferIpv4 = preferIpv4, - BufferContent = false - - }).ConfigureAwait(false)) - { - using (var reader = new StreamReader(stream)) - { - var addressString = await reader.ReadToEndAsync().ConfigureAwait(false); - - return IPAddress.Parse(addressString); - } - } - } - - private string CacheFilePath - { - get { return Path.Combine(_appPaths.DataPath, "wan.txt"); } - } - - private void CacheAddress(IPAddress address) - { - var path = CacheFilePath; - - try - { - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - _fileSystem.WriteAllText(path, address.ToString(), Encoding.UTF8); - } - catch (Exception ex) - { - _logger.ErrorException("Error saving data", ex); - } - } - - private void LoadCachedAddress() - { - var path = CacheFilePath; - - _logger.Info("Loading data from {0}", path); - - try - { - var endpoint = _fileSystem.ReadAllText(path, Encoding.UTF8); - IPAddress ipAddress; - - if (IPAddress.TryParse(endpoint, out ipAddress)) - { - ((ConnectManager)_connectManager).OnWanAddressResolved(ipAddress); - } - } - catch (IOException) - { - // File isn't there. no biggie - } - catch (Exception ex) - { - _logger.ErrorException("Error loading data", ex); - } - } - - public void Dispose() - { - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs deleted file mode 100644 index d7c1b0da07..0000000000 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ /dev/null @@ -1,1190 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Security; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Connect; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.Security; -using MediaBrowser.Model.Connect; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.Extensions; - -namespace MediaBrowser.Server.Implementations.Connect -{ - public class ConnectManager : IConnectManager - { - private readonly SemaphoreSlim _operationLock = new SemaphoreSlim(1, 1); - - private readonly ILogger _logger; - private readonly IApplicationPaths _appPaths; - private readonly IJsonSerializer _json; - private readonly IEncryptionManager _encryption; - private readonly IHttpClient _httpClient; - private readonly IServerApplicationHost _appHost; - private readonly IServerConfigurationManager _config; - private readonly IUserManager _userManager; - private readonly IProviderManager _providerManager; - private readonly ISecurityManager _securityManager; - private readonly IFileSystem _fileSystem; - - private ConnectData _data = new ConnectData(); - - public string ConnectServerId - { - get { return _data.ServerId; } - } - public string ConnectAccessKey - { - get { return _data.AccessKey; } - } - - private IPAddress DiscoveredWanIpAddress { get; set; } - - public string WanIpAddress - { - get - { - var address = _config.Configuration.WanDdns; - - if (!string.IsNullOrWhiteSpace(address)) - { - Uri newUri; - - if (Uri.TryCreate(address, UriKind.Absolute, out newUri)) - { - address = newUri.Host; - } - } - - if (string.IsNullOrWhiteSpace(address) && DiscoveredWanIpAddress != null) - { - if (DiscoveredWanIpAddress.AddressFamily == AddressFamily.InterNetworkV6) - { - address = "[" + DiscoveredWanIpAddress + "]"; - } - else - { - address = DiscoveredWanIpAddress.ToString(); - } - } - - return address; - } - } - - public string WanApiAddress - { - get - { - var ip = WanIpAddress; - - if (!string.IsNullOrEmpty(ip)) - { - if (!ip.StartsWith("http://", StringComparison.OrdinalIgnoreCase) && - !ip.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) - { - ip = (_appHost.EnableHttps ? "https://" : "http://") + ip; - } - - ip += ":"; - ip += _appHost.EnableHttps ? _config.Configuration.PublicHttpsPort.ToString(CultureInfo.InvariantCulture) : _config.Configuration.PublicPort.ToString(CultureInfo.InvariantCulture); - - return ip; - } - - return null; - } - } - - private string XApplicationValue - { - get { return _appHost.Name + "/" + _appHost.ApplicationVersion; } - } - - public ConnectManager(ILogger logger, - IApplicationPaths appPaths, - IJsonSerializer json, - IEncryptionManager encryption, - IHttpClient httpClient, - IServerApplicationHost appHost, - IServerConfigurationManager config, IUserManager userManager, IProviderManager providerManager, ISecurityManager securityManager, IFileSystem fileSystem) - { - _logger = logger; - _appPaths = appPaths; - _json = json; - _encryption = encryption; - _httpClient = httpClient; - _appHost = appHost; - _config = config; - _userManager = userManager; - _providerManager = providerManager; - _securityManager = securityManager; - _fileSystem = fileSystem; - - LoadCachedData(); - } - - internal void Start() - { - _config.ConfigurationUpdated += _config_ConfigurationUpdated; - } - - internal void OnWanAddressResolved(IPAddress address) - { - DiscoveredWanIpAddress = address; - - var task = UpdateConnectInfo(); - } - - private async Task UpdateConnectInfo() - { - await _operationLock.WaitAsync().ConfigureAwait(false); - - try - { - await UpdateConnectInfoInternal().ConfigureAwait(false); - } - finally - { - _operationLock.Release(); - } - } - - private async Task UpdateConnectInfoInternal() - { - var wanApiAddress = WanApiAddress; - - if (string.IsNullOrWhiteSpace(wanApiAddress)) - { - _logger.Warn("Cannot update Emby Connect information without a WanApiAddress"); - return; - } - - try - { - var localAddress = await _appHost.GetLocalApiUrl().ConfigureAwait(false); - - var hasExistingRecord = !string.IsNullOrWhiteSpace(ConnectServerId) && - !string.IsNullOrWhiteSpace(ConnectAccessKey); - - var createNewRegistration = !hasExistingRecord; - - if (hasExistingRecord) - { - try - { - await UpdateServerRegistration(wanApiAddress, localAddress).ConfigureAwait(false); - } - catch (HttpException ex) - { - if (!ex.StatusCode.HasValue || !new[] { HttpStatusCode.NotFound, HttpStatusCode.Unauthorized }.Contains(ex.StatusCode.Value)) - { - throw; - } - - createNewRegistration = true; - } - } - - if (createNewRegistration) - { - await CreateServerRegistration(wanApiAddress, localAddress).ConfigureAwait(false); - } - - _lastReportedIdentifier = GetConnectReportingIdentifier(localAddress, wanApiAddress); - - await RefreshAuthorizationsInternal(true, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error registering with Connect", ex); - } - } - - private string _lastReportedIdentifier; - private async Task<string> GetConnectReportingIdentifier() - { - var url = await _appHost.GetLocalApiUrl().ConfigureAwait(false); - return GetConnectReportingIdentifier(url, WanApiAddress); - } - private string GetConnectReportingIdentifier(string localAddress, string remoteAddress) - { - return (remoteAddress ?? string.Empty) + (localAddress ?? string.Empty); - } - - async void _config_ConfigurationUpdated(object sender, EventArgs e) - { - // If info hasn't changed, don't report anything - var connectIdentifier = await GetConnectReportingIdentifier().ConfigureAwait(false); - if (string.Equals(_lastReportedIdentifier, connectIdentifier, StringComparison.OrdinalIgnoreCase)) - { - return; - } - - await UpdateConnectInfo().ConfigureAwait(false); - } - - private async Task CreateServerRegistration(string wanApiAddress, string localAddress) - { - if (string.IsNullOrWhiteSpace(wanApiAddress)) - { - throw new ArgumentNullException("wanApiAddress"); - } - - var url = "Servers"; - url = GetConnectUrl(url); - - var postData = new Dictionary<string, string> - { - {"name", _appHost.FriendlyName}, - {"url", wanApiAddress}, - {"systemId", _appHost.SystemId} - }; - - if (!string.IsNullOrWhiteSpace(localAddress)) - { - postData["localAddress"] = localAddress; - } - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - options.SetPostData(postData); - SetApplicationHeader(options); - - using (var response = await _httpClient.Post(options).ConfigureAwait(false)) - { - var data = _json.DeserializeFromStream<ServerRegistrationResponse>(response.Content); - - _data.ServerId = data.Id; - _data.AccessKey = data.AccessKey; - - CacheData(); - } - } - - private async Task UpdateServerRegistration(string wanApiAddress, string localAddress) - { - if (string.IsNullOrWhiteSpace(wanApiAddress)) - { - throw new ArgumentNullException("wanApiAddress"); - } - - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - throw new ArgumentNullException("ConnectServerId"); - } - - var url = "Servers"; - url = GetConnectUrl(url); - url += "?id=" + ConnectServerId; - - var postData = new Dictionary<string, string> - { - {"name", _appHost.FriendlyName}, - {"url", wanApiAddress}, - {"systemId", _appHost.SystemId} - }; - - if (!string.IsNullOrWhiteSpace(localAddress)) - { - postData["localAddress"] = localAddress; - } - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - options.SetPostData(postData); - - SetServerAccessToken(options); - SetApplicationHeader(options); - - // No need to examine the response - using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) - { - } - } - - private readonly object _dataFileLock = new object(); - private string CacheFilePath - { - get { return Path.Combine(_appPaths.DataPath, "connect.txt"); } - } - - private void CacheData() - { - var path = CacheFilePath; - - try - { - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - - var json = _json.SerializeToString(_data); - - var encrypted = _encryption.EncryptString(json); - - lock (_dataFileLock) - { - _fileSystem.WriteAllText(path, encrypted, Encoding.UTF8); - } - } - catch (Exception ex) - { - _logger.ErrorException("Error saving data", ex); - } - } - - private void LoadCachedData() - { - var path = CacheFilePath; - - _logger.Info("Loading data from {0}", path); - - try - { - lock (_dataFileLock) - { - var encrypted = _fileSystem.ReadAllText(path, Encoding.UTF8); - - var json = _encryption.DecryptString(encrypted); - - _data = _json.DeserializeFromString<ConnectData>(json); - } - } - catch (IOException) - { - // File isn't there. no biggie - } - catch (Exception ex) - { - _logger.ErrorException("Error loading data", ex); - } - } - - private User GetUser(string id) - { - var user = _userManager.GetUserById(id); - - if (user == null) - { - throw new ArgumentException("User not found."); - } - - return user; - } - - private string GetConnectUrl(string handler) - { - return "https://connect.emby.media/service/" + handler; - } - - public async Task<UserLinkResult> LinkUser(string userId, string connectUsername) - { - if (string.IsNullOrWhiteSpace(userId)) - { - throw new ArgumentNullException("userId"); - } - if (string.IsNullOrWhiteSpace(connectUsername)) - { - throw new ArgumentNullException("connectUsername"); - } - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - await UpdateConnectInfo().ConfigureAwait(false); - } - - await _operationLock.WaitAsync().ConfigureAwait(false); - - try - { - return await LinkUserInternal(userId, connectUsername).ConfigureAwait(false); - } - finally - { - _operationLock.Release(); - } - } - - private async Task<UserLinkResult> LinkUserInternal(string userId, string connectUsername) - { - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - throw new ArgumentNullException("ConnectServerId"); - } - - var connectUser = await GetConnectUser(new ConnectUserQuery - { - NameOrEmail = connectUsername - - }, CancellationToken.None).ConfigureAwait(false); - - if (!connectUser.IsActive) - { - throw new ArgumentException("The Emby account has been disabled."); - } - - var existingUser = _userManager.Users.FirstOrDefault(i => string.Equals(i.ConnectUserId, connectUser.Id) && !string.IsNullOrWhiteSpace(i.ConnectAccessKey)); - if (existingUser != null) - { - throw new InvalidOperationException("This connect user is already linked to local user " + existingUser.Name); - } - - var user = GetUser(userId); - - if (!string.IsNullOrWhiteSpace(user.ConnectUserId)) - { - await RemoveConnect(user, user.ConnectUserId).ConfigureAwait(false); - } - - var url = GetConnectUrl("ServerAuthorizations"); - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - var accessToken = Guid.NewGuid().ToString("N"); - - var postData = new Dictionary<string, string> - { - {"serverId", ConnectServerId}, - {"userId", connectUser.Id}, - {"userType", "Linked"}, - {"accessToken", accessToken} - }; - - options.SetPostData(postData); - - SetServerAccessToken(options); - SetApplicationHeader(options); - - var result = new UserLinkResult(); - - // No need to examine the response - using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) - { - var response = _json.DeserializeFromStream<ServerUserAuthorizationResponse>(stream); - - result.IsPending = string.Equals(response.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase); - } - - user.ConnectAccessKey = accessToken; - user.ConnectUserName = connectUser.Name; - user.ConnectUserId = connectUser.Id; - user.ConnectLinkType = UserLinkType.LinkedUser; - - await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - - await _userManager.UpdateConfiguration(user.Id.ToString("N"), user.Configuration); - - await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); - - return result; - } - - public async Task<UserLinkResult> InviteUser(ConnectAuthorizationRequest request) - { - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - await UpdateConnectInfo().ConfigureAwait(false); - } - - await _operationLock.WaitAsync().ConfigureAwait(false); - - try - { - return await InviteUserInternal(request).ConfigureAwait(false); - } - finally - { - _operationLock.Release(); - } - } - - private async Task<UserLinkResult> InviteUserInternal(ConnectAuthorizationRequest request) - { - var connectUsername = request.ConnectUserName; - var sendingUserId = request.SendingUserId; - - if (string.IsNullOrWhiteSpace(connectUsername)) - { - throw new ArgumentNullException("connectUsername"); - } - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - throw new ArgumentNullException("ConnectServerId"); - } - - var sendingUser = GetUser(sendingUserId); - var requesterUserName = sendingUser.ConnectUserName; - - if (string.IsNullOrWhiteSpace(requesterUserName)) - { - throw new ArgumentException("A Connect account is required in order to send invitations."); - } - - string connectUserId = null; - var result = new UserLinkResult(); - - try - { - var connectUser = await GetConnectUser(new ConnectUserQuery - { - NameOrEmail = connectUsername - - }, CancellationToken.None).ConfigureAwait(false); - - if (!connectUser.IsActive) - { - throw new ArgumentException("The Emby account is not active. Please ensure the account has been activated by following the instructions within the email confirmation."); - } - - connectUserId = connectUser.Id; - result.GuestDisplayName = connectUser.Name; - } - catch (HttpException ex) - { - if (!ex.StatusCode.HasValue) - { - throw; - } - - // If they entered a username, then whatever the error is just throw it, for example, user not found - if (!Validator.EmailIsValid(connectUsername)) - { - if (ex.StatusCode.Value == HttpStatusCode.NotFound) - { - throw new ResourceNotFoundException(); - } - throw; - } - - if (ex.StatusCode.Value != HttpStatusCode.NotFound) - { - throw; - } - } - - if (string.IsNullOrWhiteSpace(connectUserId)) - { - return await SendNewUserInvitation(requesterUserName, connectUsername).ConfigureAwait(false); - } - - var url = GetConnectUrl("ServerAuthorizations"); - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - var accessToken = Guid.NewGuid().ToString("N"); - - var postData = new Dictionary<string, string> - { - {"serverId", ConnectServerId}, - {"userId", connectUserId}, - {"userType", "Guest"}, - {"accessToken", accessToken}, - {"requesterUserName", requesterUserName} - }; - - options.SetPostData(postData); - - SetServerAccessToken(options); - SetApplicationHeader(options); - - // No need to examine the response - using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) - { - var response = _json.DeserializeFromStream<ServerUserAuthorizationResponse>(stream); - - result.IsPending = string.Equals(response.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase); - - _data.PendingAuthorizations.Add(new ConnectAuthorizationInternal - { - ConnectUserId = response.UserId, - Id = response.Id, - ImageUrl = response.UserImageUrl, - UserName = response.UserName, - EnabledLibraries = request.EnabledLibraries, - EnabledChannels = request.EnabledChannels, - EnableLiveTv = request.EnableLiveTv, - AccessToken = accessToken - }); - - CacheData(); - } - - await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); - - return result; - } - - private async Task<UserLinkResult> SendNewUserInvitation(string fromName, string email) - { - var url = GetConnectUrl("users/invite"); - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - var postData = new Dictionary<string, string> - { - {"email", email}, - {"requesterUserName", fromName} - }; - - options.SetPostData(postData); - SetApplicationHeader(options); - - // No need to examine the response - using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) - { - } - - return new UserLinkResult - { - IsNewUserInvitation = true, - GuestDisplayName = email - }; - } - - public Task RemoveConnect(string userId) - { - var user = GetUser(userId); - - return RemoveConnect(user, user.ConnectUserId); - } - - private async Task RemoveConnect(User user, string connectUserId) - { - if (!string.IsNullOrWhiteSpace(connectUserId)) - { - await CancelAuthorizationByConnectUserId(connectUserId).ConfigureAwait(false); - } - - user.ConnectAccessKey = null; - user.ConnectUserName = null; - user.ConnectUserId = null; - user.ConnectLinkType = null; - - await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - } - - private async Task<ConnectUser> GetConnectUser(ConnectUserQuery query, CancellationToken cancellationToken) - { - var url = GetConnectUrl("user"); - - if (!string.IsNullOrWhiteSpace(query.Id)) - { - url = url + "?id=" + WebUtility.UrlEncode(query.Id); - } - else if (!string.IsNullOrWhiteSpace(query.NameOrEmail)) - { - url = url + "?nameOrEmail=" + WebUtility.UrlEncode(query.NameOrEmail); - } - else if (!string.IsNullOrWhiteSpace(query.Name)) - { - url = url + "?name=" + WebUtility.UrlEncode(query.Name); - } - else if (!string.IsNullOrWhiteSpace(query.Email)) - { - url = url + "?name=" + WebUtility.UrlEncode(query.Email); - } - else - { - throw new ArgumentException("Empty ConnectUserQuery supplied"); - } - - var options = new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = url, - BufferContent = false - }; - - SetServerAccessToken(options); - SetApplicationHeader(options); - - using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) - { - var response = _json.DeserializeFromStream<GetConnectUserResponse>(stream); - - return new ConnectUser - { - Email = response.Email, - Id = response.Id, - Name = response.Name, - IsActive = response.IsActive, - ImageUrl = response.ImageUrl - }; - } - } - - private void SetApplicationHeader(HttpRequestOptions options) - { - options.RequestHeaders.Add("X-Application", XApplicationValue); - } - - private void SetServerAccessToken(HttpRequestOptions options) - { - if (string.IsNullOrWhiteSpace(ConnectAccessKey)) - { - throw new ArgumentNullException("ConnectAccessKey"); - } - - options.RequestHeaders.Add("X-Connect-Token", ConnectAccessKey); - } - - public async Task RefreshAuthorizations(CancellationToken cancellationToken) - { - await _operationLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - await RefreshAuthorizationsInternal(true, cancellationToken).ConfigureAwait(false); - } - finally - { - _operationLock.Release(); - } - } - - private async Task RefreshAuthorizationsInternal(bool refreshImages, CancellationToken cancellationToken) - { - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - throw new ArgumentNullException("ConnectServerId"); - } - - var url = GetConnectUrl("ServerAuthorizations"); - - url += "?serverId=" + ConnectServerId; - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - BufferContent = false - }; - - SetServerAccessToken(options); - SetApplicationHeader(options); - - try - { - using (var stream = (await _httpClient.SendAsync(options, "GET").ConfigureAwait(false)).Content) - { - var list = _json.DeserializeFromStream<List<ServerUserAuthorizationResponse>>(stream); - - await RefreshAuthorizations(list, refreshImages).ConfigureAwait(false); - } - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing server authorizations.", ex); - } - } - - private readonly SemaphoreSlim _connectImageSemaphore = new SemaphoreSlim(5, 5); - private async Task RefreshAuthorizations(List<ServerUserAuthorizationResponse> list, bool refreshImages) - { - var users = _userManager.Users.ToList(); - - // Handle existing authorizations that were removed by the Connect server - // Handle existing authorizations whose status may have been updated - foreach (var user in users) - { - if (!string.IsNullOrWhiteSpace(user.ConnectUserId)) - { - var connectEntry = list.FirstOrDefault(i => string.Equals(i.UserId, user.ConnectUserId, StringComparison.OrdinalIgnoreCase)); - - if (connectEntry == null) - { - var deleteUser = user.ConnectLinkType.HasValue && - user.ConnectLinkType.Value == UserLinkType.Guest; - - user.ConnectUserId = null; - user.ConnectAccessKey = null; - user.ConnectUserName = null; - user.ConnectLinkType = null; - - await _userManager.UpdateUser(user).ConfigureAwait(false); - - if (deleteUser) - { - _logger.Debug("Deleting guest user {0}", user.Name); - await _userManager.DeleteUser(user).ConfigureAwait(false); - } - } - else - { - var changed = !string.Equals(user.ConnectAccessKey, connectEntry.AccessToken, StringComparison.OrdinalIgnoreCase); - - if (changed) - { - user.ConnectUserId = connectEntry.UserId; - user.ConnectAccessKey = connectEntry.AccessToken; - - await _userManager.UpdateUser(user).ConfigureAwait(false); - } - } - } - } - - var currentPendingList = _data.PendingAuthorizations.ToList(); - var newPendingList = new List<ConnectAuthorizationInternal>(); - - foreach (var connectEntry in list) - { - if (string.Equals(connectEntry.UserType, "guest", StringComparison.OrdinalIgnoreCase)) - { - var currentPendingEntry = currentPendingList.FirstOrDefault(i => string.Equals(i.Id, connectEntry.Id, StringComparison.OrdinalIgnoreCase)); - - if (string.Equals(connectEntry.AcceptStatus, "accepted", StringComparison.OrdinalIgnoreCase)) - { - var user = _userManager.Users - .FirstOrDefault(i => string.Equals(i.ConnectUserId, connectEntry.UserId, StringComparison.OrdinalIgnoreCase)); - - if (user == null) - { - // Add user - user = await _userManager.CreateUser(_userManager.MakeValidUsername(connectEntry.UserName)).ConfigureAwait(false); - - user.ConnectUserName = connectEntry.UserName; - user.ConnectUserId = connectEntry.UserId; - user.ConnectLinkType = UserLinkType.Guest; - user.ConnectAccessKey = connectEntry.AccessToken; - - await _userManager.UpdateUser(user).ConfigureAwait(false); - - user.Policy.IsHidden = true; - user.Policy.EnableLiveTvManagement = false; - user.Policy.EnableContentDeletion = false; - user.Policy.EnableRemoteControlOfOtherUsers = false; - user.Policy.EnableSharedDeviceControl = false; - user.Policy.IsAdministrator = false; - - if (currentPendingEntry != null) - { - user.Policy.EnabledFolders = currentPendingEntry.EnabledLibraries; - user.Policy.EnableAllFolders = false; - - user.Policy.EnabledChannels = currentPendingEntry.EnabledChannels; - user.Policy.EnableAllChannels = false; - - user.Policy.EnableLiveTvAccess = currentPendingEntry.EnableLiveTv; - } - - await _userManager.UpdateConfiguration(user.Id.ToString("N"), user.Configuration); - } - } - else if (string.Equals(connectEntry.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase)) - { - currentPendingEntry = currentPendingEntry ?? new ConnectAuthorizationInternal(); - - currentPendingEntry.ConnectUserId = connectEntry.UserId; - currentPendingEntry.ImageUrl = connectEntry.UserImageUrl; - currentPendingEntry.UserName = connectEntry.UserName; - currentPendingEntry.Id = connectEntry.Id; - currentPendingEntry.AccessToken = connectEntry.AccessToken; - - newPendingList.Add(currentPendingEntry); - } - } - } - - _data.PendingAuthorizations = newPendingList; - CacheData(); - - await RefreshGuestNames(list, refreshImages).ConfigureAwait(false); - } - - private async Task RefreshGuestNames(List<ServerUserAuthorizationResponse> list, bool refreshImages) - { - var users = _userManager.Users - .Where(i => !string.IsNullOrEmpty(i.ConnectUserId) && i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.Guest) - .ToList(); - - foreach (var user in users) - { - var authorization = list.FirstOrDefault(i => string.Equals(i.UserId, user.ConnectUserId, StringComparison.Ordinal)); - - if (authorization == null) - { - _logger.Warn("Unable to find connect authorization record for user {0}", user.Name); - continue; - } - - var syncConnectName = true; - var syncConnectImage = true; - - if (syncConnectName) - { - var changed = !string.Equals(authorization.UserName, user.Name, StringComparison.OrdinalIgnoreCase); - - if (changed) - { - await user.Rename(authorization.UserName).ConfigureAwait(false); - } - } - - if (syncConnectImage) - { - var imageUrl = authorization.UserImageUrl; - - if (!string.IsNullOrWhiteSpace(imageUrl)) - { - var changed = false; - - if (!user.HasImage(ImageType.Primary)) - { - changed = true; - } - else if (refreshImages) - { - using (var response = await _httpClient.SendAsync(new HttpRequestOptions - { - Url = imageUrl, - BufferContent = false - - }, "HEAD").ConfigureAwait(false)) - { - var length = response.ContentLength; - - if (length != _fileSystem.GetFileInfo(user.GetImageInfo(ImageType.Primary, 0).Path).Length) - { - changed = true; - } - } - } - - if (changed) - { - await _providerManager.SaveImage(user, imageUrl, _connectImageSemaphore, ImageType.Primary, null, CancellationToken.None).ConfigureAwait(false); - - await user.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) - { - ForceSave = true, - - }, CancellationToken.None).ConfigureAwait(false); - } - } - } - } - } - - public async Task<List<ConnectAuthorization>> GetPendingGuests() - { - var time = DateTime.UtcNow - _data.LastAuthorizationsRefresh; - - if (time.TotalMinutes >= 5) - { - await _operationLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); - - try - { - await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); - - _data.LastAuthorizationsRefresh = DateTime.UtcNow; - CacheData(); - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing authorization", ex); - } - finally - { - _operationLock.Release(); - } - } - - return _data.PendingAuthorizations.Select(i => new ConnectAuthorization - { - ConnectUserId = i.ConnectUserId, - EnableLiveTv = i.EnableLiveTv, - EnabledChannels = i.EnabledChannels, - EnabledLibraries = i.EnabledLibraries, - Id = i.Id, - ImageUrl = i.ImageUrl, - UserName = i.UserName - - }).ToList(); - } - - public async Task CancelAuthorization(string id) - { - await _operationLock.WaitAsync().ConfigureAwait(false); - - try - { - await CancelAuthorizationInternal(id).ConfigureAwait(false); - } - finally - { - _operationLock.Release(); - } - } - - private async Task CancelAuthorizationInternal(string id) - { - var connectUserId = _data.PendingAuthorizations - .First(i => string.Equals(i.Id, id, StringComparison.Ordinal)) - .ConnectUserId; - - await CancelAuthorizationByConnectUserId(connectUserId).ConfigureAwait(false); - - await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); - } - - private async Task CancelAuthorizationByConnectUserId(string connectUserId) - { - if (string.IsNullOrWhiteSpace(connectUserId)) - { - throw new ArgumentNullException("connectUserId"); - } - if (string.IsNullOrWhiteSpace(ConnectServerId)) - { - throw new ArgumentNullException("ConnectServerId"); - } - - var url = GetConnectUrl("ServerAuthorizations"); - - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false - }; - - var postData = new Dictionary<string, string> - { - {"serverId", ConnectServerId}, - {"userId", connectUserId} - }; - - options.SetPostData(postData); - - SetServerAccessToken(options); - SetApplicationHeader(options); - - try - { - // No need to examine the response - using (var stream = (await _httpClient.SendAsync(options, "DELETE").ConfigureAwait(false)).Content) - { - } - } - catch (HttpException ex) - { - // If connect says the auth doesn't exist, we can handle that gracefully since this is a remove operation - - if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound) - { - throw; - } - - _logger.Debug("Connect returned a 404 when removing a user auth link. Handling it."); - } - } - - public async Task Authenticate(string username, string passwordMd5) - { - if (string.IsNullOrWhiteSpace(username)) - { - throw new ArgumentNullException("username"); - } - - if (string.IsNullOrWhiteSpace(passwordMd5)) - { - throw new ArgumentNullException("passwordMd5"); - } - - var options = new HttpRequestOptions - { - Url = GetConnectUrl("user/authenticate"), - BufferContent = false - }; - - options.SetPostData(new Dictionary<string, string> - { - {"userName",username}, - {"password",passwordMd5} - }); - - SetApplicationHeader(options); - - // No need to examine the response - using (var response = (await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)).Content) - { - } - } - - public async Task<User> GetLocalUser(string connectUserId) - { - var user = _userManager.Users - .FirstOrDefault(i => string.Equals(i.ConnectUserId, connectUserId, StringComparison.OrdinalIgnoreCase)); - - if (user == null) - { - await RefreshAuthorizations(CancellationToken.None).ConfigureAwait(false); - } - - return _userManager.Users - .FirstOrDefault(i => string.Equals(i.ConnectUserId, connectUserId, StringComparison.OrdinalIgnoreCase)); - } - - public User GetUserFromExchangeToken(string token) - { - if (string.IsNullOrWhiteSpace(token)) - { - throw new ArgumentNullException("token"); - } - - return _userManager.Users.FirstOrDefault(u => string.Equals(token, u.ConnectAccessKey, StringComparison.OrdinalIgnoreCase)); - } - - public bool IsAuthorizationTokenValid(string token) - { - if (string.IsNullOrWhiteSpace(token)) - { - throw new ArgumentNullException("token"); - } - - return _userManager.Users.Any(u => string.Equals(token, u.ConnectAccessKey, StringComparison.OrdinalIgnoreCase)) || - _data.PendingAuthorizations.Select(i => i.AccessToken).Contains(token, StringComparer.OrdinalIgnoreCase); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Connect/Responses.cs b/MediaBrowser.Server.Implementations/Connect/Responses.cs deleted file mode 100644 index f865278294..0000000000 --- a/MediaBrowser.Server.Implementations/Connect/Responses.cs +++ /dev/null @@ -1,85 +0,0 @@ -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Connect; - -namespace MediaBrowser.Server.Implementations.Connect -{ - public class ServerRegistrationResponse - { - public string Id { get; set; } - public string Url { get; set; } - public string Name { get; set; } - public string AccessKey { get; set; } - } - - public class UpdateServerRegistrationResponse - { - public string Id { get; set; } - public string Url { get; set; } - public string Name { get; set; } - } - - public class GetConnectUserResponse - { - public string Id { get; set; } - public string Name { get; set; } - public string DisplayName { get; set; } - public string Email { get; set; } - public bool IsActive { get; set; } - public string ImageUrl { get; set; } - } - - public class ServerUserAuthorizationResponse - { - public string Id { get; set; } - public string ServerId { get; set; } - public string UserId { get; set; } - public string AccessToken { get; set; } - public string DateCreated { get; set; } - public bool IsActive { get; set; } - public string AcceptStatus { get; set; } - public string UserType { get; set; } - public string UserImageUrl { get; set; } - public string UserName { get; set; } - } - - public class ConnectUserPreferences - { - public string[] PreferredAudioLanguages { get; set; } - public bool PlayDefaultAudioTrack { get; set; } - public string[] PreferredSubtitleLanguages { get; set; } - public SubtitlePlaybackMode SubtitleMode { get; set; } - public bool GroupMoviesIntoBoxSets { get; set; } - - public ConnectUserPreferences() - { - PreferredAudioLanguages = new string[] { }; - PreferredSubtitleLanguages = new string[] { }; - } - - public static ConnectUserPreferences FromUserConfiguration(UserConfiguration config) - { - return new ConnectUserPreferences - { - PlayDefaultAudioTrack = config.PlayDefaultAudioTrack, - SubtitleMode = config.SubtitleMode, - PreferredAudioLanguages = string.IsNullOrWhiteSpace(config.AudioLanguagePreference) ? new string[] { } : new[] { config.AudioLanguagePreference }, - PreferredSubtitleLanguages = string.IsNullOrWhiteSpace(config.SubtitleLanguagePreference) ? new string[] { } : new[] { config.SubtitleLanguagePreference } - }; - } - - public void MergeInto(UserConfiguration config) - { - - } - } - - public class UserPreferencesDto<T> - { - public T data { get; set; } - } - - public class ConnectAuthorizationInternal : ConnectAuthorization - { - public string AccessToken { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/Connect/Validator.cs b/MediaBrowser.Server.Implementations/Connect/Validator.cs deleted file mode 100644 index 8cdfc4a6b3..0000000000 --- a/MediaBrowser.Server.Implementations/Connect/Validator.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Text.RegularExpressions; - -namespace MediaBrowser.Server.Implementations.Connect -{ - public static class Validator - { - static readonly Regex ValidEmailRegex = CreateValidEmailRegex(); - - /// <summary> - /// Taken from http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx - /// </summary> - /// <returns></returns> - private static Regex CreateValidEmailRegex() - { - const string validEmailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|" - + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)" - + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$"; - - return new Regex(validEmailPattern, RegexOptions.IgnoreCase); - } - - internal static bool EmailIsValid(string emailAddress) - { - bool isValid = ValidEmailRegex.IsMatch(emailAddress); - - return isValid; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs index 3dfc04c267..979a929ca7 100644 --- a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs +++ b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs @@ -3,11 +3,13 @@ using MediaBrowser.Controller.Entities; using System; using System.IO; using System.Linq; -using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Server.Implementations.Devices { @@ -62,29 +64,4 @@ namespace MediaBrowser.Server.Implementations.Devices get { return true; } } } - - public class CameraUploadsDynamicFolder : IVirtualFolderCreator - { - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - - public CameraUploadsDynamicFolder(IApplicationPaths appPaths, IFileSystem fileSystem) - { - _appPaths = appPaths; - _fileSystem = fileSystem; - } - - public BasePluginFolder GetFolder() - { - var path = Path.Combine(_appPaths.DataPath, "camerauploads"); - - _fileSystem.CreateDirectory(path); - - return new CameraUploadsFolder - { - Path = path - }; - } - } - } diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs deleted file mode 100644 index c3db9140cf..0000000000 --- a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs +++ /dev/null @@ -1,304 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Events; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Devices; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Session; -using MediaBrowser.Model.Users; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Controller.Configuration; - -namespace MediaBrowser.Server.Implementations.Devices -{ - public class DeviceManager : IDeviceManager - { - private readonly IDeviceRepository _repo; - private readonly IUserManager _userManager; - private readonly IFileSystem _fileSystem; - private readonly ILibraryMonitor _libraryMonitor; - private readonly IServerConfigurationManager _config; - private readonly ILogger _logger; - private readonly INetworkManager _network; - - public event EventHandler<GenericEventArgs<CameraImageUploadInfo>> CameraImageUploaded; - - /// <summary> - /// Occurs when [device options updated]. - /// </summary> - public event EventHandler<GenericEventArgs<DeviceInfo>> DeviceOptionsUpdated; - - public DeviceManager(IDeviceRepository repo, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IServerConfigurationManager config, ILogger logger, INetworkManager network) - { - _repo = repo; - _userManager = userManager; - _fileSystem = fileSystem; - _libraryMonitor = libraryMonitor; - _config = config; - _logger = logger; - _network = network; - } - - public async Task<DeviceInfo> RegisterDevice(string reportedId, string name, string appName, string appVersion, string usedByUserId) - { - if (string.IsNullOrWhiteSpace(reportedId)) - { - throw new ArgumentNullException("reportedId"); - } - - var device = GetDevice(reportedId) ?? new DeviceInfo - { - Id = reportedId - }; - - device.ReportedName = name; - device.AppName = appName; - device.AppVersion = appVersion; - - if (!string.IsNullOrWhiteSpace(usedByUserId)) - { - var user = _userManager.GetUserById(usedByUserId); - - device.LastUserId = user.Id.ToString("N"); - device.LastUserName = user.Name; - } - - device.DateLastModified = DateTime.UtcNow; - - await _repo.SaveDevice(device).ConfigureAwait(false); - - return device; - } - - public Task SaveCapabilities(string reportedId, ClientCapabilities capabilities) - { - return _repo.SaveCapabilities(reportedId, capabilities); - } - - public ClientCapabilities GetCapabilities(string reportedId) - { - return _repo.GetCapabilities(reportedId); - } - - public DeviceInfo GetDevice(string id) - { - return _repo.GetDevice(id); - } - - public QueryResult<DeviceInfo> GetDevices(DeviceQuery query) - { - IEnumerable<DeviceInfo> devices = _repo.GetDevices().OrderByDescending(i => i.DateLastModified); - - if (query.SupportsContentUploading.HasValue) - { - var val = query.SupportsContentUploading.Value; - - devices = devices.Where(i => GetCapabilities(i.Id).SupportsContentUploading == val); - } - - if (query.SupportsSync.HasValue) - { - var val = query.SupportsSync.Value; - - devices = devices.Where(i => GetCapabilities(i.Id).SupportsSync == val); - } - - if (query.SupportsPersistentIdentifier.HasValue) - { - var val = query.SupportsPersistentIdentifier.Value; - - devices = devices.Where(i => - { - var caps = GetCapabilities(i.Id); - var deviceVal = caps.SupportsPersistentIdentifier; - return deviceVal == val; - }); - } - - if (!string.IsNullOrWhiteSpace(query.UserId)) - { - devices = devices.Where(i => CanAccessDevice(query.UserId, i.Id)); - } - - var array = devices.ToArray(); - return new QueryResult<DeviceInfo> - { - Items = array, - TotalRecordCount = array.Length - }; - } - - public Task DeleteDevice(string id) - { - return _repo.DeleteDevice(id); - } - - public ContentUploadHistory GetCameraUploadHistory(string deviceId) - { - return _repo.GetCameraUploadHistory(deviceId); - } - - public async Task AcceptCameraUpload(string deviceId, Stream stream, LocalFileInfo file) - { - var device = GetDevice(deviceId); - var path = GetUploadPath(device); - - if (!string.IsNullOrWhiteSpace(file.Album)) - { - path = Path.Combine(path, _fileSystem.GetValidFilename(file.Album)); - } - - path = Path.Combine(path, file.Name); - path = Path.ChangeExtension(path, MimeTypes.ToExtension(file.MimeType) ?? "jpg"); - - _libraryMonitor.ReportFileSystemChangeBeginning(path); - - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - - try - { - using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) - { - await stream.CopyToAsync(fs).ConfigureAwait(false); - } - - _repo.AddCameraUpload(deviceId, file); - } - finally - { - _libraryMonitor.ReportFileSystemChangeComplete(path, true); - } - - if (CameraImageUploaded != null) - { - EventHelper.FireEventIfNotNull(CameraImageUploaded, this, new GenericEventArgs<CameraImageUploadInfo> - { - Argument = new CameraImageUploadInfo - { - Device = device, - FileInfo = file - } - }, _logger); - } - } - - private string GetUploadPath(DeviceInfo device) - { - if (!string.IsNullOrWhiteSpace(device.CameraUploadPath)) - { - return device.CameraUploadPath; - } - - var config = _config.GetUploadOptions(); - if (!string.IsNullOrWhiteSpace(config.CameraUploadPath)) - { - return config.CameraUploadPath; - } - - var path = DefaultCameraUploadsPath; - - if (config.EnableCameraUploadSubfolders) - { - path = Path.Combine(path, _fileSystem.GetValidFilename(device.Name)); - } - - return path; - } - - private string DefaultCameraUploadsPath - { - get { return Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads"); } - } - - public async Task UpdateDeviceInfo(string id, DeviceOptions options) - { - var device = GetDevice(id); - - device.CustomName = options.CustomName; - device.CameraUploadPath = options.CameraUploadPath; - - await _repo.SaveDevice(device).ConfigureAwait(false); - - EventHelper.FireEventIfNotNull(DeviceOptionsUpdated, this, new GenericEventArgs<DeviceInfo>(device), _logger); - } - - public bool CanAccessDevice(string userId, string deviceId) - { - if (string.IsNullOrWhiteSpace(userId)) - { - throw new ArgumentNullException("userId"); - } - if (string.IsNullOrWhiteSpace(deviceId)) - { - throw new ArgumentNullException("deviceId"); - } - - var user = _userManager.GetUserById(userId); - - if (user == null) - { - throw new ArgumentException("user not found"); - } - - if (!CanAccessDevice(user.Policy, deviceId)) - { - var capabilities = GetCapabilities(deviceId); - - if (capabilities != null && capabilities.SupportsPersistentIdentifier) - { - return false; - } - } - - return true; - } - - private bool CanAccessDevice(UserPolicy policy, string id) - { - if (policy.EnableAllDevices) - { - return true; - } - - if (policy.IsAdministrator) - { - return true; - } - - return ListHelper.ContainsIgnoreCase(policy.EnabledDevices, id); - } - } - - public class DevicesConfigStore : IConfigurationFactory - { - public IEnumerable<ConfigurationStore> GetConfigurations() - { - return new List<ConfigurationStore> - { - new ConfigurationStore - { - Key = "devices", - ConfigurationType = typeof(DevicesOptions) - } - }; - } - } - - public static class UploadConfigExtension - { - public static DevicesOptions GetUploadOptions(this IConfigurationManager config) - { - return config.GetConfiguration<DevicesOptions>("devices"); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs b/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs deleted file mode 100644 index 6e67af82b4..0000000000 --- a/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs +++ /dev/null @@ -1,208 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Model.Devices; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Session; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.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(Path.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 (DirectoryNotFoundException) - { - } - - _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(Path.GetDirectoryName(path)); - - lock (_syncLock) - { - ContentUploadHistory history; - - try - { - history = _json.DeserializeFromFile<ContentUploadHistory>(path); - } - catch (IOException) - { - history = new ContentUploadHistory - { - DeviceId = deviceId - }; - } - - history.DeviceId = deviceId; - history.FilesUploaded.Add(file); - - _json.SerializeToFile(history, path); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs deleted file mode 100644 index a0f7aa999e..0000000000 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ /dev/null @@ -1,1607 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Drawing; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Sync; -using MoreLinq; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Dto -{ - public class DtoService : IDtoService - { - private readonly ILogger _logger; - private readonly ILibraryManager _libraryManager; - private readonly IUserDataManager _userDataRepository; - private readonly IItemRepository _itemRepo; - - private readonly IImageProcessor _imageProcessor; - private readonly IServerConfigurationManager _config; - private readonly IFileSystem _fileSystem; - private readonly IProviderManager _providerManager; - - private readonly Func<IChannelManager> _channelManagerFactory; - private readonly ISyncManager _syncManager; - private readonly IApplicationHost _appHost; - private readonly Func<IDeviceManager> _deviceManager; - private readonly Func<IMediaSourceManager> _mediaSourceManager; - private readonly Func<ILiveTvManager> _livetvManager; - - public DtoService(ILogger logger, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager, Func<IChannelManager> channelManagerFactory, ISyncManager syncManager, IApplicationHost appHost, Func<IDeviceManager> deviceManager, Func<IMediaSourceManager> mediaSourceManager, Func<ILiveTvManager> livetvManager) - { - _logger = logger; - _libraryManager = libraryManager; - _userDataRepository = userDataRepository; - _itemRepo = itemRepo; - _imageProcessor = imageProcessor; - _config = config; - _fileSystem = fileSystem; - _providerManager = providerManager; - _channelManagerFactory = channelManagerFactory; - _syncManager = syncManager; - _appHost = appHost; - _deviceManager = deviceManager; - _mediaSourceManager = mediaSourceManager; - _livetvManager = livetvManager; - } - - /// <summary> - /// Converts a BaseItem to a DTOBaseItem - /// </summary> - /// <param name="item">The item.</param> - /// <param name="fields">The fields.</param> - /// <param name="user">The user.</param> - /// <param name="owner">The owner.</param> - /// <returns>Task{DtoBaseItem}.</returns> - /// <exception cref="System.ArgumentNullException">item</exception> - public BaseItemDto GetBaseItemDto(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null) - { - var options = new DtoOptions - { - Fields = fields - }; - - return GetBaseItemDto(item, options, user, owner); - } - - public async Task<List<BaseItemDto>> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null) - { - if (items == null) - { - throw new ArgumentNullException("items"); - } - - if (options == null) - { - throw new ArgumentNullException("options"); - } - - var syncDictionary = GetSyncedItemProgress(options); - - var list = new List<BaseItemDto>(); - var programTuples = new List<Tuple<BaseItem, BaseItemDto>>(); - var channelTuples = new List<Tuple<BaseItemDto, LiveTvChannel>>(); - - foreach (var item in items) - { - var dto = await GetBaseItemDtoInternal(item, options, user, owner).ConfigureAwait(false); - - var tvChannel = item as LiveTvChannel; - if (tvChannel != null) - { - channelTuples.Add(new Tuple<BaseItemDto, LiveTvChannel>(dto, tvChannel)); - } - else if (item is LiveTvProgram) - { - programTuples.Add(new Tuple<BaseItem, BaseItemDto>(item, dto)); - } - - var byName = item as IItemByName; - - if (byName != null) - { - if (options.Fields.Contains(ItemFields.ItemCounts)) - { - var libraryItems = byName.GetTaggedItems(new InternalItemsQuery(user) - { - Recursive = true - }); - - SetItemByNameInfo(item, dto, libraryItems.ToList(), user); - } - } - - FillSyncInfo(dto, item, options, user, syncDictionary); - - list.Add(dto); - } - - if (programTuples.Count > 0) - { - await _livetvManager().AddInfoToProgramDto(programTuples, options.Fields, user).ConfigureAwait(false); - } - - if (channelTuples.Count > 0) - { - _livetvManager().AddChannelInfo(channelTuples, options, user); - } - - return list; - } - - public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null) - { - var syncDictionary = GetSyncedItemProgress(options); - - var dto = GetBaseItemDtoInternal(item, options, user, owner).Result; - var tvChannel = item as LiveTvChannel; - if (tvChannel != null) - { - var list = new List<Tuple<BaseItemDto, LiveTvChannel>> { new Tuple<BaseItemDto, LiveTvChannel>(dto, tvChannel) }; - _livetvManager().AddChannelInfo(list, options, user); - } - else if (item is LiveTvProgram) - { - var list = new List<Tuple<BaseItem, BaseItemDto>> { new Tuple<BaseItem, BaseItemDto>(item, dto) }; - var task = _livetvManager().AddInfoToProgramDto(list, options.Fields, user); - Task.WaitAll(task); - } - - var byName = item as IItemByName; - - if (byName != null) - { - if (options.Fields.Contains(ItemFields.ItemCounts)) - { - SetItemByNameInfo(item, dto, GetTaggedItems(byName, user), user); - } - - FillSyncInfo(dto, item, options, user, syncDictionary); - return dto; - } - - FillSyncInfo(dto, item, options, user, syncDictionary); - - return dto; - } - - private List<BaseItem> GetTaggedItems(IItemByName byName, User user) - { - var items = byName.GetTaggedItems(new InternalItemsQuery(user) - { - Recursive = true - - }).ToList(); - - return items; - } - - public Dictionary<string, SyncedItemProgress> GetSyncedItemProgress(DtoOptions options) - { - if (!options.Fields.Contains(ItemFields.BasicSyncInfo) && - !options.Fields.Contains(ItemFields.SyncInfo)) - { - return new Dictionary<string, SyncedItemProgress>(); - } - - var deviceId = options.DeviceId; - if (string.IsNullOrWhiteSpace(deviceId)) - { - return new Dictionary<string, SyncedItemProgress>(); - } - - var caps = _deviceManager().GetCapabilities(deviceId); - if (caps == null || !caps.SupportsSync) - { - return new Dictionary<string, SyncedItemProgress>(); - } - - return _syncManager.GetSyncedItemProgresses(new SyncJobItemQuery - { - TargetId = deviceId, - Statuses = new[] - { - SyncJobItemStatus.Converting, - SyncJobItemStatus.Queued, - SyncJobItemStatus.Transferring, - SyncJobItemStatus.ReadyToTransfer, - SyncJobItemStatus.Synced - } - }); - } - - public void FillSyncInfo(IEnumerable<Tuple<BaseItem, BaseItemDto>> tuples, DtoOptions options, User user) - { - if (options.Fields.Contains(ItemFields.BasicSyncInfo) || - options.Fields.Contains(ItemFields.SyncInfo)) - { - var syncProgress = GetSyncedItemProgress(options); - - foreach (var tuple in tuples) - { - var item = tuple.Item1; - - FillSyncInfo(tuple.Item2, item, options, user, syncProgress); - } - } - } - - private void FillSyncInfo(IHasSyncInfo dto, BaseItem item, DtoOptions options, User user, Dictionary<string, SyncedItemProgress> syncProgress) - { - var hasFullSyncInfo = options.Fields.Contains(ItemFields.SyncInfo); - - if (!options.Fields.Contains(ItemFields.BasicSyncInfo) && - !hasFullSyncInfo) - { - return; - } - - if (dto.SupportsSync ?? false) - { - SyncedItemProgress syncStatus; - if (syncProgress.TryGetValue(dto.Id, out syncStatus)) - { - if (syncStatus.Status == SyncJobItemStatus.Synced) - { - dto.SyncPercent = 100; - } - else - { - dto.SyncPercent = syncStatus.Progress; - } - - if (hasFullSyncInfo) - { - dto.HasSyncJob = true; - dto.SyncStatus = syncStatus.Status; - } - } - } - } - - private async Task<BaseItemDto> GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null) - { - var fields = options.Fields; - - if (item == null) - { - throw new ArgumentNullException("item"); - } - - if (fields == null) - { - throw new ArgumentNullException("fields"); - } - - var dto = new BaseItemDto - { - ServerId = _appHost.SystemId - }; - - if (item.SourceType == SourceType.Channel) - { - dto.SourceType = item.SourceType.ToString(); - } - - if (fields.Contains(ItemFields.People)) - { - AttachPeople(dto, item); - } - - if (fields.Contains(ItemFields.PrimaryImageAspectRatio)) - { - try - { - AttachPrimaryImageAspectRatio(dto, item); - } - catch (Exception ex) - { - // Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions - _logger.ErrorException("Error generating PrimaryImageAspectRatio for {0}", ex, item.Name); - } - } - - if (fields.Contains(ItemFields.DisplayPreferencesId)) - { - dto.DisplayPreferencesId = item.DisplayPreferencesId.ToString("N"); - } - - if (user != null) - { - await AttachUserSpecificInfo(dto, item, user, options).ConfigureAwait(false); - } - - var hasMediaSources = item as IHasMediaSources; - if (hasMediaSources != null) - { - if (fields.Contains(ItemFields.MediaSources)) - { - if (user == null) - { - dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true).ToList(); - } - else - { - dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user).ToList(); - } - } - } - - if (fields.Contains(ItemFields.Studios)) - { - AttachStudios(dto, item); - } - - AttachBasicFields(dto, item, owner, options); - - var collectionFolder = item as ICollectionFolder; - if (collectionFolder != null) - { - dto.OriginalCollectionType = collectionFolder.CollectionType; - - dto.CollectionType = user == null ? - collectionFolder.CollectionType : - collectionFolder.GetViewType(user); - } - - if (fields.Contains(ItemFields.CanDelete)) - { - dto.CanDelete = user == null - ? item.CanDelete() - : item.CanDelete(user); - } - - if (fields.Contains(ItemFields.CanDownload)) - { - dto.CanDownload = user == null - ? item.CanDownload() - : item.CanDownload(user); - } - - if (fields.Contains(ItemFields.Etag)) - { - dto.Etag = item.GetEtag(user); - } - - if (item is ILiveTvRecording) - { - _livetvManager().AddInfoToRecordingDto(item, dto, user); - } - - return dto; - } - - public BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, Dictionary<string, SyncedItemProgress> syncProgress, User user = null) - { - var dto = GetBaseItemDtoInternal(item, options, user).Result; - - if (taggedItems != null && options.Fields.Contains(ItemFields.ItemCounts)) - { - SetItemByNameInfo(item, dto, taggedItems, user); - } - - FillSyncInfo(dto, item, options, user, syncProgress); - - return dto; - } - - private void SetItemByNameInfo(BaseItem item, BaseItemDto dto, List<BaseItem> taggedItems, User user = null) - { - if (item is MusicArtist) - { - dto.AlbumCount = taggedItems.Count(i => i is MusicAlbum); - dto.MusicVideoCount = taggedItems.Count(i => i is MusicVideo); - dto.SongCount = taggedItems.Count(i => i is Audio); - } - else if (item is MusicGenre) - { - dto.ArtistCount = taggedItems.Count(i => i is MusicArtist); - dto.AlbumCount = taggedItems.Count(i => i is MusicAlbum); - dto.MusicVideoCount = taggedItems.Count(i => i is MusicVideo); - dto.SongCount = taggedItems.Count(i => i is Audio); - } - else if (item is GameGenre) - { - dto.GameCount = taggedItems.Count(i => i is Game); - } - else - { - // This populates them all and covers Genre, Person, Studio, Year - - dto.ArtistCount = taggedItems.Count(i => i is MusicArtist); - dto.AlbumCount = taggedItems.Count(i => i is MusicAlbum); - dto.EpisodeCount = taggedItems.Count(i => i is Episode); - dto.GameCount = taggedItems.Count(i => i is Game); - dto.MovieCount = taggedItems.Count(i => i is Movie); - dto.TrailerCount = taggedItems.Count(i => i is Trailer); - dto.MusicVideoCount = taggedItems.Count(i => i is MusicVideo); - dto.SeriesCount = taggedItems.Count(i => i is Series); - dto.ProgramCount = taggedItems.Count(i => i is LiveTvProgram); - dto.SongCount = taggedItems.Count(i => i is Audio); - } - - dto.ChildCount = taggedItems.Count; - } - - /// <summary> - /// Attaches the user specific info. - /// </summary> - private async Task AttachUserSpecificInfo(BaseItemDto dto, BaseItem item, User user, DtoOptions dtoOptions) - { - var fields = dtoOptions.Fields; - - if (item.IsFolder) - { - var folder = (Folder)item; - - if (dtoOptions.EnableUserData) - { - dto.UserData = await _userDataRepository.GetUserDataDto(item, dto, user).ConfigureAwait(false); - } - - if (!dto.ChildCount.HasValue && item.SourceType == SourceType.Library) - { - dto.ChildCount = GetChildCount(folder, user); - } - - if (fields.Contains(ItemFields.CumulativeRunTimeTicks)) - { - dto.CumulativeRunTimeTicks = item.RunTimeTicks; - } - - if (fields.Contains(ItemFields.DateLastMediaAdded)) - { - dto.DateLastMediaAdded = folder.DateLastMediaAdded; - } - } - - else - { - if (dtoOptions.EnableUserData) - { - dto.UserData = _userDataRepository.GetUserDataDto(item, user).Result; - } - } - - dto.PlayAccess = item.GetPlayAccess(user); - - if (fields.Contains(ItemFields.BasicSyncInfo) || fields.Contains(ItemFields.SyncInfo)) - { - var userCanSync = user != null && user.Policy.EnableSync; - if (userCanSync && _syncManager.SupportsSync(item)) - { - dto.SupportsSync = true; - } - } - - if (fields.Contains(ItemFields.SeasonUserData)) - { - var episode = item as Episode; - - if (episode != null) - { - var season = episode.Season; - - if (season != null) - { - dto.SeasonUserData = await _userDataRepository.GetUserDataDto(season, user).ConfigureAwait(false); - } - } - } - - var userView = item as UserView; - if (userView != null) - { - dto.HasDynamicCategories = userView.ContainsDynamicCategories(user); - } - - var collectionFolder = item as ICollectionFolder; - if (collectionFolder != null) - { - dto.HasDynamicCategories = false; - } - } - - private int GetChildCount(Folder folder, User user) - { - // Right now this is too slow to calculate for top level folders on a per-user basis - // Just return something so that apps that are expecting a value won't think the folders are empty - if (folder is ICollectionFolder || folder is UserView) - { - return new Random().Next(1, 10); - } - - return folder.GetChildCount(user); - } - - /// <summary> - /// Gets client-side Id of a server-side BaseItem - /// </summary> - /// <param name="item">The item.</param> - /// <returns>System.String.</returns> - /// <exception cref="System.ArgumentNullException">item</exception> - public string GetDtoId(BaseItem item) - { - if (item == null) - { - throw new ArgumentNullException("item"); - } - - return item.Id.ToString("N"); - } - - /// <summary> - /// Converts a UserItemData to a DTOUserItemData - /// </summary> - /// <param name="data">The data.</param> - /// <returns>DtoUserItemData.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public UserItemDataDto GetUserItemDataDto(UserItemData data) - { - if (data == null) - { - throw new ArgumentNullException("data"); - } - - return new UserItemDataDto - { - IsFavorite = data.IsFavorite, - Likes = data.Likes, - PlaybackPositionTicks = data.PlaybackPositionTicks, - PlayCount = data.PlayCount, - Rating = data.Rating, - Played = data.Played, - LastPlayedDate = data.LastPlayedDate, - Key = data.Key - }; - } - private void SetBookProperties(BaseItemDto dto, Book item) - { - dto.SeriesName = item.SeriesName; - } - private void SetPhotoProperties(BaseItemDto dto, Photo item) - { - dto.Width = item.Width; - dto.Height = item.Height; - dto.CameraMake = item.CameraMake; - dto.CameraModel = item.CameraModel; - dto.Software = item.Software; - dto.ExposureTime = item.ExposureTime; - dto.FocalLength = item.FocalLength; - dto.ImageOrientation = item.Orientation; - dto.Aperture = item.Aperture; - dto.ShutterSpeed = item.ShutterSpeed; - - dto.Latitude = item.Latitude; - dto.Longitude = item.Longitude; - dto.Altitude = item.Altitude; - dto.IsoSpeedRating = item.IsoSpeedRating; - - var album = item.AlbumEntity; - - if (album != null) - { - dto.Album = album.Name; - dto.AlbumId = album.Id.ToString("N"); - } - } - - private void SetMusicVideoProperties(BaseItemDto dto, MusicVideo item) - { - if (!string.IsNullOrEmpty(item.Album)) - { - var parentAlbum = _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(MusicAlbum).Name }, - Name = item.Album - - }).FirstOrDefault(); - - if (parentAlbum != null) - { - dto.AlbumId = GetDtoId(parentAlbum); - } - } - - dto.Album = item.Album; - } - - private void SetGameProperties(BaseItemDto dto, Game item) - { - dto.Players = item.PlayersSupported; - dto.GameSystem = item.GameSystem; - dto.MultiPartGameFiles = item.MultiPartGameFiles; - } - - private void SetGameSystemProperties(BaseItemDto dto, GameSystem item) - { - dto.GameSystem = item.GameSystemName; - } - - private List<string> GetImageTags(BaseItem item, List<ItemImageInfo> images) - { - return images - .Select(p => GetImageCacheTag(item, p)) - .Where(i => i != null) - .ToList(); - } - - private string GetImageCacheTag(BaseItem item, ImageType type) - { - try - { - return _imageProcessor.GetImageCacheTag(item, type); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting {0} image info", ex, type); - return null; - } - } - - private string GetImageCacheTag(BaseItem item, ItemImageInfo image) - { - try - { - return _imageProcessor.GetImageCacheTag(item, image); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting {0} image info for {1}", ex, image.Type, image.Path); - return null; - } - } - - /// <summary> - /// Attaches People DTO's to a DTOBaseItem - /// </summary> - /// <param name="dto">The dto.</param> - /// <param name="item">The item.</param> - /// <returns>Task.</returns> - private void AttachPeople(BaseItemDto dto, BaseItem item) - { - // Ordering by person type to ensure actors and artists are at the front. - // This is taking advantage of the fact that they both begin with A - // This should be improved in the future - var people = _libraryManager.GetPeople(item).OrderBy(i => i.SortOrder ?? int.MaxValue) - .ThenBy(i => - { - if (i.IsType(PersonType.Actor)) - { - return 0; - } - if (i.IsType(PersonType.GuestStar)) - { - return 1; - } - if (i.IsType(PersonType.Director)) - { - return 2; - } - if (i.IsType(PersonType.Writer)) - { - return 3; - } - if (i.IsType(PersonType.Producer)) - { - return 4; - } - if (i.IsType(PersonType.Composer)) - { - return 4; - } - - return 10; - }) - .ToList(); - - var list = new List<BaseItemPerson>(); - - var dictionary = people.Select(p => p.Name) - .Distinct(StringComparer.OrdinalIgnoreCase).Select(c => - { - try - { - return _libraryManager.GetPerson(c); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting person {0}", ex, c); - return null; - } - - }).Where(i => i != null) - .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase) - .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); - - for (var i = 0; i < people.Count; i++) - { - var person = people[i]; - - var baseItemPerson = new BaseItemPerson - { - Name = person.Name, - Role = person.Role, - Type = person.Type - }; - - Person entity; - - if (dictionary.TryGetValue(person.Name, out entity)) - { - baseItemPerson.PrimaryImageTag = GetImageCacheTag(entity, ImageType.Primary); - baseItemPerson.Id = entity.Id.ToString("N"); - list.Add(baseItemPerson); - } - } - - dto.People = list.ToArray(); - } - - /// <summary> - /// Attaches the studios. - /// </summary> - /// <param name="dto">The dto.</param> - /// <param name="item">The item.</param> - /// <returns>Task.</returns> - private void AttachStudios(BaseItemDto dto, BaseItem item) - { - var studios = item.Studios.ToList(); - - dto.Studios = new StudioDto[studios.Count]; - - var dictionary = studios.Distinct(StringComparer.OrdinalIgnoreCase).Select(name => - { - try - { - return _libraryManager.GetStudio(name); - } - catch (IOException ex) - { - _logger.ErrorException("Error getting studio {0}", ex, name); - return null; - } - }) - .Where(i => i != null) - .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase) - .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); - - for (var i = 0; i < studios.Count; i++) - { - var studio = studios[i]; - - var studioDto = new StudioDto - { - Name = studio - }; - - Studio entity; - - if (dictionary.TryGetValue(studio, out entity)) - { - studioDto.Id = entity.Id.ToString("N"); - studioDto.PrimaryImageTag = GetImageCacheTag(entity, ImageType.Primary); - } - - dto.Studios[i] = studioDto; - } - } - - /// <summary> - /// Gets the chapter info dto. - /// </summary> - /// <param name="chapterInfo">The chapter info.</param> - /// <param name="item">The item.</param> - /// <returns>ChapterInfoDto.</returns> - private ChapterInfoDto GetChapterInfoDto(ChapterInfo chapterInfo, BaseItem item) - { - var dto = new ChapterInfoDto - { - Name = chapterInfo.Name, - StartPositionTicks = chapterInfo.StartPositionTicks - }; - - if (!string.IsNullOrEmpty(chapterInfo.ImagePath)) - { - dto.ImageTag = GetImageCacheTag(item, new ItemImageInfo - { - Path = chapterInfo.ImagePath, - Type = ImageType.Chapter, - DateModified = chapterInfo.ImageDateModified - }); - } - - return dto; - } - - public List<ChapterInfoDto> GetChapterInfoDtos(BaseItem item) - { - return _itemRepo.GetChapters(item.Id) - .Select(c => GetChapterInfoDto(c, item)) - .ToList(); - } - - /// <summary> - /// Sets simple property values on a DTOBaseItem - /// </summary> - /// <param name="dto">The dto.</param> - /// <param name="item">The item.</param> - /// <param name="owner">The owner.</param> - /// <param name="options">The options.</param> - private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, DtoOptions options) - { - var fields = options.Fields; - - if (fields.Contains(ItemFields.DateCreated)) - { - dto.DateCreated = item.DateCreated; - } - - if (fields.Contains(ItemFields.DisplayMediaType)) - { - dto.DisplayMediaType = item.DisplayMediaType; - } - - if (fields.Contains(ItemFields.Settings)) - { - dto.LockedFields = item.LockedFields; - dto.LockData = item.IsLocked; - dto.ForcedSortName = item.ForcedSortName; - } - dto.Container = item.Container; - - var hasBudget = item as IHasBudget; - if (hasBudget != null) - { - if (fields.Contains(ItemFields.Budget)) - { - dto.Budget = hasBudget.Budget; - } - - if (fields.Contains(ItemFields.Revenue)) - { - dto.Revenue = hasBudget.Revenue; - } - } - - dto.EndDate = item.EndDate; - - if (fields.Contains(ItemFields.HomePageUrl)) - { - dto.HomePageUrl = item.HomePageUrl; - } - - if (fields.Contains(ItemFields.ExternalUrls)) - { - dto.ExternalUrls = _providerManager.GetExternalUrls(item).ToArray(); - } - - if (fields.Contains(ItemFields.Tags)) - { - dto.Tags = item.Tags; - } - - if (fields.Contains(ItemFields.Keywords)) - { - dto.Keywords = item.Keywords; - } - - var hasAspectRatio = item as IHasAspectRatio; - if (hasAspectRatio != null) - { - dto.AspectRatio = hasAspectRatio.AspectRatio; - } - - if (fields.Contains(ItemFields.Metascore)) - { - var hasMetascore = item as IHasMetascore; - if (hasMetascore != null) - { - dto.Metascore = hasMetascore.Metascore; - } - } - - if (fields.Contains(ItemFields.AwardSummary)) - { - var hasAwards = item as IHasAwards; - if (hasAwards != null) - { - dto.AwardSummary = hasAwards.AwardSummary; - } - } - - var backdropLimit = options.GetImageLimit(ImageType.Backdrop); - if (backdropLimit > 0) - { - dto.BackdropImageTags = GetImageTags(item, item.GetImages(ImageType.Backdrop).Take(backdropLimit).ToList()); - } - - if (fields.Contains(ItemFields.ScreenshotImageTags)) - { - var screenshotLimit = options.GetImageLimit(ImageType.Screenshot); - if (screenshotLimit > 0) - { - dto.ScreenshotImageTags = GetImageTags(item, item.GetImages(ImageType.Screenshot).Take(screenshotLimit).ToList()); - } - } - - if (fields.Contains(ItemFields.Genres)) - { - dto.Genres = item.Genres; - } - - if (options.EnableImages) - { - dto.ImageTags = new Dictionary<ImageType, string>(); - - // Prevent implicitly captured closure - var currentItem = item; - foreach (var image in currentItem.ImageInfos.Where(i => !currentItem.AllowsMultipleImages(i.Type)) - .ToList()) - { - if (options.GetImageLimit(image.Type) > 0) - { - var tag = GetImageCacheTag(item, image); - - if (tag != null) - { - dto.ImageTags[image.Type] = tag; - } - } - } - } - - dto.Id = GetDtoId(item); - dto.IndexNumber = item.IndexNumber; - dto.ParentIndexNumber = item.ParentIndexNumber; - - if (item.IsFolder) - { - dto.IsFolder = true; - } - else if (item is IHasMediaSources) - { - dto.IsFolder = false; - } - - dto.MediaType = item.MediaType; - dto.LocationType = item.LocationType; - if (item.IsHD.HasValue && item.IsHD.Value) - { - dto.IsHD = item.IsHD; - } - dto.Audio = item.Audio; - - if (fields.Contains(ItemFields.Settings)) - { - dto.PreferredMetadataCountryCode = item.PreferredMetadataCountryCode; - dto.PreferredMetadataLanguage = item.PreferredMetadataLanguage; - } - - dto.CriticRating = item.CriticRating; - - if (fields.Contains(ItemFields.CriticRatingSummary)) - { - dto.CriticRatingSummary = item.CriticRatingSummary; - } - - var hasTrailers = item as IHasTrailers; - if (hasTrailers != null) - { - dto.LocalTrailerCount = hasTrailers.GetTrailerIds().Count; - } - - var hasDisplayOrder = item as IHasDisplayOrder; - if (hasDisplayOrder != null) - { - dto.DisplayOrder = hasDisplayOrder.DisplayOrder; - } - - var userView = item as UserView; - if (userView != null) - { - dto.CollectionType = userView.ViewType; - } - - if (fields.Contains(ItemFields.RemoteTrailers)) - { - dto.RemoteTrailers = hasTrailers != null ? - hasTrailers.RemoteTrailers : - new List<MediaUrl>(); - } - - dto.Name = item.Name; - dto.OfficialRating = item.OfficialRating; - - if (fields.Contains(ItemFields.Overview)) - { - dto.Overview = item.Overview; - } - - if (fields.Contains(ItemFields.OriginalTitle)) - { - dto.OriginalTitle = item.OriginalTitle; - } - - if (fields.Contains(ItemFields.ShortOverview)) - { - dto.ShortOverview = item.ShortOverview; - } - - if (fields.Contains(ItemFields.ParentId)) - { - var displayParentId = item.DisplayParentId; - if (displayParentId.HasValue) - { - dto.ParentId = displayParentId.Value.ToString("N"); - } - } - - AddInheritedImages(dto, item, options, owner); - - if (fields.Contains(ItemFields.Path)) - { - dto.Path = GetMappedPath(item); - } - - dto.PremiereDate = item.PremiereDate; - dto.ProductionYear = item.ProductionYear; - - if (fields.Contains(ItemFields.ProviderIds)) - { - dto.ProviderIds = item.ProviderIds; - } - - dto.RunTimeTicks = item.RunTimeTicks; - - if (fields.Contains(ItemFields.SortName)) - { - dto.SortName = item.SortName; - } - - if (fields.Contains(ItemFields.CustomRating)) - { - dto.CustomRating = item.CustomRating; - } - - if (fields.Contains(ItemFields.Taglines)) - { - if (!string.IsNullOrWhiteSpace(item.Tagline)) - { - dto.Taglines = new List<string> { item.Tagline }; - } - - if (dto.Taglines == null) - { - dto.Taglines = new List<string>(); - } - } - - dto.Type = item.GetClientTypeName(); - dto.CommunityRating = item.CommunityRating; - - if (fields.Contains(ItemFields.VoteCount)) - { - dto.VoteCount = item.VoteCount; - } - - //if (item.IsFolder) - //{ - // var folder = (Folder)item; - - // if (fields.Contains(ItemFields.IndexOptions)) - // { - // dto.IndexOptions = folder.IndexByOptionStrings.ToArray(); - // } - //} - - var supportsPlaceHolders = item as ISupportsPlaceHolders; - if (supportsPlaceHolders != null) - { - dto.IsPlaceHolder = supportsPlaceHolders.IsPlaceHolder; - } - - // Add audio info - var audio = item as Audio; - if (audio != null) - { - dto.Album = audio.Album; - dto.ExtraType = audio.ExtraType; - - var albumParent = audio.AlbumEntity; - - if (albumParent != null) - { - dto.AlbumId = GetDtoId(albumParent); - - dto.AlbumPrimaryImageTag = GetImageCacheTag(albumParent, ImageType.Primary); - } - - //if (fields.Contains(ItemFields.MediaSourceCount)) - //{ - // Songs always have one - //} - } - - var hasArtist = item as IHasArtist; - if (hasArtist != null) - { - dto.Artists = hasArtist.Artists; - - var artistItems = _libraryManager.GetArtists(new InternalItemsQuery - { - EnableTotalRecordCount = false, - ItemIds = new[] { item.Id.ToString("N") } - }); - - dto.ArtistItems = artistItems.Items - .Select(i => - { - var artist = i.Item1; - return new NameIdPair - { - Name = artist.Name, - Id = artist.Id.ToString("N") - }; - }) - .ToList(); - - // Include artists that are not in the database yet, e.g., just added via metadata editor - var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList(); - dto.ArtistItems.AddRange(hasArtist.Artists - .Except(foundArtists, new DistinctNameComparer()) - .Select(i => - { - // This should not be necessary but we're seeing some cases of it - if (string.IsNullOrWhiteSpace(i)) - { - return null; - } - - var artist = _libraryManager.GetArtist(i); - if (artist != null) - { - return new NameIdPair - { - Name = artist.Name, - Id = artist.Id.ToString("N") - }; - } - - return null; - - }).Where(i => i != null)); - } - - var hasAlbumArtist = item as IHasAlbumArtist; - if (hasAlbumArtist != null) - { - dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault(); - - var artistItems = _libraryManager.GetAlbumArtists(new InternalItemsQuery - { - EnableTotalRecordCount = false, - ItemIds = new[] { item.Id.ToString("N") } - }); - - dto.AlbumArtists = artistItems.Items - .Select(i => - { - var artist = i.Item1; - return new NameIdPair - { - Name = artist.Name, - Id = artist.Id.ToString("N") - }; - }) - .ToList(); - } - - // Add video info - var video = item as Video; - if (video != null) - { - dto.VideoType = video.VideoType; - dto.Video3DFormat = video.Video3DFormat; - dto.IsoType = video.IsoType; - - if (video.HasSubtitles) - { - dto.HasSubtitles = video.HasSubtitles; - } - - if (video.AdditionalParts.Count != 0) - { - dto.PartCount = video.AdditionalParts.Count + 1; - } - - if (fields.Contains(ItemFields.MediaSourceCount)) - { - var mediaSourceCount = video.MediaSourceCount; - if (mediaSourceCount != 1) - { - dto.MediaSourceCount = mediaSourceCount; - } - } - - if (fields.Contains(ItemFields.Chapters)) - { - dto.Chapters = GetChapterInfoDtos(item); - } - - dto.ExtraType = video.ExtraType; - } - - if (fields.Contains(ItemFields.MediaStreams)) - { - // Add VideoInfo - var iHasMediaSources = item as IHasMediaSources; - - if (iHasMediaSources != null) - { - List<MediaStream> mediaStreams; - - if (dto.MediaSources != null && dto.MediaSources.Count > 0) - { - mediaStreams = dto.MediaSources.Where(i => new Guid(i.Id) == item.Id) - .SelectMany(i => i.MediaStreams) - .ToList(); - } - else - { - mediaStreams = _mediaSourceManager().GetStaticMediaSources(iHasMediaSources, true).First().MediaStreams; - } - - dto.MediaStreams = mediaStreams; - } - } - - var hasSpecialFeatures = item as IHasSpecialFeatures; - if (hasSpecialFeatures != null) - { - var specialFeatureCount = hasSpecialFeatures.SpecialFeatureIds.Count; - - if (specialFeatureCount > 0) - { - dto.SpecialFeatureCount = specialFeatureCount; - } - } - - // Add EpisodeInfo - var episode = item as Episode; - if (episode != null) - { - dto.IndexNumberEnd = episode.IndexNumberEnd; - dto.SeriesName = episode.SeriesName; - - if (fields.Contains(ItemFields.AlternateEpisodeNumbers)) - { - dto.DvdSeasonNumber = episode.DvdSeasonNumber; - dto.DvdEpisodeNumber = episode.DvdEpisodeNumber; - dto.AbsoluteEpisodeNumber = episode.AbsoluteEpisodeNumber; - } - - if (fields.Contains(ItemFields.SpecialEpisodeNumbers)) - { - dto.AirsAfterSeasonNumber = episode.AirsAfterSeasonNumber; - dto.AirsBeforeEpisodeNumber = episode.AirsBeforeEpisodeNumber; - dto.AirsBeforeSeasonNumber = episode.AirsBeforeSeasonNumber; - } - - var seasonId = episode.SeasonId; - if (seasonId.HasValue) - { - dto.SeasonId = seasonId.Value.ToString("N"); - } - - dto.SeasonName = episode.SeasonName; - - var seriesId = episode.SeriesId; - if (seriesId.HasValue) - { - dto.SeriesId = seriesId.Value.ToString("N"); - } - - Series episodeSeries = null; - - if (fields.Contains(ItemFields.SeriesGenres)) - { - episodeSeries = episodeSeries ?? episode.Series; - if (episodeSeries != null) - { - dto.SeriesGenres = episodeSeries.Genres.ToList(); - } - } - - //if (fields.Contains(ItemFields.SeriesPrimaryImage)) - { - episodeSeries = episodeSeries ?? episode.Series; - if (episodeSeries != null) - { - dto.SeriesPrimaryImageTag = GetImageCacheTag(episodeSeries, ImageType.Primary); - } - } - - if (fields.Contains(ItemFields.SeriesStudio)) - { - episodeSeries = episodeSeries ?? episode.Series; - if (episodeSeries != null) - { - dto.SeriesStudio = episodeSeries.Studios.FirstOrDefault(); - } - } - } - - // Add SeriesInfo - var series = item as Series; - if (series != null) - { - dto.AirDays = series.AirDays; - dto.AirTime = series.AirTime; - dto.SeriesStatus = series.Status; - - dto.AnimeSeriesIndex = series.AnimeSeriesIndex; - } - - // Add SeasonInfo - var season = item as Season; - if (season != null) - { - dto.SeriesName = season.SeriesName; - - var seriesId = season.SeriesId; - if (seriesId.HasValue) - { - dto.SeriesId = seriesId.Value.ToString("N"); - } - - series = null; - - if (fields.Contains(ItemFields.SeriesStudio)) - { - series = series ?? season.Series; - if (series != null) - { - dto.SeriesStudio = series.Studios.FirstOrDefault(); - } - } - - if (fields.Contains(ItemFields.SeriesPrimaryImage)) - { - series = series ?? season.Series; - if (series != null) - { - dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary); - } - } - } - - var game = item as Game; - - if (game != null) - { - SetGameProperties(dto, game); - } - - var gameSystem = item as GameSystem; - - if (gameSystem != null) - { - SetGameSystemProperties(dto, gameSystem); - } - - var musicVideo = item as MusicVideo; - if (musicVideo != null) - { - SetMusicVideoProperties(dto, musicVideo); - } - - var book = item as Book; - if (book != null) - { - SetBookProperties(dto, book); - } - - if (item.ProductionLocations.Count > 0 || item is Movie) - { - dto.ProductionLocations = item.ProductionLocations.ToArray(); - } - - var photo = item as Photo; - if (photo != null) - { - SetPhotoProperties(dto, photo); - } - - dto.ChannelId = item.ChannelId; - - if (item.SourceType == SourceType.Channel && !string.IsNullOrWhiteSpace(item.ChannelId)) - { - var channel = _libraryManager.GetItemById(item.ChannelId); - if (channel != null) - { - dto.ChannelName = channel.Name; - } - } - } - - private void AddInheritedImages(BaseItemDto dto, BaseItem item, DtoOptions options, BaseItem owner) - { - var logoLimit = options.GetImageLimit(ImageType.Logo); - var artLimit = options.GetImageLimit(ImageType.Art); - var thumbLimit = options.GetImageLimit(ImageType.Thumb); - var backdropLimit = options.GetImageLimit(ImageType.Backdrop); - - if (logoLimit == 0 && artLimit == 0 && thumbLimit == 0 && backdropLimit == 0) - { - return; - } - - BaseItem parent = null; - var isFirst = true; - - while (((!dto.HasLogo && logoLimit > 0) || (!dto.HasArtImage && artLimit > 0) || (!dto.HasThumb && thumbLimit > 0) || parent is Series) && - (parent = parent ?? (isFirst ? item.GetParent() ?? owner : parent)) != null) - { - if (parent == null) - { - break; - } - - var allImages = parent.ImageInfos; - - if (logoLimit > 0 && !dto.HasLogo && dto.ParentLogoItemId == null) - { - var image = allImages.FirstOrDefault(i => i.Type == ImageType.Logo); - - if (image != null) - { - dto.ParentLogoItemId = GetDtoId(parent); - dto.ParentLogoImageTag = GetImageCacheTag(parent, image); - } - } - if (artLimit > 0 && !dto.HasArtImage && dto.ParentArtItemId == null) - { - var image = allImages.FirstOrDefault(i => i.Type == ImageType.Art); - - if (image != null) - { - dto.ParentArtItemId = GetDtoId(parent); - dto.ParentArtImageTag = GetImageCacheTag(parent, image); - } - } - if (thumbLimit > 0 && !dto.HasThumb && (dto.ParentThumbItemId == null || parent is Series)) - { - var image = allImages.FirstOrDefault(i => i.Type == ImageType.Thumb); - - if (image != null) - { - dto.ParentThumbItemId = GetDtoId(parent); - dto.ParentThumbImageTag = GetImageCacheTag(parent, image); - } - } - if (backdropLimit > 0 && !dto.HasBackdrop) - { - var images = allImages.Where(i => i.Type == ImageType.Backdrop).Take(backdropLimit).ToList(); - - if (images.Count > 0) - { - dto.ParentBackdropItemId = GetDtoId(parent); - dto.ParentBackdropImageTags = GetImageTags(parent, images); - } - } - - isFirst = false; - parent = parent.GetParent(); - } - } - - private string GetMappedPath(BaseItem item) - { - var path = item.Path; - - var locationType = item.LocationType; - - if (locationType == LocationType.FileSystem || locationType == LocationType.Offline) - { - path = _libraryManager.GetPathAfterNetworkSubstitution(path, item); - } - - return path; - } - - /// <summary> - /// Attaches the primary image aspect ratio. - /// </summary> - /// <param name="dto">The dto.</param> - /// <param name="item">The item.</param> - /// <returns>Task.</returns> - public void AttachPrimaryImageAspectRatio(IItemDto dto, IHasImages item) - { - dto.PrimaryImageAspectRatio = GetPrimaryImageAspectRatio(item); - } - - public double? GetPrimaryImageAspectRatio(IHasImages item) - { - var imageInfo = item.GetImageInfo(ImageType.Primary, 0); - - if (imageInfo == null || !imageInfo.IsLocalFile) - { - return null; - } - - ImageSize size; - - try - { - size = _imageProcessor.GetImageSize(imageInfo); - } - catch - { - //_logger.ErrorException("Failed to determine primary image aspect ratio for {0}", ex, path); - return null; - } - - var supportedEnhancers = _imageProcessor.GetSupportedEnhancers(item, ImageType.Primary).ToList(); - - foreach (var enhancer in supportedEnhancers) - { - try - { - size = enhancer.GetEnhancedImageSize(item, ImageType.Primary, 0, size); - } - catch (Exception ex) - { - _logger.ErrorException("Error in image enhancer: {0}", ex, enhancer.GetType().Name); - } - } - - var width = size.Width; - var height = size.Height; - - if (width == 0 || height == 0) - { - return null; - } - - var photo = item as Photo; - if (photo != null && photo.Orientation.HasValue) - { - switch (photo.Orientation.Value) - { - case ImageOrientation.LeftBottom: - case ImageOrientation.LeftTop: - case ImageOrientation.RightBottom: - case ImageOrientation.RightTop: - var temp = height; - height = width; - width = temp; - break; - } - } - - return width / height; - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs deleted file mode 100644 index a36583a412..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs +++ /dev/null @@ -1,566 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Implementations.Logging; -using MediaBrowser.Common.Plugins; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Common.Updates; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Activity; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Localization; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Controller.Subtitles; -using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Tasks; -using MediaBrowser.Model.Updates; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - public class ActivityLogEntryPoint : IServerEntryPoint - { - private readonly IInstallationManager _installationManager; - - //private readonly ILogManager _logManager; - //private readonly ILogger _logger; - private readonly ISessionManager _sessionManager; - private readonly ITaskManager _taskManager; - private readonly IActivityManager _activityManager; - private readonly ILocalizationManager _localization; - - private readonly ILibraryManager _libraryManager; - private readonly ISubtitleManager _subManager; - private readonly IUserManager _userManager; - private readonly IServerConfigurationManager _config; - private readonly IServerApplicationHost _appHost; - - public ActivityLogEntryPoint(ISessionManager sessionManager, ITaskManager taskManager, IActivityManager activityManager, ILocalizationManager localization, IInstallationManager installationManager, ILibraryManager libraryManager, ISubtitleManager subManager, IUserManager userManager, IServerConfigurationManager config, IServerApplicationHost appHost) - { - //_logger = _logManager.GetLogger("ActivityLogEntryPoint"); - _sessionManager = sessionManager; - _taskManager = taskManager; - _activityManager = activityManager; - _localization = localization; - _installationManager = installationManager; - _libraryManager = libraryManager; - _subManager = subManager; - _userManager = userManager; - _config = config; - //_logManager = logManager; - _appHost = appHost; - } - - public void Run() - { - //_taskManager.TaskExecuting += _taskManager_TaskExecuting; - //_taskManager.TaskCompleted += _taskManager_TaskCompleted; - - //_installationManager.PluginInstalled += _installationManager_PluginInstalled; - //_installationManager.PluginUninstalled += _installationManager_PluginUninstalled; - //_installationManager.PluginUpdated += _installationManager_PluginUpdated; - - //_libraryManager.ItemAdded += _libraryManager_ItemAdded; - //_libraryManager.ItemRemoved += _libraryManager_ItemRemoved; - - _sessionManager.SessionStarted += _sessionManager_SessionStarted; - _sessionManager.AuthenticationFailed += _sessionManager_AuthenticationFailed; - _sessionManager.AuthenticationSucceeded += _sessionManager_AuthenticationSucceeded; - _sessionManager.SessionEnded += _sessionManager_SessionEnded; - - _sessionManager.PlaybackStart += _sessionManager_PlaybackStart; - _sessionManager.PlaybackStopped += _sessionManager_PlaybackStopped; - - //_subManager.SubtitlesDownloaded += _subManager_SubtitlesDownloaded; - _subManager.SubtitleDownloadFailure += _subManager_SubtitleDownloadFailure; - - _userManager.UserCreated += _userManager_UserCreated; - _userManager.UserPasswordChanged += _userManager_UserPasswordChanged; - _userManager.UserDeleted += _userManager_UserDeleted; - _userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated; - _userManager.UserLockedOut += _userManager_UserLockedOut; - - //_config.ConfigurationUpdated += _config_ConfigurationUpdated; - //_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; - - //_logManager.LoggerLoaded += _logManager_LoggerLoaded; - - _appHost.ApplicationUpdated += _appHost_ApplicationUpdated; - } - - void _userManager_UserLockedOut(object sender, GenericEventArgs<User> e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("UserLockedOutWithName"), e.Argument.Name), - Type = "UserLockedOut", - UserId = e.Argument.Id.ToString("N") - }); - } - - void _subManager_SubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("SubtitleDownloadFailureForItem"), Notifications.Notifications.GetItemName(e.Item)), - Type = "SubtitleDownloadFailure", - ItemId = e.Item.Id.ToString("N"), - ShortOverview = string.Format(_localization.GetLocalizedString("ProviderValue"), e.Provider), - Overview = LogHelper.GetLogMessage(e.Exception).ToString() - }); - } - - void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e) - { - var item = e.MediaInfo; - - if (item == null) - { - //_logger.Warn("PlaybackStopped reported with null media info."); - return; - } - - var themeMedia = item as IThemeMedia; - if (themeMedia != null && themeMedia.IsThemeMedia) - { - // Don't report theme song or local trailer playback - return; - } - - if (e.Users.Count == 0) - { - return; - } - - var user = e.Users.First(); - - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), user.Name, item.Name), - Type = "PlaybackStopped", - ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName), - UserId = user.Id.ToString("N") - }); - } - - void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e) - { - var item = e.MediaInfo; - - if (item == null) - { - //_logger.Warn("PlaybackStart reported with null media info."); - return; - } - - var themeMedia = item as IThemeMedia; - if (themeMedia != null && themeMedia.IsThemeMedia) - { - // Don't report theme song or local trailer playback - return; - } - - if (e.Users.Count == 0) - { - return; - } - - var user = e.Users.First(); - - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), user.Name, item.Name), - Type = "PlaybackStart", - ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName), - UserId = user.Id.ToString("N") - }); - } - - void _sessionManager_SessionEnded(object sender, SessionEventArgs e) - { - string name; - var session = e.SessionInfo; - - if (string.IsNullOrWhiteSpace(session.UserName)) - { - name = string.Format(_localization.GetLocalizedString("DeviceOfflineWithName"), session.DeviceName); - - // Causing too much spam for now - return; - } - else - { - name = string.Format(_localization.GetLocalizedString("UserOfflineFromDevice"), session.UserName, session.DeviceName); - } - - CreateLogEntry(new ActivityLogEntry - { - Name = name, - Type = "SessionEnded", - ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint), - UserId = session.UserId.HasValue ? session.UserId.Value.ToString("N") : null - }); - } - - void _sessionManager_AuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationRequest> e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("AuthenticationSucceededWithUserName"), e.Argument.Username), - Type = "AuthenticationSucceeded", - ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), e.Argument.RemoteEndPoint) - }); - } - - void _sessionManager_AuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("FailedLoginAttemptWithUserName"), e.Argument.Username), - Type = "AuthenticationFailed", - ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), e.Argument.RemoteEndPoint), - Severity = LogSeverity.Error - }); - } - - void _appHost_ApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = _localization.GetLocalizedString("MessageApplicationUpdated"), - Type = "ApplicationUpdated", - ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), e.Argument.versionStr), - Overview = e.Argument.description - }); - } - - void _logManager_LoggerLoaded(object sender, EventArgs e) - { - } - - void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("MessageNamedServerConfigurationUpdatedWithValue"), e.Key), - Type = "NamedConfigurationUpdated" - }); - } - - void _config_ConfigurationUpdated(object sender, EventArgs e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = _localization.GetLocalizedString("MessageServerConfigurationUpdated"), - Type = "ServerConfigurationUpdated" - }); - } - - void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs<User> e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("UserConfigurationUpdatedWithName"), e.Argument.Name), - Type = "UserConfigurationUpdated", - UserId = e.Argument.Id.ToString("N") - }); - } - - void _userManager_UserDeleted(object sender, GenericEventArgs<User> e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("UserDeletedWithName"), e.Argument.Name), - Type = "UserDeleted" - }); - } - - void _userManager_UserPasswordChanged(object sender, GenericEventArgs<User> e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("UserPasswordChangedWithName"), e.Argument.Name), - Type = "UserPasswordChanged", - UserId = e.Argument.Id.ToString("N") - }); - } - - void _userManager_UserCreated(object sender, GenericEventArgs<User> e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("UserCreatedWithName"), e.Argument.Name), - Type = "UserCreated", - UserId = e.Argument.Id.ToString("N") - }); - } - - void _subManager_SubtitlesDownloaded(object sender, SubtitleDownloadEventArgs e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("SubtitlesDownloadedForItem"), Notifications.Notifications.GetItemName(e.Item)), - Type = "SubtitlesDownloaded", - ItemId = e.Item.Id.ToString("N"), - ShortOverview = string.Format(_localization.GetLocalizedString("ProviderValue"), e.Provider) - }); - } - - void _sessionManager_SessionStarted(object sender, SessionEventArgs e) - { - string name; - var session = e.SessionInfo; - - if (string.IsNullOrWhiteSpace(session.UserName)) - { - name = string.Format(_localization.GetLocalizedString("DeviceOnlineWithName"), session.DeviceName); - - // Causing too much spam for now - return; - } - else - { - name = string.Format(_localization.GetLocalizedString("UserOnlineFromDevice"), session.UserName, session.DeviceName); - } - - CreateLogEntry(new ActivityLogEntry - { - Name = name, - Type = "SessionStarted", - ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint), - UserId = session.UserId.HasValue ? session.UserId.Value.ToString("N") : null - }); - } - - void _libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e) - { - if (e.Item.SourceType != SourceType.Library) - { - return; - } - - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("ItemRemovedWithName"), Notifications.Notifications.GetItemName(e.Item)), - Type = "ItemRemoved" - }); - } - - void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) - { - if (e.Item.SourceType != SourceType.Library) - { - return; - } - - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("ItemAddedWithName"), Notifications.Notifications.GetItemName(e.Item)), - Type = "ItemAdded", - ItemId = e.Item.Id.ToString("N") - }); - } - - void _installationManager_PluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("PluginUpdatedWithName"), e.Argument.Item1.Name), - Type = "PluginUpdated", - ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), e.Argument.Item2.versionStr), - Overview = e.Argument.Item2.description - }); - } - - void _installationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("PluginUninstalledWithName"), e.Argument.Name), - Type = "PluginUninstalled" - }); - } - - void _installationManager_PluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> e) - { - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("PluginInstalledWithName"), e.Argument.name), - Type = "PluginInstalled", - ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), e.Argument.versionStr) - }); - } - - void _taskManager_TaskExecuting(object sender, GenericEventArgs<IScheduledTaskWorker> e) - { - var task = e.Argument; - - var activityTask = task.ScheduledTask as IScheduledTaskActivityLog; - if (activityTask != null && !activityTask.IsActivityLogged) - { - return; - } - - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("ScheduledTaskStartedWithName"), task.Name), - Type = "ScheduledTaskStarted" - }); - } - - void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) - { - var result = e.Result; - var task = e.Task; - - var activityTask = task.ScheduledTask as IScheduledTaskActivityLog; - if (activityTask != null && !activityTask.IsActivityLogged) - { - return; - } - - var time = result.EndTimeUtc - result.StartTimeUtc; - var runningTime = string.Format(_localization.GetLocalizedString("LabelRunningTimeValue"), ToUserFriendlyString(time)); - - if (result.Status == TaskCompletionStatus.Failed) - { - var vals = new List<string>(); - - if (!string.IsNullOrWhiteSpace(e.Result.ErrorMessage)) - { - vals.Add(e.Result.ErrorMessage); - } - if (!string.IsNullOrWhiteSpace(e.Result.LongErrorMessage)) - { - vals.Add(e.Result.LongErrorMessage); - } - - CreateLogEntry(new ActivityLogEntry - { - Name = string.Format(_localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name), - Type = "ScheduledTaskFailed", - Overview = string.Join(Environment.NewLine, vals.ToArray()), - ShortOverview = runningTime, - Severity = LogSeverity.Error - }); - } - } - - private async void CreateLogEntry(ActivityLogEntry entry) - { - try - { - await _activityManager.Create(entry).ConfigureAwait(false); - } - catch - { - // Logged at lower levels - } - } - - public void Dispose() - { - _taskManager.TaskExecuting -= _taskManager_TaskExecuting; - _taskManager.TaskCompleted -= _taskManager_TaskCompleted; - - _installationManager.PluginInstalled -= _installationManager_PluginInstalled; - _installationManager.PluginUninstalled -= _installationManager_PluginUninstalled; - _installationManager.PluginUpdated -= _installationManager_PluginUpdated; - - _libraryManager.ItemAdded -= _libraryManager_ItemAdded; - _libraryManager.ItemRemoved -= _libraryManager_ItemRemoved; - - _sessionManager.SessionStarted -= _sessionManager_SessionStarted; - _sessionManager.AuthenticationFailed -= _sessionManager_AuthenticationFailed; - _sessionManager.AuthenticationSucceeded -= _sessionManager_AuthenticationSucceeded; - _sessionManager.SessionEnded -= _sessionManager_SessionEnded; - - _sessionManager.PlaybackStart -= _sessionManager_PlaybackStart; - _sessionManager.PlaybackStopped -= _sessionManager_PlaybackStopped; - - _subManager.SubtitlesDownloaded -= _subManager_SubtitlesDownloaded; - _subManager.SubtitleDownloadFailure -= _subManager_SubtitleDownloadFailure; - - _userManager.UserCreated -= _userManager_UserCreated; - _userManager.UserPasswordChanged -= _userManager_UserPasswordChanged; - _userManager.UserDeleted -= _userManager_UserDeleted; - _userManager.UserConfigurationUpdated -= _userManager_UserConfigurationUpdated; - _userManager.UserLockedOut -= _userManager_UserLockedOut; - - _config.ConfigurationUpdated -= _config_ConfigurationUpdated; - _config.NamedConfigurationUpdated -= _config_NamedConfigurationUpdated; - - //_logManager.LoggerLoaded -= _logManager_LoggerLoaded; - - _appHost.ApplicationUpdated -= _appHost_ApplicationUpdated; - } - - /// <summary> - /// Constructs a user-friendly string for this TimeSpan instance. - /// </summary> - public static string ToUserFriendlyString(TimeSpan span) - { - const int DaysInYear = 365; - const int DaysInMonth = 30; - - // Get each non-zero value from TimeSpan component - List<string> values = new List<string>(); - - // Number of years - int days = span.Days; - if (days >= DaysInYear) - { - int years = days / DaysInYear; - values.Add(CreateValueString(years, "year")); - days = days % DaysInYear; - } - // Number of months - if (days >= DaysInMonth) - { - int months = days / DaysInMonth; - values.Add(CreateValueString(months, "month")); - days = days % DaysInMonth; - } - // Number of days - if (days >= 1) - values.Add(CreateValueString(days, "day")); - // Number of hours - if (span.Hours >= 1) - values.Add(CreateValueString(span.Hours, "hour")); - // Number of minutes - if (span.Minutes >= 1) - values.Add(CreateValueString(span.Minutes, "minute")); - // Number of seconds (include when 0 if no other components included) - if (span.Seconds >= 1 || values.Count == 0) - values.Add(CreateValueString(span.Seconds, "second")); - - // Combine values into string - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < values.Count; i++) - { - if (builder.Length > 0) - builder.Append(i == values.Count - 1 ? " and " : ", "); - builder.Append(values[i]); - } - // Return result - return builder.ToString(); - } - - /// <summary> - /// Constructs a string description of a time-span value. - /// </summary> - /// <param name="value">The value of this item</param> - /// <param name="description">The name of this item (singular form)</param> - private static string CreateValueString(int value, string description) - { - return String.Format("{0:#,##0} {1}", - value, value == 1 ? description : String.Format("{0}s", description)); - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs deleted file mode 100644 index d5f265ddad..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs +++ /dev/null @@ -1,122 +0,0 @@ -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Tasks; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.LiveTv; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - public class AutomaticRestartEntryPoint : IServerEntryPoint - { - private readonly IServerApplicationHost _appHost; - private readonly ILogger _logger; - private readonly ITaskManager _iTaskManager; - private readonly ISessionManager _sessionManager; - private readonly IServerConfigurationManager _config; - private readonly ILiveTvManager _liveTvManager; - - private Timer _timer; - - public AutomaticRestartEntryPoint(IServerApplicationHost appHost, ILogger logger, ITaskManager iTaskManager, ISessionManager sessionManager, IServerConfigurationManager config, ILiveTvManager liveTvManager) - { - _appHost = appHost; - _logger = logger; - _iTaskManager = iTaskManager; - _sessionManager = sessionManager; - _config = config; - _liveTvManager = liveTvManager; - } - - public void Run() - { - if (_appHost.CanSelfRestart) - { - _appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged; - } - } - - void _appHost_HasPendingRestartChanged(object sender, EventArgs e) - { - DisposeTimer(); - - if (_appHost.HasPendingRestart) - { - _timer = new Timer(TimerCallback, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); - } - } - - private async void TimerCallback(object state) - { - if (_config.Configuration.EnableAutomaticRestart) - { - var isIdle = await IsIdle().ConfigureAwait(false); - - if (isIdle) - { - DisposeTimer(); - - try - { - _appHost.Restart(); - } - catch (Exception ex) - { - _logger.ErrorException("Error restarting server", ex); - } - } - } - } - - private async Task<bool> IsIdle() - { - if (_iTaskManager.ScheduledTasks.Any(i => i.State != TaskState.Idle)) - { - return false; - } - - if (_liveTvManager.Services.Count == 1) - { - try - { - var timers = await _liveTvManager.GetTimers(new TimerQuery(), CancellationToken.None).ConfigureAwait(false); - if (timers.Items.Any(i => i.Status == RecordingStatus.InProgress)) - { - return false; - } - } - catch (Exception ex) - { - _logger.ErrorException("Error getting timers", ex); - } - } - - var now = DateTime.UtcNow; - - return !_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 30); - } - - public void Dispose() - { - _appHost.HasPendingRestartChanged -= _appHost_HasPendingRestartChanged; - - DisposeTimer(); - } - - private void DisposeTimer() - { - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs deleted file mode 100644 index 3274231ee7..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ /dev/null @@ -1,290 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Dlna; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Logging; -using Mono.Nat; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Net; -using MediaBrowser.Common.Threading; -using MediaBrowser.Model.Events; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - public class ExternalPortForwarding : IServerEntryPoint - { - private readonly IServerApplicationHost _appHost; - private readonly ILogger _logger; - private readonly IServerConfigurationManager _config; - private readonly IDeviceDiscovery _deviceDiscovery; - - private PeriodicTimer _timer; - private bool _isStarted; - - public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, IDeviceDiscovery deviceDiscovery) - { - _logger = logmanager.GetLogger("PortMapper"); - _appHost = appHost; - _config = config; - _deviceDiscovery = deviceDiscovery; - } - - private string _lastConfigIdentifier; - private string GetConfigIdentifier() - { - var values = new List<string>(); - var config = _config.Configuration; - - values.Add(config.EnableUPnP.ToString()); - values.Add(config.PublicPort.ToString(CultureInfo.InvariantCulture)); - values.Add(_appHost.HttpPort.ToString(CultureInfo.InvariantCulture)); - values.Add(_appHost.HttpsPort.ToString(CultureInfo.InvariantCulture)); - values.Add(config.EnableHttps.ToString()); - values.Add(_appHost.EnableHttps.ToString()); - - return string.Join("|", values.ToArray()); - } - - void _config_ConfigurationUpdated(object sender, EventArgs e) - { - if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) - { - if (_isStarted) - { - DisposeNat(); - } - - Run(); - } - } - - public void Run() - { - NatUtility.Logger = _logger; - - if (_config.Configuration.EnableUPnP) - { - Start(); - } - - _config.ConfigurationUpdated -= _config_ConfigurationUpdated; - _config.ConfigurationUpdated += _config_ConfigurationUpdated; - } - - private void Start() - { - _logger.Debug("Starting NAT discovery"); - NatUtility.EnabledProtocols = new List<NatProtocol> - { - NatProtocol.Pmp - }; - NatUtility.DeviceFound += NatUtility_DeviceFound; - - // Mono.Nat does never rise this event. The event is there however it is useless. - // You could remove it with no risk. - NatUtility.DeviceLost += NatUtility_DeviceLost; - - - // it is hard to say what one should do when an unhandled exception is raised - // because there isn't anything one can do about it. Probably save a log or ignored it. - NatUtility.UnhandledException += NatUtility_UnhandledException; - NatUtility.StartDiscovery(); - - _timer = new PeriodicTimer(ClearCreatedRules, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); - - _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered; - - _lastConfigIdentifier = GetConfigIdentifier(); - - _isStarted = true; - } - - private async void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs<UpnpDeviceInfo> e) - { - var info = e.Argument; - - string usn; - if (!info.Headers.TryGetValue("USN", out usn)) usn = string.Empty; - - string nt; - if (!info.Headers.TryGetValue("NT", out nt)) nt = string.Empty; - - // Filter device type - if (usn.IndexOf("WANIPConnection:", StringComparison.OrdinalIgnoreCase) == -1 && - nt.IndexOf("WANIPConnection:", StringComparison.OrdinalIgnoreCase) == -1 && - usn.IndexOf("WANPPPConnection:", StringComparison.OrdinalIgnoreCase) == -1 && - nt.IndexOf("WANPPPConnection:", StringComparison.OrdinalIgnoreCase) == -1) - { - return; - } - - var identifier = string.IsNullOrWhiteSpace(usn) ? nt : usn; - - if (info.Location == null) - { - return; - } - - lock (_usnsHandled) - { - if (_usnsHandled.Contains(identifier)) - { - return; - } - _usnsHandled.Add(identifier); - } - - _logger.Debug("Calling Nat.Handle on " + identifier); - - IPAddress address; - if (IPAddress.TryParse(info.Location.Host, out address)) - { - // The Handle method doesn't need the port - var endpoint = new IPEndPoint(address, info.Location.Port); - - IPAddress localAddress = null; - - try - { - var localAddressString = await _appHost.GetLocalApiUrl().ConfigureAwait(false); - - if (!IPAddress.TryParse(localAddressString, out localAddress)) - { - return; - } - } - catch - { - return; - } - - NatUtility.Handle(localAddress, info, endpoint, NatProtocol.Upnp); - } - } - - private void ClearCreatedRules(object state) - { - _createdRules = new List<string>(); - lock (_usnsHandled) - { - _usnsHandled.Clear(); - } - } - - void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) - { - var ex = e.ExceptionObject as Exception; - - if (ex == null) - { - //_logger.Error("Unidentified error reported by Mono.Nat"); - } - else - { - // Seeing some blank exceptions coming through here - //_logger.ErrorException("Error reported by Mono.Nat: ", ex); - } - } - - void NatUtility_DeviceFound(object sender, DeviceEventArgs e) - { - try - { - var device = e.Device; - _logger.Debug("NAT device found: {0}", device.LocalAddress.ToString()); - - CreateRules(device); - } - catch - { - // I think it could be a good idea to log the exception because - // you are using permanent portmapping here (never expire) and that means that next time - // CreatePortMap is invoked it can fails with a 718-ConflictInMappingEntry or not. That depends - // on the router's upnp implementation (specs says it should fail however some routers don't do it) - // It also can fail with others like 727-ExternalPortOnlySupportsWildcard, 728-NoPortMapsAvailable - // and those errors (upnp errors) could be useful for diagnosting. - - // Commenting out because users are reporting problems out of our control - //_logger.ErrorException("Error creating port forwarding rules", ex); - } - } - - private List<string> _createdRules = new List<string>(); - private List<string> _usnsHandled = new List<string>(); - private void CreateRules(INatDevice device) - { - // On some systems the device discovered event seems to fire repeatedly - // This check will help ensure we're not trying to port map the same device over and over - - var address = device.LocalAddress.ToString(); - - if (!_createdRules.Contains(address)) - { - _createdRules.Add(address); - - CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort); - CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); - } - } - - private void CreatePortMap(INatDevice device, int privatePort, int publicPort) - { - _logger.Debug("Creating port map on port {0}", privatePort); - device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) - { - Description = _appHost.Name - }); - } - - // As I said before, this method will be never invoked. You can remove it. - void NatUtility_DeviceLost(object sender, DeviceEventArgs e) - { - var device = e.Device; - _logger.Debug("NAT device lost: {0}", device.LocalAddress.ToString()); - } - - public void Dispose() - { - DisposeNat(); - } - - private void DisposeNat() - { - _logger.Debug("Stopping NAT discovery"); - - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - - _deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered; - - try - { - // This is not a significant improvement - NatUtility.StopDiscovery(); - NatUtility.DeviceFound -= NatUtility_DeviceFound; - NatUtility.DeviceLost -= NatUtility_DeviceLost; - NatUtility.UnhandledException -= NatUtility_UnhandledException; - } - // Statements in try-block will no fail because StopDiscovery is a one-line - // method that was no chances to fail. - // public static void StopDiscovery () - // { - // searching.Reset(); - // } - // IMO you could remove the catch-block - catch (Exception ex) - { - _logger.ErrorException("Error stopping NAT Discovery", ex); - } - finally - { - _isStarted = false; - } - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs deleted file mode 100644 index afc4e9702e..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ /dev/null @@ -1,340 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MoreLinq; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using MediaBrowser.Controller.Entities.Audio; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - public class LibraryChangedNotifier : IServerEntryPoint - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - - private readonly ISessionManager _sessionManager; - private readonly IUserManager _userManager; - private readonly ILogger _logger; - - /// <summary> - /// The _library changed sync lock - /// </summary> - private readonly object _libraryChangedSyncLock = new object(); - - private readonly List<Folder> _foldersAddedTo = new List<Folder>(); - private readonly List<Folder> _foldersRemovedFrom = new List<Folder>(); - - private readonly List<BaseItem> _itemsAdded = new List<BaseItem>(); - private readonly List<BaseItem> _itemsRemoved = new List<BaseItem>(); - private readonly List<BaseItem> _itemsUpdated = new List<BaseItem>(); - - /// <summary> - /// Gets or sets the library update timer. - /// </summary> - /// <value>The library update timer.</value> - private Timer LibraryUpdateTimer { get; set; } - - /// <summary> - /// The library update duration - /// </summary> - private const int LibraryUpdateDuration = 5000; - - public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IUserManager userManager, ILogger logger) - { - _libraryManager = libraryManager; - _sessionManager = sessionManager; - _userManager = userManager; - _logger = logger; - } - - public void Run() - { - _libraryManager.ItemAdded += libraryManager_ItemAdded; - _libraryManager.ItemUpdated += libraryManager_ItemUpdated; - _libraryManager.ItemRemoved += libraryManager_ItemRemoved; - - } - - /// <summary> - /// Handles the ItemAdded event of the libraryManager control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param> - void libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) - { - if (!FilterItem(e.Item)) - { - return; - } - - lock (_libraryChangedSyncLock) - { - if (LibraryUpdateTimer == null) - { - LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, - Timeout.Infinite); - } - else - { - LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); - } - - if (e.Item.Parent != null) - { - _foldersAddedTo.Add(e.Item.Parent); - } - - _itemsAdded.Add(e.Item); - } - } - - /// <summary> - /// Handles the ItemUpdated event of the libraryManager control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param> - void libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e) - { - if (!FilterItem(e.Item)) - { - return; - } - - lock (_libraryChangedSyncLock) - { - if (LibraryUpdateTimer == null) - { - LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, - Timeout.Infinite); - } - else - { - LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); - } - - _itemsUpdated.Add(e.Item); - } - } - - /// <summary> - /// Handles the ItemRemoved event of the libraryManager control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param> - void libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e) - { - if (!FilterItem(e.Item)) - { - return; - } - - lock (_libraryChangedSyncLock) - { - if (LibraryUpdateTimer == null) - { - LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, - Timeout.Infinite); - } - else - { - LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); - } - - if (e.Item.Parent != null) - { - _foldersRemovedFrom.Add(e.Item.Parent); - } - - _itemsRemoved.Add(e.Item); - } - } - - /// <summary> - /// Libraries the update timer callback. - /// </summary> - /// <param name="state">The state.</param> - private void LibraryUpdateTimerCallback(object state) - { - lock (_libraryChangedSyncLock) - { - // Remove dupes in case some were saved multiple times - var foldersAddedTo = _foldersAddedTo.DistinctBy(i => i.Id).ToList(); - - var foldersRemovedFrom = _foldersRemovedFrom.DistinctBy(i => i.Id).ToList(); - - var itemsUpdated = _itemsUpdated - .Where(i => !_itemsAdded.Contains(i)) - .DistinctBy(i => i.Id) - .ToList(); - - SendChangeNotifications(_itemsAdded.ToList(), itemsUpdated, _itemsRemoved.ToList(), foldersAddedTo, foldersRemovedFrom, CancellationToken.None); - - if (LibraryUpdateTimer != null) - { - LibraryUpdateTimer.Dispose(); - LibraryUpdateTimer = null; - } - - _itemsAdded.Clear(); - _itemsRemoved.Clear(); - _itemsUpdated.Clear(); - _foldersAddedTo.Clear(); - _foldersRemovedFrom.Clear(); - } - } - - /// <summary> - /// Sends the change notifications. - /// </summary> - /// <param name="itemsAdded">The items added.</param> - /// <param name="itemsUpdated">The items updated.</param> - /// <param name="itemsRemoved">The items removed.</param> - /// <param name="foldersAddedTo">The folders added to.</param> - /// <param name="foldersRemovedFrom">The folders removed from.</param> - /// <param name="cancellationToken">The cancellation token.</param> - private async void SendChangeNotifications(List<BaseItem> itemsAdded, List<BaseItem> itemsUpdated, List<BaseItem> itemsRemoved, List<Folder> foldersAddedTo, List<Folder> foldersRemovedFrom, CancellationToken cancellationToken) - { - foreach (var user in _userManager.Users.ToList()) - { - var id = user.Id; - var userSessions = _sessionManager.Sessions - .Where(u => u.UserId.HasValue && u.UserId.Value == id && u.SessionController != null && u.IsActive) - .ToList(); - - if (userSessions.Count > 0) - { - LibraryUpdateInfo info; - - try - { - info = GetLibraryUpdateInfo(itemsAdded, itemsUpdated, itemsRemoved, foldersAddedTo, - foldersRemovedFrom, id); - } - catch (Exception ex) - { - _logger.ErrorException("Error in GetLibraryUpdateInfo", ex); - return; - } - - foreach (var userSession in userSessions) - { - try - { - await userSession.SessionController.SendLibraryUpdateInfo(info, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending LibraryChanged message", ex); - } - } - } - - } - } - - /// <summary> - /// Gets the library update info. - /// </summary> - /// <param name="itemsAdded">The items added.</param> - /// <param name="itemsUpdated">The items updated.</param> - /// <param name="itemsRemoved">The items removed.</param> - /// <param name="foldersAddedTo">The folders added to.</param> - /// <param name="foldersRemovedFrom">The folders removed from.</param> - /// <param name="userId">The user id.</param> - /// <returns>LibraryUpdateInfo.</returns> - private LibraryUpdateInfo GetLibraryUpdateInfo(IEnumerable<BaseItem> itemsAdded, IEnumerable<BaseItem> itemsUpdated, IEnumerable<BaseItem> itemsRemoved, IEnumerable<Folder> foldersAddedTo, IEnumerable<Folder> foldersRemovedFrom, Guid userId) - { - var user = _userManager.GetUserById(userId); - - return new LibraryUpdateInfo - { - ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(), - - ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(), - - ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, true)).Select(i => i.Id.ToString("N")).Distinct().ToList(), - - FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(), - - FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList() - }; - } - - private bool FilterItem(BaseItem item) - { - if (!item.IsFolder && item.LocationType == LocationType.Virtual) - { - return false; - } - - if (item is IItemByName && !(item is MusicArtist)) - { - return false; - } - - return item.SourceType == SourceType.Library; - } - - /// <summary> - /// Translates the physical item to user library. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="item">The item.</param> - /// <param name="user">The user.</param> - /// <param name="includeIfNotFound">if set to <c>true</c> [include if not found].</param> - /// <returns>IEnumerable{``0}.</returns> - private IEnumerable<T> TranslatePhysicalItemToUserLibrary<T>(T item, User user, bool includeIfNotFound = false) - where T : BaseItem - { - // If the physical root changed, return the user root - if (item is AggregateFolder) - { - return new[] { user.RootFolder as T }; - } - - // Return it only if it's in the user's library - if (includeIfNotFound || item.IsVisibleStandalone(user)) - { - return new[] { item }; - } - - return new T[] { }; - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - if (LibraryUpdateTimer != null) - { - LibraryUpdateTimer.Dispose(); - LibraryUpdateTimer = null; - } - - _libraryManager.ItemAdded -= libraryManager_ItemAdded; - _libraryManager.ItemUpdated -= libraryManager_ItemUpdated; - _libraryManager.ItemRemoved -= libraryManager_ItemRemoved; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs deleted file mode 100644 index f41d81137f..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs +++ /dev/null @@ -1,71 +0,0 @@ -using MediaBrowser.Common.Security; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Logging; -using System; -using System.Threading.Tasks; -using MediaBrowser.Common.Threading; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - /// <summary> - /// Class LoadRegistrations - /// </summary> - public class LoadRegistrations : IServerEntryPoint - { - /// <summary> - /// The _security manager - /// </summary> - private readonly ISecurityManager _securityManager; - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - private PeriodicTimer _timer; - - /// <summary> - /// Initializes a new instance of the <see cref="LoadRegistrations" /> class. - /// </summary> - /// <param name="securityManager">The security manager.</param> - /// <param name="logManager">The log manager.</param> - public LoadRegistrations(ISecurityManager securityManager, ILogManager logManager) - { - _securityManager = securityManager; - - _logger = logManager.GetLogger("Registration Loader"); - } - - /// <summary> - /// Runs this instance. - /// </summary> - public void Run() - { - _timer = new PeriodicTimer(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(12)); - } - - private async Task LoadAllRegistrations() - { - try - { - await _securityManager.LoadAllRegistrationInfo().ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error loading registration info", ex); - } - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs deleted file mode 100644 index f7fe707da3..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ /dev/null @@ -1,546 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Plugins; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Common.Updates; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Notifications; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Notifications; -using MediaBrowser.Model.Tasks; -using MediaBrowser.Model.Updates; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Entities.TV; - -namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications -{ - /// <summary> - /// Creates notifications for various system events - /// </summary> - public class Notifications : IServerEntryPoint - { - private readonly IInstallationManager _installationManager; - private readonly IUserManager _userManager; - private readonly ILogger _logger; - - private readonly ITaskManager _taskManager; - private readonly INotificationManager _notificationManager; - - private readonly ILibraryManager _libraryManager; - private readonly ISessionManager _sessionManager; - private readonly IServerApplicationHost _appHost; - - private Timer LibraryUpdateTimer { get; set; } - private readonly object _libraryChangedSyncLock = new object(); - - private readonly IConfigurationManager _config; - private readonly IDeviceManager _deviceManager; - - public Notifications(IInstallationManager installationManager, IUserManager userManager, ILogger logger, ITaskManager taskManager, INotificationManager notificationManager, ILibraryManager libraryManager, ISessionManager sessionManager, IServerApplicationHost appHost, IConfigurationManager config, IDeviceManager deviceManager) - { - _installationManager = installationManager; - _userManager = userManager; - _logger = logger; - _taskManager = taskManager; - _notificationManager = notificationManager; - _libraryManager = libraryManager; - _sessionManager = sessionManager; - _appHost = appHost; - _config = config; - _deviceManager = deviceManager; - } - - public void Run() - { - _installationManager.PluginInstalled += _installationManager_PluginInstalled; - _installationManager.PluginUpdated += _installationManager_PluginUpdated; - _installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed; - _installationManager.PluginUninstalled += _installationManager_PluginUninstalled; - - _taskManager.TaskCompleted += _taskManager_TaskCompleted; - - _userManager.UserCreated += _userManager_UserCreated; - _libraryManager.ItemAdded += _libraryManager_ItemAdded; - _sessionManager.PlaybackStart += _sessionManager_PlaybackStart; - _sessionManager.PlaybackStopped += _sessionManager_PlaybackStopped; - _appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged; - _appHost.HasUpdateAvailableChanged += _appHost_HasUpdateAvailableChanged; - _appHost.ApplicationUpdated += _appHost_ApplicationUpdated; - _deviceManager.CameraImageUploaded += _deviceManager_CameraImageUploaded; - - _userManager.UserLockedOut += _userManager_UserLockedOut; - } - - async void _userManager_UserLockedOut(object sender, GenericEventArgs<User> e) - { - var type = NotificationType.UserLockedOut.ToString(); - - var notification = new NotificationRequest - { - NotificationType = type - }; - - notification.Variables["UserName"] = e.Argument.Name; - - await SendNotification(notification).ConfigureAwait(false); - } - - async void _deviceManager_CameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e) - { - var type = NotificationType.CameraImageUploaded.ToString(); - - var notification = new NotificationRequest - { - NotificationType = type - }; - - notification.Variables["DeviceName"] = e.Argument.Device.Name; - - await SendNotification(notification).ConfigureAwait(false); - } - - async void _appHost_ApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e) - { - var type = NotificationType.ApplicationUpdateInstalled.ToString(); - - var notification = new NotificationRequest - { - NotificationType = type, - Url = e.Argument.infoUrl - }; - - notification.Variables["Version"] = e.Argument.versionStr; - notification.Variables["ReleaseNotes"] = e.Argument.description; - - await SendNotification(notification).ConfigureAwait(false); - } - - async void _installationManager_PluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e) - { - var type = NotificationType.PluginUpdateInstalled.ToString(); - - var installationInfo = e.Argument.Item1; - - var notification = new NotificationRequest - { - Description = e.Argument.Item2.description, - NotificationType = type - }; - - notification.Variables["Name"] = installationInfo.Name; - notification.Variables["Version"] = installationInfo.Version.ToString(); - notification.Variables["ReleaseNotes"] = e.Argument.Item2.description; - - await SendNotification(notification).ConfigureAwait(false); - } - - async void _installationManager_PluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> e) - { - var type = NotificationType.PluginInstalled.ToString(); - - var installationInfo = e.Argument; - - var notification = new NotificationRequest - { - Description = installationInfo.description, - NotificationType = type - }; - - notification.Variables["Name"] = installationInfo.name; - notification.Variables["Version"] = installationInfo.versionStr; - - await SendNotification(notification).ConfigureAwait(false); - } - - async void _appHost_HasUpdateAvailableChanged(object sender, EventArgs e) - { - // This notification is for users who can't auto-update (aka running as service) - if (!_appHost.HasUpdateAvailable || _appHost.CanSelfUpdate) - { - return; - } - - var type = NotificationType.ApplicationUpdateAvailable.ToString(); - - var notification = new NotificationRequest - { - Description = "Please see emby.media for details.", - NotificationType = type - }; - - await SendNotification(notification).ConfigureAwait(false); - } - - async void _appHost_HasPendingRestartChanged(object sender, EventArgs e) - { - if (!_appHost.HasPendingRestart) - { - return; - } - - var type = NotificationType.ServerRestartRequired.ToString(); - - var notification = new NotificationRequest - { - NotificationType = type - }; - - await SendNotification(notification).ConfigureAwait(false); - } - - private NotificationOptions GetOptions() - { - return _config.GetConfiguration<NotificationOptions>("notifications"); - } - - void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e) - { - var item = e.MediaInfo; - - if (item == null) - { - _logger.Warn("PlaybackStart reported with null media info."); - return; - } - - var video = e.Item as Video; - if (video != null && video.IsThemeMedia) - { - return; - } - - var type = GetPlaybackNotificationType(item.MediaType); - - SendPlaybackNotification(type, e); - } - - void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e) - { - var item = e.MediaInfo; - - if (item == null) - { - _logger.Warn("PlaybackStopped reported with null media info."); - return; - } - - var video = e.Item as Video; - if (video != null && video.IsThemeMedia) - { - return; - } - - var type = GetPlaybackStoppedNotificationType(item.MediaType); - - SendPlaybackNotification(type, e); - } - - private async void SendPlaybackNotification(string type, PlaybackProgressEventArgs e) - { - var user = e.Users.FirstOrDefault(); - - if (user != null && !GetOptions().IsEnabledToMonitorUser(type, user.Id.ToString("N"))) - { - return; - } - - var item = e.MediaInfo; - var themeMedia = item as IThemeMedia; - - if (themeMedia != null && themeMedia.IsThemeMedia) - { - // Don't report theme song or local trailer playback - return; - } - - var notification = new NotificationRequest - { - NotificationType = type - }; - - if (e.Item != null) - { - notification.Variables["ItemName"] = GetItemName(e.Item); - } - else - { - notification.Variables["ItemName"] = item.Name; - } - - notification.Variables["UserName"] = user == null ? "Unknown user" : user.Name; - notification.Variables["AppName"] = e.ClientName; - notification.Variables["DeviceName"] = e.DeviceName; - - await SendNotification(notification).ConfigureAwait(false); - } - - private string GetPlaybackNotificationType(string mediaType) - { - if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.AudioPlayback.ToString(); - } - if (string.Equals(mediaType, MediaType.Game, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.GamePlayback.ToString(); - } - if (string.Equals(mediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.VideoPlayback.ToString(); - } - - return null; - } - - private string GetPlaybackStoppedNotificationType(string mediaType) - { - if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.AudioPlaybackStopped.ToString(); - } - if (string.Equals(mediaType, MediaType.Game, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.GamePlaybackStopped.ToString(); - } - if (string.Equals(mediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.VideoPlaybackStopped.ToString(); - } - - return null; - } - - private readonly List<BaseItem> _itemsAdded = new List<BaseItem>(); - void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) - { - if (!FilterItem(e.Item)) - { - return; - } - - lock (_libraryChangedSyncLock) - { - if (LibraryUpdateTimer == null) - { - LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, 5000, - Timeout.Infinite); - } - else - { - LibraryUpdateTimer.Change(5000, Timeout.Infinite); - } - - _itemsAdded.Add(e.Item); - } - } - - private bool FilterItem(BaseItem item) - { - if (item.IsFolder) - { - return false; - } - - if (item.LocationType == LocationType.Virtual) - { - return false; - } - - if (item is IItemByName) - { - return false; - } - - return item.SourceType == SourceType.Library; - } - - private async void LibraryUpdateTimerCallback(object state) - { - List<BaseItem> items; - - lock (_libraryChangedSyncLock) - { - items = _itemsAdded.ToList(); - _itemsAdded.Clear(); - DisposeLibraryUpdateTimer(); - } - - items = items.Take(10).ToList(); - - foreach (var item in items) - { - var notification = new NotificationRequest - { - NotificationType = NotificationType.NewLibraryContent.ToString() - }; - - notification.Variables["Name"] = GetItemName(item); - - await SendNotification(notification).ConfigureAwait(false); - } - } - - public static string GetItemName(BaseItem item) - { - var name = item.Name; - var episode = item as Episode; - if (episode != null) - { - if (episode.IndexNumber.HasValue) - { - name = string.Format("Ep{0} - {1}", episode.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), name); - } - if (episode.ParentIndexNumber.HasValue) - { - name = string.Format("S{0}, {1}", episode.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture), name); - } - } - - var hasSeries = item as IHasSeries; - - if (hasSeries != null) - { - name = hasSeries.SeriesName + " - " + name; - } - - var hasArtist = item as IHasArtist; - if (hasArtist != null) - { - var artists = hasArtist.AllArtists; - - if (artists.Count > 0) - { - name = hasArtist.AllArtists[0] + " - " + name; - } - } - - return name; - } - - async void _userManager_UserCreated(object sender, GenericEventArgs<User> e) - { - var notification = new NotificationRequest - { - UserIds = new List<string> { e.Argument.Id.ToString("N") }, - Name = "Welcome to Emby!", - Description = "Check back here for more notifications." - }; - - await SendNotification(notification).ConfigureAwait(false); - } - - async void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) - { - var result = e.Result; - - if (result.Status == TaskCompletionStatus.Failed) - { - var type = NotificationType.TaskFailed.ToString(); - - var notification = new NotificationRequest - { - Description = result.ErrorMessage, - Level = NotificationLevel.Error, - NotificationType = type - }; - - notification.Variables["Name"] = result.Name; - notification.Variables["ErrorMessage"] = result.ErrorMessage; - - await SendNotification(notification).ConfigureAwait(false); - } - } - - async void _installationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e) - { - var type = NotificationType.PluginUninstalled.ToString(); - - var plugin = e.Argument; - - var notification = new NotificationRequest - { - NotificationType = type - }; - - notification.Variables["Name"] = plugin.Name; - notification.Variables["Version"] = plugin.Version.ToString(); - - await SendNotification(notification).ConfigureAwait(false); - } - - async void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e) - { - var installationInfo = e.InstallationInfo; - - var type = NotificationType.InstallationFailed.ToString(); - - var notification = new NotificationRequest - { - Level = NotificationLevel.Error, - Description = e.Exception.Message, - NotificationType = type - }; - - notification.Variables["Name"] = installationInfo.Name; - notification.Variables["Version"] = installationInfo.Version; - - await SendNotification(notification).ConfigureAwait(false); - } - - private async Task SendNotification(NotificationRequest notification) - { - try - { - await _notificationManager.SendNotification(notification, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending notification", ex); - } - } - - public void Dispose() - { - DisposeLibraryUpdateTimer(); - - _installationManager.PluginInstalled -= _installationManager_PluginInstalled; - _installationManager.PluginUpdated -= _installationManager_PluginUpdated; - _installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed; - _installationManager.PluginUninstalled -= _installationManager_PluginUninstalled; - - _taskManager.TaskCompleted -= _taskManager_TaskCompleted; - - _userManager.UserCreated -= _userManager_UserCreated; - _libraryManager.ItemAdded -= _libraryManager_ItemAdded; - _sessionManager.PlaybackStart -= _sessionManager_PlaybackStart; - - _appHost.HasPendingRestartChanged -= _appHost_HasPendingRestartChanged; - _appHost.HasUpdateAvailableChanged -= _appHost_HasUpdateAvailableChanged; - _appHost.ApplicationUpdated -= _appHost_ApplicationUpdated; - - _deviceManager.CameraImageUploaded -= _deviceManager_CameraImageUploaded; - _userManager.UserLockedOut -= _userManager_UserLockedOut; - } - - private void DisposeLibraryUpdateTimer() - { - if (LibraryUpdateTimer != null) - { - LibraryUpdateTimer.Dispose(); - LibraryUpdateTimer = null; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/WebSocketNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/WebSocketNotifier.cs deleted file mode 100644 index 916b4a6224..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/WebSocketNotifier.cs +++ /dev/null @@ -1,54 +0,0 @@ -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Notifications; -using MediaBrowser.Controller.Plugins; -using System.Linq; - -namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications -{ - /// <summary> - /// Notifies clients anytime a notification is added or udpated - /// </summary> - public class WebSocketNotifier : IServerEntryPoint - { - private readonly INotificationsRepository _notificationsRepo; - - private readonly IServerManager _serverManager; - - public WebSocketNotifier(INotificationsRepository notificationsRepo, IServerManager serverManager) - { - _notificationsRepo = notificationsRepo; - _serverManager = serverManager; - } - - public void Run() - { - _notificationsRepo.NotificationAdded += _notificationsRepo_NotificationAdded; - - _notificationsRepo.NotificationsMarkedRead += _notificationsRepo_NotificationsMarkedRead; - } - - void _notificationsRepo_NotificationsMarkedRead(object sender, NotificationReadEventArgs e) - { - var list = e.IdList.ToList(); - - list.Add(e.UserId); - list.Add(e.IsRead.ToString().ToLower()); - - var msg = string.Join("|", list.ToArray()); - - _serverManager.SendWebSocketMessage("NotificationsMarkedRead", msg); - } - - void _notificationsRepo_NotificationAdded(object sender, NotificationUpdateEventArgs e) - { - var msg = e.Notification.UserId + "|" + e.Notification.Id; - - _serverManager.SendWebSocketMessage("NotificationAdded", msg); - } - - public void Dispose() - { - _notificationsRepo.NotificationAdded -= _notificationsRepo_NotificationAdded; - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/RecordingNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/RecordingNotifier.cs deleted file mode 100644 index 414fda400b..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/RecordingNotifier.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Linq; -using System.Threading; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - public class RecordingNotifier : IServerEntryPoint - { - private readonly ILiveTvManager _liveTvManager; - private readonly ISessionManager _sessionManager; - private readonly IUserManager _userManager; - private readonly ILogger _logger; - - public RecordingNotifier(ISessionManager sessionManager, IUserManager userManager, ILogger logger, ILiveTvManager liveTvManager) - { - _sessionManager = sessionManager; - _userManager = userManager; - _logger = logger; - _liveTvManager = liveTvManager; - } - - public void Run() - { - _liveTvManager.TimerCancelled += _liveTvManager_TimerCancelled; - _liveTvManager.SeriesTimerCancelled += _liveTvManager_SeriesTimerCancelled; - _liveTvManager.TimerCreated += _liveTvManager_TimerCreated; - _liveTvManager.SeriesTimerCreated += _liveTvManager_SeriesTimerCreated; - } - - private void _liveTvManager_SeriesTimerCreated(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e) - { - SendMessage("SeriesTimerCreated", e.Argument); - } - - private void _liveTvManager_TimerCreated(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e) - { - SendMessage("TimerCreated", e.Argument); - } - - private void _liveTvManager_SeriesTimerCancelled(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e) - { - SendMessage("SeriesTimerCancelled", e.Argument); - } - - private void _liveTvManager_TimerCancelled(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e) - { - SendMessage("TimerCancelled", e.Argument); - } - - private async void SendMessage(string name, TimerEventInfo info) - { - var users = _userManager.Users.Where(i => i.Policy.EnableLiveTvAccess).Select(i => i.Id.ToString("N")).ToList(); - - try - { - await _sessionManager.SendMessageToUserSessions<TimerEventInfo>(users, name, info, CancellationToken.None); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending message", ex); - } - } - - public void Dispose() - { - _liveTvManager.TimerCancelled -= _liveTvManager_TimerCancelled; - _liveTvManager.SeriesTimerCancelled -= _liveTvManager_SeriesTimerCancelled; - _liveTvManager.TimerCreated -= _liveTvManager_TimerCreated; - _liveTvManager.SeriesTimerCreated -= _liveTvManager_SeriesTimerCreated; - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs b/MediaBrowser.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs deleted file mode 100644 index a0b7ff515c..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs +++ /dev/null @@ -1,41 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; -using System.Threading; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - /// <summary> - /// Class RefreshUsersMetadata - /// </summary> - public class RefreshUsersMetadata : IServerEntryPoint - { - /// <summary> - /// The _user manager - /// </summary> - private readonly IUserManager _userManager; - - /// <summary> - /// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class. - /// </summary> - /// <param name="userManager">The user manager.</param> - public RefreshUsersMetadata(IUserManager userManager) - { - _userManager = userManager; - } - - /// <summary> - /// Runs this instance. - /// </summary> - public async void Run() - { - await _userManager.RefreshUsersMetadata(CancellationToken.None).ConfigureAwait(false); - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs deleted file mode 100644 index 3ea8417f86..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ /dev/null @@ -1,203 +0,0 @@ -using MediaBrowser.Common.Plugins; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Common.Updates; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Sync; -using System; -using System.Collections.Generic; -using System.Threading; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - /// <summary> - /// Class WebSocketEvents - /// </summary> - public class ServerEventNotifier : IServerEntryPoint - { - /// <summary> - /// The _server manager - /// </summary> - private readonly IServerManager _serverManager; - - /// <summary> - /// The _user manager - /// </summary> - private readonly IUserManager _userManager; - - /// <summary> - /// The _installation manager - /// </summary> - private readonly IInstallationManager _installationManager; - - /// <summary> - /// The _kernel - /// </summary> - private readonly IServerApplicationHost _appHost; - - /// <summary> - /// The _task manager - /// </summary> - private readonly ITaskManager _taskManager; - - private readonly ISessionManager _sessionManager; - private readonly ISyncManager _syncManager; - - public ServerEventNotifier(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, ISessionManager sessionManager, ISyncManager syncManager) - { - _serverManager = serverManager; - _userManager = userManager; - _installationManager = installationManager; - _appHost = appHost; - _taskManager = taskManager; - _sessionManager = sessionManager; - _syncManager = syncManager; - } - - public void Run() - { - _userManager.UserDeleted += userManager_UserDeleted; - _userManager.UserUpdated += userManager_UserUpdated; - _userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated; - - _appHost.HasPendingRestartChanged += kernel_HasPendingRestartChanged; - - _installationManager.PluginUninstalled += InstallationManager_PluginUninstalled; - _installationManager.PackageInstalling += _installationManager_PackageInstalling; - _installationManager.PackageInstallationCancelled += _installationManager_PackageInstallationCancelled; - _installationManager.PackageInstallationCompleted += _installationManager_PackageInstallationCompleted; - _installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed; - - _taskManager.TaskCompleted += _taskManager_TaskCompleted; - _syncManager.SyncJobCreated += _syncManager_SyncJobCreated; - _syncManager.SyncJobCancelled += _syncManager_SyncJobCancelled; - } - - void _syncManager_SyncJobCancelled(object sender, GenericEventArgs<SyncJob> e) - { - _sessionManager.SendMessageToUserDeviceSessions(e.Argument.TargetId, "SyncJobCancelled", e.Argument, CancellationToken.None); - } - - void _syncManager_SyncJobCreated(object sender, GenericEventArgs<SyncJobCreationResult> e) - { - _sessionManager.SendMessageToUserDeviceSessions(e.Argument.Job.TargetId, "SyncJobCreated", e.Argument, CancellationToken.None); - } - - void _installationManager_PackageInstalling(object sender, InstallationEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstalling", e.InstallationInfo); - } - - void _installationManager_PackageInstallationCancelled(object sender, InstallationEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstallationCancelled", e.InstallationInfo); - } - - void _installationManager_PackageInstallationCompleted(object sender, InstallationEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstallationCompleted", e.InstallationInfo); - } - - void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstallationFailed", e.InstallationInfo); - } - - void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) - { - _serverManager.SendWebSocketMessage("ScheduledTaskEnded", e.Result); - } - - /// <summary> - /// Installations the manager_ plugin uninstalled. - /// </summary> - /// <param name="sender">The sender.</param> - /// <param name="e">The e.</param> - void InstallationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e) - { - _serverManager.SendWebSocketMessage("PluginUninstalled", e.Argument.GetPluginInfo()); - } - - /// <summary> - /// Handles the HasPendingRestartChanged event of the kernel control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> - void kernel_HasPendingRestartChanged(object sender, EventArgs e) - { - _sessionManager.SendRestartRequiredNotification(CancellationToken.None); - } - - /// <summary> - /// Users the manager_ user updated. - /// </summary> - /// <param name="sender">The sender.</param> - /// <param name="e">The e.</param> - void userManager_UserUpdated(object sender, GenericEventArgs<User> e) - { - var dto = _userManager.GetUserDto(e.Argument); - - SendMessageToUserSession(e.Argument, "UserUpdated", dto); - } - - /// <summary> - /// Users the manager_ user deleted. - /// </summary> - /// <param name="sender">The sender.</param> - /// <param name="e">The e.</param> - void userManager_UserDeleted(object sender, GenericEventArgs<User> e) - { - SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N")); - } - - void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs<User> e) - { - var dto = _userManager.GetUserDto(e.Argument); - - SendMessageToUserSession(e.Argument, "UserConfigurationUpdated", dto); - } - - private async void SendMessageToUserSession<T>(User user, string name, T data) - { - await _sessionManager.SendMessageToUserSessions(new List<string> { user.Id.ToString("N") }, name, data, CancellationToken.None); - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - _userManager.UserDeleted -= userManager_UserDeleted; - _userManager.UserUpdated -= userManager_UserUpdated; - _userManager.UserConfigurationUpdated -= _userManager_UserConfigurationUpdated; - - _installationManager.PluginUninstalled -= InstallationManager_PluginUninstalled; - _installationManager.PackageInstalling -= _installationManager_PackageInstalling; - _installationManager.PackageInstallationCancelled -= _installationManager_PackageInstallationCancelled; - _installationManager.PackageInstallationCompleted -= _installationManager_PackageInstallationCompleted; - _installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed; - - _appHost.HasPendingRestartChanged -= kernel_HasPendingRestartChanged; - _syncManager.SyncJobCreated -= _syncManager_SyncJobCreated; - _syncManager.SyncJobCancelled -= _syncManager_SyncJobCancelled; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs deleted file mode 100644 index 386c16513b..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ /dev/null @@ -1,92 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Server.Implementations.Udp; -using System.Net.Sockets; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - /// <summary> - /// Class UdpServerEntryPoint - /// </summary> - public class UdpServerEntryPoint : IServerEntryPoint - { - /// <summary> - /// Gets or sets the UDP server. - /// </summary> - /// <value>The UDP server.</value> - private UdpServer UdpServer { get; set; } - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - /// <summary> - /// The _network manager - /// </summary> - private readonly INetworkManager _networkManager; - private readonly IServerApplicationHost _appHost; - private readonly IJsonSerializer _json; - - public const int PortNumber = 7359; - - /// <summary> - /// Initializes a new instance of the <see cref="UdpServerEntryPoint" /> class. - /// </summary> - /// <param name="logger">The logger.</param> - /// <param name="networkManager">The network manager.</param> - /// <param name="appHost">The application host.</param> - /// <param name="json">The json.</param> - public UdpServerEntryPoint(ILogger logger, INetworkManager networkManager, IServerApplicationHost appHost, IJsonSerializer json) - { - _logger = logger; - _networkManager = networkManager; - _appHost = appHost; - _json = json; - } - - /// <summary> - /// Runs this instance. - /// </summary> - public void Run() - { - var udpServer = new UdpServer(_logger, _networkManager, _appHost, _json); - - try - { - udpServer.Start(PortNumber); - - UdpServer = udpServer; - } - catch (SocketException ex) - { - _logger.ErrorException("Failed to start UDP Server", ex); - } - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - if (UdpServer != null) - { - UdpServer.Dispose(); - } - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs deleted file mode 100644 index d14bd43689..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs +++ /dev/null @@ -1,133 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Configuration; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - /// <summary> - /// Class UsageEntryPoint - /// </summary> - public class UsageEntryPoint : IServerEntryPoint - { - private readonly IApplicationHost _applicationHost; - private readonly IHttpClient _httpClient; - private readonly ILogger _logger; - private readonly ISessionManager _sessionManager; - private readonly IUserManager _userManager; - private readonly IServerConfigurationManager _config; - - private readonly ConcurrentDictionary<Guid, ClientInfo> _apps = new ConcurrentDictionary<Guid, ClientInfo>(); - - public UsageEntryPoint(ILogger logger, IApplicationHost applicationHost, IHttpClient httpClient, ISessionManager sessionManager, IUserManager userManager, IServerConfigurationManager config) - { - _logger = logger; - _applicationHost = applicationHost; - _httpClient = httpClient; - _sessionManager = sessionManager; - _userManager = userManager; - _config = config; - - _sessionManager.SessionStarted += _sessionManager_SessionStarted; - } - - void _sessionManager_SessionStarted(object sender, SessionEventArgs e) - { - var session = e.SessionInfo; - - if (!string.IsNullOrEmpty(session.Client) && - !string.IsNullOrEmpty(session.DeviceName) && - !string.IsNullOrEmpty(session.DeviceId) && - !string.IsNullOrEmpty(session.ApplicationVersion)) - { - var keys = new List<string> - { - session.Client, - session.DeviceName, - session.DeviceId, - session.ApplicationVersion - }; - - var key = string.Join("_", keys.ToArray()).GetMD5(); - - _apps.GetOrAdd(key, guid => GetNewClientInfo(session)); - } - } - - private async void ReportNewSession(ClientInfo client) - { - if (!_config.Configuration.EnableAnonymousUsageReporting) - { - return; - } - - try - { - await new UsageReporter(_applicationHost, _httpClient, _userManager, _logger) - .ReportAppUsage(client, CancellationToken.None) - .ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending anonymous usage statistics.", ex); - } - } - - private ClientInfo GetNewClientInfo(SessionInfo session) - { - var info = new ClientInfo - { - AppName = session.Client, - AppVersion = session.ApplicationVersion, - DeviceName = session.DeviceName, - DeviceId = session.DeviceId - }; - - ReportNewSession(info); - - return info; - } - - public async void Run() - { - await Task.Delay(5000).ConfigureAwait(false); - OnTimerFired(); - } - - /// <summary> - /// Called when [timer fired]. - /// </summary> - private async void OnTimerFired() - { - if (!_config.Configuration.EnableAnonymousUsageReporting) - { - return; - } - - try - { - await new UsageReporter(_applicationHost, _httpClient, _userManager, _logger) - .ReportServerUsage(CancellationToken.None) - .ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending anonymous usage statistics.", ex); - } - } - - public void Dispose() - { - _sessionManager.SessionStarted -= _sessionManager_SessionStarted; - } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs deleted file mode 100644 index e445300e4d..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs +++ /dev/null @@ -1,138 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Connect; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - public class UsageReporter - { - private readonly IApplicationHost _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) - { - _applicationHost = applicationHost; - _httpClient = httpClient; - _userManager = userManager; - _logger = logger; - } - - public async Task ReportServerUsage(CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var data = new Dictionary<string, string> - { - { "feature", _applicationHost.Name }, - { "mac", _applicationHost.SystemId }, - { "serverid", _applicationHost.SystemId }, - { "deviceid", _applicationHost.SystemId }, - { "ver", _applicationHost.ApplicationVersion.ToString() }, - { "platform", _applicationHost.OperatingSystemDisplayName }, - { "isservice", _applicationHost.IsRunningAsService.ToString().ToLower()} - }; - - var users = _userManager.Users.ToList(); - - data["localusers"] = users.Count(i => !i.ConnectLinkType.HasValue).ToString(CultureInfo.InvariantCulture); - data["guests"] = users.Count(i => i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.Guest).ToString(CultureInfo.InvariantCulture); - data["linkedusers"] = users.Count(i => i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.LinkedUser).ToString(CultureInfo.InvariantCulture); - - data["plugins"] = string.Join(",", _applicationHost.Plugins.Select(i => i.Id).ToArray()); - - var logErrors = false; -#if DEBUG - logErrors = true; -#endif - var options = new HttpRequestOptions - { - Url = MbAdminUrl + "service/registration/ping", - CancellationToken = cancellationToken, - - // Seeing block length errors - EnableHttpCompression = false, - - LogRequest = false, - LogErrors = logErrors, - BufferContent = false - }; - - options.SetPostData(data); - - using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)) - { - - } - } - - public async Task ReportAppUsage(ClientInfo app, CancellationToken cancellationToken) - { - if (string.IsNullOrWhiteSpace(app.DeviceId)) - { - throw new ArgumentException("Client info must have a device Id"); - } - - _logger.Info("App Activity: app: {0}, version: {1}, deviceId: {2}, deviceName: {3}", - app.AppName ?? "Unknown App", - app.AppVersion ?? "Unknown", - app.DeviceId, - app.DeviceName ?? "Unknown"); - - cancellationToken.ThrowIfCancellationRequested(); - - var data = new Dictionary<string, string> - { - { "feature", app.AppName ?? "Unknown App" }, - { "serverid", _applicationHost.SystemId }, - { "deviceid", app.DeviceId }, - { "mac", app.DeviceId }, - { "ver", app.AppVersion ?? "Unknown" }, - { "platform", app.DeviceName }, - }; - - var logErrors = false; - -#if DEBUG - logErrors = true; -#endif - var options = new HttpRequestOptions - { - Url = MbAdminUrl + "service/registration/ping", - CancellationToken = cancellationToken, - - // Seeing block length errors - EnableHttpCompression = false, - - LogRequest = false, - LogErrors = logErrors, - BufferContent = false - }; - - options.SetPostData(data); - - using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)) - { - - } - } - } - - public class ClientInfo - { - public string AppName { get; set; } - public string AppVersion { get; set; } - public string DeviceName { get; set; } - public string DeviceId { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs deleted file mode 100644 index 2bb0101330..0000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs +++ /dev/null @@ -1,162 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Session; -using MoreLinq; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - class UserDataChangeNotifier : IServerEntryPoint - { - private readonly ISessionManager _sessionManager; - private readonly ILogger _logger; - private readonly IUserDataManager _userDataManager; - private readonly IUserManager _userManager; - - private readonly object _syncLock = new object(); - private Timer UpdateTimer { get; set; } - private const int UpdateDuration = 500; - - private readonly Dictionary<Guid, List<IHasUserData>> _changedItems = new Dictionary<Guid, List<IHasUserData>>(); - - public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, ILogger logger, IUserManager userManager) - { - _userDataManager = userDataManager; - _sessionManager = sessionManager; - _logger = logger; - _userManager = userManager; - } - - public void Run() - { - _userDataManager.UserDataSaved += _userDataManager_UserDataSaved; - } - - void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e) - { - if (e.SaveReason == UserDataSaveReason.PlaybackProgress) - { - return; - } - - lock (_syncLock) - { - if (UpdateTimer == null) - { - UpdateTimer = new Timer(UpdateTimerCallback, null, UpdateDuration, - Timeout.Infinite); - } - else - { - UpdateTimer.Change(UpdateDuration, Timeout.Infinite); - } - - List<IHasUserData> keys; - - if (!_changedItems.TryGetValue(e.UserId, out keys)) - { - keys = new List<IHasUserData>(); - _changedItems[e.UserId] = keys; - } - - keys.Add(e.Item); - - var baseItem = e.Item as BaseItem; - - // Go up one level for indicators - if (baseItem != null) - { - var parent = baseItem.GetParent(); - - if (parent != null) - { - keys.Add(parent); - } - } - } - } - - private void UpdateTimerCallback(object state) - { - lock (_syncLock) - { - // Remove dupes in case some were saved multiple times - var changes = _changedItems.ToList(); - _changedItems.Clear(); - - var task = SendNotifications(changes, CancellationToken.None); - - if (UpdateTimer != null) - { - UpdateTimer.Dispose(); - UpdateTimer = null; - } - } - } - - private async Task SendNotifications(IEnumerable<KeyValuePair<Guid, List<IHasUserData>>> changes, CancellationToken cancellationToken) - { - foreach (var pair in changes) - { - var userId = pair.Key; - var userSessions = _sessionManager.Sessions - .Where(u => u.ContainsUser(userId) && u.SessionController != null && u.IsActive) - .ToList(); - - if (userSessions.Count > 0) - { - var user = _userManager.GetUserById(userId); - - var dtoList = pair.Value - .DistinctBy(i => i.Id) - .Select(i => - { - var dto = _userDataManager.GetUserDataDto(i, user).Result; - dto.ItemId = i.Id.ToString("N"); - return dto; - }) - .ToList(); - - var info = new UserDataChangeInfo - { - UserId = userId.ToString("N"), - - UserDataList = dtoList - }; - - foreach (var userSession in userSessions) - { - try - { - await userSession.SessionController.SendUserDataChangeInfo(info, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending UserDataChanged message", ex); - } - } - } - - } - } - - public void Dispose() - { - if (UpdateTimer != null) - { - UpdateTimer.Dispose(); - UpdateTimer = null; - } - - _userDataManager.UserDataSaved -= _userDataManager_UserDataSaved; - } - } -} diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs deleted file mode 100644 index 5e01666a9a..0000000000 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ /dev/null @@ -1,829 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.FileOrganization; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.Library; -using MediaBrowser.Server.Implementations.Logging; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.FileOrganization -{ - public class EpisodeFileOrganizer - { - private readonly ILibraryMonitor _libraryMonitor; - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly IFileOrganizationService _organizationService; - private readonly IServerConfigurationManager _config; - private readonly IProviderManager _providerManager; - - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - public EpisodeFileOrganizer(IFileOrganizationService organizationService, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager) - { - _organizationService = organizationService; - _config = config; - _fileSystem = fileSystem; - _logger = logger; - _libraryManager = libraryManager; - _libraryMonitor = libraryMonitor; - _providerManager = providerManager; - } - - public async Task<FileOrganizationResult> OrganizeEpisodeFile(string path, AutoOrganizeOptions options, bool overwriteExisting, CancellationToken cancellationToken) - { - _logger.Info("Sorting file {0}", path); - - var result = new FileOrganizationResult - { - Date = DateTime.UtcNow, - OriginalPath = path, - OriginalFileName = Path.GetFileName(path), - Type = FileOrganizerType.Episode, - FileSize = new FileInfo(path).Length - }; - - try - { - 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 Naming.TV.EpisodeResolver(namingOptions, new PatternsLogger()); - - var episodeInfo = resolver.Resolve(path, false) ?? - new Naming.TV.EpisodeInfo(); - - var seriesName = episodeInfo.SeriesName; - - if (!string.IsNullOrEmpty(seriesName)) - { - var seasonNumber = episodeInfo.SeasonNumber; - - result.ExtractedSeasonNumber = seasonNumber; - - // Passing in true will include a few extra regex's - var episodeNumber = episodeInfo.EpisodeNumber; - - result.ExtractedEpisodeNumber = episodeNumber; - - 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) - { - _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 - { - var msg = string.Format("Unable to determine episode number 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); - - 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) - { - return previousResult; - } - } - - await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - result.Status = FileSortingStatus.Failure; - result.StatusMessage = ex.Message; - } - - return result; - } - - public async Task<FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, AutoOrganizeOptions options, CancellationToken cancellationToken) - { - 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; - - int year; - if (int.TryParse(request.NewSeriesYear, out year)) - { - series.ProductionYear = year; - } - - var seriesFolderName = series.Name; - if (series.ProductionYear.HasValue) - { - seriesFolderName = string.Format("{0} ({1})", seriesFolderName, series.ProductionYear); - } - - series.Path = Path.Combine(request.TargetFolder, seriesFolderName); - - series.ProviderIds = request.NewSeriesProviderIds; - - await series.RefreshMetadata(refreshOptions, cancellationToken); - } - - 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); - } - catch (Exception ex) - { - result.Status = FileSortingStatus.Failure; - result.StatusMessage = ex.Message; - } - - return result; - } - - private Task OrganizeEpisode(string sourcePath, - string seriesName, - int? seasonNumber, - int? episodeNumber, - int? endingEpiosdeNumber, - DateTime? premiereDate, - AutoOrganizeOptions options, - bool overwriteExisting, - bool rememberCorrection, - FileOrganizationResult result, - CancellationToken cancellationToken) - { - var series = GetMatchingSeries(seriesName, result, options); - - if (series == null) - { - var msg = string.Format("Unable to find series in library matching name {0}", seriesName); - result.Status = FileSortingStatus.Failure; - result.StatusMessage = msg; - _logger.Warn(msg); - return Task.FromResult(true); - } - - return OrganizeEpisode(sourcePath, - series, - seasonNumber, - episodeNumber, - endingEpiosdeNumber, - premiereDate, - options, - overwriteExisting, - rememberCorrection, - result, - cancellationToken); - } - - private async Task OrganizeEpisode(string sourcePath, - Series series, - int? seasonNumber, - int? episodeNumber, - int? endingEpiosdeNumber, - DateTime? premiereDate, - AutoOrganizeOptions options, - bool overwriteExisting, - bool rememberCorrection, - FileOrganizationResult result, - CancellationToken cancellationToken) - { - _logger.Info("Sorting file {0} into series {1}", sourcePath, series.Path); - - var originalExtractedSeriesString = result.ExtractedName; - - bool isNew = string.IsNullOrWhiteSpace(result.Id); - - if (isNew) - { - await _organizationService.SaveResult(result, cancellationToken); - } - - if (!_organizationService.AddToInProgressList(result, isNew)) - { - 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) - { - 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; - } - - if (fileExists) - { - 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; - } - - 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; - } - } - - PerformFileSorting(options.TvOptions, result); - - if (overwriteExisting) - { - var hasRenamedFiles = false; - - foreach (var path in otherDuplicatePaths) - { - _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; - result.StatusMessage = ex.Message; - _logger.Warn(ex.Message); - return; - } - finally - { - _organizationService.RemoveFromInprogressList(result); - } - - if (rememberCorrection) - { - SaveSmartMatchString(originalExtractedSeriesString, series, options); - } - } - - private void SaveSmartMatchString(string matchString, Series series, AutoOrganizeOptions options) - { - if (string.IsNullOrEmpty(matchString) || matchString.Length < 3) - { - return; - } - - SmartMatchInfo info = options.SmartMatchInfos.FirstOrDefault(i => string.Equals(i.ItemName, series.Name, StringComparison.OrdinalIgnoreCase)); - - if (info == null) - { - info = new SmartMatchInfo(); - info.ItemName = series.Name; - info.OrganizerType = FileOrganizerType.Episode; - info.DisplayName = series.Name; - var list = options.SmartMatchInfos.ToList(); - list.Add(info); - options.SmartMatchInfos = list.ToArray(); - } - - if (!info.MatchStrings.Contains(matchString, StringComparer.OrdinalIgnoreCase)) - { - var list = info.MatchStrings.ToList(); - list.Add(matchString); - info.MatchStrings = list.ToArray(); - _config.SaveAutoOrganizeOptions(options); - } - } - - private void DeleteLibraryFile(string path, bool renameRelatedFiles, string targetPath) - { - _fileSystem.DeleteFile(path); - - if (!renameRelatedFiles) - { - return; - } - - // Now find other files - var originalFilenameWithoutExtension = Path.GetFileNameWithoutExtension(path); - var directory = Path.GetDirectoryName(path); - - if (!string.IsNullOrWhiteSpace(originalFilenameWithoutExtension) && !string.IsNullOrWhiteSpace(directory)) - { - // Get all related files, e.g. metadata, images, etc - var files = _fileSystem.GetFilePaths(directory) - .Where(i => (Path.GetFileNameWithoutExtension(i) ?? string.Empty).StartsWith(originalFilenameWithoutExtension, StringComparison.OrdinalIgnoreCase)) - .ToList(); - - var targetFilenameWithoutExtension = Path.GetFileNameWithoutExtension(targetPath); - - foreach (var file in files) - { - directory = Path.GetDirectoryName(file); - var filename = Path.GetFileName(file); - - filename = filename.Replace(originalFilenameWithoutExtension, targetFilenameWithoutExtension, - StringComparison.OrdinalIgnoreCase); - - var destination = Path.Combine(directory, filename); - - _fileSystem.MoveFile(file, destination); - } - } - } - - private List<string> GetOtherDuplicatePaths(string targetPath, - Series series, - int? seasonNumber, - int? episodeNumber, - int? endingEpisodeNumber) - { - // TODO: Support date-naming? - if (!seasonNumber.HasValue || !episodeNumber.HasValue) - { - return new List<string>(); - } - - var episodePaths = series.GetRecursiveChildren() - .OfType<Episode>() - .Where(i => - { - var locationType = i.LocationType; - - // Must be file system based and match exactly - if (locationType != LocationType.Remote && - locationType != LocationType.Virtual && - i.ParentIndexNumber.HasValue && - i.ParentIndexNumber.Value == seasonNumber && - i.IndexNumber.HasValue && - i.IndexNumber.Value == episodeNumber) - { - - if (endingEpisodeNumber.HasValue || i.IndexNumberEnd.HasValue) - { - return endingEpisodeNumber.HasValue && i.IndexNumberEnd.HasValue && - endingEpisodeNumber.Value == i.IndexNumberEnd.Value; - } - - return true; - } - - return false; - }) - .Select(i => i.Path) - .ToList(); - - var folder = Path.GetDirectoryName(targetPath); - var targetFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(targetPath); - - try - { - var filesOfOtherExtensions = _fileSystem.GetFilePaths(folder) - .Where(i => _libraryManager.IsVideoFile(i) && string.Equals(_fileSystem.GetFileNameWithoutExtension(i), targetFileNameWithoutExtension, StringComparison.OrdinalIgnoreCase)); - - episodePaths.AddRange(filesOfOtherExtensions); - } - catch (DirectoryNotFoundException) - { - // No big deal. Maybe the season folder doesn't already exist. - } - - return episodePaths.Where(i => !string.Equals(i, targetPath, StringComparison.OrdinalIgnoreCase)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToList(); - } - - private void PerformFileSorting(TvFileOrganizationOptions options, FileOrganizationResult result) - { - _libraryMonitor.ReportFileSystemChangeBeginning(result.TargetPath); - - _fileSystem.CreateDirectory(Path.GetDirectoryName(result.TargetPath)); - - var targetAlreadyExists = _fileSystem.FileExists(result.TargetPath); - - try - { - if (targetAlreadyExists || options.CopyOriginalFile) - { - _fileSystem.CopyFile(result.OriginalPath, result.TargetPath, true); - } - else - { - _fileSystem.MoveFile(result.OriginalPath, result.TargetPath); - } - - result.Status = FileSortingStatus.Success; - result.StatusMessage = string.Empty; - } - catch (Exception ex) - { - var errorMsg = string.Format("Failed to move file from {0} to {1}: {2}", result.OriginalPath, result.TargetPath, ex.Message); - - result.Status = FileSortingStatus.Failure; - result.StatusMessage = errorMsg; - _logger.ErrorException(errorMsg, ex); - - return; - } - finally - { - _libraryMonitor.ReportFileSystemChangeComplete(result.TargetPath, true); - } - - if (targetAlreadyExists && !options.CopyOriginalFile) - { - try - { - _fileSystem.DeleteFile(result.OriginalPath); - } - catch (Exception ex) - { - _logger.ErrorException("Error deleting {0}", ex, result.OriginalPath); - } - } - } - - private Series GetMatchingSeries(string seriesName, FileOrganizationResult result, AutoOrganizeOptions options) - { - var parsedName = _libraryManager.ParseName(seriesName); - - var yearInName = parsedName.Year; - var nameWithoutYear = parsedName.Name; - - result.ExtractedName = nameWithoutYear; - result.ExtractedYear = yearInName; - - var series = _libraryManager.GetItemList(new Controller.Entities.InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Series).Name }, - Recursive = true - }) - .Cast<Series>() - .Select(i => NameUtils.GetMatchScore(nameWithoutYear, yearInName, i)) - .Where(i => i.Item2 > 0) - .OrderByDescending(i => i.Item2) - .Select(i => i.Item1) - .FirstOrDefault(); - - if (series == null) - { - SmartMatchInfo info = options.SmartMatchInfos.FirstOrDefault(e => e.MatchStrings.Contains(nameWithoutYear, StringComparer.OrdinalIgnoreCase)); - - if (info != null) - { - series = _libraryManager.GetItemList(new Controller.Entities.InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Series).Name }, - Recursive = true, - Name = info.ItemName - - }).Cast<Series>().FirstOrDefault(); - } - } - - return series; - } - - /// <summary> - /// Gets the new path. - /// </summary> - /// <param name="sourcePath">The source path.</param> - /// <param name="series">The series.</param> - /// <param name="seasonNumber">The season number.</param> - /// <param name="episodeNumber">The episode number.</param> - /// <param name="endingEpisodeNumber">The ending episode number.</param> - /// <param name="premiereDate">The premiere date.</param> - /// <param name="options">The options.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>System.String.</returns> - private async Task<string> GetNewPath(string sourcePath, - Series series, - int? seasonNumber, - int? episodeNumber, - int? endingEpisodeNumber, - DateTime? premiereDate, - TvFileOrganizationOptions options, - CancellationToken cancellationToken) - { - var episodeInfo = new EpisodeInfo - { - IndexNumber = episodeNumber, - IndexNumberEnd = endingEpisodeNumber, - MetadataCountryCode = series.GetPreferredMetadataCountryCode(), - MetadataLanguage = series.GetPreferredMetadataLanguage(), - ParentIndexNumber = seasonNumber, - SeriesProviderIds = series.ProviderIds, - PremiereDate = premiereDate - }; - - var searchResults = await _providerManager.GetRemoteSearchResults<Episode, EpisodeInfo>(new RemoteSearchQuery<EpisodeInfo> - { - SearchInfo = episodeInfo - - }, cancellationToken).ConfigureAwait(false); - - var episode = searchResults.FirstOrDefault(); - - if (episode == null) - { - var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber); - _logger.Warn(msg); - throw new Exception(msg); - } - - var episodeName = episode.Name; - - //if (string.IsNullOrWhiteSpace(episodeName)) - //{ - // var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber); - // _logger.Warn(msg); - // return null; - //} - - seasonNumber = seasonNumber ?? episode.ParentIndexNumber; - episodeNumber = episodeNumber ?? episode.IndexNumber; - - var newPath = GetSeasonFolderPath(series, seasonNumber.Value, options); - - // MAX_PATH - trailing <NULL> charachter - drive component: 260 - 1 - 3 = 256 - // Usually newPath would include the drive component, but use 256 to be sure - var maxFilenameLength = 256 - newPath.Length; - - if (!newPath.EndsWith(@"\")) - { - // Remove 1 for missing backslash combining path and filename - maxFilenameLength--; - } - - // Remove additional 4 chars to prevent PathTooLongException for downloaded subtitles (eg. filename.ext.eng.srt) - maxFilenameLength -= 4; - - var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber.Value, episodeNumber.Value, endingEpisodeNumber, episodeName, options, maxFilenameLength); - - if (string.IsNullOrEmpty(episodeFileName)) - { - // cause failure - return string.Empty; - } - - newPath = Path.Combine(newPath, episodeFileName); - - return newPath; - } - - /// <summary> - /// Gets the season folder path. - /// </summary> - /// <param name="series">The series.</param> - /// <param name="seasonNumber">The season number.</param> - /// <param name="options">The options.</param> - /// <returns>System.String.</returns> - private string GetSeasonFolderPath(Series series, int seasonNumber, TvFileOrganizationOptions options) - { - // If there's already a season folder, use that - var season = series - .GetRecursiveChildren(i => i is Season && i.LocationType == LocationType.FileSystem && i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber) - .FirstOrDefault(); - - if (season != null) - { - return season.Path; - } - - var path = series.Path; - - if (series.ContainsEpisodesWithoutSeasonFolders) - { - return path; - } - - if (seasonNumber == 0) - { - return Path.Combine(path, _fileSystem.GetValidFilename(options.SeasonZeroFolderName)); - } - - var seasonFolderName = options.SeasonFolderPattern - .Replace("%s", seasonNumber.ToString(_usCulture)) - .Replace("%0s", seasonNumber.ToString("00", _usCulture)) - .Replace("%00s", seasonNumber.ToString("000", _usCulture)); - - return Path.Combine(path, _fileSystem.GetValidFilename(seasonFolderName)); - } - - private string GetEpisodeFileName(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, string episodeTitle, TvFileOrganizationOptions options, int? maxLength) - { - seriesName = _fileSystem.GetValidFilename(seriesName).Trim(); - - if (string.IsNullOrWhiteSpace(episodeTitle)) - { - episodeTitle = string.Empty; - } - else - { - episodeTitle = _fileSystem.GetValidFilename(episodeTitle).Trim(); - } - - var sourceExtension = (Path.GetExtension(sourcePath) ?? string.Empty).TrimStart('.'); - - var pattern = endingEpisodeNumber.HasValue ? options.MultiEpisodeNamePattern : options.EpisodeNamePattern; - - if (string.IsNullOrWhiteSpace(pattern)) - { - throw new Exception("GetEpisodeFileName: Configured episode name pattern is empty!"); - } - - var result = pattern.Replace("%sn", seriesName) - .Replace("%s.n", seriesName.Replace(" ", ".")) - .Replace("%s_n", seriesName.Replace(" ", "_")) - .Replace("%s", seasonNumber.ToString(_usCulture)) - .Replace("%0s", seasonNumber.ToString("00", _usCulture)) - .Replace("%00s", seasonNumber.ToString("000", _usCulture)) - .Replace("%ext", sourceExtension) - .Replace("%en", "%#1") - .Replace("%e.n", "%#2") - .Replace("%e_n", "%#3"); - - if (endingEpisodeNumber.HasValue) - { - result = result.Replace("%ed", endingEpisodeNumber.Value.ToString(_usCulture)) - .Replace("%0ed", endingEpisodeNumber.Value.ToString("00", _usCulture)) - .Replace("%00ed", endingEpisodeNumber.Value.ToString("000", _usCulture)); - } - - result = result.Replace("%e", episodeNumber.ToString(_usCulture)) - .Replace("%0e", episodeNumber.ToString("00", _usCulture)) - .Replace("%00e", episodeNumber.ToString("000", _usCulture)); - - if (maxLength.HasValue && result.Contains("%#")) - { - // Substract 3 for the temp token length (%#1, %#2 or %#3) - int maxRemainingTitleLength = maxLength.Value - result.Length + 3; - string shortenedEpisodeTitle = string.Empty; - - if (maxRemainingTitleLength > 5) - { - // A title with fewer than 5 letters wouldn't be of much value - shortenedEpisodeTitle = episodeTitle.Substring(0, Math.Min(maxRemainingTitleLength, episodeTitle.Length)); - } - - result = result.Replace("%#1", shortenedEpisodeTitle) - .Replace("%#2", shortenedEpisodeTitle.Replace(" ", ".")) - .Replace("%#3", shortenedEpisodeTitle.Replace(" ", "_")); - } - - if (maxLength.HasValue && result.Length > maxLength.Value) - { - // There may be cases where reducing the title length may still not be sufficient to - // stay below maxLength - var msg = string.Format("Unable to generate an episode file name shorter than {0} characters to constrain to the max path limit", maxLength); - throw new Exception(msg); - } - - return result; - } - - private bool IsSameEpisode(string sourcePath, string newPath) - { - try - { - var sourceFileInfo = new FileInfo(sourcePath); - var destinationFileInfo = new FileInfo(newPath); - - if (sourceFileInfo.Length == destinationFileInfo.Length) - { - return true; - } - } - catch (FileNotFoundException) - { - return false; - } - catch (DirectoryNotFoundException) - { - return false; - } - - return false; - } - } -} diff --git a/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs b/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs deleted file mode 100644 index c560152dbe..0000000000 --- a/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.FileOrganization; -using System.Collections.Generic; - -namespace MediaBrowser.Server.Implementations.FileOrganization -{ - public static class ConfigurationExtension - { - public static AutoOrganizeOptions GetAutoOrganizeOptions(this IConfigurationManager manager) - { - return manager.GetConfiguration<AutoOrganizeOptions>("autoorganize"); - } - public static void SaveAutoOrganizeOptions(this IConfigurationManager manager, AutoOrganizeOptions options) - { - manager.SaveConfiguration("autoorganize", options); - } - } - - public class AutoOrganizeOptionsFactory : IConfigurationFactory - { - public IEnumerable<ConfigurationStore> GetConfigurations() - { - return new List<ConfigurationStore> - { - new ConfigurationStore - { - Key = "autoorganize", - ConfigurationType = typeof (AutoOrganizeOptions) - } - }; - } - } -} diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationNotifier.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationNotifier.cs deleted file mode 100644 index 5c3814f669..0000000000 --- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationNotifier.cs +++ /dev/null @@ -1,80 +0,0 @@ -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.FileOrganization; -using MediaBrowser.Model.Logging; -using System; -using System.Threading; - -namespace MediaBrowser.Server.Implementations.FileOrganization -{ - /// <summary> - /// Class SessionInfoWebSocketListener - /// </summary> - class FileOrganizationNotifier : IServerEntryPoint - { - private readonly IFileOrganizationService _organizationService; - private readonly ISessionManager _sessionManager; - private readonly ITaskManager _taskManager; - - public FileOrganizationNotifier(ILogger logger, IFileOrganizationService organizationService, ISessionManager sessionManager, ITaskManager taskManager) - { - _organizationService = organizationService; - _sessionManager = sessionManager; - _taskManager = taskManager; - } - - public void Run() - { - _organizationService.ItemAdded += _organizationService_ItemAdded; - _organizationService.ItemRemoved += _organizationService_ItemRemoved; - _organizationService.ItemUpdated += _organizationService_ItemUpdated; - _organizationService.LogReset += _organizationService_LogReset; - - //_taskManager.TaskCompleted += _taskManager_TaskCompleted; - } - - private void _organizationService_LogReset(object sender, EventArgs e) - { - _sessionManager.SendMessageToAdminSessions("AutoOrganize_LogReset", (FileOrganizationResult)null, CancellationToken.None); - } - - private void _organizationService_ItemUpdated(object sender, GenericEventArgs<FileOrganizationResult> e) - { - _sessionManager.SendMessageToAdminSessions("AutoOrganize_ItemUpdated", e.Argument, CancellationToken.None); - } - - private void _organizationService_ItemRemoved(object sender, GenericEventArgs<FileOrganizationResult> e) - { - _sessionManager.SendMessageToAdminSessions("AutoOrganize_ItemRemoved", e.Argument, CancellationToken.None); - } - - private void _organizationService_ItemAdded(object sender, GenericEventArgs<FileOrganizationResult> e) - { - _sessionManager.SendMessageToAdminSessions("AutoOrganize_ItemAdded", e.Argument, CancellationToken.None); - } - - //private void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e) - //{ - // var taskWithKey = e.Task.ScheduledTask as IHasKey; - // if (taskWithKey != null && taskWithKey.Key == "AutoOrganize") - // { - // _sessionManager.SendMessageToAdminSessions("AutoOrganize_TaskCompleted", (FileOrganizationResult)null, CancellationToken.None); - // } - //} - - public void Dispose() - { - _organizationService.ItemAdded -= _organizationService_ItemAdded; - _organizationService.ItemRemoved -= _organizationService_ItemRemoved; - _organizationService.ItemUpdated -= _organizationService_ItemUpdated; - _organizationService.LogReset -= _organizationService_LogReset; - - //_taskManager.TaskCompleted -= _taskManager_TaskCompleted; - } - - - } -} diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs deleted file mode 100644 index a42eba6cae..0000000000 --- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs +++ /dev/null @@ -1,281 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.FileOrganization; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using System; -using System.Collections.Concurrent; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Events; -using MediaBrowser.Common.Events; - -namespace MediaBrowser.Server.Implementations.FileOrganization -{ - public class FileOrganizationService : IFileOrganizationService - { - private readonly ITaskManager _taskManager; - private readonly IFileOrganizationRepository _repo; - private readonly ILogger _logger; - private readonly ILibraryMonitor _libraryMonitor; - private readonly ILibraryManager _libraryManager; - private readonly IServerConfigurationManager _config; - private readonly IFileSystem _fileSystem; - private readonly IProviderManager _providerManager; - private readonly ConcurrentDictionary<string, bool> _inProgressItemIds = new ConcurrentDictionary<string, bool>(); - - public event EventHandler<GenericEventArgs<FileOrganizationResult>> ItemAdded; - public event EventHandler<GenericEventArgs<FileOrganizationResult>> ItemUpdated; - public event EventHandler<GenericEventArgs<FileOrganizationResult>> ItemRemoved; - public event EventHandler LogReset; - - public FileOrganizationService(ITaskManager taskManager, IFileOrganizationRepository repo, ILogger logger, ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager) - { - _taskManager = taskManager; - _repo = repo; - _logger = logger; - _libraryMonitor = libraryMonitor; - _libraryManager = libraryManager; - _config = config; - _fileSystem = fileSystem; - _providerManager = providerManager; - } - - public void BeginProcessNewFiles() - { - _taskManager.CancelIfRunningAndQueue<OrganizerScheduledTask>(); - } - - public Task SaveResult(FileOrganizationResult result, CancellationToken cancellationToken) - { - if (result == null || string.IsNullOrEmpty(result.OriginalPath)) - { - throw new ArgumentNullException("result"); - } - - result.Id = result.OriginalPath.GetMD5().ToString("N"); - - return _repo.SaveResult(result, cancellationToken); - } - - public QueryResult<FileOrganizationResult> GetResults(FileOrganizationResultQuery query) - { - var results = _repo.GetResults(query); - - foreach (var result in results.Items) - { - result.IsInProgress = _inProgressItemIds.ContainsKey(result.Id); - } - - return results; - } - - public FileOrganizationResult GetResult(string id) - { - var result = _repo.GetResult(id); - - if (result != null) - { - result.IsInProgress = _inProgressItemIds.ContainsKey(result.Id); - } - - return result; - } - - public FileOrganizationResult GetResultBySourcePath(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException("path"); - } - - var id = path.GetMD5().ToString("N"); - - return GetResult(id); - } - - public async Task DeleteOriginalFile(string resultId) - { - var result = _repo.GetResult(resultId); - - _logger.Info("Requested to delete {0}", result.OriginalPath); - - if (!AddToInProgressList(result, false)) - { - throw new Exception("Path is currently processed otherwise. Please try again later."); - } - - try - { - _fileSystem.DeleteFile(result.OriginalPath); - } - catch (Exception ex) - { - _logger.ErrorException("Error deleting {0}", ex, result.OriginalPath); - } - finally - { - RemoveFromInprogressList(result); - } - - await _repo.Delete(resultId); - - EventHelper.FireEventIfNotNull(ItemRemoved, this, new GenericEventArgs<FileOrganizationResult>(result), _logger); - } - - private AutoOrganizeOptions GetAutoOrganizeOptions() - { - return _config.GetAutoOrganizeOptions(); - } - - public async Task PerformOrganization(string resultId) - { - var result = _repo.GetResult(resultId); - - if (string.IsNullOrEmpty(result.TargetPath)) - { - throw new ArgumentException("No target path available."); - } - - var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, - _libraryMonitor, _providerManager); - - var organizeResult = await organizer.OrganizeEpisodeFile(result.OriginalPath, GetAutoOrganizeOptions(), true, CancellationToken.None) - .ConfigureAwait(false); - - if (organizeResult.Status != FileSortingStatus.Success) - { - throw new Exception(result.StatusMessage); - } - } - - public async Task ClearLog() - { - await _repo.DeleteAll(); - EventHelper.FireEventIfNotNull(LogReset, this, EventArgs.Empty, _logger); - } - - public async Task PerformEpisodeOrganization(EpisodeFileOrganizationRequest request) - { - var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, - _libraryMonitor, _providerManager); - - var result = await organizer.OrganizeWithCorrection(request, GetAutoOrganizeOptions(), CancellationToken.None).ConfigureAwait(false); - - if (result.Status != FileSortingStatus.Success) - { - throw new Exception(result.StatusMessage); - } - } - - public QueryResult<SmartMatchInfo> GetSmartMatchInfos(FileOrganizationResultQuery query) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - var options = GetAutoOrganizeOptions(); - - var items = options.SmartMatchInfos.Skip(query.StartIndex ?? 0).Take(query.Limit ?? Int32.MaxValue).ToArray(); - - return new QueryResult<SmartMatchInfo>() - { - Items = items, - TotalRecordCount = options.SmartMatchInfos.Length - }; - } - - public void DeleteSmartMatchEntry(string itemName, string matchString) - { - if (string.IsNullOrEmpty(itemName)) - { - throw new ArgumentNullException("itemName"); - } - - if (string.IsNullOrEmpty(matchString)) - { - throw new ArgumentNullException("matchString"); - } - - var options = GetAutoOrganizeOptions(); - - SmartMatchInfo info = options.SmartMatchInfos.FirstOrDefault(i => string.Equals(i.ItemName, itemName)); - - if (info != null && info.MatchStrings.Contains(matchString)) - { - var list = info.MatchStrings.ToList(); - list.Remove(matchString); - info.MatchStrings = list.ToArray(); - - if (info.MatchStrings.Length == 0) - { - var infos = options.SmartMatchInfos.ToList(); - infos.Remove(info); - options.SmartMatchInfos = infos.ToArray(); - } - - _config.SaveAutoOrganizeOptions(options); - } - } - - /// <summary> - /// Attempts to add a an item to the list of currently processed items. - /// </summary> - /// <param name="result">The result item.</param> - /// <param name="isNewItem">Passing true will notify the client to reload all items, otherwise only a single item will be refreshed.</param> - /// <returns>True if the item was added, False if the item is already contained in the list.</returns> - public bool AddToInProgressList(FileOrganizationResult result, bool isNewItem) - { - if (string.IsNullOrWhiteSpace(result.Id)) - { - result.Id = result.OriginalPath.GetMD5().ToString("N"); - } - - if (!_inProgressItemIds.TryAdd(result.Id, false)) - { - return false; - } - - result.IsInProgress = true; - - if (isNewItem) - { - EventHelper.FireEventIfNotNull(ItemAdded, this, new GenericEventArgs<FileOrganizationResult>(result), _logger); - } - else - { - EventHelper.FireEventIfNotNull(ItemUpdated, this, new GenericEventArgs<FileOrganizationResult>(result), _logger); - } - - return true; - } - - /// <summary> - /// Removes an item from the list of currently processed items. - /// </summary> - /// <param name="result">The result item.</param> - /// <returns>True if the item was removed, False if the item was not contained in the list.</returns> - public bool RemoveFromInprogressList(FileOrganizationResult result) - { - bool itemValue; - var retval = _inProgressItemIds.TryRemove(result.Id, out itemValue); - - result.IsInProgress = false; - - EventHelper.FireEventIfNotNull(ItemUpdated, this, new GenericEventArgs<FileOrganizationResult>(result), _logger); - - return retval; - } - - } -} diff --git a/MediaBrowser.Server.Implementations/FileOrganization/NameUtils.cs b/MediaBrowser.Server.Implementations/FileOrganization/NameUtils.cs deleted file mode 100644 index 624133d4fb..0000000000 --- a/MediaBrowser.Server.Implementations/FileOrganization/NameUtils.cs +++ /dev/null @@ -1,96 +0,0 @@ -using MediaBrowser.Model.Extensions; -using MediaBrowser.Controller.Entities; -using System; -using System.Globalization; -using System.Linq; -using System.Text; - -namespace MediaBrowser.Server.Implementations.FileOrganization -{ - public static class NameUtils - { - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - internal static Tuple<T, int> GetMatchScore<T>(string sortedName, int? year, T series) - where T : BaseItem - { - var score = 0; - - var seriesNameWithoutYear = series.Name; - if (series.ProductionYear.HasValue) - { - seriesNameWithoutYear = seriesNameWithoutYear.Replace(series.ProductionYear.Value.ToString(UsCulture), String.Empty); - } - - if (IsNameMatch(sortedName, seriesNameWithoutYear)) - { - score++; - - if (year.HasValue && series.ProductionYear.HasValue) - { - if (year.Value == series.ProductionYear.Value) - { - score++; - } - else - { - // Regardless of name, return a 0 score if the years don't match - return new Tuple<T, int>(series, 0); - } - } - } - - return new Tuple<T, int>(series, score); - } - - - private static bool IsNameMatch(string name1, string name2) - { - name1 = GetComparableName(name1); - name2 = GetComparableName(name2); - - return String.Equals(name1, name2, StringComparison.OrdinalIgnoreCase); - } - - private static string GetComparableName(string name) - { - name = RemoveDiacritics(name); - - name = " " + name + " "; - - name = name.Replace(".", " ") - .Replace("_", " ") - .Replace(" and ", " ") - .Replace(".and.", " ") - .Replace("&", " ") - .Replace("!", " ") - .Replace("(", " ") - .Replace(")", " ") - .Replace(":", " ") - .Replace(",", " ") - .Replace("-", " ") - .Replace("'", " ") - .Replace("[", " ") - .Replace("]", " ") - .Replace(" a ", String.Empty, StringComparison.OrdinalIgnoreCase) - .Replace(" the ", String.Empty, StringComparison.OrdinalIgnoreCase) - .Replace(" ", String.Empty); - - return name.Trim(); - } - - /// <summary> - /// Removes the diacritics. - /// </summary> - /// <param name="text">The text.</param> - /// <returns>System.String.</returns> - private static string RemoveDiacritics(string text) - { - return String.Concat( - text.Normalize(NormalizationForm.FormD) - .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) != - UnicodeCategory.NonSpacingMark) - ).Normalize(NormalizationForm.FormC); - } - } -} diff --git a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs deleted file mode 100644 index de98b83ef2..0000000000 --- a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs +++ /dev/null @@ -1,94 +0,0 @@ -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.FileOrganization; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.FileOrganization -{ - public class OrganizerScheduledTask : IScheduledTask, IConfigurableScheduledTask, IScheduledTaskActivityLog, IHasKey - { - private readonly ILibraryMonitor _libraryMonitor; - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly IServerConfigurationManager _config; - private readonly IFileOrganizationService _organizationService; - private readonly IProviderManager _providerManager; - - public OrganizerScheduledTask(ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IServerConfigurationManager config, IFileOrganizationService organizationService, IProviderManager providerManager) - { - _libraryMonitor = libraryMonitor; - _libraryManager = libraryManager; - _logger = logger; - _fileSystem = fileSystem; - _config = config; - _organizationService = organizationService; - _providerManager = providerManager; - } - - public string Name - { - get { return "Organize new media files"; } - } - - public string Description - { - get { return "Processes new files available in the configured watch folder."; } - } - - public string Category - { - get { return "Library"; } - } - - private AutoOrganizeOptions GetAutoOrganizeOptions() - { - return _config.GetAutoOrganizeOptions(); - } - - public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - if (GetAutoOrganizeOptions().TvOptions.IsEnabled) - { - await new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config, _providerManager) - .Organize(GetAutoOrganizeOptions(), cancellationToken, progress).ConfigureAwait(false); - } - } - - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - return new ITaskTrigger[] - { - new IntervalTrigger{ Interval = TimeSpan.FromMinutes(5)} - }; - } - - public bool IsHidden - { - get { return !GetAutoOrganizeOptions().TvOptions.IsEnabled; } - } - - public bool IsEnabled - { - get { return GetAutoOrganizeOptions().TvOptions.IsEnabled; } - } - - public bool IsActivityLogged - { - get { return false; } - } - - public string Key - { - get { return "AutoOrganize"; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs deleted file mode 100644 index 4f42d8a20d..0000000000 --- a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs +++ /dev/null @@ -1,208 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.FileOrganization; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.FileOrganization -{ - public class TvFolderOrganizer - { - private readonly ILibraryMonitor _libraryMonitor; - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly IFileOrganizationService _organizationService; - private readonly IServerConfigurationManager _config; - private readonly IProviderManager _providerManager; - - public TvFolderOrganizer(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IFileOrganizationService organizationService, IServerConfigurationManager config, IProviderManager providerManager) - { - _libraryManager = libraryManager; - _logger = logger; - _fileSystem = fileSystem; - _libraryMonitor = libraryMonitor; - _organizationService = organizationService; - _config = config; - _providerManager = providerManager; - } - - private bool EnableOrganization(FileSystemMetadata fileInfo, TvFileOrganizationOptions options) - { - var minFileBytes = options.MinFileSizeMb * 1024 * 1024; - - try - { - return _libraryManager.IsVideoFile(fileInfo.FullName) && fileInfo.Length >= minFileBytes; - } - catch (Exception ex) - { - _logger.ErrorException("Error organizing file {0}", ex, fileInfo.Name); - } - - return false; - } - - public async Task Organize(AutoOrganizeOptions options, CancellationToken cancellationToken, IProgress<double> progress) - { - var watchLocations = options.TvOptions.WatchLocations.ToList(); - - var eligibleFiles = watchLocations.SelectMany(GetFilesToOrganize) - .OrderBy(_fileSystem.GetCreationTimeUtc) - .Where(i => EnableOrganization(i, options.TvOptions)) - .ToList(); - - var processedFolders = new HashSet<string>(); - - progress.Report(10); - - if (eligibleFiles.Count > 0) - { - var numComplete = 0; - - foreach (var file in eligibleFiles) - { - var organizer = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager, - _libraryMonitor, _providerManager); - - try - { - var result = await organizer.OrganizeEpisodeFile(file.FullName, options, options.TvOptions.OverwriteExistingEpisodes, cancellationToken).ConfigureAwait(false); - if (result.Status == FileSortingStatus.Success && !processedFolders.Contains(file.DirectoryName, StringComparer.OrdinalIgnoreCase)) - { - processedFolders.Add(file.DirectoryName); - } - } - catch (Exception ex) - { - _logger.ErrorException("Error organizing episode {0}", ex, file.FullName); - } - - numComplete++; - double percent = numComplete; - percent /= eligibleFiles.Count; - - progress.Report(10 + 89 * percent); - } - } - - cancellationToken.ThrowIfCancellationRequested(); - progress.Report(99); - - foreach (var path in processedFolders) - { - var deleteExtensions = options.TvOptions.LeftOverFileExtensionsToDelete - .Select(i => i.Trim().TrimStart('.')) - .Where(i => !string.IsNullOrEmpty(i)) - .Select(i => "." + i) - .ToList(); - - if (deleteExtensions.Count > 0) - { - DeleteLeftOverFiles(path, deleteExtensions); - } - - if (options.TvOptions.DeleteEmptyFolders) - { - if (!IsWatchFolder(path, watchLocations)) - { - DeleteEmptyFolders(path); - } - } - } - - progress.Report(100); - } - - /// <summary> - /// Gets the files to organize. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>IEnumerable{FileInfo}.</returns> - private List<FileSystemMetadata> GetFilesToOrganize(string path) - { - try - { - return _fileSystem.GetFiles(path, true) - .ToList(); - } - catch (IOException ex) - { - _logger.ErrorException("Error getting files from {0}", ex, path); - - return new List<FileSystemMetadata>(); - } - } - - /// <summary> - /// Deletes the left over files. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="extensions">The extensions.</param> - private void DeleteLeftOverFiles(string path, IEnumerable<string> extensions) - { - var eligibleFiles = _fileSystem.GetFiles(path, true) - .Where(i => extensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase)) - .ToList(); - - foreach (var file in eligibleFiles) - { - try - { - _fileSystem.DeleteFile(file.FullName); - } - catch (Exception ex) - { - _logger.ErrorException("Error deleting file {0}", ex, file.FullName); - } - } - } - - /// <summary> - /// Deletes the empty folders. - /// </summary> - /// <param name="path">The path.</param> - private void DeleteEmptyFolders(string path) - { - try - { - foreach (var d in _fileSystem.GetDirectoryPaths(path)) - { - DeleteEmptyFolders(d); - } - - var entries = _fileSystem.GetFileSystemEntryPaths(path); - - if (!entries.Any()) - { - try - { - _logger.Debug("Deleting empty directory {0}", path); - _fileSystem.DeleteDirectory(path, false); - } - catch (UnauthorizedAccessException) { } - catch (DirectoryNotFoundException) { } - } - } - catch (UnauthorizedAccessException) { } - } - - /// <summary> - /// Determines if a given folder path is contained in a folder list - /// </summary> - /// <param name="path">The folder path to check.</param> - /// <param name="watchLocations">A list of folders.</param> - private bool IsWatchFolder(string path, IEnumerable<string> watchLocations) - { - return watchLocations.Contains(path, StringComparer.OrdinalIgnoreCase); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriter.cs deleted file mode 100644 index e44b0c6af1..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriter.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using ServiceStack; -using ServiceStack.Web; -using MediaBrowser.Controller.Net; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - public class AsyncStreamWriter : IStreamWriter, IAsyncStreamWriter, IHasOptions - { - /// <summary> - /// Gets or sets the source stream. - /// </summary> - /// <value>The source stream.</value> - private IAsyncStreamSource _source; - - public Action OnComplete { get; set; } - public Action OnError { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="AsyncStreamWriter" /> class. - /// </summary> - public AsyncStreamWriter(IAsyncStreamSource source) - { - _source = source; - } - - public IDictionary<string, string> Options - { - get - { - var hasOptions = _source as IHasOptions; - if (hasOptions != null) - { - return hasOptions.Options; - } - - return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - } - } - - /// <summary> - /// Writes to. - /// </summary> - /// <param name="responseStream">The response stream.</param> - public void WriteTo(Stream responseStream) - { - var task = _source.WriteToAsync(responseStream); - Task.WaitAll(task); - } - - public async Task WriteToAsync(Stream responseStream) - { - await _source.WriteToAsync(responseStream).ConfigureAwait(false); - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/ContainerAdapter.cs b/MediaBrowser.Server.Implementations/HttpServer/ContainerAdapter.cs deleted file mode 100644 index 93d224b8db..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/ContainerAdapter.cs +++ /dev/null @@ -1,53 +0,0 @@ -using MediaBrowser.Common; -using ServiceStack.Configuration; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - /// <summary> - /// Class ContainerAdapter - /// </summary> - class ContainerAdapter : IContainerAdapter, IRelease - { - /// <summary> - /// The _app host - /// </summary> - private readonly IApplicationHost _appHost; - - /// <summary> - /// Initializes a new instance of the <see cref="ContainerAdapter" /> class. - /// </summary> - /// <param name="appHost">The app host.</param> - public ContainerAdapter(IApplicationHost appHost) - { - _appHost = appHost; - } - /// <summary> - /// Resolves this instance. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <returns>``0.</returns> - public T Resolve<T>() - { - return _appHost.Resolve<T>(); - } - - /// <summary> - /// Tries the resolve. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <returns>``0.</returns> - public T TryResolve<T>() - { - return _appHost.TryResolve<T>(); - } - - /// <summary> - /// Releases the specified instance. - /// </summary> - /// <param name="instance">The instance.</param> - public void Release(object instance) - { - // Leave this empty so SS doesn't try to dispose our objects - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/GetSwaggerResource.cs b/MediaBrowser.Server.Implementations/HttpServer/GetSwaggerResource.cs deleted file mode 100644 index 36a257f632..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/GetSwaggerResource.cs +++ /dev/null @@ -1,17 +0,0 @@ -using ServiceStack; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - /// <summary> - /// Class GetDashboardResource - /// </summary> - [Route("/swagger-ui/{ResourceName*}", "GET")] - public class GetSwaggerResource - { - /// <summary> - /// Gets or sets the name. - /// </summary> - /// <value>The name.</value> - public string ResourceName { get; set; } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs deleted file mode 100644 index b3d3ec13cc..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ /dev/null @@ -1,676 +0,0 @@ -using Funq; -using MediaBrowser.Common; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.HttpServer.SocketSharp; -using ServiceStack; -using ServiceStack.Api.Swagger; -using ServiceStack.Host; -using ServiceStack.Host.Handlers; -using ServiceStack.Host.HttpListener; -using ServiceStack.Logging; -using ServiceStack.Web; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Security; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - public class HttpListenerHost : ServiceStackHost, IHttpServer - { - private string DefaultRedirectPath { get; set; } - - private readonly ILogger _logger; - public IEnumerable<string> UrlPrefixes { get; private set; } - - private readonly List<IRestfulService> _restServices = new List<IRestfulService>(); - - private IHttpListener _listener; - - private readonly ContainerAdapter _containerAdapter; - - public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected; - public event EventHandler<WebSocketConnectingEventArgs> WebSocketConnecting; - - public string CertificatePath { get; private set; } - - private readonly IServerConfigurationManager _config; - private readonly INetworkManager _networkManager; - private readonly IMemoryStreamProvider _memoryStreamProvider; - - public HttpListenerHost(IApplicationHost applicationHost, - ILogManager logManager, - IServerConfigurationManager config, - string serviceName, - string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamProvider memoryStreamProvider, params Assembly[] assembliesWithServices) - : base(serviceName, assembliesWithServices) - { - DefaultRedirectPath = defaultRedirectPath; - _networkManager = networkManager; - _memoryStreamProvider = memoryStreamProvider; - _config = config; - - _logger = logManager.GetLogger("HttpServer"); - - _containerAdapter = new ContainerAdapter(applicationHost); - } - - public string GlobalResponse { get; set; } - - public override void Configure(Container container) - { - HostConfig.Instance.DefaultRedirectPath = DefaultRedirectPath; - HostConfig.Instance.LogUnobservedTaskExceptions = false; - - HostConfig.Instance.MapExceptionToStatusCode = new Dictionary<Type, int> - { - {typeof (InvalidOperationException), 500}, - {typeof (NotImplementedException), 500}, - {typeof (ResourceNotFoundException), 404}, - {typeof (FileNotFoundException), 404}, - {typeof (DirectoryNotFoundException), 404}, - {typeof (SecurityException), 401}, - {typeof (PaymentRequiredException), 402}, - {typeof (UnauthorizedAccessException), 500}, - {typeof (ApplicationException), 500}, - {typeof (PlatformNotSupportedException), 500}, - {typeof (NotSupportedException), 500} - }; - - HostConfig.Instance.GlobalResponseHeaders = new Dictionary<string, string>(); - HostConfig.Instance.DebugMode = false; - - HostConfig.Instance.LogFactory = LogManager.LogFactory; - HostConfig.Instance.AllowJsonpRequests = false; - - // The Markdown feature causes slow startup times (5 mins+) on cold boots for some users - // Custom format allows images - HostConfig.Instance.EnableFeatures = Feature.Html | Feature.Json | Feature.Xml | Feature.CustomFormat; - - container.Adapter = _containerAdapter; - - Plugins.RemoveAll(x => x is NativeTypesFeature); - Plugins.Add(new SwaggerFeature()); - Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization")); - - //Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { - // new SessionAuthProvider(_containerAdapter.Resolve<ISessionContext>()), - //})); - - //PreRequestFilters.Add((httpReq, httpRes) => - //{ - // //Handles Request and closes Responses after emitting global HTTP Headers - // if (string.Equals(httpReq.Verb, "OPTIONS", StringComparison.OrdinalIgnoreCase)) - // { - // httpRes.EndRequest(); //add a 'using ServiceStack;' - // } - //}); - - HostContext.GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse); - } - - public override void OnAfterInit() - { - SetAppDomainData(); - - base.OnAfterInit(); - } - - public override void OnConfigLoad() - { - base.OnConfigLoad(); - - Config.HandlerFactoryPath = null; - - Config.MetadataRedirectPath = "metadata"; - } - - protected override ServiceController CreateServiceController(params Assembly[] assembliesWithServices) - { - var types = _restServices.Select(r => r.GetType()).ToArray(); - - return new ServiceController(this, () => types); - } - - public virtual void SetAppDomainData() - { - //Required for Mono to resolve VirtualPathUtility and Url.Content urls - var domain = Thread.GetDomain(); // or AppDomain.Current - domain.SetData(".appDomain", "1"); - domain.SetData(".appVPath", "/"); - domain.SetData(".appPath", domain.BaseDirectory); - if (string.IsNullOrEmpty(domain.GetData(".appId") as string)) - { - domain.SetData(".appId", "1"); - } - if (string.IsNullOrEmpty(domain.GetData(".domainId") as string)) - { - domain.SetData(".domainId", "1"); - } - } - - public override ServiceStackHost Start(string listeningAtUrlBase) - { - StartListener(); - return this; - } - - /// <summary> - /// Starts the Web Service - /// </summary> - private void StartListener() - { - HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First()); - - _listener = GetListener(); - - _listener.WebSocketConnected = OnWebSocketConnected; - _listener.WebSocketConnecting = OnWebSocketConnecting; - _listener.ErrorHandler = ErrorHandler; - _listener.RequestHandler = RequestHandler; - - _listener.Start(UrlPrefixes); - } - - private IHttpListener GetListener() - { - return new WebSocketSharpListener(_logger, CertificatePath, _memoryStreamProvider); - } - - private void OnWebSocketConnecting(WebSocketConnectingEventArgs args) - { - if (_disposed) - { - return; - } - - if (WebSocketConnecting != null) - { - WebSocketConnecting(this, args); - } - } - - private void OnWebSocketConnected(WebSocketConnectEventArgs args) - { - if (_disposed) - { - return; - } - - if (WebSocketConnected != null) - { - WebSocketConnected(this, args); - } - } - - private void ErrorHandler(Exception ex, IRequest httpReq) - { - try - { - var httpRes = httpReq.Response; - - if (httpRes.IsClosed) - { - return; - } - - var errorResponse = new ErrorResponse - { - ResponseStatus = new ResponseStatus - { - ErrorCode = ex.GetType().GetOperationName(), - Message = ex.Message, - StackTrace = ex.StackTrace - } - }; - - var contentType = httpReq.ResponseContentType; - - var serializer = HostContext.ContentTypes.GetResponseSerializer(contentType); - if (serializer == null) - { - contentType = HostContext.Config.DefaultContentType; - serializer = HostContext.ContentTypes.GetResponseSerializer(contentType); - } - - var httpError = ex as IHttpError; - if (httpError != null) - { - httpRes.StatusCode = httpError.Status; - httpRes.StatusDescription = httpError.StatusDescription; - } - else - { - httpRes.StatusCode = 500; - } - - httpRes.ContentType = contentType; - - serializer(httpReq, errorResponse, httpRes); - - httpRes.Close(); - } - catch - { - //_logger.ErrorException("Error this.ProcessRequest(context)(Exception while writing error to the response)", errorEx); - } - } - - /// <summary> - /// Shut down the Web Service - /// </summary> - public void Stop() - { - if (_listener != null) - { - _listener.Stop(); - } - } - - private readonly Dictionary<string, int> _skipLogExtensions = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase) - { - {".js", 0}, - {".css", 0}, - {".woff", 0}, - {".woff2", 0}, - {".ttf", 0}, - {".html", 0} - }; - - private bool EnableLogging(string url, string localPath) - { - var extension = GetExtension(url); - - if (string.IsNullOrWhiteSpace(extension) || !_skipLogExtensions.ContainsKey(extension)) - { - if (string.IsNullOrWhiteSpace(localPath) || localPath.IndexOf("system/ping", StringComparison.OrdinalIgnoreCase) == -1) - { - return true; - } - } - - return false; - } - - private string GetExtension(string url) - { - var parts = url.Split(new[] { '?' }, 2); - - return Path.GetExtension(parts[0]); - } - - public static string RemoveQueryStringByKey(string url, string key) - { - var uri = new Uri(url); - - // this gets all the query string key value pairs as a collection - var newQueryString = MyHttpUtility.ParseQueryString(uri.Query); - - if (newQueryString.Count == 0) - { - return url; - } - - // this removes the key if exists - newQueryString.Remove(key); - - // this gets the page path from root without QueryString - string pagePathWithoutQueryString = uri.GetLeftPart(UriPartial.Path); - - return newQueryString.Count > 0 - ? String.Format("{0}?{1}", pagePathWithoutQueryString, newQueryString) - : pagePathWithoutQueryString; - } - - private string GetUrlToLog(string url) - { - url = RemoveQueryStringByKey(url, "api_key"); - - return url; - } - - private string NormalizeConfiguredLocalAddress(string address) - { - var index = address.Trim('/').IndexOf('/'); - - if (index != -1) - { - address = address.Substring(index + 1); - } - - return address.Trim('/'); - } - - private bool ValidateHost(Uri url) - { - var hosts = _config - .Configuration - .LocalNetworkAddresses - .Select(NormalizeConfiguredLocalAddress) - .ToList(); - - if (hosts.Count == 0) - { - return true; - } - - var host = url.Host ?? string.Empty; - - _logger.Debug("Validating host {0}", host); - - if (_networkManager.IsInPrivateAddressSpace(host)) - { - hosts.Add("localhost"); - hosts.Add("127.0.0.1"); - - return hosts.Any(i => host.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1); - } - - return true; - } - - /// <summary> - /// Overridable method that can be used to implement a custom hnandler - /// </summary> - /// <param name="httpReq">The HTTP req.</param> - /// <param name="url">The URL.</param> - /// <returns>Task.</returns> - protected async Task RequestHandler(IHttpRequest httpReq, Uri url) - { - var date = DateTime.Now; - - var httpRes = httpReq.Response; - - if (_disposed) - { - httpRes.StatusCode = 503; - httpRes.Close(); - return ; - } - - if (!ValidateHost(url)) - { - httpRes.StatusCode = 400; - httpRes.ContentType = "text/plain"; - httpRes.Write("Invalid host"); - - httpRes.Close(); - return; - } - - if (string.Equals(httpReq.Verb, "OPTIONS", StringComparison.OrdinalIgnoreCase)) - { - httpRes.StatusCode = 200; - httpRes.AddHeader("Access-Control-Allow-Origin", "*"); - httpRes.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS"); - httpRes.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization"); - httpRes.ContentType = "text/html"; - - httpRes.Close(); - } - - var operationName = httpReq.OperationName; - var localPath = url.LocalPath; - - var urlString = url.OriginalString; - var enableLog = EnableLogging(urlString, localPath); - var urlToLog = urlString; - - if (enableLog) - { - urlToLog = GetUrlToLog(urlString); - LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent); - } - - if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase) || - string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl(DefaultRedirectPath); - return; - } - if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase) || - string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl("emby/" + DefaultRedirectPath); - return; - } - - if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) || - string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase) || - localPath.IndexOf("mediabrowser/web", StringComparison.OrdinalIgnoreCase) != -1) - { - httpRes.StatusCode = 200; - httpRes.ContentType = "text/html"; - var newUrl = urlString.Replace("mediabrowser", "emby", StringComparison.OrdinalIgnoreCase) - .Replace("/dashboard/", "/web/", StringComparison.OrdinalIgnoreCase); - - if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase)) - { - httpRes.Write("<!doctype html><html><head><title>Emby</title></head><body>Please update your Emby bookmark to <a href=\"" + newUrl + "\">" + newUrl + "</a></body></html>"); - - httpRes.Close(); - return; - } - } - - if (localPath.IndexOf("dashboard/", StringComparison.OrdinalIgnoreCase) != -1 && - localPath.IndexOf("web/dashboard", StringComparison.OrdinalIgnoreCase) == -1) - { - httpRes.StatusCode = 200; - httpRes.ContentType = "text/html"; - var newUrl = urlString.Replace("mediabrowser", "emby", StringComparison.OrdinalIgnoreCase) - .Replace("/dashboard/", "/web/", StringComparison.OrdinalIgnoreCase); - - if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase)) - { - httpRes.Write("<!doctype html><html><head><title>Emby</title></head><body>Please update your Emby bookmark to <a href=\"" + newUrl + "\">" + newUrl + "</a></body></html>"); - - httpRes.Close(); - return; - } - } - - if (string.Equals(localPath, "/web", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl(DefaultRedirectPath); - return; - } - if (string.Equals(localPath, "/web/", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl("../" + DefaultRedirectPath); - return; - } - if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl(DefaultRedirectPath); - return; - } - if (string.IsNullOrEmpty(localPath)) - { - httpRes.RedirectToUrl("/" + DefaultRedirectPath); - return; - } - - if (string.Equals(localPath, "/emby/pin", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl("web/pin.html"); - return; - } - - if (!string.IsNullOrWhiteSpace(GlobalResponse)) - { - httpRes.StatusCode = 503; - httpRes.ContentType = "text/html"; - httpRes.Write(GlobalResponse); - - httpRes.Close(); - return; - } - - var handler = HttpHandlerFactory.GetHandler(httpReq); - - var remoteIp = httpReq.RemoteIp; - - var serviceStackHandler = handler as IServiceStackHandler; - if (serviceStackHandler != null) - { - var restHandler = serviceStackHandler as RestHandler; - if (restHandler != null) - { - httpReq.OperationName = operationName = restHandler.RestPath.RequestType.GetOperationName(); - } - - try - { - await serviceStackHandler.ProcessRequestAsync(httpReq, httpRes, operationName).ConfigureAwait(false); - } - finally - { - httpRes.Close(); - var statusCode = httpRes.StatusCode; - - var duration = DateTime.Now - date; - - if (enableLog) - { - LoggerUtils.LogResponse(_logger, statusCode, urlToLog, remoteIp, duration); - } - } - } - else - { - httpRes.Close(); - } - } - - /// <summary> - /// Adds the rest handlers. - /// </summary> - /// <param name="services">The services.</param> - public void Init(IEnumerable<IRestfulService> services) - { - _restServices.AddRange(services); - - ServiceController = CreateServiceController(); - - _logger.Info("Calling ServiceStack AppHost.Init"); - - base.Init(); - } - - public override RouteAttribute[] GetRouteAttributes(Type requestType) - { - var routes = base.GetRouteAttributes(requestType).ToList(); - var clone = routes.ToList(); - - foreach (var route in clone) - { - routes.Add(new RouteAttribute(NormalizeEmbyRoutePath(route.Path), route.Verbs) - { - Notes = route.Notes, - Priority = route.Priority, - Summary = route.Summary - }); - - routes.Add(new RouteAttribute(NormalizeRoutePath(route.Path), route.Verbs) - { - Notes = route.Notes, - Priority = route.Priority, - Summary = route.Summary - }); - - routes.Add(new RouteAttribute(DoubleNormalizeEmbyRoutePath(route.Path), route.Verbs) - { - Notes = route.Notes, - Priority = route.Priority, - Summary = route.Summary - }); - } - - return routes.ToArray(); - } - - private string NormalizeEmbyRoutePath(string path) - { - if (path.StartsWith("/", StringComparison.OrdinalIgnoreCase)) - { - return "/emby" + path; - } - - return "emby/" + path; - } - - private string DoubleNormalizeEmbyRoutePath(string path) - { - if (path.StartsWith("/", StringComparison.OrdinalIgnoreCase)) - { - return "/emby/emby" + path; - } - - return "emby/emby/" + path; - } - - private string NormalizeRoutePath(string path) - { - if (path.StartsWith("/", StringComparison.OrdinalIgnoreCase)) - { - return "/mediabrowser" + path; - } - - return "mediabrowser/" + path; - } - - /// <summary> - /// Releases the specified instance. - /// </summary> - /// <param name="instance">The instance.</param> - public override void Release(object instance) - { - // Leave this empty so SS doesn't try to dispose our objects - } - - private bool _disposed; - private readonly object _disposeLock = new object(); - protected virtual void Dispose(bool disposing) - { - if (_disposed) return; - base.Dispose(); - - lock (_disposeLock) - { - if (_disposed) return; - - if (disposing) - { - Stop(); - } - - //release unmanaged resources here... - _disposed = true; - } - } - - public override void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - public void StartServer(IEnumerable<string> urlPrefixes, string certificatePath) - { - CertificatePath = certificatePath; - UrlPrefixes = urlPrefixes.ToList(); - Start(UrlPrefixes.First()); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs deleted file mode 100644 index 10d6f74938..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs +++ /dev/null @@ -1,691 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using ServiceStack; -using ServiceStack.Web; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Net; -using System.Text; -using System.Threading.Tasks; -using CommonIO; -using MimeTypes = MediaBrowser.Model.Net.MimeTypes; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - /// <summary> - /// Class HttpResultFactory - /// </summary> - public class HttpResultFactory : IHttpResultFactory - { - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly IJsonSerializer _jsonSerializer; - - /// <summary> - /// Initializes a new instance of the <see cref="HttpResultFactory" /> class. - /// </summary> - /// <param name="logManager">The log manager.</param> - /// <param name="fileSystem">The file system.</param> - /// <param name="jsonSerializer">The json serializer.</param> - public HttpResultFactory(ILogManager logManager, IFileSystem fileSystem, IJsonSerializer jsonSerializer) - { - _fileSystem = fileSystem; - _jsonSerializer = jsonSerializer; - _logger = logManager.GetLogger("HttpResultFactory"); - } - - /// <summary> - /// Gets the result. - /// </summary> - /// <param name="content">The content.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <returns>System.Object.</returns> - public object GetResult(object content, string contentType, IDictionary<string, string> responseHeaders = null) - { - return GetHttpResult(content, contentType, responseHeaders); - } - - /// <summary> - /// Gets the HTTP result. - /// </summary> - /// <param name="content">The content.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <returns>IHasOptions.</returns> - private IHasOptions GetHttpResult(object content, string contentType, IDictionary<string, string> responseHeaders = null) - { - IHasOptions result; - - var stream = content as Stream; - - if (stream != null) - { - result = new StreamWriter(stream, contentType, _logger); - } - - else - { - var bytes = content as byte[]; - - if (bytes != null) - { - result = new StreamWriter(bytes, contentType, _logger); - } - else - { - var text = content as string; - - if (text != null) - { - result = new StreamWriter(Encoding.UTF8.GetBytes(text), contentType, _logger); - } - else - { - result = new HttpResult(content, contentType); - } - } - } - if (responseHeaders == null) - { - responseHeaders = new Dictionary<string, string>(); - } - - responseHeaders["Expires"] = "-1"; - AddResponseHeaders(result, responseHeaders); - - return result; - } - - /// <summary> - /// Gets the optimized result. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="requestContext">The request context.</param> - /// <param name="result">The result.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">result</exception> - public object GetOptimizedResult<T>(IRequest requestContext, T result, IDictionary<string, string> responseHeaders = null) - where T : class - { - return GetOptimizedResultInternal<T>(requestContext, result, true, responseHeaders); - } - - private object GetOptimizedResultInternal<T>(IRequest requestContext, T result, bool addCachePrevention, IDictionary<string, string> responseHeaders = null) - where T : class - { - if (result == null) - { - throw new ArgumentNullException("result"); - } - - var optimizedResult = requestContext.ToOptimizedResult(result); - - if (responseHeaders == null) - { - responseHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - } - - if (addCachePrevention) - { - responseHeaders["Expires"] = "-1"; - } - - // Apply headers - var hasOptions = optimizedResult as IHasOptions; - - if (hasOptions != null) - { - AddResponseHeaders(hasOptions, responseHeaders); - } - - return optimizedResult; - } - - /// <summary> - /// Gets the optimized result using cache. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="requestContext">The request context.</param> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="factoryFn">The factory fn.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">cacheKey - /// or - /// factoryFn</exception> - public object GetOptimizedResultUsingCache<T>(IRequest requestContext, Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, IDictionary<string, string> responseHeaders = null) - where T : class - { - if (cacheKey == Guid.Empty) - { - throw new ArgumentNullException("cacheKey"); - } - if (factoryFn == null) - { - throw new ArgumentNullException("factoryFn"); - } - - var key = cacheKey.ToString("N"); - - if (responseHeaders == null) - { - responseHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - } - - // See if the result is already cached in the browser - var result = GetCachedResult(requestContext, responseHeaders, cacheKey, key, lastDateModified, cacheDuration, null); - - if (result != null) - { - return result; - } - - return GetOptimizedResultInternal(requestContext, factoryFn(), false, responseHeaders); - } - - /// <summary> - /// To the cached result. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="requestContext">The request context.</param> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="factoryFn">The factory fn.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">cacheKey</exception> - public object GetCachedResult<T>(IRequest requestContext, Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType, IDictionary<string, string> responseHeaders = null) - where T : class - { - if (cacheKey == Guid.Empty) - { - throw new ArgumentNullException("cacheKey"); - } - if (factoryFn == null) - { - throw new ArgumentNullException("factoryFn"); - } - - var key = cacheKey.ToString("N"); - - if (responseHeaders == null) - { - responseHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - } - - // See if the result is already cached in the browser - var result = GetCachedResult(requestContext, responseHeaders, cacheKey, key, lastDateModified, cacheDuration, contentType); - - if (result != null) - { - return result; - } - - result = factoryFn(); - - // Apply caching headers - var hasOptions = result as IHasOptions; - - if (hasOptions != null) - { - AddResponseHeaders(hasOptions, responseHeaders); - return hasOptions; - } - - IHasOptions httpResult; - - var stream = result as Stream; - - if (stream != null) - { - httpResult = new StreamWriter(stream, contentType, _logger); - } - else - { - // Otherwise wrap into an HttpResult - httpResult = new HttpResult(result, contentType ?? "text/html", HttpStatusCode.NotModified); - } - - AddResponseHeaders(httpResult, responseHeaders); - - return httpResult; - } - - /// <summary> - /// Pres the process optimized result. - /// </summary> - /// <param name="requestContext">The request context.</param> - /// <param name="responseHeaders">The responseHeaders.</param> - /// <param name="cacheKey">The cache key.</param> - /// <param name="cacheKeyString">The cache key string.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="contentType">Type of the content.</param> - /// <returns>System.Object.</returns> - private object GetCachedResult(IRequest requestContext, IDictionary<string, string> responseHeaders, Guid cacheKey, string cacheKeyString, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType) - { - responseHeaders["ETag"] = string.Format("\"{0}\"", cacheKeyString); - - if (IsNotModified(requestContext, cacheKey, lastDateModified, cacheDuration)) - { - AddAgeHeader(responseHeaders, lastDateModified); - AddExpiresHeader(responseHeaders, cacheKeyString, cacheDuration); - - var result = new HttpResult(new byte[] { }, contentType ?? "text/html", HttpStatusCode.NotModified); - - AddResponseHeaders(result, responseHeaders); - - return result; - } - - AddCachingHeaders(responseHeaders, cacheKeyString, lastDateModified, cacheDuration); - - return null; - } - - public Task<object> GetStaticFileResult(IRequest requestContext, - string path, - FileShare fileShare = FileShare.Read) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException("path"); - } - - return GetStaticFileResult(requestContext, new StaticFileResultOptions - { - Path = path, - FileShare = fileShare - }); - } - - public Task<object> GetStaticFileResult(IRequest requestContext, - StaticFileResultOptions options) - { - var path = options.Path; - var fileShare = options.FileShare; - - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException("path"); - } - - if (fileShare != FileShare.Read && fileShare != FileShare.ReadWrite) - { - throw new ArgumentException("FileShare must be either Read or ReadWrite"); - } - - if (string.IsNullOrWhiteSpace(options.ContentType)) - { - options.ContentType = MimeTypes.GetMimeType(path); - } - - if (!options.DateLastModified.HasValue) - { - options.DateLastModified = _fileSystem.GetLastWriteTimeUtc(path); - } - - var cacheKey = path + options.DateLastModified.Value.Ticks; - - options.CacheKey = cacheKey.GetMD5(); - options.ContentFactory = () => Task.FromResult(GetFileStream(path, fileShare)); - - return GetStaticResult(requestContext, options); - } - - /// <summary> - /// Gets the file stream. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="fileShare">The file share.</param> - /// <returns>Stream.</returns> - private Stream GetFileStream(string path, FileShare fileShare) - { - return _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, fileShare); - } - - public Task<object> GetStaticResult(IRequest requestContext, - Guid cacheKey, - DateTime? lastDateModified, - TimeSpan? cacheDuration, - string contentType, - Func<Task<Stream>> factoryFn, - IDictionary<string, string> responseHeaders = null, - bool isHeadRequest = false) - { - return GetStaticResult(requestContext, new StaticResultOptions - { - CacheDuration = cacheDuration, - CacheKey = cacheKey, - ContentFactory = factoryFn, - ContentType = contentType, - DateLastModified = lastDateModified, - IsHeadRequest = isHeadRequest, - ResponseHeaders = responseHeaders - }); - } - - public async Task<object> GetStaticResult(IRequest requestContext, StaticResultOptions options) - { - var cacheKey = options.CacheKey; - options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - var contentType = options.ContentType; - - if (cacheKey == Guid.Empty) - { - throw new ArgumentNullException("cacheKey"); - } - if (options.ContentFactory == null) - { - throw new ArgumentNullException("factoryFn"); - } - - var key = cacheKey.ToString("N"); - - // See if the result is already cached in the browser - var result = GetCachedResult(requestContext, options.ResponseHeaders, cacheKey, key, options.DateLastModified, options.CacheDuration, contentType); - - if (result != null) - { - return result; - } - - var compress = ShouldCompressResponse(requestContext, contentType); - var hasOptions = await GetStaticResult(requestContext, options, compress).ConfigureAwait(false); - AddResponseHeaders(hasOptions, options.ResponseHeaders); - - return hasOptions; - } - - /// <summary> - /// Shoulds the compress response. - /// </summary> - /// <param name="requestContext">The request context.</param> - /// <param name="contentType">Type of the content.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - private bool ShouldCompressResponse(IRequest requestContext, string contentType) - { - // It will take some work to support compression with byte range requests - if (!string.IsNullOrEmpty(requestContext.GetHeader("Range"))) - { - return false; - } - - // Don't compress media - if (contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - // Don't compress images - if (contentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - if (contentType.StartsWith("font/", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - if (contentType.StartsWith("application/", StringComparison.OrdinalIgnoreCase)) - { - if (string.Equals(contentType, "application/x-javascript", StringComparison.OrdinalIgnoreCase)) - { - return true; - } - if (string.Equals(contentType, "application/xml", StringComparison.OrdinalIgnoreCase)) - { - return true; - } - return false; - } - - return true; - } - - /// <summary> - /// The us culture - /// </summary> - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - private async Task<IHasOptions> GetStaticResult(IRequest requestContext, StaticResultOptions options, bool compress) - { - var isHeadRequest = options.IsHeadRequest; - var factoryFn = options.ContentFactory; - var contentType = options.ContentType; - var responseHeaders = options.ResponseHeaders; - - var requestedCompressionType = requestContext.GetCompressionType(); - - if (!compress || string.IsNullOrEmpty(requestedCompressionType)) - { - var rangeHeader = requestContext.GetHeader("Range"); - - var stream = await factoryFn().ConfigureAwait(false); - - if (!string.IsNullOrEmpty(rangeHeader)) - { - return new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest, _logger) - { - OnComplete = options.OnComplete - }; - } - - responseHeaders["Content-Length"] = stream.Length.ToString(UsCulture); - - if (isHeadRequest) - { - stream.Dispose(); - - return GetHttpResult(new byte[] { }, contentType); - } - - return new StreamWriter(stream, contentType, _logger) - { - OnComplete = options.OnComplete, - OnError = options.OnError - }; - } - - string content; - - using (var stream = await factoryFn().ConfigureAwait(false)) - { - using (var reader = new StreamReader(stream)) - { - content = await reader.ReadToEndAsync().ConfigureAwait(false); - } - } - - var contents = content.Compress(requestedCompressionType); - - responseHeaders["Content-Length"] = contents.Length.ToString(UsCulture); - - if (isHeadRequest) - { - return GetHttpResult(new byte[] { }, contentType); - } - - return new CompressedResult(contents, requestedCompressionType, contentType); - } - - /// <summary> - /// Adds the caching responseHeaders. - /// </summary> - /// <param name="responseHeaders">The responseHeaders.</param> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - private void AddCachingHeaders(IDictionary<string, string> responseHeaders, string cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration) - { - // Don't specify both last modified and Etag, unless caching unconditionally. They are redundant - // https://developers.google.com/speed/docs/best-practices/caching#LeverageBrowserCaching - if (lastDateModified.HasValue && (string.IsNullOrEmpty(cacheKey) || cacheDuration.HasValue)) - { - AddAgeHeader(responseHeaders, lastDateModified); - responseHeaders["Last-Modified"] = lastDateModified.Value.ToString("r"); - } - - if (cacheDuration.HasValue) - { - responseHeaders["Cache-Control"] = "public, max-age=" + Convert.ToInt32(cacheDuration.Value.TotalSeconds); - } - else if (!string.IsNullOrEmpty(cacheKey)) - { - responseHeaders["Cache-Control"] = "public"; - } - else - { - responseHeaders["Cache-Control"] = "no-cache, no-store, must-revalidate"; - responseHeaders["pragma"] = "no-cache, no-store, must-revalidate"; - } - - AddExpiresHeader(responseHeaders, cacheKey, cacheDuration); - } - - /// <summary> - /// Adds the expires header. - /// </summary> - /// <param name="responseHeaders">The responseHeaders.</param> - /// <param name="cacheKey">The cache key.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - private void AddExpiresHeader(IDictionary<string, string> responseHeaders, string cacheKey, TimeSpan? cacheDuration) - { - if (cacheDuration.HasValue) - { - responseHeaders["Expires"] = DateTime.UtcNow.Add(cacheDuration.Value).ToString("r"); - } - else if (string.IsNullOrEmpty(cacheKey)) - { - responseHeaders["Expires"] = "-1"; - } - } - - /// <summary> - /// Adds the age header. - /// </summary> - /// <param name="responseHeaders">The responseHeaders.</param> - /// <param name="lastDateModified">The last date modified.</param> - private void AddAgeHeader(IDictionary<string, string> responseHeaders, DateTime? lastDateModified) - { - if (lastDateModified.HasValue) - { - responseHeaders["Age"] = Convert.ToInt64((DateTime.UtcNow - lastDateModified.Value).TotalSeconds).ToString(CultureInfo.InvariantCulture); - } - } - /// <summary> - /// Determines whether [is not modified] [the specified cache key]. - /// </summary> - /// <param name="requestContext">The request context.</param> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <returns><c>true</c> if [is not modified] [the specified cache key]; otherwise, <c>false</c>.</returns> - private bool IsNotModified(IRequest requestContext, Guid? cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration) - { - var isNotModified = true; - - var ifModifiedSinceHeader = requestContext.GetHeader("If-Modified-Since"); - - if (!string.IsNullOrEmpty(ifModifiedSinceHeader)) - { - DateTime ifModifiedSince; - - if (DateTime.TryParse(ifModifiedSinceHeader, out ifModifiedSince)) - { - isNotModified = IsNotModified(ifModifiedSince.ToUniversalTime(), cacheDuration, lastDateModified); - } - } - - var ifNoneMatchHeader = requestContext.GetHeader("If-None-Match"); - - // Validate If-None-Match - if (isNotModified && (cacheKey.HasValue || !string.IsNullOrEmpty(ifNoneMatchHeader))) - { - Guid ifNoneMatch; - - if (Guid.TryParse(ifNoneMatchHeader ?? string.Empty, out ifNoneMatch)) - { - if (cacheKey.HasValue && cacheKey.Value == ifNoneMatch) - { - return true; - } - } - } - - return false; - } - - /// <summary> - /// Determines whether [is not modified] [the specified if modified since]. - /// </summary> - /// <param name="ifModifiedSince">If modified since.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="dateModified">The date modified.</param> - /// <returns><c>true</c> if [is not modified] [the specified if modified since]; otherwise, <c>false</c>.</returns> - private bool IsNotModified(DateTime ifModifiedSince, TimeSpan? cacheDuration, DateTime? dateModified) - { - if (dateModified.HasValue) - { - var lastModified = NormalizeDateForComparison(dateModified.Value); - ifModifiedSince = NormalizeDateForComparison(ifModifiedSince); - - return lastModified <= ifModifiedSince; - } - - if (cacheDuration.HasValue) - { - var cacheExpirationDate = ifModifiedSince.Add(cacheDuration.Value); - - if (DateTime.UtcNow < cacheExpirationDate) - { - return true; - } - } - - return false; - } - - - /// <summary> - /// When the browser sends the IfModifiedDate, it's precision is limited to seconds, so this will account for that - /// </summary> - /// <param name="date">The date.</param> - /// <returns>DateTime.</returns> - private DateTime NormalizeDateForComparison(DateTime date) - { - return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind); - } - - /// <summary> - /// Adds the response headers. - /// </summary> - /// <param name="hasOptions">The has options.</param> - /// <param name="responseHeaders">The response headers.</param> - private void AddResponseHeaders(IHasOptions hasOptions, IEnumerable<KeyValuePair<string, string>> responseHeaders) - { - foreach (var item in responseHeaders) - { - hasOptions.Options[item.Key] = item.Value; - } - } - - public object GetAsyncStreamWriter(IAsyncStreamSource streamSource) - { - return new AsyncStreamWriter(streamSource); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs deleted file mode 100644 index dc315601f2..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediaBrowser.Controller.Net; -using ServiceStack.Web; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - public interface IHttpListener : IDisposable - { - /// <summary> - /// Gets or sets the error handler. - /// </summary> - /// <value>The error handler.</value> - Action<Exception, IRequest> ErrorHandler { get; set; } - - /// <summary> - /// Gets or sets the request handler. - /// </summary> - /// <value>The request handler.</value> - Func<IHttpRequest, Uri, Task> RequestHandler { get; set; } - - /// <summary> - /// Gets or sets the web socket handler. - /// </summary> - /// <value>The web socket handler.</value> - Action<WebSocketConnectEventArgs> WebSocketConnected { get; set; } - - /// <summary> - /// Gets or sets the web socket connecting. - /// </summary> - /// <value>The web socket connecting.</value> - Action<WebSocketConnectingEventArgs> WebSocketConnecting { get; set; } - - /// <summary> - /// Starts this instance. - /// </summary> - /// <param name="urlPrefixes">The URL prefixes.</param> - void Start(IEnumerable<string> urlPrefixes); - - /// <summary> - /// Stops this instance. - /// </summary> - void Stop(); - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs deleted file mode 100644 index bfbb228edf..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs +++ /dev/null @@ -1,43 +0,0 @@ -using MediaBrowser.Model.Logging; -using System; -using System.Globalization; -using SocketHttpListener.Net; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - public static class LoggerUtils - { - /// <summary> - /// Logs the request. - /// </summary> - /// <param name="logger">The logger.</param> - /// <param name="request">The request.</param> - public static void LogRequest(ILogger logger, HttpListenerRequest request) - { - var url = request.Url.ToString(); - - logger.Info("{0} {1}. UserAgent: {2}", request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod, url, request.UserAgent ?? string.Empty); - } - - public static void LogRequest(ILogger logger, string url, string method, string userAgent) - { - logger.Info("{0} {1}. UserAgent: {2}", "HTTP " + method, url, userAgent ?? string.Empty); - } - - /// <summary> - /// Logs the response. - /// </summary> - /// <param name="logger">The logger.</param> - /// <param name="statusCode">The status code.</param> - /// <param name="url">The URL.</param> - /// <param name="endPoint">The end point.</param> - /// <param name="duration">The duration.</param> - public static void LogResponse(ILogger logger, int statusCode, string url, string endPoint, TimeSpan duration) - { - var durationMs = duration.TotalMilliseconds; - var logSuffix = durationMs >= 1000 && durationMs < 60000 ? "ms (slow)" : "ms"; - - logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url); - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs deleted file mode 100644 index 4b94095f52..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs +++ /dev/null @@ -1,293 +0,0 @@ -using MediaBrowser.Model.Logging; -using ServiceStack.Web; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Net; -using System.Threading.Tasks; -using ServiceStack; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - public class RangeRequestWriter : IStreamWriter, IAsyncStreamWriter, IHttpResult - { - /// <summary> - /// Gets or sets the source stream. - /// </summary> - /// <value>The source stream.</value> - private Stream SourceStream { get; set; } - private string RangeHeader { get; set; } - private bool IsHeadRequest { get; set; } - - private long RangeStart { get; set; } - private long RangeEnd { get; set; } - private long RangeLength { get; set; } - private long TotalContentLength { get; set; } - - public Action OnComplete { get; set; } - private readonly ILogger _logger; - - private const int BufferSize = 81920; - - /// <summary> - /// The _options - /// </summary> - private readonly Dictionary<string, string> _options = new Dictionary<string, string>(); - - /// <summary> - /// The us culture - /// </summary> - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - public Func<IDisposable> ResultScope { get; set; } - public List<Cookie> Cookies { get; private set; } - - /// <summary> - /// Additional HTTP Headers - /// </summary> - /// <value>The headers.</value> - public Dictionary<string, string> Headers - { - get { return _options; } - } - - /// <summary> - /// Gets the options. - /// </summary> - /// <value>The options.</value> - public IDictionary<string, string> Options - { - get { return Headers; } - } - - /// <summary> - /// Initializes a new instance of the <see cref="StreamWriter" /> class. - /// </summary> - /// <param name="rangeHeader">The range header.</param> - /// <param name="source">The source.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> - public RangeRequestWriter(string rangeHeader, Stream source, string contentType, bool isHeadRequest, ILogger logger) - { - if (string.IsNullOrEmpty(contentType)) - { - throw new ArgumentNullException("contentType"); - } - - RangeHeader = rangeHeader; - SourceStream = source; - IsHeadRequest = isHeadRequest; - this._logger = logger; - - ContentType = contentType; - Options["Content-Type"] = contentType; - Options["Accept-Ranges"] = "bytes"; - StatusCode = HttpStatusCode.PartialContent; - - Cookies = new List<Cookie>(); - SetRangeValues(); - } - - /// <summary> - /// Sets the range values. - /// </summary> - private void SetRangeValues() - { - var requestedRange = RequestedRanges[0]; - - TotalContentLength = SourceStream.Length; - - // If the requested range is "0-", we can optimize by just doing a stream copy - if (!requestedRange.Value.HasValue) - { - RangeEnd = TotalContentLength - 1; - } - else - { - RangeEnd = requestedRange.Value.Value; - } - - RangeStart = requestedRange.Key; - RangeLength = 1 + RangeEnd - RangeStart; - - // Content-Length is the length of what we're serving, not the original content - Options["Content-Length"] = RangeLength.ToString(UsCulture); - Options["Content-Range"] = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength); - - if (RangeStart > 0) - { - SourceStream.Position = RangeStart; - } - } - - /// <summary> - /// The _requested ranges - /// </summary> - private List<KeyValuePair<long, long?>> _requestedRanges; - /// <summary> - /// Gets the requested ranges. - /// </summary> - /// <value>The requested ranges.</value> - protected List<KeyValuePair<long, long?>> RequestedRanges - { - get - { - if (_requestedRanges == null) - { - _requestedRanges = new List<KeyValuePair<long, long?>>(); - - // Example: bytes=0-,32-63 - var ranges = RangeHeader.Split('=')[1].Split(','); - - foreach (var range in ranges) - { - var vals = range.Split('-'); - - long start = 0; - long? end = null; - - if (!string.IsNullOrEmpty(vals[0])) - { - start = long.Parse(vals[0], UsCulture); - } - if (!string.IsNullOrEmpty(vals[1])) - { - end = long.Parse(vals[1], UsCulture); - } - - _requestedRanges.Add(new KeyValuePair<long, long?>(start, end)); - } - } - - return _requestedRanges; - } - } - - /// <summary> - /// Writes to. - /// </summary> - /// <param name="responseStream">The response stream.</param> - public void WriteTo(Stream responseStream) - { - try - { - // Headers only - if (IsHeadRequest) - { - return; - } - - using (var source = SourceStream) - { - // If the requested range is "0-", we can optimize by just doing a stream copy - if (RangeEnd >= TotalContentLength - 1) - { - source.CopyTo(responseStream, BufferSize); - } - else - { - CopyToInternal(source, responseStream, RangeLength); - } - } - } - finally - { - if (OnComplete != null) - { - OnComplete(); - } - } - } - - private void CopyToInternal(Stream source, Stream destination, long copyLength) - { - var array = new byte[BufferSize]; - int count; - while ((count = source.Read(array, 0, array.Length)) != 0) - { - var bytesToCopy = Math.Min(count, copyLength); - - destination.Write(array, 0, Convert.ToInt32(bytesToCopy)); - - copyLength -= bytesToCopy; - - if (copyLength <= 0) - { - break; - } - } - } - - public async Task WriteToAsync(Stream responseStream) - { - try - { - // Headers only - if (IsHeadRequest) - { - return; - } - - using (var source = SourceStream) - { - // If the requested range is "0-", we can optimize by just doing a stream copy - if (RangeEnd >= TotalContentLength - 1) - { - await source.CopyToAsync(responseStream, BufferSize).ConfigureAwait(false); - } - else - { - await CopyToInternalAsync(source, responseStream, RangeLength).ConfigureAwait(false); - } - } - } - finally - { - if (OnComplete != null) - { - OnComplete(); - } - } - } - - private async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength) - { - var array = new byte[BufferSize]; - int count; - while ((count = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0) - { - var bytesToCopy = Math.Min(count, copyLength); - - await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy)).ConfigureAwait(false); - - copyLength -= bytesToCopy; - - if (copyLength <= 0) - { - break; - } - } - } - - public string ContentType { get; set; } - - public IRequest RequestContext { get; set; } - - public object Response { get; set; } - - public IContentTypeWriter ResponseFilter { get; set; } - - public int Status { get; set; } - - public HttpStatusCode StatusCode - { - get { return (HttpStatusCode)Status; } - set { Status = (int)value; } - } - - public string StatusDescription { get; set; } - - public int PaddingLength { get; set; } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs b/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs deleted file mode 100644 index ee05702f4c..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs +++ /dev/null @@ -1,127 +0,0 @@ -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.HttpServer.SocketSharp; -using ServiceStack.Web; -using System; -using System.Globalization; -using System.Net; -using System.Text; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - public class ResponseFilter - { - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - private readonly ILogger _logger; - - public ResponseFilter(ILogger logger) - { - _logger = logger; - } - - /// <summary> - /// Filters the response. - /// </summary> - /// <param name="req">The req.</param> - /// <param name="res">The res.</param> - /// <param name="dto">The dto.</param> - public void FilterResponse(IRequest req, IResponse res, object dto) - { - // Try to prevent compatibility view - res.AddHeader("X-UA-Compatible", "IE=Edge"); - - var exception = dto as Exception; - - if (exception != null) - { - _logger.ErrorException("Error processing request for {0}", exception, req.RawUrl); - - if (!string.IsNullOrEmpty(exception.Message)) - { - var error = exception.Message.Replace(Environment.NewLine, " "); - error = RemoveControlCharacters(error); - - res.AddHeader("X-Application-Error-Code", error); - } - } - - var vary = "Accept-Encoding"; - - var hasOptions = dto as IHasOptions; - var sharpResponse = res as WebSocketSharpResponse; - - if (hasOptions != null) - { - if (!hasOptions.Options.ContainsKey("Server")) - { - hasOptions.Options["Server"] = "Mono-HTTPAPI/1.1, UPnP/1.0 DLNADOC/1.50"; - //hasOptions.Options["Server"] = "Mono-HTTPAPI/1.1"; - } - - // Content length has to be explicitly set on on HttpListenerResponse or it won't be happy - string contentLength; - - if (hasOptions.Options.TryGetValue("Content-Length", out contentLength) && !string.IsNullOrEmpty(contentLength)) - { - var length = long.Parse(contentLength, UsCulture); - - if (length > 0) - { - res.SetContentLength(length); - - var listenerResponse = res.OriginalResponse as HttpListenerResponse; - - if (listenerResponse != null) - { - // Disable chunked encoding. Technically this is only needed when using Content-Range, but - // anytime we know the content length there's no need for it - listenerResponse.SendChunked = false; - return; - } - - if (sharpResponse != null) - { - sharpResponse.SendChunked = false; - } - } - } - - string hasOptionsVary; - if (hasOptions.Options.TryGetValue("Vary", out hasOptionsVary)) - { - vary = hasOptionsVary; - } - - hasOptions.Options["Vary"] = vary; - } - - //res.KeepAlive = false; - - // Per Google PageSpeed - // This instructs the proxies to cache two versions of the resource: one compressed, and one uncompressed. - // The correct version of the resource is delivered based on the client request header. - // This is a good choice for applications that are singly homed and depend on public proxies for user locality. - res.AddHeader("Vary", vary); - } - - /// <summary> - /// Removes the control characters. - /// </summary> - /// <param name="inString">The in string.</param> - /// <returns>System.String.</returns> - public static string RemoveControlCharacters(string inString) - { - if (inString == null) return null; - - var newString = new StringBuilder(); - - foreach (var ch in inString) - { - if (!char.IsControl(ch)) - { - newString.Append(ch); - } - } - return newString.ToString(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs deleted file mode 100644 index d8f7d889c3..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs +++ /dev/null @@ -1,246 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Connect; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Security; -using MediaBrowser.Controller.Session; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MediaBrowser.Server.Implementations.HttpServer.Security -{ - public class AuthService : IAuthService - { - private readonly IServerConfigurationManager _config; - - public AuthService(IUserManager userManager, IAuthorizationContext authorizationContext, IServerConfigurationManager config, IConnectManager connectManager, ISessionManager sessionManager, IDeviceManager deviceManager) - { - AuthorizationContext = authorizationContext; - _config = config; - DeviceManager = deviceManager; - SessionManager = sessionManager; - ConnectManager = connectManager; - UserManager = userManager; - } - - public IUserManager UserManager { get; private set; } - public IAuthorizationContext AuthorizationContext { get; private set; } - public IConnectManager ConnectManager { get; private set; } - public ISessionManager SessionManager { get; private set; } - public IDeviceManager DeviceManager { get; private set; } - - /// <summary> - /// Redirect the client to a specific URL if authentication failed. - /// If this property is null, simply `401 Unauthorized` is returned. - /// </summary> - public string HtmlRedirect { get; set; } - - public void Authenticate(IServiceRequest request, - IAuthenticationAttributes authAttribtues) - { - ValidateUser(request, authAttribtues); - } - - private void ValidateUser(IServiceRequest request, - IAuthenticationAttributes authAttribtues) - { - // This code is executed before the service - var auth = AuthorizationContext.GetAuthorizationInfo(request); - - if (!IsExemptFromAuthenticationToken(auth, authAttribtues)) - { - var valid = IsValidConnectKey(auth.Token); - - if (!valid) - { - ValidateSecurityToken(request, auth.Token); - } - } - - var user = string.IsNullOrWhiteSpace(auth.UserId) - ? null - : UserManager.GetUserById(auth.UserId); - - if (user == null & !string.IsNullOrWhiteSpace(auth.UserId)) - { - throw new SecurityException("User with Id " + auth.UserId + " not found"); - } - - if (user != null) - { - ValidateUserAccess(user, request, authAttribtues, auth); - } - - var info = GetTokenInfo(request); - - if (!IsExemptFromRoles(auth, authAttribtues, info)) - { - var roles = authAttribtues.GetRoles().ToList(); - - ValidateRoles(roles, user); - } - - if (!string.IsNullOrWhiteSpace(auth.DeviceId) && - !string.IsNullOrWhiteSpace(auth.Client) && - !string.IsNullOrWhiteSpace(auth.Device)) - { - SessionManager.LogSessionActivity(auth.Client, - auth.Version, - auth.DeviceId, - auth.Device, - request.RemoteIp, - user); - } - } - - private void ValidateUserAccess(User user, IServiceRequest request, - IAuthenticationAttributes authAttribtues, - AuthorizationInfo auth) - { - if (user.Policy.IsDisabled) - { - throw new SecurityException("User account has been disabled.") - { - SecurityExceptionType = SecurityExceptionType.Unauthenticated - }; - } - - if (!user.Policy.IsAdministrator && - !authAttribtues.EscapeParentalControl && - !user.IsParentalScheduleAllowed()) - { - request.AddResponseHeader("X-Application-Error-Code", "ParentalControl"); - - throw new SecurityException("This user account is not allowed access at this time.") - { - SecurityExceptionType = SecurityExceptionType.ParentalControl - }; - } - - if (!string.IsNullOrWhiteSpace(auth.DeviceId)) - { - if (!DeviceManager.CanAccessDevice(user.Id.ToString("N"), auth.DeviceId)) - { - throw new SecurityException("User is not allowed access from this device.") - { - SecurityExceptionType = SecurityExceptionType.ParentalControl - }; - } - } - } - - private bool IsExemptFromAuthenticationToken(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues) - { - if (!_config.Configuration.IsStartupWizardCompleted && authAttribtues.AllowBeforeStartupWizard) - { - return true; - } - - return false; - } - - private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues, AuthenticationInfo tokenInfo) - { - if (!_config.Configuration.IsStartupWizardCompleted && authAttribtues.AllowBeforeStartupWizard) - { - return true; - } - - if (string.IsNullOrWhiteSpace(auth.Token)) - { - return true; - } - - if (tokenInfo != null && string.IsNullOrWhiteSpace(tokenInfo.UserId)) - { - return true; - } - - return false; - } - - private void ValidateRoles(List<string> roles, User user) - { - if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase)) - { - if (user == null || !user.Policy.IsAdministrator) - { - throw new SecurityException("User does not have admin access.") - { - SecurityExceptionType = SecurityExceptionType.Unauthenticated - }; - } - } - if (roles.Contains("delete", StringComparer.OrdinalIgnoreCase)) - { - if (user == null || !user.Policy.EnableContentDeletion) - { - throw new SecurityException("User does not have delete access.") - { - SecurityExceptionType = SecurityExceptionType.Unauthenticated - }; - } - } - if (roles.Contains("download", StringComparer.OrdinalIgnoreCase)) - { - if (user == null || !user.Policy.EnableContentDownloading) - { - throw new SecurityException("User does not have download access.") - { - SecurityExceptionType = SecurityExceptionType.Unauthenticated - }; - } - } - } - - private AuthenticationInfo GetTokenInfo(IServiceRequest request) - { - object info; - request.Items.TryGetValue("OriginalAuthenticationInfo", out info); - return info as AuthenticationInfo; - } - - private bool IsValidConnectKey(string token) - { - if (string.IsNullOrEmpty(token)) - { - return false; - } - - return ConnectManager.IsAuthorizationTokenValid(token); - } - - private void ValidateSecurityToken(IServiceRequest request, string token) - { - if (string.IsNullOrWhiteSpace(token)) - { - throw new SecurityException("Access token is required."); - } - - var info = GetTokenInfo(request); - - if (info == null) - { - throw new SecurityException("Access token is invalid or expired."); - } - - if (!info.IsActive) - { - throw new SecurityException("Access token has expired."); - } - - //if (!string.IsNullOrWhiteSpace(info.UserId)) - //{ - // var user = _userManager.GetUserById(info.UserId); - - // if (user == null || user.Configuration.IsDisabled) - // { - // throw new SecurityException("User account has been disabled."); - // } - //} - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs deleted file mode 100644 index bc3e7b163b..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs +++ /dev/null @@ -1,195 +0,0 @@ -using MediaBrowser.Controller.Connect; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Security; -using ServiceStack.Web; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MediaBrowser.Server.Implementations.HttpServer.Security -{ - public class AuthorizationContext : IAuthorizationContext - { - private readonly IAuthenticationRepository _authRepo; - private readonly IConnectManager _connectManager; - - public AuthorizationContext(IAuthenticationRepository authRepo, IConnectManager connectManager) - { - _authRepo = authRepo; - _connectManager = connectManager; - } - - public AuthorizationInfo GetAuthorizationInfo(object requestContext) - { - var req = new ServiceStackServiceRequest((IRequest)requestContext); - return GetAuthorizationInfo(req); - } - - public AuthorizationInfo GetAuthorizationInfo(IServiceRequest requestContext) - { - object cached; - if (requestContext.Items.TryGetValue("AuthorizationInfo", out cached)) - { - return (AuthorizationInfo)cached; - } - - return GetAuthorization(requestContext); - } - - /// <summary> - /// Gets the authorization. - /// </summary> - /// <param name="httpReq">The HTTP req.</param> - /// <returns>Dictionary{System.StringSystem.String}.</returns> - private AuthorizationInfo GetAuthorization(IServiceRequest httpReq) - { - var auth = GetAuthorizationDictionary(httpReq); - - string deviceId = null; - string device = null; - string client = null; - string version = null; - - if (auth != null) - { - auth.TryGetValue("DeviceId", out deviceId); - auth.TryGetValue("Device", out device); - auth.TryGetValue("Client", out client); - auth.TryGetValue("Version", out version); - } - - var token = httpReq.Headers["X-Emby-Token"]; - - if (string.IsNullOrWhiteSpace(token)) - { - token = httpReq.Headers["X-MediaBrowser-Token"]; - } - if (string.IsNullOrWhiteSpace(token)) - { - token = httpReq.QueryString["api_key"]; - } - - var info = new AuthorizationInfo - { - Client = client, - Device = device, - DeviceId = deviceId, - Version = version, - Token = token - }; - - if (!string.IsNullOrWhiteSpace(token)) - { - var result = _authRepo.Get(new AuthenticationInfoQuery - { - AccessToken = token - }); - - var tokenInfo = result.Items.FirstOrDefault(); - - if (tokenInfo != null) - { - info.UserId = tokenInfo.UserId; - - // TODO: Remove these checks for IsNullOrWhiteSpace - if (string.IsNullOrWhiteSpace(info.Client)) - { - info.Client = tokenInfo.AppName; - } - if (string.IsNullOrWhiteSpace(info.Device)) - { - info.Device = tokenInfo.DeviceName; - } - if (string.IsNullOrWhiteSpace(info.DeviceId)) - { - info.DeviceId = tokenInfo.DeviceId; - } - if (string.IsNullOrWhiteSpace(info.Version)) - { - info.Version = tokenInfo.AppVersion; - } - } - else - { - var user = _connectManager.GetUserFromExchangeToken(token); - if (user != null) - { - info.UserId = user.Id.ToString("N"); - } - } - httpReq.Items["OriginalAuthenticationInfo"] = tokenInfo; - } - - httpReq.Items["AuthorizationInfo"] = info; - - return info; - } - - /// <summary> - /// Gets the auth. - /// </summary> - /// <param name="httpReq">The HTTP req.</param> - /// <returns>Dictionary{System.StringSystem.String}.</returns> - private Dictionary<string, string> GetAuthorizationDictionary(IServiceRequest httpReq) - { - var auth = httpReq.Headers["X-Emby-Authorization"]; - - if (string.IsNullOrWhiteSpace(auth)) - { - auth = httpReq.Headers["Authorization"]; - } - - return GetAuthorization(auth); - } - - /// <summary> - /// Gets the authorization. - /// </summary> - /// <param name="authorizationHeader">The authorization header.</param> - /// <returns>Dictionary{System.StringSystem.String}.</returns> - private Dictionary<string, string> GetAuthorization(string authorizationHeader) - { - if (authorizationHeader == null) return null; - - var parts = authorizationHeader.Split(new[] { ' ' }, 2); - - // There should be at least to parts - if (parts.Length != 2) return null; - - // It has to be a digest request - if (!string.Equals(parts[0], "MediaBrowser", StringComparison.OrdinalIgnoreCase)) - { - return null; - } - - // Remove uptil the first space - authorizationHeader = parts[1]; - parts = authorizationHeader.Split(','); - - var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - - foreach (var item in parts) - { - var param = item.Trim().Split(new[] { '=' }, 2); - - if (param.Length == 2) - { - var value = NormalizeValue (param[1].Trim(new[] { '"' })); - result.Add(param[0], value); - } - } - - return result; - } - - private string NormalizeValue(string value) - { - if (string.IsNullOrWhiteSpace (value)) - { - return value; - } - - return System.Net.WebUtility.HtmlEncode(value); - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/SessionAuthProvider.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/SessionAuthProvider.cs deleted file mode 100644 index 7c31731012..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/SessionAuthProvider.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MediaBrowser.Controller.Net; -using ServiceStack; -using ServiceStack.Auth; - -namespace MediaBrowser.Server.Implementations.HttpServer.Security -{ - public class SessionAuthProvider : CredentialsAuthProvider - { - private readonly ISessionContext _sessionContext; - - public SessionAuthProvider(ISessionContext sessionContext) - { - _sessionContext = sessionContext; - } - - public override bool TryAuthenticate(IServiceBase authService, string userName, string password) - { - return true; - } - - public override bool IsAuthorized(IAuthSession session, IAuthTokens tokens, Authenticate request = null) - { - return true; - } - - protected override void SaveUserAuth(IServiceBase authService, IAuthSession session, IAuthRepository authRepo, IAuthTokens tokens) - { - } - - public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request) - { - return base.Authenticate(authService, session, request); - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs deleted file mode 100644 index a498d32fac..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs +++ /dev/null @@ -1,67 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Security; -using MediaBrowser.Controller.Session; -using ServiceStack.Web; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.HttpServer.Security -{ - public class SessionContext : ISessionContext - { - private readonly IUserManager _userManager; - private readonly ISessionManager _sessionManager; - private readonly IAuthorizationContext _authContext; - - public SessionContext(IUserManager userManager, IAuthorizationContext authContext, ISessionManager sessionManager) - { - _userManager = userManager; - _authContext = authContext; - _sessionManager = sessionManager; - } - - public Task<SessionInfo> GetSession(IServiceRequest requestContext) - { - var authorization = _authContext.GetAuthorizationInfo(requestContext); - - //if (!string.IsNullOrWhiteSpace(authorization.Token)) - //{ - // var auth = GetTokenInfo(requestContext); - // if (auth != null) - // { - // return _sessionManager.GetSessionByAuthenticationToken(auth, authorization.DeviceId, requestContext.RemoteIp, authorization.Version); - // } - //} - - var user = string.IsNullOrWhiteSpace(authorization.UserId) ? null : _userManager.GetUserById(authorization.UserId); - return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.RemoteIp, user); - } - - private AuthenticationInfo GetTokenInfo(IServiceRequest request) - { - object info; - request.Items.TryGetValue("OriginalAuthenticationInfo", out info); - return info as AuthenticationInfo; - } - - public Task<SessionInfo> GetSession(object requestContext) - { - var req = new ServiceStackServiceRequest((IRequest)requestContext); - return GetSession(req); - } - - public async Task<User> GetUser(IServiceRequest requestContext) - { - var session = await GetSession(requestContext).ConfigureAwait(false); - - return session == null || !session.UserId.HasValue ? null : _userManager.GetUserById(session.UserId.Value); - } - - public Task<User> GetUser(object requestContext) - { - var req = new ServiceStackServiceRequest((IRequest)requestContext); - return GetUser(req); - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs deleted file mode 100644 index 8a7c14eb66..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Logging; -using ServiceStack.Logging; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - /// <summary> - /// Class ServerFactory - /// </summary> - public static class ServerFactory - { - /// <summary> - /// Creates the server. - /// </summary> - /// <returns>IHttpServer.</returns> - public static IHttpServer CreateServer(IApplicationHost applicationHost, - ILogManager logManager, - IServerConfigurationManager config, - INetworkManager _networkmanager, - IMemoryStreamProvider streamProvider, - string serverName, - string defaultRedirectpath) - { - LogManager.LogFactory = new ServerLogFactory(logManager); - - return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, _networkmanager, streamProvider); - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs deleted file mode 100644 index 40af3f3b05..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using MediaBrowser.Model.Logging; -using ServiceStack.Logging; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - /// <summary> - /// Class ServerLogFactory - /// </summary> - public class ServerLogFactory : ILogFactory - { - /// <summary> - /// The _log manager - /// </summary> - private readonly ILogManager _logManager; - - /// <summary> - /// Initializes a new instance of the <see cref="ServerLogFactory"/> class. - /// </summary> - /// <param name="logManager">The log manager.</param> - public ServerLogFactory(ILogManager logManager) - { - _logManager = logManager; - } - - /// <summary> - /// Gets the logger. - /// </summary> - /// <param name="typeName">Name of the type.</param> - /// <returns>ILog.</returns> - public ILog GetLogger(string typeName) - { - return new ServerLogger(_logManager.GetLogger(typeName)); - } - - /// <summary> - /// Gets the logger. - /// </summary> - /// <param name="type">The type.</param> - /// <returns>ILog.</returns> - public ILog GetLogger(Type type) - { - return GetLogger(type.Name); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs deleted file mode 100644 index bf79247841..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs +++ /dev/null @@ -1,194 +0,0 @@ -using MediaBrowser.Model.Logging; -using ServiceStack.Logging; -using System; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - /// <summary> - /// Class ServerLogger - /// </summary> - public class ServerLogger : ILog - { - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - /// <summary> - /// Initializes a new instance of the <see cref="ServerLogger"/> class. - /// </summary> - /// <param name="logger">The logger.</param> - public ServerLogger(ILogger logger) - { - _logger = logger; - } - - /// <summary> - /// Logs a Debug message and exception. - /// </summary> - /// <param name="message">The message.</param> - /// <param name="exception">The exception.</param> - public void Debug(object message, Exception exception) - { - _logger.ErrorException(GetMesssage(message), exception); - } - - /// <summary> - /// Logs a Debug message. - /// </summary> - /// <param name="message">The message.</param> - public void Debug(object message) - { - // Way too verbose. Can always make this configurable if needed again. - //_logger.Debug(GetMesssage(message)); - } - - /// <summary> - /// Logs a Debug format message. - /// </summary> - /// <param name="format">The format.</param> - /// <param name="args">The args.</param> - public void DebugFormat(string format, params object[] args) - { - // Way too verbose. Can always make this configurable if needed again. - //_logger.Debug(format, args); - } - - /// <summary> - /// Logs a Error message and exception. - /// </summary> - /// <param name="message">The message.</param> - /// <param name="exception">The exception.</param> - public void Error(object message, Exception exception) - { - _logger.ErrorException(GetMesssage(message), exception); - } - - /// <summary> - /// Logs a Error message. - /// </summary> - /// <param name="message">The message.</param> - public void Error(object message) - { - _logger.Error(GetMesssage(message)); - } - - /// <summary> - /// Logs a Error format message. - /// </summary> - /// <param name="format">The format.</param> - /// <param name="args">The args.</param> - public void ErrorFormat(string format, params object[] args) - { - _logger.Error(format, args); - } - - /// <summary> - /// Logs a Fatal message and exception. - /// </summary> - /// <param name="message">The message.</param> - /// <param name="exception">The exception.</param> - public void Fatal(object message, Exception exception) - { - _logger.FatalException(GetMesssage(message), exception); - } - - /// <summary> - /// Logs a Fatal message. - /// </summary> - /// <param name="message">The message.</param> - public void Fatal(object message) - { - _logger.Fatal(GetMesssage(message)); - } - - /// <summary> - /// Logs a Error format message. - /// </summary> - /// <param name="format">The format.</param> - /// <param name="args">The args.</param> - public void FatalFormat(string format, params object[] args) - { - _logger.Fatal(format, args); - } - - /// <summary> - /// Logs an Info message and exception. - /// </summary> - /// <param name="message">The message.</param> - /// <param name="exception">The exception.</param> - public void Info(object message, Exception exception) - { - _logger.ErrorException(GetMesssage(message), exception); - } - - /// <summary> - /// Logs an Info message and exception. - /// </summary> - /// <param name="message">The message.</param> - public void Info(object message) - { - _logger.Info(GetMesssage(message)); - } - - /// <summary> - /// Logs an Info format message. - /// </summary> - /// <param name="format">The format.</param> - /// <param name="args">The args.</param> - public void InfoFormat(string format, params object[] args) - { - _logger.Info(format, args); - } - - /// <summary> - /// Gets or sets a value indicating whether this instance is debug enabled. - /// </summary> - /// <value><c>true</c> if this instance is debug enabled; otherwise, <c>false</c>.</value> - public bool IsDebugEnabled - { - get { return true; } - } - - /// <summary> - /// Logs a Warning message and exception. - /// </summary> - /// <param name="message">The message.</param> - /// <param name="exception">The exception.</param> - public void Warn(object message, Exception exception) - { - _logger.ErrorException(GetMesssage(message), exception); - } - - /// <summary> - /// Logs a Warning message. - /// </summary> - /// <param name="message">The message.</param> - public void Warn(object message) - { - // Hide StringMapTypeDeserializer messages - // _logger.Warn(GetMesssage(message)); - } - - /// <summary> - /// Logs a Warning format message. - /// </summary> - /// <param name="format">The format.</param> - /// <param name="args">The args.</param> - public void WarnFormat(string format, params object[] args) - { - // Hide StringMapTypeDeserializer messages - // _logger.Warn(format, args); - } - - /// <summary> - /// Gets the messsage. - /// </summary> - /// <param name="o">The o.</param> - /// <returns>System.String.</returns> - private string GetMesssage(object o) - { - return o == null ? string.Empty : o.ToString(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs deleted file mode 100644 index 154313fb90..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs +++ /dev/null @@ -1,28 +0,0 @@ -using MediaBrowser.Model.Logging; -using SocketHttpListener.Net; -using System; - -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp -{ - public static class Extensions - { - public static string GetOperationName(this HttpListenerRequest request) - { - return request.Url.Segments[request.Url.Segments.Length - 1]; - } - - public static void CloseOutputStream(this HttpListenerResponse response, ILogger logger) - { - try - { - response.OutputStream.Flush(); - response.OutputStream.Close(); - response.Close(); - } - catch (Exception ex) - { - logger.ErrorException("Error in HttpListenerResponseWrapper: " + ex.Message, ex); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs deleted file mode 100644 index 3ef48d13a0..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs +++ /dev/null @@ -1,941 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Text; - -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp -{ - public static class MyHttpUtility - { - sealed class HttpQSCollection : NameValueCollection - { - public override string ToString() - { - int count = Count; - if (count == 0) - return ""; - StringBuilder sb = new StringBuilder(); - string[] keys = AllKeys; - for (int i = 0; i < count; i++) - { - sb.AppendFormat("{0}={1}&", keys[i], this[keys[i]]); - } - if (sb.Length > 0) - sb.Length--; - return sb.ToString(); - } - } - - // Must be sorted - static readonly long[] entities = new long[] { - (long)'A' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24, - (long)'A' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'A' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, - (long)'A' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, - (long)'A' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24, - (long)'A' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24, - (long)'A' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, - (long)'A' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'B' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32, - (long)'C' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16, - (long)'C' << 56 | (long)'h' << 48 | (long)'i' << 40, - (long)'D' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16, - (long)'D' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24, - (long)'E' << 56 | (long)'T' << 48 | (long)'H' << 40, - (long)'E' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'E' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, - (long)'E' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, - (long)'E' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8, - (long)'E' << 56 | (long)'t' << 48 | (long)'a' << 40, - (long)'E' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'G' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24, - (long)'I' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'I' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, - (long)'I' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, - (long)'I' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32, - (long)'I' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'K' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24, - (long)'L' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16, - (long)'M' << 56 | (long)'u' << 48, - (long)'N' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, - (long)'N' << 56 | (long)'u' << 48, - (long)'O' << 56 | (long)'E' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24, - (long)'O' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'O' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, - (long)'O' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, - (long)'O' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24, - (long)'O' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8, - (long)'O' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16, - (long)'O' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, - (long)'O' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'P' << 56 | (long)'h' << 48 | (long)'i' << 40, - (long)'P' << 56 | (long)'i' << 48, - (long)'P' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24, - (long)'P' << 56 | (long)'s' << 48 | (long)'i' << 40, - (long)'R' << 56 | (long)'h' << 48 | (long)'o' << 40, - (long)'S' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16, - (long)'S' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24, - (long)'T' << 56 | (long)'H' << 48 | (long)'O' << 40 | (long)'R' << 32 | (long)'N' << 24, - (long)'T' << 56 | (long)'a' << 48 | (long)'u' << 40, - (long)'T' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24, - (long)'U' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'U' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, - (long)'U' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, - (long)'U' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8, - (long)'U' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'X' << 56 | (long)'i' << 48, - (long)'Y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'Y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'Z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32, - (long)'a' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'a' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, - (long)'a' << 56 | (long)'c' << 48 | (long)'u' << 40 | (long)'t' << 32 | (long)'e' << 24, - (long)'a' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24, - (long)'a' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, - (long)'a' << 56 | (long)'l' << 48 | (long)'e' << 40 | (long)'f' << 32 | (long)'s' << 24 | (long)'y' << 16 | (long)'m' << 8, - (long)'a' << 56 | (long)'l' << 48 | (long)'p' << 40 | (long)'h' << 32 | (long)'a' << 24, - (long)'a' << 56 | (long)'m' << 48 | (long)'p' << 40, - (long)'a' << 56 | (long)'n' << 48 | (long)'d' << 40, - (long)'a' << 56 | (long)'n' << 48 | (long)'g' << 40, - (long)'a' << 56 | (long)'p' << 48 | (long)'o' << 40 | (long)'s' << 32, - (long)'a' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'g' << 24, - (long)'a' << 56 | (long)'s' << 48 | (long)'y' << 40 | (long)'m' << 32 | (long)'p' << 24, - (long)'a' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, - (long)'a' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'b' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, - (long)'b' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32, - (long)'b' << 56 | (long)'r' << 48 | (long)'v' << 40 | (long)'b' << 32 | (long)'a' << 24 | (long)'r' << 16, - (long)'b' << 56 | (long)'u' << 48 | (long)'l' << 40 | (long)'l' << 32, - (long)'c' << 56 | (long)'a' << 48 | (long)'p' << 40, - (long)'c' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'d' << 32 | (long)'i' << 24 | (long)'l' << 16, - (long)'c' << 56 | (long)'e' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'l' << 24, - (long)'c' << 56 | (long)'e' << 48 | (long)'n' << 40 | (long)'t' << 32, - (long)'c' << 56 | (long)'h' << 48 | (long)'i' << 40, - (long)'c' << 56 | (long)'i' << 48 | (long)'r' << 40 | (long)'c' << 32, - (long)'c' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'b' << 32 | (long)'s' << 24, - (long)'c' << 56 | (long)'o' << 48 | (long)'n' << 40 | (long)'g' << 32, - (long)'c' << 56 | (long)'o' << 48 | (long)'p' << 40 | (long)'y' << 32, - (long)'c' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'r' << 24, - (long)'c' << 56 | (long)'u' << 48 | (long)'p' << 40, - (long)'c' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'n' << 16, - (long)'d' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32, - (long)'d' << 56 | (long)'a' << 48 | (long)'g' << 40 | (long)'g' << 32 | (long)'e' << 24 | (long)'r' << 16, - (long)'d' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32, - (long)'d' << 56 | (long)'e' << 48 | (long)'g' << 40, - (long)'d' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'t' << 32 | (long)'a' << 24, - (long)'d' << 56 | (long)'i' << 48 | (long)'a' << 40 | (long)'m' << 32 | (long)'s' << 24, - (long)'d' << 56 | (long)'i' << 48 | (long)'v' << 40 | (long)'i' << 32 | (long)'d' << 24 | (long)'e' << 16, - (long)'e' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'e' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, - (long)'e' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, - (long)'e' << 56 | (long)'m' << 48 | (long)'p' << 40 | (long)'t' << 32 | (long)'y' << 24, - (long)'e' << 56 | (long)'m' << 48 | (long)'s' << 40 | (long)'p' << 32, - (long)'e' << 56 | (long)'n' << 48 | (long)'s' << 40 | (long)'p' << 32, - (long)'e' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8, - (long)'e' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'i' << 32 | (long)'v' << 24, - (long)'e' << 56 | (long)'t' << 48 | (long)'a' << 40, - (long)'e' << 56 | (long)'t' << 48 | (long)'h' << 40, - (long)'e' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'e' << 56 | (long)'u' << 48 | (long)'r' << 40 | (long)'o' << 32, - (long)'e' << 56 | (long)'x' << 48 | (long)'i' << 40 | (long)'s' << 32 | (long)'t' << 24, - (long)'f' << 56 | (long)'n' << 48 | (long)'o' << 40 | (long)'f' << 32, - (long)'f' << 56 | (long)'o' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'l' << 24 | (long)'l' << 16, - (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'2' << 16, - (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'1' << 24 | (long)'4' << 16, - (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'c' << 32 | (long)'3' << 24 | (long)'4' << 16, - (long)'f' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'l' << 24, - (long)'g' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'m' << 32 | (long)'a' << 24, - (long)'g' << 56 | (long)'e' << 48, - (long)'g' << 56 | (long)'t' << 48, - (long)'h' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32, - (long)'h' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32, - (long)'h' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'t' << 24 | (long)'s' << 16, - (long)'h' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'l' << 32 | (long)'i' << 24 | (long)'p' << 16, - (long)'i' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'i' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, - (long)'i' << 56 | (long)'e' << 48 | (long)'x' << 40 | (long)'c' << 32 | (long)'l' << 24, - (long)'i' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, - (long)'i' << 56 | (long)'m' << 48 | (long)'a' << 40 | (long)'g' << 32 | (long)'e' << 24, - (long)'i' << 56 | (long)'n' << 48 | (long)'f' << 40 | (long)'i' << 32 | (long)'n' << 24, - (long)'i' << 56 | (long)'n' << 48 | (long)'t' << 40, - (long)'i' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'a' << 32, - (long)'i' << 56 | (long)'q' << 48 | (long)'u' << 40 | (long)'e' << 32 | (long)'s' << 24 | (long)'t' << 16, - (long)'i' << 56 | (long)'s' << 48 | (long)'i' << 40 | (long)'n' << 32, - (long)'i' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'k' << 56 | (long)'a' << 48 | (long)'p' << 40 | (long)'p' << 32 | (long)'a' << 24, - (long)'l' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32, - (long)'l' << 56 | (long)'a' << 48 | (long)'m' << 40 | (long)'b' << 32 | (long)'d' << 24 | (long)'a' << 16, - (long)'l' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32, - (long)'l' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, - (long)'l' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32, - (long)'l' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24, - (long)'l' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, - (long)'l' << 56 | (long)'e' << 48, - (long)'l' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16, - (long)'l' << 56 | (long)'o' << 48 | (long)'w' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'t' << 16, - (long)'l' << 56 | (long)'o' << 48 | (long)'z' << 40, - (long)'l' << 56 | (long)'r' << 48 | (long)'m' << 40, - (long)'l' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16, - (long)'l' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, - (long)'l' << 56 | (long)'t' << 48, - (long)'m' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'r' << 32, - (long)'m' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24, - (long)'m' << 56 | (long)'i' << 48 | (long)'c' << 40 | (long)'r' << 32 | (long)'o' << 24, - (long)'m' << 56 | (long)'i' << 48 | (long)'d' << 40 | (long)'d' << 32 | (long)'o' << 24 | (long)'t' << 16, - (long)'m' << 56 | (long)'i' << 48 | (long)'n' << 40 | (long)'u' << 32 | (long)'s' << 24, - (long)'m' << 56 | (long)'u' << 48, - (long)'n' << 56 | (long)'a' << 48 | (long)'b' << 40 | (long)'l' << 32 | (long)'a' << 24, - (long)'n' << 56 | (long)'b' << 48 | (long)'s' << 40 | (long)'p' << 32, - (long)'n' << 56 | (long)'d' << 48 | (long)'a' << 40 | (long)'s' << 32 | (long)'h' << 24, - (long)'n' << 56 | (long)'e' << 48, - (long)'n' << 56 | (long)'i' << 48, - (long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40, - (long)'n' << 56 | (long)'o' << 48 | (long)'t' << 40 | (long)'i' << 32 | (long)'n' << 24, - (long)'n' << 56 | (long)'s' << 48 | (long)'u' << 40 | (long)'b' << 32, - (long)'n' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, - (long)'n' << 56 | (long)'u' << 48, - (long)'o' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'o' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, - (long)'o' << 56 | (long)'e' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24, - (long)'o' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, - (long)'o' << 56 | (long)'l' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'e' << 24, - (long)'o' << 56 | (long)'m' << 48 | (long)'e' << 40 | (long)'g' << 32 | (long)'a' << 24, - (long)'o' << 56 | (long)'m' << 48 | (long)'i' << 40 | (long)'c' << 32 | (long)'r' << 24 | (long)'o' << 16 | (long)'n' << 8, - (long)'o' << 56 | (long)'p' << 48 | (long)'l' << 40 | (long)'u' << 32 | (long)'s' << 24, - (long)'o' << 56 | (long)'r' << 48, - (long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'f' << 32, - (long)'o' << 56 | (long)'r' << 48 | (long)'d' << 40 | (long)'m' << 32, - (long)'o' << 56 | (long)'s' << 48 | (long)'l' << 40 | (long)'a' << 32 | (long)'s' << 24 | (long)'h' << 16, - (long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'l' << 32 | (long)'d' << 24 | (long)'e' << 16, - (long)'o' << 56 | (long)'t' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24 | (long)'s' << 16, - (long)'o' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'a' << 32, - (long)'p' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'t' << 32, - (long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'m' << 32 | (long)'i' << 24 | (long)'l' << 16, - (long)'p' << 56 | (long)'e' << 48 | (long)'r' << 40 | (long)'p' << 32, - (long)'p' << 56 | (long)'h' << 48 | (long)'i' << 40, - (long)'p' << 56 | (long)'i' << 48, - (long)'p' << 56 | (long)'i' << 48 | (long)'v' << 40, - (long)'p' << 56 | (long)'l' << 48 | (long)'u' << 40 | (long)'s' << 32 | (long)'m' << 24 | (long)'n' << 16, - (long)'p' << 56 | (long)'o' << 48 | (long)'u' << 40 | (long)'n' << 32 | (long)'d' << 24, - (long)'p' << 56 | (long)'r' << 48 | (long)'i' << 40 | (long)'m' << 32 | (long)'e' << 24, - (long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'d' << 32, - (long)'p' << 56 | (long)'r' << 48 | (long)'o' << 40 | (long)'p' << 32, - (long)'p' << 56 | (long)'s' << 48 | (long)'i' << 40, - (long)'q' << 56 | (long)'u' << 48 | (long)'o' << 40 | (long)'t' << 32, - (long)'r' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32, - (long)'r' << 56 | (long)'a' << 48 | (long)'d' << 40 | (long)'i' << 32 | (long)'c' << 24, - (long)'r' << 56 | (long)'a' << 48 | (long)'n' << 40 | (long)'g' << 32, - (long)'r' << 56 | (long)'a' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, - (long)'r' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32, - (long)'r' << 56 | (long)'c' << 48 | (long)'e' << 40 | (long)'i' << 32 | (long)'l' << 24, - (long)'r' << 56 | (long)'d' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, - (long)'r' << 56 | (long)'e' << 48 | (long)'a' << 40 | (long)'l' << 32, - (long)'r' << 56 | (long)'e' << 48 | (long)'g' << 40, - (long)'r' << 56 | (long)'f' << 48 | (long)'l' << 40 | (long)'o' << 32 | (long)'o' << 24 | (long)'r' << 16, - (long)'r' << 56 | (long)'h' << 48 | (long)'o' << 40, - (long)'r' << 56 | (long)'l' << 48 | (long)'m' << 40, - (long)'r' << 56 | (long)'s' << 48 | (long)'a' << 40 | (long)'q' << 32 | (long)'u' << 24 | (long)'o' << 16, - (long)'r' << 56 | (long)'s' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, - (long)'s' << 56 | (long)'b' << 48 | (long)'q' << 40 | (long)'u' << 32 | (long)'o' << 24, - (long)'s' << 56 | (long)'c' << 48 | (long)'a' << 40 | (long)'r' << 32 | (long)'o' << 24 | (long)'n' << 16, - (long)'s' << 56 | (long)'d' << 48 | (long)'o' << 40 | (long)'t' << 32, - (long)'s' << 56 | (long)'e' << 48 | (long)'c' << 40 | (long)'t' << 32, - (long)'s' << 56 | (long)'h' << 48 | (long)'y' << 40, - (long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24, - (long)'s' << 56 | (long)'i' << 48 | (long)'g' << 40 | (long)'m' << 32 | (long)'a' << 24 | (long)'f' << 16, - (long)'s' << 56 | (long)'i' << 48 | (long)'m' << 40, - (long)'s' << 56 | (long)'p' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24 | (long)'s' << 16, - (long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40, - (long)'s' << 56 | (long)'u' << 48 | (long)'b' << 40 | (long)'e' << 32, - (long)'s' << 56 | (long)'u' << 48 | (long)'m' << 40, - (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40, - (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'1' << 32, - (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'2' << 32, - (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'3' << 32, - (long)'s' << 56 | (long)'u' << 48 | (long)'p' << 40 | (long)'e' << 32, - (long)'s' << 56 | (long)'z' << 48 | (long)'l' << 40 | (long)'i' << 32 | (long)'g' << 24, - (long)'t' << 56 | (long)'a' << 48 | (long)'u' << 40, - (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'r' << 32 | (long)'e' << 24 | (long)'4' << 16, - (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24, - (long)'t' << 56 | (long)'h' << 48 | (long)'e' << 40 | (long)'t' << 32 | (long)'a' << 24 | (long)'s' << 16 | (long)'y' << 8 | (long)'m' << 0, - (long)'t' << 56 | (long)'h' << 48 | (long)'i' << 40 | (long)'n' << 32 | (long)'s' << 24 | (long)'p' << 16, - (long)'t' << 56 | (long)'h' << 48 | (long)'o' << 40 | (long)'r' << 32 | (long)'n' << 24, - (long)'t' << 56 | (long)'i' << 48 | (long)'l' << 40 | (long)'d' << 32 | (long)'e' << 24, - (long)'t' << 56 | (long)'i' << 48 | (long)'m' << 40 | (long)'e' << 32 | (long)'s' << 24, - (long)'t' << 56 | (long)'r' << 48 | (long)'a' << 40 | (long)'d' << 32 | (long)'e' << 24, - (long)'u' << 56 | (long)'A' << 48 | (long)'r' << 40 | (long)'r' << 32, - (long)'u' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'u' << 56 | (long)'a' << 48 | (long)'r' << 40 | (long)'r' << 32, - (long)'u' << 56 | (long)'c' << 48 | (long)'i' << 40 | (long)'r' << 32 | (long)'c' << 24, - (long)'u' << 56 | (long)'g' << 48 | (long)'r' << 40 | (long)'a' << 32 | (long)'v' << 24 | (long)'e' << 16, - (long)'u' << 56 | (long)'m' << 48 | (long)'l' << 40, - (long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'h' << 24, - (long)'u' << 56 | (long)'p' << 48 | (long)'s' << 40 | (long)'i' << 32 | (long)'l' << 24 | (long)'o' << 16 | (long)'n' << 8, - (long)'u' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'w' << 56 | (long)'e' << 48 | (long)'i' << 40 | (long)'e' << 32 | (long)'r' << 24 | (long)'p' << 16, - (long)'x' << 56 | (long)'i' << 48, - (long)'y' << 56 | (long)'a' << 48 | (long)'c' << 40 | (long)'u' << 32 | (long)'t' << 24 | (long)'e' << 16, - (long)'y' << 56 | (long)'e' << 48 | (long)'n' << 40, - (long)'y' << 56 | (long)'u' << 48 | (long)'m' << 40 | (long)'l' << 32, - (long)'z' << 56 | (long)'e' << 48 | (long)'t' << 40 | (long)'a' << 32, - (long)'z' << 56 | (long)'w' << 48 | (long)'j' << 40, - (long)'z' << 56 | (long)'w' << 48 | (long)'n' << 40 | (long)'j' << 32 - }; - - static readonly char[] entities_values = new char[] { - '\u00C6', - '\u00C1', - '\u00C2', - '\u00C0', - '\u0391', - '\u00C5', - '\u00C3', - '\u00C4', - '\u0392', - '\u00C7', - '\u03A7', - '\u2021', - '\u0394', - '\u00D0', - '\u00C9', - '\u00CA', - '\u00C8', - '\u0395', - '\u0397', - '\u00CB', - '\u0393', - '\u00CD', - '\u00CE', - '\u00CC', - '\u0399', - '\u00CF', - '\u039A', - '\u039B', - '\u039C', - '\u00D1', - '\u039D', - '\u0152', - '\u00D3', - '\u00D4', - '\u00D2', - '\u03A9', - '\u039F', - '\u00D8', - '\u00D5', - '\u00D6', - '\u03A6', - '\u03A0', - '\u2033', - '\u03A8', - '\u03A1', - '\u0160', - '\u03A3', - '\u00DE', - '\u03A4', - '\u0398', - '\u00DA', - '\u00DB', - '\u00D9', - '\u03A5', - '\u00DC', - '\u039E', - '\u00DD', - '\u0178', - '\u0396', - '\u00E1', - '\u00E2', - '\u00B4', - '\u00E6', - '\u00E0', - '\u2135', - '\u03B1', - '\u0026', - '\u2227', - '\u2220', - '\u0027', - '\u00E5', - '\u2248', - '\u00E3', - '\u00E4', - '\u201E', - '\u03B2', - '\u00A6', - '\u2022', - '\u2229', - '\u00E7', - '\u00B8', - '\u00A2', - '\u03C7', - '\u02C6', - '\u2663', - '\u2245', - '\u00A9', - '\u21B5', - '\u222A', - '\u00A4', - '\u21D3', - '\u2020', - '\u2193', - '\u00B0', - '\u03B4', - '\u2666', - '\u00F7', - '\u00E9', - '\u00EA', - '\u00E8', - '\u2205', - '\u2003', - '\u2002', - '\u03B5', - '\u2261', - '\u03B7', - '\u00F0', - '\u00EB', - '\u20AC', - '\u2203', - '\u0192', - '\u2200', - '\u00BD', - '\u00BC', - '\u00BE', - '\u2044', - '\u03B3', - '\u2265', - '\u003E', - '\u21D4', - '\u2194', - '\u2665', - '\u2026', - '\u00ED', - '\u00EE', - '\u00A1', - '\u00EC', - '\u2111', - '\u221E', - '\u222B', - '\u03B9', - '\u00BF', - '\u2208', - '\u00EF', - '\u03BA', - '\u21D0', - '\u03BB', - '\u2329', - '\u00AB', - '\u2190', - '\u2308', - '\u201C', - '\u2264', - '\u230A', - '\u2217', - '\u25CA', - '\u200E', - '\u2039', - '\u2018', - '\u003C', - '\u00AF', - '\u2014', - '\u00B5', - '\u00B7', - '\u2212', - '\u03BC', - '\u2207', - '\u00A0', - '\u2013', - '\u2260', - '\u220B', - '\u00AC', - '\u2209', - '\u2284', - '\u00F1', - '\u03BD', - '\u00F3', - '\u00F4', - '\u0153', - '\u00F2', - '\u203E', - '\u03C9', - '\u03BF', - '\u2295', - '\u2228', - '\u00AA', - '\u00BA', - '\u00F8', - '\u00F5', - '\u2297', - '\u00F6', - '\u00B6', - '\u2202', - '\u2030', - '\u22A5', - '\u03C6', - '\u03C0', - '\u03D6', - '\u00B1', - '\u00A3', - '\u2032', - '\u220F', - '\u221D', - '\u03C8', - '\u0022', - '\u21D2', - '\u221A', - '\u232A', - '\u00BB', - '\u2192', - '\u2309', - '\u201D', - '\u211C', - '\u00AE', - '\u230B', - '\u03C1', - '\u200F', - '\u203A', - '\u2019', - '\u201A', - '\u0161', - '\u22C5', - '\u00A7', - '\u00AD', - '\u03C3', - '\u03C2', - '\u223C', - '\u2660', - '\u2282', - '\u2286', - '\u2211', - '\u2283', - '\u00B9', - '\u00B2', - '\u00B3', - '\u2287', - '\u00DF', - '\u03C4', - '\u2234', - '\u03B8', - '\u03D1', - '\u2009', - '\u00FE', - '\u02DC', - '\u00D7', - '\u2122', - '\u21D1', - '\u00FA', - '\u2191', - '\u00FB', - '\u00F9', - '\u00A8', - '\u03D2', - '\u03C5', - '\u00FC', - '\u2118', - '\u03BE', - '\u00FD', - '\u00A5', - '\u00FF', - '\u03B6', - '\u200D', - '\u200C' - }; - - #region Methods - - static void WriteCharBytes(IList buf, char ch, Encoding e) - { - if (ch > 255) - { - foreach (byte b in e.GetBytes(new char[] { ch })) - buf.Add(b); - } - else - buf.Add((byte)ch); - } - - public static string UrlDecode(string s, Encoding e) - { - if (null == s) - return null; - - if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1) - return s; - - if (e == null) - e = Encoding.UTF8; - - long len = s.Length; - var bytes = new List<byte>(); - int xchar; - char ch; - - for (int i = 0; i < len; i++) - { - ch = s[i]; - if (ch == '%' && i + 2 < len && s[i + 1] != '%') - { - if (s[i + 1] == 'u' && i + 5 < len) - { - // unicode hex sequence - xchar = GetChar(s, i + 2, 4); - if (xchar != -1) - { - WriteCharBytes(bytes, (char)xchar, e); - i += 5; - } - else - WriteCharBytes(bytes, '%', e); - } - else if ((xchar = GetChar(s, i + 1, 2)) != -1) - { - WriteCharBytes(bytes, (char)xchar, e); - i += 2; - } - else - { - WriteCharBytes(bytes, '%', e); - } - continue; - } - - if (ch == '+') - WriteCharBytes(bytes, ' ', e); - else - WriteCharBytes(bytes, ch, e); - } - - byte[] buf = bytes.ToArray(); - bytes = null; - return e.GetString(buf); - - } - - static int GetInt(byte b) - { - char c = (char)b; - if (c >= '0' && c <= '9') - return c - '0'; - - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - - return -1; - } - - static int GetChar(string str, int offset, int length) - { - int val = 0; - int end = length + offset; - for (int i = offset; i < end; i++) - { - char c = str[i]; - if (c > 127) - return -1; - - int current = GetInt((byte)c); - if (current == -1) - return -1; - val = (val << 4) + current; - } - - return val; - } - - static bool TryConvertKeyToEntity(string key, out char value) - { - var token = CalculateKeyValue(key); - if (token == 0) - { - value = '\0'; - return false; - } - - var idx = Array.BinarySearch(entities, token); - if (idx < 0) - { - value = '\0'; - return false; - } - - value = entities_values[idx]; - return true; - } - - static long CalculateKeyValue(string s) - { - if (s.Length > 8) - return 0; - - long key = 0; - for (int i = 0; i < s.Length; ++i) - { - long ch = s[i]; - if (ch > 'z' || ch < '0') - return 0; - - key |= ch << ((7 - i) * 8); - } - - return key; - } - - /// <summary> - /// Decodes an HTML-encoded string and returns the decoded string. - /// </summary> - /// <param name="s">The HTML string to decode. </param> - /// <returns>The decoded text.</returns> - public static string HtmlDecode(string s) - { - if (s == null) - throw new ArgumentNullException("s"); - - if (s.IndexOf('&') == -1) - return s; - - StringBuilder entity = new StringBuilder(); - StringBuilder output = new StringBuilder(); - int len = s.Length; - // 0 -> nothing, - // 1 -> right after '&' - // 2 -> between '&' and ';' but no '#' - // 3 -> '#' found after '&' and getting numbers - int state = 0; - int number = 0; - int digit_start = 0; - bool hex_number = false; - - for (int i = 0; i < len; i++) - { - char c = s[i]; - if (state == 0) - { - if (c == '&') - { - entity.Append(c); - state = 1; - } - else - { - output.Append(c); - } - continue; - } - - if (c == '&') - { - state = 1; - if (digit_start > 0) - { - entity.Append(s, digit_start, i - digit_start); - digit_start = 0; - } - - output.Append(entity.ToString()); - entity.Length = 0; - entity.Append('&'); - continue; - } - - switch (state) - { - case 1: - if (c == ';') - { - state = 0; - output.Append(entity.ToString()); - output.Append(c); - entity.Length = 0; - break; - } - - number = 0; - hex_number = false; - if (c != '#') - { - state = 2; - } - else - { - state = 3; - } - entity.Append(c); - - break; - case 2: - entity.Append(c); - if (c == ';') - { - string key = entity.ToString(); - state = 0; - entity.Length = 0; - - if (key.Length > 1) - { - var skey = key.Substring(1, key.Length - 2); - if (TryConvertKeyToEntity(skey, out c)) - { - output.Append(c); - break; - } - } - - output.Append(key); - } - - break; - case 3: - if (c == ';') - { - if (number < 0x10000) - { - output.Append((char)number); - } - else - { - output.Append((char)(0xd800 + ((number - 0x10000) >> 10))); - output.Append((char)(0xdc00 + ((number - 0x10000) & 0x3ff))); - } - state = 0; - entity.Length = 0; - digit_start = 0; - break; - } - - if (c == 'x' || c == 'X' && !hex_number) - { - digit_start = i; - hex_number = true; - break; - } - - if (Char.IsDigit(c)) - { - if (digit_start == 0) - digit_start = i; - - number = number * (hex_number ? 16 : 10) + ((int)c - '0'); - break; - } - - if (hex_number) - { - if (c >= 'a' && c <= 'f') - { - number = number * 16 + 10 + ((int)c - 'a'); - break; - } - if (c >= 'A' && c <= 'F') - { - number = number * 16 + 10 + ((int)c - 'A'); - break; - } - } - - state = 2; - if (digit_start > 0) - { - entity.Append(s, digit_start, i - digit_start); - digit_start = 0; - } - - entity.Append(c); - break; - } - } - - if (entity.Length > 0) - { - output.Append(entity); - } - else if (digit_start > 0) - { - output.Append(s, digit_start, s.Length - digit_start); - } - return output.ToString(); - } - - public static NameValueCollection ParseQueryString(string query) - { - return ParseQueryString(query, Encoding.UTF8); - } - - public static NameValueCollection ParseQueryString(string query, Encoding encoding) - { - if (query == null) - throw new ArgumentNullException("query"); - if (encoding == null) - throw new ArgumentNullException("encoding"); - if (query.Length == 0 || (query.Length == 1 && query[0] == '?')) - return new NameValueCollection(); - if (query[0] == '?') - query = query.Substring(1); - - NameValueCollection result = new HttpQSCollection(); - ParseQueryString(query, encoding, result); - return result; - } - - internal static void ParseQueryString(string query, Encoding encoding, NameValueCollection result) - { - if (query.Length == 0) - return; - - string decoded = HtmlDecode(query); - int decodedLength = decoded.Length; - int namePos = 0; - bool first = true; - while (namePos <= decodedLength) - { - int valuePos = -1, valueEnd = -1; - for (int q = namePos; q < decodedLength; q++) - { - if (valuePos == -1 && decoded[q] == '=') - { - valuePos = q + 1; - } - else if (decoded[q] == '&') - { - valueEnd = q; - break; - } - } - - if (first) - { - first = false; - if (decoded[namePos] == '?') - namePos++; - } - - string name, value; - if (valuePos == -1) - { - name = null; - valuePos = namePos; - } - else - { - name = UrlDecode(decoded.Substring(namePos, valuePos - namePos - 1), encoding); - } - if (valueEnd < 0) - { - namePos = -1; - valueEnd = decoded.Length; - } - else - { - namePos = valueEnd + 1; - } - value = UrlDecode(decoded.Substring(valuePos, valueEnd - valuePos), encoding); - - result.Add(name, value); - if (namePos == -1) - break; - } - } - #endregion // Methods - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs deleted file mode 100644 index d20dd7ec08..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs +++ /dev/null @@ -1,916 +0,0 @@ -using System; -using System.Collections.Specialized; -using System.Globalization; -using System.IO; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using ServiceStack; -using ServiceStack.Web; - -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp -{ - public partial class WebSocketSharpRequest : IHttpRequest - { - static internal string GetParameter(string header, string attr) - { - int ap = header.IndexOf(attr); - if (ap == -1) - return null; - - ap += attr.Length; - if (ap >= header.Length) - return null; - - char ending = header[ap]; - if (ending != '"') - ending = ' '; - - int end = header.IndexOf(ending, ap + 1); - if (end == -1) - return ending == '"' ? null : header.Substring(ap); - - return header.Substring(ap + 1, end - ap - 1); - } - - async Task LoadMultiPart() - { - string boundary = GetParameter(ContentType, "; boundary="); - if (boundary == null) - return; - - using (var requestStream = GetSubStream(InputStream, _memoryStreamProvider)) - { - //DB: 30/01/11 - Hack to get around non-seekable stream and received HTTP request - //Not ending with \r\n? - var ms = _memoryStreamProvider.CreateNew(32 * 1024); - await requestStream.CopyToAsync(ms).ConfigureAwait(false); - - var input = ms; - ms.WriteByte((byte)'\r'); - ms.WriteByte((byte)'\n'); - - input.Position = 0; - - //Uncomment to debug - //var content = new StreamReader(ms).ReadToEnd(); - //Console.WriteLine(boundary + "::" + content); - //input.Position = 0; - - var multi_part = new HttpMultipart(input, boundary, ContentEncoding); - - HttpMultipart.Element e; - while ((e = multi_part.ReadNextElement()) != null) - { - if (e.Filename == null) - { - byte[] copy = new byte[e.Length]; - - input.Position = e.Start; - input.Read(copy, 0, (int)e.Length); - - form.Add(e.Name, (e.Encoding ?? ContentEncoding).GetString(copy)); - } - else - { - // - // We use a substream, as in 2.x we will support large uploads streamed to disk, - // - HttpPostedFile sub = new HttpPostedFile(e.Filename, e.ContentType, input, e.Start, e.Length); - files.AddFile(e.Name, sub); - } - } - } - } - - public NameValueCollection Form - { - get - { - if (form == null) - { - form = new WebROCollection(); - files = new HttpFileCollection(); - - if (IsContentType("multipart/form-data", true)) - { - var task = LoadMultiPart(); - Task.WaitAll(task); - } - else if (IsContentType("application/x-www-form-urlencoded", true)) - { - var task = LoadWwwForm(); - Task.WaitAll(task); - } - - form.Protect(); - } - -#if NET_4_0 - if (validateRequestNewMode && !checked_form) { - // Setting this before calling the validator prevents - // possible endless recursion - checked_form = true; - ValidateNameValueCollection ("Form", query_string_nvc, RequestValidationSource.Form); - } else -#endif - if (validate_form && !checked_form) - { - checked_form = true; - ValidateNameValueCollection("Form", form); - } - - return form; - } - } - - public string Accept - { - get - { - return string.IsNullOrEmpty(request.Headers[HttpHeaders.Accept]) ? null : request.Headers[HttpHeaders.Accept]; - } - } - - public string Authorization - { - get - { - return string.IsNullOrEmpty(request.Headers[HttpHeaders.Authorization]) ? null : request.Headers[HttpHeaders.Authorization]; - } - } - - protected bool validate_cookies, validate_query_string, validate_form; - protected bool checked_cookies, checked_query_string, checked_form; - - static void ThrowValidationException(string name, string key, string value) - { - string v = "\"" + value + "\""; - if (v.Length > 20) - v = v.Substring(0, 16) + "...\""; - - string msg = String.Format("A potentially dangerous Request.{0} value was " + - "detected from the client ({1}={2}).", name, key, v); - - throw new HttpRequestValidationException(msg); - } - - static void ValidateNameValueCollection(string name, NameValueCollection coll) - { - if (coll == null) - return; - - foreach (string key in coll.Keys) - { - string val = coll[key]; - if (val != null && val.Length > 0 && IsInvalidString(val)) - ThrowValidationException(name, key, val); - } - } - - internal static bool IsInvalidString(string val) - { - int validationFailureIndex; - - return IsInvalidString(val, out validationFailureIndex); - } - - internal static bool IsInvalidString(string val, out int validationFailureIndex) - { - validationFailureIndex = 0; - - int len = val.Length; - if (len < 2) - return false; - - char current = val[0]; - for (int idx = 1; idx < len; idx++) - { - char next = val[idx]; - // See http://secunia.com/advisories/14325 - if (current == '<' || current == '\xff1c') - { - if (next == '!' || next < ' ' - || (next >= 'a' && next <= 'z') - || (next >= 'A' && next <= 'Z')) - { - validationFailureIndex = idx - 1; - return true; - } - } - else if (current == '&' && next == '#') - { - validationFailureIndex = idx - 1; - return true; - } - - current = next; - } - - return false; - } - - public void ValidateInput() - { - validate_cookies = true; - validate_query_string = true; - validate_form = true; - } - - bool IsContentType(string ct, bool starts_with) - { - if (ct == null || ContentType == null) return false; - - if (starts_with) - return StrUtils.StartsWith(ContentType, ct, true); - - return String.Compare(ContentType, ct, true, Helpers.InvariantCulture) == 0; - } - - async Task LoadWwwForm() - { - using (Stream input = GetSubStream(InputStream, _memoryStreamProvider)) - { - using (var ms = _memoryStreamProvider.CreateNew()) - { - await input.CopyToAsync(ms).ConfigureAwait(false); - ms.Position = 0; - - using (StreamReader s = new StreamReader(ms, ContentEncoding)) - { - StringBuilder key = new StringBuilder(); - StringBuilder value = new StringBuilder(); - int c; - - while ((c = s.Read()) != -1) - { - if (c == '=') - { - value.Length = 0; - while ((c = s.Read()) != -1) - { - if (c == '&') - { - AddRawKeyValue(key, value); - break; - } - else - value.Append((char)c); - } - if (c == -1) - { - AddRawKeyValue(key, value); - return; - } - } - else if (c == '&') - AddRawKeyValue(key, value); - else - key.Append((char)c); - } - if (c == -1) - AddRawKeyValue(key, value); - } - } - } - } - - void AddRawKeyValue(StringBuilder key, StringBuilder value) - { - string decodedKey = HttpUtility.UrlDecode(key.ToString(), ContentEncoding); - form.Add(decodedKey, - HttpUtility.UrlDecode(value.ToString(), ContentEncoding)); - - key.Length = 0; - value.Length = 0; - } - - WebROCollection form; - - HttpFileCollection files; - - public sealed class HttpFileCollection : NameObjectCollectionBase - { - internal HttpFileCollection() - { - } - - internal void AddFile(string name, HttpPostedFile file) - { - BaseAdd(name, file); - } - - public void CopyTo(Array dest, int index) - { - /* XXX this is kind of gross and inefficient - * since it makes a copy of the superclass's - * list */ - object[] values = BaseGetAllValues(); - values.CopyTo(dest, index); - } - - public string GetKey(int index) - { - return BaseGetKey(index); - } - - public HttpPostedFile Get(int index) - { - return (HttpPostedFile)BaseGet(index); - } - - public HttpPostedFile Get(string key) - { - return (HttpPostedFile)BaseGet(key); - } - - public HttpPostedFile this[string key] - { - get - { - return Get(key); - } - } - - public HttpPostedFile this[int index] - { - get - { - return Get(index); - } - } - - public string[] AllKeys - { - get - { - return BaseGetAllKeys(); - } - } - } - class WebROCollection : NameValueCollection - { - bool got_id; - int id; - - public bool GotID - { - get { return got_id; } - } - - public int ID - { - get { return id; } - set - { - got_id = true; - id = value; - } - } - public void Protect() - { - IsReadOnly = true; - } - - public void Unprotect() - { - IsReadOnly = false; - } - - public override string ToString() - { - StringBuilder result = new StringBuilder(); - foreach (string key in AllKeys) - { - if (result.Length > 0) - result.Append('&'); - - if (key != null && key.Length > 0) - { - result.Append(key); - result.Append('='); - } - result.Append(Get(key)); - } - - return result.ToString(); - } - } - - public sealed class HttpPostedFile - { - string name; - string content_type; - Stream stream; - - class ReadSubStream : Stream - { - Stream s; - long offset; - long end; - long position; - - public ReadSubStream(Stream s, long offset, long length) - { - this.s = s; - this.offset = offset; - this.end = offset + length; - position = offset; - } - - public override void Flush() - { - } - - public override int Read(byte[] buffer, int dest_offset, int count) - { - if (buffer == null) - throw new ArgumentNullException("buffer"); - - if (dest_offset < 0) - throw new ArgumentOutOfRangeException("dest_offset", "< 0"); - - if (count < 0) - throw new ArgumentOutOfRangeException("count", "< 0"); - - int len = buffer.Length; - if (dest_offset > len) - throw new ArgumentException("destination offset is beyond array size"); - // reordered to avoid possible integer overflow - if (dest_offset > len - count) - throw new ArgumentException("Reading would overrun buffer"); - - if (count > end - position) - count = (int)(end - position); - - if (count <= 0) - return 0; - - s.Position = position; - int result = s.Read(buffer, dest_offset, count); - if (result > 0) - position += result; - else - position = end; - - return result; - } - - public override int ReadByte() - { - if (position >= end) - return -1; - - s.Position = position; - int result = s.ReadByte(); - if (result < 0) - position = end; - else - position++; - - return result; - } - - public override long Seek(long d, SeekOrigin origin) - { - long real; - switch (origin) - { - case SeekOrigin.Begin: - real = offset + d; - break; - case SeekOrigin.End: - real = end + d; - break; - case SeekOrigin.Current: - real = position + d; - break; - default: - throw new ArgumentException(); - } - - long virt = real - offset; - if (virt < 0 || virt > Length) - throw new ArgumentException(); - - position = s.Seek(real, SeekOrigin.Begin); - return position; - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotSupportedException(); - } - - public override bool CanRead - { - get { return true; } - } - public override bool CanSeek - { - get { return true; } - } - public override bool CanWrite - { - get { return false; } - } - - public override long Length - { - get { return end - offset; } - } - - public override long Position - { - get - { - return position - offset; - } - set - { - if (value > Length) - throw new ArgumentOutOfRangeException(); - - position = Seek(value, SeekOrigin.Begin); - } - } - } - - internal HttpPostedFile(string name, string content_type, Stream base_stream, long offset, long length) - { - this.name = name; - this.content_type = content_type; - this.stream = new ReadSubStream(base_stream, offset, length); - } - - public string ContentType - { - get - { - return content_type; - } - } - - public int ContentLength - { - get - { - return (int)stream.Length; - } - } - - public string FileName - { - get - { - return name; - } - } - - public Stream InputStream - { - get - { - return stream; - } - } - } - - class Helpers - { - public static readonly CultureInfo InvariantCulture = CultureInfo.InvariantCulture; - } - - internal sealed class StrUtils - { - StrUtils() { } - - public static bool StartsWith(string str1, string str2) - { - return StartsWith(str1, str2, false); - } - - public static bool StartsWith(string str1, string str2, bool ignore_case) - { - int l2 = str2.Length; - if (l2 == 0) - return true; - - int l1 = str1.Length; - if (l2 > l1) - return false; - - return 0 == String.Compare(str1, 0, str2, 0, l2, ignore_case, Helpers.InvariantCulture); - } - - public static bool EndsWith(string str1, string str2) - { - return EndsWith(str1, str2, false); - } - - public static bool EndsWith(string str1, string str2, bool ignore_case) - { - int l2 = str2.Length; - if (l2 == 0) - return true; - - int l1 = str1.Length; - if (l2 > l1) - return false; - - return 0 == String.Compare(str1, l1 - l2, str2, 0, l2, ignore_case, Helpers.InvariantCulture); - } - } - - class HttpMultipart - { - - public class Element - { - public string ContentType; - public string Name; - public string Filename; - public Encoding Encoding; - public long Start; - public long Length; - - public override string ToString() - { - return "ContentType " + ContentType + ", Name " + Name + ", Filename " + Filename + ", Start " + - Start.ToString() + ", Length " + Length.ToString(); - } - } - - Stream data; - string boundary; - byte[] boundary_bytes; - byte[] buffer; - bool at_eof; - Encoding encoding; - StringBuilder sb; - - const byte HYPHEN = (byte)'-', LF = (byte)'\n', CR = (byte)'\r'; - - // See RFC 2046 - // In the case of multipart entities, in which one or more different - // sets of data are combined in a single body, a "multipart" media type - // field must appear in the entity's header. The body must then contain - // one or more body parts, each preceded by a boundary delimiter line, - // and the last one followed by a closing boundary delimiter line. - // After its boundary delimiter line, each body part then consists of a - // header area, a blank line, and a body area. Thus a body part is - // similar to an RFC 822 message in syntax, but different in meaning. - - public HttpMultipart(Stream data, string b, Encoding encoding) - { - this.data = data; - //DB: 30/01/11: cannot set or read the Position in HttpListener in Win.NET - //var ms = new MemoryStream(32 * 1024); - //data.CopyTo(ms); - //this.data = ms; - - boundary = b; - boundary_bytes = encoding.GetBytes(b); - buffer = new byte[boundary_bytes.Length + 2]; // CRLF or '--' - this.encoding = encoding; - sb = new StringBuilder(); - } - - string ReadLine() - { - // CRLF or LF are ok as line endings. - bool got_cr = false; - int b = 0; - sb.Length = 0; - while (true) - { - b = data.ReadByte(); - if (b == -1) - { - return null; - } - - if (b == LF) - { - break; - } - got_cr = b == CR; - sb.Append((char)b); - } - - if (got_cr) - sb.Length--; - - return sb.ToString(); - - } - - static string GetContentDispositionAttribute(string l, string name) - { - int idx = l.IndexOf(name + "=\""); - if (idx < 0) - return null; - int begin = idx + name.Length + "=\"".Length; - int end = l.IndexOf('"', begin); - if (end < 0) - return null; - if (begin == end) - return ""; - return l.Substring(begin, end - begin); - } - - string GetContentDispositionAttributeWithEncoding(string l, string name) - { - int idx = l.IndexOf(name + "=\""); - if (idx < 0) - return null; - int begin = idx + name.Length + "=\"".Length; - int end = l.IndexOf('"', begin); - if (end < 0) - return null; - if (begin == end) - return ""; - - string temp = l.Substring(begin, end - begin); - byte[] source = new byte[temp.Length]; - for (int i = temp.Length - 1; i >= 0; i--) - source[i] = (byte)temp[i]; - - return encoding.GetString(source); - } - - bool ReadBoundary() - { - try - { - string line = ReadLine(); - while (line == "") - line = ReadLine(); - if (line[0] != '-' || line[1] != '-') - return false; - - if (!StrUtils.EndsWith(line, boundary, false)) - return true; - } - catch - { - } - - return false; - } - - string ReadHeaders() - { - string s = ReadLine(); - if (s == "") - return null; - - return s; - } - - bool CompareBytes(byte[] orig, byte[] other) - { - for (int i = orig.Length - 1; i >= 0; i--) - if (orig[i] != other[i]) - return false; - - return true; - } - - long MoveToNextBoundary() - { - long retval = 0; - bool got_cr = false; - - int state = 0; - int c = data.ReadByte(); - while (true) - { - if (c == -1) - return -1; - - if (state == 0 && c == LF) - { - retval = data.Position - 1; - if (got_cr) - retval--; - state = 1; - c = data.ReadByte(); - } - else if (state == 0) - { - got_cr = c == CR; - c = data.ReadByte(); - } - else if (state == 1 && c == '-') - { - c = data.ReadByte(); - if (c == -1) - return -1; - - if (c != '-') - { - state = 0; - got_cr = false; - continue; // no ReadByte() here - } - - int nread = data.Read(buffer, 0, buffer.Length); - int bl = buffer.Length; - if (nread != bl) - return -1; - - if (!CompareBytes(boundary_bytes, buffer)) - { - state = 0; - data.Position = retval + 2; - if (got_cr) - { - data.Position++; - got_cr = false; - } - c = data.ReadByte(); - continue; - } - - if (buffer[bl - 2] == '-' && buffer[bl - 1] == '-') - { - at_eof = true; - } - else if (buffer[bl - 2] != CR || buffer[bl - 1] != LF) - { - state = 0; - data.Position = retval + 2; - if (got_cr) - { - data.Position++; - got_cr = false; - } - c = data.ReadByte(); - continue; - } - data.Position = retval + 2; - if (got_cr) - data.Position++; - break; - } - else - { - // state == 1 - state = 0; // no ReadByte() here - } - } - - return retval; - } - - public Element ReadNextElement() - { - if (at_eof || ReadBoundary()) - return null; - - Element elem = new Element(); - string header; - while ((header = ReadHeaders()) != null) - { - if (StrUtils.StartsWith(header, "Content-Disposition:", true)) - { - elem.Name = GetContentDispositionAttribute(header, "name"); - elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename")); - } - else if (StrUtils.StartsWith(header, "Content-Type:", true)) - { - elem.ContentType = header.Substring("Content-Type:".Length).Trim(); - elem.Encoding = GetEncoding(elem.ContentType); - } - } - - long start = 0; - start = data.Position; - elem.Start = start; - long pos = MoveToNextBoundary(); - if (pos == -1) - return null; - - elem.Length = pos - start; - return elem; - } - - static string StripPath(string path) - { - if (path == null || path.Length == 0) - return path; - - if (path.IndexOf(":\\") != 1 && !path.StartsWith("\\\\")) - return path; - return path.Substring(path.LastIndexOf('\\') + 1); - } - } - - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs deleted file mode 100644 index d363c4de6c..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs +++ /dev/null @@ -1,172 +0,0 @@ -using MediaBrowser.Common.Events; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Logging; -using System; -using System.Threading; -using System.Threading.Tasks; -using WebSocketState = MediaBrowser.Model.Net.WebSocketState; - -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp -{ - public class SharpWebSocket : IWebSocket - { - /// <summary> - /// The logger - /// </summary> - private readonly ILogger _logger; - - public event EventHandler<EventArgs> Closed; - - /// <summary> - /// Gets or sets the web socket. - /// </summary> - /// <value>The web socket.</value> - private SocketHttpListener.WebSocket WebSocket { get; set; } - - private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - - /// <summary> - /// Initializes a new instance of the <see cref="NativeWebSocket" /> class. - /// </summary> - /// <param name="socket">The socket.</param> - /// <param name="logger">The logger.</param> - /// <exception cref="System.ArgumentNullException">socket</exception> - public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger) - { - if (socket == null) - { - throw new ArgumentNullException("socket"); - } - - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - - _logger = logger; - WebSocket = socket; - - socket.OnMessage += socket_OnMessage; - socket.OnClose += socket_OnClose; - socket.OnError += socket_OnError; - - WebSocket.ConnectAsServer(); - } - - void socket_OnError(object sender, SocketHttpListener.ErrorEventArgs e) - { - _logger.Error("Error in SharpWebSocket: {0}", e.Message ?? string.Empty); - //EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger); - } - - void socket_OnClose(object sender, SocketHttpListener.CloseEventArgs e) - { - EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger); - } - - void socket_OnMessage(object sender, SocketHttpListener.MessageEventArgs e) - { - //if (!string.IsNullOrWhiteSpace(e.Data)) - //{ - // if (OnReceive != null) - // { - // OnReceive(e.Data); - // } - // return; - //} - if (OnReceiveBytes != null) - { - OnReceiveBytes(e.RawData); - } - } - - /// <summary> - /// Gets or sets the state. - /// </summary> - /// <value>The state.</value> - public WebSocketState State - { - get - { - WebSocketState commonState; - - if (!Enum.TryParse(WebSocket.ReadyState.ToString(), true, out commonState)) - { - _logger.Warn("Unrecognized WebSocketState: {0}", WebSocket.ReadyState.ToString()); - } - - return commonState; - } - } - - /// <summary> - /// Sends the async. - /// </summary> - /// <param name="bytes">The bytes.</param> - /// <param name="endOfMessage">if set to <c>true</c> [end of message].</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken) - { - var completionSource = new TaskCompletionSource<bool>(); - - WebSocket.SendAsync(bytes, res => completionSource.TrySetResult(true)); - - return completionSource.Task; - } - - /// <summary> - /// Sends the asynchronous. - /// </summary> - /// <param name="text">The text.</param> - /// <param name="endOfMessage">if set to <c>true</c> [end of message].</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken) - { - var completionSource = new TaskCompletionSource<bool>(); - - WebSocket.SendAsync(text, res => completionSource.TrySetResult(true)); - - return completionSource.Task; - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - WebSocket.OnMessage -= socket_OnMessage; - WebSocket.OnClose -= socket_OnClose; - WebSocket.OnError -= socket_OnError; - - _cancellationTokenSource.Cancel(); - - WebSocket.Close(); - } - } - - /// <summary> - /// Gets or sets the receive action. - /// </summary> - /// <value>The receive action.</value> - public Action<byte[]> OnReceiveBytes { get; set; } - - /// <summary> - /// Gets or sets the on receive. - /// </summary> - /// <value>The on receive.</value> - public Action<string> OnReceive { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs deleted file mode 100644 index b090c97c6e..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ /dev/null @@ -1,208 +0,0 @@ -using System.Collections.Specialized; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.Logging; -using ServiceStack; -using ServiceStack.Web; -using SocketHttpListener.Net; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp -{ - public class WebSocketSharpListener : IHttpListener - { - private HttpListener _listener; - - private readonly ILogger _logger; - private readonly string _certificatePath; - private readonly IMemoryStreamProvider _memoryStreamProvider; - - public WebSocketSharpListener(ILogger logger, string certificatePath, IMemoryStreamProvider memoryStreamProvider) - { - _logger = logger; - _certificatePath = certificatePath; - _memoryStreamProvider = memoryStreamProvider; - } - - public Action<Exception, IRequest> ErrorHandler { get; set; } - - public Func<IHttpRequest, Uri, Task> RequestHandler { get; set; } - - public Action<WebSocketConnectingEventArgs> WebSocketConnecting { get; set; } - - public Action<WebSocketConnectEventArgs> WebSocketConnected { get; set; } - - public void Start(IEnumerable<string> urlPrefixes) - { - if (_listener == null) - _listener = new HttpListener(new PatternsLogger(_logger), _certificatePath); - - foreach (var prefix in urlPrefixes) - { - _logger.Info("Adding HttpListener prefix " + prefix); - _listener.Prefixes.Add(prefix); - } - - _listener.OnContext = ProcessContext; - - _listener.Start(); - } - - private void ProcessContext(HttpListenerContext context) - { - Task.Factory.StartNew(() => InitTask(context)); - } - - private void InitTask(HttpListenerContext context) - { - try - { - var task = this.ProcessRequestAsync(context); - task.ContinueWith(x => HandleError(x.Exception, context), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent); - - //if (task.Status == TaskStatus.Created) - //{ - // task.RunSynchronously(); - //} - } - catch (Exception ex) - { - HandleError(ex, context); - } - } - - private Task ProcessRequestAsync(HttpListenerContext context) - { - var request = context.Request; - - if (request.IsWebSocketRequest) - { - LoggerUtils.LogRequest(_logger, request); - - ProcessWebSocketRequest(context); - return Task.FromResult(true); - } - - if (string.IsNullOrEmpty(context.Request.RawUrl)) - return ((object)null).AsTaskResult(); - - var httpReq = GetRequest(context); - - return RequestHandler(httpReq, request.Url); - } - - private void ProcessWebSocketRequest(HttpListenerContext ctx) - { - try - { - var endpoint = ctx.Request.RemoteEndPoint.ToString(); - var url = ctx.Request.RawUrl; - var queryString = new NameValueCollection(ctx.Request.QueryString ?? new NameValueCollection()); - - var connectingArgs = new WebSocketConnectingEventArgs - { - Url = url, - QueryString = queryString, - Endpoint = endpoint - }; - - if (WebSocketConnecting != null) - { - WebSocketConnecting(connectingArgs); - } - - if (connectingArgs.AllowConnection) - { - _logger.Debug("Web socket connection allowed"); - - var webSocketContext = ctx.AcceptWebSocket(null); - - if (WebSocketConnected != null) - { - WebSocketConnected(new WebSocketConnectEventArgs - { - Url = url, - QueryString = queryString, - WebSocket = new SharpWebSocket(webSocketContext.WebSocket, _logger), - Endpoint = endpoint - }); - } - } - else - { - _logger.Warn("Web socket connection not allowed"); - ctx.Response.StatusCode = 401; - ctx.Response.Close(); - } - } - catch (Exception ex) - { - _logger.ErrorException("AcceptWebSocketAsync error", ex); - ctx.Response.StatusCode = 500; - ctx.Response.Close(); - } - } - - private IHttpRequest GetRequest(HttpListenerContext httpContext) - { - var operationName = httpContext.Request.GetOperationName(); - - var req = new WebSocketSharpRequest(httpContext, operationName, RequestAttributes.None, _logger, _memoryStreamProvider); - req.RequestAttributes = req.GetAttributes(); - - return req; - } - - private void HandleError(Exception ex, HttpListenerContext context) - { - var httpReq = GetRequest(context); - - if (ErrorHandler != null) - { - ErrorHandler(ex, httpReq); - } - } - - public void Stop() - { - if (_listener != null) - { - foreach (var prefix in _listener.Prefixes.ToList()) - { - _listener.Prefixes.Remove(prefix); - } - - _listener.Close(); - } - } - - public void Dispose() - { - Dispose(true); - } - - private bool _disposed; - private readonly object _disposeLock = new object(); - protected virtual void Dispose(bool disposing) - { - if (_disposed) return; - - lock (_disposeLock) - { - if (_disposed) return; - - if (disposing) - { - Stop(); - } - - //release unmanaged resources here... - _disposed = true; - } - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs deleted file mode 100644 index b5c8d01075..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs +++ /dev/null @@ -1,494 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using Funq; -using MediaBrowser.Common.IO; -using MediaBrowser.Model.Logging; -using ServiceStack; -using ServiceStack.Host; -using ServiceStack.Web; -using SocketHttpListener.Net; - -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp -{ - public partial class WebSocketSharpRequest : IHttpRequest - { - public Container Container { get; set; } - private readonly HttpListenerRequest request; - private readonly IHttpResponse response; - private readonly IMemoryStreamProvider _memoryStreamProvider; - - public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, RequestAttributes requestAttributes, ILogger logger, IMemoryStreamProvider memoryStreamProvider) - { - this.OperationName = operationName; - this.RequestAttributes = requestAttributes; - _memoryStreamProvider = memoryStreamProvider; - this.request = httpContext.Request; - this.response = new WebSocketSharpResponse(logger, httpContext.Response, this); - - this.RequestPreferences = new RequestPreferences(this); - } - - public HttpListenerRequest HttpRequest - { - get { return request; } - } - - public object OriginalRequest - { - get { return request; } - } - - public IResponse Response - { - get { return response; } - } - - public IHttpResponse HttpResponse - { - get { return response; } - } - - public RequestAttributes RequestAttributes { get; set; } - - public IRequestPreferences RequestPreferences { get; private set; } - - public T TryResolve<T>() - { - if (typeof(T) == typeof(IHttpRequest)) - throw new Exception("You don't need to use IHttpRequest.TryResolve<IHttpRequest> to resolve itself"); - - if (typeof(T) == typeof(IHttpResponse)) - throw new Exception("Resolve IHttpResponse with 'Response' property instead of IHttpRequest.TryResolve<IHttpResponse>"); - - return Container == null - ? HostContext.TryResolve<T>() - : Container.TryResolve<T>(); - } - - public string OperationName { get; set; } - - public object Dto { get; set; } - - public string GetRawBody() - { - if (bufferedStream != null) - { - return bufferedStream.ToArray().FromUtf8Bytes(); - } - - using (var reader = new StreamReader(InputStream)) - { - return reader.ReadToEnd(); - } - } - - public string RawUrl - { - get { return request.RawUrl; } - } - - public string AbsoluteUri - { - get { return request.Url.AbsoluteUri.TrimEnd('/'); } - } - - public string UserHostAddress - { - get { return request.UserHostAddress; } - } - - public string XForwardedFor - { - get - { - return String.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedFor]) ? null : request.Headers[HttpHeaders.XForwardedFor]; - } - } - - public int? XForwardedPort - { - get - { - return string.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedPort]) ? (int?)null : int.Parse(request.Headers[HttpHeaders.XForwardedPort]); - } - } - - public string XForwardedProtocol - { - get - { - return string.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedProtocol]) ? null : request.Headers[HttpHeaders.XForwardedProtocol]; - } - } - - public string XRealIp - { - get - { - return String.IsNullOrEmpty(request.Headers[HttpHeaders.XRealIp]) ? null : request.Headers[HttpHeaders.XRealIp]; - } - } - - private string remoteIp; - public string RemoteIp - { - get - { - return remoteIp ?? - (remoteIp = (CheckBadChars(XForwardedFor)) ?? - (NormalizeIp(CheckBadChars(XRealIp)) ?? - (request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.Address.ToString()) : null))); - } - } - - private static readonly char[] HttpTrimCharacters = new char[] { (char)0x09, (char)0xA, (char)0xB, (char)0xC, (char)0xD, (char)0x20 }; - - // - // CheckBadChars - throws on invalid chars to be not found in header name/value - // - internal static string CheckBadChars(string name) - { - if (name == null || name.Length == 0) - { - return name; - } - - // VALUE check - //Trim spaces from both ends - name = name.Trim(HttpTrimCharacters); - - //First, check for correctly formed multi-line value - //Second, check for absenece of CTL characters - int crlf = 0; - for (int i = 0; i < name.Length; ++i) - { - char c = (char)(0x000000ff & (uint)name[i]); - switch (crlf) - { - case 0: - if (c == '\r') - { - crlf = 1; - } - else if (c == '\n') - { - // Technically this is bad HTTP. But it would be a breaking change to throw here. - // Is there an exploit? - crlf = 2; - } - else if (c == 127 || (c < ' ' && c != '\t')) - { - throw new ArgumentException("net_WebHeaderInvalidControlChars"); - } - break; - - case 1: - if (c == '\n') - { - crlf = 2; - break; - } - throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); - - case 2: - if (c == ' ' || c == '\t') - { - crlf = 0; - break; - } - throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); - } - } - if (crlf != 0) - { - throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); - } - return name; - } - - internal static bool ContainsNonAsciiChars(string token) - { - for (int i = 0; i < token.Length; ++i) - { - if ((token[i] < 0x20) || (token[i] > 0x7e)) - { - return true; - } - } - return false; - } - - private string NormalizeIp(string ip) - { - if (!string.IsNullOrWhiteSpace(ip)) - { - // Handle ipv4 mapped to ipv6 - const string srch = "::ffff:"; - var index = ip.IndexOf(srch, StringComparison.OrdinalIgnoreCase); - if (index == 0) - { - ip = ip.Substring(srch.Length); - } - } - - return ip; - } - - public bool IsSecureConnection - { - get { return request.IsSecureConnection || XForwardedProtocol == "https"; } - } - - public string[] AcceptTypes - { - get { return request.AcceptTypes; } - } - - private Dictionary<string, object> items; - public Dictionary<string, object> Items - { - get { return items ?? (items = new Dictionary<string, object>()); } - } - - private string responseContentType; - public string ResponseContentType - { - get - { - return responseContentType - ?? (responseContentType = this.GetResponseContentType()); - } - set - { - this.responseContentType = value; - HasExplicitResponseContentType = true; - } - } - - public bool HasExplicitResponseContentType { get; private set; } - - private string pathInfo; - public string PathInfo - { - get - { - if (this.pathInfo == null) - { - var mode = HostContext.Config.HandlerFactoryPath; - - var pos = request.RawUrl.IndexOf("?"); - if (pos != -1) - { - var path = request.RawUrl.Substring(0, pos); - this.pathInfo = HttpRequestExtensions.GetPathInfo( - path, - mode, - mode ?? ""); - } - else - { - this.pathInfo = request.RawUrl; - } - - this.pathInfo = this.pathInfo.UrlDecode(); - this.pathInfo = NormalizePathInfo(pathInfo, mode); - } - return this.pathInfo; - } - } - - private Dictionary<string, System.Net.Cookie> cookies; - public IDictionary<string, System.Net.Cookie> Cookies - { - get - { - if (cookies == null) - { - cookies = new Dictionary<string, System.Net.Cookie>(); - for (var i = 0; i < this.request.Cookies.Count; i++) - { - var httpCookie = this.request.Cookies[i]; - cookies[httpCookie.Name] = new System.Net.Cookie(httpCookie.Name, httpCookie.Value, httpCookie.Path, httpCookie.Domain); - } - } - - return cookies; - } - } - - public string UserAgent - { - get { return request.UserAgent; } - } - - private NameValueCollectionWrapper headers; - public INameValueCollection Headers - { - get { return headers ?? (headers = new NameValueCollectionWrapper(request.Headers)); } - } - - private NameValueCollectionWrapper queryString; - public INameValueCollection QueryString - { - get { return queryString ?? (queryString = new NameValueCollectionWrapper(MyHttpUtility.ParseQueryString(request.Url.Query))); } - } - - private NameValueCollectionWrapper formData; - public INameValueCollection FormData - { - get { return formData ?? (formData = new NameValueCollectionWrapper(this.Form)); } - } - - public bool IsLocal - { - get { return request.IsLocal; } - } - - private string httpMethod; - public string HttpMethod - { - get - { - return httpMethod - ?? (httpMethod = Param(HttpHeaders.XHttpMethodOverride) - ?? request.HttpMethod); - } - } - - public string Verb - { - get { return HttpMethod; } - } - - public string Param(string name) - { - return Headers[name] - ?? QueryString[name] - ?? FormData[name]; - } - - public string ContentType - { - get { return request.ContentType; } - } - - public Encoding contentEncoding; - public Encoding ContentEncoding - { - get { return contentEncoding ?? request.ContentEncoding; } - set { contentEncoding = value; } - } - - public Uri UrlReferrer - { - get { return request.UrlReferrer; } - } - - public static Encoding GetEncoding(string contentTypeHeader) - { - var param = GetParameter(contentTypeHeader, "charset="); - if (param == null) return null; - try - { - return Encoding.GetEncoding(param); - } - catch (ArgumentException) - { - return null; - } - } - - public bool UseBufferedStream - { - get { return bufferedStream != null; } - set - { - bufferedStream = value - ? bufferedStream ?? _memoryStreamProvider.CreateNew(request.InputStream.ReadFully()) - : null; - } - } - - private MemoryStream bufferedStream; - public Stream InputStream - { - get { return bufferedStream ?? request.InputStream; } - } - - public long ContentLength - { - get { return request.ContentLength64; } - } - - private IHttpFile[] httpFiles; - public IHttpFile[] Files - { - get - { - if (httpFiles == null) - { - if (files == null) - return httpFiles = new IHttpFile[0]; - - httpFiles = new IHttpFile[files.Count]; - for (var i = 0; i < files.Count; i++) - { - var reqFile = files[i]; - - httpFiles[i] = new HttpFile - { - ContentType = reqFile.ContentType, - ContentLength = reqFile.ContentLength, - FileName = reqFile.FileName, - InputStream = reqFile.InputStream, - }; - } - } - return httpFiles; - } - } - - static Stream GetSubStream(Stream stream, IMemoryStreamProvider streamProvider) - { - if (stream is MemoryStream) - { - var other = (MemoryStream)stream; - try - { - return new MemoryStream(other.GetBuffer(), 0, (int)other.Length, false, true); - } - catch (UnauthorizedAccessException) - { - return new MemoryStream(other.ToArray(), 0, (int)other.Length, false, true); - } - } - - return stream; - } - - public static string GetHandlerPathIfAny(string listenerUrl) - { - if (listenerUrl == null) return null; - var pos = listenerUrl.IndexOf("://", StringComparison.InvariantCultureIgnoreCase); - if (pos == -1) return null; - var startHostUrl = listenerUrl.Substring(pos + "://".Length); - var endPos = startHostUrl.IndexOf('/'); - if (endPos == -1) return null; - var endHostUrl = startHostUrl.Substring(endPos + 1); - return String.IsNullOrEmpty(endHostUrl) ? null : endHostUrl.TrimEnd('/'); - } - - public static string NormalizePathInfo(string pathInfo, string handlerPath) - { - if (handlerPath != null && pathInfo.TrimStart('/').StartsWith( - handlerPath, StringComparison.InvariantCultureIgnoreCase)) - { - return pathInfo.TrimStart('/').Substring(handlerPath.Length); - } - - return pathInfo; - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs deleted file mode 100644 index a58645ec54..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using MediaBrowser.Model.Logging; -using ServiceStack; -using ServiceStack.Host; -using ServiceStack.Web; -using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse; - -namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp -{ - public class WebSocketSharpResponse : IHttpResponse - { - private readonly ILogger _logger; - private readonly HttpListenerResponse response; - - public WebSocketSharpResponse(ILogger logger, HttpListenerResponse response, IRequest request) - { - _logger = logger; - this.response = response; - Items = new Dictionary<string, object>(); - Request = request; - } - - public IRequest Request { get; private set; } - public bool UseBufferedStream { get; set; } - public Dictionary<string, object> Items { get; private set; } - public object OriginalResponse - { - get { return response; } - } - - public int StatusCode - { - get { return this.response.StatusCode; } - set { this.response.StatusCode = value; } - } - - public string StatusDescription - { - get { return this.response.StatusDescription; } - set { this.response.StatusDescription = value; } - } - - public string ContentType - { - get { return response.ContentType; } - set { response.ContentType = value; } - } - - public ICookies Cookies { get; set; } - - public void AddHeader(string name, string value) - { - if (string.Equals(name, "Content-Type", StringComparison.OrdinalIgnoreCase)) - { - ContentType = value; - return; - } - - response.AddHeader(name, value); - } - - public string GetHeader(string name) - { - return response.Headers[name]; - } - - public void Redirect(string url) - { - response.Redirect(url); - } - - public Stream OutputStream - { - get { return response.OutputStream; } - } - - public object Dto { get; set; } - - public void Write(string text) - { - var bOutput = System.Text.Encoding.UTF8.GetBytes(text); - response.ContentLength64 = bOutput.Length; - - var outputStream = response.OutputStream; - outputStream.Write(bOutput, 0, bOutput.Length); - Close(); - } - - public void Close() - { - if (!this.IsClosed) - { - this.IsClosed = true; - - try - { - this.response.CloseOutputStream(_logger); - } - catch (Exception ex) - { - _logger.ErrorException("Error closing HttpListener output stream", ex); - } - } - } - - public void End() - { - Close(); - } - - public void Flush() - { - response.OutputStream.Flush(); - } - - public bool IsClosed - { - get; - private set; - } - - public void SetContentLength(long contentLength) - { - //you can happily set the Content-Length header in Asp.Net - //but HttpListener will complain if you do - you have to set ContentLength64 on the response. - //workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header - response.ContentLength64 = contentLength; - } - - public void SetCookie(Cookie cookie) - { - var cookieStr = cookie.AsHeaderValue(); - response.Headers.Add(HttpHeaders.SetCookie, cookieStr); - } - - public bool SendChunked - { - get { return response.SendChunked; } - set { response.SendChunked = value; } - } - - public bool KeepAlive { get; set; } - - public void ClearCookies() - { - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs deleted file mode 100644 index 5f122fb96f..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs +++ /dev/null @@ -1,169 +0,0 @@ -using MediaBrowser.Model.Logging; -using ServiceStack.Web; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Threading.Tasks; -using MediaBrowser.Common.IO; -using ServiceStack; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - /// <summary> - /// Class StreamWriter - /// </summary> - public class StreamWriter : IStreamWriter, IAsyncStreamWriter, IHasOptions - { - private ILogger Logger { get; set; } - - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - /// <summary> - /// Gets or sets the source stream. - /// </summary> - /// <value>The source stream.</value> - private Stream SourceStream { get; set; } - - /// <summary> - /// The _options - /// </summary> - private readonly IDictionary<string, string> _options = new Dictionary<string, string>(); - /// <summary> - /// Gets the options. - /// </summary> - /// <value>The options.</value> - public IDictionary<string, string> Options - { - get { return _options; } - } - - public Action OnComplete { get; set; } - public Action OnError { get; set; } - private readonly byte[] _bytes; - - /// <summary> - /// Initializes a new instance of the <see cref="StreamWriter" /> class. - /// </summary> - /// <param name="source">The source.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="logger">The logger.</param> - public StreamWriter(Stream source, string contentType, ILogger logger) - { - if (string.IsNullOrEmpty(contentType)) - { - throw new ArgumentNullException("contentType"); - } - - SourceStream = source; - Logger = logger; - - Options["Content-Type"] = contentType; - - if (source.CanSeek) - { - Options["Content-Length"] = source.Length.ToString(UsCulture); - } - } - - /// <summary> - /// Initializes a new instance of the <see cref="StreamWriter"/> class. - /// </summary> - /// <param name="source">The source.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="logger">The logger.</param> - public StreamWriter(byte[] source, string contentType, ILogger logger) - : this(new MemoryStream(source), contentType, logger) - { - if (string.IsNullOrEmpty(contentType)) - { - throw new ArgumentNullException("contentType"); - } - - _bytes = source; - Logger = logger; - - Options["Content-Type"] = contentType; - - Options["Content-Length"] = source.Length.ToString(UsCulture); - } - - private const int BufferSize = 81920; - - /// <summary> - /// Writes to. - /// </summary> - /// <param name="responseStream">The response stream.</param> - public void WriteTo(Stream responseStream) - { - try - { - if (_bytes != null) - { - responseStream.Write(_bytes, 0, _bytes.Length); - } - else - { - using (var src = SourceStream) - { - src.CopyTo(responseStream, BufferSize); - } - } - } - catch (Exception ex) - { - Logger.ErrorException("Error streaming data", ex); - - if (OnError != null) - { - OnError(); - } - - throw; - } - finally - { - if (OnComplete != null) - { - OnComplete(); - } - } - } - - public async Task WriteToAsync(Stream responseStream) - { - try - { - if (_bytes != null) - { - await responseStream.WriteAsync(_bytes, 0, _bytes.Length); - } - else - { - using (var src = SourceStream) - { - await src.CopyToAsync(responseStream, BufferSize).ConfigureAwait(false); - } - } - } - catch (Exception ex) - { - Logger.ErrorException("Error streaming data", ex); - - if (OnError != null) - { - OnError(); - } - - throw; - } - finally - { - if (OnComplete != null) - { - OnComplete(); - } - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/SwaggerService.cs b/MediaBrowser.Server.Implementations/HttpServer/SwaggerService.cs deleted file mode 100644 index d91f316d6d..0000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/SwaggerService.cs +++ /dev/null @@ -1,43 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Net; -using ServiceStack.Web; -using System.IO; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - public class SwaggerService : IHasResultFactory, IRestfulService - { - private readonly IServerApplicationPaths _appPaths; - - public SwaggerService(IServerApplicationPaths appPaths) - { - _appPaths = appPaths; - } - - /// <summary> - /// Gets the specified request. - /// </summary> - /// <param name="request">The request.</param> - /// <returns>System.Object.</returns> - public object Get(GetSwaggerResource request) - { - var swaggerDirectory = Path.Combine(_appPaths.ApplicationResourcesPath, "swagger-ui"); - - var requestedFile = Path.Combine(swaggerDirectory, request.ResourceName.Replace('/', Path.DirectorySeparatorChar)); - - return ResultFactory.GetStaticFileResult(Request, requestedFile).Result; - } - - /// <summary> - /// Gets or sets the result factory. - /// </summary> - /// <value>The result factory.</value> - public IHttpResultFactory ResultFactory { get; set; } - - /// <summary> - /// Gets or sets the request context. - /// </summary> - /// <value>The request context.</value> - public IRequest Request { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/IO/FileRefresher.cs b/MediaBrowser.Server.Implementations/IO/FileRefresher.cs deleted file mode 100644 index c2c776c2bb..0000000000 --- a/MediaBrowser.Server.Implementations/IO/FileRefresher.cs +++ /dev/null @@ -1,319 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.Events; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.ScheduledTasks; -using MoreLinq; - -namespace MediaBrowser.Server.Implementations.IO -{ - public class FileRefresher : IDisposable - { - private ILogger Logger { get; set; } - private ITaskManager TaskManager { get; set; } - private ILibraryManager LibraryManager { get; set; } - private IServerConfigurationManager ConfigurationManager { get; set; } - private readonly IFileSystem _fileSystem; - private readonly List<string> _affectedPaths = new List<string>(); - private Timer _timer; - private readonly object _timerLock = new object(); - public string Path { get; private set; } - - public event EventHandler<EventArgs> Completed; - - public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger) - { - logger.Debug("New file refresher created for {0}", path); - Path = path; - - _fileSystem = fileSystem; - ConfigurationManager = configurationManager; - LibraryManager = libraryManager; - TaskManager = taskManager; - Logger = logger; - AddPath(path); - } - - private void AddAffectedPath(string path) - { - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException("path"); - } - - if (!_affectedPaths.Contains(path, StringComparer.Ordinal)) - { - _affectedPaths.Add(path); - } - } - - public void AddPath(string path) - { - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException("path"); - } - - lock (_timerLock) - { - AddAffectedPath(path); - } - RestartTimer(); - } - - public void RestartTimer() - { - if (_disposed) - { - return; - } - - lock (_timerLock) - { - if (_disposed) - { - return; - } - - if (_timer == null) - { - _timer = new Timer(OnTimerCallback, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); - } - else - { - _timer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); - } - } - } - - public void ResetPath(string path, string affectedFile) - { - lock (_timerLock) - { - Logger.Debug("Resetting file refresher from {0} to {1}", Path, path); - - Path = path; - AddAffectedPath(path); - - if (!string.IsNullOrWhiteSpace(affectedFile)) - { - AddAffectedPath(affectedFile); - } - } - RestartTimer(); - } - - private async void OnTimerCallback(object state) - { - List<string> paths; - - lock (_timerLock) - { - paths = _affectedPaths.ToList(); - } - - // Extend the timer as long as any of the paths are still being written to. - if (paths.Any(IsFileLocked)) - { - Logger.Info("Timer extended."); - RestartTimer(); - return; - } - - Logger.Debug("Timer stopped."); - - DisposeTimer(); - EventHelper.FireEventIfNotNull(Completed, this, EventArgs.Empty, Logger); - - try - { - await ProcessPathChanges(paths.ToList()).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.ErrorException("Error processing directory changes", ex); - } - } - - private async Task ProcessPathChanges(List<string> paths) - { - var itemsToRefresh = paths - .Distinct(StringComparer.OrdinalIgnoreCase) - .Select(GetAffectedBaseItem) - .Where(item => item != null) - .DistinctBy(i => i.Id) - .ToList(); - - foreach (var p in paths) - { - Logger.Info(p + " reports change."); - } - - // If the root folder changed, run the library task so the user can see it - if (itemsToRefresh.Any(i => i is AggregateFolder)) - { - TaskManager.CancelIfRunningAndQueue<RefreshMediaLibraryTask>(); - return; - } - - foreach (var item in itemsToRefresh) - { - Logger.Info(item.Name + " (" + item.Path + ") will be refreshed."); - - try - { - await item.ChangedExternally().ConfigureAwait(false); - } - catch (IOException ex) - { - // For now swallow and log. - // Research item: If an IOException occurs, the item may be in a disconnected state (media unavailable) - // Should we remove it from it's parent? - Logger.ErrorException("Error refreshing {0}", ex, item.Name); - } - catch (Exception ex) - { - Logger.ErrorException("Error refreshing {0}", ex, item.Name); - } - } - } - - /// <summary> - /// Gets the affected base item. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>BaseItem.</returns> - private BaseItem GetAffectedBaseItem(string path) - { - BaseItem item = null; - - while (item == null && !string.IsNullOrEmpty(path)) - { - item = LibraryManager.FindByPath(path, null); - - path = System.IO.Path.GetDirectoryName(path); - } - - if (item != null) - { - // If the item has been deleted find the first valid parent that still exists - while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path)) - { - item = item.GetParent(); - - if (item == null) - { - break; - } - } - } - - return item; - } - - private bool IsFileLocked(string path) - { - if (Environment.OSVersion.Platform != PlatformID.Win32NT) - { - // Causing lockups on linux - return false; - } - - try - { - var data = _fileSystem.GetFileSystemInfo(path); - - if (!data.Exists - || data.IsDirectory - - // Opening a writable stream will fail with readonly files - || data.Attributes.HasFlag(FileAttributes.ReadOnly)) - { - return false; - } - } - catch (IOException) - { - return false; - } - catch (Exception ex) - { - Logger.ErrorException("Error getting file system info for: {0}", ex, path); - return false; - } - - // 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 - ? FileAccess.ReadWrite - : FileAccess.Read; - - try - { - using (_fileSystem.GetFileStream(path, FileMode.Open, requestedFileAccess, FileShare.ReadWrite)) - { - //file is not locked - return false; - } - } - catch (DirectoryNotFoundException) - { - // File may have been deleted - return false; - } - catch (FileNotFoundException) - { - // File may have been deleted - return false; - } - catch (UnauthorizedAccessException) - { - Logger.Debug("No write permission for: {0}.", path); - return false; - } - catch (IOException) - { - //the file is unavailable because it is: - //still being written to - //or being processed by another thread - //or does not exist (has already been processed) - Logger.Debug("{0} is locked.", path); - return true; - } - catch (Exception ex) - { - Logger.ErrorException("Error determining if file is locked: {0}", ex, path); - return false; - } - } - - private void DisposeTimer() - { - lock (_timerLock) - { - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - } - } - - private bool _disposed; - public void Dispose() - { - _disposed = true; - DisposeTimer(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs deleted file mode 100644 index b550d1dda2..0000000000 --- a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ /dev/null @@ -1,146 +0,0 @@ -using MediaBrowser.Model.Extensions; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Resolvers; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Library -{ - /// <summary> - /// Provides the core resolver ignore rules - /// </summary> - public class CoreResolutionIgnoreRule : IResolverIgnoreRule - { - private readonly IFileSystem _fileSystem; - private readonly ILibraryManager _libraryManager; - - /// <summary> - /// Any folder named in this list will be ignored - can be added to at runtime for extensibility - /// </summary> - public static readonly List<string> IgnoreFolders = new List<string> - { - "metadata", - "ps3_update", - "ps3_vprm", - "extrafanart", - "extrathumbs", - ".actors", - ".wd_tv", - - // Synology - "@eaDir", - "eaDir", - "#recycle" - - }; - - public CoreResolutionIgnoreRule(IFileSystem fileSystem, ILibraryManager libraryManager) - { - _fileSystem = fileSystem; - _libraryManager = libraryManager; - } - - /// <summary> - /// Shoulds the ignore. - /// </summary> - /// <param name="fileInfo">The file information.</param> - /// <param name="parent">The parent.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent) - { - var filename = fileInfo.Name; - var isHidden = (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden; - var path = fileInfo.FullName; - - // Handle mac .DS_Store - // https://github.com/MediaBrowser/MediaBrowser/issues/427 - if (filename.IndexOf("._", StringComparison.OrdinalIgnoreCase) == 0) - { - return true; - } - - // Ignore hidden files and folders - if (isHidden) - { - if (parent == null) - { - var parentFolderName = Path.GetFileName(Path.GetDirectoryName(path)); - - if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) - { - return false; - } - if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) - { - return false; - } - } - - // Sometimes these are marked hidden - if (_fileSystem.IsRootPath(path)) - { - return false; - } - - return true; - } - - if (fileInfo.IsDirectory) - { - // Ignore any folders in our list - if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - - if (parent != null) - { - // Ignore trailer folders but allow it at the collection level - if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) && - !(parent is AggregateFolder) && !(parent is UserRootFolder)) - { - return true; - } - - if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - } - else - { - if (parent != null) - { - // Don't resolve these into audio files - if (string.Equals(_fileSystem.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && _libraryManager.IsAudioFile(filename)) - { - return true; - } - } - - // Ignore samples - var sampleFilename = " " + filename.Replace(".", " ", StringComparison.OrdinalIgnoreCase) - .Replace("-", " ", StringComparison.OrdinalIgnoreCase) - .Replace("_", " ", StringComparison.OrdinalIgnoreCase) - .Replace("!", " ", StringComparison.OrdinalIgnoreCase); - - if (sampleFilename.IndexOf(" sample ", StringComparison.OrdinalIgnoreCase) != -1) - { - return true; - } - } - - return false; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs deleted file mode 100644 index 64abcc0440..0000000000 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ /dev/null @@ -1,3078 +0,0 @@ -using Interfaces.IO; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Progress; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.IO; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using MediaBrowser.Naming.Audio; -using MediaBrowser.Naming.Common; -using MediaBrowser.Naming.TV; -using MediaBrowser.Naming.Video; -using MediaBrowser.Server.Implementations.Library.Validators; -using MediaBrowser.Server.Implementations.Logging; -using MediaBrowser.Server.Implementations.ScheduledTasks; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Library; -using MediaBrowser.Model.Net; -using MediaBrowser.Server.Implementations.Library.Resolvers; -using MoreLinq; -using SortOrder = MediaBrowser.Model.Entities.SortOrder; -using VideoResolver = MediaBrowser.Naming.Video.VideoResolver; -using MediaBrowser.Common.Configuration; - -namespace MediaBrowser.Server.Implementations.Library -{ - /// <summary> - /// Class LibraryManager - /// </summary> - public class LibraryManager : ILibraryManager - { - /// <summary> - /// Gets or sets the postscan tasks. - /// </summary> - /// <value>The postscan tasks.</value> - private ILibraryPostScanTask[] PostscanTasks { get; set; } - - /// <summary> - /// Gets the intro providers. - /// </summary> - /// <value>The intro providers.</value> - private IIntroProvider[] IntroProviders { get; set; } - - /// <summary> - /// Gets the list of entity resolution ignore rules - /// </summary> - /// <value>The entity resolution ignore rules.</value> - private IResolverIgnoreRule[] EntityResolutionIgnoreRules { get; set; } - - /// <summary> - /// Gets the list of BasePluginFolders added by plugins - /// </summary> - /// <value>The plugin folders.</value> - private IVirtualFolderCreator[] PluginFolderCreators { get; set; } - - /// <summary> - /// Gets the list of currently registered entity resolvers - /// </summary> - /// <value>The entity resolvers enumerable.</value> - private IItemResolver[] EntityResolvers { get; set; } - private IMultiItemResolver[] MultiItemResolvers { get; set; } - - /// <summary> - /// Gets or sets the comparers. - /// </summary> - /// <value>The comparers.</value> - private IBaseItemComparer[] Comparers { get; set; } - - /// <summary> - /// Gets the active item repository - /// </summary> - /// <value>The item repository.</value> - public IItemRepository ItemRepository { get; set; } - - /// <summary> - /// Occurs when [item added]. - /// </summary> - public event EventHandler<ItemChangeEventArgs> ItemAdded; - - /// <summary> - /// Occurs when [item updated]. - /// </summary> - public event EventHandler<ItemChangeEventArgs> ItemUpdated; - - /// <summary> - /// Occurs when [item removed]. - /// </summary> - public event EventHandler<ItemChangeEventArgs> ItemRemoved; - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - /// <summary> - /// The _task manager - /// </summary> - private readonly ITaskManager _taskManager; - - /// <summary> - /// The _user manager - /// </summary> - private readonly IUserManager _userManager; - - /// <summary> - /// The _user data repository - /// </summary> - private readonly IUserDataManager _userDataRepository; - - /// <summary> - /// Gets or sets the configuration manager. - /// </summary> - /// <value>The configuration manager.</value> - private IServerConfigurationManager ConfigurationManager { get; set; } - - /// <summary> - /// A collection of items that may be referenced from multiple physical places in the library - /// (typically, multiple user roots). We store them here and be sure they all reference a - /// single instance. - /// </summary> - /// <value>The by reference items.</value> - private ConcurrentDictionary<Guid, BaseItem> ByReferenceItems { get; set; } - - private readonly Func<ILibraryMonitor> _libraryMonitorFactory; - private readonly Func<IProviderManager> _providerManagerFactory; - private readonly Func<IUserViewManager> _userviewManager; - public bool IsScanRunning { get; private set; } - - /// <summary> - /// The _library items cache - /// </summary> - private readonly ConcurrentDictionary<Guid, BaseItem> _libraryItemsCache; - /// <summary> - /// Gets the library items cache. - /// </summary> - /// <value>The library items cache.</value> - private ConcurrentDictionary<Guid, BaseItem> LibraryItemsCache - { - get - { - return _libraryItemsCache; - } - } - - private readonly IFileSystem _fileSystem; - - /// <summary> - /// Initializes a new instance of the <see cref="LibraryManager" /> class. - /// </summary> - /// <param name="logger">The logger.</param> - /// <param name="taskManager">The task manager.</param> - /// <param name="userManager">The user manager.</param> - /// <param name="configurationManager">The configuration manager.</param> - /// <param name="userDataRepository">The user data repository.</param> - public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, Func<ILibraryMonitor> libraryMonitorFactory, IFileSystem fileSystem, Func<IProviderManager> providerManagerFactory, Func<IUserViewManager> userviewManager) - { - _logger = logger; - _taskManager = taskManager; - _userManager = userManager; - ConfigurationManager = configurationManager; - _userDataRepository = userDataRepository; - _libraryMonitorFactory = libraryMonitorFactory; - _fileSystem = fileSystem; - _providerManagerFactory = providerManagerFactory; - _userviewManager = userviewManager; - ByReferenceItems = new ConcurrentDictionary<Guid, BaseItem>(); - _libraryItemsCache = new ConcurrentDictionary<Guid, BaseItem>(); - - ConfigurationManager.ConfigurationUpdated += ConfigurationUpdated; - - RecordConfigurationValues(configurationManager.Configuration); - } - - /// <summary> - /// Adds the parts. - /// </summary> - /// <param name="rules">The rules.</param> - /// <param name="pluginFolders">The plugin folders.</param> - /// <param name="resolvers">The resolvers.</param> - /// <param name="introProviders">The intro providers.</param> - /// <param name="itemComparers">The item comparers.</param> - /// <param name="postscanTasks">The postscan tasks.</param> - public void AddParts(IEnumerable<IResolverIgnoreRule> rules, - IEnumerable<IVirtualFolderCreator> pluginFolders, - IEnumerable<IItemResolver> resolvers, - IEnumerable<IIntroProvider> introProviders, - IEnumerable<IBaseItemComparer> itemComparers, - IEnumerable<ILibraryPostScanTask> postscanTasks) - { - EntityResolutionIgnoreRules = rules.ToArray(); - PluginFolderCreators = pluginFolders.ToArray(); - EntityResolvers = resolvers.OrderBy(i => i.Priority).ToArray(); - MultiItemResolvers = EntityResolvers.OfType<IMultiItemResolver>().ToArray(); - IntroProviders = introProviders.ToArray(); - Comparers = itemComparers.ToArray(); - - PostscanTasks = postscanTasks.OrderBy(i => - { - var hasOrder = i as IHasOrder; - - return hasOrder == null ? 0 : hasOrder.Order; - - }).ToArray(); - } - - /// <summary> - /// The _root folder - /// </summary> - private volatile AggregateFolder _rootFolder; - /// <summary> - /// The _root folder sync lock - /// </summary> - private readonly object _rootFolderSyncLock = new object(); - /// <summary> - /// Gets the root folder. - /// </summary> - /// <value>The root folder.</value> - public AggregateFolder RootFolder - { - get - { - if (_rootFolder == null) - { - lock (_rootFolderSyncLock) - { - if (_rootFolder == null) - { - _rootFolder = CreateRootFolder(); - } - } - } - return _rootFolder; - } - } - - /// <summary> - /// The _season zero display name - /// </summary> - private string _seasonZeroDisplayName; - - private bool _wizardCompleted; - /// <summary> - /// Records the configuration values. - /// </summary> - /// <param name="configuration">The configuration.</param> - private void RecordConfigurationValues(ServerConfiguration configuration) - { - _seasonZeroDisplayName = configuration.SeasonZeroDisplayName; - _wizardCompleted = configuration.IsStartupWizardCompleted; - } - - /// <summary> - /// Configurations the updated. - /// </summary> - /// <param name="sender">The sender.</param> - /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> - void ConfigurationUpdated(object sender, EventArgs e) - { - var config = ConfigurationManager.Configuration; - - var newSeasonZeroName = ConfigurationManager.Configuration.SeasonZeroDisplayName; - var seasonZeroNameChanged = !string.Equals(_seasonZeroDisplayName, newSeasonZeroName, StringComparison.Ordinal); - var wizardChanged = config.IsStartupWizardCompleted != _wizardCompleted; - - RecordConfigurationValues(config); - - if (seasonZeroNameChanged || wizardChanged) - { - _taskManager.CancelIfRunningAndQueue<RefreshMediaLibraryTask>(); - } - - if (seasonZeroNameChanged) - { - Task.Run(async () => - { - await UpdateSeasonZeroNames(newSeasonZeroName, CancellationToken.None).ConfigureAwait(false); - - }); - } - } - - /// <summary> - /// Updates the season zero names. - /// </summary> - /// <param name="newName">The new name.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - private async Task UpdateSeasonZeroNames(string newName, CancellationToken cancellationToken) - { - var seasons = GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Season).Name }, - Recursive = true, - IndexNumber = 0 - - }).Cast<Season>() - .Where(i => !string.Equals(i.Name, newName, StringComparison.Ordinal)) - .ToList(); - - foreach (var season in seasons) - { - season.Name = newName; - - try - { - await UpdateItem(season, ItemUpdateType.MetadataDownload, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error saving {0}", ex, season.Path); - } - } - } - - public void RegisterItem(BaseItem item) - { - if (item == null) - { - throw new ArgumentNullException("item"); - } - RegisterItem(item.Id, item); - } - - private void RegisterItem(Guid id, BaseItem item) - { - if (item is IItemByName) - { - if (!(item is MusicArtist)) - { - return; - } - } - - if (item.IsFolder) - { - if (!(item is ICollectionFolder) && !(item is UserView) && !(item is Channel) && !(item is AggregateFolder)) - { - if (item.SourceType != SourceType.Library) - { - return; - } - } - } - else - { - if (item is Photo) - { - return; - } - } - - LibraryItemsCache.AddOrUpdate(id, item, delegate { return item; }); - } - - public async Task DeleteItem(BaseItem item, DeleteOptions options) - { - if (item == null) - { - throw new ArgumentNullException("item"); - } - - _logger.Debug("Deleting item, Type: {0}, Name: {1}, Path: {2}, Id: {3}", - item.GetType().Name, - item.Name ?? "Unknown name", - item.Path ?? string.Empty, - item.Id); - - var parent = item.Parent; - - var locationType = item.LocationType; - - var children = item.IsFolder - ? ((Folder)item).GetRecursiveChildren(false).ToList() - : new List<BaseItem>(); - - foreach (var metadataPath in GetMetadataPaths(item, children)) - { - _logger.Debug("Deleting path {0}", metadataPath); - - try - { - _fileSystem.DeleteDirectory(metadataPath, true); - } - catch (DirectoryNotFoundException) - { - - } - catch (Exception ex) - { - _logger.ErrorException("Error deleting {0}", ex, metadataPath); - } - } - - if (options.DeleteFileLocation && locationType != LocationType.Remote && locationType != LocationType.Virtual) - { - foreach (var path in item.GetDeletePaths().ToList()) - { - if (_fileSystem.DirectoryExists(path)) - { - _logger.Debug("Deleting path {0}", path); - _fileSystem.DeleteDirectory(path, true); - } - else if (_fileSystem.FileExists(path)) - { - _logger.Debug("Deleting path {0}", path); - _fileSystem.DeleteFile(path); - } - } - - if (parent != null) - { - await parent.ValidateChildren(new Progress<double>(), CancellationToken.None) - .ConfigureAwait(false); - } - } - else if (parent != null) - { - parent.RemoveChild(item); - } - - await ItemRepository.DeleteItem(item.Id, CancellationToken.None).ConfigureAwait(false); - foreach (var child in children) - { - await ItemRepository.DeleteItem(child.Id, CancellationToken.None).ConfigureAwait(false); - } - - BaseItem removed; - _libraryItemsCache.TryRemove(item.Id, out removed); - - ReportItemRemoved(item); - } - - private IEnumerable<string> GetMetadataPaths(BaseItem item, IEnumerable<BaseItem> children) - { - var list = new List<string> - { - item.GetInternalMetadataPath() - }; - - list.AddRange(children.Select(i => i.GetInternalMetadataPath())); - - return list; - } - - /// <summary> - /// Resolves the item. - /// </summary> - /// <param name="args">The args.</param> - /// <param name="resolvers">The resolvers.</param> - /// <returns>BaseItem.</returns> - private BaseItem ResolveItem(ItemResolveArgs args, IItemResolver[] resolvers) - { - var item = (resolvers ?? EntityResolvers).Select(r => Resolve(args, r)) - .FirstOrDefault(i => i != null); - - if (item != null) - { - ResolverHelper.SetInitialItemValues(item, args, _fileSystem, this); - } - - return item; - } - - private BaseItem Resolve(ItemResolveArgs args, IItemResolver resolver) - { - try - { - return resolver.ResolvePath(args); - } - catch (Exception ex) - { - _logger.ErrorException("Error in {0} resolving {1}", ex, resolver.GetType().Name, args.Path); - return null; - } - } - - public Guid GetNewItemId(string key, Type type) - { - if (string.IsNullOrWhiteSpace(key)) - { - throw new ArgumentNullException("key"); - } - if (type == null) - { - throw new ArgumentNullException("type"); - } - - if (ConfigurationManager.Configuration.EnableLocalizedGuids && key.StartsWith(ConfigurationManager.ApplicationPaths.ProgramDataPath)) - { - // Try to normalize paths located underneath program-data in an attempt to make them more portable - key = key.Substring(ConfigurationManager.ApplicationPaths.ProgramDataPath.Length) - .TrimStart(new[] { '/', '\\' }) - .Replace("/", "\\"); - } - - if (!ConfigurationManager.Configuration.EnableCaseSensitiveItemIds) - { - key = key.ToLower(); - } - - key = type.FullName + key; - - return key.GetMD5(); - } - - /// <summary> - /// Ensure supplied item has only one instance throughout - /// </summary> - /// <param name="item">The item.</param> - /// <returns>The proper instance to the item</returns> - public BaseItem GetOrAddByReferenceItem(BaseItem item) - { - // Add this item to our list if not there already - if (!ByReferenceItems.TryAdd(item.Id, item)) - { - // Already there - return the existing reference - item = ByReferenceItems[item.Id]; - } - return item; - } - - public BaseItem ResolvePath(FileSystemMetadata fileInfo, - Folder parent = null) - { - return ResolvePath(fileInfo, new DirectoryService(_logger, _fileSystem), null, parent); - } - - private BaseItem ResolvePath(FileSystemMetadata fileInfo, - IDirectoryService directoryService, - IItemResolver[] resolvers, - Folder parent = null, - string collectionType = null, - LibraryOptions libraryOptions = null) - { - if (fileInfo == null) - { - throw new ArgumentNullException("fileInfo"); - } - - var fullPath = fileInfo.FullName; - - if (string.IsNullOrWhiteSpace(collectionType) && parent != null) - { - collectionType = GetContentTypeOverride(fullPath, true); - } - - var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService) - { - Parent = parent, - Path = fullPath, - FileInfo = fileInfo, - CollectionType = collectionType, - LibraryOptions = libraryOptions - }; - - // Return null if ignore rules deem that we should do so - if (IgnoreFile(args.FileInfo, args.Parent)) - { - return null; - } - - // Gather child folder and files - if (args.IsDirectory) - { - var isPhysicalRoot = args.IsPhysicalRoot; - - // When resolving the root, we need it's grandchildren (children of user views) - var flattenFolderDepth = isPhysicalRoot ? 2 : 0; - - var fileSystemDictionary = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, _fileSystem, _logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf); - - // Need to remove subpaths that may have been resolved from shortcuts - // Example: if \\server\movies exists, then strip out \\server\movies\action - if (isPhysicalRoot) - { - var paths = NormalizeRootPathList(fileSystemDictionary.Values); - - fileSystemDictionary = paths.ToDictionary(i => i.FullName); - } - - args.FileSystemDictionary = fileSystemDictionary; - } - - // Check to see if we should resolve based on our contents - if (args.IsDirectory && !ShouldResolvePathContents(args)) - { - return null; - } - - return ResolveItem(args, resolvers); - } - - private readonly List<string> _ignoredPaths = new List<string>(); - - public void RegisterIgnoredPath(string path) - { - lock (_ignoredPaths) - { - _ignoredPaths.Add(path); - } - } - public void UnRegisterIgnoredPath(string path) - { - lock (_ignoredPaths) - { - _ignoredPaths.Remove(path); - } - } - - public bool IgnoreFile(FileSystemMetadata file, BaseItem parent) - { - if (EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(file, parent))) - { - return true; - } - - //lock (_ignoredPaths) - { - if (_ignoredPaths.Contains(file.FullName, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - } - return false; - } - - public IEnumerable<FileSystemMetadata> NormalizeRootPathList(IEnumerable<FileSystemMetadata> paths) - { - var originalList = paths.ToList(); - - var list = originalList.Where(i => i.IsDirectory) - .Select(i => _fileSystem.NormalizePath(i.FullName)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToList(); - - var dupes = list.Where(subPath => !subPath.EndsWith(":\\", StringComparison.OrdinalIgnoreCase) && list.Any(i => _fileSystem.ContainsSubPath(i, subPath))) - .ToList(); - - foreach (var dupe in dupes) - { - _logger.Info("Found duplicate path: {0}", dupe); - } - - var newList = list.Except(dupes, StringComparer.OrdinalIgnoreCase).Select(_fileSystem.GetDirectoryInfo).ToList(); - newList.AddRange(originalList.Where(i => !i.IsDirectory)); - return newList; - } - - /// <summary> - /// Determines whether a path should be ignored based on its contents - called after the contents have been read - /// </summary> - /// <param name="args">The args.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - private static bool ShouldResolvePathContents(ItemResolveArgs args) - { - // Ignore any folders containing a file called .ignore - return !args.ContainsFileSystemEntryByName(".ignore"); - } - - public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, string collectionType) - { - return ResolvePaths(files, directoryService, parent, libraryOptions, collectionType, EntityResolvers); - } - - public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, - IDirectoryService directoryService, - Folder parent, - LibraryOptions libraryOptions, - string collectionType, - IItemResolver[] resolvers) - { - var fileList = files.Where(i => !IgnoreFile(i, parent)).ToList(); - - if (parent != null) - { - var multiItemResolvers = resolvers == null ? MultiItemResolvers : resolvers.OfType<IMultiItemResolver>().ToArray(); - - foreach (var resolver in multiItemResolvers) - { - var result = resolver.ResolveMultiple(parent, fileList, collectionType, directoryService); - - if (result != null && result.Items.Count > 0) - { - var items = new List<BaseItem>(); - items.AddRange(result.Items); - - foreach (var item in items) - { - ResolverHelper.SetInitialItemValues(item, parent, _fileSystem, this, directoryService); - } - items.AddRange(ResolveFileList(result.ExtraFiles, directoryService, parent, collectionType, resolvers, libraryOptions)); - return items; - } - } - } - - return ResolveFileList(fileList, directoryService, parent, collectionType, resolvers, libraryOptions); - } - - private IEnumerable<BaseItem> ResolveFileList(IEnumerable<FileSystemMetadata> fileList, - IDirectoryService directoryService, - Folder parent, - string collectionType, - IItemResolver[] resolvers, - LibraryOptions libraryOptions) - { - return fileList.Select(f => - { - try - { - return ResolvePath(f, directoryService, resolvers, parent, collectionType, libraryOptions); - } - catch (Exception ex) - { - _logger.ErrorException("Error resolving path {0}", ex, f.FullName); - return null; - } - }).Where(i => i != null); - } - - /// <summary> - /// Creates the root media folder - /// </summary> - /// <returns>AggregateFolder.</returns> - /// <exception cref="System.InvalidOperationException">Cannot create the root folder until plugins have loaded</exception> - public AggregateFolder CreateRootFolder() - { - var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath; - - _fileSystem.CreateDirectory(rootFolderPath); - - var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath)); - - // Add in the plug-in folders - foreach (var child in PluginFolderCreators) - { - var folder = child.GetFolder(); - - if (folder != null) - { - if (folder.Id == Guid.Empty) - { - if (string.IsNullOrWhiteSpace(folder.Path)) - { - folder.Id = GetNewItemId(folder.GetType().Name, folder.GetType()); - } - else - { - folder.Id = GetNewItemId(folder.Path, folder.GetType()); - } - } - - var dbItem = GetItemById(folder.Id) as BasePluginFolder; - - if (dbItem != null && string.Equals(dbItem.Path, folder.Path, StringComparison.OrdinalIgnoreCase)) - { - folder = dbItem; - } - - if (folder.ParentId != rootFolder.Id) - { - folder.ParentId = rootFolder.Id; - var task = folder.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None); - Task.WaitAll(task); - } - - rootFolder.AddVirtualChild(folder); - - RegisterItem(folder); - } - } - - return rootFolder; - } - - private volatile UserRootFolder _userRootFolder; - private readonly object _syncLock = new object(); - public Folder GetUserRootFolder() - { - if (_userRootFolder == null) - { - lock (_syncLock) - { - if (_userRootFolder == null) - { - var userRootPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - - _fileSystem.CreateDirectory(userRootPath); - - var tmpItem = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder; - - if (tmpItem == null) - { - tmpItem = (UserRootFolder)ResolvePath(_fileSystem.GetDirectoryInfo(userRootPath)); - } - - _userRootFolder = tmpItem; - } - } - } - - return _userRootFolder; - } - - public BaseItem FindByPath(string path, bool? isFolder) - { - // If this returns multiple items it could be tricky figuring out which one is correct. - // In most cases, the newest one will be and the others obsolete but not yet cleaned up - - var query = new InternalItemsQuery - { - Path = path, - IsFolder = isFolder, - SortBy = new[] { ItemSortBy.DateCreated }, - SortOrder = SortOrder.Descending, - Limit = 1 - }; - - return GetItemList(query) - .FirstOrDefault(); - } - - /// <summary> - /// Gets a Person - /// </summary> - /// <param name="name">The name.</param> - /// <returns>Task{Person}.</returns> - public Person GetPerson(string name) - { - return CreateItemByName<Person>(Person.GetPath(name), name); - } - - /// <summary> - /// Gets a Studio - /// </summary> - /// <param name="name">The name.</param> - /// <returns>Task{Studio}.</returns> - public Studio GetStudio(string name) - { - return CreateItemByName<Studio>(Studio.GetPath(name), name); - } - - /// <summary> - /// Gets a Genre - /// </summary> - /// <param name="name">The name.</param> - /// <returns>Task{Genre}.</returns> - public Genre GetGenre(string name) - { - return CreateItemByName<Genre>(Genre.GetPath(name), name); - } - - /// <summary> - /// Gets the genre. - /// </summary> - /// <param name="name">The name.</param> - /// <returns>Task{MusicGenre}.</returns> - public MusicGenre GetMusicGenre(string name) - { - return CreateItemByName<MusicGenre>(MusicGenre.GetPath(name), name); - } - - /// <summary> - /// Gets the game genre. - /// </summary> - /// <param name="name">The name.</param> - /// <returns>Task{GameGenre}.</returns> - public GameGenre GetGameGenre(string name) - { - return CreateItemByName<GameGenre>(GameGenre.GetPath(name), name); - } - - /// <summary> - /// Gets a Year - /// </summary> - /// <param name="value">The value.</param> - /// <returns>Task{Year}.</returns> - /// <exception cref="System.ArgumentOutOfRangeException"></exception> - public Year GetYear(int value) - { - if (value <= 0) - { - throw new ArgumentOutOfRangeException("Years less than or equal to 0 are invalid."); - } - - var name = value.ToString(CultureInfo.InvariantCulture); - - return CreateItemByName<Year>(Year.GetPath(name), name); - } - - /// <summary> - /// Gets a Genre - /// </summary> - /// <param name="name">The name.</param> - /// <returns>Task{Genre}.</returns> - public MusicArtist GetArtist(string name) - { - return CreateItemByName<MusicArtist>(MusicArtist.GetPath(name), name); - } - - private T CreateItemByName<T>(string path, string name) - where T : BaseItem, new() - { - if (typeof(T) == typeof(MusicArtist)) - { - var existing = GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(T).Name }, - Name = name - - }).Cast<MusicArtist>() - .OrderBy(i => i.IsAccessedByName ? 1 : 0) - .Cast<T>() - .FirstOrDefault(); - - if (existing != null) - { - return existing; - } - } - - var id = GetNewItemId(path, typeof(T)); - - var item = GetItemById(id) as T; - - if (item == null) - { - item = new T - { - Name = name, - Id = id, - DateCreated = DateTime.UtcNow, - DateModified = DateTime.UtcNow, - Path = path - }; - - var task = CreateItem(item, CancellationToken.None); - Task.WaitAll(task); - } - - return item; - } - - public IEnumerable<MusicArtist> GetAlbumArtists(IEnumerable<IHasAlbumArtist> items) - { - var names = items - .SelectMany(i => i.AlbumArtists) - .DistinctNames() - .Select(i => - { - try - { - var artist = GetArtist(i); - - return artist; - } - catch - { - // Already logged at lower levels - return null; - } - }) - .Where(i => i != null); - - return names; - } - - public IEnumerable<MusicArtist> GetArtists(IEnumerable<IHasArtist> items) - { - var names = items - .SelectMany(i => i.AllArtists) - .DistinctNames() - .Select(i => - { - try - { - var artist = GetArtist(i); - - return artist; - } - catch - { - // Already logged at lower levels - return null; - } - }) - .Where(i => i != null); - - return names; - } - - /// <summary> - /// Validate and refresh the People sub-set of the IBN. - /// The items are stored in the db but not loaded into memory until actually requested by an operation. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress) - { - // Ensure the location is available. - _fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath); - - return new PeopleValidator(this, _logger, ConfigurationManager, _fileSystem).ValidatePeople(cancellationToken, progress); - } - - /// <summary> - /// Reloads the root media folder - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task ValidateMediaLibrary(IProgress<double> progress, CancellationToken cancellationToken) - { - // Just run the scheduled task so that the user can see it - _taskManager.CancelIfRunningAndQueue<RefreshMediaLibraryTask>(); - - return Task.FromResult(true); - } - - /// <summary> - /// Queues the library scan. - /// </summary> - public void QueueLibraryScan() - { - // Just run the scheduled task so that the user can see it - _taskManager.QueueScheduledTask<RefreshMediaLibraryTask>(); - } - - /// <summary> - /// Validates the media library internal. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task ValidateMediaLibraryInternal(IProgress<double> progress, CancellationToken cancellationToken) - { - IsScanRunning = true; - _libraryMonitorFactory().Stop(); - - try - { - await PerformLibraryValidation(progress, cancellationToken).ConfigureAwait(false); - } - finally - { - _libraryMonitorFactory().Start(); - IsScanRunning = false; - } - } - - private async Task PerformLibraryValidation(IProgress<double> progress, CancellationToken cancellationToken) - { - _logger.Info("Validating media library"); - - await RootFolder.RefreshMetadata(cancellationToken).ConfigureAwait(false); - - progress.Report(.5); - - // Start by just validating the children of the root, but go no further - await RootFolder.ValidateChildren(new Progress<double>(), cancellationToken, new MetadataRefreshOptions(_fileSystem), recursive: false); - - progress.Report(1); - - var userRoot = GetUserRootFolder(); - - await userRoot.RefreshMetadata(cancellationToken).ConfigureAwait(false); - - await userRoot.ValidateChildren(new Progress<double>(), cancellationToken, new MetadataRefreshOptions(_fileSystem), recursive: false).ConfigureAwait(false); - progress.Report(2); - - var innerProgress = new ActionableProgress<double>(); - - innerProgress.RegisterAction(pct => progress.Report(2 + pct * .73)); - - // Now validate the entire media library - await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(_fileSystem), recursive: true).ConfigureAwait(false); - - progress.Report(75); - - innerProgress = new ActionableProgress<double>(); - - innerProgress.RegisterAction(pct => progress.Report(75 + pct * .25)); - - // Run post-scan tasks - await RunPostScanTasks(innerProgress, cancellationToken).ConfigureAwait(false); - - progress.Report(100); - } - - /// <summary> - /// Runs the post scan tasks. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - private async Task RunPostScanTasks(IProgress<double> progress, CancellationToken cancellationToken) - { - var tasks = PostscanTasks.ToList(); - - var numComplete = 0; - var numTasks = tasks.Count; - - foreach (var task in tasks) - { - var innerProgress = new ActionableProgress<double>(); - - // Prevent access to modified closure - var currentNumComplete = numComplete; - - innerProgress.RegisterAction(pct => - { - double innerPercent = currentNumComplete * 100 + pct; - innerPercent /= numTasks; - progress.Report(innerPercent); - }); - - _logger.Debug("Running post-scan task {0}", task.GetType().Name); - - try - { - await task.Run(innerProgress, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - _logger.Info("Post-scan task cancelled: {0}", task.GetType().Name); - } - catch (Exception ex) - { - _logger.ErrorException("Error running postscan task", ex); - } - - numComplete++; - double percent = numComplete; - percent /= numTasks; - progress.Report(percent * 100); - } - - progress.Report(100); - } - - /// <summary> - /// Gets the default view. - /// </summary> - /// <returns>IEnumerable{VirtualFolderInfo}.</returns> - public IEnumerable<VirtualFolderInfo> GetVirtualFolders() - { - return GetView(ConfigurationManager.ApplicationPaths.DefaultUserViewsPath); - } - - /// <summary> - /// Gets the view. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>IEnumerable{VirtualFolderInfo}.</returns> - private IEnumerable<VirtualFolderInfo> GetView(string path) - { - var topLibraryFolders = GetUserRootFolder().Children.ToList(); - - return _fileSystem.GetDirectoryPaths(path) - .Select(dir => GetVirtualFolderInfo(dir, topLibraryFolders)); - } - - private VirtualFolderInfo GetVirtualFolderInfo(string dir, List<BaseItem> allCollectionFolders) - { - var info = new VirtualFolderInfo - { - Name = Path.GetFileName(dir), - - Locations = Directory.EnumerateFiles(dir, "*.mblink", SearchOption.TopDirectoryOnly) - .Select(_fileSystem.ResolveShortcut) - .OrderBy(i => i) - .ToList(), - - CollectionType = GetCollectionType(dir) - }; - - var libraryFolder = allCollectionFolders.FirstOrDefault(i => string.Equals(i.Path, dir, StringComparison.OrdinalIgnoreCase)); - - if (libraryFolder != null && libraryFolder.HasImage(ImageType.Primary)) - { - info.PrimaryImageItemId = libraryFolder.Id.ToString("N"); - } - - if (libraryFolder != null) - { - info.ItemId = libraryFolder.Id.ToString("N"); - info.LibraryOptions = GetLibraryOptions(libraryFolder); - } - - return info; - } - - private string GetCollectionType(string path) - { - return _fileSystem.GetFiles(path, false) - .Where(i => string.Equals(i.Extension, ".collection", StringComparison.OrdinalIgnoreCase)) - .Select(i => _fileSystem.GetFileNameWithoutExtension(i)) - .FirstOrDefault(); - } - - /// <summary> - /// Gets the item by id. - /// </summary> - /// <param name="id">The id.</param> - /// <returns>BaseItem.</returns> - /// <exception cref="System.ArgumentNullException">id</exception> - public BaseItem GetItemById(Guid id) - { - if (id == Guid.Empty) - { - throw new ArgumentNullException("id"); - } - - BaseItem item; - - if (LibraryItemsCache.TryGetValue(id, out item)) - { - return item; - } - - item = RetrieveItem(id); - - //_logger.Debug("GetitemById {0}", id); - - if (item != null) - { - RegisterItem(item); - } - - return item; - } - - public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query) - { - if (query.Recursive && query.ParentId.HasValue) - { - var parent = GetItemById(query.ParentId.Value); - if (parent != null) - { - SetTopParentIdsOrAncestors(query, new List<BaseItem> { parent }); - query.ParentId = null; - } - } - - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - return ItemRepository.GetItemList(query); - } - - public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, IEnumerable<string> parentIds) - { - var parents = parentIds.Select(i => GetItemById(new Guid(i))).Where(i => i != null).ToList(); - - SetTopParentIdsOrAncestors(query, parents); - - if (query.AncestorIds.Length == 0 && query.TopParentIds.Length == 0) - { - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - } - - return ItemRepository.GetItemList(query); - } - - public QueryResult<BaseItem> QueryItems(InternalItemsQuery query) - { - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - if (query.EnableTotalRecordCount) - { - return ItemRepository.GetItems(query); - } - - return new QueryResult<BaseItem> - { - Items = ItemRepository.GetItemList(query).ToArray() - }; - } - - public List<Guid> GetItemIds(InternalItemsQuery query) - { - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - return ItemRepository.GetItemIdsList(query); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetStudios(InternalItemsQuery query) - { - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - SetTopParentOrAncestorIds(query); - return ItemRepository.GetStudios(query); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query) - { - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - SetTopParentOrAncestorIds(query); - return ItemRepository.GetGenres(query); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query) - { - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - SetTopParentOrAncestorIds(query); - return ItemRepository.GetGameGenres(query); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query) - { - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - SetTopParentOrAncestorIds(query); - return ItemRepository.GetMusicGenres(query); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetAllArtists(InternalItemsQuery query) - { - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - SetTopParentOrAncestorIds(query); - return ItemRepository.GetAllArtists(query); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query) - { - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - SetTopParentOrAncestorIds(query); - return ItemRepository.GetArtists(query); - } - - private void SetTopParentOrAncestorIds(InternalItemsQuery query) - { - if (query.AncestorIds.Length == 0) - { - return; - } - - var parents = query.AncestorIds.Select(i => GetItemById(new Guid(i))).ToList(); - - if (parents.All(i => - { - if (i is ICollectionFolder || i is UserView) - { - return true; - } - - //_logger.Debug("Query requires ancestor query due to type: " + i.GetType().Name); - return false; - - })) - { - // Optimize by querying against top level views - query.TopParentIds = parents.SelectMany(i => GetTopParentsForQuery(i, query.User)).Select(i => i.Id.ToString("N")).ToArray(); - query.AncestorIds = new string[] { }; - } - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query) - { - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - SetTopParentOrAncestorIds(query); - return ItemRepository.GetAlbumArtists(query); - } - - public QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query) - { - if (query.Recursive && query.ParentId.HasValue) - { - var parent = GetItemById(query.ParentId.Value); - if (parent != null) - { - SetTopParentIdsOrAncestors(query, new List<BaseItem> { parent }); - query.ParentId = null; - } - } - - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - if (query.EnableTotalRecordCount) - { - return ItemRepository.GetItems(query); - } - - return new QueryResult<BaseItem> - { - Items = ItemRepository.GetItemList(query).ToArray() - }; - } - - private void SetTopParentIdsOrAncestors(InternalItemsQuery query, List<BaseItem> parents) - { - if (parents.All(i => - { - if (i is ICollectionFolder || i is UserView) - { - return true; - } - - //_logger.Debug("Query requires ancestor query due to type: " + i.GetType().Name); - return false; - - })) - { - // Optimize by querying against top level views - query.TopParentIds = parents.SelectMany(i => GetTopParentsForQuery(i, query.User)).Select(i => i.Id.ToString("N")).ToArray(); - } - else - { - // We need to be able to query from any arbitrary ancestor up the tree - query.AncestorIds = parents.SelectMany(i => i.GetIdsForAncestorQuery()).Select(i => i.ToString("N")).ToArray(); - } - } - - private void AddUserToQuery(InternalItemsQuery query, User user) - { - if (query.AncestorIds.Length == 0 && - !query.ParentId.HasValue && - query.ChannelIds.Length == 0 && - query.TopParentIds.Length == 0 && - string.IsNullOrWhiteSpace(query.AncestorWithPresentationUniqueKey) - && query.ItemIds.Length == 0) - { - var userViews = _userviewManager().GetUserViews(new UserViewQuery - { - UserId = user.Id.ToString("N"), - IncludeHidden = true - - }, CancellationToken.None).Result.ToList(); - - query.TopParentIds = userViews.SelectMany(i => GetTopParentsForQuery(i, user)).Select(i => i.Id.ToString("N")).ToArray(); - } - } - - private IEnumerable<BaseItem> GetTopParentsForQuery(BaseItem item, User user) - { - var view = item as UserView; - - if (view != null) - { - if (string.Equals(view.ViewType, CollectionType.LiveTv)) - { - return new[] { view }; - } - if (string.Equals(view.ViewType, CollectionType.Channels)) - { - var channelResult = BaseItem.ChannelManager.GetChannelsInternal(new ChannelQuery - { - UserId = user.Id.ToString("N") - - }, CancellationToken.None).Result; - - return channelResult.Items; - } - - // Translate view into folders - if (view.DisplayParentId != Guid.Empty) - { - var displayParent = GetItemById(view.DisplayParentId); - if (displayParent != null) - { - return GetTopParentsForQuery(displayParent, user); - } - return new BaseItem[] { }; - } - if (view.ParentId != Guid.Empty) - { - var displayParent = GetItemById(view.ParentId); - if (displayParent != null) - { - return GetTopParentsForQuery(displayParent, user); - } - return new BaseItem[] { }; - } - - // Handle grouping - if (user != null && !string.IsNullOrWhiteSpace(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType)) - { - return user.RootFolder - .GetChildren(user, true) - .OfType<CollectionFolder>() - .Where(i => string.IsNullOrWhiteSpace(i.CollectionType) || string.Equals(i.CollectionType, view.ViewType, StringComparison.OrdinalIgnoreCase)) - .Where(i => user.IsFolderGrouped(i.Id)) - .SelectMany(i => GetTopParentsForQuery(i, user)); - } - return new BaseItem[] { }; - } - - var collectionFolder = item as CollectionFolder; - if (collectionFolder != null) - { - return collectionFolder.GetPhysicalParents(); - } - - var topParent = item.GetTopParent(); - if (topParent != null) - { - return new[] { topParent }; - } - return new BaseItem[] { }; - } - - /// <summary> - /// Gets the intros. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="user">The user.</param> - /// <returns>IEnumerable{System.String}.</returns> - public async Task<IEnumerable<Video>> GetIntros(BaseItem item, User user) - { - var tasks = IntroProviders - .OrderBy(i => i.GetType().Name.IndexOf("Default", StringComparison.OrdinalIgnoreCase) == -1 ? 0 : 1) - .Take(1) - .Select(i => GetIntros(i, item, user)); - - var items = await Task.WhenAll(tasks).ConfigureAwait(false); - - return items - .SelectMany(i => i.ToArray()) - .Select(ResolveIntro) - .Where(i => i != null); - } - - /// <summary> - /// Gets the intros. - /// </summary> - /// <param name="provider">The provider.</param> - /// <param name="item">The item.</param> - /// <param name="user">The user.</param> - /// <returns>Task<IEnumerable<IntroInfo>>.</returns> - private async Task<IEnumerable<IntroInfo>> GetIntros(IIntroProvider provider, BaseItem item, User user) - { - try - { - return await provider.GetIntros(item, user).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting intros", ex); - - return new List<IntroInfo>(); - } - } - - /// <summary> - /// Gets all intro files. - /// </summary> - /// <returns>IEnumerable{System.String}.</returns> - public IEnumerable<string> GetAllIntroFiles() - { - return IntroProviders.SelectMany(i => - { - try - { - return i.GetAllIntroFiles().ToList(); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting intro files", ex); - - return new List<string>(); - } - }); - } - - /// <summary> - /// Resolves the intro. - /// </summary> - /// <param name="info">The info.</param> - /// <returns>Video.</returns> - private Video ResolveIntro(IntroInfo info) - { - Video video = null; - - if (info.ItemId.HasValue) - { - // Get an existing item by Id - video = GetItemById(info.ItemId.Value) as Video; - - if (video == null) - { - _logger.Error("Unable to locate item with Id {0}.", info.ItemId.Value); - } - } - else if (!string.IsNullOrEmpty(info.Path)) - { - try - { - // Try to resolve the path into a video - video = ResolvePath(_fileSystem.GetFileSystemInfo(info.Path)) as Video; - - if (video == null) - { - _logger.Error("Intro resolver returned null for {0}.", info.Path); - } - else - { - // Pull the saved db item that will include metadata - var dbItem = GetItemById(video.Id) as Video; - - if (dbItem != null) - { - video = dbItem; - } - else - { - return null; - } - } - } - catch (Exception ex) - { - _logger.ErrorException("Error resolving path {0}.", ex, info.Path); - } - } - else - { - _logger.Error("IntroProvider returned an IntroInfo with null Path and ItemId."); - } - - return video; - } - - /// <summary> - /// Sorts the specified sort by. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="user">The user.</param> - /// <param name="sortBy">The sort by.</param> - /// <param name="sortOrder">The sort order.</param> - /// <returns>IEnumerable{BaseItem}.</returns> - public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<string> sortBy, SortOrder sortOrder) - { - var isFirst = true; - - IOrderedEnumerable<BaseItem> orderedItems = null; - - foreach (var orderBy in sortBy.Select(o => GetComparer(o, user)).Where(c => c != null)) - { - if (isFirst) - { - orderedItems = sortOrder == SortOrder.Descending ? items.OrderByDescending(i => i, orderBy) : items.OrderBy(i => i, orderBy); - } - else - { - orderedItems = sortOrder == SortOrder.Descending ? orderedItems.ThenByDescending(i => i, orderBy) : orderedItems.ThenBy(i => i, orderBy); - } - - isFirst = false; - } - - return orderedItems ?? items; - } - - /// <summary> - /// Gets the comparer. - /// </summary> - /// <param name="name">The name.</param> - /// <param name="user">The user.</param> - /// <returns>IBaseItemComparer.</returns> - private IBaseItemComparer GetComparer(string name, User user) - { - var comparer = Comparers.FirstOrDefault(c => string.Equals(name, c.Name, StringComparison.OrdinalIgnoreCase)); - - if (comparer != null) - { - // If it requires a user, create a new one, and assign the user - if (comparer is IUserBaseItemComparer) - { - var userComparer = (IUserBaseItemComparer)Activator.CreateInstance(comparer.GetType()); - - userComparer.User = user; - userComparer.UserManager = _userManager; - userComparer.UserDataRepository = _userDataRepository; - - return userComparer; - } - } - - return comparer; - } - - /// <summary> - /// Creates the item. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task CreateItem(BaseItem item, CancellationToken cancellationToken) - { - return CreateItems(new[] { item }, cancellationToken); - } - - /// <summary> - /// Creates the items. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task CreateItems(IEnumerable<BaseItem> items, CancellationToken cancellationToken) - { - var list = items.ToList(); - - await ItemRepository.SaveItems(list, cancellationToken).ConfigureAwait(false); - - foreach (var item in list) - { - RegisterItem(item); - } - - if (ItemAdded != null) - { - foreach (var item in list) - { - try - { - ItemAdded(this, new ItemChangeEventArgs { Item = item }); - } - catch (Exception ex) - { - _logger.ErrorException("Error in ItemAdded event handler", ex); - } - } - } - } - - /// <summary> - /// Updates the item. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="updateReason">The update reason.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task UpdateItem(BaseItem item, ItemUpdateType updateReason, CancellationToken cancellationToken) - { - var locationType = item.LocationType; - if (locationType != LocationType.Remote && locationType != LocationType.Virtual) - { - await _providerManagerFactory().SaveMetadata(item, updateReason).ConfigureAwait(false); - } - - item.DateLastSaved = DateTime.UtcNow; - - var logName = item.LocationType == LocationType.Remote ? item.Name ?? item.Path : item.Path ?? item.Name; - _logger.Debug("Saving {0} to database.", logName); - - await ItemRepository.SaveItem(item, cancellationToken).ConfigureAwait(false); - - RegisterItem(item); - - if (ItemUpdated != null) - { - try - { - ItemUpdated(this, new ItemChangeEventArgs - { - Item = item, - UpdateReason = updateReason - }); - } - catch (Exception ex) - { - _logger.ErrorException("Error in ItemUpdated event handler", ex); - } - } - } - - /// <summary> - /// Reports the item removed. - /// </summary> - /// <param name="item">The item.</param> - public void ReportItemRemoved(BaseItem item) - { - if (ItemRemoved != null) - { - try - { - ItemRemoved(this, new ItemChangeEventArgs { Item = item }); - } - catch (Exception ex) - { - _logger.ErrorException("Error in ItemRemoved event handler", ex); - } - } - } - - /// <summary> - /// Retrieves the item. - /// </summary> - /// <param name="id">The id.</param> - /// <returns>BaseItem.</returns> - public BaseItem RetrieveItem(Guid id) - { - return ItemRepository.RetrieveItem(id); - } - - public IEnumerable<Folder> GetCollectionFolders(BaseItem item) - { - while (!(item.GetParent() is AggregateFolder) && item.GetParent() != null) - { - item = item.GetParent(); - } - - if (item == null) - { - return new List<Folder>(); - } - - return GetUserRootFolder().Children - .OfType<Folder>() - .Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path, StringComparer.OrdinalIgnoreCase)); - } - - public LibraryOptions GetLibraryOptions(BaseItem item) - { - var collectionFolder = item as CollectionFolder; - if (collectionFolder == null) - { - collectionFolder = GetCollectionFolders(item) - .OfType<CollectionFolder>() - .FirstOrDefault(); - } - - 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; - } - - public string GetContentType(BaseItem item) - { - string configuredContentType = GetConfiguredContentType(item, false); - if (!string.IsNullOrWhiteSpace(configuredContentType)) - { - return configuredContentType; - } - configuredContentType = GetConfiguredContentType(item, true); - if (!string.IsNullOrWhiteSpace(configuredContentType)) - { - return configuredContentType; - } - return GetInheritedContentType(item); - } - - public string GetInheritedContentType(BaseItem item) - { - var type = GetTopFolderContentType(item); - - if (!string.IsNullOrWhiteSpace(type)) - { - return type; - } - - return item.GetParents() - .Select(GetConfiguredContentType) - .LastOrDefault(i => !string.IsNullOrWhiteSpace(i)); - } - - public string GetConfiguredContentType(BaseItem item) - { - return GetConfiguredContentType(item, false); - } - - public string GetConfiguredContentType(string path) - { - return GetContentTypeOverride(path, false); - } - - public string GetConfiguredContentType(BaseItem item, bool inheritConfiguredPath) - { - ICollectionFolder collectionFolder = item as ICollectionFolder; - if (collectionFolder != null) - { - return collectionFolder.CollectionType; - } - return GetContentTypeOverride(item.ContainingFolderPath, inheritConfiguredPath); - } - - 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))); - if (nameValuePair != null) - { - return nameValuePair.Value; - } - return null; - } - - private string GetTopFolderContentType(BaseItem item) - { - if (item == null) - { - return null; - } - - while (!(item.GetParent() is AggregateFolder) && item.GetParent() != null) - { - item = item.GetParent(); - } - - return GetUserRootFolder().Children - .OfType<ICollectionFolder>() - .Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path)) - .Select(i => i.CollectionType) - .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); - } - - private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromHours(24); - //private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromMinutes(1); - - public Task<UserView> GetNamedView(User user, - string name, - string viewType, - string sortName, - CancellationToken cancellationToken) - { - return GetNamedView(user, name, null, viewType, sortName, cancellationToken); - } - - public async Task<UserView> GetNamedView(string name, - string viewType, - string sortName, - CancellationToken cancellationToken) - { - var path = Path.Combine(ConfigurationManager.ApplicationPaths.ItemsByNamePath, "views"); - - path = Path.Combine(path, _fileSystem.GetValidFilename(viewType)); - - var id = GetNewItemId(path + "_namedview_" + name, typeof(UserView)); - - var item = GetItemById(id) as UserView; - - var refresh = false; - - if (item == null || !string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase)) - { - _fileSystem.CreateDirectory(path); - - item = new UserView - { - Path = path, - Id = id, - DateCreated = DateTime.UtcNow, - Name = name, - ViewType = viewType, - ForcedSortName = sortName - }; - - await CreateItem(item, cancellationToken).ConfigureAwait(false); - - refresh = true; - } - - if (!refresh) - { - refresh = DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval; - } - - if (!refresh && item.DisplayParentId != Guid.Empty) - { - var displayParent = GetItemById(item.DisplayParentId); - refresh = displayParent != null && displayParent.DateLastSaved > item.DateLastRefreshed; - } - - if (refresh) - { - await item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None).ConfigureAwait(false); - _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem) - { - // Not sure why this is necessary but need to figure it out - // View images are not getting utilized without this - ForceSave = true - }); - } - - return item; - } - - public async Task<UserView> GetNamedView(User user, - string name, - string parentId, - string viewType, - string sortName, - CancellationToken cancellationToken) - { - var idValues = "38_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty) + (viewType ?? string.Empty); - - var id = GetNewItemId(idValues, typeof(UserView)); - - var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N")); - - var item = GetItemById(id) as UserView; - - var isNew = false; - - if (item == null) - { - _fileSystem.CreateDirectory(path); - - item = new UserView - { - Path = path, - Id = id, - DateCreated = DateTime.UtcNow, - Name = name, - ViewType = viewType, - ForcedSortName = sortName, - UserId = user.Id - }; - - if (!string.IsNullOrWhiteSpace(parentId)) - { - item.DisplayParentId = new Guid(parentId); - } - - await CreateItem(item, cancellationToken).ConfigureAwait(false); - - isNew = true; - } - - var refresh = isNew || DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval; - - if (!refresh && item.DisplayParentId != Guid.Empty) - { - var displayParent = GetItemById(item.DisplayParentId); - refresh = displayParent != null && displayParent.DateLastSaved > item.DateLastRefreshed; - } - - if (refresh) - { - _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem) - { - // Need to force save to increment DateLastSaved - ForceSave = true - }); - } - - return item; - } - - public async Task<UserView> GetShadowView(BaseItem parent, - string viewType, - string sortName, - CancellationToken cancellationToken) - { - if (parent == null) - { - throw new ArgumentNullException("parent"); - } - - var name = parent.Name; - var parentId = parent.Id; - - var idValues = "38_namedview_" + name + parentId + (viewType ?? string.Empty); - - var id = GetNewItemId(idValues, typeof(UserView)); - - var path = parent.Path; - - var item = GetItemById(id) as UserView; - - var isNew = false; - - if (item == null) - { - _fileSystem.CreateDirectory(path); - - item = new UserView - { - Path = path, - Id = id, - DateCreated = DateTime.UtcNow, - Name = name, - ViewType = viewType, - ForcedSortName = sortName - }; - - item.DisplayParentId = parentId; - - await CreateItem(item, cancellationToken).ConfigureAwait(false); - - isNew = true; - } - - var refresh = isNew || DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval; - - if (!refresh && item.DisplayParentId != Guid.Empty) - { - var displayParent = GetItemById(item.DisplayParentId); - refresh = displayParent != null && displayParent.DateLastSaved > item.DateLastRefreshed; - } - - if (refresh) - { - _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem) - { - // Need to force save to increment DateLastSaved - ForceSave = true - }); - } - - return item; - } - - public async Task<UserView> GetNamedView(string name, - string parentId, - string viewType, - string sortName, - string uniqueId, - CancellationToken cancellationToken) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - - var idValues = "37_namedview_" + name + (parentId ?? string.Empty) + (viewType ?? string.Empty); - if (!string.IsNullOrWhiteSpace(uniqueId)) - { - idValues += uniqueId; - } - - var id = GetNewItemId(idValues, typeof(UserView)); - - var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N")); - - var item = GetItemById(id) as UserView; - - var isNew = false; - - if (item == null) - { - _fileSystem.CreateDirectory(path); - - item = new UserView - { - Path = path, - Id = id, - DateCreated = DateTime.UtcNow, - Name = name, - ViewType = viewType, - ForcedSortName = sortName - }; - - if (!string.IsNullOrWhiteSpace(parentId)) - { - item.DisplayParentId = new Guid(parentId); - } - - await CreateItem(item, cancellationToken).ConfigureAwait(false); - - isNew = true; - } - - if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase)) - { - item.ViewType = viewType; - await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); - } - - var refresh = isNew || DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval; - - if (!refresh && item.DisplayParentId != Guid.Empty) - { - var displayParent = GetItemById(item.DisplayParentId); - refresh = displayParent != null && displayParent.DateLastSaved > item.DateLastRefreshed; - } - - if (refresh) - { - _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem) - { - // Need to force save to increment DateLastSaved - ForceSave = true - }); - } - - return item; - } - - public bool IsVideoFile(string path, LibraryOptions libraryOptions) - { - var resolver = new VideoResolver(GetNamingOptions(libraryOptions), new PatternsLogger()); - return resolver.IsVideoFile(path); - } - - public bool IsVideoFile(string path) - { - return IsVideoFile(path, new LibraryOptions()); - } - - public bool IsAudioFile(string path, LibraryOptions libraryOptions) - { - var parser = new AudioFileParser(GetNamingOptions(libraryOptions)); - return parser.IsAudioFile(path); - } - - public bool IsAudioFile(string path) - { - return IsAudioFile(path, new LibraryOptions()); - } - - public int? GetSeasonNumberFromPath(string path) - { - return new SeasonPathParser(GetNamingOptions(), new RegexProvider()).Parse(path, true, true).SeasonNumber; - } - - public bool FillMissingEpisodeNumbersFromPath(Episode episode) - { - var resolver = new EpisodeResolver(GetNamingOptions(), - new PatternsLogger()); - - var isFolder = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd || - episode.VideoType == VideoType.HdDvd; - - var locationType = episode.LocationType; - - var episodeInfo = locationType == LocationType.FileSystem || locationType == LocationType.Offline ? - resolver.Resolve(episode.Path, isFolder) : - new Naming.TV.EpisodeInfo(); - - if (episodeInfo == null) - { - episodeInfo = new Naming.TV.EpisodeInfo(); - } - - var changed = false; - - if (episodeInfo.IsByDate) - { - if (episode.IndexNumber.HasValue) - { - episode.IndexNumber = null; - changed = true; - } - - if (episode.IndexNumberEnd.HasValue) - { - episode.IndexNumberEnd = null; - changed = true; - } - - if (!episode.PremiereDate.HasValue) - { - if (episodeInfo.Year.HasValue && episodeInfo.Month.HasValue && episodeInfo.Day.HasValue) - { - episode.PremiereDate = new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value).ToUniversalTime(); - } - - if (episode.PremiereDate.HasValue) - { - changed = true; - } - } - - if (!episode.ProductionYear.HasValue) - { - episode.ProductionYear = episodeInfo.Year; - - if (episode.ProductionYear.HasValue) - { - changed = true; - } - } - - if (!episode.ParentIndexNumber.HasValue) - { - var season = episode.Season; - - if (season != null) - { - episode.ParentIndexNumber = season.IndexNumber; - } - - if (episode.ParentIndexNumber.HasValue) - { - changed = true; - } - } - } - else - { - if (!episode.IndexNumber.HasValue) - { - episode.IndexNumber = episodeInfo.EpisodeNumber; - - if (episode.IndexNumber.HasValue) - { - changed = true; - } - } - - if (!episode.IndexNumberEnd.HasValue) - { - episode.IndexNumberEnd = episodeInfo.EndingEpsiodeNumber; - - if (episode.IndexNumberEnd.HasValue) - { - changed = true; - } - } - - if (!episode.ParentIndexNumber.HasValue) - { - episode.ParentIndexNumber = episodeInfo.SeasonNumber; - - if (!episode.ParentIndexNumber.HasValue) - { - var season = episode.Season; - - if (season != null) - { - episode.ParentIndexNumber = season.IndexNumber; - } - } - - if (episode.ParentIndexNumber.HasValue) - { - changed = true; - } - } - } - - return changed; - } - - public NamingOptions GetNamingOptions() - { - return GetNamingOptions(new LibraryOptions()); - } - - public NamingOptions GetNamingOptions(LibraryOptions libraryOptions) - { - var options = new ExtendedNamingOptions(); - - // These cause apps to have problems - options.AudioFileExtensions.Remove(".m3u"); - options.AudioFileExtensions.Remove(".wpl"); - - if (!libraryOptions.EnableArchiveMediaFiles) - { - options.AudioFileExtensions.Remove(".rar"); - options.AudioFileExtensions.Remove(".zip"); - } - - if (!libraryOptions.EnableArchiveMediaFiles) - { - options.VideoFileExtensions.Remove(".rar"); - options.VideoFileExtensions.Remove(".zip"); - } - - return options; - } - - public ItemLookupInfo ParseName(string name) - { - var resolver = new VideoResolver(GetNamingOptions(), new PatternsLogger()); - - var result = resolver.CleanDateTime(name); - var cleanName = resolver.CleanString(result.Name); - - return new ItemLookupInfo - { - Name = cleanName.Name, - Year = result.Year - }; - } - - public IEnumerable<Video> FindTrailers(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) - { - var files = owner.DetectIsInMixedFolder() ? new List<FileSystemMetadata>() : fileSystemChildren.Where(i => i.IsDirectory) - .Where(i => string.Equals(i.Name, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase)) - .SelectMany(i => _fileSystem.GetFiles(i.FullName, false)) - .ToList(); - - var videoListResolver = new VideoListResolver(GetNamingOptions(), new PatternsLogger()); - - var videos = videoListResolver.Resolve(fileSystemChildren.Select(i => new FileMetadata - { - Id = i.FullName, - IsFolder = (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory - - }).ToList()); - - var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files.First().Path, StringComparison.OrdinalIgnoreCase)); - - if (currentVideo != null) - { - files.AddRange(currentVideo.Extras.Where(i => string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase)).Select(i => _fileSystem.GetFileInfo(i.Path))); - } - - var resolvers = new IItemResolver[] - { - new GenericVideoResolver<Trailer>(this) - }; - - return ResolvePaths(files, directoryService, null, new LibraryOptions(), null, resolvers) - .OfType<Trailer>() - .Select(video => - { - // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = GetItemById(video.Id) as Trailer; - - if (dbItem != null) - { - video = dbItem; - } - - video.ExtraType = ExtraType.Trailer; - video.TrailerTypes = new List<TrailerType> { TrailerType.LocalTrailer }; - - return video; - - // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path).ToList(); - } - - public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) - { - var files = fileSystemChildren.Where(i => i.IsDirectory) - .Where(i => string.Equals(i.Name, "extras", StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, "specials", StringComparison.OrdinalIgnoreCase)) - .SelectMany(i => _fileSystem.GetFiles(i.FullName, false)) - .ToList(); - - var videoListResolver = new VideoListResolver(GetNamingOptions(), new PatternsLogger()); - - var videos = videoListResolver.Resolve(fileSystemChildren.Select(i => new FileMetadata - { - Id = i.FullName, - IsFolder = (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory - - }).ToList()); - - var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files.First().Path, StringComparison.OrdinalIgnoreCase)); - - if (currentVideo != null) - { - files.AddRange(currentVideo.Extras.Where(i => !string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase)).Select(i => _fileSystem.GetFileInfo(i.Path))); - } - - return ResolvePaths(files, directoryService, null, new LibraryOptions(), null) - .OfType<Video>() - .Select(video => - { - // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = GetItemById(video.Id) as Video; - - if (dbItem != null) - { - video = dbItem; - } - - SetExtraTypeFromFilename(video); - - return video; - - // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path).ToList(); - } - - public string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem) - { - if (ownerItem != null) - { - var libraryOptions = GetLibraryOptions(ownerItem); - if (libraryOptions != null) - { - foreach (var pathInfo in libraryOptions.PathInfos) - { - if (string.IsNullOrWhiteSpace(pathInfo.NetworkPath)) - { - continue; - } - - var substitutionResult = SubstitutePathInternal(path, pathInfo.Path, pathInfo.NetworkPath); - if (substitutionResult.Item2) - { - return substitutionResult.Item1; - } - } - } - } - - var metadataPath = ConfigurationManager.Configuration.MetadataPath; - var metadataNetworkPath = ConfigurationManager.Configuration.MetadataNetworkPath; - - if (!string.IsNullOrWhiteSpace(metadataPath) && !string.IsNullOrWhiteSpace(metadataNetworkPath)) - { - var metadataSubstitutionResult = SubstitutePathInternal(path, metadataPath, metadataNetworkPath); - if (metadataSubstitutionResult.Item2) - { - return metadataSubstitutionResult.Item1; - } - } - - foreach (var map in ConfigurationManager.Configuration.PathSubstitutions) - { - var substitutionResult = SubstitutePathInternal(path, map.From, map.To); - if (substitutionResult.Item2) - { - return substitutionResult.Item1; - } - } - - return path; - } - - public string SubstitutePath(string path, string from, string to) - { - return SubstitutePathInternal(path, from, to).Item1; - } - - private Tuple<string, bool> SubstitutePathInternal(string path, string from, string to) - { - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException("path"); - } - if (string.IsNullOrWhiteSpace(from)) - { - throw new ArgumentNullException("from"); - } - if (string.IsNullOrWhiteSpace(to)) - { - throw new ArgumentNullException("to"); - } - - from = from.Trim(); - to = to.Trim(); - - var newPath = path.Replace(from, to, StringComparison.OrdinalIgnoreCase); - var changed = false; - - if (!string.Equals(newPath, path)) - { - if (to.IndexOf('/') != -1) - { - newPath = newPath.Replace('\\', '/'); - } - else - { - newPath = newPath.Replace('/', '\\'); - } - - changed = true; - } - - return new Tuple<string, bool>(newPath, changed); - } - - private void SetExtraTypeFromFilename(Video item) - { - var resolver = new ExtraResolver(GetNamingOptions(), new PatternsLogger(), new RegexProvider()); - - var result = resolver.GetExtraInfo(item.Path); - - if (string.Equals(result.ExtraType, "deletedscene", StringComparison.OrdinalIgnoreCase)) - { - item.ExtraType = ExtraType.DeletedScene; - } - else if (string.Equals(result.ExtraType, "behindthescenes", StringComparison.OrdinalIgnoreCase)) - { - item.ExtraType = ExtraType.BehindTheScenes; - } - else if (string.Equals(result.ExtraType, "interview", StringComparison.OrdinalIgnoreCase)) - { - item.ExtraType = ExtraType.Interview; - } - else if (string.Equals(result.ExtraType, "scene", StringComparison.OrdinalIgnoreCase)) - { - item.ExtraType = ExtraType.Scene; - } - else if (string.Equals(result.ExtraType, "sample", StringComparison.OrdinalIgnoreCase)) - { - item.ExtraType = ExtraType.Sample; - } - else - { - item.ExtraType = ExtraType.Clip; - } - } - - public List<PersonInfo> GetPeople(InternalPeopleQuery query) - { - return ItemRepository.GetPeople(query); - } - - public List<PersonInfo> GetPeople(BaseItem item) - { - if (item.SupportsPeople) - { - var people = GetPeople(new InternalPeopleQuery - { - ItemId = item.Id - }); - - if (people.Count > 0) - { - return people; - } - } - - return new List<PersonInfo>(); - } - - public List<Person> GetPeopleItems(InternalPeopleQuery query) - { - return ItemRepository.GetPeopleNames(query).Select(i => - { - try - { - return GetPerson(i); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting person", ex); - return null; - } - - }).Where(i => i != null).ToList(); - } - - public List<string> GetPeopleNames(InternalPeopleQuery query) - { - return ItemRepository.GetPeopleNames(query); - } - - public Task UpdatePeople(BaseItem item, List<PersonInfo> people) - { - if (!item.SupportsPeople) - { - return Task.FromResult(true); - } - - return ItemRepository.UpdatePeople(item.Id, people); - } - - private readonly SemaphoreSlim _dynamicImageResourcePool = new SemaphoreSlim(1, 1); - public async Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex) - { - foreach (var url in image.Path.Split('|')) - { - try - { - _logger.Debug("ConvertImageToLocal item {0} - image url: {1}", item.Id, url); - - await _providerManagerFactory().SaveImage(item, url, _dynamicImageResourcePool, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false); - - var newImage = item.GetImageInfo(image.Type, imageIndex); - - if (newImage != null) - { - newImage.IsPlaceholder = image.IsPlaceholder; - } - - await item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); - - return item.GetImageInfo(image.Type, imageIndex); - } - catch (HttpException ex) - { - if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound) - { - continue; - } - throw; - } - } - - // Remove this image to prevent it from retrying over and over - item.RemoveImage(image); - await item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); - - throw new InvalidOperationException(); - } - - public void AddVirtualFolder(string name, string collectionType, LibraryOptions options, bool refreshLibrary) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - - name = _fileSystem.GetValidFilename(name); - - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - - var virtualFolderPath = Path.Combine(rootFolderPath, name); - while (_fileSystem.DirectoryExists(virtualFolderPath)) - { - name += "1"; - virtualFolderPath = Path.Combine(rootFolderPath, name); - } - - var mediaPathInfos = options.PathInfos; - if (mediaPathInfos != null) - { - var invalidpath = mediaPathInfos.FirstOrDefault(i => !_fileSystem.DirectoryExists(i.Path)); - if (invalidpath != null) - { - throw new ArgumentException("The specified path does not exist: " + invalidpath.Path + "."); - } - } - - _libraryMonitorFactory().Stop(); - - try - { - _fileSystem.CreateDirectory(virtualFolderPath); - - if (!string.IsNullOrEmpty(collectionType)) - { - var path = Path.Combine(virtualFolderPath, collectionType + ".collection"); - - using (File.Create(path)) - { - - } - } - - CollectionFolder.SaveLibraryOptions(virtualFolderPath, options); - - if (mediaPathInfos != null) - { - foreach (var path in mediaPathInfos) - { - AddMediaPathInternal(name, path, false); - } - } - } - finally - { - Task.Run(() => - { - // No need to start if scanning the library because it will handle it - if (refreshLibrary) - { - ValidateMediaLibrary(new Progress<double>(), CancellationToken.None); - } - else - { - // Need to add a delay here or directory watchers may still pick up the changes - var task = Task.Delay(1000); - // Have to block here to allow exceptions to bubble - Task.WaitAll(task); - - _libraryMonitorFactory().Start(); - } - }); - } - } - - private bool ValidateNetworkPath(string path) - { - if (Environment.OSVersion.Platform == PlatformID.Win32NT) - { - // We can't validate protocol-based paths, so just allow them - if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) == -1) - { - return Directory.Exists(path); - } - } - - // Without native support for unc, we cannot validate this when running under mono - return true; - } - - private const string ShortcutFileExtension = ".mblink"; - private const string ShortcutFileSearch = "*" + ShortcutFileExtension; - public void AddMediaPath(string virtualFolderName, MediaPathInfo pathInfo) - { - AddMediaPathInternal(virtualFolderName, pathInfo, true); - } - - private void AddMediaPathInternal(string virtualFolderName, MediaPathInfo pathInfo, bool saveLibraryOptions) - { - if (pathInfo == null) - { - throw new ArgumentNullException("path"); - } - - var path = pathInfo.Path; - - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException("path"); - } - - if (!_fileSystem.DirectoryExists(path)) - { - throw new DirectoryNotFoundException("The path does not exist."); - } - - if (!string.IsNullOrWhiteSpace(pathInfo.NetworkPath) && !ValidateNetworkPath(pathInfo.NetworkPath)) - { - throw new DirectoryNotFoundException("The network path does not exist."); - } - - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); - - var shortcutFilename = _fileSystem.GetFileNameWithoutExtension(path); - - var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); - - while (_fileSystem.FileExists(lnk)) - { - shortcutFilename += "1"; - lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension); - } - - _fileSystem.CreateShortcut(lnk, path); - - RemoveContentTypeOverrides(path); - - if (saveLibraryOptions) - { - var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath); - - var list = libraryOptions.PathInfos.ToList(); - list.Add(pathInfo); - libraryOptions.PathInfos = list.ToArray(); - - SyncLibraryOptionsToLocations(virtualFolderPath, libraryOptions); - - CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions); - } - } - - public void UpdateMediaPath(string virtualFolderName, MediaPathInfo pathInfo) - { - if (pathInfo == null) - { - throw new ArgumentNullException("path"); - } - - if (!string.IsNullOrWhiteSpace(pathInfo.NetworkPath) && !ValidateNetworkPath(pathInfo.NetworkPath)) - { - throw new DirectoryNotFoundException("The network path does not exist."); - } - - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); - - var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath); - - SyncLibraryOptionsToLocations(virtualFolderPath, libraryOptions); - - var list = libraryOptions.PathInfos.ToList(); - foreach (var originalPathInfo in list) - { - if (string.Equals(pathInfo.Path, originalPathInfo.Path, StringComparison.Ordinal)) - { - originalPathInfo.NetworkPath = pathInfo.NetworkPath; - break; - } - } - - libraryOptions.PathInfos = list.ToArray(); - - CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions); - } - - private void SyncLibraryOptionsToLocations(string virtualFolderPath, LibraryOptions options) - { - var topLibraryFolders = GetUserRootFolder().Children.ToList(); - var info = GetVirtualFolderInfo(virtualFolderPath, topLibraryFolders); - - if (info.Locations.Count > 0 && info.Locations.Count != options.PathInfos.Length) - { - var list = options.PathInfos.ToList(); - - foreach (var location in info.Locations) - { - if (!list.Any(i => string.Equals(i.Path, location, StringComparison.Ordinal))) - { - list.Add(new MediaPathInfo - { - Path = location - }); - } - } - - options.PathInfos = list.ToArray(); - } - } - - public void RemoveVirtualFolder(string name, bool refreshLibrary) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - - var path = Path.Combine(rootFolderPath, name); - - if (!_fileSystem.DirectoryExists(path)) - { - throw new DirectoryNotFoundException("The media folder does not exist"); - } - - _libraryMonitorFactory().Stop(); - - try - { - _fileSystem.DeleteDirectory(path, true); - } - finally - { - Task.Run(() => - { - // No need to start if scanning the library because it will handle it - if (refreshLibrary) - { - ValidateMediaLibrary(new Progress<double>(), CancellationToken.None); - } - else - { - // Need to add a delay here or directory watchers may still pick up the changes - var task = Task.Delay(1000); - // Have to block here to allow exceptions to bubble - Task.WaitAll(task); - - _libraryMonitorFactory().Start(); - } - }); - } - } - - private void RemoveContentTypeOverrides(string path) - { - if (string.IsNullOrWhiteSpace(path)) - { - throw new ArgumentNullException("path"); - } - - var removeList = new List<NameValuePair>(); - - foreach (var contentType in ConfigurationManager.Configuration.ContentTypes) - { - if (string.Equals(path, contentType.Name, StringComparison.OrdinalIgnoreCase) - || _fileSystem.ContainsSubPath(path, contentType.Name)) - { - removeList.Add(contentType); - } - } - - if (removeList.Count > 0) - { - ConfigurationManager.Configuration.ContentTypes = ConfigurationManager.Configuration.ContentTypes - .Except(removeList) - .ToArray(); - - ConfigurationManager.SaveConfiguration(); - } - } - - public void RemoveMediaPath(string virtualFolderName, string mediaPath) - { - if (string.IsNullOrWhiteSpace(mediaPath)) - { - throw new ArgumentNullException("mediaPath"); - } - - var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; - var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); - - if (!_fileSystem.DirectoryExists(virtualFolderPath)) - { - throw new DirectoryNotFoundException(string.Format("The media collection {0} does not exist", virtualFolderName)); - } - - var shortcut = Directory.EnumerateFiles(virtualFolderPath, ShortcutFileSearch, SearchOption.AllDirectories).FirstOrDefault(f => _fileSystem.ResolveShortcut(f).Equals(mediaPath, StringComparison.OrdinalIgnoreCase)); - - if (!string.IsNullOrEmpty(shortcut)) - { - _fileSystem.DeleteFile(shortcut); - } - - var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath); - - libraryOptions.PathInfos = libraryOptions - .PathInfos - .Where(i => !string.Equals(i.Path, mediaPath, StringComparison.Ordinal)) - .ToArray(); - - CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs deleted file mode 100644 index 78107b82d1..0000000000 --- a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs +++ /dev/null @@ -1,102 +0,0 @@ -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; - -namespace MediaBrowser.Server.Implementations.Library -{ - public class LocalTrailerPostScanTask : ILibraryPostScanTask - { - private readonly ILibraryManager _libraryManager; - private readonly IChannelManager _channelManager; - - public LocalTrailerPostScanTask(ILibraryManager libraryManager, IChannelManager channelManager) - { - _libraryManager = libraryManager; - _channelManager = channelManager; - } - - public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - var items = _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(BoxSet).Name, typeof(Game).Name, typeof(Movie).Name, typeof(Series).Name }, - Recursive = true - - }).OfType<IHasTrailers>().ToList(); - - var trailerTypes = Enum.GetNames(typeof(TrailerType)) - .Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true)) - .Except(new[] { TrailerType.LocalTrailer }) - .ToArray(); - - var trailers = _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Trailer).Name }, - TrailerTypes = trailerTypes, - Recursive = true - - }).ToArray(); - - var numComplete = 0; - - foreach (var item in items) - { - cancellationToken.ThrowIfCancellationRequested(); - - await AssignTrailers(item, trailers).ConfigureAwait(false); - - numComplete++; - double percent = numComplete; - percent /= items.Count; - progress.Report(percent * 100); - } - - progress.Report(100); - } - - private async Task AssignTrailers(IHasTrailers item, BaseItem[] channelTrailers) - { - if (item is Game) - { - return; - } - - var imdbId = item.GetProviderId(MetadataProviders.Imdb); - var tmdbId = item.GetProviderId(MetadataProviders.Tmdb); - - var trailers = channelTrailers.Where(i => - { - if (!string.IsNullOrWhiteSpace(imdbId) && - string.Equals(imdbId, i.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase)) - { - return true; - } - if (!string.IsNullOrWhiteSpace(tmdbId) && - string.Equals(tmdbId, i.GetProviderId(MetadataProviders.Tmdb), StringComparison.OrdinalIgnoreCase)) - { - return true; - } - return false; - }); - - var trailerIds = trailers.Select(i => i.Id) - .ToList(); - - if (!trailerIds.SequenceEqual(item.RemoteTrailerIds)) - { - item.RemoteTrailerIds = trailerIds; - - var baseItem = (BaseItem)item; - await baseItem.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None) - .ConfigureAwait(false); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs deleted file mode 100644 index e7bfe56f2e..0000000000 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ /dev/null @@ -1,646 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Model.Configuration; - -namespace MediaBrowser.Server.Implementations.Library -{ - public class MediaSourceManager : IMediaSourceManager, IDisposable - { - private readonly IItemRepository _itemRepo; - private readonly IUserManager _userManager; - private readonly ILibraryManager _libraryManager; - private readonly IJsonSerializer _jsonSerializer; - private readonly IFileSystem _fileSystem; - - private IMediaSourceProvider[] _providers; - private readonly ILogger _logger; - private readonly IUserDataManager _userDataManager; - - public MediaSourceManager(IItemRepository itemRepo, IUserManager userManager, ILibraryManager libraryManager, ILogger logger, IJsonSerializer jsonSerializer, IFileSystem fileSystem, IUserDataManager userDataManager) - { - _itemRepo = itemRepo; - _userManager = userManager; - _libraryManager = libraryManager; - _logger = logger; - _jsonSerializer = jsonSerializer; - _fileSystem = fileSystem; - _userDataManager = userDataManager; - } - - public void AddParts(IEnumerable<IMediaSourceProvider> providers) - { - _providers = providers.ToArray(); - } - - public IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query) - { - var list = _itemRepo.GetMediaStreams(query) - .ToList(); - - foreach (var stream in list) - { - stream.SupportsExternalStream = StreamSupportsExternalStream(stream); - } - - return list; - } - - private bool StreamSupportsExternalStream(MediaStream stream) - { - if (stream.IsExternal) - { - return true; - } - - if (stream.IsTextSubtitleStream) - { - return true; - } - - return false; - } - - public IEnumerable<MediaStream> GetMediaStreams(string mediaSourceId) - { - var list = GetMediaStreams(new MediaStreamQuery - { - ItemId = new Guid(mediaSourceId) - }); - - return GetMediaStreamsForItem(list); - } - - public IEnumerable<MediaStream> GetMediaStreams(Guid itemId) - { - var list = GetMediaStreams(new MediaStreamQuery - { - ItemId = itemId - }); - - return GetMediaStreamsForItem(list); - } - - private IEnumerable<MediaStream> GetMediaStreamsForItem(IEnumerable<MediaStream> streams) - { - var list = streams.ToList(); - - var subtitleStreams = list - .Where(i => i.Type == MediaStreamType.Subtitle) - .ToList(); - - if (subtitleStreams.Count > 0) - { - foreach (var subStream in subtitleStreams) - { - subStream.SupportsExternalStream = StreamSupportsExternalStream(subStream); - } - } - - return list; - } - - public async Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, string[] supportedLiveMediaTypes, CancellationToken cancellationToken) - { - var item = _libraryManager.GetItemById(id); - - var hasMediaSources = (IHasMediaSources)item; - User user = null; - - if (!string.IsNullOrWhiteSpace(userId)) - { - user = _userManager.GetUserById(userId); - } - - var mediaSources = GetStaticMediaSources(hasMediaSources, enablePathSubstitution, user); - var dynamicMediaSources = await GetDynamicMediaSources(hasMediaSources, cancellationToken).ConfigureAwait(false); - - var list = new List<MediaSourceInfo>(); - - list.AddRange(mediaSources); - - foreach (var source in dynamicMediaSources) - { - if (user != null) - { - SetUserProperties(hasMediaSources, source, user); - } - if (source.Protocol == MediaProtocol.File) - { - // TODO: Path substitution - if (!_fileSystem.FileExists(source.Path)) - { - source.SupportsDirectStream = false; - } - } - else if (source.Protocol == MediaProtocol.Http) - { - // TODO: Allow this when the source is plain http, e.g. not HLS or Mpeg Dash - source.SupportsDirectStream = false; - } - else - { - source.SupportsDirectStream = false; - } - - list.Add(source); - } - - foreach (var source in list) - { - if (user != null) - { - if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)) - { - if (!user.Policy.EnableAudioPlaybackTranscoding) - { - source.SupportsTranscoding = false; - } - } - } - } - - return SortMediaSources(list).Where(i => i.Type != MediaSourceType.Placeholder); - } - - private async Task<IEnumerable<MediaSourceInfo>> GetDynamicMediaSources(IHasMediaSources item, CancellationToken cancellationToken) - { - var tasks = _providers.Select(i => GetDynamicMediaSources(item, i, cancellationToken)); - var results = await Task.WhenAll(tasks).ConfigureAwait(false); - - return results.SelectMany(i => i.ToList()); - } - - private async Task<IEnumerable<MediaSourceInfo>> GetDynamicMediaSources(IHasMediaSources item, IMediaSourceProvider provider, CancellationToken cancellationToken) - { - try - { - var sources = await provider.GetMediaSources(item, cancellationToken).ConfigureAwait(false); - var list = sources.ToList(); - - foreach (var mediaSource in list) - { - SetKeyProperties(provider, mediaSource); - } - - return list; - } - catch (Exception ex) - { - _logger.ErrorException("Error getting media sources", ex); - return new List<MediaSourceInfo>(); - } - } - - private void SetKeyProperties(IMediaSourceProvider provider, MediaSourceInfo mediaSource) - { - var prefix = provider.GetType().FullName.GetMD5().ToString("N") + LiveStreamIdDelimeter; - - if (!string.IsNullOrWhiteSpace(mediaSource.OpenToken) && !mediaSource.OpenToken.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) - { - mediaSource.OpenToken = prefix + mediaSource.OpenToken; - } - - if (!string.IsNullOrWhiteSpace(mediaSource.LiveStreamId) && !mediaSource.LiveStreamId.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) - { - mediaSource.LiveStreamId = prefix + mediaSource.LiveStreamId; - } - } - - public async Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, string liveStreamId, bool enablePathSubstitution, CancellationToken cancellationToken) - { - if (!string.IsNullOrWhiteSpace(liveStreamId)) - { - return await GetLiveStream(liveStreamId, cancellationToken).ConfigureAwait(false); - } - //await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - - //try - //{ - // var stream = _openStreams.Values.FirstOrDefault(i => string.Equals(i.MediaSource.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); - - // if (stream != null) - // { - // return stream.MediaSource; - // } - //} - //finally - //{ - // _liveStreamSemaphore.Release(); - //} - - var sources = await GetPlayackMediaSources(item.Id.ToString("N"), null, enablePathSubstitution, new[] { MediaType.Audio, MediaType.Video }, - CancellationToken.None).ConfigureAwait(false); - - return sources.FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); - } - - public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null) - { - if (item == null) - { - throw new ArgumentNullException("item"); - } - - if (!(item is Video)) - { - return item.GetMediaSources(enablePathSubstitution); - } - - var sources = item.GetMediaSources(enablePathSubstitution).ToList(); - - if (user != null) - { - foreach (var source in sources) - { - SetUserProperties(item, source, user); - } - } - - return sources; - } - - private void SetUserProperties(IHasUserData item, MediaSourceInfo source, User user) - { - var userData = item == null ? new UserItemData() : _userDataManager.GetUserData(user, item); - - var allowRememberingSelection = item == null || item.EnableRememberingTrackSelections; - - SetDefaultAudioStreamIndex(source, userData, user, allowRememberingSelection); - SetDefaultSubtitleStreamIndex(source, userData, user, allowRememberingSelection); - } - - private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) - { - if (userData.SubtitleStreamIndex.HasValue && user.Configuration.RememberSubtitleSelections && user.Configuration.SubtitleMode != SubtitlePlaybackMode.None && allowRememberingSelection) - { - var index = userData.SubtitleStreamIndex.Value; - // Make sure the saved index is still valid - if (index == -1 || source.MediaStreams.Any(i => i.Type == MediaStreamType.Subtitle && i.Index == index)) - { - source.DefaultSubtitleStreamIndex = index; - return; - } - } - - var preferredSubs = string.IsNullOrEmpty(user.Configuration.SubtitleLanguagePreference) - ? new List<string>() : new List<string> { user.Configuration.SubtitleLanguagePreference }; - - var defaultAudioIndex = source.DefaultAudioStreamIndex; - var audioLangage = defaultAudioIndex == null - ? null - : source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault(); - - source.DefaultSubtitleStreamIndex = MediaStreamSelector.GetDefaultSubtitleStreamIndex(source.MediaStreams, - preferredSubs, - user.Configuration.SubtitleMode, - audioLangage); - - MediaStreamSelector.SetSubtitleStreamScores(source.MediaStreams, preferredSubs, - user.Configuration.SubtitleMode, audioLangage); - } - - private void SetDefaultAudioStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) - { - if (userData.AudioStreamIndex.HasValue && user.Configuration.RememberAudioSelections && allowRememberingSelection) - { - var index = userData.AudioStreamIndex.Value; - // Make sure the saved index is still valid - if (source.MediaStreams.Any(i => i.Type == MediaStreamType.Audio && i.Index == index)) - { - source.DefaultAudioStreamIndex = index; - return; - } - } - - var preferredAudio = string.IsNullOrEmpty(user.Configuration.AudioLanguagePreference) - ? new string[] { } - : new[] { user.Configuration.AudioLanguagePreference }; - - source.DefaultAudioStreamIndex = MediaStreamSelector.GetDefaultAudioStreamIndex(source.MediaStreams, preferredAudio, user.Configuration.PlayDefaultAudioTrack); - } - - private IEnumerable<MediaSourceInfo> SortMediaSources(IEnumerable<MediaSourceInfo> sources) - { - return sources.OrderBy(i => - { - if (i.VideoType.HasValue && i.VideoType.Value == VideoType.VideoFile) - { - return 0; - } - - return 1; - - }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0) - .ThenByDescending(i => - { - var stream = i.VideoStream; - - return stream == null || stream.Width == null ? 0 : stream.Width.Value; - }) - .ToList(); - } - - private readonly Dictionary<string, LiveStreamInfo> _openStreams = new Dictionary<string, LiveStreamInfo>(StringComparer.OrdinalIgnoreCase); - private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1); - - public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken) - { - await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - var tuple = GetProvider(request.OpenToken); - var provider = tuple.Item1; - - var mediaSourceTuple = await provider.OpenMediaSource(tuple.Item2, cancellationToken).ConfigureAwait(false); - - var mediaSource = mediaSourceTuple.Item1; - - if (string.IsNullOrWhiteSpace(mediaSource.LiveStreamId)) - { - throw new InvalidOperationException(string.Format("{0} returned null LiveStreamId", provider.GetType().Name)); - } - - SetKeyProperties(provider, mediaSource); - - var info = new LiveStreamInfo - { - Date = DateTime.UtcNow, - EnableCloseTimer = enableAutoClose, - Id = mediaSource.LiveStreamId, - MediaSource = mediaSource, - DirectStreamProvider = mediaSourceTuple.Item2 - }; - - _openStreams[mediaSource.LiveStreamId] = info; - - if (enableAutoClose) - { - StartCloseTimer(); - } - - var json = _jsonSerializer.SerializeToString(mediaSource); - _logger.Debug("Live stream opened: " + json); - var clone = _jsonSerializer.DeserializeFromString<MediaSourceInfo>(json); - - if (!string.IsNullOrWhiteSpace(request.UserId)) - { - var user = _userManager.GetUserById(request.UserId); - var item = string.IsNullOrWhiteSpace(request.ItemId) - ? null - : _libraryManager.GetItemById(request.ItemId); - SetUserProperties(item, clone, user); - } - - return new LiveStreamResponse - { - MediaSource = clone - }; - } - finally - { - _liveStreamSemaphore.Release(); - } - } - - public async Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetLiveStreamWithDirectStreamProvider(string id, CancellationToken cancellationToken) - { - if (string.IsNullOrWhiteSpace(id)) - { - throw new ArgumentNullException("id"); - } - - _logger.Debug("Getting already opened live stream {0}", id); - - await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - LiveStreamInfo info; - if (_openStreams.TryGetValue(id, out info)) - { - return new Tuple<MediaSourceInfo, IDirectStreamProvider>(info.MediaSource, info.DirectStreamProvider); - } - else - { - throw new ResourceNotFoundException(); - } - } - finally - { - _liveStreamSemaphore.Release(); - } - } - - public async Task<MediaSourceInfo> GetLiveStream(string id, CancellationToken cancellationToken) - { - var result = await GetLiveStreamWithDirectStreamProvider(id, cancellationToken).ConfigureAwait(false); - return result.Item1; - } - - public async Task PingLiveStream(string id, CancellationToken cancellationToken) - { - await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - LiveStreamInfo info; - if (_openStreams.TryGetValue(id, out info)) - { - info.Date = DateTime.UtcNow; - } - else - { - _logger.Error("Failed to ping live stream {0}", id); - } - } - finally - { - _liveStreamSemaphore.Release(); - } - } - - private async Task CloseLiveStreamWithProvider(IMediaSourceProvider provider, string streamId) - { - _logger.Info("Closing live stream {0} with provider {1}", streamId, provider.GetType().Name); - - try - { - await provider.CloseMediaSource(streamId).ConfigureAwait(false); - } - catch (NotImplementedException) - { - } - catch (Exception ex) - { - _logger.ErrorException("Error closing live stream {0}", ex, streamId); - } - } - - public async Task CloseLiveStream(string id) - { - if (string.IsNullOrWhiteSpace(id)) - { - throw new ArgumentNullException("id"); - } - - await _liveStreamSemaphore.WaitAsync().ConfigureAwait(false); - - try - { - LiveStreamInfo current; - - if (_openStreams.TryGetValue(id, out current)) - { - _openStreams.Remove(id); - current.Closed = true; - - if (current.MediaSource.RequiresClosing) - { - var tuple = GetProvider(id); - - await CloseLiveStreamWithProvider(tuple.Item1, tuple.Item2).ConfigureAwait(false); - } - - if (_openStreams.Count == 0) - { - StopCloseTimer(); - } - } - } - finally - { - _liveStreamSemaphore.Release(); - } - } - - // Do not use a pipe here because Roku http requests to the server will fail, without any explicit error message. - private const char LiveStreamIdDelimeter = '_'; - - private Tuple<IMediaSourceProvider, string> GetProvider(string key) - { - if (string.IsNullOrWhiteSpace(key)) - { - throw new ArgumentException("key"); - } - - var keys = key.Split(new[] { LiveStreamIdDelimeter }, 2); - - var provider = _providers.FirstOrDefault(i => string.Equals(i.GetType().FullName.GetMD5().ToString("N"), keys[0], StringComparison.OrdinalIgnoreCase)); - - var splitIndex = key.IndexOf(LiveStreamIdDelimeter); - var keyId = key.Substring(splitIndex + 1); - - return new Tuple<IMediaSourceProvider, string>(provider, keyId); - } - - private Timer _closeTimer; - private readonly TimeSpan _openStreamMaxAge = TimeSpan.FromSeconds(180); - - private void StartCloseTimer() - { - StopCloseTimer(); - - _closeTimer = new Timer(CloseTimerCallback, null, _openStreamMaxAge, _openStreamMaxAge); - } - - private void StopCloseTimer() - { - var timer = _closeTimer; - - if (timer != null) - { - _closeTimer = null; - timer.Dispose(); - } - } - - private async void CloseTimerCallback(object state) - { - List<LiveStreamInfo> infos; - await _liveStreamSemaphore.WaitAsync().ConfigureAwait(false); - - try - { - infos = _openStreams - .Values - .Where(i => i.EnableCloseTimer && DateTime.UtcNow - i.Date > _openStreamMaxAge) - .ToList(); - } - finally - { - _liveStreamSemaphore.Release(); - } - - foreach (var info in infos) - { - if (!info.Closed) - { - try - { - await CloseLiveStream(info.Id).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error closing media source", ex); - } - } - } - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - StopCloseTimer(); - Dispose(true); - } - - private readonly object _disposeLock = new object(); - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - lock (_disposeLock) - { - foreach (var key in _openStreams.Keys.ToList()) - { - var task = CloseLiveStream(key); - - Task.WaitAll(task); - } - } - } - } - - private class LiveStreamInfo - { - public DateTime Date; - public bool EnableCloseTimer; - public string Id; - public bool Closed; - public MediaSourceInfo MediaSource; - public IDirectStreamProvider DirectStreamProvider; - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Library/MusicManager.cs b/MediaBrowser.Server.Implementations/Library/MusicManager.cs deleted file mode 100644 index 3ff4348981..0000000000 --- a/MediaBrowser.Server.Implementations/Library/MusicManager.cs +++ /dev/null @@ -1,157 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Playlists; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MediaBrowser.Server.Implementations.Library -{ - public class MusicManager : IMusicManager - { - private readonly ILibraryManager _libraryManager; - - public MusicManager(ILibraryManager libraryManager) - { - _libraryManager = libraryManager; - } - - public IEnumerable<Audio> GetInstantMixFromSong(Audio item, User user) - { - var list = new List<Audio> - { - item - }; - - return list.Concat(GetInstantMixFromGenres(item.Genres, user)); - } - - public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist artist, User user) - { - var genres = user.RootFolder - .GetRecursiveChildren(user, new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Audio).Name } - }) - .Cast<Audio>() - .Where(i => i.HasAnyArtist(artist.Name)) - .SelectMany(i => i.Genres) - .Concat(artist.Genres) - .Distinct(StringComparer.OrdinalIgnoreCase); - - return GetInstantMixFromGenres(genres, user); - } - - public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user) - { - var genres = item - .GetRecursiveChildren(user, new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Audio).Name } - }) - .Cast<Audio>() - .SelectMany(i => i.Genres) - .Concat(item.Genres) - .DistinctNames(); - - return GetInstantMixFromGenres(genres, user); - } - - public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user) - { - var genres = item - .GetRecursiveChildren(user, new InternalItemsQuery(user) - { - IncludeItemTypes = new[] {typeof(Audio).Name} - }) - .Cast<Audio>() - .SelectMany(i => i.Genres) - .Concat(item.Genres) - .DistinctNames(); - - return GetInstantMixFromGenres(genres, user); - } - - public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user) - { - var genres = item - .GetRecursiveChildren(user, new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Audio).Name } - }) - .Cast<Audio>() - .SelectMany(i => i.Genres) - .Concat(item.Genres) - .DistinctNames(); - - return GetInstantMixFromGenres(genres, user); - } - - public IEnumerable<Audio> GetInstantMixFromGenres(IEnumerable<string> genres, User user) - { - var genreList = genres.ToList(); - - var inputItems = _libraryManager.GetItemList(new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Audio).Name }, - - Genres = genreList.ToArray() - - }); - - var genresDictionary = genreList.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); - - 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) - .OrderBy(i => Guid.NewGuid()); - } - - public IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user) - { - var genre = item as MusicGenre; - if (genre != null) - { - return GetInstantMixFromGenres(new[] { item.Name }, user); - } - - var playlist = item as Playlist; - if (playlist != null) - { - return GetInstantMixFromPlaylist(playlist, user); - } - - var album = item as MusicAlbum; - if (album != null) - { - return GetInstantMixFromAlbum(album, user); - } - - var artist = item as MusicArtist; - if (artist != null) - { - return GetInstantMixFromArtist(artist, user); - } - - var song = item as Audio; - if (song != null) - { - return GetInstantMixFromSong(song, user); - } - - var folder = item as Folder; - if (folder != null) - { - return GetInstantMixFromFolder(folder, user); - } - - return new Audio[] { }; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/PathExtensions.cs b/MediaBrowser.Server.Implementations/Library/PathExtensions.cs deleted file mode 100644 index 6c0e3237e8..0000000000 --- a/MediaBrowser.Server.Implementations/Library/PathExtensions.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Text.RegularExpressions; - -namespace MediaBrowser.Server.Implementations.Library -{ - public static class PathExtensions - { - /// <summary> - /// Gets the attribute value. - /// </summary> - /// <param name="str">The STR.</param> - /// <param name="attrib">The attrib.</param> - /// <returns>System.String.</returns> - /// <exception cref="System.ArgumentNullException">attrib</exception> - public static string GetAttributeValue(this string str, string attrib) - { - if (string.IsNullOrEmpty(str)) - { - throw new ArgumentNullException("str"); - } - - if (string.IsNullOrEmpty(attrib)) - { - throw new ArgumentNullException("attrib"); - } - - string srch = "[" + attrib + "="; - int start = str.IndexOf(srch, StringComparison.OrdinalIgnoreCase); - if (start > -1) - { - start += srch.Length; - int end = str.IndexOf(']', start); - return str.Substring(start, end - start); - } - // for imdbid we also accept pattern matching - if (string.Equals(attrib, "imdbid", StringComparison.OrdinalIgnoreCase)) - { - var m = Regex.Match(str, "tt\\d{7}", RegexOptions.IgnoreCase); - return m.Success ? m.Value : null; - } - - return null; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/ResolverHelper.cs b/MediaBrowser.Server.Implementations/Library/ResolverHelper.cs deleted file mode 100644 index 9f949db92a..0000000000 --- a/MediaBrowser.Server.Implementations/Library/ResolverHelper.cs +++ /dev/null @@ -1,181 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using System; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Library -{ - /// <summary> - /// Class ResolverHelper - /// </summary> - public static class ResolverHelper - { - /// <summary> - /// Sets the initial item values. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="parent">The parent.</param> - /// <param name="fileSystem">The file system.</param> - /// <param name="libraryManager">The library manager.</param> - /// <param name="directoryService">The directory service.</param> - /// <exception cref="System.ArgumentException">Item must have a path</exception> - public static void SetInitialItemValues(BaseItem item, Folder parent, IFileSystem fileSystem, ILibraryManager libraryManager, IDirectoryService directoryService) - { - // This version of the below method has no ItemResolveArgs, so we have to require the path already being set - if (string.IsNullOrWhiteSpace(item.Path)) - { - throw new ArgumentException("Item must have a Path"); - } - - // If the resolver didn't specify this - if (parent != null) - { - item.SetParent(parent); - } - - item.Id = libraryManager.GetNewItemId(item.Path, item.GetType()); - - item.IsLocked = item.Path.IndexOf("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) != -1 || - item.GetParents().Any(i => i.IsLocked); - - // Make sure DateCreated and DateModified have values - var fileInfo = directoryService.GetFile(item.Path); - SetDateCreated(item, fileSystem, fileInfo); - - EnsureName(item, fileInfo); - } - - /// <summary> - /// Sets the initial item values. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="args">The args.</param> - /// <param name="fileSystem">The file system.</param> - /// <param name="libraryManager">The library manager.</param> - public static void SetInitialItemValues(BaseItem item, ItemResolveArgs args, IFileSystem fileSystem, ILibraryManager libraryManager) - { - // If the resolver didn't specify this - if (string.IsNullOrEmpty(item.Path)) - { - item.Path = args.Path; - } - - // If the resolver didn't specify this - if (args.Parent != null) - { - item.SetParent(args.Parent); - } - - item.Id = libraryManager.GetNewItemId(item.Path, item.GetType()); - - // Make sure the item has a name - EnsureName(item, args.FileInfo); - - item.IsLocked = item.Path.IndexOf("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) != -1 || - item.GetParents().Any(i => i.IsLocked); - - // Make sure DateCreated and DateModified have values - EnsureDates(fileSystem, item, args); - } - - /// <summary> - /// Ensures the name. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="fileInfo">The file information.</param> - private static void EnsureName(BaseItem item, FileSystemMetadata fileInfo) - { - // If the subclass didn't supply a name, add it here - if (string.IsNullOrEmpty(item.Name) && !string.IsNullOrEmpty(item.Path)) - { - item.Name = GetDisplayName(fileInfo.Name, fileInfo.IsDirectory); - } - } - - /// <summary> - /// Gets the display name. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="isDirectory">if set to <c>true</c> [is directory].</param> - /// <returns>System.String.</returns> - private static string GetDisplayName(string path, bool isDirectory) - { - return isDirectory ? Path.GetFileName(path) : Path.GetFileNameWithoutExtension(path); - } - - /// <summary> - /// The MB name regex - /// </summary> - private static readonly Regex MbNameRegex = new Regex(@"(\[.*?\])", RegexOptions.Compiled); - - internal static string StripBrackets(string inputString) - { - var output = MbNameRegex.Replace(inputString, string.Empty).Trim(); - return Regex.Replace(output, @"\s+", " "); - } - - /// <summary> - /// Ensures DateCreated and DateModified have values - /// </summary> - /// <param name="fileSystem">The file system.</param> - /// <param name="item">The item.</param> - /// <param name="args">The args.</param> - private static void EnsureDates(IFileSystem fileSystem, BaseItem item, ItemResolveArgs args) - { - if (fileSystem == null) - { - throw new ArgumentNullException("fileSystem"); - } - if (item == null) - { - throw new ArgumentNullException("item"); - } - if (args == null) - { - throw new ArgumentNullException("args"); - } - - // See if a different path came out of the resolver than what went in - if (!string.Equals(args.Path, item.Path, StringComparison.OrdinalIgnoreCase)) - { - var childData = args.IsDirectory ? args.GetFileSystemEntryByPath(item.Path) : null; - - if (childData != null) - { - SetDateCreated(item, fileSystem, childData); - } - else - { - var fileData = fileSystem.GetFileSystemInfo(item.Path); - - if (fileData.Exists) - { - SetDateCreated(item, fileSystem, fileData); - } - } - } - else - { - SetDateCreated(item, fileSystem, args.FileInfo); - } - } - - private static void SetDateCreated(BaseItem item, IFileSystem fileSystem, FileSystemMetadata info) - { - var config = BaseItem.ConfigurationManager.GetMetadataConfiguration(); - - if (config.UseFileCreationTimeForDateAdded) - { - item.DateCreated = fileSystem.GetCreationTimeUtc(info); - } - else - { - item.DateCreated = DateTime.UtcNow; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs deleted file mode 100644 index 039a17100a..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs +++ /dev/null @@ -1,68 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.Entities; -using System; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio -{ - /// <summary> - /// Class AudioResolver - /// </summary> - public class AudioResolver : ItemResolver<Controller.Entities.Audio.Audio> - { - private readonly ILibraryManager _libraryManager; - - public AudioResolver(ILibraryManager libraryManager) - { - _libraryManager = libraryManager; - } - - /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public override ResolverPriority Priority - { - get { return ResolverPriority.Last; } - } - - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>Entities.Audio.Audio.</returns> - protected override Controller.Entities.Audio.Audio Resolve(ItemResolveArgs args) - { - // Return audio if the path is a file and has a matching extension - - if (!args.IsDirectory) - { - var libraryOptions = args.GetLibraryOptions(); - - if (_libraryManager.IsAudioFile(args.Path, libraryOptions)) - { - var collectionType = args.GetCollectionType(); - - var isMixed = string.IsNullOrWhiteSpace(collectionType); - - // For conflicting extensions, give priority to videos - if (isMixed && _libraryManager.IsVideoFile(args.Path, libraryOptions)) - { - return null; - } - - var isStandalone = args.Parent == null; - - if (isStandalone || - string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase) || - isMixed) - { - return new Controller.Entities.Audio.Audio(); - } - } - } - - return null; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs deleted file mode 100644 index 7f35fc3ea5..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ /dev/null @@ -1,171 +0,0 @@ -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Naming.Audio; -using MediaBrowser.Server.Implementations.Logging; -using System; -using System.Collections.Generic; -using System.IO; -using CommonIO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Model.Configuration; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio -{ - /// <summary> - /// Class MusicAlbumResolver - /// </summary> - public class MusicAlbumResolver : ItemResolver<MusicAlbum> - { - private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly ILibraryManager _libraryManager; - - public MusicAlbumResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager) - { - _logger = logger; - _fileSystem = fileSystem; - _libraryManager = libraryManager; - } - - /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public override ResolverPriority Priority - { - get - { - // Behind special folder resolver - return ResolverPriority.Second; - } - } - - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>MusicAlbum.</returns> - protected override MusicAlbum Resolve(ItemResolveArgs args) - { - if (!args.IsDirectory) return null; - - // Avoid mis-identifying top folders - if (args.HasParent<MusicAlbum>()) return null; - if (args.Parent.IsRoot) return null; - - var collectionType = args.GetCollectionType(); - - var isMusicMediaFolder = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase); - - // If there's a collection type and it's not music, don't allow it. - if (!isMusicMediaFolder) - { - return null; - } - - return IsMusicAlbum(args) ? new MusicAlbum() : null; - } - - - /// <summary> - /// Determine if the supplied file data points to a music album - /// </summary> - public bool IsMusicAlbum(string path, IDirectoryService directoryService, LibraryOptions libraryOptions) - { - return ContainsMusic(directoryService.GetFileSystemEntries(path), true, directoryService, _logger, _fileSystem, libraryOptions, _libraryManager); - } - - /// <summary> - /// Determine if the supplied resolve args should be considered a music album - /// </summary> - /// <param name="args">The args.</param> - /// <returns><c>true</c> if [is music album] [the specified args]; otherwise, <c>false</c>.</returns> - private bool IsMusicAlbum(ItemResolveArgs args) - { - // Args points to an album if parent is an Artist folder or it directly contains music - if (args.IsDirectory) - { - //if (args.Parent is MusicArtist) return true; //saves us from testing children twice - if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, args.GetLibraryOptions(), _libraryManager)) return true; - } - - return false; - } - - /// <summary> - /// Determine if the supplied list contains what we should consider music - /// </summary> - private bool ContainsMusic(IEnumerable<FileSystemMetadata> list, - bool allowSubfolders, - IDirectoryService directoryService, - ILogger logger, - IFileSystem fileSystem, - LibraryOptions libraryOptions, - ILibraryManager libraryManager) - { - var discSubfolderCount = 0; - var notMultiDisc = false; - - foreach (var fileSystemInfo in list) - { - if ((fileSystemInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory) - { - if (allowSubfolders) - { - var path = fileSystemInfo.FullName; - var isMultiDisc = IsMultiDiscFolder(path, libraryOptions); - - if (isMultiDisc) - { - var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryOptions, libraryManager); - - if (hasMusic) - { - logger.Debug("Found multi-disc folder: " + path); - discSubfolderCount++; - } - } - else - { - var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryOptions, libraryManager); - - if (hasMusic) - { - // If there are folders underneath with music that are not multidisc, then this can't be a multi-disc album - notMultiDisc = true; - } - } - } - } - - var fullName = fileSystemInfo.FullName; - - if (libraryManager.IsAudioFile(fullName, libraryOptions)) - { - return true; - } - } - - if (notMultiDisc) - { - return false; - } - - return discSubfolderCount > 0; - } - - private bool IsMultiDiscFolder(string path, LibraryOptions libraryOptions) - { - var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(libraryOptions); - - var parser = new AlbumParser(namingOptions, new PatternsLogger()); - var result = parser.ParseMultiPart(path); - - return result.IsMultiPart; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs deleted file mode 100644 index 686105ddb1..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs +++ /dev/null @@ -1,92 +0,0 @@ -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using System; -using System.IO; -using System.Linq; -using CommonIO; -using MediaBrowser.Controller.Configuration; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio -{ - /// <summary> - /// Class MusicArtistResolver - /// </summary> - public class MusicArtistResolver : ItemResolver<MusicArtist> - { - private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly ILibraryManager _libraryManager; - private readonly IServerConfigurationManager _config; - - public MusicArtistResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager, IServerConfigurationManager config) - { - _logger = logger; - _fileSystem = fileSystem; - _libraryManager = libraryManager; - _config = config; - } - - /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public override ResolverPriority Priority - { - get - { - // Behind special folder resolver - return ResolverPriority.Second; - } - } - - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>MusicArtist.</returns> - protected override MusicArtist Resolve(ItemResolveArgs args) - { - if (!args.IsDirectory) return null; - - // Don't allow nested artists - if (args.HasParent<MusicArtist>() || args.HasParent<MusicAlbum>()) - { - return null; - } - - var collectionType = args.GetCollectionType(); - - var isMusicMediaFolder = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase); - - // If there's a collection type and it's not music, it can't be a series - if (!isMusicMediaFolder) - { - return null; - } - - if (args.ContainsFileSystemEntryByName("artist.nfo")) - { - return new MusicArtist(); - } - - if (_config.Configuration.EnableSimpleArtistDetection) - { - return null; - } - - // Avoid mis-identifying top folders - if (args.Parent.IsRoot) return null; - - var directoryService = args.DirectoryService; - - var albumResolver = new MusicAlbumResolver(_logger, _fileSystem, _libraryManager); - - // If we contain an album assume we are an artist folder - return args.FileSystemChildren.Where(i => (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory).Any(i => albumResolver.IsMusicAlbum(i.FullName, directoryService, args.GetLibraryOptions())) ? new MusicArtist() : null; - } - - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs deleted file mode 100644 index d0042a9907..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ /dev/null @@ -1,297 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; -using MediaBrowser.Naming.Video; -using MediaBrowser.Server.Implementations.Logging; -using System; -using System.IO; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers -{ - /// <summary> - /// Resolves a Path into a Video or Video subclass - /// </summary> - /// <typeparam name="T"></typeparam> - public abstract class BaseVideoResolver<T> : Controller.Resolvers.ItemResolver<T> - where T : Video, new() - { - protected readonly ILibraryManager LibraryManager; - - protected BaseVideoResolver(ILibraryManager libraryManager) - { - LibraryManager = libraryManager; - } - - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>`0.</returns> - protected override T Resolve(ItemResolveArgs args) - { - return ResolveVideo<T>(args, false); - } - - /// <summary> - /// Resolves the video. - /// </summary> - /// <typeparam name="TVideoType">The type of the T video type.</typeparam> - /// <param name="args">The args.</param> - /// <param name="parseName">if set to <c>true</c> [parse name].</param> - /// <returns>``0.</returns> - protected TVideoType ResolveVideo<TVideoType>(ItemResolveArgs args, bool parseName) - where TVideoType : Video, new() - { - var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); - - // If the path is a file check for a matching extensions - var parser = new Naming.Video.VideoResolver(namingOptions, new PatternsLogger()); - - if (args.IsDirectory) - { - TVideoType video = null; - VideoFileInfo videoInfo = null; - - // Loop through each child file/folder and see if we find a video - foreach (var child in args.FileSystemChildren) - { - var filename = child.Name; - - if ((child.Attributes & FileAttributes.Directory) == FileAttributes.Directory) - { - if (IsDvdDirectory(filename)) - { - videoInfo = parser.ResolveDirectory(args.Path); - - if (videoInfo == null) - { - return null; - } - - video = new TVideoType - { - Path = args.Path, - VideoType = VideoType.Dvd, - ProductionYear = videoInfo.Year - }; - break; - } - if (IsBluRayDirectory(filename)) - { - videoInfo = parser.ResolveDirectory(args.Path); - - if (videoInfo == null) - { - return null; - } - - video = new TVideoType - { - Path = args.Path, - VideoType = VideoType.BluRay, - ProductionYear = videoInfo.Year - }; - break; - } - } - else if (IsDvdFile(filename)) - { - videoInfo = parser.ResolveDirectory(args.Path); - - if (videoInfo == null) - { - return null; - } - - video = new TVideoType - { - Path = args.Path, - VideoType = VideoType.Dvd, - ProductionYear = videoInfo.Year - }; - break; - } - } - - if (video != null) - { - video.Name = parseName ? - videoInfo.Name : - Path.GetFileName(args.Path); - - Set3DFormat(video, videoInfo); - } - - return video; - } - else - { - var videoInfo = parser.Resolve(args.Path, false, false); - - if (videoInfo == null) - { - return null; - } - - if (LibraryManager.IsVideoFile(args.Path, args.GetLibraryOptions()) || videoInfo.IsStub) - { - var path = args.Path; - - var video = new TVideoType - { - Path = path, - IsInMixedFolder = true, - ProductionYear = videoInfo.Year - }; - - SetVideoType(video, videoInfo); - - video.Name = parseName ? - videoInfo.Name : - Path.GetFileNameWithoutExtension(args.Path); - - Set3DFormat(video, videoInfo); - - return video; - } - } - - return null; - } - - protected void SetVideoType(Video video, VideoFileInfo videoInfo) - { - var extension = Path.GetExtension(video.Path); - video.VideoType = string.Equals(extension, ".iso", StringComparison.OrdinalIgnoreCase) || - string.Equals(extension, ".img", StringComparison.OrdinalIgnoreCase) ? - VideoType.Iso : - VideoType.VideoFile; - - video.IsShortcut = string.Equals(extension, ".strm", StringComparison.OrdinalIgnoreCase); - video.IsPlaceHolder = videoInfo.IsStub; - - if (videoInfo.IsStub) - { - if (string.Equals(videoInfo.StubType, "dvd", StringComparison.OrdinalIgnoreCase)) - { - video.VideoType = VideoType.Dvd; - } - else if (string.Equals(videoInfo.StubType, "hddvd", StringComparison.OrdinalIgnoreCase)) - { - video.VideoType = VideoType.HdDvd; - video.IsHD = true; - } - else if (string.Equals(videoInfo.StubType, "bluray", StringComparison.OrdinalIgnoreCase)) - { - video.VideoType = VideoType.BluRay; - video.IsHD = true; - } - else if (string.Equals(videoInfo.StubType, "hdtv", StringComparison.OrdinalIgnoreCase)) - { - video.IsHD = true; - } - } - - SetIsoType(video); - } - - protected void SetIsoType(Video video) - { - if (video.VideoType == VideoType.Iso) - { - if (video.Path.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1) - { - video.IsoType = IsoType.Dvd; - } - else if (video.Path.IndexOf("bluray", StringComparison.OrdinalIgnoreCase) != -1) - { - video.IsoType = IsoType.BluRay; - } - } - } - - protected void Set3DFormat(Video video, bool is3D, string format3D) - { - if (is3D) - { - if (string.Equals(format3D, "fsbs", StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.FullSideBySide; - } - else if (string.Equals(format3D, "ftab", StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.FullTopAndBottom; - } - else if (string.Equals(format3D, "hsbs", StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.HalfSideBySide; - } - else if (string.Equals(format3D, "htab", StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.HalfTopAndBottom; - } - else if (string.Equals(format3D, "sbs", StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.HalfSideBySide; - } - else if (string.Equals(format3D, "sbs3d", StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.HalfSideBySide; - } - else if (string.Equals(format3D, "tab", StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.HalfTopAndBottom; - } - else if (string.Equals(format3D, "mvc", StringComparison.OrdinalIgnoreCase)) - { - video.Video3DFormat = Video3DFormat.MVC; - } - } - } - - protected void Set3DFormat(Video video, VideoFileInfo videoInfo) - { - Set3DFormat(video, videoInfo.Is3D, videoInfo.Format3D); - } - - protected void Set3DFormat(Video video) - { - var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); - - var resolver = new Format3DParser(namingOptions, new PatternsLogger()); - var result = resolver.Parse(video.Path); - - Set3DFormat(video, result.Is3D, result.Format3D); - } - - /// <summary> - /// Determines whether [is DVD directory] [the specified directory name]. - /// </summary> - /// <param name="directoryName">Name of the directory.</param> - /// <returns><c>true</c> if [is DVD directory] [the specified directory name]; otherwise, <c>false</c>.</returns> - protected bool IsDvdDirectory(string directoryName) - { - return string.Equals(directoryName, "video_ts", StringComparison.OrdinalIgnoreCase); - } - - /// <summary> - /// Determines whether [is DVD file] [the specified name]. - /// </summary> - /// <param name="name">The name.</param> - /// <returns><c>true</c> if [is DVD file] [the specified name]; otherwise, <c>false</c>.</returns> - protected bool IsDvdFile(string name) - { - return string.Equals(name, "video_ts.ifo", StringComparison.OrdinalIgnoreCase); - } - - /// <summary> - /// Determines whether [is blu ray directory] [the specified directory name]. - /// </summary> - /// <param name="directoryName">Name of the directory.</param> - /// <returns><c>true</c> if [is blu ray directory] [the specified directory name]; otherwise, <c>false</c>.</returns> - protected bool IsBluRayDirectory(string directoryName) - { - return string.Equals(directoryName, "bdmv", StringComparison.OrdinalIgnoreCase); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs deleted file mode 100644 index ff07c5282f..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs +++ /dev/null @@ -1,56 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Resolvers; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers -{ - /// <summary> - /// Class FolderResolver - /// </summary> - public class FolderResolver : FolderResolver<Folder> - { - /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public override ResolverPriority Priority - { - get { return ResolverPriority.Last; } - } - - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>Folder.</returns> - protected override Folder Resolve(ItemResolveArgs args) - { - if (args.IsDirectory) - { - return new Folder(); - } - - return null; - } - } - - /// <summary> - /// Class FolderResolver - /// </summary> - /// <typeparam name="TItemType">The type of the T item type.</typeparam> - public abstract class FolderResolver<TItemType> : ItemResolver<TItemType> - where TItemType : Folder, new() - { - /// <summary> - /// Sets the initial item values. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="args">The args.</param> - protected override void SetInitialItemValues(TItemType item, ItemResolveArgs args) - { - base.SetInitialItemValues(item, args); - - item.IsRoot = args.Parent == null; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/ItemResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/ItemResolver.cs deleted file mode 100644 index a03eda263a..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/ItemResolver.cs +++ /dev/null @@ -1,62 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Resolvers; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers -{ - /// <summary> - /// Class ItemResolver - /// </summary> - /// <typeparam name="T"></typeparam> - public abstract class ItemResolver<T> : IItemResolver - where T : BaseItem, new() - { - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>`0.</returns> - protected virtual T Resolve(ItemResolveArgs args) - { - return null; - } - - /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public virtual ResolverPriority Priority - { - get - { - return ResolverPriority.First; - } - } - - /// <summary> - /// Sets initial values on the newly resolved item - /// </summary> - /// <param name="item">The item.</param> - /// <param name="args">The args.</param> - protected virtual void SetInitialItemValues(T item, ItemResolveArgs args) - { - } - - /// <summary> - /// Resolves the path. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>BaseItem.</returns> - BaseItem IItemResolver.ResolvePath(ItemResolveArgs args) - { - var item = Resolve(args); - - if (item != null) - { - SetInitialItemValues(item, args); - } - - return item; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs deleted file mode 100644 index e3447afc99..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs +++ /dev/null @@ -1,77 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; -using System; -using System.IO; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies -{ - /// <summary> - /// Class BoxSetResolver - /// </summary> - public class BoxSetResolver : FolderResolver<BoxSet> - { - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>BoxSet.</returns> - protected override BoxSet Resolve(ItemResolveArgs args) - { - // It's a boxset if all of the following conditions are met: - // Is a Directory - // Contains [boxset] in the path - if (args.IsDirectory) - { - var filename = Path.GetFileName(args.Path); - - if (string.IsNullOrEmpty(filename)) - { - return null; - } - - if (filename.IndexOf("[boxset]", StringComparison.OrdinalIgnoreCase) != -1 || - args.ContainsFileSystemEntryByName("collection.xml")) - { - return new BoxSet - { - Path = args.Path, - Name = ResolverHelper.StripBrackets(Path.GetFileName(args.Path)) - }; - } - } - - return null; - } - - /// <summary> - /// Sets the initial item values. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="args">The args.</param> - protected override void SetInitialItemValues(BoxSet item, ItemResolveArgs args) - { - base.SetInitialItemValues(item, args); - - SetProviderIdFromPath(item); - } - - /// <summary> - /// Sets the provider id from path. - /// </summary> - /// <param name="item">The item.</param> - private void SetProviderIdFromPath(BaseItem item) - { - //we need to only look at the name of this actual item (not parents) - var justName = Path.GetFileName(item.Path); - - var id = justName.GetAttributeValue("tmdbid"); - - if (!string.IsNullOrEmpty(id)) - { - item.SetProviderId(MetadataProviders.Tmdb, id); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs deleted file mode 100644 index 5f41995647..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ /dev/null @@ -1,545 +0,0 @@ -using Interfaces.IO; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Naming.Video; -using MediaBrowser.Server.Implementations.Logging; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies -{ - /// <summary> - /// Class MovieResolver - /// </summary> - public class MovieResolver : BaseVideoResolver<Video>, IMultiItemResolver - { - public MovieResolver(ILibraryManager libraryManager) - : base(libraryManager) - { - } - - /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public override ResolverPriority Priority - { - get - { - // Give plugins a chance to catch iso's first - // Also since we have to loop through child files looking for videos, - // see if we can avoid some of that by letting other resolvers claim folders first - // Also run after series resolver - return ResolverPriority.Third; - } - } - - public MultiItemResolverResult ResolveMultiple(Folder parent, - List<FileSystemMetadata> files, - string collectionType, - IDirectoryService directoryService) - { - var result = ResolveMultipleInternal(parent, files, collectionType, directoryService); - - if (result != null) - { - foreach (var item in result.Items) - { - SetInitialItemValues((Video)item, null); - } - } - - return result; - } - - private MultiItemResolverResult ResolveMultipleInternal(Folder parent, - List<FileSystemMetadata> files, - string collectionType, - IDirectoryService directoryService) - { - if (IsInvalid(parent, collectionType)) - { - return null; - } - - if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) - { - return ResolveVideos<MusicVideo>(parent, files, directoryService, false); - } - - if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) || - string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase)) - { - return ResolveVideos<Video>(parent, files, directoryService, false); - } - - if (string.IsNullOrEmpty(collectionType)) - { - // Owned items should just use the plain video type - if (parent == null) - { - return ResolveVideos<Video>(parent, files, directoryService, false); - } - - if (parent is Series || parent.GetParents().OfType<Series>().Any()) - { - return null; - } - - return ResolveVideos<Movie>(parent, files, directoryService, false); - } - - if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) - { - return ResolveVideos<Movie>(parent, files, directoryService, true); - } - - return null; - } - - private MultiItemResolverResult ResolveVideos<T>(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions) - where T : Video, new() - { - var files = new List<FileSystemMetadata>(); - var videos = new List<BaseItem>(); - var leftOver = new List<FileSystemMetadata>(); - - // Loop through each child file/folder and see if we find a video - foreach (var child in fileSystemEntries) - { - if ((child.Attributes & FileAttributes.Directory) == FileAttributes.Directory) - { - leftOver.Add(child); - } - else if (IsIgnored(child.Name)) - { - - } - else - { - files.Add(child); - } - } - - var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); - - var resolver = new VideoListResolver(namingOptions, new PatternsLogger()); - var resolverResult = resolver.Resolve(files.Select(i => new FileMetadata - { - Id = i.FullName, - IsFolder = i.IsDirectory - - }).ToList(), suppportMultiEditions).ToList(); - - var result = new MultiItemResolverResult - { - ExtraFiles = leftOver, - Items = videos - }; - - var isInMixedFolder = resolverResult.Count > 1; - - foreach (var video in resolverResult) - { - var firstVideo = video.Files.First(); - - var videoItem = new T - { - Path = video.Files[0].Path, - IsInMixedFolder = isInMixedFolder, - ProductionYear = video.Year, - Name = video.Name, - AdditionalParts = video.Files.Skip(1).Select(i => i.Path).ToList(), - LocalAlternateVersions = video.AlternateVersions.Select(i => i.Path).ToList() - }; - - SetVideoType(videoItem, firstVideo); - Set3DFormat(videoItem, firstVideo); - - result.Items.Add(videoItem); - } - - result.ExtraFiles.AddRange(files.Where(i => !ContainsFile(resolverResult, i))); - - return result; - } - - private bool ContainsFile(List<VideoInfo> result, FileSystemMetadata file) - { - return result.Any(i => ContainsFile(i, file)); - } - - private bool ContainsFile(VideoInfo result, FileSystemMetadata file) - { - return result.Files.Any(i => ContainsFile(i, file)) || - result.AlternateVersions.Any(i => ContainsFile(i, file)) || - result.Extras.Any(i => ContainsFile(i, file)); - } - - private bool ContainsFile(VideoFileInfo result, FileSystemMetadata file) - { - return string.Equals(result.Path, file.FullName, StringComparison.OrdinalIgnoreCase); - } - - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>Video.</returns> - protected override Video Resolve(ItemResolveArgs args) - { - var collectionType = args.GetCollectionType(); - - if (IsInvalid(args.Parent, collectionType)) - { - return null; - } - - // Find movies with their own folders - if (args.IsDirectory) - { - var files = args.FileSystemChildren - .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) - .ToList(); - - if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) - { - return FindMovie<MusicVideo>(args.Path, args.Parent, files, args.DirectoryService, collectionType, false); - } - - if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) - { - return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType, false); - } - - if (string.IsNullOrEmpty(collectionType)) - { - // Owned items will be caught by the plain video resolver - if (args.Parent == null) - { - //return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType); - return null; - } - - if (args.HasParent<Series>()) - { - return null; - } - - { - return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType, true); - } - } - - if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) - { - return FindMovie<Movie>(args.Path, args.Parent, files, args.DirectoryService, collectionType, true); - } - - return null; - } - - // Owned items will be caught by the plain video resolver - if (args.Parent == null) - { - return null; - } - - Video item = null; - - if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) - { - item = ResolveVideo<MusicVideo>(args, false); - } - - // To find a movie file, the collection type must be movies or boxsets - else if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) - { - item = ResolveVideo<Movie>(args, true); - } - - else if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) || - string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase)) - { - item = ResolveVideo<Video>(args, false); - } - else if (string.IsNullOrEmpty(collectionType)) - { - if (args.HasParent<Series>()) - { - return null; - } - - item = ResolveVideo<Video>(args, false); - } - - if (item != null) - { - item.IsInMixedFolder = true; - } - - return item; - } - - private bool IsIgnored(string filename) - { - // Ignore samples - var sampleFilename = " " + filename.Replace(".", " ", StringComparison.OrdinalIgnoreCase) - .Replace("-", " ", StringComparison.OrdinalIgnoreCase) - .Replace("_", " ", StringComparison.OrdinalIgnoreCase) - .Replace("!", " ", StringComparison.OrdinalIgnoreCase); - - if (sampleFilename.IndexOf(" sample ", StringComparison.OrdinalIgnoreCase) != -1) - { - return true; - } - - return false; - } - - /// <summary> - /// Sets the initial item values. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="args">The args.</param> - protected override void SetInitialItemValues(Video item, ItemResolveArgs args) - { - base.SetInitialItemValues(item, args); - - SetProviderIdsFromPath(item); - } - - /// <summary> - /// Sets the provider id from path. - /// </summary> - /// <param name="item">The item.</param> - private void SetProviderIdsFromPath(Video item) - { - if (item is Movie || item is MusicVideo) - { - //we need to only look at the name of this actual item (not parents) - var justName = item.IsInMixedFolder ? Path.GetFileName(item.Path) : Path.GetFileName(item.ContainingFolderPath); - - if (!string.IsNullOrWhiteSpace(justName)) - { - // check for tmdb id - var tmdbid = justName.GetAttributeValue("tmdbid"); - - if (!string.IsNullOrWhiteSpace(tmdbid)) - { - item.SetProviderId(MetadataProviders.Tmdb, tmdbid); - } - } - - if (!string.IsNullOrWhiteSpace(item.Path)) - { - // check for imdb id - we use full media path, as we can assume, that this will match in any use case (wither id in parent dir or in file name) - var imdbid = item.Path.GetAttributeValue("imdbid"); - - if (!string.IsNullOrWhiteSpace(imdbid)) - { - item.SetProviderId(MetadataProviders.Imdb, imdbid); - } - } - } - } - - /// <summary> - /// Finds a movie based on a child file system entries - /// </summary> - /// <typeparam name="T"></typeparam> - /// <returns>Movie.</returns> - private T FindMovie<T>(string path, Folder parent, List<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, string collectionType, bool allowFilesAsFolders) - where T : Video, new() - { - var multiDiscFolders = new List<FileSystemMetadata>(); - - // Search for a folder rip - foreach (var child in fileSystemEntries) - { - var filename = child.Name; - - if ((child.Attributes & FileAttributes.Directory) == FileAttributes.Directory) - { - if (IsDvdDirectory(filename)) - { - var movie = new T - { - Path = path, - VideoType = VideoType.Dvd - }; - Set3DFormat(movie); - return movie; - } - if (IsBluRayDirectory(filename)) - { - var movie = new T - { - Path = path, - VideoType = VideoType.BluRay - }; - Set3DFormat(movie); - return movie; - } - - multiDiscFolders.Add(child); - } - else if (IsDvdFile(filename)) - { - var movie = new T - { - Path = path, - VideoType = VideoType.Dvd - }; - Set3DFormat(movie); - return movie; - } - } - - if (allowFilesAsFolders) - { - // TODO: Allow GetMultiDiscMovie in here - var supportsMultiVersion = !string.Equals(collectionType, CollectionType.HomeVideos) && - !string.Equals(collectionType, CollectionType.Photos) && - !string.Equals(collectionType, CollectionType.MusicVideos); - - var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion); - - if (result.Items.Count == 1) - { - var movie = (T)result.Items[0]; - movie.IsInMixedFolder = false; - movie.Name = Path.GetFileName(movie.ContainingFolderPath); - return movie; - } - - if (result.Items.Count == 0 && multiDiscFolders.Count > 0) - { - return GetMultiDiscMovie<T>(multiDiscFolders, directoryService); - } - } - - return null; - } - - /// <summary> - /// Gets the multi disc movie. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="multiDiscFolders">The folders.</param> - /// <param name="directoryService">The directory service.</param> - /// <returns>``0.</returns> - private T GetMultiDiscMovie<T>(List<FileSystemMetadata> multiDiscFolders, IDirectoryService directoryService) - where T : Video, new() - { - var videoTypes = new List<VideoType>(); - - var folderPaths = multiDiscFolders.Select(i => i.FullName).Where(i => - { - var subFileEntries = directoryService.GetFileSystemEntries(i) - .ToList(); - - var subfolders = subFileEntries - .Where(e => (e.Attributes & FileAttributes.Directory) == FileAttributes.Directory) - .Select(d => d.Name) - .ToList(); - - if (subfolders.Any(IsDvdDirectory)) - { - videoTypes.Add(VideoType.Dvd); - return true; - } - if (subfolders.Any(IsBluRayDirectory)) - { - videoTypes.Add(VideoType.BluRay); - return true; - } - - var subFiles = subFileEntries - .Where(e => (e.Attributes & FileAttributes.Directory) != FileAttributes.Directory) - .Select(d => d.Name); - - if (subFiles.Any(IsDvdFile)) - { - videoTypes.Add(VideoType.Dvd); - return true; - } - - return false; - - }).OrderBy(i => i).ToList(); - - // If different video types were found, don't allow this - if (videoTypes.Distinct().Count() > 1) - { - return null; - } - - if (folderPaths.Count == 0) - { - return null; - } - - var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); - var resolver = new StackResolver(namingOptions, new PatternsLogger()); - - var result = resolver.ResolveDirectories(folderPaths); - - if (result.Stacks.Count != 1) - { - return null; - } - - var returnVideo = new T - { - Path = folderPaths[0], - - AdditionalParts = folderPaths.Skip(1).ToList(), - - VideoType = videoTypes[0], - - Name = result.Stacks[0].Name - }; - - SetIsoType(returnVideo); - - return returnVideo; - } - - private bool IsInvalid(Folder parent, string collectionType) - { - if (parent != null) - { - if (parent.IsRoot) - { - return true; - } - } - - var validCollectionTypes = new[] - { - CollectionType.Movies, - CollectionType.HomeVideos, - CollectionType.MusicVideos, - CollectionType.Movies, - CollectionType.Photos - }; - - if (string.IsNullOrWhiteSpace(collectionType)) - { - return false; - } - - return !validCollectionTypes.Contains(collectionType, StringComparer.OrdinalIgnoreCase); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs deleted file mode 100644 index e7f2397800..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs +++ /dev/null @@ -1,56 +0,0 @@ -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.Entities; -using System; -using System.IO; -using System.Linq; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers -{ - public class PhotoAlbumResolver : FolderResolver<PhotoAlbum> - { - private readonly IImageProcessor _imageProcessor; - public PhotoAlbumResolver(IImageProcessor imageProcessor) - { - _imageProcessor = imageProcessor; - } - - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>Trailer.</returns> - protected override PhotoAlbum Resolve(ItemResolveArgs args) - { - // Must be an image file within a photo collection - if (args.IsDirectory && string.Equals(args.GetCollectionType(), CollectionType.Photos, StringComparison.OrdinalIgnoreCase)) - { - if (HasPhotos(args)) - { - return new PhotoAlbum - { - Path = args.Path - }; - } - } - - return null; - } - - private bool HasPhotos(ItemResolveArgs args) - { - return args.FileSystemChildren.Any(i => ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) && PhotoResolver.IsImageFile(i.FullName, _imageProcessor)); - } - - public override ResolverPriority Priority - { - get - { - // Behind special folder resolver - return ResolverPriority.Second; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PlaylistResolver.cs deleted file mode 100644 index a95739f227..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/PlaylistResolver.cs +++ /dev/null @@ -1,42 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Playlists; -using System; -using System.IO; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers -{ - public class PlaylistResolver : FolderResolver<Playlist> - { - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>BoxSet.</returns> - protected override Playlist Resolve(ItemResolveArgs args) - { - // It's a boxset if all of the following conditions are met: - // Is a Directory - // Contains [playlist] in the path - if (args.IsDirectory) - { - var filename = Path.GetFileName(args.Path); - - if (string.IsNullOrEmpty(filename)) - { - return null; - } - - if (filename.IndexOf("[playlist]", StringComparison.OrdinalIgnoreCase) != -1) - { - return new Playlist - { - Path = args.Path, - Name = ResolverHelper.StripBrackets(Path.GetFileName(args.Path)) - }; - } - } - - return null; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs deleted file mode 100644 index 7bb66ed89d..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ /dev/null @@ -1,83 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Resolvers; -using System; -using System.IO; -using System.Linq; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers -{ - class SpecialFolderResolver : FolderResolver<Folder> - { - private readonly IFileSystem _fileSystem; - private readonly IServerApplicationPaths _appPaths; - - public SpecialFolderResolver(IFileSystem fileSystem, IServerApplicationPaths appPaths) - { - _fileSystem = fileSystem; - _appPaths = appPaths; - } - - /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public override ResolverPriority Priority - { - get { return ResolverPriority.First; } - } - - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>Folder.</returns> - protected override Folder Resolve(ItemResolveArgs args) - { - if (args.IsDirectory) - { - if (args.IsPhysicalRoot) - { - return new AggregateFolder(); - } - if (string.Equals(args.Path, _appPaths.DefaultUserViewsPath, StringComparison.OrdinalIgnoreCase)) - { - return new UserRootFolder(); //if we got here and still a root - must be user root - } - if (args.IsVf) - { - return new CollectionFolder - { - CollectionType = GetCollectionType(args), - PhysicalLocationsList = args.PhysicalLocations.ToList() - }; - } - } - - return null; - } - - private string GetCollectionType(ItemResolveArgs args) - { - return args.FileSystemChildren - .Where(i => - { - - try - { - return (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory && - string.Equals(".collection", i.Extension, StringComparison.OrdinalIgnoreCase); - } - catch (IOException) - { - return false; - } - - }) - .Select(i => _fileSystem.GetFileNameWithoutExtension(i)) - .FirstOrDefault(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs deleted file mode 100644 index 6edc4a009e..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using System.Linq; -using MediaBrowser.Model.Entities; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV -{ - /// <summary> - /// Class EpisodeResolver - /// </summary> - public class EpisodeResolver : BaseVideoResolver<Episode> - { - public EpisodeResolver(ILibraryManager libraryManager) : base(libraryManager) - { - } - - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>Episode.</returns> - protected override Episode Resolve(ItemResolveArgs args) - { - var parent = args.Parent; - - if (parent == null) - { - return null; - } - - var season = parent as Season; - // Just in case the user decided to nest episodes. - // Not officially supported but in some cases we can handle it. - if (season == null) - { - season = parent.GetParents().OfType<Season>().FirstOrDefault(); - } - - // If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something - // Also handle flat tv folders - if (season != null || - string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || - args.HasParent<Series>()) - { - var episode = ResolveVideo<Episode>(args, false); - - if (episode != null) - { - var series = parent as Series; - if (series == null) - { - series = parent.GetParents().OfType<Series>().FirstOrDefault(); - } - - if (series != null) - { - episode.SeriesId = series.Id; - episode.SeriesName = series.Name; - episode.SeriesSortName = series.SortName; - } - if (season != null) - { - episode.SeasonId = season.Id; - episode.SeasonName = season.Name; - } - } - - return episode; - } - - return null; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs deleted file mode 100644 index fc49297482..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ /dev/null @@ -1,62 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Naming.Common; -using MediaBrowser.Naming.TV; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV -{ - /// <summary> - /// Class SeasonResolver - /// </summary> - public class SeasonResolver : FolderResolver<Season> - { - /// <summary> - /// The _config - /// </summary> - private readonly IServerConfigurationManager _config; - - private readonly ILibraryManager _libraryManager; - - /// <summary> - /// Initializes a new instance of the <see cref="SeasonResolver"/> class. - /// </summary> - /// <param name="config">The config.</param> - public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager) - { - _config = config; - _libraryManager = libraryManager; - } - - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>Season.</returns> - protected override Season Resolve(ItemResolveArgs args) - { - if (args.Parent is Series && args.IsDirectory) - { - var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); - var series = ((Series)args.Parent); - - var season = new Season - { - IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber, - SeriesId = series.Id, - SeriesSortName = series.SortName, - SeriesName = series.Name - }; - - if (season.IndexNumber.HasValue && season.IndexNumber.Value == 0) - { - season.Name = _config.Configuration.SeasonZeroDisplayName; - } - - return season; - } - - return null; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs deleted file mode 100644 index 3217cd67b9..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ /dev/null @@ -1,251 +0,0 @@ -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Naming.Common; -using MediaBrowser.Naming.TV; -using MediaBrowser.Server.Implementations.Logging; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using CommonIO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Model.Configuration; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV -{ - /// <summary> - /// Class SeriesResolver - /// </summary> - public class SeriesResolver : FolderResolver<Series> - { - private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; - private readonly ILibraryManager _libraryManager; - - public SeriesResolver(IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager) - { - _fileSystem = fileSystem; - _logger = logger; - _libraryManager = libraryManager; - } - - /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public override ResolverPriority Priority - { - get - { - return ResolverPriority.Second; - } - } - - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>Series.</returns> - protected override Series Resolve(ItemResolveArgs args) - { - if (args.IsDirectory) - { - if (args.HasParent<Series>() || args.HasParent<Season>()) - { - return null; - } - - var collectionType = args.GetCollectionType(); - if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) - { - //if (args.ContainsFileSystemEntryByName("tvshow.nfo")) - //{ - // return new Series - // { - // Path = args.Path, - // Name = Path.GetFileName(args.Path) - // }; - //} - - var configuredContentType = _libraryManager.GetConfiguredContentType(args.Path); - if (!string.Equals(configuredContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) - { - return new Series - { - Path = args.Path, - Name = Path.GetFileName(args.Path) - }; - } - } - else if (string.IsNullOrWhiteSpace(collectionType)) - { - if (args.ContainsFileSystemEntryByName("tvshow.nfo")) - { - if (args.Parent.IsRoot) - { - // For now, return null, but if we want to allow this in the future then add some additional checks to guard against a misplaced tvshow.nfo - return null; - } - - return new Series - { - Path = args.Path, - Name = Path.GetFileName(args.Path) - }; - } - - if (args.Parent.IsRoot) - { - return null; - } - - if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, args.GetLibraryOptions(), false)) - { - return new Series - { - Path = args.Path, - Name = Path.GetFileName(args.Path) - }; - } - } - } - - return null; - } - - public static bool IsSeriesFolder(string path, - IEnumerable<FileSystemMetadata> fileSystemChildren, - IDirectoryService directoryService, - IFileSystem fileSystem, - ILogger logger, - ILibraryManager libraryManager, - LibraryOptions libraryOptions, - bool isTvContentType) - { - foreach (var child in fileSystemChildren) - { - var attributes = child.Attributes; - - //if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden) - //{ - // //logger.Debug("Igoring series file or folder marked hidden: {0}", child.FullName); - // continue; - //} - - // Can't enforce this because files saved by Bitcasa are always marked System - //if ((attributes & FileAttributes.System) == FileAttributes.System) - //{ - // logger.Debug("Igoring series subfolder marked system: {0}", child.FullName); - // continue; - //} - - if ((attributes & FileAttributes.Directory) == FileAttributes.Directory) - { - if (IsSeasonFolder(child.FullName, isTvContentType, libraryManager)) - { - //logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName); - return true; - } - } - else - { - string fullName = child.FullName; - if (libraryManager.IsVideoFile(fullName, libraryOptions)) - { - if (isTvContentType) - { - return true; - } - - var namingOptions = ((LibraryManager)libraryManager).GetNamingOptions(); - - // In mixed folders we need to be conservative and avoid expressions that may result in false positives (e.g. movies with numbers in the title) - if (!isTvContentType) - { - namingOptions.EpisodeExpressions = namingOptions.EpisodeExpressions - .Where(i => i.IsNamed && !i.IsOptimistic) - .ToList(); - } - - var episodeResolver = new Naming.TV.EpisodeResolver(namingOptions, new PatternsLogger()); - var episodeInfo = episodeResolver.Resolve(fullName, false, false); - if (episodeInfo != null && episodeInfo.EpisodeNumber.HasValue) - { - return true; - } - } - } - } - - logger.Debug("{0} is not a series folder.", path); - return false; - } - - /// <summary> - /// Determines whether [is place holder] [the specified path]. - /// </summary> - /// <param name="path">The path.</param> - /// <returns><c>true</c> if [is place holder] [the specified path]; otherwise, <c>false</c>.</returns> - /// <exception cref="System.ArgumentNullException">path</exception> - private static bool IsVideoPlaceHolder(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException("path"); - } - - var extension = Path.GetExtension(path); - - return string.Equals(extension, ".disc", StringComparison.OrdinalIgnoreCase); - } - - /// <summary> - /// Determines whether [is season folder] [the specified path]. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="isTvContentType">if set to <c>true</c> [is tv content type].</param> - /// <param name="libraryManager">The library manager.</param> - /// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns> - private static bool IsSeasonFolder(string path, bool isTvContentType, ILibraryManager libraryManager) - { - var namingOptions = ((LibraryManager)libraryManager).GetNamingOptions(); - - var seasonNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(path, isTvContentType, isTvContentType).SeasonNumber; - - return seasonNumber.HasValue; - } - - /// <summary> - /// Sets the initial item values. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="args">The args.</param> - protected override void SetInitialItemValues(Series item, ItemResolveArgs args) - { - base.SetInitialItemValues(item, args); - - SetProviderIdFromPath(item, args.Path); - } - - /// <summary> - /// Sets the provider id from path. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="path">The path.</param> - private void SetProviderIdFromPath(Series item, string path) - { - var justName = Path.GetFileName(path); - - var id = justName.GetAttributeValue("tvdbid"); - - if (!string.IsNullOrEmpty(id)) - { - item.SetProviderId(MetadataProviders.Tvdb, id); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs deleted file mode 100644 index c7f21cef16..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Resolvers; - -namespace MediaBrowser.Server.Implementations.Library.Resolvers -{ - /// <summary> - /// Resolves a Path into a Video - /// </summary> - public class VideoResolver : BaseVideoResolver<Video> - { - public VideoResolver(ILibraryManager libraryManager) - : base(libraryManager) - { - } - - protected override Video Resolve(ItemResolveArgs args) - { - if (args.Parent != null) - { - // The movie resolver will handle this - return null; - } - - return base.Resolve(args); - } - - /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public override ResolverPriority Priority - { - get { return ResolverPriority.Last; } - } - } - - public class GenericVideoResolver<T> : BaseVideoResolver<T> - where T : Video, new () - { - public GenericVideoResolver(ILibraryManager libraryManager) : base(libraryManager) - { - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs deleted file mode 100644 index 40cca7baba..0000000000 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ /dev/null @@ -1,278 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Search; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Library -{ - /// <summary> - /// Class LuceneSearchEngine - /// http://www.codeproject.com/Articles/320219/Lucene-Net-ultra-fast-search-for-MVC-or-WebForms - /// </summary> - public class SearchEngine : ISearchEngine - { - private readonly ILibraryManager _libraryManager; - private readonly IUserManager _userManager; - private readonly ILogger _logger; - - public SearchEngine(ILogManager logManager, ILibraryManager libraryManager, IUserManager userManager) - { - _libraryManager = libraryManager; - _userManager = userManager; - - _logger = logManager.GetLogger("Lucene"); - } - - public async Task<QueryResult<SearchHintInfo>> GetSearchHints(SearchQuery query) - { - User user = null; - - if (string.IsNullOrWhiteSpace(query.UserId)) - { - } - else - { - user = _userManager.GetUserById(query.UserId); - } - - var results = await GetSearchHints(query, user).ConfigureAwait(false); - - var searchResultArray = results.ToArray(); - results = searchResultArray; - - var count = searchResultArray.Length; - - if (query.StartIndex.HasValue) - { - results = results.Skip(query.StartIndex.Value); - } - - if (query.Limit.HasValue) - { - results = results.Take(query.Limit.Value); - } - - return new QueryResult<SearchHintInfo> - { - TotalRecordCount = count, - - Items = results.ToArray() - }; - } - - private void AddIfMissing(List<string> list, string value) - { - if (!list.Contains(value, StringComparer.OrdinalIgnoreCase)) - { - list.Add(value); - } - } - - /// <summary> - /// Gets the search hints. - /// </summary> - /// <param name="query">The query.</param> - /// <param name="user">The user.</param> - /// <returns>IEnumerable{SearchHintResult}.</returns> - /// <exception cref="System.ArgumentNullException">searchTerm</exception> - private Task<IEnumerable<SearchHintInfo>> GetSearchHints(SearchQuery query, User user) - { - var searchTerm = query.SearchTerm; - - if (searchTerm != null) - { - searchTerm = searchTerm.Trim().RemoveDiacritics(); - } - - if (string.IsNullOrWhiteSpace(searchTerm)) - { - throw new ArgumentNullException("searchTerm"); - } - - var terms = GetWords(searchTerm); - - var hints = new List<Tuple<BaseItem, string, int>>(); - - var excludeItemTypes = new List<string>(); - var includeItemTypes = (query.IncludeItemTypes ?? new string[] { }).ToList(); - - excludeItemTypes.Add(typeof(Year).Name); - excludeItemTypes.Add(typeof(Folder).Name); - - if (query.IncludeGenres && (includeItemTypes.Count == 0 || includeItemTypes.Contains("Genre", StringComparer.OrdinalIgnoreCase))) - { - if (!query.IncludeMedia) - { - AddIfMissing(includeItemTypes, typeof(Genre).Name); - AddIfMissing(includeItemTypes, typeof(GameGenre).Name); - AddIfMissing(includeItemTypes, typeof(MusicGenre).Name); - } - } - else - { - AddIfMissing(excludeItemTypes, typeof(Genre).Name); - AddIfMissing(excludeItemTypes, typeof(GameGenre).Name); - AddIfMissing(excludeItemTypes, typeof(MusicGenre).Name); - } - - if (query.IncludePeople && (includeItemTypes.Count == 0 || includeItemTypes.Contains("People", StringComparer.OrdinalIgnoreCase) || includeItemTypes.Contains("Person", StringComparer.OrdinalIgnoreCase))) - { - if (!query.IncludeMedia) - { - AddIfMissing(includeItemTypes, typeof(Person).Name); - } - } - else - { - AddIfMissing(excludeItemTypes, typeof(Person).Name); - } - - if (query.IncludeStudios && (includeItemTypes.Count == 0 || includeItemTypes.Contains("Studio", StringComparer.OrdinalIgnoreCase))) - { - if (!query.IncludeMedia) - { - AddIfMissing(includeItemTypes, typeof(Studio).Name); - } - } - else - { - AddIfMissing(excludeItemTypes, typeof(Studio).Name); - } - - if (query.IncludeArtists && (includeItemTypes.Count == 0 || includeItemTypes.Contains("MusicArtist", StringComparer.OrdinalIgnoreCase))) - { - if (!query.IncludeMedia) - { - AddIfMissing(includeItemTypes, typeof(MusicArtist).Name); - } - } - else - { - AddIfMissing(excludeItemTypes, typeof(MusicArtist).Name); - } - - AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name); - - var mediaItems = _libraryManager.GetItemList(new InternalItemsQuery(user) - { - NameContains = searchTerm, - ExcludeItemTypes = excludeItemTypes.ToArray(), - IncludeItemTypes = includeItemTypes.ToArray(), - Limit = query.Limit, - IncludeItemsByName = true, - IsVirtualItem = false - }); - - // Add search hints based on item name - hints.AddRange(mediaItems.Select(item => - { - var index = GetIndex(item.Name, searchTerm, terms); - - return new Tuple<BaseItem, string, int>(item, index.Item1, index.Item2); - })); - - var returnValue = hints.Where(i => i.Item3 >= 0).OrderBy(i => i.Item3).Select(i => new SearchHintInfo - { - Item = i.Item1, - MatchedTerm = i.Item2 - }); - - return Task.FromResult(returnValue); - } - - /// <summary> - /// Gets the index. - /// </summary> - /// <param name="input">The input.</param> - /// <param name="searchInput">The search input.</param> - /// <param name="searchWords">The search input.</param> - /// <returns>System.Int32.</returns> - private Tuple<string, int> GetIndex(string input, string searchInput, List<string> searchWords) - { - if (string.IsNullOrWhiteSpace(input)) - { - throw new ArgumentNullException("input"); - } - - input = input.RemoveDiacritics(); - - if (string.Equals(input, searchInput, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, int>(searchInput, 0); - } - - var index = input.IndexOf(searchInput, StringComparison.OrdinalIgnoreCase); - - if (index == 0) - { - return new Tuple<string, int>(searchInput, 1); - } - if (index > 0) - { - return new Tuple<string, int>(searchInput, 2); - } - - var items = GetWords(input); - - for (var i = 0; i < searchWords.Count; i++) - { - var searchTerm = searchWords[i]; - - for (var j = 0; j < items.Count; j++) - { - var item = items[j]; - - if (string.Equals(item, searchTerm, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, int>(searchTerm, 3 + (i + 1) * (j + 1)); - } - - index = item.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase); - - if (index == 0) - { - return new Tuple<string, int>(searchTerm, 4 + (i + 1) * (j + 1)); - } - if (index > 0) - { - return new Tuple<string, int>(searchTerm, 5 + (i + 1) * (j + 1)); - } - } - } - return new Tuple<string, int>(null, -1); - } - - /// <summary> - /// Gets the words. - /// </summary> - /// <param name="term">The term.</param> - /// <returns>System.String[][].</returns> - private List<string> GetWords(string term) - { - var stoplist = GetStopList().ToList(); - - return term.Split() - .Where(i => !string.IsNullOrWhiteSpace(i) && !stoplist.Contains(i, StringComparer.OrdinalIgnoreCase)) - .ToList(); - } - - private IEnumerable<string> GetStopList() - { - return new[] - { - "the", - "a", - "of", - "an" - }; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs deleted file mode 100644 index 9ee65a57c6..0000000000 --- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs +++ /dev/null @@ -1,287 +0,0 @@ -using MediaBrowser.Common.Events; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Library -{ - /// <summary> - /// Class UserDataManager - /// </summary> - public class UserDataManager : IUserDataManager - { - public event EventHandler<UserDataSaveEventArgs> UserDataSaved; - - private readonly ConcurrentDictionary<string, UserItemData> _userData = - new ConcurrentDictionary<string, UserItemData>(StringComparer.OrdinalIgnoreCase); - - private readonly ILogger _logger; - private readonly IServerConfigurationManager _config; - - public UserDataManager(ILogManager logManager, IServerConfigurationManager config) - { - _config = config; - _logger = logManager.GetLogger(GetType().Name); - } - - /// <summary> - /// Gets or sets the repository. - /// </summary> - /// <value>The repository.</value> - public IUserDataRepository Repository { get; set; } - - public async Task SaveUserData(Guid userId, IHasUserData item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken) - { - if (userData == null) - { - throw new ArgumentNullException("userData"); - } - if (item == null) - { - throw new ArgumentNullException("item"); - } - if (userId == Guid.Empty) - { - throw new ArgumentNullException("userId"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - var keys = item.GetUserDataKeys(); - - foreach (var key in keys) - { - await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); - } - - var cacheKey = GetCacheKey(userId, item.Id); - _userData.AddOrUpdate(cacheKey, userData, (k, v) => userData); - - EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs - { - Keys = keys, - UserData = userData, - SaveReason = reason, - UserId = userId, - Item = item - - }, _logger); - } - - /// <summary> - /// Save the provided user data for the given user. Batch operation. Does not fire any events or update the cache. - /// </summary> - /// <param name="userId"></param> - /// <param name="userData"></param> - /// <param name="cancellationToken"></param> - /// <returns></returns> - public async Task SaveAllUserData(Guid userId, IEnumerable<UserItemData> userData, CancellationToken cancellationToken) - { - if (userData == null) - { - throw new ArgumentNullException("userData"); - } - if (userId == Guid.Empty) - { - throw new ArgumentNullException("userId"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - await Repository.SaveAllUserData(userId, userData, cancellationToken).ConfigureAwait(false); - } - - /// <summary> - /// Retrieve all user data for the given user - /// </summary> - /// <param name="userId"></param> - /// <returns></returns> - public IEnumerable<UserItemData> GetAllUserData(Guid userId) - { - if (userId == Guid.Empty) - { - throw new ArgumentNullException("userId"); - } - - return Repository.GetAllUserData(userId); - } - - public UserItemData GetUserData(Guid userId, Guid itemId, List<string> keys) - { - if (userId == Guid.Empty) - { - throw new ArgumentNullException("userId"); - } - if (keys == null) - { - throw new ArgumentNullException("keys"); - } - if (keys.Count == 0) - { - throw new ArgumentException("UserData keys cannot be empty."); - } - - var cacheKey = GetCacheKey(userId, itemId); - - return _userData.GetOrAdd(cacheKey, k => GetUserDataInternal(userId, keys)); - } - - private UserItemData GetUserDataInternal(Guid userId, List<string> keys) - { - var userData = Repository.GetUserData(userId, keys); - - if (userData != null) - { - return userData; - } - - if (keys.Count > 0) - { - return new UserItemData - { - UserId = userId, - Key = keys[0] - }; - } - - return null; - } - - /// <summary> - /// Gets the internal key. - /// </summary> - /// <returns>System.String.</returns> - private string GetCacheKey(Guid userId, Guid itemId) - { - return userId.ToString("N") + itemId.ToString("N"); - } - - public UserItemData GetUserData(IHasUserData user, IHasUserData item) - { - return GetUserData(user.Id, item); - } - - public UserItemData GetUserData(string userId, IHasUserData item) - { - return GetUserData(new Guid(userId), item); - } - - public UserItemData GetUserData(Guid userId, IHasUserData item) - { - return GetUserData(userId, item.Id, item.GetUserDataKeys()); - } - - public async Task<UserItemDataDto> GetUserDataDto(IHasUserData item, User user) - { - var userData = GetUserData(user.Id, item); - var dto = GetUserItemDataDto(userData); - - await item.FillUserDataDtoValues(dto, userData, null, user).ConfigureAwait(false); - return dto; - } - - public async Task<UserItemDataDto> GetUserDataDto(IHasUserData item, BaseItemDto itemDto, User user) - { - var userData = GetUserData(user.Id, item); - var dto = GetUserItemDataDto(userData); - - await item.FillUserDataDtoValues(dto, userData, itemDto, user).ConfigureAwait(false); - return dto; - } - - /// <summary> - /// Converts a UserItemData to a DTOUserItemData - /// </summary> - /// <param name="data">The data.</param> - /// <returns>DtoUserItemData.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - private UserItemDataDto GetUserItemDataDto(UserItemData data) - { - if (data == null) - { - throw new ArgumentNullException("data"); - } - - return new UserItemDataDto - { - IsFavorite = data.IsFavorite, - Likes = data.Likes, - PlaybackPositionTicks = data.PlaybackPositionTicks, - PlayCount = data.PlayCount, - Rating = data.Rating, - Played = data.Played, - LastPlayedDate = data.LastPlayedDate, - Key = data.Key - }; - } - - public bool UpdatePlayState(BaseItem item, UserItemData data, long? reportedPositionTicks) - { - var playedToCompletion = false; - - var positionTicks = reportedPositionTicks ?? item.RunTimeTicks ?? 0; - var hasRuntime = item.RunTimeTicks.HasValue && item.RunTimeTicks > 0; - - // If a position has been reported, and if we know the duration - if (positionTicks > 0 && hasRuntime) - { - var pctIn = Decimal.Divide(positionTicks, item.RunTimeTicks.Value) * 100; - - // Don't track in very beginning - if (pctIn < _config.Configuration.MinResumePct) - { - positionTicks = 0; - } - - // If we're at the end, assume completed - else if (pctIn > _config.Configuration.MaxResumePct || positionTicks >= item.RunTimeTicks.Value) - { - positionTicks = 0; - data.Played = playedToCompletion = true; - } - - else - { - // Enforce MinResumeDuration - var durationSeconds = TimeSpan.FromTicks(item.RunTimeTicks.Value).TotalSeconds; - - if (durationSeconds < _config.Configuration.MinResumeDurationSeconds) - { - positionTicks = 0; - data.Played = playedToCompletion = true; - } - } - } - else if (!hasRuntime) - { - // If we don't know the runtime we'll just have to assume it was fully played - data.Played = playedToCompletion = true; - positionTicks = 0; - } - - if (!item.SupportsPlayedStatus) - { - positionTicks = 0; - data.Played = false; - } - if (item is Audio) - { - positionTicks = 0; - } - - data.PlaybackPositionTicks = positionTicks; - - return playedToCompletion; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs deleted file mode 100644 index 6456d7f81b..0000000000 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ /dev/null @@ -1,1019 +0,0 @@ -using MediaBrowser.Common.Events; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Connect; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Connect; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Users; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Library -{ - /// <summary> - /// Class UserManager - /// </summary> - public class UserManager : IUserManager - { - /// <summary> - /// Gets the users. - /// </summary> - /// <value>The users.</value> - public IEnumerable<User> Users { get; private set; } - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - /// <summary> - /// Gets or sets the configuration manager. - /// </summary> - /// <value>The configuration manager.</value> - private IServerConfigurationManager ConfigurationManager { get; set; } - - /// <summary> - /// Gets the active user repository - /// </summary> - /// <value>The user repository.</value> - private IUserRepository UserRepository { get; set; } - public event EventHandler<GenericEventArgs<User>> UserPasswordChanged; - - private readonly IXmlSerializer _xmlSerializer; - private readonly IJsonSerializer _jsonSerializer; - - private readonly INetworkManager _networkManager; - - private readonly Func<IImageProcessor> _imageProcessorFactory; - private readonly Func<IDtoService> _dtoServiceFactory; - private readonly Func<IConnectManager> _connectFactory; - private readonly IServerApplicationHost _appHost; - private readonly IFileSystem _fileSystem; - - public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, Func<IConnectManager> connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem) - { - _logger = logger; - UserRepository = userRepository; - _xmlSerializer = xmlSerializer; - _networkManager = networkManager; - _imageProcessorFactory = imageProcessorFactory; - _dtoServiceFactory = dtoServiceFactory; - _connectFactory = connectFactory; - _appHost = appHost; - _jsonSerializer = jsonSerializer; - _fileSystem = fileSystem; - ConfigurationManager = configurationManager; - Users = new List<User>(); - - DeletePinFile(); - } - - #region UserUpdated Event - /// <summary> - /// Occurs when [user updated]. - /// </summary> - public event EventHandler<GenericEventArgs<User>> UserUpdated; - public event EventHandler<GenericEventArgs<User>> UserConfigurationUpdated; - public event EventHandler<GenericEventArgs<User>> UserLockedOut; - - /// <summary> - /// Called when [user updated]. - /// </summary> - /// <param name="user">The user.</param> - private void OnUserUpdated(User user) - { - EventHelper.FireEventIfNotNull(UserUpdated, this, new GenericEventArgs<User> { Argument = user }, _logger); - } - #endregion - - #region UserDeleted Event - /// <summary> - /// Occurs when [user deleted]. - /// </summary> - public event EventHandler<GenericEventArgs<User>> UserDeleted; - /// <summary> - /// Called when [user deleted]. - /// </summary> - /// <param name="user">The user.</param> - private void OnUserDeleted(User user) - { - EventHelper.QueueEventIfNotNull(UserDeleted, this, new GenericEventArgs<User> { Argument = user }, _logger); - } - #endregion - - /// <summary> - /// Gets a User by Id - /// </summary> - /// <param name="id">The id.</param> - /// <returns>User.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public User GetUserById(Guid id) - { - if (id == Guid.Empty) - { - throw new ArgumentNullException("id"); - } - - return Users.FirstOrDefault(u => u.Id == id); - } - - /// <summary> - /// Gets the user by identifier. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>User.</returns> - public User GetUserById(string id) - { - return GetUserById(new Guid(id)); - } - - public User GetUserByName(string name) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - - return Users.FirstOrDefault(u => string.Equals(u.Name, name, StringComparison.OrdinalIgnoreCase)); - } - - public async Task Initialize() - { - Users = await LoadUsers().ConfigureAwait(false); - - var users = Users.ToList(); - - // If there are no local users with admin rights, make them all admins - if (!users.Any(i => i.Policy.IsAdministrator)) - { - foreach (var user in users) - { - if (!user.ConnectLinkType.HasValue || user.ConnectLinkType.Value == UserLinkType.LinkedUser) - { - user.Policy.IsAdministrator = true; - await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false); - } - } - } - } - - public Task<bool> AuthenticateUser(string username, string passwordSha1, string remoteEndPoint) - { - return AuthenticateUser(username, passwordSha1, null, remoteEndPoint); - } - - public bool IsValidUsername(string username) - { - // Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.) - return username.All(IsValidUsernameCharacter); - } - - private bool IsValidUsernameCharacter(char i) - { - return char.IsLetterOrDigit(i) || char.Equals(i, '-') || char.Equals(i, '_') || char.Equals(i, '\'') || - char.Equals(i, '.'); - } - - public string MakeValidUsername(string username) - { - if (IsValidUsername(username)) - { - return username; - } - - // Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.) - var builder = new StringBuilder(); - - foreach (var c in username) - { - if (IsValidUsernameCharacter(c)) - { - builder.Append(c); - } - } - return builder.ToString(); - } - - public async Task<bool> AuthenticateUser(string username, string passwordSha1, string passwordMd5, string remoteEndPoint) - { - if (string.IsNullOrWhiteSpace(username)) - { - throw new ArgumentNullException("username"); - } - - var user = Users - .FirstOrDefault(i => string.Equals(username, i.Name, 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)); - } - - var success = false; - - // 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); - - if (!success && _networkManager.IsInLocalNetwork(remoteEndPoint) && user.Configuration.EnableLocalPassword) - { - success = string.Equals(GetLocalPasswordHash(user), passwordSha1.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase); - } - } - - // Update LastActivityDate and LastLoginDate, then save - if (success) - { - user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow; - await UpdateUser(user).ConfigureAwait(false); - await UpdateInvalidLoginAttemptCount(user, 0).ConfigureAwait(false); - } - else - { - await UpdateInvalidLoginAttemptCount(user, user.Policy.InvalidLoginAttemptCount + 1).ConfigureAwait(false); - } - - _logger.Info("Authentication request for {0} {1}.", user.Name, success ? "has succeeded" : "has been denied"); - - return success; - } - - private async Task UpdateInvalidLoginAttemptCount(User user, int newValue) - { - if (user.Policy.InvalidLoginAttemptCount != newValue || newValue > 0) - { - user.Policy.InvalidLoginAttemptCount = newValue; - - var maxCount = user.Policy.IsAdministrator ? - 3 : - 5; - - var fireLockout = false; - - if (newValue >= maxCount) - { - //_logger.Debug("Disabling user {0} due to {1} unsuccessful login attempts.", user.Name, newValue.ToString(CultureInfo.InvariantCulture)); - //user.Policy.IsDisabled = true; - - //fireLockout = true; - } - - await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false); - - if (fireLockout) - { - if (UserLockedOut != null) - { - EventHelper.FireEventIfNotNull(UserLockedOut, this, new GenericEventArgs<User>(user), _logger); - } - } - } - } - - private string GetPasswordHash(User user) - { - return string.IsNullOrEmpty(user.Password) - ? GetSha1String(string.Empty) - : user.Password; - } - - private string GetLocalPasswordHash(User user) - { - return string.IsNullOrEmpty(user.EasyPassword) - ? GetSha1String(string.Empty) - : user.EasyPassword; - } - - private bool IsPasswordEmpty(string passwordHash) - { - return string.Equals(passwordHash, GetSha1String(string.Empty), StringComparison.OrdinalIgnoreCase); - } - - /// <summary> - /// Gets the sha1 string. - /// </summary> - /// <param name="str">The STR.</param> - /// <returns>System.String.</returns> - private static string GetSha1String(string str) - { - using (var provider = SHA1.Create()) - { - var hash = provider.ComputeHash(Encoding.UTF8.GetBytes(str)); - return BitConverter.ToString(hash).Replace("-", string.Empty); - } - } - - /// <summary> - /// Loads the users from the repository - /// </summary> - /// <returns>IEnumerable{User}.</returns> - private async Task<IEnumerable<User>> LoadUsers() - { - var users = UserRepository.RetrieveAllUsers().ToList(); - - // There always has to be at least one user. - if (users.Count == 0) - { - var name = MakeValidUsername(Environment.UserName); - - var user = InstantiateNewUser(name); - - user.DateLastSaved = DateTime.UtcNow; - - await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false); - - users.Add(user); - - user.Policy.IsAdministrator = true; - user.Policy.EnableContentDeletion = true; - user.Policy.EnableRemoteControlOfOtherUsers = true; - await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false); - } - - return users; - } - - public UserDto GetUserDto(User user, string remoteEndPoint = null) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - - var passwordHash = GetPasswordHash(user); - - var hasConfiguredPassword = !IsPasswordEmpty(passwordHash); - var hasConfiguredEasyPassword = !IsPasswordEmpty(GetLocalPasswordHash(user)); - - var hasPassword = user.Configuration.EnableLocalPassword && !string.IsNullOrEmpty(remoteEndPoint) && _networkManager.IsInLocalNetwork(remoteEndPoint) ? - hasConfiguredEasyPassword : - hasConfiguredPassword; - - var dto = new UserDto - { - Id = user.Id.ToString("N"), - Name = user.Name, - HasPassword = hasPassword, - HasConfiguredPassword = hasConfiguredPassword, - HasConfiguredEasyPassword = hasConfiguredEasyPassword, - LastActivityDate = user.LastActivityDate, - LastLoginDate = user.LastLoginDate, - Configuration = user.Configuration, - ConnectLinkType = user.ConnectLinkType, - ConnectUserId = user.ConnectUserId, - ConnectUserName = user.ConnectUserName, - ServerId = _appHost.SystemId, - Policy = user.Policy - }; - - var image = user.GetImageInfo(ImageType.Primary, 0); - - if (image != null) - { - dto.PrimaryImageTag = GetImageCacheTag(user, image); - - try - { - _dtoServiceFactory().AttachPrimaryImageAspectRatio(dto, user); - } - catch (Exception ex) - { - // Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions - _logger.ErrorException("Error generating PrimaryImageAspectRatio for {0}", ex, user.Name); - } - } - - return dto; - } - - public UserDto GetOfflineUserDto(User user) - { - var dto = GetUserDto(user); - - var offlinePasswordHash = GetLocalPasswordHash(user); - dto.HasPassword = !IsPasswordEmpty(offlinePasswordHash); - - dto.OfflinePasswordSalt = Guid.NewGuid().ToString("N"); - - // Hash the pin with the device Id to create a unique result for this device - dto.OfflinePassword = GetSha1String((offlinePasswordHash + dto.OfflinePasswordSalt).ToLower()); - - dto.ServerName = _appHost.FriendlyName; - - return dto; - } - - private string GetImageCacheTag(BaseItem item, ItemImageInfo image) - { - try - { - return _imageProcessorFactory().GetImageCacheTag(item, image); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting {0} image info for {1}", ex, image.Type, image.Path); - return null; - } - } - - /// <summary> - /// Refreshes metadata for each user - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task RefreshUsersMetadata(CancellationToken cancellationToken) - { - var tasks = Users.Select(user => user.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), cancellationToken)).ToList(); - - return Task.WhenAll(tasks); - } - - /// <summary> - /// Renames the user. - /// </summary> - /// <param name="user">The user.</param> - /// <param name="newName">The new name.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">user</exception> - /// <exception cref="System.ArgumentException"></exception> - public async Task RenameUser(User user, string newName) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - - if (string.IsNullOrEmpty(newName)) - { - throw new ArgumentNullException("newName"); - } - - if (Users.Any(u => u.Id != user.Id && u.Name.Equals(newName, StringComparison.OrdinalIgnoreCase))) - { - throw new ArgumentException(string.Format("A user with the name '{0}' already exists.", newName)); - } - - if (user.Name.Equals(newName, StringComparison.Ordinal)) - { - throw new ArgumentException("The new and old names must be different."); - } - - await user.Rename(newName); - - OnUserUpdated(user); - } - - /// <summary> - /// Updates the user. - /// </summary> - /// <param name="user">The user.</param> - /// <exception cref="System.ArgumentNullException">user</exception> - /// <exception cref="System.ArgumentException"></exception> - public async Task UpdateUser(User user) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - - if (user.Id == Guid.Empty || !Users.Any(u => u.Id.Equals(user.Id))) - { - throw new ArgumentException(string.Format("User with name '{0}' and Id {1} does not exist.", user.Name, user.Id)); - } - - user.DateModified = DateTime.UtcNow; - user.DateLastSaved = DateTime.UtcNow; - - await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false); - - OnUserUpdated(user); - } - - public event EventHandler<GenericEventArgs<User>> UserCreated; - - private readonly SemaphoreSlim _userListLock = new SemaphoreSlim(1, 1); - - /// <summary> - /// Creates the user. - /// </summary> - /// <param name="name">The name.</param> - /// <returns>User.</returns> - /// <exception cref="System.ArgumentNullException">name</exception> - /// <exception cref="System.ArgumentException"></exception> - public async Task<User> CreateUser(string name) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - - if (!IsValidUsername(name)) - { - throw new ArgumentException("Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"); - } - - if (Users.Any(u => u.Name.Equals(name, StringComparison.OrdinalIgnoreCase))) - { - throw new ArgumentException(string.Format("A user with the name '{0}' already exists.", name)); - } - - await _userListLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); - - try - { - var user = InstantiateNewUser(name); - - var list = Users.ToList(); - list.Add(user); - Users = list; - - user.DateLastSaved = DateTime.UtcNow; - - await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false); - - EventHelper.QueueEventIfNotNull(UserCreated, this, new GenericEventArgs<User> { Argument = user }, _logger); - - return user; - } - finally - { - _userListLock.Release(); - } - } - - /// <summary> - /// Deletes the user. - /// </summary> - /// <param name="user">The user.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">user</exception> - /// <exception cref="System.ArgumentException"></exception> - public async Task DeleteUser(User user) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - - if (user.ConnectLinkType.HasValue) - { - await _connectFactory().RemoveConnect(user.Id.ToString("N")).ConfigureAwait(false); - } - - var allUsers = Users.ToList(); - - if (allUsers.FirstOrDefault(u => u.Id == user.Id) == null) - { - throw new ArgumentException(string.Format("The user cannot be deleted because there is no user with the Name {0} and Id {1}.", user.Name, user.Id)); - } - - if (allUsers.Count == 1) - { - throw new ArgumentException(string.Format("The user '{0}' cannot be deleted because there must be at least one user in the system.", user.Name)); - } - - if (user.Policy.IsAdministrator && allUsers.Count(i => i.Policy.IsAdministrator) == 1) - { - throw new ArgumentException(string.Format("The user '{0}' cannot be deleted because there must be at least one admin user in the system.", user.Name)); - } - - await _userListLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); - - try - { - var configPath = GetConfigurationFilePath(user); - - await UserRepository.DeleteUser(user, CancellationToken.None).ConfigureAwait(false); - - try - { - _fileSystem.DeleteFile(configPath); - } - catch (IOException ex) - { - _logger.ErrorException("Error deleting file {0}", ex, configPath); - } - - DeleteUserPolicy(user); - - // Force this to be lazy loaded again - Users = await LoadUsers().ConfigureAwait(false); - - OnUserDeleted(user); - } - finally - { - _userListLock.Release(); - } - } - - /// <summary> - /// Resets the password by clearing it. - /// </summary> - /// <returns>Task.</returns> - public Task ResetPassword(User user) - { - return ChangePassword(user, GetSha1String(string.Empty)); - } - - public Task ResetEasyPassword(User user) - { - return ChangeEasyPassword(user, GetSha1String(string.Empty)); - } - - public async Task ChangePassword(User user, string newPasswordSha1) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - if (string.IsNullOrWhiteSpace(newPasswordSha1)) - { - throw new ArgumentNullException("newPasswordSha1"); - } - - if (user.ConnectLinkType.HasValue && user.ConnectLinkType.Value == UserLinkType.Guest) - { - throw new ArgumentException("Passwords for guests cannot be changed."); - } - - user.Password = newPasswordSha1; - - await UpdateUser(user).ConfigureAwait(false); - - EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger); - } - - public async Task ChangeEasyPassword(User user, string newPasswordSha1) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - if (string.IsNullOrWhiteSpace(newPasswordSha1)) - { - throw new ArgumentNullException("newPasswordSha1"); - } - - user.EasyPassword = newPasswordSha1; - - await UpdateUser(user).ConfigureAwait(false); - - EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger); - } - - /// <summary> - /// Instantiates the new user. - /// </summary> - /// <param name="name">The name.</param> - /// <returns>User.</returns> - private User InstantiateNewUser(string name) - { - return new User - { - Name = name, - Id = Guid.NewGuid(), - DateCreated = DateTime.UtcNow, - DateModified = DateTime.UtcNow, - UsesIdForConfigurationPath = true - }; - } - - private string PasswordResetFile - { - get { return Path.Combine(ConfigurationManager.ApplicationPaths.ProgramDataPath, "passwordreset.txt"); } - } - - private string _lastPin; - private PasswordPinCreationResult _lastPasswordPinCreationResult; - private int _pinAttempts; - - private PasswordPinCreationResult CreatePasswordResetPin() - { - var num = new Random().Next(1, 9999); - - var path = PasswordResetFile; - - var pin = num.ToString("0000", CultureInfo.InvariantCulture); - _lastPin = pin; - - var time = TimeSpan.FromMinutes(5); - var expiration = DateTime.UtcNow.Add(time); - - var text = new StringBuilder(); - - var localAddress = _appHost.GetLocalApiUrl().Result ?? string.Empty; - - text.AppendLine("Use your web browser to visit:"); - text.AppendLine(string.Empty); - text.AppendLine(localAddress + "/web/forgotpasswordpin.html"); - text.AppendLine(string.Empty); - text.AppendLine("Enter the following pin code:"); - text.AppendLine(string.Empty); - text.AppendLine(pin); - text.AppendLine(string.Empty); - text.AppendLine("The pin code will expire at " + expiration.ToLocalTime().ToShortDateString() + " " + expiration.ToLocalTime().ToShortTimeString()); - - _fileSystem.WriteAllText(path, text.ToString(), Encoding.UTF8); - - var result = new PasswordPinCreationResult - { - PinFile = path, - ExpirationDate = expiration - }; - - _lastPasswordPinCreationResult = result; - _pinAttempts = 0; - - return result; - } - - public ForgotPasswordResult StartForgotPasswordProcess(string enteredUsername, bool isInNetwork) - { - DeletePinFile(); - - var user = string.IsNullOrWhiteSpace(enteredUsername) ? - null : - GetUserByName(enteredUsername); - - if (user != null && user.ConnectLinkType.HasValue && user.ConnectLinkType.Value == UserLinkType.Guest) - { - throw new ArgumentException("Unable to process forgot password request for guests."); - } - - var action = ForgotPasswordAction.InNetworkRequired; - string pinFile = null; - DateTime? expirationDate = null; - - if (user != null && !user.Policy.IsAdministrator) - { - action = ForgotPasswordAction.ContactAdmin; - } - else - { - if (isInNetwork) - { - action = ForgotPasswordAction.PinCode; - } - - var result = CreatePasswordResetPin(); - pinFile = result.PinFile; - expirationDate = result.ExpirationDate; - } - - return new ForgotPasswordResult - { - Action = action, - PinFile = pinFile, - PinExpirationDate = expirationDate - }; - } - - public async Task<PinRedeemResult> RedeemPasswordResetPin(string pin) - { - DeletePinFile(); - - var usersReset = new List<string>(); - - var valid = !string.IsNullOrWhiteSpace(_lastPin) && - string.Equals(_lastPin, pin, StringComparison.OrdinalIgnoreCase) && - _lastPasswordPinCreationResult != null && - _lastPasswordPinCreationResult.ExpirationDate > DateTime.UtcNow; - - if (valid) - { - _lastPin = null; - _lastPasswordPinCreationResult = null; - - var users = Users.Where(i => !i.ConnectLinkType.HasValue || i.ConnectLinkType.Value != UserLinkType.Guest) - .ToList(); - - foreach (var user in users) - { - await ResetPassword(user).ConfigureAwait(false); - - if (user.Policy.IsDisabled) - { - user.Policy.IsDisabled = false; - await UpdateUserPolicy(user, user.Policy, true).ConfigureAwait(false); - } - usersReset.Add(user.Name); - } - } - else - { - _pinAttempts++; - if (_pinAttempts >= 3) - { - _lastPin = null; - _lastPasswordPinCreationResult = null; - } - } - - return new PinRedeemResult - { - Success = valid, - UsersReset = usersReset.ToArray() - }; - } - - private void DeletePinFile() - { - try - { - _fileSystem.DeleteFile(PasswordResetFile); - } - catch - { - - } - } - - class PasswordPinCreationResult - { - public string PinFile { get; set; } - public DateTime ExpirationDate { get; set; } - } - - public UserPolicy GetUserPolicy(User user) - { - var path = GetPolifyFilePath(user); - - try - { - lock (_policySyncLock) - { - return (UserPolicy)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), path); - } - } - catch (DirectoryNotFoundException) - { - return GetDefaultPolicy(user); - } - catch (FileNotFoundException) - { - return GetDefaultPolicy(user); - } - catch (Exception ex) - { - _logger.ErrorException("Error reading policy file: {0}", ex, path); - - return GetDefaultPolicy(user); - } - } - - private UserPolicy GetDefaultPolicy(User user) - { - return new UserPolicy - { - EnableSync = true - }; - } - - private readonly object _policySyncLock = new object(); - public Task UpdateUserPolicy(string userId, UserPolicy userPolicy) - { - var user = GetUserById(userId); - return UpdateUserPolicy(user, userPolicy, true); - } - - private async Task UpdateUserPolicy(User user, UserPolicy userPolicy, bool fireEvent) - { - // The xml serializer will output differently if the type is not exact - if (userPolicy.GetType() != typeof(UserPolicy)) - { - var json = _jsonSerializer.SerializeToString(userPolicy); - userPolicy = _jsonSerializer.DeserializeFromString<UserPolicy>(json); - } - - var path = GetPolifyFilePath(user); - - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - - lock (_policySyncLock) - { - _xmlSerializer.SerializeToFile(userPolicy, path); - user.Policy = userPolicy; - } - - await UpdateConfiguration(user, user.Configuration, true).ConfigureAwait(false); - } - - private void DeleteUserPolicy(User user) - { - var path = GetPolifyFilePath(user); - - try - { - lock (_policySyncLock) - { - _fileSystem.DeleteFile(path); - } - } - catch (IOException) - { - - } - catch (Exception ex) - { - _logger.ErrorException("Error deleting policy file", ex); - } - } - - private string GetPolifyFilePath(User user) - { - return Path.Combine(user.ConfigurationDirectoryPath, "policy.xml"); - } - - private string GetConfigurationFilePath(User user) - { - return Path.Combine(user.ConfigurationDirectoryPath, "config.xml"); - } - - public UserConfiguration GetUserConfiguration(User user) - { - var path = GetConfigurationFilePath(user); - - try - { - lock (_configSyncLock) - { - return (UserConfiguration)_xmlSerializer.DeserializeFromFile(typeof(UserConfiguration), path); - } - } - catch (DirectoryNotFoundException) - { - return new UserConfiguration(); - } - catch (FileNotFoundException) - { - return new UserConfiguration(); - } - catch (Exception ex) - { - _logger.ErrorException("Error reading policy file: {0}", ex, path); - - return new UserConfiguration(); - } - } - - private readonly object _configSyncLock = new object(); - public Task UpdateConfiguration(string userId, UserConfiguration config) - { - var user = GetUserById(userId); - return UpdateConfiguration(user, config, true); - } - - private async Task UpdateConfiguration(User user, UserConfiguration config, bool fireEvent) - { - var path = GetConfigurationFilePath(user); - - // The xml serializer will output differently if the type is not exact - if (config.GetType() != typeof(UserConfiguration)) - { - var json = _jsonSerializer.SerializeToString(config); - config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json); - } - - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - - lock (_configSyncLock) - { - _xmlSerializer.SerializeToFile(config, path); - user.Configuration = config; - } - - if (fireEvent) - { - EventHelper.FireEventIfNotNull(UserConfigurationUpdated, this, new GenericEventArgs<User> { Argument = user }, _logger); - } - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs deleted file mode 100644 index 2cbee7c97f..0000000000 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ /dev/null @@ -1,292 +0,0 @@ -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Localization; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Library; -using MediaBrowser.Model.Querying; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Entities.Audio; - -namespace MediaBrowser.Server.Implementations.Library -{ - public class UserViewManager : IUserViewManager - { - private readonly ILibraryManager _libraryManager; - private readonly ILocalizationManager _localizationManager; - private readonly IUserManager _userManager; - - private readonly IChannelManager _channelManager; - private readonly ILiveTvManager _liveTvManager; - private readonly IServerConfigurationManager _config; - - public UserViewManager(ILibraryManager libraryManager, ILocalizationManager localizationManager, IUserManager userManager, IChannelManager channelManager, ILiveTvManager liveTvManager, IServerConfigurationManager config) - { - _libraryManager = libraryManager; - _localizationManager = localizationManager; - _userManager = userManager; - _channelManager = channelManager; - _liveTvManager = liveTvManager; - _config = config; - } - - public async Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken) - { - var user = _userManager.GetUserById(query.UserId); - - var folders = user.RootFolder - .GetChildren(user, true) - .OfType<Folder>() - .ToList(); - - if (!query.IncludeHidden) - { - folders = folders.Where(i => - { - var hidden = i as IHiddenFromDisplay; - return hidden == null || !hidden.IsHiddenFromUser(user); - }).ToList(); - } - - var plainFolderIds = user.Configuration.PlainFolderViews.Select(i => new Guid(i)).ToList(); - - var groupedFolders = new List<ICollectionFolder>(); - - var list = new List<Folder>(); - - foreach (var folder in folders) - { - var collectionFolder = folder as ICollectionFolder; - var folderViewType = collectionFolder == null ? null : collectionFolder.CollectionType; - - if (UserView.IsUserSpecific(folder)) - { - list.Add(await _libraryManager.GetNamedView(user, folder.Name, folder.Id.ToString("N"), folderViewType, null, cancellationToken).ConfigureAwait(false)); - 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); - continue; - } - - if (query.PresetViews.Contains(folderViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) - { - list.Add(await GetUserView(folder, folderViewType, string.Empty, cancellationToken).ConfigureAwait(false)); - } - else - { - list.Add(folder); - } - } - - foreach (var viewType in new[] { CollectionType.Movies, CollectionType.TvShows }) - { - var parents = groupedFolders.Where(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.CollectionType)) - .ToList(); - - if (parents.Count > 0) - { - list.Add(await GetUserView(parents, viewType, string.Empty, user, query.PresetViews, cancellationToken).ConfigureAwait(false)); - } - } - - if (_config.Configuration.EnableFolderView) - { - var name = _localizationManager.GetLocalizedString("ViewType" + CollectionType.Folders); - list.Add(await _libraryManager.GetNamedView(name, CollectionType.Folders, string.Empty, cancellationToken).ConfigureAwait(false)); - } - - if (query.IncludeExternalContent) - { - var channelResult = await _channelManager.GetChannelsInternal(new ChannelQuery - { - UserId = query.UserId - - }, cancellationToken).ConfigureAwait(false); - - var channels = channelResult.Items; - - if (_config.Configuration.EnableChannelView && channels.Length > 0) - { - list.Add(await _channelManager.GetInternalChannelFolder(cancellationToken).ConfigureAwait(false)); - } - else - { - list.AddRange(channels); - } - - if (_liveTvManager.GetEnabledUsers().Select(i => i.Id.ToString("N")).Contains(query.UserId)) - { - list.Add(await _liveTvManager.GetInternalLiveTvFolder(CancellationToken.None).ConfigureAwait(false)); - } - } - - var sorted = _libraryManager.Sort(list, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList(); - - var orders = user.Configuration.OrderedViews.ToList(); - - return list - .OrderBy(i => - { - var index = orders.IndexOf(i.Id.ToString("N")); - - if (index == -1) - { - var view = i as UserView; - if (view != null) - { - if (view.DisplayParentId != Guid.Empty) - { - index = orders.IndexOf(view.DisplayParentId.ToString("N")); - } - } - } - - return index == -1 ? int.MaxValue : index; - }) - .ThenBy(sorted.IndexOf) - .ThenBy(i => i.SortName); - } - - public Task<UserView> GetUserSubView(string name, string parentId, string type, string sortName, CancellationToken cancellationToken) - { - var uniqueId = parentId + "subview" + type; - - return _libraryManager.GetNamedView(name, parentId, type, sortName, uniqueId, cancellationToken); - } - - public Task<UserView> GetUserSubView(string parentId, string type, string sortName, CancellationToken cancellationToken) - { - var name = _localizationManager.GetLocalizedString("ViewType" + type); - - return GetUserSubView(name, parentId, type, sortName, cancellationToken); - } - - private async Task<Folder> GetUserView(List<ICollectionFolder> parents, string viewType, string sortName, User user, string[] presetViews, CancellationToken cancellationToken) - { - if (parents.Count == 1 && parents.All(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase))) - { - if (!presetViews.Contains(viewType, StringComparer.OrdinalIgnoreCase)) - { - return (Folder)parents[0]; - } - - return await GetUserView((Folder)parents[0], viewType, string.Empty, cancellationToken).ConfigureAwait(false); - } - - var name = _localizationManager.GetLocalizedString("ViewType" + viewType); - return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false); - } - - public Task<UserView> GetUserView(Folder parent, string viewType, string sortName, CancellationToken cancellationToken) - { - return _libraryManager.GetShadowView(parent, viewType, sortName, cancellationToken); - } - - public List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request) - { - var user = _userManager.GetUserById(request.UserId); - - var libraryItems = GetItemsForLatestItems(user, request); - - var list = new List<Tuple<BaseItem, List<BaseItem>>>(); - - foreach (var item in libraryItems) - { - // Only grab the index container for media - var container = item.IsFolder || !request.GroupItems ? null : item.LatestItemsIndexContainer; - - if (container == null) - { - list.Add(new Tuple<BaseItem, List<BaseItem>>(null, new List<BaseItem> { item })); - } - else - { - var current = list.FirstOrDefault(i => i.Item1 != null && i.Item1.Id == container.Id); - - if (current != null) - { - current.Item2.Add(item); - } - else - { - list.Add(new Tuple<BaseItem, List<BaseItem>>(container, new List<BaseItem> { item })); - } - } - - if (list.Count >= request.Limit) - { - break; - } - } - - return list; - } - - private IEnumerable<BaseItem> GetItemsForLatestItems(User user, LatestItemsQuery request) - { - var parentId = request.ParentId; - - var includeItemTypes = request.IncludeItemTypes; - var limit = request.Limit ?? 10; - - var parentIds = string.IsNullOrEmpty(parentId) - ? new string[] { } - : new[] { parentId }; - - if (parentIds.Length == 0) - { - parentIds = user.RootFolder.GetChildren(user, true) - .OfType<Folder>() - .Select(i => i.Id.ToString("N")) - .Where(i => !user.Configuration.LatestItemsExcludes.Contains(i)) - .ToArray(); - } - - if (parentIds.Length == 0) - { - return new List<BaseItem>(); - } - - var excludeItemTypes = includeItemTypes.Length == 0 ? new[] - { - typeof(Person).Name, - typeof(Studio).Name, - typeof(Year).Name, - typeof(GameGenre).Name, - typeof(MusicGenre).Name, - typeof(Genre).Name - - } : new string[] { }; - - return _libraryManager.GetItemList(new InternalItemsQuery(user) - { - IncludeItemTypes = includeItemTypes, - SortOrder = SortOrder.Descending, - SortBy = new[] { ItemSortBy.DateCreated }, - IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null, - ExcludeItemTypes = excludeItemTypes, - ExcludeLocationTypes = new[] { LocationType.Virtual }, - Limit = limit * 5, - SourceTypes = parentIds.Length == 0 ? new[] { SourceType.Library } : new SourceType[] { }, - IsPlayed = request.IsPlayed - - }, parentIds); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs deleted file mode 100644 index 91b035a350..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs +++ /dev/null @@ -1,44 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Persistence; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - /// <summary> - /// Class ArtistsPostScanTask - /// </summary> - public class ArtistsPostScanTask : ILibraryPostScanTask - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - - /// <summary> - /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class. - /// </summary> - /// <param name="libraryManager">The library manager.</param> - public ArtistsPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - return new ArtistsValidator(_libraryManager, _logger, _itemRepo).Run(progress, cancellationToken); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs deleted file mode 100644 index 3dcdbeae9d..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs +++ /dev/null @@ -1,84 +0,0 @@ -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Persistence; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - /// <summary> - /// Class ArtistsValidator - /// </summary> - public class ArtistsValidator - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - - /// <summary> - /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class. - /// </summary> - /// <param name="libraryManager">The library manager.</param> - /// <param name="logger">The logger.</param> - public ArtistsValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - var names = _itemRepo.GetAllArtistNames(); - - var numComplete = 0; - var count = names.Count; - - foreach (var name in names) - { - try - { - var item = _libraryManager.GetArtist(name); - - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - // Don't clutter the log - break; - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing {0}", ex, name); - } - - numComplete++; - double percent = numComplete; - percent /= count; - percent *= 100; - - progress.Report(percent); - } - - progress.Report(100); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs deleted file mode 100644 index f3891180e2..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Persistence; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - /// <summary> - /// Class GameGenresPostScanTask - /// </summary> - public class GameGenresPostScanTask : ILibraryPostScanTask - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - - /// <summary> - /// Initializes a new instance of the <see cref="GameGenresPostScanTask" /> class. - /// </summary> - /// <param name="libraryManager">The library manager.</param> - /// <param name="logger">The logger.</param> - public GameGenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - return new GameGenresValidator(_libraryManager, _logger, _itemRepo).Run(progress, cancellationToken); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs deleted file mode 100644 index b06c0b3b9b..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs +++ /dev/null @@ -1,74 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Persistence; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - class GameGenresValidator - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - - public GameGenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - var names = _itemRepo.GetGameGenreNames(); - - var numComplete = 0; - var count = names.Count; - - foreach (var name in names) - { - try - { - var item = _libraryManager.GetGameGenre(name); - - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - // Don't clutter the log - break; - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing {0}", ex, name); - } - - numComplete++; - double percent = numComplete; - percent /= count; - percent *= 100; - - progress.Report(percent); - } - - progress.Report(100); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs deleted file mode 100644 index ed2429769c..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/GenresPostScanTask.cs +++ /dev/null @@ -1,42 +0,0 @@ -using MediaBrowser.Controller.Library; -using System; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - public class GenresPostScanTask : ILibraryPostScanTask - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - - /// <summary> - /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class. - /// </summary> - /// <param name="libraryManager">The library manager.</param> - /// <param name="logger">The logger.</param> - public GenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - return new GenresValidator(_libraryManager, _logger, _itemRepo).Run(progress, cancellationToken); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs deleted file mode 100644 index f35bb51363..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs +++ /dev/null @@ -1,75 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Persistence; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - class GenresValidator - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - private readonly IItemRepository _itemRepo; - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - public GenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - var names = _itemRepo.GetGenreNames(); - - var numComplete = 0; - var count = names.Count; - - foreach (var name in names) - { - try - { - var item = _libraryManager.GetGenre(name); - - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - // Don't clutter the log - break; - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing {0}", ex, name); - } - - numComplete++; - double percent = numComplete; - percent /= count; - percent *= 100; - - progress.Report(percent); - } - - progress.Report(100); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs deleted file mode 100644 index 777532ff87..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Persistence; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - /// <summary> - /// Class MusicGenresPostScanTask - /// </summary> - public class MusicGenresPostScanTask : ILibraryPostScanTask - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - - /// <summary> - /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class. - /// </summary> - /// <param name="libraryManager">The library manager.</param> - /// <param name="logger">The logger.</param> - public MusicGenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - return new MusicGenresValidator(_libraryManager, _logger, _itemRepo).Run(progress, cancellationToken); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs deleted file mode 100644 index 2be99f106e..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs +++ /dev/null @@ -1,75 +0,0 @@ -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Persistence; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - class MusicGenresValidator - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - - public MusicGenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - var names = _itemRepo.GetMusicGenreNames(); - - var numComplete = 0; - var count = names.Count; - - foreach (var name in names) - { - try - { - var item = _libraryManager.GetMusicGenre(name); - - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - // Don't clutter the log - break; - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing {0}", ex, name); - } - - numComplete++; - double percent = numComplete; - percent /= count; - percent *= 100; - - progress.Report(percent); - } - - progress.Report(100); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs deleted file mode 100644 index 93b9c0da1e..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs +++ /dev/null @@ -1,170 +0,0 @@ -using MediaBrowser.Common.Progress; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - /// <summary> - /// Class PeopleValidator - /// </summary> - public class PeopleValidator - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - private readonly IServerConfigurationManager _config; - private readonly IFileSystem _fileSystem; - - /// <summary> - /// Initializes a new instance of the <see cref="PeopleValidator" /> class. - /// </summary> - /// <param name="libraryManager">The library manager.</param> - /// <param name="logger">The logger.</param> - public PeopleValidator(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem) - { - _libraryManager = libraryManager; - _logger = logger; - _config = config; - _fileSystem = fileSystem; - } - - private bool DownloadMetadata(PersonInfo i, PeopleMetadataOptions options) - { - if (i.IsType(PersonType.Actor)) - { - return options.DownloadActorMetadata; - } - if (i.IsType(PersonType.Director)) - { - return options.DownloadDirectorMetadata; - } - if (i.IsType(PersonType.Composer)) - { - return options.DownloadComposerMetadata; - } - if (i.IsType(PersonType.Writer)) - { - return options.DownloadWriterMetadata; - } - if (i.IsType(PersonType.Producer)) - { - return options.DownloadProducerMetadata; - } - if (i.IsType(PersonType.GuestStar)) - { - return options.DownloadGuestStarMetadata; - } - - return options.DownloadOtherPeopleMetadata; - } - - /// <summary> - /// Validates the people. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public async Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress) - { - var innerProgress = new ActionableProgress<double>(); - - innerProgress.RegisterAction(pct => progress.Report(pct * .15)); - - var peopleOptions = _config.Configuration.PeopleMetadataOptions; - - var people = _libraryManager.GetPeople(new InternalPeopleQuery()); - - var dict = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase); - - foreach (var person in people) - { - var isMetadataEnabled = DownloadMetadata(person, peopleOptions); - - bool currentValue; - if (dict.TryGetValue(person.Name, out currentValue)) - { - if (!currentValue && isMetadataEnabled) - { - dict[person.Name] = true; - } - } - else - { - dict[person.Name] = isMetadataEnabled; - } - } - - var numComplete = 0; - - _logger.Debug("Will refresh {0} people", dict.Count); - - var numPeople = dict.Count; - - foreach (var person in dict) - { - cancellationToken.ThrowIfCancellationRequested(); - - try - { - var item = _libraryManager.GetPerson(person.Key); - - var hasMetdata = !string.IsNullOrWhiteSpace(item.Overview); - var performFullRefresh = !hasMetdata && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= 30; - - var defaultMetadataRefreshMode = performFullRefresh - ? MetadataRefreshMode.FullRefresh - : MetadataRefreshMode.Default; - - var imageRefreshMode = performFullRefresh - ? ImageRefreshMode.FullRefresh - : ImageRefreshMode.Default; - - var options = new MetadataRefreshOptions(_fileSystem) - { - MetadataRefreshMode = person.Value ? defaultMetadataRefreshMode : MetadataRefreshMode.ValidationOnly, - ImageRefreshMode = person.Value ? imageRefreshMode : ImageRefreshMode.ValidationOnly, - ForceSave = performFullRefresh - }; - - await item.RefreshMetadata(options, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error validating IBN entry {0}", ex, person); - } - - // Update progress - numComplete++; - double percent = numComplete; - percent /= numPeople; - - progress.Report(100 * percent); - } - - progress.Report(100); - - _logger.Info("People validation complete"); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/StudiosPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/StudiosPostScanTask.cs deleted file mode 100644 index 77c6d51465..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/StudiosPostScanTask.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Persistence; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - /// <summary> - /// Class MusicGenresPostScanTask - /// </summary> - public class StudiosPostScanTask : ILibraryPostScanTask - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - - /// <summary> - /// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class. - /// </summary> - /// <param name="libraryManager">The library manager.</param> - public StudiosPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - return new StudiosValidator(_libraryManager, _logger, _itemRepo).Run(progress, cancellationToken); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs deleted file mode 100644 index a19b8158a0..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs +++ /dev/null @@ -1,74 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Persistence; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - class StudiosValidator - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - - private readonly IItemRepository _itemRepo; - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - public StudiosValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - var names = _itemRepo.GetStudioNames(); - - var numComplete = 0; - var count = names.Count; - - foreach (var name in names) - { - try - { - var item = _libraryManager.GetStudio(name); - - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - // Don't clutter the log - break; - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing {0}", ex, name); - } - - numComplete++; - double percent = numComplete; - percent /= count; - percent *= 100; - - progress.Report(percent); - } - - progress.Report(100); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs deleted file mode 100644 index 164b142234..0000000000 --- a/MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs +++ /dev/null @@ -1,55 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Library.Validators -{ - public class YearsPostScanTask : ILibraryPostScanTask - { - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - - public YearsPostScanTask(ILibraryManager libraryManager, ILogger logger) - { - _libraryManager = libraryManager; - _logger = logger; - } - - public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - var yearNumber = 1900; - var maxYear = DateTime.UtcNow.Year + 3; - var count = maxYear - yearNumber + 1; - var numComplete = 0; - - while (yearNumber < maxYear) - { - try - { - var year = _libraryManager.GetYear(yearNumber); - - await year.RefreshMetadata(cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - // Don't clutter the log - break; - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing year {0}", ex, yearNumber); - } - - numComplete++; - double percent = numComplete; - percent /= count; - percent *= 100; - - progress.Report(percent); - yearNumber++; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs deleted file mode 100644 index 23560b1aa1..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs +++ /dev/null @@ -1,85 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.LiveTv -{ - public class ChannelImageProvider : IDynamicImageProvider, IHasItemChangeMonitor - { - private readonly ILiveTvManager _liveTvManager; - private readonly IHttpClient _httpClient; - private readonly ILogger _logger; - private readonly IApplicationHost _appHost; - - public ChannelImageProvider(ILiveTvManager liveTvManager, IHttpClient httpClient, ILogger logger, IApplicationHost appHost) - { - _liveTvManager = liveTvManager; - _httpClient = httpClient; - _logger = logger; - _appHost = appHost; - } - - public IEnumerable<ImageType> GetSupportedImages(IHasImages item) - { - return new[] { ImageType.Primary }; - } - - public async Task<DynamicImageResponse> GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken) - { - var liveTvItem = (LiveTvChannel)item; - - var imageResponse = new DynamicImageResponse(); - - var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, liveTvItem.ServiceName, StringComparison.OrdinalIgnoreCase)); - - if (service != null && !item.HasImage(ImageType.Primary)) - { - try - { - var response = await service.GetChannelImageAsync(liveTvItem.ExternalId, cancellationToken).ConfigureAwait(false); - - if (response != null) - { - imageResponse.HasImage = true; - imageResponse.Stream = response.Stream; - imageResponse.Format = response.Format; - } - } - catch (NotImplementedException) - { - } - } - - return imageResponse; - } - - public string Name - { - get { return "Live TV Service Provider"; } - } - - public bool Supports(IHasImages item) - { - return item is LiveTvChannel; - } - - public int Order - { - get { return 0; } - } - - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) - { - return GetSupportedImages(item).Any(i => !item.HasImage(i)); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs deleted file mode 100644 index 0f8c15e719..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV -{ - public class DirectRecorder : IRecorder - { - private readonly ILogger _logger; - private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; - - public DirectRecorder(ILogger logger, IHttpClient httpClient, IFileSystem fileSystem) - { - _logger = logger; - _httpClient = httpClient; - _fileSystem = fileSystem; - } - - public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile) - { - return targetFile; - } - - public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) - { - var httpRequestOptions = new HttpRequestOptions() - { - Url = mediaSource.Path - }; - - httpRequestOptions.BufferContent = false; - - using (var response = await _httpClient.SendAsync(httpRequestOptions, "GET").ConfigureAwait(false)) - { - _logger.Info("Opened recording stream from tuner provider"); - - using (var output = _fileSystem.GetFileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read)) - { - onStarted(); - - _logger.Info("Copying recording stream to file {0}", targetFile); - - // The media source if infinite so we need to handle stopping ourselves - var durationToken = new CancellationTokenSource(duration); - cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; - - await CopyUntilCancelled(response.Content, output, cancellationToken).ConfigureAwait(false); - } - } - - _logger.Info("Recording completed to file {0}", targetFile); - } - - private const int BufferSize = 81920; - public static Task CopyUntilCancelled(Stream source, Stream target, CancellationToken cancellationToken) - { - return CopyUntilCancelled(source, target, null, cancellationToken); - } - public static async Task CopyUntilCancelled(Stream source, Stream target, Action onStarted, CancellationToken cancellationToken) - { - while (!cancellationToken.IsCancellationRequested) - { - var bytesRead = await CopyToAsyncInternal(source, target, BufferSize, onStarted, cancellationToken).ConfigureAwait(false); - - onStarted = null; - - //var position = fs.Position; - //_logger.Debug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path); - - if (bytesRead == 0) - { - await Task.Delay(100).ConfigureAwait(false); - } - } - } - - private static async Task<int> CopyToAsyncInternal(Stream source, Stream destination, Int32 bufferSize, Action onStarted, CancellationToken cancellationToken) - { - byte[] buffer = new byte[bufferSize]; - int bytesRead; - int totalBytesRead = 0; - - while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) - { - await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); - - totalBytesRead += bytesRead; - - if (onStarted != null) - { - onStarted(); - } - onStarted = null; - } - - return totalBytesRead; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs deleted file mode 100644 index 214bb87169..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ /dev/null @@ -1,1974 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Security; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Server.Implementations.FileOrganization; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Xml; -using CommonIO; -using MediaBrowser.Common.Events; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.FileOrganization; -using Microsoft.Win32; - -namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV -{ - public class EmbyTV : ILiveTvService, ISupportsDirectStreamProvider, ISupportsNewTimerIds, IDisposable - { - private readonly IServerApplicationHost _appHost; - private readonly ILogger _logger; - private readonly IHttpClient _httpClient; - private readonly IServerConfigurationManager _config; - private readonly IJsonSerializer _jsonSerializer; - - private readonly ItemDataProvider<SeriesTimerInfo> _seriesTimerProvider; - private readonly TimerManager _timerProvider; - - private readonly LiveTvManager _liveTvManager; - private readonly IFileSystem _fileSystem; - - private readonly ILibraryMonitor _libraryMonitor; - private readonly ILibraryManager _libraryManager; - private readonly IProviderManager _providerManager; - private readonly IFileOrganizationService _organizationService; - private readonly IMediaEncoder _mediaEncoder; - - public static EmbyTV Current; - - public event EventHandler DataSourceChanged; - public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged; - - private readonly ConcurrentDictionary<string, ActiveRecordingInfo> _activeRecordings = - new ConcurrentDictionary<string, ActiveRecordingInfo>(StringComparer.OrdinalIgnoreCase); - - public EmbyTV(IServerApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder) - { - Current = this; - - _appHost = appHost; - _logger = logger; - _httpClient = httpClient; - _config = config; - _fileSystem = fileSystem; - _libraryManager = libraryManager; - _libraryMonitor = libraryMonitor; - _providerManager = providerManager; - _organizationService = organizationService; - _mediaEncoder = mediaEncoder; - _liveTvManager = (LiveTvManager)liveTvManager; - _jsonSerializer = jsonSerializer; - - _seriesTimerProvider = new SeriesTimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers")); - _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger); - _timerProvider.TimerFired += _timerProvider_TimerFired; - - _config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; - } - - private void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) - { - if (string.Equals(e.Key, "livetv", StringComparison.OrdinalIgnoreCase)) - { - OnRecordingFoldersChanged(); - } - } - - public void Start() - { - _timerProvider.RestartTimers(); - - SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; - CreateRecordingFolders(); - } - - private void OnRecordingFoldersChanged() - { - CreateRecordingFolders(); - } - - internal void CreateRecordingFolders() - { - try - { - CreateRecordingFoldersInternal(); - } - catch (Exception ex) - { - _logger.ErrorException("Error creating recording folders", ex); - } - } - - internal void CreateRecordingFoldersInternal() - { - var recordingFolders = GetRecordingFolders(); - - var virtualFolders = _libraryManager.GetVirtualFolders() - .ToList(); - - var allExistingPaths = virtualFolders.SelectMany(i => i.Locations).ToList(); - - var pathsAdded = new List<string>(); - - foreach (var recordingFolder in recordingFolders) - { - var pathsToCreate = recordingFolder.Locations - .Where(i => !allExistingPaths.Contains(i, StringComparer.OrdinalIgnoreCase)) - .ToList(); - - if (pathsToCreate.Count == 0) - { - continue; - } - - var mediaPathInfos = pathsToCreate.Select(i => new MediaPathInfo { Path = i }).ToArray(); - - var libraryOptions = new LibraryOptions - { - PathInfos = mediaPathInfos - }; - try - { - _libraryManager.AddVirtualFolder(recordingFolder.Name, recordingFolder.CollectionType, libraryOptions, true); - } - catch (Exception ex) - { - _logger.ErrorException("Error creating virtual folder", ex); - } - - pathsAdded.AddRange(pathsToCreate); - } - - var config = GetConfiguration(); - - var pathsToRemove = config.MediaLocationsCreated - .Except(recordingFolders.SelectMany(i => i.Locations)) - .ToList(); - - if (pathsAdded.Count > 0 || pathsToRemove.Count > 0) - { - pathsAdded.InsertRange(0, config.MediaLocationsCreated); - config.MediaLocationsCreated = pathsAdded.Except(pathsToRemove).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); - _config.SaveConfiguration("livetv", config); - } - - foreach (var path in pathsToRemove) - { - RemovePathFromLibrary(path); - } - } - - private void RemovePathFromLibrary(string path) - { - _logger.Debug("Removing path from library: {0}", path); - - var requiresRefresh = false; - var virtualFolders = _libraryManager.GetVirtualFolders() - .ToList(); - - foreach (var virtualFolder in virtualFolders) - { - if (!virtualFolder.Locations.Contains(path, StringComparer.OrdinalIgnoreCase)) - { - continue; - } - - if (virtualFolder.Locations.Count == 1) - { - // remove entire virtual folder - try - { - _libraryManager.RemoveVirtualFolder(virtualFolder.Name, true); - } - catch (Exception ex) - { - _logger.ErrorException("Error removing virtual folder", ex); - } - } - else - { - try - { - _libraryManager.RemoveMediaPath(virtualFolder.Name, path); - requiresRefresh = true; - } - catch (Exception ex) - { - _logger.ErrorException("Error removing media path", ex); - } - } - } - - if (requiresRefresh) - { - _libraryManager.ValidateMediaLibrary(new Progress<Double>(), CancellationToken.None); - } - } - - void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) - { - _logger.Info("Power mode changed to {0}", e.Mode); - - if (e.Mode == PowerModes.Resume) - { - _timerProvider.RestartTimers(); - } - } - - public string Name - { - get { return "Emby"; } - } - - public string DataPath - { - get { return Path.Combine(_config.CommonApplicationPaths.DataPath, "livetv"); } - } - - private string DefaultRecordingPath - { - get - { - return Path.Combine(DataPath, "recordings"); - } - } - - private string RecordingPath - { - get - { - var path = GetConfiguration().RecordingPath; - - return string.IsNullOrWhiteSpace(path) - ? DefaultRecordingPath - : path; - } - } - - public string HomePageUrl - { - get { return "http://emby.media"; } - } - - public async Task<LiveTvServiceStatusInfo> GetStatusInfoAsync(CancellationToken cancellationToken) - { - var status = new LiveTvServiceStatusInfo(); - var list = new List<LiveTvTunerInfo>(); - - foreach (var hostInstance in _liveTvManager.TunerHosts) - { - try - { - var tuners = await hostInstance.GetTunerInfos(cancellationToken).ConfigureAwait(false); - - list.AddRange(tuners); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting tuners", ex); - } - } - - status.Tuners = list; - status.Status = LiveTvServiceStatus.Ok; - status.Version = _appHost.ApplicationVersion.ToString(); - status.IsVisible = false; - return status; - } - - public async Task RefreshSeriesTimers(CancellationToken cancellationToken, IProgress<double> progress) - { - var seriesTimers = await GetSeriesTimersAsync(cancellationToken).ConfigureAwait(false); - - List<ChannelInfo> channels = null; - - foreach (var timer in seriesTimers) - { - List<ProgramInfo> epgData; - - if (timer.RecordAnyChannel) - { - if (channels == null) - { - channels = (await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false)).ToList(); - } - var channelIds = channels.Select(i => i.Id).ToList(); - epgData = GetEpgDataForChannels(channelIds); - } - else - { - epgData = GetEpgDataForChannel(timer.ChannelId); - } - await UpdateTimersForSeriesTimer(epgData, timer, true).ConfigureAwait(false); - } - - var timers = await GetTimersAsync(cancellationToken).ConfigureAwait(false); - - foreach (var timer in timers.ToList()) - { - if (DateTime.UtcNow > timer.EndDate && !_activeRecordings.ContainsKey(timer.Id)) - { - OnTimerOutOfDate(timer); - } - } - } - - private void OnTimerOutOfDate(TimerInfo timer) - { - _timerProvider.Delete(timer); - } - - private async Task<IEnumerable<ChannelInfo>> GetChannelsAsync(bool enableCache, CancellationToken cancellationToken) - { - var list = new List<ChannelInfo>(); - - foreach (var hostInstance in _liveTvManager.TunerHosts) - { - try - { - var channels = await hostInstance.GetChannels(enableCache, cancellationToken).ConfigureAwait(false); - - list.AddRange(channels); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting channels", ex); - } - } - - foreach (var provider in GetListingProviders()) - { - var enabledChannels = list - .Where(i => IsListingProviderEnabledForTuner(provider.Item2, i.TunerHostId)) - .ToList(); - - if (enabledChannels.Count > 0) - { - try - { - await provider.Item1.AddMetadata(provider.Item2, enabledChannels, cancellationToken).ConfigureAwait(false); - } - catch (NotSupportedException) - { - - } - catch (Exception ex) - { - _logger.ErrorException("Error adding metadata", ex); - } - } - } - - return list; - } - - public async Task<List<ChannelInfo>> GetChannelsForListingsProvider(ListingsProviderInfo listingsProvider, CancellationToken cancellationToken) - { - var list = new List<ChannelInfo>(); - - foreach (var hostInstance in _liveTvManager.TunerHosts) - { - try - { - var channels = await hostInstance.GetChannels(false, cancellationToken).ConfigureAwait(false); - - list.AddRange(channels); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting channels", ex); - } - } - - return list - .Where(i => IsListingProviderEnabledForTuner(listingsProvider, i.TunerHostId)) - .ToList(); - } - - public Task<IEnumerable<ChannelInfo>> GetChannelsAsync(CancellationToken cancellationToken) - { - return GetChannelsAsync(false, cancellationToken); - } - - public Task CancelSeriesTimerAsync(string timerId, CancellationToken cancellationToken) - { - var timers = _timerProvider - .GetAll() - .Where(i => string.Equals(i.SeriesTimerId, timerId, StringComparison.OrdinalIgnoreCase)) - .ToList(); - - foreach (var timer in timers) - { - CancelTimerInternal(timer.Id, true); - } - - var remove = _seriesTimerProvider.GetAll().FirstOrDefault(r => string.Equals(r.Id, timerId, StringComparison.OrdinalIgnoreCase)); - if (remove != null) - { - _seriesTimerProvider.Delete(remove); - } - return Task.FromResult(true); - } - - private void CancelTimerInternal(string timerId, bool isSeriesCancelled) - { - var timer = _timerProvider.GetTimer(timerId); - if (timer != null) - { - if (string.IsNullOrWhiteSpace(timer.SeriesTimerId) || isSeriesCancelled) - { - _timerProvider.Delete(timer); - } - else - { - timer.Status = RecordingStatus.Cancelled; - _timerProvider.AddOrUpdate(timer, false); - } - } - ActiveRecordingInfo activeRecordingInfo; - - if (_activeRecordings.TryGetValue(timerId, out activeRecordingInfo)) - { - activeRecordingInfo.CancellationTokenSource.Cancel(); - } - } - - public Task CancelTimerAsync(string timerId, CancellationToken cancellationToken) - { - CancelTimerInternal(timerId, false); - return Task.FromResult(true); - } - - public Task DeleteRecordingAsync(string recordingId, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task CreateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public Task<string> CreateTimer(TimerInfo timer, CancellationToken cancellationToken) - { - var existingTimer = _timerProvider.GetAll() - .FirstOrDefault(i => string.Equals(timer.ProgramId, i.ProgramId, StringComparison.OrdinalIgnoreCase)); - - if (existingTimer != null) - { - if (existingTimer.Status == RecordingStatus.Cancelled || - existingTimer.Status == RecordingStatus.Completed) - { - existingTimer.Status = RecordingStatus.New; - _timerProvider.Update(existingTimer); - return Task.FromResult(existingTimer.Id); - } - else - { - throw new ArgumentException("A scheduled recording already exists for this program."); - } - } - - timer.Id = Guid.NewGuid().ToString("N"); - - ProgramInfo programInfo = null; - - if (!string.IsNullOrWhiteSpace(timer.ProgramId)) - { - programInfo = GetProgramInfoFromCache(timer.ChannelId, timer.ProgramId); - } - if (programInfo == null) - { - _logger.Info("Unable to find program with Id {0}. Will search using start date", timer.ProgramId); - programInfo = GetProgramInfoFromCache(timer.ChannelId, timer.StartDate); - } - - if (programInfo != null) - { - RecordingHelper.CopyProgramInfoToTimerInfo(programInfo, timer); - } - - _timerProvider.Add(timer); - return Task.FromResult(timer.Id); - } - - public async Task<string> CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken) - { - info.Id = Guid.NewGuid().ToString("N"); - - List<ProgramInfo> epgData; - if (info.RecordAnyChannel) - { - var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false); - var channelIds = channels.Select(i => i.Id).ToList(); - epgData = GetEpgDataForChannels(channelIds); - } - else - { - epgData = GetEpgDataForChannel(info.ChannelId); - } - - // populate info.seriesID - var program = epgData.FirstOrDefault(i => string.Equals(i.Id, info.ProgramId, StringComparison.OrdinalIgnoreCase)); - - if (program != null) - { - info.SeriesId = program.SeriesId; - } - else - { - throw new InvalidOperationException("SeriesId for program not found"); - } - - _seriesTimerProvider.Add(info); - await UpdateTimersForSeriesTimer(epgData, info, false).ConfigureAwait(false); - - return info.Id; - } - - public async Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken) - { - var instance = _seriesTimerProvider.GetAll().FirstOrDefault(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase)); - - if (instance != null) - { - instance.ChannelId = info.ChannelId; - instance.Days = info.Days; - instance.EndDate = info.EndDate; - instance.IsPostPaddingRequired = info.IsPostPaddingRequired; - instance.IsPrePaddingRequired = info.IsPrePaddingRequired; - instance.PostPaddingSeconds = info.PostPaddingSeconds; - instance.PrePaddingSeconds = info.PrePaddingSeconds; - instance.Priority = info.Priority; - instance.RecordAnyChannel = info.RecordAnyChannel; - instance.RecordAnyTime = info.RecordAnyTime; - instance.RecordNewOnly = info.RecordNewOnly; - instance.SkipEpisodesInLibrary = info.SkipEpisodesInLibrary; - instance.KeepUpTo = info.KeepUpTo; - instance.KeepUntil = info.KeepUntil; - instance.StartDate = info.StartDate; - - _seriesTimerProvider.Update(instance); - - List<ProgramInfo> epgData; - if (instance.RecordAnyChannel) - { - var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false); - var channelIds = channels.Select(i => i.Id).ToList(); - epgData = GetEpgDataForChannels(channelIds); - } - else - { - epgData = GetEpgDataForChannel(instance.ChannelId); - } - - await UpdateTimersForSeriesTimer(epgData, instance, true).ConfigureAwait(false); - } - } - - public Task UpdateTimerAsync(TimerInfo updatedTimer, CancellationToken cancellationToken) - { - var existingTimer = _timerProvider.GetTimer(updatedTimer.Id); - - if (existingTimer == null) - { - throw new ResourceNotFoundException(); - } - - // Only update if not currently active - ActiveRecordingInfo activeRecordingInfo; - if (!_activeRecordings.TryGetValue(updatedTimer.Id, out activeRecordingInfo)) - { - existingTimer.PrePaddingSeconds = updatedTimer.PrePaddingSeconds; - existingTimer.PostPaddingSeconds = updatedTimer.PostPaddingSeconds; - existingTimer.IsPostPaddingRequired = updatedTimer.IsPostPaddingRequired; - existingTimer.IsPrePaddingRequired = updatedTimer.IsPrePaddingRequired; - } - - return Task.FromResult(true); - } - - private void UpdateExistingTimerWithNewMetadata(TimerInfo existingTimer, TimerInfo updatedTimer) - { - // Update the program info but retain the status - existingTimer.ChannelId = updatedTimer.ChannelId; - existingTimer.CommunityRating = updatedTimer.CommunityRating; - existingTimer.EndDate = updatedTimer.EndDate; - existingTimer.EpisodeNumber = updatedTimer.EpisodeNumber; - existingTimer.EpisodeTitle = updatedTimer.EpisodeTitle; - existingTimer.Genres = updatedTimer.Genres; - existingTimer.HomePageUrl = updatedTimer.HomePageUrl; - existingTimer.IsKids = updatedTimer.IsKids; - existingTimer.IsNews = updatedTimer.IsNews; - existingTimer.IsMovie = updatedTimer.IsMovie; - existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries; - existingTimer.IsRepeat = updatedTimer.IsRepeat; - existingTimer.IsSports = updatedTimer.IsSports; - existingTimer.Name = updatedTimer.Name; - existingTimer.OfficialRating = updatedTimer.OfficialRating; - existingTimer.OriginalAirDate = updatedTimer.OriginalAirDate; - existingTimer.Overview = updatedTimer.Overview; - existingTimer.ProductionYear = updatedTimer.ProductionYear; - existingTimer.ProgramId = updatedTimer.ProgramId; - existingTimer.SeasonNumber = updatedTimer.SeasonNumber; - existingTimer.ShortOverview = updatedTimer.ShortOverview; - existingTimer.StartDate = updatedTimer.StartDate; - } - - public Task<ImageStream> GetChannelImageAsync(string channelId, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public Task<ImageStream> GetRecordingImageAsync(string recordingId, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public Task<ImageStream> GetProgramImageAsync(string programId, string channelId, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public async Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken) - { - return _activeRecordings.Values.ToList().Select(GetRecordingInfo).ToList(); - } - - public string GetActiveRecordingPath(string id) - { - ActiveRecordingInfo info; - - if (_activeRecordings.TryGetValue(id, out info)) - { - return info.Path; - } - return null; - } - - private RecordingInfo GetRecordingInfo(ActiveRecordingInfo info) - { - var timer = info.Timer; - var program = info.Program; - - var result = new RecordingInfo - { - ChannelId = timer.ChannelId, - CommunityRating = timer.CommunityRating, - DateLastUpdated = DateTime.UtcNow, - EndDate = timer.EndDate, - EpisodeTitle = timer.EpisodeTitle, - Genres = timer.Genres, - Id = "recording" + timer.Id, - IsKids = timer.IsKids, - IsMovie = timer.IsMovie, - IsNews = timer.IsNews, - IsRepeat = timer.IsRepeat, - IsSeries = timer.IsProgramSeries, - IsSports = timer.IsSports, - Name = timer.Name, - OfficialRating = timer.OfficialRating, - OriginalAirDate = timer.OriginalAirDate, - Overview = timer.Overview, - ProgramId = timer.ProgramId, - SeriesTimerId = timer.SeriesTimerId, - StartDate = timer.StartDate, - Status = RecordingStatus.InProgress, - TimerId = timer.Id - }; - - if (program != null) - { - result.Audio = program.Audio; - result.ImagePath = program.ImagePath; - result.ImageUrl = program.ImageUrl; - result.IsHD = program.IsHD; - result.IsLive = program.IsLive; - result.IsPremiere = program.IsPremiere; - result.ShowId = program.ShowId; - } - - return result; - } - - public Task<IEnumerable<TimerInfo>> GetTimersAsync(CancellationToken cancellationToken) - { - var excludeStatues = new List<RecordingStatus> - { - RecordingStatus.Completed - }; - - var timers = _timerProvider.GetAll() - .Where(i => !excludeStatues.Contains(i.Status)); - - return Task.FromResult(timers); - } - - public Task<SeriesTimerInfo> GetNewTimerDefaultsAsync(CancellationToken cancellationToken, ProgramInfo program = null) - { - var config = GetConfiguration(); - - var defaults = new SeriesTimerInfo() - { - PostPaddingSeconds = Math.Max(config.PostPaddingSeconds, 0), - PrePaddingSeconds = Math.Max(config.PrePaddingSeconds, 0), - RecordAnyChannel = false, - RecordAnyTime = true, - RecordNewOnly = true, - - Days = new List<DayOfWeek> - { - DayOfWeek.Sunday, - DayOfWeek.Monday, - DayOfWeek.Tuesday, - DayOfWeek.Wednesday, - DayOfWeek.Thursday, - DayOfWeek.Friday, - DayOfWeek.Saturday - } - }; - - if (program != null) - { - defaults.SeriesId = program.SeriesId; - defaults.ProgramId = program.Id; - defaults.RecordNewOnly = !program.IsRepeat; - } - - defaults.SkipEpisodesInLibrary = defaults.RecordNewOnly; - defaults.KeepUntil = KeepUntil.UntilDeleted; - - return Task.FromResult(defaults); - } - - public Task<IEnumerable<SeriesTimerInfo>> GetSeriesTimersAsync(CancellationToken cancellationToken) - { - return Task.FromResult((IEnumerable<SeriesTimerInfo>)_seriesTimerProvider.GetAll()); - } - - public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) - { - try - { - return await GetProgramsAsyncInternal(channelId, startDateUtc, endDateUtc, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error getting programs", ex); - return GetEpgDataForChannel(channelId).Where(i => i.StartDate <= endDateUtc && i.EndDate >= startDateUtc); - } - } - - private bool IsListingProviderEnabledForTuner(ListingsProviderInfo info, string tunerHostId) - { - if (info.EnableAllTuners) - { - return true; - } - - if (string.IsNullOrWhiteSpace(tunerHostId)) - { - throw new ArgumentNullException("tunerHostId"); - } - - return info.EnabledTuners.Contains(tunerHostId, StringComparer.OrdinalIgnoreCase); - } - - private async Task<IEnumerable<ProgramInfo>> GetProgramsAsyncInternal(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) - { - var channels = await GetChannelsAsync(true, cancellationToken).ConfigureAwait(false); - var channel = channels.First(i => string.Equals(i.Id, channelId, StringComparison.OrdinalIgnoreCase)); - - foreach (var provider in GetListingProviders()) - { - if (!IsListingProviderEnabledForTuner(provider.Item2, channel.TunerHostId)) - { - _logger.Debug("Skipping getting programs for channel {0}-{1} from {2}-{3}, because it's not enabled for this tuner.", channel.Number, channel.Name, provider.Item1.Name, provider.Item2.ListingsId ?? string.Empty); - continue; - } - - _logger.Debug("Getting programs for channel {0}-{1} from {2}-{3}", channel.Number, channel.Name, provider.Item1.Name, provider.Item2.ListingsId ?? string.Empty); - - var channelMappings = GetChannelMappings(provider.Item2); - var channelNumber = channel.Number; - string mappedChannelNumber; - if (channelMappings.TryGetValue(channelNumber, out mappedChannelNumber)) - { - _logger.Debug("Found mapped channel on provider {0}. Tuner channel number: {1}, Mapped channel number: {2}", provider.Item1.Name, channelNumber, mappedChannelNumber); - channelNumber = mappedChannelNumber; - } - - var programs = await provider.Item1.GetProgramsAsync(provider.Item2, channelNumber, channel.Name, startDateUtc, endDateUtc, cancellationToken) - .ConfigureAwait(false); - - var list = programs.ToList(); - - // Replace the value that came from the provider with a normalized value - foreach (var program in list) - { - program.ChannelId = channelId; - } - - if (list.Count > 0) - { - SaveEpgDataForChannel(channelId, list); - - return list; - } - } - - return new List<ProgramInfo>(); - } - - private Dictionary<string, string> GetChannelMappings(ListingsProviderInfo info) - { - var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - - foreach (var mapping in info.ChannelMappings) - { - dict[mapping.Name] = mapping.Value; - } - - return dict; - } - - private List<Tuple<IListingsProvider, ListingsProviderInfo>> GetListingProviders() - { - return GetConfiguration().ListingProviders - .Select(i => - { - var provider = _liveTvManager.ListingProviders.FirstOrDefault(l => string.Equals(l.Type, i.Type, StringComparison.OrdinalIgnoreCase)); - - return provider == null ? null : new Tuple<IListingsProvider, ListingsProviderInfo>(provider, i); - }) - .Where(i => i != null) - .ToList(); - } - - public Task<MediaSourceInfo> GetRecordingStream(string recordingId, string streamId, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - private readonly SemaphoreSlim _liveStreamsSemaphore = new SemaphoreSlim(1, 1); - private readonly List<LiveStream> _liveStreams = new List<LiveStream>(); - - public async Task<MediaSourceInfo> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken) - { - var result = await GetChannelStreamWithDirectStreamProvider(channelId, streamId, cancellationToken).ConfigureAwait(false); - - return result.Item1; - } - - public async Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetChannelStreamWithDirectStreamProvider(string channelId, string streamId, CancellationToken cancellationToken) - { - var result = await GetChannelStreamInternal(channelId, streamId, cancellationToken).ConfigureAwait(false); - - return new Tuple<MediaSourceInfo, IDirectStreamProvider>(result.Item2, result.Item1 as IDirectStreamProvider); - } - - private MediaSourceInfo CloneMediaSource(MediaSourceInfo mediaSource, bool enableStreamSharing) - { - var json = _jsonSerializer.SerializeToString(mediaSource); - mediaSource = _jsonSerializer.DeserializeFromString<MediaSourceInfo>(json); - - mediaSource.Id = Guid.NewGuid().ToString("N") + "_" + mediaSource.Id; - - //if (mediaSource.DateLiveStreamOpened.HasValue && enableStreamSharing) - //{ - // var ticks = (DateTime.UtcNow - mediaSource.DateLiveStreamOpened.Value).Ticks - TimeSpan.FromSeconds(10).Ticks; - // ticks = Math.Max(0, ticks); - // mediaSource.Path += "?t=" + ticks.ToString(CultureInfo.InvariantCulture) + "&s=" + mediaSource.DateLiveStreamOpened.Value.Ticks.ToString(CultureInfo.InvariantCulture); - //} - - return mediaSource; - } - - public async Task<LiveStream> GetLiveStream(string uniqueId) - { - await _liveStreamsSemaphore.WaitAsync().ConfigureAwait(false); - - try - { - return _liveStreams - .FirstOrDefault(i => string.Equals(i.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase)); - } - finally - { - _liveStreamsSemaphore.Release(); - } - - } - - private async Task<Tuple<LiveStream, MediaSourceInfo, ITunerHost>> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken) - { - _logger.Info("Streaming Channel " + channelId); - - await _liveStreamsSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - - var result = _liveStreams.FirstOrDefault(i => string.Equals(i.OriginalStreamId, streamId, StringComparison.OrdinalIgnoreCase)); - - if (result != null && result.EnableStreamSharing) - { - var openedMediaSource = CloneMediaSource(result.OpenedMediaSource, result.EnableStreamSharing); - result.SharedStreamIds.Add(openedMediaSource.Id); - _liveStreamsSemaphore.Release(); - - _logger.Info("Live stream {0} consumer count is now {1}", streamId, result.ConsumerCount); - - return new Tuple<LiveStream, MediaSourceInfo, ITunerHost>(result, openedMediaSource, result.TunerHost); - } - - try - { - foreach (var hostInstance in _liveTvManager.TunerHosts) - { - try - { - result = await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false); - - var openedMediaSource = CloneMediaSource(result.OpenedMediaSource, result.EnableStreamSharing); - - result.SharedStreamIds.Add(openedMediaSource.Id); - _liveStreams.Add(result); - - result.TunerHost = hostInstance; - result.OriginalStreamId = streamId; - - _logger.Info("Returning mediasource streamId {0}, mediaSource.Id {1}, mediaSource.LiveStreamId {2}", - streamId, openedMediaSource.Id, openedMediaSource.LiveStreamId); - - return new Tuple<LiveStream, MediaSourceInfo, ITunerHost>(result, openedMediaSource, hostInstance); - } - catch (FileNotFoundException) - { - } - catch (OperationCanceledException) - { - } - } - } - finally - { - _liveStreamsSemaphore.Release(); - } - - throw new ApplicationException("Tuner not found."); - } - - public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken) - { - foreach (var hostInstance in _liveTvManager.TunerHosts) - { - try - { - var sources = await hostInstance.GetChannelStreamMediaSources(channelId, cancellationToken).ConfigureAwait(false); - - if (sources.Count > 0) - { - return sources; - } - } - catch (NotImplementedException) - { - - } - } - - throw new NotImplementedException(); - } - - public async Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken) - { - ActiveRecordingInfo info; - - recordingId = recordingId.Replace("recording", string.Empty); - - if (_activeRecordings.TryGetValue(recordingId, out info)) - { - var stream = new MediaSourceInfo - { - Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveRecordings/" + recordingId + "/stream", - Id = recordingId, - SupportsDirectPlay = false, - SupportsDirectStream = true, - SupportsTranscoding = true, - IsInfiniteStream = true, - RequiresOpening = false, - RequiresClosing = false, - Protocol = Model.MediaInfo.MediaProtocol.Http, - BufferMs = 0 - }; - - var isAudio = false; - await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false); - - return new List<MediaSourceInfo> - { - stream - }; - } - - throw new FileNotFoundException(); - } - - public async Task CloseLiveStream(string id, CancellationToken cancellationToken) - { - // Ignore the consumer id - //id = id.Substring(id.IndexOf('_') + 1); - - await _liveStreamsSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - var stream = _liveStreams.FirstOrDefault(i => i.SharedStreamIds.Contains(id)); - if (stream != null) - { - stream.SharedStreamIds.Remove(id); - - _logger.Info("Live stream {0} consumer count is now {1}", id, stream.ConsumerCount); - - if (stream.ConsumerCount <= 0) - { - _liveStreams.Remove(stream); - - _logger.Info("Closing live stream {0}", id); - - await stream.Close().ConfigureAwait(false); - _logger.Info("Live stream {0} closed successfully", id); - } - } - else - { - _logger.Warn("Live stream not found: {0}, unable to close", id); - } - } - catch (OperationCanceledException) - { - } - catch (Exception ex) - { - _logger.ErrorException("Error closing live stream", ex); - } - finally - { - _liveStreamsSemaphore.Release(); - } - } - - public Task RecordLiveStream(string id, CancellationToken cancellationToken) - { - return Task.FromResult(0); - } - - public Task ResetTuner(string id, CancellationToken cancellationToken) - { - return Task.FromResult(0); - } - - async void _timerProvider_TimerFired(object sender, GenericEventArgs<TimerInfo> e) - { - var timer = e.Argument; - - _logger.Info("Recording timer fired."); - - try - { - var recordingEndDate = timer.EndDate.AddSeconds(timer.PostPaddingSeconds); - - if (recordingEndDate <= DateTime.UtcNow) - { - _logger.Warn("Recording timer fired for updatedTimer {0}, Id: {1}, but the program has already ended.", timer.Name, timer.Id); - OnTimerOutOfDate(timer); - return; - } - - var activeRecordingInfo = new ActiveRecordingInfo - { - CancellationTokenSource = new CancellationTokenSource(), - Timer = timer - }; - - if (_activeRecordings.TryAdd(timer.Id, activeRecordingInfo)) - { - await RecordStream(timer, recordingEndDate, activeRecordingInfo, activeRecordingInfo.CancellationTokenSource.Token).ConfigureAwait(false); - } - else - { - _logger.Info("Skipping RecordStream because it's already in progress."); - } - } - catch (OperationCanceledException) - { - - } - catch (Exception ex) - { - _logger.ErrorException("Error recording stream", ex); - } - } - - private string GetRecordingPath(TimerInfo timer, out string seriesPath) - { - var recordPath = RecordingPath; - var config = GetConfiguration(); - seriesPath = null; - - if (timer.IsProgramSeries) - { - var customRecordingPath = config.SeriesRecordingPath; - var allowSubfolder = true; - if (!string.IsNullOrWhiteSpace(customRecordingPath)) - { - allowSubfolder = string.Equals(customRecordingPath, recordPath, StringComparison.OrdinalIgnoreCase); - recordPath = customRecordingPath; - } - - if (allowSubfolder && config.EnableRecordingSubfolders) - { - recordPath = Path.Combine(recordPath, "Series"); - } - - var folderName = _fileSystem.GetValidFilename(timer.Name).Trim(); - - // Can't use the year here in the folder name because it is the year of the episode, not the series. - recordPath = Path.Combine(recordPath, folderName); - - seriesPath = recordPath; - - if (timer.SeasonNumber.HasValue) - { - folderName = string.Format("Season {0}", timer.SeasonNumber.Value.ToString(CultureInfo.InvariantCulture)); - recordPath = Path.Combine(recordPath, folderName); - } - } - else if (timer.IsMovie) - { - var customRecordingPath = config.MovieRecordingPath; - var allowSubfolder = true; - if (!string.IsNullOrWhiteSpace(customRecordingPath)) - { - allowSubfolder = string.Equals(customRecordingPath, recordPath, StringComparison.OrdinalIgnoreCase); - recordPath = customRecordingPath; - } - - if (allowSubfolder && config.EnableRecordingSubfolders) - { - recordPath = Path.Combine(recordPath, "Movies"); - } - - var folderName = _fileSystem.GetValidFilename(timer.Name).Trim(); - if (timer.ProductionYear.HasValue) - { - folderName += " (" + timer.ProductionYear.Value.ToString(CultureInfo.InvariantCulture) + ")"; - } - recordPath = Path.Combine(recordPath, folderName); - } - else if (timer.IsKids) - { - if (config.EnableRecordingSubfolders) - { - recordPath = Path.Combine(recordPath, "Kids"); - } - - var folderName = _fileSystem.GetValidFilename(timer.Name).Trim(); - if (timer.ProductionYear.HasValue) - { - folderName += " (" + timer.ProductionYear.Value.ToString(CultureInfo.InvariantCulture) + ")"; - } - recordPath = Path.Combine(recordPath, folderName); - } - else if (timer.IsSports) - { - if (config.EnableRecordingSubfolders) - { - recordPath = Path.Combine(recordPath, "Sports"); - } - recordPath = Path.Combine(recordPath, _fileSystem.GetValidFilename(timer.Name).Trim()); - } - else - { - if (config.EnableRecordingSubfolders) - { - recordPath = Path.Combine(recordPath, "Other"); - } - recordPath = Path.Combine(recordPath, _fileSystem.GetValidFilename(timer.Name).Trim()); - } - - var recordingFileName = _fileSystem.GetValidFilename(RecordingHelper.GetRecordingName(timer)).Trim() + ".ts"; - - return Path.Combine(recordPath, recordingFileName); - } - - private async Task RecordStream(TimerInfo timer, DateTime recordingEndDate, - ActiveRecordingInfo activeRecordingInfo, CancellationToken cancellationToken) - { - if (timer == null) - { - throw new ArgumentNullException("timer"); - } - - ProgramInfo programInfo = null; - - if (!string.IsNullOrWhiteSpace(timer.ProgramId)) - { - programInfo = GetProgramInfoFromCache(timer.ChannelId, timer.ProgramId); - } - if (programInfo == null) - { - _logger.Info("Unable to find program with Id {0}. Will search using start date", timer.ProgramId); - programInfo = GetProgramInfoFromCache(timer.ChannelId, timer.StartDate); - } - - if (programInfo != null) - { - RecordingHelper.CopyProgramInfoToTimerInfo(programInfo, timer); - activeRecordingInfo.Program = programInfo; - } - - string seriesPath = null; - var recordPath = GetRecordingPath(timer, out seriesPath); - var recordingStatus = RecordingStatus.New; - - string liveStreamId = null; - - OnRecordingStatusChanged(); - - try - { - var allMediaSources = await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false); - - var liveStreamInfo = await GetChannelStreamInternal(timer.ChannelId, allMediaSources[0].Id, CancellationToken.None) - .ConfigureAwait(false); - - var mediaStreamInfo = liveStreamInfo.Item2; - liveStreamId = mediaStreamInfo.Id; - - // HDHR doesn't seem to release the tuner right away after first probing with ffmpeg - //await Task.Delay(3000, cancellationToken).ConfigureAwait(false); - - var recorder = await GetRecorder().ConfigureAwait(false); - - recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath); - recordPath = EnsureFileUnique(recordPath, timer.Id); - - _libraryManager.RegisterIgnoredPath(recordPath); - _libraryMonitor.ReportFileSystemChangeBeginning(recordPath); - _fileSystem.CreateDirectory(Path.GetDirectoryName(recordPath)); - activeRecordingInfo.Path = recordPath; - - var duration = recordingEndDate - DateTime.UtcNow; - - _logger.Info("Beginning recording. Will record for {0} minutes.", - duration.TotalMinutes.ToString(CultureInfo.InvariantCulture)); - - _logger.Info("Writing file to path: " + recordPath); - _logger.Info("Opening recording stream from tuner provider"); - - Action onStarted = () => - { - timer.Status = RecordingStatus.InProgress; - _timerProvider.AddOrUpdate(timer, false); - - SaveNfo(timer, recordPath, seriesPath); - EnforceKeepUpTo(timer); - }; - - await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken) - .ConfigureAwait(false); - - recordingStatus = RecordingStatus.Completed; - _logger.Info("Recording completed: {0}", recordPath); - } - catch (OperationCanceledException) - { - _logger.Info("Recording stopped: {0}", recordPath); - recordingStatus = RecordingStatus.Completed; - } - catch (Exception ex) - { - _logger.ErrorException("Error recording to {0}", ex, recordPath); - recordingStatus = RecordingStatus.Error; - } - - if (!string.IsNullOrWhiteSpace(liveStreamId)) - { - try - { - await CloseLiveStream(liveStreamId, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error closing live stream", ex); - } - } - - _libraryManager.UnRegisterIgnoredPath(recordPath); - _libraryMonitor.ReportFileSystemChangeComplete(recordPath, true); - - ActiveRecordingInfo removed; - _activeRecordings.TryRemove(timer.Id, out removed); - - if (recordingStatus != RecordingStatus.Completed && DateTime.UtcNow < timer.EndDate) - { - const int retryIntervalSeconds = 60; - _logger.Info("Retrying recording in {0} seconds.", retryIntervalSeconds); - - timer.Status = RecordingStatus.New; - timer.StartDate = DateTime.UtcNow.AddSeconds(retryIntervalSeconds); - _timerProvider.AddOrUpdate(timer); - } - else if (File.Exists(recordPath)) - { - timer.RecordingPath = recordPath; - timer.Status = RecordingStatus.Completed; - _timerProvider.AddOrUpdate(timer, false); - OnSuccessfulRecording(timer, recordPath); - } - else - { - _timerProvider.Delete(timer); - } - - OnRecordingStatusChanged(); - } - - private void OnRecordingStatusChanged() - { - EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs - { - - }, _logger); - } - - private async void EnforceKeepUpTo(TimerInfo timer) - { - if (string.IsNullOrWhiteSpace(timer.SeriesTimerId)) - { - return; - } - - var seriesTimerId = timer.SeriesTimerId; - var seriesTimer = _seriesTimerProvider.GetAll().FirstOrDefault(i => string.Equals(i.Id, seriesTimerId, StringComparison.OrdinalIgnoreCase)); - - if (seriesTimer == null || seriesTimer.KeepUpTo <= 1) - { - return; - } - - if (_disposed) - { - return; - } - - await _recordingDeleteSemaphore.WaitAsync().ConfigureAwait(false); - - try - { - if (_disposed) - { - return; - } - - var timersToDelete = _timerProvider.GetAll() - .Where(i => i.Status == RecordingStatus.Completed && !string.IsNullOrWhiteSpace(i.RecordingPath)) - .Where(i => string.Equals(i.SeriesTimerId, seriesTimerId, StringComparison.OrdinalIgnoreCase)) - .OrderByDescending(i => i.EndDate) - .Where(i => File.Exists(i.RecordingPath)) - .Skip(seriesTimer.KeepUpTo - 1) - .ToList(); - - await DeleteLibraryItemsForTimers(timersToDelete).ConfigureAwait(false); - } - finally - { - _recordingDeleteSemaphore.Release(); - } - } - - private readonly SemaphoreSlim _recordingDeleteSemaphore = new SemaphoreSlim(1, 1); - private async Task DeleteLibraryItemsForTimers(List<TimerInfo> timers) - { - foreach (var timer in timers) - { - if (_disposed) - { - return; - } - - try - { - await DeleteLibraryItemForTimer(timer).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error deleting recording", ex); - } - } - } - - private async Task DeleteLibraryItemForTimer(TimerInfo timer) - { - var libraryItem = _libraryManager.FindByPath(timer.RecordingPath, false); - - if (libraryItem != null) - { - await _libraryManager.DeleteItem(libraryItem, new DeleteOptions - { - DeleteFileLocation = true - }); - } - else - { - try - { - File.Delete(timer.RecordingPath); - } - catch (DirectoryNotFoundException) - { - - } - catch (FileNotFoundException) - { - - } - } - - _timerProvider.Delete(timer); - } - - private string EnsureFileUnique(string path, string timerId) - { - var originalPath = path; - var index = 1; - - while (FileExists(path, timerId)) - { - var parent = Path.GetDirectoryName(originalPath); - var name = Path.GetFileNameWithoutExtension(originalPath); - name += "-" + index.ToString(CultureInfo.InvariantCulture); - - path = Path.ChangeExtension(Path.Combine(parent, name), Path.GetExtension(originalPath)); - index++; - } - - return path; - } - - private bool FileExists(string path, string timerId) - { - if (_fileSystem.FileExists(path)) - { - return true; - } - - var hasRecordingAtPath = _activeRecordings - .Values - .ToList() - .Any(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Timer.Id, timerId, StringComparison.OrdinalIgnoreCase)); - - if (hasRecordingAtPath) - { - return true; - } - return false; - } - - private async Task<IRecorder> GetRecorder() - { - var config = GetConfiguration(); - - if (config.EnableRecordingEncoding) - { - var regInfo = await _liveTvManager.GetRegistrationInfo("embytvrecordingconversion").ConfigureAwait(false); - - if (regInfo.IsValid) - { - return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config, _httpClient); - } - } - - return new DirectRecorder(_logger, _httpClient, _fileSystem); - } - - private async void OnSuccessfulRecording(TimerInfo timer, string path) - { - if (timer.IsProgramSeries && GetConfiguration().EnableAutoOrganize) - { - try - { - // this is to account for the library monitor holding a lock for additional time after the change is complete. - // ideally this shouldn't be hard-coded - await Task.Delay(30000).ConfigureAwait(false); - - var organize = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); - - var result = await organize.OrganizeEpisodeFile(path, _config.GetAutoOrganizeOptions(), false, CancellationToken.None).ConfigureAwait(false); - - if (result.Status == FileSortingStatus.Success) - { - return; - } - } - catch (Exception ex) - { - _logger.ErrorException("Error processing new recording", ex); - } - } - } - - private void SaveNfo(TimerInfo timer, string recordingPath, string seriesPath) - { - try - { - if (timer.IsProgramSeries) - { - SaveSeriesNfo(timer, recordingPath, seriesPath); - } - else if (!timer.IsMovie || timer.IsSports || timer.IsNews) - { - SaveVideoNfo(timer, recordingPath); - } - } - catch (Exception ex) - { - _logger.ErrorException("Error saving nfo", ex); - } - } - - private void SaveSeriesNfo(TimerInfo timer, string recordingPath, string seriesPath) - { - var nfoPath = Path.Combine(seriesPath, "tvshow.nfo"); - - if (File.Exists(nfoPath)) - { - return; - } - - using (var stream = _fileSystem.GetFileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.Read)) - { - var settings = new XmlWriterSettings - { - Indent = true, - Encoding = Encoding.UTF8, - CloseOutput = false - }; - - using (XmlWriter writer = XmlWriter.Create(stream, settings)) - { - writer.WriteStartDocument(true); - writer.WriteStartElement("tvshow"); - - if (!string.IsNullOrWhiteSpace(timer.Name)) - { - writer.WriteElementString("title", timer.Name); - } - - writer.WriteEndElement(); - writer.WriteEndDocument(); - } - } - } - - public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss"; - private void SaveVideoNfo(TimerInfo timer, string recordingPath) - { - var nfoPath = Path.ChangeExtension(recordingPath, ".nfo"); - - if (File.Exists(nfoPath)) - { - return; - } - - using (var stream = _fileSystem.GetFileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.Read)) - { - var settings = new XmlWriterSettings - { - Indent = true, - Encoding = Encoding.UTF8, - CloseOutput = false - }; - - using (XmlWriter writer = XmlWriter.Create(stream, settings)) - { - writer.WriteStartDocument(true); - writer.WriteStartElement("movie"); - - if (!string.IsNullOrWhiteSpace(timer.Name)) - { - writer.WriteElementString("title", timer.Name); - } - - writer.WriteElementString("dateadded", DateTime.UtcNow.ToLocalTime().ToString(DateAddedFormat)); - - if (timer.ProductionYear.HasValue) - { - writer.WriteElementString("year", timer.ProductionYear.Value.ToString(CultureInfo.InvariantCulture)); - } - if (!string.IsNullOrEmpty(timer.OfficialRating)) - { - writer.WriteElementString("mpaa", timer.OfficialRating); - } - - var overview = (timer.Overview ?? string.Empty) - .StripHtml() - .Replace(""", "'"); - - writer.WriteElementString("plot", overview); - writer.WriteElementString("lockdata", true.ToString().ToLower()); - - if (timer.CommunityRating.HasValue) - { - writer.WriteElementString("rating", timer.CommunityRating.Value.ToString(CultureInfo.InvariantCulture)); - } - - if (timer.IsSports) - { - AddGenre(timer.Genres, "Sports"); - } - if (timer.IsKids) - { - AddGenre(timer.Genres, "Kids"); - AddGenre(timer.Genres, "Children"); - } - if (timer.IsNews) - { - AddGenre(timer.Genres, "News"); - } - - foreach (var genre in timer.Genres) - { - writer.WriteElementString("genre", genre); - } - - if (!string.IsNullOrWhiteSpace(timer.ShortOverview)) - { - writer.WriteElementString("outline", timer.ShortOverview); - } - - if (!string.IsNullOrWhiteSpace(timer.HomePageUrl)) - { - writer.WriteElementString("website", timer.HomePageUrl); - } - - writer.WriteEndElement(); - writer.WriteEndDocument(); - } - } - } - - private void AddGenre(List<string> genres, string genre) - { - if (!genres.Contains(genre, StringComparer.OrdinalIgnoreCase)) - { - genres.Add(genre); - } - } - - private ProgramInfo GetProgramInfoFromCache(string channelId, string programId) - { - var epgData = GetEpgDataForChannel(channelId); - return epgData.FirstOrDefault(p => string.Equals(p.Id, programId, StringComparison.OrdinalIgnoreCase)); - } - - private ProgramInfo GetProgramInfoFromCache(string channelId, DateTime startDateUtc) - { - var epgData = GetEpgDataForChannel(channelId); - var startDateTicks = startDateUtc.Ticks; - // Find the first program that starts within 3 minutes - return epgData.FirstOrDefault(p => Math.Abs(startDateTicks - p.StartDate.Ticks) <= TimeSpan.FromMinutes(3).Ticks); - } - - private LiveTvOptions GetConfiguration() - { - return _config.GetConfiguration<LiveTvOptions>("livetv"); - } - - private bool ShouldCancelTimerForSeriesTimer(SeriesTimerInfo seriesTimer, TimerInfo timer) - { - if (!seriesTimer.RecordAnyTime) - { - if (Math.Abs(seriesTimer.StartDate.TimeOfDay.Ticks - timer.StartDate.TimeOfDay.Ticks) >= TimeSpan.FromMinutes(5).Ticks) - { - return true; - } - - if (!seriesTimer.Days.Contains(timer.StartDate.ToLocalTime().DayOfWeek)) - { - return true; - } - } - - if (seriesTimer.RecordNewOnly && timer.IsRepeat) - { - return true; - } - - if (!seriesTimer.RecordAnyChannel && !string.Equals(timer.ChannelId, seriesTimer.ChannelId, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - return seriesTimer.SkipEpisodesInLibrary && IsProgramAlreadyInLibrary(timer); - } - - private async Task UpdateTimersForSeriesTimer(List<ProgramInfo> epgData, SeriesTimerInfo seriesTimer, bool deleteInvalidTimers) - { - var allTimers = GetTimersForSeries(seriesTimer, epgData) - .ToList(); - - var registration = await _liveTvManager.GetRegistrationInfo("seriesrecordings").ConfigureAwait(false); - - if (registration.IsValid) - { - foreach (var timer in allTimers) - { - var existingTimer = _timerProvider.GetTimer(timer.Id); - - if (existingTimer == null) - { - if (ShouldCancelTimerForSeriesTimer(seriesTimer, timer)) - { - timer.Status = RecordingStatus.Cancelled; - } - _timerProvider.Add(timer); - } - else - { - // Only update if not currently active - ActiveRecordingInfo activeRecordingInfo; - if (!_activeRecordings.TryGetValue(timer.Id, out activeRecordingInfo)) - { - UpdateExistingTimerWithNewMetadata(existingTimer, timer); - - if (ShouldCancelTimerForSeriesTimer(seriesTimer, timer)) - { - existingTimer.Status = RecordingStatus.Cancelled; - } - - existingTimer.SeriesTimerId = seriesTimer.Id; - _timerProvider.Update(existingTimer); - } - } - } - } - - if (deleteInvalidTimers) - { - var allTimerIds = allTimers - .Select(i => i.Id) - .ToList(); - - var deleteStatuses = new List<RecordingStatus> - { - RecordingStatus.New - }; - - var deletes = _timerProvider.GetAll() - .Where(i => string.Equals(i.SeriesTimerId, seriesTimer.Id, StringComparison.OrdinalIgnoreCase)) - .Where(i => !allTimerIds.Contains(i.Id, StringComparer.OrdinalIgnoreCase) && i.StartDate > DateTime.UtcNow) - .Where(i => deleteStatuses.Contains(i.Status)) - .ToList(); - - foreach (var timer in deletes) - { - CancelTimerInternal(timer.Id, false); - } - } - } - - private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer, - IEnumerable<ProgramInfo> allPrograms) - { - if (seriesTimer == null) - { - throw new ArgumentNullException("seriesTimer"); - } - if (allPrograms == null) - { - throw new ArgumentNullException("allPrograms"); - } - - // Exclude programs that have already ended - allPrograms = allPrograms.Where(i => i.EndDate > DateTime.UtcNow); - - allPrograms = GetProgramsForSeries(seriesTimer, allPrograms); - - return allPrograms.Select(i => RecordingHelper.CreateTimer(i, seriesTimer)); - } - - private bool IsProgramAlreadyInLibrary(TimerInfo program) - { - if ((program.EpisodeNumber.HasValue && program.SeasonNumber.HasValue) || !string.IsNullOrWhiteSpace(program.EpisodeTitle)) - { - var seriesIds = _libraryManager.GetItemIds(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Series).Name }, - Name = program.Name - - }).Select(i => i.ToString("N")).ToArray(); - - if (seriesIds.Length == 0) - { - return false; - } - - if (program.EpisodeNumber.HasValue && program.SeasonNumber.HasValue) - { - var result = _libraryManager.GetItemsResult(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Episode).Name }, - ParentIndexNumber = program.SeasonNumber.Value, - IndexNumber = program.EpisodeNumber.Value, - AncestorIds = seriesIds, - IsVirtualItem = false - }); - - if (result.TotalRecordCount > 0) - { - return true; - } - } - } - - return false; - } - - private IEnumerable<ProgramInfo> GetProgramsForSeries(SeriesTimerInfo seriesTimer, IEnumerable<ProgramInfo> allPrograms) - { - if (string.IsNullOrWhiteSpace(seriesTimer.SeriesId)) - { - _logger.Error("seriesTimer.SeriesId is null. Cannot find programs for series"); - return new List<ProgramInfo>(); - } - - return allPrograms.Where(i => string.Equals(i.SeriesId, seriesTimer.SeriesId, StringComparison.OrdinalIgnoreCase)); - } - - private string GetChannelEpgCachePath(string channelId) - { - return Path.Combine(_config.CommonApplicationPaths.CachePath, "embytvepg", channelId + ".json"); - } - - private readonly object _epgLock = new object(); - private void SaveEpgDataForChannel(string channelId, List<ProgramInfo> epgData) - { - var path = GetChannelEpgCachePath(channelId); - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - lock (_epgLock) - { - _jsonSerializer.SerializeToFile(epgData, path); - } - } - private List<ProgramInfo> GetEpgDataForChannel(string channelId) - { - try - { - lock (_epgLock) - { - return _jsonSerializer.DeserializeFromFile<List<ProgramInfo>>(GetChannelEpgCachePath(channelId)); - } - } - catch - { - return new List<ProgramInfo>(); - } - } - private List<ProgramInfo> GetEpgDataForChannels(List<string> channelIds) - { - return channelIds.SelectMany(GetEpgDataForChannel).ToList(); - } - - private bool _disposed; - public void Dispose() - { - _disposed = true; - foreach (var pair in _activeRecordings.ToList()) - { - pair.Value.CancellationTokenSource.Cancel(); - } - } - - public List<VirtualFolderInfo> GetRecordingFolders() - { - var list = new List<VirtualFolderInfo>(); - - var defaultFolder = RecordingPath; - var defaultName = "Recordings"; - - if (Directory.Exists(defaultFolder)) - { - list.Add(new VirtualFolderInfo - { - Locations = new List<string> { defaultFolder }, - Name = defaultName - }); - } - - var customPath = GetConfiguration().MovieRecordingPath; - if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && Directory.Exists(customPath)) - { - list.Add(new VirtualFolderInfo - { - Locations = new List<string> { customPath }, - Name = "Recorded Movies", - CollectionType = CollectionType.Movies - }); - } - - customPath = GetConfiguration().SeriesRecordingPath; - if ((!string.IsNullOrWhiteSpace(customPath) && !string.Equals(customPath, defaultFolder, StringComparison.OrdinalIgnoreCase)) && Directory.Exists(customPath)) - { - list.Add(new VirtualFolderInfo - { - Locations = new List<string> { customPath }, - Name = "Recorded Series", - CollectionType = CollectionType.TvShows - }); - } - - return list; - } - - class ActiveRecordingInfo - { - public string Path { get; set; } - public TimerInfo Timer { get; set; } - public ProgramInfo Program { get; set; } - public CancellationTokenSource CancellationTokenSource { get; set; } - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTVRegistration.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTVRegistration.cs deleted file mode 100644 index 675fca3258..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTVRegistration.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Threading.Tasks; -using MediaBrowser.Common.Security; - -namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV -{ - public class EmbyTVRegistration : IRequiresRegistration - { - private readonly ISecurityManager _securityManager; - - public static EmbyTVRegistration Instance; - - public EmbyTVRegistration(ISecurityManager securityManager) - { - _securityManager = securityManager; - Instance = this; - } - - private bool? _isXmlTvEnabled; - - public Task LoadRegistrationInfoAsync() - { - _isXmlTvEnabled = null; - return Task.FromResult(true); - } - - public async Task<bool> EnableXmlTv() - { - if (!_isXmlTvEnabled.HasValue) - { - var info = await _securityManager.GetRegistrationStatus("xmltv").ConfigureAwait(false); - _isXmlTvEnabled = info.IsValid; - } - return _isXmlTvEnabled.Value; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs deleted file mode 100644 index cdf8e75974..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ /dev/null @@ -1,325 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV -{ - public class EncodedRecorder : IRecorder - { - private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly IHttpClient _httpClient; - private readonly IMediaEncoder _mediaEncoder; - private readonly IServerApplicationPaths _appPaths; - private readonly LiveTvOptions _liveTvOptions; - private bool _hasExited; - private Stream _logFileStream; - private string _targetPath; - private Process _process; - private readonly IJsonSerializer _json; - private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>(); - - public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, LiveTvOptions liveTvOptions, IHttpClient httpClient) - { - _logger = logger; - _fileSystem = fileSystem; - _mediaEncoder = mediaEncoder; - _appPaths = appPaths; - _json = json; - _liveTvOptions = liveTvOptions; - _httpClient = httpClient; - } - - private string OutputFormat - { - get - { - var format = _liveTvOptions.RecordingEncodingFormat; - - if (string.Equals(format, "mkv", StringComparison.OrdinalIgnoreCase) || _liveTvOptions.EnableOriginalVideoWithEncodedRecordings) - { - return "mkv"; - } - - return "mp4"; - } - } - - public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile) - { - return Path.ChangeExtension(targetFile, "." + OutputFormat); - } - - public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) - { - var durationToken = new CancellationTokenSource(duration); - cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; - - await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false); - - _logger.Info("Recording completed to file {0}", targetFile); - } - - private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) - { - _targetPath = targetFile; - _fileSystem.CreateDirectory(Path.GetDirectoryName(targetFile)); - - var process = new Process - { - StartInfo = new ProcessStartInfo - { - CreateNoWindow = true, - UseShellExecute = false, - - // Must consume both stdout and stderr or deadlocks may occur - //RedirectStandardOutput = true, - RedirectStandardError = true, - RedirectStandardInput = true, - - FileName = _mediaEncoder.EncoderPath, - Arguments = GetCommandLineArgs(mediaSource, inputFile, targetFile, duration), - - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }, - - EnableRaisingEvents = true - }; - - _process = process; - - var commandLineLogMessage = process.StartInfo.FileName + " " + process.StartInfo.Arguments; - _logger.Info(commandLineLogMessage); - - var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt"); - _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); - - // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - _logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true); - - var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(_json.SerializeToString(mediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); - _logFileStream.Write(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length); - - process.Exited += (sender, args) => OnFfMpegProcessExited(process, inputFile); - - process.Start(); - - cancellationToken.Register(Stop); - - // MUST read both stdout and stderr asynchronously or a deadlock may occurr - //process.BeginOutputReadLine(); - - onStarted(); - - // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback - StartStreamingLog(process.StandardError.BaseStream, _logFileStream); - - _logger.Info("ffmpeg recording process started for {0}", _targetPath); - - return _taskCompletionSource.Task; - } - - private string GetCommandLineArgs(MediaSourceInfo mediaSource, string inputTempFile, string targetFile, TimeSpan duration) - { - string videoArgs; - if (EncodeVideo(mediaSource)) - { - var maxBitrate = 25000000; - videoArgs = string.Format( - "-codec:v:0 libx264 -force_key_frames \"expr:gte(t,n_forced*5)\" {0} -pix_fmt yuv420p -preset superfast -crf 23 -b:v {1} -maxrate {1} -bufsize ({1}*2) -vsync -1 -profile:v high -level 41", - GetOutputSizeParam(), - maxBitrate.ToString(CultureInfo.InvariantCulture)); - } - else - { - videoArgs = "-codec:v:0 copy"; - } - - var durationParam = " -t " + _mediaEncoder.GetTimeParameter(duration.Ticks); - var inputModifiers = "-fflags +genpts -async 1 -vsync -1"; - var commandLineArgs = "-i \"{0}\"{4} -sn {2} -map_metadata -1 -threads 0 {3} -y \"{1}\""; - - long startTimeTicks = 0; - //if (mediaSource.DateLiveStreamOpened.HasValue) - //{ - // var elapsed = DateTime.UtcNow - mediaSource.DateLiveStreamOpened.Value; - // elapsed -= TimeSpan.FromSeconds(10); - // if (elapsed.TotalSeconds >= 0) - // { - // startTimeTicks = elapsed.Ticks + startTimeTicks; - // } - //} - - if (mediaSource.ReadAtNativeFramerate) - { - inputModifiers += " -re"; - } - - if (startTimeTicks > 0) - { - inputModifiers = "-ss " + _mediaEncoder.GetTimeParameter(startTimeTicks) + " " + inputModifiers; - } - - commandLineArgs = string.Format(commandLineArgs, inputTempFile, targetFile, videoArgs, GetAudioArgs(mediaSource), durationParam); - - return inputModifiers + " " + commandLineArgs; - } - - private string GetAudioArgs(MediaSourceInfo mediaSource) - { - var mediaStreams = mediaSource.MediaStreams ?? new List<MediaStream>(); - var inputAudioCodec = mediaStreams.Where(i => i.Type == MediaStreamType.Audio).Select(i => i.Codec).FirstOrDefault() ?? string.Empty; - - // do not copy aac because many players have difficulty with aac_latm - if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings && !string.Equals(inputAudioCodec, "aac", StringComparison.OrdinalIgnoreCase)) - { - return "-codec:a:0 copy"; - } - - var audioChannels = 2; - var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio); - if (audioStream != null) - { - audioChannels = audioStream.Channels ?? audioChannels; - } - return "-codec:a:0 aac -strict experimental -ab 320000"; - } - - private bool EncodeVideo(MediaSourceInfo mediaSource) - { - if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings) - { - return false; - } - - var mediaStreams = mediaSource.MediaStreams ?? new List<MediaStream>(); - return !mediaStreams.Any(i => i.Type == MediaStreamType.Video && string.Equals(i.Codec, "h264", StringComparison.OrdinalIgnoreCase) && !i.IsInterlaced); - } - - protected string GetOutputSizeParam() - { - var filters = new List<string>(); - - filters.Add("yadif=0:-1:0"); - - var output = string.Empty; - - if (filters.Count > 0) - { - output += string.Format(" -vf \"{0}\"", string.Join(",", filters.ToArray())); - } - - return output; - } - - private void Stop() - { - if (!_hasExited) - { - try - { - _logger.Info("Killing 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); - } - } - } - - /// <summary> - /// Processes the exited. - /// </summary> - private void OnFfMpegProcessExited(Process process, string inputFile) - { - _hasExited = true; - - DisposeLogStream(); - - try - { - var exitCode = process.ExitCode; - - _logger.Info("FFMpeg recording exited with code {0} for {1}", exitCode, _targetPath); - - if (exitCode == 0) - { - _taskCompletionSource.TrySetResult(true); - } - else - { - _taskCompletionSource.TrySetException(new Exception(string.Format("Recording for {0} failed. Exit code {1}", _targetPath, exitCode))); - } - } - catch - { - _logger.Error("FFMpeg recording exited with an error for {0}.", _targetPath); - _taskCompletionSource.TrySetException(new Exception(string.Format("Recording for {0} failed", _targetPath))); - } - } - - private void DisposeLogStream() - { - if (_logFileStream != null) - { - try - { - _logFileStream.Dispose(); - } - catch (Exception ex) - { - _logger.ErrorException("Error disposing recording log stream", ex); - } - - _logFileStream = null; - } - } - - private async void StartStreamingLog(Stream source, Stream target) - { - try - { - using (var reader = new StreamReader(source)) - { - while (!reader.EndOfStream) - { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - - var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line); - - await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); - await target.FlushAsync().ConfigureAwait(false); - } - } - } - catch (ObjectDisposedException) - { - // Don't spam the log. This doesn't seem to throw in windows, but sometimes under linux - } - catch (Exception ex) - { - _logger.ErrorException("Error reading ffmpeg recording log", ex); - } - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs deleted file mode 100644 index 713cb9cd30..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs +++ /dev/null @@ -1,16 +0,0 @@ -using MediaBrowser.Controller.Plugins; - -namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV -{ - public class EntryPoint : IServerEntryPoint - { - public void Run() - { - EmbyTV.Current.Start(); - } - - public void Dispose() - { - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs deleted file mode 100644 index 5706b6ae9e..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Dto; - -namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV -{ - public interface IRecorder - { - /// <summary> - /// Records the specified media source. - /// </summary> - /// <param name="mediaSource">The media source.</param> - /// <param name="targetFile">The target file.</param> - /// <param name="duration">The duration.</param> - /// <param name="onStarted">The on started.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken); - - string GetOutputPath(MediaSourceInfo mediaSource, string targetFile); - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs deleted file mode 100644 index 7fe271bea4..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ /dev/null @@ -1,147 +0,0 @@ -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV -{ - public class ItemDataProvider<T> - where T : class - { - private readonly object _fileDataLock = new object(); - private List<T> _items; - private readonly IJsonSerializer _jsonSerializer; - protected readonly ILogger Logger; - private readonly string _dataPath; - protected readonly Func<T, T, bool> EqualityComparer; - private readonly IFileSystem _fileSystem; - - public ItemDataProvider(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, Func<T, T, bool> equalityComparer) - { - Logger = logger; - _dataPath = dataPath; - EqualityComparer = equalityComparer; - _jsonSerializer = jsonSerializer; - _fileSystem = fileSystem; - } - - public IReadOnlyList<T> GetAll() - { - lock (_fileDataLock) - { - if (_items == null) - { - Logger.Info("Loading live tv data from {0}", _dataPath); - _items = GetItemsFromFile(_dataPath); - } - return _items.ToList(); - } - } - - private List<T> GetItemsFromFile(string path) - { - var jsonFile = path + ".json"; - - try - { - return _jsonSerializer.DeserializeFromFile<List<T>>(jsonFile) ?? new List<T>(); - } - catch (FileNotFoundException) - { - } - catch (DirectoryNotFoundException) - { - } - catch (IOException ex) - { - Logger.ErrorException("Error deserializing {0}", ex, jsonFile); - } - catch (Exception ex) - { - Logger.ErrorException("Error deserializing {0}", ex, jsonFile); - } - return new List<T>(); - } - - private void UpdateList(List<T> newList) - { - if (newList == null) - { - throw new ArgumentNullException("newList"); - } - - var file = _dataPath + ".json"; - _fileSystem.CreateDirectory(Path.GetDirectoryName(file)); - - lock (_fileDataLock) - { - _jsonSerializer.SerializeToFile(newList, file); - _items = newList; - } - } - - public virtual void Update(T item) - { - if (item == null) - { - throw new ArgumentNullException("item"); - } - - var list = GetAll().ToList(); - - var index = list.FindIndex(i => EqualityComparer(i, item)); - - if (index == -1) - { - throw new ArgumentException("item not found"); - } - - list[index] = item; - - UpdateList(list); - } - - public virtual void Add(T item) - { - if (item == null) - { - throw new ArgumentNullException("item"); - } - - var list = GetAll().ToList(); - - if (list.Any(i => EqualityComparer(i, item))) - { - throw new ArgumentException("item already exists"); - } - - list.Add(item); - - UpdateList(list); - } - - public void AddOrUpdate(T item) - { - var list = GetAll().ToList(); - - if (!list.Any(i => EqualityComparer(i, item))) - { - Add(item); - } - else - { - Update(item); - } - } - - public virtual void Delete(T item) - { - var list = GetAll().Where(i => !EqualityComparer(i, item)).ToList(); - - UpdateList(list); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs deleted file mode 100644 index f7b4b3fde6..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ /dev/null @@ -1,105 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.LiveTv; -using System; -using System.Globalization; -using MediaBrowser.Model.LiveTv; - -namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV -{ - internal class RecordingHelper - { - public static DateTime GetStartTime(TimerInfo timer) - { - return timer.StartDate.AddSeconds(-timer.PrePaddingSeconds); - } - - public static TimerInfo CreateTimer(ProgramInfo parent, SeriesTimerInfo seriesTimer) - { - var timer = new TimerInfo(); - - timer.ChannelId = parent.ChannelId; - timer.Id = (seriesTimer.Id + parent.Id).GetMD5().ToString("N"); - timer.StartDate = parent.StartDate; - timer.EndDate = parent.EndDate; - timer.ProgramId = parent.Id; - timer.PrePaddingSeconds = seriesTimer.PrePaddingSeconds; - timer.PostPaddingSeconds = seriesTimer.PostPaddingSeconds; - timer.IsPostPaddingRequired = seriesTimer.IsPostPaddingRequired; - timer.IsPrePaddingRequired = seriesTimer.IsPrePaddingRequired; - timer.KeepUntil = seriesTimer.KeepUntil; - timer.Priority = seriesTimer.Priority; - timer.Name = parent.Name; - timer.Overview = parent.Overview; - timer.SeriesTimerId = seriesTimer.Id; - - CopyProgramInfoToTimerInfo(parent, timer); - - return timer; - } - - public static void CopyProgramInfoToTimerInfo(ProgramInfo programInfo, TimerInfo timerInfo) - { - timerInfo.SeasonNumber = programInfo.SeasonNumber; - timerInfo.EpisodeNumber = programInfo.EpisodeNumber; - timerInfo.IsMovie = programInfo.IsMovie; - timerInfo.IsKids = programInfo.IsKids; - timerInfo.IsNews = programInfo.IsNews; - timerInfo.IsSports = programInfo.IsSports; - timerInfo.ProductionYear = programInfo.ProductionYear; - timerInfo.EpisodeTitle = programInfo.EpisodeTitle; - timerInfo.OriginalAirDate = programInfo.OriginalAirDate; - timerInfo.IsProgramSeries = programInfo.IsSeries; - - timerInfo.HomePageUrl = programInfo.HomePageUrl; - timerInfo.CommunityRating = programInfo.CommunityRating; - timerInfo.ShortOverview = programInfo.ShortOverview; - timerInfo.OfficialRating = programInfo.OfficialRating; - timerInfo.IsRepeat = programInfo.IsRepeat; - } - - public static string GetRecordingName(TimerInfo info) - { - var name = info.Name; - - if (info.IsProgramSeries) - { - var addHyphen = true; - - if (info.SeasonNumber.HasValue && info.EpisodeNumber.HasValue) - { - name += string.Format(" S{0}E{1}", info.SeasonNumber.Value.ToString("00", CultureInfo.InvariantCulture), info.EpisodeNumber.Value.ToString("00", CultureInfo.InvariantCulture)); - addHyphen = false; - } - else if (info.OriginalAirDate.HasValue) - { - name += " " + info.OriginalAirDate.Value.ToString("yyyy-MM-dd"); - } - else - { - name += " " + DateTime.Now.ToString("yyyy-MM-dd"); - } - - if (!string.IsNullOrWhiteSpace(info.EpisodeTitle)) - { - if (addHyphen) - { - name += " -"; - } - - name += " " + info.EpisodeTitle; - } - } - - else if (info.IsMovie && info.ProductionYear != null) - { - name += " (" + info.ProductionYear + ")"; - } - else - { - name += " " + info.StartDate.ToString("yyyy-MM-dd") + " " + info.Id; - } - - return name; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs deleted file mode 100644 index 40e532c4e6..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV -{ - public class SeriesTimerManager : ItemDataProvider<SeriesTimerInfo> - { - public SeriesTimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath) - : base(fileSystem, jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase)) - { - } - - public override void Add(SeriesTimerInfo item) - { - if (string.IsNullOrWhiteSpace(item.Id)) - { - throw new ArgumentException("SeriesTimerInfo.Id cannot be null or empty."); - } - - base.Add(item); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs deleted file mode 100644 index bddce04201..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs +++ /dev/null @@ -1,165 +0,0 @@ -using MediaBrowser.Common.Events; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Concurrent; -using System.Globalization; -using System.Linq; -using System.Threading; -using CommonIO; -using MediaBrowser.Model.LiveTv; - -namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV -{ - public class TimerManager : ItemDataProvider<TimerInfo> - { - private readonly ConcurrentDictionary<string, Timer> _timers = new ConcurrentDictionary<string, Timer>(StringComparer.OrdinalIgnoreCase); - private readonly ILogger _logger; - - public event EventHandler<GenericEventArgs<TimerInfo>> TimerFired; - - public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, ILogger logger1) - : base(fileSystem, jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase)) - { - _logger = logger1; - } - - public void RestartTimers() - { - StopTimers(); - - foreach (var item in GetAll().ToList()) - { - AddOrUpdateSystemTimer(item); - } - } - - public void StopTimers() - { - foreach (var pair in _timers.ToList()) - { - pair.Value.Dispose(); - } - - _timers.Clear(); - } - - public override void Delete(TimerInfo item) - { - base.Delete(item); - StopTimer(item); - } - - public override void Update(TimerInfo item) - { - base.Update(item); - AddOrUpdateSystemTimer(item); - } - - public void AddOrUpdate(TimerInfo item, bool resetTimer) - { - if (resetTimer) - { - AddOrUpdate(item); - return; - } - - var list = GetAll().ToList(); - - if (!list.Any(i => EqualityComparer(i, item))) - { - base.Add(item); - } - else - { - base.Update(item); - } - } - - public override void Add(TimerInfo item) - { - if (string.IsNullOrWhiteSpace(item.Id)) - { - throw new ArgumentException("TimerInfo.Id cannot be null or empty."); - } - - base.Add(item); - AddOrUpdateSystemTimer(item); - } - - private bool ShouldStartTimer(TimerInfo item) - { - if (item.Status == RecordingStatus.Completed || - item.Status == RecordingStatus.Cancelled) - { - return false; - } - - return true; - } - - private void AddOrUpdateSystemTimer(TimerInfo item) - { - StopTimer(item); - - if (!ShouldStartTimer(item)) - { - return; - } - - var startDate = RecordingHelper.GetStartTime(item); - var now = DateTime.UtcNow; - - if (startDate < now) - { - EventHelper.FireEventIfNotNull(TimerFired, this, new GenericEventArgs<TimerInfo> { Argument = item }, Logger); - return; - } - - var dueTime = startDate - now; - StartTimer(item, dueTime); - } - - private void StartTimer(TimerInfo item, TimeSpan dueTime) - { - var timer = new Timer(TimerCallback, item.Id, dueTime, TimeSpan.Zero); - - if (_timers.TryAdd(item.Id, timer)) - { - _logger.Info("Creating recording timer for {0}, {1}. Timer will fire in {2} minutes", item.Id, item.Name, dueTime.TotalMinutes.ToString(CultureInfo.InvariantCulture)); - } - else - { - timer.Dispose(); - _logger.Warn("Timer already exists for item {0}", item.Id); - } - } - - private void StopTimer(TimerInfo item) - { - Timer timer; - if (_timers.TryRemove(item.Id, out timer)) - { - timer.Dispose(); - } - } - - private void TimerCallback(object state) - { - var timerId = (string)state; - - var timer = GetAll().FirstOrDefault(i => string.Equals(i.Id, timerId, StringComparison.OrdinalIgnoreCase)); - if (timer != null) - { - EventHelper.FireEventIfNotNull(TimerFired, this, new GenericEventArgs<TimerInfo> { Argument = timer }, Logger); - } - } - - public TimerInfo GetTimer(string id) - { - return GetAll().FirstOrDefault(r => string.Equals(r.Id, id, StringComparison.OrdinalIgnoreCase)); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs deleted file mode 100644 index d3549aef55..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ /dev/null @@ -1,233 +0,0 @@ -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.LiveTv; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Emby.XmlTv.Classes; -using Emby.XmlTv.Entities; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.LiveTv.Listings -{ - public class XmlTvListingsProvider : IListingsProvider - { - private readonly IServerConfigurationManager _config; - private readonly IHttpClient _httpClient; - private readonly ILogger _logger; - - public XmlTvListingsProvider(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger) - { - _config = config; - _httpClient = httpClient; - _logger = logger; - } - - public string Name - { - get { return "XmlTV"; } - } - - public string Type - { - get { return "xmltv"; } - } - - private string GetLanguage() - { - return _config.Configuration.PreferredMetadataLanguage; - } - - private async Task<string> GetXml(string path, CancellationToken cancellationToken) - { - _logger.Info("xmltv path: {0}", path); - - if (!path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - return path; - } - - var cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + ".xml"; - var cacheFile = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename); - if (File.Exists(cacheFile)) - { - return cacheFile; - } - - _logger.Info("Downloading xmltv listings from {0}", path); - - var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = path, - Progress = new Progress<Double>(), - DecompressionMethod = DecompressionMethods.GZip, - - // It's going to come back gzipped regardless of this value - // So we need to make sure the decompression method is set to gzip - EnableHttpCompression = true - - }).ConfigureAwait(false); - - Directory.CreateDirectory(Path.GetDirectoryName(cacheFile)); - - using (var stream = File.OpenRead(tempFile)) - { - using (var reader = new StreamReader(stream, Encoding.UTF8)) - { - using (var fileStream = File.OpenWrite(cacheFile)) - { - using (var writer = new StreamWriter(fileStream)) - { - while (!reader.EndOfStream) - { - writer.WriteLine(reader.ReadLine()); - } - } - } - } - } - - _logger.Debug("Returning xmltv path {0}", cacheFile); - return cacheFile; - } - - public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) - { - if (!await EmbyTV.EmbyTVRegistration.Instance.EnableXmlTv().ConfigureAwait(false)) - { - var length = endDateUtc - startDateUtc; - if (length.TotalDays > 1) - { - endDateUtc = startDateUtc.AddDays(1); - } - } - - var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); - var reader = new XmlTvReader(path, GetLanguage(), null); - - var results = reader.GetProgrammes(channelNumber, startDateUtc, endDateUtc, cancellationToken); - return results.Select(p => GetProgramInfo(p, info)); - } - - private ProgramInfo GetProgramInfo(XmlTvProgram p, ListingsProviderInfo info) - { - var programInfo = new ProgramInfo - { - ChannelId = p.ChannelId, - EndDate = GetDate(p.EndDate), - EpisodeNumber = p.Episode == null ? null : p.Episode.Episode, - EpisodeTitle = p.Episode == null ? null : p.Episode.Title, - Genres = p.Categories, - Id = String.Format("{0}_{1:O}", p.ChannelId, p.StartDate), // Construct an id from the channel and start date, - StartDate = GetDate(p.StartDate), - Name = p.Title, - Overview = p.Description, - ShortOverview = p.Description, - ProductionYear = !p.CopyrightDate.HasValue ? (int?)null : p.CopyrightDate.Value.Year, - SeasonNumber = p.Episode == null ? null : p.Episode.Series, - IsSeries = p.Episode != null, - IsRepeat = p.IsRepeat, - IsPremiere = p.Premiere != null, - IsKids = p.Categories.Any(c => info.KidsCategories.Contains(c, StringComparer.InvariantCultureIgnoreCase)), - IsMovie = p.Categories.Any(c => info.MovieCategories.Contains(c, StringComparer.InvariantCultureIgnoreCase)), - IsNews = p.Categories.Any(c => info.NewsCategories.Contains(c, StringComparer.InvariantCultureIgnoreCase)), - IsSports = p.Categories.Any(c => info.SportsCategories.Contains(c, StringComparer.InvariantCultureIgnoreCase)), - ImageUrl = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source) ? p.Icon.Source : null, - HasImage = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source), - OfficialRating = p.Rating != null && !String.IsNullOrEmpty(p.Rating.Value) ? p.Rating.Value : null, - CommunityRating = p.StarRating.HasValue ? p.StarRating.Value : (float?)null, - SeriesId = p.Episode != null ? p.Title.GetMD5().ToString("N") : null - }; - - if (programInfo.IsMovie) - { - programInfo.IsSeries = false; - programInfo.EpisodeNumber = null; - programInfo.EpisodeTitle = null; - } - - return programInfo; - } - - private DateTime GetDate(DateTime date) - { - if (date.Kind != DateTimeKind.Utc) - { - date = DateTime.SpecifyKind(date, DateTimeKind.Utc); - } - return date; - } - - public async Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken) - { - // Add the channel image url - var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); - var reader = new XmlTvReader(path, GetLanguage(), null); - var results = reader.GetChannels().ToList(); - - if (channels != null) - { - channels.ForEach(c => - { - var channelNumber = info.GetMappedChannel(c.Number); - var match = results.FirstOrDefault(r => string.Equals(r.Id, channelNumber, StringComparison.OrdinalIgnoreCase)); - - if (match != null && match.Icon != null && !String.IsNullOrEmpty(match.Icon.Source)) - { - c.ImageUrl = match.Icon.Source; - } - }); - } - } - - public Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings) - { - // Assume all urls are valid. check files for existence - if (!info.Path.StartsWith("http", StringComparison.OrdinalIgnoreCase) && !File.Exists(info.Path)) - { - throw new FileNotFoundException("Could not find the XmlTv file specified:", info.Path); - } - - return Task.FromResult(true); - } - - public async Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location) - { - // In theory this should never be called because there is always only one lineup - var path = await GetXml(info.Path, CancellationToken.None).ConfigureAwait(false); - var reader = new XmlTvReader(path, GetLanguage(), null); - var results = reader.GetChannels(); - - // Should this method be async? - return results.Select(c => new NameIdPair() { Id = c.Id, Name = c.DisplayName }).ToList(); - } - - public async Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken) - { - // In theory this should never be called because there is always only one lineup - var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); - var reader = new XmlTvReader(path, GetLanguage(), null); - var results = reader.GetChannels(); - - // Should this method be async? - return results.Select(c => new ChannelInfo() - { - Id = c.Id, - Name = c.DisplayName, - ImageUrl = c.Icon != null && !String.IsNullOrEmpty(c.Icon.Source) ? c.Icon.Source : null, - Number = c.Id - - }).ToList(); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveStreamHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveStreamHelper.cs deleted file mode 100644 index 336c32baef..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveStreamHelper.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.LiveTv -{ - public class LiveStreamHelper - { - private readonly IMediaEncoder _mediaEncoder; - private readonly ILogger _logger; - - public LiveStreamHelper(IMediaEncoder mediaEncoder, ILogger logger) - { - _mediaEncoder = mediaEncoder; - _logger = logger; - } - - public async Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken) - { - var originalRuntime = mediaSource.RunTimeTicks; - - var now = DateTime.UtcNow; - - var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest - { - InputPath = mediaSource.Path, - Protocol = mediaSource.Protocol, - MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video, - ExtractChapters = false, - AnalyzeDurationSections = 2 - - }, cancellationToken).ConfigureAwait(false); - - _logger.Info("Live tv media info probe took {0} seconds", (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture)); - - mediaSource.Bitrate = info.Bitrate; - mediaSource.Container = info.Container; - mediaSource.Formats = info.Formats; - mediaSource.MediaStreams = info.MediaStreams; - mediaSource.RunTimeTicks = info.RunTimeTicks; - mediaSource.Size = info.Size; - mediaSource.Timestamp = info.Timestamp; - mediaSource.Video3DFormat = info.Video3DFormat; - mediaSource.VideoType = info.VideoType; - - mediaSource.DefaultSubtitleStreamIndex = null; - - // Null this out so that it will be treated like a live stream - if (!originalRuntime.HasValue) - { - mediaSource.RunTimeTicks = null; - } - - var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio); - - if (audioStream == null || audioStream.Index == -1) - { - mediaSource.DefaultAudioStreamIndex = null; - } - else - { - mediaSource.DefaultAudioStreamIndex = audioStream.Index; - } - - var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video); - if (videoStream != null) - { - if (!videoStream.BitRate.HasValue) - { - var width = videoStream.Width ?? 1920; - - if (width >= 1900) - { - videoStream.BitRate = 8000000; - } - - else if (width >= 1260) - { - videoStream.BitRate = 3000000; - } - - else if (width >= 700) - { - videoStream.BitRate = 1000000; - } - } - - // This is coming up false and preventing stream copy - videoStream.IsAVC = null; - } - - // Try to estimate this - if (!mediaSource.Bitrate.HasValue) - { - var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum(); - - if (total > 0) - { - mediaSource.Bitrate = total; - } - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs deleted file mode 100644 index 57d1d79e16..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.LiveTv; -using System.Collections.Generic; - -namespace MediaBrowser.Server.Implementations.LiveTv -{ - public class LiveTvConfigurationFactory : IConfigurationFactory - { - public IEnumerable<ConfigurationStore> GetConfigurations() - { - return new List<ConfigurationStore> - { - new ConfigurationStore - { - ConfigurationType = typeof(LiveTvOptions), - Key = "livetv" - } - }; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs deleted file mode 100644 index c7a2d295d9..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ /dev/null @@ -1,390 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.LiveTv -{ - public class LiveTvDtoService - { - private readonly ILogger _logger; - private readonly IImageProcessor _imageProcessor; - - private readonly IUserDataManager _userDataManager; - private readonly IDtoService _dtoService; - private readonly IApplicationHost _appHost; - private readonly ILibraryManager _libraryManager; - - public LiveTvDtoService(IDtoService dtoService, IUserDataManager userDataManager, IImageProcessor imageProcessor, ILogger logger, IApplicationHost appHost, ILibraryManager libraryManager) - { - _dtoService = dtoService; - _userDataManager = userDataManager; - _imageProcessor = imageProcessor; - _logger = logger; - _appHost = appHost; - _libraryManager = libraryManager; - } - - public TimerInfoDto GetTimerInfoDto(TimerInfo info, ILiveTvService service, LiveTvProgram program, LiveTvChannel channel) - { - var dto = new TimerInfoDto - { - Id = GetInternalTimerId(service.Name, info.Id).ToString("N"), - Overview = info.Overview, - EndDate = info.EndDate, - Name = info.Name, - StartDate = info.StartDate, - ExternalId = info.Id, - ChannelId = GetInternalChannelId(service.Name, info.ChannelId).ToString("N"), - Status = info.Status, - SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId) ? null : GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N"), - PrePaddingSeconds = info.PrePaddingSeconds, - PostPaddingSeconds = info.PostPaddingSeconds, - IsPostPaddingRequired = info.IsPostPaddingRequired, - IsPrePaddingRequired = info.IsPrePaddingRequired, - KeepUntil = info.KeepUntil, - ExternalChannelId = info.ChannelId, - ExternalSeriesTimerId = info.SeriesTimerId, - ServiceName = service.Name, - ExternalProgramId = info.ProgramId, - Priority = info.Priority, - RunTimeTicks = (info.EndDate - info.StartDate).Ticks, - ServerId = _appHost.SystemId - }; - - if (!string.IsNullOrEmpty(info.ProgramId)) - { - dto.ProgramId = GetInternalProgramId(service.Name, info.ProgramId).ToString("N"); - } - - if (program != null) - { - dto.ProgramInfo = _dtoService.GetBaseItemDto(program, new DtoOptions()); - - if (info.Status != RecordingStatus.Cancelled && info.Status != RecordingStatus.Error) - { - dto.ProgramInfo.TimerId = dto.Id; - dto.ProgramInfo.Status = info.Status.ToString(); - } - - dto.ProgramInfo.SeriesTimerId = dto.SeriesTimerId; - } - - if (channel != null) - { - dto.ChannelName = channel.Name; - } - - return dto; - } - - public SeriesTimerInfoDto GetSeriesTimerInfoDto(SeriesTimerInfo info, ILiveTvService service, string channelName) - { - var dto = new SeriesTimerInfoDto - { - Id = GetInternalSeriesTimerId(service.Name, info.Id).ToString("N"), - Overview = info.Overview, - EndDate = info.EndDate, - Name = info.Name, - StartDate = info.StartDate, - ExternalId = info.Id, - PrePaddingSeconds = info.PrePaddingSeconds, - PostPaddingSeconds = info.PostPaddingSeconds, - IsPostPaddingRequired = info.IsPostPaddingRequired, - IsPrePaddingRequired = info.IsPrePaddingRequired, - Days = info.Days, - Priority = info.Priority, - RecordAnyChannel = info.RecordAnyChannel, - RecordAnyTime = info.RecordAnyTime, - SkipEpisodesInLibrary = info.SkipEpisodesInLibrary, - KeepUpTo = info.KeepUpTo, - KeepUntil = info.KeepUntil, - RecordNewOnly = info.RecordNewOnly, - ExternalChannelId = info.ChannelId, - ExternalProgramId = info.ProgramId, - ServiceName = service.Name, - ChannelName = channelName, - ServerId = _appHost.SystemId - }; - - if (!string.IsNullOrEmpty(info.ChannelId)) - { - dto.ChannelId = GetInternalChannelId(service.Name, info.ChannelId).ToString("N"); - } - - if (!string.IsNullOrEmpty(info.ProgramId)) - { - dto.ProgramId = GetInternalProgramId(service.Name, info.ProgramId).ToString("N"); - } - - dto.DayPattern = info.Days == null ? null : GetDayPattern(info.Days); - - if (!string.IsNullOrWhiteSpace(info.SeriesId)) - { - var program = _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name }, - ExternalSeriesId = info.SeriesId, - Limit = 1, - ImageTypes = new ImageType[] { ImageType.Primary } - - }).FirstOrDefault(); - - if (program != null) - { - var image = program.GetImageInfo(ImageType.Primary, 0); - if (image != null) - { - try - { - dto.ParentPrimaryImageTag = _imageProcessor.GetImageCacheTag(program, image); - dto.ParentPrimaryImageItemId = program.Id.ToString("N"); - } - catch (Exception ex) - { - } - } - } - } - - return dto; - } - - public DayPattern? GetDayPattern(List<DayOfWeek> days) - { - DayPattern? pattern = null; - - if (days.Count > 0) - { - if (days.Count == 7) - { - pattern = DayPattern.Daily; - } - else if (days.Count == 2) - { - if (days.Contains(DayOfWeek.Saturday) && days.Contains(DayOfWeek.Sunday)) - { - pattern = DayPattern.Weekends; - } - } - else if (days.Count == 5) - { - if (days.Contains(DayOfWeek.Monday) && days.Contains(DayOfWeek.Tuesday) && days.Contains(DayOfWeek.Wednesday) && days.Contains(DayOfWeek.Thursday) && days.Contains(DayOfWeek.Friday)) - { - pattern = DayPattern.Weekdays; - } - } - } - - return pattern; - } - - public LiveTvTunerInfoDto GetTunerInfoDto(string serviceName, LiveTvTunerInfo info, string channelName) - { - var dto = new LiveTvTunerInfoDto - { - Name = info.Name, - Id = info.Id, - Clients = info.Clients, - ProgramName = info.ProgramName, - SourceType = info.SourceType, - Status = info.Status, - ChannelName = channelName, - Url = info.Url, - CanReset = info.CanReset - }; - - if (!string.IsNullOrEmpty(info.ChannelId)) - { - dto.ChannelId = GetInternalChannelId(serviceName, info.ChannelId).ToString("N"); - } - - if (!string.IsNullOrEmpty(info.RecordingId)) - { - dto.RecordingId = GetInternalRecordingId(serviceName, info.RecordingId).ToString("N"); - } - - return dto; - } - - internal string GetImageTag(IHasImages info) - { - try - { - return _imageProcessor.GetImageCacheTag(info, ImageType.Primary); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting image info for {0}", ex, info.Name); - } - - return null; - } - - private const string InternalVersionNumber = "4"; - - public Guid GetInternalChannelId(string serviceName, string externalId) - { - var name = serviceName + externalId + InternalVersionNumber; - - return _libraryManager.GetNewItemId(name.ToLower(), typeof(LiveTvChannel)); - } - - public Guid GetInternalTimerId(string serviceName, string externalId) - { - var name = serviceName + externalId + InternalVersionNumber; - - return name.ToLower().GetMD5(); - } - - public Guid GetInternalSeriesTimerId(string serviceName, string externalId) - { - var name = serviceName + externalId + InternalVersionNumber; - - return name.ToLower().GetMD5(); - } - - public Guid GetInternalProgramId(string serviceName, string externalId) - { - var name = serviceName + externalId + InternalVersionNumber; - - return _libraryManager.GetNewItemId(name.ToLower(), typeof(LiveTvProgram)); - } - - public Guid GetInternalRecordingId(string serviceName, string externalId) - { - var name = serviceName + externalId + InternalVersionNumber + "0"; - - return _libraryManager.GetNewItemId(name.ToLower(), typeof(ILiveTvRecording)); - } - - public async Task<TimerInfo> GetTimerInfo(TimerInfoDto dto, bool isNew, LiveTvManager liveTv, CancellationToken cancellationToken) - { - var info = new TimerInfo - { - Overview = dto.Overview, - EndDate = dto.EndDate, - Name = dto.Name, - StartDate = dto.StartDate, - Status = dto.Status, - PrePaddingSeconds = dto.PrePaddingSeconds, - PostPaddingSeconds = dto.PostPaddingSeconds, - IsPostPaddingRequired = dto.IsPostPaddingRequired, - IsPrePaddingRequired = dto.IsPrePaddingRequired, - KeepUntil = dto.KeepUntil, - Priority = dto.Priority, - SeriesTimerId = dto.ExternalSeriesTimerId, - ProgramId = dto.ExternalProgramId, - ChannelId = dto.ExternalChannelId, - Id = dto.ExternalId - }; - - // Convert internal server id's to external tv provider id's - if (!isNew && !string.IsNullOrEmpty(dto.Id) && string.IsNullOrEmpty(info.Id)) - { - var timer = await liveTv.GetSeriesTimer(dto.Id, cancellationToken).ConfigureAwait(false); - - info.Id = timer.ExternalId; - } - - if (!string.IsNullOrEmpty(dto.ChannelId) && string.IsNullOrEmpty(info.ChannelId)) - { - var channel = liveTv.GetInternalChannel(dto.ChannelId); - - if (channel != null) - { - info.ChannelId = channel.ExternalId; - } - } - - if (!string.IsNullOrEmpty(dto.ProgramId) && string.IsNullOrEmpty(info.ProgramId)) - { - var program = liveTv.GetInternalProgram(dto.ProgramId); - - if (program != null) - { - info.ProgramId = program.ExternalId; - } - } - - if (!string.IsNullOrEmpty(dto.SeriesTimerId) && string.IsNullOrEmpty(info.SeriesTimerId)) - { - var timer = await liveTv.GetSeriesTimer(dto.SeriesTimerId, cancellationToken).ConfigureAwait(false); - - if (timer != null) - { - info.SeriesTimerId = timer.ExternalId; - } - } - - return info; - } - - public async Task<SeriesTimerInfo> GetSeriesTimerInfo(SeriesTimerInfoDto dto, bool isNew, LiveTvManager liveTv, CancellationToken cancellationToken) - { - var info = new SeriesTimerInfo - { - Overview = dto.Overview, - EndDate = dto.EndDate, - Name = dto.Name, - StartDate = dto.StartDate, - PrePaddingSeconds = dto.PrePaddingSeconds, - PostPaddingSeconds = dto.PostPaddingSeconds, - IsPostPaddingRequired = dto.IsPostPaddingRequired, - IsPrePaddingRequired = dto.IsPrePaddingRequired, - Days = dto.Days, - Priority = dto.Priority, - RecordAnyChannel = dto.RecordAnyChannel, - RecordAnyTime = dto.RecordAnyTime, - SkipEpisodesInLibrary = dto.SkipEpisodesInLibrary, - KeepUpTo = dto.KeepUpTo, - KeepUntil = dto.KeepUntil, - RecordNewOnly = dto.RecordNewOnly, - ProgramId = dto.ExternalProgramId, - ChannelId = dto.ExternalChannelId, - Id = dto.ExternalId - }; - - // Convert internal server id's to external tv provider id's - if (!isNew && !string.IsNullOrEmpty(dto.Id) && string.IsNullOrEmpty(info.Id)) - { - var timer = await liveTv.GetSeriesTimer(dto.Id, cancellationToken).ConfigureAwait(false); - - info.Id = timer.ExternalId; - } - - if (!string.IsNullOrEmpty(dto.ChannelId) && string.IsNullOrEmpty(info.ChannelId)) - { - var channel = liveTv.GetInternalChannel(dto.ChannelId); - - if (channel != null) - { - info.ChannelId = channel.ExternalId; - } - } - - if (!string.IsNullOrEmpty(dto.ProgramId) && string.IsNullOrEmpty(info.ProgramId)) - { - var program = liveTv.GetInternalProgram(dto.ProgramId); - - if (program != null) - { - info.ProgramId = program.ExternalId; - } - } - - return info; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs deleted file mode 100644 index 902afb2003..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ /dev/null @@ -1,3010 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Progress; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Localization; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Serialization; -using MoreLinq; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using IniParser; -using IniParser.Model; -using MediaBrowser.Common.Events; -using MediaBrowser.Common.Security; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Model.Events; -using MediaBrowser.Server.Implementations.LiveTv.Listings; - -namespace MediaBrowser.Server.Implementations.LiveTv -{ - /// <summary> - /// Class LiveTvManager - /// </summary> - public class LiveTvManager : ILiveTvManager, IDisposable - { - private readonly IServerConfigurationManager _config; - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - private readonly IUserManager _userManager; - private readonly IUserDataManager _userDataManager; - private readonly ILibraryManager _libraryManager; - private readonly ITaskManager _taskManager; - private readonly IJsonSerializer _jsonSerializer; - private readonly IProviderManager _providerManager; - private readonly ISecurityManager _security; - - private readonly IDtoService _dtoService; - private readonly ILocalizationManager _localization; - - private readonly LiveTvDtoService _tvDtoService; - - private readonly List<ILiveTvService> _services = new List<ILiveTvService>(); - - private readonly SemaphoreSlim _refreshRecordingsLock = new SemaphoreSlim(1, 1); - - private readonly List<ITunerHost> _tunerHosts = new List<ITunerHost>(); - private readonly List<IListingsProvider> _listingProviders = new List<IListingsProvider>(); - private readonly IFileSystem _fileSystem; - - public event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled; - public event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled; - public event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated; - public event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated; - - public LiveTvManager(IApplicationHost appHost, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager, IFileSystem fileSystem, ISecurityManager security) - { - _config = config; - _logger = logger; - _itemRepo = itemRepo; - _userManager = userManager; - _libraryManager = libraryManager; - _taskManager = taskManager; - _localization = localization; - _jsonSerializer = jsonSerializer; - _providerManager = providerManager; - _fileSystem = fileSystem; - _security = security; - _dtoService = dtoService; - _userDataManager = userDataManager; - - _tvDtoService = new LiveTvDtoService(dtoService, userDataManager, imageProcessor, logger, appHost, _libraryManager); - } - - /// <summary> - /// Gets the services. - /// </summary> - /// <value>The services.</value> - public IReadOnlyList<ILiveTvService> Services - { - get { return _services; } - } - - private LiveTvOptions GetConfiguration() - { - return _config.GetConfiguration<LiveTvOptions>("livetv"); - } - - /// <summary> - /// Adds the parts. - /// </summary> - /// <param name="services">The services.</param> - /// <param name="tunerHosts">The tuner hosts.</param> - /// <param name="listingProviders">The listing providers.</param> - public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders) - { - _services.AddRange(services); - _tunerHosts.AddRange(tunerHosts); - _listingProviders.AddRange(listingProviders); - - foreach (var service in _services) - { - service.DataSourceChanged += service_DataSourceChanged; - service.RecordingStatusChanged += Service_RecordingStatusChanged; - } - } - - private void Service_RecordingStatusChanged(object sender, RecordingStatusChangedEventArgs e) - { - _lastRecordingRefreshTime = DateTime.MinValue; - } - - public List<ITunerHost> TunerHosts - { - get { return _tunerHosts; } - } - - public List<IListingsProvider> ListingProviders - { - get { return _listingProviders; } - } - - void service_DataSourceChanged(object sender, EventArgs e) - { - if (!_isDisposed) - { - _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>(); - } - } - - public async Task<QueryResult<LiveTvChannel>> GetInternalChannels(LiveTvChannelQuery query, CancellationToken cancellationToken) - { - var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); - - var topFolder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); - - var internalQuery = new InternalItemsQuery(user) - { - IsMovie = query.IsMovie, - IsNews = query.IsNews, - IsKids = query.IsKids, - IsSports = query.IsSports, - IsSeries = query.IsSeries, - IncludeItemTypes = new[] { typeof(LiveTvChannel).Name }, - SortOrder = query.SortOrder ?? SortOrder.Ascending, - TopParentIds = new[] { topFolder.Id.ToString("N") }, - IsFavorite = query.IsFavorite, - IsLiked = query.IsLiked, - StartIndex = query.StartIndex, - Limit = query.Limit - }; - - internalQuery.OrderBy.AddRange(query.SortBy.Select(i => new Tuple<string, SortOrder>(i, query.SortOrder ?? SortOrder.Ascending))); - - if (query.EnableFavoriteSorting) - { - internalQuery.OrderBy.Insert(0, new Tuple<string, SortOrder>(ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending)); - } - - if (!internalQuery.OrderBy.Any(i => string.Equals(i.Item1, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase))) - { - internalQuery.OrderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending)); - } - - var channelResult = _libraryManager.GetItemsResult(internalQuery); - - var result = new QueryResult<LiveTvChannel> - { - Items = channelResult.Items.Cast<LiveTvChannel>().ToArray(), - TotalRecordCount = channelResult.TotalRecordCount - }; - - return result; - } - - public LiveTvChannel GetInternalChannel(string id) - { - return GetInternalChannel(new Guid(id)); - } - - private LiveTvChannel GetInternalChannel(Guid id) - { - return _libraryManager.GetItemById(id) as LiveTvChannel; - } - - internal LiveTvProgram GetInternalProgram(string id) - { - return _libraryManager.GetItemById(id) as LiveTvProgram; - } - - internal LiveTvProgram GetInternalProgram(Guid id) - { - return _libraryManager.GetItemById(id) as LiveTvProgram; - } - - public async Task<BaseItem> GetInternalRecording(string id, CancellationToken cancellationToken) - { - if (string.IsNullOrWhiteSpace(id)) - { - throw new ArgumentNullException("id"); - } - - var result = await GetInternalRecordings(new RecordingQuery - { - Id = id - - }, cancellationToken).ConfigureAwait(false); - - return result.Items.FirstOrDefault(); - } - - public async Task<MediaSourceInfo> GetRecordingStream(string id, CancellationToken cancellationToken) - { - var info = await GetLiveStream(id, null, false, cancellationToken).ConfigureAwait(false); - - return info.Item1; - } - - public async Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetChannelStream(string id, string mediaSourceId, CancellationToken cancellationToken) - { - return await GetLiveStream(id, mediaSourceId, true, cancellationToken).ConfigureAwait(false); - } - - public async Task<IEnumerable<MediaSourceInfo>> GetRecordingMediaSources(IHasMediaSources item, CancellationToken cancellationToken) - { - var baseItem = (BaseItem)item; - var service = GetService(baseItem); - - return await service.GetRecordingStreamMediaSources(baseItem.ExternalId, cancellationToken).ConfigureAwait(false); - } - - public async Task<IEnumerable<MediaSourceInfo>> GetChannelMediaSources(IHasMediaSources item, CancellationToken cancellationToken) - { - var baseItem = (LiveTvChannel)item; - var service = GetService(baseItem); - - var sources = await service.GetChannelStreamMediaSources(baseItem.ExternalId, cancellationToken).ConfigureAwait(false); - - if (sources.Count == 0) - { - throw new NotImplementedException(); - } - - var list = sources.ToList(); - - foreach (var source in list) - { - Normalize(source, service, baseItem.ChannelType == ChannelType.TV); - } - - return list; - } - - private ILiveTvService GetService(ILiveTvRecording item) - { - return GetService(item.ServiceName); - } - - private ILiveTvService GetService(BaseItem item) - { - return GetService(item.ServiceName); - } - - private ILiveTvService GetService(string name) - { - return _services.FirstOrDefault(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)); - } - - private async Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetLiveStream(string id, string mediaSourceId, bool isChannel, CancellationToken cancellationToken) - { - if (string.Equals(id, mediaSourceId, StringComparison.OrdinalIgnoreCase)) - { - mediaSourceId = null; - } - - MediaSourceInfo info; - bool isVideo; - ILiveTvService service; - IDirectStreamProvider directStreamProvider = null; - - if (isChannel) - { - var channel = GetInternalChannel(id); - isVideo = channel.ChannelType == ChannelType.TV; - service = GetService(channel); - _logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId); - - var supportsManagedStream = service as ISupportsDirectStreamProvider; - if (supportsManagedStream != null) - { - var streamInfo = await supportsManagedStream.GetChannelStreamWithDirectStreamProvider(channel.ExternalId, mediaSourceId, cancellationToken).ConfigureAwait(false); - info = streamInfo.Item1; - directStreamProvider = streamInfo.Item2; - } - else - { - info = await service.GetChannelStream(channel.ExternalId, mediaSourceId, cancellationToken).ConfigureAwait(false); - } - info.RequiresClosing = true; - - if (info.RequiresClosing) - { - var idPrefix = service.GetType().FullName.GetMD5().ToString("N") + "_"; - - info.LiveStreamId = idPrefix + info.Id; - } - } - else - { - var recording = await GetInternalRecording(id, cancellationToken).ConfigureAwait(false); - isVideo = !string.Equals(recording.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase); - service = GetService(recording); - - _logger.Info("Opening recording stream from {0}, external recording Id: {1}", service.Name, recording.ExternalId); - info = await service.GetRecordingStream(recording.ExternalId, null, cancellationToken).ConfigureAwait(false); - info.RequiresClosing = true; - - if (info.RequiresClosing) - { - var idPrefix = service.GetType().FullName.GetMD5().ToString("N") + "_"; - - info.LiveStreamId = idPrefix + info.Id; - } - } - - _logger.Info("Live stream info: {0}", _jsonSerializer.SerializeToString(info)); - Normalize(info, service, isVideo); - - return new Tuple<MediaSourceInfo, IDirectStreamProvider>(info, directStreamProvider); - } - - private void Normalize(MediaSourceInfo mediaSource, ILiveTvService service, bool isVideo) - { - if (mediaSource.MediaStreams.Count == 0) - { - if (isVideo) - { - mediaSource.MediaStreams.AddRange(new List<MediaStream> - { - new MediaStream - { - Type = MediaStreamType.Video, - // Set the index to -1 because we don't know the exact index of the video stream within the container - Index = -1, - - // Set to true if unknown to enable deinterlacing - IsInterlaced = true - }, - new MediaStream - { - Type = MediaStreamType.Audio, - // Set the index to -1 because we don't know the exact index of the audio stream within the container - Index = -1 - } - }); - } - else - { - mediaSource.MediaStreams.AddRange(new List<MediaStream> - { - new MediaStream - { - Type = MediaStreamType.Audio, - // Set the index to -1 because we don't know the exact index of the audio stream within the container - Index = -1 - } - }); - } - } - - // Clean some bad data coming from providers - foreach (var stream in mediaSource.MediaStreams) - { - if (stream.BitRate.HasValue && stream.BitRate <= 0) - { - stream.BitRate = null; - } - if (stream.Channels.HasValue && stream.Channels <= 0) - { - stream.Channels = null; - } - if (stream.AverageFrameRate.HasValue && stream.AverageFrameRate <= 0) - { - stream.AverageFrameRate = null; - } - if (stream.RealFrameRate.HasValue && stream.RealFrameRate <= 0) - { - stream.RealFrameRate = null; - } - if (stream.Width.HasValue && stream.Width <= 0) - { - stream.Width = null; - } - if (stream.Height.HasValue && stream.Height <= 0) - { - stream.Height = null; - } - if (stream.SampleRate.HasValue && stream.SampleRate <= 0) - { - stream.SampleRate = null; - } - if (stream.Level.HasValue && stream.Level <= 0) - { - stream.Level = null; - } - } - - var indexes = mediaSource.MediaStreams.Select(i => i.Index).Distinct().ToList(); - - // If there are duplicate stream indexes, set them all to unknown - if (indexes.Count != mediaSource.MediaStreams.Count) - { - foreach (var stream in mediaSource.MediaStreams) - { - stream.Index = -1; - } - } - - // 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; - } - } - - if (!(service is EmbyTV.EmbyTV)) - { - // We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says - mediaSource.SupportsDirectStream = false; - mediaSource.SupportsTranscoding = true; - foreach (var stream in mediaSource.MediaStreams) - { - if (stream.Type == MediaStreamType.Video && string.IsNullOrWhiteSpace(stream.NalLengthSize)) - { - stream.NalLengthSize = "0"; - } - } - } - } - - private async Task<LiveTvChannel> GetChannel(ChannelInfo channelInfo, string serviceName, Guid parentFolderId, CancellationToken cancellationToken) - { - var isNew = false; - var forceUpdate = false; - - var id = _tvDtoService.GetInternalChannelId(serviceName, channelInfo.Id); - - var item = _itemRepo.RetrieveItem(id) as LiveTvChannel; - - if (item == null) - { - item = new LiveTvChannel - { - Name = channelInfo.Name, - Id = id, - DateCreated = DateTime.UtcNow, - }; - - isNew = true; - } - - if (!string.Equals(channelInfo.Id, item.ExternalId)) - { - isNew = true; - } - item.ExternalId = channelInfo.Id; - - if (!item.ParentId.Equals(parentFolderId)) - { - isNew = true; - } - item.ParentId = parentFolderId; - - item.ChannelType = channelInfo.ChannelType; - item.ServiceName = serviceName; - item.Number = channelInfo.Number; - - //if (!string.Equals(item.ProviderImageUrl, channelInfo.ImageUrl, StringComparison.OrdinalIgnoreCase)) - //{ - // isNew = true; - // replaceImages.Add(ImageType.Primary); - //} - //if (!string.Equals(item.ProviderImagePath, channelInfo.ImagePath, StringComparison.OrdinalIgnoreCase)) - //{ - // isNew = true; - // replaceImages.Add(ImageType.Primary); - //} - - if (!item.HasImage(ImageType.Primary)) - { - if (!string.IsNullOrWhiteSpace(channelInfo.ImagePath)) - { - item.SetImagePath(ImageType.Primary, channelInfo.ImagePath); - forceUpdate = true; - } - else if (!string.IsNullOrWhiteSpace(channelInfo.ImageUrl)) - { - item.SetImagePath(ImageType.Primary, channelInfo.ImageUrl); - forceUpdate = true; - } - } - - if (string.IsNullOrEmpty(item.Name)) - { - item.Name = channelInfo.Name; - } - - if (isNew) - { - await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); - } - else if (forceUpdate) - { - await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); - } - - await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) - { - ForceSave = isNew || forceUpdate - - }, cancellationToken); - - return item; - } - - private Tuple<LiveTvProgram, bool, bool> GetProgram(ProgramInfo info, Dictionary<Guid, LiveTvProgram> allExistingPrograms, LiveTvChannel channel, ChannelType channelType, string serviceName, CancellationToken cancellationToken) - { - var id = _tvDtoService.GetInternalProgramId(serviceName, info.Id); - - LiveTvProgram item = null; - allExistingPrograms.TryGetValue(id, out item); - - var isNew = false; - var forceUpdate = false; - - if (item == null) - { - isNew = true; - item = new LiveTvProgram - { - Name = info.Name, - Id = id, - DateCreated = DateTime.UtcNow, - DateModified = DateTime.UtcNow, - ExternalEtag = info.Etag - }; - } - - var seriesId = info.SeriesId; - - if (!item.ParentId.Equals(channel.Id)) - { - forceUpdate = true; - } - item.ParentId = channel.Id; - - //item.ChannelType = channelType; - if (!string.Equals(item.ServiceName, serviceName, StringComparison.Ordinal)) - { - forceUpdate = true; - } - item.ServiceName = serviceName; - - item.Audio = info.Audio; - item.ChannelId = channel.Id.ToString("N"); - item.CommunityRating = item.CommunityRating ?? info.CommunityRating; - - item.EpisodeTitle = info.EpisodeTitle; - item.ExternalId = info.Id; - item.ExternalSeriesIdLegacy = seriesId; - - if (!string.IsNullOrWhiteSpace(seriesId) && !string.Equals(item.ExternalSeriesId, seriesId, StringComparison.Ordinal)) - { - forceUpdate = true; - } - item.ExternalSeriesId = seriesId; - - item.Genres = info.Genres; - item.IsHD = info.IsHD; - item.IsKids = info.IsKids; - item.IsLive = info.IsLive; - item.IsMovie = info.IsMovie; - item.IsNews = info.IsNews; - item.IsPremiere = info.IsPremiere; - item.IsRepeat = info.IsRepeat; - item.IsSeries = info.IsSeries; - item.IsSports = info.IsSports; - item.Name = info.Name; - item.OfficialRating = item.OfficialRating ?? info.OfficialRating; - item.Overview = item.Overview ?? info.Overview; - item.RunTimeTicks = (info.EndDate - info.StartDate).Ticks; - - if (item.StartDate != info.StartDate) - { - forceUpdate = true; - } - item.StartDate = info.StartDate; - - if (item.EndDate != info.EndDate) - { - forceUpdate = true; - } - item.EndDate = info.EndDate; - - item.HomePageUrl = info.HomePageUrl; - - item.ProductionYear = info.ProductionYear; - - if (!info.IsSeries || info.IsRepeat) - { - item.PremiereDate = info.OriginalAirDate; - } - - item.IndexNumber = info.EpisodeNumber; - item.ParentIndexNumber = info.SeasonNumber; - - if (!item.HasImage(ImageType.Primary)) - { - if (!string.IsNullOrWhiteSpace(info.ImagePath)) - { - item.SetImage(new ItemImageInfo - { - Path = info.ImagePath, - Type = ImageType.Primary, - IsPlaceholder = true - }, 0); - } - else if (!string.IsNullOrWhiteSpace(info.ImageUrl)) - { - item.SetImage(new ItemImageInfo - { - Path = info.ImageUrl, - Type = ImageType.Primary, - IsPlaceholder = true - }, 0); - } - } - - var isUpdated = false; - if (isNew) - { - } - else if (forceUpdate || string.IsNullOrWhiteSpace(info.Etag)) - { - isUpdated = true; - } - else - { - // Increment this whenver some internal change deems it necessary - var etag = info.Etag + "4"; - - if (!string.Equals(etag, item.ExternalEtag, StringComparison.OrdinalIgnoreCase)) - { - item.ExternalEtag = etag; - isUpdated = true; - } - } - - return new Tuple<LiveTvProgram, bool, bool>(item, isNew, isUpdated); - } - - private async Task<Guid> CreateRecordingRecord(RecordingInfo info, string serviceName, Guid parentFolderId, CancellationToken cancellationToken) - { - var isNew = false; - - var id = _tvDtoService.GetInternalRecordingId(serviceName, info.Id); - - var item = _itemRepo.RetrieveItem(id); - - if (item == null) - { - if (info.ChannelType == ChannelType.TV) - { - item = new LiveTvVideoRecording - { - Name = info.Name, - Id = id, - DateCreated = DateTime.UtcNow, - DateModified = DateTime.UtcNow, - VideoType = VideoType.VideoFile - }; - } - else - { - item = new LiveTvAudioRecording - { - Name = info.Name, - Id = id, - DateCreated = DateTime.UtcNow, - DateModified = DateTime.UtcNow - }; - } - - isNew = true; - } - - item.ChannelId = _tvDtoService.GetInternalChannelId(serviceName, info.ChannelId).ToString("N"); - item.CommunityRating = info.CommunityRating; - item.OfficialRating = info.OfficialRating; - item.Overview = info.Overview; - item.EndDate = info.EndDate; - item.Genres = info.Genres; - item.PremiereDate = info.OriginalAirDate; - - var recording = (ILiveTvRecording)item; - - recording.ExternalId = info.Id; - - var dataChanged = false; - - recording.Audio = info.Audio; - recording.EndDate = info.EndDate; - recording.EpisodeTitle = info.EpisodeTitle; - recording.IsHD = info.IsHD; - recording.IsKids = info.IsKids; - recording.IsLive = info.IsLive; - recording.IsMovie = info.IsMovie; - recording.IsNews = info.IsNews; - recording.IsPremiere = info.IsPremiere; - recording.IsRepeat = info.IsRepeat; - recording.IsSports = info.IsSports; - recording.SeriesTimerId = info.SeriesTimerId; - recording.TimerId = info.TimerId; - recording.StartDate = info.StartDate; - - if (!dataChanged) - { - dataChanged = recording.IsSeries != info.IsSeries; - } - recording.IsSeries = info.IsSeries; - - if (!item.ParentId.Equals(parentFolderId)) - { - dataChanged = true; - } - item.ParentId = parentFolderId; - - if (!item.HasImage(ImageType.Primary)) - { - if (!string.IsNullOrWhiteSpace(info.ImagePath)) - { - item.SetImage(new ItemImageInfo - { - Path = info.ImagePath, - Type = ImageType.Primary, - IsPlaceholder = true - }, 0); - } - else if (!string.IsNullOrWhiteSpace(info.ImageUrl)) - { - item.SetImage(new ItemImageInfo - { - Path = info.ImageUrl, - Type = ImageType.Primary, - IsPlaceholder = true - }, 0); - } - } - - var statusChanged = info.Status != recording.Status; - - recording.Status = info.Status; - - recording.ServiceName = serviceName; - - if (!string.IsNullOrEmpty(info.Path)) - { - if (!dataChanged) - { - dataChanged = !string.Equals(item.Path, info.Path); - } - var fileInfo = _fileSystem.GetFileInfo(info.Path); - - recording.DateCreated = _fileSystem.GetCreationTimeUtc(fileInfo); - recording.DateModified = _fileSystem.GetLastWriteTimeUtc(fileInfo); - item.Path = info.Path; - } - else if (!string.IsNullOrEmpty(info.Url)) - { - if (!dataChanged) - { - dataChanged = !string.Equals(item.Path, info.Url); - } - item.Path = info.Url; - } - - var metadataRefreshMode = MetadataRefreshMode.Default; - - if (isNew) - { - await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); - } - else if (dataChanged || info.DateLastUpdated > recording.DateLastSaved || statusChanged) - { - metadataRefreshMode = MetadataRefreshMode.FullRefresh; - await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); - } - - if (info.Status != RecordingStatus.InProgress) - { - _providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem) - { - MetadataRefreshMode = metadataRefreshMode - }); - } - - return item.Id; - } - - public async Task<BaseItemDto> GetProgram(string id, CancellationToken cancellationToken, User user = null) - { - var program = GetInternalProgram(id); - - var dto = _dtoService.GetBaseItemDto(program, new DtoOptions(), user); - - var list = new List<Tuple<BaseItemDto, string, string, string>>(); - list.Add(new Tuple<BaseItemDto, string, string, string>(dto, program.ServiceName, program.ExternalId, program.ExternalSeriesIdLegacy)); - - await AddRecordingInfo(list, cancellationToken).ConfigureAwait(false); - - return dto; - } - - public async Task<QueryResult<BaseItemDto>> GetPrograms(ProgramQuery query, DtoOptions options, CancellationToken cancellationToken) - { - var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); - - var topFolder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); - - if (query.SortBy.Length == 0) - { - // Unless something else was specified, order by start date to take advantage of a specialized index - query.SortBy = new[] { ItemSortBy.StartDate }; - } - - var internalQuery = new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(LiveTvProgram).Name }, - MinEndDate = query.MinEndDate, - MinStartDate = query.MinStartDate, - MaxEndDate = query.MaxEndDate, - MaxStartDate = query.MaxStartDate, - ChannelIds = query.ChannelIds, - IsMovie = query.IsMovie, - IsSeries = query.IsSeries, - IsSports = query.IsSports, - IsKids = query.IsKids, - IsNews = query.IsNews, - Genres = query.Genres, - StartIndex = query.StartIndex, - Limit = query.Limit, - SortBy = query.SortBy, - SortOrder = query.SortOrder ?? SortOrder.Ascending, - EnableTotalRecordCount = query.EnableTotalRecordCount, - TopParentIds = new[] { topFolder.Id.ToString("N") }, - Name = query.Name, - DtoOptions = options - }; - - if (!string.IsNullOrWhiteSpace(query.SeriesTimerId)) - { - var seriesTimers = await GetSeriesTimersInternal(new SeriesTimerQuery { }, cancellationToken).ConfigureAwait(false); - var seriesTimer = seriesTimers.Items.FirstOrDefault(i => string.Equals(_tvDtoService.GetInternalSeriesTimerId(i.ServiceName, i.Id).ToString("N"), query.SeriesTimerId, StringComparison.OrdinalIgnoreCase)); - if (seriesTimer != null) - { - internalQuery.ExternalSeriesId = seriesTimer.SeriesId; - - if (string.IsNullOrWhiteSpace(seriesTimer.SeriesId)) - { - // Better to return nothing than every program in the database - return new QueryResult<BaseItemDto>(); - } - } - else - { - // Better to return nothing than every program in the database - return new QueryResult<BaseItemDto>(); - } - } - - if (query.HasAired.HasValue) - { - if (query.HasAired.Value) - { - internalQuery.MaxEndDate = DateTime.UtcNow; - } - else - { - internalQuery.MinEndDate = DateTime.UtcNow; - } - } - - var queryResult = _libraryManager.QueryItems(internalQuery); - - RemoveFields(options); - - var returnArray = (await _dtoService.GetBaseItemDtos(queryResult.Items, options, user).ConfigureAwait(false)).ToArray(); - - var result = new QueryResult<BaseItemDto> - { - Items = returnArray, - TotalRecordCount = queryResult.TotalRecordCount - }; - - return result; - } - - public async Task<QueryResult<LiveTvProgram>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken) - { - var user = _userManager.GetUserById(query.UserId); - - var topFolder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); - - var internalQuery = new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(LiveTvProgram).Name }, - IsAiring = query.IsAiring, - IsNews = query.IsNews, - IsMovie = query.IsMovie, - IsSeries = query.IsSeries, - IsSports = query.IsSports, - IsKids = query.IsKids, - EnableTotalRecordCount = query.EnableTotalRecordCount, - SortBy = new[] { ItemSortBy.StartDate }, - TopParentIds = new[] { topFolder.Id.ToString("N") }, - DtoOptions = options - }; - - if (query.Limit.HasValue) - { - internalQuery.Limit = Math.Max(query.Limit.Value * 4, 200); - } - - if (query.HasAired.HasValue) - { - if (query.HasAired.Value) - { - internalQuery.MaxEndDate = DateTime.UtcNow; - } - else - { - internalQuery.MinEndDate = DateTime.UtcNow; - } - } - - IEnumerable<LiveTvProgram> programs = _libraryManager.QueryItems(internalQuery).Items.Cast<LiveTvProgram>(); - - var programList = programs.ToList(); - - var factorChannelWatchCount = (query.IsAiring ?? false) || (query.IsKids ?? false) || (query.IsSports ?? false) || (query.IsMovie ?? false) || (query.IsNews ?? false) || (query.IsSeries ?? false); - - programs = programList.OrderBy(i => i.StartDate.Date) - .ThenByDescending(i => GetRecommendationScore(i, user.Id, factorChannelWatchCount)) - .ThenBy(i => i.StartDate); - - if (query.Limit.HasValue) - { - programs = programs.Take(query.Limit.Value); - } - - programList = programs.ToList(); - - var returnArray = programList.ToArray(); - - var result = new QueryResult<LiveTvProgram> - { - Items = returnArray, - TotalRecordCount = returnArray.Length - }; - - return result; - } - - public async Task<QueryResult<BaseItemDto>> GetRecommendedPrograms(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken) - { - var internalResult = await GetRecommendedProgramsInternal(query, options, cancellationToken).ConfigureAwait(false); - - var user = _userManager.GetUserById(query.UserId); - - RemoveFields(options); - - var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user).ConfigureAwait(false)).ToArray(); - - var result = new QueryResult<BaseItemDto> - { - Items = returnArray, - TotalRecordCount = internalResult.TotalRecordCount - }; - - return result; - } - - private int GetRecommendationScore(LiveTvProgram program, Guid userId, bool factorChannelWatchCount) - { - var score = 0; - - if (program.IsLive) - { - score++; - } - - if (program.IsSeries && !program.IsRepeat) - { - score++; - } - - var channel = GetInternalChannel(program.ChannelId); - - var channelUserdata = _userDataManager.GetUserData(userId, channel); - - if (channelUserdata.Likes ?? false) - { - score += 2; - } - else if (!(channelUserdata.Likes ?? true)) - { - score -= 2; - } - - if (channelUserdata.IsFavorite) - { - score += 3; - } - - if (factorChannelWatchCount) - { - score += channelUserdata.PlayCount; - } - - return score; - } - - private async Task AddRecordingInfo(IEnumerable<Tuple<BaseItemDto, string, string, string>> programs, CancellationToken cancellationToken) - { - var timers = new Dictionary<string, List<TimerInfo>>(); - var seriesTimers = new Dictionary<string, List<SeriesTimerInfo>>(); - - foreach (var programTuple in programs) - { - var program = programTuple.Item1; - var serviceName = programTuple.Item2; - var externalProgramId = programTuple.Item3; - string externalSeriesId = programTuple.Item4; - - if (string.IsNullOrWhiteSpace(serviceName)) - { - continue; - } - - List<TimerInfo> timerList; - if (!timers.TryGetValue(serviceName, out timerList)) - { - try - { - var tempTimers = await GetService(serviceName).GetTimersAsync(cancellationToken).ConfigureAwait(false); - timers[serviceName] = timerList = tempTimers.ToList(); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting timer infos", ex); - timers[serviceName] = timerList = new List<TimerInfo>(); - } - } - - var timer = timerList.FirstOrDefault(i => string.Equals(i.ProgramId, externalProgramId, StringComparison.OrdinalIgnoreCase)); - var foundSeriesTimer = false; - - if (timer != null) - { - if (timer.Status != RecordingStatus.Cancelled && timer.Status != RecordingStatus.Error) - { - program.TimerId = _tvDtoService.GetInternalTimerId(serviceName, timer.Id) - .ToString("N"); - - program.Status = timer.Status.ToString(); - } - - if (!string.IsNullOrEmpty(timer.SeriesTimerId)) - { - program.SeriesTimerId = _tvDtoService.GetInternalSeriesTimerId(serviceName, timer.SeriesTimerId) - .ToString("N"); - - foundSeriesTimer = true; - } - } - - if (foundSeriesTimer || string.IsNullOrWhiteSpace(externalSeriesId)) - { - continue; - } - - List<SeriesTimerInfo> seriesTimerList; - if (!seriesTimers.TryGetValue(serviceName, out seriesTimerList)) - { - try - { - var tempTimers = await GetService(serviceName).GetSeriesTimersAsync(cancellationToken).ConfigureAwait(false); - seriesTimers[serviceName] = seriesTimerList = tempTimers.ToList(); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting series timer infos", ex); - seriesTimers[serviceName] = seriesTimerList = new List<SeriesTimerInfo>(); - } - } - - var seriesTimer = seriesTimerList.FirstOrDefault(i => string.Equals(i.SeriesId, externalSeriesId, StringComparison.OrdinalIgnoreCase)); - - if (seriesTimer != null) - { - program.SeriesTimerId = _tvDtoService.GetInternalSeriesTimerId(serviceName, seriesTimer.Id) - .ToString("N"); - } - } - } - - internal Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken) - { - return RefreshChannelsInternal(progress, cancellationToken); - } - - private async Task RefreshChannelsInternal(IProgress<double> progress, CancellationToken cancellationToken) - { - EmbyTV.EmbyTV.Current.CreateRecordingFolders(); - - var numComplete = 0; - double progressPerService = _services.Count == 0 - ? 0 - : 1 / _services.Count; - - var newChannelIdList = new List<Guid>(); - var newProgramIdList = new List<Guid>(); - - foreach (var service in _services) - { - cancellationToken.ThrowIfCancellationRequested(); - - _logger.Debug("Refreshing guide from {0}", service.Name); - - try - { - var innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(p => progress.Report(p * progressPerService)); - - var idList = await RefreshChannelsInternal(service, innerProgress, cancellationToken).ConfigureAwait(false); - - newChannelIdList.AddRange(idList.Item1); - newProgramIdList.AddRange(idList.Item2); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing channels for service", ex); - } - - numComplete++; - double percent = numComplete; - percent /= _services.Count; - - progress.Report(100 * percent); - } - - await CleanDatabaseInternal(newChannelIdList, new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false); - await CleanDatabaseInternal(newProgramIdList, new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false); - - var coreService = _services.OfType<EmbyTV.EmbyTV>().FirstOrDefault(); - - if (coreService != null) - { - await coreService.RefreshSeriesTimers(cancellationToken, new Progress<double>()).ConfigureAwait(false); - } - - // Load these now which will prefetch metadata - var dtoOptions = new DtoOptions(); - dtoOptions.Fields.Remove(ItemFields.SyncInfo); - dtoOptions.Fields.Remove(ItemFields.BasicSyncInfo); - await GetRecordings(new RecordingQuery(), dtoOptions, cancellationToken).ConfigureAwait(false); - - progress.Report(100); - } - - private async Task<Tuple<List<Guid>, List<Guid>>> RefreshChannelsInternal(ILiveTvService service, IProgress<double> progress, CancellationToken cancellationToken) - { - progress.Report(10); - - var allChannels = await GetChannels(service, cancellationToken).ConfigureAwait(false); - var allChannelsList = allChannels.ToList(); - - var list = new List<LiveTvChannel>(); - - var numComplete = 0; - var parentFolder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); - var parentFolderId = parentFolder.Id; - - foreach (var channelInfo in allChannelsList) - { - cancellationToken.ThrowIfCancellationRequested(); - - try - { - var item = await GetChannel(channelInfo.Item2, channelInfo.Item1, parentFolderId, cancellationToken).ConfigureAwait(false); - - list.Add(item); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error getting channel information for {0}", ex, channelInfo.Item2.Name); - } - - numComplete++; - double percent = numComplete; - percent /= allChannelsList.Count; - - progress.Report(5 * percent + 10); - } - - progress.Report(15); - - numComplete = 0; - var programs = new List<Guid>(); - var channels = new List<Guid>(); - - var guideDays = GetGuideDays(); - - _logger.Info("Refreshing guide with {0} days of guide data", guideDays); - - cancellationToken.ThrowIfCancellationRequested(); - - foreach (var currentChannel in list) - { - channels.Add(currentChannel.Id); - cancellationToken.ThrowIfCancellationRequested(); - - try - { - var start = DateTime.UtcNow.AddHours(-1); - var end = start.AddDays(guideDays); - - var isMovie = false; - var isSports = false; - var isNews = false; - var isKids = false; - var iSSeries = false; - - var channelPrograms = await service.GetProgramsAsync(currentChannel.ExternalId, start, end, cancellationToken).ConfigureAwait(false); - - var existingPrograms = _libraryManager.GetItemList(new InternalItemsQuery - { - - IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name }, - ChannelIds = new string[] { currentChannel.Id.ToString("N") } - - }).Cast<LiveTvProgram>().ToDictionary(i => i.Id); - - var newPrograms = new List<LiveTvProgram>(); - var updatedPrograms = new List<LiveTvProgram>(); - - foreach (var program in channelPrograms) - { - var programTuple = GetProgram(program, existingPrograms, currentChannel, currentChannel.ChannelType, service.Name, cancellationToken); - var programItem = programTuple.Item1; - - if (programTuple.Item2) - { - newPrograms.Add(programItem); - } - else if (programTuple.Item3) - { - updatedPrograms.Add(programItem); - } - - programs.Add(programItem.Id); - - if (program.IsMovie) - { - isMovie = true; - } - - if (program.IsSeries) - { - iSSeries = true; - } - - if (program.IsSports) - { - isSports = true; - } - - if (program.IsNews) - { - isNews = true; - } - - if (program.IsKids) - { - isKids = true; - } - } - - _logger.Debug("Channel {0} has {1} new programs and {2} updated programs", currentChannel.Name, newPrograms.Count, updatedPrograms.Count); - - if (newPrograms.Count > 0) - { - await _libraryManager.CreateItems(newPrograms, cancellationToken).ConfigureAwait(false); - } - - // TODO: Do this in bulk - foreach (var program in updatedPrograms) - { - await _libraryManager.UpdateItem(program, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); - } - - foreach (var program in newPrograms) - { - _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem)); - } - foreach (var program in updatedPrograms) - { - _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem)); - } - - currentChannel.IsMovie = isMovie; - currentChannel.IsNews = isNews; - currentChannel.IsSports = isSports; - currentChannel.IsKids = isKids; - currentChannel.IsSeries = iSSeries; - - await currentChannel.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error getting programs for channel {0}", ex, currentChannel.Name); - } - - numComplete++; - double percent = numComplete; - percent /= allChannelsList.Count; - - progress.Report(80 * percent + 10); - } - progress.Report(100); - - return new Tuple<List<Guid>, List<Guid>>(channels, programs); - } - - private async Task CleanDatabaseInternal(List<Guid> currentIdList, string[] validTypes, IProgress<double> progress, CancellationToken cancellationToken) - { - var list = _itemRepo.GetItemIdsList(new InternalItemsQuery - { - IncludeItemTypes = validTypes - - }).ToList(); - - var numComplete = 0; - - foreach (var itemId in list) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (itemId == Guid.Empty) - { - // Somehow some invalid data got into the db. It probably predates the boundary checking - continue; - } - - if (!currentIdList.Contains(itemId)) - { - var item = _libraryManager.GetItemById(itemId); - - if (item != null) - { - await _libraryManager.DeleteItem(item, new DeleteOptions - { - DeleteFileLocation = false - - }).ConfigureAwait(false); - } - } - - numComplete++; - double percent = numComplete; - percent /= list.Count; - - progress.Report(100 * percent); - } - } - - private const int MaxGuideDays = 14; - private double GetGuideDays() - { - var config = GetConfiguration(); - - if (config.GuideDays.HasValue) - { - return Math.Max(1, Math.Min(config.GuideDays.Value, MaxGuideDays)); - } - - return 7; - } - - private async Task<IEnumerable<Tuple<string, ChannelInfo>>> GetChannels(ILiveTvService service, CancellationToken cancellationToken) - { - var channels = await service.GetChannelsAsync(cancellationToken).ConfigureAwait(false); - - return channels.Select(i => new Tuple<string, ChannelInfo>(service.Name, i)); - } - - private DateTime _lastRecordingRefreshTime; - private async Task RefreshRecordings(CancellationToken cancellationToken) - { - const int cacheMinutes = 3; - - if ((DateTime.UtcNow - _lastRecordingRefreshTime).TotalMinutes < cacheMinutes) - { - return; - } - - await _refreshRecordingsLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - if ((DateTime.UtcNow - _lastRecordingRefreshTime).TotalMinutes < cacheMinutes) - { - return; - } - - var tasks = _services.Select(async i => - { - try - { - var recs = await i.GetRecordingsAsync(cancellationToken).ConfigureAwait(false); - return recs.Select(r => new Tuple<RecordingInfo, ILiveTvService>(r, i)); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting recordings", ex); - return new List<Tuple<RecordingInfo, ILiveTvService>>(); - } - }); - - var results = await Task.WhenAll(tasks).ConfigureAwait(false); - var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); - var parentFolderId = folder.Id; - - var recordingTasks = results.SelectMany(i => i.ToList()).Select(i => CreateRecordingRecord(i.Item1, i.Item2.Name, parentFolderId, cancellationToken)); - - var idList = await Task.WhenAll(recordingTasks).ConfigureAwait(false); - - await CleanDatabaseInternal(idList.ToList(), new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }, new Progress<double>(), cancellationToken).ConfigureAwait(false); - - _lastRecordingRefreshTime = DateTime.UtcNow; - } - finally - { - _refreshRecordingsLock.Release(); - } - } - - private QueryResult<BaseItem> GetEmbyRecordings(RecordingQuery query, DtoOptions dtoOptions, User user) - { - if (user == null) - { - return new QueryResult<BaseItem>(); - } - - if ((query.IsInProgress ?? false)) - { - return new QueryResult<BaseItem>(); - } - - var folders = EmbyTV.EmbyTV.Current.GetRecordingFolders() - .SelectMany(i => i.Locations) - .Distinct(StringComparer.OrdinalIgnoreCase) - .Select(i => _libraryManager.FindByPath(i, true)) - .Where(i => i != null) - .Where(i => i.IsVisibleStandalone(user)) - .ToList(); - - if (folders.Count == 0) - { - return new QueryResult<BaseItem>(); - } - - var includeItemTypes = new List<string>(); - var excludeItemTypes = new List<string>(); - var genres = new List<string>(); - - if (query.IsMovie.HasValue) - { - if (query.IsMovie.Value) - { - includeItemTypes.Add(typeof(Movie).Name); - } - else - { - excludeItemTypes.Add(typeof(Movie).Name); - } - } - if (query.IsSeries.HasValue) - { - if (query.IsSeries.Value) - { - includeItemTypes.Add(typeof(Episode).Name); - } - else - { - excludeItemTypes.Add(typeof(Episode).Name); - } - } - if (query.IsSports.HasValue) - { - if (query.IsSports.Value) - { - genres.Add("Sports"); - } - } - if (query.IsKids.HasValue) - { - if (query.IsKids.Value) - { - genres.Add("Kids"); - genres.Add("Children"); - genres.Add("Family"); - } - } - - return _libraryManager.GetItemsResult(new InternalItemsQuery(user) - { - MediaTypes = new[] { MediaType.Video }, - Recursive = true, - AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(), - IsFolder = false, - ExcludeLocationTypes = new[] { LocationType.Virtual }, - Limit = query.Limit, - SortBy = new[] { ItemSortBy.DateCreated }, - SortOrder = SortOrder.Descending, - EnableTotalRecordCount = query.EnableTotalRecordCount, - IncludeItemTypes = includeItemTypes.ToArray(), - ExcludeItemTypes = excludeItemTypes.ToArray(), - Genres = genres.ToArray(), - DtoOptions = dtoOptions - }); - } - - public async Task<QueryResult<BaseItemDto>> GetRecordingSeries(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken) - { - var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); - if (user != null && !IsLiveTvEnabled(user)) - { - return new QueryResult<BaseItemDto>(); - } - - if (_services.Count > 1) - { - return new QueryResult<BaseItemDto>(); - } - - if (user == null || (query.IsInProgress ?? false)) - { - return new QueryResult<BaseItemDto>(); - } - - var folders = EmbyTV.EmbyTV.Current.GetRecordingFolders() - .SelectMany(i => i.Locations) - .Distinct(StringComparer.OrdinalIgnoreCase) - .Select(i => _libraryManager.FindByPath(i, true)) - .Where(i => i != null) - .Where(i => i.IsVisibleStandalone(user)) - .ToList(); - - if (folders.Count == 0) - { - return new QueryResult<BaseItemDto>(); - } - - var includeItemTypes = new List<string>(); - var excludeItemTypes = new List<string>(); - - includeItemTypes.Add(typeof(Series).Name); - - var internalResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user) - { - Recursive = true, - AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(), - Limit = query.Limit, - SortBy = new[] { ItemSortBy.DateCreated }, - SortOrder = SortOrder.Descending, - EnableTotalRecordCount = query.EnableTotalRecordCount, - IncludeItemTypes = includeItemTypes.ToArray(), - ExcludeItemTypes = excludeItemTypes.ToArray() - }); - - RemoveFields(options); - - var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user).ConfigureAwait(false)).ToArray(); - - return new QueryResult<BaseItemDto> - { - Items = returnArray, - TotalRecordCount = internalResult.TotalRecordCount - }; - } - - public async Task<QueryResult<BaseItem>> GetInternalRecordings(RecordingQuery query, CancellationToken cancellationToken) - { - var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); - if (user != null && !IsLiveTvEnabled(user)) - { - return new QueryResult<BaseItem>(); - } - - if (_services.Count == 1 && !(query.IsInProgress ?? false)) - { - return GetEmbyRecordings(query, new DtoOptions(), user); - } - - await RefreshRecordings(cancellationToken).ConfigureAwait(false); - - var internalQuery = new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name } - }; - - if (!string.IsNullOrEmpty(query.ChannelId)) - { - internalQuery.ChannelIds = new[] { query.ChannelId }; - } - - var queryResult = _libraryManager.GetItemList(internalQuery); - IEnumerable<ILiveTvRecording> recordings = queryResult.Cast<ILiveTvRecording>(); - - if (!string.IsNullOrWhiteSpace(query.Id)) - { - var guid = new Guid(query.Id); - - recordings = recordings - .Where(i => i.Id == guid); - } - - if (!string.IsNullOrWhiteSpace(query.GroupId)) - { - var guid = new Guid(query.GroupId); - - recordings = recordings.Where(i => GetRecordingGroupIds(i).Contains(guid)); - } - - if (query.IsInProgress.HasValue) - { - var val = query.IsInProgress.Value; - recordings = recordings.Where(i => i.Status == RecordingStatus.InProgress == val); - } - - if (query.Status.HasValue) - { - var val = query.Status.Value; - recordings = recordings.Where(i => i.Status == val); - } - - if (query.IsMovie.HasValue) - { - var val = query.IsMovie.Value; - recordings = recordings.Where(i => i.IsMovie == val); - } - - if (query.IsNews.HasValue) - { - var val = query.IsNews.Value; - recordings = recordings.Where(i => i.IsNews == val); - } - - if (query.IsSeries.HasValue) - { - var val = query.IsSeries.Value; - recordings = recordings.Where(i => i.IsSeries == val); - } - - if (query.IsKids.HasValue) - { - var val = query.IsKids.Value; - recordings = recordings.Where(i => i.IsKids == val); - } - - if (query.IsSports.HasValue) - { - var val = query.IsSports.Value; - recordings = recordings.Where(i => i.IsSports == val); - } - - if (!string.IsNullOrEmpty(query.SeriesTimerId)) - { - var guid = new Guid(query.SeriesTimerId); - - recordings = recordings - .Where(i => _tvDtoService.GetInternalSeriesTimerId(i.ServiceName, i.SeriesTimerId) == guid); - } - - recordings = recordings.OrderByDescending(i => i.StartDate); - - var entityList = recordings.ToList(); - IEnumerable<ILiveTvRecording> entities = entityList; - - if (query.StartIndex.HasValue) - { - entities = entities.Skip(query.StartIndex.Value); - } - - if (query.Limit.HasValue) - { - entities = entities.Take(query.Limit.Value); - } - - return new QueryResult<BaseItem> - { - Items = entities.Cast<BaseItem>().ToArray(), - TotalRecordCount = entityList.Count - }; - } - - public async Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> tuples, List<ItemFields> fields, User user = null) - { - var programTuples = new List<Tuple<BaseItemDto, string, string, string>>(); - - foreach (var tuple in tuples) - { - var program = (LiveTvProgram)tuple.Item1; - var dto = tuple.Item2; - - dto.StartDate = program.StartDate; - dto.EpisodeTitle = program.EpisodeTitle; - - if (program.IsRepeat) - { - dto.IsRepeat = program.IsRepeat; - } - if (program.IsMovie) - { - dto.IsMovie = program.IsMovie; - } - if (program.IsSeries) - { - dto.IsSeries = program.IsSeries; - } - if (program.IsSports) - { - dto.IsSports = program.IsSports; - } - if (program.IsLive) - { - dto.IsLive = program.IsLive; - } - if (program.IsNews) - { - dto.IsNews = program.IsNews; - } - if (program.IsKids) - { - dto.IsKids = program.IsKids; - } - if (program.IsPremiere) - { - dto.IsPremiere = program.IsPremiere; - } - - if (fields.Contains(ItemFields.ChannelInfo)) - { - var channel = GetInternalChannel(program.ChannelId); - - if (channel != null) - { - dto.ChannelName = channel.Name; - dto.MediaType = channel.MediaType; - dto.ChannelNumber = channel.Number; - - if (channel.HasImage(ImageType.Primary)) - { - dto.ChannelPrimaryImageTag = _tvDtoService.GetImageTag(channel); - } - } - } - - var serviceName = program.ServiceName; - - if (fields.Contains(ItemFields.ServiceName)) - { - dto.ServiceName = serviceName; - } - - programTuples.Add(new Tuple<BaseItemDto, string, string, string>(dto, serviceName, program.ExternalId, program.ExternalSeriesIdLegacy)); - } - - await AddRecordingInfo(programTuples, CancellationToken.None).ConfigureAwait(false); - } - - public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, User user = null) - { - var recording = (ILiveTvRecording)item; - var service = GetService(recording); - - var channel = string.IsNullOrWhiteSpace(recording.ChannelId) ? null : GetInternalChannel(recording.ChannelId); - - var info = recording; - - dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId) - ? null - : _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N"); - - dto.TimerId = string.IsNullOrEmpty(info.TimerId) - ? null - : _tvDtoService.GetInternalTimerId(service.Name, info.TimerId).ToString("N"); - - dto.StartDate = info.StartDate; - dto.RecordingStatus = info.Status; - dto.IsRepeat = info.IsRepeat; - dto.EpisodeTitle = info.EpisodeTitle; - dto.IsMovie = info.IsMovie; - dto.IsSeries = info.IsSeries; - dto.IsSports = info.IsSports; - dto.IsLive = info.IsLive; - dto.IsNews = info.IsNews; - dto.IsKids = info.IsKids; - dto.IsPremiere = info.IsPremiere; - - dto.CanDelete = user == null - ? recording.CanDelete() - : recording.CanDelete(user); - - if (dto.MediaSources == null) - { - dto.MediaSources = recording.GetMediaSources(true).ToList(); - } - - if (dto.MediaStreams == null) - { - dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToList(); - } - - if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue) - { - var now = DateTime.UtcNow.Ticks; - var start = info.StartDate.Ticks; - var end = info.EndDate.Value.Ticks; - - var pct = now - start; - pct /= end; - pct *= 100; - dto.CompletionPercentage = pct; - } - - if (channel != null) - { - dto.ChannelName = channel.Name; - - if (channel.HasImage(ImageType.Primary)) - { - dto.ChannelPrimaryImageTag = _tvDtoService.GetImageTag(channel); - } - } - } - - public async Task<QueryResult<BaseItemDto>> GetRecordings(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken) - { - var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); - - var internalResult = await GetInternalRecordings(query, cancellationToken).ConfigureAwait(false); - - RemoveFields(options); - - var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user).ConfigureAwait(false)).ToArray(); - - return new QueryResult<BaseItemDto> - { - Items = returnArray, - TotalRecordCount = internalResult.TotalRecordCount - }; - } - - public async Task<QueryResult<TimerInfoDto>> GetTimers(TimerQuery query, CancellationToken cancellationToken) - { - var tasks = _services.Select(async i => - { - try - { - var recs = await i.GetTimersAsync(cancellationToken).ConfigureAwait(false); - return recs.Select(r => new Tuple<TimerInfo, ILiveTvService>(r, i)); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting recordings", ex); - return new List<Tuple<TimerInfo, ILiveTvService>>(); - } - }); - var results = await Task.WhenAll(tasks).ConfigureAwait(false); - var timers = results.SelectMany(i => i.ToList()); - - if (query.IsActive.HasValue) - { - if (query.IsActive.Value) - { - timers = timers.Where(i => i.Item1.Status == RecordingStatus.InProgress); - } - else - { - timers = timers.Where(i => i.Item1.Status != RecordingStatus.InProgress); - } - } - - if (query.IsScheduled.HasValue) - { - if (query.IsScheduled.Value) - { - timers = timers.Where(i => i.Item1.Status == RecordingStatus.New); - } - else - { - timers = timers.Where(i => i.Item1.Status != RecordingStatus.New); - } - } - - if (!string.IsNullOrEmpty(query.ChannelId)) - { - var guid = new Guid(query.ChannelId); - timers = timers.Where(i => guid == _tvDtoService.GetInternalChannelId(i.Item2.Name, i.Item1.ChannelId)); - } - - if (!string.IsNullOrEmpty(query.SeriesTimerId)) - { - var guid = new Guid(query.SeriesTimerId); - - timers = timers - .Where(i => _tvDtoService.GetInternalSeriesTimerId(i.Item2.Name, i.Item1.SeriesTimerId) == guid); - } - - var returnList = new List<TimerInfoDto>(); - - foreach (var i in timers) - { - var program = string.IsNullOrEmpty(i.Item1.ProgramId) ? - null : - GetInternalProgram(_tvDtoService.GetInternalProgramId(i.Item2.Name, i.Item1.ProgramId).ToString("N")); - - var channel = string.IsNullOrEmpty(i.Item1.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(i.Item2.Name, i.Item1.ChannelId)); - - returnList.Add(_tvDtoService.GetTimerInfoDto(i.Item1, i.Item2, program, channel)); - } - - var returnArray = returnList - .OrderBy(i => i.StartDate) - .ToArray(); - - return new QueryResult<TimerInfoDto> - { - Items = returnArray, - TotalRecordCount = returnArray.Length - }; - } - - public Task OnRecordingFileDeleted(BaseItem recording) - { - var service = GetService(recording); - - if (service is EmbyTV.EmbyTV) - { - // We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says - return service.DeleteRecordingAsync(recording.ExternalId, CancellationToken.None); - } - - return Task.FromResult(true); - } - - public async Task DeleteRecording(string recordingId) - { - var recording = await GetInternalRecording(recordingId, CancellationToken.None).ConfigureAwait(false); - - if (recording == null) - { - throw new ResourceNotFoundException(string.Format("Recording with Id {0} not found", recordingId)); - } - - await DeleteRecording((BaseItem)recording).ConfigureAwait(false); - } - - public async Task DeleteRecording(BaseItem recording) - { - var service = GetService(recording.ServiceName); - - try - { - await service.DeleteRecordingAsync(recording.ExternalId, CancellationToken.None).ConfigureAwait(false); - } - catch (ResourceNotFoundException) - { - - } - - _lastRecordingRefreshTime = DateTime.MinValue; - - // This is the responsibility of the live tv service - await _libraryManager.DeleteItem((BaseItem)recording, new DeleteOptions - { - DeleteFileLocation = false - - }).ConfigureAwait(false); - - _lastRecordingRefreshTime = DateTime.MinValue; - } - - public async Task CancelTimer(string id) - { - var timer = await GetTimer(id, CancellationToken.None).ConfigureAwait(false); - - if (timer == null) - { - throw new ResourceNotFoundException(string.Format("Timer with Id {0} not found", id)); - } - - var service = GetService(timer.ServiceName); - - await service.CancelTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false); - _lastRecordingRefreshTime = DateTime.MinValue; - - EventHelper.QueueEventIfNotNull(TimerCancelled, this, new GenericEventArgs<TimerEventInfo> - { - Argument = new TimerEventInfo - { - Id = id - } - }, _logger); - } - - public async Task CancelSeriesTimer(string id) - { - var timer = await GetSeriesTimer(id, CancellationToken.None).ConfigureAwait(false); - - if (timer == null) - { - throw new ResourceNotFoundException(string.Format("Timer with Id {0} not found", id)); - } - - var service = GetService(timer.ServiceName); - - await service.CancelSeriesTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false); - _lastRecordingRefreshTime = DateTime.MinValue; - - EventHelper.QueueEventIfNotNull(SeriesTimerCancelled, this, new GenericEventArgs<TimerEventInfo> - { - Argument = new TimerEventInfo - { - Id = id - } - }, _logger); - } - - public async Task<BaseItemDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null) - { - var item = await GetInternalRecording(id, cancellationToken).ConfigureAwait(false); - - if (item == null) - { - return null; - } - - return _dtoService.GetBaseItemDto((BaseItem)item, options, user); - } - - public async Task<TimerInfoDto> GetTimer(string id, CancellationToken cancellationToken) - { - var results = await GetTimers(new TimerQuery(), cancellationToken).ConfigureAwait(false); - - return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)); - } - - public async Task<SeriesTimerInfoDto> GetSeriesTimer(string id, CancellationToken cancellationToken) - { - var results = await GetSeriesTimers(new SeriesTimerQuery(), cancellationToken).ConfigureAwait(false); - - return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)); - } - - private async Task<QueryResult<SeriesTimerInfo>> GetSeriesTimersInternal(SeriesTimerQuery query, CancellationToken cancellationToken) - { - var tasks = _services.Select(async i => - { - try - { - var recs = await i.GetSeriesTimersAsync(cancellationToken).ConfigureAwait(false); - return recs.Select(r => - { - r.ServiceName = i.Name; - return new Tuple<SeriesTimerInfo, ILiveTvService>(r, i); - }); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting recordings", ex); - return new List<Tuple<SeriesTimerInfo, ILiveTvService>>(); - } - }); - var results = await Task.WhenAll(tasks).ConfigureAwait(false); - var timers = results.SelectMany(i => i.ToList()); - - if (string.Equals(query.SortBy, "Priority", StringComparison.OrdinalIgnoreCase)) - { - timers = query.SortOrder == SortOrder.Descending ? - timers.OrderBy(i => i.Item1.Priority).ThenByStringDescending(i => i.Item1.Name) : - timers.OrderByDescending(i => i.Item1.Priority).ThenByString(i => i.Item1.Name); - } - else - { - timers = query.SortOrder == SortOrder.Descending ? - timers.OrderByStringDescending(i => i.Item1.Name) : - timers.OrderByString(i => i.Item1.Name); - } - - var returnArray = timers - .Select(i => - { - return i.Item1; - - }) - .ToArray(); - - return new QueryResult<SeriesTimerInfo> - { - Items = returnArray, - TotalRecordCount = returnArray.Length - }; - } - - public async Task<QueryResult<SeriesTimerInfoDto>> GetSeriesTimers(SeriesTimerQuery query, CancellationToken cancellationToken) - { - var tasks = _services.Select(async i => - { - try - { - var recs = await i.GetSeriesTimersAsync(cancellationToken).ConfigureAwait(false); - return recs.Select(r => new Tuple<SeriesTimerInfo, ILiveTvService>(r, i)); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting recordings", ex); - return new List<Tuple<SeriesTimerInfo, ILiveTvService>>(); - } - }); - var results = await Task.WhenAll(tasks).ConfigureAwait(false); - var timers = results.SelectMany(i => i.ToList()); - - if (string.Equals(query.SortBy, "Priority", StringComparison.OrdinalIgnoreCase)) - { - timers = query.SortOrder == SortOrder.Descending ? - timers.OrderBy(i => i.Item1.Priority).ThenByStringDescending(i => i.Item1.Name) : - timers.OrderByDescending(i => i.Item1.Priority).ThenByString(i => i.Item1.Name); - } - else - { - timers = query.SortOrder == SortOrder.Descending ? - timers.OrderByStringDescending(i => i.Item1.Name) : - timers.OrderByString(i => i.Item1.Name); - } - - var returnArray = timers - .Select(i => - { - string channelName = null; - - if (!string.IsNullOrEmpty(i.Item1.ChannelId)) - { - var internalChannelId = _tvDtoService.GetInternalChannelId(i.Item2.Name, i.Item1.ChannelId); - var channel = GetInternalChannel(internalChannelId); - channelName = channel == null ? null : channel.Name; - } - - return _tvDtoService.GetSeriesTimerInfoDto(i.Item1, i.Item2, channelName); - - }) - .ToArray(); - - return new QueryResult<SeriesTimerInfoDto> - { - Items = returnArray, - TotalRecordCount = returnArray.Length - }; - } - - public void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> tuples, DtoOptions options, User user) - { - var now = DateTime.UtcNow; - - var channelIds = tuples.Select(i => i.Item2.Id.ToString("N")).Distinct().ToArray(); - - var programs = options.AddCurrentProgram ? _libraryManager.GetItemList(new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(LiveTvProgram).Name }, - ChannelIds = channelIds, - MaxStartDate = now, - MinEndDate = now, - Limit = channelIds.Length, - SortBy = new[] { "StartDate" }, - TopParentIds = new[] { GetInternalLiveTvFolder(CancellationToken.None).Result.Id.ToString("N") } - - }).ToList() : new List<BaseItem>(); - - RemoveFields(options); - - foreach (var tuple in tuples) - { - var dto = tuple.Item1; - var channel = tuple.Item2; - - dto.Number = channel.Number; - dto.ChannelNumber = channel.Number; - dto.ChannelType = channel.ChannelType; - dto.ServiceName = channel.ServiceName; - - if (options.Fields.Contains(ItemFields.MediaSources)) - { - dto.MediaSources = channel.GetMediaSources(true).ToList(); - } - - if (options.AddCurrentProgram) - { - var channelIdString = channel.Id.ToString("N"); - var currentProgram = programs.FirstOrDefault(i => string.Equals(i.ChannelId, channelIdString)); - - if (currentProgram != null) - { - dto.CurrentProgram = _dtoService.GetBaseItemDto(currentProgram, options, user); - } - } - } - } - - private async Task<Tuple<SeriesTimerInfo, ILiveTvService>> GetNewTimerDefaultsInternal(CancellationToken cancellationToken, LiveTvProgram program = null) - { - var service = program != null && !string.IsNullOrWhiteSpace(program.ServiceName) ? - GetService(program) : - _services.FirstOrDefault(); - - ProgramInfo programInfo = null; - - if (program != null) - { - var channel = GetInternalChannel(program.ChannelId); - - programInfo = new ProgramInfo - { - Audio = program.Audio, - ChannelId = channel.ExternalId, - CommunityRating = program.CommunityRating, - EndDate = program.EndDate ?? DateTime.MinValue, - EpisodeTitle = program.EpisodeTitle, - Genres = program.Genres, - Id = program.ExternalId, - IsHD = program.IsHD, - IsKids = program.IsKids, - IsLive = program.IsLive, - IsMovie = program.IsMovie, - IsNews = program.IsNews, - IsPremiere = program.IsPremiere, - IsRepeat = program.IsRepeat, - IsSeries = program.IsSeries, - IsSports = program.IsSports, - OriginalAirDate = program.PremiereDate, - Overview = program.Overview, - StartDate = program.StartDate, - //ImagePath = program.ExternalImagePath, - Name = program.Name, - OfficialRating = program.OfficialRating - }; - } - - var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false); - - info.RecordAnyTime = true; - info.Days = new List<DayOfWeek> - { - DayOfWeek.Sunday, - DayOfWeek.Monday, - DayOfWeek.Tuesday, - DayOfWeek.Wednesday, - DayOfWeek.Thursday, - DayOfWeek.Friday, - DayOfWeek.Saturday - }; - - info.Id = null; - - return new Tuple<SeriesTimerInfo, ILiveTvService>(info, service); - } - - public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(CancellationToken cancellationToken) - { - var info = await GetNewTimerDefaultsInternal(cancellationToken).ConfigureAwait(false); - - var obj = _tvDtoService.GetSeriesTimerInfoDto(info.Item1, info.Item2, null); - - return obj; - } - - public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(string programId, CancellationToken cancellationToken) - { - var program = GetInternalProgram(programId); - var programDto = await GetProgram(programId, cancellationToken).ConfigureAwait(false); - - var defaults = await GetNewTimerDefaultsInternal(cancellationToken, program).ConfigureAwait(false); - var info = _tvDtoService.GetSeriesTimerInfoDto(defaults.Item1, defaults.Item2, null); - - info.Days = defaults.Item1.Days; - - info.DayPattern = _tvDtoService.GetDayPattern(info.Days); - - info.Name = program.Name; - info.ChannelId = programDto.ChannelId; - info.ChannelName = programDto.ChannelName; - info.StartDate = program.StartDate; - info.Name = program.Name; - info.Overview = program.Overview; - info.ProgramId = programDto.Id; - info.ExternalProgramId = program.ExternalId; - - if (program.EndDate.HasValue) - { - info.EndDate = program.EndDate.Value; - } - - return info; - } - - public async Task CreateTimer(TimerInfoDto timer, CancellationToken cancellationToken) - { - var service = GetService(timer.ServiceName); - - var info = await _tvDtoService.GetTimerInfo(timer, true, this, cancellationToken).ConfigureAwait(false); - - // Set priority from default values - var defaultValues = await service.GetNewTimerDefaultsAsync(cancellationToken).ConfigureAwait(false); - info.Priority = defaultValues.Priority; - - string newTimerId = null; - var supportsNewTimerIds = service as ISupportsNewTimerIds; - if (supportsNewTimerIds != null) - { - newTimerId = await supportsNewTimerIds.CreateTimer(info, cancellationToken).ConfigureAwait(false); - newTimerId = _tvDtoService.GetInternalTimerId(timer.ServiceName, newTimerId).ToString("N"); - } - else - { - await service.CreateTimerAsync(info, cancellationToken).ConfigureAwait(false); - } - - _lastRecordingRefreshTime = DateTime.MinValue; - _logger.Info("New recording scheduled"); - - EventHelper.QueueEventIfNotNull(TimerCreated, this, new GenericEventArgs<TimerEventInfo> - { - Argument = new TimerEventInfo - { - ProgramId = _tvDtoService.GetInternalProgramId(timer.ServiceName, info.ProgramId).ToString("N"), - Id = newTimerId - } - }, _logger); - } - - public async Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken) - { - var registration = await GetRegistrationInfo("seriesrecordings").ConfigureAwait(false); - - if (!registration.IsValid) - { - _logger.Info("Creating series recordings requires an active Emby Premiere subscription."); - return; - } - - var service = GetService(timer.ServiceName); - - var info = await _tvDtoService.GetSeriesTimerInfo(timer, true, this, cancellationToken).ConfigureAwait(false); - - // Set priority from default values - var defaultValues = await service.GetNewTimerDefaultsAsync(cancellationToken).ConfigureAwait(false); - info.Priority = defaultValues.Priority; - - string newTimerId = null; - var supportsNewTimerIds = service as ISupportsNewTimerIds; - if (supportsNewTimerIds != null) - { - newTimerId = await supportsNewTimerIds.CreateSeriesTimer(info, cancellationToken).ConfigureAwait(false); - newTimerId = _tvDtoService.GetInternalSeriesTimerId(timer.ServiceName, newTimerId).ToString("N"); - } - else - { - await service.CreateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false); - } - - _lastRecordingRefreshTime = DateTime.MinValue; - - EventHelper.QueueEventIfNotNull(SeriesTimerCreated, this, new GenericEventArgs<TimerEventInfo> - { - Argument = new TimerEventInfo - { - ProgramId = _tvDtoService.GetInternalProgramId(timer.ServiceName, info.ProgramId).ToString("N"), - Id = newTimerId - } - }, _logger); - } - - public async Task UpdateTimer(TimerInfoDto timer, CancellationToken cancellationToken) - { - var info = await _tvDtoService.GetTimerInfo(timer, false, this, cancellationToken).ConfigureAwait(false); - - var service = GetService(timer.ServiceName); - - await service.UpdateTimerAsync(info, cancellationToken).ConfigureAwait(false); - _lastRecordingRefreshTime = DateTime.MinValue; - } - - public async Task UpdateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken) - { - var info = await _tvDtoService.GetSeriesTimerInfo(timer, false, this, cancellationToken).ConfigureAwait(false); - - var service = GetService(timer.ServiceName); - - await service.UpdateSeriesTimerAsync(info, cancellationToken).ConfigureAwait(false); - _lastRecordingRefreshTime = DateTime.MinValue; - } - - private IEnumerable<string> GetRecordingGroupNames(ILiveTvRecording recording) - { - var list = new List<string>(); - - if (recording.IsSeries) - { - list.Add(recording.Name); - } - - if (recording.IsKids) - { - list.Add("Kids"); - } - - if (recording.IsMovie) - { - list.Add("Movies"); - } - - if (recording.IsNews) - { - list.Add("News"); - } - - if (recording.IsSports) - { - list.Add("Sports"); - } - - if (!recording.IsSports && !recording.IsNews && !recording.IsMovie && !recording.IsKids && !recording.IsSeries) - { - list.Add("Others"); - } - - return list; - } - - private List<Guid> GetRecordingGroupIds(ILiveTvRecording recording) - { - return GetRecordingGroupNames(recording).Select(i => i.ToLower() - .GetMD5()) - .ToList(); - } - - public async Task<QueryResult<BaseItemDto>> GetRecordingGroups(RecordingGroupQuery query, CancellationToken cancellationToken) - { - var recordingResult = await GetInternalRecordings(new RecordingQuery - { - UserId = query.UserId - - }, cancellationToken).ConfigureAwait(false); - - var recordings = recordingResult.Items.OfType<ILiveTvRecording>().ToList(); - - var groups = new List<BaseItemDto>(); - - var series = recordings - .Where(i => i.IsSeries) - .ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase) - .ToList(); - - groups.AddRange(series.OrderByString(i => i.Key).Select(i => new BaseItemDto - { - Name = i.Key, - RecordingCount = i.Count() - })); - - groups.Add(new BaseItemDto - { - Name = "Kids", - RecordingCount = recordings.Count(i => i.IsKids) - }); - - groups.Add(new BaseItemDto - { - Name = "Movies", - RecordingCount = recordings.Count(i => i.IsMovie) - }); - - groups.Add(new BaseItemDto - { - Name = "News", - RecordingCount = recordings.Count(i => i.IsNews) - }); - - groups.Add(new BaseItemDto - { - Name = "Sports", - RecordingCount = recordings.Count(i => i.IsSports) - }); - - groups.Add(new BaseItemDto - { - Name = "Others", - RecordingCount = recordings.Count(i => !i.IsSports && !i.IsNews && !i.IsMovie && !i.IsKids && !i.IsSeries) - }); - - groups = groups - .Where(i => i.RecordingCount > 0) - .ToList(); - - foreach (var group in groups) - { - group.Id = group.Name.ToLower().GetMD5().ToString("N"); - } - - return new QueryResult<BaseItemDto> - { - Items = groups.ToArray(), - TotalRecordCount = groups.Count - }; - } - - public async Task CloseLiveStream(string id) - { - var parts = id.Split(new[] { '_' }, 2); - - var service = _services.FirstOrDefault(i => string.Equals(i.GetType().FullName.GetMD5().ToString("N"), parts[0], StringComparison.OrdinalIgnoreCase)); - - if (service == null) - { - throw new ArgumentException("Service not found."); - } - - id = parts[1]; - - _logger.Info("Closing live stream from {0}, stream Id: {1}", service.Name, id); - - await service.CloseLiveStream(id, CancellationToken.None).ConfigureAwait(false); - } - - public GuideInfo GetGuideInfo() - { - var startDate = DateTime.UtcNow; - var endDate = startDate.AddDays(14); - - return new GuideInfo - { - StartDate = startDate, - EndDate = endDate - }; - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - } - - private bool _isDisposed = false; - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - _isDisposed = true; - } - } - - private async Task<IEnumerable<LiveTvServiceInfo>> GetServiceInfos(CancellationToken cancellationToken) - { - var tasks = Services.Select(i => GetServiceInfo(i, cancellationToken)); - - return await Task.WhenAll(tasks).ConfigureAwait(false); - } - - private async Task<LiveTvServiceInfo> GetServiceInfo(ILiveTvService service, CancellationToken cancellationToken) - { - var info = new LiveTvServiceInfo - { - Name = service.Name - }; - - var tunerIdPrefix = service.GetType().FullName.GetMD5().ToString("N") + "_"; - - try - { - var statusInfo = await service.GetStatusInfoAsync(cancellationToken).ConfigureAwait(false); - - info.Status = statusInfo.Status; - info.StatusMessage = statusInfo.StatusMessage; - info.Version = statusInfo.Version; - info.HasUpdateAvailable = statusInfo.HasUpdateAvailable; - info.HomePageUrl = service.HomePageUrl; - info.IsVisible = statusInfo.IsVisible; - - info.Tuners = statusInfo.Tuners.Select(i => - { - string channelName = null; - - if (!string.IsNullOrEmpty(i.ChannelId)) - { - var internalChannelId = _tvDtoService.GetInternalChannelId(service.Name, i.ChannelId); - var channel = GetInternalChannel(internalChannelId); - channelName = channel == null ? null : channel.Name; - } - - var dto = _tvDtoService.GetTunerInfoDto(service.Name, i, channelName); - - dto.Id = tunerIdPrefix + dto.Id; - - return dto; - - }).ToList(); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting service status info from {0}", ex, service.Name ?? string.Empty); - - info.Status = LiveTvServiceStatus.Unavailable; - info.StatusMessage = ex.Message; - } - - return info; - } - - public async Task<LiveTvInfo> GetLiveTvInfo(CancellationToken cancellationToken) - { - var services = await GetServiceInfos(CancellationToken.None).ConfigureAwait(false); - var servicesList = services.ToList(); - - var info = new LiveTvInfo - { - Services = servicesList.ToList(), - IsEnabled = servicesList.Count > 0 - }; - - info.EnabledUsers = _userManager.Users - .Where(IsLiveTvEnabled) - .Select(i => i.Id.ToString("N")) - .ToList(); - - return info; - } - - private bool IsLiveTvEnabled(User user) - { - return user.Policy.EnableLiveTvAccess && (Services.Count > 1 || GetConfiguration().TunerHosts.Count(i => i.IsEnabled) > 0); - } - - public IEnumerable<User> GetEnabledUsers() - { - return _userManager.Users - .Where(IsLiveTvEnabled); - } - - /// <summary> - /// Resets the tuner. - /// </summary> - /// <param name="id">The identifier.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task ResetTuner(string id, CancellationToken cancellationToken) - { - var parts = id.Split(new[] { '_' }, 2); - - var service = _services.FirstOrDefault(i => string.Equals(i.GetType().FullName.GetMD5().ToString("N"), parts[0], StringComparison.OrdinalIgnoreCase)); - - if (service == null) - { - throw new ArgumentException("Service not found."); - } - - return service.ResetTuner(parts[1], cancellationToken); - } - - public async Task<BaseItemDto> GetLiveTvFolder(string userId, CancellationToken cancellationToken) - { - var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(userId); - - var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); - - return _dtoService.GetBaseItemDto(folder, new DtoOptions(), user); - } - - private void RemoveFields(DtoOptions options) - { - options.Fields.Remove(ItemFields.CanDelete); - options.Fields.Remove(ItemFields.CanDownload); - options.Fields.Remove(ItemFields.DisplayPreferencesId); - options.Fields.Remove(ItemFields.Etag); - } - - public async Task<Folder> GetInternalLiveTvFolder(CancellationToken cancellationToken) - { - var name = _localization.GetLocalizedString("ViewTypeLiveTV"); - return await _libraryManager.GetNamedView(name, CollectionType.LiveTv, name, cancellationToken).ConfigureAwait(false); - } - - public async Task<TunerHostInfo> SaveTunerHost(TunerHostInfo info, bool dataSourceChanged = true) - { - info = _jsonSerializer.DeserializeFromString<TunerHostInfo>(_jsonSerializer.SerializeToString(info)); - - var provider = _tunerHosts.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); - - if (provider == null) - { - throw new ResourceNotFoundException(); - } - - var configurable = provider as IConfigurableTunerHost; - if (configurable != null) - { - await configurable.Validate(info).ConfigureAwait(false); - } - - var config = GetConfiguration(); - - var index = config.TunerHosts.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase)); - - if (index == -1 || string.IsNullOrWhiteSpace(info.Id)) - { - info.Id = Guid.NewGuid().ToString("N"); - config.TunerHosts.Add(info); - } - else - { - config.TunerHosts[index] = info; - } - - _config.SaveConfiguration("livetv", config); - - if (dataSourceChanged) - { - _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>(); - } - - return info; - } - - public async Task<ListingsProviderInfo> SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings) - { - info = _jsonSerializer.DeserializeFromString< ListingsProviderInfo>(_jsonSerializer.SerializeToString(info)); - - var provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); - - if (provider == null) - { - throw new ResourceNotFoundException(); - } - - await provider.Validate(info, validateLogin, validateListings).ConfigureAwait(false); - - var config = GetConfiguration(); - - var index = config.ListingProviders.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase)); - - if (index == -1 || string.IsNullOrWhiteSpace(info.Id)) - { - info.Id = Guid.NewGuid().ToString("N"); - config.ListingProviders.Add(info); - } - else - { - config.ListingProviders[index] = info; - } - - _config.SaveConfiguration("livetv", config); - - _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>(); - - return info; - } - - public void DeleteListingsProvider(string id) - { - var config = GetConfiguration(); - - config.ListingProviders = config.ListingProviders.Where(i => !string.Equals(id, i.Id, StringComparison.OrdinalIgnoreCase)).ToList(); - - _config.SaveConfiguration("livetv", config); - _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>(); - } - - public async Task<TunerChannelMapping> SetChannelMapping(string providerId, string tunerChannelNumber, string providerChannelNumber) - { - var config = GetConfiguration(); - - var listingsProviderInfo = config.ListingProviders.First(i => string.Equals(providerId, i.Id, StringComparison.OrdinalIgnoreCase)); - listingsProviderInfo.ChannelMappings = listingsProviderInfo.ChannelMappings.Where(i => !string.Equals(i.Name, tunerChannelNumber, StringComparison.OrdinalIgnoreCase)).ToArray(); - - if (!string.Equals(tunerChannelNumber, providerChannelNumber, StringComparison.OrdinalIgnoreCase)) - { - var list = listingsProviderInfo.ChannelMappings.ToList(); - list.Add(new NameValuePair - { - Name = tunerChannelNumber, - Value = providerChannelNumber - }); - listingsProviderInfo.ChannelMappings = list.ToArray(); - } - - _config.SaveConfiguration("livetv", config); - - var tunerChannels = await GetChannelsForListingsProvider(providerId, CancellationToken.None) - .ConfigureAwait(false); - - var providerChannels = await GetChannelsFromListingsProviderData(providerId, CancellationToken.None) - .ConfigureAwait(false); - - var mappings = listingsProviderInfo.ChannelMappings.ToList(); - - var tunerChannelMappings = - tunerChannels.Select(i => GetTunerChannelMapping(i, mappings, providerChannels)).ToList(); - - _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>(); - - return tunerChannelMappings.First(i => string.Equals(i.Number, tunerChannelNumber, StringComparison.OrdinalIgnoreCase)); - } - - public TunerChannelMapping GetTunerChannelMapping(ChannelInfo channel, List<NameValuePair> mappings, List<ChannelInfo> providerChannels) - { - var result = new TunerChannelMapping - { - Name = channel.Number + " " + channel.Name, - Number = channel.Number - }; - - var mapping = mappings.FirstOrDefault(i => string.Equals(i.Name, channel.Number, StringComparison.OrdinalIgnoreCase)); - var providerChannelNumber = channel.Number; - - if (mapping != null) - { - providerChannelNumber = mapping.Value; - } - - var providerChannel = providerChannels.FirstOrDefault(i => string.Equals(i.Number, providerChannelNumber, StringComparison.OrdinalIgnoreCase)); - - if (providerChannel != null) - { - result.ProviderChannelNumber = providerChannel.Number; - result.ProviderChannelName = providerChannel.Name; - } - - return result; - } - - public Task<List<NameIdPair>> GetLineups(string providerType, string providerId, string country, string location) - { - var config = GetConfiguration(); - - if (string.IsNullOrWhiteSpace(providerId)) - { - var provider = _listingProviders.FirstOrDefault(i => string.Equals(providerType, i.Type, StringComparison.OrdinalIgnoreCase)); - - if (provider == null) - { - throw new ResourceNotFoundException(); - } - - return provider.GetLineups(null, country, location); - } - else - { - var info = config.ListingProviders.FirstOrDefault(i => string.Equals(i.Id, providerId, StringComparison.OrdinalIgnoreCase)); - - var provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); - - if (provider == null) - { - throw new ResourceNotFoundException(); - } - - return provider.GetLineups(info, country, location); - } - } - - public Task<MBRegistrationRecord> GetRegistrationInfo(string feature) - { - if (string.Equals(feature, "seriesrecordings", StringComparison.OrdinalIgnoreCase)) - { - feature = "embytvseriesrecordings"; - } - - if (string.Equals(feature, "dvr-l", StringComparison.OrdinalIgnoreCase)) - { - var config = GetConfiguration(); - if (config.TunerHosts.Count(i => i.IsEnabled) > 0 && - config.ListingProviders.Count(i => (i.EnableAllTuners || i.EnabledTuners.Length > 0) && string.Equals(i.Type, SchedulesDirect.TypeName, StringComparison.OrdinalIgnoreCase)) > 0) - { - return Task.FromResult(new MBRegistrationRecord - { - IsRegistered = true, - IsValid = true - }); - } - } - - return _security.GetRegistrationStatus(feature); - } - - public List<NameValuePair> GetSatIniMappings() - { - var names = GetType().Assembly.GetManifestResourceNames().Where(i => i.IndexOf("SatIp.ini", StringComparison.OrdinalIgnoreCase) != -1).ToList(); - - return names.Select(GetSatIniMappings).Where(i => i != null).DistinctBy(i => i.Value.Split('|')[0]).ToList(); - } - - public NameValuePair GetSatIniMappings(string resource) - { - using (var stream = GetType().Assembly.GetManifestResourceStream(resource)) - { - using (var reader = new StreamReader(stream)) - { - var parser = new StreamIniDataParser(); - IniData data = parser.ReadData(reader); - - var satType1 = data["SATTYPE"]["1"]; - var satType2 = data["SATTYPE"]["2"]; - - if (string.IsNullOrWhiteSpace(satType2)) - { - return null; - } - - var srch = "SatIp.ini."; - var filename = Path.GetFileName(resource); - - return new NameValuePair - { - Name = satType1 + " " + satType2, - Value = satType2 + "|" + filename.Substring(filename.IndexOf(srch) + srch.Length) - }; - } - } - } - - public Task<List<ChannelInfo>> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken) - { - return new TunerHosts.SatIp.ChannelScan(_logger).Scan(info, cancellationToken); - } - - public Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken) - { - var info = GetConfiguration().ListingProviders.First(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)); - return EmbyTV.EmbyTV.Current.GetChannelsForListingsProvider(info, cancellationToken); - } - - public Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken) - { - var info = GetConfiguration().ListingProviders.First(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)); - var provider = _listingProviders.First(i => string.Equals(i.Type, info.Type, StringComparison.OrdinalIgnoreCase)); - return provider.GetChannels(info, cancellationToken); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs deleted file mode 100644 index 393708fb7d..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ /dev/null @@ -1,224 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Dlna; - -namespace MediaBrowser.Server.Implementations.LiveTv -{ - public class LiveTvMediaSourceProvider : IMediaSourceProvider - { - private readonly ILiveTvManager _liveTvManager; - private readonly IJsonSerializer _jsonSerializer; - private readonly ILogger _logger; - private readonly IMediaSourceManager _mediaSourceManager; - private readonly IMediaEncoder _mediaEncoder; - private readonly IServerApplicationHost _appHost; - - public LiveTvMediaSourceProvider(ILiveTvManager liveTvManager, IJsonSerializer jsonSerializer, ILogManager logManager, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, IServerApplicationHost appHost) - { - _liveTvManager = liveTvManager; - _jsonSerializer = jsonSerializer; - _mediaSourceManager = mediaSourceManager; - _mediaEncoder = mediaEncoder; - _appHost = appHost; - _logger = logManager.GetLogger(GetType().Name); - } - - public Task<IEnumerable<MediaSourceInfo>> GetMediaSources(IHasMediaSources item, CancellationToken cancellationToken) - { - var baseItem = (BaseItem)item; - - if (baseItem.SourceType == SourceType.LiveTV) - { - if (string.IsNullOrWhiteSpace(baseItem.Path)) - { - return GetMediaSourcesInternal(item, cancellationToken); - } - } - - return Task.FromResult<IEnumerable<MediaSourceInfo>>(new List<MediaSourceInfo>()); - } - - // Do not use a pipe here because Roku http requests to the server will fail, without any explicit error message. - private const char StreamIdDelimeter = '_'; - private const string StreamIdDelimeterString = "_"; - - private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(IHasMediaSources item, CancellationToken cancellationToken) - { - IEnumerable<MediaSourceInfo> sources; - - var forceRequireOpening = false; - - try - { - if (item is ILiveTvRecording) - { - sources = await _liveTvManager.GetRecordingMediaSources(item, cancellationToken) - .ConfigureAwait(false); - } - else - { - sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken) - .ConfigureAwait(false); - } - } - catch (NotImplementedException) - { - var hasMediaSources = (IHasMediaSources)item; - - sources = _mediaSourceManager.GetStaticMediaSources(hasMediaSources, false) - .ToList(); - - forceRequireOpening = true; - } - - var list = sources.ToList(); - var serverUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false); - - foreach (var source in list) - { - source.Type = MediaSourceType.Default; - source.BufferMs = source.BufferMs ?? 1500; - - if (source.RequiresOpening || forceRequireOpening) - { - source.RequiresOpening = true; - } - - if (source.RequiresOpening) - { - var openKeys = new List<string>(); - openKeys.Add(item.GetType().Name); - openKeys.Add(item.Id.ToString("N")); - openKeys.Add(source.Id ?? string.Empty); - source.OpenToken = string.Join(StreamIdDelimeterString, openKeys.ToArray()); - } - - // Dummy this up so that direct play checks can still run - if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http) - { - source.Path = serverUrl; - } - } - - _logger.Debug("MediaSources: {0}", _jsonSerializer.SerializeToString(list)); - - return list; - } - - public async Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> OpenMediaSource(string openToken, CancellationToken cancellationToken) - { - MediaSourceInfo stream = null; - const bool isAudio = false; - - var keys = openToken.Split(new[] { StreamIdDelimeter }, 3); - var mediaSourceId = keys.Length >= 3 ? keys[2] : null; - IDirectStreamProvider directStreamProvider = null; - - if (string.Equals(keys[0], typeof(LiveTvChannel).Name, StringComparison.OrdinalIgnoreCase)) - { - var info = await _liveTvManager.GetChannelStream(keys[1], mediaSourceId, cancellationToken).ConfigureAwait(false); - stream = info.Item1; - directStreamProvider = info.Item2; - } - else - { - stream = await _liveTvManager.GetRecordingStream(keys[1], cancellationToken).ConfigureAwait(false); - } - - try - { - if (!stream.SupportsProbing || stream.MediaStreams.Any(i => i.Index != -1)) - { - await AddMediaInfo(stream, isAudio, cancellationToken).ConfigureAwait(false); - } - else - { - await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false); - } - } - catch (Exception ex) - { - _logger.ErrorException("Error probing live tv stream", ex); - } - - return new Tuple<MediaSourceInfo, IDirectStreamProvider>(stream, directStreamProvider); - } - - private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken) - { - var originalRuntime = mediaSource.RunTimeTicks; - - mediaSource.DefaultSubtitleStreamIndex = null; - - // Null this out so that it will be treated like a live stream - if (!originalRuntime.HasValue) - { - mediaSource.RunTimeTicks = null; - } - - var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio); - - if (audioStream == null || audioStream.Index == -1) - { - mediaSource.DefaultAudioStreamIndex = null; - } - else - { - mediaSource.DefaultAudioStreamIndex = audioStream.Index; - } - - var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video); - if (videoStream != null) - { - if (!videoStream.BitRate.HasValue) - { - var width = videoStream.Width ?? 1920; - - if (width >= 1900) - { - videoStream.BitRate = 8000000; - } - - else if (width >= 1260) - { - videoStream.BitRate = 3000000; - } - - else if (width >= 700) - { - videoStream.BitRate = 1000000; - } - } - } - - // Try to estimate this - if (!mediaSource.Bitrate.HasValue) - { - var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum(); - - if (total > 0) - { - mediaSource.Bitrate = total; - } - } - } - - public Task CloseMediaSource(string liveStreamId) - { - return _liveTvManager.CloseLiveStream(liveStreamId); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs deleted file mode 100644 index 3f0538bd0b..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs +++ /dev/null @@ -1,88 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.LiveTv -{ - public class ProgramImageProvider : IDynamicImageProvider, IHasItemChangeMonitor, IHasOrder - { - private readonly ILiveTvManager _liveTvManager; - - public ProgramImageProvider(ILiveTvManager liveTvManager) - { - _liveTvManager = liveTvManager; - } - - public IEnumerable<ImageType> GetSupportedImages(IHasImages item) - { - return new[] { ImageType.Primary }; - } - - public async Task<DynamicImageResponse> GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken) - { - var liveTvItem = (LiveTvProgram)item; - - var imageResponse = new DynamicImageResponse(); - - var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, liveTvItem.ServiceName, StringComparison.OrdinalIgnoreCase)); - - if (service != null) - { - try - { - var channel = _liveTvManager.GetInternalChannel(liveTvItem.ChannelId); - - var response = await service.GetProgramImageAsync(liveTvItem.ExternalId, channel.ExternalId, cancellationToken).ConfigureAwait(false); - - if (response != null) - { - imageResponse.HasImage = true; - imageResponse.Stream = response.Stream; - imageResponse.Format = response.Format; - } - } - catch (NotImplementedException) - { - } - } - - return imageResponse; - } - - public string Name - { - get { return "Live TV Service Provider"; } - } - - public bool Supports(IHasImages item) - { - return item is LiveTvProgram; - } - - public int Order - { - get - { - // Let the better providers run first - return 100; - } - } - - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) - { - var liveTvItem = item as LiveTvProgram; - - if (liveTvItem != null) - { - return !liveTvItem.HasImage(ImageType.Primary); - } - return false; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs deleted file mode 100644 index 25678c29d3..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs +++ /dev/null @@ -1,82 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.LiveTv -{ - public class RecordingImageProvider : IDynamicImageProvider, IHasItemChangeMonitor - { - private readonly ILiveTvManager _liveTvManager; - - public RecordingImageProvider(ILiveTvManager liveTvManager) - { - _liveTvManager = liveTvManager; - } - - public IEnumerable<ImageType> GetSupportedImages(IHasImages item) - { - return new[] { ImageType.Primary }; - } - - public async Task<DynamicImageResponse> GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken) - { - var liveTvItem = (ILiveTvRecording)item; - - var imageResponse = new DynamicImageResponse(); - - var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, liveTvItem.ServiceName, StringComparison.OrdinalIgnoreCase)); - - if (service != null) - { - try - { - var response = await service.GetRecordingImageAsync(liveTvItem.ExternalId, cancellationToken).ConfigureAwait(false); - - if (response != null) - { - imageResponse.HasImage = true; - imageResponse.Stream = response.Stream; - imageResponse.Format = response.Format; - } - } - catch (NotImplementedException) - { - } - } - - return imageResponse; - } - - public string Name - { - get { return "Live TV Service Provider"; } - } - - public bool Supports(IHasImages item) - { - return item is ILiveTvRecording; - } - - public int Order - { - get { return 0; } - } - - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) - { - var liveTvItem = item as ILiveTvRecording; - - if (liveTvItem != null) - { - return !liveTvItem.HasImage(ImageType.Primary); - } - return false; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs b/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs deleted file mode 100644 index 3fb1d96614..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs +++ /dev/null @@ -1,73 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.LiveTv; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.LiveTv -{ - public class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask, IHasKey - { - private readonly ILiveTvManager _liveTvManager; - private readonly IConfigurationManager _config; - - public RefreshChannelsScheduledTask(ILiveTvManager liveTvManager, IConfigurationManager config) - { - _liveTvManager = liveTvManager; - _config = config; - } - - public string Name - { - get { return "Refresh Guide"; } - } - - public string Description - { - get { return "Downloads channel information from live tv services."; } - } - - public string Category - { - get { return "Live TV"; } - } - - public Task Execute(System.Threading.CancellationToken cancellationToken, IProgress<double> progress) - { - var manager = (LiveTvManager)_liveTvManager; - - return manager.RefreshChannels(progress, cancellationToken); - } - - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - return new ITaskTrigger[] - { - new IntervalTrigger{ Interval = TimeSpan.FromHours(12)} - }; - } - - private LiveTvOptions GetConfiguration() - { - return _config.GetConfiguration<LiveTvOptions>("livetv"); - } - - public bool IsHidden - { - get { return _liveTvManager.Services.Count == 1 && GetConfiguration().TunerHosts.Count(i => i.IsEnabled) == 0; } - } - - public bool IsEnabled - { - get { return true; } - } - - public string Key - { - get { return "RefreshGuide"; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs deleted file mode 100644 index 0fe74798f5..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ /dev/null @@ -1,249 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts -{ - public abstract class BaseTunerHost - { - protected readonly IServerConfigurationManager Config; - protected readonly ILogger Logger; - protected IJsonSerializer JsonSerializer; - protected readonly IMediaEncoder MediaEncoder; - - private readonly ConcurrentDictionary<string, ChannelCache> _channelCache = - new ConcurrentDictionary<string, ChannelCache>(StringComparer.OrdinalIgnoreCase); - - protected BaseTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder) - { - Config = config; - Logger = logger; - JsonSerializer = jsonSerializer; - MediaEncoder = mediaEncoder; - } - - protected abstract Task<IEnumerable<ChannelInfo>> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken); - public abstract string Type { get; } - - public async Task<IEnumerable<ChannelInfo>> GetChannels(TunerHostInfo tuner, bool enableCache, CancellationToken cancellationToken) - { - ChannelCache cache = null; - var key = tuner.Id; - - if (enableCache && !string.IsNullOrWhiteSpace(key) && _channelCache.TryGetValue(key, out cache)) - { - if (DateTime.UtcNow - cache.Date < TimeSpan.FromMinutes(60)) - { - return cache.Channels.ToList(); - } - } - - var result = await GetChannelsInternal(tuner, cancellationToken).ConfigureAwait(false); - var list = result.ToList(); - Logger.Debug("Channels from {0}: {1}", tuner.Url, JsonSerializer.SerializeToString(list)); - - if (!string.IsNullOrWhiteSpace(key) && list.Count > 0) - { - cache = cache ?? new ChannelCache(); - cache.Date = DateTime.UtcNow; - cache.Channels = list; - _channelCache.AddOrUpdate(key, cache, (k, v) => cache); - } - - return list; - } - - protected virtual List<TunerHostInfo> GetTunerHosts() - { - return GetConfiguration().TunerHosts - .Where(i => i.IsEnabled && string.Equals(i.Type, Type, StringComparison.OrdinalIgnoreCase)) - .ToList(); - } - - public async Task<IEnumerable<ChannelInfo>> GetChannels(bool enableCache, CancellationToken cancellationToken) - { - var list = new List<ChannelInfo>(); - - var hosts = GetTunerHosts(); - - foreach (var host in hosts) - { - try - { - var channels = await GetChannels(host, enableCache, cancellationToken).ConfigureAwait(false); - var newChannels = channels.Where(i => !list.Any(l => string.Equals(i.Id, l.Id, StringComparison.OrdinalIgnoreCase))).ToList(); - - list.AddRange(newChannels); - } - catch (Exception ex) - { - Logger.ErrorException("Error getting channel list", ex); - } - } - - return list; - } - - protected abstract Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken); - - public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken) - { - if (IsValidChannelId(channelId)) - { - var hosts = GetTunerHosts(); - - var hostsWithChannel = new List<TunerHostInfo>(); - - foreach (var host in hosts) - { - try - { - var channels = await GetChannels(host, true, cancellationToken).ConfigureAwait(false); - - if (channels.Any(i => string.Equals(i.Id, channelId, StringComparison.OrdinalIgnoreCase))) - { - hostsWithChannel.Add(host); - } - } - catch (Exception ex) - { - Logger.Error("Error getting channels", ex); - } - } - - foreach (var host in hostsWithChannel) - { - try - { - // Check to make sure the tuner is available - // If there's only one tuner, don't bother with the check and just let the tuner be the one to throw an error - if (hostsWithChannel.Count > 1 && - !await IsAvailable(host, channelId, cancellationToken).ConfigureAwait(false)) - { - Logger.Error("Tuner is not currently available"); - continue; - } - - var mediaSources = await GetChannelStreamMediaSources(host, channelId, cancellationToken).ConfigureAwait(false); - - // Prefix the id with the host Id so that we can easily find it - foreach (var mediaSource in mediaSources) - { - mediaSource.Id = host.Id + mediaSource.Id; - } - - return mediaSources; - } - catch (Exception ex) - { - Logger.Error("Error opening tuner", ex); - } - } - } - - return new List<MediaSourceInfo>(); - } - - protected abstract Task<LiveStream> GetChannelStream(TunerHostInfo tuner, string channelId, string streamId, CancellationToken cancellationToken); - - public async Task<LiveStream> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken) - { - if (!IsValidChannelId(channelId)) - { - throw new FileNotFoundException(); - } - - var hosts = GetTunerHosts(); - - var hostsWithChannel = new List<TunerHostInfo>(); - - foreach (var host in hosts) - { - if (string.IsNullOrWhiteSpace(streamId)) - { - try - { - var channels = await GetChannels(host, true, cancellationToken).ConfigureAwait(false); - - if (channels.Any(i => string.Equals(i.Id, channelId, StringComparison.OrdinalIgnoreCase))) - { - hostsWithChannel.Add(host); - } - } - catch (Exception ex) - { - Logger.Error("Error getting channels", ex); - } - } - else if (streamId.StartsWith(host.Id, StringComparison.OrdinalIgnoreCase)) - { - hostsWithChannel = new List<TunerHostInfo> { host }; - streamId = streamId.Substring(host.Id.Length); - break; - } - } - - foreach (var host in hostsWithChannel) - { - try - { - var liveStream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false); - await liveStream.Open(cancellationToken).ConfigureAwait(false); - return liveStream; - } - catch (Exception ex) - { - Logger.Error("Error opening tuner", ex); - } - } - - throw new LiveTvConflictException(); - } - - protected virtual bool EnableMediaProbing - { - get { return false; } - } - - protected async Task<bool> IsAvailable(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken) - { - try - { - return await IsAvailableInternal(tuner, channelId, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.ErrorException("Error checking tuner availability", ex); - return false; - } - } - - protected abstract Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken); - - protected abstract bool IsValidChannelId(string channelId); - - protected LiveTvOptions GetConfiguration() - { - return Config.GetConfiguration<LiveTvOptions>("livetv"); - } - - private class ChannelCache - { - public DateTime Date; - public List<ChannelInfo> Channels; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs deleted file mode 100644 index cd168ba580..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs +++ /dev/null @@ -1,158 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Dlna; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using System; -using System.Linq; -using System.Threading; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun -{ - public class HdHomerunDiscovery : IServerEntryPoint - { - private readonly IDeviceDiscovery _deviceDiscovery; - private readonly IServerConfigurationManager _config; - private readonly ILogger _logger; - private readonly ILiveTvManager _liveTvManager; - private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); - private readonly IHttpClient _httpClient; - private readonly IJsonSerializer _json; - - public HdHomerunDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager, IHttpClient httpClient, IJsonSerializer json) - { - _deviceDiscovery = deviceDiscovery; - _config = config; - _logger = logger; - _liveTvManager = liveTvManager; - _httpClient = httpClient; - _json = json; - } - - public void Run() - { - _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered; - } - - void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs<UpnpDeviceInfo> e) - { - string server = null; - var info = e.Argument; - - if (info.Headers.TryGetValue("SERVER", out server) && server.IndexOf("HDHomeRun", StringComparison.OrdinalIgnoreCase) != -1) - { - string location; - if (info.Headers.TryGetValue("Location", out location)) - { - //_logger.Debug("HdHomerun found at {0}", location); - - // Just get the beginning of the url - Uri uri; - if (Uri.TryCreate(location, UriKind.Absolute, out uri)) - { - var apiUrl = location.Replace(uri.LocalPath, String.Empty, StringComparison.OrdinalIgnoreCase) - .TrimEnd('/'); - - //_logger.Debug("HdHomerun api url: {0}", apiUrl); - AddDevice(apiUrl); - } - } - } - } - - private async void AddDevice(string url) - { - await _semaphore.WaitAsync().ConfigureAwait(false); - - try - { - var options = GetConfiguration(); - - if (options.TunerHosts.Any(i => - string.Equals(i.Type, HdHomerunHost.DeviceType, StringComparison.OrdinalIgnoreCase) && - UriEquals(i.Url, url))) - { - return; - } - - // Strip off the port - url = new Uri(url).GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped).TrimEnd('/'); - - // Test it by pulling down the lineup - using (var stream = await _httpClient.Get(new HttpRequestOptions - { - Url = string.Format("{0}/discover.json", url), - CancellationToken = CancellationToken.None, - BufferContent = false - })) - { - var response = _json.DeserializeFromStream<HdHomerunHost.DiscoverResponse>(stream); - - var existing = GetConfiguration().TunerHosts - .FirstOrDefault(i => string.Equals(i.Type, HdHomerunHost.DeviceType, StringComparison.OrdinalIgnoreCase) && string.Equals(i.DeviceId, response.DeviceID, StringComparison.OrdinalIgnoreCase)); - - if (existing == null) - { - await _liveTvManager.SaveTunerHost(new TunerHostInfo - { - Type = HdHomerunHost.DeviceType, - Url = url, - DataVersion = 1, - DeviceId = response.DeviceID - - }).ConfigureAwait(false); - } - else - { - if (!string.Equals(existing.Url, url, StringComparison.OrdinalIgnoreCase)) - { - existing.Url = url; - await _liveTvManager.SaveTunerHost(existing).ConfigureAwait(false); - } - } - } - } - catch (Exception ex) - { - _logger.ErrorException("Error saving device", ex); - } - finally - { - _semaphore.Release(); - } - } - - private bool UriEquals(string savedUri, string location) - { - return string.Equals(NormalizeUrl(location), NormalizeUrl(savedUri), StringComparison.OrdinalIgnoreCase); - } - - private string NormalizeUrl(string url) - { - if (!url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - url = "http://" + url; - } - - url = url.TrimEnd('/'); - - // Strip off the port - return new Uri(url).GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped); - } - - private LiveTvOptions GetConfiguration() - { - return _config.GetConfiguration<LiveTvOptions>("livetv"); - } - - public void Dispose() - { - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs deleted file mode 100644 index 97d52836d3..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ /dev/null @@ -1,568 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Net; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun -{ - public class HdHomerunHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost - { - private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; - private readonly IServerApplicationHost _appHost; - - public HdHomerunHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IHttpClient httpClient, IFileSystem fileSystem, IServerApplicationHost appHost) - : base(config, logger, jsonSerializer, mediaEncoder) - { - _httpClient = httpClient; - _fileSystem = fileSystem; - _appHost = appHost; - } - - public string Name - { - get { return "HD Homerun"; } - } - - public override string Type - { - get { return DeviceType; } - } - - public static string DeviceType - { - get { return "hdhomerun"; } - } - - private const string ChannelIdPrefix = "hdhr_"; - - private string GetChannelId(TunerHostInfo info, Channels i) - { - var id = ChannelIdPrefix + i.GuideNumber.ToString(CultureInfo.InvariantCulture); - - if (info.DataVersion >= 1) - { - id += '_' + (i.GuideName ?? string.Empty).GetMD5().ToString("N"); - } - - return id; - } - - private async Task<IEnumerable<Channels>> GetLineup(TunerHostInfo info, CancellationToken cancellationToken) - { - var options = new HttpRequestOptions - { - Url = string.Format("{0}/lineup.json", GetApiUrl(info, false)), - CancellationToken = cancellationToken, - BufferContent = false - }; - using (var stream = await _httpClient.Get(options)) - { - var lineup = JsonSerializer.DeserializeFromStream<List<Channels>>(stream) ?? new List<Channels>(); - - if (info.ImportFavoritesOnly) - { - lineup = lineup.Where(i => i.Favorite).ToList(); - } - - return lineup.Where(i => !i.DRM).ToList(); - } - } - - protected override async Task<IEnumerable<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) - { - var lineup = await GetLineup(info, cancellationToken).ConfigureAwait(false); - - return lineup.Select(i => new ChannelInfo - { - Name = i.GuideName, - Number = i.GuideNumber.ToString(CultureInfo.InvariantCulture), - Id = GetChannelId(info, i), - IsFavorite = i.Favorite, - TunerHostId = info.Id, - IsHD = i.HD == 1, - AudioCodec = i.AudioCodec, - VideoCodec = i.VideoCodec - }); - } - - private readonly Dictionary<string, DiscoverResponse> _modelCache = new Dictionary<string, DiscoverResponse>(); - private async Task<string> GetModelInfo(TunerHostInfo info, CancellationToken cancellationToken) - { - lock (_modelCache) - { - DiscoverResponse response; - if (_modelCache.TryGetValue(info.Url, out response)) - { - return response.ModelNumber; - } - } - - try - { - using (var stream = await _httpClient.Get(new HttpRequestOptions() - { - Url = string.Format("{0}/discover.json", GetApiUrl(info, false)), - CancellationToken = cancellationToken, - CacheLength = TimeSpan.FromDays(1), - CacheMode = CacheMode.Unconditional, - TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds), - BufferContent = false - })) - { - var response = JsonSerializer.DeserializeFromStream<DiscoverResponse>(stream); - - lock (_modelCache) - { - _modelCache[info.Id] = response; - } - - return response.ModelNumber; - } - } - catch (HttpException ex) - { - if (ex.StatusCode.HasValue && ex.StatusCode.Value == System.Net.HttpStatusCode.NotFound) - { - var defaultValue = "HDHR"; - // HDHR4 doesn't have this api - lock (_modelCache) - { - _modelCache[info.Id] = new DiscoverResponse - { - ModelNumber = defaultValue - }; - } - return defaultValue; - } - - throw; - } - } - - public async Task<List<LiveTvTunerInfo>> GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) - { - var model = await GetModelInfo(info, cancellationToken).ConfigureAwait(false); - - using (var stream = await _httpClient.Get(new HttpRequestOptions() - { - Url = string.Format("{0}/tuners.html", GetApiUrl(info, false)), - CancellationToken = cancellationToken, - TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds), - BufferContent = false - })) - { - var tuners = new List<LiveTvTunerInfo>(); - using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8)) - { - while (!sr.EndOfStream) - { - string line = StripXML(sr.ReadLine()); - if (line.Contains("Channel")) - { - LiveTvTunerStatus status; - var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); - var name = line.Substring(0, index - 1); - var currentChannel = line.Substring(index + 7); - if (currentChannel != "none") { status = LiveTvTunerStatus.LiveTv; } else { status = LiveTvTunerStatus.Available; } - tuners.Add(new LiveTvTunerInfo - { - Name = name, - SourceType = string.IsNullOrWhiteSpace(model) ? Name : model, - ProgramName = currentChannel, - Status = status - }); - } - } - } - return tuners; - } - } - - public async Task<List<LiveTvTunerInfo>> GetTunerInfos(CancellationToken cancellationToken) - { - var list = new List<LiveTvTunerInfo>(); - - foreach (var host in GetConfiguration().TunerHosts - .Where(i => i.IsEnabled && string.Equals(i.Type, Type, StringComparison.OrdinalIgnoreCase))) - { - try - { - list.AddRange(await GetTunerInfos(host, cancellationToken).ConfigureAwait(false)); - } - catch (Exception ex) - { - Logger.ErrorException("Error getting tuner info", ex); - } - } - - return list; - } - - private string GetApiUrl(TunerHostInfo info, bool isPlayback) - { - var url = info.Url; - - if (string.IsNullOrWhiteSpace(url)) - { - throw new ArgumentException("Invalid tuner info"); - } - - if (!url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - url = "http://" + url; - } - - var uri = new Uri(url); - - if (isPlayback) - { - var builder = new UriBuilder(uri); - builder.Port = 5004; - uri = builder.Uri; - } - - return uri.AbsoluteUri.TrimEnd('/'); - } - - private static string StripXML(string source) - { - char[] buffer = new char[source.Length]; - int bufferIndex = 0; - bool inside = false; - - for (int i = 0; i < source.Length; i++) - { - char let = source[i]; - if (let == '<') - { - inside = true; - continue; - } - if (let == '>') - { - inside = false; - continue; - } - if (!inside) - { - buffer[bufferIndex] = let; - bufferIndex++; - } - } - return new string(buffer, 0, bufferIndex); - } - - private class Channels - { - public string GuideNumber { get; set; } - public string GuideName { get; set; } - public string VideoCodec { get; set; } - public string AudioCodec { get; set; } - public string URL { get; set; } - public bool Favorite { get; set; } - public bool DRM { get; set; } - public int HD { get; set; } - } - - private async Task<MediaSourceInfo> GetMediaSource(TunerHostInfo info, string channelId, string profile) - { - int? width = null; - int? height = null; - bool isInterlaced = true; - string videoCodec = null; - string audioCodec = "ac3"; - - int? videoBitrate = null; - int? audioBitrate = null; - - if (string.Equals(profile, "mobile", StringComparison.OrdinalIgnoreCase)) - { - width = 1280; - height = 720; - isInterlaced = false; - videoCodec = "h264"; - videoBitrate = 2000000; - } - else if (string.Equals(profile, "heavy", StringComparison.OrdinalIgnoreCase)) - { - width = 1920; - height = 1080; - isInterlaced = false; - videoCodec = "h264"; - videoBitrate = 15000000; - } - else if (string.Equals(profile, "internet540", StringComparison.OrdinalIgnoreCase)) - { - width = 960; - height = 546; - isInterlaced = false; - videoCodec = "h264"; - videoBitrate = 2500000; - } - else if (string.Equals(profile, "internet480", StringComparison.OrdinalIgnoreCase)) - { - width = 848; - height = 480; - isInterlaced = false; - videoCodec = "h264"; - videoBitrate = 2000000; - } - else if (string.Equals(profile, "internet360", StringComparison.OrdinalIgnoreCase)) - { - width = 640; - height = 360; - isInterlaced = false; - videoCodec = "h264"; - videoBitrate = 1500000; - } - else if (string.Equals(profile, "internet240", StringComparison.OrdinalIgnoreCase)) - { - width = 432; - height = 240; - isInterlaced = false; - videoCodec = "h264"; - videoBitrate = 1000000; - } - - var channels = await GetChannels(info, true, CancellationToken.None).ConfigureAwait(false); - var channel = channels.FirstOrDefault(i => string.Equals(i.Number, channelId, StringComparison.OrdinalIgnoreCase)); - if (channel != null) - { - if (string.IsNullOrWhiteSpace(videoCodec)) - { - videoCodec = channel.VideoCodec; - } - audioCodec = channel.AudioCodec; - - if (!videoBitrate.HasValue) - { - videoBitrate = (channel.IsHD ?? true) ? 15000000 : 2000000; - } - audioBitrate = (channel.IsHD ?? true) ? 448000 : 192000; - } - - // normalize - if (string.Equals(videoCodec, "mpeg2", StringComparison.OrdinalIgnoreCase)) - { - videoCodec = "mpeg2video"; - } - - string nal = null; - if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) - { - nal = "0"; - } - - var url = GetApiUrl(info, true) + "/auto/v" + channelId; - - if (!string.IsNullOrWhiteSpace(profile) && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase)) - { - url += "?transcode=" + profile; - } - - var id = profile; - if (string.IsNullOrWhiteSpace(id)) - { - id = "native"; - } - id += "_" + url.GetMD5().ToString("N"); - - var mediaSource = new MediaSourceInfo - { - Path = url, - Protocol = MediaProtocol.Http, - MediaStreams = new List<MediaStream> - { - new MediaStream - { - Type = MediaStreamType.Video, - // Set the index to -1 because we don't know the exact index of the video stream within the container - Index = -1, - IsInterlaced = isInterlaced, - Codec = videoCodec, - Width = width, - Height = height, - BitRate = videoBitrate, - NalLengthSize = nal - - }, - new MediaStream - { - Type = MediaStreamType.Audio, - // Set the index to -1 because we don't know the exact index of the audio stream within the container - Index = -1, - Codec = audioCodec, - BitRate = audioBitrate - } - }, - RequiresOpening = true, - RequiresClosing = false, - BufferMs = 0, - Container = "ts", - Id = id, - SupportsDirectPlay = false, - SupportsDirectStream = true, - SupportsTranscoding = true, - IsInfiniteStream = true - }; - - return mediaSource; - } - - protected EncodingOptions GetEncodingOptions() - { - return Config.GetConfiguration<EncodingOptions>("encoding"); - } - - private string GetHdHrIdFromChannelId(string channelId) - { - return channelId.Split('_')[1]; - } - - protected override async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, string channelId, CancellationToken cancellationToken) - { - var list = new List<MediaSourceInfo>(); - - if (!channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase)) - { - return list; - } - var hdhrId = GetHdHrIdFromChannelId(channelId); - - list.Add(await GetMediaSource(info, hdhrId, "native").ConfigureAwait(false)); - - try - { - if (info.AllowHWTranscoding) - { - string model = await GetModelInfo(info, cancellationToken).ConfigureAwait(false); - model = model ?? string.Empty; - - if ((model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1)) - { - list.Add(await GetMediaSource(info, hdhrId, "heavy").ConfigureAwait(false)); - - list.Add(await GetMediaSource(info, hdhrId, "internet540").ConfigureAwait(false)); - list.Add(await GetMediaSource(info, hdhrId, "internet480").ConfigureAwait(false)); - list.Add(await GetMediaSource(info, hdhrId, "internet360").ConfigureAwait(false)); - list.Add(await GetMediaSource(info, hdhrId, "internet240").ConfigureAwait(false)); - list.Add(await GetMediaSource(info, hdhrId, "mobile").ConfigureAwait(false)); - } - } - } - catch - { - - } - - return list; - } - - protected override bool IsValidChannelId(string channelId) - { - if (string.IsNullOrWhiteSpace(channelId)) - { - throw new ArgumentNullException("channelId"); - } - - return channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase); - } - - protected override async Task<LiveStream> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken) - { - var profile = streamId.Split('_')[0]; - - Logger.Info("GetChannelStream: channel id: {0}. stream id: {1} profile: {2}", channelId, streamId, profile); - - if (!channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase)) - { - throw new ArgumentException("Channel not found"); - } - var hdhrId = GetHdHrIdFromChannelId(channelId); - - var mediaSource = await GetMediaSource(info, hdhrId, profile).ConfigureAwait(false); - - var liveStream = new HdHomerunLiveStream(mediaSource, streamId, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost); - liveStream.EnableStreamSharing = true; - return liveStream; - } - - public async Task Validate(TunerHostInfo info) - { - if (!info.IsEnabled) - { - return; - } - - lock (_modelCache) - { - _modelCache.Clear(); - } - - try - { - // Test it by pulling down the lineup - using (var stream = await _httpClient.Get(new HttpRequestOptions - { - Url = string.Format("{0}/discover.json", GetApiUrl(info, false)), - CancellationToken = CancellationToken.None, - BufferContent = false - })) - { - var response = JsonSerializer.DeserializeFromStream<DiscoverResponse>(stream); - - info.DeviceId = response.DeviceID; - } - } - catch (HttpException ex) - { - if (ex.StatusCode.HasValue && ex.StatusCode.Value == System.Net.HttpStatusCode.NotFound) - { - // HDHR4 doesn't have this api - return; - } - - throw; - } - } - - protected override async Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken) - { - var info = await GetTunerInfos(tuner, cancellationToken).ConfigureAwait(false); - - return info.Any(i => i.Status == LiveTvTunerStatus.Available); - } - - public class DiscoverResponse - { - public string FriendlyName { get; set; } - public string ModelNumber { get; set; } - public string FirmwareName { get; set; } - public string FirmwareVersion { get; set; } - public string DeviceID { get; set; } - public string DeviceAuth { get; set; } - public string BaseURL { get; set; } - public string LineupURL { get; set; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs deleted file mode 100644 index 91f0ee832f..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Server.Implementations.LiveTv.EmbyTV; -using System.Collections.Generic; -using System.Linq; -using MediaBrowser.Common.Extensions; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun -{ - public class HdHomerunLiveStream : LiveStream, IDirectStreamProvider - { - private readonly ILogger _logger; - private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; - private readonly IServerApplicationPaths _appPaths; - private readonly IServerApplicationHost _appHost; - - private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource(); - 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) - { - _fileSystem = fileSystem; - _httpClient = httpClient; - _logger = logger; - _appPaths = appPaths; - _appHost = appHost; - OriginalStreamId = originalStreamId; - _multicastStream = new MulticastStream(_logger); - } - - protected override async Task OpenInternal(CancellationToken openCancellationToken) - { - _liveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); - - var mediaSource = OriginalMediaSource; - - var url = mediaSource.Path; - - _logger.Info("Opening HDHR Live stream from {0}", url); - - var taskCompletionSource = new TaskCompletionSource<bool>(); - - StartStreaming(url, taskCompletionSource, _liveStreamCancellationTokenSource.Token); - - //OpenedMediaSource.Protocol = MediaProtocol.File; - //OpenedMediaSource.Path = tempFile; - //OpenedMediaSource.ReadAtNativeFramerate = true; - - OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; - OpenedMediaSource.Protocol = MediaProtocol.Http; - OpenedMediaSource.SupportsDirectPlay = false; - OpenedMediaSource.SupportsDirectStream = true; - OpenedMediaSource.SupportsTranscoding = true; - - await taskCompletionSource.Task.ConfigureAwait(false); - - //await Task.Delay(5000).ConfigureAwait(false); - } - - public override Task Close() - { - _logger.Info("Closing HDHR live stream"); - _liveStreamCancellationTokenSource.Cancel(); - - return _liveStreamTaskCompletionSource.Task; - } - - private async Task StartStreaming(string url, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken) - { - await Task.Run(async () => - { - var isFirstAttempt = true; - - while (!cancellationToken.IsCancellationRequested) - { - try - { - using (var response = await _httpClient.SendAsync(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - BufferContent = false - - }, "GET").ConfigureAwait(false)) - { - _logger.Info("Opened HDHR stream from {0}", url); - - if (!cancellationToken.IsCancellationRequested) - { - _logger.Info("Beginning multicastStream.CopyUntilCancelled"); - - Action onStarted = null; - if (isFirstAttempt) - { - onStarted = () => openTaskCompletionSource.TrySetResult(true); - } - - await _multicastStream.CopyUntilCancelled(response.Content, onStarted, cancellationToken).ConfigureAwait(false); - } - } - } - catch (OperationCanceledException) - { - break; - } - catch (Exception ex) - { - if (isFirstAttempt) - { - _logger.ErrorException("Error opening live stream:", ex); - openTaskCompletionSource.TrySetException(ex); - break; - } - - _logger.ErrorException("Error copying live stream, will reopen", ex); - } - - isFirstAttempt = false; - } - - _liveStreamTaskCompletionSource.TrySetResult(true); - - }).ConfigureAwait(false); - } - - public Task CopyToAsync(Stream stream, CancellationToken cancellationToken) - { - return _multicastStream.CopyToAsync(stream); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs deleted file mode 100644 index 48117f2251..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ /dev/null @@ -1,165 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Server.Implementations.LiveTv.EmbyTV; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts -{ - public class M3UTunerHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost - { - private readonly IFileSystem _fileSystem; - private readonly IHttpClient _httpClient; - private readonly IServerApplicationHost _appHost; - - public M3UTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost) - : base(config, logger, jsonSerializer, mediaEncoder) - { - _fileSystem = fileSystem; - _httpClient = httpClient; - _appHost = appHost; - } - - public override string Type - { - get { return "m3u"; } - } - - public string Name - { - get { return "M3U Tuner"; } - } - - private const string ChannelIdPrefix = "m3u_"; - - 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); - } - - public Task<List<LiveTvTunerInfo>> GetTunerInfos(CancellationToken cancellationToken) - { - var list = GetTunerHosts() - .Select(i => new LiveTvTunerInfo() - { - Name = Name, - SourceType = Type, - Status = LiveTvTunerStatus.Available, - Id = i.Url.GetMD5().ToString("N"), - Url = i.Url - }) - .ToList(); - - return Task.FromResult(list); - } - - protected override async Task<LiveStream> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken) - { - var sources = await GetChannelStreamMediaSources(info, channelId, cancellationToken).ConfigureAwait(false); - - var liveStream = new LiveStream(sources.First()); - return liveStream; - } - - public async Task Validate(TunerHostInfo info) - { - using (var stream = await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false)) - { - - } - } - - protected override bool IsValidChannelId(string channelId) - { - return channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase); - } - - protected override async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, string channelId, CancellationToken cancellationToken) - { - var urlHash = info.Url.GetMD5().ToString("N"); - var prefix = ChannelIdPrefix + urlHash; - if (!channelId.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) - { - return null; - } - - var channels = await GetChannels(info, true, cancellationToken).ConfigureAwait(false); - var m3uchannels = channels.Cast<M3UChannel>(); - var channel = m3uchannels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase)); - if (channel != null) - { - var path = channel.Path; - MediaProtocol protocol = MediaProtocol.File; - if (path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - protocol = MediaProtocol.Http; - } - else if (path.StartsWith("rtmp", StringComparison.OrdinalIgnoreCase)) - { - protocol = MediaProtocol.Rtmp; - } - else if (path.StartsWith("rtsp", StringComparison.OrdinalIgnoreCase)) - { - protocol = MediaProtocol.Rtsp; - } - else if (path.StartsWith("udp", StringComparison.OrdinalIgnoreCase)) - { - protocol = MediaProtocol.Udp; - } - - var mediaSource = new MediaSourceInfo - { - Path = channel.Path, - Protocol = protocol, - MediaStreams = new List<MediaStream> - { - new MediaStream - { - Type = MediaStreamType.Video, - // Set the index to -1 because we don't know the exact index of the video stream within the container - Index = -1, - IsInterlaced = true - }, - new MediaStream - { - Type = MediaStreamType.Audio, - // Set the index to -1 because we don't know the exact index of the audio stream within the container - Index = -1 - - } - }, - RequiresOpening = false, - RequiresClosing = false, - - ReadAtNativeFramerate = false, - - Id = channel.Path.GetMD5().ToString("N"), - IsInfiniteStream = true - }; - - return new List<MediaSourceInfo> { mediaSource }; - } - return new List<MediaSourceInfo>(); - } - - protected override Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs deleted file mode 100644 index 454abddddb..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts -{ - public class M3uParser - { - private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly IHttpClient _httpClient; - private readonly IServerApplicationHost _appHost; - - public M3uParser(ILogger logger, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost) - { - _logger = logger; - _fileSystem = fileSystem; - _httpClient = httpClient; - _appHost = appHost; - } - - public async Task<List<M3UChannel>> Parse(string url, string channelIdPrefix, string tunerHostId, 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); - } - } - - public Task<Stream> GetListingsStream(string url, CancellationToken cancellationToken) - { - if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - return _httpClient.Get(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - // Some data providers will require a user agent - UserAgent = _appHost.FriendlyName + "/" + _appHost.ApplicationVersion - }); - } - return Task.FromResult(_fileSystem.OpenRead(url)); - } - - private List<M3UChannel> GetChannels(StreamReader reader, string urlHash, string channelIdPrefix, string tunerHostId) - { - var channels = new List<M3UChannel>(); - string line; - string extInf = ""; - while ((line = reader.ReadLine()) != null) - { - line = line.Trim(); - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - - if (line.StartsWith("#EXTM3U", StringComparison.OrdinalIgnoreCase)) - { - continue; - } - - if (line.StartsWith("#EXTINF:", StringComparison.OrdinalIgnoreCase)) - { - extInf = line.Substring(8).Trim(); - _logger.Info("Found m3u channel: {0}", extInf); - } - else if (!string.IsNullOrWhiteSpace(extInf) && !line.StartsWith("#", StringComparison.OrdinalIgnoreCase)) - { - var channel = GetChannelnfo(extInf, tunerHostId, line); - channel.Id = channelIdPrefix + urlHash + line.GetMD5().ToString("N"); - channel.Path = line; - channels.Add(channel); - extInf = ""; - } - } - return channels; - } - private M3UChannel GetChannelnfo(string extInf, string tunerHostId, string mediaUrl) - { - var titleIndex = extInf.LastIndexOf(','); - var channel = new M3UChannel(); - channel.TunerHostId = tunerHostId; - - channel.Number = extInf.Trim().Split(' ')[0] ?? "0"; - channel.Name = extInf.Substring(titleIndex + 1); - - //Check for channel number with the format from SatIp - int number; - var numberIndex = channel.Name.IndexOf('.'); - if (numberIndex > 0) - { - if (int.TryParse(channel.Name.Substring(0, numberIndex), out number)) - { - channel.Number = number.ToString(); - channel.Name = channel.Name.Substring(numberIndex + 1); - } - } - - if (string.Equals(channel.Number, "-1", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(mediaUrl)) - { - channel.Number = Path.GetFileNameWithoutExtension(mediaUrl.Split('/').Last()); - } - - if (string.Equals(channel.Number, "-1", StringComparison.OrdinalIgnoreCase)) - { - channel.Number = "0"; - } - - channel.ImageUrl = FindProperty("tvg-logo", extInf); - - var name = FindProperty("tvg-name", extInf); - if (string.IsNullOrWhiteSpace(name)) - { - name = FindProperty("tvg-id", extInf); - } - - channel.Name = name; - - var numberString = FindProperty("tvg-id", extInf); - if (string.IsNullOrWhiteSpace(numberString)) - { - numberString = FindProperty("channel-id", extInf); - } - - if (!string.IsNullOrWhiteSpace(numberString)) - { - channel.Number = numberString; - } - - return channel; - - } - private string FindProperty(string property, string properties) - { - var reg = new Regex(@"([a-z0-9\-_]+)=\""([^""]+)\""", RegexOptions.IgnoreCase); - var matches = reg.Matches(properties); - foreach (Match match in matches) - { - if (match.Groups[1].Value == property) - { - return match.Groups[2].Value; - } - } - return null; - } - } - - - public class M3UChannel : ChannelInfo - { - public string Path { get; set; } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs deleted file mode 100644 index 8ff3fd6c17..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts -{ - public class MulticastStream - { - private readonly List<QueueStream> _outputStreams = new List<QueueStream>(); - private const int BufferSize = 81920; - private CancellationToken _cancellationToken; - private readonly ILogger _logger; - - public MulticastStream(ILogger logger) - { - _logger = logger; - } - - public async Task CopyUntilCancelled(Stream source, Action onStarted, CancellationToken cancellationToken) - { - _cancellationToken = cancellationToken; - - while (!cancellationToken.IsCancellationRequested) - { - byte[] buffer = new byte[BufferSize]; - - var bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); - - if (bytesRead > 0) - { - byte[] copy = new byte[bytesRead]; - Buffer.BlockCopy(buffer, 0, copy, 0, bytesRead); - - List<QueueStream> streams = null; - - lock (_outputStreams) - { - streams = _outputStreams.ToList(); - } - - foreach (var stream in streams) - { - stream.Queue(copy); - } - - if (onStarted != null) - { - var onStartedCopy = onStarted; - onStarted = null; - Task.Run(onStartedCopy); - } - } - - else - { - await Task.Delay(100).ConfigureAwait(false); - } - } - } - - public Task CopyToAsync(Stream stream) - { - var result = new QueueStream(stream, _logger) - { - OnFinished = OnFinished - }; - - lock (_outputStreams) - { - _outputStreams.Add(result); - } - - result.Start(_cancellationToken); - - return result.TaskCompletion.Task; - } - - public void RemoveOutputStream(QueueStream stream) - { - lock (_outputStreams) - { - _outputStreams.Remove(stream); - } - } - - private void OnFinished(QueueStream queueStream) - { - RemoveOutputStream(queueStream); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/QueueStream.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/QueueStream.cs deleted file mode 100644 index c1566b9006..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/QueueStream.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts -{ - public class QueueStream - { - private readonly Stream _outputStream; - private readonly ConcurrentQueue<byte[]> _queue = new ConcurrentQueue<byte[]>(); - private CancellationToken _cancellationToken; - public TaskCompletionSource<bool> TaskCompletion { get; private set; } - - public Action<QueueStream> OnFinished { get; set; } - private readonly ILogger _logger; - - public QueueStream(Stream outputStream, ILogger logger) - { - _outputStream = outputStream; - _logger = logger; - TaskCompletion = new TaskCompletionSource<bool>(); - } - - public void Queue(byte[] bytes) - { - _queue.Enqueue(bytes); - } - - public void Start(CancellationToken cancellationToken) - { - _cancellationToken = cancellationToken; - Task.Run(() => StartInternal()); - } - - private byte[] Dequeue() - { - byte[] bytes; - if (_queue.TryDequeue(out bytes)) - { - return bytes; - } - - return null; - } - - private async Task StartInternal() - { - var cancellationToken = _cancellationToken; - - try - { - while (!cancellationToken.IsCancellationRequested) - { - var bytes = Dequeue(); - if (bytes != null) - { - await _outputStream.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false); - } - else - { - await Task.Delay(50, cancellationToken).ConfigureAwait(false); - } - } - - TaskCompletion.TrySetResult(true); - _logger.Debug("QueueStream complete"); - } - catch (OperationCanceledException) - { - _logger.Debug("QueueStream cancelled"); - TaskCompletion.TrySetCanceled(); - } - catch (Exception ex) - { - _logger.ErrorException("Error in QueueStream", ex); - TaskCompletion.TrySetException(ex); - } - finally - { - if (OnFinished != null) - { - OnFinished(this); - } - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs deleted file mode 100644 index fdeae25b0e..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using IniParser; -using IniParser.Model; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp -{ - public class ChannelScan - { - private readonly ILogger _logger; - - public ChannelScan(ILogger logger) - { - _logger = logger; - } - - public async Task<List<ChannelInfo>> Scan(TunerHostInfo info, CancellationToken cancellationToken) - { - var ini = info.SourceA.Split('|')[1]; - var resource = GetType().Assembly.GetManifestResourceNames().FirstOrDefault(i => i.EndsWith(ini, StringComparison.OrdinalIgnoreCase)); - - _logger.Info("Opening ini file {0}", resource); - var list = new List<ChannelInfo>(); - - using (var stream = GetType().Assembly.GetManifestResourceStream(resource)) - { - using (var reader = new StreamReader(stream)) - { - var parser = new StreamIniDataParser(); - var data = parser.ReadData(reader); - - var count = GetInt(data, "DVB", "0", 0); - - _logger.Info("DVB Count: {0}", count); - - var index = 1; - var source = "1"; - - while (index <= count) - { - cancellationToken.ThrowIfCancellationRequested(); - - using (var rtspSession = new RtspSession(info.Url, _logger)) - { - float percent = count == 0 ? 0 : (float)(index) / count; - percent = Math.Max(percent * 100, 100); - - //SetControlPropertyThreadSafe(pgbSearchResult, "Value", (int)percent); - var strArray = data["DVB"][index.ToString(CultureInfo.InvariantCulture)].Split(','); - - string tuning; - if (strArray[4] == "S2") - { - tuning = string.Format("src={0}&freq={1}&pol={2}&sr={3}&fec={4}&msys=dvbs2&mtype={5}&plts=on&ro=0.35&pids=0,16,17,18,20", source, strArray[0], strArray[1].ToLower(), strArray[2].ToLower(), strArray[3], strArray[5].ToLower()); - } - else - { - tuning = string.Format("src={0}&freq={1}&pol={2}&sr={3}&fec={4}&msys=dvbs&mtype={5}&pids=0,16,17,18,20", source, strArray[0], strArray[1].ToLower(), strArray[2], strArray[3], strArray[5].ToLower()); - } - - rtspSession.Setup(tuning, "unicast"); - - rtspSession.Play(string.Empty); - - int signallevel; - int signalQuality; - rtspSession.Describe(out signallevel, out signalQuality); - - await Task.Delay(500).ConfigureAwait(false); - index++; - } - } - } - } - - return list; - } - - private int GetInt(IniData data, string s1, string s2, int defaultValue) - { - var value = data[s1][s2]; - int numericValue; - if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out numericValue)) - { - return numericValue; - } - - return defaultValue; - } - } - - public class SatChannel - { - // TODO: Add properties - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs deleted file mode 100644 index dddd771790..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp -{ - public class ReportBlock - { - /// <summary> - /// Get the length of the block. - /// </summary> - public int BlockLength { get { return (24); } } - /// <summary> - /// Get the synchronization source. - /// </summary> - public string SynchronizationSource { get; private set; } - /// <summary> - /// Get the fraction lost. - /// </summary> - public int FractionLost { get; private set; } - /// <summary> - /// Get the cumulative packets lost. - /// </summary> - public int CumulativePacketsLost { get; private set; } - /// <summary> - /// Get the highest number received. - /// </summary> - public int HighestNumberReceived { get; private set; } - /// <summary> - /// Get the inter arrival jitter. - /// </summary> - public int InterArrivalJitter { get; private set; } - /// <summary> - /// Get the timestamp of the last report. - /// </summary> - public int LastReportTimeStamp { get; private set; } - /// <summary> - /// Get the delay since the last report. - /// </summary> - public int DelaySinceLastReport { get; private set; } - - /// <summary> - /// Initialize a new instance of the ReportBlock class. - /// </summary> - public ReportBlock() { } - - /// <summary> - /// Unpack the data in a packet. - /// </summary> - /// <param name="buffer">The buffer containing the packet.</param> - /// <param name="offset">The offset to the first byte of the packet within the buffer.</param> - /// <returns>An ErrorSpec instance if an error occurs; null otherwise.</returns> - public void Process(byte[] buffer, int offset) - { - SynchronizationSource = Utils.ConvertBytesToString(buffer, offset, 4); - FractionLost = buffer[offset + 4]; - CumulativePacketsLost = Utils.Convert3BytesToInt(buffer, offset + 5); - HighestNumberReceived = Utils.Convert4BytesToInt(buffer, offset + 8); - InterArrivalJitter = Utils.Convert4BytesToInt(buffer, offset + 12); - LastReportTimeStamp = Utils.Convert4BytesToInt(buffer, offset + 16); - DelaySinceLastReport = Utils.Convert4BytesToInt(buffer, offset + 20); - - - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs deleted file mode 100644 index 990b6dd949..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ -using System.Text; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp -{ - class RtcpAppPacket : RtcpPacket - { - /// <summary> - /// Get the synchronization source. - /// </summary> - public int SynchronizationSource { get; private set; } - /// <summary> - /// Get the name. - /// </summary> - public string Name { get; private set; } - /// <summary> - /// Get the identity. - /// </summary> - public int Identity { get; private set; } - /// <summary> - /// Get the variable data portion. - /// </summary> - public string Data { get; private set; } - - public override void Parse(byte[] buffer, int offset) - { - base.Parse(buffer, offset); - SynchronizationSource = Utils.Convert4BytesToInt(buffer, offset + 4); - Name = Utils.ConvertBytesToString(buffer, offset + 8, 4); - Identity = Utils.Convert2BytesToInt(buffer, offset + 12); - - int dataLength = Utils.Convert2BytesToInt(buffer, offset + 14); - if (dataLength != 0) - Data = Utils.ConvertBytesToString(buffer, offset + 16, dataLength); - } - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - sb.AppendFormat("Application Specific.\n"); - sb.AppendFormat("Version : {0} .\n", Version); - sb.AppendFormat("Padding : {0} .\n", Padding); - sb.AppendFormat("Report Count : {0} .\n", ReportCount); - sb.AppendFormat("PacketType: {0} .\n", Type); - sb.AppendFormat("Length : {0} .\n", Length); - sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource); - sb.AppendFormat("Name : {0} .\n", Name); - sb.AppendFormat("Identity : {0} .\n", Identity); - sb.AppendFormat("Data : {0} .\n", Data); - sb.AppendFormat(".\n"); - return sb.ToString(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs deleted file mode 100644 index c79ea31a89..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Collections.ObjectModel; -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ -using System.Text; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp -{ - public class RtcpByePacket :RtcpPacket - { - public Collection<string> SynchronizationSources { get; private set; } - public string ReasonForLeaving { get; private set; } - public override void Parse(byte[] buffer, int offset) - { - base.Parse(buffer, offset); - SynchronizationSources = new Collection<string>(); - int index = 4; - - while (SynchronizationSources.Count < ReportCount) - { - SynchronizationSources.Add(Utils.ConvertBytesToString(buffer, offset + index, 4)); - index += 4; - } - - if (index < Length) - { - int reasonLength = buffer[offset + index]; - ReasonForLeaving = Utils.ConvertBytesToString(buffer, offset + index + 1, reasonLength); - } - } - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - sb.AppendFormat("ByeBye .\n"); - sb.AppendFormat("Version : {0} .\n", Version); - sb.AppendFormat("Padding : {0} .\n", Padding); - sb.AppendFormat("Report Count : {0} .\n", ReportCount); - sb.AppendFormat("PacketType: {0} .\n", Type); - sb.AppendFormat("Length : {0} .\n", Length); - sb.AppendFormat("SynchronizationSources : {0} .\n", SynchronizationSources); - sb.AppendFormat("ReasonForLeaving : {0} .\n", ReasonForLeaving); - sb.AppendFormat(".\n"); - return sb.ToString(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs deleted file mode 100644 index 2c54f06654..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs +++ /dev/null @@ -1,203 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp -{ - public class RtcpListener - { - private readonly ILogger _logger; - private Thread _rtcpListenerThread; - private AutoResetEvent _rtcpListenerThreadStopEvent = null; - private UdpClient _udpClient; - private IPEndPoint _multicastEndPoint; - private IPEndPoint _serverEndPoint; - private TransmissionMode _transmissionMode; - - public RtcpListener(String address, int port, TransmissionMode mode,ILogger logger) - { - _logger = logger; - _transmissionMode = mode; - switch (mode) - { - case TransmissionMode.Unicast: - _udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(address), port)); - _serverEndPoint = new IPEndPoint(IPAddress.Any, 0); - break; - case TransmissionMode.Multicast: - _multicastEndPoint = new IPEndPoint(IPAddress.Parse(address), port); - _serverEndPoint = new IPEndPoint(IPAddress.Any, 0); - _udpClient = new UdpClient(); - _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); - _udpClient.ExclusiveAddressUse = false; - _udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port)); - _udpClient.JoinMulticastGroup(_multicastEndPoint.Address); - break; - } - //StartRtcpListenerThread(); - } - - public void StartRtcpListenerThread() - { - // Kill the existing thread if it is in "zombie" state. - if (_rtcpListenerThread != null && !_rtcpListenerThread.IsAlive) - { - StopRtcpListenerThread(); - } - - if (_rtcpListenerThread == null) - { - _logger.Info("SAT>IP : starting new RTCP listener thread"); - _rtcpListenerThreadStopEvent = new AutoResetEvent(false); - _rtcpListenerThread = new Thread(new ThreadStart(RtcpListenerThread)); - _rtcpListenerThread.Name = string.Format("SAT>IP tuner RTCP listener"); - _rtcpListenerThread.IsBackground = true; - _rtcpListenerThread.Priority = ThreadPriority.Lowest; - _rtcpListenerThread.Start(); - } - } - - public void StopRtcpListenerThread() - { - if (_rtcpListenerThread != null) - { - if (!_rtcpListenerThread.IsAlive) - { - _logger.Info("SAT>IP : aborting old RTCP listener thread"); - _rtcpListenerThread.Abort(); - } - else - { - _rtcpListenerThreadStopEvent.Set(); - if (!_rtcpListenerThread.Join(400 * 2)) - { - _logger.Info("SAT>IP : failed to join RTCP listener thread, aborting thread"); - _rtcpListenerThread.Abort(); - } - } - _rtcpListenerThread = null; - if (_rtcpListenerThreadStopEvent != null) - { - _rtcpListenerThreadStopEvent.Close(); - _rtcpListenerThreadStopEvent = null; - } - } - } - - private void RtcpListenerThread() - { - try - { - bool receivedGoodBye = false; - try - { - _udpClient.Client.ReceiveTimeout = 400; - IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Any, 0); - while (!receivedGoodBye && !_rtcpListenerThreadStopEvent.WaitOne(1)) - { - byte[] packets = _udpClient.Receive(ref serverEndPoint); - if (packets == null) - { - continue; - } - - int offset = 0; - while (offset < packets.Length) - { - switch (packets[offset + 1]) - { - case 200: //sr - var sr = new RtcpSenderReportPacket(); - sr.Parse(packets, offset); - offset += sr.Length; - break; - case 201: //rr - var rr = new RtcpReceiverReportPacket(); - rr.Parse(packets, offset); - offset += rr.Length; - break; - case 202: //sd - var sd = new RtcpSourceDescriptionPacket(); - sd.Parse(packets, offset); - offset += sd.Length; - break; - case 203: // bye - var bye = new RtcpByePacket(); - bye.Parse(packets, offset); - receivedGoodBye = true; - OnPacketReceived(new RtcpPacketReceivedArgs(bye)); - offset += bye.Length; - break; - case 204: // app - var app = new RtcpAppPacket(); - app.Parse(packets, offset); - OnPacketReceived(new RtcpPacketReceivedArgs(app)); - offset += app.Length; - break; - } - } - - } - } - finally - { - switch (_transmissionMode) - { - case TransmissionMode.Multicast: - _udpClient.DropMulticastGroup(_multicastEndPoint.Address); - _udpClient.Close(); - break; - case TransmissionMode.Unicast: - _udpClient.Close(); - break; - } - } - } - catch (ThreadAbortException) - { - } - catch (Exception ex) - { - _logger.Info(string.Format("SAT>IP : RTCP listener thread exception"), ex); - return; - } - _logger.Info("SAT>IP : RTCP listener thread stopping"); - } - public delegate void PacketReceivedHandler(object sender, RtcpPacketReceivedArgs e); - public event PacketReceivedHandler PacketReceived; - public class RtcpPacketReceivedArgs : EventArgs - { - public Object Packet { get; private set; } - - public RtcpPacketReceivedArgs(Object packet) - { - Packet = packet; - } - } - protected void OnPacketReceived(RtcpPacketReceivedArgs args) - { - if (PacketReceived != null) - { - PacketReceived(this, args); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs deleted file mode 100644 index 0a949eb7ed..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp -{ - public abstract class RtcpPacket - { - public int Version { get; private set; } - public bool Padding { get; private set; } - public int ReportCount { get; private set; } - public int Type { get; private set; } - public int Length { get; private set; } - - public virtual void Parse(byte[] buffer, int offset) - { - Version = buffer[offset] >> 6; - Padding = (buffer[offset] & 0x20) != 0; - ReportCount = buffer[offset] & 0x1f; - Type = buffer[offset + 1]; - Length = (Utils.Convert2BytesToInt(buffer, offset + 2) * 4) + 4; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpReceiverReportPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpReceiverReportPacket.cs deleted file mode 100644 index abb8636522..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpReceiverReportPacket.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Collections.ObjectModel; -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ -using System.Text; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp -{ - public class RtcpReceiverReportPacket :RtcpPacket - { - public string SynchronizationSource { get; private set; } - public Collection<ReportBlock> ReportBlocks { get; private set; } - public byte[] ProfileExtension { get; private set; } - public override void Parse(byte[] buffer, int offset) - { - base.Parse(buffer, offset); - SynchronizationSource = Utils.ConvertBytesToString(buffer, offset + 4, 4); - - ReportBlocks = new Collection<ReportBlock>(); - int index = 8; - - while (ReportBlocks.Count < ReportCount) - { - ReportBlock reportBlock = new ReportBlock(); - reportBlock.Process(buffer, offset + index); - ReportBlocks.Add(reportBlock); - index += reportBlock.BlockLength; - } - - if (index < Length) - { - ProfileExtension = new byte[Length - index]; - - for (int extensionIndex = 0; index < Length; index++) - { - ProfileExtension[extensionIndex] = buffer[offset + index]; - extensionIndex++; - } - } - } - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - sb.AppendFormat("Receiver Report.\n"); - sb.AppendFormat("Version : {0} .\n", Version); - sb.AppendFormat("Padding : {0} .\n", Padding); - sb.AppendFormat("Report Count : {0} .\n", ReportCount); - sb.AppendFormat("PacketType: {0} .\n", Type); - sb.AppendFormat("Length : {0} .\n", Length); - sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource); - sb.AppendFormat(".\n"); - return sb.ToString(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSenderReportPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSenderReportPacket.cs deleted file mode 100644 index dda5d6a033..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSenderReportPacket.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System.Collections.ObjectModel; -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ -using System.Text; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp -{ - public class RtcpSenderReportPacket : RtcpPacket - { - #region Properties - /// <summary> - /// Get the synchronization source. - /// </summary> - public int SynchronizationSource { get; private set; } - /// <summary> - /// Get the NPT timestamp. - /// </summary> - public long NPTTimeStamp { get; private set; } - /// <summary> - /// Get the RTP timestamp. - /// </summary> - public int RTPTimeStamp { get; private set; } - /// <summary> - /// Get the packet count. - /// </summary> - public int SenderPacketCount { get; private set; } - /// <summary> - /// Get the octet count. - /// </summary> - public int SenderOctetCount { get; private set; } - /// <summary> - /// Get the list of report blocks. - /// </summary> - public Collection<ReportBlock> ReportBlocks { get; private set; } - /// <summary> - /// Get the profile extension data. - /// </summary> - public byte[] ProfileExtension { get; private set; } - #endregion - - public override void Parse(byte[] buffer, int offset) - { - base.Parse(buffer, offset); - SynchronizationSource = Utils.Convert4BytesToInt(buffer, offset + 4); - NPTTimeStamp = Utils.Convert8BytesToLong(buffer, offset + 8); - RTPTimeStamp = Utils.Convert4BytesToInt(buffer, offset + 16); - SenderPacketCount = Utils.Convert4BytesToInt(buffer, offset + 20); - SenderOctetCount = Utils.Convert4BytesToInt(buffer, offset + 24); - - ReportBlocks = new Collection<ReportBlock>(); - int index = 28; - - while (ReportBlocks.Count < ReportCount) - { - ReportBlock reportBlock = new ReportBlock(); - reportBlock.Process(buffer, offset + index); - ReportBlocks.Add(reportBlock); - index += reportBlock.BlockLength; - } - - if (index < Length) - { - ProfileExtension = new byte[Length - index]; - - for (int extensionIndex = 0; index < Length; index++) - { - ProfileExtension[extensionIndex] = buffer[offset + index]; - extensionIndex++; - } - } - } - - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - sb.AppendFormat("Sender Report.\n"); - sb.AppendFormat("Version : {0} .\n", Version); - sb.AppendFormat("Padding : {0} .\n", Padding); - sb.AppendFormat("Report Count : {0} .\n", ReportCount); - sb.AppendFormat("PacketType: {0} .\n", Type); - sb.AppendFormat("Length : {0} .\n", Length); - sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource); - sb.AppendFormat("NTP Timestamp : {0} .\n", Utils.NptTimestampToDateTime(NPTTimeStamp)); - sb.AppendFormat("RTP Timestamp : {0} .\n", RTPTimeStamp); - sb.AppendFormat("Sender PacketCount : {0} .\n", SenderPacketCount); - sb.AppendFormat("Sender Octet Count : {0} .\n", SenderOctetCount); - sb.AppendFormat(".\n"); - return sb.ToString(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSourceDescriptionPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSourceDescriptionPacket.cs deleted file mode 100644 index 0a95a44133..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSourceDescriptionPacket.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Collections.ObjectModel; -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ -using System.Text; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp -{ - class RtcpSourceDescriptionPacket :RtcpPacket - { /// <summary> - /// Get the list of source descriptions. - /// </summary> - public Collection<SourceDescriptionBlock> Descriptions; - public override void Parse(byte[] buffer, int offset) - { - base.Parse(buffer, offset); - Descriptions = new Collection<SourceDescriptionBlock>(); - - int index = 4; - - while (Descriptions.Count < ReportCount) - { - SourceDescriptionBlock descriptionBlock = new SourceDescriptionBlock(); - descriptionBlock.Process(buffer, offset + index); - Descriptions.Add(descriptionBlock); - index += descriptionBlock.BlockLength; - } - } - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - sb.AppendFormat("Source Description.\n"); - sb.AppendFormat("Version : {0} .\n", Version); - sb.AppendFormat("Padding : {0} .\n", Padding); - sb.AppendFormat("Report Count : {0} .\n", ReportCount); - sb.AppendFormat("PacketType: {0} .\n", Type); - sb.AppendFormat("Length : {0} .\n", Length); - sb.AppendFormat("Descriptions : {0} .\n", Descriptions); - - sb.AppendFormat(".\n"); - return sb.ToString(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionBlock.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionBlock.cs deleted file mode 100644 index bf56087cd8..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionBlock.cs +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ -using System.Collections.ObjectModel; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp -{ - class SourceDescriptionBlock - { - /// <summary> - /// Get the length of the block. - /// </summary> - public int BlockLength { get { return (blockLength + (blockLength % 4)); } } - - /// <summary> - /// Get the synchronization source. - /// </summary> - public string SynchronizationSource { get; private set; } - /// <summary> - /// Get the list of source descriptioni items. - /// </summary> - public Collection<SourceDescriptionItem> Items; - - private int blockLength; - - public void Process(byte[] buffer, int offset) - { - SynchronizationSource = Utils.ConvertBytesToString(buffer, offset, 4); - Items = new Collection<SourceDescriptionItem>(); - int index = 4; - bool done = false; - do - { - SourceDescriptionItem item = new SourceDescriptionItem(); - item.Process(buffer, offset + index); - - if (item.Type != 0) - { - Items.Add(item); - index += item.ItemLength; - blockLength += item.ItemLength; - } - else - { - blockLength++; - done = true; - } - } - while (!done); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs deleted file mode 100644 index 5dd0336421..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp -{ - /// <summary> - /// The class that describes a source description item. - /// </summary> - public class SourceDescriptionItem - { - /// <summary> - /// Get the type. - /// </summary> - public int Type { get; private set; } - /// <summary> - /// Get the text. - /// </summary> - public string Text { get; private set; } - - /// <summary> - /// Get the length of the item. - /// </summary> - public int ItemLength { get { return (Text.Length + 2); } } - - /// <summary> - /// Initialize a new instance of the SourceDescriptionItem class. - /// </summary> - public SourceDescriptionItem() { } - - /// <summary> - /// Unpack the data in a packet. - /// </summary> - /// <param name="buffer">The buffer containing the packet.</param> - /// <param name="offset">The offset to the first byte of the packet within the buffer.</param> - /// <returns>An ErrorSpec instance if an error occurs; null otherwise.</returns> - public void Process(byte[] buffer, int offset) - { - Type = buffer[offset]; - if (Type != 0) - { - int length = buffer[offset + 1]; - Text = Utils.ConvertBytesToString(buffer, offset + 2, length); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs deleted file mode 100644 index ea6a9ba6aa..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs +++ /dev/null @@ -1,160 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtp -{ - public class RtpListener - { - private readonly ILogger _logger; - private AutoResetEvent _rtpListenerThreadStopEvent; - private Thread _rtpListenerThread; - private UdpClient _udpClient; - private IPEndPoint _multicastEndPoint; - private IPEndPoint _serverEndPoint; - private TransmissionMode _transmissionMode; - public RtpListener(String address, int port,TransmissionMode mode,ILogger logger) - { - _logger = logger; - _transmissionMode = mode; - switch (mode) - { - case TransmissionMode.Unicast: - _udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(address), port)); - _serverEndPoint = new IPEndPoint(IPAddress.Any, 0); - break; - case TransmissionMode.Multicast: - _multicastEndPoint = new IPEndPoint(IPAddress.Parse(address), port); - _serverEndPoint = null; - _udpClient = new UdpClient(); - _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); - _udpClient.ExclusiveAddressUse = false; - _udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, _multicastEndPoint.Port)); - _udpClient.JoinMulticastGroup(_multicastEndPoint.Address); - break; - } - //StartRtpListenerThread(); - } - public void StartRtpListenerThread() - { - // Kill the existing thread if it is in "zombie" state. - if (_rtpListenerThread != null && !_rtpListenerThread.IsAlive) - { - StopRtpListenerThread(); - } - - if (_rtpListenerThread == null) - { - _logger.Info("SAT>IP : starting new RTP listener thread"); - _rtpListenerThreadStopEvent = new AutoResetEvent(false); - _rtpListenerThread = new Thread(new ThreadStart(RtpListenerThread)); - _rtpListenerThread.Name = string.Format("SAT>IP tuner RTP listener"); - _rtpListenerThread.IsBackground = true; - _rtpListenerThread.Priority = ThreadPriority.Lowest; - _rtpListenerThread.Start(); - } - } - - public void StopRtpListenerThread() - { - if (_rtpListenerThread != null) - { - if (!_rtpListenerThread.IsAlive) - { - _logger.Info("SAT>IP : aborting old RTP listener thread"); - _rtpListenerThread.Abort(); - } - else - { - _rtpListenerThreadStopEvent.Set(); - if (!_rtpListenerThread.Join(400 * 2)) - { - _logger.Info("SAT>IP : failed to join RTP listener thread, aborting thread"); - _rtpListenerThread.Abort(); - } - } - _rtpListenerThread = null; - if (_rtpListenerThreadStopEvent != null) - { - _rtpListenerThreadStopEvent.Close(); - _rtpListenerThreadStopEvent = null; - } - } - } - - private void RtpListenerThread() - { - try - { - try - { - - while (!_rtpListenerThreadStopEvent.WaitOne(1)) - { - byte[] receivedbytes = _udpClient.Receive(ref _serverEndPoint); - RtpPacket packet = RtpPacket.Decode(receivedbytes); - OnPacketReceived(new RtpPacketReceivedArgs(packet)); - } - } - finally - { - switch (_transmissionMode) - { - case TransmissionMode.Multicast: - _udpClient.DropMulticastGroup(_multicastEndPoint.Address); - _udpClient.Close(); - break; - case TransmissionMode.Unicast: - _udpClient.Close(); - break; - } - } - } - catch (ThreadAbortException) - { - } - catch (Exception ex) - { - _logger.Info(string.Format("SAT>IP : RTP listener thread exception"), ex); - return; - } - _logger.Info("SAT>IP : RTP listener thread stopping"); - } - public delegate void PacketReceivedHandler(object sender, RtpPacketReceivedArgs e); - public event PacketReceivedHandler PacketReceived; - public class RtpPacketReceivedArgs : EventArgs - { - public RtpPacket Packet { get; private set; } - - public RtpPacketReceivedArgs(RtpPacket packet) - { - Packet = packet; - } - } - protected void OnPacketReceived(RtpPacketReceivedArgs args) - { - if (PacketReceived != null) - { - PacketReceived(this, args); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs deleted file mode 100644 index 489d7f087c..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs +++ /dev/null @@ -1,116 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ - -using System; -using System.Collections.ObjectModel; -using System.Text; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtp -{ - public class RtpPacket - { - private static int MinHeaderLength = 12; - public int HeaderSize = MinHeaderLength; - public int Version { get; set; } - public Boolean Padding { get; set; } - public Boolean Extension { get; set; } - public int ContributingSourceCount { get; set; } - public Boolean Marker { get; set; } - public int PayloadType { get; set; } - public int SequenceNumber { get; set; } - public long TimeStamp { get; set; } - public long SynchronizationSource { get; set; } - public Collection<string> ContributingSources { get; private set; } - public int ExtensionHeaderId = 0; - public int ExtensionHeaderLength = 0; - public bool HasPayload { get; set; } - public byte[] Payload { get; set; } - public RtpPacket() - { - - } - public static RtpPacket Decode(byte[] buffer) - { - var packet = new RtpPacket(); - packet.Version = buffer[0] >> 6; - packet.Padding = (buffer[0] & 0x20) != 0; - packet.Extension = (buffer[0] & 0x10) != 0; - packet.ContributingSourceCount = buffer[0] & 0x0f; - - packet.Marker = (buffer[1] & 0x80) != 0; - packet.PayloadType = buffer[1] & 0x7f; - - packet.SequenceNumber = Utils.Convert2BytesToInt(buffer, 2); - packet.TimeStamp = Utils.Convert4BytesToLong(buffer, 4); - packet.SynchronizationSource = Utils.Convert4BytesToLong(buffer, 8); - - int index = 12; - - if (packet.ContributingSourceCount != 0) - { - packet.ContributingSources = new Collection<string>(); - - while (packet.ContributingSources.Count < packet.ContributingSourceCount) - { - packet.ContributingSources.Add(Utils.ConvertBytesToString(buffer, index, 4)); - index += 4; - } - } - var dataoffset = 0; - if (!packet.Extension) - dataoffset = index; - else - { - packet.ExtensionHeaderId = Utils.Convert2BytesToInt(buffer, index); - packet.ExtensionHeaderLength = Utils.Convert2BytesToInt(buffer, index + 2); - dataoffset = index + packet.ExtensionHeaderLength + 4; - } - - var dataLength = buffer.Length - dataoffset; - if (dataLength > dataoffset) - { - packet.HasPayload = true; - packet.Payload = new byte[dataLength]; - Array.Copy(buffer, dataoffset, packet.Payload, 0, dataLength); - } - else - { - packet.HasPayload = false; - } - return packet; - } - - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - sb.AppendFormat("RTP Packet"); - sb.AppendFormat("Version: {0} \n", Version); - sb.AppendFormat("Padding: {0} \n", Padding); - sb.AppendFormat("Extension: {0} \n", Extension); - sb.AppendFormat("Contributing Source Identifiers Count: {0} \n", ContributingSourceCount); - sb.AppendFormat("Marker: {0} \n", Marker); - sb.AppendFormat("Payload Type: {0} \n", PayloadType); - sb.AppendFormat("Sequence Number: {0} \n", SequenceNumber); - sb.AppendFormat("Timestamp: {0} .\n", TimeStamp); - sb.AppendFormat("Synchronization Source Identifier: {0} \n", SynchronizationSource); - sb.AppendFormat("\n"); - return sb.ToString(); - } - - } - -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs deleted file mode 100644 index 5f286f1db5..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs +++ /dev/null @@ -1,88 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ - -using System.Collections.Generic; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp -{ - /// <summary> - /// Standard RTSP request methods. - /// </summary> - public sealed class RtspMethod - { - public override int GetHashCode() - { - return (_name != null ? _name.GetHashCode() : 0); - } - - private readonly string _name; - private static readonly IDictionary<string, RtspMethod> _values = new Dictionary<string, RtspMethod>(); - - public static readonly RtspMethod Describe = new RtspMethod("DESCRIBE"); - public static readonly RtspMethod Announce = new RtspMethod("ANNOUNCE"); - public static readonly RtspMethod GetParameter = new RtspMethod("GET_PARAMETER"); - public static readonly RtspMethod Options = new RtspMethod("OPTIONS"); - public static readonly RtspMethod Pause = new RtspMethod("PAUSE"); - public static readonly RtspMethod Play = new RtspMethod("PLAY"); - public static readonly RtspMethod Record = new RtspMethod("RECORD"); - public static readonly RtspMethod Redirect = new RtspMethod("REDIRECT"); - public static readonly RtspMethod Setup = new RtspMethod("SETUP"); - public static readonly RtspMethod SetParameter = new RtspMethod("SET_PARAMETER"); - public static readonly RtspMethod Teardown = new RtspMethod("TEARDOWN"); - - private RtspMethod(string name) - { - _name = name; - _values.Add(name, this); - } - - public override string ToString() - { - return _name; - } - - public override bool Equals(object obj) - { - var method = obj as RtspMethod; - if (method != null && this == method) - { - return true; - } - return false; - } - - public static ICollection<RtspMethod> Values - { - get { return _values.Values; } - } - - public static explicit operator RtspMethod(string name) - { - RtspMethod value; - if (!_values.TryGetValue(name, out value)) - { - return null; - } - return value; - } - - public static implicit operator string(RtspMethod method) - { - return method._name; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs deleted file mode 100644 index 600eda02da..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs +++ /dev/null @@ -1,140 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ - -using System.Collections.Generic; -using System.Text; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp -{ - /// <summary> - /// A simple class that can be used to serialise RTSP requests. - /// </summary> - public class RtspRequest - { - private readonly RtspMethod _method; - private readonly string _uri; - private readonly int _majorVersion; - private readonly int _minorVersion; - private IDictionary<string, string> _headers = new Dictionary<string, string>(); - private string _body = string.Empty; - - /// <summary> - /// Initialise a new instance of the <see cref="RtspRequest"/> class. - /// </summary> - /// <param name="method">The request method.</param> - /// <param name="uri">The request URI</param> - /// <param name="majorVersion">The major version number.</param> - /// <param name="minorVersion">The minor version number.</param> - public RtspRequest(RtspMethod method, string uri, int majorVersion, int minorVersion) - { - _method = method; - _uri = uri; - _majorVersion = majorVersion; - _minorVersion = minorVersion; - } - - /// <summary> - /// Get the request method. - /// </summary> - public RtspMethod Method - { - get - { - return _method; - } - } - - /// <summary> - /// Get the request URI. - /// </summary> - public string Uri - { - get - { - return _uri; - } - } - - /// <summary> - /// Get the request major version number. - /// </summary> - public int MajorVersion - { - get - { - return _majorVersion; - } - } - - /// <summary> - /// Get the request minor version number. - /// </summary> - public int MinorVersion - { - get - { - return _minorVersion; - } - } - - /// <summary> - /// Get or set the request headers. - /// </summary> - public IDictionary<string, string> Headers - { - get - { - return _headers; - } - set - { - _headers = value; - } - } - - /// <summary> - /// Get or set the request body. - /// </summary> - public string Body - { - get - { - return _body; - } - set - { - _body = value; - } - } - - /// <summary> - /// Serialise this request. - /// </summary> - /// <returns>raw request bytes</returns> - public byte[] Serialise() - { - var request = new StringBuilder(); - request.AppendFormat("{0} {1} RTSP/{2}.{3}\r\n", _method, _uri, _majorVersion, _minorVersion); - foreach (var header in _headers) - { - request.AppendFormat("{0}: {1}\r\n", header.Key, header.Value); - } - request.AppendFormat("\r\n{0}", _body); - return Encoding.UTF8.GetBytes(request.ToString()); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs deleted file mode 100644 index 97290623b9..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs +++ /dev/null @@ -1,149 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp -{ - /// <summary> - /// A simple class that can be used to deserialise RTSP responses. - /// </summary> - public class RtspResponse - { - private static readonly Regex RegexStatusLine = new Regex(@"RTSP/(\d+)\.(\d+)\s+(\d+)\s+([^.]+?)\r\n(.*)", RegexOptions.Singleline); - - private int _majorVersion = 1; - private int _minorVersion; - private RtspStatusCode _statusCode; - private string _reasonPhrase; - private IDictionary<string, string> _headers; - private string _body; - - /// <summary> - /// Initialise a new instance of the <see cref="RtspResponse"/> class. - /// </summary> - private RtspResponse() - { - } - - /// <summary> - /// Get the response major version number. - /// </summary> - public int MajorVersion - { - get - { - return _majorVersion; - } - } - - /// <summary> - /// Get the response minor version number. - /// </summary> - public int MinorVersion - { - get - { - return _minorVersion; - } - } - - /// <summary> - /// Get the response status code. - /// </summary> - public RtspStatusCode StatusCode - { - get - { - return _statusCode; - } - } - - /// <summary> - /// Get the response reason phrase. - /// </summary> - public string ReasonPhrase - { - get - { - return _reasonPhrase; - } - } - - /// <summary> - /// Get the response headers. - /// </summary> - public IDictionary<string, string> Headers - { - get - { - return _headers; - } - } - - /// <summary> - /// Get the response body. - /// </summary> - public string Body - { - get - { - return _body; - } - set - { - _body = value; - } - } - - /// <summary> - /// Deserialise/parse an RTSP response. - /// </summary> - /// <param name="responseBytes">The raw response bytes.</param> - /// <param name="responseByteCount">The number of valid bytes in the response.</param> - /// <returns>a response object</returns> - public static RtspResponse Deserialise(byte[] responseBytes, int responseByteCount) - { - var response = new RtspResponse(); - var responseString = Encoding.UTF8.GetString(responseBytes, 0, responseByteCount); - - var m = RegexStatusLine.Match(responseString); - if (m.Success) - { - response._majorVersion = int.Parse(m.Groups[1].Captures[0].Value); - response._minorVersion = int.Parse(m.Groups[2].Captures[0].Value); - response._statusCode = (RtspStatusCode)int.Parse(m.Groups[3].Captures[0].Value); - response._reasonPhrase = m.Groups[4].Captures[0].Value; - responseString = m.Groups[5].Captures[0].Value; - } - - var sections = responseString.Split(new[] { "\r\n\r\n" }, StringSplitOptions.None); - response._body = sections[1]; - var headers = sections[0].Split(new[] { "\r\n" }, StringSplitOptions.None); - response._headers = new Dictionary<string, string>(); - foreach (var headerInfo in headers.Select(header => header.Split(':'))) - { - response._headers.Add(headerInfo[0], headerInfo[1].Trim()); - } - return response; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs deleted file mode 100644 index 0f8682b7cc..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs +++ /dev/null @@ -1,688 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; -using System.Text.RegularExpressions; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp -{ - public class RtspSession : IDisposable - { - #region Private Fields - private static readonly Regex RegexRtspSessionHeader = new Regex(@"\s*([^\s;]+)(;timeout=(\d+))?"); - private const int DefaultRtspSessionTimeout = 30; // unit = s - private static readonly Regex RegexDescribeResponseSignalInfo = new Regex(@";tuner=\d+,(\d+),(\d+),(\d+),", RegexOptions.Singleline | RegexOptions.IgnoreCase); - private string _address; - private string _rtspSessionId; - - public string RtspSessionId - { - get { return _rtspSessionId; } - set { _rtspSessionId = value; } - } - private int _rtspSessionTimeToLive = 0; - private string _rtspStreamId; - private int _clientRtpPort; - private int _clientRtcpPort; - private int _serverRtpPort; - private int _serverRtcpPort; - private int _rtpPort; - private int _rtcpPort; - private string _rtspStreamUrl; - private string _destination; - private string _source; - private string _transport; - private int _signalLevel; - private int _signalQuality; - private Socket _rtspSocket; - private int _rtspSequenceNum = 1; - private bool _disposed = false; - private readonly ILogger _logger; - #endregion - - #region Constructor - - public RtspSession(string address, ILogger logger) - { - if (string.IsNullOrWhiteSpace(address)) - { - throw new ArgumentNullException("address"); - } - - _address = address; - _logger = logger; - - _logger.Info("Creating RtspSession with url {0}", address); - } - ~RtspSession() - { - Dispose(false); - } - #endregion - - #region Properties - - #region Rtsp - - public string RtspStreamId - { - get { return _rtspStreamId; } - set { if (_rtspStreamId != value) { _rtspStreamId = value; OnPropertyChanged("RtspStreamId"); } } - } - public string RtspStreamUrl - { - get { return _rtspStreamUrl; } - set { if (_rtspStreamUrl != value) { _rtspStreamUrl = value; OnPropertyChanged("RtspStreamUrl"); } } - } - - public int RtspSessionTimeToLive - { - get - { - if (_rtspSessionTimeToLive == 0) - _rtspSessionTimeToLive = DefaultRtspSessionTimeout; - return _rtspSessionTimeToLive * 1000 - 20; - } - set { if (_rtspSessionTimeToLive != value) { _rtspSessionTimeToLive = value; OnPropertyChanged("RtspSessionTimeToLive"); } } - } - - #endregion - - #region Rtp Rtcp - - /// <summary> - /// The LocalEndPoint Address - /// </summary> - public string Destination - { - get - { - if (string.IsNullOrEmpty(_destination)) - { - var result = ""; - var host = Dns.GetHostName(); - var hostentry = Dns.GetHostEntry(host); - foreach (var ip in hostentry.AddressList.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork)) - { - result = ip.ToString(); - } - - _destination = result; - } - return _destination; - } - set - { - if (_destination != value) - { - _destination = value; - OnPropertyChanged("Destination"); - } - } - } - - /// <summary> - /// The RemoteEndPoint Address - /// </summary> - public string Source - { - get { return _source; } - set - { - if (_source != value) - { - _source = value; - OnPropertyChanged("Source"); - } - } - } - - /// <summary> - /// The Media Data Delivery RemoteEndPoint Port if we use Unicast - /// </summary> - public int ServerRtpPort - { - get - { - return _serverRtpPort; - } - set { if (_serverRtpPort != value) { _serverRtpPort = value; OnPropertyChanged("ServerRtpPort"); } } - } - - /// <summary> - /// The Media Metadata Delivery RemoteEndPoint Port if we use Unicast - /// </summary> - public int ServerRtcpPort - { - get { return _serverRtcpPort; } - set { if (_serverRtcpPort != value) { _serverRtcpPort = value; OnPropertyChanged("ServerRtcpPort"); } } - } - - /// <summary> - /// The Media Data Delivery LocalEndPoint Port if we use Unicast - /// </summary> - public int ClientRtpPort - { - get { return _clientRtpPort; } - set { if (_clientRtpPort != value) { _clientRtpPort = value; OnPropertyChanged("ClientRtpPort"); } } - } - - /// <summary> - /// The Media Metadata Delivery LocalEndPoint Port if we use Unicast - /// </summary> - public int ClientRtcpPort - { - get { return _clientRtcpPort; } - set { if (_clientRtcpPort != value) { _clientRtcpPort = value; OnPropertyChanged("ClientRtcpPort"); } } - } - - /// <summary> - /// The Media Data Delivery RemoteEndPoint Port if we use Multicast - /// </summary> - public int RtpPort - { - get { return _rtpPort; } - set { if (_rtpPort != value) { _rtpPort = value; OnPropertyChanged("RtpPort"); } } - } - - /// <summary> - /// The Media Meta Delivery RemoteEndPoint Port if we use Multicast - /// </summary> - public int RtcpPort - { - get { return _rtcpPort; } - set { if (_rtcpPort != value) { _rtcpPort = value; OnPropertyChanged("RtcpPort"); } } - } - - #endregion - - public string Transport - { - get - { - if (string.IsNullOrEmpty(_transport)) - { - _transport = "unicast"; - } - return _transport; - } - set - { - if (_transport != value) - { - _transport = value; - OnPropertyChanged("Transport"); - } - } - } - public int SignalLevel - { - get { return _signalLevel; } - set { if (_signalLevel != value) { _signalLevel = value; OnPropertyChanged("SignalLevel"); } } - } - public int SignalQuality - { - get { return _signalQuality; } - set { if (_signalQuality != value) { _signalQuality = value; OnPropertyChanged("SignalQuality"); } } - } - - #endregion - - #region Private Methods - - private void ProcessSessionHeader(string sessionHeader, string response) - { - if (!string.IsNullOrEmpty(sessionHeader)) - { - var m = RegexRtspSessionHeader.Match(sessionHeader); - if (!m.Success) - { - _logger.Error("Failed to tune, RTSP {0} response session header {1} format not recognised", response, sessionHeader); - } - _rtspSessionId = m.Groups[1].Captures[0].Value; - _rtspSessionTimeToLive = m.Groups[3].Captures.Count == 1 ? int.Parse(m.Groups[3].Captures[0].Value) : DefaultRtspSessionTimeout; - } - } - private void ProcessTransportHeader(string transportHeader) - { - if (!string.IsNullOrEmpty(transportHeader)) - { - var transports = transportHeader.Split(','); - foreach (var transport in transports) - { - if (transport.Trim().StartsWith("RTP/AVP")) - { - var sections = transport.Split(';'); - foreach (var section in sections) - { - var parts = section.Split('='); - if (parts[0].Equals("server_port")) - { - var ports = parts[1].Split('-'); - _serverRtpPort = int.Parse(ports[0]); - _serverRtcpPort = int.Parse(ports[1]); - } - else if (parts[0].Equals("destination")) - { - _destination = parts[1]; - } - else if (parts[0].Equals("port")) - { - var ports = parts[1].Split('-'); - _rtpPort = int.Parse(ports[0]); - _rtcpPort = int.Parse(ports[1]); - } - else if (parts[0].Equals("ttl")) - { - _rtspSessionTimeToLive = int.Parse(parts[1]); - } - else if (parts[0].Equals("source")) - { - _source = parts[1]; - } - else if (parts[0].Equals("client_port")) - { - var ports = parts[1].Split('-'); - var rtp = int.Parse(ports[0]); - var rtcp = int.Parse(ports[1]); - //if (!rtp.Equals(_rtpPort)) - //{ - // Logger.Error("SAT>IP base: server specified RTP client port {0} instead of {1}", rtp, _rtpPort); - //} - //if (!rtcp.Equals(_rtcpPort)) - //{ - // Logger.Error("SAT>IP base: server specified RTCP client port {0} instead of {1}", rtcp, _rtcpPort); - //} - _rtpPort = rtp; - _rtcpPort = rtcp; - } - } - } - } - } - } - private void Connect() - { - _rtspSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - var ip = IPAddress.Parse(_address); - var rtspEndpoint = new IPEndPoint(ip, 554); - _rtspSocket.Connect(rtspEndpoint); - } - private void Disconnect() - { - if (_rtspSocket != null && _rtspSocket.Connected) - { - _rtspSocket.Shutdown(SocketShutdown.Both); - _rtspSocket.Close(); - } - } - private void SendRequest(RtspRequest request) - { - if (_rtspSocket == null) - { - Connect(); - } - try - { - request.Headers.Add("CSeq", _rtspSequenceNum.ToString()); - _rtspSequenceNum++; - byte[] requestBytes = request.Serialise(); - if (_rtspSocket != null) - { - var requestBytesCount = _rtspSocket.Send(requestBytes, requestBytes.Length, SocketFlags.None); - if (requestBytesCount < 1) - { - - } - } - } - catch (Exception e) - { - _logger.Error(e.Message); - } - } - private void ReceiveResponse(out RtspResponse response) - { - response = null; - var responseBytesCount = 0; - byte[] responseBytes = new byte[1024]; - try - { - responseBytesCount = _rtspSocket.Receive(responseBytes, responseBytes.Length, SocketFlags.None); - response = RtspResponse.Deserialise(responseBytes, responseBytesCount); - string contentLengthString; - int contentLength = 0; - if (response.Headers.TryGetValue("Content-Length", out contentLengthString)) - { - contentLength = int.Parse(contentLengthString); - if ((string.IsNullOrEmpty(response.Body) && contentLength > 0) || response.Body.Length < contentLength) - { - if (response.Body == null) - { - response.Body = string.Empty; - } - while (responseBytesCount > 0 && response.Body.Length < contentLength) - { - responseBytesCount = _rtspSocket.Receive(responseBytes, responseBytes.Length, SocketFlags.None); - response.Body += System.Text.Encoding.UTF8.GetString(responseBytes, 0, responseBytesCount); - } - } - } - } - catch (SocketException) - { - } - } - - #endregion - - #region Public Methods - - public RtspStatusCode Setup(string query, string transporttype) - { - - RtspRequest request; - RtspResponse response; - //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); - if ((_rtspSocket == null)) - { - Connect(); - } - if (string.IsNullOrEmpty(_rtspSessionId)) - { - request = new RtspRequest(RtspMethod.Setup, string.Format("rtsp://{0}:{1}/?{2}", _address, 554, query), 1, 0); - switch (transporttype) - { - case "multicast": - request.Headers.Add("Transport", string.Format("RTP/AVP;multicast")); - break; - case "unicast": - var activeTcpConnections = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections(); - var usedPorts = new HashSet<int>(); - foreach (var connection in activeTcpConnections) - { - usedPorts.Add(connection.LocalEndPoint.Port); - } - for (var port = 40000; port <= 65534; port += 2) - { - if (!usedPorts.Contains(port) && !usedPorts.Contains(port + 1)) - { - - _clientRtpPort = port; - _clientRtcpPort = port + 1; - break; - } - } - request.Headers.Add("Transport", string.Format("RTP/AVP;unicast;client_port={0}-{1}", _clientRtpPort, _clientRtcpPort)); - break; - } - } - else - { - request = new RtspRequest(RtspMethod.Setup, string.Format("rtsp://{0}:{1}/?{2}", _address, 554, query), 1, 0); - switch (transporttype) - { - case "multicast": - request.Headers.Add("Transport", string.Format("RTP/AVP;multicast")); - break; - case "unicast": - request.Headers.Add("Transport", string.Format("RTP/AVP;unicast;client_port={0}-{1}", _clientRtpPort, _clientRtcpPort)); - break; - } - - } - SendRequest(request); - ReceiveResponse(out response); - - //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) - //{ - // Logger.Error("Failed to tune, non-OK RTSP SETUP status code {0} {1}", response.StatusCode, response.ReasonPhrase); - //} - if (!response.Headers.TryGetValue("com.ses.streamID", out _rtspStreamId)) - { - _logger.Error(string.Format("Failed to tune, not able to locate Stream ID header in RTSP SETUP response")); - } - string sessionHeader; - if (!response.Headers.TryGetValue("Session", out sessionHeader)) - { - _logger.Error(string.Format("Failed to tune, not able to locate Session header in RTSP SETUP response")); - } - ProcessSessionHeader(sessionHeader, "Setup"); - string transportHeader; - if (!response.Headers.TryGetValue("Transport", out transportHeader)) - { - _logger.Error(string.Format("Failed to tune, not able to locate Transport header in RTSP SETUP response")); - } - ProcessTransportHeader(transportHeader); - return response.StatusCode; - } - - public RtspStatusCode Play(string query) - { - if ((_rtspSocket == null)) - { - Connect(); - } - //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); - RtspResponse response; - string data; - if (string.IsNullOrEmpty(query)) - { - data = string.Format("rtsp://{0}:{1}/stream={2}", _address, - 554, _rtspStreamId); - } - else - { - data = string.Format("rtsp://{0}:{1}/stream={2}?{3}", _address, - 554, _rtspStreamId, query); - } - var request = new RtspRequest(RtspMethod.Play, data, 1, 0); - request.Headers.Add("Session", _rtspSessionId); - SendRequest(request); - ReceiveResponse(out response); - //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) - //{ - // Logger.Error("Failed to tune, non-OK RTSP SETUP status code {0} {1}", response.StatusCode, response.ReasonPhrase); - //} - //Logger.Info("RtspSession-Play : \r\n {0}", response); - string sessionHeader; - if (!response.Headers.TryGetValue("Session", out sessionHeader)) - { - _logger.Error(string.Format("Failed to tune, not able to locate Session header in RTSP Play response")); - } - ProcessSessionHeader(sessionHeader, "Play"); - string rtpinfoHeader; - if (!response.Headers.TryGetValue("RTP-Info", out rtpinfoHeader)) - { - _logger.Error(string.Format("Failed to tune, not able to locate Rtp-Info header in RTSP Play response")); - } - return response.StatusCode; - } - - public RtspStatusCode Options() - { - if ((_rtspSocket == null)) - { - Connect(); - } - //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); - RtspRequest request; - RtspResponse response; - - - if (string.IsNullOrEmpty(_rtspSessionId)) - { - request = new RtspRequest(RtspMethod.Options, string.Format("rtsp://{0}:{1}/", _address, 554), 1, 0); - } - else - { - request = new RtspRequest(RtspMethod.Options, string.Format("rtsp://{0}:{1}/", _address, 554), 1, 0); - request.Headers.Add("Session", _rtspSessionId); - } - SendRequest(request); - ReceiveResponse(out response); - //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) - //{ - // Logger.Error("Failed to tune, non-OK RTSP SETUP status code {0} {1}", response.StatusCode, response.ReasonPhrase); - //} - //Logger.Info("RtspSession-Options : \r\n {0}", response); - string sessionHeader; - if (!response.Headers.TryGetValue("Session", out sessionHeader)) - { - _logger.Error(string.Format("Failed to tune, not able to locate session header in RTSP Options response")); - } - ProcessSessionHeader(sessionHeader, "Options"); - string optionsHeader; - if (!response.Headers.TryGetValue("Public", out optionsHeader)) - { - _logger.Error(string.Format("Failed to tune, not able to Options header in RTSP Options response")); - } - return response.StatusCode; - } - - public RtspStatusCode Describe(out int level, out int quality) - { - if ((_rtspSocket == null)) - { - Connect(); - } - //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); - RtspRequest request; - RtspResponse response; - level = 0; - quality = 0; - - if (string.IsNullOrEmpty(_rtspSessionId)) - { - request = new RtspRequest(RtspMethod.Describe, string.Format("rtsp://{0}:{1}/", _address, 554), 1, 0); - request.Headers.Add("Accept", "application/sdp"); - - } - else - { - request = new RtspRequest(RtspMethod.Describe, string.Format("rtsp://{0}:{1}/stream={2}", _address, 554, _rtspStreamId), 1, 0); - request.Headers.Add("Accept", "application/sdp"); - request.Headers.Add("Session", _rtspSessionId); - } - SendRequest(request); - ReceiveResponse(out response); - //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) - //{ - // Logger.Error("Failed to tune, non-OK RTSP Describe status code {0} {1}", response.StatusCode, response.ReasonPhrase); - //} - //Logger.Info("RtspSession-Describe : \r\n {0}", response); - string sessionHeader; - if (!response.Headers.TryGetValue("Session", out sessionHeader)) - { - _logger.Error(string.Format("Failed to tune, not able to locate session header in RTSP Describe response")); - } - ProcessSessionHeader(sessionHeader, "Describe"); - var m = RegexDescribeResponseSignalInfo.Match(response.Body); - if (m.Success) - { - - //isSignalLocked = m.Groups[2].Captures[0].Value.Equals("1"); - level = int.Parse(m.Groups[1].Captures[0].Value) * 100 / 255; // level: 0..255 => 0..100 - quality = int.Parse(m.Groups[3].Captures[0].Value) * 100 / 15; // quality: 0..15 => 0..100 - - } - /* - v=0 - o=- 1378633020884883 1 IN IP4 192.168.2.108 - s=SatIPServer:1 4 - t=0 0 - a=tool:idl4k - m=video 52780 RTP/AVP 33 - c=IN IP4 0.0.0.0 - b=AS:5000 - a=control:stream=4 - a=fmtp:33 ver=1.0;tuner=1,0,0,0,12344,h,dvbs2,,off,,22000,34;pids=0,100,101,102,103,106 - =sendonly - */ - - - return response.StatusCode; - } - - public RtspStatusCode TearDown() - { - if ((_rtspSocket == null)) - { - Connect(); - } - //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); - RtspResponse response; - - var request = new RtspRequest(RtspMethod.Teardown, string.Format("rtsp://{0}:{1}/stream={2}", _address, 554, _rtspStreamId), 1, 0); - request.Headers.Add("Session", _rtspSessionId); - SendRequest(request); - ReceiveResponse(out response); - //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) - //{ - // Logger.Error("Failed to tune, non-OK RTSP Teardown status code {0} {1}", response.StatusCode, response.ReasonPhrase); - //} - return response.StatusCode; - } - - #endregion - - #region Public Events - - ////public event PropertyChangedEventHandler PropertyChanged; - - #endregion - - #region Protected Methods - - protected void OnPropertyChanged(string name) - { - //var handler = PropertyChanged; - //if (handler != null) - //{ - // handler(this, new PropertyChangedEventArgs(name)); - //} - } - - #endregion - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this);//Disconnect(); - } - - protected virtual void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - { - TearDown(); - Disconnect(); - } - } - _disposed = true; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs deleted file mode 100644 index 6d6d50623b..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs +++ /dev/null @@ -1,251 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ - -using System.ComponentModel; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp -{ - /// <summary> - /// Standard RTSP status codes. - /// </summary> - public enum RtspStatusCode - { - /// <summary> - /// 100 continue - /// </summary> - Continue = 100, - - /// <summary> - /// 200 OK - /// </summary> - [Description("Okay")] - Ok = 200, - /// <summary> - /// 201 created - /// </summary> - Created = 201, - - /// <summary> - /// 250 low on storage space - /// </summary> - [Description("Low On Storage Space")] - LowOnStorageSpace = 250, - - /// <summary> - /// 300 multiple choices - /// </summary> - [Description("Multiple Choices")] - MultipleChoices = 300, - /// <summary> - /// 301 moved permanently - /// </summary> - [Description("Moved Permanently")] - MovedPermanently = 301, - /// <summary> - /// 302 moved temporarily - /// </summary> - [Description("Moved Temporarily")] - MovedTemporarily = 302, - /// <summary> - /// 303 see other - /// </summary> - [Description("See Other")] - SeeOther = 303, - /// <summary> - /// 304 not modified - /// </summary> - [Description("Not Modified")] - NotModified = 304, - /// <summary> - /// 305 use proxy - /// </summary> - [Description("Use Proxy")] - UseProxy = 305, - - /// <summary> - /// 400 bad request - /// </summary> - [Description("Bad Request")] - BadRequest = 400, - /// <summary> - /// 401 unauthorised - /// </summary> - Unauthorised = 401, - /// <summary> - /// 402 payment required - /// </summary> - [Description("Payment Required")] - PaymentRequired = 402, - /// <summary> - /// 403 forbidden - /// </summary> - Forbidden = 403, - /// <summary> - /// 404 not found - /// </summary> - [Description("Not Found")] - NotFound = 404, - /// <summary> - /// 405 method not allowed - /// </summary> - [Description("Method Not Allowed")] - MethodNotAllowed = 405, - /// <summary> - /// 406 not acceptable - /// </summary> - [Description("Not Acceptable")] - NotAcceptable = 406, - /// <summary> - /// 407 proxy authentication required - /// </summary> - [Description("Proxy Authentication Required")] - ProxyAuthenticationRequred = 407, - /// <summary> - /// 408 request time-out - /// </summary> - [Description("Request Time-Out")] - RequestTimeOut = 408, - - /// <summary> - /// 410 gone - /// </summary> - Gone = 410, - /// <summary> - /// 411 length required - /// </summary> - [Description("Length Required")] - LengthRequired = 411, - /// <summary> - /// 412 precondition failed - /// </summary> - [Description("Precondition Failed")] - PreconditionFailed = 412, - /// <summary> - /// 413 request entity too large - /// </summary> - [Description("Request Entity Too Large")] - RequestEntityTooLarge = 413, - /// <summary> - /// 414 request URI too large - /// </summary> - [Description("Request URI Too Large")] - RequestUriTooLarge = 414, - /// <summary> - /// 415 unsupported media type - /// </summary> - [Description("Unsupported Media Type")] - UnsupportedMediaType = 415, - - /// <summary> - /// 451 parameter not understood - /// </summary> - [Description("Parameter Not Understood")] - ParameterNotUnderstood = 451, - /// <summary> - /// 452 conference not found - /// </summary> - [Description("Conference Not Found")] - ConferenceNotFound = 452, - /// <summary> - /// 453 not enough bandwidth - /// </summary> - [Description("Not Enough Bandwidth")] - NotEnoughBandwidth = 453, - /// <summary> - /// 454 session not found - /// </summary> - [Description("Session Not Found")] - SessionNotFound = 454, - /// <summary> - /// 455 method not valid in this state - /// </summary> - [Description("Method Not Valid In This State")] - MethodNotValidInThisState = 455, - /// <summary> - /// 456 header field not valid for this resource - /// </summary> - [Description("Header Field Not Valid For This Resource")] - HeaderFieldNotValidForThisResource = 456, - /// <summary> - /// 457 invalid range - /// </summary> - [Description("Invalid Range")] - InvalidRange = 457, - /// <summary> - /// 458 parameter is read-only - /// </summary> - [Description("Parameter Is Read-Only")] - ParameterIsReadOnly = 458, - /// <summary> - /// 459 aggregate operation not allowed - /// </summary> - [Description("Aggregate Operation Not Allowed")] - AggregateOperationNotAllowed = 459, - /// <summary> - /// 460 only aggregate operation allowed - /// </summary> - [Description("Only Aggregate Operation Allowed")] - OnlyAggregateOperationAllowed = 460, - /// <summary> - /// 461 unsupported transport - /// </summary> - [Description("Unsupported Transport")] - UnsupportedTransport = 461, - /// <summary> - /// 462 destination unreachable - /// </summary> - [Description("Destination Unreachable")] - DestinationUnreachable = 462, - - /// <summary> - /// 500 internal server error - /// </summary> - [Description("Internal Server Error")] - InternalServerError = 500, - /// <summary> - /// 501 not implemented - /// </summary> - [Description("Not Implemented")] - NotImplemented = 501, - /// <summary> - /// 502 bad gateway - /// </summary> - [Description("Bad Gateway")] - BadGateway = 502, - /// <summary> - /// 503 service unavailable - /// </summary> - [Description("Service Unavailable")] - ServiceUnavailable = 503, - /// <summary> - /// 504 gateway time-out - /// </summary> - [Description("Gateway Time-Out")] - GatewayTimeOut = 504, - /// <summary> - /// 505 RTSP version not supported - /// </summary> - [Description("RTSP Version Not Supported")] - RtspVersionNotSupported = 505, - - /// <summary> - /// 551 option not supported - /// </summary> - [Description("Option Not Supported")] - OptionNotSupported = 551 - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs deleted file mode 100644 index a0b8ef5f79..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs +++ /dev/null @@ -1,347 +0,0 @@ -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Xml; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Dlna; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Extensions; -using System.Xml.Linq; -using MediaBrowser.Model.Events; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp -{ - public class SatIpDiscovery : IServerEntryPoint - { - private readonly IDeviceDiscovery _deviceDiscovery; - private readonly IServerConfigurationManager _config; - private readonly ILogger _logger; - private readonly ILiveTvManager _liveTvManager; - private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); - private readonly IHttpClient _httpClient; - private readonly IJsonSerializer _json; - private int _tunerCountDVBS=0; - private int _tunerCountDVBC=0; - private int _tunerCountDVBT=0; - private bool _supportsDVBS=false; - private bool _supportsDVBC=false; - private bool _supportsDVBT=false; - public static SatIpDiscovery Current; - - public SatIpDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager, IHttpClient httpClient, IJsonSerializer json) - { - _deviceDiscovery = deviceDiscovery; - _config = config; - _logger = logger; - _liveTvManager = liveTvManager; - _httpClient = httpClient; - _json = json; - Current = this; - } - - public void Run() - { - _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered; - } - - void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs<UpnpDeviceInfo> e) - { - var info = e.Argument; - - string st = null; - string nt = null; - info.Headers.TryGetValue("ST", out st); - info.Headers.TryGetValue("NT", out nt); - - if (string.Equals(st, "urn:ses-com:device:SatIPServer:1", StringComparison.OrdinalIgnoreCase) || - string.Equals(nt, "urn:ses-com:device:SatIPServer:1", StringComparison.OrdinalIgnoreCase)) - { - string location; - if (info.Headers.TryGetValue("Location", out location) && !string.IsNullOrWhiteSpace(location)) - { - _logger.Debug("SAT IP found at {0}", location); - - // Just get the beginning of the url - Uri uri; - if (Uri.TryCreate(location, UriKind.Absolute, out uri)) - { - var apiUrl = location.Replace(uri.LocalPath, String.Empty, StringComparison.OrdinalIgnoreCase) - .TrimEnd('/'); - - AddDevice(apiUrl, location); - } - } - } - } - - private async void AddDevice(string deviceUrl, string infoUrl) - { - await _semaphore.WaitAsync().ConfigureAwait(false); - - try - { - var options = GetConfiguration(); - - if (options.TunerHosts.Any(i => string.Equals(i.Type, SatIpHost.DeviceType, StringComparison.OrdinalIgnoreCase) && UriEquals(i.Url, deviceUrl))) - { - return; - } - - _logger.Debug("Will attempt to add SAT device {0}", deviceUrl); - var info = await GetInfo(infoUrl, CancellationToken.None).ConfigureAwait(false); - - var existing = GetConfiguration().TunerHosts - .FirstOrDefault(i => string.Equals(i.Type, SatIpHost.DeviceType, StringComparison.OrdinalIgnoreCase) && string.Equals(i.DeviceId, info.DeviceId, StringComparison.OrdinalIgnoreCase)); - - if (existing == null) - { - //if (string.IsNullOrWhiteSpace(info.M3UUrl)) - //{ - // return; - //} - - await _liveTvManager.SaveTunerHost(new TunerHostInfo - { - Type = SatIpHost.DeviceType, - Url = deviceUrl, - InfoUrl = infoUrl, - DataVersion = 1, - DeviceId = info.DeviceId, - FriendlyName = info.FriendlyName, - Tuners = info.Tuners, - M3UUrl = info.M3UUrl, - IsEnabled = true - - }, true).ConfigureAwait(false); - } - else - { - existing.Url = deviceUrl; - existing.InfoUrl = infoUrl; - existing.M3UUrl = info.M3UUrl; - existing.FriendlyName = info.FriendlyName; - existing.Tuners = info.Tuners; - await _liveTvManager.SaveTunerHost(existing, false).ConfigureAwait(false); - } - } - catch (OperationCanceledException) - { - - } - catch (NotImplementedException) - { - - } - catch (Exception ex) - { - _logger.ErrorException("Error saving device", ex); - } - finally - { - _semaphore.Release(); - } - } - - private bool UriEquals(string savedUri, string location) - { - return string.Equals(NormalizeUrl(location), NormalizeUrl(savedUri), StringComparison.OrdinalIgnoreCase); - } - - private string NormalizeUrl(string url) - { - if (!url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - url = "http://" + url; - } - - url = url.TrimEnd('/'); - - // Strip off the port - return new Uri(url).GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped); - } - - private LiveTvOptions GetConfiguration() - { - return _config.GetConfiguration<LiveTvOptions>("livetv"); - } - - public void Dispose() - { - } - private void ReadCapability(string capability) - { - - string[] cap = capability.Split('-'); - switch (cap[0].ToLower()) - { - case "dvbs": - case "dvbs2": - { - // Optional that you know what an device Supports can you add an flag - _supportsDVBS = true; - - for (int i = 0; i < int.Parse(cap[1]); i++) - { - //ToDo Create Digital Recorder / Tuner Capture Instance here for each with index FE param in Sat>Ip Spec for direct communication with this instance - } - _tunerCountDVBS = int.Parse(cap[1]); - break; - } - case "dvbc": - case "dvbc2": - { - // Optional that you know what an device Supports can you add an flag - _supportsDVBC = true; - - for (int i = 0; i < int.Parse(cap[1]); i++) - { - //ToDo Create Digital Recorder / Tuner Capture Instance here for each with index FE param in Sat>Ip Spec for direct communication with this instance - - } - _tunerCountDVBC = int.Parse(cap[1]); - break; - } - case "dvbt": - case "dvbt2": - { - // Optional that you know what an device Supports can you add an flag - _supportsDVBT = true; - - - for (int i = 0; i < int.Parse(cap[1]); i++) - { - //ToDo Create Digital Recorder / Tuner Capture Instance here for each with index FE param in Sat>Ip Spec for direct communication with this instance - - } - _tunerCountDVBT = int.Parse(cap[1]); - break; - } - } - - } - public async Task<SatIpTunerHostInfo> GetInfo(string url, CancellationToken cancellationToken) - { - Uri locationUri = new Uri(url); - string devicetype = ""; - string friendlyname = ""; - string uniquedevicename = ""; - string manufacturer = ""; - string manufacturerurl = ""; - string modelname = ""; - string modeldescription = ""; - string modelnumber = ""; - string modelurl = ""; - string serialnumber = ""; - string presentationurl = ""; - //string capabilities = ""; - string m3u = ""; - var document = XDocument.Load(locationUri.AbsoluteUri); - var xnm = new XmlNamespaceManager(new NameTable()); - XNamespace n1 = "urn:ses-com:satip"; - XNamespace n0 = "urn:schemas-upnp-org:device-1-0"; - xnm.AddNamespace("root", n0.NamespaceName); - xnm.AddNamespace("satip:", n1.NamespaceName); - if (document.Root != null) - { - var deviceElement = document.Root.Element(n0 + "device"); - if (deviceElement != null) - { - var devicetypeElement = deviceElement.Element(n0 + "deviceType"); - if (devicetypeElement != null) - devicetype = devicetypeElement.Value; - var friendlynameElement = deviceElement.Element(n0 + "friendlyName"); - if (friendlynameElement != null) - friendlyname = friendlynameElement.Value; - var manufactureElement = deviceElement.Element(n0 + "manufacturer"); - if (manufactureElement != null) - manufacturer = manufactureElement.Value; - var manufactureurlElement = deviceElement.Element(n0 + "manufacturerURL"); - if (manufactureurlElement != null) - manufacturerurl = manufactureurlElement.Value; - var modeldescriptionElement = deviceElement.Element(n0 + "modelDescription"); - if (modeldescriptionElement != null) - modeldescription = modeldescriptionElement.Value; - var modelnameElement = deviceElement.Element(n0 + "modelName"); - if (modelnameElement != null) - modelname = modelnameElement.Value; - var modelnumberElement = deviceElement.Element(n0 + "modelNumber"); - if (modelnumberElement != null) - modelnumber = modelnumberElement.Value; - var modelurlElement = deviceElement.Element(n0 + "modelURL"); - if (modelurlElement != null) - modelurl = modelurlElement.Value; - var serialnumberElement = deviceElement.Element(n0 + "serialNumber"); - if (serialnumberElement != null) - serialnumber = serialnumberElement.Value; - var uniquedevicenameElement = deviceElement.Element(n0 + "UDN"); - if (uniquedevicenameElement != null) uniquedevicename = uniquedevicenameElement.Value; - var presentationUrlElement = deviceElement.Element(n0 + "presentationURL"); - if (presentationUrlElement != null) presentationurl = presentationUrlElement.Value; - var capabilitiesElement = deviceElement.Element(n1 + "X_SATIPCAP"); - if (capabilitiesElement != null) - { - //_capabilities = capabilitiesElement.Value; - if (capabilitiesElement.Value.Contains(',')) - { - string[] capabilities = capabilitiesElement.Value.Split(','); - foreach (var capability in capabilities) - { - ReadCapability(capability); - } - } - else - { - ReadCapability(capabilitiesElement.Value); - } - } - else - { - _supportsDVBS = true; - _tunerCountDVBS =1; - } - var m3uElement = deviceElement.Element(n1 + "X_SATIPM3U"); - if (m3uElement != null) m3u = m3uElement.Value; - } - } - - var result = new SatIpTunerHostInfo - { - Url = url, - Id = uniquedevicename, - IsEnabled = true, - Type = SatIpHost.DeviceType, - Tuners = _tunerCountDVBS, - TunersAvailable = _tunerCountDVBS, - M3UUrl = m3u - }; - - result.FriendlyName = friendlyname; - if (string.IsNullOrWhiteSpace(result.Id)) - { - throw new NotImplementedException(); - } - - else if (!result.M3UUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - var fullM3uUrl = url.Substring(0, url.LastIndexOf('/')); - result.M3UUrl = fullM3uUrl + "/" + result.M3UUrl.TrimStart('/'); - } - - _logger.Debug("SAT device result: {0}", _json.SerializeToString(result)); - - return result; - } - } - - public class SatIpTunerHostInfo : TunerHostInfo - { - public int TunersAvailable { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs deleted file mode 100644 index 1fe767e521..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs +++ /dev/null @@ -1,180 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Server.Implementations.LiveTv.EmbyTV; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp -{ - public class SatIpHost : BaseTunerHost, ITunerHost - { - private readonly IFileSystem _fileSystem; - private readonly IHttpClient _httpClient; - private readonly IServerApplicationHost _appHost; - - public SatIpHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost) - : base(config, logger, jsonSerializer, mediaEncoder) - { - _fileSystem = fileSystem; - _httpClient = httpClient; - _appHost = appHost; - } - - private const string ChannelIdPrefix = "sat_"; - - protected override async Task<IEnumerable<ChannelInfo>> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken) - { - if (!string.IsNullOrWhiteSpace(tuner.M3UUrl)) - { - return await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).Parse(tuner.M3UUrl, ChannelIdPrefix, tuner.Id, cancellationToken).ConfigureAwait(false); - } - - var channels = await new ChannelScan(Logger).Scan(tuner, cancellationToken).ConfigureAwait(false); - return channels; - } - - public static string DeviceType - { - get { return "satip"; } - } - - public override string Type - { - get { return DeviceType; } - } - - protected override async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken) - { - var urlHash = tuner.Url.GetMD5().ToString("N"); - var prefix = ChannelIdPrefix + urlHash; - if (!channelId.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) - { - return null; - } - - var channels = await GetChannels(tuner, true, cancellationToken).ConfigureAwait(false); - var m3uchannels = channels.Cast<M3UChannel>(); - var channel = m3uchannels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase)); - if (channel != null) - { - var path = channel.Path; - MediaProtocol protocol = MediaProtocol.File; - if (path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - protocol = MediaProtocol.Http; - } - else if (path.StartsWith("rtmp", StringComparison.OrdinalIgnoreCase)) - { - protocol = MediaProtocol.Rtmp; - } - else if (path.StartsWith("rtsp", StringComparison.OrdinalIgnoreCase)) - { - protocol = MediaProtocol.Rtsp; - } - - var mediaSource = new MediaSourceInfo - { - Path = channel.Path, - Protocol = protocol, - MediaStreams = new List<MediaStream> - { - new MediaStream - { - Type = MediaStreamType.Video, - // Set the index to -1 because we don't know the exact index of the video stream within the container - Index = -1, - IsInterlaced = true - }, - new MediaStream - { - Type = MediaStreamType.Audio, - // Set the index to -1 because we don't know the exact index of the audio stream within the container - Index = -1 - - } - }, - RequiresOpening = false, - RequiresClosing = false - }; - - return new List<MediaSourceInfo> { mediaSource }; - } - return new List<MediaSourceInfo>(); - } - - protected override async Task<LiveStream> GetChannelStream(TunerHostInfo tuner, string channelId, string streamId, CancellationToken cancellationToken) - { - var sources = await GetChannelStreamMediaSources(tuner, channelId, cancellationToken).ConfigureAwait(false); - - var liveStream = new LiveStream(sources.First()); - - return liveStream; - } - - protected override async Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken) - { - var updatedInfo = await SatIpDiscovery.Current.GetInfo(tuner.InfoUrl, cancellationToken).ConfigureAwait(false); - - return updatedInfo.TunersAvailable > 0; - } - - protected override bool IsValidChannelId(string channelId) - { - return channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase); - } - - public string Name - { - get { return "Sat IP"; } - } - - public Task<List<LiveTvTunerInfo>> GetTunerInfos(CancellationToken cancellationToken) - { - var list = GetTunerHosts() - .SelectMany(i => GetTunerInfos(i, cancellationToken)) - .ToList(); - - return Task.FromResult(list); - } - - public List<LiveTvTunerInfo> GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) - { - var list = new List<LiveTvTunerInfo>(); - - for (var i = 0; i < info.Tuners; i++) - { - list.Add(new LiveTvTunerInfo - { - Name = info.FriendlyName ?? Name, - SourceType = Type, - Status = LiveTvTunerStatus.Available, - Id = info.Url.GetMD5().ToString("N") + i.ToString(CultureInfo.InvariantCulture), - Url = info.Url - }); - } - - return list; - } - - public string ApplyDuration(string streamPath, TimeSpan duration) - { - return streamPath; - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/TransmissionMode.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/TransmissionMode.cs deleted file mode 100644 index 71d7656d95..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/TransmissionMode.cs +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp -{ - public enum TransmissionMode - { - Unicast, - Multicast - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Utils.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Utils.cs deleted file mode 100644 index 3595e4b0ad..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Utils.cs +++ /dev/null @@ -1,90 +0,0 @@ -/* - Copyright (C) <2007-2016> <Kay Diefenthal> - - SatIp.RtspSample is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SatIp.RtspSample is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SatIp.RtspSample. If not, see <http://www.gnu.org/licenses/>. -*/ -using System; -using System.Text; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp -{ - public class Utils - { - public static int Convert2BytesToInt(byte[] buffer, int offset) - { - int temp = (int)buffer[offset]; - temp = (temp * 256) + buffer[offset + 1]; - - return (temp); - } - public static int Convert3BytesToInt(byte[] buffer, int offset) - { - int temp = (int)buffer[offset]; - temp = (temp * 256) + buffer[offset + 1]; - temp = (temp * 256) + buffer[offset + 2]; - - return (temp); - } - public static int Convert4BytesToInt(byte[] buffer, int offset) - { - int temp =(int)buffer[offset]; - temp = (temp * 256) + buffer[offset + 1]; - temp = (temp * 256) + buffer[offset + 2]; - temp = (temp * 256) + buffer[offset + 3]; - - return (temp); - } - public static long Convert4BytesToLong(byte[] buffer, int offset) - { - long temp = 0; - - for (int index = 0; index < 4; index++) - temp = (temp * 256) + buffer[offset + index]; - - return (temp); - } - public static long Convert8BytesToLong(byte[] buffer, int offset) - { - long temp = 0; - - for (int index = 0; index < 8; index++) - temp = (temp * 256) + buffer[offset + index]; - - return (temp); - } - public static string ConvertBytesToString(byte[] buffer, int offset, int length) - { - StringBuilder reply = new StringBuilder(4); - for (int index = 0; index < length; index++) - reply.Append((char)buffer[offset + index]); - return (reply.ToString()); - } - public static DateTime NptTimestampToDateTime(long nptTimestamp) { return NptTimestampToDateTime((uint)((nptTimestamp >> 32) & 0xFFFFFFFF), (uint)(nptTimestamp & 0xFFFFFFFF),null); } - - public static DateTime NptTimestampToDateTime(uint seconds, uint fractions, DateTime? epoch ) - { - ulong ticks =(ulong)((seconds * TimeSpan.TicksPerSecond) + ((fractions * TimeSpan.TicksPerSecond) / 0x100000000L)); - if (epoch.HasValue) return epoch.Value + TimeSpan.FromTicks((Int64)ticks); - return (seconds & 0x80000000L) == 0 ? UtcEpoch2036 + TimeSpan.FromTicks((Int64)ticks) : UtcEpoch1900 + TimeSpan.FromTicks((Int64)ticks); - } - - //When the First Epoch will wrap (The real Y2k) - public static DateTime UtcEpoch2036 = new DateTime(2036, 2, 7, 6, 28, 16, DateTimeKind.Utc); - - public static DateTime UtcEpoch1900 = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc); - - public static DateTime UtcEpoch1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0030.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0030.ini deleted file mode 100644 index 1caa948cf6..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0030.ini +++ /dev/null @@ -1,100 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0030 -2=Eutelsat 3B/Rascom QAF 1R (3.0E) - -[DVB] -0=91 -1=3794,H,3590,23,S2,8PSK -2=3797,H,2442,23,DVB-S,QPSK -3=3970,V,2741,34,DVB-S,QPSK -4=3975,V,3111,23,DVB-S,QPSK -5=3986,V,13557,56,DVB-S,QPSK -6=4151,V,2141,56,S2,QPSK -7=4173,V,1917,56,S2,QPSK -8=10961,H,10000,34,S2,8PSK -9=10973,H,10000,34,S2,8PSK -10=10985,H,10000,34,S2,QPSK -11=11042,H,4279,89,S2,QPSK -12=11049,H,1000,23,S2,8PSK -13=11051,H,2100,56,S2,QPSK -14=11078,H,7430,56,S2,QPSK -15=11088,H,7430,56,S2,QPSK -16=11097,H,7430,56,S2,QPSK -17=11456,V,2876,78,DVB-S,QPSK -18=11456,H,1480,34,S2,8PSK -19=11457,H,3000,78,DVB-S,QPSK -20=11461,V,2000,34,DVB-S,QPSK -21=11465,V,2500,78,DVB-S,QPSK -22=11468,H,2963,34,DVB-S,QPSK -23=11471,V,2500,78,DVB-S,QPSK -24=11472,H,2600,34,DVB-S,QPSK -25=11476,H,2600,34,DVB-S,QPSK -26=11479,V,3000,56,S2,QPSK -27=11480,H,1480,78,DVB-S,QPSK -28=11482,V,11852,34,DVB-S,QPSK -29=11487,H,1480,34,S2,8PSK -30=11490,H,2222,56,DVB-S,QPSK -31=11496,H,3000,34,DVB-S,QPSK -32=11498,V,11852,34,DVB-S,QPSK -33=11503,H,1480,56,S2,8PSK -34=11507,H,1480,34,S2,8PSK -35=11521,H,8800,23,S2,8PSK -36=11521,V,1500,34,S2,8PSK -37=11530,V,1500,34,S2,8PSK -38=11532,V,1500,34,S2,8PSK -39=11533,H,8800,23,S2,8PSK -40=11544,H,3550,34,S2,8PSK -41=11555,H,8800,23,DVB-S,QPSK -42=11562,H,2850,34,DVB-S,QPSK -43=11585,H,9600,23,S2,8PSK -44=11585,V,9260,56,DVB-S,QPSK -45=11594,V,3333,78,DVB-S,QPSK -46=11597,H,2250,34,DVB-S,QPSK -47=11598,V,2250,34,DVB-S,QPSK -48=11606,V,1480,56,S2,8PSK -49=11609,H,9600,23,S2,8PSK -50=11615,V,2200,34,DVB-S,QPSK -51=11621,H,9600,56,S2,8PSK -52=11621,V,1200,34,S2,8PSK -53=11632,V,2200,34,DVB-S,QPSK -54=11642,H,1111,34,S2,8PSK -55=11645,H,3000,34,DVB-S,QPSK -56=11649,H,3000,34,DVB-S,QPSK -57=11655,H,2304,34,S2,8PSK -58=11660,H,2400,56,DVB-S,QPSK -59=11663,H,1550,56,S2,8PSK -60=11671,V,1500,34,S2,8PSK -61=11673,V,1500,34,S2,8PSK -62=11675,V,1500,56,S2,8PSK -63=11680,V,3750,34,DVB-S,QPSK -64=11692,V,1860,78,DVB-S,QPSK -65=11696,V,2000,34,DVB-S,QPSK -66=12526,H,4444,34,S2,8PSK -67=12531,H,2265,89,S2,QPSK -68=12534,H,2500,34,S2,8PSK -69=12537,H,2500,34,S2,8PSK -70=12548,V,3000,56,S2,QPSK -71=12553,V,1100,56,S2,8PSK -72=12554,V,1100,56,S2,8PSK -73=12556,V,1100,34,S2,8PSK -74=12557,V,1500,34,DVB-S,QPSK -75=12559,V,1500,56,S2,8PSK -76=12563,V,1500,34,S2,8PSK -77=12566,V,2750,23,S2,8PSK -78=12571,V,3650,23,S2,8PSK -79=12572,H,10000,34,S2,QPSK -80=12574,V,1447,34,DVB-S,QPSK -81=12576,V,1570,34,S2,8PSK -82=12609,H,9600,23,S2,8PSK -83=12638,V,14400,34,S2,8PSK -84=12692,H,1450,56,S2,8PSK -85=12702,H,13960,35,S2,QPSK -86=12703,V,3704,34,S2,8PSK -87=12707,V,2963,34,S2,8PSK -88=12717,V,2143,56,DVB-S,QPSK -89=12720,H,13960,35,S2,QPSK -90=12734,V,16750,35,S2,QPSK -91=12737,H,2930,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0049.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0049.ini deleted file mode 100644 index 92a0e7dda5..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0049.ini +++ /dev/null @@ -1,102 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0049 -2=Astra 4A/SES 5 (4.9E) - -[DVB] -0=93 -1=3644,H,1300,56,S2,QPSK -2=3843,V,1055,910,S2,QPSK -3=3857,V,1520,35,S2,QPSK -4=3863,V,1130,56,S2,QPSK -5=3866,V,1400,23,S2,QPSK -6=3868,V,1203,56,S2,QPSK -7=3871,V,1550,23,S2,QPSK -8=3876,V,6200,23,S2,QPSK -9=11265,H,30000,34,S2,8PSK -10=11265,V,30000,34,S2,8PSK -11=11305,H,30000,34,S2,8PSK -12=11305,V,30000,34,S2,8PSK -13=11345,H,30000,34,S2,8PSK -14=11345,V,30000,34,S2,8PSK -15=11385,V,30000,34,S2,8PSK -16=11727,H,27500,56,DVB-S,QPSK -17=11747,V,27500,23,S2,QPSK -18=11766,H,27500,34,DVB-S,QPSK -19=11785,V,27500,56,DVB-S,8PSK -20=11804,H,27500,34,DVB-S,QPSK -21=11823,V,27500,34,DVB-S,QPSK -22=11843,H,27500,34,DVB-S,QPSK -23=11862,V,27500,34,DVB-S,8PSK -24=11881,H,27500,34,DVB-S,QPSK -25=11900,V,27500,34,DVB-S,QPSK -26=11919,H,27500,34,DVB-S,QPSK -27=11938,V,27500,34,DVB-S,8PSK -28=11958,H,27500,34,DVB-S,QPSK -29=11977,V,27500,34,DVB-S,8PSK -30=11996,H,27500,34,DVB-S,8PSK -31=12015,V,27500,56,DVB-S,QPSK -32=12034,H,27500,34,DVB-S,QPSK -33=12054,V,27500,34,DVB-S,QPSK -34=12073,H,27500,34,DVB-S,8PSK -35=12092,V,27500,34,DVB-S,QPSK -36=12111,H,27500,56,DVB-S,QPSK -37=12130,V,27500,34,DVB-S,QPSK -38=12149,H,27500,34,DVB-S,QPSK -39=12169,V,27500,34,S2,8PSK -40=12188,H,30000,34,S2,8PSK -41=12207,V,30000,34,S2,8PSK -42=12245,V,27500,34,DVB-S,QPSK -43=12284,V,27500,34,DVB-S,QPSK -44=12303,H,25546,78,DVB-S,8PSK -45=12322,V,27500,56,S2,QPSK -46=12341,H,30000,34,S2,8PSK -47=12360,V,27500,56,S2,8PSK -48=12380,H,27500,34,DVB-S,8PSK -49=12399,V,27500,34,DVB-S,QPSK -50=12418,H,27500,34,DVB-S,8PSK -51=12437,V,27500,34,S2,8PSK -52=12476,V,27500,34,DVB-S,QPSK -53=12514,H,6111,34,DVB-S,QPSK -54=12515,V,7200,34,S2,8PSK -55=12519,H,4610,34,S2,8PSK -56=12524,V,7200,34,S2,8PSK -57=12528,H,9874,34,S2,8PSK -58=12538,V,4610,34,S2,8PSK -59=12540,H,3750,23,S2,8PSK -60=12543,V,4610,34,S2,8PSK -61=12551,V,7400,34,S2,8PSK -62=12560,V,7200,34,S2,8PSK -63=12580,V,3829,34,DVB-S,QPSK -64=12593,V,7200,34,S2,8PSK -65=12602,V,6111,34,DVB-S,QPSK -66=12608,H,27500,34,DVB-S,QPSK -67=12612,V,6111,34,DVB-S,QPSK -68=12620,V,6111,34,DVB-S,QPSK -69=12621,V,3660,23,DVB-S,QPSK -70=12637,H,14468,34,DVB-S,QPSK -71=12670,H,2600,23,DVB-S,QPSK -72=12671,V,3333,34,DVB-S,QPSK -73=12673,H,3750,35,S2,8PSK -74=12674,V,3333,34,DVB-S,QPSK -75=12678,H,6666,78,DVB-S,QPSK -76=12694,H,6666,34,DVB-S,QPSK -77=12694,V,3333,56,DVB-S,QPSK -78=12699,H,3040,78,DVB-S,QPSK -79=12702,V,3333,34,DVB-S,QPSK -80=12702,H,2100,34,S2,8PSK -81=12710,V,4430,34,DVB-S,QPSK -82=12712,H,5000,78,DVB-S,QPSK -83=12716,V,4430,34,DVB-S,QPSK -84=12719,H,2960,34,DVB-S,QPSK -85=12719,V,2950,34,DVB-S,QPSK -86=12722,V,4430,34,DVB-S,QPSK -87=12725,V,1480,89,S2,8PSK -88=12728,V,4430,34,DVB-S,QPSK -89=12730,V,2960,34,DVB-S,QPSK -90=12733,H,3400,34,DVB-S,QPSK -91=12734,V,4430,34,DVB-S,8PSK -92=12737,H,3472,34,DVB-S,QPSK -93=12740,V,4430,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0070.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0070.ini deleted file mode 100644 index 800b097c89..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0070.ini +++ /dev/null @@ -1,134 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0070 -2=Eutelsat 7A/7B (7.0E) - -[DVB] -0=125 -1=10721,H,22000,34,DVB-S,8PSK -2=10721,V,27500,34,DVB-S,QPSK -3=10762,V,30000,34,DVB-S,QPSK -4=10804,H,30000,56,S2,QPSK -5=10804,V,29900,34,DVB-S,QPSK -6=10845,H,30000,56,S2,QPSK -7=10845,V,30000,34,DVB-S,QPSK -8=10887,H,30000,34,S2,QPSK -9=10887,V,30000,56,S2,QPSK -10=10928,H,30000,34,S2,8PSK -11=10928,V,30000,56,S2,QPSK -12=10958,V,4936,34,S2,8PSK -13=10959,H,4936,34,S2,8PSK -14=10962,H,3255,23,DVB-S,QPSK -15=10970,V,4434,78,DVB-S,QPSK -16=10971,H,4936,34,S2,8PSK -17=10976,H,4936,34,S2,8PSK -18=10978,V,7200,34,S2,8PSK -19=10987,H,4936,34,S2,8PSK -20=10994,V,4936,34,S2,8PSK -21=10997,H,9874,34,S2,8PSK -22=10999,H,3209,Auto,DVB-S,QPSK -23=11000,V,4936,34,S2,8PSK -24=11006,V,4936,34,S2,8PSK -25=11009,H,9874,34,S2,8PSK -26=11012,V,4936,34,S2,8PSK -27=11014,H,6111,Auto,DVB-S,QPSK -28=11018,V,3255,78,DVB-S,QPSK -29=11021,H,9874,34,S2,8PSK -30=11022,V,3676,34,S2,8PSK -31=11023,H,6111,Auto,S2,QPSK -32=11042,V,4936,34,S2,8PSK -33=11046,H,8335,56,S2,8PSK -34=11048,V,14400,34,S2,8PSK -35=11054,H,4936,34,S2,8PSK -36=11057,V,9874,34,S2,8PSK -37=11059,H,14238,56,S2,QPSK -38=11060,H,4936,34,S2,8PSK -39=11066,H,4936,34,S2,8PSK -40=11068,V,9874,34,S2,8PSK -41=11080,V,9874,34,S2,8PSK -42=11084,H,4936,34,S2,8PSK -43=11090,H,4936,34,S2,8PSK -44=11090,V,4936,34,S2,8PSK -45=11096,H,4936,34,S2,8PSK -46=11102,H,14400,34,S2,8PSK -47=11105,H,4340,34,DVB-S,QPSK -48=11107,V,7200,34,S2,8PSK -49=11124,V,3600,34,S2,8PSK -50=11128,H,9874,34,S2,8PSK -51=11128,V,3750,34,S2,8PSK -52=11134,V,5000,34,S2,8PSK -53=11137,H,4936,34,S2,8PSK -54=11140,V,9600,34,S2,8PSK -55=11143,H,4936,34,S2,8PSK -56=11148,H,4936,34,S2,8PSK -57=11153,V,7200,34,S2,8PSK -58=11154,H,4936,34,S2,8PSK -59=11160,H,3254,56,S2,8PSK -60=11161,V,4936,34,S2,8PSK -61=11164,H,3255,34,S2,8PSK -62=11165,V,3204,34,DVB-S,QPSK -63=11171,H,7500,56,S2,8PSK -64=11173,V,3674,34,S2,8PSK -65=11181,V,7442,34,S2,8PSK -66=11184,H,5714,Auto,DVB-S,QPSK -67=11186,V,3255,34,DVB-S,QPSK -68=11192,H,3210,34,DVB-S,QPSK -69=11192,V,3700,34,S2,8PSK -70=11221,H,27500,34,DVB-S,QPSK -71=11262,H,27500,56,DVB-S,QPSK -72=11356,H,45000,56,S2,QPSK -73=11387,H,27500,34,DVB-S,QPSK -74=11418,H,45000,56,S2,QPSK -75=11456,V,20050,34,DVB-S,QPSK -76=11471,H,30000,34,DVB-S,QPSK -77=11492,V,30000,34,DVB-S,QPSK -78=11513,H,29900,34,DVB-S,QPSK -79=11534,V,30000,34,DVB-S,QPSK -80=11554,H,30000,34,DVB-S,QPSK -81=11575,V,30000,34,DVB-S,QPSK -82=11596,H,30000,34,DVB-S,QPSK -83=11617,V,30000,34,DVB-S,QPSK -84=11668,V,30000,56,S2,QPSK -85=11678,H,30000,34,DVB-S,QPSK -86=12510,H,7120,34,S2,8PSK -87=12519,H,6144,34,S2,8PSK -88=12520,V,9800,34,S2,8PSK -89=12532,V,1852,23,S2,QPSK -90=12545,H,4950,34,S2,8PSK -91=12548,V,3650,34,S2,8PSK -92=12555,H,4830,78,DVB-S,8PSK -93=12556,V,4035,56,S2,8PSK -94=12565,H,6750,23,S2,8PSK -95=12573,H,7120,34,S2,8PSK -96=12596,V,2500,34,S2,8PSK -97=12603,H,30000,23,S2,8PSK -98=12603,V,2500,34,S2,8PSK -99=12606,V,2500,34,S2,8PSK -100=12611,V,5000,34,S2,8PSK -101=12615,V,2500,34,S2,8PSK -102=12619,V,4444,78,DVB-S,QPSK -103=12624,V,2500,34,S2,8PSK -104=12627,V,2500,34,S2,8PSK -105=12630,V,2500,34,S2,8PSK -106=12643,V,6430,23,S2,8PSK -107=12645,H,30000,23,S2,8PSK -108=12650,V,2400,34,S2,8PSK -109=12653,V,2400,56,S2,8PSK -110=12659,V,4936,34,S2,8PSK -111=12675,H,6430,23,S2,8PSK -112=12687,H,6975,56,S2,8PSK -113=12695,V,6666,78,DVB-S,8PSK -114=12701,H,4800,34,S2,8PSK -115=12704,V,7500,34,S2,8PSK -116=12711,V,4936,34,S2,8PSK -117=12727,V,10000,34,S2,8PSK -118=12728,H,30000,56,DVB-S,QPSK -119=12740,V,6111,34,DVB-S,QPSK -120=21439,H,6111,34,DVB-S,QPSK -121=21553,H,9600,56,S2,8PSK -122=21565,H,1571,78,DVB-S,QPSK -123=21571,H,2442,23,DVB-S,QPSK -124=21584,H,1100,34,S2,8PSK -125=21603,H,6428,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0090.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0090.ini deleted file mode 100644 index 6202569d99..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0090.ini +++ /dev/null @@ -1,40 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0090 -2=Eutelsat 9A/Ka-Sat 9A (9.0E) - -[DVB] -0=31 -1=11727,V,27500,34,DVB-S,QPSK -2=11747,H,27500,23,S2,8PSK -3=11766,V,27500,34,DVB-S,QPSK -4=11785,H,27500,23,S2,8PSK -5=11804,V,27500,34,DVB-S,QPSK -6=11823,H,27500,34,DVB-S,QPSK -7=11843,V,27500,35,S2,8PSK -8=11861,H,27500,23,S2,8PSK -9=11881,V,27500,23,S2,8PSK -10=11900,H,27500,23,S2,8PSK -11=11919,V,27500,34,DVB-S,QPSK -12=11938,H,27500,34,DVB-S,QPSK -13=11958,V,27500,23,S2,8PSK -14=11996,V,27500,34,DVB-S,QPSK -15=12015,H,27500,23,S2,8PSK -16=12034,V,27500,34,S2,8PSK -17=12054,H,27500,23,S2,8PSK -18=12074,V,27500,34,S2,8PSK -19=12092,H,27500,34,S2,8PSK -20=12130,H,27500,34,DVB-S,QPSK -21=12149,V,27500,23,S2,8PSK -22=12226,V,27500,23,S2,8PSK -23=12265,V,27500,23,S2,8PSK -24=12284,H,27500,23,S2,8PSK -25=12322,H,27500,34,DVB-S,QPSK -26=12360,H,27500,23,S2,8PSK -27=12380,V,27500,23,S2,8PSK -28=12399,H,27500,23,S2,8PSK -29=12418,V,27500,23,S2,8PSK -30=12437,H,27500,23,S2,8PSK -31=20185,H,25000,23,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0100.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0100.ini deleted file mode 100644 index 0614ba88c6..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0100.ini +++ /dev/null @@ -1,206 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0100 -2=Eutelsat 10A (10.0E) - -[DVB] -0=197 -1=3649,H,20160,23,S2,QPSK -2=3706,V,6250,56,S2,8PSK -3=3708,H,1002,56,S2,8PSK -4=3721,V,3303,56,S2,8PSK -5=3729,V,10321,56,S2,8PSK -6=3741,V,10114,56,S2,8PSK -7=3759,V,19816,56,S2,8PSK -8=3781,V,16445,56,S2,8PSK -9=3827,V,3080,34,S2,8PSK -10=3835,V,1000,45,S2,QPSK -11=3837,V,1185,34,S2,8PSK -12=3839,V,1185,34,S2,8PSK -13=3865,V,13333,78,DVB-S,QPSK -14=3956,V,1500,23,DVB-S,QPSK -15=4039,V,2222,34,S2,8PSK -16=10707,V,3100,34,DVB-S,QPSK -17=10712,V,4167,56,DVB-S,QPSK -18=10717,V,3215,34,DVB-S,QPSK -19=10734,V,1447,34,DVB-S,QPSK -20=10738,V,2894,34,DVB-S,QPSK -21=10742,V,2894,34,DVB-S,QPSK -22=10747,V,4000,910,S2,8PSK -23=10756,V,2480,78,DVB-S,QPSK -24=10792,V,4936,34,S2,QPSK -25=10798,V,4936,34,S2,8PSK -26=10803,V,6111,34,DVB-S,QPSK -27=10810,V,4430,34,DVB-S,QPSK -28=10822,V,4430,34,S2,8PSK -29=10832,V,8876,56,S2,8PSK -30=10840,V,3255,12,DVB-S,QPSK -31=10848,V,6111,34,DVB-S,QPSK -32=10859,V,2875,Auto,S2,QPSK -33=10877,V,6111,34,DVB-S,QPSK -34=10886,V,6111,Auto,DVB-S,QPSK -35=10893,V,4936,34,S2,QPSK -36=10899,V,4936,34,S2,8PSK -37=10905,V,4936,34,S2,QPSK -38=10918,V,4430,34,DVB-S,QPSK -39=10923,V,4600,56,S2,8PSK -40=10931,V,7120,34,S2,8PSK -41=10940,V,6080,34,DVB-S,QPSK -42=10956,H,2500,56,DVB-S,QPSK -43=10960,V,4167,56,DVB-S,QPSK -44=10965,H,3124,34,DVB-S,QPSK -45=10965,V,4167,56,DVB-S,QPSK -46=10969,H,3124,34,DVB-S,QPSK -47=10970,V,4167,56,DVB-S,QPSK -48=10973,H,3124,34,DVB-S,QPSK -49=10976,V,4167,56,DVB-S,QPSK -50=10977,H,3124,34,DVB-S,QPSK -51=10981,H,3124,34,DVB-S,QPSK -52=10981,V,4600,56,S2,8PSK -53=10985,H,3124,34,DVB-S,QPSK -54=10988,H,3124,34,DVB-S,QPSK -55=10992,H,3124,34,DVB-S,QPSK -56=10998,V,2900,34,DVB-S,QPSK -57=11004,V,2400,34,DVB-S,QPSK -58=11005,H,7120,34,S2,8PSK -59=11008,V,2963,34,DVB-S,QPSK -60=11014,H,7120,34,S2,8PSK -61=11018,V,2857,34,DVB-S,QPSK -62=11022,V,2650,34,DVB-S,QPSK -63=11023,H,7120,34,S2,8PSK -64=11043,H,7120,23,S2,8PSK -65=11060,H,4937,34,S2,8PSK -66=11066,H,4937,34,S2,8PSK -67=11074,H,4937,34,S2,8PSK -68=11075,V,68571,34,DVB-S,QPSK -69=11093,H,9874,34,S2,8PSK -70=11107,H,4936,34,S2,8PSK -71=11124,H,3300,34,DVB-S,8PSK -72=11127,V,6111,34,DVB-S,QPSK -73=11129,H,3333,34,DVB-S,8PSK -74=11134,H,3333,34,DVB-S,QPSK -75=11136,V,7400,34,S2,8PSK -76=11138,H,2400,56,S2,8PSK -77=11144,H,6111,34,DVB-S,QPSK -78=11144,V,6666,78,DVB-S,QPSK -79=11151,H,3254,34,DVB-S,QPSK -80=11154,V,5632,34,DVB-S,QPSK -81=11160,H,2267,56,S2,8PSK -82=11162,V,2400,34,DVB-S,QPSK -83=11165,H,3750,34,S2,8PSK -84=11168,V,2300,34,DVB-S,QPSK -85=11169,H,3028,34,S2,QPSK -86=11173,H,3028,34,S2,QPSK -87=11179,H,2066,23,S2,8PSK -88=11182,H,2400,23,S2,8PSK -89=11186,H,2667,56,DVB-S,QPSK -90=11189,H,2352,34,DVB-S,QPSK -91=11193,H,2880,34,S2,QPSK -92=11207,H,7500,34,S2,8PSK -93=11221,V,30000,56,S2,QPSK -94=11291,H,9875,34,S2,8PSK -95=11294,V,14400,34,S2,8PSK -96=11317,H,7500,56,S2,8PSK -97=11346,H,27500,34,DVB-S,QPSK -98=11375,V,9874,34,S2,8PSK -99=11399,V,9874,34,S2,8PSK -100=11419,H,11814,56,S2,8PSK -101=11434,H,10098,35,S2,QPSK -102=11457,H,6111,34,DVB-S,QPSK -103=11483,V,4000,56,S2,8PSK -104=11488,H,2100,34,DVB-S,QPSK -105=11498,V,7450,34,S2,8PSK -106=11501,H,2894,34,DVB-S,QPSK -107=11505,H,3000,34,DVB-S,QPSK -108=11509,H,3000,34,DVB-S,QPSK -109=11511,V,3324,34,DVB-S,QPSK -110=11515,V,4200,34,DVB-S,QPSK -111=11520,V,4200,34,DVB-S,QPSK -112=11524,H,2810,34,DVB-S,QPSK -113=11525,V,4167,56,DVB-S,QPSK -114=11528,H,2800,34,DVB-S,QPSK -115=11534,V,2300,34,DVB-S,QPSK -116=11536,H,2960,34,DVB-S,QPSK -117=11538,V,2900,34,DVB-S,QPSK -118=11541,H,2600,34,S2,8PSK -119=11542,V,2816,78,DVB-S,QPSK -120=11551,V,1993,34,DVB-S,QPSK -121=11552,H,4800,34,S2,8PSK -122=11554,V,3700,56,DVB-S,QPSK -123=11557,H,3333,56,S2,8PSK -124=11561,V,6666,34,S2,8PSK -125=11561,H,3333,56,DVB-S,QPSK -126=11567,H,6666,78,DVB-S,QPSK -127=11584,H,9875,34,S2,8PSK -128=11590,H,2160,34,S2,8PSK -129=11595,V,30000,23,S2,8PSK -130=11615,H,2500,34,DVB-S,QPSK -131=11619,H,2900,34,DVB-S,QPSK -132=11624,V,2900,34,DVB-S,QPSK -133=11624,H,2500,34,DVB-S,QPSK -134=11627,H,2963,34,DVB-S,QPSK -135=11638,H,5300,56,DVB-S,QPSK -136=11645,H,4800,23,S2,QPSK -137=11651,H,2590,34,DVB-S,QPSK -138=11659,H,1500,56,S2,QPSK -139=11663,H,5540,34,DVB-S,QPSK -140=11664,V,6666,78,DVB-S,QPSK -141=11669,V,3000,56,DVB-S,QPSK -142=11671,H,7200,34,S2,8PSK -143=11676,H,11153,78,DVB-S,QPSK -144=11680,V,2220,34,DVB-S,QPSK -145=11681,H,3200,56,S2,8PSK -146=11684,V,2300,34,DVB-S,QPSK -147=11688,H,9874,34,DVB-S,QPSK -148=11693,V,2210,78,DVB-S,QPSK -149=11696,H,2980,34,DVB-S,QPSK -150=11697,V,2300,34,DVB-S,QPSK -151=12504,H,2880,56,DVB-S,QPSK -152=12508,H,2880,56,DVB-S,QPSK -153=12513,H,3214,34,DVB-S,QPSK -154=12520,H,1100,56,S2,8PSK -155=12526,V,3600,34,S2,8PSK -156=12527,H,2143,34,DVB-S,QPSK -157=12535,V,2220,Auto,DVB-S,QPSK -158=12545,H,3400,34,DVB-S,QPSK -159=12551,V,5632,34,DVB-S,QPSK -160=12553,H,2900,34,DVB-S,QPSK -161=12556,V,2900,78,DVB-S,QPSK -162=12563,V,5632,34,DVB-S,QPSK -163=12571,V,2220,78,DVB-S,QPSK -164=12576,V,3300,34,DVB-S,QPSK -165=12593,V,4800,34,S2,8PSK -166=12594,H,3300,Auto,DVB-S,QPSK -167=12602,V,3333,78,DVB-S,QPSK -168=12610,V,1852,34,DVB-S,QPSK -169=12611,H,2960,34,DVB-S,QPSK -170=12615,H,3214,34,S2,8PSK -171=12620,H,3750,56,S2,8PSK -172=12637,V,18400,23,S2,8PSK -173=12648,H,2300,56,DVB-S,QPSK -174=12652,H,4936,34,S2,8PSK -175=12654,V,2300,78,DVB-S,QPSK -176=12658,H,3214,34,S2,8PSK -177=12674,V,2962,56,DVB-S,QPSK -178=12674,H,3750,34,S2,8PSK -179=12679,V,2894,34,DVB-S,QPSK -180=12680,H,3750,34,S2,8PSK -181=12684,H,3200,34,DVB-S,QPSK -182=12688,H,3200,34,DVB-S,QPSK -183=12692,V,3146,34,DVB-S,QPSK -184=12694,H,6666,78,DVB-S,QPSK -185=12696,V,5632,34,DVB-S,QPSK -186=12701,V,2962,34,DVB-S,QPSK -187=12705,V,2922,34,DVB-S,QPSK -188=12706,H,3750,34,DVB-S,QPSK -189=12710,H,3750,34,S2,8PSK -190=12714,V,9874,34,S2,8PSK -191=12715,H,3200,34,DVB-S,QPSK -192=12729,V,4167,56,DVB-S,QPSK -193=12729,H,3325,34,DVB-S,QPSK -194=12733,H,3200,34,DVB-S,QPSK -195=12736,V,4600,56,S2,8PSK -196=12741,V,4167,56,DVB-S,QPSK -197=12742,H,3500,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0130.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0130.ini deleted file mode 100644 index 265104298f..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0130.ini +++ /dev/null @@ -1,106 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0130 -2=Eutelsat Hot Bird 13B/13C/13D (13.0E) - -[DVB] -0=97 -1=10719,V,27500,56,DVB-S,QPSK -2=10758,V,27500,34,S2,8PSK -3=10775,H,29900,56,DVB-S,QPSK -4=10796,V,27500,56,DVB-S,QPSK -5=10815,H,27500,56,DVB-S,QPSK -6=10834,V,27500,34,S2,8PSK -7=10853,H,29900,23,S2,8PSK -8=10873,V,27500,34,DVB-S,QPSK -9=10892,H,27500,34,DVB-S,QPSK -10=10911,V,27500,34,S2,8PSK -11=10930,H,30000,23,S2,8PSK -12=10949,V,27500,34,DVB-S,QPSK -13=10971,H,29700,23,S2,8PSK -14=10992,V,27500,23,DVB-S,QPSK -15=11034,V,27500,34,DVB-S,QPSK -16=11054,H,27500,56,DVB-S,QPSK -17=11075,V,27500,34,DVB-S,QPSK -18=11096,H,29900,23,S2,8PSK -19=11117,V,27500,34,DVB-S,QPSK -20=11137,H,27500,34,DVB-S,QPSK -21=11158,V,27500,56,DVB-S,QPSK -22=11179,H,27500,34,DVB-S,QPSK -23=11200,V,27500,56,DVB-S,QPSK -24=11219,H,29900,56,DVB-S,QPSK -25=11240,V,27500,34,DVB-S,QPSK -26=11258,H,27500,34,S2,8PSK -27=11278,V,27500,34,S2,8PSK -28=11296,H,27500,34,S2,8PSK -29=11317,V,27500,34,DVB-S,QPSK -30=11334,H,27500,34,DVB-S,QPSK -31=11355,V,29900,56,DVB-S,QPSK -32=11393,V,27500,56,DVB-S,QPSK -33=11411,H,27500,56,S2,8PSK -34=11449,H,27500,34,S2,8PSK -35=11471,V,27500,56,DVB-S,QPSK -36=11488,H,27500,56,DVB-S,QPSK -37=11508,V,27500,34,S2,8PSK -38=11526,H,27500,34,DVB-S,QPSK -39=11541,V,22000,56,DVB-S,QPSK -40=11566,H,27500,34,DVB-S,QPSK -41=11585,V,27500,34,DVB-S,QPSK -42=11604,H,27500,56,DVB-S,QPSK -43=11623,V,27500,34,DVB-S,QPSK -44=11642,H,27500,34,DVB-S,QPSK -45=11662,V,27500,34,S2,8PSK -46=11681,H,27500,34,S2,8PSK -47=11727,V,27500,34,DVB-S,QPSK -48=11747,H,27500,34,DVB-S,QPSK -49=11766,V,27500,23,DVB-S,QPSK -50=11785,H,29900,34,S2,8PSK -51=11804,V,27500,23,DVB-S,QPSK -52=11823,H,27500,34,DVB-S,QPSK -53=11843,V,29900,34,S2,8PSK -54=11862,H,29900,56,DVB-S,QPSK -55=11881,V,27500,34,DVB-S,QPSK -56=11900,H,29900,34,S2,8PSK -57=11919,V,29900,56,DVB-S,8PSK -58=11938,H,27500,34,S2,8PSK -59=11958,V,27500,34,DVB-S,QPSK -60=11977,H,29900,56,DVB-S,QPSK -61=11996,V,29900,34,S2,8PSK -62=12015,H,27500,34,DVB-S,QPSK -63=12034,V,29900,56,DVB-S,QPSK -64=12054,H,29900,56,DVB-S,QPSK -65=12073,V,29900,56,DVB-S,QPSK -66=12092,H,29900,34,S2,8PSK -67=12111,V,27500,34,DVB-S,QPSK -68=12130,H,27500,34,S2,8PSK -69=12149,V,27500,34,DVB-S,QPSK -70=12169,H,27500,34,S2,8PSK -71=12188,V,27500,56,DVB-S,QPSK -72=12207,H,29900,34,S2,8PSK -73=12226,V,27500,34,DVB-S,QPSK -74=12265,V,27500,34,S2,8PSK -75=12284,H,27500,56,DVB-S,QPSK -76=12303,V,27500,34,S2,8PSK -77=12322,H,27500,34,DVB-S,QPSK -78=12341,V,29900,34,S2,8PSK -79=12360,H,29900,34,S2,8PSK -80=12380,V,27500,34,DVB-S,QPSK -81=12399,H,27500,34,DVB-S,QPSK -82=12418,V,29900,34,S2,8PSK -83=12437,H,29900,34,S2,QPSK -84=12466,V,29900,56,DVB-S,QPSK -85=12476,H,29900,34,S2,8PSK -86=12520,V,27500,34,DVB-S,QPSK -87=12539,H,27500,23,S2,QPSK -88=12558,V,27500,34,DVB-S,QPSK -89=12577,H,27500,34,S2,8PSK -90=12597,V,27500,34,DVB-S,QPSK -91=12616,H,29900,56,DVB-S,QPSK -92=12635,V,29900,56,DVB-S,QPSK -93=12654,H,27500,56,DVB-S,QPSK -94=12673,V,29900,56,DVB-S,QPSK -95=12692,H,27500,34,S2,8PSK -96=12713,V,29900,56,DVB-S,QPSK -97=12731,H,29900,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0160.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0160.ini deleted file mode 100644 index 9a9503eb58..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0160.ini +++ /dev/null @@ -1,156 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0160 -2=Eutelsat 16A (16.0E) - -[DVB] -0=147 -1=10721,H,27500,34,DVB-S,QPSK -2=10762,H,30000,35,S2,8PSK -3=10804,H,30000,23,S2,8PSK -4=10845,H,30000,Auto,S2,QPSK -5=10887,H,30000,Auto,S2,QPSK -6=10928,H,30000,89,S2,QPSK -7=10957,H,3750,34,S2,8PSK -8=10961,H,3750,34,S2,8PSK -9=10966,H,3750,34,S2,8PSK -10=10971,H,3750,34,S2,8PSK -11=10972,V,27500,56,DVB-S,QPSK -12=10975,H,3750,34,S2,8PSK -13=10977,H,24113,Auto,S2,8PSK -14=10981,H,3462,56,S2,8PSK -15=10992,H,2500,56,S2,8PSK -16=10997,H,2500,56,S2,8PSK -17=11001,H,2500,56,S2,8PSK -18=11007,H,5000,34,S2,8PSK -19=11011,V,27500,56,DVB-S,QPSK -20=11012,H,3333,78,DVB-S,QPSK -21=11016,H,1500,23,S2,8PSK -22=11019,H,1795,Auto,S2,QPSK -23=11023,H,7500,34,S2,8PSK -24=11024,H,3330,Auto,DVB-S,8PSK -25=11029,H,2300,Auto,DVB-S,QPSK -26=11046,H,10555,34,DVB-S,QPSK -27=11060,H,4615,56,DVB-S,QPSK -28=11063,H,3328,34,DVB-S,QPSK -29=11074,H,1250,34,DVB-S,QPSK -30=11082,H,10000,Auto,S2,QPSK -31=11092,H,3600,34,S2,8PSK -32=11104,H,7400,34,S2,8PSK -33=11127,H,10000,56,S2,8PSK -34=11131,V,16593,23,S2,8PSK -35=11139,H,10000,56,S2,8PSK -36=11151,V,13268,23,S2,8PSK -37=11152,H,10000,56,S2,8PSK -38=11164,H,10000,56,S2,8PSK -39=11175,H,10000,56,S2,8PSK -40=11178,V,27500,34,DVB-S,QPSK -41=11187,H,10000,56,S2,8PSK -42=11221,H,30000,34,DVB-S,QPSK -43=11231,V,30000,34,DVB-S,QPSK -44=11262,H,30000,23,DVB-S,QPSK -45=11283,V,30000,23,S2,8PSK -46=11294,H,45000,34,S2,8PSK -47=11303,H,30000,23,S2,8PSK -48=11324,V,30000,34,DVB-S,QPSK -49=11345,H,30000,35,S2,8PSK -50=11356,H,45000,34,S2,8PSK -51=11366,V,30000,34,DVB-S,QPSK -52=11387,H,30000,34,DVB-S,QPSK -53=11400,V,13846,34,S2,8PSK -54=11427,V,27500,34,S2,8PSK -55=11470,V,30000,56,S2,8PSK -56=11471,H,30000,89,S2,QPSK -57=11512,H,30000,89,S2,QPSK -58=11512,V,29950,23,S2,8PSK -59=11554,H,30000,56,S2,QPSK -60=11554,V,30000,56,S2,8PSK -61=11595,H,30000,34,S2,8PSK -62=11595,V,30000,56,S2,8PSK -63=11596,H,30000,89,S2,QPSK -64=11604,V,14400,34,S2,8PSK -65=11637,H,30000,89,S2,QPSK -66=11645,V,27700,56,S2,QPSK -67=11675,V,9874,34,S2,8PSK -68=11678,H,30000,35,S2,8PSK -69=11687,V,9874,34,S2,8PSK -70=12508,H,3600,34,S2,8PSK -71=12512,H,3166,23,S2,8PSK -72=12516,H,3166,23,S2,8PSK -73=12517,V,8000,56,S2,8PSK -74=12521,H,30000,23,S2,8PSK -75=12522,H,3166,23,S2,8PSK -76=12527,H,2816,34,DVB-S,QPSK -77=12528,V,10000,56,S2,8PSK -78=12533,H,6333,23,S2,8PSK -79=12538,H,3166,23,S2,8PSK -80=12541,V,10000,56,S2,8PSK -81=12542,H,2816,34,DVB-S,QPSK -82=12548,H,6333,23,S2,8PSK -83=12554,H,2816,34,DVB-S,QPSK -84=12557,H,3166,23,S2,8PSK -85=12559,V,2222,34,S2,QPSK -86=12562,H,3166,23,S2,8PSK -87=12564,H,30000,23,S2,8PSK -88=12564,V,3617,34,DVB-S,QPSK -89=12570,H,3703,78,DVB-S,QPSK -90=12575,V,6000,34,S2,8PSK -91=12593,H,7120,34,S2,8PSK -92=12593,V,2500,23,DVB-S,QPSK -93=12597,V,2848,23,DVB-S,QPSK -94=12600,H,3200,23,S2,8PSK -95=12604,H,30000,23,S2,8PSK -96=12605,H,3166,23,S2,8PSK -97=12605,V,7125,34,S2,QPSK -98=12609,H,3200,23,S2,8PSK -99=12611,V,1415,34,DVB-S,QPSK -100=12614,H,3200,23,S2,8PSK -101=12618,H,3166,23,S2,8PSK -102=12620,V,3750,56,S2,8PSK -103=12623,H,4936,34,S2,8PSK -104=12624,V,1650,56,S2,8PSK -105=12626,V,1650,56,S2,8PSK -106=12628,V,1650,56,S2,8PSK -107=12633,V,4883,12,DVB-S,QPSK -108=12644,V,13200,34,S2,QPSK -109=12654,H,11111,23,DVB-S,QPSK -110=12656,V,4883,12,DVB-S,QPSK -111=12676,H,4248,34,DVB-S,QPSK -112=12677,V,2400,34,S2,8PSK -113=12680,V,2400,34,S2,8PSK -114=12683,V,2400,34,S2,8PSK -115=12686,V,2400,34,S2,8PSK -116=12689,V,2400,34,S2,8PSK -117=12692,V,2400,34,S2,8PSK -118=12695,V,2400,34,S2,8PSK -119=12698,V,2400,34,S2,8PSK -120=12699,H,9880,12,DVB-S,QPSK -121=12701,V,2400,34,S2,8PSK -122=12704,V,2400,34,S2,8PSK -123=12707,V,2400,34,S2,8PSK -124=12710,H,5165,35,S2,8PSK -125=12710,V,2400,34,S2,8PSK -126=12713,V,2400,34,S2,8PSK -127=12717,H,4936,34,S2,8PSK -128=12717,V,2400,34,S2,8PSK -129=12720,V,2400,34,S2,8PSK -130=12723,V,2400,34,S2,8PSK -131=12723,H,4936,34,S2,8PSK -132=12728,V,2400,34,S2,8PSK -133=12737,V,2400,34,S2,8PSK -134=12738,H,4500,34,DVB-S,QPSK -135=21537,H,1070,34,S2,8PSK -136=21538,H,1054,34,S2,8PSK -137=21540,H,1071,34,S2,8PSK -138=21541,H,1071,34,S2,8PSK -139=21545,H,2143,56,S2,8PSK -140=21550,H,1054,34,S2,8PSK -141=21551,H,1060,23,DVB-S,QPSK -142=21559,H,1071,34,S2,8PSK -143=21560,H,1010,23,S2,8PSK -144=21562,H,1010,23,S2,8PSK -145=21563,H,1250,23,S2,8PSK -146=21569,H,1071,34,S2,8PSK -147=21571,H,2900,56,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0170.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0170.ini deleted file mode 100644 index 52ba9e5f70..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0170.ini +++ /dev/null @@ -1,60 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0170 -2=Amos 5 (17.0E) - -[DVB] -0=51 -1=3538,V,4444,34,DVB-S,QPSK -2=3547,V,7200,34,S2,8PSK -3=3553,V,1285,56,S2,8PSK -4=3617,V,1167,23,S2,8PSK -5=3620,V,1000,34,S2,8PSK -6=3622,V,1000,23,S2,8PSK -7=3626,V,2000,34,DVB-S,QPSK -8=3626,H,1200,23,DVB-S,QPSK -9=3665,H,3300,78,DVB-S,QPSK -10=3685,V,1924,78,DVB-S,QPSK -11=3688,V,2000,34,DVB-S,QPSK -12=3728,H,3300,78,DVB-S,QPSK -13=3731,H,2500,56,S2,8PSK -14=3757,V,3300,78,DVB-S,QPSK -15=3785,V,1168,34,DVB-S,QPSK -16=3802,V,1666,34,S2,8PSK -17=3828,V,1250,23,S2,8PSK -18=3830,V,1480,56,S2,QPSK -19=3852,V,1000,56,S2,QPSK -20=4066,V,1000,23,S2,8PSK -21=4119,V,7200,34,DVB-S,QPSK -22=4125,V,2170,34,DVB-S,QPSK -23=4130,V,6850,35,S2,8PSK -24=4136,V,2500,23,S2,8PSK -25=4139,V,1000,34,S2,8PSK -26=4141,V,1550,34,S2,8PSK -27=4142,V,1000,23,S2,8PSK -28=4144,V,1334,56,DVB-S,QPSK -29=4160,V,4166,56,DVB-S,QPSK -30=10961,V,2200,12,S2,QPSK -31=10983,V,3333,56,DVB-S,QPSK -32=11038,V,1760,34,S2,QPSK -33=11041,V,1594,34,S2,QPSK -34=11057,V,4273,12,S2,QPSK -35=11062,V,1250,34,S2,QPSK -36=11064,V,1244,34,S2,QPSK -37=11087,V,1245,34,S2,QPSK -38=11092,V,1244,34,DVB-S,QPSK -39=11139,V,30000,Auto,S2,QPSK -40=11761,V,15000,34,S2,QPSK -41=11801,V,30000,23,S2,QPSK -42=11884,V,27500,34,DVB-S,QPSK -43=11967,V,30000,34,S2,QPSK -44=12004,V,30000,34,S2,QPSK -45=12035,H,4000,Auto,S2,8PSK -46=12068,V,45000,56,S2,QPSK -47=12208,H,17666,45,S2,QPSK -48=12260,V,17666,45,S2,QPSK -49=12335,V,27500,34,DVB-S,QPSK -50=12384,V,30000,34,S2,QPSK -51=12418,V,30000,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0192.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0192.ini deleted file mode 100644 index fbe65c9b5d..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0192.ini +++ /dev/null @@ -1,127 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0192 -2=Astra 1KR/1L/1M/1N (19.2E) - -[DVB] -0=118 -1=10729,V,22000,23,S2,8PSK -2=10744,H,22000,56,DVB-S,QPSK -3=10758,V,22000,56,DVB-S,QPSK -4=10773,H,22000,34,S2,8PSK -5=10788,V,22000,56,DVB-S,QPSK -6=10803,H,22000,34,S2,8PSK -7=10818,V,22000,23,S2,8PSK -8=10832,H,22000,23,S2,8PSK -9=10847,V,22000,56,DVB-S,QPSK -10=10862,H,22000,23,S2,8PSK -11=10876,V,22000,56,DVB-S,QPSK -12=10891,H,22000,23,S2,8PSK -13=10906,V,22000,23,S2,8PSK -14=10921,H,22000,78,DVB-S,QPSK -15=10936,V,22000,23,S2,8PSK -16=10964,H,22000,23,S2,8PSK -17=10979,V,22000,56,DVB-S,QPSK -18=10994,H,22000,910,S2,QPSK -19=11023,H,23500,34,S2,8PSK -20=11038,V,22000,56,DVB-S,QPSK -21=11053,H,22000,23,S2,8PSK -22=11068,V,22000,56,DVB-S,QPSK -23=11082,H,22000,34,S2,8PSK -24=11097,V,22000,56,DVB-S,QPSK -25=11112,H,22000,23,S2,8PSK -26=11127,V,22000,23,S2,8PSK -27=11156,V,22000,56,DVB-S,QPSK -28=11171,H,22000,34,S2,8PSK -29=11186,V,22000,56,DVB-S,QPSK -30=11229,V,22000,23,S2,8PSK -31=11244,H,22000,56,DVB-S,QPSK -32=11259,V,22000,23,S2,8PSK -33=11273,H,22000,23,S2,8PSK -34=11288,V,22000,23,S2,8PSK -35=11303,H,22000,23,S2,8PSK -36=11318,V,22000,56,DVB-S,QPSK -37=11332,H,22000,34,S2,8PSK -38=11347,V,22000,23,S2,8PSK -39=11362,H,22000,23,S2,8PSK -40=11377,V,22000,23,S2,8PSK -41=11391,H,22000,56,DVB-S,QPSK -42=11421,H,22000,56,DVB-S,QPSK -43=11436,V,22000,23,S2,8PSK -44=11464,H,22000,23,S2,8PSK -45=11494,H,22000,23,S2,8PSK -46=11509,V,22000,56,DVB-S,QPSK -47=11523,H,22000,56,DVB-S,QPSK -48=11538,V,22000,56,DVB-S,QPSK -49=11553,H,22000,34,S2,8PSK -50=11568,V,22000,23,S2,8PSK -51=11582,H,22000,23,S2,8PSK -52=11597,V,22000,56,DVB-S,QPSK -53=11612,H,22000,56,DVB-S,QPSK -54=11627,V,22000,56,DVB-S,QPSK -55=11641,H,22000,56,DVB-S,QPSK -56=11671,H,22000,23,S2,8PSK -57=11686,V,22000,56,DVB-S,QPSK -58=11720,H,27500,34,DVB-S,QPSK -59=11739,V,27500,34,DVB-S,QPSK -60=11758,H,27500,34,DVB-S,QPSK -61=11778,V,27500,34,DVB-S,QPSK -62=11798,H,27500,34,DVB-S,QPSK -63=11817,V,29700,56,S2,QPSK -64=11836,H,27500,34,DVB-S,QPSK -65=11856,V,27500,34,DVB-S,QPSK -66=11876,H,27500,34,S2,8PSK -67=11914,H,27500,910,S2,QPSK -68=11934,V,27500,34,DVB-S,QPSK -69=11954,H,27500,34,DVB-S,QPSK -70=11973,V,27500,34,DVB-S,QPSK -71=11992,H,27500,910,S2,QPSK -72=12012,V,29700,56,S2,QPSK -73=12032,H,27500,34,DVB-S,QPSK -74=12051,V,27500,34,DVB-S,QPSK -75=12070,H,27500,34,DVB-S,QPSK -76=12090,V,29700,56,S2,QPSK -77=12110,H,27500,34,DVB-S,QPSK -78=12129,V,29700,56,S2,QPSK -79=12148,H,27500,34,DVB-S,QPSK -80=12168,V,29700,56,S2,QPSK -81=12188,H,27500,34,DVB-S,QPSK -82=12207,V,29700,56,S2,QPSK -83=12226,H,27500,34,DVB-S,QPSK -84=12246,V,29700,56,S2,QPSK -85=12266,H,27500,34,DVB-S,QPSK -86=12285,V,29700,23,S2,8PSK -87=12304,H,27500,910,S2,QPSK -88=12324,V,29700,56,S2,QPSK -89=12363,V,27500,34,DVB-S,QPSK -90=12382,H,27500,910,S2,QPSK -91=12402,V,27500,34,DVB-S,QPSK -92=12422,H,27500,34,DVB-S,QPSK -93=12441,V,29700,56,S2,QPSK -94=12460,H,27500,34,DVB-S,QPSK -95=12480,V,27500,34,DVB-S,QPSK -96=12515,H,22000,56,DVB-S,QPSK -97=12522,V,22000,23,S2,8PSK -98=12545,H,22000,56,DVB-S,QPSK -99=12552,V,22000,56,DVB-S,QPSK -100=12574,H,22000,23,S2,8PSK -101=12581,V,22000,23,S2,8PSK -102=12604,H,22000,56,DVB-S,QPSK -103=12610,V,22000,23,S2,8PSK -104=12633,H,22000,56,DVB-S,QPSK -105=12640,V,22000,23,S2,8PSK -106=12663,H,22000,56,DVB-S,QPSK -107=12670,V,22000,23,S2,8PSK -108=12692,H,22000,56,DVB-S,QPSK -109=12699,V,22000,56,DVB-S,QPSK -110=12722,H,23500,23,S2,8PSK -111=12728,V,22000,56,DVB-S,QPSK -112=18366,V,15000,12,S2,QPSK -113=18515,V,3630,23,S2,8PSK -114=18538,V,3344,34,S2,8PSK -115=18556,V,3630,23,S2,8PSK -116=18754,H,4500,34,DVB-S,QPSK -117=18760,H,5500,23,S2,8PSK -118=18766,H,3110,12,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0200.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0200.ini deleted file mode 100644 index 6eb757f162..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0200.ini +++ /dev/null @@ -1,19 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0200 -2=Arabsat 5C (20.0E) - -[DVB] -0=10 -1=3710,V,2600,34,DVB-S,QPSK -2=3714,V,2600,34,DVB-S,QPSK -3=3720,V,6660,34,DVB-S,QPSK -4=3796,H,1850,34,DVB-S,QPSK -5=3884,V,27500,56,DVB-S,QPSK -6=3934,H,27500,78,DVB-S,QPSK -7=4004,V,27500,34,DVB-S,QPSK -8=4054,H,27500,34,DVB-S,QPSK -9=4110,V,3889,78,DVB-S,QPSK -10=4114,V,2988,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0215.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0215.ini deleted file mode 100644 index 30f3d5c6e9..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0215.ini +++ /dev/null @@ -1,103 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0215 -2=Eutelsat 21B (21.5E) - -[DVB] -0=94 -1=10955,H,3220,56,DVB-S,QPSK -2=10958,H,2590,34,DVB-S,QPSK -3=10966,H,2590,34,DVB-S,QPSK -4=10970,H,2500,34,DVB-S,QPSK -5=10975,H,2200,56,S2,8PSK -6=10978,V,2170,34,DVB-S,QPSK -7=10986,H,2150,34,DVB-S,QPSK -8=10992,H,3220,56,S2,8PSK -9=10995,H,2667,34,DVB-S,QPSK -10=10998,V,8888,34,DVB-S,QPSK -11=10999,H,3590,34,S2,8PSK -12=11003,H,2222,34,DVB-S,QPSK -13=11006,H,2592,56,DVB-S,QPSK -14=11009,H,2170,78,DVB-S,QPSK -15=11010,V,10000,34,S2,8PSK -16=11012,H,2667,34,DVB-S,QPSK -17=11015,H,2667,34,DVB-S,QPSK -18=11027,H,2200,34,S2,QPSK -19=11036,H,2100,34,DVB-S,QPSK -20=11038,V,2000,34,DVB-S,QPSK -21=11040,H,3600,34,DVB-S,QPSK -22=11061,V,2000,34,DVB-S,QPSK -23=11082,V,7400,23,S2,8PSK -24=11093,V,10000,34,S2,8PSK -25=11110,H,2667,34,DVB-S,QPSK -26=11128,H,10450,45,S2,QPSK -27=11190,V,6666,23,DVB-S,QPSK -28=11341,H,26460,23,S2,8PSK -29=11464,H,2590,34,DVB-S,QPSK -30=11468,H,1317,56,S2,8PSK -31=11470,H,2000,34,DVB-S,QPSK -32=11473,H,1900,56,S2,8PSK -33=11475,V,2100,34,DVB-S,QPSK -34=11476,H,2857,34,DVB-S,QPSK -35=11479,H,3184,34,DVB-S,QPSK -36=11480,V,2970,34,DVB-S,QPSK -37=11482,H,2856,34,DVB-S,QPSK -38=11483,V,3000,34,DVB-S,QPSK -39=11487,H,2700,56,DVB-S,QPSK -40=11488,V,2150,34,DVB-S,QPSK -41=11490,V,2220,34,DVB-S,QPSK -42=11497,V,2170,34,DVB-S,QPSK -43=11503,V,3300,34,DVB-S,QPSK -44=11508,V,3300,34,DVB-S,QPSK -45=11517,H,3333,56,S2,8PSK -46=11519,V,1500,56,S2,8PSK -47=11521,H,3300,34,DVB-S,QPSK -48=11526,H,2200,56,DVB-S,QPSK -49=11530,H,2200,34,DVB-S,QPSK -50=11532,V,2857,34,DVB-S,QPSK -51=11537,V,2755,34,DVB-S,QPSK -52=11541,V,6534,45,S2,QPSK -53=11546,V,2592,34,DVB-S,QPSK -54=11550,V,2142,34,DVB-S,QPSK -55=11557,H,3000,23,S2,8PSK -56=11558,V,1650,34,S2,8PSK -57=11564,V,7214,34,S2,8PSK -58=11574,V,2300,56,S2,8PSK -59=11578,V,3300,34,DVB-S,QPSK -60=11581,H,5000,34,DVB-S,QPSK -61=11582,V,2850,78,DVB-S,QPSK -62=11585,V,1600,34,DVB-S,QPSK -63=11588,H,5000,34,DVB-S,QPSK -64=11590,V,2856,78,DVB-S,QPSK -65=11593,V,1500,34,S2,8PSK -66=11596,H,5000,34,DVB-S,QPSK -67=11610,H,6200,78,DVB-S,QPSK -68=11619,V,12500,23,DVB-S,QPSK -69=11627,H,4260,56,S2,8PSK -70=11633,H,4260,56,S2,8PSK -71=11639,H,4260,56,S2,8PSK -72=11645,V,1600,45,S2,8PSK -73=11649,V,1600,34,S2,8PSK -74=11653,V,1600,34,S2,8PSK -75=11659,V,2850,78,DVB-S,QPSK -76=11663,H,3220,56,S2,8PSK -77=11665,V,2850,34,S2,8PSK -78=11673,V,2000,34,DVB-S,QPSK -79=11676,H,2150,34,DVB-S,QPSK -80=11678,V,2850,78,DVB-S,QPSK -81=11681,H,2963,34,DVB-S,QPSK -82=11684,V,2100,34,S2,8PSK -83=11686,H,1800,34,DVB-S,QPSK -84=11689,H,1500,34,DVB-S,QPSK -85=11691,V,1447,34,DVB-S,QPSK -86=11693,H,1500,34,S2,8PSK -87=11697,H,2500,34,DVB-S,QPSK -88=12508,H,3300,34,DVB-S,QPSK -89=12516,H,2200,34,DVB-S,QPSK -90=12521,H,2857,34,DVB-S,QPSK -91=12532,H,2220,34,DVB-S,QPSK -92=12536,H,2200,34,DVB-S,QPSK -93=12591,V,3124,34,DVB-S,QPSK -94=12622,V,3124,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0235.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0235.ini deleted file mode 100644 index b1abb39c66..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0235.ini +++ /dev/null @@ -1,127 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0235 -2=Astra 3B (23.5E) - -[DVB] -0=118 -1=11459,V,6666,78,DVB-S,QPSK -2=11460,H,7200,34,S2,QPSK -3=11469,H,3214,34,S2,8PSK -4=11470,V,7500,34,S2,8PSK -5=11476,V,3703,34,DVB-S,QPSK -6=11479,H,4444,34,DVB-S,QPSK -7=11484,V,4444,34,DVB-S,QPSK -8=11490,V,3250,34,DVB-S,QPSK -9=11490,H,3300,56,S2,8PSK -10=11496,V,2170,Auto,DVB-S,QPSK -11=11501,H,7200,56,S2,8PSK -12=11501,V,3750,89,S2,8PSK -13=11506,H,4800,34,S2,8PSK -14=11508,V,3600,34,S2,QPSK -15=11512,V,4800,34,S2,QPSK -16=11516,H,4444,34,DVB-S,QPSK -17=11516,V,3600,34,S2,QPSK -18=11521,H,3630,23,S2,8PSK -19=11527,H,7200,34,S2,QPSK -20=11530,V,4800,34,S2,8PSK -21=11532,H,3333,34,DVB-S,QPSK -22=11579,H,4333,78,DVB-S,QPSK -23=11583,V,10000,56,S2,8PSK -24=11591,H,7500,34,S2,8PSK -25=11597,V,4500,78,DVB-S,QPSK -26=11599,H,4800,56,S2,8PSK -27=11608,H,7200,34,S2,8PSK -28=11619,V,3750,23,S2,8PSK -29=11620,H,7200,34,S2,8PSK -30=11622,V,2333,56,S2,QPSK -31=11625,V,2333,56,S2,QPSK -32=11628,V,2333,56,S2,QPSK -33=11630,H,6666,78,DVB-S,QPSK -34=11631,V,2333,56,S2,QPSK -35=11634,V,2333,56,S2,QPSK -36=11636,H,3630,23,S2,8PSK -37=11642,V,2333,910,S2,8PSK -38=11648,H,6666,78,DVB-S,QPSK -39=11650,V,4610,34,S2,8PSK -40=11658,V,2333,56,S2,QPSK -41=11663,V,4666,56,S2,QPSK -42=11668,V,3656,34,S2,8PSK -43=11671,H,4444,34,DVB-S,QPSK -44=11672,V,3656,34,S2,8PSK -45=11676,V,1410,45,S2,QPSK -46=11678,V,1024,23,S2,8PSK -47=11679,H,6111,34,S2,8PSK -48=11679,V,1024,23,S2,8PSK -49=11680,V,1024,23,S2,8PSK -50=11683,V,2734,56,DVB-S,QPSK -51=11686,V,2750,34,S2,8PSK -52=11720,H,28200,56,S2,8PSK -53=11739,V,27500,23,S2,8PSK -54=11758,H,30000,Auto,S2,QPSK -55=11778,V,27500,910,S2,QPSK -56=11798,H,29500,34,S2,8PSK -57=11836,H,27500,56,DVB-S,QPSK -58=11856,V,27500,23,S2,8PSK -59=11876,H,29900,34,S2,8PSK -60=11895,V,27500,56,DVB-S,QPSK -61=11914,H,29900,23,S2,8PSK -62=11934,V,27500,34,S2,8PSK -63=11973,V,27500,56,DVB-S,QPSK -64=12032,H,27500,910,S2,QPSK -65=12070,H,27500,34,DVB-S,QPSK -66=12110,H,27500,34,S2,8PSK -67=12129,V,27500,23,S2,8PSK -68=12148,H,27500,56,S2,8PSK -69=12168,V,27500,34,DVB-S,QPSK -70=12188,H,27500,23,S2,8PSK -71=12207,V,27500,56,S2,8PSK -72=12304,H,27500,56,S2,8PSK -73=12344,H,27500,56,S2,8PSK -74=12363,V,29500,34,S2,8PSK -75=12382,H,30000,89,S2,8PSK -76=12402,V,30000,34,S2,8PSK -77=12525,H,27500,56,S2,8PSK -78=12525,V,27500,34,DVB-S,QPSK -79=12550,V,1663,56,S2,8PSK -80=12550,H,14400,34,S2,8PSK -81=12554,V,1666,56,S2,8PSK -82=12562,V,4937,34,S2,8PSK -83=12568,V,4937,34,S2,8PSK -84=12572,V,3300,78,DVB-S,QPSK -85=12576,V,3300,78,DVB-S,QPSK -86=12580,V,4937,34,S2,8PSK -87=12591,H,7200,34,S2,8PSK -88=12593,V,9600,34,S2,8PSK -89=12601,H,6666,78,DVB-S,QPSK -90=12608,V,4800,34,S2,8PSK -91=12609,H,6666,78,DVB-S,QPSK -92=12614,V,5000,56,S2,8PSK -93=12621,H,4936,34,S2,8PSK -94=12621,V,3750,34,S2,8PSK -95=12631,H,7200,34,S2,8PSK -96=12636,V,5000,34,S2,8PSK -97=12652,V,3333,34,S2,8PSK -98=12656,V,3600,34,S2,8PSK -99=12658,H,7200,34,S2,8PSK -100=12661,V,3600,34,S2,8PSK -101=12671,H,6666,78,DVB-S,QPSK -102=12674,V,3600,34,S2,8PSK -103=12677,V,2200,34,S2,8PSK -104=12680,V,2400,56,S2,8PSK -105=12680,H,6666,78,DVB-S,QPSK -106=12683,V,2400,56,S2,8PSK -107=12687,V,2400,56,S2,8PSK -108=12690,H,7200,34,S2,8PSK -109=12692,V,4800,34,S2,8PSK -110=12697,V,4800,34,S2,8PSK -111=12699,H,6666,78,S2,8PSK -112=12710,V,4800,34,S2,8PSK -113=12717,V,4800,34,S2,QPSK -114=12723,V,4800,34,S2,QPSK -115=12725,H,30000,89,S2,8PSK -116=12730,V,3600,34,S2,QPSK -117=12735,V,3600,34,S2,QPSK -118=12740,V,2400,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0255.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0255.ini deleted file mode 100644 index f72c91b41a..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0255.ini +++ /dev/null @@ -1,19 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0255 -2=Eutelsat 25B/Es'hail 1 (25.5E) - -[DVB] -0=10 -1=11046,H,27500,34,DVB-S,QPSK -2=11142,V,27500,34,DVB-S,QPSK -3=11547,V,27500,23,S2,8PSK -4=11566,H,27500,34,DVB-S,8PSK -5=11585,V,27500,23,S2,8PSK -6=11604,H,27500,34,DVB-S,QPSK -7=11623,V,27500,23,S2,8PSK -8=11642,H,27500,23,S2,8PSK -9=11678,H,27500,56,DVB-S,QPSK -10=21421,V,27500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0260.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0260.ini deleted file mode 100644 index 299779fb54..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0260.ini +++ /dev/null @@ -1,107 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0260 -2=Badr 4/5/6 (26.0E) - -[DVB] -0=98 -1=3958,V,12000,34,DVB-S,QPSK -2=10730,H,27500,34,DVB-S,QPSK -3=10730,V,27500,34,S2,8PSK -4=10770,H,27500,34,DVB-S,QPSK -5=10810,H,27500,34,DVB-S,QPSK -6=10810,V,27500,12,S2,8PSK -7=10850,H,27500,56,DVB-S,QPSK -8=10850,V,27500,34,DVB-S,QPSK -9=10890,H,27500,34,S2,8PSK -10=10890,V,27500,34,S2,8PSK -11=10930,H,27500,34,DVB-S,QPSK -12=10930,V,27500,34,S2,8PSK -13=11228,V,27500,34,DVB-S,QPSK -14=11557,H,2960,34,DVB-S,QPSK -15=11563,H,1500,34,DVB-S,QPSK -16=11727,H,27500,Auto,S2,8PSK -17=11747,V,27500,34,DVB-S,QPSK -18=11785,V,27500,34,DVB-S,QPSK -19=11804,H,27500,34,DVB-S,QPSK -20=11823,V,27500,12,S2,8PSK -21=11843,H,27500,34,DVB-S,QPSK -22=11862,V,27500,34,DVB-S,QPSK -23=11881,H,27500,56,S2,8PSK -24=11900,V,27500,34,DVB-S,QPSK -25=11919,H,27500,34,DVB-S,QPSK -26=11938,V,27500,34,DVB-S,QPSK -27=11958,H,27500,34,DVB-S,QPSK -28=11996,H,27500,34,DVB-S,QPSK -29=12015,V,27500,34,DVB-S,QPSK -30=12034,H,27500,34,DVB-S,QPSK -31=12054,V,27500,34,DVB-S,QPSK -32=12073,H,27500,34,DVB-S,QPSK -33=12092,V,27500,34,DVB-S,QPSK -34=12111,H,27500,34,DVB-S,QPSK -35=12130,V,27500,34,DVB-S,QPSK -36=12149,H,30000,56,S2,QPSK -37=12169,V,22000,34,S2,QPSK -38=12182,H,16200,34,DVB-S,QPSK -39=12207,V,27500,34,DVB-S,QPSK -40=12226,H,27500,34,DVB-S,QPSK -41=12245,V,27500,56,S2,QPSK -42=12265,H,27500,56,S2,QPSK -43=12284,V,27500,34,DVB-S,QPSK -44=12303,H,27500,34,DVB-S,QPSK -45=12322,V,27500,34,DVB-S,QPSK -46=12360,V,27500,34,DVB-S,QPSK -47=12399,V,27500,34,S2,8PSK -48=12418,H,27500,34,S2,8PSK -49=12437,V,27500,34,DVB-S,QPSK -50=12456,H,27500,34,DVB-S,QPSK -51=12476,V,27500,34,DVB-S,QPSK -52=12523,H,27500,34,DVB-S,QPSK -53=12547,H,2000,34,DVB-S,QPSK -54=12550,H,2950,34,DVB-S,QPSK -55=12550,V,7000,56,S2,8PSK -56=12558,V,7000,56,S2,8PSK -57=12559,H,2220,34,DVB-S,QPSK -58=12562,H,2220,34,DVB-S,QPSK -59=12565,H,2220,34,DVB-S,QPSK -60=12567,V,2200,34,DVB-S,QPSK -61=12568,H,1850,34,DVB-S,QPSK -62=12570,V,2200,34,DVB-S,QPSK -63=12570,H,1820,34,DVB-S,QPSK -64=12575,H,2200,56,DVB-S,QPSK -65=12576,V,7000,56,S2,8PSK -66=12579,H,2100,34,DVB-S,QPSK -67=12586,V,2220,34,DVB-S,QPSK -68=12587,H,2000,34,DVB-S,QPSK -69=12591,H,2200,34,DVB-S,QPSK -70=12591,V,2200,34,DVB-S,QPSK -71=12594,H,2200,34,DVB-S,QPSK -72=12600,V,7000,56,S2,QPSK -73=12602,H,2960,56,DVB-S,QPSK -74=12605,V,2220,34,DVB-S,QPSK -75=12607,H,3000,34,DVB-S,QPSK -76=12608,V,1820,34,DVB-S,QPSK -77=12611,V,2220,34,DVB-S,QPSK -78=12618,H,2220,34,DVB-S,QPSK -79=12620,V,2200,34,DVB-S,QPSK -80=12644,V,1850,34,DVB-S,QPSK -81=12647,H,2950,34,DVB-S,QPSK -82=12647,V,1595,34,S2,8PSK -83=12656,H,2892,34,DVB-S,QPSK -84=12666,H,2400,34,DVB-S,QPSK -85=12672,H,4440,34,DVB-S,QPSK -86=12679,H,2220,78,DVB-S,QPSK -87=12683,V,27500,34,DVB-S,QPSK -88=12705,H,2220,56,DVB-S,QPSK -89=12708,H,2220,56,DVB-S,QPSK -90=12711,H,2220,34,DVB-S,8PSK -91=12711,V,5632,34,DVB-S,QPSK -92=12717,V,2143,56,DVB-S,QPSK -93=12718,H,3000,56,DVB-S,QPSK -94=12722,H,3000,56,DVB-S,QPSK -95=12729,H,2200,34,DVB-S,QPSK -96=12734,H,3000,34,DVB-S,QPSK -97=12736,V,5632,34,DVB-S,QPSK -98=12740,H,2200,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0282.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0282.ini deleted file mode 100644 index 07c5ccebe7..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0282.ini +++ /dev/null @@ -1,101 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0282 -2=Astra 2E/2F/2G (28.2E) - -[DVB] -0=92 -1=10714,H,22000,56,DVB-S,QPSK -2=10729,V,22000,56,DVB-S,QPSK -3=10744,H,22000,56,DVB-S,QPSK -4=10758,V,22000,56,DVB-S,QPSK -5=10773,H,22000,56,DVB-S,QPSK -6=10788,V,22000,56,DVB-S,QPSK -7=10803,H,22000,56,DVB-S,QPSK -8=10818,V,22000,56,DVB-S,QPSK -9=10832,H,22000,56,DVB-S,QPSK -10=10847,V,23000,23,S2,8PSK -11=10862,H,23000,23,S2,8PSK -12=10876,V,22000,56,DVB-S,QPSK -13=10891,H,22000,56,DVB-S,QPSK -14=10906,V,22000,56,DVB-S,QPSK -15=10936,V,23000,23,S2,8PSK -16=10964,H,22000,56,DVB-S,QPSK -17=10994,H,22000,56,DVB-S,QPSK -18=11023,H,23000,23,S2,8PSK -19=11053,H,23000,34,S2,8PSK -20=11068,V,23000,23,S2,8PSK -21=11082,H,22000,56,DVB-S,QPSK -22=11097,V,23000,23,S2,8PSK -23=11112,H,22000,56,DVB-S,QPSK -24=11126,V,22000,56,DVB-S,QPSK -25=11141,H,22000,56,DVB-S,QPSK -26=11171,H,22000,56,DVB-S,QPSK -27=11224,H,27500,23,DVB-S,QPSK -28=11224,V,27500,23,DVB-S,QPSK -29=11264,V,27500,23,DVB-S,QPSK -30=11264,H,27500,23,DVB-S,QPSK -31=11306,V,27500,23,DVB-S,QPSK -32=11306,H,27500,23,DVB-S,QPSK -33=11344,V,27500,23,DVB-S,QPSK -34=11344,H,27500,23,DVB-S,QPSK -35=11386,V,27500,23,DVB-S,QPSK -36=11386,H,27500,23,DVB-S,QPSK -37=11426,H,27500,23,DVB-S,QPSK -38=11426,V,27500,23,DVB-S,QPSK -39=11464,H,22000,56,DVB-S,QPSK -40=11479,V,22000,56,DVB-S,QPSK -41=11509,V,22000,56,DVB-S,QPSK -42=11523,H,22000,56,DVB-S,QPSK -43=11538,V,23000,23,S2,8PSK -44=11553,H,22000,56,DVB-S,QPSK -45=11568,V,22000,56,DVB-S,QPSK -46=11582,H,22000,56,DVB-S,QPSK -47=11597,V,22000,56,DVB-S,QPSK -48=11618,V,1562,56,S2,QPSK -49=11671,H,22000,56,DVB-S,QPSK -50=11675,H,30000,56,S2,QPSK -51=11686,V,22000,56,DVB-S,QPSK -52=11720,H,29500,34,S2,QPSK -53=11739,V,29500,34,S2,QPSK -54=11758,H,29500,34,S2,QPSK -55=11798,H,29500,34,S2,QPSK -56=11817,V,27500,23,DVB-S,QPSK -57=11836,H,27500,56,DVB-S,QPSK -58=11856,V,29500,34,S2,QPSK -59=11876,H,27500,23,DVB-S,QPSK -60=11895,V,27500,23,DVB-S,QPSK -61=11914,H,27500,56,DVB-S,QPSK -62=11934,V,27500,56,DVB-S,QPSK -63=11954,H,27500,23,DVB-S,QPSK -64=11973,V,29500,34,S2,QPSK -65=11992,H,27500,23,DVB-S,QPSK -66=12012,V,29500,34,S2,QPSK -67=12051,V,27500,23,DVB-S,QPSK -68=12070,H,27500,56,DVB-S,QPSK -69=12090,V,29500,34,S2,QPSK -70=12110,H,27500,56,DVB-S,QPSK -71=12148,H,27500,56,DVB-S,QPSK -72=12168,V,29500,34,S2,QPSK -73=12188,H,27500,56,DVB-S,QPSK -74=12207,V,27500,56,DVB-S,QPSK -75=12226,H,29500,34,S2,QPSK -76=12246,V,29500,34,S2,QPSK -77=12266,H,27500,56,DVB-S,QPSK -78=12285,V,27500,23,DVB-S,QPSK -79=12324,V,29500,34,S2,QPSK -80=12344,H,29500,34,S2,QPSK -81=12363,V,29500,34,S2,QPSK -82=12441,V,29500,34,S2,QPSK -83=12460,H,29500,34,S2,QPSK -84=12480,V,27500,23,DVB-S,QPSK -85=12522,V,27000,Auto,DVB-S,QPSK -86=12573,H,6960,23,S2,QPSK -87=12581,V,7200,34,S2,8PSK -88=12582,H,6960,23,S2,QPSK -89=12603,V,3095,Auto,S2,QPSK -90=12683,H,6960,23,S2,8PSK -91=12692,H,6960,23,S2,8PSK -92=12699,H,4640,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0305.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0305.ini deleted file mode 100644 index 196196c956..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0305.ini +++ /dev/null @@ -1,96 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0305 -2=Arabsat 5A (30.5E) - -[DVB] -0=87 -1=3770,V,2200,34,DVB-S,QPSK -2=3820,V,2848,34,DVB-S,QPSK -3=3880,V,3888,78,DVB-S,QPSK -4=3884,V,3888,78,DVB-S,QPSK -5=3888,V,3888,78,DVB-S,QPSK -6=3947,V,2200,34,DVB-S,QPSK -7=3951,V,2220,34,DVB-S,QPSK -8=4061,V,1615,78,DVB-S,QPSK -9=4126,V,2892,34,DVB-S,QPSK -10=10717,H,2069,23,S2,8PSK -11=10721,H,4300,23,S2,8PSK -12=10727,H,4300,23,DVB-S,QPSK -13=10744,H,4300,23,DVB-S,QPSK -14=10749,H,3125,Auto,DVB-S,QPSK -15=10757,H,2220,34,DVB-S,QPSK -16=10760,H,2050,23,S2,8PSK -17=10765,H,1950,34,S2,QPSK -18=10770,H,1650,23,S2,8PSK -19=10777,H,2960,34,DVB-S,QPSK -20=10782,H,2960,34,DVB-S,QPSK -21=10797,H,8000,56,S2,8PSK -22=10805,H,3885,56,DVB-S,QPSK -23=10816,H,8000,56,DVB-S,QPSK -24=10827,H,5800,34,DVB-S,QPSK -25=10832,V,2780,56,DVB-S,QPSK -26=10858,V,2960,34,DVB-S,QPSK -27=10924,H,17000,34,DVB-S,QPSK -28=10940,H,8000,56,DVB-S,QPSK -29=10946,H,2400,78,DVB-S,QPSK -30=12503,V,2220,34,DVB-S,QPSK -31=12506,V,2220,34,DVB-S,QPSK -32=12507,H,2220,34,DVB-S,QPSK -33=12509,V,2222,34,DVB-S,QPSK -34=12511,V,2200,34,DVB-S,QPSK -35=12514,V,2220,34,DVB-S,QPSK -36=12516,H,2230,34,DVB-S,QPSK -37=12523,V,6000,Auto,DVB-S,QPSK -38=12533,V,3890,34,DVB-S,QPSK -39=12538,V,2690,34,DVB-S,QPSK -40=12539,H,2960,34,DVB-S,QPSK -41=12543,V,2410,34,S2,8PSK -42=12559,H,2963,34,DVB-S,QPSK -43=12568,H,2960,Auto,DVB-S,QPSK -44=12576,H,1613,Auto,S2,QPSK -45=12588,H,3000,34,DVB-S,QPSK -46=12593,H,2960,34,DVB-S,QPSK -47=12596,H,2220,34,DVB-S,QPSK -48=12596,V,1800,78,DVB-S,QPSK -49=12603,V,3300,34,DVB-S,QPSK -50=12607,V,2590,56,DVB-S,QPSK -51=12608,H,2200,34,DVB-S,QPSK -52=12610,V,2970,34,DVB-S,QPSK -53=12611,H,3000,34,DVB-S,QPSK -54=12614,H,2200,34,DVB-S,QPSK -55=12614,V,3820,89,S2,QPSK -56=12618,H,2960,34,DVB-S,QPSK -57=12621,V,3800,34,S2,8PSK -58=12624,V,2220,34,DVB-S,QPSK -59=12630,V,2893,34,DVB-S,QPSK -60=12634,V,2893,34,DVB-S,QPSK -61=12638,V,2894,34,DVB-S,QPSK -62=12641,V,2894,34,DVB-S,QPSK -63=12644,V,2894,34,DVB-S,QPSK -64=12647,H,2960,34,DVB-S,QPSK -65=12648,V,2894,34,DVB-S,QPSK -66=12651,H,3885,34,DVB-S,QPSK -67=12652,V,2893,34,DVB-S,QPSK -68=12655,H,2410,34,DVB-S,QPSK -69=12656,V,1660,56,S2,8PSK -70=12667,H,4112,34,DVB-S,QPSK -71=12667,V,2220,34,DVB-S,QPSK -72=12671,V,2600,34,DVB-S,QPSK -73=12675,V,4300,34,DVB-S,QPSK -74=12679,V,3000,34,DVB-S,QPSK -75=12685,V,4300,34,DVB-S,QPSK -76=12697,V,4300,34,DVB-S,QPSK -77=12708,V,2590,34,DVB-S,QPSK -78=12712,H,2220,34,DVB-S,QPSK -79=12713,V,1850,34,DVB-S,QPSK -80=12716,V,2600,34,DVB-S,QPSK -81=12719,H,2960,34,DVB-S,QPSK -82=12719,V,3000,34,DVB-S,QPSK -83=12722,H,2200,34,DVB-S,QPSK -84=12724,V,2220,34,DVB-S,QPSK -85=12732,V,2000,78,DVB-S,QPSK -86=12733,H,2960,34,DVB-S,QPSK -87=12737,H,2220,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0308.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0308.ini deleted file mode 100644 index fe4f41569b..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0308.ini +++ /dev/null @@ -1,30 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0308 -2=Eutelsat 31A (30.8E) - -[DVB] -0=21 -1=10960,H,3330,78,DVB-S,QPSK -2=10965,H,3330,78,DVB-S,QPSK -3=10970,H,3330,78,DVB-S,QPSK -4=10975,H,3330,78,DVB-S,QPSK -5=10979,H,3330,78,DVB-S,QPSK -6=10984,H,3330,56,DVB-S,QPSK -7=10988,H,3330,78,DVB-S,QPSK -8=10992,H,3330,78,DVB-S,QPSK -9=11004,H,7500,34,S2,8PSK -10=11011,H,3330,56,DVB-S,QPSK -11=11015,H,3330,78,DVB-S,QPSK -12=11019,H,3330,78,DVB-S,QPSK -13=11024,H,3330,78,DVB-S,QPSK -14=11044,H,21000,56,S2,QPSK -15=11560,H,21000,56,S2,8PSK -16=11622,H,2300,56,DVB-S,QPSK -17=11624,H,2200,56,DVB-S,QPSK -18=11627,H,2300,56,DVB-S,QPSK -19=11630,H,2222,56,DVB-S,QPSK -20=11644,H,2300,910,S2,8PSK -21=11651,H,7500,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0310.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0310.ini deleted file mode 100644 index be556fdd2b..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0310.ini +++ /dev/null @@ -1,10 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0310 -2=Hylas 2 (31.0E) - -[DVB] -0=1 -1=20036,H,10000,12,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0315.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0315.ini deleted file mode 100644 index 6581c91691..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0315.ini +++ /dev/null @@ -1,24 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0315 -2=Astra 5B (31.5E) - -[DVB] -0=15 -1=11758,H,27500,34,DVB-S,QPSK -2=11817,V,27500,34,DVB-S,QPSK -3=11934,V,30000,23,S2,8PSK -4=11954,H,27500,56,S2,8PSK -5=11973,V,27500,56,S2,8PSK -6=12012,V,30000,34,S2,8PSK -7=12070,H,30000,34,S2,8PSK -8=12090,V,30000,34,S2,8PSK -9=12168,V,30000,34,S2,8PSK -10=12207,V,27500,56,S2,8PSK -11=12246,V,30000,34,S2,8PSK -12=12266,H,27500,56,S2,8PSK -13=12324,V,30000,34,S2,8PSK -14=12402,V,30000,34,S2,8PSK -15=12480,V,30000,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0330.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0330.ini deleted file mode 100644 index b395913cc6..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0330.ini +++ /dev/null @@ -1,47 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0330 -2=Eutelsat 33B/33C/Intelsat 28 (33.0E) - -[DVB] -0=38 -1=10968,V,6665,45,S2,QPSK -2=10975,H,30000,910,S2,QPSK -3=10976,V,6665,45,S2,QPSK -4=11043,H,7200,34,S2,8PSK -5=11052,H,7200,56,S2,8PSK -6=11072,H,3333,78,DVB-S,QPSK -7=11077,H,3750,34,S2,8PSK -8=11094,H,3000,34,S2,8PSK -9=11098,H,2960,56,DVB-S,QPSK -10=11101,H,2222,56,DVB-S,QPSK -11=11105,H,3333,34,S2,8PSK -12=11154,V,15710,12,DVB-S,QPSK -13=11429,V,10098,35,S2,QPSK -14=11457,V,1704,56,S2,8PSK -15=11461,V,2000,78,DVB-S,QPSK -16=11467,V,3600,34,S2,8PSK -17=11471,V,3820,34,S2,8PSK -18=11475,V,3820,34,S2,8PSK -19=11476,H,3820,34,S2,8PSK -20=11580,H,2478,23,S2,8PSK -21=11583,H,2478,23,S2,8PSK -22=11593,H,15710,12,DVB-S,QPSK -23=11605,V,3333,56,S2,8PSK -24=11608,H,3810,56,S2,8PSK -25=12630,V,2400,35,S2,8PSK -26=12634,V,4800,34,S2,8PSK -27=12640,V,2400,23,S2,8PSK -28=12643,V,2400,23,S2,8PSK -29=12646,V,4800,34,S2,8PSK -30=12650,V,2400,23,S2,8PSK -31=12653,V,2400,23,S2,8PSK -32=12656,V,2400,23,S2,8PSK -33=12684,V,2050,56,S2,8PSK -34=12691,V,2222,78,DVB-S,QPSK -35=12698,V,3333,34,DVB-S,QPSK -36=12722,V,16730,34,S2,QPSK -37=12736,V,4444,34,DVB-S,QPSK -38=12742,V,4444,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0360.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0360.ini deleted file mode 100644 index 49042dfb7c..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0360.ini +++ /dev/null @@ -1,111 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0360 -2=Eutelsat 36A/36B (36.0E) - -[DVB] -0=102 -1=11053,V,2894,34,DVB-S,QPSK -2=11057,V,2894,34,DVB-S,QPSK -3=11212,H,14400,35,S2,8PSK -4=11221,V,30000,56,S2,QPSK -5=11263,V,30000,56,S2,QPSK -6=11304,V,30000,56,S2,QPSK -7=11346,V,30000,56,S2,QPSK -8=11387,V,30000,56,S2,QPSK -9=11429,V,30000,56,S2,QPSK -10=11429,H,2893,34,DVB-S,QPSK -11=11442,H,2500,56,S2,8PSK -12=11474,V,30000,56,DVB-S,QPSK -13=11481,V,2200,34,S2,8PSK -14=11510,V,30000,56,DVB-S,QPSK -15=11590,V,2524,35,S2,QPSK -16=11593,V,2524,35,S2,QPSK -17=11727,H,27500,34,S2,8PSK -18=11727,V,27500,34,DVB-S,QPSK -19=11747,H,27500,34,DVB-S,QPSK -20=11747,V,27500,34,S2,8PSK -21=11766,V,27500,34,DVB-S,QPSK -22=11766,H,27500,34,S2,8PSK -23=11785,H,27500,34,DVB-S,QPSK -24=11785,V,27500,34,DVB-S,QPSK -25=11804,V,27500,34,S2,8PSK -26=11804,H,27500,34,S2,8PSK -27=11823,H,27500,34,DVB-S,QPSK -28=11823,V,27500,34,S2,8PSK -29=11843,V,27500,34,DVB-S,QPSK -30=11843,H,27500,34,S2,8PSK -31=11862,H,27500,34,DVB-S,QPSK -32=11862,V,27500,34,DVB-S,QPSK -33=11881,V,27500,34,DVB-S,QPSK -34=11881,H,27500,34,DVB-S,QPSK -35=11900,H,26480,12,DVB-S,QPSK -36=11900,V,27500,34,DVB-S,QPSK -37=11919,V,27500,34,S2,8PSK -38=11919,H,27500,34,S2,8PSK -39=11938,V,27500,34,S2,8PSK -40=11940,H,27500,34,DVB-S,QPSK -41=11958,V,27500,34,DVB-S,QPSK -42=11958,H,27500,34,S2,8PSK -43=11977,H,27500,34,DVB-S,QPSK -44=11977,V,27500,34,DVB-S,QPSK -45=11996,V,27500,34,S2,8PSK -46=11996,H,27500,34,S2,8PSK -47=12015,H,27500,34,DVB-S,QPSK -48=12015,V,27500,34,S2,8PSK -49=12034,V,27500,34,DVB-S,QPSK -50=12034,H,27500,34,S2,8PSK -51=12054,H,27500,34,DVB-S,QPSK -52=12054,V,27500,34,S2,8PSK -53=12073,H,27500,34,S2,8PSK -54=12073,V,27500,34,DVB-S,QPSK -55=12092,H,27500,23,S2,8PSK -56=12092,V,27500,34,DVB-S,QPSK -57=12111,H,27500,34,S2,8PSK -58=12130,V,27500,34,S2,8PSK -59=12149,H,27500,34,S2,8PSK -60=12169,V,27500,34,S2,8PSK -61=12174,H,4340,34,DVB-S,QPSK -62=12190,H,20000,34,DVB-S,QPSK -63=12207,V,27500,34,S2,8PSK -64=12226,H,27500,34,DVB-S,QPSK -65=12245,V,27500,34,DVB-S,QPSK -66=12245,H,27500,34,DVB-S,QPSK -67=12265,H,27500,34,DVB-S,QPSK -68=12284,V,27500,34,DVB-S,QPSK -69=12303,H,27500,34,DVB-S,QPSK -70=12322,V,27500,34,DVB-S,QPSK -71=12322,H,23437,34,DVB-S,QPSK -72=12341,H,27500,34,DVB-S,QPSK -73=12360,V,27500,34,S2,8PSK -74=12360,H,26480,12,DVB-S,QPSK -75=12380,H,27500,34,DVB-S,QPSK -76=12399,V,27500,34,DVB-S,QPSK -77=12418,H,27500,34,S2,8PSK -78=12437,V,27500,34,S2,8PSK -79=12440,H,23437,23,DVB-S,QPSK -80=12456,H,27500,34,DVB-S,QPSK -81=12476,V,27500,34,DVB-S,QPSK -82=12476,H,26040,23,DVB-S,QPSK -83=12511,H,4340,12,DVB-S,QPSK -84=12520,H,4340,12,DVB-S,QPSK -85=12522,V,1346,34,DVB-S,QPSK -86=12540,V,2220,34,DVB-S,QPSK -87=12557,V,1346,34,S2,QPSK -88=12563,H,7120,34,DVB-S,QPSK -89=12571,H,2894,34,DVB-S,QPSK -90=12572,V,1786,34,S2,8PSK -91=12575,H,2894,34,DVB-S,QPSK -92=12608,V,6200,34,S2,QPSK -93=12629,H,3444,34,S2,8PSK -94=12654,V,1800,78,DVB-S,QPSK -95=12689,V,2170,34,DVB-S,QPSK -96=12693,V,2532,34,DVB-S,QPSK -97=12699,V,6000,34,DVB-S,QPSK -98=12703,V,2200,78,DVB-S,QPSK -99=12706,V,1800,78,DVB-S,QPSK -100=12709,V,2200,78,DVB-S,QPSK -101=12713,V,1800,78,DVB-S,QPSK -102=12716,V,1800,78,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0380.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0380.ini deleted file mode 100644 index 25b53cd3d8..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0380.ini +++ /dev/null @@ -1,79 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0380 -2=Paksat 1R (38.0E) - -[DVB] -0=70 -1=3715,V,7200,34,DVB-S,QPSK -2=3732,V,18000,89,S2,QPSK -3=3762,V,4340,34,DVB-S,QPSK -4=3770,V,7700,78,DVB-S,QPSK -5=3775,V,1004,34,DVB-S,QPSK -6=3782,V,2170,34,DVB-S,QPSK -7=3800,V,7300,34,DVB-S,QPSK -8=3806,V,1444,34,S2,QPSK -9=3818,V,2200,34,DVB-S,QPSK -10=3824,V,2800,34,DVB-S,QPSK -11=3830,H,2000,34,DVB-S,QPSK -12=3833,V,2600,34,DVB-S,QPSK -13=3856,V,2894,34,DVB-S,QPSK -14=3860,V,3333,34,DVB-S,QPSK -15=3865,V,2894,34,DVB-S,QPSK -16=3959,V,7234,34,DVB-S,QPSK -17=3966,V,2800,34,DVB-S,QPSK -18=3973,V,6510,34,DVB-S,QPSK -19=3976,H,1750,34,DVB-S,QPSK -20=3979,V,3255,34,DVB-S,QPSK -21=3981,H,2222,34,DVB-S,QPSK -22=3984,V,2893,34,DVB-S,QPSK -23=3992,V,2170,56,DVB-S,QPSK -24=4003,V,15550,34,DVB-S,QPSK -25=4005,H,13845,78,DVB-S,QPSK -26=4013,V,2893,34,DVB-S,QPSK -27=4023,V,5700,35,S2,8PSK -28=4031,V,1078,34,DVB-S,QPSK -29=4037,V,4800,56,S2,QPSK -30=4042,V,2800,34,S2,QPSK -31=4047,V,3255,34,DVB-S,QPSK -32=4054,V,7000,34,DVB-S,QPSK -33=4060,H,23000,56,DVB-S,QPSK -34=4060,V,2893,34,DVB-S,QPSK -35=4073,V,6150,34,S2,QPSK -36=4081,V,3255,34,DVB-S,QPSK -37=4085,V,2960,34,DVB-S,QPSK -38=4090,V,3330,34,DVB-S,QPSK -39=4093,V,2527,34,DVB-S,QPSK -40=4098,H,1600,34,DVB-S,QPSK -41=4101,V,2800,34,DVB-S,QPSK -42=4105,V,2310,56,DVB-S,QPSK -43=4114,V,5700,34,DVB-S,QPSK -44=4124,V,5000,34,DVB-S,QPSK -45=4130,V,2500,34,DVB-S,QPSK -46=4133,V,2220,89,S2,QPSK -47=4135,H,3330,34,DVB-S,QPSK -48=4141,V,2800,34,DVB-S,QPSK -49=4158,V,12000,34,DVB-S,QPSK -50=4168,V,2800,34,DVB-S,QPSK -51=4172,V,2800,34,DVB-S,QPSK -52=4180,V,2170,34,DVB-S,QPSK -53=4184,V,2800,34,S2,QPSK -54=4188,V,2170,34,DVB-S,QPSK -55=10971,V,1000,56,S2,8PSK -56=10972,V,1000,56,S2,8PSK -57=10990,V,1650,34,DVB-S,QPSK -58=10992,V,1500,34,DVB-S,QPSK -59=11103,V,3012,34,DVB-S,QPSK -60=11122,V,1808,34,DVB-S,QPSK -61=11124,V,1300,34,DVB-S,QPSK -62=11150,V,3760,34,DVB-S,QPSK -63=11167,V,3000,78,DVB-S,QPSK -64=11184,V,2000,34,DVB-S,QPSK -65=11188,V,2000,34,DVB-S,QPSK -66=11191,V,2000,34,DVB-S,QPSK -67=12652,V,2050,34,DVB-S,QPSK -68=12687,V,2170,78,DVB-S,QPSK -69=12691,V,3333,34,DVB-S,QPSK -70=12696,V,3333,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0390.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0390.ini deleted file mode 100644 index e779197537..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0390.ini +++ /dev/null @@ -1,60 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0390 -2=Hellas Sat 2 (39.0E) - -[DVB] -0=51 -1=10955,V,4444,34,S2,8PSK -2=10960,V,1852,34,DVB-S,QPSK -3=10968,V,4400,34,DVB-S,QPSK -4=10972,V,3300,34,DVB-S,QPSK -5=10977,V,3300,34,DVB-S,QPSK -6=10981,V,3300,34,DVB-S,QPSK -7=10987,V,3333,78,DVB-S,QPSK -8=11012,V,30000,34,S2,8PSK -9=11053,V,30000,34,S2,8PSK -10=11078,V,3333,34,DVB-S,QPSK -11=11083,V,4400,34,DVB-S,QPSK -12=11091,V,1666,34,DVB-S,QPSK -13=11097,H,6111,34,DVB-S,QPSK -14=11104,V,14400,34,DVB-S,QPSK -15=11135,V,30000,23,S2,8PSK -16=11464,H,3224,78,DVB-S,QPSK -17=11473,H,4444,34,S2,8PSK -18=11479,H,3190,56,DVB-S,QPSK -19=11482,H,2905,34,DVB-S,QPSK -20=11486,H,2509,56,S2,8PSK -21=11496,H,2960,34,DVB-S,QPSK -22=11500,H,2960,23,S2,8PSK -23=11503,H,2200,56,DVB-S,QPSK -24=11507,H,2220,34,DVB-S,QPSK -25=11559,H,1950,23,S2,8PSK -26=11565,H,2250,34,DVB-S,QPSK -27=11608,H,2100,34,DVB-S,QPSK -28=11611,H,2100,34,DVB-S,QPSK -29=11618,H,2500,78,DVB-S,QPSK -30=11622,H,2800,56,DVB-S,QPSK -31=11624,V,3255,34,DVB-S,QPSK -32=11625,H,3333,34,DVB-S,QPSK -33=11628,H,2800,56,DVB-S,QPSK -34=11632,H,2800,56,DVB-S,QPSK -35=11649,H,4433,34,DVB-S,QPSK -36=11663,H,5925,34,DVB-S,QPSK -37=11670,H,3720,34,DVB-S,QPSK -38=11679,H,3700,56,DVB-S,QPSK -39=11685,H,3700,34,DVB-S,QPSK -40=11692,H,2300,78,DVB-S,QPSK -41=12524,V,30000,78,DVB-S,QPSK -42=12524,H,30000,78,DVB-S,QPSK -43=12565,V,30000,78,DVB-S,QPSK -44=12565,H,30000,78,DVB-S,QPSK -45=12606,V,30000,78,DVB-S,QPSK -46=12606,H,30000,78,DVB-S,QPSK -47=12647,V,30000,78,DVB-S,QPSK -48=12647,H,30000,34,S2,8PSK -49=12688,V,30000,78,DVB-S,QPSK -50=12688,H,30000,78,DVB-S,QPSK -51=12729,V,30000,78,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0400.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0400.ini deleted file mode 100644 index c1a56c8458..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0400.ini +++ /dev/null @@ -1,30 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0400 -2=Express AM7 (40.0E) - -[DVB] -0=21 -1=3557,V,2894,78,DVB-S,QPSK -2=3558,H,3720,34,S2,8PSK -3=3561,V,2905,34,DVB-S,QPSK -4=3563,H,3600,34,S2,8PSK -5=3565,V,2896,34,DVB-S,QPSK -6=3566,H,1850,34,S2,8PSK -7=3569,V,2905,34,DVB-S,QPSK -8=3573,V,2896,34,DVB-S,QPSK -9=3577,V,2905,34,DVB-S,QPSK -10=3581,V,2894,34,DVB-S,QPSK -11=3585,V,2905,34,DVB-S,QPSK -12=3589,V,2905,34,DVB-S,QPSK -13=3592,V,2894,34,DVB-S,QPSK -14=3615,V,14990,34,S2,8PSK -15=3635,V,15280,34,S2,8PSK -16=3665,H,14990,34,S2,8PSK -17=3675,V,33483,78,DVB-S,QPSK -18=3685,H,15284,34,S2,8PSK -19=3725,H,28108,35,S2,QPSK -20=3739,V,1922,78,DVB-S,QPSK -21=3742,V,2893,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0420.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0420.ini deleted file mode 100644 index 3d884a86bd..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0420.ini +++ /dev/null @@ -1,199 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0420 -2=Trksat 2A/3A/4A (42.0E) - -[DVB] -0=190 -1=10962,H,16666,34,DVB-S,QPSK -2=10970,V,30000,56,S2,8PSK -3=10974,H,2660,56,S2,8PSK -4=10978,H,2660,56,S2,8PSK -5=10982,H,2660,56,S2,8PSK -6=10986,H,2660,56,S2,8PSK -7=10997,H,3333,56,DVB-S,QPSK -8=11001,H,3200,34,DVB-S,QPSK -9=11006,H,2222,56,DVB-S,QPSK -10=11012,V,30000,56,DVB-S,QPSK -11=11014,H,9600,34,DVB-S,QPSK -12=11021,H,2222,34,DVB-S,QPSK -13=11027,H,2222,56,DVB-S,QPSK -14=11031,H,2222,56,DVB-S,QPSK -15=11039,H,4800,23,S2,8PSK -16=11045,H,4800,34,DVB-S,QPSK -17=11053,H,8000,34,DVB-S,QPSK -18=11054,V,30000,34,S2,8PSK -19=11062,H,4820,34,DVB-S,QPSK -20=11068,H,2400,56,DVB-S,QPSK -21=11071,H,2200,56,DVB-S,QPSK -22=11096,V,30000,56,DVB-S,QPSK -23=11096,H,30000,56,DVB-S,QPSK -24=11128,H,3150,56,S2,QPSK -25=11137,H,2960,56,DVB-S,QPSK -26=11138,V,13000,12,S2,QPSK -27=11142,H,2221,56,DVB-S,QPSK -28=11146,H,3330,Auto,DVB-S,QPSK -29=11152,H,2222,Auto,DVB-S,QPSK -30=11156,V,2222,56,DVB-S,QPSK -31=11157,H,3180,56,DVB-S,QPSK -32=11161,V,2222,56,DVB-S,QPSK -33=11161,H,3180,56,DVB-S,QPSK -34=11165,H,3180,56,DVB-S,QPSK -35=11169,V,3333,56,DVB-S,QPSK -36=11169,H,3180,56,DVB-S,QPSK -37=11173,H,3180,56,DVB-S,QPSK -38=11174,V,2200,Auto,DVB-S,QPSK -39=11177,H,2222,56,DVB-S,QPSK -40=11178,V,3600,56,DVB-S,QPSK -41=11180,H,2960,56,S2,8PSK -42=11183,V,2222,56,DVB-S,QPSK -43=11187,H,2080,56,DVB-S,QPSK -44=11191,H,2070,78,DVB-S,QPSK -45=11195,H,4000,56,S2,8PSK -46=11196,V,3200,56,DVB-S,QPSK -47=11458,V,3200,34,S2,8PSK -48=11462,V,3200,34,S2,8PSK -49=11466,V,3200,34,S2,8PSK -50=11470,V,3200,34,S2,8PSK -51=11472,H,23450,56,DVB-S,QPSK -52=11473,V,3200,34,S2,8PSK -53=11477,V,3200,34,S2,8PSK -54=11480,V,3200,34,S2,8PSK -55=11486,V,3200,34,S2,8PSK -56=11490,V,3200,56,DVB-S,QPSK -57=11496,V,2960,56,DVB-S,QPSK -58=11500,V,2222,56,DVB-S,QPSK -59=11504,V,3200,56,DVB-S,QPSK -60=11509,H,30000,23,DVB-S,QPSK -61=11518,V,2222,Auto,DVB-S,QPSK -62=11521,V,2222,Auto,DVB-S,QPSK -63=11524,V,2222,Auto,DVB-S,QPSK -64=11528,V,2960,Auto,DVB-S,QPSK -65=11540,H,3600,56,DVB-S,QPSK -66=11545,H,4425,56,DVB-S,QPSK -67=11550,H,2110,56,S2,QPSK -68=11558,V,30000,23,DVB-S,QPSK -69=11566,H,3200,56,S2,QPSK -70=11573,H,1800,56,DVB-S,QPSK -71=11574,V,2222,56,DVB-S,QPSK -72=11577,H,2222,Auto,DVB-S,QPSK -73=11594,V,25000,23,DVB-S,QPSK -74=11596,H,22000,34,S2,QPSK -75=11622,V,2960,56,DVB-S,QPSK -76=11624,V,2222,56,DVB-S,QPSK -77=11624,H,2960,56,DVB-S,QPSK -78=11626,V,2300,56,DVB-S,QPSK -79=11627,H,4444,56,DVB-S,QPSK -80=11633,V,2222,78,DVB-S,QPSK -81=11637,V,2222,56,DVB-S,QPSK -82=11642,V,2220,56,DVB-S,QPSK -83=11647,H,3333,Auto,DVB-S,QPSK -84=11649,V,2960,Auto,DVB-S,QPSK -85=11651,H,2222,56,DVB-S,QPSK -86=11652,V,2222,56,DVB-S,QPSK -87=11656,V,3200,56,DVB-S,QPSK -88=11660,H,7500,34,S2,8PSK -89=11667,H,2960,56,DVB-S,QPSK -90=11675,H,2222,Auto,DVB-S,QPSK -91=11676,V,24444,34,DVB-S,QPSK -92=11680,H,1666,23,DVB-S,QPSK -93=11683,H,2222,56,DVB-S,QPSK -94=11691,H,2222,56,DVB-S,QPSK -95=11691,V,2222,56,DVB-S,QPSK -96=11727,V,27000,56,DVB-S,QPSK -97=11746,H,27500,56,DVB-S,QPSK -98=11775,V,27500,34,S2,8PSK -99=11794,H,27500,56,DVB-S,QPSK -100=11797,V,8800,56,DVB-S,QPSK -101=11807,V,8000,34,S2,8PSK -102=11821,H,17000,34,DVB-S,QPSK -103=11824,V,8000,34,DVB-S,QPSK -104=11853,H,25000,23,S2,8PSK -105=11855,V,30000,34,DVB-S,QPSK -106=11880,H,20000,23,S2,8PSK -107=11883,V,4800,56,DVB-S,QPSK -108=11916,V,30000,34,DVB-S,QPSK -109=11958,V,27500,56,DVB-S,QPSK -110=11977,H,27500,56,DVB-S,QPSK -111=11986,V,9600,56,DVB-S,QPSK -112=11999,V,11666,23,S2,8PSK -113=12009,V,4444,34,DVB-S,QPSK -114=12015,H,27500,56,DVB-S,QPSK -115=12034,V,27500,56,DVB-S,QPSK -116=12054,H,27500,56,DVB-S,QPSK -117=12073,V,27500,56,S2,8PSK -118=12079,H,6400,56,DVB-S,QPSK -119=12086,H,2960,56,DVB-S,QPSK -120=12090,H,2960,56,DVB-S,QPSK -121=12095,H,4800,56,DVB-S,QPSK -122=12103,H,8333,23,S2,8PSK -123=12123,H,15000,34,S2,8PSK -124=12130,V,27500,56,DVB-S,QPSK -125=12188,V,27500,56,DVB-S,QPSK -126=12196,H,9600,23,S2,8PSK -127=12209,H,10000,34,S2,8PSK -128=12213,V,5833,23,S2,8PSK -129=12219,H,6500,34,DVB-S,QPSK -130=12220,V,4800,56,DVB-S,QPSK -131=12228,V,8400,56,DVB-S,QPSK -132=12238,V,7200,56,DVB-S,QPSK -133=12245,H,27500,56,S2,8PSK -134=12265,V,27500,56,DVB-S,QPSK -135=12303,V,27500,56,DVB-S,QPSK -136=12329,H,6666,23,S2,8PSK -137=12336,H,5520,34,DVB-S,QPSK -138=12344,V,30000,34,DVB-S,QPSK -139=12346,H,9600,34,DVB-S,QPSK -140=12356,H,7100,23,S2,8PSK -141=12379,H,30000,34,DVB-S,QPSK -142=12380,V,27500,34,DVB-S,QPSK -143=12422,V,27500,34,DVB-S,QPSK -144=12422,H,30000,34,DVB-S,QPSK -145=12442,H,2963,78,DVB-S,QPSK -146=12447,H,2400,34,DVB-S,QPSK -147=12455,H,10800,23,S2,8PSK -148=12458,V,30000,34,DVB-S,QPSK -149=12509,H,3333,56,DVB-S,QPSK -150=12513,H,2215,56,DVB-S,QPSK -151=12516,H,2222,56,DVB-S,QPSK -152=12519,H,2222,56,DVB-S,QPSK -153=12524,V,22500,23,DVB-S,QPSK -154=12540,H,30000,34,DVB-S,QPSK -155=12559,V,27500,23,DVB-S,QPSK -156=12562,H,2960,56,S2,8PSK -157=12576,H,2090,78,DVB-S,QPSK -158=12578,H,2222,56,DVB-S,QPSK -159=12588,V,22500,34,DVB-S,QPSK -160=12588,H,3200,56,S2,8PSK -161=12595,H,4800,56,S2,8PSK -162=12605,V,27500,23,DVB-S,QPSK -163=12606,H,2222,78,DVB-S,QPSK -164=12611,H,5924,56,DVB-S,QPSK -165=12617,H,3333,56,DVB-S,QPSK -166=12620,V,2244,56,DVB-S,QPSK -167=12621,H,3333,56,DVB-S,QPSK -168=12624,V,2170,56,DVB-S,QPSK -169=12627,V,2278,78,DVB-S,QPSK -170=12632,V,2220,78,DVB-S,8PSK -171=12635,V,2240,56,S2,8PSK -172=12639,V,5000,56,S2,8PSK -173=12641,H,30000,23,DVB-S,QPSK -174=12646,V,4000,56,S2,8PSK -175=12651,V,5000,34,S2,8PSK -176=12658,V,2222,56,DVB-S,QPSK -177=12673,V,9600,34,DVB-S,QPSK -178=12685,H,30000,34,DVB-S,QPSK -179=12687,V,11400,34,DVB-S,QPSK -180=12699,V,7700,56,S2,QPSK -181=12711,V,2278,78,DVB-S,QPSK -182=12714,V,2960,56,DVB-S,QPSK -183=12718,V,2278,56,DVB-S,QPSK -184=12721,V,2278,78,DVB-S,QPSK -185=12723,V,2222,56,DVB-S,QPSK -186=12728,V,2222,56,DVB-S,QPSK -187=12729,H,27500,23,DVB-S,QPSK -188=12731,V,2222,56,DVB-S,QPSK -189=12746,V,2222,56,DVB-S,QPSK -190=18669,H,22500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0435.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0435.ini deleted file mode 100644 index a7e5fdb799..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0435.ini +++ /dev/null @@ -1,35 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0435 -2=Astra 2G (43.5E) - -[DVB] -0=26 -1=10964,H,22000,56,DVB-S,QPSK -2=10994,H,22000,56,DVB-S,QPSK -3=11023,H,23000,23,S2,8PSK -4=11053,H,23000,34,S2,8PSK -5=11068,V,23000,23,S2,8PSK -6=11082,H,22000,56,DVB-S,QPSK -7=11097,V,23000,23,S2,8PSK -8=11112,H,22000,56,DVB-S,QPSK -9=11126,V,22000,56,DVB-S,QPSK -10=11141,H,22000,56,DVB-S,QPSK -11=11171,H,22000,56,DVB-S,QPSK -12=11224,V,27500,23,DVB-S,QPSK -13=11224,H,27500,23,DVB-S,QPSK -14=11264,V,27500,23,DVB-S,QPSK -15=11264,H,27500,23,DVB-S,QPSK -16=11464,H,22000,56,DVB-S,QPSK -17=11479,V,22000,56,DVB-S,QPSK -18=11509,V,22000,56,DVB-S,QPSK -19=11523,H,22000,56,DVB-S,QPSK -20=11538,V,23000,23,S2,8PSK -21=11553,H,22000,56,DVB-S,QPSK -22=11568,V,22000,56,DVB-S,QPSK -23=11582,H,22000,56,DVB-S,QPSK -24=11597,V,22000,56,DVB-S,QPSK -25=11671,H,22000,56,DVB-S,QPSK -26=11686,V,22000,56,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0450.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0450.ini deleted file mode 100644 index 0737fb4f18..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0450.ini +++ /dev/null @@ -1,23 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0450 -2=Intelsat 12 (45.0E) - -[DVB] -0=14 -1=11451,H,3254,78,DVB-S,QPSK -2=11468,V,27689,56,DVB-S,8PSK -3=11493,V,2960,78,DVB-S,QPSK -4=11506,V,1808,34,DVB-S,QPSK -5=11509,V,10000,23,S2,8PSK -6=11517,V,2960,78,DVB-S,QPSK -7=11523,V,5787,34,DVB-S,QPSK -8=11550,V,28800,35,S2,8PSK -9=11591,V,27689,56,DVB-S,8PSK -10=11632,V,27689,56,DVB-S,8PSK -11=11673,V,27689,56,DVB-S,8PSK -12=12518,H,14236,34,S2,8PSK -13=12568,V,8335,23,S2,8PSK -14=12580,H,6600,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0460.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0460.ini deleted file mode 100644 index 7611715ec8..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0460.ini +++ /dev/null @@ -1,49 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0460 -2=AzerSpace 1/Africasat 1a (46.0E) - -[DVB] -0=40 -1=3730,V,30000,34,S2,8PSK -2=3753,V,30000,23,S2,8PSK -3=3833,V,1077,23,S2,8PSK -4=3953,V,1180,34,S2,8PSK -5=4016,V,1200,34,S2,8PSK -6=4021,V,1180,34,S2,8PSK -7=4024,V,1190,34,S2,8PSK -8=4026,V,1200,34,S2,8PSK -9=4028,V,1166,34,S2,8PSK -10=4105,H,1320,56,S2,QPSK -11=4145,H,6666,23,DVB-S,QPSK -12=10961,V,7500,23,S2,8PSK -13=10968,V,5000,23,S2,8PSK -14=10973,H,2221,56,DVB-S,QPSK -15=10979,V,7500,56,S2,8PSK -16=10987,V,7500,56,S2,8PSK -17=10988,H,2400,56,S2,8PSK -18=10991,H,1536,56,DVB-S,QPSK -19=10999,V,3570,56,DVB-S,QPSK -20=11002,V,2222,56,DVB-S,QPSK -21=11005,V,2222,56,DVB-S,QPSK -22=11008,V,2222,56,DVB-S,QPSK -23=11011,V,2222,56,DVB-S,QPSK -24=11014,V,2222,56,DVB-S,QPSK -25=11015,H,30000,56,DVB-S,QPSK -26=11024,V,12700,56,DVB-S,QPSK -27=11038,H,3333,56,S2,8PSK -28=11039,V,3700,78,DVB-S,QPSK -29=11047,V,10000,34,DVB-S,QPSK -30=11058,H,7500,56,DVB-S,QPSK -31=11061,V,3333,34,DVB-S,QPSK -32=11067,H,7500,56,S2,8PSK -33=11073,H,3333,78,DVB-S,QPSK -34=11077,V,2500,56,S2,8PSK -35=11095,H,27500,56,DVB-S,QPSK -36=11110,V,2222,56,DVB-S,QPSK -37=11134,H,27500,56,DVB-S,QPSK -38=11135,V,28800,56,S2,8PSK -39=11175,V,28800,56,S2,8PSK -40=11175,H,27500,56,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0475.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0475.ini deleted file mode 100644 index bc671123fe..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0475.ini +++ /dev/null @@ -1,31 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0475 -2=Intelsat 10 (47.5E) - -[DVB] -0=22 -1=11475,V,2700,34,DVB-S,QPSK -2=11531,V,2755,34,DVB-S,QPSK -3=11548,V,2000,56,S2,QPSK -4=11606,V,2200,56,S2,8PSK -5=11639,V,1900,78,DVB-S,QPSK -6=11642,V,1480,34,S2,8PSK -7=11644,V,1450,56,DVB-S,QPSK -8=11647,V,3200,34,DVB-S,QPSK -9=11654,V,1450,56,DVB-S,QPSK -10=11665,V,2000,34,DVB-S,QPSK -11=11670,V,2123,34,DVB-S,QPSK -12=11675,V,1900,78,DVB-S,QPSK -13=12517,H,6660,78,DVB-S,QPSK -14=12532,V,14395,34,S2,8PSK -15=12548,H,6111,Auto,DVB-S,QPSK -16=12564,H,3750,56,S2,QPSK -17=12574,H,6111,34,DVB-S,QPSK -18=12602,V,10112,12,S2,QPSK -19=12673,H,7200,34,DVB-S,QPSK -20=12691,H,14400,34,S2,8PSK -21=12712,H,13200,34,DVB-S,QPSK -22=12721,V,10000,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0480.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0480.ini deleted file mode 100644 index fa955de652..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0480.ini +++ /dev/null @@ -1,10 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0480 -2=Afghansat 1 (48.0E) - -[DVB] -0=1 -1=11293,V,27500,56,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0490.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0490.ini deleted file mode 100644 index a85ad11b97..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0490.ini +++ /dev/null @@ -1,30 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0490 -2=Yamal 202 (49.0E) - -[DVB] -0=21 -1=3635,H,3230,34,DVB-S,QPSK -2=3640,H,3215,34,DVB-S,QPSK -3=3644,H,3230,34,DVB-S,QPSK -4=3660,H,3333,34,DVB-S,QPSK -5=3714,H,8888,34,DVB-S,QPSK -6=3735,V,3219,34,DVB-S,QPSK -7=3743,H,34075,34,DVB-S,QPSK -8=3752,V,3230,34,DVB-S,QPSK -9=3781,H,1900,34,DVB-S,QPSK -10=3793,H,1800,34,DVB-S,QPSK -11=3826,H,2960,34,DVB-S,QPSK -12=3832,V,1500,34,DVB-S,QPSK -13=3866,H,3310,Auto,DVB-S,QPSK -14=3908,H,1356,12,DVB-S,QPSK -15=3936,H,3230,34,DVB-S,QPSK -16=3941,H,4000,34,DVB-S,QPSK -17=3950,H,3500,34,S2,8PSK -18=3961,H,8570,34,DVB-S,QPSK -19=3970,H,4275,34,DVB-S,QPSK -20=3976,H,4285,34,DVB-S,QPSK -21=4078,H,14400,89,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0505.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0505.ini deleted file mode 100644 index 5bbfe62977..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0505.ini +++ /dev/null @@ -1,11 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0505 -2=NSS 5 (50.5E) - -[DVB] -0=2 -1=4172,V,13330,34,DVB-S,QPSK -2=12710,V,26670,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0510.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0510.ini deleted file mode 100644 index 355d0e5b5a..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0510.ini +++ /dev/null @@ -1,28 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0510 -2=Express AM6 (51.0E) - -[DVB] -0=19 -1=3675,V,33483,78,DVB-S,QPSK -2=3708,H,4280,78,DVB-S,QPSK -3=10974,H,8150,34,DVB-S,QPSK -4=10990,V,3111,34,DVB-S,QPSK -5=10995,H,3255,34,DVB-S,QPSK -6=11001,H,4160,56,S2,QPSK -7=11044,V,44950,34,DVB-S,QPSK -8=11471,H,2400,34,DVB-S,QPSK -9=11474,H,4666,34,DVB-S,QPSK -10=11504,H,2200,56,DVB-S,QPSK -11=11506,H,1481,34,DVB-S,QPSK -12=11520,H,4800,56,DVB-S,QPSK -13=12511,V,2170,34,DVB-S,QPSK -14=12528,H,2100,34,S2,8PSK -15=12545,H,3000,23,DVB-S,QPSK -16=12572,H,1320,78,DVB-S,QPSK -17=12594,V,2050,34,DVB-S,QPSK -18=12594,H,2050,34,DVB-S,QPSK -19=12631,V,3000,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0520.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0520.ini deleted file mode 100644 index 8631604aa7..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0520.ini +++ /dev/null @@ -1,11 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0520 -2=Turkmenlem52E/MonacoSat (52.0E) - -[DVB] -0=2 -1=12265,V,27500,23,S2,QPSK -2=12303,V,27500,23,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0525.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0525.ini deleted file mode 100644 index 2eb001a81f..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0525.ini +++ /dev/null @@ -1,24 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0525 -2=Y1A (52.5E) - -[DVB] -0=15 -1=11747,H,27500,89,S2,QPSK -2=11766,V,27500,56,DVB-S,QPSK -3=11785,H,27500,56,DVB-S,QPSK -4=11823,H,27500,89,S2,QPSK -5=11862,H,27500,56,DVB-S,QPSK -6=11881,V,27500,56,DVB-S,QPSK -7=11900,H,27500,56,DVB-S,QPSK -8=11938,H,27500,56,DVB-S,QPSK -9=11958,V,27500,78,DVB-S,QPSK -10=11977,H,27500,89,S2,QPSK -11=11996,V,27500,56,DVB-S,QPSK -12=12015,H,27500,56,DVB-S,QPSK -13=12034,V,27500,23,S2,8PSK -14=12073,V,27500,78,DVB-S,QPSK -15=12092,H,27500,89,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0530.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0530.ini deleted file mode 100644 index 965c41f150..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0530.ini +++ /dev/null @@ -1,28 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0530 -2=Express AM6 (53.0E) - -[DVB] -0=19 -1=3675,V,33483,78,DVB-S,QPSK -2=3708,H,4280,78,DVB-S,QPSK -3=10974,H,8150,34,DVB-S,QPSK -4=10990,V,3111,34,DVB-S,QPSK -5=10995,H,3255,34,DVB-S,QPSK -6=11001,H,4160,56,S2,QPSK -7=11044,V,44950,34,DVB-S,QPSK -8=11471,H,2400,34,DVB-S,QPSK -9=11474,H,4666,34,DVB-S,QPSK -10=11504,H,2200,56,DVB-S,QPSK -11=11506,H,1481,34,DVB-S,QPSK -12=11520,H,4800,56,DVB-S,QPSK -13=12511,V,2170,34,DVB-S,QPSK -14=12528,H,2100,34,S2,8PSK -15=12545,H,3000,23,DVB-S,QPSK -16=12572,H,1320,78,DVB-S,QPSK -17=12594,H,2050,34,DVB-S,QPSK -18=12594,V,2050,34,DVB-S,QPSK -19=12631,V,3000,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0549.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0549.ini deleted file mode 100644 index b2fdf5a5c8..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0549.ini +++ /dev/null @@ -1,37 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0549 -2=G-Sat 8/Yamal 402 (54.9E) - -[DVB] -0=28 -1=10845,V,32727,Auto,S2,QPSK -2=10962,V,5926,34,DVB-S,QPSK -3=10968,V,2951,Auto,DVB-S,QPSK -4=10976,H,2200,35,S2,8PSK -5=11008,V,3600,34,S2,QPSK -6=11045,V,40000,23,DVB-S,QPSK -7=11156,V,22000,12,S2,QPSK -8=11186,V,6642,34,S2,8PSK -9=11215,H,13000,12,S2,QPSK -10=11225,V,30000,89,S2,8PSK -11=11232,H,17000,34,S2,QPSK -12=11265,V,30000,34,DVB-S,QPSK -13=11305,V,10000,34,S2,QPSK -14=11345,V,30000,34,S2,8PSK -15=11425,V,30000,12,S2,QPSK -16=11486,V,8000,12,S2,QPSK -17=11531,H,3015,34,DVB-S,QPSK -18=11554,V,3800,56,DVB-S,QPSK -19=11686,H,3333,23,DVB-S,QPSK -20=12522,V,27500,34,S2,8PSK -21=12531,H,2500,56,S2,QPSK -22=12604,V,16080,56,DVB-S,QPSK -23=12630,H,3333,34,DVB-S,QPSK -24=12674,V,14940,34,S2,8PSK -25=12685,H,30000,34,S2,QPSK -26=12694,V,15282,34,S2,8PSK -27=12720,H,30000,34,S2,QPSK -28=12732,V,9557,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0560.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0560.ini deleted file mode 100644 index bed5b87b5a..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0560.ini +++ /dev/null @@ -1,31 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0560 -2=Express AT1 (56.0E) - -[DVB] -0=22 -1=11727,H,27500,34,S2,8PSK -2=11881,H,27500,34,S2,8PSK -3=11919,H,27500,34,S2,8PSK -4=11958,H,27500,34,S2,8PSK -5=11996,H,27500,34,S2,8PSK -6=12034,H,27500,34,S2,8PSK -7=12073,H,27500,34,S2,8PSK -8=12111,H,27500,34,S2,8PSK -9=12130,V,27500,34,S2,8PSK -10=12149,H,27500,34,DVB-S,QPSK -11=12169,V,27500,56,S2,8PSK -12=12188,H,27500,34,DVB-S,QPSK -13=12226,H,27500,34,DVB-S,QPSK -14=12245,V,27500,56,S2,8PSK -15=12265,H,27500,34,S2,8PSK -16=12284,V,27500,34,DVB-S,QPSK -17=12303,H,27500,34,S2,8PSK -18=12322,V,27500,56,S2,8PSK -19=12341,H,27500,34,S2,8PSK -20=12399,V,27500,56,S2,8PSK -21=12437,V,27500,56,DVB-S,QPSK -22=12476,V,27500,56,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0570.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0570.ini deleted file mode 100644 index 27df363114..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0570.ini +++ /dev/null @@ -1,67 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0570 -2=NSS 12 (57.0E) - -[DVB] -0=58 -1=3632,V,2625,23,DVB-S,QPSK -2=3636,V,1762,23,DVB-S,QPSK -3=3661,H,8882,34,DVB-S,QPSK -4=3800,V,20000,35,S2,QPSK -5=3912,V,2222,23,DVB-S,QPSK -6=4026,H,2963,34,DVB-S,QPSK -7=4031,H,3689,34,DVB-S,QPSK -8=4055,V,26000,34,DVB-S,QPSK -9=4061,H,3500,12,DVB-S,QPSK -10=4065,H,3500,12,DVB-S,QPSK -11=4069,V,3500,12,DVB-S,QPSK -12=4071,H,3500,12,DVB-S,QPSK -13=4074,V,3500,12,DVB-S,QPSK -14=4079,H,2000,78,DVB-S,QPSK -15=4082,H,2000,12,DVB-S,QPSK -16=4147,V,9246,56,S2,QPSK -17=11007,H,4883,12,DVB-S,QPSK -18=11039,V,3100,34,DVB-S,QPSK -19=11042,H,2600,34,DVB-S,QPSK -20=11051,H,1230,34,DVB-S,QPSK -21=11105,H,45000,45,S2,QPSK -22=11129,V,2200,34,DVB-S,QPSK -23=11134,V,2200,34,S2,QPSK -24=11140,V,2200,56,S2,8PSK -25=11181,V,2400,56,S2,8PSK -26=11184,V,1211,34,S2,QPSK -27=11186,V,2290,34,DVB-S,QPSK -28=11189,V,1775,34,S2,QPSK -29=11191,V,1452,34,S2,QPSK -30=11460,H,3500,23,DVB-S,QPSK -31=11461,H,3500,23,DVB-S,QPSK -32=11464,H,3100,34,DVB-S,QPSK -33=11469,H,3100,34,DVB-S,QPSK -34=11473,H,3100,34,DVB-S,QPSK -35=11499,H,4090,23,DVB-S,QPSK -36=11503,H,2880,12,DVB-S,QPSK -37=11509,H,3333,23,DVB-S,QPSK -38=11510,H,3330,Auto,DVB-S,QPSK -39=11520,H,2222,56,S2,8PSK -40=11554,H,3300,34,S2,QPSK -41=11598,H,4200,78,DVB-S,QPSK -42=11604,H,4200,78,DVB-S,QPSK -43=11605,H,45000,45,S2,QPSK -44=11606,V,1852,56,S2,8PSK -45=11645,V,3333,34,DVB-S,QPSK -46=12292,V,2500,34,DVB-S,QPSK -47=12306,V,2000,34,DVB-S,QPSK -48=12313,V,2123,56,DVB-S,QPSK -49=12316,V,2123,34,DVB-S,QPSK -50=12413,V,1600,34,DVB-S,QPSK -51=12429,V,3500,34,S2,8PSK -52=12554,V,1800,34,DVB-S,QPSK -53=12556,V,1600,34,DVB-S,QPSK -54=12559,V,1600,34,DVB-S,QPSK -55=12571,V,2500,34,DVB-S,QPSK -56=12579,V,4000,34,DVB-S,QPSK -57=12621,V,2000,34,DVB-S,QPSK -58=12625,V,2200,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0600.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0600.ini deleted file mode 100644 index 1a711cf263..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0600.ini +++ /dev/null @@ -1,48 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0600 -2=Intelsat 904 (60.0E) - -[DVB] -0=39 -1=3676,H,3617,34,DVB-S,QPSK -2=3698,V,1666,56,S2,QPSK -3=3718,H,13333,78,DVB-S,QPSK -4=3730,H,2815,34,DVB-S,QPSK -5=3740,H,10750,56,DVB-S,QPSK -6=3744,V,18315,56,S2,QPSK -7=3756,V,2315,34,DVB-S,QPSK -8=3759,V,2315,34,DVB-S,QPSK -9=3765,V,5000,34,DVB-S,QPSK -10=3768,V,2067,34,S2,8PSK -11=3775,V,9361,12,S2,8PSK -12=3964,V,5000,34,DVB-S,QPSK -13=4168,V,14240,34,S2,8PSK -14=4185,V,2895,34,DVB-S,QPSK -15=4194,H,1594,Auto,DVB-S,QPSK -16=4194,V,6111,34,DVB-S,QPSK -17=10957,V,3700,34,DVB-S,QPSK -18=10962,V,3730,34,DVB-S,QPSK -19=10964,H,3327,34,DVB-S,QPSK -20=10967,V,2573,78,DVB-S,QPSK -21=10973,V,3330,34,DVB-S,QPSK -22=10977,V,3225,34,DVB-S,QPSK -23=11020,V,3700,34,DVB-S,QPSK -24=11460,V,3730,34,DVB-S,QPSK -25=11464,V,1000,78,DVB-S,QPSK -26=11473,V,1324,56,S2,8PSK -27=11475,V,1324,56,S2,8PSK -28=11477,V,1324,56,S2,8PSK -29=11481,V,2645,34,S2,8PSK -30=11484,V,2645,78,DVB-S,QPSK -31=11490,V,5788,34,DVB-S,QPSK -32=11497,V,4284,78,DVB-S,QPSK -33=11502,V,4284,78,DVB-S,QPSK -34=11555,H,30000,34,S2,8PSK -35=11567,V,10000,78,DVB-S,QPSK -36=11595,H,29270,56,DVB-S,QPSK -37=11622,V,8527,34,S2,8PSK -38=11635,H,30000,34,S2,8PSK -39=11675,H,30000,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0620.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0620.ini deleted file mode 100644 index ae5cf34bf1..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0620.ini +++ /dev/null @@ -1,70 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0620 -2=Intelsat 902 (62.0E) - -[DVB] -0=61 -1=3715,H,6111,34,DVB-S,QPSK -2=3727,V,34286,89,S2,8PSK -3=3763,V,34286,89,S2,8PSK -4=3807,V,34286,89,S2,8PSK -5=3814,H,4213,35,S2,QPSK -6=3843,V,34286,89,S2,8PSK -7=3853,H,1445,Auto,DVB-S,QPSK -8=3857,H,2465,Auto,DVB-S,QPSK -9=3860,H,3100,34,DVB-S,QPSK -10=3967,H,9326,Auto,DVB-S,QPSK -11=3992,H,26000,56,DVB-S,QPSK -12=4047,V,4444,12,DVB-S,QPSK -13=4055,V,34286,89,S2,8PSK -14=4107,H,12780,78,DVB-S,QPSK -15=10952,V,2700,78,DVB-S,QPSK -16=10961,V,3000,78,DVB-S,QPSK -17=10967,V,3000,78,DVB-S,QPSK -18=10975,V,3200,34,S2,8PSK -19=10978,V,1591,56,S2,8PSK -20=10982,V,4800,34,S2,8PSK -21=10986,V,1600,34,S2,8PSK -22=10989,V,3200,34,S2,8PSK -23=10992,V,1600,34,S2,8PSK -24=10996,V,4800,34,S2,8PSK -25=10998,H,3333,34,DVB-S,QPSK -26=11003,V,4800,34,S2,8PSK -27=11008,V,3200,34,S2,8PSK -28=11011,V,1600,34,S2,8PSK -29=11015,V,4800,34,S2,8PSK -30=11019,V,1600,34,S2,8PSK -31=11022,V,3200,34,S2,8PSK -32=11025,V,1600,34,S2,8PSK -33=11029,V,4820,34,S2,8PSK -34=11036,H,3000,34,DVB-S,QPSK -35=11043,H,2300,78,DVB-S,QPSK -36=11058,V,6111,34,DVB-S,QPSK -37=11063,H,3100,34,DVB-S,QPSK -38=11074,H,2300,78,DVB-S,QPSK -39=11082,H,3333,34,DVB-S,QPSK -40=11085,H,2700,78,DVB-S,QPSK -41=11088,H,2800,78,DVB-S,QPSK -42=11091,H,3400,34,DVB-S,QPSK -43=11122,H,2600,34,S2,8PSK -44=11165,H,2300,78,DVB-S,QPSK -45=11168,H,2500,78,DVB-S,QPSK -46=11172,H,2190,78,DVB-S,QPSK -47=11467,H,12500,34,S2,8PSK -48=11509,H,7500,34,S2,8PSK -49=11513,V,2300,34,S2,8PSK -50=11518,H,7500,34,S2,8PSK -51=11522,V,2200,78,DVB-S,QPSK -52=11555,V,30000,23,S2,8PSK -53=11555,H,28900,34,S2,8PSK -54=11587,V,5632,34,DVB-S,QPSK -55=11595,H,31003,78,DVB-S,QPSK -56=11625,V,1550,78,DVB-S,QPSK -57=11662,H,7500,56,S2,QPSK -58=11674,H,2200,78,DVB-S,QPSK -59=11680,H,10000,34,S2,8PSK -60=11683,V,15000,56,S2,8PSK -61=11688,H,7500,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0642.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0642.ini deleted file mode 100644 index 324d99e83c..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0642.ini +++ /dev/null @@ -1,28 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0642 -2=Intelsat 906 (64.2E) - -[DVB] -0=19 -1=3644,V,8545,23,DVB-S,QPSK -2=3654,V,5632,34,DVB-S,QPSK -3=3721,V,4882,23,DVB-S,QPSK -4=3760,H,2790,78,DVB-S,QPSK -5=3765,V,1413,34,S2,QPSK -6=3884,H,4900,12,DVB-S,QPSK -7=3893,H,3072,12,DVB-S,QPSK -8=3900,H,3800,12,DVB-S,QPSK -9=4039,H,2034,23,DVB-S,QPSK -10=4044,H,2848,Auto,DVB-S,QPSK -11=4066,H,2848,23,DVB-S,QPSK -12=4094,H,3680,23,DVB-S,QPSK -13=4185,V,2532,34,DVB-S,QPSK -14=10990,V,53000,34,S2,QPSK -15=11127,V,4000,34,DVB-S,QPSK -16=11134,V,4000,34,DVB-S,QPSK -17=11140,V,4000,34,DVB-S,QPSK -18=11146,V,4000,34,DVB-S,QPSK -19=11152,V,4000,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0650.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0650.ini deleted file mode 100644 index 81021a0b21..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0650.ini +++ /dev/null @@ -1,15 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0650 -2=Amos 4 (65.0E) - -[DVB] -0=6 -1=10736,V,45000,23,S2,QPSK -2=10790,V,45000,23,S2,QPSK -3=10861,V,45000,12,S2,QPSK -4=10915,V,45000,12,S2,QPSK -5=11236,V,45000,12,S2,QPSK -6=11290,V,45000,12,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0660.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0660.ini deleted file mode 100644 index a118dfa389..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0660.ini +++ /dev/null @@ -1,39 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0660 -2=Intelsat 17 (66.0E) - -[DVB] -0=30 -1=3845,H,30000,34,S2,8PSK -2=3845,V,27692,78,DVB-S,QPSK -3=3876,H,14300,34,S2,8PSK -4=3885,V,30000,34,S2,8PSK -5=3894,H,13840,56,S2,8PSK -6=3914,H,11200,34,S2,8PSK -7=3925,V,30000,34,S2,8PSK -8=3966,H,14400,23,S2,8PSK -9=3968,V,8800,23,S2,8PSK -10=3984,H,14400,23,S2,8PSK -11=4006,H,14400,23,S2,8PSK -12=4015,V,30000,34,S2,8PSK -13=4024,H,14400,23,S2,8PSK -14=4121,H,7200,34,S2,QPSK -15=10962,H,3100,Auto,DVB-S,QPSK -16=11011,H,2811,34,DVB-S,QPSK -17=11498,H,2400,Auto,DVB-S,QPSK -18=11505,H,13271,34,DVB-S,QPSK -19=11515,H,1735,Auto,DVB-S,QPSK -20=11519,H,3255,34,DVB-S,QPSK -21=11527,H,3094,Auto,DVB-S,QPSK -22=11556,H,20129,12,S2,QPSK -23=12602,H,2000,56,S2,QPSK -24=12605,H,1025,78,DVB-S,QPSK -25=12613,H,3965,78,DVB-S,QPSK -26=12648,H,3900,78,DVB-S,QPSK -27=12652,H,3900,78,DVB-S,QPSK -28=12687,H,3400,78,DVB-S,QPSK -29=12703,H,3400,78,DVB-S,QPSK -30=12708,H,3400,78,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0685.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0685.ini deleted file mode 100644 index 7c2cab6818..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0685.ini +++ /dev/null @@ -1,110 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0685 -2=Intelsat 20 (68.5E) - -[DVB] -0=101 -1=3708,V,7900,34,S2,8PSK -2=3712,H,14454,34,S2,QPSK -3=3723,V,9600,34,S2,8PSK -4=3732,V,7200,34,S2,8PSK -5=3739,H,26590,12,DVB-S,QPSK -6=3742,V,7000,34,S2,8PSK -7=3752,V,9300,34,S2,8PSK -8=3765,V,2950,56,DVB-S,QPSK -9=3774,V,2944,34,DVB-S,QPSK -10=3777,V,2940,34,DVB-S,QPSK -11=3782,V,2965,34,DVB-S,QPSK -12=3790,H,7200,34,S2,8PSK -13=3790,V,1681,34,S2,QPSK -14=3796,V,7300,34,S2,8PSK -15=3802,H,10000,34,DVB-S,QPSK -16=3802,V,1954,34,DVB-S,QPSK -17=3810,H,3312,23,DVB-S,QPSK -18=3828,V,7200,23,S2,8PSK -19=3836,V,7200,23,S2,8PSK -20=3838,H,16296,34,DVB-S,QPSK -21=3845,V,6111,34,DVB-S,QPSK -22=3854,V,7500,34,DVB-S,QPSK -23=3863,V,6111,34,DVB-S,QPSK -24=3867,V,9875,34,S2,8PSK -25=3873,V,7200,34,DVB-S,QPSK -26=3887,V,2960,34,DVB-S,QPSK -27=3891,V,1954,56,DVB-S,QPSK -28=3900,H,22222,56,DVB-S,QPSK -29=3900,V,10370,34,DVB-S,QPSK -30=3913,V,6510,34,DVB-S,QPSK -31=3919,H,1600,56,S2,QPSK -32=3922,H,3200,56,S2,QPSK -33=3922,V,7000,56,S2,QPSK -34=3930,H,9600,56,S2,QPSK -35=3940,V,7200,34,S2,QPSK -36=3974,H,19500,34,DVB-S,QPSK -37=3974,V,19850,34,DVB-S,QPSK -38=3994,H,4000,23,DVB-S,QPSK -39=3996,V,6666,34,DVB-S,QPSK -40=4000,H,6500,34,DVB-S,QPSK -41=4003,V,7200,34,S2,8PSK -42=4006,H,2990,34,DVB-S,QPSK -43=4013,H,7200,34,S2,8PSK -44=4013,V,6111,34,DVB-S,QPSK -45=4034,H,20500,23,DVB-S,QPSK -46=4036,V,21600,56,S2,QPSK -47=4054,V,4400,34,DVB-S,QPSK -48=4059,V,3529,34,DVB-S,QPSK -49=4064,H,19850,78,DVB-S,QPSK -50=4064,V,4400,34,DVB-S,QPSK -51=4070,V,4340,34,DVB-S,QPSK -52=4076,V,3600,34,S2,8PSK -53=4085,V,7020,34,DVB-S,QPSK -54=4090,H,14368,34,S2,8PSK -55=4092,V,2963,34,DVB-S,QPSK -56=4103,H,5720,34,DVB-S,QPSK -57=4103,V,7800,34,S2,8PSK -58=4117,H,3333,23,DVB-S,QPSK -59=4118,V,8800,Auto,S2,8PSK -60=4130,H,6400,34,S2,8PSK -61=4130,V,10369,34,DVB-S,QPSK -62=4150,H,15000,23,S2,8PSK -63=4155,V,22500,56,S2,8PSK -64=4163,H,7200,34,S2,QPSK -65=4184,V,21600,56,S2,8PSK -66=10970,V,30000,56,DVB-S,QPSK -67=10970,H,30000,56,DVB-S,QPSK -68=11010,V,30000,56,DVB-S,QPSK -69=11010,H,30000,56,DVB-S,QPSK -70=11014,V,3750,34,S2,8PSK -71=11050,V,30000,23,S2,8PSK -72=11050,H,30000,56,DVB-S,QPSK -73=11090,V,30000,56,DVB-S,QPSK -74=11090,H,30000,56,DVB-S,QPSK -75=11092,H,1024,34,DVB-S,QPSK -76=11130,V,30000,56,DVB-S,QPSK -77=11130,H,30000,56,DVB-S,QPSK -78=11170,V,28800,56,S2,8PSK -79=11170,H,30000,56,DVB-S,QPSK -80=11474,H,30000,56,DVB-S,QPSK -81=11477,V,2170,34,DVB-S,QPSK -82=11514,V,28750,12,S2,QPSK -83=11514,H,30000,23,S2,8PSK -84=11554,V,30000,23,S2,8PSK -85=11554,H,30000,23,S2,8PSK -86=11594,V,27500,56,DVB-S,QPSK -87=11594,H,30000,56,DVB-S,QPSK -88=11634,V,30000,56,DVB-S,QPSK -89=11634,H,30000,23,S2,8PSK -90=11674,H,30000,56,DVB-S,QPSK -91=12522,V,27500,34,DVB-S,QPSK -92=12562,H,26657,23,DVB-S,QPSK -93=12567,V,3100,34,DVB-S,QPSK -94=12574,V,9700,12,DVB-S,QPSK -95=12602,V,26657,23,DVB-S,QPSK -96=12638,V,4690,34,DVB-S,QPSK -97=12657,V,4883,34,DVB-S,QPSK -98=12682,V,30000,23,DVB-S,QPSK -99=12682,H,26657,23,DVB-S,QPSK -100=12722,V,26657,12,DVB-S,QPSK -101=12722,H,26657,23,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0705.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0705.ini deleted file mode 100644 index 0af8237c99..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0705.ini +++ /dev/null @@ -1,20 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0705 -2=Eutelsat 70B (70.5E) - -[DVB] -0=11 -1=11092,V,1028,34,DVB-S,QPSK -2=11211,H,5110,12,DVB-S,QPSK -3=11213,V,16667,56,S2,8PSK -4=11255,V,4832,Auto,S2,QPSK -5=11294,H,44900,23,S2,QPSK -6=11356,V,44900,34,S2,QPSK -7=11477,V,2170,12,S2,QPSK -8=11490,V,2150,23,S2,QPSK -9=11520,V,3332,12,S2,QPSK -10=11555,H,3034,12,S2,QPSK -11=11565,H,11401,Auto,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0721.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0721.ini deleted file mode 100644 index c25a6ecf5c..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0721.ini +++ /dev/null @@ -1,14 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0721 -2=Intelsat 22 (72.1E) - -[DVB] -0=5 -1=3724,H,16073,34,S2,8PSK -2=3735,H,2325,23,S2,8PSK -3=3754,H,7500,34,DVB-S,QPSK -4=4067,V,6111,34,DVB-S,QPSK -5=12541,H,2300,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0740.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0740.ini deleted file mode 100644 index 91356547c5..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0740.ini +++ /dev/null @@ -1,47 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0740 -2=Insat 3C/4CR (74.0E) - -[DVB] -0=38 -1=3740,V,2500,34,DVB-S,QPSK -2=3745,V,2500,34,DVB-S,QPSK -3=3752,V,2500,34,DVB-S,QPSK -4=3756,V,2500,34,DVB-S,QPSK -5=3776,V,3800,34,DVB-S,QPSK -6=3780,H,6250,34,DVB-S,QPSK -7=3781,V,2000,34,DVB-S,QPSK -8=3788,V,3800,34,DVB-S,QPSK -9=3796,V,3800,34,DVB-S,QPSK -10=3801,V,3800,34,DVB-S,QPSK -11=3868,H,2250,34,DVB-S,QPSK -12=3871,H,2250,34,DVB-S,QPSK -13=3874,H,1923,34,DVB-S,QPSK -14=3879,H,2200,34,DVB-S,QPSK -15=3884,H,2250,34,DVB-S,QPSK -16=3889,H,2250,34,DVB-S,QPSK -17=3895,H,2000,34,DVB-S,QPSK -18=3898,H,1500,34,DVB-S,QPSK -19=3901,H,1500,34,DVB-S,QPSK -20=4165,H,26000,12,DVB-S,QPSK -21=11513,H,3000,23,DVB-S,QPSK -22=11520,H,1700,34,DVB-S,QPSK -23=11523,H,1700,34,DVB-S,QPSK -24=11526,H,1700,34,DVB-S,QPSK -25=11578,H,5000,78,DVB-S,QPSK -26=11587,V,4000,78,DVB-S,QPSK -27=11592,V,2000,34,DVB-S,QPSK -28=11597,H,2000,34,DVB-S,QPSK -29=11599,V,1800,34,DVB-S,QPSK -30=11603,V,2000,34,DVB-S,QPSK -31=11607,V,2000,34,DVB-S,QPSK -32=11656,V,3333,34,DVB-S,QPSK -33=11667,V,3000,34,DVB-S,QPSK -34=11672,V,2500,34,DVB-S,QPSK -35=11680,H,1400,34,DVB-S,QPSK -36=11680,V,2965,34,DVB-S,QPSK -37=11683,H,1600,34,DVB-S,QPSK -38=11685,V,2900,78,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0750.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0750.ini deleted file mode 100644 index 8cdc075909..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0750.ini +++ /dev/null @@ -1,44 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0750 -2=ABS 2 (75.0E) - -[DVB] -0=35 -1=3545,H,1956,34,S2,QPSK -2=3590,V,1850,34,DVB-S,QPSK -3=3618,V,29000,56,S2,QPSK -4=3766,V,3000,34,DVB-S,QPSK -5=3770,V,2142,23,S2,8PSK -6=3772,V,2400,23,S2,QPSK -7=3779,V,7495,34,DVB-S,QPSK -8=3781,V,35342,23,S2,QPSK -9=3791,V,3703,23,DVB-S,QPSK -10=3846,V,2300,34,DVB-S,QPSK -11=3942,V,30000,23,S2,QPSK -12=3978,V,29000,56,S2,QPSK -13=4123,V,2800,56,S2,8PSK -14=10985,H,35007,34,S2,8PSK -15=11045,H,44922,56,DVB-S,QPSK -16=11105,H,43200,56,DVB-S,QPSK -17=11473,V,22500,34,S2,8PSK -18=11491,V,4650,23,S2,8PSK -19=11505,V,3400,78,DVB-S,QPSK -20=11531,V,22000,56,DVB-S,QPSK -21=11559,V,22000,56,DVB-S,QPSK -22=11605,V,43200,78,DVB-S,QPSK -23=11665,V,44922,56,DVB-S,QPSK -24=11733,V,43000,56,DVB-S,QPSK -25=11734,H,44000,23,DVB-S,QPSK -26=11790,H,44000,23,DVB-S,QPSK -27=11793,V,43200,56,DVB-S,QPSK -28=11853,V,45000,23,S2,8PSK -29=11913,V,45000,23,S2,8PSK -30=11973,V,45000,23,S2,8PSK -31=12033,V,45000,23,S2,8PSK -32=12093,V,45000,23,S2,8PSK -33=12153,V,45000,23,S2,8PSK -34=12153,H,41900,45,S2,QPSK -35=12524,H,30000,12,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0765.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0765.ini deleted file mode 100644 index 1a6195f9ae..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0765.ini +++ /dev/null @@ -1,85 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0765 -2=Apstar 7 (76.5E) - -[DVB] -0=76 -1=3629,H,1489,34,S2,QPSK -2=3638,H,1600,35,S2,8PSK -3=3685,V,3333,34,DVB-S,QPSK -4=3690,H,13000,34,S2,8PSK -5=3705,V,8888,23,S2,8PSK -6=3720,H,29620,34,S2,8PSK -7=3747,H,2500,34,DVB-S,QPSK -8=3753,H,2400,34,DVB-S,QPSK -9=3757,H,4440,34,S2,QPSK -10=3769,H,13333,56,DVB-S,QPSK -11=3780,V,30000,34,S2,8PSK -12=3787,H,4600,23,DVB-S,QPSK -13=3793,H,4443,34,DVB-S,QPSK -14=3805,H,4800,34,S2,8PSK -15=3812,H,2200,34,S2,8PSK -16=3815,H,3333,34,DVB-S,QPSK -17=3824,H,2400,34,DVB-S,QPSK -18=3832,V,6111,34,DVB-S,QPSK -19=3835,H,3256,34,DVB-S,QPSK -20=3840,H,3000,34,DVB-S,QPSK -21=3847,H,5357,78,DVB-S,QPSK -22=3847,V,7857,56,S2,QPSK -23=3852,H,3000,34,DVB-S,QPSK -24=3857,H,3200,Auto,S2,8PSK -25=3880,H,30000,34,S2,8PSK -26=3914,V,3255,34,DVB-S,QPSK -27=3920,H,28340,56,DVB-S,QPSK -28=3932,V,1480,34,DVB-S,QPSK -29=3951,V,1480,34,DVB-S,QPSK -30=3960,H,30000,34,S2,8PSK -31=3985,H,3700,34,DVB-S,QPSK -32=3990,H,4300,34,S2,QPSK -33=3998,H,3200,34,DVB-S,QPSK -34=4003,H,4340,34,DVB-S,QPSK -35=4009,H,4300,34,DVB-S,QPSK -36=4016,H,4340,34,DVB-S,QPSK -37=4019,V,2222,23,S2,QPSK -38=4022,V,2961,12,DVB-S,QPSK -39=4026,H,4800,34,DVB-S,QPSK -40=4034,H,4300,34,DVB-S,QPSK -41=4038,H,1600,23,S2,8PSK -42=4041,H,1600,23,S2,QPSK -43=4044,H,1600,23,S2,QPSK -44=4048,V,2450,23,S2,8PSK -45=4050,H,4300,34,DVB-S,QPSK -46=4056,H,3600,35,S2,8PSK -47=4059,V,7857,56,S2,QPSK -48=4063,H,1250,34,DVB-S,QPSK -49=4067,H,2500,89,S2,QPSK -50=4079,H,1600,34,S2,QPSK -51=4082,H,2857,23,S2,8PSK -52=4088,V,7750,56,S2,8PSK -53=4104,H,5000,34,S2,QPSK -54=4110,H,4600,34,DVB-S,QPSK -55=4117,H,4285,34,DVB-S,QPSK -56=4125,H,4441,34,DVB-S,QPSK -57=4129,V,11395,34,DVB-S,QPSK -58=4131,H,3600,34,DVB-S,QPSK -59=4135,H,3333,34,DVB-S,QPSK -60=4151,H,14670,34,S2,8PSK -61=4188,V,3200,34,DVB-S,QPSK -62=10973,V,24500,23,S2,QPSK -63=11010,V,30000,12,DVB-S,QPSK -64=11052,V,30000,23,DVB-S,QPSK -65=11105,V,45000,23,DVB-S,QPSK -66=11167,V,45000,23,DVB-S,QPSK -67=11532,H,3732,56,S2,8PSK -68=11536,H,3732,56,S2,8PSK -69=11541,H,3450,34,S2,8PSK -70=11547,H,2500,34,S2,QPSK -71=11568,H,3330,34,S2,8PSK -72=11596,H,3732,56,S2,8PSK -73=12531,V,15000,34,S2,QPSK -74=12604,V,30000,56,S2,QPSK -75=12638,V,15000,34,S2,8PSK -76=12719,V,45000,56,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0785.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0785.ini deleted file mode 100644 index 8dcf19d376..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0785.ini +++ /dev/null @@ -1,112 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0785 -2=Thaicom 5/6 (78.5E) - -[DVB] -0=103 -1=3408,V,2916,34,DVB-S,QPSK -2=3414,V,2916,34,DVB-S,QPSK -3=3418,V,3750,34,S2,QPSK -4=3422,V,2222,34,DVB-S,QPSK -5=3425,V,2592,12,DVB-S,QPSK -6=3433,V,5000,34,DVB-S,QPSK -7=3438,V,2915,34,DVB-S,QPSK -8=3440,H,26666,34,DVB-S,QPSK -9=3441,V,1556,34,DVB-S,QPSK -10=3444,V,1630,34,DVB-S,QPSK -11=3450,V,2500,34,DVB-S,QPSK -12=3454,V,3333,34,DVB-S,QPSK -13=3457,V,2857,34,DVB-S,QPSK -14=3462,V,2857,34,DVB-S,QPSK -15=3480,H,30000,56,DVB-S,QPSK -16=3515,V,2917,34,DVB-S,QPSK -17=3520,H,28125,34,DVB-S,QPSK -18=3545,V,30000,56,DVB-S,QPSK -19=3551,H,13333,34,DVB-S,QPSK -20=3563,H,5555,35,S2,8PSK -21=3574,H,6510,34,DVB-S,QPSK -22=3585,V,30000,56,DVB-S,QPSK -23=3600,H,26667,34,DVB-S,QPSK -24=3625,V,30000,34,S2,8PSK -25=3640,H,28066,34,DVB-S,QPSK -26=3665,H,3704,34,DVB-S,QPSK -27=3683,H,7500,34,S2,8PSK -28=3690,H,2417,78,DVB-S,QPSK -29=3696,H,4167,35,S2,8PSK -30=3703,V,3333,78,DVB-S,QPSK -31=3709,H,13333,23,S2,8PSK -32=3711,V,1458,78,DVB-S,QPSK -33=3715,V,1481,34,DVB-S,QPSK -34=3718,V,1600,34,DVB-S,QPSK -35=3719,H,2500,23,S2,8PSK -36=3731,H,12500,78,DVB-S,QPSK -37=3745,V,4688,34,DVB-S,QPSK -38=3749,V,4688,34,DVB-S,QPSK -39=3757,V,4688,34,DVB-S,QPSK -40=3758,H,28066,34,DVB-S,QPSK -41=3760,H,30000,56,DVB-S,QPSK -42=3784,V,4262,34,DVB-S,QPSK -43=3792,V,4262,34,DVB-S,QPSK -44=3797,V,4262,34,DVB-S,QPSK -45=3800,H,30000,56,DVB-S,QPSK -46=3803,V,4551,34,DVB-S,QPSK -47=3809,V,4550,34,DVB-S,QPSK -48=3826,H,4700,34,DVB-S,QPSK -49=3834,H,8000,56,S2,8PSK -50=3840,V,30000,56,DVB-S,QPSK -51=3841,H,2900,34,DVB-S,QPSK -52=3847,H,4700,34,DVB-S,QPSK -53=3851,H,2900,34,DVB-S,QPSK -54=3880,H,30000,34,DVB-S,QPSK -55=3910,V,14650,45,S2,QPSK -56=3920,H,30000,34,DVB-S,QPSK -57=3930,V,15000,56,S2,QPSK -58=3949,V,2550,78,DVB-S,QPSK -59=3975,V,2500,35,S2,8PSK -60=3990,V,12000,23,S2,8PSK -61=4000,V,4815,34,DVB-S,QPSK -62=4000,H,30000,23,S2,8PSK -63=4005,V,4815,34,DVB-S,QPSK -64=4017,V,1800,34,DVB-S,QPSK -65=4040,H,30000,23,S2,8PSK -66=4053,V,8333,34,DVB-S,QPSK -67=4080,H,30000,35,S2,8PSK -68=4091,V,2000,34,DVB-S,QPSK -69=4096,V,5295,34,DVB-S,QPSK -70=4120,V,30000,910,S2,QPSK -71=4120,H,30000,56,DVB-S,QPSK -72=4144,H,2530,34,DVB-S,QPSK -73=4148,H,4688,34,DVB-S,QPSK -74=4154,H,3125,34,DVB-S,QPSK -75=4157,H,2530,34,DVB-S,QPSK -76=4160,V,30000,56,DVB-S,QPSK -77=4160,H,2530,34,DVB-S,QPSK -78=4163,H,2530,34,DVB-S,QPSK -79=4167,H,2530,34,DVB-S,QPSK -80=4170,H,2530,34,DVB-S,QPSK -81=4173,H,2530,34,DVB-S,QPSK -82=4177,H,2530,34,DVB-S,QPSK -83=12272,H,30000,23,DVB-S,QPSK -84=12313,H,30000,23,DVB-S,QPSK -85=12313,V,30000,34,DVB-S,QPSK -86=12355,H,30000,56,DVB-S,QPSK -87=12355,V,30000,23,S2,8PSK -88=12396,H,30000,35,S2,8PSK -89=12405,V,45000,34,S2,8PSK -90=12438,H,30000,23,DVB-S,QPSK -91=12467,V,45000,34,DVB-S,QPSK -92=12479,H,30000,35,S2,8PSK -93=12521,H,30000,35,S2,8PSK -94=12521,V,30000,34,S2,8PSK -95=12562,H,25776,23,DVB-S,QPSK -96=12562,V,30000,34,S2,8PSK -97=12604,H,30000,56,DVB-S,8PSK -98=12604,V,30000,34,DVB-S,QPSK -99=12645,V,30000,23,S2,8PSK -100=12657,H,45000,34,S2,8PSK -101=12687,V,30000,23,DVB-S,QPSK -102=12720,H,45000,34,S2,8PSK -103=12728,V,30000,23,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0830.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0830.ini deleted file mode 100644 index ac7588e57d..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0830.ini +++ /dev/null @@ -1,74 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0830 -2=G-Sat 10/Insat 4A (83.0E) - -[DVB] -0=65 -1=3725,H,26666,34,DVB-S,QPSK -2=3756,H,13333,34,DVB-S,QPSK -3=3756,V,3200,Auto,DVB-S,QPSK -4=3767,H,3000,34,S2,QPSK -5=3774,V,4250,Auto,DVB-S,QPSK -6=3777,H,10900,34,DVB-S,QPSK -7=3805,H,28500,78,DVB-S,QPSK -8=3828,H,3200,34,DVB-S,QPSK -9=3832,H,2100,34,DVB-S,QPSK -10=3836,H,1800,34,DVB-S,QPSK -11=3841,H,6920,78,DVB-S,QPSK -12=3847,H,3333,34,DVB-S,QPSK -13=3860,H,6920,34,DVB-S,QPSK -14=3868,H,3000,34,DVB-S,QPSK -15=3874,H,3400,34,S2,8PSK -16=3880,H,4600,34,DVB-S,QPSK -17=3884,H,1500,34,DVB-S,QPSK -18=3888,H,1071,34,DVB-S,QPSK -19=3892,H,3300,34,DVB-S,QPSK -20=3898,H,6800,34,DVB-S,QPSK -21=3909,H,4000,34,S2,8PSK -22=3921,H,13000,78,DVB-S,QPSK -23=3936,H,10100,78,DVB-S,QPSK -24=3949,H,3673,56,S2,8PSK -25=3958,H,9500,78,DVB-S,QPSK -26=3968,H,2000,34,DVB-S,QPSK -27=3976,H,3200,34,DVB-S,QPSK -28=3979,H,1451,34,DVB-S,QPSK -29=3983,H,1451,34,DVB-S,QPSK -30=3990,H,2140,34,DVB-S,QPSK -31=4004,H,22220,56,DVB-S,QPSK -32=4020,H,2140,34,DVB-S,QPSK -33=4030,H,4440,34,DVB-S,QPSK -34=4040,H,7500,78,DVB-S,QPSK -35=4054,H,13230,34,DVB-S,QPSK -36=4072,H,6500,34,DVB-S,QPSK -37=4076,H,1500,34,DVB-S,QPSK -38=4080,H,2000,34,DVB-S,QPSK -39=4083,H,2100,34,DVB-S,QPSK -40=4087,H,3300,34,DVB-S,QPSK -41=4091,H,3000,34,DVB-S,QPSK -42=4096,H,2170,23,S2,8PSK -43=4100,H,4750,34,DVB-S,QPSK -44=4109,H,1800,34,DVB-S,QPSK -45=4115,H,7776,34,DVB-S,QPSK -46=4122,H,1800,34,DVB-S,QPSK -47=4133,H,11888,34,S2,8PSK -48=4142,H,1255,34,DVB-S,QPSK -49=4151,H,6500,34,DVB-S,QPSK -50=4161,H,6500,34,DVB-S,QPSK -51=4170,H,4650,34,DVB-S,QPSK -52=4175,H,2977,56,DVB-S,QPSK -53=4180,H,3233,34,DVB-S,QPSK -54=10970,H,32000,23,S2,8PSK -55=11010,H,27500,34,DVB-S,8PSK -56=11050,H,32000,23,S2,8PSK -57=11090,H,32000,23,S2,8PSK -58=11130,H,32000,23,S2,8PSK -59=11170,H,32000,23,DVB-S,8PSK -60=11470,H,32000,23,S2,8PSK -61=11510,H,32000,23,S2,8PSK -62=11550,H,32000,23,S2,8PSK -63=11590,H,32000,23,S2,8PSK -64=11630,H,32000,23,S2,8PSK -65=11670,H,32000,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0851.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0851.ini deleted file mode 100644 index faefe54dc7..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0851.ini +++ /dev/null @@ -1,38 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0851 -2=Horizons 2/Intelsat 15 (85.1E) - -[DVB] -0=29 -1=10969,H,1800,34,S2,8PSK -2=10980,H,2220,34,DVB-S,QPSK -3=11466,H,2000,56,S2,8PSK -4=11468,H,2000,56,S2,8PSK -5=11470,H,1100,56,S2,8PSK -6=11479,H,2200,34,DVB-S,QPSK -7=11483,H,1800,56,DVB-S,QPSK -8=11559,H,2200,78,DVB-S,QPSK -9=11588,H,2500,34,DVB-S,QPSK -10=11594,H,2500,34,DVB-S,QPSK -11=11687,H,2000,89,S2,8PSK -12=11720,H,28800,34,DVB-S,QPSK -13=11760,H,28800,23,S2,8PSK -14=11800,H,28800,23,S2,8PSK -15=11840,H,28800,23,S2,8PSK -16=11872,H,15000,12,DVB-S,8PSK -17=11920,H,28800,23,S2,8PSK -18=11960,H,28800,35,S2,8PSK -19=12000,H,28000,23,DVB-S,QPSK -20=12040,H,28800,34,DVB-S,QPSK -21=12080,H,26700,35,S2,8PSK -22=12120,H,26700,35,S2,8PSK -23=12160,H,28800,35,S2,8PSK -24=12504,V,4217,34,DVB-S,QPSK -25=12510,V,3700,78,DVB-S,QPSK -26=12515,V,3353,34,S2,8PSK -27=12560,V,30000,56,DVB-S,QPSK -28=12600,V,30000,23,S2,8PSK -29=12640,V,30000,56,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0865.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0865.ini deleted file mode 100644 index f5a946f000..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0865.ini +++ /dev/null @@ -1,30 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0865 -2=KazSat 2 (86.5E) - -[DVB] -0=21 -1=11495,V,8750,89,S2,8PSK -2=11504,V,6250,89,S2,8PSK -3=11632,V,1457,89,S2,QPSK -4=11642,V,1080,34,S2,8PSK -5=11643,V,1080,34,S2,8PSK -6=11645,V,1080,34,S2,8PSK -7=11646,V,1080,34,S2,8PSK -8=11647,V,1080,34,S2,8PSK -9=11649,V,1080,34,S2,8PSK -10=11650,V,1080,34,S2,8PSK -11=11651,V,1080,34,S2,8PSK -12=11653,V,1080,34,S2,8PSK -13=11654,V,1080,34,S2,8PSK -14=11656,V,2100,34,S2,8PSK -15=11658,V,1080,34,S2,8PSK -16=11660,V,2100,34,S2,8PSK -17=11663,V,5500,56,S2,8PSK -18=11672,V,5500,34,S2,8PSK -19=11678,V,5500,56,S2,8PSK -20=11683,V,5500,56,S2,8PSK -21=11689,V,5500,56,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0875.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0875.ini deleted file mode 100644 index 3f856ba713..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0875.ini +++ /dev/null @@ -1,13 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0875 -2=ChinaSat 12 (87.5E) - -[DVB] -0=4 -1=3774,H,1800,34,S2,QPSK -2=4035,H,1200,34,DVB-S,QPSK -3=4067,H,1500,56,S2,QPSK -4=4140,V,28800,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0880.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0880.ini deleted file mode 100644 index a2716d7625..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0880.ini +++ /dev/null @@ -1,34 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0880 -2=ST 2 (88.0E) - -[DVB] -0=25 -1=3629,H,24700,34,S2,8PSK -2=3632,V,30000,34,S2,8PSK -3=3657,H,3000,34,DVB-S,QPSK -4=3671,H,9256,34,DVB-S,QPSK -5=11062,V,1000,89,S2,8PSK -6=11066,V,2000,56,DVB-S,QPSK -7=11164,H,44995,23,S2,8PSK -8=11164,V,44995,23,S2,8PSK -9=11483,V,44995,23,S2,8PSK -10=11483,H,44995,23,S2,8PSK -11=11546,H,44995,23,S2,8PSK -12=11546,V,44995,23,S2,8PSK -13=11609,V,43975,23,S2,8PSK -14=11609,H,44995,23,S2,8PSK -15=11633,H,30000,56,S2,QPSK -16=11669,H,30000,56,S2,QPSK -17=11672,V,44995,23,S2,8PSK -18=11672,H,44995,23,S2,8PSK -19=12516,H,10833,34,DVB-S,QPSK -20=12533,H,9620,34,S2,8PSK -21=12642,H,24000,34,DVB-S,QPSK -22=12702,H,20000,34,DVB-S,QPSK -23=12705,V,2200,56,DVB-S,QPSK -24=12722,H,2200,56,DVB-S,QPSK -25=12730,H,3202,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0900.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0900.ini deleted file mode 100644 index d423f69b64..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0900.ini +++ /dev/null @@ -1,59 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0900 -2=Yamal 401 (90.0E) - -[DVB] -0=50 -1=3539,H,2500,34,DVB-S,QPSK -2=3553,H,20000,34,DVB-S,QPSK -3=3582,H,2850,34,DVB-S,QPSK -4=3588,H,4285,34,DVB-S,QPSK -5=3594,H,2850,34,DVB-S,QPSK -6=3600,H,5925,34,DVB-S,QPSK -7=3603,V,3300,34,DVB-S,QPSK -8=3605,H,2626,34,DVB-S,QPSK -9=3613,H,4285,34,DVB-S,QPSK -10=3617,V,1850,34,DVB-S,QPSK -11=3618,H,3038,34,DVB-S,QPSK -12=3623,H,4285,34,DVB-S,QPSK -13=3645,H,28000,34,DVB-S,QPSK -14=3675,H,17500,34,DVB-S,QPSK -15=3819,H,13333,34,S2,8PSK -16=3837,H,14815,34,DVB-S,QPSK -17=3858,H,1850,78,DVB-S,QPSK -18=3908,H,2850,34,DVB-S,QPSK -19=3920,H,3000,34,DVB-S,QPSK -20=3924,H,2850,34,DVB-S,QPSK -21=4026,H,14940,35,S2,8PSK -22=4046,H,15284,34,S2,8PSK -23=4106,V,14990,34,S2,8PSK -24=4124,H,14990,34,S2,8PSK -25=4126,V,15284,34,S2,8PSK -26=4144,H,15284,34,S2,8PSK -27=10972,H,11200,34,DVB-S,QPSK -28=11057,H,22222,34,S2,8PSK -29=11092,H,30000,34,S2,8PSK -30=11131,V,11160,23,S2,8PSK -31=11165,H,25000,23,S2,8PSK -32=11239,V,2737,34,S2,8PSK -33=11462,V,1400,78,DVB-S,QPSK -34=11492,H,6115,34,S2,QPSK -35=11504,H,2080,34,DVB-S,QPSK -36=11507,V,7000,56,DVB-S,QPSK -37=11512,H,6160,Auto,S2,QPSK -38=11524,V,2000,78,DVB-S,QPSK -39=11531,V,4280,34,DVB-S,QPSK -40=11558,H,20000,34,S2,QPSK -41=11565,V,1980,23,S2,8PSK -42=11573,V,5000,34,DVB-S,QPSK -43=11649,H,2170,34,DVB-S,QPSK -44=11654,H,6500,34,DVB-S,QPSK -45=11670,H,14400,56,S2,8PSK -46=11674,V,7800,56,S2,8PSK -47=12505,V,2020,Auto,S2,8PSK -48=12533,V,11760,34,S2,QPSK -49=12718,H,27500,56,S2,8PSK -50=12718,V,27500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0915.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0915.ini deleted file mode 100644 index 3c28ff2540..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0915.ini +++ /dev/null @@ -1,84 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0915 -2=Measat 3/3a/3b (91.5E) - -[DVB] -0=75 -1=3464,H,2963,23,DVB-S,QPSK -2=3469,V,7500,34,S2,8PSK -3=3472,H,6000,34,DVB-S,QPSK -4=3475,H,2963,23,DVB-S,QPSK -5=3480,V,2961,23,DVB-S,QPSK -6=3481,H,2963,23,DVB-S,QPSK -7=3485,V,2961,23,DVB-S,QPSK -8=3492,H,2963,23,DVB-S,QPSK -9=3606,V,3750,34,DVB-S,QPSK -10=3625,V,1600,34,DVB-S,QPSK -11=3638,H,6666,34,DVB-S,QPSK -12=3641,V,13333,23,S2,8PSK -13=3650,H,6666,34,DVB-S,QPSK -14=3705,H,4290,34,DVB-S,QPSK -15=3708,V,1400,34,S2,QPSK -16=3710,H,2860,34,DVB-S,QPSK -17=3717,H,7500,23,S2,8PSK -18=3718,V,1916,56,S2,QPSK -19=3720,V,2170,78,DVB-S,QPSK -20=3724,V,3030,23,S2,8PSK -21=3727,H,9833,23,S2,8PSK -22=3760,V,29700,56,S2,8PSK -23=3786,V,7200,56,S2,QPSK -24=3795,V,5064,34,S2,QPSK -25=3802,V,3333,34,DVB-S,QPSK -26=3805,V,3255,34,S2,QPSK -27=3814,V,6660,35,S2,8PSK -28=3840,H,30000,56,S2,8PSK -29=3840,V,29720,56,S2,8PSK -30=3880,V,29720,56,S2,8PSK -31=3904,H,2916,23,S2,8PSK -32=3918,H,18385,23,S2,8PSK -33=3920,V,29720,56,S2,8PSK -34=3960,H,29700,56,S2,8PSK -35=4000,H,29700,56,S2,8PSK -36=4040,H,28600,56,S2,8PSK -37=4120,V,29720,56,S2,8PSK -38=4120,H,30000,56,S2,8PSK -39=4147,H,7200,56,S2,QPSK -40=4153,V,2090,34,S2,QPSK -41=4164,H,20640,23,S2,8PSK -42=10852,V,30000,Auto,S2,QPSK -43=10932,V,30000,Auto,S2,QPSK -44=10982,V,30000,34,DVB-S,QPSK -45=11022,V,30000,34,S2,8PSK -46=11062,V,30000,34,DVB-S,QPSK -47=11142,V,30000,78,DVB-S,QPSK -48=11182,V,30000,78,DVB-S,QPSK -49=11482,V,30000,78,DVB-S,QPSK -50=11522,V,30000,78,DVB-S,QPSK -51=11562,V,30000,78,DVB-S,QPSK -52=11602,V,30000,78,DVB-S,QPSK -53=11642,V,30000,78,DVB-S,QPSK -54=11682,V,30000,78,DVB-S,QPSK -55=12276,V,30000,35,S2,8PSK -56=12316,H,30000,56,DVB-S,8PSK -57=12316,V,30000,35,S2,8PSK -58=12356,V,30000,35,S2,8PSK -59=12396,V,30000,35,S2,8PSK -60=12396,H,31000,23,S2,8PSK -61=12436,V,30000,35,S2,8PSK -62=12436,H,31000,23,S2,8PSK -63=12476,V,30000,35,S2,8PSK -64=12523,V,30000,78,DVB-S,QPSK -65=12523,H,30000,56,DVB-S,QPSK -66=12563,V,30000,56,S2,8PSK -67=12563,H,30000,56,S2,8PSK -68=12603,V,30000,56,S2,8PSK -69=12603,H,30000,56,S2,8PSK -70=12643,V,30000,78,DVB-S,QPSK -71=12643,H,30000,56,S2,8PSK -72=12683,V,30000,56,DVB-S,QPSK -73=12683,H,27500,56,DVB-S,QPSK -74=12723,V,30000,56,DVB-S,QPSK -75=12723,H,30000,56,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0922.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0922.ini deleted file mode 100644 index 1aaa166417..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0922.ini +++ /dev/null @@ -1,19 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0922 -2=ChinaSat 9 (92.2E) - -[DVB] -0=10 -1=11880,H,28800,34,DVB-S,QPSK -2=11920,H,28800,34,DVB-S,QPSK -3=11940,V,28800,34,DVB-S,QPSK -4=11960,H,28800,34,DVB-S,QPSK -5=11980,V,28800,34,DVB-S,QPSK -6=12020,V,28800,34,DVB-S,QPSK -7=12060,V,28800,34,DVB-S,QPSK -8=12100,V,28800,34,DVB-S,QPSK -9=12140,V,28800,34,DVB-S,QPSK -10=12180,V,28800,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0935.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0935.ini deleted file mode 100644 index e47df32779..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0935.ini +++ /dev/null @@ -1,77 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0935 -2=Insat 3A/4B (93.5E) - -[DVB] -0=68 -1=3725,H,27500,34,DVB-S,QPSK -2=3732,V,6250,34,DVB-S,QPSK -3=3740,V,6250,34,DVB-S,QPSK -4=3750,V,6250,34,DVB-S,QPSK -5=3750,H,3000,34,DVB-S,QPSK -6=3756,H,3000,34,DVB-S,QPSK -7=3758,V,6250,34,DVB-S,QPSK -8=3762,H,2500,34,DVB-S,QPSK -9=3768,H,2500,34,DVB-S,QPSK -10=3772,V,6250,34,DVB-S,QPSK -11=3774,H,4250,34,DVB-S,QPSK -12=3780,V,6250,34,DVB-S,QPSK -13=3780,H,2500,34,DVB-S,QPSK -14=3790,H,2500,34,DVB-S,QPSK -15=3791,V,8600,34,DVB-S,QPSK -16=3797,H,4250,34,DVB-S,QPSK -17=3800,V,4250,34,DVB-S,QPSK -18=3802,H,4250,34,DVB-S,QPSK -19=3808,H,2500,34,DVB-S,QPSK -20=3812,V,6250,34,DVB-S,QPSK -21=3815,H,2500,34,DVB-S,QPSK -22=3821,V,6250,34,DVB-S,QPSK -23=3822,H,4250,34,DVB-S,QPSK -24=3831,V,8600,34,DVB-S,QPSK -25=3832,H,6250,34,DVB-S,QPSK -26=3840,H,6250,34,DVB-S,QPSK -27=3841,V,4250,34,DVB-S,QPSK -28=3848,H,4250,34,DVB-S,QPSK -29=3855,H,3800,34,DVB-S,QPSK -30=3860,H,2500,34,DVB-S,QPSK -31=3888,V,1400,34,DVB-S,QPSK -32=3891,V,2000,34,DVB-S,QPSK -33=3894,V,2000,34,DVB-S,QPSK -34=3894,H,1500,34,DVB-S,QPSK -35=3897,V,1500,34,DVB-S,QPSK -36=3907,V,3125,34,DVB-S,QPSK -37=3910,V,1500,34,DVB-S,QPSK -38=3913,V,1000,34,DVB-S,QPSK -39=3916,V,1300,34,DVB-S,QPSK -40=3919,V,2000,34,DVB-S,QPSK -41=3922,V,2000,34,DVB-S,QPSK -42=3925,H,27500,34,DVB-S,QPSK -43=3932,V,6250,34,DVB-S,QPSK -44=3940,V,6250,34,DVB-S,QPSK -45=3950,V,6250,34,DVB-S,QPSK -46=3958,V,6250,34,DVB-S,QPSK -47=4086,V,1400,34,DVB-S,QPSK -48=4092,V,6250,34,DVB-S,QPSK -49=4101,V,6250,34,DVB-S,QPSK -50=4109,V,4250,34,DVB-S,QPSK -51=4115,V,4250,34,DVB-S,QPSK -52=4120,V,4250,34,DVB-S,QPSK -53=4132,V,4000,34,DVB-S,QPSK -54=4136,V,2000,34,DVB-S,QPSK -55=4141,V,5150,34,DVB-S,QPSK -56=4148,V,3000,34,DVB-S,QPSK -57=4151,V,2100,34,DVB-S,QPSK -58=10990,V,28500,34,DVB-S,QPSK -59=11030,V,32000,34,S2,8PSK -60=11053,V,1800,34,DVB-S,QPSK -61=11070,V,28500,34,DVB-S,QPSK -62=11110,V,30000,35,S2,8PSK -63=11150,V,28500,34,DVB-S,QPSK -64=11197,V,3333,34,DVB-S,QPSK -65=11490,V,30000,35,S2,8PSK -66=11508,V,1400,78,DVB-S,QPSK -67=11528,V,1400,34,DVB-S,QPSK -68=11570,V,28500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0950.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0950.ini deleted file mode 100644 index 1b6ba4775e..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0950.ini +++ /dev/null @@ -1,47 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0950 -2=NSS 6/SES 8 (95.0E) - -[DVB] -0=38 -1=10977,V,40000,78,DVB-S,QPSK -2=11004,V,2355,34,DVB-S,QPSK -3=11037,H,40700,34,DVB-S,QPSK -4=11038,V,45000,56,DVB-S,QPSK -5=11090,H,30000,56,S2,QPSK -6=11090,V,30000,34,DVB-S,QPSK -7=11147,V,2750,23,DVB-S,QPSK -8=11164,V,3300,34,DVB-S,QPSK -9=11172,H,30000,56,DVB-S,QPSK -10=11456,H,3125,34,DVB-S,QPSK -11=11460,H,3125,34,DVB-S,QPSK -12=11468,H,3000,34,DVB-S,QPSK -13=11475,H,6111,34,DVB-S,QPSK -14=11481,H,45000,34,DVB-S,QPSK -15=11483,H,3125,34,DVB-S,QPSK -16=11503,H,6111,34,DVB-S,QPSK -17=11542,V,43200,34,S2,8PSK -18=11542,H,45000,56,S2,8PSK -19=11604,V,3200,34,DVB-S,QPSK -20=11619,H,5000,34,S2,8PSK -21=11635,H,27500,34,DVB-S,QPSK -22=11651,V,3333,34,DVB-S,QPSK -23=11661,H,5632,34,DVB-S,QPSK -24=11670,V,5000,23,DVB-S,QPSK -25=11676,V,28800,34,S2,8PSK -26=11685,V,6600,34,DVB-S,QPSK -27=11990,H,43000,Auto,DVB-S,QPSK -28=12110,H,40700,34,DVB-S,QPSK -29=12170,H,40700,Auto,DVB-S,QPSK -30=12535,V,43200,34,DVB-S,QPSK -31=12595,H,43200,34,DVB-S,QPSK -32=12595,V,43200,34,DVB-S,QPSK -33=12647,H,30000,Auto,DVB-S,QPSK -34=12647,V,32700,56,DVB-S,QPSK -35=12688,H,3270,34,DVB-S,QPSK -36=12688,V,27500,56,DVB-S,QPSK -37=12729,H,26400,34,DVB-S,QPSK -38=12729,V,32700,56,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0965.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0965.ini deleted file mode 100644 index 45d28a1fe6..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/0965.ini +++ /dev/null @@ -1,28 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=0965 -2=Express AM33 (96.5E) - -[DVB] -0=19 -1=3675,V,33483,78,DVB-S,QPSK -2=3758,V,4340,34,DVB-S,QPSK -3=3808,V,3215,34,DVB-S,QPSK -4=3817,V,4270,34,DVB-S,QPSK -5=3838,V,3230,34,DVB-S,QPSK -6=3843,V,3220,34,DVB-S,QPSK -7=3875,V,33390,89,S2,8PSK -8=3925,V,4883,12,DVB-S,QPSK -9=4108,V,4275,34,DVB-S,QPSK -10=4114,V,4285,34,DVB-S,QPSK -11=4175,V,3294,34,DVB-S,QPSK -12=10980,H,3200,34,DVB-S,QPSK -13=11000,H,5700,34,DVB-S,QPSK -14=11006,H,4444,34,DVB-S,QPSK -15=11028,V,1666,78,DVB-S,QPSK -16=11053,V,1570,23,S2,8PSK -17=11055,V,1666,23,S2,8PSK -18=11116,V,34000,89,S2,8PSK -19=11117,H,4444,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1005.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1005.ini deleted file mode 100644 index fe9374bcf0..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1005.ini +++ /dev/null @@ -1,80 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1005 -2=AsiaSat 5 (100.5E) - -[DVB] -0=71 -1=3660,V,27500,34,DVB-S,QPSK -2=3668,H,7120,34,DVB-S,QPSK -3=3674,H,1500,34,DVB-S,QPSK -4=3678,H,3600,35,S2,QPSK -5=3686,H,7120,34,S2,8PSK -6=3693,H,6111,34,DVB-S,QPSK -7=3700,V,30000,34,S2,8PSK -8=3707,H,7120,34,S2,8PSK -9=3717,H,4167,34,DVB-S,QPSK -10=3730,H,13800,34,S2,8PSK -11=3733,V,6111,34,DVB-S,QPSK -12=3744,V,7120,34,S2,8PSK -13=3754,V,7120,34,S2,8PSK -14=3760,H,27500,34,DVB-S,QPSK -15=3765,V,4640,34,S2,8PSK -16=3770,V,2644,34,S2,QPSK -17=3774,H,6111,34,DVB-S,QPSK -18=3776,V,6111,34,DVB-S,QPSK -19=3786,H,6000,78,DVB-S,QPSK -20=3794,H,4640,35,S2,8PSK -21=3799,H,3255,34,DVB-S,QPSK -22=3816,H,3624,23,S2,8PSK -23=3820,V,27500,34,DVB-S,QPSK -24=3840,H,26666,34,S2,8PSK -25=3854,H,7500,Auto,S2,QPSK -26=3860,V,30000,23,S2,8PSK -27=3877,H,7200,Auto,S2,8PSK -28=3884,H,7200,Auto,S2,QPSK -29=3886,V,7500,34,DVB-S,QPSK -30=3895,V,6111,34,DVB-S,QPSK -31=3908,H,6666,34,DVB-S,QPSK -32=3913,V,6111,34,DVB-S,QPSK -33=3915,H,7120,Auto,S2,QPSK -34=3924,H,7200,Auto,S2,QPSK -35=3928,V,7200,Auto,S2,QPSK -36=3935,H,7120,34,S2,8PSK -37=3937,V,4500,34,DVB-S,QPSK -38=3945,V,6200,34,DVB-S,QPSK -39=3953,V,7200,Auto,S2,QPSK -40=3960,H,30000,56,S2,8PSK -41=3980,V,29720,56,S2,8PSK -42=4000,H,28125,34,DVB-S,QPSK -43=4040,H,29720,56,S2,8PSK -44=4076,H,7200,Auto,S2,8PSK -45=4086,H,7200,34,S2,8PSK -46=4094,H,9874,Auto,S2,QPSK -47=4114,H,18400,23,S2,8PSK -48=4132,H,10587,23,S2,QPSK -49=4148,H,7100,Auto,S2,QPSK -50=4148,V,11852,34,DVB-S,QPSK -51=4155,H,6666,34,DVB-S,QPSK -52=4165,H,6673,Auto,S2,QPSK -53=4175,H,7200,34,S2,8PSK -54=12267,V,3000,34,DVB-S,QPSK -55=12288,V,1330,34,DVB-S,QPSK -56=12323,V,12000,34,DVB-S,QPSK -57=12377,V,2000,34,DVB-S,QPSK -58=12381,V,2000,34,DVB-S,QPSK -59=12386,V,2000,34,DVB-S,QPSK -60=12437,V,2590,34,DVB-S,QPSK -61=12515,H,6200,34,DVB-S,QPSK -62=12522,V,40700,34,DVB-S,QPSK -63=12542,H,6111,34,DVB-S,QPSK -64=12582,H,5632,34,DVB-S,QPSK -65=12582,V,40700,23,S2,8PSK -66=12591,H,5632,34,DVB-S,QPSK -67=12602,H,5632,34,DVB-S,QPSK -68=12620,H,6300,34,DVB-S,QPSK -69=12635,H,8880,34,DVB-S,QPSK -70=12642,V,40700,23,S2,8PSK -71=12702,V,40700,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1030.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1030.ini deleted file mode 100644 index f4607ef89f..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1030.ini +++ /dev/null @@ -1,13 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1030 -2=Express AM3 (103.0E) - -[DVB] -0=4 -1=3610,V,2500,56,S2,QPSK -2=3675,V,31900,56,S2,8PSK -3=11606,V,34425,35,S2,8PSK -4=11669,V,34425,35,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1055.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1055.ini deleted file mode 100644 index 79c54d9d81..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1055.ini +++ /dev/null @@ -1,57 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1055 -2=AsiaSat 7/8 (105.5E) - -[DVB] -0=48 -1=3683,H,27500,Auto,S2,QPSK -2=3706,H,6000,34,DVB-S,QPSK -3=3712,V,9000,35,S2,8PSK -4=3715,H,8167,34,DVB-S,QPSK -5=3725,V,4833,45,S2,QPSK -6=3729,H,13650,34,DVB-S,QPSK -7=3732,V,6500,34,DVB-S,QPSK -8=3739,V,2815,34,DVB-S,QPSK -9=3742,V,1500,34,DVB-S,QPSK -10=3745,V,2626,34,DVB-S,QPSK -11=3755,V,4418,78,DVB-S,QPSK -12=3760,H,26000,78,DVB-S,QPSK -13=3780,V,28100,34,DVB-S,QPSK -14=3820,V,27500,34,DVB-S,QPSK -15=3840,H,29720,56,S2,8PSK -16=3860,V,28100,56,S2,8PSK -17=3880,H,27500,34,DVB-S,QPSK -18=3890,V,11838,35,S2,8PSK -19=3898,V,2240,35,S2,8PSK -20=3906,V,2913,34,DVB-S,QPSK -21=3915,V,7260,56,DVB-S,QPSK -22=3940,V,28100,56,S2,8PSK -23=3960,H,27500,34,DVB-S,QPSK -24=3980,V,28100,34,DVB-S,QPSK -25=4000,H,26850,78,DVB-S,QPSK -26=4020,V,27250,34,DVB-S,QPSK -27=4040,H,26500,12,DVB-S,QPSK -28=4060,V,26666,34,DVB-S,QPSK -29=4065,H,4296,34,DVB-S,QPSK -30=4078,H,3185,78,DVB-S,QPSK -31=4082,H,3185,56,DVB-S,QPSK -32=4087,H,3185,34,DVB-S,QPSK -33=4091,H,2894,34,DVB-S,QPSK -34=4095,H,2894,34,DVB-S,QPSK -35=4100,V,29720,56,S2,8PSK -36=4120,H,27500,78,DVB-S,QPSK -37=4140,V,27500,34,DVB-S,QPSK -38=4146,H,5317,34,DVB-S,QPSK -39=4155,H,9833,35,S2,8PSK -40=4165,H,5040,34,DVB-S,QPSK -41=4172,H,2480,34,DVB-S,QPSK -42=4176,H,2444,34,DVB-S,QPSK -43=4180,V,26666,34,DVB-S,QPSK -44=12468,H,4195,34,DVB-S,QPSK -45=12534,H,3300,34,S2,8PSK -46=12579,H,4000,34,S2,8PSK -47=12596,V,30000,56,DVB-S,QPSK -48=12720,V,30000,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1082.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1082.ini deleted file mode 100644 index a53b0c2e8b..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1082.ini +++ /dev/null @@ -1,99 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1082 -2=NSS 11/SES 7/Telkom 1 (108.2E) - -[DVB] -0=90 -1=2535,H,22500,78,DVB-S,QPSK -2=2535,V,22500,34,S2,8PSK -3=2565,H,22500,78,DVB-S,QPSK -4=2565,V,22500,78,DVB-S,QPSK -5=2595,H,20000,78,DVB-S,QPSK -6=2595,V,22500,78,DVB-S,QPSK -7=2625,H,22500,78,DVB-S,QPSK -8=2625,V,22500,34,S2,QPSK -9=2655,H,22500,78,DVB-S,QPSK -10=2655,V,22500,Auto,S2,8PSK -11=3483,V,3000,34,DVB-S,QPSK -12=3515,V,23111,23,S2,QPSK -13=3552,H,3100,34,DVB-S,QPSK -14=3580,H,30000,34,S2,8PSK -15=3600,V,30000,34,S2,8PSK -16=3620,H,30000,34,S2,8PSK -17=3640,V,30000,34,S2,8PSK -18=3707,H,6000,34,S2,8PSK -19=3722,H,3330,34,DVB-S,QPSK -20=3727,V,7000,34,DVB-S,QPSK -21=3732,H,4160,34,DVB-S,QPSK -22=3735,H,1200,34,DVB-S,QPSK -23=3745,H,3000,34,DVB-S,QPSK -24=3776,H,4280,34,DVB-S,QPSK -25=3787,H,6750,34,DVB-S,QPSK -26=3793,H,3000,34,DVB-S,QPSK -27=3797,H,3905,34,DVB-S,QPSK -28=3802,H,3000,78,DVB-S,QPSK -29=3812,H,3000,34,DVB-S,QPSK -30=3817,H,3000,34,DVB-S,QPSK -31=3830,H,3000,34,DVB-S,QPSK -32=3880,H,3000,34,S2,8PSK -33=3890,H,6000,34,DVB-S,QPSK -34=3895,H,2500,34,DVB-S,QPSK -35=3913,H,2400,34,DVB-S,QPSK -36=3916,H,3330,34,DVB-S,QPSK -37=3920,H,3000,34,DVB-S,QPSK -38=3947,H,1500,34,DVB-S,QPSK -39=3960,H,3000,34,DVB-S,QPSK -40=3971,H,2100,34,DVB-S,QPSK -41=3981,V,1235,34,DVB-S,QPSK -42=3990,H,6000,34,DVB-S,QPSK -43=3998,H,3000,34,DVB-S,QPSK -44=4004,H,6000,34,DVB-S,QPSK -45=4014,H,6000,34,DVB-S,QPSK -46=4029,H,5122,34,DVB-S,QPSK -47=4036,H,3100,34,DVB-S,QPSK -48=4040,H,3000,34,DVB-S,QPSK -49=4079,H,3100,34,DVB-S,QPSK -50=4086,H,6000,34,DVB-S,QPSK -51=4092,H,3570,34,DVB-S,QPSK -52=4097,H,3125,34,DVB-S,QPSK -53=4130,V,2100,34,DVB-S,QPSK -54=4159,H,3000,34,DVB-S,QPSK -55=4163,V,1840,34,DVB-S,QPSK -56=11480,V,28800,23,S2,8PSK -57=11481,H,18750,34,S2,8PSK -58=11483,H,26600,34,S2,8PSK -59=11510,H,20000,34,S2,8PSK -60=11520,V,30000,34,S2,8PSK -61=11520,H,30000,34,S2,8PSK -62=11560,V,30000,34,S2,8PSK -63=11560,H,30000,34,S2,8PSK -64=11568,V,20000,34,S2,8PSK -65=11568,H,20000,34,S2,8PSK -66=11598,V,20000,34,S2,8PSK -67=11598,H,20000,23,S2,8PSK -68=11600,V,30000,34,S2,8PSK -69=11600,H,30000,34,S2,8PSK -70=11627,H,20000,34,S2,8PSK -71=11640,V,30000,34,S2,8PSK -72=11640,H,24000,34,S2,8PSK -73=11656,H,18750,34,DVB-S,QPSK -74=11680,V,30000,34,S2,8PSK -75=11685,H,18750,34,DVB-S,QPSK -76=12328,H,5000,34,DVB-S,QPSK -77=12401,V,2400,34,S2,8PSK -78=12406,V,3330,56,DVB-S,QPSK -79=12421,V,2962,34,DVB-S,QPSK -80=12427,V,4440,34,DVB-S,QPSK -81=12431,H,30000,56,DVB-S,QPSK -82=12434,H,2000,34,DVB-S,QPSK -83=12439,H,1900,12,DVB-S,QPSK -84=12444,H,1900,34,DVB-S,QPSK -85=12447,H,3000,34,DVB-S,QPSK -86=12471,H,30000,56,DVB-S,QPSK -87=12486,H,2000,34,DVB-S,QPSK -88=12651,V,26667,34,DVB-S,QPSK -89=12711,H,30000,23,S2,8PSK -90=12731,V,30000,56,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1100.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1100.ini deleted file mode 100644 index 789b56cca7..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1100.ini +++ /dev/null @@ -1,33 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1100 -2=BSAT 3A/3C/JCSAT 110R/N-Sat 110 (110.0E) - -[DVB] -0=24 -1=11727,V,28860,23,DVB-S,8PSK -2=11766,V,28860,23,DVB-S,8PSK -3=11804,V,28860,23,DVB-S,8PSK -4=11843,V,28860,23,DVB-S,8PSK -5=11881,V,28860,23,DVB-S,8PSK -6=11919,V,28860,23,DVB-S,8PSK -7=11958,V,28860,23,DVB-S,8PSK -8=11996,V,28860,23,DVB-S,8PSK -9=12034,V,28860,23,DVB-S,QPSK -10=12073,V,28860,23,DVB-S,8PSK -11=12111,V,28860,23,DVB-S,8PSK -12=12149,V,28860,23,DVB-S,8PSK -13=12291,V,28860,23,DVB-S,QPSK -14=12331,V,28860,23,DVB-S,QPSK -15=12371,V,28860,23,DVB-S,QPSK -16=12411,V,28860,23,DVB-S,QPSK -17=12451,V,28860,23,DVB-S,QPSK -18=12491,V,28860,23,DVB-S,QPSK -19=12531,V,28860,23,DVB-S,QPSK -20=12571,V,28860,23,DVB-S,QPSK -21=12611,V,28860,23,DVB-S,QPSK -22=12651,V,28860,23,DVB-S,QPSK -23=12691,V,28860,23,DVB-S,QPSK -24=12731,V,28860,23,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1105.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1105.ini deleted file mode 100644 index aafe004557..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1105.ini +++ /dev/null @@ -1,14 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1105 -2=ChinaSat 10 (110.5E) - -[DVB] -0=5 -1=3650,V,6200,56,S2,8PSK -2=3660,V,6200,56,S2,8PSK -3=3728,V,4340,34,DVB-S,QPSK -4=3984,V,3617,34,DVB-S,QPSK -5=4134,V,4340,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1130.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1130.ini deleted file mode 100644 index d9c69d3f73..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1130.ini +++ /dev/null @@ -1,81 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1130 -2=Koreasat 5/Palapa D (113.0E) - -[DVB] -0=72 -1=3420,H,5000,Auto,S2,QPSK -2=3433,H,4383,56,DVB-S,8PSK -3=3437,H,1800,34,S2,8PSK -4=3460,H,29900,34,S2,QPSK -5=3574,V,6363,78,DVB-S,QPSK -6=3600,V,31000,23,S2,8PSK -7=3628,H,17985,23,DVB-S,QPSK -8=3709,H,10000,35,S2,QPSK -9=3720,H,30000,34,S2,QPSK -10=3744,H,3125,78,DVB-S,QPSK -11=3747,H,6250,34,DVB-S,QPSK -12=3756,H,6250,34,S2,8PSK -13=3762,H,3500,34,DVB-S,QPSK -14=3767,H,4000,45,S2,QPSK -15=3770,V,3000,34,DVB-S,QPSK -16=3774,H,6520,34,DVB-S,QPSK -17=3780,V,29900,34,S2,8PSK -18=3786,H,5632,34,DVB-S,QPSK -19=3792,H,3000,34,DVB-S,8PSK -20=3818,V,27500,34,S2,8PSK -21=3832,H,12592,34,DVB-S,QPSK -22=3852,V,2000,56,DVB-S,QPSK -23=3863,V,4333,34,DVB-S,QPSK -24=3880,H,30000,34,S2,QPSK -25=3917,H,3000,34,DVB-S,QPSK -26=3925,H,2590,34,DVB-S,QPSK -27=3932,V,15800,56,DVB-S,QPSK -28=3934,H,6500,34,DVB-S,QPSK -29=3946,V,7400,56,DVB-S,QPSK -30=3952,V,3000,34,DVB-S,QPSK -31=3957,V,3000,34,DVB-S,QPSK -32=3960,H,30000,34,S2,8PSK -33=3980,V,31000,23,S2,8PSK -34=3984,H,2244,34,S2,8PSK -35=3987,H,2250,34,DVB-S,QPSK -36=3992,H,2250,34,DVB-S,QPSK -37=4006,V,6400,34,DVB-S,QPSK -38=4016,V,3000,34,S2,8PSK -39=4025,H,2124,34,DVB-S,QPSK -40=4035,V,6000,34,DVB-S,QPSK -41=4044,H,2124,34,DVB-S,QPSK -42=4044,V,2833,34,DVB-S,QPSK -43=4048,H,2124,34,DVB-S,QPSK -44=4051,V,1600,56,S2,8PSK -45=4052,H,3333,78,DVB-S,QPSK -46=4055,H,3000,34,DVB-S,QPSK -47=4074,V,3000,34,DVB-S,QPSK -48=4080,H,28125,34,DVB-S,QPSK -49=4100,V,30000,34,S2,8PSK -50=4110,H,11669,34,S2,8PSK -51=4124,H,5632,34,DVB-S,QPSK -52=4136,H,3000,34,DVB-S,QPSK -53=4140,V,30000,78,DVB-S,QPSK -54=4165,H,20000,34,DVB-S,QPSK -55=4171,V,15000,Auto,S2,QPSK -56=4184,V,6700,34,DVB-S,QPSK -57=12347,H,3180,23,S2,8PSK -58=12390,V,25600,56,DVB-S,QPSK -59=12430,V,25600,56,DVB-S,QPSK -60=12436,H,3564,56,DVB-S,QPSK -61=12452,H,2500,56,S2,8PSK -62=12470,V,25600,56,DVB-S,QPSK -63=12530,H,26000,56,DVB-S,QPSK -64=12560,H,2300,23,S2,8PSK -65=12590,H,29900,34,S2,8PSK -66=12590,V,28000,34,DVB-S,QPSK -67=12618,V,3900,12,DVB-S,QPSK -68=12645,V,2893,34,DVB-S,QPSK -69=12665,H,4320,34,S2,8PSK -70=12670,V,28000,34,DVB-S,QPSK -71=12673,H,30000,34,S2,8PSK -72=12710,H,29900,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1155.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1155.ini deleted file mode 100644 index 4bfa662708..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1155.ini +++ /dev/null @@ -1,53 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1155 -2=ChinaSat 6B (115.5E) - -[DVB] -0=44 -1=3600,V,27500,78,DVB-S,QPSK -2=3640,V,27500,78,DVB-S,QPSK -3=3680,V,27500,78,DVB-S,QPSK -4=3709,H,10920,34,DVB-S,QPSK -5=3740,V,27500,34,DVB-S,QPSK -6=3750,H,10490,34,DVB-S,QPSK -7=3769,H,13400,78,DVB-S,QPSK -8=3780,V,27500,34,DVB-S,QPSK -9=3796,H,6930,12,DVB-S,QPSK -10=3807,V,6000,34,DVB-S,QPSK -11=3808,H,8800,34,DVB-S,QPSK -12=3815,V,4420,34,DVB-S,QPSK -13=3825,V,6780,34,DVB-S,QPSK -14=3834,V,5400,34,DVB-S,QPSK -15=3840,H,27500,34,DVB-S,QPSK -16=3846,V,5950,34,DVB-S,QPSK -17=3854,V,4420,34,DVB-S,QPSK -18=3861,V,4800,34,DVB-S,QPSK -19=3871,V,9080,34,DVB-S,QPSK -20=3880,H,27500,34,DVB-S,QPSK -21=3885,V,4340,34,DVB-S,QPSK -22=3892,V,4420,34,DVB-S,QPSK -23=3903,V,9300,34,DVB-S,QPSK -24=3913,V,6400,34,DVB-S,QPSK -25=3920,H,27500,34,DVB-S,QPSK -26=3929,V,8840,34,DVB-S,QPSK -27=3940,V,5948,34,DVB-S,QPSK -28=3950,H,11406,56,DVB-S,QPSK -29=3951,V,9520,34,DVB-S,QPSK -30=3960,H,3570,34,DVB-S,QPSK -31=3971,H,10000,34,DVB-S,QPSK -32=3980,V,27500,34,DVB-S,QPSK -33=4000,H,27500,34,DVB-S,QPSK -34=4020,V,27500,34,DVB-S,QPSK -35=4040,H,27500,34,DVB-S,QPSK -36=4060,V,27500,34,DVB-S,QPSK -37=4080,H,27500,34,DVB-S,QPSK -38=4116,H,21374,34,DVB-S,QPSK -39=4140,V,27500,34,DVB-S,QPSK -40=4147,H,6150,34,DVB-S,QPSK -41=4158,H,8680,34,DVB-S,QPSK -42=4171,H,9200,34,DVB-S,QPSK -43=4175,V,18000,12,DVB-S,QPSK -44=4192,V,6000,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1160.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1160.ini deleted file mode 100644 index 3ef951d9a5..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1160.ini +++ /dev/null @@ -1,42 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1160 -2=ABS 7/Koreasat 6 (116.0E) - -[DVB] -0=33 -1=11747,H,21300,56,S2,8PSK -2=11785,H,21300,78,DVB-S,QPSK -3=11823,H,21300,56,S2,8PSK -4=11862,H,21300,56,S2,8PSK -5=11900,H,21300,23,S2,8PSK -6=11938,H,21300,56,S2,8PSK -7=12290,H,27489,34,S2,8PSK -8=12330,H,27489,34,S2,8PSK -9=12350,V,26700,78,DVB-S,QPSK -10=12370,H,27489,34,S2,8PSK -11=12390,V,26700,78,DVB-S,QPSK -12=12410,H,29500,34,S2,8PSK -13=12430,V,26700,78,DVB-S,QPSK -14=12450,H,27489,34,S2,8PSK -15=12467,V,12300,34,S2,QPSK -16=12490,H,27489,34,S2,8PSK -17=12497,V,4331,34,S2,8PSK -18=12501,V,3515,34,DVB-S,QPSK -19=12506,V,3515,34,DVB-S,QPSK -20=12511,V,3515,34,DVB-S,QPSK -21=12517,V,3515,34,DVB-S,QPSK -22=12523,V,7900,56,S2,8PSK -23=12530,H,27489,34,S2,8PSK -24=12570,H,27489,34,S2,8PSK -25=12610,H,27489,34,S2,8PSK -26=12650,H,27489,34,S2,8PSK -27=12670,V,26700,78,DVB-S,QPSK -28=12687,H,2050,34,DVB-S,QPSK -29=12690,H,27489,34,S2,8PSK -30=12695,V,3515,34,DVB-S,QPSK -31=12706,V,6000,34,DVB-S,QPSK -32=12724,V,5330,34,S2,8PSK -33=12730,H,27489,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1180.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1180.ini deleted file mode 100644 index d41e3f5ad2..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1180.ini +++ /dev/null @@ -1,11 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1180 -2=Telkom 2 (118.0E) - -[DVB] -0=2 -1=3776,H,2132,34,DVB-S,QPSK -2=4110,H,2900,12,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1195.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1195.ini deleted file mode 100644 index 42af4d1c98..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1195.ini +++ /dev/null @@ -1,14 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1195 -2=Thaicom 4 (119.5E) - -[DVB] -0=5 -1=11542,V,15533,Auto,S2,QPSK -2=11592,V,25000,12,S2,QPSK -3=11675,V,45000,23,S2,8PSK -4=12696,V,30000,23,S2,QPSK -5=12732,V,30000,23,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1222.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1222.ini deleted file mode 100644 index 4d833f21bb..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1222.ini +++ /dev/null @@ -1,29 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1222 -2=AsiaSat 4 (122.2E) - -[DVB] -0=20 -1=3756,H,21600,23,S2,8PSK -2=3827,H,6620,34,DVB-S,QPSK -3=3845,H,6620,34,DVB-S,QPSK -4=3900,V,26660,23,DVB-S,QPSK -5=4040,H,4000,34,DVB-S,QPSK -6=4157,H,2170,34,DVB-S,QPSK -7=4160,H,2300,34,S2,8PSK -8=4164,H,5037,78,DVB-S,QPSK -9=11727,V,25000,23,S2,8PSK -10=11766,V,27500,23,S2,8PSK -11=11804,V,27500,23,S2,8PSK -12=11881,V,275000,23,S2,8PSK -13=11958,V,27500,23,S2,8PSK -14=12034,V,27500,23,S2,8PSK -15=12274,V,6000,34,DVB-S,QPSK -16=12414,V,43200,23,S2,QPSK -17=12536,V,4800,56,S2,8PSK -18=12545,V,2400,34,S2,8PSK -19=12590,V,6620,34,DVB-S,QPSK -20=12743,H,10000,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1240.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1240.ini deleted file mode 100644 index ed948c78ea..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1240.ini +++ /dev/null @@ -1,43 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1240 -2=JCSAT 4B (124.0E) - -[DVB] -0=34 -1=12268,V,23303,35,S2,8PSK -2=12313,H,23303,35,S2,8PSK -3=12330,H,30000,56,S2,8PSK -4=12343,H,23303,35,S2,8PSK -5=12358,V,23303,35,S2,8PSK -6=12370,H,30000,56,S2,8PSK -7=12373,H,23303,35,S2,8PSK -8=12388,V,23303,35,S2,8PSK -9=12410,H,30000,56,S2,8PSK -10=12418,V,23303,35,S2,8PSK -11=12432,H,23303,35,S2,8PSK -12=12448,V,21096,34,DVB-S,QPSK -13=12450,H,30000,56,S2,8PSK -14=12490,H,30000,56,S2,8PSK -15=12493,H,23303,35,S2,8PSK -16=12508,V,23303,35,S2,8PSK -17=12530,H,30000,56,S2,8PSK -18=12538,V,23303,35,S2,8PSK -19=12553,H,23303,35,S2,8PSK -20=12568,V,23303,35,S2,8PSK -21=12570,H,30000,56,S2,8PSK -22=12583,H,23303,35,S2,8PSK -23=12598,V,23303,35,S2,8PSK -24=12610,H,30000,56,S2,8PSK -25=12613,H,23303,35,S2,8PSK -26=12628,V,23303,35,S2,8PSK -27=12643,H,23303,35,S2,8PSK -28=12650,H,30000,56,S2,8PSK -29=12673,H,23303,35,S2,8PSK -30=12688,V,23303,35,S2,8PSK -31=12690,H,30000,56,S2,8PSK -32=12703,H,23303,35,S2,8PSK -33=12718,V,23303,35,S2,8PSK -34=12730,H,30000,56,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1250.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1250.ini deleted file mode 100644 index 738a7debe7..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1250.ini +++ /dev/null @@ -1,38 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1250 -2=ChinaSat 6A (125.0E) - -[DVB] -0=29 -1=3720,H,27500,34,DVB-S,QPSK -2=3740,V,27500,34,DVB-S,QPSK -3=3750,H,14900,34,DVB-S,QPSK -4=3780,V,27500,34,DVB-S,QPSK -5=3800,H,30600,34,DVB-S,QPSK -6=3820,V,30000,34,DVB-S,QPSK -7=3827,H,6220,34,DVB-S,QPSK -8=3845,H,17778,34,DVB-S,QPSK -9=3857,V,25000,34,DVB-S,QPSK -10=3885,H,5720,34,DVB-S,QPSK -11=3889,V,9988,34,DVB-S,QPSK -12=3893,H,6880,34,DVB-S,QPSK -13=3909,H,8934,34,DVB-S,QPSK -14=3912,V,9900,34,DVB-S,QPSK -15=3922,H,7250,34,DVB-S,QPSK -16=3933,H,6590,34,DVB-S,QPSK -17=3951,H,13400,78,DVB-S,QPSK -18=3970,H,11580,34,DVB-S,QPSK -19=3970,V,13400,78,DVB-S,QPSK -20=3989,H,9070,34,DVB-S,QPSK -21=3999,H,4420,34,DVB-S,QPSK -22=4006,H,4420,34,DVB-S,QPSK -23=4013,H,3950,34,DVB-S,QPSK -24=4013,V,16600,78,DVB-S,QPSK -25=4033,V,9580,78,DVB-S,QPSK -26=4040,H,30600,34,DVB-S,QPSK -27=4080,H,27500,34,DVB-S,QPSK -28=4100,V,27500,34,DVB-S,QPSK -29=4120,H,27500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1280.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1280.ini deleted file mode 100644 index bb2f556c08..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1280.ini +++ /dev/null @@ -1,24 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1280 -2=JCSAT 3A (128.0E) - -[DVB] -0=15 -1=4120,V,30000,34,S2,8PSK -2=4160,V,30000,34,S2,8PSK -3=12348,V,23303,35,S2,8PSK -4=12428,V,23303,35,S2,8PSK -5=12468,V,23303,35,S2,8PSK -6=12523,H,23303,35,S2,8PSK -7=12553,H,23303,35,S2,8PSK -8=12583,H,23303,35,S2,8PSK -9=12598,V,23303,35,S2,8PSK -10=12613,H,23303,35,S2,8PSK -11=12628,V,21096,34,DVB-S,QPSK -12=12643,H,23303,35,S2,8PSK -13=12673,H,23303,35,S2,8PSK -14=12703,H,23303,35,S2,8PSK -15=12733,H,23303,35,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1320.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1320.ini deleted file mode 100644 index 4694425d39..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1320.ini +++ /dev/null @@ -1,51 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1320 -2=JCSAT 5A/Vinasat 1/2 (132.0E) - -[DVB] -0=42 -1=3413,V,10800,23,S2,8PSK -2=3433,V,13600,34,S2,8PSK -3=3446,V,1666,34,S2,8PSK -4=3451,V,1668,23,S2,8PSK -5=3480,V,3000,34,S2,8PSK -6=3493,H,1600,34,DVB-S,QPSK -7=3544,V,1600,34,S2,8PSK -8=3549,V,1200,34,S2,8PSK -9=3560,V,1510,34,DVB-S,QPSK -10=3572,V,8000,23,S2,8PSK -11=3590,V,19200,23,S2,8PSK -12=10968,H,28800,34,S2,8PSK -13=11008,H,28800,34,S2,8PSK -14=11048,H,28800,56,DVB-S,QPSK -15=11050,V,30000,34,S2,8PSK -16=11085,H,24000,34,S2,8PSK -17=11088,V,28800,34,S2,8PSK -18=11119,V,14400,34,S2,8PSK -19=11135,H,9600,34,S2,8PSK -20=11167,V,30000,34,S2,8PSK -21=11472,H,23200,34,S2,8PSK -22=11510,V,30000,34,S2,8PSK -23=11517,H,4702,34,DVB-S,QPSK -24=11523,H,4702,34,DVB-S,QPSK -25=11531,H,2500,34,DVB-S,QPSK -26=11549,H,28500,56,DVB-S,QPSK -27=11550,V,30000,34,S2,8PSK -28=11589,H,28800,34,DVB-S,QPSK -29=11590,V,30000,34,S2,8PSK -30=11629,H,28800,34,DVB-S,QPSK -31=11630,V,30000,34,S2,8PSK -32=11669,H,30000,34,S2,8PSK -33=11670,V,30000,34,S2,8PSK -34=12257,V,3096,34,DVB-S,QPSK -35=12288,H,7241,34,DVB-S,QPSK -36=12320,V,7241,34,DVB-S,QPSK -37=12340,H,7241,34,DVB-S,QPSK -38=12400,V,7241,34,DVB-S,QPSK -39=12408,H,7241,34,DVB-S,QPSK -40=12420,H,7241,34,DVB-S,QPSK -41=12711,V,19476,12,S2,8PSK -42=12746,H,3096,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1340.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1340.ini deleted file mode 100644 index 4ca7c83a01..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1340.ini +++ /dev/null @@ -1,27 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1340 -2=Apstar 6 (134.0E) - -[DVB] -0=18 -1=3720,H,30000,Auto,S2,QPSK -2=3776,H,5632,34,DVB-S,QPSK -3=3830,V,3700,34,S2,8PSK -4=3840,H,27500,34,DVB-S,QPSK -5=3878,H,3000,34,DVB-S,QPSK -6=3913,V,1920,45,S2,QPSK -7=4020,V,30000,34,S2,8PSK -8=4032,H,2688,34,S2,8PSK -9=4051,H,9628,34,DVB-S,QPSK -10=4149,H,13500,34,DVB-S,QPSK -11=4160,H,2963,34,DVB-S,QPSK -12=12269,V,18000,12,DVB-S,QPSK -13=12322,V,3600,34,DVB-S,QPSK -14=12395,V,27500,34,DVB-S,QPSK -15=12435,V,27500,34,DVB-S,QPSK -16=12515,V,27500,34,DVB-S,QPSK -17=12595,V,27500,34,DVB-S,QPSK -18=12675,V,27500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1380.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1380.ini deleted file mode 100644 index cb952425b2..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1380.ini +++ /dev/null @@ -1,37 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1380 -2=Telstar 18 (138.0E) - -[DVB] -0=28 -1=3703,V,4444,23,S2,8PSK -2=3707,H,4500,34,S2,8PSK -3=3734,H,2222,34,S2,8PSK -4=3820,V,30000,34,S2,8PSK -5=3837,H,2200,34,DVB-S,QPSK -6=3847,H,4444,34,S2,8PSK -7=3854,H,6700,34,DVB-S,QPSK -8=3866,H,4290,34,DVB-S,QPSK -9=3872,H,6660,34,DVB-S,QPSK -10=3933,V,3000,34,DVB-S,QPSK -11=3948,V,17600,34,S2,8PSK -12=12272,H,33333,23,S2,8PSK -13=12292,V,45000,Auto,S2,8PSK -14=12354,V,43000,34,DVB-S,QPSK -15=12401,V,22425,34,DVB-S,QPSK -16=12429,H,3330,12,DVB-S,QPSK -17=12430,V,22425,56,S2,8PSK -18=12439,H,2500,34,DVB-S,QPSK -19=12443,H,1495,34,DVB-S,QPSK -20=12472,V,33500,34,S2,8PSK -21=12499,V,7200,34,S2,8PSK -22=12507,H,45000,23,S2,8PSK -23=12538,V,41250,12,DVB-S,QPSK -24=12598,V,43000,34,S2,8PSK -25=12629,H,43200,34,S2,8PSK -26=12660,V,45000,56,DVB-S,QPSK -27=12690,H,43200,34,S2,8PSK -28=12721,V,41250,12,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1400.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1400.ini deleted file mode 100644 index b4e6dc7c0c..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1400.ini +++ /dev/null @@ -1,31 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1400 -2=Express AM5/AT2 (140.0E) - -[DVB] -0=22 -1=3571,V,3000,34,DVB-S,QPSK -2=3577,V,4285,34,DVB-S,QPSK -3=3584,V,3000,34,DVB-S,QPSK -4=3589,V,4340,34,DVB-S,QPSK -5=3609,V,4340,34,DVB-S,QPSK -6=3627,V,4340,34,DVB-S,QPSK -7=3632,V,4340,34,DVB-S,QPSK -8=3639,V,1000,34,DVB-S,QPSK -9=3675,V,33483,78,DVB-S,QPSK -10=3874,V,3200,34,DVB-S,QPSK -11=4180,V,4340,34,DVB-S,QPSK -12=10981,V,44948,56,DVB-S,QPSK -13=11082,H,2500,56,S2,8PSK -14=11104,V,3617,34,S2,8PSK -15=11495,V,10600,34,S2,8PSK -16=11530,H,22250,23,S2,8PSK -17=11557,H,22250,23,S2,8PSK -18=11657,V,24800,56,DVB-S,QPSK -19=11681,V,15520,23,S2,8PSK -20=12188,H,27500,34,DVB-S,QPSK -21=12207,V,27500,34,S2,8PSK -22=12341,H,27500,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1440.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1440.ini deleted file mode 100644 index e31e028abf..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1440.ini +++ /dev/null @@ -1,22 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1440 -2=Superbird C2 (144.0E) - -[DVB] -0=13 -1=12276,V,7457,23,S2,8PSK -2=12306,V,7457,23,S2,8PSK -3=12319,V,14910,34,DVB-S,QPSK -4=12336,V,7457,23,S2,QPSK -5=12385,V,7457,23,S2,8PSK -6=12394,V,7457,23,S2,QPSK -7=12403,V,7457,23,S2,8PSK -8=12508,V,21096,34,DVB-S,QPSK -9=12546,H,9365,35,S2,8PSK -10=12549,V,2900,34,DVB-S,QPSK -11=12558,V,3515,34,DVB-S,QPSK -12=12598,V,21096,34,DVB-S,QPSK -13=12658,V,21096,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1500.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1500.ini deleted file mode 100644 index 6acfb16798..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1500.ini +++ /dev/null @@ -1,12 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1500 -2=JCSAT 1B (150.0E) - -[DVB] -0=3 -1=12423,V,6912,12,DVB-S,QPSK -2=12662,V,12825,34,DVB-S,QPSK -3=12693,V,12825,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1520.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1520.ini deleted file mode 100644 index 0034b3e138..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1520.ini +++ /dev/null @@ -1,25 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1520 -2=Optus D2 (152.0E) - -[DVB] -0=16 -1=12274,V,6670,34,DVB-S,QPSK -2=12295,V,1644,Auto,DVB-S,QPSK -3=12328,V,15000,78,DVB-S,QPSK -4=12469,H,6670,Auto,DVB-S,QPSK -5=12519,V,22500,34,DVB-S,QPSK -6=12536,H,6980,34,DVB-S,QPSK -7=12545,H,6980,34,DVB-S,QPSK -8=12546,V,22500,34,DVB-S,QPSK -9=12554,H,6980,34,DVB-S,QPSK -10=12581,H,22500,34,DVB-S,QPSK -11=12608,H,22500,34,DVB-S,QPSK -12=12639,V,15000,78,DVB-S,QPSK -13=12657,V,15000,78,DVB-S,QPSK -14=12675,V,15000,78,DVB-S,QPSK -15=12706,V,22500,34,DVB-S,QPSK -16=12734,V,22500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1540.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1540.ini deleted file mode 100644 index 365575a8ce..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1540.ini +++ /dev/null @@ -1,32 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1540 -2=JCSAT 2A (154.0E) - -[DVB] -0=23 -1=3936,V,3333,34,DVB-S,QPSK -2=12263,V,5082,34,DVB-S,QPSK -3=12278,V,4820,34,DVB-S,QPSK -4=12280,H,4820,34,DVB-S,QPSK -5=12298,V,21096,34,DVB-S,QPSK -6=12310,H,3515,34,S2,8PSK -7=12317,H,6036,35,S2,QPSK -8=12318,V,4820,34,DVB-S,QPSK -9=12324,V,4820,34,DVB-S,QPSK -10=12331,V,4820,34,DVB-S,QPSK -11=12338,V,4820,34,DVB-S,QPSK -12=12362,V,4820,34,DVB-S,QPSK -13=12373,H,7082,34,S2,8PSK -14=12376,V,1680,34,S2,QPSK -15=12409,V,4820,34,DVB-S,QPSK -16=12436,H,3100,34,DVB-S,QPSK -17=12505,H,2856,23,S2,8PSK -18=12505,V,4821,34,DVB-S,QPSK -19=12576,V,7242,34,DVB-S,QPSK -20=12613,H,21096,34,DVB-S,QPSK -21=12688,V,21096,34,DVB-S,QPSK -22=12700,H,5274,34,DVB-S,QPSK -23=12729,V,3096,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1560.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1560.ini deleted file mode 100644 index be5b9c2f69..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1560.ini +++ /dev/null @@ -1,44 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1560 -2=Optus C1/D3 (156.0E) - -[DVB] -0=35 -1=11720,H,29455,35,S2,8PSK -2=11762,H,27800,34,DVB-S,QPSK -3=11804,V,30000,35,S2,8PSK -4=11845,V,27800,Auto,DVB-S,QPSK -5=11886,V,30000,35,S2,8PSK -6=11886,H,27800,34,DVB-S,QPSK -7=11928,V,30000,35,S2,8PSK -8=11928,H,27800,34,DVB-S,QPSK -9=11970,H,27800,34,DVB-S,QPSK -10=12011,V,27800,34,DVB-S,QPSK -11=12011,H,29455,35,S2,8PSK -12=12052,V,27800,34,DVB-S,QPSK -13=12052,H,29455,35,S2,8PSK -14=12094,V,27800,34,DVB-S,QPSK -15=12094,H,29455,35,S2,8PSK -16=12136,V,27800,34,DVB-S,QPSK -17=12136,H,27800,34,DVB-S,QPSK -18=12177,V,27800,34,DVB-S,QPSK -19=12177,H,27800,34,DVB-S,QPSK -20=12358,H,27800,34,DVB-S,QPSK -21=12369,V,30000,35,S2,8PSK -22=12398,H,27800,34,DVB-S,QPSK -23=12407,V,24450,Auto,DVB-S,QPSK -24=12438,H,27800,34,DVB-S,QPSK -25=12478,H,27800,34,DVB-S,QPSK -26=12487,V,30000,35,S2,8PSK -27=12518,H,27800,34,DVB-S,QPSK -28=12558,H,27800,34,DVB-S,QPSK -29=12567,V,30000,35,S2,8PSK -30=12598,H,27800,34,DVB-S,QPSK -31=12607,V,30000,35,S2,8PSK -32=12638,H,27800,34,DVB-S,QPSK -33=12647,V,30000,35,S2,8PSK -34=12689,H,27800,34,DVB-S,QPSK -35=12707,H,22500,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1590.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1590.ini deleted file mode 100644 index 567b3cc09e..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1590.ini +++ /dev/null @@ -1,14 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1590 -2=ABS 6 (159.0E) - -[DVB] -0=5 -1=3888,V,8340,23,DVB-S,QPSK -2=3897,V,4445,34,DVB-S,QPSK -3=3908,V,4445,34,DVB-S,QPSK -4=3915,V,4445,34,DVB-S,QPSK -5=12696,V,10000,12,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1600 OPTUS D1 FTA (160.0E).ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1600 OPTUS D1 FTA (160.0E).ini deleted file mode 100644 index 8650617397..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1600 OPTUS D1 FTA (160.0E).ini +++ /dev/null @@ -1,11 +0,0 @@ -[SATTYPE] -1=1600.0 -2=OPTUS D1 FTA (160.0E) - -[DVB] -0=5 -1=12456,H,22500,0 -2=12483,H,22500,0 -3=12644,H,22500,0 -4=12707,H,22500,0 -5=12381,V,3750,23,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1600.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1600.ini deleted file mode 100644 index 08083f62f2..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1600.ini +++ /dev/null @@ -1,47 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1600 -2=Optus D1 (160.0E) - -[DVB] -0=38 -1=12267,H,22500,23,S2,8PSK -2=12295,H,22500,34,S2,8PSK -3=12331,H,22500,23,S2,8PSK -4=12348,H,14293,78,DVB-S,QPSK -5=12358,H,22500,23,S2,8PSK -6=12381,V,3750,23,S2,QPSK -7=12394,H,22500,34,DVB-S,QPSK -8=12421,H,22500,34,DVB-S,QPSK -9=12430,V,6111,Auto,DVB-S,QPSK -10=12452,H,12600,56,DVB-S,QPSK -11=12456,H,22500,34,DVB-S,QPSK -12=12470,H,12600,56,DVB-S,QPSK -13=12483,H,22500,34,DVB-S,QPSK -14=12487,H,12600,56,DVB-S,QPSK -15=12514,H,14294,78,DVB-S,QPSK -16=12519,H,22500,34,DVB-S,QPSK -17=12528,V,6660,Auto,DVB-S,QPSK -18=12532,H,14294,78,DVB-S,QPSK -19=12546,V,6670,Auto,DVB-S,QPSK -20=12546,H,22500,34,DVB-S,QPSK -21=12550,H,14294,78,DVB-S,QPSK -22=12556,V,6670,Auto,DVB-S,QPSK -23=12577,H,14294,78,DVB-S,QPSK -24=12581,H,22500,34,DVB-S,QPSK -25=12595,H,14294,78,DVB-S,QPSK -26=12607,V,7177,Auto,DVB-S,QPSK -27=12608,H,22500,34,DVB-S,QPSK -28=12613,H,14294,78,DVB-S,QPSK -29=12637,V,5100,Auto,DVB-S,QPSK -30=12644,H,22500,34,DVB-S,QPSK -31=12661,V,7200,Auto,DVB-S,QPSK -32=12670,V,7200,Auto,DVB-S,QPSK -33=12671,H,22500,34,DVB-S,QPSK -34=12679,V,7200,Auto,DVB-S,QPSK -35=12681,H,7200,34,DVB-S,QPSK -36=12699,H,7200,34,DVB-S,QPSK -37=12707,H,22500,34,DVB-S,QPSK -38=12734,H,22500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1620.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1620.ini deleted file mode 100644 index 9a16504dc5..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1620.ini +++ /dev/null @@ -1,32 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1620 -2=Superbird B2 (162.0E) - -[DVB] -0=23 -1=12277,V,6150,34,DVB-S,QPSK -2=12286,V,6150,34,DVB-S,QPSK -3=12295,V,6150,34,DVB-S,QPSK -4=12304,V,6150,34,DVB-S,QPSK -5=12373,V,4095,34,DVB-S,QPSK -6=12382,H,14143,56,S2,QPSK -7=12384,V,4095,34,DVB-S,QPSK -8=12423,V,6143,35,S2,8PSK -9=12440,V,11708,34,S2,QPSK -10=12455,H,4095,34,DVB-S,QPSK -11=12500,H,10000,23,DVB-S,QPSK -12=12523,V,6428,34,DVB-S,QPSK -13=12526,H,5274,34,DVB-S,QPSK -14=12535,H,5274,34,DVB-S,QPSK -15=12543,H,5274,34,DVB-S,QPSK -16=12550,H,5274,34,DVB-S,QPSK -17=12557,V,5275,34,DVB-S,QPSK -18=12596,V,6620,34,DVB-S,QPSK -19=12644,H,5275,34,DVB-S,QPSK -20=12656,V,5275,34,DVB-S,QPSK -21=12664,V,5275,34,DVB-S,QPSK -22=12676,H,6144,34,DVB-S,QPSK -23=12724,H,7072,34,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1640.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1640.ini deleted file mode 100644 index 9650ab47a0..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1640.ini +++ /dev/null @@ -1,12 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1640 -2=Optus 10/B3 (164.0E) - -[DVB] -0=3 -1=12345,V,7200,Auto,DVB-S,QPSK -2=12388,H,7200,Auto,DVB-S,QPSK -3=12463,V,7200,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1660.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1660.ini deleted file mode 100644 index 8c040e8841..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1660.ini +++ /dev/null @@ -1,52 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1660 -2=Intelsat 19 (166.0E) - -[DVB] -0=43 -1=3705,V,3000,78,DVB-S,QPSK -2=3719,V,1620,56,S2,8PSK -3=3724,V,5185,34,DVB-S,QPSK -4=3736,V,2963,34,DVB-S,QPSK -5=3740,H,27500,34,DVB-S,QPSK -6=3760,V,27690,34,DVB-S,QPSK -7=3780,H,25000,34,DVB-S,QPSK -8=3784,V,1464,35,S2,8PSK -9=3795,V,3500,34,DVB-S,QPSK -10=3800,V,3500,34,DVB-S,QPSK -11=3805,V,3960,34,S2,QPSK -12=3810,H,15000,Auto,S2,8PSK -13=3815,V,4400,34,DVB-S,QPSK -14=3851,V,9950,34,DVB-S,QPSK -15=3900,H,30000,23,S2,8PSK -16=3920,V,28800,12,S2,QPSK -17=3940,H,27690,78,DVB-S,QPSK -18=3959,V,7090,34,DVB-S,QPSK -19=3980,H,27690,34,DVB-S,QPSK -20=4040,V,30000,34,S2,8PSK -21=4060,H,26590,12,DVB-S,QPSK -22=4080,V,28270,23,S2,8PSK -23=4086,H,5787,34,DVB-S,QPSK -24=4096,H,5787,34,DVB-S,QPSK -25=4146,V,5632,34,DVB-S,QPSK -26=4165,V,3448,35,S2,QPSK -27=4180,H,30000,23,S2,8PSK -28=12286,H,30000,34,S2,QPSK -29=12390,H,7200,23,S2,8PSK -30=12399,H,7200,23,S2,8PSK -31=12407,H,29500,34,S2,8PSK -32=12412,V,14400,Auto,S2,8PSK -33=12432,H,5632,Auto,DVB-S,QPSK -34=12480,V,6666,Auto,DVB-S,QPSK -35=12495,H,15000,23,S2,8PSK -36=12526,H,30000,34,S2,8PSK -37=12557,H,15000,34,S2,8PSK -38=12575,H,13845,23,DVB-S,QPSK -39=12592,H,2894,34,DVB-S,QPSK -40=12613,H,2222,12,DVB-S,QPSK -41=12646,H,28066,34,DVB-S,QPSK -42=12686,H,28124,34,DVB-S,QPSK -43=12726,H,28066,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1690.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1690.ini deleted file mode 100644 index c7470a5e4a..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1690.ini +++ /dev/null @@ -1,14 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1690 -2=Intelsat 8 (169.0E) - -[DVB] -0=5 -1=3771,H,13234,Auto,S2,QPSK -2=3809,V,4286,34,DVB-S,QPSK -3=3815,V,4286,34,DVB-S,QPSK -4=3816,H,6620,34,DVB-S,QPSK -5=4032,H,8545,23,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1720.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1720.ini deleted file mode 100644 index 6f0a6f0ea1..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1720.ini +++ /dev/null @@ -1,17 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1720 -2=Eutelsat 172A (172.0E) - -[DVB] -0=8 -1=3916,H,3330,34,DVB-S,QPSK -2=11515,V,2500,89,S2,QPSK -3=11537,V,1500,Auto,S2,QPSK -4=11623,V,3500,89,S2,QPSK -5=11646,V,2200,Auto,S2,QPSK -6=12716,V,7200,34,DVB-S,QPSK -7=12725,V,7200,34,DVB-S,QPSK -8=12734,V,7200,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1800.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1800.ini deleted file mode 100644 index a3f5044cfb..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1800.ini +++ /dev/null @@ -1,19 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1800 -2=Intelsat 18 (180.0E) - -[DVB] -0=10 -1=3753,V,28000,34,DVB-S,QPSK -2=4015,H,30000,Auto,S2,QPSK -3=4070,V,3443,34,S2,QPSK -4=4095,H,30000,Auto,S2,QPSK -5=4174,H,3680,23,DVB-S,QPSK -6=10995,H,45000,34,S2,QPSK -7=11075,V,45000,34,S2,8PSK -8=11075,H,45000,34,S2,QPSK -9=11155,V,28588,34,S2,8PSK -10=11155,H,28588,56,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1830.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1830.ini deleted file mode 100644 index 8775bb5d3e..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/1830.ini +++ /dev/null @@ -1,18 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=1830 -2=NSS 9/Yamal 300K (177.0W) - -[DVB] -0=9 -1=3792,V,2048,23,S2,QPSK -2=3922,V,1122,56,S2,QPSK -3=3976,H,30000,23,DVB-S,QPSK -4=3987,V,8950,23,DVB-S,QPSK -5=3999,V,2960,34,DVB-S,QPSK -6=4055,H,30000,34,DVB-S,QPSK -7=4103,V,15196,56,S2,QPSK -8=4152,V,2127,Auto,DVB-S,QPSK -9=4163,V,2644,34,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2210.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2210.ini deleted file mode 100644 index 123055dd4c..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2210.ini +++ /dev/null @@ -1,12 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2210 -2=AMC 8 (139.0W) - -[DVB] -0=3 -1=3756,V,2100,34,DVB-S,QPSK -2=4056,H,13250,34,DVB-S,QPSK -3=4111,V,5000,23,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2230.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2230.ini deleted file mode 100644 index fe661385bb..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2230.ini +++ /dev/null @@ -1,11 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2230 -2=AMC 7 (137.0W) - -[DVB] -0=2 -1=3760,H,25195,34,DVB-S,QPSK -2=4100,V,6500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2250.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2250.ini deleted file mode 100644 index 4f5a9494da..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2250.ini +++ /dev/null @@ -1,25 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2250 -2=AMC 10 (135.0W) - -[DVB] -0=16 -1=3720,V,30000,56,S2,8PSK -2=3760,V,30000,56,S2,8PSK -3=3780,H,29200,34,DVB-S,QPSK -4=3800,V,30000,56,S2,QPSK -5=3820,H,29270,34,DVB-S,QPSK -6=3840,V,29270,34,DVB-S,QPSK -7=3900,H,29270,34,DVB-S,QPSK -8=3920,V,29270,34,DVB-S,QPSK -9=3960,V,29270,34,DVB-S,QPSK -10=3980,H,29270,34,DVB-S,QPSK -11=4040,V,30000,56,S2,8PSK -12=4080,V,29270,34,DVB-S,QPSK -13=4120,V,30000,34,S2,8PSK -14=4136,H,19510,34,DVB-S,QPSK -15=4149,H,9760,34,DVB-S,QPSK -16=4180,H,29270,78,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2270.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2270.ini deleted file mode 100644 index 18a777c4b7..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2270.ini +++ /dev/null @@ -1,32 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2270 -2=Galaxy 15 (133.0W) - -[DVB] -0=23 -1=3720,H,29270,56,DVB-S,QPSK -2=3740,V,31250,34,S2,8PSK -3=3760,H,19510,34,DVB-S,QPSK -4=3780,V,31250,34,S2,8PSK -5=3790,H,11936,34,DVB-S,QPSK -6=3808,H,16303,34,S2,8PSK -7=3825,V,13800,56,DVB-S,QPSK -8=3840,H,29270,34,DVB-S,QPSK -9=3860,V,28000,34,DVB-S,QPSK -10=3900,V,31250,34,S2,8PSK -11=3960,H,19510,34,DVB-S,QPSK -12=3980,V,29270,34,DVB-S,QPSK -13=4000,H,30000,56,S2,8PSK -14=4020,V,29270,Auto,DVB-S,QPSK -15=4025,H,4880,34,DVB-S,QPSK -16=4044,H,22500,56,S2,8PSK -17=4060,V,29270,78,DVB-S,QPSK -18=4080,H,30000,56,S2,8PSK -19=4100,V,31250,34,S2,8PSK -20=4120,H,31250,34,S2,8PSK -21=4140,V,31250,34,S2,8PSK -22=4160,H,29270,78,DVB-S,QPSK -23=4180,V,29270,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2290.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2290.ini deleted file mode 100644 index 631af13d23..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2290.ini +++ /dev/null @@ -1,32 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2290 -2=AMC 11 (131.0W) - -[DVB] -0=23 -1=3760,V,19510,34,DVB-S,QPSK -2=3780,H,29270,34,DVB-S,QPSK -3=3790,V,12400,78,DVB-S,QPSK -4=3808,V,15800,56,S2,8PSK -5=3860,H,30000,56,S2,8PSK -6=3880,V,19510,34,DVB-S,QPSK -7=3900,H,30000,56,S2,QPSK -8=3910,V,13200,56,DVB-S,8PSK -9=3928,V,14323,56,DVB-S,QPSK -10=3940,H,29270,34,DVB-S,QPSK -11=3960,V,30000,34,S2,8PSK -12=3980,H,30000,56,S2,8PSK -13=3995,V,19510,34,DVB-S,QPSK -14=4020,H,29270,34,DVB-S,QPSK -15=4040,V,29270,34,DVB-S,QPSK -16=4060,H,29270,34,DVB-S,QPSK -17=4075,V,19510,34,DVB-S,QPSK -18=4092,V,9760,34,DVB-S,QPSK -19=4100,H,30000,56,S2,8PSK -20=4120,V,30000,56,S2,8PSK -21=4140,H,19510,34,DVB-S,QPSK -22=4160,V,29200,34,DVB-S,QPSK -23=4180,H,29270,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2310.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2310.ini deleted file mode 100644 index 5915c23650..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2310.ini +++ /dev/null @@ -1,41 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2310 -2=Ciel 2/Galaxy 12 (129.0W) - -[DVB] -0=32 -1=12224,V,21500,23,DVB-S,8PSK -2=12239,H,21500,23,DVB-S,8PSK -3=12253,V,21500,23,DVB-S,8PSK -4=12268,H,21500,23,DVB-S,8PSK -5=12282,V,21500,23,DVB-S,8PSK -6=12297,H,21500,23,DVB-S,8PSK -7=12311,V,21500,23,DVB-S,8PSK -8=12326,H,21500,23,DVB-S,8PSK -9=12341,V,21500,23,DVB-S,8PSK -10=12355,H,21500,23,DVB-S,8PSK -11=12370,V,21500,23,DVB-S,8PSK -12=12384,H,21500,23,DVB-S,8PSK -13=12399,V,20000,78,DVB-S,8PSK -14=12414,H,21500,23,DVB-S,8PSK -15=12428,V,21500,23,DVB-S,8PSK -16=12443,H,21500,23,DVB-S,8PSK -17=12457,V,21500,23,DVB-S,8PSK -18=12472,H,21500,23,DVB-S,8PSK -19=12486,V,21500,23,DVB-S,8PSK -20=12501,H,21500,23,DVB-S,8PSK -21=12516,V,20000,56,DVB-S,QPSK -22=12530,H,21500,23,DVB-S,8PSK -23=12545,V,21500,23,DVB-S,8PSK -24=12559,H,21500,23,DVB-S,8PSK -25=12574,V,21500,23,DVB-S,8PSK -26=12588,H,21500,23,DVB-S,8PSK -27=12603,V,21500,23,DVB-S,8PSK -28=12618,H,21500,23,DVB-S,8PSK -29=12632,V,21500,23,DVB-S,8PSK -30=12647,H,21500,23,DVB-S,8PSK -31=12661,V,21500,23,DVB-S,8PSK -32=12676,H,21500,23,DVB-S,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2330.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2330.ini deleted file mode 100644 index 3ab17e6a1f..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2330.ini +++ /dev/null @@ -1,32 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2330 -2=Galaxy 13/Horizons 1 (127.0W) - -[DVB] -0=23 -1=3760,V,28076,34,DVB-S,QPSK -2=3780,H,30000,23,S2,8PSK -3=3800,V,27690,34,DVB-S,QPSK -4=3820,H,30000,56,S2,8PSK -5=3840,V,30000,56,S2,8PSK -6=3880,V,30000,89,S2,8PSK -7=3900,H,29270,78,DVB-S,QPSK -8=3920,V,29270,78,DVB-S,QPSK -9=3960,V,30000,56,S2,8PSK -10=3980,H,30000,34,S2,8PSK -11=4000,V,30000,89,S2,8PSK -12=4052,H,17500,56,S2,8PSK -13=4066,H,3310,34,DVB-S,QPSK -14=4070,H,3257,34,S2,8PSK -15=4080,V,28076,34,DVB-S,QPSK -16=4120,V,30000,56,S2,8PSK -17=4140,H,30000,34,S2,8PSK -18=4160,V,30000,56,S2,8PSK -19=11727,V,6620,Auto,DVB-S,QPSK -20=12050,H,13020,Auto,DVB-S,QPSK -21=12087,V,6111,Auto,DVB-S,QPSK -22=12140,V,30000,34,DVB-S,QPSK -23=12180,V,16278,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2350.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2350.ini deleted file mode 100644 index cdaa5042ea..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2350.ini +++ /dev/null @@ -1,43 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2350 -2=AMC 21/Galaxy 14 (125.0W) - -[DVB] -0=34 -1=3720,H,26667,34,DVB-S,QPSK -2=3740,V,30000,56,S2,8PSK -3=3760,H,19886,34,DVB-S,QPSK -4=3780,V,30000,34,S2,8PSK -5=3820,V,30000,34,S2,8PSK -6=3840,H,30000,56,S2,8PSK -7=3860,V,30000,56,S2,8PSK -8=3880,H,30000,56,S2,8PSK -9=3900,V,29079,56,S2,8PSK -10=3920,H,29270,34,DVB-S,QPSK -11=3940,V,19510,34,DVB-S,QPSK -12=3960,H,29270,34,DVB-S,QPSK -13=3980,V,30000,56,S2,8PSK -14=4020,V,30000,56,S2,8PSK -15=4040,H,30000,34,S2,8PSK -16=4080,H,30000,34,S2,8PSK -17=4100,V,29270,78,DVB-S,QPSK -18=4120,H,29270,34,DVB-S,QPSK -19=4140,V,30000,34,S2,8PSK -20=4160,H,30000,56,S2,8PSK -21=4180,V,30000,56,S2,8PSK -22=11740,V,30000,34,S2,QPSK -23=11760,H,30000,34,S2,QPSK -24=11780,V,30000,34,S2,QPSK -25=11800,H,30000,34,S2,QPSK -26=11980,V,30000,34,S2,QPSK -27=12106,V,2398,23,S2,QPSK -28=12112,V,8703,34,S2,8PSK -29=12146,H,6250,34,S2,QPSK -30=12155,H,6250,34,S2,QPSK -31=12163,H,4444,34,DVB-S,QPSK -32=12169,H,4444,34,DVB-S,QPSK -33=12175,H,4444,34,DVB-S,QPSK -34=12180,V,30000,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2370.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2370.ini deleted file mode 100644 index ce1a1f239f..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2370.ini +++ /dev/null @@ -1,23 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2370 -2=Galaxy 18 (123.0W) - -[DVB] -0=14 -1=4020,H,30000,56,S2,8PSK -2=4040,V,29270,34,DVB-S,QPSK -3=4100,H,29270,34,DVB-S,QPSK -4=4120,V,29270,34,DVB-S,QPSK -5=4140,H,30000,56,S2,8PSK -6=4160,V,29270,34,DVB-S,QPSK -7=4176,H,20000,34,DVB-S,QPSK -8=11732,H,13240,34,DVB-S,QPSK -9=11747,V,2667,Auto,DVB-S,QPSK -10=11772,V,3361,34,S2,QPSK -11=11776,V,2848,23,DVB-S,QPSK -12=11848,V,1784,34,S2,8PSK -13=12033,H,8200,34,DVB-S,QPSK -14=12078,V,3680,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2390.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2390.ini deleted file mode 100644 index 73ca36a7b6..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2390.ini +++ /dev/null @@ -1,42 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2390 -2=EchoStar 9/Galaxy 23 (121.0W) - -[DVB] -0=33 -1=3714,H,4340,78,DVB-S,QPSK -2=3730,H,8824,34,DVB-S,QPSK -3=3732,V,14400,89,S2,8PSK -4=3750,V,14027,34,DVB-S,QPSK -5=3780,V,29270,78,DVB-S,QPSK -6=3800,H,19510,34,DVB-S,QPSK -7=3820,V,29270,34,DVB-S,QPSK -8=3840,H,30000,56,S2,8PSK -9=3877,H,4444,34,DVB-S,QPSK -10=3889,H,13020,34,DVB-S,QPSK -11=3910,H,14400,34,S2,8PSK -12=3980,V,29270,78,DVB-S,QPSK -13=4000,H,19510,34,DVB-S,QPSK -14=4011,V,15000,56,S2,8PSK -15=4033,V,8333,56,DVB-S,QPSK -16=4050,V,2590,34,DVB-S,QPSK -17=4055,V,6510,34,DVB-S,QPSK -18=4080,H,30000,56,S2,8PSK -19=4100,V,29270,34,DVB-S,QPSK -20=4115,H,18085,34,DVB-S,QPSK -21=4172,V,18916,23,S2,8PSK -22=4192,V,11070,56,DVB-S,QPSK -23=11715,V,6510,Auto,DVB-S,QPSK -24=11724,V,6510,Auto,DVB-S,QPSK -25=11899,V,20000,34,DVB-S,QPSK -26=11928,V,20000,34,DVB-S,QPSK -27=11943,H,20000,34,DVB-S,QPSK -28=11957,V,20000,12,DVB-S,QPSK -29=11990,H,20000,34,DVB-S,QPSK -30=12016,V,20000,34,DVB-S,QPSK -31=12045,V,20000,34,DVB-S,QPSK -32=12167,H,6000,Auto,DVB-S,QPSK -33=12171,V,5800,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2410.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2410.ini deleted file mode 100644 index 188507e9dd..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2410.ini +++ /dev/null @@ -1,72 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2410 -2=Anik F3/DirecTV 7S/EchoStar 14 (119.0W) - -[DVB] -0=63 -1=3934,H,5714,34,DVB-S,QPSK -2=11715,V,20000,34,DVB-S,QPSK -3=11728,H,20000,34,DVB-S,QPSK -4=11745,V,20000,34,DVB-S,QPSK -5=11758,H,20000,34,DVB-S,QPSK -6=11776,V,20000,34,DVB-S,QPSK -7=11789,H,20000,34,DVB-S,QPSK -8=11806,V,20000,34,DVB-S,QPSK -9=11819,H,20000,34,DVB-S,QPSK -10=11837,V,20000,34,DVB-S,QPSK -11=11850,H,20000,34,DVB-S,QPSK -12=11867,V,20000,34,DVB-S,QPSK -13=11880,H,20000,34,DVB-S,QPSK -14=11898,V,20000,34,DVB-S,QPSK -15=11911,H,20000,34,DVB-S,QPSK -16=11928,V,20000,34,DVB-S,QPSK -17=11972,H,20000,34,DVB-S,QPSK -18=11989,V,20000,34,DVB-S,QPSK -19=12002,H,20000,34,DVB-S,QPSK -20=12020,V,20000,34,DVB-S,QPSK -21=12033,H,20000,34,DVB-S,QPSK -22=12050,V,20000,34,DVB-S,QPSK -23=12063,H,20000,34,DVB-S,QPSK -24=12081,V,20000,34,DVB-S,QPSK -25=12094,H,20000,34,DVB-S,QPSK -26=12111,V,20000,34,DVB-S,QPSK -27=12124,H,20000,34,DVB-S,QPSK -28=12142,V,20000,34,DVB-S,QPSK -29=12155,H,20000,34,DVB-S,QPSK -30=12172,V,20000,34,DVB-S,QPSK -31=12185,H,20000,34,DVB-S,QPSK -32=12224,V,21500,23,DVB-S,8PSK -33=12239,H,21500,23,DVB-S,8PSK -34=12253,V,21500,23,DVB-S,8PSK -35=12268,H,21500,23,DVB-S,8PSK -36=12282,V,21500,23,DVB-S,8PSK -37=12297,H,20000,78,DVB-S,QPSK -38=12311,V,21500,23,DVB-S,8PSK -39=12326,H,20000,78,DVB-S,QPSK -40=12341,V,20000,78,DVB-S,QPSK -41=12355,H,20000,78,DVB-S,QPSK -42=12370,V,20000,78,DVB-S,QPSK -43=12384,H,20000,78,DVB-S,QPSK -44=12399,V,20000,78,DVB-S,QPSK -45=12414,H,20000,78,DVB-S,QPSK -46=12428,V,20000,78,DVB-S,QPSK -47=12443,H,20000,78,DVB-S,QPSK -48=12457,V,20000,78,DVB-S,QPSK -49=12472,H,20000,78,DVB-S,QPSK -50=12486,V,20000,78,DVB-S,QPSK -51=12501,H,20000,78,DVB-S,QPSK -52=12516,V,20000,78,DVB-S,QPSK -53=12530,H,20000,Auto,DVB-S,QPSK -54=12545,V,20000,Auto,DVB-S,QPSK -55=12559,H,20000,23,S2,8PSK -56=12574,V,20000,Auto,DVB-S,QPSK -57=12588,H,20000,Auto,DVB-S,QPSK -58=12603,V,20000,Auto,DVB-S,QPSK -59=12618,H,20000,Auto,DVB-S,QPSK -60=12632,V,20000,Auto,DVB-S,QPSK -61=12647,H,20000,Auto,DVB-S,QPSK -62=12661,V,20000,Auto,DVB-S,QPSK -63=12676,H,20000,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2432.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2432.ini deleted file mode 100644 index aacb92c284..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2432.ini +++ /dev/null @@ -1,85 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2432 -2=Eutelsat 117 West A (116.8W) - -[DVB] -0=76 -1=3720,V,27000,34,DVB-S,QPSK -2=3744,V,2665,34,S2,8PSK -3=3748,V,2100,78,DVB-S,QPSK -4=3768,V,4800,34,S2,8PSK -5=3772,V,3515,34,DVB-S,QPSK -6=3786,V,6900,34,DVB-S,QPSK -7=3793,V,4240,34,S2,QPSK -8=3798,V,5225,56,S2,8PSK -9=3804,V,1480,56,S2,8PSK -10=3804,H,4000,34,DVB-S,QPSK -11=3808,H,2170,34,DVB-S,QPSK -12=3820,H,2000,34,S2,8PSK -13=3824,H,1808,34,DVB-S,QPSK -14=3835,V,19510,23,DVB-S,QPSK -15=3850,H,4710,34,DVB-S,QPSK -16=3853,H,1667,34,S2,8PSK -17=3854,V,8333,23,S2,8PSK -18=3868,V,8131,34,S2,8PSK -19=3883,H,1350,34,S2,8PSK -20=3885,H,1481,34,DVB-S,QPSK -21=3888,V,1480,23,S2,8PSK -22=3889,H,4181,34,DVB-S,QPSK -23=3895,H,3609,34,DVB-S,QPSK -24=3897,V,1480,34,DVB-S,QPSK -25=3899,H,4167,34,S2,QPSK -26=3903,H,1480,56,S2,8PSK -27=3903,V,2200,78,DVB-S,QPSK -28=3905,H,1600,34,S2,QPSK -29=3908,H,2170,34,DVB-S,QPSK -30=3911,H,2500,34,DVB-S,QPSK -31=3914,H,2105,56,S2,8PSK -32=3916,H,1520,34,DVB-S,QPSK -33=3920,V,7320,34,DVB-S,QPSK -34=3926,V,2222,34,DVB-S,QPSK -35=3930,V,2310,78,DVB-S,QPSK -36=3932,V,1447,34,S2,8PSK -37=3940,H,29270,34,DVB-S,QPSK -38=3949,V,11250,23,S2,8PSK -39=3957,V,1595,56,S2,8PSK -40=3960,V,1595,56,S2,8PSK -41=3962,V,1800,34,S2,QPSK -42=3968,V,7500,34,DVB-S,QPSK -43=3969,H,1100,34,S2,QPSK -44=3975,H,2170,34,S2,8PSK -45=3976,V,2666,34,DVB-S,QPSK -46=3984,V,3100,34,DVB-S,QPSK -47=3989,V,2892,34,DVB-S,QPSK -48=4009,V,6379,34,DVB-S,QPSK -49=4015,V,3000,34,DVB-S,QPSK -50=4031,V,15200,56,DVB-S,QPSK -51=4044,H,3333,34,DVB-S,QPSK -52=4049,H,3330,34,DVB-S,QPSK -53=4052,V,4307,34,DVB-S,QPSK -54=4056,V,1800,23,DVB-S,QPSK -55=4064,H,19510,34,DVB-S,QPSK -56=4075,H,2962,34,DVB-S,QPSK -57=4084,H,3162,78,DVB-S,QPSK -58=4090,H,5000,56,S2,8PSK -59=4103,H,1600,23,S2,8PSK -60=4106,H,3200,23,DVB-S,QPSK -61=4109,H,2885,34,S2,QPSK -62=4116,H,2900,34,S2,QPSK -63=4120,V,30000,56,S2,8PSK -64=4134,H,4400,34,DVB-S,QPSK -65=4152,H,1321,35,S2,8PSK -66=4155,H,1480,34,S2,8PSK -67=4175,H,1850,Auto,S2,8PSK -68=4178,H,2800,34,S2,8PSK -69=4189,H,9760,34,DVB-S,QPSK -70=12060,V,30000,34,DVB-S,8PSK -71=12080,H,30000,34,DVB-S,8PSK -72=12100,V,29000,34,DVB-S,8PSK -73=12126,V,5400,34,DVB-S,QPSK -74=12175,H,3704,34,DVB-S,QPSK -75=12180,H,3000,12,DVB-S,QPSK -76=12189,H,1660,78,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2451.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2451.ini deleted file mode 100644 index 0272503f2e..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2451.ini +++ /dev/null @@ -1,14 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2451 -2=Eutelsat 115 West A (114.9W) - -[DVB] -0=5 -1=12041,V,1562,Auto,DVB-S,QPSK -2=12044,V,1955,Auto,S2,QPSK -3=12049,V,1955,Auto,S2,QPSK -4=12063,H,3332,Auto,DVB-S,QPSK -5=12087,V,3400,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2470.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2470.ini deleted file mode 100644 index 0042e0ef12..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2470.ini +++ /dev/null @@ -1,64 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2470 -2=Eutelsat 113 West A (113.0W) - -[DVB] -0=55 -1=3704,V,2222,34,S2,QPSK -2=3709,V,3255,34,DVB-S,QPSK -3=3714,V,2120,34,DVB-S,QPSK -4=3731,V,3782,78,DVB-S,QPSK -5=3734,H,3410,Auto,DVB-S,QPSK -6=3736,V,3254,34,DVB-S,QPSK -7=3744,V,2893,34,DVB-S,QPSK -8=3752,V,2893,34,DVB-S,QPSK -9=3760,V,2893,34,DVB-S,QPSK -10=3764,H,2934,34,DVB-S,QPSK -11=3765,V,3254,34,DVB-S,QPSK -12=3768,H,2976,78,DVB-S,QPSK -13=3769,V,3363,34,DVB-S,QPSK -14=3773,V,2532,34,DVB-S,QPSK -15=3773,H,2875,34,DVB-S,QPSK -16=3780,H,4406,56,DVB-S,QPSK -17=3784,H,2666,78,DVB-S,QPSK -18=3787,H,2083,34,DVB-S,QPSK -19=3821,H,3255,78,DVB-S,QPSK -20=3825,H,3621,56,S2,8PSK -21=3828,V,2550,56,DVB-S,QPSK -22=3829,H,3620,56,S2,8PSK -23=3834,H,3620,56,S2,8PSK -24=3835,V,1807,34,DVB-S,QPSK -25=3837,V,2550,78,DVB-S,QPSK -26=3848,V,13842,34,S2,8PSK -27=3848,H,2893,34,DVB-S,QPSK -28=3853,H,3255,34,DVB-S,QPSK -29=3857,H,2804,34,DVB-S,QPSK -30=3863,H,3200,34,DVB-S,QPSK -31=3867,H,2415,35,S2,8PSK -32=3875,H,4166,34,DVB-S,QPSK -33=3880,V,29270,34,DVB-S,QPSK -34=3900,H,30000,35,S2,8PSK -35=3920,V,29270,34,DVB-S,QPSK -36=3955,H,2400,Auto,S2,QPSK -37=4034,H,3551,34,DVB-S,QPSK -38=4064,V,3080,34,S2,8PSK -39=4080,V,2920,34,DVB-S,QPSK -40=4140,H,20008,56,S2,8PSK -41=11989,V,3750,34,DVB-S,QPSK -42=11994,V,4340,23,DVB-S,QPSK -43=12028,H,2600,Auto,DVB-S,QPSK -44=12046,H,14200,35,S2,8PSK -45=12089,H,11719,34,DVB-S,QPSK -46=12110,H,2170,Auto,DVB-S,QPSK -47=12126,V,6022,Auto,DVB-S,QPSK -48=12136,V,3255,Auto,DVB-S,QPSK -49=12151,V,3255,Auto,DVB-S,QPSK -50=12157,V,3038,Auto,DVB-S,QPSK -51=12161,H,1480,34,DVB-S,QPSK -52=12165,H,3333,Auto,DVB-S,QPSK -53=12165,V,3255,Auto,DVB-S,QPSK -54=12172,V,3333,Auto,DVB-S,QPSK -55=12193,V,3255,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2489.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2489.ini deleted file mode 100644 index c71cfdd790..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2489.ini +++ /dev/null @@ -1,40 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2489 -2=Anik F2 (111.1W) - -[DVB] -0=31 -1=4168,V,9737,12,S2,8PSK -2=11745,V,20500,23,DVB-S,8PSK -3=11758,H,20500,23,DVB-S,8PSK -4=11770,V,3270,Auto,DVB-S,QPSK -5=11819,H,20500,23,DVB-S,8PSK -6=11837,V,20500,23,DVB-S,8PSK -7=11850,H,20500,23,DVB-S,8PSK -8=11880,H,20500,23,DVB-S,8PSK -9=11898,V,20500,23,DVB-S,8PSK -10=11928,V,20500,23,DVB-S,8PSK -11=11972,H,20500,23,DVB-S,8PSK -12=11989,V,20500,23,DVB-S,8PSK -13=12002,H,19510,34,DVB-S,QPSK -14=12020,V,20500,23,DVB-S,8PSK -15=12033,H,20500,23,DVB-S,8PSK -16=12050,V,20500,23,DVB-S,8PSK -17=12063,H,19510,34,DVB-S,QPSK -18=12081,V,20500,23,DVB-S,8PSK -19=12094,H,19510,34,DVB-S,QPSK -20=12111,V,19510,34,DVB-S,QPSK -21=12142,V,20500,23,DVB-S,8PSK -22=12155,H,20500,23,DVB-S,8PSK -23=12172,V,19510,34,DVB-S,QPSK -24=12185,H,20500,23,DVB-S,8PSK -25=19776,H,15000,34,DVB-S,QPSK -26=19794,H,15000,34,DVB-S,QPSK -27=19814,H,15000,34,DVB-S,QPSK -28=19905,H,22500,34,DVB-S,QPSK -29=19932,H,22500,34,DVB-S,QPSK -30=19966,H,15000,12,DVB-S,QPSK -31=20002,H,15000,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2500.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2500.ini deleted file mode 100644 index 0fb566b488..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2500.ini +++ /dev/null @@ -1,38 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2500 -2=DirecTV 5/EchoStar 10/11 (110.0W) - -[DVB] -0=29 -1=12224,V,20000,78,DVB-S,QPSK -2=12239,H,20000,78,DVB-S,QPSK -3=12253,V,20000,78,DVB-S,QPSK -4=12268,H,21500,23,DVB-S,8PSK -5=12282,V,20000,78,DVB-S,QPSK -6=12297,H,20000,78,DVB-S,QPSK -7=12311,V,21500,23,DVB-S,8PSK -8=12326,H,20000,78,DVB-S,QPSK -9=12341,V,20000,78,DVB-S,QPSK -10=12355,H,20000,78,DVB-S,QPSK -11=12370,V,20000,78,DVB-S,QPSK -12=12384,H,20000,56,DVB-S,QPSK -13=12399,V,21500,23,DVB-S,8PSK -14=12414,H,20000,78,DVB-S,QPSK -15=12428,V,20000,78,DVB-S,QPSK -16=12443,H,20000,78,DVB-S,QPSK -17=12472,H,21500,23,DVB-S,8PSK -18=12486,V,21500,23,DVB-S,8PSK -19=12501,H,21500,23,DVB-S,8PSK -20=12516,V,20000,78,DVB-S,QPSK -21=12530,H,21500,23,DVB-S,8PSK -22=12545,V,21500,23,DVB-S,8PSK -23=12559,H,20000,78,DVB-S,QPSK -24=12574,V,20000,56,DVB-S,8PSK -25=12588,H,20000,56,DVB-S,QPSK -26=12603,V,20000,56,DVB-S,QPSK -27=12618,H,20000,Auto,DVB-S,QPSK -28=12632,V,21500,23,DVB-S,8PSK -29=12661,V,21500,23,DVB-S,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2527.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2527.ini deleted file mode 100644 index 41b4e2981c..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2527.ini +++ /dev/null @@ -1,79 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2527 -2=Anik F1R/G1 (107.3W) - -[DVB] -0=70 -1=3734,V,1665,56,DVB-S,QPSK -2=3780,V,28346,78,DVB-S,QPSK -3=3807,V,6500,12,DVB-S,QPSK -4=3825,V,6500,12,DVB-S,QPSK -5=3840,H,30000,34,S2,8PSK -6=3860,V,30000,23,S2,8PSK -7=3913,V,7078,23,S2,8PSK -8=3920,H,30000,34,DVB-S,8PSK -9=3924,V,3000,78,DVB-S,QPSK -10=3948,V,14630,34,DVB-S,QPSK -11=3962,H,9120,78,DVB-S,QPSK -12=4020,V,30000,56,S2,8PSK -13=4040,H,30000,34,S2,8PSK -14=4060,V,28346,78,DVB-S,QPSK -15=4080,H,30000,34,S2,8PSK -16=4100,V,28346,78,DVB-S,QPSK -17=4107,H,7440,56,DVB-S,QPSK -18=4117,H,6200,56,DVB-S,QPSK -19=4140,V,30000,56,S2,8PSK -20=4160,H,30000,34,S2,8PSK -21=11092,V,22000,89,DVB-S,8PSK -22=11092,H,22000,89,DVB-S,8PSK -23=11122,V,22000,89,DVB-S,8PSK -24=11122,H,22000,89,DVB-S,8PSK -25=11152,V,22000,89,DVB-S,8PSK -26=11152,H,22000,89,DVB-S,8PSK -27=11183,V,22000,89,DVB-S,8PSK -28=11183,H,22000,89,DVB-S,8PSK -29=11592,V,22000,56,DVB-S,8PSK -30=11592,H,22000,89,DVB-S,8PSK -31=11622,V,22000,56,DVB-S,8PSK -32=11622,H,22000,89,DVB-S,8PSK -33=11652,V,22000,56,DVB-S,8PSK -34=11683,V,22000,56,DVB-S,8PSK -35=11683,H,20500,56,DVB-S,8PSK -36=11715,V,21000,34,DVB-S,8PSK -37=11728,H,19510,34,DVB-S,QPSK -38=11745,V,19510,34,DVB-S,QPSK -39=11758,H,19510,34,DVB-S,QPSK -40=11776,V,19510,34,DVB-S,QPSK -41=11789,H,19510,34,DVB-S,QPSK -42=11806,V,19510,34,DVB-S,QPSK -43=11819,H,19510,34,DVB-S,QPSK -44=11837,V,19510,34,DVB-S,QPSK -45=11850,H,19510,34,DVB-S,QPSK -46=11867,V,19510,34,DVB-S,QPSK -47=11880,H,19510,34,DVB-S,QPSK -48=11898,V,19510,34,DVB-S,QPSK -49=11902,H,5859,34,DVB-S,QPSK -50=11912,H,5859,34,DVB-S,QPSK -51=11928,V,19510,34,DVB-S,QPSK -52=11933,H,5859,34,DVB-S,QPSK -53=11941,H,5859,34,DVB-S,QPSK -54=11949,H,5859,34,DVB-S,QPSK -55=11959,V,19510,34,DVB-S,QPSK -56=11972,H,19510,34,DVB-S,QPSK -57=11989,V,20500,23,DVB-S,8PSK -58=12002,H,19510,34,DVB-S,QPSK -59=12020,V,19510,34,DVB-S,QPSK -60=12033,H,19510,34,DVB-S,QPSK -61=12050,V,19510,34,DVB-S,QPSK -62=12063,H,19510,34,DVB-S,QPSK -63=12081,V,20500,23,DVB-S,8PSK -64=12094,H,19510,34,DVB-S,QPSK -65=12111,V,19510,34,DVB-S,QPSK -66=12124,H,19510,34,DVB-S,QPSK -67=12142,V,19510,34,DVB-S,QPSK -68=12155,H,19510,34,DVB-S,QPSK -69=12172,V,19510,34,DVB-S,QPSK -70=12185,H,19510,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2550.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2550.ini deleted file mode 100644 index d573433b8b..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2550.ini +++ /dev/null @@ -1,37 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2550 -2=AMC 15/18 (105.0W) - -[DVB] -0=28 -1=3720,V,19510,34,DVB-S,QPSK -2=3760,V,28068,34,DVB-S,QPSK -3=3780,H,30000,34,S2,8PSK -4=3840,V,30000,56,S2,8PSK -5=3860,H,30000,56,S2,8PSK -6=3900,H,19510,34,DVB-S,QPSK -7=3940,H,30000,56,S2,8PSK -8=4000,V,30000,56,S2,8PSK -9=4020,H,30000,56,S2,8PSK -10=4060,H,19510,34,DVB-S,QPSK -11=4080,V,30000,56,S2,8PSK -12=4100,H,19510,34,DVB-S,QPSK -13=4120,V,19510,34,DVB-S,QPSK -14=4140,H,19510,34,DVB-S,QPSK -15=4160,V,30000,56,S2,8PSK -16=4180,H,19510,34,DVB-S,QPSK -17=11706,V,6620,34,DVB-S,QPSK -18=11716,V,6620,34,DVB-S,QPSK -19=11724,V,6113,34,DVB-S,QPSK -20=11729,H,3979,34,DVB-S,QPSK -21=11734,V,6113,34,DVB-S,QPSK -22=11756,V,6113,34,DVB-S,QPSK -23=11766,V,4411,Auto,DVB-S,QPSK -24=11766,H,6113,34,DVB-S,QPSK -25=11830,V,6620,Auto,DVB-S,QPSK -26=11834,H,13235,Auto,DVB-S,QPSK -27=11856,V,3548,12,DVB-S,QPSK -28=12122,H,1000,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2570.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2570.ini deleted file mode 100644 index 1fcd356437..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2570.ini +++ /dev/null @@ -1,73 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2570 -2=SES 3/Spaceway 1 & DirecTV 10/12 (103.0W) - -[DVB] -0=64 -1=3740,V,29270,78,DVB-S,QPSK -2=3760,H,30000,34,S2,8PSK -3=3780,V,28800,56,S2,8PSK -4=3800,H,29270,78,DVB-S,QPSK -5=3820,V,29270,34,DVB-S,QPSK -6=3840,H,26681,34,DVB-S,QPSK -7=3860,V,30000,56,S2,8PSK -8=3891,V,14400,23,S2,8PSK -9=3904,V,6667,23,S2,8PSK -10=3906,H,6511,34,DVB-S,QPSK -11=3913,H,2927,34,DVB-S,QPSK -12=3920,H,3150,56,DVB-S,QPSK -13=3924,H,2734,Auto,S2,QPSK -14=3960,H,30000,56,S2,8PSK -15=3972,V,14800,56,DVB-S,QPSK -16=4040,H,30000,23,S2,8PSK -17=4081,H,7233,34,DVB-S,QPSK -18=4089,H,5923,56,S2,8PSK -19=4091,V,14029,34,DVB-S,QPSK -20=4120,H,30000,56,S2,8PSK -21=4140,V,30000,56,S2,8PSK -22=4160,H,26681,34,DVB-S,QPSK -23=11760,H,30000,56,S2,8PSK -24=11840,H,30000,56,S2,8PSK -25=11880,H,30000,56,S2,8PSK -26=11940,V,20000,34,DVB-S,QPSK -27=11985,H,4600,34,S2,8PSK -28=12009,H,4600,34,S2,8PSK -29=12015,H,4600,56,DVB-S,QPSK -30=12025,H,4600,34,S2,8PSK -31=12065,H,4232,56,DVB-S,QPSK -32=12071,H,4600,34,S2,8PSK -33=12076,V,4250,56,S2,8PSK -34=12077,H,4600,34,S2,8PSK -35=12083,H,4600,34,S2,8PSK -36=12089,H,4600,34,S2,8PSK -37=12095,H,4600,34,S2,8PSK -38=12145,V,20000,34,DVB-S,QPSK -39=12157,H,4600,34,S2,8PSK -40=12175,H,4600,34,S2,8PSK -41=12182,V,25000,34,DVB-S,QPSK -42=18327,H,30000,23,S2,QPSK -43=18327,V,30000,23,S2,QPSK -44=18367,H,30000,23,S2,QPSK -45=18367,V,30000,23,S2,QPSK -46=18407,H,30000,23,S2,QPSK -47=18407,V,30000,23,S2,QPSK -48=18447,H,30000,23,S2,QPSK -49=18447,V,30000,23,S2,QPSK -50=18487,H,30000,23,S2,QPSK -51=18487,V,30000,23,S2,QPSK -52=18527,H,30000,23,S2,QPSK -53=18527,V,30000,23,S2,QPSK -54=18567,H,30000,23,S2,QPSK -55=18567,V,30000,23,S2,QPSK -56=18607,H,30000,23,S2,QPSK -57=18607,V,30000,23,S2,QPSK -58=18648,V,30000,23,S2,QPSK -59=19741,H,30000,34,S2,QPSK -60=19741,V,30000,34,S2,QPSK -61=19804,H,30000,34,S2,QPSK -62=19804,V,30000,34,S2,QPSK -63=19866,H,30000,34,S2,QPSK -64=19866,V,30000,34,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2590.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2590.ini deleted file mode 100644 index 322d683c18..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2590.ini +++ /dev/null @@ -1,55 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2590 -2=DirecTV 4S/8/SES 1 (101.0W) - -[DVB] -0=46 -1=3710,V,4340,34,DVB-S,QPSK -2=3716,V,4775,35,S2,8PSK -3=3722,V,5600,34,S2,8PSK -4=3773,V,4442,34,DVB-S,QPSK -5=3920,V,30000,56,S2,8PSK -6=3953,V,2734,56,DVB-S,QPSK -7=3957,V,2734,56,DVB-S,QPSK -8=3961,V,2734,56,DVB-S,QPSK -9=3974,V,5924,56,DVB-S,QPSK -10=4020,H,28000,34,S2,8PSK -11=11705,V,3650,34,S2,QPSK -12=11795,H,4342,56,DVB-S,QPSK -13=11820,H,20000,34,DVB-S,QPSK -14=12172,H,15000,Auto,DVB-S,QPSK -15=12224,V,20000,Auto,DVB-S,QPSK -16=12239,H,20000,Auto,DVB-S,QPSK -17=12253,V,20000,Auto,DVB-S,QPSK -18=12268,H,20000,23,DVB-S,QPSK -19=12282,V,20000,Auto,DVB-S,QPSK -20=12297,H,20000,Auto,DVB-S,QPSK -21=12311,V,20000,Auto,DVB-S,QPSK -22=12326,H,20000,Auto,DVB-S,QPSK -23=12341,V,20000,Auto,DVB-S,QPSK -24=12355,H,20000,Auto,DVB-S,QPSK -25=12370,V,20000,Auto,DVB-S,QPSK -26=12384,H,20000,Auto,DVB-S,QPSK -27=12399,V,20000,Auto,DVB-S,QPSK -28=12414,H,20000,Auto,DVB-S,QPSK -29=12428,V,20000,Auto,DVB-S,QPSK -30=12443,H,20000,Auto,DVB-S,QPSK -31=12457,V,20000,Auto,DVB-S,QPSK -32=12472,H,20000,Auto,DVB-S,QPSK -33=12486,V,20000,Auto,DVB-S,QPSK -34=12501,H,20000,Auto,DVB-S,QPSK -35=12516,V,20000,Auto,DVB-S,QPSK -36=12530,H,20000,Auto,DVB-S,QPSK -37=12545,V,20000,Auto,DVB-S,QPSK -38=12559,H,20000,Auto,DVB-S,QPSK -39=12574,V,20000,Auto,DVB-S,QPSK -40=12588,H,20000,23,DVB-S,QPSK -41=12603,V,20000,Auto,DVB-S,QPSK -42=12618,H,20000,Auto,DVB-S,QPSK -43=12632,V,20000,Auto,DVB-S,QPSK -44=12647,H,20000,Auto,DVB-S,QPSK -45=12661,V,20000,Auto,DVB-S,QPSK -46=12676,H,20000,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2608.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2608.ini deleted file mode 100644 index e3200b7cdf..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2608.ini +++ /dev/null @@ -1,81 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2608 -2=DirecTV 14/Galaxy 16/Spaceway 2 & DirecTV 11 (99.2W) - -[DVB] -0=72 -1=3720,H,8700,34,S2,8PSK -2=3735,H,3775,34,DVB-S,QPSK -3=3740,V,30000,56,S2,QPSK -4=3770,H,1220,34,S2,QPSK -5=3785,H,4850,34,S2,8PSK -6=3789,H,1666,56,DVB-S,QPSK -7=3791,H,1665,56,DVB-S,QPSK -8=3793,V,7030,12,S2,QPSK -9=3795,H,3255,34,DVB-S,QPSK -10=3811,H,8030,34,DVB-S,QPSK -11=3820,V,26000,34,DVB-S,QPSK -12=3900,V,28000,34,DVB-S,QPSK -13=3904,H,3125,78,DVB-S,QPSK -14=3912,H,10833,89,S2,8PSK -15=3924,H,3125,78,DVB-S,QPSK -16=3925,V,3979,23,DVB-S,QPSK -17=3928,H,3125,78,DVB-S,QPSK -18=3930,V,3680,23,DVB-S,QPSK -19=3931,H,1562,56,DVB-S,QPSK -20=3938,H,1561,78,DVB-S,QPSK -21=3940,V,27600,56,S2,QPSK -22=3953,H,3125,78,DVB-S,QPSK -23=3977,H,2555,Auto,DVB-S,QPSK -24=3980,V,26470,56,DVB-S,QPSK -25=4000,H,26400,34,DVB-S,QPSK -26=4006,V,5833,34,S2,QPSK -27=4060,V,27780,56,DVB-S,QPSK -28=4080,H,27780,56,DVB-S,QPSK -29=4120,H,30000,910,S2,8PSK -30=4140,V,30000,910,S2,8PSK -31=4145,H,3308,34,DVB-S,QPSK -32=4193,V,6620,23,DVB-S,QPSK -33=11765,V,4000,34,DVB-S,QPSK -34=11782,V,3979,34,DVB-S,QPSK -35=11787,V,3979,34,DVB-S,QPSK -36=11792,V,3979,34,DVB-S,QPSK -37=11800,H,30000,34,S2,QPSK -38=11804,V,3979,34,DVB-S,QPSK -39=11809,V,3979,34,DVB-S,QPSK -40=11815,V,3979,34,DVB-S,QPSK -41=11820,V,3979,34,DVB-S,QPSK -42=11825,V,3979,34,DVB-S,QPSK -43=11825,H,3979,34,DVB-S,QPSK -44=11830,V,3979,34,DVB-S,QPSK -45=11830,H,3979,34,DVB-S,QPSK -46=11836,V,3979,34,DVB-S,QPSK -47=11836,H,3979,34,DVB-S,QPSK -48=11842,H,3979,34,DVB-S,QPSK -49=11848,H,3979,34,DVB-S,QPSK -50=11854,H,3979,34,DVB-S,QPSK -51=11865,H,3979,34,DVB-S,QPSK -52=11871,H,3979,34,DVB-S,QPSK -53=11876,H,3979,34,DVB-S,QPSK -54=11882,H,3979,34,DVB-S,QPSK -55=11884,V,3979,34,DVB-S,QPSK -56=11888,H,3979,34,DVB-S,QPSK -57=11889,V,3979,34,DVB-S,QPSK -58=11894,H,3979,34,DVB-S,QPSK -59=11895,V,3979,34,DVB-S,QPSK -60=11900,V,3979,34,DVB-S,QPSK -61=11905,V,3979,34,DVB-S,QPSK -62=11905,H,3979,34,DVB-S,QPSK -63=11910,V,3979,34,DVB-S,QPSK -64=11911,H,3979,34,DVB-S,QPSK -65=11916,V,3979,34,DVB-S,QPSK -66=11917,H,3979,34,DVB-S,QPSK -67=11960,H,30000,78,DVB-S,QPSK -68=11980,V,30000,56,DVB-S,QPSK -69=12020,V,20000,910,S2,8PSK -70=12040,H,26665,23,DVB-S,QPSK -71=12093,H,6620,34,DVB-S,QPSK -72=12100,V,30000,56,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2630.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2630.ini deleted file mode 100644 index 1a888553ad..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2630.ini +++ /dev/null @@ -1,57 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2630 -2=Galaxy 19 (97.0W) - -[DVB] -0=48 -1=3706,V,6111,34,DVB-S,QPSK -2=3760,V,31456,35,S2,8PSK -3=3780,H,29270,34,DVB-S,QPSK -4=3800,V,29860,910,S2,8PSK -5=3831,V,11800,56,DVB-S,QPSK -6=3839,V,2940,78,DVB-S,QPSK -7=3847,V,2200,34,DVB-S,QPSK -8=3851,V,3532,34,DVB-S,QPSK -9=3857,V,2940,Auto,DVB-S,QPSK -10=3880,V,30000,56,S2,8PSK -11=3896,H,20000,34,DVB-S,QPSK -12=3914,H,7000,34,S2,8PSK -13=3922,V,3703,34,DVB-S,QPSK -14=3940,H,30000,56,S2,8PSK -15=3960,V,29300,34,DVB-S,QPSK -16=3985,V,3600,Auto,S2,8PSK -17=4001,V,1481,89,S2,8PSK -18=4009,V,4407,56,S2,8PSK -19=4027,V,7200,23,S2,8PSK -20=4034,H,6111,34,DVB-S,QPSK -21=4060,H,32362,34,DVB-S,QPSK -22=4080,V,29856,910,S2,8PSK -23=4100,H,29856,910,S2,8PSK -24=4120,V,30000,56,S2,8PSK -25=4140,H,29856,910,S2,8PSK -26=4160,V,29856,910,S2,8PSK -27=4167,H,6922,56,S2,8PSK -28=11836,V,20770,34,DVB-S,QPSK -29=11842,H,22000,34,DVB-S,QPSK -30=11867,V,22000,34,DVB-S,QPSK -31=11898,V,22000,34,DVB-S,QPSK -32=11904,H,22000,34,DVB-S,QPSK -33=11929,V,22000,34,DVB-S,QPSK -34=11936,H,20000,34,DVB-S,QPSK -35=11960,V,22000,34,DVB-S,QPSK -36=11966,H,22000,34,DVB-S,QPSK -37=12022,V,22000,34,DVB-S,QPSK -38=12028,H,21991,34,DVB-S,QPSK -39=12053,V,22000,34,DVB-S,QPSK -40=12060,H,22000,34,DVB-S,QPSK -41=12084,V,22000,34,DVB-S,QPSK -42=12090,H,20000,34,DVB-S,QPSK -43=12115,V,22425,34,DVB-S,QPSK -44=12122,H,20000,34,DVB-S,QPSK -45=12146,V,22000,34,DVB-S,QPSK -46=12152,H,20000,34,DVB-S,QPSK -47=12177,V,23000,34,DVB-S,QPSK -48=12184,H,21991,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2650.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2650.ini deleted file mode 100644 index f3c4e0de6f..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2650.ini +++ /dev/null @@ -1,83 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2650 -2=Galaxy 3C/Intelsat 30/Spaceway 3 (95.0W) - -[DVB] -0=74 -1=3785,V,6922,56,S2,8PSK -2=3800,H,29270,Auto,DVB-S,QPSK -3=3827,H,6922,56,S2,8PSK -4=3829,V,13000,56,S2,8PSK -5=3884,V,1035,34,S2,QPSK -6=3889,V,3074,34,DVB-S,QPSK -7=3893,V,3074,34,DVB-S,QPSK -8=3896,V,2000,34,S2,8PSK -9=3901,V,1836,34,S2,8PSK -10=3911,V,3074,34,DVB-S,QPSK -11=3911,H,15000,56,S2,8PSK -12=3924,V,3074,34,DVB-S,QPSK -13=3929,V,3074,34,DVB-S,QPSK -14=3935,V,2000,34,S2,8PSK -15=3940,V,2000,34,S2,8PSK -16=3943,V,3074,34,DVB-S,QPSK -17=3950,V,2000,34,S2,8PSK -18=3956,V,3302,34,S2,8PSK -19=3965,V,1035,34,S2,8PSK -20=3970,V,1035,34,S2,QPSK -21=3974,V,3074,34,DVB-S,QPSK -22=3980,V,1035,34,S2,QPSK -23=3984,V,1035,34,S2,QPSK -24=3988,V,3074,34,DVB-S,QPSK -25=3992,V,3074,34,DVB-S,QPSK -26=3996,V,3074,34,DVB-S,QPSK -27=4000,H,30000,910,S2,8PSK -28=4031,H,14035,34,S2,8PSK -29=4060,V,31250,34,S2,8PSK -30=4080,H,31250,34,S2,8PSK -31=4120,H,29270,Auto,DVB-S,QPSK -32=4173,V,2221,Auto,DVB-S,QPSK -33=11480,V,22500,Auto,DVB-S,QPSK -34=11480,H,20000,23,DVB-S,QPSK -35=11510,V,20000,23,DVB-S,QPSK -36=11510,H,22500,Auto,DVB-S,QPSK -37=11539,V,22500,Auto,DVB-S,QPSK -38=11539,H,22500,Auto,DVB-S,QPSK -39=11568,V,20000,23,DVB-S,QPSK -40=11568,H,22500,Auto,DVB-S,QPSK -41=11597,V,21500,56,S2,QPSK -42=11597,H,22500,Auto,DVB-S,QPSK -43=11626,V,22500,Auto,DVB-S,QPSK -44=11626,H,22500,Auto,DVB-S,QPSK -45=11655,V,22500,Auto,DVB-S,QPSK -46=11655,H,22500,Auto,DVB-S,QPSK -47=11685,V,22500,Auto,DVB-S,QPSK -48=11685,H,22500,Auto,DVB-S,QPSK -49=11720,H,20000,23,DVB-S,QPSK -50=11750,H,30000,23,S2,QPSK -51=11780,H,20760,34,DVB-S,QPSK -52=11810,H,30000,23,S2,QPSK -53=11840,H,20000,23,DVB-S,QPSK -54=11900,H,20000,23,DVB-S,QPSK -55=11930,H,30000,23,S2,QPSK -56=11930,H,20000,23,DVB-S,QPSK -57=11960,H,20000,23,DVB-S,QPSK -58=11960,V,20000,23,DVB-S,QPSK -59=11975,H,20000,23,DVB-S,QPSK -60=11990,H,20000,23,DVB-S,QPSK -61=11990,V,20000,23,DVB-S,QPSK -62=12020,V,21000,56,S2,QPSK -63=12035,H,21000,56,S2,QPSK -64=12050,H,20000,34,DVB-S,QPSK -65=12050,V,21000,56,S2,QPSK -66=12080,H,20000,23,DVB-S,QPSK -67=12080,V,20000,23,DVB-S,QPSK -68=12095,H,20000,23,DVB-S,QPSK -69=12110,H,2220,Auto,DVB-S,QPSK -70=12110,V,20000,23,DVB-S,QPSK -71=12140,H,20000,23,DVB-S,QPSK -72=12140,V,20000,23,DVB-S,QPSK -73=12155,H,20000,23,DVB-S,QPSK -74=12170,V,20000,23,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2669.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2669.ini deleted file mode 100644 index ccb7e85319..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2669.ini +++ /dev/null @@ -1,16 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2669 -2=Galaxy 25 (93.1W) - -[DVB] -0=7 -1=4036,V,19852,56,DVB-S,QPSK -2=4053,V,6617,56,DVB-S,QPSK -3=4180,H,26470,56,DVB-S,QPSK -4=11986,V,5075,Auto,DVB-S,QPSK -5=12010,V,11574,Auto,DVB-S,QPSK -6=12124,V,6615,Auto,DVB-S,QPSK -7=12126,V,2220,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2690.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2690.ini deleted file mode 100644 index e3c73e65c4..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2690.ini +++ /dev/null @@ -1,97 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2690 -2=Galaxy 17/Nimiq 6 (91.0W) - -[DVB] -0=88 -1=3720,H,28800,35,S2,8PSK -2=3740,V,31250,34,S2,8PSK -3=3751,H,14410,56,S2,8PSK -4=3764,H,7500,56,S2,8PSK -5=3780,V,29270,34,DVB-S,QPSK -6=3800,H,31250,34,S2,8PSK -7=3820,V,30000,56,DVB-S,QPSK -8=3840,H,29270,78,DVB-S,QPSK -9=3860,V,31250,34,S2,8PSK -10=3866,H,6620,12,DVB-S,QPSK -11=3920,H,30000,34,S2,8PSK -12=3925,V,4249,23,S2,8PSK -13=3934,V,2480,78,DVB-S,QPSK -14=3952,V,10833,56,S2,8PSK -15=3960,H,29270,78,DVB-S,QPSK -16=3984,V,22500,56,S2,8PSK -17=4000,H,30000,56,S2,8PSK -18=4020,V,31250,34,S2,8PSK -19=4040,H,31250,34,S2,8PSK -20=4066,V,6051,56,S2,8PSK -21=4076,V,3000,34,DVB-S,QPSK -22=4080,H,30000,34,S2,8PSK -23=4100,V,30000,56,S2,8PSK -24=4115,H,19510,34,DVB-S,QPSK -25=4134,H,6960,56,S2,8PSK -26=4140,V,31250,34,S2,8PSK -27=4160,H,31250,34,S2,8PSK -28=4180,V,30000,56,S2,8PSK -29=11740,V,30000,78,DVB-S,QPSK -30=11925,V,3979,34,DVB-S,QPSK -31=11930,V,3979,34,DVB-S,QPSK -32=11935,V,3979,34,DVB-S,QPSK -33=11940,V,3979,34,DVB-S,QPSK -34=11945,V,3979,34,DVB-S,QPSK -35=11950,V,3979,34,DVB-S,QPSK -36=11952,H,5859,Auto,DVB-S,QPSK -37=11955,V,3979,34,DVB-S,QPSK -38=11965,V,3979,Auto,DVB-S,QPSK -39=11970,V,3979,Auto,DVB-S,QPSK -40=11973,H,6111,34,DVB-S,QPSK -41=11975,V,3979,Auto,DVB-S,QPSK -42=11980,V,3979,Auto,DVB-S,QPSK -43=11985,V,3979,Auto,DVB-S,QPSK -44=11987,H,6111,Auto,DVB-S,QPSK -45=11990,V,3979,Auto,DVB-S,QPSK -46=11995,V,3979,Auto,DVB-S,QPSK -47=11995,H,6111,34,DVB-S,QPSK -48=12010,V,11574,34,DVB-S,QPSK -49=12020,V,3979,34,DVB-S,QPSK -50=12025,V,3979,34,DVB-S,QPSK -51=12030,V,3979,34,DVB-S,QPSK -52=12035,V,3979,34,DVB-S,QPSK -53=12076,H,13000,Auto,DVB-S,QPSK -54=12115,H,13235,Auto,DVB-S,QPSK -55=12130,H,13000,34,DVB-S,QPSK -56=12180,V,5632,34,DVB-S,QPSK -57=12224,V,20000,78,DVB-S,QPSK -58=12239,H,20000,56,DVB-S,QPSK -59=12253,V,20000,78,DVB-S,QPSK -60=12268,H,20000,78,DVB-S,QPSK -61=12282,V,20000,Auto,DVB-S,QPSK -62=12297,H,20000,56,DVB-S,QPSK -63=12311,V,20000,78,DVB-S,QPSK -64=12326,H,20000,78,DVB-S,QPSK -65=12341,V,20000,Auto,DVB-S,QPSK -66=12355,H,20000,78,DVB-S,QPSK -67=12370,V,20000,Auto,DVB-S,QPSK -68=12384,H,20000,78,DVB-S,QPSK -69=12399,V,20000,78,DVB-S,QPSK -70=12414,H,20000,56,DVB-S,QPSK -71=12428,V,20000,56,DVB-S,QPSK -72=12443,H,20000,56,DVB-S,QPSK -73=12457,V,20000,Auto,DVB-S,QPSK -74=12472,H,20000,78,DVB-S,QPSK -75=12486,V,20000,56,DVB-S,QPSK -76=12501,H,20000,56,DVB-S,QPSK -77=12516,V,20000,78,DVB-S,QPSK -78=12530,H,20000,78,DVB-S,QPSK -79=12545,V,20000,78,DVB-S,QPSK -80=12559,H,20000,78,DVB-S,QPSK -81=12574,V,20000,78,DVB-S,QPSK -82=12588,H,20000,78,DVB-S,QPSK -83=12603,V,20000,56,DVB-S,QPSK -84=12618,H,20000,56,DVB-S,QPSK -85=12632,V,20000,56,DVB-S,QPSK -86=12647,H,20000,56,DVB-S,QPSK -87=12661,V,20000,56,DVB-S,QPSK -88=12676,H,20000,56,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2710.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2710.ini deleted file mode 100644 index 8e5aa26881..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2710.ini +++ /dev/null @@ -1,69 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2710 -2=Galaxy 28 (89.0W) - -[DVB] -0=60 -1=3840,V,29860,910,S2,8PSK -2=3860,H,26000,Auto,S2,8PSK -3=3880,V,29860,910,S2,QPSK -4=3900,H,32360,34,DVB-S,QPSK -5=3920,V,29860,910,S2,8PSK -6=3980,H,32360,34,DVB-S,QPSK -7=4005,V,6111,34,DVB-S,QPSK -8=4014,V,6111,34,DVB-S,QPSK -9=4060,H,32362,34,S2,QPSK -10=4110,H,2835,Auto,S2,8PSK -11=4154,V,4434,Auto,DVB-S,QPSK -12=4166,H,7440,Auto,DVB-S,QPSK -13=4175,H,7440,Auto,DVB-S,QPSK -14=4185,H,7440,Auto,DVB-S,QPSK -15=11711,H,6620,Auto,DVB-S,QPSK -16=11724,H,6500,Auto,DVB-S,QPSK -17=11732,H,4440,Auto,DVB-S,QPSK -18=11745,H,7030,Auto,DVB-S,QPSK -19=11747,H,6620,Auto,DVB-S,QPSK -20=11756,H,6620,Auto,DVB-S,QPSK -21=11800,H,30000,23,S2,8PSK -22=11845,H,6510,Auto,DVB-S,QPSK -23=11884,H,2788,45,S2,QPSK -24=11920,V,30000,78,DVB-S,QPSK -25=11920,H,30000,23,S2,8PSK -26=11925,H,3979,34,DVB-S,QPSK -27=11930,H,3979,34,DVB-S,QPSK -28=11935,H,3979,34,DVB-S,QPSK -29=11940,H,3979,34,DVB-S,QPSK -30=11945,H,3979,34,DVB-S,QPSK -31=11950,H,3979,34,DVB-S,QPSK -32=11955,H,3979,34,DVB-S,QPSK -33=11960,H,28800,34,DVB-S,QPSK -34=11965,H,3979,34,DVB-S,QPSK -35=11970,V,3979,34,DVB-S,QPSK -36=11970,H,3979,34,DVB-S,QPSK -37=11975,H,3979,34,DVB-S,QPSK -38=11980,H,3979,34,DVB-S,QPSK -39=11985,H,3979,34,DVB-S,QPSK -40=11989,V,6111,34,DVB-S,QPSK -41=11990,H,3979,34,DVB-S,QPSK -42=11995,H,3979,34,DVB-S,QPSK -43=12000,H,28800,34,DVB-S,QPSK -44=12009,V,6111,34,DVB-S,QPSK -45=12035,V,6111,34,DVB-S,QPSK -46=12047,V,6111,Auto,DVB-S,QPSK -47=12100,H,30000,78,DVB-S,QPSK -48=12121,H,2676,34,DVB-S,QPSK -49=12140,H,30000,78,DVB-S,QPSK -50=12160,V,30000,78,DVB-S,QPSK -51=12164,H,2785,34,DVB-S,QPSK -52=12167,H,2785,34,DVB-S,QPSK -53=12171,H,2785,34,DVB-S,QPSK -54=12174,H,2785,34,DVB-S,QPSK -55=12178,H,2785,34,DVB-S,QPSK -56=12181,H,2785,34,DVB-S,QPSK -57=12185,H,2785,34,DVB-S,QPSK -58=12188,H,2785,34,DVB-S,QPSK -59=12192,H,2785,34,DVB-S,QPSK -60=12195,H,2785,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2728.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2728.ini deleted file mode 100644 index 9b148a0460..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2728.ini +++ /dev/null @@ -1,11 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2728 -2=TKSat 1 (87.2W) - -[DVB] -0=2 -1=11479,V,15000,Auto,S2,QPSK -2=12486,V,21702,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2730.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2730.ini deleted file mode 100644 index fdb17c5c09..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2730.ini +++ /dev/null @@ -1,41 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2730 -2=SES 2 (87.0W) - -[DVB] -0=32 -1=3743,V,5000,56,S2,8PSK -2=3753,V,8680,34,DVB-S,QPSK -3=3760,H,26680,Auto,DVB-S,QPSK -4=3780,V,28800,56,DVB-S,QPSK -5=3842,H,6150,78,DVB-S,QPSK -6=3887,H,18400,23,S2,8PSK -7=3949,V,4164,34,S2,8PSK -8=3954,V,2500,34,DVB-S,QPSK -9=4000,H,29125,56,S2,8PSK -10=4026,H,2300,34,S2,8PSK -11=4044,H,3910,34,DVB-S,QPSK -12=4146,H,6789,34,DVB-S,QPSK -13=4149,H,5063,34,DVB-S,QPSK -14=4188,V,3027,Auto,DVB-S,QPSK -15=11725,H,3675,23,DVB-S,QPSK -16=11737,V,8333,23,DVB-S,QPSK -17=11745,H,3979,34,DVB-S,QPSK -18=11750,V,7320,78,DVB-S,QPSK -19=11800,H,2686,34,DVB-S,QPSK -20=11804,H,1250,35,S2,8PSK -21=11811,H,11150,35,S2,8PSK -22=11820,V,30000,56,DVB-S,QPSK -23=11900,V,30000,23,DVB-S,QPSK -24=11960,H,29270,34,DVB-S,QPSK -25=12008,V,5000,12,DVB-S,QPSK -26=12009,H,2170,34,DVB-S,QPSK -27=12044,V,3200,23,S2,8PSK -28=12064,V,6510,56,DVB-S,QPSK -29=12152,H,15000,Auto,S2,8PSK -30=12165,H,6110,34,DVB-S,QPSK -31=12175,H,4342,Auto,DVB-S,QPSK -32=12184,V,3500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2750.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2750.ini deleted file mode 100644 index 8f2358d56e..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2750.ini +++ /dev/null @@ -1,19 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2750 -2=AMC 16 (85.0W) - -[DVB] -0=10 -1=11966,H,5632,Auto,DVB-S,QPSK -2=11980,H,29270,Auto,DVB-S,QPSK -3=12000,V,29270,Auto,DVB-S,QPSK -4=12106,V,6113,Auto,DVB-S,QPSK -5=12116,V,6113,Auto,DVB-S,QPSK -6=12130,H,13021,Auto,DVB-S,QPSK -7=12144,H,3979,Auto,DVB-S,QPSK -8=12146,V,6111,Auto,DVB-S,QPSK -9=12164,V,6111,Auto,DVB-S,QPSK -10=12194,H,3978,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2760.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2760.ini deleted file mode 100644 index 253d2cced0..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2760.ini +++ /dev/null @@ -1,20 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2760 -2=Brasilsat B4 (84.0W) - -[DVB] -0=11 -1=3643,H,3565,34,DVB-S,QPSK -2=3650,V,3460,12,DVB-S,QPSK -3=3684,V,3200,34,DVB-S,QPSK -4=3690,V,3330,34,DVB-S,QPSK -5=3720,H,2222,34,DVB-S,QPSK -6=3725,H,2222,34,DVB-S,QPSK -7=3785,H,4500,56,DVB-S,QPSK -8=3806,H,1666,34,S2,8PSK -9=3852,V,3333,34,S2,8PSK -10=4135,H,2500,34,DVB-S,QPSK -11=4152,V,3255,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2770.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2770.ini deleted file mode 100644 index 12cbcc729e..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2770.ini +++ /dev/null @@ -1,38 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2770 -2=AMC 9 (83.0W) - -[DVB] -0=29 -1=3804,V,4167,34,DVB-S,QPSK -2=3810,V,2400,34,DVB-S,QPSK -3=3813,V,2222,34,DVB-S,QPSK -4=3817,V,2879,34,DVB-S,QPSK -5=3825,V,4035,56,S2,8PSK -6=3831,V,2960,56,DVB-S,QPSK -7=3912,H,2615,Auto,DVB-S,QPSK -8=11745,H,4232,56,DVB-S,QPSK -9=11751,H,4232,56,DVB-S,QPSK -10=11757,H,4232,56,DVB-S,QPSK -11=11763,H,4232,56,DVB-S,QPSK -12=11769,H,4232,56,DVB-S,QPSK -13=11775,H,4232,56,DVB-S,QPSK -14=11790,H,4232,Auto,DVB-S,QPSK -15=11803,H,4232,Auto,DVB-S,QPSK -16=11809,H,4232,Auto,DVB-S,QPSK -17=11815,H,4232,Auto,DVB-S,QPSK -18=11864,H,3979,Auto,DVB-S,QPSK -19=11871,H,13000,Auto,DVB-S,QPSK -20=11874,V,6111,34,DVB-S,QPSK -21=11889,H,13025,Auto,DVB-S,QPSK -22=11926,V,6511,34,DVB-S,QPSK -23=11953,V,3979,Auto,DVB-S,QPSK -24=11960,H,5000,34,DVB-S,QPSK -25=12002,H,3979,Auto,DVB-S,QPSK -26=12011,H,3979,Auto,DVB-S,QPSK -27=12051,V,13022,Auto,DVB-S,QPSK -28=12160,H,29269,Auto,DVB-S,QPSK -29=12180,V,29271,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2780.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2780.ini deleted file mode 100644 index 7080fc519a..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2780.ini +++ /dev/null @@ -1,40 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2780 -2=Nimiq 4 (82.0W) - -[DVB] -0=31 -1=12224,V,21500,23,DVB-S,8PSK -2=12239,H,21500,23,DVB-S,8PSK -3=12253,V,21500,23,DVB-S,8PSK -4=12268,H,21500,23,DVB-S,8PSK -5=12282,V,21500,23,DVB-S,8PSK -6=12297,H,21500,23,DVB-S,8PSK -7=12311,V,21500,23,DVB-S,8PSK -8=12326,H,21500,23,DVB-S,8PSK -9=12341,V,21500,23,DVB-S,8PSK -10=12355,H,21500,23,DVB-S,8PSK -11=12370,V,21500,23,DVB-S,8PSK -12=12384,H,21500,23,DVB-S,8PSK -13=12399,V,21500,23,DVB-S,8PSK -14=12414,H,21500,23,DVB-S,8PSK -15=12443,H,20000,78,DVB-S,QPSK -16=12457,V,21500,23,DVB-S,8PSK -17=12472,H,21500,23,DVB-S,8PSK -18=12486,V,21500,23,DVB-S,8PSK -19=12501,H,21500,23,DVB-S,8PSK -20=12516,V,21500,23,DVB-S,8PSK -21=12530,H,21500,23,DVB-S,8PSK -22=12545,V,21500,23,DVB-S,8PSK -23=12559,H,21500,23,DVB-S,8PSK -24=12574,V,21500,23,DVB-S,8PSK -25=12588,H,21500,23,DVB-S,8PSK -26=12603,V,21500,23,DVB-S,8PSK -27=12618,H,21500,23,DVB-S,8PSK -28=12632,V,21500,23,DVB-S,8PSK -29=12647,H,21500,23,DVB-S,8PSK -30=12661,V,21500,23,DVB-S,8PSK -31=12676,H,20000,Auto,DVB-S,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2812.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2812.ini deleted file mode 100644 index 61b29bb930..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2812.ini +++ /dev/null @@ -1,29 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2812 -2=Sky Mexico 1 (78.8W) - -[DVB] -0=20 -1=11720,H,30000,Auto,DVB-S,QPSK -2=11740,V,30000,Auto,DVB-S,QPSK -3=11800,H,30000,Auto,DVB-S,QPSK -4=11820,V,30000,Auto,DVB-S,QPSK -5=11880,H,30000,Auto,DVB-S,QPSK -6=11900,V,30000,Auto,DVB-S,QPSK -7=11920,H,30000,Auto,DVB-S,QPSK -8=11940,V,30000,Auto,DVB-S,QPSK -9=11960,H,30000,Auto,DVB-S,QPSK -10=11980,V,30000,Auto,DVB-S,QPSK -11=12000,H,30000,Auto,DVB-S,QPSK -12=12020,V,30000,Auto,DVB-S,QPSK -13=12040,H,30000,Auto,DVB-S,QPSK -14=12060,V,30000,Auto,DVB-S,QPSK -15=12080,H,30000,Auto,DVB-S,QPSK -16=12100,V,30000,Auto,DVB-S,QPSK -17=12120,H,30000,Auto,DVB-S,QPSK -18=12140,V,30000,Auto,DVB-S,QPSK -19=12160,H,30000,Auto,DVB-S,QPSK -20=12180,V,30000,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2820.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2820.ini deleted file mode 100644 index 0aa5cc903c..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2820.ini +++ /dev/null @@ -1,23 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2820 -2=Simn Bolvar (78.0W) - -[DVB] -0=14 -1=3838,V,6670,34,DVB-S,QPSK -2=3885,V,23000,34,DVB-S,QPSK -3=3912,V,3100,Auto,DVB-S,QPSK -4=3916,V,3002,Auto,DVB-S,QPSK -5=3922,V,3002,Auto,DVB-S,QPSK -6=11323,H,3100,Auto,DVB-S,QPSK -7=11380,H,42355,34,S2,QPSK -8=11410,V,29500,34,S2,QPSK -9=11509,V,2900,34,DVB-S,QPSK -10=11512,V,3100,34,DVB-S,QPSK -11=11520,V,4444,34,DVB-S,QPSK -12=11535,H,4340,34,DVB-S,QPSK -13=11624,V,3000,34,DVB-S,QPSK -14=11731,H,28126,56,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2830.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2830.ini deleted file mode 100644 index c6536b22be..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2830.ini +++ /dev/null @@ -1,41 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2830 -2=EchoStar 8/QuetzSat 1 (77.0W) - -[DVB] -0=32 -1=12224,V,22500,56,DVB-S,QPSK -2=12239,H,22500,56,DVB-S,QPSK -3=12253,V,20000,56,DVB-S,QPSK -4=12268,H,22500,56,DVB-S,QPSK -5=12282,V,22500,56,DVB-S,QPSK -6=12297,H,20000,56,DVB-S,QPSK -7=12311,V,22500,56,DVB-S,QPSK -8=12326,H,22500,56,DVB-S,QPSK -9=12341,V,22500,56,DVB-S,QPSK -10=12355,H,20000,56,DVB-S,QPSK -11=12370,V,22500,56,DVB-S,QPSK -12=12384,H,22500,56,DVB-S,QPSK -13=12399,V,20000,56,DVB-S,QPSK -14=12414,H,22500,56,DVB-S,QPSK -15=12428,V,20000,56,DVB-S,QPSK -16=12443,H,22500,56,DVB-S,QPSK -17=12457,V,22500,56,DVB-S,QPSK -18=12472,H,20000,56,DVB-S,QPSK -19=12486,V,20000,56,DVB-S,QPSK -20=12501,H,22500,56,DVB-S,QPSK -21=12516,V,22500,56,DVB-S,QPSK -22=12530,H,22500,56,DVB-S,QPSK -23=12545,V,22500,56,DVB-S,QPSK -24=12559,H,22500,56,DVB-S,QPSK -25=12574,V,22500,56,DVB-S,QPSK -26=12588,H,20000,56,DVB-S,QPSK -27=12603,V,22500,56,DVB-S,QPSK -28=12618,H,22500,56,DVB-S,QPSK -29=12632,V,22500,56,DVB-S,QPSK -30=12647,H,22500,56,DVB-S,QPSK -31=12661,V,20000,56,DVB-S,QPSK -32=12676,H,22500,56,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2850.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2850.ini deleted file mode 100644 index cc6088079e..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2850.ini +++ /dev/null @@ -1,98 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2850 -2=Star One C3 (75.0W) - -[DVB] -0=89 -1=3627,H,3255,34,DVB-S,QPSK -2=3632,H,3333,34,DVB-S,QPSK -3=3636,H,3333,34,DVB-S,QPSK -4=3649,H,3002,34,DVB-S,QPSK -5=3660,V,30000,23,S2,QPSK -6=3665,H,5000,34,S2,QPSK -7=3680,H,2400,34,S2,8PSK -8=3684,H,2500,34,S2,QPSK -9=3684,V,2963,34,DVB-S,QPSK -10=3689,V,2666,34,DVB-S,QPSK -11=3690,H,5000,34,S2,QPSK -12=3697,V,6990,34,S2,QPSK -13=3703,V,2400,23,DVB-S,QPSK -14=3705,H,4280,34,S2,QPSK -15=3706,V,3600,34,DVB-S,QPSK -16=3709,H,3333,34,S2,QPSK -17=3711,V,3255,34,DVB-S,QPSK -18=3714,H,3333,34,DVB-S,QPSK -19=3715,V,2535,34,DVB-S,QPSK -20=3722,H,3565,34,DVB-S,QPSK -21=3727,H,5000,34,S2,QPSK -22=3727,V,5833,34,S2,QPSK -23=3733,V,4444,34,DVB-S,QPSK -24=3735,H,5833,23,S2,QPSK -25=3736,V,2033,89,S2,QPSK -26=3740,V,2072,56,S2,QPSK -27=3745,V,5833,34,S2,QPSK -28=3747,H,6250,34,S2,QPSK -29=3754,H,6250,34,S2,QPSK -30=3765,V,4170,34,S2,QPSK -31=3770,H,17500,34,S2,QPSK -32=3771,V,4170,34,S2,QPSK -33=3776,V,5000,34,S2,8PSK -34=3780,V,2222,78,DVB-S,QPSK -35=3784,V,2500,34,S2,QPSK -36=3788,V,1111,34,DVB-S,QPSK -37=3828,V,4340,34,DVB-S,QPSK -38=3833,V,3255,34,DVB-S,QPSK -39=3837,V,2532,34,DVB-S,QPSK -40=3846,V,4340,56,DVB-S,QPSK -41=3852,V,6247,34,S2,QPSK -42=3863,V,3209,34,DVB-S,QPSK -43=3868,V,4283,34,DVB-S,QPSK -44=3874,V,6250,34,S2,QPSK -45=3883,H,3928,34,DVB-S,QPSK -46=3885,V,5000,23,S2,QPSK -47=3890,H,2170,34,DVB-S,QPSK -48=3890,V,3704,34,DVB-S,QPSK -49=3895,H,5833,34,S2,QPSK -50=3901,V,5000,34,S2,8PSK -51=3907,V,2232,34,DVB-S,QPSK -52=3910,H,12500,23,S2,QPSK -53=3911,V,2222,34,DVB-S,QPSK -54=3917,V,3750,34,S2,QPSK -55=3925,V,5000,34,S2,QPSK -56=3927,H,14100,23,S2,8PSK -57=3935,V,8000,34,DVB-S,QPSK -58=3936,H,3195,35,S2,QPSK -59=3943,V,3260,34,DVB-S,QPSK -60=3954,V,6666,34,S2,QPSK -61=3979,V,3255,34,DVB-S,QPSK -62=3986,V,5590,34,DVB-S,QPSK -63=3994,V,6250,34,S2,QPSK -64=4048,V,3330,56,DVB-S,QPSK -65=4052,V,2500,34,S2,QPSK -66=4055,V,2500,34,DVB-S,QPSK -67=4066,H,5833,23,S2,QPSK -68=4073,H,5833,34,S2,8PSK -69=4080,H,5833,23,S2,QPSK -70=4086,H,4170,34,S2,QPSK -71=4091,H,4170,34,S2,QPSK -72=4096,H,4170,34,S2,QPSK -73=4100,V,30000,56,S2,8PSK -74=4105,H,3633,34,S2,QPSK -75=4120,H,20840,34,S2,QPSK -76=4136,H,4170,34,S2,QPSK -77=4144,H,5000,34,S2,QPSK -78=4151,H,5000,34,S2,QPSK -79=4157,H,5000,34,S2,QPSK -80=4164,H,5000,34,S2,QPSK -81=4165,V,5000,34,S2,QPSK -82=4170,H,5000,34,S2,8PSK -83=4171,V,5000,34,S2,QPSK -84=4175,H,5000,34,S2,QPSK -85=4177,V,5000,34,S2,QPSK -86=4183,H,5000,34,S2,QPSK -87=4193,V,4762,34,S2,QPSK -88=4197,V,2073,56,S2,QPSK -89=11764,V,3480,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2873.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2873.ini deleted file mode 100644 index 6c39037ae5..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2873.ini +++ /dev/null @@ -1,40 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2873 -2=Nimiq 5 (72.7W) - -[DVB] -0=31 -1=12224,V,21500,23,DVB-S,8PSK -2=12239,H,21500,23,DVB-S,8PSK -3=12253,V,21500,23,DVB-S,8PSK -4=12268,H,21500,23,DVB-S,8PSK -5=12282,V,21500,23,DVB-S,8PSK -6=12297,H,21500,23,DVB-S,8PSK -7=12311,V,21500,23,DVB-S,8PSK -8=12326,H,21500,23,DVB-S,8PSK -9=12341,V,21500,23,DVB-S,8PSK -10=12355,H,21500,23,DVB-S,8PSK -11=12370,V,21500,23,DVB-S,8PSK -12=12384,H,21500,23,DVB-S,8PSK -13=12399,V,21500,23,DVB-S,8PSK -14=12428,V,21500,23,DVB-S,8PSK -15=12443,H,21500,23,DVB-S,8PSK -16=12457,V,21500,23,DVB-S,8PSK -17=12472,H,21500,23,DVB-S,8PSK -18=12486,V,21500,23,DVB-S,8PSK -19=12501,H,21500,23,DVB-S,8PSK -20=12516,V,21500,23,DVB-S,8PSK -21=12530,H,21500,23,DVB-S,8PSK -22=12545,V,21500,23,DVB-S,8PSK -23=12559,H,21500,23,DVB-S,8PSK -24=12574,V,21500,23,DVB-S,8PSK -25=12588,H,21500,23,DVB-S,8PSK -26=12603,V,21500,23,DVB-S,8PSK -27=12618,H,21500,23,DVB-S,8PSK -28=12632,V,21500,23,DVB-S,8PSK -29=12647,H,21500,23,DVB-S,8PSK -30=12661,V,21500,23,DVB-S,8PSK -31=12676,H,21500,23,DVB-S,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2880.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2880.ini deleted file mode 100644 index 2abb9f716b..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2880.ini +++ /dev/null @@ -1,38 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2880 -2=AMC 6 (72.0W) - -[DVB] -0=29 -1=11703,V,3979,Auto,DVB-S,QPSK -2=11709,V,4600,34,S2,8PSK -3=11715,V,4600,34,S2,8PSK -4=11720,V,4600,34,S2,8PSK -5=11725,V,3979,Auto,DVB-S,QPSK -6=11729,V,3979,Auto,DVB-S,QPSK -7=11734,V,3979,Auto,DVB-S,QPSK -8=11745,H,3979,Auto,DVB-S,QPSK -9=11746,V,3979,Auto,DVB-S,QPSK -10=11752,V,3979,Auto,DVB-S,QPSK -11=11760,V,4600,34,S2,8PSK -12=11766,V,4600,34,S2,8PSK -13=11778,V,4600,34,S2,8PSK -14=11817,H,5000,34,DVB-S,QPSK -15=11921,V,3979,Auto,DVB-S,QPSK -16=11927,V,3979,Auto,DVB-S,QPSK -17=11986,V,3979,34,DVB-S,QPSK -18=11995,V,3979,34,DVB-S,QPSK -19=12004,V,6889,Auto,DVB-S,QPSK -20=12020,H,3979,Auto,DVB-S,QPSK -21=12028,V,4600,34,S2,8PSK -22=12036,H,6111,Auto,DVB-S,QPSK -23=12040,V,3979,Auto,DVB-S,QPSK -24=12045,V,1580,Auto,DVB-S,QPSK -25=12046,H,6111,Auto,DVB-S,QPSK -26=12055,V,6890,56,DVB-S,QPSK -27=12114,V,13000,Auto,DVB-S,QPSK -28=12130,V,6111,Auto,DVB-S,QPSK -29=12188,H,6511,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2881.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2881.ini deleted file mode 100644 index 5a3d34b2c1..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2881.ini +++ /dev/null @@ -1,112 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2881 -2=AMC 6/Arsat 1 (71.9W) - -[DVB] -0=103 -1=11175,V,4200,34,DVB-S,QPSK -2=11179,V,3100,34,DVB-S,QPSK -3=11466,V,3500,34,DVB-S,QPSK -4=11540,H,3330,34,DVB-S,QPSK -5=11544,H,6660,Auto,DVB-S,QPSK -6=11546,V,12000,23,DVB-S,QPSK -7=11552,H,2591,34,DVB-S,QPSK -8=11555,H,1904,Auto,DVB-S,QPSK -9=11564,H,3200,34,DVB-S,QPSK -10=11568,H,3350,34,DVB-S,QPSK -11=11573,H,3333,34,DVB-S,QPSK -12=11577,H,3333,34,DVB-S,QPSK -13=11577,V,2400,56,DVB-S,QPSK -14=11581,H,1325,34,DVB-S,QPSK -15=11582,V,2850,34,S2,8PSK -16=11584,H,2655,78,DVB-S,QPSK -17=11595,H,1904,78,DVB-S,QPSK -18=11598,H,2500,34,DVB-S,QPSK -19=11640,V,8500,Auto,DVB-S,QPSK -20=11651,V,1904,78,DVB-S,QPSK -21=11657,H,1904,78,DVB-S,QPSK -22=11660,H,2500,Auto,S2,8PSK -23=11660,V,2943,Auto,DVB-S,QPSK -24=11667,H,6665,34,S2,QPSK -25=11670,V,30000,56,S2,QPSK -26=11675,H,1904,34,DVB-S,QPSK -27=11678,H,1904,34,DVB-S,QPSK -28=11686,V,2222,34,DVB-S,QPSK -29=11703,V,3979,Auto,DVB-S,QPSK -30=11708,H,6660,34,S2,8PSK -31=11709,V,4600,34,S2,8PSK -32=11715,V,4600,34,S2,8PSK -33=11718,H,6660,12,S2,8PSK -34=11718,V,6660,34,S2,8PSK -35=11720,V,4600,34,S2,8PSK -36=11725,V,3979,Auto,DVB-S,QPSK -37=11728,V,3300,34,DVB-S,QPSK -38=11729,V,3979,Auto,DVB-S,QPSK -39=11731,H,3124,34,DVB-S,QPSK -40=11734,H,2655,34,DVB-S,QPSK -41=11734,V,3979,Auto,DVB-S,QPSK -42=11745,V,2373,34,DVB-S,QPSK -43=11745,H,3979,Auto,DVB-S,QPSK -44=11746,V,3979,Auto,DVB-S,QPSK -45=11752,H,2373,34,DVB-S,QPSK -46=11752,V,3979,Auto,DVB-S,QPSK -47=11755,H,2963,Auto,S2,QPSK -48=11756,V,3200,34,DVB-S,QPSK -49=11760,V,4600,34,S2,8PSK -50=11766,V,4600,34,S2,8PSK -51=11778,V,4600,34,S2,8PSK -52=11779,V,3600,Auto,DVB-S,QPSK -53=11794,V,3600,Auto,DVB-S,QPSK -54=11805,V,3300,Auto,DVB-S,QPSK -55=11809,V,3350,Auto,DVB-S,QPSK -56=11817,H,5000,34,DVB-S,QPSK -57=11817,V,3333,34,DVB-S,QPSK -58=11829,V,3330,34,DVB-S,QPSK -59=11848,V,3333,34,DVB-S,QPSK -60=11851,V,3350,34,S2,QPSK -61=11853,V,2343,34,DVB-S,QPSK -62=11861,V,3330,34,DVB-S,QPSK -63=11866,V,3300,34,DVB-S,QPSK -64=11870,H,14089,23,S2,QPSK -65=11876,H,6666,Auto,DVB-S,QPSK -66=11877,V,2355,34,DVB-S,QPSK -67=11882,H,3333,34,S2,QPSK -68=11888,V,3330,34,DVB-S,QPSK -69=11892,H,3333,Auto,DVB-S,QPSK -70=11896,H,3330,34,DVB-S,QPSK -71=11897,V,3200,34,DVB-S,QPSK -72=11907,V,2373,34,DVB-S,QPSK -73=11910,V,2600,34,S2,8PSK -74=11915,V,2600,34,DVB-S,QPSK -75=11921,V,3979,Auto,DVB-S,QPSK -76=11927,V,3979,Auto,DVB-S,QPSK -77=11986,V,3979,34,DVB-S,QPSK -78=11995,V,3979,34,DVB-S,QPSK -79=12004,V,6889,Auto,DVB-S,QPSK -80=12020,H,3979,Auto,DVB-S,QPSK -81=12028,V,4600,34,S2,8PSK -82=12036,H,6111,Auto,DVB-S,QPSK -83=12040,V,3979,Auto,DVB-S,QPSK -84=12045,V,1580,Auto,DVB-S,QPSK -85=12046,H,6111,Auto,DVB-S,QPSK -86=12051,V,2200,56,DVB-S,QPSK -87=12054,H,6620,34,S2,8PSK -88=12055,V,2150,Auto,S2,8PSK -89=12058,V,2223,56,DVB-S,QPSK -90=12058,H,7400,23,DVB-S,QPSK -91=12063,V,4170,23,DVB-S,QPSK -92=12066,H,2500,34,DVB-S,QPSK -93=12067,V,3333,34,DVB-S,QPSK -94=12070,H,2000,56,DVB-S,QPSK -95=12074,V,2400,56,DVB-S,QPSK -96=12075,H,1660,56,S2,8PSK -97=12080,H,7200,34,S2,QPSK -98=12083,V,2850,78,DVB-S,QPSK -99=12086,V,4170,23,DVB-S,QPSK -100=12092,H,4000,23,DVB-S,QPSK -101=12114,V,13000,Auto,DVB-S,QPSK -102=12130,V,6111,Auto,DVB-S,QPSK -103=12188,H,6511,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2882.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2882.ini deleted file mode 100644 index 591ba2fe42..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2882.ini +++ /dev/null @@ -1,84 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2882 -2=Arsat 1 (71.8W) - -[DVB] -0=75 -1=11175,V,4200,34,DVB-S,QPSK -2=11179,V,3100,34,DVB-S,QPSK -3=11466,V,3500,34,DVB-S,QPSK -4=11540,H,3330,34,DVB-S,QPSK -5=11544,H,6660,Auto,DVB-S,QPSK -6=11546,V,12000,23,DVB-S,QPSK -7=11552,H,2591,34,DVB-S,QPSK -8=11555,H,1904,Auto,DVB-S,QPSK -9=11564,H,3200,34,DVB-S,QPSK -10=11568,H,3350,34,DVB-S,QPSK -11=11573,H,3333,34,DVB-S,QPSK -12=11577,H,3333,34,DVB-S,QPSK -13=11577,V,2400,56,DVB-S,QPSK -14=11581,H,1325,34,DVB-S,QPSK -15=11582,V,2850,34,S2,8PSK -16=11584,H,2655,78,DVB-S,QPSK -17=11595,H,1904,78,DVB-S,QPSK -18=11598,H,2500,34,DVB-S,QPSK -19=11640,V,8500,Auto,DVB-S,QPSK -20=11651,V,1904,78,DVB-S,QPSK -21=11657,H,1904,78,DVB-S,QPSK -22=11660,H,2500,Auto,S2,8PSK -23=11660,V,2943,Auto,DVB-S,QPSK -24=11667,H,6665,34,S2,QPSK -25=11670,V,30000,56,S2,QPSK -26=11675,H,1904,34,DVB-S,QPSK -27=11678,H,1904,34,DVB-S,QPSK -28=11686,V,2222,34,DVB-S,QPSK -29=11708,H,6660,34,S2,8PSK -30=11718,H,6660,12,S2,8PSK -31=11718,V,6660,34,S2,8PSK -32=11728,V,3300,34,DVB-S,QPSK -33=11731,H,3124,34,DVB-S,QPSK -34=11734,H,2655,34,DVB-S,QPSK -35=11745,V,2373,34,DVB-S,QPSK -36=11752,H,2373,34,DVB-S,QPSK -37=11755,H,2963,Auto,S2,QPSK -38=11756,V,3200,34,DVB-S,QPSK -39=11779,V,3600,Auto,DVB-S,QPSK -40=11794,V,3600,Auto,DVB-S,QPSK -41=11805,V,3300,Auto,DVB-S,QPSK -42=11809,V,3350,Auto,DVB-S,QPSK -43=11817,V,3333,34,DVB-S,QPSK -44=11829,V,3330,34,DVB-S,QPSK -45=11848,V,3333,34,DVB-S,QPSK -46=11851,V,3350,34,S2,QPSK -47=11853,V,2343,34,DVB-S,QPSK -48=11861,V,3330,34,DVB-S,QPSK -49=11866,V,3300,34,DVB-S,QPSK -50=11870,H,14089,23,S2,QPSK -51=11876,H,6666,Auto,DVB-S,QPSK -52=11877,V,2355,34,DVB-S,QPSK -53=11882,H,3333,34,S2,QPSK -54=11888,V,3330,34,DVB-S,QPSK -55=11892,H,3333,Auto,DVB-S,QPSK -56=11896,H,3330,34,DVB-S,QPSK -57=11897,V,3200,34,DVB-S,QPSK -58=11907,V,2373,34,DVB-S,QPSK -59=11910,V,2600,34,S2,8PSK -60=11915,V,2600,34,DVB-S,QPSK -61=12051,V,2200,56,DVB-S,QPSK -62=12054,H,6620,34,S2,8PSK -63=12055,V,2150,Auto,S2,8PSK -64=12058,H,7400,23,DVB-S,QPSK -65=12058,V,2223,56,DVB-S,QPSK -66=12063,V,4170,23,DVB-S,QPSK -67=12066,H,2500,34,DVB-S,QPSK -68=12067,V,3333,34,DVB-S,QPSK -69=12070,H,2000,56,DVB-S,QPSK -70=12074,V,2400,56,DVB-S,QPSK -71=12075,H,1660,56,S2,8PSK -72=12080,H,7200,34,S2,QPSK -73=12083,V,2850,78,DVB-S,QPSK -74=12086,V,4170,23,DVB-S,QPSK -75=12092,H,4000,23,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2900.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2900.ini deleted file mode 100644 index 3a4144bf6b..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2900.ini +++ /dev/null @@ -1,72 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2900 -2=Star One C2/C4 (70.0W) - -[DVB] -0=63 -1=3628,H,3000,34,DVB-S,QPSK -2=3632,H,4688,34,DVB-S,QPSK -3=3642,H,4583,34,S2,8PSK -4=3644,V,3214,34,DVB-S,QPSK -5=3648,V,2170,34,DVB-S,QPSK -6=3650,H,5000,23,S2,8PSK -7=3652,V,2777,23,DVB-S,QPSK -8=3656,H,3393,34,DVB-S,QPSK -9=3657,V,7500,23,DVB-S,QPSK -10=3665,V,2400,34,DVB-S,QPSK -11=3665,H,3818,34,DVB-S,QPSK -12=3667,V,2500,56,DVB-S,QPSK -13=3672,H,7500,23,S2,8PSK -14=3674,V,6666,34,DVB-S,QPSK -15=3680,H,7500,23,S2,8PSK -16=3685,V,5000,34,S2,8PSK -17=3689,H,7500,23,S2,8PSK -18=3690,V,2220,34,DVB-S,QPSK -19=3695,H,3599,34,DVB-S,QPSK -20=3702,V,15000,34,S2,8PSK -21=3704,H,3750,23,S2,8PSK -22=3711,V,2170,34,DVB-S,QPSK -23=3715,V,5000,34,S2,8PSK -24=3753,V,6220,34,DVB-S,QPSK -25=3808,V,7500,23,S2,QPSK -26=3816,V,6666,23,S2,8PSK -27=3825,V,6666,23,S2,8PSK -28=3833,V,4073,56,S2,8PSK -29=3874,V,7500,23,S2,8PSK -30=3887,V,7500,Auto,S2,8PSK -31=3895,V,7500,23,S2,8PSK -32=3906,V,7500,23,S2,8PSK -33=3916,V,7500,23,S2,8PSK -34=3940,V,30000,23,S2,8PSK -35=3947,H,7200,23,DVB-S,QPSK -36=3955,H,4400,34,DVB-S,QPSK -37=3959,H,1875,34,DVB-S,QPSK -38=3965,V,4069,23,DVB-S,QPSK -39=3967,H,7500,23,S2,8PSK -40=3970,V,1852,56,DVB-S,QPSK -41=3973,V,4000,23,DVB-S,QPSK -42=3973,H,7500,23,S2,8PSK -43=3978,V,3617,56,DVB-S,QPSK -44=3982,V,4573,34,S2,8PSK -45=3985,H,2170,34,DVB-S,QPSK -46=3990,V,7400,34,S2,8PSK -47=3993,H,12416,Auto,DVB-S,QPSK -48=3996,V,2300,34,DVB-S,QPSK -49=4047,V,7143,34,DVB-S,QPSK -50=10974,H,29890,34,DVB-S,QPSK -51=11014,H,29890,35,S2,QPSK -52=11130,V,29890,34,DVB-S,QPSK -53=11170,V,29890,34,DVB-S,QPSK -54=11740,H,29890,34,S2,8PSK -55=11780,H,29890,34,DVB-S,QPSK -56=11820,H,29890,34,DVB-S,QPSK -57=11880,H,41500,34,DVB-S,QPSK -58=11940,H,29890,34,DVB-S,QPSK -59=11960,V,29900,35,S2,QPSK -60=12020,V,41500,34,DVB-S,QPSK -61=12080,V,29890,34,S2,8PSK -62=12120,V,29890,34,DVB-S,QPSK -63=12160,V,28890,35,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2930.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2930.ini deleted file mode 100644 index b144562e4d..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2930.ini +++ /dev/null @@ -1,16 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2930 -2=AMC 4 (67.0W) - -[DVB] -0=7 -1=11720,V,28888,34,DVB-S,QPSK -2=11760,V,28888,34,DVB-S,QPSK -3=11800,V,28888,34,DVB-S,QPSK -4=11840,V,28888,34,DVB-S,QPSK -5=11880,V,28888,34,DVB-S,QPSK -6=11920,V,28888,34,DVB-S,QPSK -7=12162,V,9600,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2950.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2950.ini deleted file mode 100644 index 3b6a477fc3..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2950.ini +++ /dev/null @@ -1,51 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2950 -2=Star One C1 (65.0W) - -[DVB] -0=42 -1=3650,V,4440,Auto,DVB-S,QPSK -2=3669,V,4686,34,S2,8PSK -3=3670,H,9043,34,S2,QPSK -4=3687,H,3214,Auto,DVB-S,QPSK -5=3691,H,4000,23,S2,8PSK -6=3697,H,4400,23,S2,8PSK -7=3720,H,2963,34,DVB-S,QPSK -8=3732,V,2222,Auto,DVB-S,QPSK -9=3734,V,2852,34,DVB-S,QPSK -10=3736,H,1808,34,DVB-S,QPSK -11=3736,V,2853,34,DVB-S,QPSK -12=3744,H,2110,Auto,DVB-S,QPSK -13=3762,H,2222,78,DVB-S,QPSK -14=3766,H,3336,34,DVB-S,QPSK -15=3771,V,1480,34,DVB-S,QPSK -16=3774,V,2222,34,DVB-S,QPSK -17=3792,V,3393,34,DVB-S,QPSK -18=3800,H,30000,56,S2,8PSK -19=3832,H,4800,56,DVB-S,QPSK -20=3850,H,6666,Auto,DVB-S,QPSK -21=3853,H,2170,78,DVB-S,QPSK -22=3864,H,3333,34,DVB-S,QPSK -23=3876,V,2740,34,DVB-S,QPSK -24=3894,H,6666,Auto,DVB-S,QPSK -25=3920,H,27500,78,DVB-S,QPSK -26=3926,V,7072,34,S2,8PSK -27=3935,V,7072,23,S2,8PSK -28=3943,V,8500,34,S2,8PSK -29=3950,V,3200,23,S2,8PSK -30=3968,V,7500,Auto,S2,8PSK -31=3975,V,4167,34,S2,QPSK -32=4014,H,3750,Auto,S2,8PSK -33=4017,H,2083,34,S2,8PSK -34=4046,V,4000,56,DVB-S,QPSK -35=4051,V,5416,23,S2,8PSK -36=4100,V,30000,56,S2,8PSK -37=4121,H,4800,34,DVB-S,QPSK -38=4130,H,1850,23,DVB-S,QPSK -39=4140,V,30000,56,S2,8PSK -40=11885,H,2000,12,S2,QPSK -41=11893,H,2034,Auto,DVB-S,QPSK -42=11930,H,14400,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2970.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2970.ini deleted file mode 100644 index 60e1423fd8..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2970.ini +++ /dev/null @@ -1,27 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2970 -2=Telstar 14R (63.0W) - -[DVB] -0=18 -1=11600,V,13744,Auto,DVB-S,QPSK -2=11640,V,18100,78,DVB-S,QPSK -3=11706,V,2278,34,S2,QPSK -4=11710,V,3200,23,DVB-S,QPSK -5=11722,V,2963,34,DVB-S,QPSK -6=11726,V,3333,34,DVB-S,QPSK -7=11732,V,2222,Auto,DVB-S,QPSK -8=11736,V,2963,34,DVB-S,QPSK -9=11795,V,4444,Auto,DVB-S,QPSK -10=11805,V,6666,Auto,DVB-S,QPSK -11=11827,V,3200,Auto,DVB-S,QPSK -12=11844,V,5348,Auto,DVB-S,QPSK -13=11850,V,2280,34,DVB-S,QPSK -14=11871,V,2000,34,DVB-S,QPSK -15=11888,V,3330,34,DVB-S,QPSK -16=11905,V,2362,34,DVB-S,QPSK -17=11958,H,3255,Auto,DVB-S,QPSK -18=12162,H,13021,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2985.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2985.ini deleted file mode 100644 index 1dc03e67ff..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2985.ini +++ /dev/null @@ -1,41 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2985 -2=EchoStar 12/16 (61.5W) - -[DVB] -0=32 -1=12224,V,20000,78,DVB-S,QPSK -2=12239,H,21500,23,DVB-S,8PSK -3=12253,V,21500,23,DVB-S,8PSK -4=12268,H,21500,23,DVB-S,8PSK -5=12282,V,21500,23,DVB-S,8PSK -6=12297,H,21500,23,DVB-S,8PSK -7=12311,V,21500,23,DVB-S,8PSK -8=12326,H,21500,23,DVB-S,8PSK -9=12341,V,21500,23,DVB-S,8PSK -10=12355,H,21500,23,DVB-S,8PSK -11=12370,V,21500,23,DVB-S,8PSK -12=12384,H,21500,23,DVB-S,8PSK -13=12399,V,21500,23,DVB-S,8PSK -14=12414,H,20000,78,DVB-S,QPSK -15=12428,V,21500,23,DVB-S,8PSK -16=12443,H,21500,23,DVB-S,8PSK -17=12457,V,21500,23,DVB-S,8PSK -18=12472,H,21500,34,DVB-S,8PSK -19=12486,V,21500,34,DVB-S,8PSK -20=12501,H,21500,34,DVB-S,8PSK -21=12516,V,21500,34,DVB-S,8PSK -22=12530,H,21500,34,DVB-S,8PSK -23=12545,V,21500,34,DVB-S,8PSK -24=12559,H,21500,34,DVB-S,8PSK -25=12574,V,21500,34,DVB-S,8PSK -26=12588,H,21500,34,DVB-S,8PSK -27=12603,V,21500,34,DVB-S,8PSK -28=12618,H,21500,34,DVB-S,8PSK -29=12632,V,21500,34,DVB-S,8PSK -30=12647,H,21500,34,DVB-S,8PSK -31=12661,V,21500,34,DVB-S,8PSK -32=12676,H,21500,34,DVB-S,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2990.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2990.ini deleted file mode 100644 index ce35c62f5d..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/2990.ini +++ /dev/null @@ -1,67 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=2990 -2=Amazonas 2/3/4A (61.0W) - -[DVB] -0=58 -1=3630,H,2785,34,DVB-S,QPSK -2=3659,H,6666,Auto,DVB-S,QPSK -3=3668,H,6666,Auto,DVB-S,QPSK -4=3767,H,1600,34,S2,QPSK -5=3925,V,3333,34,DVB-S,QPSK -6=3927,V,2222,34,DVB-S,QPSK -7=3941,V,3480,34,DVB-S,QPSK -8=3948,H,4440,Auto,DVB-S,QPSK -9=3958,H,4440,Auto,DVB-S,QPSK -10=3967,H,6670,Auto,DVB-S,QPSK -11=3990,H,2142,34,DVB-S,QPSK -12=3996,H,7501,23,S2,8PSK -13=4139,H,4543,34,S2,QPSK -14=4142,V,2651,34,DVB-S,QPSK -15=4148,H,5384,35,S2,8PSK -16=4156,H,2813,Auto,DVB-S,QPSK -17=4160,V,2500,34,S2,QPSK -18=4164,H,3846,34,DVB-S,QPSK -19=4168,H,3461,34,DVB-S,QPSK -20=10728,H,28888,34,DVB-S,QPSK -21=10728,V,30000,34,S2,8PSK -22=10768,H,28888,34,DVB-S,QPSK -23=10768,V,30000,23,S2,8PSK -24=10808,H,30000,23,S2,8PSK -25=10848,H,30000,23,S2,8PSK -26=10888,V,28888,34,DVB-S,QPSK -27=10928,H,28888,34,DVB-S,QPSK -28=11015,H,28880,34,DVB-S,QPSK -29=11026,V,10805,23,S2,8PSK -30=11055,H,28880,34,DVB-S,QPSK -31=11095,H,28880,34,DVB-S,QPSK -32=11095,V,30000,23,S2,8PSK -33=11135,H,28880,34,DVB-S,QPSK -34=11135,V,28880,Auto,DVB-S,QPSK -35=11175,H,28888,34,DVB-S,QPSK -36=11222,H,28888,34,DVB-S,QPSK -37=11222,V,30000,23,S2,8PSK -38=11262,H,30000,23,S2,8PSK -39=11262,V,30000,23,S2,8PSK -40=11302,H,28888,34,DVB-S,QPSK -41=11342,H,28888,34,DVB-S,QPSK -42=11342,V,30000,23,S2,8PSK -43=11382,H,28888,34,DVB-S,QPSK -44=11422,H,28888,34,DVB-S,QPSK -45=11738,V,40000,23,DVB-S,QPSK -46=11851,H,28880,Auto,DVB-S,QPSK -47=11885,H,15000,23,S2,8PSK -48=11932,H,28888,23,DVB-S,QPSK -49=11972,V,30000,34,DVB-S,QPSK -50=11972,H,28888,34,DVB-S,QPSK -51=12012,H,28888,34,DVB-S,QPSK -52=12052,H,28888,34,DVB-S,QPSK -53=12060,V,18000,Auto,DVB-S,QPSK -54=12092,V,30000,23,DVB-S,QPSK -55=12092,H,28880,34,DVB-S,QPSK -56=12132,H,30000,23,S2,8PSK -57=12172,V,30000,23,DVB-S,QPSK -58=12172,H,30000,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3020.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3020.ini deleted file mode 100644 index 3b6673b47d..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3020.ini +++ /dev/null @@ -1,67 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3020 -2=Intelsat 21 (58.0W) - -[DVB] -0=58 -1=3720,V,30000,89,S2,8PSK -2=3720,H,27000,34,S2,8PSK -3=3760,V,27690,78,DVB-S,QPSK -4=3760,H,30000,56,S2,8PSK -5=3785,H,5200,910,S2,QPSK -6=3791,H,3330,34,DVB-S,QPSK -7=3797,H,2218,34,DVB-S,QPSK -8=3805,H,3147,34,DVB-S,QPSK -9=3840,V,27690,78,DVB-S,QPSK -10=3840,H,27690,78,DVB-S,QPSK -11=3880,V,30000,34,S2,8PSK -12=3880,H,27690,78,DVB-S,QPSK -13=3910,V,15000,23,S2,8PSK -14=3920,H,27690,78,S2,QPSK -15=3924,V,6620,34,DVB-S,QPSK -16=3933,V,7000,34,DVB-S,QPSK -17=3952,H,15145,23,S2,8PSK -18=3960,V,30000,34,S2,8PSK -19=3972,H,9850,56,S2,QPSK -20=4000,H,28120,56,S2,8PSK -21=4040,V,30000,56,S2,8PSK -22=4040,H,26590,12,DVB-S,QPSK -23=4080,V,27690,56,DVB-S,QPSK -24=4080,H,30000,56,S2,8PSK -25=4107,H,9850,34,DVB-S,QPSK -26=4120,V,27500,34,DVB-S,QPSK -27=4122,H,2222,34,DVB-S,QPSK -28=4126,H,3700,34,DVB-S,QPSK -29=4137,H,2020,56,DVB-S,QPSK -30=4144,V,2205,34,DVB-S,QPSK -31=4147,H,6111,34,S2,QPSK -32=4151,V,3000,78,DVB-S,QPSK -33=4155,H,5632,34,DVB-S,QPSK -34=4156,V,4300,56,DVB-S,QPSK -35=4160,V,2941,34,DVB-S,QPSK -36=4166,H,5632,34,DVB-S,QPSK -37=4169,V,3000,34,DVB-S,QPSK -38=4174,V,2941,34,DVB-S,QPSK -39=4175,H,6620,34,DVB-S,QPSK -40=11648,V,2520,Auto,DVB-S,QPSK -41=11693,V,2970,Auto,DVB-S,QPSK -42=11720,H,30000,35,S2,8PSK -43=11740,V,30000,35,S2,8PSK -44=11840,H,30000,56,DVB-S,QPSK -45=11860,V,30000,35,S2,8PSK -46=11960,H,30000,Auto,DVB-S,QPSK -47=11980,V,30000,Auto,DVB-S,QPSK -48=12000,H,30000,Auto,DVB-S,QPSK -49=12020,V,30000,Auto,DVB-S,QPSK -50=12040,H,30000,Auto,DVB-S,QPSK -51=12060,V,30000,Auto,DVB-S,QPSK -52=12067,V,2522,23,DVB-S,QPSK -53=12080,H,30000,Auto,DVB-S,QPSK -54=12100,V,30000,Auto,DVB-S,QPSK -55=12120,H,30000,Auto,DVB-S,QPSK -56=12140,V,30000,Auto,DVB-S,QPSK -57=12160,H,30000,Auto,DVB-S,QPSK -58=12180,V,30000,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3045.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3045.ini deleted file mode 100644 index 1d462c1a83..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3045.ini +++ /dev/null @@ -1,107 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3045 -2=Amazonas 1/Galaxy 11/Intelsat 805 (55.5W) - -[DVB] -0=98 -1=3478,V,5632,34,DVB-S,QPSK -2=3670,H,1374,34,DVB-S,QPSK -3=3675,V,7120,34,S2,8PSK -4=3678,H,2960,34,DVB-S,QPSK -5=3682,V,3333,34,DVB-S,QPSK -6=3687,V,3333,34,DVB-S,QPSK -7=3688,H,3320,34,DVB-S,QPSK -8=3693,H,3320,34,DVB-S,QPSK -9=3715,H,8890,34,DVB-S,QPSK -10=3719,V,1950,Auto,S2,8PSK -11=3727,V,3333,34,DVB-S,QPSK -12=3735,V,8681,34,DVB-S,QPSK -13=3740,H,1205,23,DVB-S,QPSK -14=3743,H,2500,34,S2,8PSK -15=3747,H,1600,35,S2,QPSK -16=3750,V,3750,Auto,S2,8PSK -17=3754,H,4232,34,DVB-S,QPSK -18=3759,V,18400,23,S2,8PSK -19=3759,H,2963,34,DVB-S,QPSK -20=3763,H,3000,34,S2,QPSK -21=3768,H,4427,23,DVB-S,QPSK -22=3776,H,7996,35,S2,8PSK -23=3791,V,3255,Auto,DVB-S,QPSK -24=3794,H,1600,23,S2,QPSK -25=3808,V,26666,78,DVB-S,QPSK -26=3816,H,26666,34,DVB-S,QPSK -27=3823,V,4430,34,DVB-S,QPSK -28=3836,H,2500,34,S2,QPSK -29=3839,H,2600,89,S2,QPSK -30=3842,H,2580,34,DVB-S,QPSK -31=3845,V,26700,34,DVB-S,QPSK -32=3849,H,1600,23,S2,8PSK -33=3855,H,2220,Auto,S2,8PSK -34=3859,H,3330,56,S2,8PSK -35=3872,H,9333,35,S2,8PSK -36=3890,H,3333,56,DVB-S,QPSK -37=3894,H,3617,34,DVB-S,QPSK -38=3910,H,5832,56,S2,QPSK -39=3915,H,3300,34,DVB-S,QPSK -40=3924,H,7200,34,S2,8PSK -41=3930,H,3255,23,DVB-S,QPSK -42=3936,H,3255,23,DVB-S,QPSK -43=3963,V,3330,34,DVB-S,QPSK -44=3965,H,7120,34,S2,8PSK -45=3966,V,2963,34,DVB-S,QPSK -46=3970,V,3702,23,DVB-S,QPSK -47=3972,H,6920,34,S2,8PSK -48=3978,H,3200,34,DVB-S,QPSK -49=3982,H,4440,34,DVB-S,QPSK -50=3987,V,3330,34,S2,8PSK -51=3990,V,3590,23,S2,8PSK -52=3991,H,6666,34,DVB-S,QPSK -53=4003,V,8681,34,DVB-S,QPSK -54=4011,V,3330,23,S2,8PSK -55=4015,H,30000,23,S2,8PSK -56=4023,V,4289,Auto,DVB-S,QPSK -57=4028,V,4410,34,DVB-S,QPSK -58=4042,H,7120,34,DVB-S,QPSK -59=4052,V,3125,34,DVB-S,QPSK -60=4056,H,3320,34,DVB-S,QPSK -61=4067,V,4440,34,DVB-S,QPSK -62=4070,H,7120,34,S2,8PSK -63=4080,V,4400,56,DVB-S,QPSK -64=4084,H,10560,35,S2,8PSK -65=4086,V,4074,56,S2,QPSK -66=4093,V,3617,34,DVB-S,QPSK -67=4093,H,3040,35,S2,8PSK -68=4096,H,1300,35,S2,8PSK -69=4097,V,3700,78,DVB-S,QPSK -70=4098,H,2272,56,S2,QPSK -71=4100,H,1840,35,S2,8PSK -72=4101,V,2320,89,S2,QPSK -73=4106,H,5360,35,S2,8PSK -74=4107,V,2960,34,DVB-S,QPSK -75=4111,V,1850,23,S2,8PSK -76=4111,H,4000,35,S2,8PSK -77=4127,H,2961,34,DVB-S,QPSK -78=4134,H,4444,34,DVB-S,QPSK -79=4136,V,30000,56,S2,8PSK -80=4137,H,2000,34,DVB-S,8PSK -81=4142,H,5000,34,S2,8PSK -82=4147,H,3444,34,DVB-S,QPSK -83=4151,H,2500,34,DVB-S,QPSK -84=4160,H,5600,23,S2,8PSK -85=4170,H,6111,Auto,DVB-S,QPSK -86=4177,V,30000,56,S2,8PSK -87=4193,H,4444,34,S2,QPSK -88=10976,H,22000,34,S2,8PSK -89=11006,H,23300,34,S2,8PSK -90=11024,V,23300,34,S2,8PSK -91=11036,H,23300,34,S2,8PSK -92=11054,V,23300,34,S2,8PSK -93=11066,H,23300,34,S2,8PSK -94=11096,H,23300,34,S2,8PSK -95=11126,H,23300,34,S2,8PSK -96=11156,H,23300,34,S2,8PSK -97=11186,H,23300,34,S2,8PSK -98=11921,V,39200,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3070.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3070.ini deleted file mode 100644 index 16baee6ce0..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3070.ini +++ /dev/null @@ -1,24 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3070 -2=Intelsat 23 (53.0W) - -[DVB] -0=15 -1=3715,V,2500,34,S2,QPSK -2=3720,V,3906,12,DVB-S,QPSK -3=3820,V,3255,Auto,DVB-S,QPSK -4=3882,V,18808,34,DVB-S,QPSK -5=3932,V,4340,Auto,DVB-S,QPSK -6=3998,H,4445,12,DVB-S,QPSK -7=4004,H,4445,12,DVB-S,QPSK -8=4009,H,2963,34,DVB-S,QPSK -9=4012,H,2963,34,DVB-S,QPSK -10=4016,H,2963,34,DVB-S,QPSK -11=4028,H,2963,34,DVB-S,QPSK -12=4119,V,6666,34,DVB-S,QPSK -13=4135,H,4300,78,DVB-S,QPSK -14=11911,V,2821,34,DVB-S,QPSK -15=12138,H,3111,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3100.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3100.ini deleted file mode 100644 index 2155127dc4..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3100.ini +++ /dev/null @@ -1,43 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3100 -2=Intelsat 1R (50.0W) - -[DVB] -0=34 -1=3743,V,7200,Auto,S2,QPSK -2=3760,V,2410,Auto,DVB-S,QPSK -3=3765,V,2410,12,DVB-S,QPSK -4=3778,V,5184,Auto,DVB-S,QPSK -5=3784,V,2240,Auto,DVB-S,QPSK -6=3792,V,2222,Auto,DVB-S,QPSK -7=4094,H,2963,34,DVB-S,QPSK -8=4098,H,2963,34,DVB-S,QPSK -9=4102,H,2963,34,DVB-S,QPSK -10=4106,H,2963,34,DVB-S,QPSK -11=4111,H,2963,34,DVB-S,QPSK -12=4125,V,10713,34,DVB-S,QPSK -13=4135,V,3382,34,DVB-S,QPSK -14=4141,V,5384,35,DVB-S,QPSK -15=4149,V,6153,Auto,DVB-S,QPSK -16=4182,V,7600,12,S2,8PSK -17=11050,V,27902,34,S2,QPSK -18=11090,V,27902,34,S2,QPSK -19=11130,V,27902,34,S2,QPSK -20=11170,V,27902,34,S2,QPSK -21=11455,V,4440,Auto,DVB-S,QPSK -22=11464,V,3320,Auto,DVB-S,QPSK -23=11469,V,3320,Auto,DVB-S,QPSK -24=11473,V,3320,Auto,DVB-S,QPSK -25=11478,V,3320,Auto,DVB-S,QPSK -26=11483,V,3320,Auto,DVB-S,QPSK -27=11787,H,3330,Auto,DVB-S,QPSK -28=11789,V,10000,Auto,DVB-S,QPSK -29=11797,H,6500,Auto,DVB-S,QPSK -30=11804,H,6500,Auto,DVB-S,QPSK -31=11804,V,4440,Auto,DVB-S,QPSK -32=11813,H,6500,Auto,DVB-S,QPSK -33=11816,V,2960,Auto,DVB-S,QPSK -34=11825,H,4500,Auto,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3125.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3125.ini deleted file mode 100644 index 07c07c7ff9..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3125.ini +++ /dev/null @@ -1,17 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3125 -2=NSS 806 (47.5W) - -[DVB] -0=8 -1=3725,H,30000,34,S2,8PSK -2=3803,V,28000,34,S2,8PSK -3=4002,V,7200,34,S2,QPSK -4=4015,H,30000,23,S2,8PSK -5=4055,V,30000,56,S2,8PSK -6=4135,V,28000,34,S2,8PSK -7=4163,V,9247,56,S2,QPSK -8=4178,H,30000,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3150.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3150.ini deleted file mode 100644 index e322e36f86..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3150.ini +++ /dev/null @@ -1,33 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3150 -2=Intelsat 14 (45.0W) - -[DVB] -0=24 -1=3759,V,4412,34,DVB-S,QPSK -2=3766,V,3255,34,DVB-S,QPSK -3=3769,V,2400,34,DVB-S,QPSK -4=3777,V,2400,56,DVB-S,QPSK -5=3780,V,2941,34,DVB-S,QPSK -6=3789,V,1667,Auto,S2,QPSK -7=3844,V,2222,Auto,DVB-S,QPSK -8=3853,V,11029,78,DVB-S,QPSK -9=3866,V,10073,78,DVB-S,QPSK -10=3913,H,2482,23,S2,QPSK -11=3968,V,3600,Auto,DVB-S,QPSK -12=3986,V,4411,56,DVB-S,QPSK -13=4072,V,2068,56,DVB-S,QPSK -14=4110,H,4444,34,DVB-S,QPSK -15=4165,V,4412,56,DVB-S,QPSK -16=4171,V,3309,34,DVB-S,QPSK -17=4176,V,3888,Auto,DVB-S,QPSK -18=4186,H,4960,35,S2,QPSK -19=4192,H,2075,34,DVB-S,QPSK -20=4192,V,1600,35,S2,8PSK -21=11600,V,1000,34,DVB-S,QPSK -22=11608,H,1852,56,DVB-S,QPSK -23=11638,H,5632,34,DVB-S,QPSK -24=11647,H,6620,23,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3169.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3169.ini deleted file mode 100644 index 8ed74f2ef9..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3169.ini +++ /dev/null @@ -1,76 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3169 -2=Intelsat 11 (43.1W) - -[DVB] -0=67 -1=3717,H,22000,56,S2,8PSK -2=3718,V,21600,56,S2,8PSK -3=3736,H,29270,78,DVB-S,QPSK -4=3745,V,21610,34,S2,8PSK -5=3780,H,27690,78,DVB-S,QPSK -6=3783,V,30000,56,S2,8PSK -7=3808,V,15000,56,S2,8PSK -8=3808,H,14950,56,S2,8PSK -9=3825,H,7500,34,S2,QPSK -10=3828,V,3300,34,DVB-S,QPSK -11=3834,H,3200,35,S2,8PSK -12=3836,V,7780,23,S2,8PSK -13=3838,H,3600,34,DVB-S,QPSK -14=3844,H,3600,34,DVB-S,QPSK -15=3845,V,7700,34,S2,QPSK -16=3850,H,7500,23,S2,8PSK -17=3854,V,5945,34,DVB-S,QPSK -18=3864,V,7120,34,S2,8PSK -19=3868,H,13600,34,S2,8PSK -20=3871,V,2500,34,S2,8PSK -21=3874,V,2421,34,S2,8PSK -22=3875,H,3750,35,S2,8PSK -23=3877,V,1546,23,DVB-S,QPSK -24=3888,H,7200,34,S2,8PSK -25=3895,V,17405,34,DVB-S,QPSK -26=3927,V,30000,56,DVB-S,QPSK -27=3928,H,14060,34,S2,8PSK -28=3945,H,6250,34,S2,8PSK -29=3963,V,13400,56,DVB-S,QPSK -30=3966,H,21090,34,DVB-S,QPSK -31=3975,V,3590,56,S2,8PSK -32=3984,V,9760,34,DVB-S,QPSK -33=3992,V,7320,23,DVB-S,QPSK -34=3994,H,21090,34,DVB-S,QPSK -35=4012,V,6650,Auto,DVB-S,QPSK -36=4026,V,16900,78,DVB-S,QPSK -37=4040,H,30800,78,DVB-S,QPSK -38=4048,V,20832,34,S2,8PSK -39=4074,V,2500,56,S2,8PSK -40=4079,V,4400,34,DVB-S,QPSK -41=4113,H,19510,Auto,DVB-S,QPSK -42=4115,V,19580,34,S2,8PSK -43=4135,V,2222,34,DVB-S,QPSK -44=4140,H,9600,34,S2,8PSK -45=4149,V,20083,23,S2,8PSK -46=4150,H,7500,23,S2,8PSK -47=4168,H,4800,Auto,S2,8PSK -48=4185,H,7120,34,S2,8PSK -49=4193,H,6620,34,S2,QPSK -50=10722,V,30000,34,DVB-S,QPSK -51=10722,H,30000,34,DVB-S,QPSK -52=10802,V,30000,34,DVB-S,QPSK -53=10802,H,28000,Auto,DVB-S,QPSK -54=10882,V,30000,34,DVB-S,QPSK -55=10882,H,30000,34,DVB-S,QPSK -56=10970,V,28000,Auto,DVB-S,QPSK -57=10970,H,29000,34,DVB-S,QPSK -58=11050,V,29000,Auto,DVB-S,QPSK -59=11050,H,29000,Auto,DVB-S,QPSK -60=11130,V,29000,34,DVB-S,QPSK -61=11130,H,28000,Auto,DVB-S,QPSK -62=11222,V,30000,23,S2,8PSK -63=11222,H,30000,23,S2,8PSK -64=11302,V,30000,23,S2,8PSK -65=11302,H,30000,23,S2,8PSK -66=11382,V,30000,34,DVB-S,QPSK -67=11382,H,30000,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3195.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3195.ini deleted file mode 100644 index b331b7d64b..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3195.ini +++ /dev/null @@ -1,151 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3195 -2=SES 6 (40.5W) - -[DVB] -0=142 -1=3626,H,2800,34,S2,8PSK -2=3628,V,2170,34,DVB-S,QPSK -3=3630,H,2222,34,DVB-S,QPSK -4=3633,H,1480,56,S2,8PSK -5=3634,V,2712,34,DVB-S,QPSK -6=3637,H,1855,34,DVB-S,QPSK -7=3641,V,2666,34,DVB-S,QPSK -8=3641,H,2788,Auto,S2,8PSK -9=3644,H,2532,34,DVB-S,QPSK -10=3646,V,6666,34,DVB-S,QPSK -11=3648,H,2068,23,S2,8PSK -12=3652,H,4000,56,DVB-S,QPSK -13=3658,H,1666,56,S2,8PSK -14=3658,V,4800,89,S2,QPSK -15=3666,V,2222,56,DVB-S,QPSK -16=3668,H,2170,34,DVB-S,QPSK -17=3673,V,4700,56,S2,8PSK -18=3673,H,4350,34,DVB-S,QPSK -19=3677,H,2000,23,S2,8PSK -20=3682,H,3333,34,DVB-S,QPSK -21=3684,V,3750,34,S2,8PSK -22=3688,V,3650,34,DVB-S,QPSK -23=3691,H,2740,23,DVB-S,QPSK -24=3694,V,5180,34,DVB-S,QPSK -25=3695,H,2963,34,DVB-S,QPSK -26=3699,V,2200,34,DVB-S,QPSK -27=3710,H,7400,78,DVB-S,QPSK -28=3725,H,10000,56,S2,8PSK -29=3732,V,8156,56,DVB-S,QPSK -30=3735,H,7400,78,DVB-S,QPSK -31=3758,H,18500,78,DVB-S,QPSK -32=3763,V,30000,56,S2,8PSK -33=3803,V,26860,78,DVB-S,QPSK -34=3803,H,27500,78,DVB-S,QPSK -35=3830,V,6142,78,DVB-S,QPSK -36=3835,V,2082,34,S2,8PSK -37=3843,H,30000,89,S2,8PSK -38=3848,V,2800,34,DVB-S,QPSK -39=3856,V,8370,34,S2,8PSK -40=3866,H,2222,78,DVB-S,QPSK -41=3870,H,3750,56,S2,8PSK -42=3875,H,3867,34,S2,QPSK -43=3883,V,26660,56,DVB-S,QPSK -44=3883,H,1837,34,S2,8PSK -45=3886,H,2617,34,S2,8PSK -46=3888,H,1050,56,S2,8PSK -47=3893,H,2217,78,DVB-S,QPSK -48=3897,H,2000,34,S2,8PSK -49=3899,H,1900,34,DVB-S,QPSK -50=3907,H,2548,34,S2,8PSK -51=3909,H,2455,34,S2,8PSK -52=3915,H,5830,23,S2,8PSK -53=3920,V,20000,35,S2,QPSK -54=3935,H,8880,34,DVB-S,QPSK -55=3937,V,2170,34,DVB-S,QPSK -56=3960,V,1259,78,DVB-S,QPSK -57=3964,V,2000,56,S2,8PSK -58=3966,V,1920,23,S2,8PSK -59=3980,V,17800,34,DVB-S,QPSK -60=3980,H,21600,34,S2,8PSK -61=3990,V,4195,34,DVB-S,QPSK -62=3998,H,1630,34,S2,8PSK -63=4000,H,1600,34,S2,8PSK -64=4002,H,1570,34,S2,8PSK -65=4004,H,1530,34,S2,8PSK -66=4006,H,1500,34,S2,8PSK -67=4008,H,1470,34,S2,8PSK -68=4013,H,6600,34,S2,8PSK -69=4021,V,3200,34,S2,8PSK -70=4025,H,12832,34,S2,8PSK -71=4028,V,8000,34,S2,8PSK -72=4047,H,3330,78,DVB-S,QPSK -73=4054,H,6666,34,DVB-S,QPSK -74=4056,V,3000,23,DVB-S,QPSK -75=4063,H,7000,56,S2,8PSK -76=4065,V,12500,34,DVB-S,QPSK -77=4070,H,4440,78,DVB-S,QPSK -78=4080,H,4937,Auto,DVB-S,QPSK -79=4081,V,6511,56,DVB-S,QPSK -80=4086,V,1476,78,DVB-S,QPSK -81=4092,H,1600,56,S2,QPSK -82=4092,V,1150,34,DVB-S,QPSK -83=4100,V,6111,34,DVB-S,QPSK -84=4111,V,2000,56,DVB-S,QPSK -85=4119,V,2960,34,DVB-S,QPSK -86=4121,H,2400,34,S2,8PSK -87=4124,V,4196,34,DVB-S,QPSK -88=4125,H,3625,56,S2,8PSK -89=4130,V,3844,78,DVB-S,QPSK -90=4132,H,2480,34,DVB-S,QPSK -91=4136,V,3000,56,S2,8PSK -92=4137,H,4400,34,DVB-S,QPSK -93=4140,V,2220,78,DVB-S,QPSK -94=4142,V,1030,78,DVB-S,QPSK -95=4142,H,2222,78,DVB-S,QPSK -96=4144,V,2800,34,S2,8PSK -97=4146,H,2571,78,DVB-S,QPSK -98=4151,V,3280,56,DVB-S,QPSK -99=4161,H,6510,34,DVB-S,QPSK -100=4168,H,2400,23,DVB-S,QPSK -101=4168,V,18392,23,S2,8PSK -102=4170,H,2222,34,DVB-S,QPSK -103=4175,H,3350,23,S2,8PSK -104=4179,H,3332,23,S2,8PSK -105=4187,V,11500,34,DVB-S,QPSK -106=4196,V,2960,56,DVB-S,QPSK -107=11480,V,30000,12,S2,8PSK -108=11480,H,30000,34,S2,8PSK -109=11520,V,30000,34,S2,8PSK -110=11520,H,30000,34,S2,8PSK -111=11560,V,30000,23,S2,8PSK -112=11560,H,30000,34,S2,8PSK -113=11600,H,30000,34,S2,8PSK -114=11600,V,30000,34,S2,8PSK -115=11640,H,30000,34,S2,8PSK -116=11640,V,30000,34,S2,8PSK -117=11680,H,30000,34,S2,8PSK -118=11680,V,30000,34,S2,8PSK -119=11736,V,22500,34,S2,8PSK -120=11764,V,22500,34,S2,8PSK -121=11796,V,22500,34,S2,8PSK -122=11824,V,22500,34,S2,8PSK -123=11856,V,22500,34,S2,8PSK -124=11884,V,22500,34,S2,8PSK -125=11916,V,22500,34,S2,8PSK -126=11944,V,22500,34,S2,8PSK -127=11976,V,22500,34,S2,8PSK -128=11976,H,22500,34,S2,8PSK -129=12004,V,22500,34,S2,8PSK -130=12004,H,22500,34,S2,8PSK -131=12036,H,22500,34,S2,8PSK -132=12036,V,22500,34,S2,8PSK -133=12064,H,22500,34,S2,8PSK -134=12064,V,22500,34,S2,8PSK -135=12096,H,22500,34,S2,8PSK -136=12096,V,22500,34,S2,8PSK -137=12124,H,22500,34,S2,8PSK -138=12124,V,22500,34,S2,8PSK -139=12156,H,22500,34,S2,8PSK -140=12156,V,22500,34,S2,8PSK -141=12184,H,22500,34,S2,8PSK -142=12184,V,22500,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3225.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3225.ini deleted file mode 100644 index 800e74334f..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3225.ini +++ /dev/null @@ -1,62 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3225 -2=NSS 10/Telstar 11N (37.5W) - -[DVB] -0=53 -1=3746,V,1229,56,S2,QPSK -2=3746,H,1229,56,S2,QPSK -3=3749,V,1674,78,DVB-S,QPSK -4=3749,H,1674,78,DVB-S,QPSK -5=3756,V,1777,34,S2,8PSK -6=3756,H,1777,34,S2,8PSK -7=3833,H,2893,34,DVB-S,QPSK -8=3868,V,6666,34,DVB-S,QPSK -9=3888,H,3250,34,DVB-S,QPSK -10=3929,H,8882,34,DVB-S,QPSK -11=4044,V,3250,34,DVB-S,QPSK -12=4055,V,2700,56,DVB-S,QPSK -13=4059,V,3214,56,DVB-S,QPSK -14=4066,V,2893,34,DVB-S,QPSK -15=4068,V,2540,78,DVB-S,QPSK -16=4072,V,3150,34,DVB-S,QPSK -17=4083,H,10000,23,S2,8PSK -18=4172,H,8888,Auto,DVB-S,QPSK -19=4177,V,23500,12,S2,QPSK -20=10965,V,3300,56,DVB-S,QPSK -21=10970,V,1847,56,S2,QPSK -22=10975,H,3250,Auto,S2,QPSK -23=10975,V,2894,34,S2,8PSK -24=10978,H,3124,34,DVB-S,QPSK -25=10979,V,2894,34,S2,8PSK -26=10982,V,1000,Auto,S2,QPSK -27=10989,V,5632,34,DVB-S,QPSK -28=10991,H,6111,34,DVB-S,QPSK -29=10994,V,4800,34,S2,8PSK -30=11001,V,4280,34,DVB-S,QPSK -31=11032,V,6111,34,DVB-S,QPSK -32=11043,V,6666,78,DVB-S,QPSK -33=11482,H,11970,56,DVB-S,QPSK -34=11637,V,3885,34,S2,8PSK -35=11679,V,4090,34,S2,8PSK -36=11839,V,3125,Auto,DVB-S,QPSK -37=11875,V,5632,Auto,DVB-S,QPSK -38=12504,V,3400,78,DVB-S,QPSK -39=12515,H,3460,78,DVB-S,QPSK -40=12517,V,10800,Auto,S2,QPSK -41=12524,V,3600,Auto,DVB-S,QPSK -42=12533,V,6111,34,DVB-S,QPSK -43=12542,V,6111,34,DVB-S,QPSK -44=12543,V,3500,34,DVB-S,QPSK -45=12551,V,6111,34,DVB-S,QPSK -46=12584,V,6111,34,DVB-S,QPSK -47=12595,V,6650,34,DVB-S,QPSK -48=12606,V,9600,34,S2,8PSK -49=12615,V,3124,34,DVB-S,QPSK -50=12674,V,7500,56,S2,8PSK -51=12690,V,7500,56,S2,8PSK -52=12708,V,7200,23,S2,8PSK -53=12717,V,6620,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3255.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3255.ini deleted file mode 100644 index eb56de14b9..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3255.ini +++ /dev/null @@ -1,42 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3255 -2=Intelsat 903 (34.5W) - -[DVB] -0=33 -1=3658,V,3300,34,DVB-S,QPSK -2=3676,V,3220,34,DVB-S,QPSK -3=4045,H,13500,23,S2,QPSK -4=4095,V,30000,34,S2,QPSK -5=4126,H,3680,23,DVB-S,QPSK -6=10960,V,5632,34,DVB-S,QPSK -7=10968,V,5632,34,DVB-S,QPSK -8=10977,V,5632,34,DVB-S,QPSK -9=10986,V,5632,34,DVB-S,QPSK -10=10993,V,7200,34,S2,QPSK -11=10995,H,44950,56,S2,QPSK -12=11028,V,5000,23,S2,8PSK -13=11049,V,13333,78,DVB-S,QPSK -14=11075,H,45000,34,S2,QPSK -15=11088,V,20640,56,S2,8PSK -16=11106,V,7750,23,S2,8PSK -17=11190,H,3333,Auto,DVB-S,QPSK -18=11495,H,45000,34,S2,QPSK -19=11555,H,30000,89,S2,QPSK -20=11568,V,6111,34,DVB-S,QPSK -21=11580,V,6220,56,DVB-S,QPSK -22=11589,V,6220,56,DVB-S,QPSK -23=11596,H,30000,89,S2,QPSK -24=11598,V,6220,56,DVB-S,QPSK -25=11604,V,4280,34,DVB-S,QPSK -26=11610,V,6111,34,DVB-S,QPSK -27=11620,V,4224,78,DVB-S,QPSK -28=11625,V,4224,78,DVB-S,QPSK -29=11631,V,4224,78,DVB-S,QPSK -30=11635,H,30000,89,S2,QPSK -31=11644,V,12000,34,DVB-S,QPSK -32=11675,V,26040,56,DVB-S,QPSK -33=11675,H,30000,89,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3285.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3285.ini deleted file mode 100644 index c5632384c1..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3285.ini +++ /dev/null @@ -1,13 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3285 -2=Intelsat 25 (31.5W) - -[DVB] -0=4 -1=4114,V,5300,Auto,DVB-S,QPSK -2=12284,V,2200,23,S2,QPSK -3=12341,V,2120,78,DVB-S,QPSK -4=12344,V,2120,78,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3300.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3300.ini deleted file mode 100644 index 7b1595a531..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3300.ini +++ /dev/null @@ -1,117 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3300 -2=Hispasat 1D/1E (30.0W) - -[DVB] -0=108 -1=10730,H,27500,34,S2,8PSK -2=10730,V,30000,34,S2,8PSK -3=10890,V,27500,34,DVB-S,QPSK -4=10946,H,4000,910,S2,QPSK -5=11472,H,5632,34,DVB-S,QPSK -6=11495,H,6900,34,S2,8PSK -7=11503,H,4444,34,DVB-S,QPSK -8=11510,V,10000,34,DVB-S,QPSK -9=11510,H,4444,34,DVB-S,QPSK -10=11519,V,2222,56,DVB-S,QPSK -11=11522,V,2400,34,DVB-S,QPSK -12=11522,H,4400,34,S2,8PSK -13=11528,H,4400,34,S2,8PSK -14=11529,V,10000,910,S2,QPSK -15=11537,H,4500,34,DVB-S,QPSK -16=11538,V,4800,34,S2,8PSK -17=11544,V,4444,34,DVB-S,QPSK -18=11546,H,4444,34,DVB-S,QPSK -19=11550,V,5000,34,S2,8PSK -20=11551,H,5632,34,DVB-S,QPSK -21=11562,V,5000,34,S2,8PSK -22=11564,H,4444,34,DVB-S,QPSK -23=11568,V,5000,34,S2,8PSK -24=11570,H,4875,34,S2,8PSK -25=11573,V,7200,34,S2,8PSK -26=11579,V,2300,34,S2,8PSK -27=11581,H,3400,23,S2,8PSK -28=11586,H,3400,23,DVB-S,QPSK -29=11588,V,3400,23,S2,8PSK -30=11590,H,3400,23,S2,8PSK -31=11593,V,3400,23,S2,8PSK -32=11594,H,3400,23,S2,8PSK -33=11602,H,6650,34,DVB-S,QPSK -34=11603,V,6111,34,DVB-S,QPSK -35=11612,H,4500,34,DVB-S,QPSK -36=11613,V,4800,34,S2,8PSK -37=11619,V,4800,34,S2,8PSK -38=11626,V,4444,34,DVB-S,QPSK -39=11632,V,4800,34,S2,8PSK -40=11654,V,5632,34,DVB-S,QPSK -41=11661,V,4500,34,DVB-S,QPSK -42=11667,V,4500,34,DVB-S,QPSK -43=11672,V,2300,56,DVB-S,QPSK -44=11678,V,2000,56,DVB-S,QPSK -45=11683,V,3400,34,DVB-S,QPSK -46=11731,V,27500,34,DVB-S,QPSK -47=11771,V,27500,34,DVB-S,QPSK -48=11811,V,27500,34,DVB-S,QPSK -49=11851,V,27500,34,DVB-S,QPSK -50=11884,V,27500,23,DVB-S,QPSK -51=11891,V,30000,56,DVB-S,QPSK -52=11911,V,12000,34,S2,8PSK -53=11931,V,27500,34,DVB-S,QPSK -54=11958,V,2500,78,DVB-S,QPSK -55=11960,H,6666,34,S2,8PSK -56=11960,V,1110,Auto,DVB-S,QPSK -57=11969,H,7200,34,S2,8PSK -58=11977,V,3255,Auto,DVB-S,QPSK -59=11983,H,13333,34,DVB-S,QPSK -60=11987,V,3702,34,DVB-S,QPSK -61=12052,V,27500,34,DVB-S,QPSK -62=12052,H,27500,34,DVB-S,QPSK -63=12076,V,4000,89,S2,QPSK -64=12092,V,27500,34,DVB-S,QPSK -65=12092,H,27500,34,DVB-S,QPSK -66=12108,V,4190,23,DVB-S,QPSK -67=12130,H,27500,34,S2,8PSK -68=12132,H,27500,34,DVB-S,QPSK -69=12169,H,27500,34,S2,8PSK -70=12207,H,27500,34,S2,8PSK -71=12226,V,27500,34,DVB-S,QPSK -72=12246,H,27500,34,S2,8PSK -73=12303,V,27500,34,DVB-S,QPSK -74=12322,H,27500,34,DVB-S,QPSK -75=12360,H,27500,56,DVB-S,QPSK -76=12380,V,27500,34,DVB-S,QPSK -77=12399,H,27500,34,S2,8PSK -78=12425,V,4440,Auto,DVB-S,QPSK -79=12437,H,27500,34,S2,8PSK -80=12456,V,30000,56,DVB-S,QPSK -81=12476,H,27500,34,S2,8PSK -82=12528,H,4444,34,DVB-S,QPSK -83=12550,H,3400,34,DVB-S,QPSK -84=12564,V,4500,34,DVB-S,QPSK -85=12580,H,9600,34,S2,8PSK -86=12588,H,4444,34,DVB-S,QPSK -87=12593,H,3600,34,S2,8PSK -88=12600,H,3200,34,S2,8PSK -89=12604,H,3200,34,S2,8PSK -90=12608,H,3200,34,S2,8PSK -91=12618,H,6120,34,DVB-S,QPSK -92=12629,H,4444,34,DVB-S,QPSK -93=12634,H,4500,34,DVB-S,QPSK -94=12640,H,4500,34,DVB-S,QPSK -95=12645,H,4500,34,DVB-S,QPSK -96=12657,H,7200,34,S2,QPSK -97=12663,H,5000,34,S2,8PSK -98=12669,H,3600,34,S2,8PSK -99=12673,H,3400,34,DVB-S,QPSK -100=12678,H,3400,23,DVB-S,QPSK -101=12682,H,3600,34,S2,8PSK -102=12687,H,4444,34,DVB-S,8PSK -103=12700,V,1483,34,DVB-S,QPSK -104=12706,V,4444,34,DVB-S,QPSK -105=12706,H,20000,12,S2,QPSK -106=12712,V,7200,34,S2,8PSK -107=12724,V,4444,34,DVB-S,QPSK -108=12732,V,4500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3325.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3325.ini deleted file mode 100644 index 380ed40725..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3325.ini +++ /dev/null @@ -1,34 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3325 -2=Intelsat 907 (27.5W) - -[DVB] -0=25 -1=3648,V,30000,Auto,S2,QPSK -2=3718,V,12000,12,DVB-S,QPSK -3=3723,V,21092,Auto,S2,QPSK -4=3759,V,26665,Auto,S2,QPSK -5=3764,V,24450,34,DVB-S,QPSK -6=3784,H,6510,23,DVB-S,QPSK -7=3791,H,6510,23,DVB-S,QPSK -8=3795,V,7000,23,S2,8PSK -9=3800,V,2400,Auto,DVB-S,QPSK -10=3802,V,2000,23,DVB-S,QPSK -11=3831,V,5787,34,DVB-S,QPSK -12=3838,V,7235,34,DVB-S,QPSK -13=3855,H,4134,34,S2,8PSK -14=3859,H,5250,23,S2,8PSK -15=3873,H,3200,Auto,DVB-S,QPSK -16=3902,V,1807,34,DVB-S,QPSK -17=3936,V,4550,12,DVB-S,QPSK -18=3940,H,2400,Auto,S2,QPSK -19=4003,H,5632,34,DVB-S,QPSK -20=4054,V,4000,Auto,S2,QPSK -21=4110,H,1384,34,DVB-S,QPSK -22=4119,H,2893,34,DVB-S,QPSK -23=4151,H,1517,34,DVB-S,QPSK -24=11050,H,17100,78,DVB-S,QPSK -25=11495,V,44100,910,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3355.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3355.ini deleted file mode 100644 index 542d9bd46b..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3355.ini +++ /dev/null @@ -1,106 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3355 -2=Intelsat 905 (24.5W) - -[DVB] -0=97 -1=3653,V,3906,34,DVB-S,QPSK -2=3688,V,21050,34,DVB-S,QPSK -3=3829,V,6110,Auto,DVB-S,QPSK -4=4061,V,2848,23,DVB-S,QPSK -5=4068,H,2915,78,DVB-S,QPSK -6=4069,V,3800,12,DVB-S,QPSK -7=4122,V,5303,12,DVB-S,QPSK -8=4162,V,6111,34,DVB-S,QPSK -9=4168,V,3100,23,DVB-S,QPSK -10=4181,V,6111,34,DVB-S,QPSK -11=4192,H,2100,23,DVB-S,QPSK -12=10957,V,6660,34,S2,8PSK -13=10963,V,4800,34,S2,8PSK -14=10976,V,7200,34,S2,8PSK -15=10987,V,5000,35,S2,QPSK -16=10992,V,4800,34,S2,8PSK -17=10997,H,6666,56,DVB-S,QPSK -18=10998,V,4800,34,S2,8PSK -19=11004,H,3300,78,DVB-S,QPSK -20=11004,V,4800,34,S2,8PSK -21=11007,H,1600,56,S2,8PSK -22=11010,V,4800,34,S2,8PSK -23=11011,H,3100,78,DVB-S,QPSK -24=11015,H,1600,56,S2,8PSK -25=11017,H,1600,56,S2,8PSK -26=11020,V,3550,34,S2,8PSK -27=11022,H,4280,34,DVB-S,QPSK -28=11028,H,4280,34,DVB-S,QPSK -29=11041,V,3750,34,S2,8PSK -30=11042,H,1600,56,S2,8PSK -31=11045,V,3750,34,S2,8PSK -32=11046,H,3400,23,S2,8PSK -33=11049,V,6620,34,DVB-S,QPSK -34=11050,H,3200,56,S2,8PSK -35=11054,H,3700,34,S2,8PSK -36=11060,H,3400,23,S2,8PSK -37=11060,V,7200,34,S2,8PSK -38=11068,H,3111,34,DVB-S,QPSK -39=11072,V,4444,34,DVB-S,QPSK -40=11078,H,3400,23,S2,8PSK -41=11079,V,6111,34,DVB-S,QPSK -42=11082,H,3400,23,S2,8PSK -43=11084,V,4444,34,DVB-S,QPSK -44=11086,H,1600,56,S2,8PSK -45=11090,V,4444,34,DVB-S,QPSK -46=11090,H,4444,34,DVB-S,QPSK -47=11095,H,4800,34,S2,8PSK -48=11096,V,4444,34,DVB-S,QPSK -49=11103,V,3400,34,S2,8PSK -50=11108,V,3400,23,S2,8PSK -51=11108,H,4445,34,DVB-S,QPSK -52=11121,H,3400,23,S2,8PSK -53=11122,V,7200,34,S2,8PSK -54=11126,H,3400,23,S2,8PSK -55=11130,H,3400,23,S2,8PSK -56=11132,V,14115,12,DVB-S,QPSK -57=11134,H,3400,23,S2,8PSK -58=11139,H,3400,23,S2,8PSK -59=11144,H,3400,23,S2,8PSK -60=11148,H,3400,23,S2,8PSK -61=11148,V,3200,34,DVB-S,QPSK -62=11152,H,3400,23,S2,8PSK -63=11157,V,3400,23,S2,8PSK -64=11157,H,3400,23,S2,8PSK -65=11161,V,3400,23,S2,8PSK -66=11162,H,3400,23,S2,8PSK -67=11165,V,4834,56,S2,QPSK -68=11166,H,3400,23,S2,8PSK -69=11171,H,3516,34,S2,8PSK -70=11177,V,6666,78,DVB-S,QPSK -71=11177,H,7200,34,S2,8PSK -72=11182,H,3400,23,S2,8PSK -73=11187,H,1600,56,S2,8PSK -74=11188,V,3400,23,S2,8PSK -75=11193,V,4666,34,S2,QPSK -76=11455,V,3450,34,DVB-S,QPSK -77=11463,V,3583,89,S2,QPSK -78=11471,V,3400,23,S2,8PSK -79=11476,V,3400,23,S2,8PSK -80=11477,H,27500,34,DVB-S,QPSK -81=11488,V,11640,56,S2,8PSK -82=11509,V,3750,34,DVB-S,QPSK -83=11513,H,27500,34,DVB-S,QPSK -84=11518,V,7100,12,S2,8PSK -85=11527,V,2600,45,S2,QPSK -86=11530,V,2000,34,DVB-S,QPSK -87=11580,H,7120,34,S2,8PSK -88=11589,H,7120,34,S2,8PSK -89=11598,H,7120,34,S2,8PSK -90=11608,H,7120,34,S2,8PSK -91=11620,V,3600,34,S2,8PSK -92=11626,H,13500,78,DVB-S,QPSK -93=11636,H,3500,23,S2,8PSK -94=11638,V,21000,56,S2,8PSK -95=11642,H,3400,23,S2,8PSK -96=11646,H,1600,56,S2,8PSK -97=11650,H,3200,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3380.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3380.ini deleted file mode 100644 index 39d26fdbb6..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3380.ini +++ /dev/null @@ -1,64 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3380 -2=SES 4 (22.0W) - -[DVB] -0=55 -1=3631,V,7200,34,S2,8PSK -2=3631,H,7200,Auto,S2,QPSK -3=3713,V,3254,23,DVB-S,QPSK -4=3724,H,30000,23,S2,8PSK -5=3726,H,1000,34,S2,8PSK -6=3761,V,22650,23,DVB-S,QPSK -7=3825,H,8950,56,DVB-S,QPSK -8=3966,H,2221,23,DVB-S,QPSK -9=3970,H,3332,34,DVB-S,QPSK -10=3976,H,1844,34,DVB-S,QPSK -11=4016,H,3662,23,DVB-S,QPSK -12=4033,V,3689,34,DVB-S,QPSK -13=4039,V,3906,34,DVB-S,QPSK -14=4043,V,3560,23,S2,8PSK -15=4048,V,3333,23,DVB-S,QPSK -16=4053,V,3333,23,DVB-S,QPSK -17=4056,V,2441,23,DVB-S,QPSK -18=4061,V,3333,Auto,S2,8PSK -19=4065,H,3590,34,S2,QPSK -20=4071,V,3502,34,DVB-S,QPSK -21=4097,V,23500,34,S2,QPSK -22=4115,H,3680,23,DVB-S,QPSK -23=4141,H,1925,45,S2,QPSK -24=10986,V,30000,34,DVB-S,QPSK -25=11108,H,15000,56,S2,8PSK -26=11128,H,14300,35,S2,8PSK -27=11540,H,12238,45,S2,QPSK -28=11551,V,40000,Auto,S2,8PSK -29=11552,H,3255,12,DVB-S,QPSK -30=11563,H,6111,34,DVB-S,QPSK -31=11574,H,7500,56,S2,8PSK -32=11667,H,7500,910,S2,8PSK -33=11671,V,30000,34,DVB-S,QPSK -34=11674,H,3500,34,DVB-S,QPSK -35=11684,H,8570,910,S2,8PSK -36=11693,H,7500,910,S2,8PSK -37=11777,H,4000,34,DVB-S,QPSK -38=11861,H,35000,34,DVB-S,QPSK -39=11921,H,35000,34,DVB-S,QPSK -40=12037,H,4610,34,S2,8PSK -41=12076,H,4610,34,S2,8PSK -42=12082,H,4610,34,S2,8PSK -43=12089,H,4610,34,S2,8PSK -44=12530,V,30000,34,DVB-S,QPSK -45=12570,V,30000,34,DVB-S,QPSK -46=12610,V,30000,34,DVB-S,QPSK -47=12635,H,4610,34,S2,8PSK -48=12644,H,5136,34,DVB-S,QPSK -49=12650,V,30000,34,DVB-S,QPSK -50=12653,H,3055,34,DVB-S,QPSK -51=12658,H,3055,34,DVB-S,QPSK -52=12673,H,20250,34,DVB-S,QPSK -53=12690,V,30000,34,DVB-S,QPSK -54=12717,H,1500,34,S2,8PSK -55=12730,V,30000,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3400.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3400.ini deleted file mode 100644 index c23fe0b194..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3400.ini +++ /dev/null @@ -1,18 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3400 -2=NSS 7 (20.0W) - -[DVB] -0=9 -1=3969,V,3410,Auto,DVB-S,QPSK -2=3973,V,3410,Auto,DVB-S,QPSK -3=3977,V,3410,Auto,DVB-S,QPSK -4=4129,V,15405,12,S2,QPSK -5=11166,H,7500,34,S2,8PSK -6=11175,H,7500,34,S2,8PSK -7=11184,H,7500,34,S2,8PSK -8=11192,H,7500,34,S2,8PSK -9=11585,H,2200,12,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3420.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3420.ini deleted file mode 100644 index 2470d71f95..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3420.ini +++ /dev/null @@ -1,16 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3420 -2=Intelsat 901 (18.0W) - -[DVB] -0=7 -1=3631,V,1600,56,S2,8PSK -2=3887,H,26500,Auto,DVB-S,QPSK -3=3961,H,2960,78,DVB-S,QPSK -4=4010,V,6730,34,S2,QPSK -5=4018,V,4444,23,DVB-S,QPSK -6=4027,V,9037,56,S2,8PSK -7=11033,V,2530,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3450.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3450.ini deleted file mode 100644 index cae2fe8b9d..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3450.ini +++ /dev/null @@ -1,92 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3450 -2=Telstar 12 (15.0W) - -[DVB] -0=83 -1=10997,V,2894,34,DVB-S,QPSK -2=11005,H,8880,34,DVB-S,QPSK -3=11012,V,3400,34,DVB-S,QPSK -4=11016,V,3333,34,DVB-S,QPSK -5=11033,V,2130,34,DVB-S,QPSK -6=11063,V,7200,34,S2,8PSK -7=11079,H,4610,34,S2,8PSK -8=11088,H,7500,34,S2,8PSK -9=11123,H,21600,34,DVB-S,QPSK -10=11123,V,21540,34,S2,8PSK -11=11150,H,21600,34,DVB-S,QPSK -12=11150,V,19279,34,DVB-S,QPSK -13=11457,V,3255,34,DVB-S,QPSK -14=11472,H,3310,34,DVB-S,QPSK -15=11477,H,4500,34,DVB-S,QPSK -16=11487,H,7200,34,S2,QPSK -17=11497,H,7200,34,S2,8PSK -18=11498,V,6111,34,DVB-S,QPSK -19=11524,H,14400,34,S2,8PSK -20=11534,H,3200,78,DVB-S,QPSK -21=11539,H,4610,34,DVB-S,QPSK -22=11545,V,4088,34,DVB-S,QPSK -23=11546,H,4610,34,S2,8PSK -24=11564,H,7500,34,S2,8PSK -25=11591,V,2893,34,DVB-S,QPSK -26=11597,V,3200,78,DVB-S,QPSK -27=11604,V,1810,78,DVB-S,QPSK -28=11604,H,5886,23,DVB-S,QPSK -29=11611,H,4054,34,S2,8PSK -30=11618,H,7000,56,S2,8PSK -31=11625,V,3979,34,DVB-S,QPSK -32=11627,H,7000,34,S2,8PSK -33=11642,H,4610,34,S2,8PSK -34=11644,V,5632,34,DVB-S,QPSK -35=11651,V,5632,34,DVB-S,QPSK -36=11651,H,4610,34,S2,8PSK -37=11662,V,6111,78,DVB-S,QPSK -38=11667,H,3255,78,DVB-S,QPSK -39=11671,V,6666,78,DVB-S,QPSK -40=11690,V,2200,34,DVB-S,QPSK -41=11691,H,6111,34,DVB-S,QPSK -42=11709,V,3198,78,DVB-S,QPSK -43=11710,H,6750,Auto,DVB-S,QPSK -44=11720,H,6600,Auto,DVB-S,QPSK -45=11726,V,3200,Auto,DVB-S,QPSK -46=11737,H,6600,Auto,DVB-S,QPSK -47=11755,V,5500,Auto,DVB-S,QPSK -48=11771,V,4800,23,S2,8PSK -49=11860,H,45000,Auto,S2,8PSK -50=11920,H,45000,Auto,S2,8PSK -51=11964,H,14714,23,DVB-S,QPSK -52=11993,H,6666,78,DVB-S,QPSK -53=12004,H,6111,Auto,DVB-S,QPSK -54=12044,H,45000,Auto,S2,8PSK -55=12087,V,3200,34,DVB-S,QPSK -56=12094,V,2000,34,DVB-S,QPSK -57=12100,V,3200,78,DVB-S,QPSK -58=12107,V,3330,Auto,DVB-S,QPSK -59=12123,V,3480,78,DVB-S,QPSK -60=12126,V,2000,56,DVB-S,QPSK -61=12170,H,45000,56,S2,QPSK -62=12509,H,3198,78,DVB-S,QPSK -63=12511,V,7552,34,DVB-S,QPSK -64=12513,H,3400,34,S2,8PSK -65=12518,H,3198,78,DVB-S,QPSK -66=12521,H,3198,78,DVB-S,QPSK -67=12570,V,2900,34,S2,8PSK -68=12570,H,2900,34,S2,8PSK -69=12573,V,2900,34,S2,8PSK -70=12584,H,3976,34,DVB-S,QPSK -71=12589,H,1925,78,DVB-S,QPSK -72=12608,H,19279,23,DVB-S,QPSK -73=12620,V,3012,23,DVB-S,QPSK -74=12645,H,3255,34,DVB-S,QPSK -75=12658,H,3255,78,DVB-S,QPSK -76=12662,V,8000,34,DVB-S,QPSK -77=12666,H,3255,78,DVB-S,QPSK -78=12674,H,5632,34,DVB-S,QPSK -79=12676,V,14170,34,S2,8PSK -80=12696,H,5632,34,DVB-S,QPSK -81=12705,H,5632,34,DVB-S,QPSK -82=12710,V,6666,78,DVB-S,QPSK -83=12740,V,5632,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3460.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3460.ini deleted file mode 100644 index 46a7c1b624..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3460.ini +++ /dev/null @@ -1,11 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3460 -2=Express A4 (14.0W) - -[DVB] -0=2 -1=3975,V,30000,34,S2,QPSK -2=4025,V,30000,34,S2,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3475.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3475.ini deleted file mode 100644 index e7a7afc1d4..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3475.ini +++ /dev/null @@ -1,116 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3475 -2=Eutelsat 12 West A (12.5W) - -[DVB] -0=107 -1=10958,H,4940,34,S2,8PSK -2=10965,H,4444,78,DVB-S,QPSK -3=10971,H,4444,78,DVB-S,QPSK -4=10977,H,4444,78,DVB-S,QPSK -5=10983,H,4444,78,DVB-S,QPSK -6=10989,H,4444,78,DVB-S,QPSK -7=10995,H,4940,34,S2,8PSK -8=11001,H,4444,78,DVB-S,QPSK -9=11007,H,4444,78,DVB-S,QPSK -10=11013,H,4900,34,S2,8PSK -11=11019,H,4444,78,DVB-S,QPSK -12=11022,V,6666,78,DVB-S,QPSK -13=11025,H,4444,78,DVB-S,QPSK -14=11040,H,3270,56,DVB-S,QPSK -15=11044,H,3270,56,DVB-S,QPSK -16=11048,H,3270,56,DVB-S,8PSK -17=11052,H,3270,56,DVB-S,QPSK -18=11058,H,3270,56,DVB-S,QPSK -19=11062,H,3270,56,DVB-S,QPSK -20=11064,V,7500,910,S2,8PSK -21=11068,H,3333,34,DVB-S,QPSK -22=11070,V,3680,56,DVB-S,QPSK -23=11072,H,4500,34,DVB-S,QPSK -24=11075,V,3630,56,S2,8PSK -25=11079,V,3270,56,DVB-S,QPSK -26=11081,H,6511,34,DVB-S,QPSK -27=11083,V,3270,56,DVB-S,QPSK -28=11087,H,3400,34,S2,8PSK -29=11088,V,3400,56,DVB-S,QPSK -30=11091,H,3333,34,DVB-S,QPSK -31=11093,V,3270,56,DVB-S,QPSK -32=11097,V,3630,23,S2,8PSK -33=11103,V,3630,23,S2,8PSK -34=11108,V,3250,56,DVB-S,QPSK -35=11125,V,7100,34,DVB-S,QPSK -36=11126,H,4800,34,S2,8PSK -37=11135,V,7100,34,DVB-S,QPSK -38=11142,H,4208,56,S2,8PSK -39=11149,H,4208,56,S2,8PSK -40=11153,H,3204,34,DVB-S,QPSK -41=11160,H,3270,56,DVB-S,QPSK -42=11164,H,3270,56,DVB-S,QPSK -43=11171,H,7200,34,S2,8PSK -44=11181,H,7390,34,S2,8PSK -45=11188,H,3600,35,S2,8PSK -46=11192,H,3600,35,S2,8PSK -47=11329,H,3214,56,DVB-S,8PSK -48=11334,H,3214,56,DVB-S,QPSK -49=11340,H,2136,34,DVB-S,QPSK -50=11350,H,6700,34,S2,8PSK -51=11359,H,6700,34,S2,8PSK -52=11371,H,3400,34,DVB-S,QPSK -53=11375,H,3400,34,DVB-S,QPSK -54=11380,H,3215,34,DVB-S,QPSK -55=11393,H,12750,78,DVB-S,QPSK -56=11403,H,6111,34,DVB-S,QPSK -57=11408,V,27500,34,DVB-S,QPSK -58=11414,H,7120,34,S2,8PSK -59=11424,H,7120,34,S2,8PSK -60=11431,H,6700,34,S2,8PSK -61=11442,H,7120,34,S2,8PSK -62=11597,H,3884,Auto,DVB-S,QPSK -63=11622,H,3255,Auto,DVB-S,QPSK -64=11643,H,2398,Auto,DVB-S,QPSK -65=11645,V,4790,Auto,DVB-S,QPSK -66=11647,H,3992,Auto,DVB-S,QPSK -67=11651,V,3688,Auto,DVB-S,QPSK -68=11655,H,6666,56,DVB-S,QPSK -69=11664,H,6111,34,DVB-S,QPSK -70=11690,H,5700,34,DVB-S,QPSK -71=12507,V,3125,34,DVB-S,QPSK -72=12514,H,3600,34,S2,8PSK -73=12520,H,3400,34,DVB-S,QPSK -74=12521,V,2400,34,DVB-S,QPSK -75=12532,V,7360,56,S2,8PSK -76=12540,V,3111,78,DVB-S,QPSK -77=12546,V,6111,34,DVB-S,QPSK -78=12555,V,4104,23,S2,QPSK -79=12574,V,3400,34,DVB-S,QPSK -80=12577,H,2222,56,S2,QPSK -81=12583,H,2894,34,DVB-S,QPSK -82=12590,H,3600,23,DVB-S,QPSK -83=12595,H,1875,56,S2,8PSK -84=12606,H,2500,56,S2,8PSK -85=12606,V,3600,34,S2,8PSK -86=12614,H,8570,34,S2,8PSK -87=12614,V,8570,34,S2,8PSK -88=12634,V,7200,34,S2,8PSK -89=12638,H,14400,34,S2,8PSK -90=12648,V,9874,34,S2,8PSK -91=12650,H,3600,34,S2,8PSK -92=12661,V,4444,34,DVB-S,QPSK -93=12668,H,3213,34,DVB-S,QPSK -94=12668,V,3270,56,DVB-S,QPSK -95=12672,H,2141,34,DVB-S,QPSK -96=12672,V,3270,56,DVB-S,QPSK -97=12676,H,3178,34,DVB-S,QPSK -98=12679,V,7500,34,S2,8PSK -99=12681,H,3178,34,DVB-S,QPSK -100=12694,V,1580,56,S2,8PSK -101=12696,V,1580,56,S2,8PSK -102=12699,V,1580,56,S2,8PSK -103=12717,V,3333,78,DVB-S,QPSK -104=12718,H,36510,56,S2,8PSK -105=12723,V,6111,34,DVB-S,QPSK -106=12730,V,3254,34,DVB-S,QPSK -107=12739,V,7500,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3490.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3490.ini deleted file mode 100644 index 7d57379795..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3490.ini +++ /dev/null @@ -1,39 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3490 -2=Express AM44 (11.0W) - -[DVB] -0=30 -1=3662,V,10808,12,DVB-S,QPSK -2=4092,V,2224,35,S2,8PSK -3=10957,V,2300,56,S2,8PSK -4=10983,V,12110,Auto,DVB-S,QPSK -5=11059,H,3124,34,DVB-S,QPSK -6=11095,H,3000,34,DVB-S,QPSK -7=11144,H,3214,34,S2,8PSK -8=11154,H,7200,34,S2,8PSK -9=11174,H,9874,34,S2,8PSK -10=11191,H,7200,34,S2,8PSK -11=11479,H,7500,34,S2,8PSK -12=11483,V,3470,78,DVB-S,QPSK -13=11492,H,6428,34,DVB-S,QPSK -14=11499,H,3214,34,DVB-S,QPSK -15=11505,H,2222,34,S2,8PSK -16=11522,H,1185,23,DVB-S,QPSK -17=11523,H,1280,56,S2,8PSK -18=11533,H,3333,34,DVB-S,QPSK -19=11542,H,3600,34,S2,QPSK -20=11542,V,2170,56,DVB-S,QPSK -21=11566,H,8000,34,S2,8PSK -22=11581,H,2050,34,DVB-S,QPSK -23=11599,H,3600,56,DVB-S,QPSK -24=11603,H,3333,34,DVB-S,QPSK -25=11608,H,5000,34,DVB-S,QPSK -26=11612,H,3333,34,DVB-S,QPSK -27=11618,H,3333,34,DVB-S,QPSK -28=11628,H,6422,56,DVB-S,QPSK -29=11642,H,3333,34,DVB-S,QPSK -30=11669,H,5000,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3520.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3520.ini deleted file mode 100644 index 6274b967e3..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3520.ini +++ /dev/null @@ -1,80 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3520 -2=Eutelsat 8 West A (8.0W) - -[DVB] -0=71 -1=11471,V,27500,56,DVB-S,QPSK -2=11512,V,27500,56,DVB-S,QPSK -3=11554,V,27500,34,DVB-S,QPSK -4=11595,V,27500,34,DVB-S,QPSK -5=11637,V,27500,34,DVB-S,QPSK -6=11678,H,30000,Auto,S2,QPSK -7=11678,V,27500,34,DVB-S,QPSK -8=12509,V,4150,34,S2,QPSK -9=12509,H,5000,34,S2,8PSK -10=12513,V,4150,34,S2,QPSK -11=12515,H,2500,Auto,S2,8PSK -12=12518,V,4150,34,S2,QPSK -13=12523,V,4150,34,S2,QPSK -14=12524,H,9600,34,S2,8PSK -15=12527,V,4150,34,S2,QPSK -16=12531,V,3488,56,S2,8PSK -17=12536,V,4150,34,S2,QPSK -18=12549,H,4800,34,S2,8PSK -19=12550,V,2267,56,S2,8PSK -20=12554,H,3600,34,S2,8PSK -21=12554,V,2267,56,S2,8PSK -22=12558,V,2267,56,S2,8PSK -23=12558,H,3600,34,S2,8PSK -24=12561,V,2267,56,S2,8PSK -25=12564,V,2267,56,S2,8PSK -26=12567,V,2267,56,S2,8PSK -27=12570,V,2267,56,S2,8PSK -28=12572,H,7200,34,S2,8PSK -29=12573,V,2267,56,S2,8PSK -30=12578,V,2267,56,S2,8PSK -31=12580,H,3200,56,S2,8PSK -32=12582,V,2744,56,S2,8PSK -33=12585,H,3124,34,DVB-S,QPSK -34=12589,H,9874,34,S2,8PSK -35=12592,V,4800,34,S2,QPSK -36=12599,V,3333,78,DVB-S,QPSK -37=12601,H,6975,56,S2,8PSK -38=12606,V,1300,910,S2,8PSK -39=12609,V,2400,56,S2,8PSK -40=12613,H,3056,34,S2,QPSK -41=12614,V,2400,56,S2,8PSK -42=12619,V,2400,56,S2,8PSK -43=12624,H,7200,34,S2,8PSK -44=12627,V,2222,12,DVB-S,QPSK -45=12632,V,2500,56,S2,8PSK -46=12633,H,7200,34,S2,8PSK -47=12638,H,3055,34,DVB-S,QPSK -48=12640,V,5000,34,S2,8PSK -49=12646,V,5000,34,S2,8PSK -50=12652,V,5000,34,S2,8PSK -51=12656,H,7200,34,S2,8PSK -52=12658,V,5000,56,S2,8PSK -53=12666,H,5632,34,DVB-S,QPSK -54=12673,H,2778,34,DVB-S,QPSK -55=12676,H,2778,34,DVB-S,QPSK -56=12676,V,5632,34,DVB-S,QPSK -57=12684,H,5632,34,DVB-S,QPSK -58=12686,V,6111,34,DVB-S,QPSK -59=12695,V,6111,34,DVB-S,QPSK -60=12703,V,5632,34,DVB-S,QPSK -61=12705,H,4800,34,S2,8PSK -62=12715,H,9600,34,S2,8PSK -63=12718,V,7200,34,S2,8PSK -64=12725,V,2267,56,S2,8PSK -65=12727,H,9600,34,S2,8PSK -66=12735,V,3600,34,S2,8PSK -67=12739,H,9600,34,S2,8PSK -68=12741,V,3600,34,S2,8PSK -69=12744,V,3270,56,S2,8PSK -70=12747,H,4800,34,S2,8PSK -71=12747,V,3600,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3527.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3527.ini deleted file mode 100644 index b5aa217800..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3527.ini +++ /dev/null @@ -1,94 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3527 -2=Eutelsat 7 West A/Eutelsat 8 West C/Nilesat 102/201 (7.3W) - -[DVB] -0=85 -1=10719,V,22000,34,S2,QPSK -2=10727,H,27500,56,DVB-S,QPSK -3=10758,V,27500,56,DVB-S,QPSK -4=10777,H,27500,56,DVB-S,QPSK -5=10796,V,27500,56,DVB-S,QPSK -6=10815,H,27500,56,DVB-S,QPSK -7=10834,V,27500,23,S2,8PSK -8=10853,H,27500,23,S2,8PSK -9=10873,V,27500,56,DVB-S,QPSK -10=10892,H,27500,34,DVB-S,QPSK -11=10922,V,27500,56,DVB-S,QPSK -12=10930,H,27500,56,DVB-S,QPSK -13=10971,H,27500,34,DVB-S,QPSK -14=10992,V,27500,34,DVB-S,QPSK -15=11006,H,17000,23,S2,8PSK -16=11034,V,27500,34,DVB-S,QPSK -17=11054,H,27500,34,DVB-S,QPSK -18=11075,V,27500,34,DVB-S,QPSK -19=11096,H,27500,34,DVB-S,QPSK -20=11117,V,27500,34,DVB-S,QPSK -21=11137,H,27500,34,DVB-S,QPSK -22=11158,V,27500,56,DVB-S,QPSK -23=11179,H,27500,34,DVB-S,QPSK -24=11219,H,27500,56,DVB-S,QPSK -25=11227,V,27500,56,DVB-S,QPSK -26=11258,H,27500,56,DVB-S,QPSK -27=11277,V,27500,23,S2,8PSK -28=11296,H,27500,34,DVB-S,QPSK -29=11315,V,27500,56,DVB-S,QPSK -30=11334,H,27500,56,DVB-S,QPSK -31=11354,V,27500,56,DVB-S,QPSK -32=11373,H,27500,23,S2,8PSK -33=11392,V,27500,56,DVB-S,QPSK -34=11411,H,27500,23,S2,8PSK -35=11430,V,27500,56,DVB-S,QPSK -36=11449,H,27500,56,DVB-S,QPSK -37=11476,V,27500,34,DVB-S,8PSK -38=11488,H,27500,56,DVB-S,QPSK -39=11526,H,27500,56,DVB-S,QPSK -40=11559,V,27500,56,S2,8PSK -41=11564,H,27500,56,DVB-S,QPSK -42=11595,V,27500,34,DVB-S,QPSK -43=11603,H,27500,56,DVB-S,QPSK -44=11641,H,27500,56,DVB-S,QPSK -45=11661,V,27500,23,DVB-S,QPSK -46=11680,H,27500,56,DVB-S,QPSK -47=11727,H,27500,56,S2,8PSK -48=11747,V,27500,34,DVB-S,QPSK -49=11766,H,27500,56,DVB-S,QPSK -50=11785,V,27500,34,DVB-S,QPSK -51=11804,H,27500,56,S2,QPSK -52=11823,V,27500,56,DVB-S,QPSK -53=11843,H,27500,56,DVB-S,QPSK -54=11862,V,27500,34,S2,8PSK -55=11881,H,27500,56,S2,QPSK -56=11900,V,27500,56,DVB-S,QPSK -57=11919,H,27500,34,S2,8PSK -58=11938,V,27500,34,DVB-S,QPSK -59=11958,H,27500,56,DVB-S,QPSK -60=11977,V,27500,56,DVB-S,QPSK -61=11996,H,27500,23,S2,8PSK -62=12015,V,27500,56,DVB-S,QPSK -63=12034,H,27500,56,DVB-S,QPSK -64=12054,V,27500,56,DVB-S,QPSK -65=12073,H,27500,23,S2,8PSK -66=12092,V,27500,56,S2,QPSK -67=12111,H,27500,34,DVB-S,QPSK -68=12130,V,27500,56,DVB-S,QPSK -69=12169,V,27500,56,DVB-S,QPSK -70=12188,H,27500,56,S2,QPSK -71=12207,V,27500,34,DVB-S,QPSK -72=12226,H,27500,34,DVB-S,QPSK -73=12245,V,27500,23,S2,8PSK -74=12265,H,27500,23,S2,8PSK -75=12284,V,27500,34,DVB-S,QPSK -76=12303,H,27500,56,DVB-S,QPSK -77=12322,V,27500,23,S2,8PSK -78=12341,H,27500,56,DVB-S,QPSK -79=12360,V,27500,34,DVB-S,QPSK -80=12380,H,27500,56,DVB-S,QPSK -81=12399,V,27500,56,DVB-S,QPSK -82=12418,H,27500,34,DVB-S,QPSK -83=12437,V,27500,56,DVB-S,QPSK -84=12467,H,27500,23,S2,8PSK -85=12476,V,27500,23,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3550.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3550.ini deleted file mode 100644 index 5ae30b7787..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3550.ini +++ /dev/null @@ -1,69 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3550 -2=Eutelsat 5 West A (5.0W) - -[DVB] -0=60 -1=3630,V,3255,23,DVB-S,QPSK -2=3633,V,2018,78,DVB-S,QPSK -3=3646,V,2170,34,DVB-S,QPSK -4=3656,V,2917,35,S2,8PSK -5=3712,H,2480,78,DVB-S,QPSK -6=3717,H,2222,56,S2,8PSK -7=3719,H,1286,23,S2,8PSK -8=3721,H,1837,34,S2,8PSK -9=3727,V,29950,78,DVB-S,QPSK -10=3743,H,2785,56,DVB-S,QPSK -11=4015,V,3591,34,S2,8PSK -12=4021,V,1245,34,S2,8PSK -13=4022,V,1200,34,S2,8PSK -14=4030,V,4593,35,S2,8PSK -15=4077,H,3100,56,S2,QPSK -16=4110,H,2141,56,S2,QPSK -17=4114,H,2143,56,DVB-S,QPSK -18=4123,V,8319,34,DVB-S,QPSK -19=4137,H,2510,78,DVB-S,QPSK -20=4138,V,4434,78,DVB-S,QPSK -21=4154,H,2289,78,DVB-S,QPSK -22=4154,V,28485,56,S2,8PSK -23=4156,H,1793,78,DVB-S,QPSK -24=4159,H,1944,78,DVB-S,QPSK -25=4162,H,1500,34,DVB-S,QPSK -26=10972,V,29950,78,DVB-S,QPSK -27=11054,V,29950,78,DVB-S,QPSK -28=11059,H,23700,34,DVB-S,QPSK -29=11096,V,29950,34,S2,8PSK -30=11108,H,3125,34,DVB-S,QPSK -31=11168,H,6111,34,DVB-S,QPSK -32=11177,H,6111,34,DVB-S,QPSK -33=11184,H,5632,34,DVB-S,QPSK -34=11195,H,3333,34,DVB-S,QPSK -35=11456,H,2400,34,S2,QPSK -36=11460,H,1704,34,S2,8PSK -37=11469,H,3100,78,DVB-S,QPSK -38=11471,V,29950,34,S2,8PSK -39=11472,H,2000,34,S2,8PSK -40=11480,H,3215,34,S2,8PSK -41=11496,H,6111,34,DVB-S,QPSK -42=11505,H,5632,34,DVB-S,QPSK -43=11512,V,29950,78,DVB-S,QPSK -44=11513,H,5632,34,DVB-S,QPSK -45=11522,H,6111,34,DVB-S,QPSK -46=11538,H,8681,78,DVB-S,QPSK -47=11554,V,29950,78,DVB-S,QPSK -48=11591,V,20000,23,DVB-S,QPSK -49=11592,H,25000,12,S2,QPSK -50=11604,H,3333,34,DVB-S,QPSK -51=11608,H,3333,34,DVB-S,QPSK -52=11609,V,5968,12,DVB-S,QPSK -53=11634,H,29950,34,S2,8PSK -54=11679,V,29950,78,DVB-S,QPSK -55=12522,V,29950,23,S2,8PSK -56=12543,H,27500,34,DVB-S,QPSK -57=12564,V,29950,78,DVB-S,QPSK -58=12648,V,29500,89,S2,8PSK -59=12654,H,5500,23,S2,8PSK -60=12690,V,30000,35,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3560.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3560.ini deleted file mode 100644 index bf3006b2e4..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3560.ini +++ /dev/null @@ -1,73 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3560 -2=Amos 2/3 (4.0W) - -[DVB] -0=64 -1=10722,V,30000,23,S2,8PSK -2=10722,H,27500,34,DVB-S,QPSK -3=10758,V,30000,34,S2,8PSK -4=10759,H,30000,34,DVB-S,QPSK -5=10806,V,30000,34,S2,8PSK -6=10806,H,30000,34,DVB-S,QPSK -7=10842,V,30000,34,S2,8PSK -8=10876,H,7500,23,S2,8PSK -9=10888,H,11570,34,DVB-S,QPSK -10=10889,V,30000,34,S2,8PSK -11=10890,V,27500,56,DVB-S,QPSK -12=10921,H,7500,23,S2,8PSK -13=10925,V,27500,56,DVB-S,QPSK -14=10926,V,30000,34,S2,8PSK -15=10935,H,13750,56,DVB-S,QPSK -16=10959,H,3700,34,DVB-S,QPSK -17=10972,V,30000,23,S2,8PSK -18=11006,H,3700,34,DVB-S,QPSK -19=11008,V,30000,23,S2,8PSK -20=11015,H,2295,34,DVB-S,QPSK -21=11130,H,10000,23,S2,8PSK -22=11140,H,3200,Auto,DVB-S,QPSK -23=11166,H,3333,34,DVB-S,QPSK -24=11180,H,5650,34,DVB-S,QPSK -25=11190,H,3400,34,DVB-S,QPSK -26=11222,V,27500,56,DVB-S,QPSK -27=11222,H,30000,56,S2,QPSK -28=11258,V,27500,56,DVB-S,QPSK -29=11291,H,2800,34,DVB-S,QPSK -30=11304,H,13330,34,DVB-S,QPSK -31=11315,H,5000,34,S2,8PSK -32=11332,H,12500,78,DVB-S,QPSK -33=11389,H,27500,34,DVB-S,QPSK -34=11411,H,3330,34,DVB-S,QPSK -35=11432,H,2500,34,DVB-S,QPSK -36=11435,H,2600,34,DVB-S,QPSK -37=11474,V,27500,34,DVB-S,QPSK -38=11510,V,30000,23,S2,8PSK -39=11541,V,2963,34,DVB-S,QPSK -40=11542,H,3700,34,DVB-S,QPSK -41=11544,V,1480,56,DVB-S,QPSK -42=11546,V,2600,56,S2,8PSK -43=11547,H,3333,34,DVB-S,QPSK -44=11549,V,1240,34,DVB-S,QPSK -45=11551,H,3333,56,DVB-S,QPSK -46=11552,V,1222,78,DVB-S,QPSK -47=11555,V,1240,78,DVB-S,QPSK -48=11565,V,3000,34,DVB-S,QPSK -49=11578,V,1222,78,DVB-S,QPSK -50=11580,V,1110,78,DVB-S,QPSK -51=11601,H,8888,34,DVB-S,QPSK -52=11610,H,3600,34,DVB-S,QPSK -53=11624,H,2604,56,DVB-S,QPSK -54=11625,V,3000,34,DVB-S,QPSK -55=11627,V,6295,34,S2,QPSK -56=11635,H,6333,34,DVB-S,QPSK -57=11635,V,4410,56,DVB-S,QPSK -58=11639,V,2000,56,DVB-S,QPSK -59=11647,V,8518,34,DVB-S,QPSK -60=11658,H,3333,34,DVB-S,QPSK -61=11658,V,8520,23,DVB-S,QPSK -62=11671,V,1480,34,DVB-S,QPSK -63=11684,H,3350,78,DVB-S,QPSK -64=11687,V,5185,34,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3592.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3592.ini deleted file mode 100644 index b1118d4fbb..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3592.ini +++ /dev/null @@ -1,110 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3592 -2=Thor 5/6/7/Intelsat 10-02 (0.8W) - -[DVB] -0=101 -1=3722,V,18000,34,S2,8PSK -2=3977,H,17777,34,DVB-S,QPSK -3=3985,V,9764,23,DVB-S,QPSK -4=4025,V,7324,23,DVB-S,QPSK -5=4032,H,1000,56,S2,8PSK -6=4175,V,28000,34,DVB-S,QPSK -7=10716,H,24500,78,DVB-S,QPSK -8=10747,V,25000,34,S2,8PSK -9=10747,H,25000,34,S2,8PSK -10=10778,V,25000,34,S2,8PSK -11=10778,H,24500,78,DVB-S,QPSK -12=10809,V,24500,78,DVB-S,QPSK -13=10809,H,24500,78,DVB-S,QPSK -14=10841,H,25000,34,S2,8PSK -15=10872,V,25000,34,S2,8PSK -16=10872,H,25000,34,S2,8PSK -17=10903,V,25000,34,S2,8PSK -18=10903,H,25000,34,S2,8PSK -19=10934,V,24500,78,DVB-S,QPSK -20=10934,H,25000,34,S2,8PSK -21=10962,H,1550,78,DVB-S,QPSK -22=11038,H,2200,56,S2,8PSK -23=11048,H,3100,34,DVB-S,QPSK -24=11063,H,1500,56,S2,8PSK -25=11080,H,1100,34,DVB-S,QPSK -26=11104,H,3360,23,S2,8PSK -27=11216,V,24500,78,DVB-S,QPSK -28=11229,H,24500,78,DVB-S,QPSK -29=11247,V,24500,78,DVB-S,QPSK -30=11261,H,25000,34,S2,8PSK -31=11278,V,24500,78,DVB-S,QPSK -32=11293,H,25000,34,S2,8PSK -33=11309,V,24500,78,DVB-S,QPSK -34=11325,H,24500,78,DVB-S,QPSK -35=11341,V,25000,34,S2,8PSK -36=11357,H,24500,78,DVB-S,QPSK -37=11372,V,24500,78,DVB-S,QPSK -38=11389,H,24500,78,DVB-S,QPSK -39=11403,V,24500,78,DVB-S,QPSK -40=11421,H,24500,78,DVB-S,QPSK -41=11461,V,4937,34,S2,8PSK -42=11467,V,2500,34,S2,8PSK -43=11471,V,3300,34,S2,8PSK -44=11479,V,4936,34,S2,8PSK -45=11489,V,6680,23,S2,8PSK -46=11502,V,2220,34,S2,QPSK -47=11512,V,2222,78,DVB-S,QPSK -48=11517,V,7500,56,S2,8PSK -49=11529,V,2222,78,DVB-S,QPSK -50=11533,V,3600,Auto,S2,QPSK -51=11542,V,3472,34,S2,8PSK -52=11547,V,3472,34,S2,8PSK -53=11554,V,6111,34,DVB-S,QPSK -54=11559,V,3600,34,S2,8PSK -55=11565,V,2200,34,S2,8PSK -56=11608,H,5655,78,DVB-S,QPSK -57=11643,H,3333,34,DVB-S,QPSK -58=11727,V,28000,78,DVB-S,QPSK -59=11747,H,28000,56,DVB-S,QPSK -60=11766,V,28000,78,DVB-S,QPSK -61=11785,H,30000,34,S2,8PSK -62=11804,V,28000,78,DVB-S,QPSK -63=11823,H,30000,56,S2,8PSK -64=11843,V,30000,34,S2,8PSK -65=11900,H,28000,56,DVB-S,QPSK -66=11919,V,28000,78,DVB-S,QPSK -67=11938,H,28000,78,DVB-S,QPSK -68=11977,H,30000,34,S2,8PSK -69=11996,V,28000,78,DVB-S,QPSK -70=12015,H,30000,34,S2,8PSK -71=12034,V,30000,34,S2,8PSK -72=12054,H,30000,34,S2,8PSK -73=12073,V,28000,78,DVB-S,QPSK -74=12092,H,28000,78,DVB-S,QPSK -75=12111,V,28000,78,DVB-S,QPSK -76=12188,V,28000,78,DVB-S,QPSK -77=12207,H,30000,34,S2,8PSK -78=12226,V,27500,56,DVB-S,QPSK -79=12265,V,28000,78,DVB-S,QPSK -80=12303,V,27500,56,S2,8PSK -81=12380,V,28000,56,DVB-S,QPSK -82=12418,V,28000,78,DVB-S,QPSK -83=12456,V,28000,78,DVB-S,QPSK -84=12511,V,3300,56,S2,8PSK -85=12515,V,3300,56,S2,8PSK -86=12520,V,3700,56,S2,8PSK -87=12524,V,3750,56,S2,8PSK -88=12527,H,27500,34,DVB-S,QPSK -89=12529,V,4750,56,S2,8PSK -90=12535,V,5000,89,S2,8PSK -91=12541,V,6660,56,S2,8PSK -92=12563,H,27500,34,DVB-S,QPSK -93=12563,V,27500,34,DVB-S,QPSK -94=12607,H,27500,34,DVB-S,QPSK -95=12607,V,26667,23,S2,8PSK -96=12643,H,27500,34,DVB-S,QPSK -97=12643,V,27500,34,DVB-S,QPSK -98=12687,H,27500,34,DVB-S,QPSK -99=12687,V,27500,34,DVB-S,QPSK -100=12723,H,27500,34,DVB-S,QPSK -101=12735,V,8800,56,DVB-S,QPSK diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3594.ini b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3594.ini deleted file mode 100644 index f762d2f6fb..0000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ini/satellite/3594.ini +++ /dev/null @@ -1,10 +0,0 @@ -; file generated on saturday, 22nd of august 2015, 19:35:09 [GMT] -; by online transponder .ini generator @ http://satellites-xml.eu -; please let us know if you find any inconsistencies in this file -[SATTYPE] -1=3594 -2=Thor 7 (0.6W) - -[DVB] -0=1 -1=12207,H,30000,34,S2,8PSK diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ar.json b/MediaBrowser.Server.Implementations/Localization/Core/ar.json deleted file mode 100644 index 28977c4f92..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/ar.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "\u062e\u0631\u0648\u062c", - "LabelVisitCommunity": "\u0632\u064a\u0627\u0631\u0629 \u0627\u0644\u0645\u062c\u062a\u0645\u0639", - "LabelGithub": "\u062c\u064a\u062a \u0647\u0628", - "LabelApiDocumentation": "\u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0645\u062f\u062e\u0644 \u0628\u0631\u0645\u062c\u0629 \u0627\u0644\u062a\u0637\u0628\u064a\u0642", - "LabelDeveloperResources": "\u0645\u0643\u062a\u0628\u0629 \u0627\u0644\u0645\u0628\u0631\u0645\u062c", - "LabelBrowseLibrary": "\u062a\u0635\u0641\u062d \u0627\u0644\u0645\u0643\u062a\u0628\u0629", - "LabelConfigureServer": "\u0625\u0639\u062f\u0627\u062f \u0625\u0645\u0628\u064a", - "LabelRestartServer": "\u0627\u0639\u0627\u062f\u0629 \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u062e\u0627\u062f\u0645", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/bg-BG.json b/MediaBrowser.Server.Implementations/Localization/Core/bg-BG.json deleted file mode 100644 index 22b99408df..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/bg-BG.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "\u0421\u043c\u0435\u0441\u0435\u043d\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435", - "FolderTypeMovies": "\u0424\u0438\u043b\u043c\u0438", - "FolderTypeMusic": "\u041c\u0443\u0437\u0438\u043a\u0430", - "FolderTypeAdultVideos": "\u041a\u043b\u0438\u043f\u043e\u0432\u0435 \u0437\u0430 \u0432\u044a\u0437\u0440\u0430\u0441\u0442\u043d\u0438", - "FolderTypePhotos": "\u0421\u043d\u0438\u043c\u043a\u0438", - "FolderTypeMusicVideos": "\u041c\u0443\u0437\u0438\u043a\u0430\u043b\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", - "FolderTypeHomeVideos": "\u0414\u043e\u043c\u0430\u0448\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", - "FolderTypeGames": "\u0418\u0433\u0440\u0438", - "FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "\u041d\u0430\u0441\u043b\u0435\u0434\u0438", - "HeaderCastCrew": "\u0415\u043a\u0438\u043f", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "\u0418\u0437\u0445\u043e\u0434", - "LabelVisitCommunity": "\u041f\u043e\u0441\u0435\u0442\u0438 \u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e\u0442\u043e", - "LabelGithub": "Github", - "LabelApiDocumentation": "API \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f", - "LabelDeveloperResources": "\u0420\u0435\u0441\u0443\u0440\u0441\u0438 \u0437\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u0446\u0438", - "LabelBrowseLibrary": "\u0420\u0430\u0437\u0433\u043b\u0435\u0434\u0430\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430", - "LabelConfigureServer": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0439 Emby", - "LabelRestartServer": "\u0420\u0435\u0441\u0442\u0430\u0440\u0442\u0438\u0440\u0430\u0439 \u0441\u044a\u0440\u0432\u044a\u0440\u0430", - "CategorySync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437.", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "\u0412\u0435\u0440\u0441\u0438\u044f {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby \u0441\u044a\u0440\u0432\u044a\u0440\u044a\u0442 \u0431\u0435 \u043e\u0431\u043d\u043e\u0432\u0435\u043d.", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "\u0410\u0443\u0434\u0438\u043e", - "HeaderVideo": "\u0412\u0438\u0434\u0435\u043e", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "\u0421\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435:", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ca.json b/MediaBrowser.Server.Implementations/Localization/Core/ca.json deleted file mode 100644 index 7ca8e1553d..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/ca.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Si et plau espera mentre la teva base de dades del Servidor Emby \u00e9s actualitzada. {0}% completat.", - "AppDeviceValues": "App: {0}, Dispositiu: {1}", - "UserDownloadingItemWithValues": "{0} est\u00e0 descarregant {1}", - "FolderTypeMixed": "Contingut barrejat", - "FolderTypeMovies": "Pel\u00b7l\u00edcules", - "FolderTypeMusic": "M\u00fasica", - "FolderTypeAdultVideos": "V\u00eddeos per adults", - "FolderTypePhotos": "Fotos", - "FolderTypeMusicVideos": "V\u00eddeos musicals", - "FolderTypeHomeVideos": "V\u00eddeos dom\u00e8stics", - "FolderTypeGames": "Jocs", - "FolderTypeBooks": "Llibres", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Heretat", - "HeaderCastCrew": "Repartiment i Equip", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Cap\u00edtol {0}", - "NameSeasonNumber": "Temporada {0}", - "LabelExit": "Sortir", - "LabelVisitCommunity": "Visita la Comunitat", - "LabelGithub": "Github", - "LabelApiDocumentation": "Documentaci\u00f3 de l'API", - "LabelDeveloperResources": "Recursos per a Desenvolupadors", - "LabelBrowseLibrary": "Examina la Biblioteca", - "LabelConfigureServer": "Configura Emby", - "LabelRestartServer": "Reiniciar Servidor", - "CategorySync": "Sync", - "CategoryUser": "Usuari", - "CategorySystem": "Sistema", - "CategoryApplication": "Aplicaci\u00f3", - "CategoryPlugin": "Complement", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Actualitzaci\u00f3 d'aplicaci\u00f3 disponible", - "NotificationOptionApplicationUpdateInstalled": "Actualitzaci\u00f3 d'aplicaci\u00f3 instal\u00b7lada", - "NotificationOptionPluginUpdateInstalled": "Actualitzaci\u00f3 de complement instal\u00b7lada", - "NotificationOptionPluginInstalled": "Complement instal\u00b7lat", - "NotificationOptionPluginUninstalled": "Complement desinstal\u00b7lat", - "NotificationOptionVideoPlayback": "Reproducci\u00f3 de v\u00eddeo iniciada", - "NotificationOptionAudioPlayback": "Reproducci\u00f3 d'\u00e0udio iniciada", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Reproducci\u00f3 de v\u00eddeo aturada", - "NotificationOptionAudioPlaybackStopped": "Reproducci\u00f3 d'\u00e0udio aturada", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Tasca programada fallida", - "NotificationOptionInstallationFailed": "Instal\u00b7laci\u00f3 fallida", - "NotificationOptionNewLibraryContent": "Nou contingut afegit", - "NotificationOptionNewLibraryContentMultiple": "Nous continguts afegits", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "Usuari blocat", - "NotificationOptionServerRestartRequired": "Cal reiniciar el servidor", - "ViewTypePlaylists": "Llistes de reproducci\u00f3", - "ViewTypeMovies": "Pel\u00b7l\u00edcules", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Jocs", - "ViewTypeMusic": "M\u00fasica", - "ViewTypeMusicGenres": "G\u00e8neres", - "ViewTypeMusicArtists": "Artistes", - "ViewTypeBoxSets": "Col\u00b7leccions", - "ViewTypeChannels": "Canals", - "ViewTypeLiveTV": "TV en Directe", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Darrers Jocs", - "ViewTypeRecentlyPlayedGames": "Reprodu\u00eft Recentment", - "ViewTypeGameFavorites": "Preferits", - "ViewTypeGameSystems": "Sistemes de Jocs", - "ViewTypeGameGenres": "G\u00e8neres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "A Continuaci\u00f3", - "ViewTypeTvLatest": "Darrers", - "ViewTypeTvShowSeries": "S\u00e8ries:", - "ViewTypeTvGenres": "G\u00e8neres", - "ViewTypeTvFavoriteSeries": "S\u00e8ries Preferides", - "ViewTypeTvFavoriteEpisodes": "Episodis Preferits", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Darrers", - "ViewTypeMovieMovies": "Pel\u00b7l\u00edcules", - "ViewTypeMovieCollections": "Col\u00b7leccions", - "ViewTypeMovieFavorites": "Preferides", - "ViewTypeMovieGenres": "G\u00e8neres", - "ViewTypeMusicLatest": "Novetats", - "ViewTypeMusicPlaylists": "Llistes de reproducci\u00f3", - "ViewTypeMusicAlbums": "\u00c0lbums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Prefer\u00e8ncies de Visualitzaci\u00f3", - "ViewTypeMusicSongs": "Can\u00e7ons", - "ViewTypeMusicFavorites": "Preferides", - "ViewTypeMusicFavoriteAlbums": "\u00c0lbums Preferits", - "ViewTypeMusicFavoriteArtists": "Artistes Preferits", - "ViewTypeMusicFavoriteSongs": "Can\u00e7ons Preferides", - "ViewTypeFolders": "Directoris", - "ViewTypeLiveTvRecordingGroups": "Enregistraments", - "ViewTypeLiveTvChannels": "Canals", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Versi\u00f3 {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} afegit a la biblioteca", - "ItemRemovedWithName": "{0} eliminat de la biblioteca", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Prove\u00efdor: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "L'usuari {0} ha estat eliminat", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} autenticat correctament", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "L'usuari {0} ha estat blocat", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} ha comen\u00e7at a reproduir {1}", - "UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "Usuari", - "HeaderName": "Nom", - "HeaderDate": "Data", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Data afegida", - "HeaderReleaseDate": "Data de publicaci\u00f3", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Temporada", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "S\u00e8ries:", - "HeaderNetwork": "Network", - "HeaderYear": "Any:", - "HeaderYears": "Anys:", - "HeaderParentalRating": "Valoraci\u00f3 Parental", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Tr\u00e0ilers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Sistemes de Jocs", - "HeaderPlayers": "Jugadors:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "\u00c0udio", - "HeaderVideo": "V\u00eddeo", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subt\u00edtols", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Estat", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "M\u00fasic", - "HeaderLocked": "Blocat", - "HeaderStudios": "Estudis", - "HeaderActor": "Actors", - "HeaderComposer": "Compositors", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Artista convidat", - "HeaderProducer": "Productors", - "HeaderWriter": "Escriptors", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Qualificacions de la comunitat", - "StartupEmbyServerIsLoading": "El servidor d'Emby s'està carregant. Si et plau, tornau-ho a provar de nou en breu." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/core.json b/MediaBrowser.Server.Implementations/Localization/Core/core.json deleted file mode 100644 index 976faa8cbc..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/core.json +++ /dev/null @@ -1,179 +0,0 @@ -{ - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly.", - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete." -} diff --git a/MediaBrowser.Server.Implementations/Localization/Core/cs.json b/MediaBrowser.Server.Implementations/Localization/Core/cs.json deleted file mode 100644 index e3055f5bac..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/cs.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Po\u010dkejte pros\u00edm, datab\u00e1ze Emby Serveru je aktualizov\u00e1na na novou verzi. Hotovo {0}%.", - "AppDeviceValues": "Aplikace: {0}, Za\u0159\u00edzen\u00ed: {1}", - "UserDownloadingItemWithValues": "{0} pr\u00e1v\u011b stahuje {1}", - "FolderTypeMixed": "Sm\u00ed\u0161en\u00fd obsah", - "FolderTypeMovies": "Filmy", - "FolderTypeMusic": "Hudba", - "FolderTypeAdultVideos": "Filmy pro dosp\u011bl\u00e9", - "FolderTypePhotos": "Fotky", - "FolderTypeMusicVideos": "Hudebn\u00ed klipy", - "FolderTypeHomeVideos": "Dom\u00e1c\u00ed video", - "FolderTypeGames": "Hry", - "FolderTypeBooks": "Knihy", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Zd\u011bdit", - "HeaderCastCrew": "Herci a obsazen\u00ed", - "HeaderPeople": "Lid\u00e9", - "ValueSpecialEpisodeName": "Speci\u00e1l - {0}", - "LabelChapterName": "Kapitola {0}", - "NameSeasonNumber": "Sez\u00f3na {0}", - "LabelExit": "Zav\u0159\u00edt", - "LabelVisitCommunity": "Nav\u0161t\u00edvit komunitu", - "LabelGithub": "Github", - "LabelApiDocumentation": "Dokumentace API", - "LabelDeveloperResources": "Zdroje v\u00fdvoj\u00e1\u0159\u016f", - "LabelBrowseLibrary": "Proch\u00e1zet knihovnu", - "LabelConfigureServer": "Konfigurovat Emby", - "LabelRestartServer": "Restartovat server", - "CategorySync": "Synchronizace", - "CategoryUser": "U\u017eivatel:", - "CategorySystem": "Syst\u00e9m", - "CategoryApplication": "Aplikace", - "CategoryPlugin": "Z\u00e1suvn\u00fd modul", - "NotificationOptionPluginError": "Chyba z\u00e1suvn\u00e9ho modulu", - "NotificationOptionApplicationUpdateAvailable": "Dostupnost aktualizace aplikace", - "NotificationOptionApplicationUpdateInstalled": "Instalace aktualizace aplikace", - "NotificationOptionPluginUpdateInstalled": "Aktualizace z\u00e1suvn\u00e9ho modulu instalov\u00e1na", - "NotificationOptionPluginInstalled": "Z\u00e1suvn\u00fd modul instalov\u00e1n", - "NotificationOptionPluginUninstalled": "Z\u00e1suvn\u00fd modul odstran\u011bn", - "NotificationOptionVideoPlayback": "P\u0159ehr\u00e1v\u00e1n\u00ed videa zah\u00e1jeno", - "NotificationOptionAudioPlayback": "P\u0159ehr\u00e1v\u00e1n\u00ed audia zah\u00e1jeno", - "NotificationOptionGamePlayback": "Spu\u0161t\u011bn\u00ed hry zah\u00e1jeno", - "NotificationOptionVideoPlaybackStopped": "P\u0159ehr\u00e1v\u00e1n\u00ed videa ukon\u010deno", - "NotificationOptionAudioPlaybackStopped": "P\u0159ehr\u00e1v\u00e1n\u00ed audia ukon\u010deno", - "NotificationOptionGamePlaybackStopped": "Hra ukon\u010dena", - "NotificationOptionTaskFailed": "Chyba napl\u00e1novan\u00e9 \u00falohy", - "NotificationOptionInstallationFailed": "Chyba instalace", - "NotificationOptionNewLibraryContent": "P\u0159id\u00e1n nov\u00fd obsah", - "NotificationOptionNewLibraryContentMultiple": "P\u0159id\u00e1n nov\u00fd obsah (v\u00edcen\u00e1sobn\u00fd)", - "NotificationOptionCameraImageUploaded": "Kamerov\u00fd z\u00e1znam nahr\u00e1n", - "NotificationOptionUserLockedOut": "U\u017eivatel uzam\u010den", - "NotificationOptionServerRestartRequired": "Je vy\u017eadov\u00e1n restart serveru", - "ViewTypePlaylists": "Playlisty", - "ViewTypeMovies": "Filmy", - "ViewTypeTvShows": "Televize", - "ViewTypeGames": "Hry", - "ViewTypeMusic": "Hudba", - "ViewTypeMusicGenres": "\u017d\u00e1nry", - "ViewTypeMusicArtists": "\u00dam\u011blci", - "ViewTypeBoxSets": "Kolekce", - "ViewTypeChannels": "Kan\u00e1ly", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Vys\u00edl\u00e1no nyn\u00ed", - "ViewTypeLatestGames": "Nejnov\u011bj\u0161\u00ed hry", - "ViewTypeRecentlyPlayedGames": "Ned\u00e1vno p\u0159ehr\u00e1no", - "ViewTypeGameFavorites": "Obl\u00edben\u00e9", - "ViewTypeGameSystems": "Syst\u00e9my hry", - "ViewTypeGameGenres": "\u017d\u00e1nry", - "ViewTypeTvResume": "Obnovit", - "ViewTypeTvNextUp": "O\u010dek\u00e1van\u00e9", - "ViewTypeTvLatest": "Nejnov\u011bj\u0161\u00ed", - "ViewTypeTvShowSeries": "Seri\u00e1l", - "ViewTypeTvGenres": "\u017d\u00e1nry", - "ViewTypeTvFavoriteSeries": "Obl\u00edben\u00e9 seri\u00e1ly", - "ViewTypeTvFavoriteEpisodes": "Obl\u00edben\u00e9 epizody", - "ViewTypeMovieResume": "Obnovit", - "ViewTypeMovieLatest": "Nejnov\u011bj\u0161\u00ed", - "ViewTypeMovieMovies": "Filmy", - "ViewTypeMovieCollections": "Kolekce", - "ViewTypeMovieFavorites": "Obl\u00edben\u00e9", - "ViewTypeMovieGenres": "\u017d\u00e1nry", - "ViewTypeMusicLatest": "Nejnov\u011bj\u0161\u00ed", - "ViewTypeMusicPlaylists": "Playlisty", - "ViewTypeMusicAlbums": "Alba", - "ViewTypeMusicAlbumArtists": "Alba \u00fam\u011blc\u016f", - "HeaderOtherDisplaySettings": "Nastaven\u00ed zobrazen\u00ed", - "ViewTypeMusicSongs": "Songy", - "ViewTypeMusicFavorites": "Obl\u00edben\u00e9", - "ViewTypeMusicFavoriteAlbums": "Obl\u00edben\u00e1 alba", - "ViewTypeMusicFavoriteArtists": "Obl\u00edben\u00ed \u00fam\u011blci", - "ViewTypeMusicFavoriteSongs": "Obl\u00edben\u00e9 songy", - "ViewTypeFolders": "Slo\u017eky", - "ViewTypeLiveTvRecordingGroups": "Nahr\u00e1vky", - "ViewTypeLiveTvChannels": "Kan\u00e1ly", - "ScheduledTaskFailedWithName": "{0} selhalo", - "LabelRunningTimeValue": "D\u00e9lka m\u00e9dia: {0}", - "ScheduledTaskStartedWithName": "{0} zah\u00e1jeno", - "VersionNumber": "Verze {0}", - "PluginInstalledWithName": "{0} byl nainstalov\u00e1n", - "PluginUpdatedWithName": "{0} byl aktualizov\u00e1n", - "PluginUninstalledWithName": "{0} byl odinstalov\u00e1n", - "ItemAddedWithName": "{0} byl p\u0159id\u00e1n do knihovny", - "ItemRemovedWithName": "{0} byl odstran\u011bn z knihovny", - "LabelIpAddressValue": "IP adresa: {0}", - "DeviceOnlineWithName": "{0} je p\u0159ipojen", - "UserOnlineFromDevice": "{0} se p\u0159ipojil z {1}", - "ProviderValue": "Poskytl: {0}", - "SubtitlesDownloadedForItem": "Sta\u017eeny titulky pro {0}", - "UserConfigurationUpdatedWithName": "Konfigurace u\u017eivatele byla aktualizov\u00e1na pro {0}", - "UserCreatedWithName": "U\u017eivatel {0} byl vytvo\u0159en", - "UserPasswordChangedWithName": "Pro u\u017eivatele {0} byla provedena zm\u011bna hesla", - "UserDeletedWithName": "U\u017eivatel {0} byl smaz\u00e1n", - "MessageServerConfigurationUpdated": "Konfigurace serveru byla aktualizov\u00e1na", - "MessageNamedServerConfigurationUpdatedWithValue": "Konfigurace sekce {0} na serveru byla aktualizov\u00e1na", - "MessageApplicationUpdated": "Emby Server byl aktualizov\u00e1n", - "FailedLoginAttemptWithUserName": "Ne\u00fasp\u011b\u0161n\u00fd pokus o p\u0159ihl\u00e1\u0161en\u00ed z {0}", - "AuthenticationSucceededWithUserName": "{0} \u00fasp\u011b\u0161n\u011b ov\u011b\u0159en", - "DeviceOfflineWithName": "{0} se odpojil", - "UserLockedOutWithName": "U\u017eivatel {0} byl odem\u010den", - "UserOfflineFromDevice": "{0} se odpojil od {1}", - "UserStartedPlayingItemWithValues": "{0} spustil p\u0159ehr\u00e1v\u00e1n\u00ed {1}", - "UserStoppedPlayingItemWithValues": "{0} zastavil p\u0159ehr\u00e1v\u00e1n\u00ed {1}", - "SubtitleDownloadFailureForItem": "Stahov\u00e1n\u00ed titulk\u016f selhalo pro {0}", - "HeaderUnidentified": "Neidentifikov\u00e1n", - "HeaderImagePrimary": "Prim\u00e1rn\u00ed", - "HeaderImageBackdrop": "Pozad\u00ed", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "Avatar u\u017eivatele", - "HeaderOverview": "P\u0159ehled", - "HeaderShortOverview": "Stru\u010dn\u00fd p\u0159ehled", - "HeaderType": "Typ", - "HeaderSeverity": "Z\u00e1va\u017enost", - "HeaderUser": "U\u017eivatel", - "HeaderName": "N\u00e1zev", - "HeaderDate": "Datum", - "HeaderPremiereDate": "Premi\u00e9ra", - "HeaderDateAdded": "P\u0159id\u00e1no", - "HeaderReleaseDate": "Datum vyd\u00e1n\u00ed", - "HeaderRuntime": "D\u00e9lka", - "HeaderPlayCount": "P\u0159ehr\u00e1no (po\u010det)", - "HeaderSeason": "Sez\u00f3na", - "HeaderSeasonNumber": "\u010c\u00edslo sez\u00f3ny", - "HeaderSeries": "Seri\u00e1l:", - "HeaderNetwork": "S\u00ed\u0165", - "HeaderYear": "Rok:", - "HeaderYears": "V letech:", - "HeaderParentalRating": "Rodi\u010dovsk\u00e9 hodnocen\u00ed", - "HeaderCommunityRating": "Hodnocen\u00ed komunity", - "HeaderTrailers": "Trailery", - "HeaderSpecials": "Speci\u00e1ly", - "HeaderGameSystems": "Syst\u00e9m hry", - "HeaderPlayers": "Hr\u00e1\u010di:", - "HeaderAlbumArtists": "\u00dam\u011blci alba", - "HeaderAlbums": "Alba", - "HeaderDisc": "Disk", - "HeaderTrack": "Stopa", - "HeaderAudio": "Zvuk", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Vlo\u017een\u00fd obr\u00e1zek", - "HeaderResolution": "Rozli\u0161en\u00ed", - "HeaderSubtitles": "Titulky", - "HeaderGenres": "\u017d\u00e1nry", - "HeaderCountries": "Zem\u011b", - "HeaderStatus": "Stav", - "HeaderTracks": "Stopy", - "HeaderMusicArtist": "Hudebn\u00ed \u00fam\u011blec", - "HeaderLocked": "Uzam\u010deno", - "HeaderStudios": "Studia", - "HeaderActor": "Herci", - "HeaderComposer": "Skladatel\u00e9", - "HeaderDirector": "Re\u017eis\u00e9\u0159i", - "HeaderGuestStar": "Hostuj\u00edc\u00ed hv\u011bzda", - "HeaderProducer": "Producenti", - "HeaderWriter": "Spisovatel\u00e9", - "HeaderParentalRatings": "Rodi\u010dovsk\u00e1 hodnocen\u00ed", - "HeaderCommunityRatings": "Hodnocen\u00ed komunity", - "StartupEmbyServerIsLoading": "Emby Server je na\u010d\u00edt\u00e1n. Zkuste to pros\u00edm znovu v brzk\u00e9 dob\u011b." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/da.json b/MediaBrowser.Server.Implementations/Localization/Core/da.json deleted file mode 100644 index d2a628a809..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/da.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Enhed: {1}", - "UserDownloadingItemWithValues": "{0} henter {1}", - "FolderTypeMixed": "Blandet indhold", - "FolderTypeMovies": "FIlm", - "FolderTypeMusic": "Musik", - "FolderTypeAdultVideos": "Voksenfilm", - "FolderTypePhotos": "Fotos", - "FolderTypeMusicVideos": "Musikvideoer", - "FolderTypeHomeVideos": "Hjemmevideoer", - "FolderTypeGames": "Spil", - "FolderTypeBooks": "B\u00f8ger", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Nedarv", - "HeaderCastCrew": "Medvirkende", - "HeaderPeople": "Mennesker", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Kapitel {0}", - "NameSeasonNumber": "S\u00e6son {0}", - "LabelExit": "Afslut", - "LabelVisitCommunity": "Bes\u00f8g F\u00e6lleskab", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api dokumentation", - "LabelDeveloperResources": "Udviklerressourcer", - "LabelBrowseLibrary": "Gennemse bibliotek", - "LabelConfigureServer": "Konfigurer Emby", - "LabelRestartServer": "Genstart Server", - "CategorySync": "Sync", - "CategoryUser": "Bruger", - "CategorySystem": "System", - "CategoryApplication": "Program", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin fejl", - "NotificationOptionApplicationUpdateAvailable": "Programopdatering tilg\u00e6ngelig", - "NotificationOptionApplicationUpdateInstalled": "Programopdatering installeret", - "NotificationOptionPluginUpdateInstalled": "Opdatering til plugin installeret", - "NotificationOptionPluginInstalled": "Plugin installeret", - "NotificationOptionPluginUninstalled": "Plugin afinstalleret", - "NotificationOptionVideoPlayback": "Videoafspilning startet", - "NotificationOptionAudioPlayback": "Lydafspilning startet", - "NotificationOptionGamePlayback": "Spilafspilning startet", - "NotificationOptionVideoPlaybackStopped": "Videoafspilning stoppet", - "NotificationOptionAudioPlaybackStopped": "Lydafspilning stoppet", - "NotificationOptionGamePlaybackStopped": "Spilafspilning stoppet", - "NotificationOptionTaskFailed": "Fejl i planlagt opgave", - "NotificationOptionInstallationFailed": "Fejl ved installation", - "NotificationOptionNewLibraryContent": "Nyt indhold tilf\u00f8jet", - "NotificationOptionNewLibraryContentMultiple": "Nyt indhold tilf\u00f8jet (flere)", - "NotificationOptionCameraImageUploaded": "Kamerabillede tilf\u00f8jet", - "NotificationOptionUserLockedOut": "Bruger l\u00e5st", - "NotificationOptionServerRestartRequired": "Genstart af serveren p\u00e5kr\u00e6vet", - "ViewTypePlaylists": "Afspilningslister", - "ViewTypeMovies": "Film", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Spil", - "ViewTypeMusic": "Musik", - "ViewTypeMusicGenres": "Genrer", - "ViewTypeMusicArtists": "Artister", - "ViewTypeBoxSets": "Samlinger", - "ViewTypeChannels": "Kanaler", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Vises nu", - "ViewTypeLatestGames": "Seneste spil", - "ViewTypeRecentlyPlayedGames": "Afspillet for nylig", - "ViewTypeGameFavorites": "Favoritter", - "ViewTypeGameSystems": "Spilsystemer", - "ViewTypeGameGenres": "Genrer", - "ViewTypeTvResume": "Forts\u00e6t", - "ViewTypeTvNextUp": "N\u00e6ste", - "ViewTypeTvLatest": "Seneste", - "ViewTypeTvShowSeries": "Serier", - "ViewTypeTvGenres": "Genrer", - "ViewTypeTvFavoriteSeries": "Favoritserier", - "ViewTypeTvFavoriteEpisodes": "Favoritepisoder", - "ViewTypeMovieResume": "Forts\u00e6t", - "ViewTypeMovieLatest": "Seneste", - "ViewTypeMovieMovies": "Film", - "ViewTypeMovieCollections": "Samlinger", - "ViewTypeMovieFavorites": "Favoritter", - "ViewTypeMovieGenres": "Genrer", - "ViewTypeMusicLatest": "Seneste", - "ViewTypeMusicPlaylists": "Afspilningslister", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Albumartister", - "HeaderOtherDisplaySettings": "Indstillinger for visning", - "ViewTypeMusicSongs": "Sange", - "ViewTypeMusicFavorites": "Favoritter", - "ViewTypeMusicFavoriteAlbums": "Favoritalbums", - "ViewTypeMusicFavoriteArtists": "Favoritartister", - "ViewTypeMusicFavoriteSongs": "Favoritsange", - "ViewTypeFolders": "Mapper", - "ViewTypeLiveTvRecordingGroups": "Optagelser", - "ViewTypeLiveTvChannels": "Kanaler", - "ScheduledTaskFailedWithName": "{0} fejlede", - "LabelRunningTimeValue": "K\u00f8rselstid: {0}", - "ScheduledTaskStartedWithName": "{0} startet", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} blev installeret", - "PluginUpdatedWithName": "{0} blev opdateret", - "PluginUninstalledWithName": "{0} blev afinstalleret", - "ItemAddedWithName": "{0} blev tilf\u00f8jet til biblioteket", - "ItemRemovedWithName": "{0} blev fjernet fra biblioteket", - "LabelIpAddressValue": "IP-adresse: {0}", - "DeviceOnlineWithName": "{0} er forbundet", - "UserOnlineFromDevice": "{0} er online fra {1}", - "ProviderValue": "Udbyder: {0}", - "SubtitlesDownloadedForItem": "Undertekster hentet til {0}", - "UserConfigurationUpdatedWithName": "Brugerkonfigurationen for {0} er blevet opdateret", - "UserCreatedWithName": "Bruger {0} er skabt", - "UserPasswordChangedWithName": "Adgangskoden for {0} er blevet \u00e6ndret", - "UserDeletedWithName": "Bruger {0} er slettet", - "MessageServerConfigurationUpdated": "Serverkonfigurationen er opdateret", - "MessageNamedServerConfigurationUpdatedWithValue": "Serverkonfiguration sektion {0} er opdateret", - "MessageApplicationUpdated": "Emby er blevet opdateret", - "FailedLoginAttemptWithUserName": "Fejlslagent loginfors\u00f8g fra {0}", - "AuthenticationSucceededWithUserName": "{0} autentificeret", - "DeviceOfflineWithName": "{0} har afbrudt forbindelsen", - "UserLockedOutWithName": "Bruger {0} er blevet l\u00e5st", - "UserOfflineFromDevice": "{0} har afbrudt forbindelsen fra {1}", - "UserStartedPlayingItemWithValues": "{0} afspiller {1}", - "UserStoppedPlayingItemWithValues": "{0} har stoppet afpilningen af {1}", - "SubtitleDownloadFailureForItem": "Hentning af undertekster til {0} fejlede", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "Bruger", - "HeaderName": "Navn", - "HeaderDate": "Dato", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Udgivelsesdato", - "HeaderRuntime": "Varighed", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "S\u00e6son", - "HeaderSeasonNumber": "S\u00e6sonnummer", - "HeaderSeries": "Series:", - "HeaderNetwork": "Netv\u00e6rk", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "F\u00e6llesskabsvurdering", - "HeaderTrailers": "Trailere", - "HeaderSpecials": "S\u00e6rudsendelser", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disk", - "HeaderTrack": "Spor", - "HeaderAudio": "Lyd", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Indlejret billede", - "HeaderResolution": "Opl\u00f8sning", - "HeaderSubtitles": "Undertekster", - "HeaderGenres": "Genrer", - "HeaderCountries": "Lande", - "HeaderStatus": "Status", - "HeaderTracks": "Spor", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studier", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Aldersgr\u00e6nser", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/de.json b/MediaBrowser.Server.Implementations/Localization/Core/de.json deleted file mode 100644 index 30e3d9215e..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/de.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Bitte warten Sie w\u00e4hrend die Emby Datenbank aktualisiert wird. {0}% verarbeitet.", - "AppDeviceValues": "App: {0}, Ger\u00e4t: {1}", - "UserDownloadingItemWithValues": "{0} l\u00e4dt {1} herunter", - "FolderTypeMixed": "Gemischte Inhalte", - "FolderTypeMovies": "Filme", - "FolderTypeMusic": "Musik", - "FolderTypeAdultVideos": "Videos f\u00fcr Erwachsene", - "FolderTypePhotos": "Fotos", - "FolderTypeMusicVideos": "Musikvideos", - "FolderTypeHomeVideos": "Heimvideos", - "FolderTypeGames": "Spiele", - "FolderTypeBooks": "B\u00fccher", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "\u00dcbernehmen", - "HeaderCastCrew": "Besetzung & Crew", - "HeaderPeople": "Personen", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Kapitel {0}", - "NameSeasonNumber": "Staffel {0}", - "LabelExit": "Beenden", - "LabelVisitCommunity": "Besuche die Community", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Dokumentation", - "LabelDeveloperResources": "Entwickler Ressourcen", - "LabelBrowseLibrary": "Bibliothek durchsuchen", - "LabelConfigureServer": "Konfiguriere Emby", - "LabelRestartServer": "Server neustarten", - "CategorySync": "Sync", - "CategoryUser": "Benutzer", - "CategorySystem": "System", - "CategoryApplication": "Anwendung", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin Fehler", - "NotificationOptionApplicationUpdateAvailable": "Anwendungsaktualisierung verf\u00fcgbar", - "NotificationOptionApplicationUpdateInstalled": "Anwendungsaktualisierung installiert", - "NotificationOptionPluginUpdateInstalled": "Pluginaktualisierung installiert", - "NotificationOptionPluginInstalled": "Plugin installiert", - "NotificationOptionPluginUninstalled": "Plugin deinstalliert", - "NotificationOptionVideoPlayback": "Videowiedergabe gestartet", - "NotificationOptionAudioPlayback": "Audiowiedergabe gestartet", - "NotificationOptionGamePlayback": "Spielwiedergabe gestartet", - "NotificationOptionVideoPlaybackStopped": "Videowiedergabe gestoppt", - "NotificationOptionAudioPlaybackStopped": "Audiowiedergabe gestoppt", - "NotificationOptionGamePlaybackStopped": "Spielwiedergabe gestoppt", - "NotificationOptionTaskFailed": "Fehler bei geplanter Aufgabe", - "NotificationOptionInstallationFailed": "Installationsfehler", - "NotificationOptionNewLibraryContent": "Neuer Inhalt hinzugef\u00fcgt", - "NotificationOptionNewLibraryContentMultiple": "Neuen Inhalte hinzugef\u00fcgt (mehrere)", - "NotificationOptionCameraImageUploaded": "Kamera Bild hochgeladen", - "NotificationOptionUserLockedOut": "Benutzer ausgeschlossen", - "NotificationOptionServerRestartRequired": "Serverneustart notwendig", - "ViewTypePlaylists": "Wiedergabelisten", - "ViewTypeMovies": "Filme", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Spiele", - "ViewTypeMusic": "Musik", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "K\u00fcnstler", - "ViewTypeBoxSets": "Sammlungen", - "ViewTypeChannels": "Kan\u00e4le", - "ViewTypeLiveTV": "Live-TV", - "ViewTypeLiveTvNowPlaying": "Gerade ausgestrahlt", - "ViewTypeLatestGames": "Neueste Spiele", - "ViewTypeRecentlyPlayedGames": "K\u00fcrzlich abgespielt", - "ViewTypeGameFavorites": "Favoriten", - "ViewTypeGameSystems": "Spielesysteme", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Fortsetzen", - "ViewTypeTvNextUp": "Als n\u00e4chstes", - "ViewTypeTvLatest": "Neueste", - "ViewTypeTvShowSeries": "Serien", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Serien Favoriten", - "ViewTypeTvFavoriteEpisodes": "Episoden Favoriten", - "ViewTypeMovieResume": "Fortsetzen", - "ViewTypeMovieLatest": "Neueste", - "ViewTypeMovieMovies": "Filme", - "ViewTypeMovieCollections": "Sammlungen", - "ViewTypeMovieFavorites": "Favoriten", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Neueste", - "ViewTypeMusicPlaylists": "Wiedergabelisten", - "ViewTypeMusicAlbums": "Alben", - "ViewTypeMusicAlbumArtists": "Album-K\u00fcnstler", - "HeaderOtherDisplaySettings": "Anzeige Einstellungen", - "ViewTypeMusicSongs": "Lieder", - "ViewTypeMusicFavorites": "Favoriten", - "ViewTypeMusicFavoriteAlbums": "Album Favoriten", - "ViewTypeMusicFavoriteArtists": "Interpreten Favoriten", - "ViewTypeMusicFavoriteSongs": "Lieder Favoriten", - "ViewTypeFolders": "Verzeichnisse", - "ViewTypeLiveTvRecordingGroups": "Aufnahmen", - "ViewTypeLiveTvChannels": "Kan\u00e4le", - "ScheduledTaskFailedWithName": "{0} fehlgeschlagen", - "LabelRunningTimeValue": "Laufzeit: {0}", - "ScheduledTaskStartedWithName": "{0} gestartet", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} wurde installiert", - "PluginUpdatedWithName": "{0} wurde aktualisiert", - "PluginUninstalledWithName": "{0} wurde deinstalliert", - "ItemAddedWithName": "{0} wurde der Bibliothek hinzugef\u00fcgt", - "ItemRemovedWithName": "{0} wurde aus der Bibliothek entfernt", - "LabelIpAddressValue": "IP Adresse: {0}", - "DeviceOnlineWithName": "{0} ist verbunden", - "UserOnlineFromDevice": "{0} ist online von {1}", - "ProviderValue": "Anbieter: {0}", - "SubtitlesDownloadedForItem": "Untertitel heruntergeladen f\u00fcr {0}", - "UserConfigurationUpdatedWithName": "Benutzereinstellungen wurden aktualisiert f\u00fcr {0}", - "UserCreatedWithName": "Benutzer {0} wurde erstellt", - "UserPasswordChangedWithName": "Das Passwort f\u00fcr Benutzer {0} wurde ge\u00e4ndert", - "UserDeletedWithName": "Benutzer {0} wurde gel\u00f6scht", - "MessageServerConfigurationUpdated": "Server Einstellungen wurden aktualisiert", - "MessageNamedServerConfigurationUpdatedWithValue": "Der Server Einstellungsbereich {0} wurde aktualisiert", - "MessageApplicationUpdated": "Emby Server wurde auf den neusten Stand gebracht.", - "FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}", - "AuthenticationSucceededWithUserName": "{0} erfolgreich authentifiziert", - "DeviceOfflineWithName": "{0} wurde getrennt", - "UserLockedOutWithName": "Benutzer {0} wurde ausgeschlossen", - "UserOfflineFromDevice": "{0} wurde getrennt von {1}", - "UserStartedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} gestartet", - "UserStoppedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} beendet", - "SubtitleDownloadFailureForItem": "Download der Untertitel fehlgeschlagen f\u00fcr {0}", - "HeaderUnidentified": "Nicht identifiziert", - "HeaderImagePrimary": "Bevorzugt", - "HeaderImageBackdrop": "Hintergrund", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "Benutzerbild", - "HeaderOverview": "\u00dcbersicht", - "HeaderShortOverview": "Kurz\u00fcbersicht", - "HeaderType": "Typ", - "HeaderSeverity": "Schwere", - "HeaderUser": "Benutzer", - "HeaderName": "Name", - "HeaderDate": "Datum", - "HeaderPremiereDate": "Premiere Datum", - "HeaderDateAdded": "Datum hinzugef\u00fcgt", - "HeaderReleaseDate": "Ver\u00f6ffentlichungsdatum", - "HeaderRuntime": "Laufzeit", - "HeaderPlayCount": "Anzahl Wiedergaben", - "HeaderSeason": "Staffel", - "HeaderSeasonNumber": "Staffel Nummer", - "HeaderSeries": "Serien:", - "HeaderNetwork": "Netzwerk", - "HeaderYear": "Jahr:", - "HeaderYears": "Jahre:", - "HeaderParentalRating": "Altersfreigabe", - "HeaderCommunityRating": "Community Bewertung", - "HeaderTrailers": "Trailer", - "HeaderSpecials": "Extras", - "HeaderGameSystems": "Spiele Systeme", - "HeaderPlayers": "Spieler:", - "HeaderAlbumArtists": "Album K\u00fcnstler", - "HeaderAlbums": "Alben", - "HeaderDisc": "Disc", - "HeaderTrack": "St\u00fcck", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Integriertes Bild", - "HeaderResolution": "Aufl\u00f6sung", - "HeaderSubtitles": "Untertitel", - "HeaderGenres": "Genres", - "HeaderCountries": "L\u00e4nder", - "HeaderStatus": "Status", - "HeaderTracks": "Lieder", - "HeaderMusicArtist": "Musik K\u00fcnstler", - "HeaderLocked": "Blockiert", - "HeaderStudios": "Studios", - "HeaderActor": "Schauspieler", - "HeaderComposer": "Komponierer", - "HeaderDirector": "Regie", - "HeaderGuestStar": "Gaststar", - "HeaderProducer": "Produzenten", - "HeaderWriter": "Autoren", - "HeaderParentalRatings": "Altersbeschr\u00e4nkung", - "HeaderCommunityRatings": "Community Bewertungen", - "StartupEmbyServerIsLoading": "Emby Server startet, bitte versuchen Sie es gleich noch einmal." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/el.json b/MediaBrowser.Server.Implementations/Localization/Core/el.json deleted file mode 100644 index 9e2d321cc4..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/el.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "\u0391\u03bd\u03ac\u03bc\u03b5\u03b9\u03ba\u03c4\u03bf \u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03bf", - "FolderTypeMovies": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2", - "FolderTypeMusic": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae", - "FolderTypeAdultVideos": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2 \u0395\u03bd\u03b7\u03bb\u03af\u03ba\u03c9\u03bd", - "FolderTypePhotos": "\u03a6\u03c9\u03c4\u03bf\u03b3\u03c1\u03b1\u03c6\u03af\u03b5\u03c2", - "FolderTypeMusicVideos": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ac \u0392\u03af\u03bd\u03c4\u03b5\u03bf", - "FolderTypeHomeVideos": "\u03a0\u03c1\u03bf\u03c3\u03c9\u03c0\u03b9\u03ba\u03ac \u0392\u03af\u03bd\u03c4\u03b5\u03bf", - "FolderTypeGames": "\u03a0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9\u03b1", - "FolderTypeBooks": "\u0392\u03b9\u03b2\u03bb\u03af\u03b1", - "FolderTypeTvShows": "\u03a4\u03b7\u03bb\u03b5\u03cc\u03c1\u03b1\u03c3\u03b7", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "\u0397\u03b8\u03bf\u03c0\u03bf\u03b9\u03bf\u03af \u03ba\u03b1\u03b9 \u03c3\u03c5\u03bd\u03b5\u03c1\u03b3\u03b5\u03af\u03bf", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "\u0388\u03be\u03bf\u03b4\u03bf\u03c2", - "LabelVisitCommunity": "\u039a\u03bf\u03b9\u03bd\u03cc\u03c4\u03b7\u03c4\u03b1", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "\u03a0\u03b7\u03b3\u03ad\u03c2 \u03a0\u03c1\u03bf\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03b9\u03c3\u03c4\u03ae", - "LabelBrowseLibrary": "\u03a0\u03b5\u03c1\u03b9\u03b7\u03b3\u03b7\u03b8\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03b7 \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7", - "LabelConfigureServer": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 Emby", - "LabelRestartServer": "\u0395\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03b4\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae", - "CategorySync": "\u03a3\u03c5\u03c7\u03c1\u03bf\u03bd\u03b9\u03c3\u03bc\u03cc\u03c2", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "\u0388\u03ba\u03b4\u03bf\u03c3\u03b7 {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "\u0389\u03c7\u03bf\u03c2", - "HeaderVideo": "\u0392\u03af\u03bd\u03c4\u03b5\u03bf", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/en-GB.json b/MediaBrowser.Server.Implementations/Localization/Core/en-GB.json deleted file mode 100644 index 493c6c4e99..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/en-GB.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Series {0}", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New (multiple) content added", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Showing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favourites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favourite Series", - "ViewTypeTvFavoriteEpisodes": "Favourite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favourites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favourites", - "ViewTypeMusicFavoriteAlbums": "Favourite Albums", - "ViewTypeMusicFavoriteArtists": "Favourite Artists", - "ViewTypeMusicFavoriteSongs": "Favourite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/en-US.json b/MediaBrowser.Server.Implementations/Localization/Core/en-US.json deleted file mode 100644 index bc0dc236d4..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/en-US.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonUnknown": "Season Unknown", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/es-AR.json b/MediaBrowser.Server.Implementations/Localization/Core/es-AR.json deleted file mode 100644 index 0555aa9d9c..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/es-AR.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Salir", - "LabelVisitCommunity": "Visit Community", - "LabelGithub": "Github", - "LabelApiDocumentation": "Documentaci\u00f3n API", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configurar Emby", - "LabelRestartServer": "Reiniciar el servidor", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/es-MX.json b/MediaBrowser.Server.Implementations/Localization/Core/es-MX.json deleted file mode 100644 index 630c7a0379..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/es-MX.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Por favor espere mientras la base de datos de su Servidor Emby es actualizada. {0}% completo.", - "AppDeviceValues": "App: {0}, Dispositivo: {1}", - "UserDownloadingItemWithValues": "{0} esta descargando {1}", - "FolderTypeMixed": "Contenido mezclado", - "FolderTypeMovies": "Pel\u00edculas", - "FolderTypeMusic": "M\u00fasica", - "FolderTypeAdultVideos": "Videos para adultos", - "FolderTypePhotos": "Fotos", - "FolderTypeMusicVideos": "Videos musicales", - "FolderTypeHomeVideos": "Videos caseros", - "FolderTypeGames": "Juegos", - "FolderTypeBooks": "Libros", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Heredar", - "HeaderCastCrew": "Reparto y Personal", - "HeaderPeople": "Personas", - "ValueSpecialEpisodeName": "Especial: {0}", - "LabelChapterName": "Cap\u00edtulo {0}", - "NameSeasonNumber": "Temporada {0}", - "LabelExit": "Salir", - "LabelVisitCommunity": "Visitar la Comunidad", - "LabelGithub": "Github", - "LabelApiDocumentation": "Documentaci\u00f3n del API", - "LabelDeveloperResources": "Recursos para Desarrolladores", - "LabelBrowseLibrary": "Explorar Biblioteca", - "LabelConfigureServer": "Configurar Emby", - "LabelRestartServer": "Reiniciar el Servidor", - "CategorySync": "Sinc.", - "CategoryUser": "Usuario", - "CategorySystem": "Sistema", - "CategoryApplication": "Aplicaci\u00f3n", - "CategoryPlugin": "Complemento", - "NotificationOptionPluginError": "Falla de complemento", - "NotificationOptionApplicationUpdateAvailable": "Actualizaci\u00f3n de aplicaci\u00f3n disponible", - "NotificationOptionApplicationUpdateInstalled": "Actualizaci\u00f3n de aplicaci\u00f3n instalada", - "NotificationOptionPluginUpdateInstalled": "Actualizaci\u00f3n de complemento instalada", - "NotificationOptionPluginInstalled": "Complemento instalado", - "NotificationOptionPluginUninstalled": "Complemento desinstalado", - "NotificationOptionVideoPlayback": "Reproducci\u00f3n de video iniciada", - "NotificationOptionAudioPlayback": "Reproducci\u00f3n de audio iniciada", - "NotificationOptionGamePlayback": "Ejecuci\u00f3n de juego iniciada", - "NotificationOptionVideoPlaybackStopped": "Reproducci\u00f3n de video detenida", - "NotificationOptionAudioPlaybackStopped": "Reproducci\u00f3n de audio detenida", - "NotificationOptionGamePlaybackStopped": "Ejecuci\u00f3n de juego detenida", - "NotificationOptionTaskFailed": "Falla de tarea programada", - "NotificationOptionInstallationFailed": "Falla de instalaci\u00f3n", - "NotificationOptionNewLibraryContent": "Nuevo contenido agregado", - "NotificationOptionNewLibraryContentMultiple": "Nuevo contenido agregado (varios)", - "NotificationOptionCameraImageUploaded": "Imagen de la c\u00e1mara subida", - "NotificationOptionUserLockedOut": "Usuario bloqueado", - "NotificationOptionServerRestartRequired": "Reinicio del servidor requerido", - "ViewTypePlaylists": "Listas de Reproducci\u00f3n", - "ViewTypeMovies": "Pel\u00edculas", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Juegos", - "ViewTypeMusic": "M\u00fasica", - "ViewTypeMusicGenres": "G\u00e9neros", - "ViewTypeMusicArtists": "Artistas", - "ViewTypeBoxSets": "Colecciones", - "ViewTypeChannels": "Canales", - "ViewTypeLiveTV": "TV en Vivo", - "ViewTypeLiveTvNowPlaying": "Transmiti\u00e9ndose", - "ViewTypeLatestGames": "Juegos Recientes", - "ViewTypeRecentlyPlayedGames": "Reproducido Reci\u00e9ntemente", - "ViewTypeGameFavorites": "Favoritos", - "ViewTypeGameSystems": "Sistemas de Juego", - "ViewTypeGameGenres": "G\u00e9neros", - "ViewTypeTvResume": "Continuar", - "ViewTypeTvNextUp": "A Continuaci\u00f3n", - "ViewTypeTvLatest": "Recientes", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "G\u00e9neros", - "ViewTypeTvFavoriteSeries": "Series Favoritas", - "ViewTypeTvFavoriteEpisodes": "Episodios Favoritos", - "ViewTypeMovieResume": "Continuar", - "ViewTypeMovieLatest": "Recientes", - "ViewTypeMovieMovies": "Pel\u00edculas", - "ViewTypeMovieCollections": "Colecciones", - "ViewTypeMovieFavorites": "Favoritos", - "ViewTypeMovieGenres": "G\u00e9neros", - "ViewTypeMusicLatest": "Recientes", - "ViewTypeMusicPlaylists": "Listas", - "ViewTypeMusicAlbums": "\u00c1lbumes", - "ViewTypeMusicAlbumArtists": "Artistas del \u00c1lbum", - "HeaderOtherDisplaySettings": "Configuraci\u00f3n de Pantalla", - "ViewTypeMusicSongs": "Canciones", - "ViewTypeMusicFavorites": "Favoritos", - "ViewTypeMusicFavoriteAlbums": "\u00c1lbumes Favoritos", - "ViewTypeMusicFavoriteArtists": "Artistas Favoritos", - "ViewTypeMusicFavoriteSongs": "Canciones Favoritas", - "ViewTypeFolders": "Carpetas", - "ViewTypeLiveTvRecordingGroups": "Grabaciones", - "ViewTypeLiveTvChannels": "Canales", - "ScheduledTaskFailedWithName": "{0} fall\u00f3", - "LabelRunningTimeValue": "Duraci\u00f3n: {0}", - "ScheduledTaskStartedWithName": "{0} Iniciado", - "VersionNumber": "Versi\u00f3n {0}", - "PluginInstalledWithName": "{0} fue instalado", - "PluginUpdatedWithName": "{0} fue actualizado", - "PluginUninstalledWithName": "{0} fue desinstalado", - "ItemAddedWithName": "{0} fue agregado a la biblioteca", - "ItemRemovedWithName": "{0} fue removido de la biblioteca", - "LabelIpAddressValue": "Direcci\u00f3n IP: {0}", - "DeviceOnlineWithName": "{0} est\u00e1 conectado", - "UserOnlineFromDevice": "{0} est\u00e1 en l\u00ednea desde {1}", - "ProviderValue": "Proveedor: {0}", - "SubtitlesDownloadedForItem": "Subt\u00edtulos descargados para {0}", - "UserConfigurationUpdatedWithName": "Se ha actualizado la configuraci\u00f3n del usuario {0}", - "UserCreatedWithName": "Se ha creado el usuario {0}", - "UserPasswordChangedWithName": "Se ha cambiado la contrase\u00f1a para el usuario {0}", - "UserDeletedWithName": "Se ha eliminado al usuario {0}", - "MessageServerConfigurationUpdated": "Se ha actualizado la configuraci\u00f3n del servidor", - "MessageNamedServerConfigurationUpdatedWithValue": "Se ha actualizado la secci\u00f3n {0} de la configuraci\u00f3n del servidor", - "MessageApplicationUpdated": "El servidor Emby ha sido actualizado", - "FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesi\u00f3n de {0}", - "AuthenticationSucceededWithUserName": "{0} autenticado con \u00e9xito", - "DeviceOfflineWithName": "{0} se ha desconectado", - "UserLockedOutWithName": "El usuario {0} ha sido bloqueado", - "UserOfflineFromDevice": "{0} se ha desconectado desde {1}", - "UserStartedPlayingItemWithValues": "{0} ha iniciado la reproducci\u00f3n de {1}", - "UserStoppedPlayingItemWithValues": "{0} ha detenido la reproducci\u00f3n de {1}", - "SubtitleDownloadFailureForItem": "Fall\u00f3 la descarga de subt\u00edtulos para {0}", - "HeaderUnidentified": "No Identificado", - "HeaderImagePrimary": "Principal", - "HeaderImageBackdrop": "Imagen de Fondo", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "Imagen de Usuario", - "HeaderOverview": "Resumen", - "HeaderShortOverview": "Sinopsis corta:", - "HeaderType": "Tipo", - "HeaderSeverity": "Severidad", - "HeaderUser": "Usuario", - "HeaderName": "Nombre", - "HeaderDate": "Fecha", - "HeaderPremiereDate": "Fecha de Estreno", - "HeaderDateAdded": "Fecha de Adici\u00f3n", - "HeaderReleaseDate": "Fecha de estreno", - "HeaderRuntime": "Duraci\u00f3n", - "HeaderPlayCount": "Contador", - "HeaderSeason": "Temporada", - "HeaderSeasonNumber": "N\u00famero de temporada", - "HeaderSeries": "Series:", - "HeaderNetwork": "Cadena", - "HeaderYear": "A\u00f1o:", - "HeaderYears": "A\u00f1os:", - "HeaderParentalRating": "Clasificaci\u00f3n Parental", - "HeaderCommunityRating": "Calificaci\u00f3n de la comunidad", - "HeaderTrailers": "Tr\u00e1ilers", - "HeaderSpecials": "Especiales", - "HeaderGameSystems": "Sistemas de Juego", - "HeaderPlayers": "Reproductores:", - "HeaderAlbumArtists": "Artistas del \u00c1lbum", - "HeaderAlbums": "\u00c1lbumes", - "HeaderDisc": "Disco", - "HeaderTrack": "Pista", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Im\u00e1gen embebida", - "HeaderResolution": "Resoluci\u00f3n", - "HeaderSubtitles": "Subt\u00edtulos", - "HeaderGenres": "G\u00e9neros", - "HeaderCountries": "Pa\u00edses", - "HeaderStatus": "Estado", - "HeaderTracks": "Pistas", - "HeaderMusicArtist": "Int\u00e9rprete", - "HeaderLocked": "Bloqueado", - "HeaderStudios": "Estudios", - "HeaderActor": "Actores", - "HeaderComposer": "Compositores", - "HeaderDirector": "Directores", - "HeaderGuestStar": "Estrella invitada", - "HeaderProducer": "Productores", - "HeaderWriter": "Guionistas", - "HeaderParentalRatings": "Clasificaci\u00f3n Parental", - "HeaderCommunityRatings": "Clasificaciones de la comunidad", - "StartupEmbyServerIsLoading": "El servidor Emby esta cargando. Por favor intente de nuevo dentro de poco." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/es.json b/MediaBrowser.Server.Implementations/Localization/Core/es.json deleted file mode 100644 index d1a56240dd..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/es.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Por favor espere mientras la base de datos de su servidor Emby se actualiza. {0}% completado.", - "AppDeviceValues": "Aplicaci\u00f3n: {0}, Dispositivo: {1}", - "UserDownloadingItemWithValues": "{0} est\u00e1 descargando {1}", - "FolderTypeMixed": "Contenido mezclado", - "FolderTypeMovies": "Peliculas", - "FolderTypeMusic": "Musica", - "FolderTypeAdultVideos": "Videos para adultos", - "FolderTypePhotos": "Fotos", - "FolderTypeMusicVideos": "Videos Musicales", - "FolderTypeHomeVideos": "Videos caseros", - "FolderTypeGames": "Juegos", - "FolderTypeBooks": "Libros", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Heredado", - "HeaderCastCrew": "Reparto y equipo t\u00e9cnico", - "HeaderPeople": "Gente", - "ValueSpecialEpisodeName": "Especial - {0}", - "LabelChapterName": "Cap\u00edtulo {0}", - "NameSeasonNumber": "Temporada {0}", - "LabelExit": "Salir", - "LabelVisitCommunity": "Visitar la comunidad", - "LabelGithub": "Github", - "LabelApiDocumentation": "Documentaci\u00f3n API", - "LabelDeveloperResources": "Recursos del Desarrollador", - "LabelBrowseLibrary": "Navegar biblioteca", - "LabelConfigureServer": "Configurar Emby", - "LabelRestartServer": "Reiniciar el servidor", - "CategorySync": "Sincronizar", - "CategoryUser": "Usuario", - "CategorySystem": "Sistema", - "CategoryApplication": "Aplicaci\u00f3n", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Error en plugin", - "NotificationOptionApplicationUpdateAvailable": "Disponible actualizaci\u00f3n de la aplicaci\u00f3n", - "NotificationOptionApplicationUpdateInstalled": "Se ha instalado la actualizaci\u00f3n de la aplicaci\u00f3n", - "NotificationOptionPluginUpdateInstalled": "Se ha instalado la actualizaci\u00f3n del plugin", - "NotificationOptionPluginInstalled": "Plugin instalado", - "NotificationOptionPluginUninstalled": "Plugin desinstalado", - "NotificationOptionVideoPlayback": "Reproduccion de video a iniciado", - "NotificationOptionAudioPlayback": "Reproduccion de audio a iniciado", - "NotificationOptionGamePlayback": "Reproduccion de video juego a iniciado", - "NotificationOptionVideoPlaybackStopped": "Reproducci\u00f3n de video detenida", - "NotificationOptionAudioPlaybackStopped": "Reproducci\u00f3n de audio detenida", - "NotificationOptionGamePlaybackStopped": "Reproducci\u00f3n de juego detenida", - "NotificationOptionTaskFailed": "La tarea programada ha fallado", - "NotificationOptionInstallationFailed": "Fallo en la instalaci\u00f3n", - "NotificationOptionNewLibraryContent": "Nuevo contenido a\u00f1adido", - "NotificationOptionNewLibraryContentMultiple": "Nuevo contenido a\u00f1adido (multiple)", - "NotificationOptionCameraImageUploaded": "Imagen de camara se a carcado", - "NotificationOptionUserLockedOut": "Usuario bloqueado", - "NotificationOptionServerRestartRequired": "Se requiere el reinicio del servidor", - "ViewTypePlaylists": "Listas de reproducci\u00f3n", - "ViewTypeMovies": "Pel\u00edculas", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Juegos", - "ViewTypeMusic": "M\u00fasica", - "ViewTypeMusicGenres": "G\u00e9neros", - "ViewTypeMusicArtists": "Artistas", - "ViewTypeBoxSets": "Colecciones", - "ViewTypeChannels": "Canales", - "ViewTypeLiveTV": "Tv en vivo", - "ViewTypeLiveTvNowPlaying": "Transmiti\u00e9ndose ahora", - "ViewTypeLatestGames": "\u00daltimos juegos", - "ViewTypeRecentlyPlayedGames": "Reproducido recientemente", - "ViewTypeGameFavorites": "Favoritos", - "ViewTypeGameSystems": "Sistemas de juego", - "ViewTypeGameGenres": "G\u00e9neros", - "ViewTypeTvResume": "Reanudar", - "ViewTypeTvNextUp": "Pr\u00f3ximamente", - "ViewTypeTvLatest": "\u00daltimas", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "G\u00e9neros", - "ViewTypeTvFavoriteSeries": "Series favoritas", - "ViewTypeTvFavoriteEpisodes": "Episodios favoritos", - "ViewTypeMovieResume": "Reanudar", - "ViewTypeMovieLatest": "\u00daltimas", - "ViewTypeMovieMovies": "Pel\u00edculas", - "ViewTypeMovieCollections": "Colecciones", - "ViewTypeMovieFavorites": "Favoritos", - "ViewTypeMovieGenres": "G\u00e9neros", - "ViewTypeMusicLatest": "\u00daltimas", - "ViewTypeMusicPlaylists": "Lista", - "ViewTypeMusicAlbums": "\u00c1lbumes", - "ViewTypeMusicAlbumArtists": "\u00c1lbumes de artistas", - "HeaderOtherDisplaySettings": "Configuraci\u00f3n de pantalla", - "ViewTypeMusicSongs": "Canciones", - "ViewTypeMusicFavorites": "Favoritos", - "ViewTypeMusicFavoriteAlbums": "\u00c1lbumes favoritos", - "ViewTypeMusicFavoriteArtists": "Artistas favoritos", - "ViewTypeMusicFavoriteSongs": "Canciones favoritas", - "ViewTypeFolders": "Carpetas", - "ViewTypeLiveTvRecordingGroups": "Grabaciones", - "ViewTypeLiveTvChannels": "Canales", - "ScheduledTaskFailedWithName": "{0} fall\u00f3", - "LabelRunningTimeValue": "Tiempo de ejecuci\u00f3n: {0}", - "ScheduledTaskStartedWithName": "{0} iniciado", - "VersionNumber": "Versi\u00f3n {0}", - "PluginInstalledWithName": "{0} ha sido instalado", - "PluginUpdatedWithName": "{0} ha sido actualizado", - "PluginUninstalledWithName": "{0} ha sido desinstalado", - "ItemAddedWithName": "{0} ha sido a\u00f1adido a la biblioteca", - "ItemRemovedWithName": "{0} se ha eliminado de la biblioteca", - "LabelIpAddressValue": "Direcci\u00f3n IP: {0}", - "DeviceOnlineWithName": "{0} est\u00e1 conectado", - "UserOnlineFromDevice": "{0} est\u00e1 conectado desde {1}", - "ProviderValue": "Proveedor: {0}", - "SubtitlesDownloadedForItem": "Subt\u00edtulos descargados para {0}", - "UserConfigurationUpdatedWithName": "Se ha actualizado la configuraci\u00f3n de usuario para {0}", - "UserCreatedWithName": "Se ha creado el usuario {0}", - "UserPasswordChangedWithName": "Contrase\u00f1a cambiada al usuario {0}", - "UserDeletedWithName": "El usuario {0} ha sido eliminado", - "MessageServerConfigurationUpdated": "Se ha actualizado la configuraci\u00f3n del servidor", - "MessageNamedServerConfigurationUpdatedWithValue": "Se ha actualizado la secci\u00f3n {0} de la configuraci\u00f3n del servidor", - "MessageApplicationUpdated": "Se ha actualizado el servidor Emby", - "FailedLoginAttemptWithUserName": "Intento de inicio de sesi\u00f3n fallido desde {0}", - "AuthenticationSucceededWithUserName": "{0} se ha autenticado satisfactoriamente", - "DeviceOfflineWithName": "{0} se ha desconectado", - "UserLockedOutWithName": "El usuario {0} ha sido bloqueado", - "UserOfflineFromDevice": "{0} se ha desconectado de {1}", - "UserStartedPlayingItemWithValues": "{0} ha empezado a reproducir {1}", - "UserStoppedPlayingItemWithValues": "{0} ha parado de reproducir {1}", - "SubtitleDownloadFailureForItem": "Fallo en la descarga de subt\u00edtulos para {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "Usuario", - "HeaderName": "Nombre", - "HeaderDate": "Fecha", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subt\u00edtulos", - "HeaderGenres": "G\u00e9neros", - "HeaderCountries": "Paises", - "HeaderStatus": "Estado", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Estudios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Clasificaci\u00f3n parental", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/fi.json b/MediaBrowser.Server.Implementations/Localization/Core/fi.json deleted file mode 100644 index 20efa14067..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/fi.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Poistu", - "LabelVisitCommunity": "K\u00e4y Yhteis\u00f6ss\u00e4", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Selaa Kirjastoa", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "K\u00e4ynnist\u00e4 Palvelin uudelleen", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/fr-CA.json b/MediaBrowser.Server.Implementations/Localization/Core/fr-CA.json deleted file mode 100644 index 789817c843..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/fr-CA.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Veuillez patienter pendant que la base de donn\u00e9e de votre Serveur Emby se met \u00e0 jour. Termin\u00e9e \u00e0 {0}%.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Quitter", - "LabelVisitCommunity": "Visiter la Communaut\u00e9", - "LabelGithub": "Github", - "LabelApiDocumentation": "Documentation de l'API", - "LabelDeveloperResources": "Ressources pour d\u00e9veloppeurs", - "LabelBrowseLibrary": "Parcourir la biblioth\u00e8que", - "LabelConfigureServer": "Configurer Emby", - "LabelRestartServer": "Red\u00e9marrer le Serveur", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/fr.json b/MediaBrowser.Server.Implementations/Localization/Core/fr.json deleted file mode 100644 index 25c722989c..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/fr.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Veuillez patienter pendant que la base de donn\u00e9e de votre Emby Serveur se met \u00e0 jour. Termin\u00e9e \u00e0 {0}%.", - "AppDeviceValues": "Application : {0}, Appareil: {1}", - "UserDownloadingItemWithValues": "{0} est en train de t\u00e9l\u00e9charger {1}", - "FolderTypeMixed": "Contenus m\u00e9lang\u00e9s", - "FolderTypeMovies": "Films", - "FolderTypeMusic": "Musique", - "FolderTypeAdultVideos": "Vid\u00e9os Adultes", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Vid\u00e9os Musical", - "FolderTypeHomeVideos": "Vid\u00e9os personnelles", - "FolderTypeGames": "Jeux", - "FolderTypeBooks": "Livres", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "H\u00e9rite", - "HeaderCastCrew": "\u00c9quipe de tournage", - "HeaderPeople": "Personnes", - "ValueSpecialEpisodeName": "Sp\u00e9cial - {0}", - "LabelChapterName": "Chapitre {0}", - "NameSeasonNumber": "Saison {0}", - "LabelExit": "Quitter", - "LabelVisitCommunity": "Visiter la Communaut\u00e9", - "LabelGithub": "Github", - "LabelApiDocumentation": "Documentation de l'API", - "LabelDeveloperResources": "Ressources pour d\u00e9veloppeurs", - "LabelBrowseLibrary": "Parcourir la biblioth\u00e8que", - "LabelConfigureServer": "Configurer Emby", - "LabelRestartServer": "Red\u00e9marrer le Serveur", - "CategorySync": "Sync", - "CategoryUser": "Utilisateur", - "CategorySystem": "Syst\u00e8me", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Erreur de plugin", - "NotificationOptionApplicationUpdateAvailable": "Mise \u00e0 jour d'application disponible", - "NotificationOptionApplicationUpdateInstalled": "Mise \u00e0 jour d'application install\u00e9e", - "NotificationOptionPluginUpdateInstalled": "Mise \u00e0 jour de plugin install\u00e9e", - "NotificationOptionPluginInstalled": "Plugin install\u00e9", - "NotificationOptionPluginUninstalled": "Plugin d\u00e9sinstall\u00e9", - "NotificationOptionVideoPlayback": "Lecture vid\u00e9o d\u00e9marr\u00e9e", - "NotificationOptionAudioPlayback": "Lecture audio d\u00e9marr\u00e9e", - "NotificationOptionGamePlayback": "Lecture de jeu d\u00e9marr\u00e9e", - "NotificationOptionVideoPlaybackStopped": "Lecture vid\u00e9o arr\u00eat\u00e9e", - "NotificationOptionAudioPlaybackStopped": "Lecture audio arr\u00eat\u00e9e", - "NotificationOptionGamePlaybackStopped": "Lecture de jeu arr\u00eat\u00e9e", - "NotificationOptionTaskFailed": "\u00c9chec de t\u00e2che planifi\u00e9e", - "NotificationOptionInstallationFailed": "\u00c9chec d'installation", - "NotificationOptionNewLibraryContent": "Nouveau contenu ajout\u00e9", - "NotificationOptionNewLibraryContentMultiple": "Nouveau contenu ajout\u00e9 (multiple)", - "NotificationOptionCameraImageUploaded": "L'image de l'appareil photo a \u00e9t\u00e9 upload\u00e9e", - "NotificationOptionUserLockedOut": "Utilisateur verrouill\u00e9", - "NotificationOptionServerRestartRequired": "Un red\u00e9marrage du serveur est requis", - "ViewTypePlaylists": "Listes de lecture", - "ViewTypeMovies": "Films", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Jeux", - "ViewTypeMusic": "Musique", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artistes", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Cha\u00eenes", - "ViewTypeLiveTV": "TV en direct", - "ViewTypeLiveTvNowPlaying": "En cours de diffusion", - "ViewTypeLatestGames": "Derniers jeux", - "ViewTypeRecentlyPlayedGames": "R\u00e9cemment jou\u00e9", - "ViewTypeGameFavorites": "Favoris", - "ViewTypeGameSystems": "Syst\u00e8me de jeu", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Reprise", - "ViewTypeTvNextUp": "A venir", - "ViewTypeTvLatest": "Derniers", - "ViewTypeTvShowSeries": "S\u00e9ries", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "S\u00e9ries favorites", - "ViewTypeTvFavoriteEpisodes": "Episodes favoris", - "ViewTypeMovieResume": "Reprise", - "ViewTypeMovieLatest": "Dernier", - "ViewTypeMovieMovies": "Films", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favoris", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Dernier", - "ViewTypeMusicPlaylists": "Listes de lectures", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Artiste de l'album", - "HeaderOtherDisplaySettings": "Param\u00e8tres d'affichage", - "ViewTypeMusicSongs": "Chansons", - "ViewTypeMusicFavorites": "Favoris", - "ViewTypeMusicFavoriteAlbums": "Albums favoris", - "ViewTypeMusicFavoriteArtists": "Artistes favoris", - "ViewTypeMusicFavoriteSongs": "Chansons favorites", - "ViewTypeFolders": "R\u00e9pertoires", - "ViewTypeLiveTvRecordingGroups": "Enregistrements", - "ViewTypeLiveTvChannels": "Cha\u00eenes", - "ScheduledTaskFailedWithName": "{0} a \u00e9chou\u00e9", - "LabelRunningTimeValue": "Dur\u00e9e: {0}", - "ScheduledTaskStartedWithName": "{0} a commenc\u00e9", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} a \u00e9t\u00e9 install\u00e9", - "PluginUpdatedWithName": "{0} a \u00e9t\u00e9 mis \u00e0 jour", - "PluginUninstalledWithName": "{0} a \u00e9t\u00e9 d\u00e9sinstall\u00e9", - "ItemAddedWithName": "{0} a \u00e9t\u00e9 ajout\u00e9 \u00e0 la biblioth\u00e8que", - "ItemRemovedWithName": "{0} a \u00e9t\u00e9 supprim\u00e9 de la biblioth\u00e8que", - "LabelIpAddressValue": "Adresse IP: {0}", - "DeviceOnlineWithName": "{0} est connect\u00e9", - "UserOnlineFromDevice": "{0} s'est connect\u00e9 depuis {1}", - "ProviderValue": "Fournisseur : {0}", - "SubtitlesDownloadedForItem": "Les sous-titres de {0} ont \u00e9t\u00e9 t\u00e9l\u00e9charg\u00e9s", - "UserConfigurationUpdatedWithName": "La configuration utilisateur de {0} a \u00e9t\u00e9 mise \u00e0 jour", - "UserCreatedWithName": "L'utilisateur {0} a \u00e9t\u00e9 cr\u00e9\u00e9.", - "UserPasswordChangedWithName": "Le mot de passe pour l'utilisateur {0} a \u00e9t\u00e9 modifi\u00e9.", - "UserDeletedWithName": "L'utilisateur {0} a \u00e9t\u00e9 supprim\u00e9.", - "MessageServerConfigurationUpdated": "La configuration du serveur a \u00e9t\u00e9 mise \u00e0 jour.", - "MessageNamedServerConfigurationUpdatedWithValue": "La configuration de la section {0} du serveur a \u00e9t\u00e9 mise \u00e0 jour.", - "MessageApplicationUpdated": "Le serveur Emby a \u00e9t\u00e9 mis \u00e0 jour", - "FailedLoginAttemptWithUserName": "Echec d'une tentative de connexion de {0}", - "AuthenticationSucceededWithUserName": "{0} s'est authentifi\u00e9 avec succ\u00e8s", - "DeviceOfflineWithName": "{0} s'est d\u00e9connect\u00e9", - "UserLockedOutWithName": "L'utilisateur {0} a \u00e9t\u00e9 verrouill\u00e9", - "UserOfflineFromDevice": "{0} s'est d\u00e9connect\u00e9 depuis {1}", - "UserStartedPlayingItemWithValues": "{0} vient de commencer la lecture de {1}", - "UserStoppedPlayingItemWithValues": "{0} vient d'arr\u00eater la lecture de {1}", - "SubtitleDownloadFailureForItem": "Le t\u00e9l\u00e9chargement des sous-titres pour {0} a \u00e9chou\u00e9.", - "HeaderUnidentified": "Non identifi\u00e9", - "HeaderImagePrimary": "Primaire", - "HeaderImageBackdrop": "Contexte", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "Avatar de l'utilisateur", - "HeaderOverview": "Aper\u00e7u", - "HeaderShortOverview": "Synopsys", - "HeaderType": "Type", - "HeaderSeverity": "S\u00e9v\u00e9rit\u00e9", - "HeaderUser": "Utilisateur", - "HeaderName": "Nom", - "HeaderDate": "Date", - "HeaderPremiereDate": "Date de la Premi\u00e8re", - "HeaderDateAdded": "Date d'ajout", - "HeaderReleaseDate": "Date de sortie ", - "HeaderRuntime": "Dur\u00e9e", - "HeaderPlayCount": "Nombre de lectures", - "HeaderSeason": "Saison", - "HeaderSeasonNumber": "Num\u00e9ro de saison", - "HeaderSeries": "S\u00e9ries :", - "HeaderNetwork": "R\u00e9seau", - "HeaderYear": "Ann\u00e9e :", - "HeaderYears": "Ann\u00e9es :", - "HeaderParentalRating": "Classification parentale", - "HeaderCommunityRating": "Note de la communaut\u00e9", - "HeaderTrailers": "Bandes-annonces", - "HeaderSpecials": "Episodes sp\u00e9ciaux", - "HeaderGameSystems": "Plateformes de jeu", - "HeaderPlayers": "Lecteurs :", - "HeaderAlbumArtists": "Artistes sur l'album", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disque", - "HeaderTrack": "Piste", - "HeaderAudio": "Audio", - "HeaderVideo": "Vid\u00e9o", - "HeaderEmbeddedImage": "Image int\u00e9gr\u00e9e", - "HeaderResolution": "R\u00e9solution", - "HeaderSubtitles": "Sous-titres", - "HeaderGenres": "Genres", - "HeaderCountries": "Pays", - "HeaderStatus": "\u00c9tat", - "HeaderTracks": "Pistes", - "HeaderMusicArtist": "Artiste de l'album", - "HeaderLocked": "Verrouill\u00e9", - "HeaderStudios": "Studios", - "HeaderActor": "Acteurs", - "HeaderComposer": "Compositeurs", - "HeaderDirector": "R\u00e9alisateurs", - "HeaderGuestStar": "R\u00f4le principal", - "HeaderProducer": "Producteurs", - "HeaderWriter": "Auteur(e)s", - "HeaderParentalRatings": "Note parentale", - "HeaderCommunityRatings": "Classification de la communaut\u00e9", - "StartupEmbyServerIsLoading": "Le serveur Emby est en cours de chargement. Veuillez r\u00e9essayer dans quelques instant." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/gsw.json b/MediaBrowser.Server.Implementations/Localization/Core/gsw.json deleted file mode 100644 index 88af82b7e4..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/gsw.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Verschiedeni Sache", - "FolderTypeMovies": "Film", - "FolderTypeMusic": "Musig", - "FolderTypeAdultVideos": "Erwachseni Film", - "FolderTypePhotos": "F\u00f6teli", - "FolderTypeMusicVideos": "Musigvideos", - "FolderTypeHomeVideos": "Heimvideos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "B\u00fcecher", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "erbf\u00e4hig", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Verlasse", - "LabelVisitCommunity": "Bsuech d'Community", - "LabelGithub": "Github", - "LabelApiDocumentation": "API Dokumentatione", - "LabelDeveloperResources": "Entwickler Ressurce", - "LabelBrowseLibrary": "Dursuech d'Bibliothek", - "LabelConfigureServer": "Konfigurier Emby", - "LabelRestartServer": "Server neustarte", - "CategorySync": "Synchronisierig", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/he.json b/MediaBrowser.Server.Implementations/Localization/Core/he.json deleted file mode 100644 index 137b455441..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/he.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "\u05ea\u05d5\u05db\u05df \u05de\u05e2\u05d5\u05e8\u05d1", - "FolderTypeMovies": "\u05e1\u05e8\u05d8\u05d9\u05dd", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "\u05d8\u05dc\u05d5\u05d9\u05d6\u05d9\u05d4", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "\u05e9\u05d7\u05e7\u05e0\u05d9\u05dd \u05d5\u05e6\u05d5\u05d5\u05ea", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "\u05d9\u05e6\u05d9\u05d0\u05d4", - "LabelVisitCommunity": "\u05d1\u05e7\u05e8 \u05d1\u05e7\u05d4\u05d9\u05dc\u05d4", - "LabelGithub": "Github", - "LabelApiDocumentation": "\u05ea\u05d9\u05e2\u05d5\u05d3 API", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "\u05d3\u05e4\u05d3\u05e3 \u05d1\u05e1\u05e4\u05e8\u05d9\u05d4", - "LabelConfigureServer": "\u05e7\u05d1\u05e2 \u05ea\u05e6\u05d5\u05e8\u05ea Emby", - "LabelRestartServer": "\u05d0\u05ea\u05d7\u05dc \u05d0\u05ea \u05d4\u05e9\u05e8\u05ea", - "CategorySync": "\u05e1\u05e0\u05db\u05e8\u05df", - "CategoryUser": "\u05de\u05e9\u05ea\u05de\u05e9", - "CategorySystem": "\u05de\u05e2\u05e8\u05db\u05ea", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "\u05ea\u05e7\u05dc\u05d4 \u05d1\u05ea\u05d5\u05e1\u05e3", - "NotificationOptionApplicationUpdateAvailable": "\u05e2\u05d3\u05db\u05d5\u05df \u05ea\u05d5\u05db\u05de\u05d4 \u05e7\u05d9\u05d9\u05dd", - "NotificationOptionApplicationUpdateInstalled": "\u05e2\u05d3\u05db\u05d5\u05df \u05ea\u05d5\u05db\u05e0\u05d4 \u05d4\u05d5\u05ea\u05e7\u05df", - "NotificationOptionPluginUpdateInstalled": "\u05e2\u05d3\u05db\u05d5\u05df \u05ea\u05d5\u05e1\u05e3 \u05d4\u05d5\u05ea\u05e7\u05df", - "NotificationOptionPluginInstalled": "\u05ea\u05d5\u05e1\u05e3 \u05d4\u05d5\u05ea\u05e7\u05df", - "NotificationOptionPluginUninstalled": "\u05ea\u05d5\u05e1\u05e3 \u05d4\u05d5\u05e1\u05e8", - "NotificationOptionVideoPlayback": "\u05e0\u05d2\u05d9\u05e0\u05ea \u05d5\u05d9\u05d3\u05d0\u05d5 \u05d4\u05d7\u05dc\u05d4", - "NotificationOptionAudioPlayback": "\u05e0\u05d2\u05d9\u05e0\u05ea \u05e6\u05dc\u05d9\u05dc \u05d4\u05d7\u05dc\u05d4", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "\u05e0\u05d2\u05d9\u05e0\u05ea \u05d5\u05d9\u05d3\u05d0\u05d5 \u05d4\u05d5\u05e4\u05e1\u05e7\u05d4", - "NotificationOptionAudioPlaybackStopped": "\u05e0\u05d2\u05d9\u05e0\u05ea \u05e6\u05dc\u05d9\u05dc \u05d4\u05d5\u05e4\u05e1\u05e7\u05d4", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "\u05de\u05e9\u05d9\u05de\u05d4 \u05de\u05ea\u05d5\u05d6\u05de\u05e0\u05ea \u05e0\u05db\u05e9\u05dc\u05d4", - "NotificationOptionInstallationFailed": "\u05d4\u05ea\u05e7\u05e0\u05d4 \u05e0\u05db\u05e9\u05dc\u05d4", - "NotificationOptionNewLibraryContent": "\u05ea\u05d5\u05db\u05df \u05d7\u05d3\u05e9 \u05e0\u05d5\u05e1\u05e3", - "NotificationOptionNewLibraryContentMultiple": "\u05d4\u05ea\u05d5\u05d5\u05e1\u05e4\u05d5 \u05ea\u05db\u05e0\u05d9\u05dd \u05d7\u05d3\u05e9\u05d9\u05dd", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "\u05e0\u05d3\u05e8\u05e9\u05ea \u05d4\u05e4\u05e2\u05dc\u05d4 \u05de\u05d7\u05d3\u05e9 \u05e9\u05dc \u05d4\u05e9\u05e8\u05ea", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "\u05e1\u05e8\u05d8\u05d9\u05dd", - "ViewTypeTvShows": "\u05d8\u05dc\u05d5\u05d9\u05d6\u05d9\u05d4", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "\u05e1\u05e8\u05d8\u05d9\u05dd", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "\u05d2\u05d9\u05e8\u05e1\u05d0 {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "\u05e9\u05dd", - "HeaderDate": "\u05ea\u05d0\u05e8\u05d9\u05da", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "\u05ea\u05d0\u05e8\u05d9\u05da \u05d4\u05d5\u05e1\u05e4\u05d4", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "\u05e1\u05d3\u05e8\u05d4", - "HeaderNetwork": "Network", - "HeaderYear": "\u05e9\u05e0\u05d4", - "HeaderYears": "\u05e9\u05e0\u05d9\u05dd", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "\u05de\u05e6\u05d1", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "\u05e9\u05d7\u05e7\u05e0\u05d9\u05dd", - "HeaderComposer": "\u05de\u05dc\u05d7\u05d9\u05e0\u05d9\u05dd", - "HeaderDirector": "\u05d1\u05de\u05d0\u05d9\u05dd", - "HeaderGuestStar": "\u05d0\u05de\u05df \u05d0\u05d5\u05e8\u05d7", - "HeaderProducer": "\u05de\u05e4\u05d9\u05e7\u05d9\u05dd", - "HeaderWriter": "\u05db\u05d5\u05ea\u05d1\u05d9\u05dd", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/hr.json b/MediaBrowser.Server.Implementations/Localization/Core/hr.json deleted file mode 100644 index 7a94dc32b7..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/hr.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Glumci i ekipa", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Izlaz", - "LabelVisitCommunity": "Posjeti zajednicu", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Pregledaj biblioteku", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restartiraj Server", - "CategorySync": "Sync", - "CategoryUser": "Korisnik", - "CategorySystem": "Sistem", - "CategoryApplication": "Aplikacija", - "CategoryPlugin": "Dodatak", - "NotificationOptionPluginError": "Dodatak otkazao", - "NotificationOptionApplicationUpdateAvailable": "Dostupno a\u017euriranje aplikacije", - "NotificationOptionApplicationUpdateInstalled": "Instalirano a\u017euriranje aplikacije", - "NotificationOptionPluginUpdateInstalled": "Instalirano a\u017euriranje za dodatak", - "NotificationOptionPluginInstalled": "Dodatak instaliran", - "NotificationOptionPluginUninstalled": "Dodatak uklonjen", - "NotificationOptionVideoPlayback": "Reprodukcija videa zapo\u010deta", - "NotificationOptionAudioPlayback": "Reprodukcija glazbe zapo\u010deta", - "NotificationOptionGamePlayback": "Igrica pokrenuta", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Zakazan zadatak nije izvr\u0161en", - "NotificationOptionInstallationFailed": "Instalacija nije izvr\u0161ena", - "NotificationOptionNewLibraryContent": "Novi sadr\u017eaj dodan", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Potrebno ponovo pokretanje servera", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Verzija {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Ime", - "HeaderDate": "Datum", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/hu.json b/MediaBrowser.Server.Implementations/Localization/Core/hu.json deleted file mode 100644 index 2b9d28d8c0..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/hu.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "K\u00e9rlek v\u00e1rj, m\u00edg az Emby Szerver adatb\u00e1zis friss\u00fcl. {0}% k\u00e9sz.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Vegyes tartalom", - "FolderTypeMovies": "Filmek", - "FolderTypeMusic": "Zen\u00e9k", - "FolderTypeAdultVideos": "Feln\u0151tt vide\u00f3k", - "FolderTypePhotos": "F\u00e9nyk\u00e9pek", - "FolderTypeMusicVideos": "Zenei vide\u00f3k", - "FolderTypeHomeVideos": "H\u00e1zi vide\u00f3k", - "FolderTypeGames": "J\u00e1t\u00e9kok", - "FolderTypeBooks": "K\u00f6nyvek", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Szerepl\u0151k & R\u00e9sztvev\u0151k", - "HeaderPeople": "Emberek", - "ValueSpecialEpisodeName": "K\u00fcl\u00f6nleges - {0}", - "LabelChapterName": "Fejezet {0}", - "NameSeasonNumber": "\u00c9vad {0}", - "LabelExit": "Kil\u00e9p\u00e9s", - "LabelVisitCommunity": "K\u00f6z\u00f6ss\u00e9g", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api dokument\u00e1ci\u00f3", - "LabelDeveloperResources": "Fejleszt\u0151i eszk\u00f6z\u00f6k", - "LabelBrowseLibrary": "M\u00e9diat\u00e1r tall\u00f3z\u00e1sa", - "LabelConfigureServer": "Emby konfigur\u00e1l\u00e1sa", - "LabelRestartServer": "Szerver \u00fajraindit\u00e1sa", - "CategorySync": "Sync", - "CategoryUser": "Felhaszn\u00e1l\u00f3", - "CategorySystem": "Rendszer", - "CategoryApplication": "Alkalmaz\u00e1s", - "CategoryPlugin": "B\u0151v\u00edtm\u00e9ny", - "NotificationOptionPluginError": "B\u0151v\u00edtm\u00e9ny hiba", - "NotificationOptionApplicationUpdateAvailable": "Friss\u00edt\u00e9s el\u00e9rhet\u0151", - "NotificationOptionApplicationUpdateInstalled": "Program friss\u00edt\u00e9s telep\u00edtve", - "NotificationOptionPluginUpdateInstalled": "B\u0151v\u00edtm\u00e9ny friss\u00edt\u00e9s telep\u00edtve", - "NotificationOptionPluginInstalled": "B\u0151v\u00edtm\u00e9ny telep\u00edtve", - "NotificationOptionPluginUninstalled": "B\u0151v\u00edtm\u00e9ny elt\u00e1vol\u00edtva", - "NotificationOptionVideoPlayback": "Vide\u00f3 elind\u00edtva", - "NotificationOptionAudioPlayback": "Zene elind\u00edtva", - "NotificationOptionGamePlayback": "J\u00e1t\u00e9k elind\u00edtva", - "NotificationOptionVideoPlaybackStopped": "Vide\u00f3 meg\u00e1ll\u00edtva", - "NotificationOptionAudioPlaybackStopped": "Zene meg\u00e1ll\u00edtva", - "NotificationOptionGamePlaybackStopped": "J\u00e1t\u00e9k meg\u00e1ll\u00edtva", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Telep\u00edt\u00e9si hiba", - "NotificationOptionNewLibraryContent": "\u00daj tartalom hozz\u00e1adva", - "NotificationOptionNewLibraryContentMultiple": "\u00daj tartalom hozz\u00e1adva (t\u00f6bbsz\u00f6r\u00f6s)", - "NotificationOptionCameraImageUploaded": "Kamera k\u00e9p felt\u00f6ltve", - "NotificationOptionUserLockedOut": "Felhaszn\u00e1l\u00f3 tiltva", - "NotificationOptionServerRestartRequired": "\u00dajraind\u00edt\u00e1s sz\u00fcks\u00e9ges", - "ViewTypePlaylists": "Lej\u00e1tsz\u00e1si list\u00e1k", - "ViewTypeMovies": "Filmek", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "J\u00e1t\u00e9kok", - "ViewTypeMusic": "Zene", - "ViewTypeMusicGenres": "M\u0171fajok", - "ViewTypeMusicArtists": "M\u0171v\u00e9szek", - "ViewTypeBoxSets": "Gy\u0171jtem\u00e9nyek", - "ViewTypeChannels": "Csatorn\u00e1k", - "ViewTypeLiveTV": "\u00c9l\u0151 TV", - "ViewTypeLiveTvNowPlaying": "Most J\u00e1tszott", - "ViewTypeLatestGames": "Leg\u00fajabb J\u00e1t\u00e9kok", - "ViewTypeRecentlyPlayedGames": "Legut\u00f3bb J\u00e1tszott", - "ViewTypeGameFavorites": "Kedvencek", - "ViewTypeGameSystems": "J\u00e1t\u00e9k Rendszer", - "ViewTypeGameGenres": "M\u0171fajok", - "ViewTypeTvResume": "Folytat\u00e1s", - "ViewTypeTvNextUp": "K\u00f6vetkez\u0151", - "ViewTypeTvLatest": "Leg\u00fajabb", - "ViewTypeTvShowSeries": "Sorozat", - "ViewTypeTvGenres": "M\u0171fajok", - "ViewTypeTvFavoriteSeries": "Kedvenc Sorozat", - "ViewTypeTvFavoriteEpisodes": "Kedvenc R\u00e9szek", - "ViewTypeMovieResume": "Folytat\u00e1s", - "ViewTypeMovieLatest": "Leg\u00fajabb", - "ViewTypeMovieMovies": "Filmek", - "ViewTypeMovieCollections": "Gy\u0171jtem\u00e9nyek", - "ViewTypeMovieFavorites": "Kedvencek", - "ViewTypeMovieGenres": "M\u0171fajok", - "ViewTypeMusicLatest": "Leg\u00fajabb", - "ViewTypeMusicPlaylists": "Lej\u00e1tsz\u00e1si list\u00e1k", - "ViewTypeMusicAlbums": "Albumok", - "ViewTypeMusicAlbumArtists": "Album El\u0151ad\u00f3k", - "HeaderOtherDisplaySettings": "Megjelen\u00edt\u00e9si Be\u00e1ll\u00edt\u00e1sok", - "ViewTypeMusicSongs": "Dalok", - "ViewTypeMusicFavorites": "Kedvencek", - "ViewTypeMusicFavoriteAlbums": "Kedvenc Albumok", - "ViewTypeMusicFavoriteArtists": "Kedvenc M\u0171v\u00e9szek", - "ViewTypeMusicFavoriteSongs": "Kedvenc Dalok", - "ViewTypeFolders": "K\u00f6nyvt\u00e1rak", - "ViewTypeLiveTvRecordingGroups": "Felv\u00e9telek", - "ViewTypeLiveTvChannels": "Csatorn\u00e1k", - "ScheduledTaskFailedWithName": "{0} hiba", - "LabelRunningTimeValue": "Fut\u00e1si id\u0151: {0}", - "ScheduledTaskStartedWithName": "{0} elkezdve", - "VersionNumber": "Verzi\u00f3 {0}", - "PluginInstalledWithName": "{0} telep\u00edtve", - "PluginUpdatedWithName": "{0} friss\u00edtve", - "PluginUninstalledWithName": "{0} elt\u00e1vol\u00edtva", - "ItemAddedWithName": "{0} k\u00f6nyvt\u00e1rhoz adva", - "ItemRemovedWithName": "{0} t\u00f6r\u00f6lve a k\u00f6nyvt\u00e1rb\u00f3l", - "LabelIpAddressValue": "Ip c\u00edm: {0}", - "DeviceOnlineWithName": "{0} kapcsol\u00f3dva", - "UserOnlineFromDevice": "{0} akt\u00edv err\u0151l {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Felirat let\u00f6lt\u00e9se ehhez {0}", - "UserConfigurationUpdatedWithName": "A k\u00f6vetkez\u0151 felhaszn\u00e1l\u00f3 be\u00e1ll\u00edt\u00e1sai friss\u00edtve {0}", - "UserCreatedWithName": "Felhaszn\u00e1l\u00f3 {0} l\u00e9trehozva", - "UserPasswordChangedWithName": "Jelsz\u00f3 m\u00f3dos\u00edtva ennek a felhaszn\u00e1l\u00f3nak {0}", - "UserDeletedWithName": "Felhaszn\u00e1l\u00f3 {0} t\u00f6r\u00f6lve", - "MessageServerConfigurationUpdated": "Szerver be\u00e1ll\u00edt\u00e1sok friss\u00edtve", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server friss\u00edtve", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} sz\u00e9tkapcsolt", - "UserLockedOutWithName": "A k\u00f6vetkez\u0151 felhaszn\u00e1l\u00f3 tiltva {0}", - "UserOfflineFromDevice": "{0} kil\u00e9pett innen {1}", - "UserStartedPlayingItemWithValues": "{0} megkezdte j\u00e1tszani a(z) {1}", - "UserStoppedPlayingItemWithValues": "{0} befejezte a(z) {1}", - "SubtitleDownloadFailureForItem": "Nem siker\u00fcl a felirat let\u00f6lt\u00e9s ehhez {0}", - "HeaderUnidentified": "Azonos\u00edtatlan", - "HeaderImagePrimary": "Els\u0151dleges", - "HeaderImageBackdrop": "H\u00e1tt\u00e9r", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "Felhaszn\u00e1l\u00f3 K\u00e9p", - "HeaderOverview": "\u00c1ttekint\u00e9s", - "HeaderShortOverview": "R\u00f6vid \u00c1ttekint\u00e9s", - "HeaderType": "T\u00edpus", - "HeaderSeverity": "Severity", - "HeaderUser": "Felhaszn\u00e1l\u00f3", - "HeaderName": "N\u00e9v", - "HeaderDate": "D\u00e1tum", - "HeaderPremiereDate": "Megjelen\u00e9s D\u00e1tuma", - "HeaderDateAdded": "Hozz\u00e1adva", - "HeaderReleaseDate": "Megjelen\u00e9s d\u00e1tuma", - "HeaderRuntime": "J\u00e1t\u00e9kid\u0151", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "\u00c9vad", - "HeaderSeasonNumber": "\u00c9vad sz\u00e1ma", - "HeaderSeries": "Sorozatok:", - "HeaderNetwork": "H\u00e1l\u00f3zat", - "HeaderYear": "\u00c9v:", - "HeaderYears": "\u00c9v:", - "HeaderParentalRating": "Korhat\u00e1r besorol\u00e1s", - "HeaderCommunityRating": "K\u00f6z\u00f6ss\u00e9gi \u00e9rt\u00e9kel\u00e9s", - "HeaderTrailers": "El\u0151zetesek", - "HeaderSpecials": "Speci\u00e1lis", - "HeaderGameSystems": "J\u00e1t\u00e9k Rendszer", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albumok", - "HeaderDisc": "Lemez", - "HeaderTrack": "S\u00e1v", - "HeaderAudio": "Audi\u00f3", - "HeaderVideo": "Vide\u00f3", - "HeaderEmbeddedImage": "Be\u00e1gyazott k\u00e9p", - "HeaderResolution": "Felbont\u00e1s", - "HeaderSubtitles": "Feliratok", - "HeaderGenres": "M\u0171fajok", - "HeaderCountries": "Orsz\u00e1gok", - "HeaderStatus": "\u00c1llapot", - "HeaderTracks": "S\u00e1vok", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Z\u00e1rt", - "HeaderStudios": "St\u00fadi\u00f3k", - "HeaderActor": "Sz\u00edn\u00e9szek", - "HeaderComposer": "Zeneszerz\u0151k", - "HeaderDirector": "Rendez\u0151k", - "HeaderGuestStar": "Vend\u00e9g szt\u00e1r", - "HeaderProducer": "Producerek", - "HeaderWriter": "\u00cdr\u00f3k", - "HeaderParentalRatings": "Korhat\u00e1r besorol\u00e1s", - "HeaderCommunityRatings": "K\u00f6z\u00f6ss\u00e9gi \u00e9rt\u00e9kel\u00e9sek", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/id.json b/MediaBrowser.Server.Implementations/Localization/Core/id.json deleted file mode 100644 index 8d64b63c46..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/id.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Silahkan menunggu sementara database Emby Server anda diupgrade. {0}% selesai.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Mewarisi", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Keluar", - "LabelVisitCommunity": "Kunjungi Komunitas", - "LabelGithub": "Github", - "LabelApiDocumentation": "Dokumentasi Api", - "LabelDeveloperResources": "Sumber daya Pengembang", - "LabelBrowseLibrary": "Telusuri Pustaka", - "LabelConfigureServer": "Konfigurasi Emby", - "LabelRestartServer": "Hidupkan ulang Server", - "CategorySync": "Singkron", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/it.json b/MediaBrowser.Server.Implementations/Localization/Core/it.json deleted file mode 100644 index d2d697c3ee..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/it.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Dispositivo: {1}", - "UserDownloadingItemWithValues": "{0} sta scaricando {1}", - "FolderTypeMixed": "contenuto misto", - "FolderTypeMovies": "Film", - "FolderTypeMusic": "Musica", - "FolderTypeAdultVideos": "Video per adulti", - "FolderTypePhotos": "Foto", - "FolderTypeMusicVideos": "Video musicali", - "FolderTypeHomeVideos": "Video personali", - "FolderTypeGames": "Giochi", - "FolderTypeBooks": "Libri", - "FolderTypeTvShows": "Tv", - "FolderTypeInherit": "ereditare", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "Persone", - "ValueSpecialEpisodeName": "Speciali - {0}", - "LabelChapterName": "Capitolo {0}", - "NameSeasonNumber": "Stagione {0}", - "LabelExit": "Esci", - "LabelVisitCommunity": "Visita la Community", - "LabelGithub": "Github", - "LabelApiDocumentation": "Documentazione Api", - "LabelDeveloperResources": "Risorse programmatori", - "LabelBrowseLibrary": "Esplora la libreria", - "LabelConfigureServer": "Configura Emby", - "LabelRestartServer": "Riavvia Server", - "CategorySync": "Sincronizza", - "CategoryUser": "Utente", - "CategorySystem": "Sistema", - "CategoryApplication": "Applicazione", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin fallito", - "NotificationOptionApplicationUpdateAvailable": "Aggiornamento dell'applicazione disponibile", - "NotificationOptionApplicationUpdateInstalled": "Aggiornamento dell'applicazione installato", - "NotificationOptionPluginUpdateInstalled": "Aggiornamento del plugin installato", - "NotificationOptionPluginInstalled": "Plugin installato", - "NotificationOptionPluginUninstalled": "Plugin disinstallato", - "NotificationOptionVideoPlayback": "La riproduzione video \u00e8 iniziata", - "NotificationOptionAudioPlayback": "Riproduzione audio iniziata", - "NotificationOptionGamePlayback": "Gioco avviato", - "NotificationOptionVideoPlaybackStopped": "Riproduzione video interrotta", - "NotificationOptionAudioPlaybackStopped": "Audio Fermato", - "NotificationOptionGamePlaybackStopped": "Gioco Fermato", - "NotificationOptionTaskFailed": "Operazione pianificata fallita", - "NotificationOptionInstallationFailed": "Installazione fallita", - "NotificationOptionNewLibraryContent": "Nuovo contenuto aggiunto", - "NotificationOptionNewLibraryContentMultiple": "Nuovi contenuti aggiunti (multipli)", - "NotificationOptionCameraImageUploaded": "Immagine fotocamera caricata", - "NotificationOptionUserLockedOut": "Utente bloccato", - "NotificationOptionServerRestartRequired": "Riavvio del server necessario", - "ViewTypePlaylists": "Playlist", - "ViewTypeMovies": "Film", - "ViewTypeTvShows": "Serie Tv", - "ViewTypeGames": "Giochi", - "ViewTypeMusic": "Musica", - "ViewTypeMusicGenres": "Generi", - "ViewTypeMusicArtists": "Artisti", - "ViewTypeBoxSets": "Collezioni", - "ViewTypeChannels": "Canali", - "ViewTypeLiveTV": "TV in diretta", - "ViewTypeLiveTvNowPlaying": "Ora in onda", - "ViewTypeLatestGames": "Ultimi Giorchi", - "ViewTypeRecentlyPlayedGames": "Guardato di recente", - "ViewTypeGameFavorites": "Preferiti", - "ViewTypeGameSystems": "Configurazione gioco", - "ViewTypeGameGenres": "Generi", - "ViewTypeTvResume": "Riprendi", - "ViewTypeTvNextUp": "Prossimi", - "ViewTypeTvLatest": "Ultimi", - "ViewTypeTvShowSeries": "Serie", - "ViewTypeTvGenres": "Generi", - "ViewTypeTvFavoriteSeries": "Serie Preferite", - "ViewTypeTvFavoriteEpisodes": "Episodi Preferiti", - "ViewTypeMovieResume": "Riprendi", - "ViewTypeMovieLatest": "Ultimi", - "ViewTypeMovieMovies": "Film", - "ViewTypeMovieCollections": "Collezioni", - "ViewTypeMovieFavorites": "Preferiti", - "ViewTypeMovieGenres": "Generi", - "ViewTypeMusicLatest": "Ultimi", - "ViewTypeMusicPlaylists": "Playlist", - "ViewTypeMusicAlbums": "Album", - "ViewTypeMusicAlbumArtists": "Album Artisti", - "HeaderOtherDisplaySettings": "Impostazioni Video", - "ViewTypeMusicSongs": "Canzoni", - "ViewTypeMusicFavorites": "Preferiti", - "ViewTypeMusicFavoriteAlbums": "Album preferiti", - "ViewTypeMusicFavoriteArtists": "Artisti preferiti", - "ViewTypeMusicFavoriteSongs": "Canzoni Preferite", - "ViewTypeFolders": "Cartelle", - "ViewTypeLiveTvRecordingGroups": "Registrazioni", - "ViewTypeLiveTvChannels": "canali", - "ScheduledTaskFailedWithName": "{0} Falliti", - "LabelRunningTimeValue": "Durata: {0}", - "ScheduledTaskStartedWithName": "{0} Avviati", - "VersionNumber": "Versione {0}", - "PluginInstalledWithName": "{0} sono stati Installati", - "PluginUpdatedWithName": "{0} sono stati aggiornati", - "PluginUninstalledWithName": "{0} non sono stati installati", - "ItemAddedWithName": "{0} aggiunti alla libreria", - "ItemRemovedWithName": "{0} rimossi dalla libreria", - "LabelIpAddressValue": "Indirizzo IP: {0}", - "DeviceOnlineWithName": "{0} \u00e8 connesso", - "UserOnlineFromDevice": "{0} \u00e8 online da {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Sottotitoli scaricati per {0}", - "UserConfigurationUpdatedWithName": "Configurazione utente \u00e8 stata aggiornata per {0}", - "UserCreatedWithName": "Utente {0} \u00e8 stato creato", - "UserPasswordChangedWithName": "Password utente cambiata per {0}", - "UserDeletedWithName": "Utente {0} \u00e8 stato cancellato", - "MessageServerConfigurationUpdated": "Configurazione server aggioprnata", - "MessageNamedServerConfigurationUpdatedWithValue": "La sezione {0} \u00e8 stata aggiornata", - "MessageApplicationUpdated": "Il Server Emby \u00e8 stato aggiornato", - "FailedLoginAttemptWithUserName": "Login fallito da {0}", - "AuthenticationSucceededWithUserName": "{0} Autenticati con successo", - "DeviceOfflineWithName": "{0} \u00e8 stato disconesso", - "UserLockedOutWithName": "L'utente {0} \u00e8 stato bloccato", - "UserOfflineFromDevice": "{0} \u00e8 stato disconesso da {1}", - "UserStartedPlayingItemWithValues": "{0} \u00e8 partito da {1}", - "UserStoppedPlayingItemWithValues": "{0} stoppato {1}", - "SubtitleDownloadFailureForItem": "Sottotitoli non scaricati per {0}", - "HeaderUnidentified": "Non identificata", - "HeaderImagePrimary": "Primaria", - "HeaderImageBackdrop": "Sfondo", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "Immagine utente", - "HeaderOverview": "Panoramica", - "HeaderShortOverview": "breve panoramica", - "HeaderType": "Tipo", - "HeaderSeverity": "gravit\u00e0", - "HeaderUser": "Utente", - "HeaderName": "Nome", - "HeaderDate": "Data", - "HeaderPremiereDate": "Data della prima", - "HeaderDateAdded": "Aggiunto il", - "HeaderReleaseDate": "Data Rilascio", - "HeaderRuntime": "Durata", - "HeaderPlayCount": "Visto N\u00b0", - "HeaderSeason": "Stagione", - "HeaderSeasonNumber": "Stagione Numero", - "HeaderSeries": "Serie:", - "HeaderNetwork": "Rete", - "HeaderYear": "Anno:", - "HeaderYears": "Anni", - "HeaderParentalRating": "Valutazione parentale", - "HeaderCommunityRating": "Voto Comunit\u00e0", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Speciali", - "HeaderGameSystems": "Sistemi di gioco", - "HeaderPlayers": "Giocatori", - "HeaderAlbumArtists": "Album Artisti", - "HeaderAlbums": "Album", - "HeaderDisc": "Disco", - "HeaderTrack": "Traccia", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Immagine incorporata", - "HeaderResolution": "Risoluzione", - "HeaderSubtitles": "Sottotitoli", - "HeaderGenres": "Generi", - "HeaderCountries": "Paesi", - "HeaderStatus": "Stato", - "HeaderTracks": "Traccia", - "HeaderMusicArtist": "Musica artisti", - "HeaderLocked": "Bloccato", - "HeaderStudios": "Studios", - "HeaderActor": "Attori", - "HeaderComposer": "Compositori", - "HeaderDirector": "Registi", - "HeaderGuestStar": "Personaggi famosi", - "HeaderProducer": "Produttori", - "HeaderWriter": "Sceneggiatori", - "HeaderParentalRatings": "Valutazioni genitori", - "HeaderCommunityRatings": "Valutazione Comunity", - "StartupEmbyServerIsLoading": "Emby server si sta avviando. Riprova tra un po" -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/kk.json b/MediaBrowser.Server.Implementations/Localization/Core/kk.json deleted file mode 100644 index 93252c30b8..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/kk.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Emby Server \u0434\u0435\u0440\u0435\u043a\u049b\u043e\u0440\u044b\u04a3\u044b\u0437\u0434\u044b\u04a3 \u0436\u0430\u04a3\u0493\u044b\u0440\u0442\u044b\u043b\u0443\u044b\u043d \u043a\u04af\u0442\u0435 \u0442\u04b1\u0440\u044b\u04a3\u044b\u0437. {0} % \u0430\u044f\u049b\u0442\u0430\u043b\u0434\u044b.", - "AppDeviceValues": "\u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430: {0}, \u049a\u04b1\u0440\u044b\u043b\u0493\u044b: {1}", - "UserDownloadingItemWithValues": "{0} \u043c\u044b\u043d\u0430\u043d\u044b \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443\u0434\u0430: {1}", - "FolderTypeMixed": "\u0410\u0440\u0430\u043b\u0430\u0441 \u043c\u0430\u0437\u043c\u04b1\u043d", - "FolderTypeMovies": "\u041a\u0438\u043d\u043e", - "FolderTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430", - "FolderTypeAdultVideos": "\u0415\u0440\u0435\u0441\u0435\u043a\u0442\u0456\u043a \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440", - "FolderTypePhotos": "\u0424\u043e\u0442\u043e\u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440", - "FolderTypeMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044b\u049b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440", - "FolderTypeHomeVideos": "\u04ae\u0439 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0456", - "FolderTypeGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440", - "FolderTypeBooks": "\u041a\u0456\u0442\u0430\u043f\u0442\u0430\u0440", - "FolderTypeTvShows": "\u0422\u0414", - "FolderTypeInherit": "\u041c\u04b1\u0440\u0430\u0493\u0430 \u0438\u0435\u043b\u0435\u043d\u0443", - "HeaderCastCrew": "\u0421\u043e\u043c\u0434\u0430\u0443\u0448\u044b\u043b\u0430\u0440 \u043c\u0435\u043d \u0442\u04af\u0441\u0456\u0440\u0443\u0448\u0456\u043b\u0435\u0440", - "HeaderPeople": "\u0410\u0434\u0430\u043c\u0434\u0430\u0440", - "ValueSpecialEpisodeName": "\u0410\u0440\u043d\u0430\u0439\u044b - {0}", - "LabelChapterName": "{0}-\u0441\u0430\u0445\u043d\u0430", - "NameSeasonNumber": "{0}-\u0441\u0435\u0437\u043e\u043d", - "LabelExit": "\u0428\u044b\u0493\u0443", - "LabelVisitCommunity": "\u049a\u0430\u0443\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u049b\u049b\u0430 \u0431\u0430\u0440\u0443", - "LabelGithub": "GitHub \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439\u0456", - "LabelApiDocumentation": "API \u049b\u04b1\u0436\u0430\u0442\u0442\u0430\u043c\u0430\u0441\u044b", - "LabelDeveloperResources": "\u0416\u0430\u0441\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u04e9\u0437\u0434\u0435\u0440\u0456", - "LabelBrowseLibrary": "\u0422\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430\u043d\u044b \u0448\u043e\u043b\u0443", - "LabelConfigureServer": "Emby \u0442\u0435\u04a3\u0448\u0435\u0443", - "LabelRestartServer": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u049b\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443", - "CategorySync": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443", - "CategoryUser": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b", - "CategorySystem": "\u0416\u04af\u0439\u0435", - "CategoryApplication": "\u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430", - "CategoryPlugin": "\u041f\u043b\u0430\u0433\u0438\u043d", - "NotificationOptionPluginError": "\u041f\u043b\u0430\u0433\u0438\u043d \u0441\u04d9\u0442\u0441\u0456\u0437\u0434\u0456\u0433\u0456", - "NotificationOptionApplicationUpdateAvailable": "\u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430 \u0436\u0430\u04a3\u0430\u0440\u0442\u0443\u044b \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456", - "NotificationOptionApplicationUpdateInstalled": "\u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430 \u0436\u0430\u04a3\u0430\u0440\u0442\u0443\u044b \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0434\u044b", - "NotificationOptionPluginUpdateInstalled": "\u041f\u043b\u0430\u0433\u0438\u043d \u0436\u0430\u04a3\u0430\u0440\u0442\u0443\u044b \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0434\u044b", - "NotificationOptionPluginInstalled": "\u041f\u043b\u0430\u0433\u0438\u043d \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0434\u044b", - "NotificationOptionPluginUninstalled": "\u041f\u043b\u0430\u0433\u0438\u043d \u043e\u0440\u043d\u0430\u0442\u0443\u044b \u0431\u043e\u043b\u0434\u044b\u0440\u044b\u043b\u043c\u0430\u0434\u044b", - "NotificationOptionVideoPlayback": "\u0411\u0435\u0439\u043d\u0435 \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u0431\u0430\u0441\u0442\u0430\u043b\u0434\u044b", - "NotificationOptionAudioPlayback": "\u0414\u044b\u0431\u044b\u0441 \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u0431\u0430\u0441\u0442\u0430\u043b\u0434\u044b", - "NotificationOptionGamePlayback": "\u041e\u0439\u044b\u043d \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u0431\u0430\u0441\u0442\u0430\u043b\u0434\u044b", - "NotificationOptionVideoPlaybackStopped": "\u0411\u0435\u0439\u043d\u0435 \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u0442\u043e\u049b\u0442\u0430\u0442\u044b\u043b\u0434\u044b", - "NotificationOptionAudioPlaybackStopped": "\u0414\u044b\u0431\u044b\u0441 \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u0442\u043e\u049b\u0442\u0430\u0442\u044b\u043b\u0434\u044b", - "NotificationOptionGamePlaybackStopped": "\u041e\u0439\u044b\u043d \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u0442\u043e\u049b\u0442\u0430\u0442\u044b\u043b\u0434\u044b", - "NotificationOptionTaskFailed": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0441\u04d9\u0442\u0441\u0456\u0437\u0434\u0456\u0433\u0456", - "NotificationOptionInstallationFailed": "\u041e\u0440\u043d\u0430\u0442\u0443 \u0441\u04d9\u0442\u0441\u0456\u0437\u0434\u0456\u0433\u0456", - "NotificationOptionNewLibraryContent": "\u0416\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d", - "NotificationOptionNewLibraryContentMultiple": "\u0416\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u049b\u043e\u0441\u044b\u043b\u0434\u044b (\u043a\u04e9\u043f\u0442\u0435\u0433\u0435\u043d)", - "NotificationOptionCameraImageUploaded": "\u041a\u0430\u043c\u0435\u0440\u0430\u0434\u0430\u043d \u0444\u043e\u0442\u043e\u0441\u0443\u0440\u0435\u0442 \u043a\u0435\u0440\u0456 \u049b\u043e\u0442\u0430\u0440\u044b\u043b\u0493\u0430\u043d", - "NotificationOptionUserLockedOut": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u049b\u04b1\u0440\u0441\u0430\u0443\u043b\u044b", - "NotificationOptionServerRestartRequired": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u049b\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443 \u049b\u0430\u0436\u0435\u0442", - "ViewTypePlaylists": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0434\u0435\u0440\u0456", - "ViewTypeMovies": "\u041a\u0438\u043d\u043e", - "ViewTypeTvShows": "\u0422\u0414", - "ViewTypeGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440", - "ViewTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430", - "ViewTypeMusicGenres": "\u0416\u0430\u043d\u0440\u043b\u0430\u0440", - "ViewTypeMusicArtists": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u043b\u0430\u0440", - "ViewTypeBoxSets": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u0430\u0440", - "ViewTypeChannels": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440", - "ViewTypeLiveTV": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414", - "ViewTypeLiveTvNowPlaying": "\u042d\u0444\u0438\u0440\u0434\u0435", - "ViewTypeLatestGames": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u043e\u0439\u044b\u043d\u0434\u0430\u0440", - "ViewTypeRecentlyPlayedGames": "\u0416\u0430\u049b\u044b\u043d\u0434\u0430 \u043e\u0439\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d\u0434\u0430\u0440", - "ViewTypeGameFavorites": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b\u043b\u0430\u0440", - "ViewTypeGameSystems": "\u041e\u0439\u044b\u043d \u0436\u04af\u0439\u0435\u043b\u0435\u0440\u0456", - "ViewTypeGameGenres": "\u0416\u0430\u043d\u0440\u043b\u0430\u0440", - "ViewTypeTvResume": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u043c\u0430\u043b\u044b", - "ViewTypeTvNextUp": "\u041a\u0435\u0437\u0435\u043a\u0442\u0456", - "ViewTypeTvLatest": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456", - "ViewTypeTvShowSeries": "\u0422\u0435\u043b\u0435\u0445\u0438\u043a\u0430\u044f\u043b\u0430\u0440", - "ViewTypeTvGenres": "\u0416\u0430\u043d\u0440\u043b\u0430\u0440", - "ViewTypeTvFavoriteSeries": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b \u0442\u0435\u043b\u0435\u0445\u0438\u043a\u0430\u044f\u043b\u0430\u0440", - "ViewTypeTvFavoriteEpisodes": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b \u0431\u04e9\u043b\u0456\u043c\u0434\u0435\u0440", - "ViewTypeMovieResume": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u043c\u0430\u043b\u044b", - "ViewTypeMovieLatest": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456", - "ViewTypeMovieMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440", - "ViewTypeMovieCollections": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u0430\u0440", - "ViewTypeMovieFavorites": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b\u043b\u0430\u0440", - "ViewTypeMovieGenres": "\u0416\u0430\u043d\u0440\u043b\u0430\u0440", - "ViewTypeMusicLatest": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456", - "ViewTypeMusicPlaylists": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0434\u0435\u0440\u0456", - "ViewTypeMusicAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u0434\u0430\u0440", - "ViewTypeMusicAlbumArtists": "\u0410\u043b\u044c\u0431\u043e\u043c \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u043b\u0430\u0440\u044b", - "HeaderOtherDisplaySettings": "\u0411\u0435\u0439\u043d\u0435\u043b\u0435\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456", - "ViewTypeMusicSongs": "\u04d8\u0443\u0435\u043d\u0434\u0435\u0440", - "ViewTypeMusicFavorites": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b\u043b\u0430\u0440", - "ViewTypeMusicFavoriteAlbums": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b \u0430\u043b\u044c\u0431\u043e\u043c\u0434\u0430\u0440", - "ViewTypeMusicFavoriteArtists": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u043b\u0430\u0440", - "ViewTypeMusicFavoriteSongs": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b \u04d9\u0443\u0435\u043d\u0434\u0435\u0440", - "ViewTypeFolders": "\u049a\u0430\u043b\u0442\u0430\u043b\u0430\u0440", - "ViewTypeLiveTvRecordingGroups": "\u0416\u0430\u0437\u0431\u0430\u043b\u0430\u0440", - "ViewTypeLiveTvChannels": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440", - "ScheduledTaskFailedWithName": "{0} \u0441\u04d9\u0442\u0441\u0456\u0437", - "LabelRunningTimeValue": "\u0406\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0443 \u0443\u0430\u049b\u044b\u0442\u044b: {0}", - "ScheduledTaskStartedWithName": "{0} \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0434\u044b", - "VersionNumber": "\u041d\u04b1\u0441\u049b\u0430\u0441\u044b: {0}", - "PluginInstalledWithName": "{0} \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0434\u044b", - "PluginUpdatedWithName": "{0} \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b", - "PluginUninstalledWithName": "{0} \u0436\u043e\u0439\u044b\u043b\u0434\u044b", - "ItemAddedWithName": "{0} (\u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430\u0493\u0430 \u04af\u0441\u0442\u0435\u043b\u0456\u043d\u0434\u0456)", - "ItemRemovedWithName": "{0} (\u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430\u0434\u0430\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0434\u044b)", - "LabelIpAddressValue": "IP \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439\u044b: {0}", - "DeviceOnlineWithName": "{0} \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d", - "UserOnlineFromDevice": "{0} - {1} \u0430\u0440\u049b\u044b\u043b\u044b \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d", - "ProviderValue": "\u0416\u0435\u0442\u043a\u0456\u0437\u0443\u0448\u0456: {0}", - "SubtitlesDownloadedForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 {0} \u04af\u0448\u0456\u043d \u0436\u04af\u043a\u0442\u0435\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0434\u044b", - "UserConfigurationUpdatedWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b", - "UserCreatedWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u0436\u0430\u0441\u0430\u043b\u0493\u0430\u043d", - "UserPasswordChangedWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u04af\u0448\u0456\u043d \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437 \u04e9\u0437\u0433\u0435\u0440\u0442\u0456\u043b\u0434\u0456", - "UserDeletedWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u0436\u043e\u0439\u044b\u043b\u0493\u0430\u043d", - "MessageServerConfigurationUpdated": "\u0421\u0435\u0440\u0432\u0435\u0440 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456 \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b", - "MessageNamedServerConfigurationUpdatedWithValue": "\u0421\u0435\u0440\u0432\u0435\u0440 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456 ({0} \u0431\u04e9\u043b\u0456\u043c\u0456) \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b", - "MessageApplicationUpdated": "Emby Server \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b.", - "FailedLoginAttemptWithUserName": "{0} \u043a\u0456\u0440\u0443 \u04d9\u0440\u0435\u043a\u0435\u0442\u0456 \u0441\u04d9\u0442\u0441\u0456\u0437", - "AuthenticationSucceededWithUserName": "{0} \u0442\u04af\u043f\u043d\u04b1\u0441\u049b\u0430\u043b\u044b\u0493\u044b\u043d \u0440\u0430\u0441\u0442\u0430\u043b\u0443\u044b \u0441\u04d9\u0442\u0442\u0456", - "DeviceOfflineWithName": "{0} \u0430\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0493\u0430\u043d", - "UserLockedOutWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u049b\u04b1\u0440\u0441\u0430\u0443\u043b\u044b", - "UserOfflineFromDevice": "{0} - {1} \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0493\u0430\u043d", - "UserStartedPlayingItemWithValues": "{0} - {1} \u043e\u0439\u043d\u0430\u0442\u0443\u044b\u043d \u0431\u0430\u0441\u0442\u0430\u0434\u044b", - "UserStoppedPlayingItemWithValues": "{0} - {1} \u043e\u0439\u043d\u0430\u0442\u0443\u044b\u043d \u0442\u043e\u049b\u0442\u0430\u0442\u0442\u044b", - "SubtitleDownloadFailureForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 {0} \u04af\u0448\u0456\u043d \u0436\u04af\u043a\u0442\u0435\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0443\u044b \u0441\u04d9\u0442\u0441\u0456\u0437", - "HeaderUnidentified": "\u0410\u043d\u044b\u049b\u0442\u0430\u043b\u043c\u0430\u0493\u0430\u043d", - "HeaderImagePrimary": "\u041d\u0435\u0433\u0456\u0437\u0433\u0456", - "HeaderImageBackdrop": "\u0410\u0440\u0442\u049b\u044b \u0441\u0443\u0440\u0435\u0442", - "HeaderImageLogo": "\u041b\u043e\u0433\u043e\u0442\u0438\u043f", - "HeaderUserPrimaryImage": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0441\u0443\u0440\u0435\u0442\u0456", - "HeaderOverview": "\u0416\u0430\u043b\u043f\u044b \u0448\u043e\u043b\u0443", - "HeaderShortOverview": "\u049a\u044b\u0441\u049b\u0430\u0448\u0430 \u0448\u043e\u043b\u0443", - "HeaderType": "\u0422\u04af\u0440\u0456", - "HeaderSeverity": "\u049a\u0438\u044b\u043d\u0434\u044b\u0493\u044b", - "HeaderUser": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b", - "HeaderName": "\u0410\u0442\u044b", - "HeaderDate": "\u041a\u04af\u043d\u0456", - "HeaderPremiereDate": "\u0422\u04b1\u0441\u0430\u0443\u043a\u0435\u0441\u0435\u0440 \u043a\u04af\u043d\u0456", - "HeaderDateAdded": "\u04ae\u0441\u0442\u0435\u043b\u0433\u0435\u043d \u043a\u04af\u043d\u0456", - "HeaderReleaseDate": "\u0428\u044b\u0493\u0430\u0440\u0443 \u043a\u04af\u043d\u0456", - "HeaderRuntime": "\u04b0\u0437\u0430\u049b\u0442\u044b\u0493\u044b", - "HeaderPlayCount": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0435\u0441\u0435\u0431\u0456", - "HeaderSeason": "\u041c\u0430\u0443\u0441\u044b\u043c", - "HeaderSeasonNumber": "\u041c\u0430\u0443\u0441\u044b\u043c \u043d\u04e9\u043c\u0456\u0440\u0456", - "HeaderSeries": "\u0422\u0435\u043b\u0435\u0445\u0438\u043a\u0430\u044f\u043b\u0430\u0440", - "HeaderNetwork": "\u0422\u0435\u043b\u0435\u0436\u0435\u043b\u0456", - "HeaderYear": "\u0416\u044b\u043b:", - "HeaderYears": "\u0416\u044b\u043b\u0434\u0430\u0440:", - "HeaderParentalRating": "\u0416\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u044b", - "HeaderCommunityRating": "\u049a\u0430\u0443\u044b\u043c \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b", - "HeaderTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440", - "HeaderSpecials": "\u0410\u0440\u043d\u0430\u0439\u044b \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440", - "HeaderGameSystems": "\u041e\u0439\u044b\u043d \u0436\u04af\u0439\u0435\u043b\u0435\u0440\u0456", - "HeaderPlayers": "\u041e\u0439\u044b\u043d\u0448\u044b\u043b\u0430\u0440:", - "HeaderAlbumArtists": "\u0410\u043b\u044c\u0431\u043e\u043c \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u043b\u0430\u0440\u044b", - "HeaderAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u0434\u0430\u0440", - "HeaderDisc": "\u0414\u0438\u0441\u043a\u0456", - "HeaderTrack": "\u0416\u043e\u043b\u0448\u044b\u049b", - "HeaderAudio": "\u0414\u044b\u0431\u044b\u0441", - "HeaderVideo": "\u0411\u0435\u0439\u043d\u0435", - "HeaderEmbeddedImage": "\u0415\u043d\u0434\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u0441\u0443\u0440\u0435\u0442", - "HeaderResolution": "\u0410\u0436\u044b\u0440\u0430\u0442\u044b\u043c\u0434\u044b\u043b\u044b\u0493\u044b", - "HeaderSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440", - "HeaderGenres": "\u0416\u0430\u043d\u0440\u043b\u0430\u0440", - "HeaderCountries": "\u0415\u043b\u0434\u0435\u0440", - "HeaderStatus": "\u041a\u04af\u0439", - "HeaderTracks": "\u0416\u043e\u043b\u0448\u044b\u049b\u0442\u0430\u0440", - "HeaderMusicArtist": "\u041c\u0443\u0437\u044b\u043a\u0430 \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b", - "HeaderLocked": "\u049a\u04b1\u043b\u044b\u043f\u0442\u0430\u043b\u0493\u0430\u043d", - "HeaderStudios": "\u0421\u0442\u0443\u0434\u0438\u044f\u043b\u0430\u0440", - "HeaderActor": "\u0410\u043a\u0442\u0435\u0440\u043b\u0435\u0440", - "HeaderComposer": "\u041a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u043b\u0430\u0440", - "HeaderDirector": "\u0420\u0435\u0436\u0438\u0441\u0441\u0435\u0440\u043b\u0435\u0440", - "HeaderGuestStar": "\u0428\u0430\u049b\u044b\u0440\u044b\u043b\u0493\u0430\u043d \u0430\u043a\u0442\u0435\u0440", - "HeaderProducer": "\u041f\u0440\u043e\u0434\u044e\u0441\u0435\u0440\u043b\u0435\u0440", - "HeaderWriter": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439\u0448\u0456\u043b\u0435\u0440", - "HeaderParentalRatings": "\u0416\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u0442\u0430\u0440", - "HeaderCommunityRatings": "\u049a\u0430\u0443\u044b\u043c \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u043b\u0430\u0440\u044b", - "StartupEmbyServerIsLoading": "Emby Server \u0436\u04af\u043a\u0442\u0435\u043b\u0443\u0434\u0435. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u043a\u04e9\u043f \u04b1\u0437\u0430\u043c\u0430\u0439 \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ko.json b/MediaBrowser.Server.Implementations/Localization/Core/ko.json deleted file mode 100644 index 834ccc17bc..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/ko.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "\uc571: {0}, \uc7a5\uce58: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "\ud63c\ud569 \ucf58\ud150\ud2b8", - "FolderTypeMovies": "\uc601\ud654", - "FolderTypeMusic": "\uc74c\uc545", - "FolderTypeAdultVideos": "\uc131\uc778 \ube44\ub514\uc624", - "FolderTypePhotos": "\uc0ac\uc9c4", - "FolderTypeMusicVideos": "\ubba4\uc9c1 \ube44\ub514\uc624", - "FolderTypeHomeVideos": "\ud648 \ube44\ub514\uc624", - "FolderTypeGames": "\uac8c\uc784", - "FolderTypeBooks": "\ucc45", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "\ubc30\uc5ed \ubc0f \uc81c\uc791\uc9c4", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "\ucc55\ud130 {0}", - "NameSeasonNumber": "\uc2dc\uc98c {0}", - "LabelExit": "\uc885\ub8cc", - "LabelVisitCommunity": "\ucee4\ubba4\ub2c8\ud2f0 \ubc29\ubb38", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api \ubb38\uc11c", - "LabelDeveloperResources": "\uac1c\ubc1c\uc790 \ub9ac\uc18c\uc2a4", - "LabelBrowseLibrary": "\ub77c\uc774\ube0c\ub7ec\ub9ac \ud0d0\uc0c9", - "LabelConfigureServer": "Emby \uc124\uc815", - "LabelRestartServer": "\uc11c\ubc84 \uc7ac\uc2dc\ub3d9", - "CategorySync": "\ub3d9\uae30\ud654", - "CategoryUser": "\uc0ac\uc6a9\uc790", - "CategorySystem": "\uc2dc\uc2a4\ud15c", - "CategoryApplication": "\uc560\ud50c\ub9ac\ucf00\uc774\uc158", - "CategoryPlugin": "\ud50c\ub7ec\uadf8\uc778", - "NotificationOptionPluginError": "\ud50c\ub7ec\uadf8\uc778 \uc2e4\ud328", - "NotificationOptionApplicationUpdateAvailable": "\uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc5c5\ub370\uc774\ud2b8 \uc0ac\uc6a9 \uac00\ub2a5", - "NotificationOptionApplicationUpdateInstalled": "\uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc5c5\ub370\uc774\ud2b8 \uc124\uce58\ub428", - "NotificationOptionPluginUpdateInstalled": "\ud50c\ub7ec\uadf8\uc778 \uc5c5\ub370\uc774\ud2b8 \uc124\uce58\ub428", - "NotificationOptionPluginInstalled": "\ud50c\ub7ec\uadf8\uc778 \uc124\uce58\ub428", - "NotificationOptionPluginUninstalled": "\ud50c\ub7ec\uadf8\uc778 \uc124\uce58 \uc81c\uac70\ub428", - "NotificationOptionVideoPlayback": "\ube44\ub514\uc624 \uc7ac\uc0dd \uc2dc\uc791\ub428", - "NotificationOptionAudioPlayback": "\uc624\ub514\uc624 \uc7ac\uc0dd \uc2dc\uc791\ub428", - "NotificationOptionGamePlayback": "\uac8c\uc784 \ud50c\ub808\uc774 \uc9c0\uc791\ub428", - "NotificationOptionVideoPlaybackStopped": "\ube44\ub514\uc624 \uc7ac\uc0dd \uc911\uc9c0\ub428", - "NotificationOptionAudioPlaybackStopped": "\uc624\ub514\uc624 \uc7ac\uc0dd \uc911\uc9c0\ub428", - "NotificationOptionGamePlaybackStopped": "\uac8c\uc784 \ud50c\ub808\uc774 \uc911\uc9c0\ub428", - "NotificationOptionTaskFailed": "\uc608\uc57d \uc791\uc5c5 \uc2e4\ud328", - "NotificationOptionInstallationFailed": "\uc124\uce58 \uc2e4\ud328", - "NotificationOptionNewLibraryContent": "\uc0c8 \ucf58\ud150\ud2b8 \ucd94\uac00\ub428", - "NotificationOptionNewLibraryContentMultiple": "\uc0c8 \ucf58\ub374\ud2b8 \ucd94\uac00\ub428 (\ubcf5\uc218)", - "NotificationOptionCameraImageUploaded": "\uce74\uba54\ub77c \uc774\ubbf8\uc9c0 \uc5c5\ub85c\ub4dc\ub428", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "\uc11c\ubc84\ub97c \ub2e4\uc2dc \uc2dc\uc791\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4", - "ViewTypePlaylists": "\uc7ac\uc0dd\ubaa9\ub85d", - "ViewTypeMovies": "\uc601\ud654", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "\uac8c\uc784", - "ViewTypeMusic": "\uc74c\uc545", - "ViewTypeMusicGenres": "\uc7a5\ub974", - "ViewTypeMusicArtists": "\uc544\ud2f0\uc2a4\ud2b8", - "ViewTypeBoxSets": "\uceec\ub809\uc158", - "ViewTypeChannels": "\ucc44\ub110", - "ViewTypeLiveTV": "TV \ubc29\uc1a1", - "ViewTypeLiveTvNowPlaying": "\uc9c0\uae08 \ubc29\uc1a1 \uc911", - "ViewTypeLatestGames": "\ucd5c\uadfc \uac8c\uc784", - "ViewTypeRecentlyPlayedGames": "\ucd5c\uadfc \ud50c\ub808\uc774", - "ViewTypeGameFavorites": "\uc990\uaca8\ucc3e\uae30", - "ViewTypeGameSystems": "\uac8c\uc784 \uc2dc\uc2a4\ud15c", - "ViewTypeGameGenres": "\uc7a5\ub974", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "\uc2dc\ub9ac\uc988", - "ViewTypeTvGenres": "\uc7a5\ub974", - "ViewTypeTvFavoriteSeries": "\uc88b\uc544\ud558\ub294 \uc2dc\ub9ac\uc988", - "ViewTypeTvFavoriteEpisodes": "\uc88b\uc544\ud558\ub294 \uc5d0\ud53c\uc18c\ub4dc", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "\uc601\ud654", - "ViewTypeMovieCollections": "\uceec\ub809\uc158", - "ViewTypeMovieFavorites": "\uc990\uaca8\ucc3e\uae30", - "ViewTypeMovieGenres": "\uc7a5\ub974", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "\uc7ac\uc0dd\ubaa9\ub85d", - "ViewTypeMusicAlbums": "\uc568\ubc94", - "ViewTypeMusicAlbumArtists": "\uc568\ubc94 \uc544\ud2f0\uc2a4\ud2b8", - "HeaderOtherDisplaySettings": "\ud654\uba74 \uc124\uc815", - "ViewTypeMusicSongs": "\ub178\ub798", - "ViewTypeMusicFavorites": "\uc990\uaca8\ucc3e\uae30", - "ViewTypeMusicFavoriteAlbums": "\uc88b\uc544\ud558\ub294 \uc568\ubc94", - "ViewTypeMusicFavoriteArtists": "\uc88b\uc544\ud558\ub294 \uc544\ud2f0\uc2a4\ud2b8", - "ViewTypeMusicFavoriteSongs": "\uc88b\uc544\ud558\ub294 \ub178\ub798", - "ViewTypeFolders": "\ud3f4\ub354", - "ViewTypeLiveTvRecordingGroups": "\ub179\ud654", - "ViewTypeLiveTvChannels": "\ucc44\ub110", - "ScheduledTaskFailedWithName": "{0} \uc2e4\ud328", - "LabelRunningTimeValue": "\uc0c1\uc601 \uc2dc\uac04: {0}", - "ScheduledTaskStartedWithName": "{0} \uc2dc\uc791\ub428", - "VersionNumber": "\ubc84\uc804 {0}", - "PluginInstalledWithName": "{0} \uc124\uce58\ub428", - "PluginUpdatedWithName": "{0} \uc5c5\ub370\uc774\ud2b8\ub428", - "PluginUninstalledWithName": "{0} \uc124\uce58 \uc81c\uac70\ub428", - "ItemAddedWithName": "\ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0 {0} \ucd94\uac00\ub428", - "ItemRemovedWithName": "\ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0\uc11c {0} \uc0ad\uc81c\ub428", - "LabelIpAddressValue": "IP \uc8fc\uc18c: {0}", - "DeviceOnlineWithName": "{0} \uc5f0\uacb0\ub428", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "\uc81c\uacf5\uc790: {0}", - "SubtitlesDownloadedForItem": "{0} \uc790\ub9c9 \ub2e4\uc6b4\ub85c\ub4dc\ub428", - "UserConfigurationUpdatedWithName": "{0} \uc0ac\uc6a9\uc790 \uc124\uc815\uc774 \uc5c5\ub370\uc774\ud2b8\ub428", - "UserCreatedWithName": "\uc0ac\uc6a9\uc790 {0} \uc0dd\uc131\ub428", - "UserPasswordChangedWithName": "\uc0ac\uc6a9\uc790 {0} \ube44\ubc00\ubc88\ud638 \ubcc0\uacbd\ub428", - "UserDeletedWithName": "\uc0ac\uc6a9\uc790 {0} \uc0ad\uc81c\ub428", - "MessageServerConfigurationUpdated": "\uc11c\ubc84 \ud658\uacbd \uc124\uc815 \uc5c5\ub370\uc774\ub4dc\ub428", - "MessageNamedServerConfigurationUpdatedWithValue": "\uc11c\ubc84 \ud658\uacbd \uc124\uc815 {0} \uc139\uc158 \uc5c5\ub370\uc774\ud2b8 \ub428", - "MessageApplicationUpdated": "Emby \uc11c\ubc84 \uc5c5\ub370\uc774\ud2b8\ub428", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} \uc5f0\uacb0 \ud574\uc81c\ub428", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{1} \uc5d0\uc11c {0} \uc5f0\uacb0 \ud574\uc81c\ub428", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "{0} \uc790\ub9c9 \ub2e4\uc6b4\ub85c\ub4dc \uc2e4\ud328", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "\ubc30\uacbd", - "HeaderImageLogo": "\ub85c\uace0", - "HeaderUserPrimaryImage": "\uc0ac\uc6a9\uc790 \uc774\ubbf8\uc9c0", - "HeaderOverview": "\uc904\uac70\ub9ac", - "HeaderShortOverview": "\uac04\ub7b5 \uc904\uac70\ub9ac", - "HeaderType": "Type", - "HeaderSeverity": "\uc2ec\uac01\ub3c4", - "HeaderUser": "\uc0ac\uc6a9\uc790", - "HeaderName": "Name", - "HeaderDate": "\ub0a0\uc9dc", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "\uac1c\ubd09\uc77c", - "HeaderRuntime": "\uc0c1\uc601 \uc2dc\uac04", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "\uc2dc\uc98c", - "HeaderSeasonNumber": "\uc2dc\uc98c \ubc88\ud638", - "HeaderSeries": "Series:", - "HeaderNetwork": "\ub124\ud2b8\uc6cc\ud06c", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "\ucee4\ubba4\ub2c8\ud2f0 \ud3c9\uc810", - "HeaderTrailers": "\uc608\uace0\ud3b8", - "HeaderSpecials": "\uc2a4\ud398\uc15c", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "\uc568\ubc94", - "HeaderDisc": "\ub514\uc2a4\ud06c", - "HeaderTrack": "\ud2b8\ub799", - "HeaderAudio": "\uc624\ub514\uc624", - "HeaderVideo": "\ube44\ub514\uc624", - "HeaderEmbeddedImage": "\ub0b4\uc7a5 \uc774\ubbf8\uc9c0", - "HeaderResolution": "\ud574\uc0c1\ub3c4", - "HeaderSubtitles": "\uc790\ub9c9", - "HeaderGenres": "\uc7a5\ub974", - "HeaderCountries": "\uad6d\uac00", - "HeaderStatus": "\uc0c1\ud0dc", - "HeaderTracks": "\ud2b8\ub799", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "\uc7a0\uae40", - "HeaderStudios": "\uc2a4\ud29c\ub514\uc624", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "\uc790\ub140 \ubcf4\ud638 \ub4f1\uae09", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ms.json b/MediaBrowser.Server.Implementations/Localization/Core/ms.json deleted file mode 100644 index fe5eef894d..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/ms.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Tutup", - "LabelVisitCommunity": "Melawat Masyarakat", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Imbas Pengumpulan", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/nb.json b/MediaBrowser.Server.Implementations/Localization/Core/nb.json deleted file mode 100644 index 315d49b5fd..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/nb.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0} , Device: {1}", - "UserDownloadingItemWithValues": "{0} laster ned {1}", - "FolderTypeMixed": "Forskjellig innhold", - "FolderTypeMovies": "Filmer", - "FolderTypeMusic": "Musikk", - "FolderTypeAdultVideos": "Voksen-videoer", - "FolderTypePhotos": "Foto", - "FolderTypeMusicVideos": "Musikk-videoer", - "FolderTypeHomeVideos": "Hjemme-videoer", - "FolderTypeGames": "Spill", - "FolderTypeBooks": "B\u00f8ker", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Arve", - "HeaderCastCrew": "Mannskap", - "HeaderPeople": "Personer", - "ValueSpecialEpisodeName": "Spesiell - {0}", - "LabelChapterName": "Kapittel {0}", - "NameSeasonNumber": "Sesong {0}", - "LabelExit": "Avslutt", - "LabelVisitCommunity": "Bes\u00f8k oss", - "LabelGithub": "Github", - "LabelApiDocumentation": "API-dokumentasjon", - "LabelDeveloperResources": "Ressurser for Utviklere", - "LabelBrowseLibrary": "Browse biblioteket", - "LabelConfigureServer": "Konfigurer Emby", - "LabelRestartServer": "Restart serveren", - "CategorySync": "Synk", - "CategoryUser": "Bruker", - "CategorySystem": "System", - "CategoryApplication": "Applikasjon", - "CategoryPlugin": "Programtillegg", - "NotificationOptionPluginError": "Programtillegg feilet", - "NotificationOptionApplicationUpdateAvailable": "Oppdatering tilgjengelig", - "NotificationOptionApplicationUpdateInstalled": "Oppdatering installert", - "NotificationOptionPluginUpdateInstalled": "Oppdatert programtillegg installert", - "NotificationOptionPluginInstalled": "Programtillegg installert", - "NotificationOptionPluginUninstalled": "Programtillegg er fjernet", - "NotificationOptionVideoPlayback": "Videoavspilling startet", - "NotificationOptionAudioPlayback": "Lydavspilling startet", - "NotificationOptionGamePlayback": "Spill startet", - "NotificationOptionVideoPlaybackStopped": "Videoavspilling stoppet", - "NotificationOptionAudioPlaybackStopped": "Lydavspilling stoppet", - "NotificationOptionGamePlaybackStopped": "Spill stoppet", - "NotificationOptionTaskFailed": "Planlagt oppgave feilet", - "NotificationOptionInstallationFailed": "Installasjon feilet", - "NotificationOptionNewLibraryContent": "Nytt innhold er lagt til", - "NotificationOptionNewLibraryContentMultiple": "Nytt innhold lagt til (flere)", - "NotificationOptionCameraImageUploaded": "Bilde fra kamera lastet opp", - "NotificationOptionUserLockedOut": "Bruker er utestengt", - "NotificationOptionServerRestartRequired": "Server m\u00e5 startes p\u00e5 nytt", - "ViewTypePlaylists": "Spillelister", - "ViewTypeMovies": "Filmer", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Spill", - "ViewTypeMusic": "Musikk", - "ViewTypeMusicGenres": "Sjangere", - "ViewTypeMusicArtists": "Artist", - "ViewTypeBoxSets": "Samlinger", - "ViewTypeChannels": "Kanaler", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Sendes n\u00e5", - "ViewTypeLatestGames": "Siste spill", - "ViewTypeRecentlyPlayedGames": "Nylig spilt", - "ViewTypeGameFavorites": "Favoritter", - "ViewTypeGameSystems": "Spillsystemer", - "ViewTypeGameGenres": "Sjangere", - "ViewTypeTvResume": "Fortsette", - "ViewTypeTvNextUp": "Neste", - "ViewTypeTvLatest": "Siste", - "ViewTypeTvShowSeries": "Serier", - "ViewTypeTvGenres": "Sjangere", - "ViewTypeTvFavoriteSeries": "Favoritt serier", - "ViewTypeTvFavoriteEpisodes": "Favoritt episoder", - "ViewTypeMovieResume": "Fortsette", - "ViewTypeMovieLatest": "Siste", - "ViewTypeMovieMovies": "Filmer", - "ViewTypeMovieCollections": "Samlinger", - "ViewTypeMovieFavorites": "Favoritter", - "ViewTypeMovieGenres": "Sjangere", - "ViewTypeMusicLatest": "Siste", - "ViewTypeMusicPlaylists": "Spillelister", - "ViewTypeMusicAlbums": "Albumer", - "ViewTypeMusicAlbumArtists": "Album artister", - "HeaderOtherDisplaySettings": "Visnings Innstillinger", - "ViewTypeMusicSongs": "Sanger", - "ViewTypeMusicFavorites": "Favoritter", - "ViewTypeMusicFavoriteAlbums": "Favorittalbumer", - "ViewTypeMusicFavoriteArtists": "Favorittartister", - "ViewTypeMusicFavoriteSongs": "Favorittsanger", - "ViewTypeFolders": "Mapper", - "ViewTypeLiveTvRecordingGroups": "Opptak", - "ViewTypeLiveTvChannels": "Kanaler", - "ScheduledTaskFailedWithName": "{0} feilet", - "LabelRunningTimeValue": "Spille tide: {0}", - "ScheduledTaskStartedWithName": "{0} startet", - "VersionNumber": "Versjon {0}", - "PluginInstalledWithName": "{0} ble installert", - "PluginUpdatedWithName": "{0} ble oppdatert", - "PluginUninstalledWithName": "{0} ble avinstallert", - "ItemAddedWithName": "{0} ble lagt til biblioteket", - "ItemRemovedWithName": "{0} ble fjernet fra biblioteket", - "LabelIpAddressValue": "Ip adresse: {0}", - "DeviceOnlineWithName": "{0} er tilkoblet", - "UserOnlineFromDevice": "{0} er online fra {1}", - "ProviderValue": "Tilbyder: {0}", - "SubtitlesDownloadedForItem": "Undertekster lastet ned for {0}", - "UserConfigurationUpdatedWithName": "Bruker konfigurasjon har blitt oppdatert for {0}", - "UserCreatedWithName": "Bruker {0} har blitt opprettet", - "UserPasswordChangedWithName": "Passord har blitt endret for bruker {0}", - "UserDeletedWithName": "Bruker {0} har blitt slettet", - "MessageServerConfigurationUpdated": "Server konfigurasjon har blitt oppdatert", - "MessageNamedServerConfigurationUpdatedWithValue": "Server konfigurasjon seksjon {0} har blitt oppdatert", - "MessageApplicationUpdated": "Emby server har blitt oppdatert", - "FailedLoginAttemptWithUserName": "P\u00e5loggingsfors\u00f8k feilet fra {0}", - "AuthenticationSucceededWithUserName": "{0} autentisert med suksess", - "DeviceOfflineWithName": "{0} har koblet fra", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} har koblet fra {1}", - "UserStartedPlayingItemWithValues": "{0} har startet avspilling av {1}", - "UserStoppedPlayingItemWithValues": "{0} har stoppet avspilling av {1}", - "SubtitleDownloadFailureForItem": "nedlasting av undertekster feilet for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "Bruker", - "HeaderName": "Navn", - "HeaderDate": "Dato", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Utgivelsesdato", - "HeaderRuntime": "Spilletid", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Sesong", - "HeaderSeasonNumber": "Sesong nummer", - "HeaderSeries": "Series:", - "HeaderNetwork": "Nettverk", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Fellesskap anmeldelse", - "HeaderTrailers": "Trailere", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albumer", - "HeaderDisc": "Disk", - "HeaderTrack": "Spor", - "HeaderAudio": "Lyd", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "innebygd bilde", - "HeaderResolution": "Oppl\u00f8sning", - "HeaderSubtitles": "Undertekster", - "HeaderGenres": "Sjanger", - "HeaderCountries": "Land", - "HeaderStatus": "Status", - "HeaderTracks": "Spor", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studioer", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Foreldresensur", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/nl.json b/MediaBrowser.Server.Implementations/Localization/Core/nl.json deleted file mode 100644 index 2818fbf6a6..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/nl.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Een ogenblik geduld terwijl uw Emby Server-database wordt bijgewerkt. {0}% voltooid.", - "AppDeviceValues": "App: {0}, Apparaat: {1}", - "UserDownloadingItemWithValues": "{0} download {1}", - "FolderTypeMixed": "Gemengde inhoud", - "FolderTypeMovies": "Films", - "FolderTypeMusic": "Muziek", - "FolderTypeAdultVideos": "Adult video's", - "FolderTypePhotos": "Foto's", - "FolderTypeMusicVideos": "Muziek video's", - "FolderTypeHomeVideos": "Thuis video's", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Boeken", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "overerven", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "Personen", - "ValueSpecialEpisodeName": "Speciaal - {0}", - "LabelChapterName": "Hoofdstuk {0}", - "NameSeasonNumber": "Seizoen {0}", - "LabelExit": "Afsluiten", - "LabelVisitCommunity": "Bezoek Gemeenschap", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api documentatie", - "LabelDeveloperResources": "Ontwikkelaars bronnen", - "LabelBrowseLibrary": "Bekijk bibliotheek", - "LabelConfigureServer": "Emby Configureren", - "LabelRestartServer": "Server herstarten", - "CategorySync": "Sync", - "CategoryUser": "Gebruiker", - "CategorySystem": "Systeem", - "CategoryApplication": "Toepassing", - "CategoryPlugin": "Plug-in", - "NotificationOptionPluginError": "Plug-in fout", - "NotificationOptionApplicationUpdateAvailable": "Programma-update beschikbaar", - "NotificationOptionApplicationUpdateInstalled": "Programma-update ge\u00efnstalleerd", - "NotificationOptionPluginUpdateInstalled": "Plug-in-update ge\u00efnstalleerd", - "NotificationOptionPluginInstalled": "Plug-in ge\u00efnstalleerd", - "NotificationOptionPluginUninstalled": "Plug-in verwijderd", - "NotificationOptionVideoPlayback": "Video afspelen gestart", - "NotificationOptionAudioPlayback": "Geluid afspelen gestart", - "NotificationOptionGamePlayback": "Game gestart", - "NotificationOptionVideoPlaybackStopped": "Video afspelen gestopt", - "NotificationOptionAudioPlaybackStopped": "Geluid afspelen gestopt", - "NotificationOptionGamePlaybackStopped": "Afspelen spel gestopt", - "NotificationOptionTaskFailed": "Mislukken van de geplande taak", - "NotificationOptionInstallationFailed": "Mislukken van de installatie", - "NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd", - "NotificationOptionNewLibraryContentMultiple": "Nieuwe content toegevoegd (meerdere)", - "NotificationOptionCameraImageUploaded": "Camera afbeelding ge\u00fcpload", - "NotificationOptionUserLockedOut": "Gebruikersaccount vergrendeld", - "NotificationOptionServerRestartRequired": "Server herstart nodig", - "ViewTypePlaylists": "Afspeellijsten", - "ViewTypeMovies": "Films", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Muziek", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artiesten", - "ViewTypeBoxSets": "Collecties", - "ViewTypeChannels": "Kanalen", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Nu uitgezonden", - "ViewTypeLatestGames": "Nieuwste games", - "ViewTypeRecentlyPlayedGames": "Recent gespeelt", - "ViewTypeGameFavorites": "Favorieten", - "ViewTypeGameSystems": "Game systemen", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Hervatten", - "ViewTypeTvNextUp": "Volgende", - "ViewTypeTvLatest": "Nieuwste", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favoriete Series", - "ViewTypeTvFavoriteEpisodes": "Favoriete Afleveringen", - "ViewTypeMovieResume": "Hervatten", - "ViewTypeMovieLatest": "Nieuwste", - "ViewTypeMovieMovies": "Films", - "ViewTypeMovieCollections": "Collecties", - "ViewTypeMovieFavorites": "Favorieten", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Nieuwste", - "ViewTypeMusicPlaylists": "Afspeellijsten", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album artiesten", - "HeaderOtherDisplaySettings": "Beeld instellingen", - "ViewTypeMusicSongs": "Nummers", - "ViewTypeMusicFavorites": "Favorieten", - "ViewTypeMusicFavoriteAlbums": "Favoriete albums", - "ViewTypeMusicFavoriteArtists": "Favoriete artiesten", - "ViewTypeMusicFavoriteSongs": "Favoriete nummers", - "ViewTypeFolders": "Mappen", - "ViewTypeLiveTvRecordingGroups": "Opnamen", - "ViewTypeLiveTvChannels": "Kanalen", - "ScheduledTaskFailedWithName": "{0} is mislukt", - "LabelRunningTimeValue": "Looptijd: {0}", - "ScheduledTaskStartedWithName": "{0} is gestart", - "VersionNumber": "Versie {0}", - "PluginInstalledWithName": "{0} is ge\u00efnstalleerd", - "PluginUpdatedWithName": "{0} is bijgewerkt", - "PluginUninstalledWithName": "{0} is gede\u00efnstalleerd", - "ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek", - "ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek", - "LabelIpAddressValue": "IP adres: {0}", - "DeviceOnlineWithName": "{0} is verbonden", - "UserOnlineFromDevice": "{0} heeft verbinding met {1}", - "ProviderValue": "Aanbieder: {0}", - "SubtitlesDownloadedForItem": "Ondertiteling voor {0} is gedownload", - "UserConfigurationUpdatedWithName": "Gebruikersinstellingen voor {0} zijn bijgewerkt", - "UserCreatedWithName": "Gebruiker {0} is aangemaakt", - "UserPasswordChangedWithName": "Wachtwoord voor {0} is gewijzigd", - "UserDeletedWithName": "Gebruiker {0} is verwijderd", - "MessageServerConfigurationUpdated": "Server configuratie is bijgewerkt", - "MessageNamedServerConfigurationUpdatedWithValue": "Sectie {0} van de server configuratie is bijgewerkt", - "MessageApplicationUpdated": "Emby Server is bijgewerkt", - "FailedLoginAttemptWithUserName": "Mislukte aanmeld poging van {0}", - "AuthenticationSucceededWithUserName": "{0} is succesvol geverifieerd", - "DeviceOfflineWithName": "{0} is losgekoppeld", - "UserLockedOutWithName": "Gebruikersaccount {0} is vergrendeld", - "UserOfflineFromDevice": "Verbinding van {0} met {1} is verbroken", - "UserStartedPlayingItemWithValues": "{0} heeft afspelen van {1} gestart", - "UserStoppedPlayingItemWithValues": "{0} heeft afspelen van {1} gestopt", - "SubtitleDownloadFailureForItem": "Downloaden van ondertiteling voor {0} is mislukt", - "HeaderUnidentified": "One\u00efdentificaard", - "HeaderImagePrimary": "Primair", - "HeaderImageBackdrop": "Achtergrond", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "Afbeelding gebruiker", - "HeaderOverview": "Overzicht", - "HeaderShortOverview": "Kort overzicht", - "HeaderType": "Type", - "HeaderSeverity": "Ernst", - "HeaderUser": "Gebruiker", - "HeaderName": "Naam", - "HeaderDate": "Datum", - "HeaderPremiereDate": "Premi\u00e8re Datum", - "HeaderDateAdded": "Datum toegevoegd", - "HeaderReleaseDate": "Uitgave datum", - "HeaderRuntime": "Speelduur", - "HeaderPlayCount": "Afspeel telling", - "HeaderSeason": "Seizoen", - "HeaderSeasonNumber": "Seizoen nummer", - "HeaderSeries": "Series:", - "HeaderNetwork": "Zender", - "HeaderYear": "Jaar:", - "HeaderYears": "Jaren:", - "HeaderParentalRating": "Kijkwijzer classificatie", - "HeaderCommunityRating": "Gemeenschap cijfer", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game systemen", - "HeaderPlayers": "Spelers:", - "HeaderAlbumArtists": "Album artiesten", - "HeaderAlbums": "Albums", - "HeaderDisc": "Schijf", - "HeaderTrack": "Track", - "HeaderAudio": "Geluid", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Ingesloten afbeelding", - "HeaderResolution": "Resolutie", - "HeaderSubtitles": "Ondertiteling", - "HeaderGenres": "Genres", - "HeaderCountries": "Landen", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Muziek artiest", - "HeaderLocked": "Vergrendeld", - "HeaderStudios": "Studio's", - "HeaderActor": "Acteurs", - "HeaderComposer": "Componisten", - "HeaderDirector": "Regiseurs", - "HeaderGuestStar": "Gast ster", - "HeaderProducer": "Producenten", - "HeaderWriter": "Schrijvers", - "HeaderParentalRatings": "Ouderlijke toezicht", - "HeaderCommunityRatings": "Gemeenschapswaardering", - "StartupEmbyServerIsLoading": "Emby Server is aan het laden, probeer het later opnieuw." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/pl.json b/MediaBrowser.Server.Implementations/Localization/Core/pl.json deleted file mode 100644 index cdaa87c4d8..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/pl.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Prosz\u0119 czeka\u0107 na koniec aktualizacji biblioteki. Post\u0119p: {0}%", - "AppDeviceValues": "Aplikacja: {0}, Urz\u0105dzenie: {1}", - "UserDownloadingItemWithValues": "{0} pobiera {1}", - "FolderTypeMixed": "Zawarto\u015b\u0107 mieszana", - "FolderTypeMovies": "Filmy", - "FolderTypeMusic": "Muzyka", - "FolderTypeAdultVideos": "Filmy dla doros\u0142ych", - "FolderTypePhotos": "Zdj\u0119cia", - "FolderTypeMusicVideos": "Teledyski", - "FolderTypeHomeVideos": "Filmy domowe", - "FolderTypeGames": "Gry", - "FolderTypeBooks": "Ksi\u0105\u017cki", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Dziedzicz", - "HeaderCastCrew": "Obsada & Eikpa", - "HeaderPeople": "Ludzie", - "ValueSpecialEpisodeName": "Specjalny - {0}", - "LabelChapterName": "Rozdzia\u0142 {0}", - "NameSeasonNumber": "Sezon {0}", - "LabelExit": "Wyj\u015bcie", - "LabelVisitCommunity": "Odwied\u017a spo\u0142eczno\u015b\u0107", - "LabelGithub": "Github", - "LabelApiDocumentation": "Dokumantacja API", - "LabelDeveloperResources": "Materia\u0142y dla deweloper\u00f3w", - "LabelBrowseLibrary": "Przegl\u0105daj bibliotek\u0119", - "LabelConfigureServer": "Konfiguracja Emby", - "LabelRestartServer": "Restart serwera", - "CategorySync": "Sync", - "CategoryUser": "U\u017cytkownik", - "CategorySystem": "System", - "CategoryApplication": "Aplikacja", - "CategoryPlugin": "Wtyczka", - "NotificationOptionPluginError": "Niepowodzenie wtyczki", - "NotificationOptionApplicationUpdateAvailable": "Dost\u0119pna aktualizacja aplikacji", - "NotificationOptionApplicationUpdateInstalled": "Zainstalowano aktualizacj\u0119 aplikacji", - "NotificationOptionPluginUpdateInstalled": "Zainstalowano aktualizacj\u0119 wtyczki", - "NotificationOptionPluginInstalled": "Zainstalowano wtyczk\u0119", - "NotificationOptionPluginUninstalled": "Odinstalowano wtyczk\u0119", - "NotificationOptionVideoPlayback": "Rozpocz\u0119to odtwarzanie wideo", - "NotificationOptionAudioPlayback": "Rozpocz\u0119to odtwarzanie audio", - "NotificationOptionGamePlayback": "Odtwarzanie gry rozpocz\u0119te", - "NotificationOptionVideoPlaybackStopped": "Odtwarzanie wideo zatrzymane", - "NotificationOptionAudioPlaybackStopped": "Odtwarzane audio zatrzymane", - "NotificationOptionGamePlaybackStopped": "Odtwarzanie gry zatrzymane", - "NotificationOptionTaskFailed": "Niepowodzenie zaplanowanego zadania", - "NotificationOptionInstallationFailed": "Niepowodzenie instalacji", - "NotificationOptionNewLibraryContent": "Nowa zawarto\u015b\u0107 dodana", - "NotificationOptionNewLibraryContentMultiple": "Nowa zawarto\u015b\u0107 dodana (wiele)", - "NotificationOptionCameraImageUploaded": "Obraz z Kamery dodany", - "NotificationOptionUserLockedOut": "U\u017cytkownik zablokowany", - "NotificationOptionServerRestartRequired": "Restart serwera wymagany", - "ViewTypePlaylists": "Playlisty", - "ViewTypeMovies": "Filmy", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Gry", - "ViewTypeMusic": "Muzyka", - "ViewTypeMusicGenres": "Gatunki", - "ViewTypeMusicArtists": "Arty\u015bci", - "ViewTypeBoxSets": "Kolekcje", - "ViewTypeChannels": "Kana\u0142y", - "ViewTypeLiveTV": "TV Na \u017bywo", - "ViewTypeLiveTvNowPlaying": "Teraz Transmitowane", - "ViewTypeLatestGames": "Ostatnie Gry", - "ViewTypeRecentlyPlayedGames": "Ostatnio Odtwarzane", - "ViewTypeGameFavorites": "Ulubione", - "ViewTypeGameSystems": "Systemy Gier Wideo", - "ViewTypeGameGenres": "Gatunki", - "ViewTypeTvResume": "Wzn\u00f3w", - "ViewTypeTvNextUp": "Nast\u0119pny", - "ViewTypeTvLatest": "Najnowsze", - "ViewTypeTvShowSeries": "Seriale", - "ViewTypeTvGenres": "Gatunki", - "ViewTypeTvFavoriteSeries": "Ulubione Seriale", - "ViewTypeTvFavoriteEpisodes": "Ulubione Odcinki", - "ViewTypeMovieResume": "Wzn\u00f3w", - "ViewTypeMovieLatest": "Najnowsze", - "ViewTypeMovieMovies": "Filmy", - "ViewTypeMovieCollections": "Kolekcje", - "ViewTypeMovieFavorites": "Ulubione", - "ViewTypeMovieGenres": "Gatunki", - "ViewTypeMusicLatest": "Najnowsze", - "ViewTypeMusicPlaylists": "Playlisty", - "ViewTypeMusicAlbums": "Albumy", - "ViewTypeMusicAlbumArtists": "Arty\u015bci albumu", - "HeaderOtherDisplaySettings": "Ustawienia Wy\u015bwietlania", - "ViewTypeMusicSongs": "Utwory", - "ViewTypeMusicFavorites": "Ulubione", - "ViewTypeMusicFavoriteAlbums": "Ulubione Albumy", - "ViewTypeMusicFavoriteArtists": "Ulubieni Arty\u015bci", - "ViewTypeMusicFavoriteSongs": "Ulubione Utwory", - "ViewTypeFolders": "Foldery", - "ViewTypeLiveTvRecordingGroups": "Nagrania", - "ViewTypeLiveTvChannels": "Kana\u0142y", - "ScheduledTaskFailedWithName": "{0} niepowodze\u0144", - "LabelRunningTimeValue": "Czas trwania: {0}", - "ScheduledTaskStartedWithName": "{0} rozpocz\u0119te", - "VersionNumber": "Wersja {0}", - "PluginInstalledWithName": "{0} zainstalowanych", - "PluginUpdatedWithName": "{0} zaktualizowanych", - "PluginUninstalledWithName": "{0} odinstalowanych", - "ItemAddedWithName": "{0} dodanych do biblioteki", - "ItemRemovedWithName": "{0} usuni\u0119tych z biblioteki", - "LabelIpAddressValue": "Adres IP: {0}", - "DeviceOnlineWithName": "{0} po\u0142\u0105czonych", - "UserOnlineFromDevice": "{0} jest online od {1}", - "ProviderValue": "Dostawca: {0}", - "SubtitlesDownloadedForItem": "Napisy pobrane dla {0}", - "UserConfigurationUpdatedWithName": "Konfiguracja u\u017cytkownika zosta\u0142a zaktualizowana dla {0}", - "UserCreatedWithName": "U\u017cytkownik {0} zosta\u0142 utworzony", - "UserPasswordChangedWithName": "Has\u0142o zosta\u0142o zmienione dla u\u017cytkownika {0}", - "UserDeletedWithName": "u\u017cytkownik {0} zosta\u0142 usuni\u0119ty", - "MessageServerConfigurationUpdated": "Konfiguracja serwera zosta\u0142a zaktualizowana", - "MessageNamedServerConfigurationUpdatedWithValue": "Sekcja {0} konfiguracji serwera zosta\u0142a zaktualizowana", - "MessageApplicationUpdated": "Serwer Emby zosta\u0142 zaktualizowany", - "FailedLoginAttemptWithUserName": "Nieudana pr\u00f3ba logowania z {0}", - "AuthenticationSucceededWithUserName": "{0} zaktualizowanych z powodzeniem", - "DeviceOfflineWithName": "{0} zosta\u0142o od\u0142aczonych", - "UserLockedOutWithName": "U\u017cytkownik {0} zosta\u0142 zablokowany", - "UserOfflineFromDevice": "{0} zosta\u0142o od\u0142\u0105czonych od {1}", - "UserStartedPlayingItemWithValues": "{0} rozpocz\u0105\u0142 odtwarzanie {1}", - "UserStoppedPlayingItemWithValues": "{0} zatrzyma\u0142 odtwarzanie {1}", - "SubtitleDownloadFailureForItem": "Napisy niepobrane dla {0}", - "HeaderUnidentified": "Niezidentyfikowane", - "HeaderImagePrimary": "Priorytetowy", - "HeaderImageBackdrop": "Obraz t\u0142a", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "Avatar u\u017cytkownika", - "HeaderOverview": "Opis", - "HeaderShortOverview": "Kr\u00f3tki Opis", - "HeaderType": "Typ", - "HeaderSeverity": "Rygor", - "HeaderUser": "U\u017cytkownik", - "HeaderName": "Nazwa", - "HeaderDate": "Data", - "HeaderPremiereDate": "Data premiery", - "HeaderDateAdded": "Data dodania", - "HeaderReleaseDate": "Data wydania", - "HeaderRuntime": "D\u0142ugo\u015b\u0107 filmu", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Sezon", - "HeaderSeasonNumber": "Numer sezonu", - "HeaderSeries": "Seriale:", - "HeaderNetwork": "Sie\u0107", - "HeaderYear": "Rok:", - "HeaderYears": "Lata:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Ocena spo\u0142eczno\u015bci", - "HeaderTrailers": "Zwiastuny", - "HeaderSpecials": "Specjalne", - "HeaderGameSystems": "Systemy gier", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albumy", - "HeaderDisc": "P\u0142yta", - "HeaderTrack": "\u015acie\u017cka", - "HeaderAudio": "Audio", - "HeaderVideo": "Wideo", - "HeaderEmbeddedImage": "Osadzony obraz", - "HeaderResolution": "Rozdzielczo\u015b\u0107", - "HeaderSubtitles": "Napisy", - "HeaderGenres": "Gatunki", - "HeaderCountries": "Kraje", - "HeaderStatus": "Status", - "HeaderTracks": "Utwory", - "HeaderMusicArtist": "Wykonawcy muzyczni", - "HeaderLocked": "Zablokowane", - "HeaderStudios": "Studia", - "HeaderActor": "Aktorzy", - "HeaderComposer": "Kopozytorzy", - "HeaderDirector": "Re\u017cyszerzy", - "HeaderGuestStar": "Go\u015b\u0107 specjalny", - "HeaderProducer": "Producenci", - "HeaderWriter": "Scenarzy\u015bci", - "HeaderParentalRatings": "Ocena rodzicielska", - "HeaderCommunityRatings": "Ocena spo\u0142eczno\u015bci", - "StartupEmbyServerIsLoading": "Serwer Emby si\u0119 \u0142aduje. Prosz\u0119 spr\u00f3bowa\u0107 za chwil\u0119." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/pt-BR.json b/MediaBrowser.Server.Implementations/Localization/Core/pt-BR.json deleted file mode 100644 index 67f204b2ee..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/pt-BR.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Por favor, aguarde enquanto a base de dados do Servidor Emby \u00e9 atualizada. {0}% completo.", - "AppDeviceValues": "App: {0}, Dispositivo: {1}", - "UserDownloadingItemWithValues": "{0} est\u00e1 fazendo download de {1}", - "FolderTypeMixed": "Conte\u00fado misto", - "FolderTypeMovies": "Filmes", - "FolderTypeMusic": "M\u00fasica", - "FolderTypeAdultVideos": "V\u00eddeos adultos", - "FolderTypePhotos": "Fotos", - "FolderTypeMusicVideos": "V\u00eddeos musicais", - "FolderTypeHomeVideos": "V\u00eddeos caseiros", - "FolderTypeGames": "Jogos", - "FolderTypeBooks": "Livros", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Herdar", - "HeaderCastCrew": "Elenco & Equipe", - "HeaderPeople": "Pessoas", - "ValueSpecialEpisodeName": "Especial - {0}", - "LabelChapterName": "Cap\u00edtulo {0}", - "NameSeasonNumber": "Temporada {0}", - "LabelExit": "Sair", - "LabelVisitCommunity": "Visitar a Comunidade", - "LabelGithub": "Github", - "LabelApiDocumentation": "Documenta\u00e7\u00e3o da Api", - "LabelDeveloperResources": "Recursos do Desenvolvedor", - "LabelBrowseLibrary": "Explorar Biblioteca", - "LabelConfigureServer": "Configurar o Emby", - "LabelRestartServer": "Reiniciar Servidor", - "CategorySync": "Sincroniza\u00e7\u00e3o", - "CategoryUser": "Usu\u00e1rio", - "CategorySystem": "Sistema", - "CategoryApplication": "Aplica\u00e7\u00e3o", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Falha no plugin", - "NotificationOptionApplicationUpdateAvailable": "Atualiza\u00e7\u00e3o da aplica\u00e7\u00e3o disponivel", - "NotificationOptionApplicationUpdateInstalled": "Atualiza\u00e7\u00e3o da aplica\u00e7\u00e3o instalada", - "NotificationOptionPluginUpdateInstalled": "Atualiza\u00e7\u00e3o do plugin instalada", - "NotificationOptionPluginInstalled": "Plugin instalado", - "NotificationOptionPluginUninstalled": "Plugin desinstalado", - "NotificationOptionVideoPlayback": "Reprodu\u00e7\u00e3o de v\u00eddeo iniciada", - "NotificationOptionAudioPlayback": "Reprodu\u00e7\u00e3o de \u00e1udio iniciada", - "NotificationOptionGamePlayback": "Reprodu\u00e7\u00e3o de jogo iniciada", - "NotificationOptionVideoPlaybackStopped": "Reprodu\u00e7\u00e3o de v\u00eddeo parada", - "NotificationOptionAudioPlaybackStopped": "Reprodu\u00e7\u00e3o de \u00e1udio parada", - "NotificationOptionGamePlaybackStopped": "Reprodu\u00e7\u00e3o de jogo parada", - "NotificationOptionTaskFailed": "Falha na tarefa agendada", - "NotificationOptionInstallationFailed": "Falha na instala\u00e7\u00e3o", - "NotificationOptionNewLibraryContent": "Novo conte\u00fado adicionado", - "NotificationOptionNewLibraryContentMultiple": "Novo conte\u00fado adicionado (m\u00faltiplo)", - "NotificationOptionCameraImageUploaded": "Imagem da c\u00e2mera carregada", - "NotificationOptionUserLockedOut": "Usu\u00e1rio bloqueado", - "NotificationOptionServerRestartRequired": "Necessidade de reiniciar servidor", - "ViewTypePlaylists": "Listas de Reprodu\u00e7\u00e3o", - "ViewTypeMovies": "Filmes", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Jogos", - "ViewTypeMusic": "M\u00fasicas", - "ViewTypeMusicGenres": "G\u00eaneros", - "ViewTypeMusicArtists": "Artistas", - "ViewTypeBoxSets": "Cole\u00e7\u00f5es", - "ViewTypeChannels": "Canais", - "ViewTypeLiveTV": "TV ao Vivo", - "ViewTypeLiveTvNowPlaying": "Exibindo Agora", - "ViewTypeLatestGames": "Jogos Recentes", - "ViewTypeRecentlyPlayedGames": "Reproduzido Recentemente", - "ViewTypeGameFavorites": "Favoritos", - "ViewTypeGameSystems": "Sistemas de Jogo", - "ViewTypeGameGenres": "G\u00eaneros", - "ViewTypeTvResume": "Retomar", - "ViewTypeTvNextUp": "Pr\u00f3ximos", - "ViewTypeTvLatest": "Recentes", - "ViewTypeTvShowSeries": "S\u00e9ries", - "ViewTypeTvGenres": "G\u00eaneros", - "ViewTypeTvFavoriteSeries": "S\u00e9ries Favoritas", - "ViewTypeTvFavoriteEpisodes": "Epis\u00f3dios Favoritos", - "ViewTypeMovieResume": "Retomar", - "ViewTypeMovieLatest": "Recentes", - "ViewTypeMovieMovies": "Filmes", - "ViewTypeMovieCollections": "Cole\u00e7\u00f5es", - "ViewTypeMovieFavorites": "Favoritos", - "ViewTypeMovieGenres": "G\u00eaneros", - "ViewTypeMusicLatest": "Recentes", - "ViewTypeMusicPlaylists": "Listas de Reprodu\u00e7\u00e3o", - "ViewTypeMusicAlbums": "\u00c1lbuns", - "ViewTypeMusicAlbumArtists": "Artistas do \u00c1lbum", - "HeaderOtherDisplaySettings": "Ajustes de Exibi\u00e7\u00e3o", - "ViewTypeMusicSongs": "M\u00fasicas", - "ViewTypeMusicFavorites": "Favoritos", - "ViewTypeMusicFavoriteAlbums": "\u00c1lbuns Favoritos", - "ViewTypeMusicFavoriteArtists": "Artistas Favoritos", - "ViewTypeMusicFavoriteSongs": "M\u00fasicas Favoritas", - "ViewTypeFolders": "Pastas", - "ViewTypeLiveTvRecordingGroups": "Grava\u00e7\u00f5es", - "ViewTypeLiveTvChannels": "Canais", - "ScheduledTaskFailedWithName": "{0} falhou", - "LabelRunningTimeValue": "Dura\u00e7\u00e3o: {0}", - "ScheduledTaskStartedWithName": "{0} iniciado", - "VersionNumber": "Vers\u00e3o {0}", - "PluginInstalledWithName": "{0} foi instalado", - "PluginUpdatedWithName": "{0} foi atualizado", - "PluginUninstalledWithName": "{0} foi desinstalado", - "ItemAddedWithName": "{0} foi adicionado \u00e0 biblioteca", - "ItemRemovedWithName": "{0} foi removido da biblioteca", - "LabelIpAddressValue": "Endere\u00e7o Ip: {0}", - "DeviceOnlineWithName": "{0} est\u00e1 conectado", - "UserOnlineFromDevice": "{0} est\u00e1 ativo em {1}", - "ProviderValue": "Provedor: {0}", - "SubtitlesDownloadedForItem": "Legendas baixadas para {0}", - "UserConfigurationUpdatedWithName": "A configura\u00e7\u00e3o do usu\u00e1rio {0} foi atualizada", - "UserCreatedWithName": "O usu\u00e1rio {0} foi criado", - "UserPasswordChangedWithName": "A senha do usu\u00e1rio {0} foi alterada", - "UserDeletedWithName": "O usu\u00e1rio {0} foi exclu\u00eddo", - "MessageServerConfigurationUpdated": "A configura\u00e7\u00e3o do servidor foi atualizada", - "MessageNamedServerConfigurationUpdatedWithValue": "A se\u00e7\u00e3o {0} da configura\u00e7\u00e3o do servidor foi atualizada", - "MessageApplicationUpdated": "O Servidor Emby foi atualizado", - "FailedLoginAttemptWithUserName": "Falha na tentativa de login de {0}", - "AuthenticationSucceededWithUserName": "{0} autenticou-se com sucesso", - "DeviceOfflineWithName": "{0} foi desconectado", - "UserLockedOutWithName": "Usu\u00e1rio {0} foi bloqueado", - "UserOfflineFromDevice": "{0} foi desconectado de {1}", - "UserStartedPlayingItemWithValues": "{0} come\u00e7ou a reproduzir {1}", - "UserStoppedPlayingItemWithValues": "{0} parou de reproduzir {1}", - "SubtitleDownloadFailureForItem": "Falha ao baixar legendas para {0}", - "HeaderUnidentified": "N\u00e3o-identificado", - "HeaderImagePrimary": "Principal", - "HeaderImageBackdrop": "Imagem de Fundo", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "Imagem do Usu\u00e1rio", - "HeaderOverview": "Sinopse", - "HeaderShortOverview": "Sinopse curta", - "HeaderType": "Tipo", - "HeaderSeverity": "Severidade", - "HeaderUser": "Usu\u00e1rio", - "HeaderName": "Nome", - "HeaderDate": "Data", - "HeaderPremiereDate": "Data da Estr\u00e9ia", - "HeaderDateAdded": "Data da Adi\u00e7\u00e3o", - "HeaderReleaseDate": "Data de lan\u00e7amento", - "HeaderRuntime": "Dura\u00e7\u00e3o", - "HeaderPlayCount": "N\u00famero de Reprodu\u00e7\u00f5es", - "HeaderSeason": "Temporada", - "HeaderSeasonNumber": "N\u00famero da temporada", - "HeaderSeries": "S\u00e9rie:", - "HeaderNetwork": "Rede de TV", - "HeaderYear": "Ano:", - "HeaderYears": "Anos:", - "HeaderParentalRating": "Classifica\u00e7\u00e3o Parental", - "HeaderCommunityRating": "Avalia\u00e7\u00e3o da Comunidade", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Especiais", - "HeaderGameSystems": "Sistemas de Jogo", - "HeaderPlayers": "Jogadores:", - "HeaderAlbumArtists": "Artistas do \u00c1lbum", - "HeaderAlbums": "\u00c1lbuns", - "HeaderDisc": "Disco", - "HeaderTrack": "Faixa", - "HeaderAudio": "\u00c1udio", - "HeaderVideo": "V\u00eddeo", - "HeaderEmbeddedImage": "Imagem incorporada", - "HeaderResolution": "Resolu\u00e7\u00e3o", - "HeaderSubtitles": "Legendas", - "HeaderGenres": "G\u00eaneros", - "HeaderCountries": "Pa\u00edses", - "HeaderStatus": "Status", - "HeaderTracks": "Faixas", - "HeaderMusicArtist": "Artista da m\u00fasica", - "HeaderLocked": "Travado", - "HeaderStudios": "Est\u00fadios", - "HeaderActor": "Atores", - "HeaderComposer": "Compositores", - "HeaderDirector": "Diretores", - "HeaderGuestStar": "Ator convidado", - "HeaderProducer": "Produtores", - "HeaderWriter": "Escritores", - "HeaderParentalRatings": "Classifica\u00e7\u00f5es Parentais", - "HeaderCommunityRatings": "Avalia\u00e7\u00f5es da comunidade", - "StartupEmbyServerIsLoading": "O Servidor Emby est\u00e1 carregando. Por favor, tente novamente em breve." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/pt-PT.json b/MediaBrowser.Server.Implementations/Localization/Core/pt-PT.json deleted file mode 100644 index f12939b102..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/pt-PT.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Filmes", - "FolderTypeMusic": "M\u00fasica", - "FolderTypeAdultVideos": "V\u00eddeos adultos", - "FolderTypePhotos": "Fotos", - "FolderTypeMusicVideos": "V\u00eddeos musicais", - "FolderTypeHomeVideos": "V\u00eddeos caseiros", - "FolderTypeGames": "Jogos", - "FolderTypeBooks": "Livros", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Elenco e Equipa", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Sair", - "LabelVisitCommunity": "Visitar a Comunidade", - "LabelGithub": "Github", - "LabelApiDocumentation": "Documenta\u00e7\u00e3o da API", - "LabelDeveloperResources": "Recursos do Programador", - "LabelBrowseLibrary": "Navegar pela Biblioteca", - "LabelConfigureServer": "Configurar o Emby", - "LabelRestartServer": "Reiniciar Servidor", - "CategorySync": "Sincroniza\u00e7\u00e3o", - "CategoryUser": "Utilizador", - "CategorySystem": "Sistema", - "CategoryApplication": "Aplica\u00e7\u00e3o", - "CategoryPlugin": "Extens\u00e3o", - "NotificationOptionPluginError": "Falha na extens\u00e3o", - "NotificationOptionApplicationUpdateAvailable": "Dispon\u00edvel atualiza\u00e7\u00e3o da aplica\u00e7\u00e3o", - "NotificationOptionApplicationUpdateInstalled": "Instalada atualiza\u00e7\u00e3o da aplica\u00e7\u00e3o", - "NotificationOptionPluginUpdateInstalled": "Instalada atualiza\u00e7\u00e3o da extens\u00e3o", - "NotificationOptionPluginInstalled": "Extens\u00e3o instalada", - "NotificationOptionPluginUninstalled": "Extens\u00e3o desinstalada", - "NotificationOptionVideoPlayback": "Reprodu\u00e7\u00e3o de v\u00eddeo iniciada", - "NotificationOptionAudioPlayback": "Reprodu\u00e7\u00e3o de \u00e1udio iniciada", - "NotificationOptionGamePlayback": "Reprodu\u00e7\u00e3o de jogo iniciada", - "NotificationOptionVideoPlaybackStopped": "Reprodu\u00e7\u00e3o de v\u00eddeo parada", - "NotificationOptionAudioPlaybackStopped": "Reprodu\u00e7\u00e3o de \u00e1udio parada", - "NotificationOptionGamePlaybackStopped": "Reprodu\u00e7\u00e3o de jogo parada", - "NotificationOptionTaskFailed": "Falha na tarefa agendada", - "NotificationOptionInstallationFailed": "Falha na instala\u00e7\u00e3o", - "NotificationOptionNewLibraryContent": "Adicionado novo conte\u00fado", - "NotificationOptionNewLibraryContentMultiple": "Novo conte\u00fado adicionado (m\u00faltiplo)", - "NotificationOptionCameraImageUploaded": "Imagem da c\u00e2mara carregada", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "\u00c9 necess\u00e1rio reiniciar o servidor", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "TV ao Vivo", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Reproduzido Recentemente", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "\u00daltimas", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "\u00daltimas", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "\u00daltimas", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Vers\u00e3o {0}", - "PluginInstalledWithName": "{0} foi instalado", - "PluginUpdatedWithName": "{0} foi atualizado", - "PluginUninstalledWithName": "{0} foi desinstalado", - "ItemAddedWithName": "{0} foi adicionado \u00e0 biblioteca", - "ItemRemovedWithName": "{0} foi removido da biblioteca", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} est\u00e1 conectado", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Nome", - "HeaderDate": "Data", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "\u00c1udio", - "HeaderVideo": "V\u00eddeo", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Estado", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ro.json b/MediaBrowser.Server.Implementations/Localization/Core/ro.json deleted file mode 100644 index c58df27d57..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/ro.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Continut mixt", - "FolderTypeMovies": "Filme", - "FolderTypeMusic": "Muzica", - "FolderTypeAdultVideos": "Filme Porno", - "FolderTypePhotos": "Fotografii", - "FolderTypeMusicVideos": "Videoclipuri", - "FolderTypeHomeVideos": "Video Personale", - "FolderTypeGames": "Jocuri", - "FolderTypeBooks": "Carti", - "FolderTypeTvShows": "Seriale TV", - "FolderTypeInherit": "Relationat", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Iesire", - "LabelVisitCommunity": "Viziteaza comunitatea", - "LabelGithub": "Github", - "LabelApiDocumentation": "Documentatie Api", - "LabelDeveloperResources": "Resurse Dezvoltator", - "LabelBrowseLibrary": "Rasfoieste Librarie", - "LabelConfigureServer": "Configureaza Emby", - "LabelRestartServer": "Restarteaza Server", - "CategorySync": "Sincronizeaza", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Muzica", - "HeaderVideo": "Filme", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ru.json b/MediaBrowser.Server.Implementations/Localization/Core/ru.json deleted file mode 100644 index 62fe3b4964..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/ru.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "\u041f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435, \u043f\u043e\u043a\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0432\u0430\u0448\u0435\u043c Emby Server \u043c\u043e\u0434\u0435\u0440\u043d\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f. {0} % \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e.", - "AppDeviceValues": "\u041f\u0440\u0438\u043b.: {0}, \u0423\u0441\u0442\u0440.: {1}", - "UserDownloadingItemWithValues": "{0} \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 {1}", - "FolderTypeMixed": "\u0421\u043c\u0435\u0448\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435", - "FolderTypeMovies": "\u041a\u0438\u043d\u043e", - "FolderTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430", - "FolderTypeAdultVideos": "\u0414\u043b\u044f \u0432\u0437\u0440\u043e\u0441\u043b\u044b\u0445", - "FolderTypePhotos": "\u0424\u043e\u0442\u043e", - "FolderTypeMusicVideos": "\u041c\u0443\u0437. \u0432\u0438\u0434\u0435\u043e", - "FolderTypeHomeVideos": "\u0414\u043e\u043c. \u0432\u0438\u0434\u0435\u043e", - "FolderTypeGames": "\u0418\u0433\u0440\u044b", - "FolderTypeBooks": "\u041b\u0438\u0442\u0435\u0440\u0430\u0442\u0443\u0440\u0430", - "FolderTypeTvShows": "\u0422\u0412", - "FolderTypeInherit": "\u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u044b\u0439", - "HeaderCastCrew": "\u0421\u043d\u0438\u043c\u0430\u043b\u0438\u0441\u044c \u0438 \u0441\u043d\u0438\u043c\u0430\u043b\u0438", - "HeaderPeople": "\u041b\u044e\u0434\u0438", - "ValueSpecialEpisodeName": "\u0421\u043f\u0435\u0446\u044d\u043f\u0438\u0437\u043e\u0434 - {0}", - "LabelChapterName": "\u0421\u0446\u0435\u043d\u0430 {0}", - "NameSeasonNumber": "\u0421\u0435\u0437\u043e\u043d {0}", - "LabelExit": "\u0412\u044b\u0445\u043e\u0434", - "LabelVisitCommunity": "\u041f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u0435 \u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430", - "LabelGithub": "GitHub", - "LabelApiDocumentation": "\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e API", - "LabelDeveloperResources": "\u0420\u0435\u0441\u0443\u0440\u0441\u044b \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432", - "LabelBrowseLibrary": "\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f \u043f\u043e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435", - "LabelConfigureServer": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Emby", - "LabelRestartServer": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430", - "CategorySync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f", - "CategoryUser": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c", - "CategorySystem": "\u0421\u0438\u0441\u0442\u0435\u043c\u0430", - "CategoryApplication": "\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435", - "CategoryPlugin": "\u041f\u043b\u0430\u0433\u0438\u043d", - "NotificationOptionPluginError": "\u0421\u0431\u043e\u0439 \u043f\u043b\u0430\u0433\u0438\u043d\u0430", - "NotificationOptionApplicationUpdateAvailable": "\u0418\u043c\u0435\u0435\u0442\u0441\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f", - "NotificationOptionApplicationUpdateInstalled": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e", - "NotificationOptionPluginUpdateInstalled": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e", - "NotificationOptionPluginInstalled": "\u041f\u043b\u0430\u0433\u0438\u043d \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d", - "NotificationOptionPluginUninstalled": "\u041f\u043b\u0430\u0433\u0438\u043d \u0443\u0434\u0430\u043b\u0451\u043d", - "NotificationOptionVideoPlayback": "\u0412\u043e\u0441\u043f\u0440-\u0438\u0435 \u0432\u0438\u0434\u0435\u043e \u0437\u0430\u043f-\u043d\u043e", - "NotificationOptionAudioPlayback": "\u0412\u043e\u0441\u043f\u0440-\u0438\u0435 \u0430\u0443\u0434\u0438\u043e \u0437\u0430\u043f-\u043d\u043e", - "NotificationOptionGamePlayback": "\u0412\u043e\u0441\u043f\u0440-\u0438\u0435 \u0438\u0433\u0440\u044b \u0437\u0430\u043f-\u043d\u043e", - "NotificationOptionVideoPlaybackStopped": "\u0412\u043e\u0441\u043f-\u0438\u0435 \u0432\u0438\u0434\u0435\u043e \u043e\u0441\u0442-\u043d\u043e", - "NotificationOptionAudioPlaybackStopped": "\u0412\u043e\u0441\u043f-\u0438\u0435 \u0430\u0443\u0434\u0438\u043e \u043e\u0441\u0442-\u043d\u043e", - "NotificationOptionGamePlaybackStopped": "\u0412\u043e\u0441\u043f-\u0438\u0435 \u0438\u0433\u0440\u044b \u043e\u0441\u0442-\u043d\u043e", - "NotificationOptionTaskFailed": "\u0421\u0431\u043e\u0439 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438", - "NotificationOptionInstallationFailed": "\u0421\u0431\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438", - "NotificationOptionNewLibraryContent": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e", - "NotificationOptionNewLibraryContentMultiple": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e (\u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e)", - "NotificationOptionCameraImageUploaded": "\u041f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0430 \u0432\u044b\u043a\u043b\u0430\u0434\u043a\u0430 \u043e\u0442\u0441\u043d\u044f\u0442\u043e\u0433\u043e \u0441 \u043a\u0430\u043c\u0435\u0440\u044b", - "NotificationOptionUserLockedOut": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d", - "NotificationOptionServerRestartRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430", - "ViewTypePlaylists": "\u041f\u043b\u0435\u0439-\u043b\u0438\u0441\u0442\u044b", - "ViewTypeMovies": "\u041a\u0438\u043d\u043e", - "ViewTypeTvShows": "\u0422\u0412", - "ViewTypeGames": "\u0418\u0433\u0440\u044b", - "ViewTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430", - "ViewTypeMusicGenres": "\u0416\u0430\u043d\u0440\u044b", - "ViewTypeMusicArtists": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438", - "ViewTypeBoxSets": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438", - "ViewTypeChannels": "\u041a\u0430\u043d\u0430\u043b\u044b", - "ViewTypeLiveTV": "\u042d\u0444\u0438\u0440", - "ViewTypeLiveTvNowPlaying": "\u0412 \u044d\u0444\u0438\u0440\u0435", - "ViewTypeLatestGames": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0438\u0433\u0440\u044b", - "ViewTypeRecentlyPlayedGames": "C\u044b\u0433\u0440\u0430\u043d\u043d\u044b\u0435 \u043d\u0435\u0434\u0430\u0432\u043d\u043e", - "ViewTypeGameFavorites": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u043e\u0435", - "ViewTypeGameSystems": "\u0418\u0433\u0440\u043e\u0432\u044b\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b", - "ViewTypeGameGenres": "\u0416\u0430\u043d\u0440\u044b", - "ViewTypeTvResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u043e\u0435", - "ViewTypeTvNextUp": "\u041e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0435", - "ViewTypeTvLatest": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435", - "ViewTypeTvShowSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b", - "ViewTypeTvGenres": "\u0416\u0430\u043d\u0440\u044b", - "ViewTypeTvFavoriteSeries": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0438\u0430\u043b\u044b", - "ViewTypeTvFavoriteEpisodes": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b", - "ViewTypeMovieResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u043e\u0435", - "ViewTypeMovieLatest": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435", - "ViewTypeMovieMovies": "\u0424\u0438\u043b\u044c\u043c\u044b", - "ViewTypeMovieCollections": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438", - "ViewTypeMovieFavorites": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u043e\u0435", - "ViewTypeMovieGenres": "\u0416\u0430\u043d\u0440\u044b", - "ViewTypeMusicLatest": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435", - "ViewTypeMusicPlaylists": "\u041f\u043b\u0435\u0439-\u043b\u0438\u0441\u0442\u044b", - "ViewTypeMusicAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u044b", - "ViewTypeMusicAlbumArtists": "\u0418\u0441\u043f-\u043b\u0438 \u0430\u043b\u044c\u0431\u043e\u043c\u0430", - "HeaderOtherDisplaySettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f", - "ViewTypeMusicSongs": "\u041a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u0438", - "ViewTypeMusicFavorites": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u043e\u0435", - "ViewTypeMusicFavoriteAlbums": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0430\u043b\u044c\u0431\u043e\u043c\u044b", - "ViewTypeMusicFavoriteArtists": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438", - "ViewTypeMusicFavoriteSongs": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u0438", - "ViewTypeFolders": "\u041f\u0430\u043f\u043a\u0438", - "ViewTypeLiveTvRecordingGroups": "\u0417\u0430\u043f\u0438\u0441\u0438", - "ViewTypeLiveTvChannels": "\u041a\u0430\u043d\u0430\u043b\u044b", - "ScheduledTaskFailedWithName": "{0} - \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u0430", - "LabelRunningTimeValue": "\u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f: {0}", - "ScheduledTaskStartedWithName": "{0} - \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430", - "VersionNumber": "\u0412\u0435\u0440\u0441\u0438\u044f {0}", - "PluginInstalledWithName": "{0} - \u0431\u044b\u043b\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e", - "PluginUpdatedWithName": "{0} - \u0431\u044b\u043b\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043e", - "PluginUninstalledWithName": "{0} - \u0431\u044b\u043b\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u043e", - "ItemAddedWithName": "{0} (\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0432 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0443)", - "ItemRemovedWithName": "{0} (\u0438\u0437\u044a\u044f\u0442\u043e \u0438\u0437 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438)", - "LabelIpAddressValue": "IP-\u0430\u0434\u0440\u0435\u0441: {0}", - "DeviceOnlineWithName": "{0} - \u043f\u043e\u0434\u043a\u043b. \u0443\u0441\u0442-\u043d\u043e", - "UserOnlineFromDevice": "{0} - \u043f\u043e\u0434\u043a\u043b. \u0441 {1} \u0443\u0441\u0442-\u043d\u043e", - "ProviderValue": "\u041f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a: {0}", - "SubtitlesDownloadedForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u0434\u043b\u044f {0} \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0438\u0441\u044c", - "UserConfigurationUpdatedWithName": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437-\u043b\u044f {0} \u0431\u044b\u043b\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0430", - "UserCreatedWithName": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c {0} \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d", - "UserPasswordChangedWithName": "\u041f\u0430\u0440\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437-\u043b\u044f {0} \u0431\u044b\u043b \u0438\u0437\u043c\u0435\u043d\u0451\u043d", - "UserDeletedWithName": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c {0} \u0431\u044b\u043b \u0443\u0434\u0430\u043b\u0451\u043d", - "MessageServerConfigurationUpdated": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0431\u044b\u043b\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0430", - "MessageNamedServerConfigurationUpdatedWithValue": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 (\u0440\u0430\u0437\u0434\u0435\u043b {0}) \u0431\u044b\u043b\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0430", - "MessageApplicationUpdated": "Emby Server \u0431\u044b\u043b \u043e\u0431\u043d\u043e\u0432\u043b\u0451\u043d", - "FailedLoginAttemptWithUserName": "{0} - \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u0430", - "AuthenticationSucceededWithUserName": "{0} - \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u0430", - "DeviceOfflineWithName": "{0} - \u043f\u043e\u0434\u043a\u043b. \u0440\u0430\u0437\u044a-\u043d\u043e", - "UserLockedOutWithName": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c {0} \u0431\u044b\u043b \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d", - "UserOfflineFromDevice": "{0} - \u043f\u043e\u0434\u043a\u043b. \u0441 {1} \u0440\u0430\u0437\u044a-\u043d\u043e", - "UserStartedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440. \u00ab{1}\u00bb \u0437\u0430\u043f-\u043d\u043e", - "UserStoppedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440. \u00ab{1}\u00bb \u043e\u0441\u0442-\u043d\u043e", - "SubtitleDownloadFailureForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u043a {0} \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c", - "HeaderUnidentified": "\u041d\u0435 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u043e", - "HeaderImagePrimary": "\u0413\u043e\u043b\u043e\u0432\u043d\u043e\u0439", - "HeaderImageBackdrop": "\u0417\u0430\u0434\u043d\u0438\u043a", - "HeaderImageLogo": "\u041b\u043e\u0433\u043e\u0442\u0438\u043f", - "HeaderUserPrimaryImage": "\u0420\u0438\u0441\u0443\u043d\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f", - "HeaderOverview": "\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435", - "HeaderShortOverview": "\u041a\u0440\u0430\u0442\u043a\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435", - "HeaderType": "\u0422\u0438\u043f", - "HeaderSeverity": "\u0412\u0430\u0436\u043d\u043e\u0441\u0442\u044c", - "HeaderUser": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c", - "HeaderName": "\u0418\u043c\u044f (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435)", - "HeaderDate": "\u0414\u0430\u0442\u0430", - "HeaderPremiereDate": "\u0414\u0430\u0442\u0430 \u043f\u0440\u0435\u043c\u044c\u0435\u0440\u044b", - "HeaderDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431.", - "HeaderReleaseDate": "\u0414\u0430\u0442\u0430 \u0432\u044b\u043f.", - "HeaderRuntime": "\u0414\u043b\u0438\u0442.", - "HeaderPlayCount": "\u041a\u043e\u043b-\u0432\u043e \u0432\u043e\u0441\u043f\u0440.", - "HeaderSeason": "\u0421\u0435\u0437\u043e\u043d", - "HeaderSeasonNumber": "\u2116 \u0441\u0435\u0437\u043e\u043d\u0430", - "HeaderSeries": "\u0421\u0435\u0440\u0438\u0430\u043b:", - "HeaderNetwork": "\u0422\u0435\u043b\u0435\u0441\u0435\u0442\u044c", - "HeaderYear": "\u0413\u043e\u0434:", - "HeaderYears": "\u0413\u043e\u0434\u044b:", - "HeaderParentalRating": "\u0412\u043e\u0437\u0440. \u043a\u0430\u0442.", - "HeaderCommunityRating": "\u041e\u0431\u0449. \u043e\u0446\u0435\u043d\u043a\u0430", - "HeaderTrailers": "\u0422\u0440\u0435\u0439\u043b.", - "HeaderSpecials": "\u0421\u043f\u0435\u0446.", - "HeaderGameSystems": "\u0418\u0433\u0440. \u0441\u0438\u0441\u0442\u0435\u043c\u044b", - "HeaderPlayers": "\u0418\u0433\u0440\u043e\u043a\u0438:", - "HeaderAlbumArtists": "\u0418\u0441\u043f-\u043b\u0438 \u0430\u043b\u044c\u0431\u043e\u043c\u0430", - "HeaderAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u044b", - "HeaderDisc": "\u0414\u0438\u0441\u043a", - "HeaderTrack": "\u0414\u043e\u0440-\u043a\u0430", - "HeaderAudio": "\u0410\u0443\u0434\u0438\u043e", - "HeaderVideo": "\u0412\u0438\u0434\u0435\u043e", - "HeaderEmbeddedImage": "\u0412\u043d\u0435\u0434\u0440\u0451\u043d\u043d\u044b\u0439 \u0440\u0438\u0441\u0443\u043d\u043e\u043a", - "HeaderResolution": "\u0420\u0430\u0437\u0440.", - "HeaderSubtitles": "\u0421\u0443\u0431\u0442.", - "HeaderGenres": "\u0416\u0430\u043d\u0440\u044b", - "HeaderCountries": "\u0421\u0442\u0440\u0430\u043d\u044b", - "HeaderStatus": "\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435", - "HeaderTracks": "\u0414\u043e\u0440-\u043a\u0438", - "HeaderMusicArtist": "\u041c\u0443\u0437. \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c", - "HeaderLocked": "\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043e", - "HeaderStudios": "\u0421\u0442\u0443\u0434\u0438\u0438", - "HeaderActor": "\u0410\u043a\u0442\u0451\u0440\u044b", - "HeaderComposer": "\u041a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u044b", - "HeaderDirector": "\u0420\u0435\u0436\u0438\u0441\u0441\u0451\u0440\u044b", - "HeaderGuestStar": "\u041f\u0440\u0438\u0433\u043b. \u0430\u043a\u0442\u0451\u0440", - "HeaderProducer": "\u041f\u0440\u043e\u0434\u044e\u0441\u0435\u0440\u044b", - "HeaderWriter": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0441\u0442\u044b", - "HeaderParentalRatings": "\u0412\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f", - "HeaderCommunityRatings": "\u041e\u0431\u0449. \u043e\u0446\u0435\u043d\u043a\u0438", - "StartupEmbyServerIsLoading": "Emby Server \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u0432 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/sl-SI.json b/MediaBrowser.Server.Implementations/Localization/Core/sl-SI.json deleted file mode 100644 index 0631e3fa88..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/sl-SI.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Prosimo pocakajte podatkovna baza Emby Streznika se posodablja. {0}% koncano.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Izhod", - "LabelVisitCommunity": "Obiscite Skupnost", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Dokumentacija", - "LabelDeveloperResources": "Vsebine za razvijalce", - "LabelBrowseLibrary": "Brskanje po knjiznici", - "LabelConfigureServer": "Emby Nastavitve", - "LabelRestartServer": "Ponovni Zagon Streznika", - "CategorySync": "Sync", - "CategoryUser": "Uporabnik", - "CategorySystem": "Sistem", - "CategoryApplication": "Aplikacija", - "CategoryPlugin": "Vticnik", - "NotificationOptionPluginError": "Napaka v vticniku", - "NotificationOptionApplicationUpdateAvailable": "Na voljo je posodobitev", - "NotificationOptionApplicationUpdateInstalled": "Posodobitev je bila namescena", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Vticnik namescen", - "NotificationOptionPluginUninstalled": "Vticnik odstranjen", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Predvajanje videa koncano", - "NotificationOptionAudioPlaybackStopped": "Predvajanje audia koncano", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Napaka v namestitvi", - "NotificationOptionNewLibraryContent": "Dodana nova vsebina", - "NotificationOptionNewLibraryContentMultiple": "Dodane nove vsebine", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Zahtevan je ponovni zagon", - "ViewTypePlaylists": "Playliste", - "ViewTypeMovies": "Filmi", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Igre", - "ViewTypeMusic": "Glasba", - "ViewTypeMusicGenres": "Zvrsti", - "ViewTypeMusicArtists": "Izvajalci", - "ViewTypeBoxSets": "Zbirke", - "ViewTypeChannels": "Kanali", - "ViewTypeLiveTV": "TV v Zivo", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Zadnje Igre", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Priljubljeno", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Zvrsti", - "ViewTypeTvResume": "Nadaljuj", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Serije", - "ViewTypeTvGenres": "Zvrsti", - "ViewTypeTvFavoriteSeries": "Priljubljene Serije", - "ViewTypeTvFavoriteEpisodes": "Priljubljene Epizode", - "ViewTypeMovieResume": "Nadaljuj", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Filmi", - "ViewTypeMovieCollections": "Zbirke", - "ViewTypeMovieFavorites": "Priljubljeno", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albumi", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Priljubljeni Albumi", - "ViewTypeMusicFavoriteArtists": "Priljubljeni Izvajalci", - "ViewTypeMusicFavoriteSongs": "Priljubljene skladbe", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Verzija {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "Uporabnik", - "HeaderName": "Name", - "HeaderDate": "Datum", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/sv.json b/MediaBrowser.Server.Implementations/Localization/Core/sv.json deleted file mode 100644 index 4a6565affe..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/sv.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "V\u00e4nligen v\u00e4nta medan databasen p\u00e5 din Emby Server uppgraderas. {0}% klar", - "AppDeviceValues": "App: {0}, enhet: {1}", - "UserDownloadingItemWithValues": "{0} laddar ned {1}", - "FolderTypeMixed": "Blandat inneh\u00e5ll", - "FolderTypeMovies": "Filmer", - "FolderTypeMusic": "Musik", - "FolderTypeAdultVideos": "Inneh\u00e5ll f\u00f6r vuxna", - "FolderTypePhotos": "Foton", - "FolderTypeMusicVideos": "Musikvideor", - "FolderTypeHomeVideos": "Hemvideor", - "FolderTypeGames": "Spel", - "FolderTypeBooks": "B\u00f6cker", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "\u00c4rv", - "HeaderCastCrew": "Rollista & bes\u00e4ttning", - "HeaderPeople": "Personer", - "ValueSpecialEpisodeName": "Specialavsnitt - {0}", - "LabelChapterName": "Kapitel {0}", - "NameSeasonNumber": "S\u00e4song {0}", - "LabelExit": "Avsluta", - "LabelVisitCommunity": "Bes\u00f6k v\u00e5rt diskussionsforum", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api-dokumentation", - "LabelDeveloperResources": "Resurser f\u00f6r utvecklare", - "LabelBrowseLibrary": "Bl\u00e4ddra i biblioteket", - "LabelConfigureServer": "Konfigurera Emby", - "LabelRestartServer": "Starta om servern", - "CategorySync": "Synkronisera", - "CategoryUser": "Anv\u00e4ndare", - "CategorySystem": "System", - "CategoryApplication": "App", - "CategoryPlugin": "Till\u00e4gg", - "NotificationOptionPluginError": "Fel uppstod med till\u00e4gget", - "NotificationOptionApplicationUpdateAvailable": "Ny programversion tillg\u00e4nglig", - "NotificationOptionApplicationUpdateInstalled": "Programuppdatering installerad", - "NotificationOptionPluginUpdateInstalled": "Till\u00e4gg har uppdaterats", - "NotificationOptionPluginInstalled": "Till\u00e4gg har installerats", - "NotificationOptionPluginUninstalled": "Till\u00e4gg har avinstallerats", - "NotificationOptionVideoPlayback": "Videouppspelning har p\u00e5b\u00f6rjats", - "NotificationOptionAudioPlayback": "Ljuduppspelning har p\u00e5b\u00f6rjats", - "NotificationOptionGamePlayback": "Spel har startats", - "NotificationOptionVideoPlaybackStopped": "Videouppspelning stoppad", - "NotificationOptionAudioPlaybackStopped": "Ljuduppspelning stoppad", - "NotificationOptionGamePlaybackStopped": "Spel stoppat", - "NotificationOptionTaskFailed": "Schemalagd aktivitet har misslyckats", - "NotificationOptionInstallationFailed": "Fel vid installation", - "NotificationOptionNewLibraryContent": "Nytt inneh\u00e5ll har tillkommit", - "NotificationOptionNewLibraryContentMultiple": "Nytillkommet inneh\u00e5ll finns (flera objekt)", - "NotificationOptionCameraImageUploaded": "Kaberabild uppladdad", - "NotificationOptionUserLockedOut": "Anv\u00e4ndare har l\u00e5sts ute", - "NotificationOptionServerRestartRequired": "Servern m\u00e5ste startas om", - "ViewTypePlaylists": "Spellistor", - "ViewTypeMovies": "Filmer", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Spel", - "ViewTypeMusic": "Musik", - "ViewTypeMusicGenres": "Genrer", - "ViewTypeMusicArtists": "Artister", - "ViewTypeBoxSets": "Samlingar", - "ViewTypeChannels": "Kanaler", - "ViewTypeLiveTV": "Live-TV", - "ViewTypeLiveTvNowPlaying": "Visas nu", - "ViewTypeLatestGames": "Senaste spelen", - "ViewTypeRecentlyPlayedGames": "Nyligen spelade", - "ViewTypeGameFavorites": "Favoriter", - "ViewTypeGameSystems": "Spelsystem", - "ViewTypeGameGenres": "Genrer", - "ViewTypeTvResume": "\u00c5teruppta", - "ViewTypeTvNextUp": "N\u00e4stkommande", - "ViewTypeTvLatest": "Nytillkommet", - "ViewTypeTvShowSeries": "Serier", - "ViewTypeTvGenres": "Genrer", - "ViewTypeTvFavoriteSeries": "Favoritserier", - "ViewTypeTvFavoriteEpisodes": "Favoritavsnitt", - "ViewTypeMovieResume": "\u00c5teruppta", - "ViewTypeMovieLatest": "Nytillkommet", - "ViewTypeMovieMovies": "Filmer", - "ViewTypeMovieCollections": "Samlingar", - "ViewTypeMovieFavorites": "Favoriter", - "ViewTypeMovieGenres": "Genrer", - "ViewTypeMusicLatest": "Nytillkommet", - "ViewTypeMusicPlaylists": "Spellistor", - "ViewTypeMusicAlbums": "Album", - "ViewTypeMusicAlbumArtists": "Albumartister", - "HeaderOtherDisplaySettings": "Visningsalternativ", - "ViewTypeMusicSongs": "L\u00e5tar", - "ViewTypeMusicFavorites": "Favoriter", - "ViewTypeMusicFavoriteAlbums": "Favoritalbum", - "ViewTypeMusicFavoriteArtists": "Favoritartister", - "ViewTypeMusicFavoriteSongs": "Favoritl\u00e5tar", - "ViewTypeFolders": "Mappar", - "ViewTypeLiveTvRecordingGroups": "Inspelningar", - "ViewTypeLiveTvChannels": "Kanaler", - "ScheduledTaskFailedWithName": "{0} misslyckades", - "LabelRunningTimeValue": "Speltid: {0}", - "ScheduledTaskStartedWithName": "{0} startad", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} installerades", - "PluginUpdatedWithName": "{0} uppdaterades", - "PluginUninstalledWithName": "{0} avinstallerades", - "ItemAddedWithName": "{0} lades till i biblioteket", - "ItemRemovedWithName": "{0} togs bort ur biblioteket", - "LabelIpAddressValue": "IP-adress: {0}", - "DeviceOnlineWithName": "{0} \u00e4r ansluten", - "UserOnlineFromDevice": "{0} \u00e4r uppkopplad fr\u00e5n {1}", - "ProviderValue": "K\u00e4lla: {0}", - "SubtitlesDownloadedForItem": "Undertexter har laddats ner f\u00f6r {0}", - "UserConfigurationUpdatedWithName": "Anv\u00e4ndarinst\u00e4llningarna f\u00f6r {0} har uppdaterats", - "UserCreatedWithName": "Anv\u00e4ndaren {0} har skapats", - "UserPasswordChangedWithName": "L\u00f6senordet f\u00f6r {0} har \u00e4ndrats", - "UserDeletedWithName": "Anv\u00e4ndaren {0} har tagits bort", - "MessageServerConfigurationUpdated": "Server konfigurationen har uppdaterats", - "MessageNamedServerConfigurationUpdatedWithValue": "Serverinst\u00e4llningarnas del {0} ar uppdaterats", - "MessageApplicationUpdated": "Emby Server har uppdaterats", - "FailedLoginAttemptWithUserName": "Misslyckat inloggningsf\u00f6rs\u00f6k fr\u00e5n {0}", - "AuthenticationSucceededWithUserName": "{0} har autentiserats", - "DeviceOfflineWithName": "{0} har avbrutit anslutningen", - "UserLockedOutWithName": "Anv\u00e4ndare {0} har l\u00e5sts ute", - "UserOfflineFromDevice": "{0} har avbrutit anslutningen fr\u00e5n {1}", - "UserStartedPlayingItemWithValues": "{0} har p\u00e5b\u00f6rjat uppspelning av {1}", - "UserStoppedPlayingItemWithValues": "{0} har avslutat uppspelning av {1}", - "SubtitleDownloadFailureForItem": "Nerladdning av undertexter f\u00f6r {0} misslyckades", - "HeaderUnidentified": "Oidentifierad", - "HeaderImagePrimary": "Huvudbild", - "HeaderImageBackdrop": "Bakgrundsbild", - "HeaderImageLogo": "Logotyp", - "HeaderUserPrimaryImage": "Anv\u00e4ndarbild", - "HeaderOverview": "\u00d6versikt", - "HeaderShortOverview": "Kort \u00f6versikt", - "HeaderType": "Typ", - "HeaderSeverity": "Severity", - "HeaderUser": "Anv\u00e4ndare", - "HeaderName": "Namn", - "HeaderDate": "Datum", - "HeaderPremiereDate": "Premi\u00e4rdatum", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Premi\u00e4rdatum:", - "HeaderRuntime": "Speltid", - "HeaderPlayCount": "Antal spelningar", - "HeaderSeason": "S\u00e4song", - "HeaderSeasonNumber": "S\u00e4songsnummer:", - "HeaderSeries": "Serie:", - "HeaderNetwork": "TV-bolag", - "HeaderYear": "\u00c5r:", - "HeaderYears": "\u00c5r:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Anv\u00e4ndaromd\u00f6me", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specialavsnitt", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Spelare:", - "HeaderAlbumArtists": "Albumartister", - "HeaderAlbums": "Album", - "HeaderDisc": "Skiva", - "HeaderTrack": "Sp\u00e5r", - "HeaderAudio": "Ljud", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Infogad bild", - "HeaderResolution": "Uppl\u00f6sning", - "HeaderSubtitles": "Undertexter", - "HeaderGenres": "Genrer", - "HeaderCountries": "L\u00e4nder", - "HeaderStatus": "Status", - "HeaderTracks": "Sp\u00e5r", - "HeaderMusicArtist": "Musikartist", - "HeaderLocked": "L\u00e5st", - "HeaderStudios": "Studior", - "HeaderActor": "Sk\u00e5despelare", - "HeaderComposer": "Komposit\u00f6rer", - "HeaderDirector": "Regiss\u00f6r", - "HeaderGuestStar": "G\u00e4startist", - "HeaderProducer": "Producenter", - "HeaderWriter": "F\u00f6rfattare", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server startar. V\u00e4nligen f\u00f6rs\u00f6k igen om en kort stund." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/tr.json b/MediaBrowser.Server.Implementations/Localization/Core/tr.json deleted file mode 100644 index a691e9d025..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/tr.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Cikis", - "LabelVisitCommunity": "Bizi Ziyaret Edin", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "K\u00fct\u00fcphane", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Server Yeniden Baslat", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Uygulamalar", - "CategoryPlugin": "Eklenti", - "NotificationOptionPluginError": "Eklenti Ba\u015far\u0131s\u0131z", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Sunucu yeniden ba\u015flat\u0131lmal\u0131", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Versiyon {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Durum", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/uk.json b/MediaBrowser.Server.Implementations/Localization/Core/uk.json deleted file mode 100644 index 0dc6afe8a2..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/uk.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "\u0424\u0456\u043b\u044c\u043c\u0438", - "FolderTypeMusic": "\u041c\u0443\u0437\u0438\u043a\u0430", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "\u0421\u0432\u0456\u0442\u043b\u0438\u043d\u0438", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "\u0406\u0433\u0440\u0438", - "FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438", - "FolderTypeTvShows": "\u0422\u0411", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "\u0412\u0438\u0439\u0442\u0438", - "LabelVisitCommunity": "Visit Community", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "\u0424\u0456\u043b\u044c\u043c\u0438", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "\u041a\u043e\u043b\u0435\u043a\u0446\u0456\u0457", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "\u041e\u0441\u0442\u0430\u043d\u043d\u0456 \u0456\u0433\u0440\u0438", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "\u0424\u0456\u043b\u044c\u043c\u0438", - "ViewTypeMovieCollections": "\u041a\u043e\u043b\u0435\u043a\u0446\u0456\u0457", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "\u041e\u0441\u0442\u0430\u043d\u043d\u0456", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "\u0421\u0435\u0437\u043e\u043d", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u0438", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u0438", - "HeaderDisc": "\u0414\u0438\u0441\u043a", - "HeaderTrack": "\u0414\u043e\u0440\u0456\u0436\u043a\u0430", - "HeaderAudio": "\u0410\u0443\u0434\u0456\u043e", - "HeaderVideo": "\u0412\u0456\u0434\u0435\u043e", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "\u0414\u043e\u0440\u0456\u0436\u043a\u0438", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "\u0421\u0442\u0443\u0434\u0456\u0457", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/vi.json b/MediaBrowser.Server.Implementations/Localization/Core/vi.json deleted file mode 100644 index 6ea1d1d3fd..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/vi.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Tho\u00e1t", - "LabelVisitCommunity": "Gh\u00e9 th\u0103m trang C\u1ed9ng \u0111\u1ed3ng", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Duy\u1ec7t th\u01b0 vi\u1ec7n", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Kh\u1edfi \u0111\u1ed9ng l\u1ea1i m\u00e1y ch\u1ee7", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "T\u00ean", - "HeaderDate": "Ng\u00e0y", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Tr\u1ea1ng th\u00e1i", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/zh-CN.json b/MediaBrowser.Server.Implementations/Localization/Core/zh-CN.json deleted file mode 100644 index 580832a9ea..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/zh-CN.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App\uff1a {0}\uff0c\u8bbe\u5907\uff1a {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "\u6df7\u5408\u5185\u5bb9", - "FolderTypeMovies": "\u7535\u5f71", - "FolderTypeMusic": "\u97f3\u4e50", - "FolderTypeAdultVideos": "\u6210\u4eba\u89c6\u9891", - "FolderTypePhotos": "\u56fe\u7247", - "FolderTypeMusicVideos": "\u97f3\u4e50\u89c6\u9891", - "FolderTypeHomeVideos": "\u5bb6\u5ead\u89c6\u9891", - "FolderTypeGames": "\u6e38\u620f", - "FolderTypeBooks": "\u4e66\u7c4d", - "FolderTypeTvShows": "\u7535\u89c6", - "FolderTypeInherit": "\u7ee7\u627f", - "HeaderCastCrew": "\u6f14\u804c\u4eba\u5458", - "HeaderPeople": "\u4eba\u7269", - "ValueSpecialEpisodeName": "\u7279\u522b - {0}", - "LabelChapterName": "\u7ae0\u8282 {0}", - "NameSeasonNumber": "\u5b63 {0}", - "LabelExit": "\u9000\u51fa", - "LabelVisitCommunity": "\u8bbf\u95ee\u793e\u533a", - "LabelGithub": "Github", - "LabelApiDocumentation": "API\u6587\u6863", - "LabelDeveloperResources": "\u5f00\u53d1\u8005\u8d44\u6e90", - "LabelBrowseLibrary": "\u6d4f\u89c8\u5a92\u4f53\u5e93", - "LabelConfigureServer": "\u914d\u7f6eEmby", - "LabelRestartServer": "\u91cd\u542f\u670d\u52a1\u5668", - "CategorySync": "\u540c\u6b65", - "CategoryUser": "\u7528\u6237", - "CategorySystem": "\u7cfb\u7edf", - "CategoryApplication": "\u5e94\u7528\u7a0b\u5e8f", - "CategoryPlugin": "\u63d2\u4ef6", - "NotificationOptionPluginError": "\u63d2\u4ef6\u5931\u8d25", - "NotificationOptionApplicationUpdateAvailable": "\u6709\u53ef\u7528\u7684\u5e94\u7528\u7a0b\u5e8f\u66f4\u65b0", - "NotificationOptionApplicationUpdateInstalled": "\u5e94\u7528\u7a0b\u5e8f\u66f4\u65b0\u5df2\u5b89\u88c5", - "NotificationOptionPluginUpdateInstalled": "\u63d2\u4ef6\u66f4\u65b0\u5df2\u5b89\u88c5", - "NotificationOptionPluginInstalled": "\u63d2\u4ef6\u5df2\u5b89\u88c5", - "NotificationOptionPluginUninstalled": "\u63d2\u4ef6\u5df2\u5378\u8f7d", - "NotificationOptionVideoPlayback": "\u89c6\u9891\u5f00\u59cb\u64ad\u653e", - "NotificationOptionAudioPlayback": "\u97f3\u9891\u5f00\u59cb\u64ad\u653e", - "NotificationOptionGamePlayback": "\u6e38\u620f\u5f00\u59cb", - "NotificationOptionVideoPlaybackStopped": "\u89c6\u9891\u64ad\u653e\u505c\u6b62", - "NotificationOptionAudioPlaybackStopped": "\u97f3\u9891\u64ad\u653e\u505c\u6b62", - "NotificationOptionGamePlaybackStopped": "\u6e38\u620f\u505c\u6b62", - "NotificationOptionTaskFailed": "\u8ba1\u5212\u4efb\u52a1\u5931\u8d25", - "NotificationOptionInstallationFailed": "\u5b89\u88c5\u5931\u8d25", - "NotificationOptionNewLibraryContent": "\u6dfb\u52a0\u65b0\u5185\u5bb9", - "NotificationOptionNewLibraryContentMultiple": "\u65b0\u7684\u5185\u5bb9\u52a0\u5165\uff08\u591a\u4e2a\uff09", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "\u9700\u8981\u91cd\u65b0\u542f\u52a8\u670d\u52a1\u5668", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "\u7535\u5f71", - "ViewTypeTvShows": "\u7535\u89c6", - "ViewTypeGames": "\u6e38\u620f", - "ViewTypeMusic": "\u97f3\u4e50", - "ViewTypeMusicGenres": "\u98ce\u683c", - "ViewTypeMusicArtists": "\u827a\u672f\u5bb6", - "ViewTypeBoxSets": "\u5408\u96c6", - "ViewTypeChannels": "\u9891\u9053", - "ViewTypeLiveTV": "\u7535\u89c6\u76f4\u64ad", - "ViewTypeLiveTvNowPlaying": "\u73b0\u5728\u64ad\u653e", - "ViewTypeLatestGames": "\u6700\u65b0\u6e38\u620f", - "ViewTypeRecentlyPlayedGames": "\u6700\u8fd1\u64ad\u653e", - "ViewTypeGameFavorites": "\u6211\u7684\u6700\u7231", - "ViewTypeGameSystems": "\u6e38\u620f\u7cfb\u7edf", - "ViewTypeGameGenres": "\u98ce\u683c", - "ViewTypeTvResume": "\u6062\u590d\u64ad\u653e", - "ViewTypeTvNextUp": "\u4e0b\u4e00\u4e2a", - "ViewTypeTvLatest": "\u6700\u65b0", - "ViewTypeTvShowSeries": "\u7535\u89c6\u5267", - "ViewTypeTvGenres": "\u98ce\u683c", - "ViewTypeTvFavoriteSeries": "\u6700\u559c\u6b22\u7684\u7535\u89c6\u5267", - "ViewTypeTvFavoriteEpisodes": "\u6700\u559c\u6b22\u7684\u5267\u96c6", - "ViewTypeMovieResume": "\u6062\u590d\u64ad\u653e", - "ViewTypeMovieLatest": "\u6700\u65b0", - "ViewTypeMovieMovies": "\u7535\u5f71", - "ViewTypeMovieCollections": "\u5408\u96c6", - "ViewTypeMovieFavorites": "\u6536\u85cf\u5939", - "ViewTypeMovieGenres": "\u98ce\u683c", - "ViewTypeMusicLatest": "\u6700\u65b0", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "\u4e13\u8f91", - "ViewTypeMusicAlbumArtists": "\u4e13\u8f91\u827a\u672f\u5bb6", - "HeaderOtherDisplaySettings": "\u663e\u793a\u8bbe\u7f6e", - "ViewTypeMusicSongs": "\u6b4c\u66f2", - "ViewTypeMusicFavorites": "\u6211\u7684\u6700\u7231", - "ViewTypeMusicFavoriteAlbums": "\u6700\u7231\u7684\u4e13\u8f91", - "ViewTypeMusicFavoriteArtists": "\u6700\u7231\u7684\u827a\u672f\u5bb6", - "ViewTypeMusicFavoriteSongs": "\u6700\u7231\u7684\u6b4c\u66f2", - "ViewTypeFolders": "\u6587\u4ef6\u5939", - "ViewTypeLiveTvRecordingGroups": "\u5f55\u5236", - "ViewTypeLiveTvChannels": "\u9891\u9053", - "ScheduledTaskFailedWithName": "{0} \u5931\u8d25", - "LabelRunningTimeValue": "\u8fd0\u884c\u65f6\u95f4\uff1a {0}", - "ScheduledTaskStartedWithName": "{0} \u5f00\u59cb", - "VersionNumber": "\u7248\u672c {0}", - "PluginInstalledWithName": "{0} \u5df2\u5b89\u88c5", - "PluginUpdatedWithName": "{0} \u5df2\u66f4\u65b0", - "PluginUninstalledWithName": "{0} \u5df2\u5378\u8f7d", - "ItemAddedWithName": "{0} \u5df2\u6dfb\u52a0\u5230\u5a92\u4f53\u5e93", - "ItemRemovedWithName": "{0} \u5df2\u4ece\u5a92\u4f53\u5e93\u4e2d\u79fb\u9664", - "LabelIpAddressValue": "Ip \u5730\u5740\uff1a {0}", - "DeviceOnlineWithName": "{0} \u5df2\u8fde\u63a5", - "UserOnlineFromDevice": "{0} \u5728\u7ebf\uff0c\u6765\u81ea {1}", - "ProviderValue": "\u63d0\u4f9b\u8005\uff1a {0}", - "SubtitlesDownloadedForItem": "\u5df2\u4e3a {0} \u4e0b\u8f7d\u4e86\u5b57\u5e55", - "UserConfigurationUpdatedWithName": "\u7528\u6237\u914d\u7f6e\u5df2\u66f4\u65b0\u4e3a {0}", - "UserCreatedWithName": "\u7528\u6237 {0} \u5df2\u88ab\u521b\u5efa", - "UserPasswordChangedWithName": "\u5df2\u4e3a\u7528\u6237 {0} \u66f4\u6539\u5bc6\u7801", - "UserDeletedWithName": "\u7528\u6237 {0} \u5df2\u88ab\u5220\u9664", - "MessageServerConfigurationUpdated": "\u670d\u52a1\u5668\u914d\u7f6e\u5df2\u66f4\u65b0", - "MessageNamedServerConfigurationUpdatedWithValue": "\u670d\u52a1\u5668\u914d\u7f6e {0} \u90e8\u5206\u5df2\u66f4\u65b0", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "\u5931\u8d25\u7684\u767b\u5f55\u5c1d\u8bd5\uff0c\u6765\u81ea {0}", - "AuthenticationSucceededWithUserName": "{0} \u6210\u529f\u88ab\u6388\u6743", - "DeviceOfflineWithName": "{0} \u5df2\u65ad\u5f00\u8fde\u63a5", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} \u5df2\u4ece {1} \u65ad\u5f00\u8fde\u63a5", - "UserStartedPlayingItemWithValues": "{0} \u5f00\u59cb\u64ad\u653e {1}", - "UserStoppedPlayingItemWithValues": "{0} \u505c\u6b62\u64ad\u653e {1}", - "SubtitleDownloadFailureForItem": "\u4e3a {0} \u4e0b\u8f7d\u5b57\u5e55\u5931\u8d25", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "\u7528\u6237", - "HeaderName": "\u540d\u5b57", - "HeaderDate": "\u65e5\u671f", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "\u53d1\u884c\u65e5\u671f", - "HeaderRuntime": "\u64ad\u653e\u65f6\u95f4", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "\u5b63", - "HeaderSeasonNumber": "\u591a\u5c11\u5b63", - "HeaderSeries": "Series:", - "HeaderNetwork": "\u7f51\u7edc", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "\u516c\u4f17\u8bc4\u5206", - "HeaderTrailers": "\u9884\u544a\u7247", - "HeaderSpecials": "\u7279\u96c6", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "\u4e13\u8f91", - "HeaderDisc": "\u5149\u76d8", - "HeaderTrack": "\u97f3\u8f68", - "HeaderAudio": "\u97f3\u9891", - "HeaderVideo": "\u89c6\u9891", - "HeaderEmbeddedImage": "\u5d4c\u5165\u5f0f\u56fe\u50cf", - "HeaderResolution": "\u5206\u8fa8\u7387", - "HeaderSubtitles": "\u5b57\u5e55", - "HeaderGenres": "\u98ce\u683c", - "HeaderCountries": "\u56fd\u5bb6", - "HeaderStatus": "\u72b6\u6001", - "HeaderTracks": "\u97f3\u8f68", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "\u5de5\u4f5c\u5ba4", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "\u5bb6\u957f\u5206\u7ea7", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/zh-HK.json b/MediaBrowser.Server.Implementations/Localization/Core/zh-HK.json deleted file mode 100644 index a70e7a0035..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/zh-HK.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "\u6df7\u5408\u5167\u5bb9", - "FolderTypeMovies": "\u96fb\u5f71", - "FolderTypeMusic": "\u97f3\u6a02", - "FolderTypeAdultVideos": "\u6210\u4eba\u5f71\u7247", - "FolderTypePhotos": "\u76f8\u7247", - "FolderTypeMusicVideos": "MV", - "FolderTypeHomeVideos": "\u500b\u4eba\u5f71\u7247", - "FolderTypeGames": "\u904a\u6232", - "FolderTypeBooks": "\u66f8\u85c9", - "FolderTypeTvShows": "\u96fb\u8996\u7bc0\u76ee", - "FolderTypeInherit": "\u7e7c\u627f", - "HeaderCastCrew": "\u6f14\u54e1\u9663\u5bb9", - "HeaderPeople": "\u4eba\u7269", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "\u5287\u96c6\u5b63\u5ea6 {0}", - "LabelExit": "\u96e2\u958b", - "LabelVisitCommunity": "\u8a2a\u554f\u8a0e\u8ad6\u5340", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api \u6587\u4ef6", - "LabelDeveloperResources": "\u958b\u767c\u8005\u8cc7\u6e90", - "LabelBrowseLibrary": "\u700f\u89bd\u8cc7\u6599\u5eab", - "LabelConfigureServer": "\u8a2d\u7f6e Emby", - "LabelRestartServer": "\u91cd\u65b0\u555f\u52d5\u4f3a\u670d\u5668", - "CategorySync": "\u540c\u6b65", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "\u9700\u8981\u91cd\u65b0\u555f\u52d5", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "\u904a\u6232", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "\u85cf\u54c1", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "\u6700\u8fd1\u904a\u6232", - "ViewTypeRecentlyPlayedGames": "\u6700\u8fd1\u64ad\u653e", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "\u904a\u6232\u7cfb\u7d71", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "\u96fb\u8996\u5287", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "\u6211\u7684\u6700\u611b\u96fb\u8996\u5287", - "ViewTypeTvFavoriteEpisodes": "\u6211\u7684\u6700\u611b\u5287\u96c6", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "\u85cf\u54c1", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "\u6b4c\u66f2", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "\u6211\u7684\u6700\u611b\u6b4c\u66f2", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "\u7248\u672c {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "\u5df2\u7d93\u70ba {0} \u4e0b\u8f09\u4e86\u5b57\u5e55", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "\u70ba {0} \u4e0b\u8f09\u5b57\u5e55\u5931\u6557", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "\u540d\u7a31", - "HeaderDate": "\u65e5\u671f", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "\u5287\u96c6\u5b63\u5ea6", - "HeaderSeasonNumber": "\u5287\u96c6\u5b63\u5ea6\u6578\u76ee", - "HeaderSeries": "\u96fb\u8996\u5287\uff1a", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "\u904a\u6232\u7cfb\u7d71", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "\u97f3\u8a0a", - "HeaderVideo": "\u5f71\u7247", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "\u5b57\u5e55", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "\u72c0\u614b", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "\u6b4c\u624b", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "\u7279\u7d04\u660e\u661f", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json b/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json deleted file mode 100644 index b711aab1f2..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "DbUpgradeMessage": "\u8acb\u7a0d\u5019\uff0cEmby\u4f3a\u670d\u5668\u8cc7\u6599\u5eab\u6b63\u5728\u66f4\u65b0...\uff08\u5df2\u5b8c\u6210{0}%\uff09", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "\u62cd\u651d\u4eba\u54e1\u53ca\u6f14\u54e1", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "\u96e2\u958b", - "LabelVisitCommunity": "\u8a2a\u554f\u793e\u7fa4", - "LabelGithub": "GitHub", - "LabelApiDocumentation": "API\u8aaa\u660e\u6587\u4ef6", - "LabelDeveloperResources": "\u958b\u767c\u4eba\u54e1\u5c08\u5340", - "LabelBrowseLibrary": "\u700f\u89bd\u5a92\u9ad4\u6ac3", - "LabelConfigureServer": "Emby\u8a2d\u5b9a", - "LabelRestartServer": "\u91cd\u65b0\u555f\u52d5\u4f3a\u670d\u5668", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "\u96fb\u8996", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "\u7248\u672c{0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "DeviceOfflineWithName": "{0} has disconnected", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "\u72c0\u614b", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs deleted file mode 100644 index ec544dd70c..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs +++ /dev/null @@ -1,406 +0,0 @@ -using MediaBrowser.Model.Extensions; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Localization; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection; -using CommonIO; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.Localization -{ - /// <summary> - /// Class LocalizationManager - /// </summary> - public class LocalizationManager : ILocalizationManager - { - /// <summary> - /// The _configuration manager - /// </summary> - private readonly IServerConfigurationManager _configurationManager; - - /// <summary> - /// The us culture - /// </summary> - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - private readonly ConcurrentDictionary<string, Dictionary<string, ParentalRating>> _allParentalRatings = - new ConcurrentDictionary<string, Dictionary<string, ParentalRating>>(StringComparer.OrdinalIgnoreCase); - - private readonly IFileSystem _fileSystem; - private readonly IJsonSerializer _jsonSerializer; - private readonly ILogger _logger; - - /// <summary> - /// Initializes a new instance of the <see cref="LocalizationManager" /> class. - /// </summary> - /// <param name="configurationManager">The configuration manager.</param> - /// <param name="fileSystem">The file system.</param> - /// <param name="jsonSerializer">The json serializer.</param> - public LocalizationManager(IServerConfigurationManager configurationManager, IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger) - { - _configurationManager = configurationManager; - _fileSystem = fileSystem; - _jsonSerializer = jsonSerializer; - _logger = logger; - - ExtractAll(); - } - - private void ExtractAll() - { - var type = GetType(); - var resourcePath = type.Namespace + ".Ratings."; - - var localizationPath = LocalizationPath; - - _fileSystem.CreateDirectory(localizationPath); - - var existingFiles = Directory.EnumerateFiles(localizationPath, "ratings-*.txt", SearchOption.TopDirectoryOnly) - .Select(Path.GetFileName) - .ToList(); - - // Extract from the assembly - foreach (var resource in type.Assembly - .GetManifestResourceNames() - .Where(i => i.StartsWith(resourcePath))) - { - var filename = "ratings-" + resource.Substring(resourcePath.Length); - - if (!existingFiles.Contains(filename)) - { - using (var stream = type.Assembly.GetManifestResourceStream(resource)) - { - var target = Path.Combine(localizationPath, filename); - _logger.Info("Extracting ratings to {0}", target); - - using (var fs = _fileSystem.GetFileStream(target, FileMode.Create, FileAccess.Write, FileShare.Read)) - { - stream.CopyTo(fs); - } - } - } - } - - foreach (var file in Directory.EnumerateFiles(localizationPath, "ratings-*.txt", SearchOption.TopDirectoryOnly)) - { - LoadRatings(file); - } - } - - /// <summary> - /// Gets the localization path. - /// </summary> - /// <value>The localization path.</value> - public string LocalizationPath - { - get - { - return Path.Combine(_configurationManager.ApplicationPaths.ProgramDataPath, "localization"); - } - } - - /// <summary> - /// Gets the cultures. - /// </summary> - /// <returns>IEnumerable{CultureDto}.</returns> - public IEnumerable<CultureDto> GetCultures() - { - var type = GetType(); - var path = type.Namespace + ".iso6392.txt"; - - var list = new List<CultureDto>(); - - using (var stream = type.Assembly.GetManifestResourceStream(path)) - { - using (var reader = new StreamReader(stream)) - { - while (!reader.EndOfStream) - { - var line = reader.ReadLine(); - - if (!string.IsNullOrWhiteSpace(line)) - { - var parts = line.Split('|'); - - if (parts.Length == 5) - { - list.Add(new CultureDto - { - DisplayName = parts[3], - Name = parts[3], - ThreeLetterISOLanguageName = parts[0], - TwoLetterISOLanguageName = parts[2] - }); - } - } - } - } - } - - return list.Where(i => !string.IsNullOrWhiteSpace(i.Name) && - !string.IsNullOrWhiteSpace(i.DisplayName) && - !string.IsNullOrWhiteSpace(i.ThreeLetterISOLanguageName) && - !string.IsNullOrWhiteSpace(i.TwoLetterISOLanguageName)); - } - - /// <summary> - /// Gets the countries. - /// </summary> - /// <returns>IEnumerable{CountryInfo}.</returns> - public IEnumerable<CountryInfo> GetCountries() - { - var type = GetType(); - var path = type.Namespace + ".countries.json"; - - using (var stream = type.Assembly.GetManifestResourceStream(path)) - { - return _jsonSerializer.DeserializeFromStream<List<CountryInfo>>(stream); - } - } - - /// <summary> - /// Gets the parental ratings. - /// </summary> - /// <returns>IEnumerable{ParentalRating}.</returns> - public IEnumerable<ParentalRating> GetParentalRatings() - { - return GetParentalRatingsDictionary().Values.ToList(); - } - - /// <summary> - /// Gets the parental ratings dictionary. - /// </summary> - /// <returns>Dictionary{System.StringParentalRating}.</returns> - private Dictionary<string, ParentalRating> GetParentalRatingsDictionary() - { - var countryCode = _configurationManager.Configuration.MetadataCountryCode; - - if (string.IsNullOrEmpty(countryCode)) - { - countryCode = "us"; - } - - var ratings = GetRatings(countryCode); - - if (ratings == null) - { - ratings = GetRatings("us"); - } - - return ratings; - } - - /// <summary> - /// Gets the ratings. - /// </summary> - /// <param name="countryCode">The country code.</param> - private Dictionary<string, ParentalRating> GetRatings(string countryCode) - { - Dictionary<string, ParentalRating> value; - - _allParentalRatings.TryGetValue(countryCode, out value); - - return value; - } - - /// <summary> - /// Loads the ratings. - /// </summary> - /// <param name="file">The file.</param> - /// <returns>Dictionary{System.StringParentalRating}.</returns> - private void LoadRatings(string file) - { - var dict = File.ReadAllLines(file).Select(i => - { - if (!string.IsNullOrWhiteSpace(i)) - { - var parts = i.Split(','); - - if (parts.Length == 2) - { - int value; - - if (int.TryParse(parts[1], NumberStyles.Integer, UsCulture, out value)) - { - return new ParentalRating { Name = parts[0], Value = value }; - } - } - } - - return null; - - }) - .Where(i => i != null) - .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); - - var countryCode = _fileSystem.GetFileNameWithoutExtension(file) - .Split('-') - .Last(); - - _allParentalRatings.TryAdd(countryCode, dict); - } - - private readonly string[] _unratedValues = {"n/a", "unrated", "not rated"}; - - /// <summary> - /// Gets the rating level. - /// </summary> - public int? GetRatingLevel(string rating) - { - if (string.IsNullOrEmpty(rating)) - { - throw new ArgumentNullException("rating"); - } - - if (_unratedValues.Contains(rating, StringComparer.OrdinalIgnoreCase)) - { - return null; - } - - // Fairly common for some users to have "Rated R" in their rating field - rating = rating.Replace("Rated ", string.Empty, StringComparison.OrdinalIgnoreCase); - - var ratingsDictionary = GetParentalRatingsDictionary(); - - ParentalRating value; - - if (!ratingsDictionary.TryGetValue(rating, out value)) - { - // If we don't find anything check all ratings systems - foreach (var dictionary in _allParentalRatings.Values) - { - if (dictionary.TryGetValue(rating, out value)) - { - return value.Value; - } - } - } - - return value == null ? (int?)null : value.Value; - } - - public string GetLocalizedString(string phrase) - { - return GetLocalizedString(phrase, _configurationManager.Configuration.UICulture); - } - - public string GetLocalizedString(string phrase, string culture) - { - var dictionary = GetLocalizationDictionary(culture); - - string value; - - if (dictionary.TryGetValue(phrase, out value)) - { - return value; - } - - return phrase; - } - - private readonly ConcurrentDictionary<string, Dictionary<string, string>> _dictionaries = - new ConcurrentDictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); - - public Dictionary<string, string> GetLocalizationDictionary(string culture) - { - const string prefix = "Core"; - var key = prefix + culture; - - return _dictionaries.GetOrAdd(key, k => GetDictionary(prefix, culture, "core.json")); - } - - private Dictionary<string, string> GetDictionary(string prefix, string culture, string baseFilename) - { - var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - - var assembly = GetType().Assembly; - var namespaceName = GetType().Namespace + "." + prefix; - - CopyInto(dictionary, namespaceName + "." + baseFilename, assembly); - CopyInto(dictionary, namespaceName + "." + GetResourceFilename(culture), assembly); - - return dictionary; - } - - private void CopyInto(IDictionary<string, string> dictionary, string resourcePath, Assembly assembly) - { - using (var stream = assembly.GetManifestResourceStream(resourcePath)) - { - if (stream != null) - { - var dict = _jsonSerializer.DeserializeFromStream<Dictionary<string, string>>(stream); - - foreach (var key in dict.Keys) - { - dictionary[key] = dict[key]; - } - } - } - } - - private string GetResourceFilename(string culture) - { - var parts = culture.Split('-'); - - if (parts.Length == 2) - { - culture = parts[0].ToLower() + "-" + parts[1].ToUpper(); - } - else - { - culture = culture.ToLower(); - } - - return culture + ".json"; - } - - public IEnumerable<LocalizatonOption> GetLocalizationOptions() - { - return new List<LocalizatonOption> - { - new LocalizatonOption{ Name="Arabic", Value="ar"}, - new LocalizatonOption{ Name="Bulgarian (Bulgaria)", Value="bg-BG"}, - new LocalizatonOption{ Name="Catalan", Value="ca"}, - new LocalizatonOption{ Name="Chinese Simplified", Value="zh-CN"}, - new LocalizatonOption{ Name="Chinese Traditional", Value="zh-TW"}, - new LocalizatonOption{ Name="Croatian", Value="hr"}, - new LocalizatonOption{ Name="Czech", Value="cs"}, - new LocalizatonOption{ Name="Danish", Value="da"}, - new LocalizatonOption{ Name="Dutch", Value="nl"}, - new LocalizatonOption{ Name="English (United Kingdom)", Value="en-GB"}, - new LocalizatonOption{ Name="English (United States)", Value="en-us"}, - new LocalizatonOption{ Name="Finnish", Value="fi"}, - new LocalizatonOption{ Name="French", Value="fr"}, - new LocalizatonOption{ Name="French (Canada)", Value="fr-CA"}, - new LocalizatonOption{ Name="German", Value="de"}, - new LocalizatonOption{ Name="Greek", Value="el"}, - new LocalizatonOption{ Name="Hebrew", Value="he"}, - new LocalizatonOption{ Name="Hungarian", Value="hu"}, - new LocalizatonOption{ Name="Indonesian", Value="id"}, - new LocalizatonOption{ Name="Italian", Value="it"}, - new LocalizatonOption{ Name="Kazakh", Value="kk"}, - new LocalizatonOption{ Name="Norwegian Bokmål", Value="nb"}, - new LocalizatonOption{ Name="Polish", Value="pl"}, - new LocalizatonOption{ Name="Portuguese (Brazil)", Value="pt-BR"}, - new LocalizatonOption{ Name="Portuguese (Portugal)", Value="pt-PT"}, - new LocalizatonOption{ Name="Russian", Value="ru"}, - new LocalizatonOption{ Name="Slovenian (Slovenia)", Value="sl-SI"}, - new LocalizatonOption{ Name="Spanish", Value="es-ES"}, - new LocalizatonOption{ Name="Spanish (Mexico)", Value="es-MX"}, - new LocalizatonOption{ Name="Swedish", Value="sv"}, - new LocalizatonOption{ Name="Turkish", Value="tr"}, - new LocalizatonOption{ Name="Ukrainian", Value="uk"}, - new LocalizatonOption{ Name="Vietnamese", Value="vi"} - - }.OrderBy(i => i.Name); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/au.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/au.txt deleted file mode 100644 index fa60f53055..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/au.txt +++ /dev/null @@ -1,8 +0,0 @@ -AU-G,1 -AU-PG,5 -AU-M,6 -AU-MA15+,7 -AU-M15+,8 -AU-R18+,9 -AU-X18+,10 -AU-RC,11 diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/be.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/be.txt deleted file mode 100644 index 99a53f664a..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/be.txt +++ /dev/null @@ -1,6 +0,0 @@ -BE-AL,1 -BE-MG6,2 -BE-6,3 -BE-9,5 -BE-12,6 -BE-16,8
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/br.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/br.txt deleted file mode 100644 index 62f00fb87e..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/br.txt +++ /dev/null @@ -1,6 +0,0 @@ -BR-L,1 -BR-10,5 -BR-12,7 -BR-14,8 -BR-16,8 -BR-18,9
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/ca.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/ca.txt deleted file mode 100644 index 5a110648cd..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/ca.txt +++ /dev/null @@ -1,6 +0,0 @@ -CA-G,1 -CA-PG,5 -CA-14A,7 -CA-A,8 -CA-18A,9 -CA-R,10
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/co.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/co.txt deleted file mode 100644 index a694a0be66..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/co.txt +++ /dev/null @@ -1,8 +0,0 @@ -CO-T,1 -CO-7,5 -CO-12,7 -CO-15,8 -CO-18,10 -CO-X,100 -CO-BANNED,15 -CO-E,15
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/de.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/de.txt deleted file mode 100644 index ad1f186197..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/de.txt +++ /dev/null @@ -1,10 +0,0 @@ -DE-0,1 -FSK-0,1 -DE-6,5 -FSK-6,5 -DE-12,7 -FSK-12,7 -DE-16,8 -FSK-16,8 -DE-18,9 -FSK-18,9
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/dk.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/dk.txt deleted file mode 100644 index b9a085e012..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/dk.txt +++ /dev/null @@ -1,4 +0,0 @@ -DA-A,1 -DA-7,5 -DA-11,6 -DA-15,8
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/fr.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/fr.txt deleted file mode 100644 index 2bb205b0da..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/fr.txt +++ /dev/null @@ -1,5 +0,0 @@ -FR-U,1 -FR-10,5 -FR-12,7 -FR-16,9 -FR-18,10
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/gb.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/gb.txt deleted file mode 100644 index c1f7d04529..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/gb.txt +++ /dev/null @@ -1,7 +0,0 @@ -GB-U,1 -GB-PG,5 -GB-12,6 -GB-12A,7 -GB-15,8 -GB-18,9 -GB-R18,15 diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/ie.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/ie.txt deleted file mode 100644 index 283f077672..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/ie.txt +++ /dev/null @@ -1,6 +0,0 @@ -IE-G,1 -IE-PG,5 -IE-12A,7 -IE-15A,8 -IE-16,9 -IE-18,10
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/jp.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/jp.txt deleted file mode 100644 index 2e1da30d81..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/jp.txt +++ /dev/null @@ -1,4 +0,0 @@ -JP-G,1 -JP-PG12,7 -JP-15+,8 -JP-18+,10
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/kz.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/kz.txt deleted file mode 100644 index b31e12d969..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/kz.txt +++ /dev/null @@ -1,6 +0,0 @@ -KZ-К,1 -KZ-БА,6 -KZ-Б14,7 -KZ-Е16,8 -KZ-Е18,10 -KZ-НА,15
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/mx.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/mx.txt deleted file mode 100644 index 93b609c3d9..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/mx.txt +++ /dev/null @@ -1,6 +0,0 @@ -MX-AA,1 -MX-A,5 -MX-B,7 -MX-B-15,8 -MX-C,9 -MX-D,10
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/nl.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/nl.txt deleted file mode 100644 index f69cc2bcc9..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/nl.txt +++ /dev/null @@ -1,6 +0,0 @@ -NL-AL,1 -NL-MG6,2 -NL-6,3 -NL-9,5 -NL-12,6 -NL-16,8
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/nz.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/nz.txt deleted file mode 100644 index bc761dcab0..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/nz.txt +++ /dev/null @@ -1,10 +0,0 @@ -NZ-G,1 -NZ-PG,5 -NZ-M,9 -NZ-R13,7 -NZ-R15,8 -NZ-R16,9 -NZ-R18,10 -NZ-RP13,7 -NZ-RP16,9 -NZ-R,10
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/ru.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/ru.txt deleted file mode 100644 index 1bc94affd6..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/ru.txt +++ /dev/null @@ -1,5 +0,0 @@ -RU-0+,1 -RU-6+,3 -RU-12+,7 -RU-16+,9 -RU-18+,10 diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/us.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/us.txt deleted file mode 100644 index 3f5311e0ea..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/us.txt +++ /dev/null @@ -1,22 +0,0 @@ -G,1 -E,1 -EC,1 -TV-G,1 -TV-Y,2 -TV-Y7,3 -TV-Y7-FV,4 -PG,5 -TV-PG,5 -PG-13,7 -T,7 -TV-14,8 -R,9 -M,9 -TV-MA,9 -NC-17,10 -AO,15 -RP,15 -UR,15 -NR,15 -X,15 -XXX,100
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/countries.json b/MediaBrowser.Server.Implementations/Localization/countries.json deleted file mode 100644 index e671b36853..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/countries.json +++ /dev/null @@ -1 +0,0 @@ -[{"Name":"AF","DisplayName":"Afghanistan","TwoLetterISORegionName":"AF","ThreeLetterISORegionName":"AFG"},{"Name":"AL","DisplayName":"Albania","TwoLetterISORegionName":"AL","ThreeLetterISORegionName":"ALB"},{"Name":"DZ","DisplayName":"Algeria","TwoLetterISORegionName":"DZ","ThreeLetterISORegionName":"DZA"},{"Name":"AR","DisplayName":"Argentina","TwoLetterISORegionName":"AR","ThreeLetterISORegionName":"ARG"},{"Name":"AM","DisplayName":"Armenia","TwoLetterISORegionName":"AM","ThreeLetterISORegionName":"ARM"},{"Name":"AU","DisplayName":"Australia","TwoLetterISORegionName":"AU","ThreeLetterISORegionName":"AUS"},{"Name":"AT","DisplayName":"Austria","TwoLetterISORegionName":"AT","ThreeLetterISORegionName":"AUT"},{"Name":"AZ","DisplayName":"Azerbaijan","TwoLetterISORegionName":"AZ","ThreeLetterISORegionName":"AZE"},{"Name":"BH","DisplayName":"Bahrain","TwoLetterISORegionName":"BH","ThreeLetterISORegionName":"BHR"},{"Name":"BD","DisplayName":"Bangladesh","TwoLetterISORegionName":"BD","ThreeLetterISORegionName":"BGD"},{"Name":"BY","DisplayName":"Belarus","TwoLetterISORegionName":"BY","ThreeLetterISORegionName":"BLR"},{"Name":"BE","DisplayName":"Belgium","TwoLetterISORegionName":"BE","ThreeLetterISORegionName":"BEL"},{"Name":"BZ","DisplayName":"Belize","TwoLetterISORegionName":"BZ","ThreeLetterISORegionName":"BLZ"},{"Name":"VE","DisplayName":"Bolivarian Republic of Venezuela","TwoLetterISORegionName":"VE","ThreeLetterISORegionName":"VEN"},{"Name":"BO","DisplayName":"Bolivia","TwoLetterISORegionName":"BO","ThreeLetterISORegionName":"BOL"},{"Name":"BA","DisplayName":"Bosnia and Herzegovina","TwoLetterISORegionName":"BA","ThreeLetterISORegionName":"BIH"},{"Name":"BW","DisplayName":"Botswana","TwoLetterISORegionName":"BW","ThreeLetterISORegionName":"BWA"},{"Name":"BR","DisplayName":"Brazil","TwoLetterISORegionName":"BR","ThreeLetterISORegionName":"BRA"},{"Name":"BN","DisplayName":"Brunei Darussalam","TwoLetterISORegionName":"BN","ThreeLetterISORegionName":"BRN"},{"Name":"BG","DisplayName":"Bulgaria","TwoLetterISORegionName":"BG","ThreeLetterISORegionName":"BGR"},{"Name":"KH","DisplayName":"Cambodia","TwoLetterISORegionName":"KH","ThreeLetterISORegionName":"KHM"},{"Name":"CM","DisplayName":"Cameroon","TwoLetterISORegionName":"CM","ThreeLetterISORegionName":"CMR"},{"Name":"CA","DisplayName":"Canada","TwoLetterISORegionName":"CA","ThreeLetterISORegionName":"CAN"},{"Name":"029","DisplayName":"Caribbean","TwoLetterISORegionName":"029","ThreeLetterISORegionName":"029"},{"Name":"CL","DisplayName":"Chile","TwoLetterISORegionName":"CL","ThreeLetterISORegionName":"CHL"},{"Name":"CO","DisplayName":"Colombia","TwoLetterISORegionName":"CO","ThreeLetterISORegionName":"COL"},{"Name":"CD","DisplayName":"Congo [DRC]","TwoLetterISORegionName":"CD","ThreeLetterISORegionName":"COD"},{"Name":"CR","DisplayName":"Costa Rica","TwoLetterISORegionName":"CR","ThreeLetterISORegionName":"CRI"},{"Name":"HR","DisplayName":"Croatia","TwoLetterISORegionName":"HR","ThreeLetterISORegionName":"HRV"},{"Name":"CZ","DisplayName":"Czech Republic","TwoLetterISORegionName":"CZ","ThreeLetterISORegionName":"CZE"},{"Name":"DK","DisplayName":"Denmark","TwoLetterISORegionName":"DK","ThreeLetterISORegionName":"DNK"},{"Name":"DO","DisplayName":"Dominican Republic","TwoLetterISORegionName":"DO","ThreeLetterISORegionName":"DOM"},{"Name":"EC","DisplayName":"Ecuador","TwoLetterISORegionName":"EC","ThreeLetterISORegionName":"ECU"},{"Name":"EG","DisplayName":"Egypt","TwoLetterISORegionName":"EG","ThreeLetterISORegionName":"EGY"},{"Name":"SV","DisplayName":"El Salvador","TwoLetterISORegionName":"SV","ThreeLetterISORegionName":"SLV"},{"Name":"ER","DisplayName":"Eritrea","TwoLetterISORegionName":"ER","ThreeLetterISORegionName":"ERI"},{"Name":"EE","DisplayName":"Estonia","TwoLetterISORegionName":"EE","ThreeLetterISORegionName":"EST"},{"Name":"ET","DisplayName":"Ethiopia","TwoLetterISORegionName":"ET","ThreeLetterISORegionName":"ETH"},{"Name":"FO","DisplayName":"Faroe Islands","TwoLetterISORegionName":"FO","ThreeLetterISORegionName":"FRO"},{"Name":"FI","DisplayName":"Finland","TwoLetterISORegionName":"FI","ThreeLetterISORegionName":"FIN"},{"Name":"FR","DisplayName":"France","TwoLetterISORegionName":"FR","ThreeLetterISORegionName":"FRA"},{"Name":"GE","DisplayName":"Georgia","TwoLetterISORegionName":"GE","ThreeLetterISORegionName":"GEO"},{"Name":"DE","DisplayName":"Germany","TwoLetterISORegionName":"DE","ThreeLetterISORegionName":"DEU"},{"Name":"GR","DisplayName":"Greece","TwoLetterISORegionName":"GR","ThreeLetterISORegionName":"GRC"},{"Name":"GL","DisplayName":"Greenland","TwoLetterISORegionName":"GL","ThreeLetterISORegionName":"GRL"},{"Name":"GT","DisplayName":"Guatemala","TwoLetterISORegionName":"GT","ThreeLetterISORegionName":"GTM"},{"Name":"HT","DisplayName":"Haiti","TwoLetterISORegionName":"HT","ThreeLetterISORegionName":"HTI"},{"Name":"HN","DisplayName":"Honduras","TwoLetterISORegionName":"HN","ThreeLetterISORegionName":"HND"},{"Name":"HK","DisplayName":"Hong Kong S.A.R.","TwoLetterISORegionName":"HK","ThreeLetterISORegionName":"HKG"},{"Name":"HU","DisplayName":"Hungary","TwoLetterISORegionName":"HU","ThreeLetterISORegionName":"HUN"},{"Name":"IS","DisplayName":"Iceland","TwoLetterISORegionName":"IS","ThreeLetterISORegionName":"ISL"},{"Name":"IN","DisplayName":"India","TwoLetterISORegionName":"IN","ThreeLetterISORegionName":"IND"},{"Name":"ID","DisplayName":"Indonesia","TwoLetterISORegionName":"ID","ThreeLetterISORegionName":"IDN"},{"Name":"IR","DisplayName":"Iran","TwoLetterISORegionName":"IR","ThreeLetterISORegionName":"IRN"},{"Name":"IQ","DisplayName":"Iraq","TwoLetterISORegionName":"IQ","ThreeLetterISORegionName":"IRQ"},{"Name":"IE","DisplayName":"Ireland","TwoLetterISORegionName":"IE","ThreeLetterISORegionName":"IRL"},{"Name":"PK","DisplayName":"Islamic Republic of Pakistan","TwoLetterISORegionName":"PK","ThreeLetterISORegionName":"PAK"},{"Name":"IL","DisplayName":"Israel","TwoLetterISORegionName":"IL","ThreeLetterISORegionName":"ISR"},{"Name":"IT","DisplayName":"Italy","TwoLetterISORegionName":"IT","ThreeLetterISORegionName":"ITA"},{"Name":"CI","DisplayName":"Ivory Coast","TwoLetterISORegionName":"CI","ThreeLetterISORegionName":"CIV"},{"Name":"JM","DisplayName":"Jamaica","TwoLetterISORegionName":"JM","ThreeLetterISORegionName":"JAM"},{"Name":"JP","DisplayName":"Japan","TwoLetterISORegionName":"JP","ThreeLetterISORegionName":"JPN"},{"Name":"JO","DisplayName":"Jordan","TwoLetterISORegionName":"JO","ThreeLetterISORegionName":"JOR"},{"Name":"KZ","DisplayName":"Kazakhstan","TwoLetterISORegionName":"KZ","ThreeLetterISORegionName":"KAZ"},{"Name":"KE","DisplayName":"Kenya","TwoLetterISORegionName":"KE","ThreeLetterISORegionName":"KEN"},{"Name":"KR","DisplayName":"Korea","TwoLetterISORegionName":"KR","ThreeLetterISORegionName":"KOR"},{"Name":"KW","DisplayName":"Kuwait","TwoLetterISORegionName":"KW","ThreeLetterISORegionName":"KWT"},{"Name":"KG","DisplayName":"Kyrgyzstan","TwoLetterISORegionName":"KG","ThreeLetterISORegionName":"KGZ"},{"Name":"LA","DisplayName":"Lao P.D.R.","TwoLetterISORegionName":"LA","ThreeLetterISORegionName":"LAO"},{"Name":"419","DisplayName":"Latin America","TwoLetterISORegionName":"419","ThreeLetterISORegionName":"419"},{"Name":"LV","DisplayName":"Latvia","TwoLetterISORegionName":"LV","ThreeLetterISORegionName":"LVA"},{"Name":"LB","DisplayName":"Lebanon","TwoLetterISORegionName":"LB","ThreeLetterISORegionName":"LBN"},{"Name":"LY","DisplayName":"Libya","TwoLetterISORegionName":"LY","ThreeLetterISORegionName":"LBY"},{"Name":"LI","DisplayName":"Liechtenstein","TwoLetterISORegionName":"LI","ThreeLetterISORegionName":"LIE"},{"Name":"LT","DisplayName":"Lithuania","TwoLetterISORegionName":"LT","ThreeLetterISORegionName":"LTU"},{"Name":"LU","DisplayName":"Luxembourg","TwoLetterISORegionName":"LU","ThreeLetterISORegionName":"LUX"},{"Name":"MO","DisplayName":"Macao S.A.R.","TwoLetterISORegionName":"MO","ThreeLetterISORegionName":"MAC"},{"Name":"MK","DisplayName":"Macedonia (FYROM)","TwoLetterISORegionName":"MK","ThreeLetterISORegionName":"MKD"},{"Name":"MY","DisplayName":"Malaysia","TwoLetterISORegionName":"MY","ThreeLetterISORegionName":"MYS"},{"Name":"MV","DisplayName":"Maldives","TwoLetterISORegionName":"MV","ThreeLetterISORegionName":"MDV"},{"Name":"ML","DisplayName":"Mali","TwoLetterISORegionName":"ML","ThreeLetterISORegionName":"MLI"},{"Name":"MT","DisplayName":"Malta","TwoLetterISORegionName":"MT","ThreeLetterISORegionName":"MLT"},{"Name":"MX","DisplayName":"Mexico","TwoLetterISORegionName":"MX","ThreeLetterISORegionName":"MEX"},{"Name":"MN","DisplayName":"Mongolia","TwoLetterISORegionName":"MN","ThreeLetterISORegionName":"MNG"},{"Name":"ME","DisplayName":"Montenegro","TwoLetterISORegionName":"ME","ThreeLetterISORegionName":"MNE"},{"Name":"MA","DisplayName":"Morocco","TwoLetterISORegionName":"MA","ThreeLetterISORegionName":"MAR"},{"Name":"NP","DisplayName":"Nepal","TwoLetterISORegionName":"NP","ThreeLetterISORegionName":"NPL"},{"Name":"NL","DisplayName":"Netherlands","TwoLetterISORegionName":"NL","ThreeLetterISORegionName":"NLD"},{"Name":"NZ","DisplayName":"New Zealand","TwoLetterISORegionName":"NZ","ThreeLetterISORegionName":"NZL"},{"Name":"NI","DisplayName":"Nicaragua","TwoLetterISORegionName":"NI","ThreeLetterISORegionName":"NIC"},{"Name":"NG","DisplayName":"Nigeria","TwoLetterISORegionName":"NG","ThreeLetterISORegionName":"NGA"},{"Name":"NO","DisplayName":"Norway","TwoLetterISORegionName":"NO","ThreeLetterISORegionName":"NOR"},{"Name":"OM","DisplayName":"Oman","TwoLetterISORegionName":"OM","ThreeLetterISORegionName":"OMN"},{"Name":"PA","DisplayName":"Panama","TwoLetterISORegionName":"PA","ThreeLetterISORegionName":"PAN"},{"Name":"PY","DisplayName":"Paraguay","TwoLetterISORegionName":"PY","ThreeLetterISORegionName":"PRY"},{"Name":"CN","DisplayName":"People's Republic of China","TwoLetterISORegionName":"CN","ThreeLetterISORegionName":"CHN"},{"Name":"PE","DisplayName":"Peru","TwoLetterISORegionName":"PE","ThreeLetterISORegionName":"PER"},{"Name":"PH","DisplayName":"Philippines","TwoLetterISORegionName":"PH","ThreeLetterISORegionName":"PHL"},{"Name":"PL","DisplayName":"Poland","TwoLetterISORegionName":"PL","ThreeLetterISORegionName":"POL"},{"Name":"PT","DisplayName":"Portugal","TwoLetterISORegionName":"PT","ThreeLetterISORegionName":"PRT"},{"Name":"MC","DisplayName":"Principality of Monaco","TwoLetterISORegionName":"MC","ThreeLetterISORegionName":"MCO"},{"Name":"PR","DisplayName":"Puerto Rico","TwoLetterISORegionName":"PR","ThreeLetterISORegionName":"PRI"},{"Name":"QA","DisplayName":"Qatar","TwoLetterISORegionName":"QA","ThreeLetterISORegionName":"QAT"},{"Name":"MD","DisplayName":"Republica Moldova","TwoLetterISORegionName":"MD","ThreeLetterISORegionName":"MDA"},{"Name":"RE","DisplayName":"Réunion","TwoLetterISORegionName":"RE","ThreeLetterISORegionName":"REU"},{"Name":"RO","DisplayName":"Romania","TwoLetterISORegionName":"RO","ThreeLetterISORegionName":"ROU"},{"Name":"RU","DisplayName":"Russia","TwoLetterISORegionName":"RU","ThreeLetterISORegionName":"RUS"},{"Name":"RW","DisplayName":"Rwanda","TwoLetterISORegionName":"RW","ThreeLetterISORegionName":"RWA"},{"Name":"SA","DisplayName":"Saudi Arabia","TwoLetterISORegionName":"SA","ThreeLetterISORegionName":"SAU"},{"Name":"SN","DisplayName":"Senegal","TwoLetterISORegionName":"SN","ThreeLetterISORegionName":"SEN"},{"Name":"RS","DisplayName":"Serbia","TwoLetterISORegionName":"RS","ThreeLetterISORegionName":"SRB"},{"Name":"CS","DisplayName":"Serbia and Montenegro (Former)","TwoLetterISORegionName":"CS","ThreeLetterISORegionName":"SCG"},{"Name":"SG","DisplayName":"Singapore","TwoLetterISORegionName":"SG","ThreeLetterISORegionName":"SGP"},{"Name":"SK","DisplayName":"Slovakia","TwoLetterISORegionName":"SK","ThreeLetterISORegionName":"SVK"},{"Name":"SI","DisplayName":"Slovenia","TwoLetterISORegionName":"SI","ThreeLetterISORegionName":"SVN"},{"Name":"SO","DisplayName":"Soomaaliya","TwoLetterISORegionName":"SO","ThreeLetterISORegionName":"SOM"},{"Name":"ZA","DisplayName":"South Africa","TwoLetterISORegionName":"ZA","ThreeLetterISORegionName":"ZAF"},{"Name":"ES","DisplayName":"Spain","TwoLetterISORegionName":"ES","ThreeLetterISORegionName":"ESP"},{"Name":"LK","DisplayName":"Sri Lanka","TwoLetterISORegionName":"LK","ThreeLetterISORegionName":"LKA"},{"Name":"SE","DisplayName":"Sweden","TwoLetterISORegionName":"SE","ThreeLetterISORegionName":"SWE"},{"Name":"CH","DisplayName":"Switzerland","TwoLetterISORegionName":"CH","ThreeLetterISORegionName":"CHE"},{"Name":"SY","DisplayName":"Syria","TwoLetterISORegionName":"SY","ThreeLetterISORegionName":"SYR"},{"Name":"TW","DisplayName":"Taiwan","TwoLetterISORegionName":"TW","ThreeLetterISORegionName":"TWN"},{"Name":"TJ","DisplayName":"Tajikistan","TwoLetterISORegionName":"TJ","ThreeLetterISORegionName":"TAJ"},{"Name":"TH","DisplayName":"Thailand","TwoLetterISORegionName":"TH","ThreeLetterISORegionName":"THA"},{"Name":"TT","DisplayName":"Trinidad and Tobago","TwoLetterISORegionName":"TT","ThreeLetterISORegionName":"TTO"},{"Name":"TN","DisplayName":"Tunisia","TwoLetterISORegionName":"TN","ThreeLetterISORegionName":"TUN"},{"Name":"TR","DisplayName":"Turkey","TwoLetterISORegionName":"TR","ThreeLetterISORegionName":"TUR"},{"Name":"TM","DisplayName":"Turkmenistan","TwoLetterISORegionName":"TM","ThreeLetterISORegionName":"TKM"},{"Name":"AE","DisplayName":"U.A.E.","TwoLetterISORegionName":"AE","ThreeLetterISORegionName":"ARE"},{"Name":"UA","DisplayName":"Ukraine","TwoLetterISORegionName":"UA","ThreeLetterISORegionName":"UKR"},{"Name":"GB","DisplayName":"United Kingdom","TwoLetterISORegionName":"GB","ThreeLetterISORegionName":"GBR"},{"Name":"US","DisplayName":"United States","TwoLetterISORegionName":"US","ThreeLetterISORegionName":"USA"},{"Name":"UY","DisplayName":"Uruguay","TwoLetterISORegionName":"UY","ThreeLetterISORegionName":"URY"},{"Name":"UZ","DisplayName":"Uzbekistan","TwoLetterISORegionName":"UZ","ThreeLetterISORegionName":"UZB"},{"Name":"VN","DisplayName":"Vietnam","TwoLetterISORegionName":"VN","ThreeLetterISORegionName":"VNM"},{"Name":"YE","DisplayName":"Yemen","TwoLetterISORegionName":"YE","ThreeLetterISORegionName":"YEM"},{"Name":"ZW","DisplayName":"Zimbabwe","TwoLetterISORegionName":"ZW","ThreeLetterISORegionName":"ZWE"}]
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/iso6392.txt b/MediaBrowser.Server.Implementations/Localization/iso6392.txt deleted file mode 100644 index 665a5375e4..0000000000 --- a/MediaBrowser.Server.Implementations/Localization/iso6392.txt +++ /dev/null @@ -1,487 +0,0 @@ -aar||aa|Afar|afar -abk||ab|Abkhazian|abkhaze -ace|||Achinese|aceh -ach|||Acoli|acoli -ada|||Adangme|adangme -ady|||Adyghe; Adygei|adyghé -afa|||Afro-Asiatic languages|afro-asiatiques, langues -afh|||Afrihili|afrihili -afr||af|Afrikaans|afrikaans -ain|||Ainu|aïnou -aka||ak|Akan|akan -akk|||Akkadian|akkadien -alb|sqi|sq|Albanian|albanais -ale|||Aleut|aléoute -alg|||Algonquian languages|algonquines, langues -alt|||Southern Altai|altai du Sud -amh||am|Amharic|amharique -ang|||English, Old (ca.450-1100)|anglo-saxon (ca.450-1100) -anp|||Angika|angika -apa|||Apache languages|apaches, langues -ara||ar|Arabic|arabe -arc|||Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE)|araméen d'empire (700-300 BCE) -arg||an|Aragonese|aragonais -arm|hye|hy|Armenian|arménien -arn|||Mapudungun; Mapuche|mapudungun; mapuche; mapuce -arp|||Arapaho|arapaho -art|||Artificial languages|artificielles, langues -arw|||Arawak|arawak -asm||as|Assamese|assamais -ast|||Asturian; Bable; Leonese; Asturleonese|asturien; bable; léonais; asturoléonais -ath|||Athapascan languages|athapascanes, langues -aus|||Australian languages|australiennes, langues -ava||av|Avaric|avar -ave||ae|Avestan|avestique -awa|||Awadhi|awadhi -aym||ay|Aymara|aymara -aze||az|Azerbaijani|azéri -bad|||Banda languages|banda, langues -bai|||Bamileke languages|bamiléké, langues -bak||ba|Bashkir|bachkir -bal|||Baluchi|baloutchi -bam||bm|Bambara|bambara -ban|||Balinese|balinais -baq|eus|eu|Basque|basque -bas|||Basa|basa -bat|||Baltic languages|baltes, langues -bej|||Beja; Bedawiyet|bedja -bel||be|Belarusian|biélorusse -bem|||Bemba|bemba -ben||bn|Bengali|bengali -ber|||Berber languages|berbères, langues -bho|||Bhojpuri|bhojpuri -bih||bh|Bihari languages|langues biharis -bik|||Bikol|bikol -bin|||Bini; Edo|bini; edo -bis||bi|Bislama|bichlamar -bla|||Siksika|blackfoot -bnt|||Bantu (Other)|bantoues, autres langues -bos||bs|Bosnian|bosniaque -bra|||Braj|braj -bre||br|Breton|breton -btk|||Batak languages|batak, langues -bua|||Buriat|bouriate -bug|||Buginese|bugi -bul||bg|Bulgarian|bulgare -bur|mya|my|Burmese|birman -byn|||Blin; Bilin|blin; bilen -cad|||Caddo|caddo -cai|||Central American Indian languages|amérindiennes de L'Amérique centrale, langues -car|||Galibi Carib|karib; galibi; carib -cat||ca|Catalan; Valencian|catalan; valencien -cau|||Caucasian languages|caucasiennes, langues -ceb|||Cebuano|cebuano -cel|||Celtic languages|celtiques, langues; celtes, langues -cha||ch|Chamorro|chamorro -chb|||Chibcha|chibcha -che||ce|Chechen|tchétchène -chg|||Chagatai|djaghataï -chi|zho|zh|Chinese|chinois -chk|||Chuukese|chuuk -chm|||Mari|mari -chn|||Chinook jargon|chinook, jargon -cho|||Choctaw|choctaw -chp|||Chipewyan; Dene Suline|chipewyan -chr|||Cherokee|cherokee -chu||cu|Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic|slavon d'église; vieux slave; slavon liturgique; vieux bulgare -chv||cv|Chuvash|tchouvache -chy|||Cheyenne|cheyenne -cmc|||Chamic languages|chames, langues -cop|||Coptic|copte -cor||kw|Cornish|cornique -cos||co|Corsican|corse -cpe|||Creoles and pidgins, English based|créoles et pidgins basés sur l'anglais -cpf|||Creoles and pidgins, French-based |créoles et pidgins basés sur le français -cpp|||Creoles and pidgins, Portuguese-based |créoles et pidgins basés sur le portugais -cre||cr|Cree|cree -crh|||Crimean Tatar; Crimean Turkish|tatar de Crimé -crp|||Creoles and pidgins |créoles et pidgins -csb|||Kashubian|kachoube -cus|||Cushitic languages|couchitiques, langues -cze|ces|cs|Czech|tchèque -dak|||Dakota|dakota -dan||da|Danish|danois -dar|||Dargwa|dargwa -day|||Land Dayak languages|dayak, langues -del|||Delaware|delaware -den|||Slave (Athapascan)|esclave (athapascan) -dgr|||Dogrib|dogrib -din|||Dinka|dinka -div||dv|Divehi; Dhivehi; Maldivian|maldivien -doi|||Dogri|dogri -dra|||Dravidian languages|dravidiennes, langues -dsb|||Lower Sorbian|bas-sorabe -dua|||Duala|douala -dum|||Dutch, Middle (ca.1050-1350)|néerlandais moyen (ca. 1050-1350) -dut|nld|nl|Dutch; Flemish|néerlandais; flamand -dyu|||Dyula|dioula -dzo||dz|Dzongkha|dzongkha -efi|||Efik|efik -egy|||Egyptian (Ancient)|égyptien -eka|||Ekajuk|ekajuk -elx|||Elamite|élamite -eng||en|English|anglais -enm|||English, Middle (1100-1500)|anglais moyen (1100-1500) -epo||eo|Esperanto|espéranto -est||et|Estonian|estonien -ewe||ee|Ewe|éwé -ewo|||Ewondo|éwondo -fan|||Fang|fang -fao||fo|Faroese|féroïen -fat|||Fanti|fanti -fij||fj|Fijian|fidjien -fil|||Filipino; Pilipino|filipino; pilipino -fin||fi|Finnish|finnois -fiu|||Finno-Ugrian languages|finno-ougriennes, langues -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) -frr|||Northern Frisian|frison septentrional -frs|||Eastern Frisian|frison oriental -fry||fy|Western Frisian|frison occidental -ful||ff|Fulah|peul -fur|||Friulian|frioulan -gaa|||Ga|ga -gay|||Gayo|gayo -gba|||Gbaya|gbaya -gem|||Germanic languages|germaniques, langues -geo|kat|ka|Georgian|géorgien -ger|deu|de|German|allemand -gez|||Geez|guèze -gil|||Gilbertese|kiribati -gla||gd|Gaelic; Scottish Gaelic|gaélique; gaélique écossais -gle||ga|Irish|irlandais -glg||gl|Galician|galicien -glv||gv|Manx|manx; mannois -gmh|||German, Middle High (ca.1050-1500)|allemand, moyen haut (ca. 1050-1500) -goh|||German, Old High (ca.750-1050)|allemand, vieux haut (ca. 750-1050) -gon|||Gondi|gond -gor|||Gorontalo|gorontalo -got|||Gothic|gothique -grb|||Grebo|grebo -grc|||Greek, Ancient (to 1453)|grec ancien (jusqu'à 1453) -gre|ell|el|Greek, Modern (1453-)|grec moderne (après 1453) -grn||gn|Guarani|guarani -gsw|||Swiss German; Alemannic; Alsatian|suisse alémanique; alémanique; alsacien -guj||gu|Gujarati|goudjrati -gwi|||Gwich'in|gwich'in -hai|||Haida|haida -hat||ht|Haitian; Haitian Creole|haïtien; créole haïtien -hau||ha|Hausa|haoussa -haw|||Hawaiian|hawaïen -heb||he|Hebrew|hébreu -her||hz|Herero|herero -hil|||Hiligaynon|hiligaynon -him|||Himachali languages; Western Pahari languages|langues himachalis; langues paharis occidentales -hin||hi|Hindi|hindi -hit|||Hittite|hittite -hmn|||Hmong; Mong|hmong -hmo||ho|Hiri Motu|hiri motu -hrv||hr|Croatian|croate -hsb|||Upper Sorbian|haut-sorabe -hun||hu|Hungarian|hongrois -hup|||Hupa|hupa -iba|||Iban|iban -ibo||ig|Igbo|igbo -ice|isl|is|Icelandic|islandais -ido||io|Ido|ido -iii||ii|Sichuan Yi; Nuosu|yi de Sichuan -ijo|||Ijo languages|ijo, langues -iku||iu|Inuktitut|inuktitut -ile||ie|Interlingue; Occidental|interlingue -ilo|||Iloko|ilocano -ina||ia|Interlingua (International Auxiliary Language Association)|interlingua (langue auxiliaire internationale) -inc|||Indic languages|indo-aryennes, langues -ind||id|Indonesian|indonésien -ine|||Indo-European languages|indo-européennes, langues -inh|||Ingush|ingouche -ipk||ik|Inupiaq|inupiaq -ira|||Iranian languages|iraniennes, langues -iro|||Iroquoian languages|iroquoises, langues -ita||it|Italian|italien -jav||jv|Javanese|javanais -jbo|||Lojban|lojban -jpn||ja|Japanese|japonais -jpr|||Judeo-Persian|judéo-persan -jrb|||Judeo-Arabic|judéo-arabe -kaa|||Kara-Kalpak|karakalpak -kab|||Kabyle|kabyle -kac|||Kachin; Jingpho|kachin; jingpho -kal||kl|Kalaallisut; Greenlandic|groenlandais -kam|||Kamba|kamba -kan||kn|Kannada|kannada -kar|||Karen languages|karen, langues -kas||ks|Kashmiri|kashmiri -kau||kr|Kanuri|kanouri -kaw|||Kawi|kawi -kaz||kk|Kazakh|kazakh -kbd|||Kabardian|kabardien -kha|||Khasi|khasi -khi|||Khoisan languages|khoïsan, langues -khm||km|Central Khmer|khmer central -kho|||Khotanese; Sakan|khotanais; sakan -kik||ki|Kikuyu; Gikuyu|kikuyu -kin||rw|Kinyarwanda|rwanda -kir||ky|Kirghiz; Kyrgyz|kirghiz -kmb|||Kimbundu|kimbundu -kok|||Konkani|konkani -kom||kv|Komi|kom -kon||kg|Kongo|kongo -kor||ko|Korean|coréen -kos|||Kosraean|kosrae -kpe|||Kpelle|kpellé -krc|||Karachay-Balkar|karatchai balkar -krl|||Karelian|carélien -kro|||Kru languages|krou, langues -kru|||Kurukh|kurukh -kua||kj|Kuanyama; Kwanyama|kuanyama; kwanyama -kum|||Kumyk|koumyk -kur||ku|Kurdish|kurde -kut|||Kutenai|kutenai -lad|||Ladino|judéo-espagnol -lah|||Lahnda|lahnda -lam|||Lamba|lamba -lao||lo|Lao|lao -lat||la|Latin|latin -lav||lv|Latvian|letton -lez|||Lezghian|lezghien -lim||li|Limburgan; Limburger; Limburgish|limbourgeois -lin||ln|Lingala|lingala -lit||lt|Lithuanian|lituanien -lol|||Mongo|mongo -loz|||Lozi|lozi -ltz||lb|Luxembourgish; Letzeburgesch|luxembourgeois -lua|||Luba-Lulua|luba-lulua -lub||lu|Luba-Katanga|luba-katanga -lug||lg|Ganda|ganda -lui|||Luiseno|luiseno -lun|||Lunda|lunda -luo|||Luo (Kenya and Tanzania)|luo (Kenya et Tanzanie) -lus|||Lushai|lushai -mac|mkd|mk|Macedonian|macédonien -mad|||Madurese|madourais -mag|||Magahi|magahi -mah||mh|Marshallese|marshall -mai|||Maithili|maithili -mak|||Makasar|makassar -mal||ml|Malayalam|malayalam -man|||Mandingo|mandingue -mao|mri|mi|Maori|maori -map|||Austronesian languages|austronésiennes, langues -mar||mr|Marathi|marathe -mas|||Masai|massaï -may|msa|ms|Malay|malais -mdf|||Moksha|moksa -mdr|||Mandar|mandar -men|||Mende|mendé -mga|||Irish, Middle (900-1200)|irlandais moyen (900-1200) -mic|||Mi'kmaq; Micmac|mi'kmaq; micmac -min|||Minangkabau|minangkabau -mis|||Uncoded languages|langues non codées -mkh|||Mon-Khmer languages|môn-khmer, langues -mlg||mg|Malagasy|malgache -mlt||mt|Maltese|maltais -mnc|||Manchu|mandchou -mni|||Manipuri|manipuri -mno|||Manobo languages|manobo, langues -moh|||Mohawk|mohawk -mon||mn|Mongolian|mongol -mos|||Mossi|moré -mul|||Multiple languages|multilingue -mun|||Munda languages|mounda, langues -mus|||Creek|muskogee -mwl|||Mirandese|mirandais -mwr|||Marwari|marvari -myn|||Mayan languages|maya, langues -myv|||Erzya|erza -nah|||Nahuatl languages|nahuatl, langues -nai|||North American Indian languages|nord-amérindiennes, langues -nap|||Neapolitan|napolitain -nau||na|Nauru|nauruan -nav||nv|Navajo; Navaho|navaho -nbl||nr|Ndebele, South; South Ndebele|ndébélé du Sud -nde||nd|Ndebele, North; North Ndebele|ndébélé du Nord -ndo||ng|Ndonga|ndonga -nds|||Low German; Low Saxon; German, Low; Saxon, Low|bas allemand; bas saxon; allemand, bas; saxon, bas -nep||ne|Nepali|népalais -new|||Nepal Bhasa; Newari|nepal bhasa; newari -nia|||Nias|nias -nic|||Niger-Kordofanian languages|nigéro-kordofaniennes, langues -niu|||Niuean|niué -nno||nn|Norwegian Nynorsk; Nynorsk, Norwegian|norvégien nynorsk; nynorsk, norvégien -nob||nb|Bokmål, Norwegian; Norwegian Bokmål|norvégien bokmål -nog|||Nogai|nogaï; nogay -non|||Norse, Old|norrois, vieux -nor||no|Norwegian|norvégien -nqo|||N'Ko|n'ko -nso|||Pedi; Sepedi; Northern Sotho|pedi; sepedi; sotho du Nord -nub|||Nubian languages|nubiennes, langues -nwc|||Classical Newari; Old Newari; Classical Nepal Bhasa|newari classique -nya||ny|Chichewa; Chewa; Nyanja|chichewa; chewa; nyanja -nym|||Nyamwezi|nyamwezi -nyn|||Nyankole|nyankolé -nyo|||Nyoro|nyoro -nzi|||Nzima|nzema -oci||oc|Occitan (post 1500); Provençal|occitan (après 1500); provençal -oji||oj|Ojibwa|ojibwa -ori||or|Oriya|oriya -orm||om|Oromo|galla -osa|||Osage|osage -oss||os|Ossetian; Ossetic|ossète -ota|||Turkish, Ottoman (1500-1928)|turc ottoman (1500-1928) -oto|||Otomian languages|otomi, langues -paa|||Papuan languages|papoues, langues -pag|||Pangasinan|pangasinan -pal|||Pahlavi|pahlavi -pam|||Pampanga; Kapampangan|pampangan -pan||pa|Panjabi; Punjabi|pendjabi -pap|||Papiamento|papiamento -pau|||Palauan|palau -peo|||Persian, Old (ca.600-400 B.C.)|perse, vieux (ca. 600-400 av. J.-C.) -per|fas|fa|Persian|persan -phi|||Philippine languages|philippines, langues -phn|||Phoenician|phénicien -pli||pi|Pali|pali -pol||pl|Polish|polonais -pon|||Pohnpeian|pohnpei -por||pt|Portuguese|portugais -pob||pt-br|Portuguese (Brazil)|portugais -pra|||Prakrit languages|prâkrit, langues -pro|||Provençal, Old (to 1500)|provençal ancien (jusqu'à 1500) -pus||ps|Pushto; Pashto|pachto -qaa-qtz|||Reserved for local use|réservée à l'usage local -que||qu|Quechua|quechua -raj|||Rajasthani|rajasthani -rap|||Rapanui|rapanui -rar|||Rarotongan; Cook Islands Maori|rarotonga; maori des îles Cook -roa|||Romance languages|romanes, langues -roh||rm|Romansh|romanche -rom|||Romany|tsigane -rum|ron|ro|Romanian; Moldavian; Moldovan|roumain; moldave -run||rn|Rundi|rundi -rup|||Aromanian; Arumanian; Macedo-Romanian|aroumain; macédo-roumain -rus||ru|Russian|russe -sad|||Sandawe|sandawe -sag||sg|Sango|sango -sah|||Yakut|iakoute -sai|||South American Indian (Other)|indiennes d'Amérique du Sud, autres langues -sal|||Salishan languages|salishennes, langues -sam|||Samaritan Aramaic|samaritain -san||sa|Sanskrit|sanskrit -sas|||Sasak|sasak -sat|||Santali|santal -scn|||Sicilian|sicilien -sco|||Scots|écossais -sel|||Selkup|selkoupe -sem|||Semitic languages|sémitiques, langues -sga|||Irish, Old (to 900)|irlandais ancien (jusqu'à 900) -sgn|||Sign Languages|langues des signes -shn|||Shan|chan -sid|||Sidamo|sidamo -sin||si|Sinhala; Sinhalese|singhalais -sio|||Siouan languages|sioux, langues -sit|||Sino-Tibetan languages|sino-tibétaines, langues -sla|||Slavic languages|slaves, langues -slo|slk|sk|Slovak|slovaque -slv||sl|Slovenian|slovène -sma|||Southern Sami|sami du Sud -sme||se|Northern Sami|sami du Nord -smi|||Sami languages|sames, langues -smj|||Lule Sami|sami de Lule -smn|||Inari Sami|sami d'Inari -smo||sm|Samoan|samoan -sms|||Skolt Sami|sami skolt -sna||sn|Shona|shona -snd||sd|Sindhi|sindhi -snk|||Soninke|soninké -sog|||Sogdian|sogdien -som||so|Somali|somali -son|||Songhai languages|songhai, langues -sot||st|Sotho, Southern|sotho du Sud -spa||es|Spanish; Castilian|espagnol; castillan -srd||sc|Sardinian|sarde -srn|||Sranan Tongo|sranan tongo -srp||sr|Serbian|serbe -srr|||Serer|sérère -ssa|||Nilo-Saharan languages|nilo-sahariennes, langues -ssw||ss|Swati|swati -suk|||Sukuma|sukuma -sun||su|Sundanese|soundanais -sus|||Susu|soussou -sux|||Sumerian|sumérien -swa||sw|Swahili|swahili -swe||sv|Swedish|suédois -syc|||Classical Syriac|syriaque classique -syr|||Syriac|syriaque -tah||ty|Tahitian|tahitien -tai|||Tai languages|tai, langues -tam||ta|Tamil|tamoul -tat||tt|Tatar|tatar -tel||te|Telugu|télougou -tem|||Timne|temne -ter|||Tereno|tereno -tet|||Tetum|tetum -tgk||tg|Tajik|tadjik -tgl||tl|Tagalog|tagalog -tha||th|Thai|thaï -tib|bod|bo|Tibetan|tibétain -tig|||Tigre|tigré -tir||ti|Tigrinya|tigrigna -tiv|||Tiv|tiv -tkl|||Tokelau|tokelau -tlh|||Klingon; tlhIngan-Hol|klingon -tli|||Tlingit|tlingit -tmh|||Tamashek|tamacheq -tog|||Tonga (Nyasa)|tonga (Nyasa) -ton||to|Tonga (Tonga Islands)|tongan (Îles Tonga) -tpi|||Tok Pisin|tok pisin -tsi|||Tsimshian|tsimshian -tsn||tn|Tswana|tswana -tso||ts|Tsonga|tsonga -tuk||tk|Turkmen|turkmène -tum|||Tumbuka|tumbuka -tup|||Tupi languages|tupi, langues -tur||tr|Turkish|turc -tut|||Altaic languages|altaïques, langues -tvl|||Tuvalu|tuvalu -twi||tw|Twi|twi -tyv|||Tuvinian|touva -udm|||Udmurt|oudmourte -uga|||Ugaritic|ougaritique -uig||ug|Uighur; Uyghur|ouïgour -ukr||uk|Ukrainian|ukrainien -umb|||Umbundu|umbundu -und|||Undetermined|indéterminée -urd||ur|Urdu|ourdou -uzb||uz|Uzbek|ouszbek -vai|||Vai|vaï -ven||ve|Venda|venda -vie||vi|Vietnamese|vietnamien -vol||vo|Volapük|volapük -vot|||Votic|vote -wak|||Wakashan languages|wakashanes, langues -wal|||Walamo|walamo -war|||Waray|waray -was|||Washo|washo -wel|cym|cy|Welsh|gallois -wen|||Sorbian languages|sorabes, langues -wln||wa|Walloon|wallon -wol||wo|Wolof|wolof -xal|||Kalmyk; Oirat|kalmouk; oïrat -xho||xh|Xhosa|xhosa -yao|||Yao|yao -yap|||Yapese|yapois -yid||yi|Yiddish|yiddish -yor||yo|Yoruba|yoruba -ypk|||Yupik languages|yupik, langues -zap|||Zapotec|zapotèque -zbl|||Blissymbols; Blissymbolics; Bliss|symboles Bliss; Bliss -zen|||Zenaga|zenaga -zgh|||Standard Moroccan Tamazight|amazighe standard marocain -zha||za|Zhuang; Chuang|zhuang; chuang -znd|||Zande languages|zandé, langues -zul||zu|Zulu|zoulou -zun|||Zuni|zuni -zxx|||No linguistic content; Not applicable|pas de contenu linguistique; non applicable -zza|||Zaza; Dimili; Dimli; Kirdki; Kirmanjki; Zazaki|zaza; dimili; dimli; kirdki; kirmanjki; zazaki
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Logging/PatternsLogger.cs b/MediaBrowser.Server.Implementations/Logging/PatternsLogger.cs deleted file mode 100644 index 00b6cc5a8b..0000000000 --- a/MediaBrowser.Server.Implementations/Logging/PatternsLogger.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Patterns.Logging; -using System; - -namespace MediaBrowser.Server.Implementations.Logging -{ - public class PatternsLogger : ILogger - { - private readonly Model.Logging.ILogger _logger; - - public PatternsLogger() - : this(new Model.Logging.NullLogger()) - { - } - - public PatternsLogger(Model.Logging.ILogger logger) - { - _logger = logger; - } - - public void Debug(string message, params object[] paramList) - { - _logger.Debug(message, paramList); - } - - public void Error(string message, params object[] paramList) - { - _logger.Error(message, paramList); - } - - public void ErrorException(string message, Exception exception, params object[] paramList) - { - _logger.ErrorException(message, exception, paramList); - } - - public void Fatal(string message, params object[] paramList) - { - _logger.Fatal(message, paramList); - } - - public void FatalException(string message, Exception exception, params object[] paramList) - { - _logger.FatalException(message, exception, paramList); - } - - public void Info(string message, params object[] paramList) - { - _logger.Info(message, paramList); - } - - public void Warn(string message, params object[] paramList) - { - _logger.Warn(message, paramList); - } - - public void Log(LogSeverity severity, string message, params object[] paramList) - { - } - - public void LogMultiline(string message, LogSeverity severity, System.Text.StringBuilder additionalContent) - { - } - } -} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index f01a107df5..3bfbff6e67 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -11,10 +11,9 @@ <AssemblyName>MediaBrowser.Server.Implementations</AssemblyName> <FileAlignment>512</FileAlignment> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> - <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion> - <ReleaseVersion> - </ReleaseVersion> - <TargetFrameworkProfile /> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <TargetFrameworkProfile>Profile7</TargetFrameworkProfile> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> @@ -42,343 +41,14 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> - <Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath> - </Reference> - <Reference Include="Emby.XmlTv, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> - <HintPath>..\packages\Emby.XmlTv.1.0.0.56\lib\net45\Emby.XmlTv.dll</HintPath> - <Private>True</Private> - </Reference> - <Reference Include="INIFileParser, Version=2.3.0.0, Culture=neutral, PublicKeyToken=79af7b307b65cf3c, processorArchitecture=MSIL"> - <HintPath>..\packages\ini-parser.2.3.0\lib\net20\INIFileParser.dll</HintPath> - <Private>True</Private> - </Reference> - <Reference Include="Interfaces.IO"> - <HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath> - </Reference> - <Reference Include="MediaBrowser.Naming, Version=1.0.6059.24054, Culture=neutral, processorArchitecture=MSIL"> - <HintPath>..\packages\MediaBrowser.Naming.1.0.0.55\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath> - <Private>True</Private> - </Reference> - <Reference Include="MoreLinq"> - <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath> - </Reference> - <Reference Include="Patterns.Logging"> - <HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath> - </Reference> - <Reference Include="ServiceStack.Api.Swagger"> - <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath> - </Reference> - <Reference Include="SimpleInjector, Version=3.2.2.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> - <HintPath>..\packages\SimpleInjector.3.2.2\lib\net45\SimpleInjector.dll</HintPath> - <Private>True</Private> - </Reference> - <Reference Include="SocketHttpListener, Version=1.0.6109.26162, Culture=neutral, processorArchitecture=MSIL"> - <HintPath>..\packages\SocketHttpListener.1.0.0.40\lib\net45\SocketHttpListener.dll</HintPath> - <Private>True</Private> - </Reference> - <Reference Include="System" /> - <Reference Include="System.Core" /> - <Reference Include="Microsoft.CSharp" /> - <Reference Include="System.Data" /> - <Reference Include="System.Net" /> - <Reference Include="System.Runtime.Serialization" /> - <Reference Include="System.Security" /> - <Reference Include="System.Web" /> - <Reference Include="System.Xml" /> - <Reference Include="ServiceStack"> - <HintPath>..\ThirdParty\ServiceStack\ServiceStack.dll</HintPath> - </Reference> - <Reference Include="ServiceStack.Client"> - <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Client.dll</HintPath> - </Reference> - <Reference Include="ServiceStack.Common"> - <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Common.dll</HintPath> - </Reference> - <Reference Include="ServiceStack.Interfaces"> - <HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath> - </Reference> - <Reference Include="ServiceStack.Text"> - <HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath> - </Reference> - <Reference Include="System.Xml.Linq" /> - <Reference Include="UniversalDetector"> - <HintPath>..\ThirdParty\UniversalDetector\UniversalDetector.dll</HintPath> - </Reference> - </ItemGroup> - <ItemGroup> <Compile Include="..\SharedVersion.cs"> <Link>Properties\SharedVersion.cs</Link> </Compile> - <Compile Include="Activity\ActivityManager.cs" /> - <Compile Include="Activity\ActivityRepository.cs" /> - <Compile Include="Branding\BrandingConfigurationFactory.cs" /> - <Compile Include="Channels\ChannelConfigurations.cs" /> - <Compile Include="Channels\ChannelDynamicMediaSourceProvider.cs" /> - <Compile Include="Channels\ChannelImageProvider.cs" /> - <Compile Include="Channels\ChannelManager.cs" /> - <Compile Include="Channels\ChannelPostScanTask.cs" /> - <Compile Include="Channels\RefreshChannelsScheduledTask.cs" /> - <Compile Include="Collections\CollectionManager.cs" /> - <Compile Include="Collections\CollectionsDynamicFolder.cs" /> - <Compile Include="Collections\CollectionImageProvider.cs" /> - <Compile Include="Configuration\ServerConfigurationManager.cs" /> - <Compile Include="Connect\ConnectData.cs" /> - <Compile Include="Connect\ConnectManager.cs" /> - <Compile Include="Connect\Responses.cs" /> - <Compile Include="Connect\Validator.cs" /> - <Compile Include="Devices\DeviceManager.cs" /> - <Compile Include="Devices\DeviceRepository.cs" /> <Compile Include="Devices\CameraUploadsFolder.cs" /> - <Compile Include="Dto\DtoService.cs" /> - <Compile Include="EntryPoints\ActivityLogEntryPoint.cs" /> - <Compile Include="EntryPoints\AutomaticRestartEntryPoint.cs" /> - <Compile Include="EntryPoints\ExternalPortForwarding.cs" /> - <Compile Include="EntryPoints\LibraryChangedNotifier.cs" /> - <Compile Include="EntryPoints\LoadRegistrations.cs" /> - <Compile Include="EntryPoints\Notifications\Notifications.cs" /> - <Compile Include="EntryPoints\Notifications\WebSocketNotifier.cs" /> - <Compile Include="EntryPoints\RecordingNotifier.cs" /> - <Compile Include="EntryPoints\RefreshUsersMetadata.cs" /> - <Compile Include="EntryPoints\UsageEntryPoint.cs" /> - <Compile Include="Connect\ConnectEntryPoint.cs" /> - <Compile Include="EntryPoints\UsageReporter.cs" /> - <Compile Include="FileOrganization\EpisodeFileOrganizer.cs" /> - <Compile Include="FileOrganization\Extensions.cs" /> - <Compile Include="FileOrganization\FileOrganizationNotifier.cs" /> - <Compile Include="FileOrganization\FileOrganizationService.cs" /> - <Compile Include="FileOrganization\NameUtils.cs" /> - <Compile Include="FileOrganization\TvFolderOrganizer.cs" /> - <Compile Include="EntryPoints\UdpServerEntryPoint.cs" /> - <Compile Include="EntryPoints\ServerEventNotifier.cs" /> - <Compile Include="EntryPoints\UserDataChangeNotifier.cs" /> - <Compile Include="FileOrganization\OrganizerScheduledTask.cs" /> - <Compile Include="HttpServer\AsyncStreamWriter.cs" /> - <Compile Include="HttpServer\IHttpListener.cs" /> - <Compile Include="HttpServer\Security\AuthorizationContext.cs" /> - <Compile Include="HttpServer\ContainerAdapter.cs" /> - <Compile Include="HttpServer\GetSwaggerResource.cs" /> - <Compile Include="HttpServer\HttpListenerHost.cs" /> - <Compile Include="HttpServer\HttpResultFactory.cs" /> - <Compile Include="HttpServer\LoggerUtils.cs" /> - <Compile Include="HttpServer\RangeRequestWriter.cs" /> - <Compile Include="HttpServer\ResponseFilter.cs" /> - <Compile Include="HttpServer\Security\AuthService.cs" /> - <Compile Include="HttpServer\Security\SessionAuthProvider.cs" /> - <Compile Include="HttpServer\ServerFactory.cs" /> - <Compile Include="HttpServer\ServerLogFactory.cs" /> - <Compile Include="HttpServer\ServerLogger.cs" /> - <Compile Include="HttpServer\Security\SessionContext.cs" /> - <Compile Include="HttpServer\SocketSharp\HttpUtility.cs" /> - <Compile Include="HttpServer\SocketSharp\SharpWebSocket.cs" /> - <Compile Include="HttpServer\StreamWriter.cs" /> - <Compile Include="HttpServer\SwaggerService.cs" /> - <Compile Include="HttpServer\SocketSharp\Extensions.cs" /> - <Compile Include="HttpServer\SocketSharp\RequestMono.cs" /> - <Compile Include="HttpServer\SocketSharp\WebSocketSharpListener.cs" /> - <Compile Include="HttpServer\SocketSharp\WebSocketSharpRequest.cs" /> - <Compile Include="HttpServer\SocketSharp\WebSocketSharpResponse.cs" /> - <Compile Include="Intros\DefaultIntroProvider.cs" /> - <Compile Include="IO\FileRefresher.cs" /> - <Compile Include="IO\LibraryMonitor.cs" /> - <Compile Include="Library\CoreResolutionIgnoreRule.cs" /> - <Compile Include="Library\LibraryManager.cs" /> - <Compile Include="Library\LocalTrailerPostScanTask.cs" /> - <Compile Include="Library\MediaSourceManager.cs" /> - <Compile Include="Library\MusicManager.cs" /> - <Compile Include="Library\PathExtensions.cs" /> - <Compile Include="Library\Resolvers\SpecialFolderResolver.cs" /> - <Compile Include="Library\Resolvers\BaseVideoResolver.cs" /> - <Compile Include="Library\Resolvers\PhotoAlbumResolver.cs" /> - <Compile Include="Library\Resolvers\PhotoResolver.cs" /> - <Compile Include="Library\Resolvers\PlaylistResolver.cs" /> - <Compile Include="Library\SearchEngine.cs" /> - <Compile Include="Library\ResolverHelper.cs" /> - <Compile Include="Library\Resolvers\Audio\AudioResolver.cs" /> - <Compile Include="Library\Resolvers\Audio\MusicAlbumResolver.cs" /> - <Compile Include="Library\Resolvers\Audio\MusicArtistResolver.cs" /> - <Compile Include="Library\Resolvers\ItemResolver.cs" /> - <Compile Include="Library\Resolvers\FolderResolver.cs" /> - <Compile Include="Library\Resolvers\Movies\BoxSetResolver.cs" /> - <Compile Include="Library\Resolvers\Movies\MovieResolver.cs" /> - <Compile Include="Library\Resolvers\TV\EpisodeResolver.cs" /> - <Compile Include="Library\Resolvers\TV\SeasonResolver.cs" /> - <Compile Include="Library\Resolvers\TV\SeriesResolver.cs" /> - <Compile Include="Library\Resolvers\VideoResolver.cs" /> - <Compile Include="Library\UserDataManager.cs" /> - <Compile Include="Library\UserManager.cs" /> - <Compile Include="Library\UserViewManager.cs" /> - <Compile Include="Library\Validators\ArtistsPostScanTask.cs" /> - <Compile Include="Library\Validators\ArtistsValidator.cs" /> - <Compile Include="Library\Validators\GameGenresPostScanTask.cs" /> - <Compile Include="Library\Validators\GameGenresValidator.cs" /> - <Compile Include="Library\Validators\GenresPostScanTask.cs" /> - <Compile Include="Library\Validators\GenresValidator.cs" /> - <Compile Include="Library\Validators\MusicGenresPostScanTask.cs" /> - <Compile Include="Library\Validators\MusicGenresValidator.cs" /> - <Compile Include="Library\Validators\PeopleValidator.cs" /> - <Compile Include="Library\Validators\StudiosPostScanTask.cs" /> - <Compile Include="Library\Validators\StudiosValidator.cs" /> - <Compile Include="Library\Validators\YearsPostScanTask.cs" /> - <Compile Include="LiveTv\ChannelImageProvider.cs" /> - <Compile Include="LiveTv\EmbyTV\DirectRecorder.cs" /> - <Compile Include="LiveTv\EmbyTV\EmbyTV.cs" /> - <Compile Include="LiveTv\EmbyTV\EmbyTVRegistration.cs" /> - <Compile Include="LiveTv\EmbyTV\EncodedRecorder.cs" /> - <Compile Include="LiveTv\EmbyTV\EntryPoint.cs" /> - <Compile Include="LiveTv\EmbyTV\IRecorder.cs" /> - <Compile Include="LiveTv\EmbyTV\ItemDataProvider.cs" /> - <Compile Include="LiveTv\EmbyTV\RecordingHelper.cs" /> - <Compile Include="LiveTv\EmbyTV\SeriesTimerManager.cs" /> - <Compile Include="LiveTv\EmbyTV\TimerManager.cs" /> - <Compile Include="LiveTv\Listings\SchedulesDirect.cs" /> - <Compile Include="LiveTv\Listings\XmlTvListingsProvider.cs" /> - <Compile Include="LiveTv\LiveStreamHelper.cs" /> - <Compile Include="LiveTv\LiveTvConfigurationFactory.cs" /> - <Compile Include="LiveTv\LiveTvDtoService.cs" /> - <Compile Include="LiveTv\LiveTvManager.cs" /> - <Compile Include="LiveTv\LiveTvMediaSourceProvider.cs" /> - <Compile Include="LiveTv\TunerHosts\BaseTunerHost.cs" /> - <Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunHost.cs" /> - <Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunDiscovery.cs" /> - <Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunLiveStream.cs" /> - <Compile Include="LiveTv\TunerHosts\M3uParser.cs" /> - <Compile Include="LiveTv\TunerHosts\M3UTunerHost.cs" /> - <Compile Include="LiveTv\ProgramImageProvider.cs" /> - <Compile Include="LiveTv\RecordingImageProvider.cs" /> - <Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" /> - <Compile Include="LiveTv\TunerHosts\MulticastStream.cs" /> - <Compile Include="LiveTv\TunerHosts\QueueStream.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\ChannelScan.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\ReportBlock.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpAppPacket.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpByePacket.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpListener.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpPacket.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpReceiverReportPacket.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpSenderReportPacket.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\RtcpSourceDescriptionPacket.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\SourceDescriptionBlock.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtcp\SourceDescriptionItem.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtp\RtpListener.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtp\RtpPacket.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspMethod.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspRequest.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspResponse.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspSession.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Rtsp\RtspStatusCode.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\SatIpHost.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\SatIpDiscovery.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\TransmissionMode.cs" /> - <Compile Include="LiveTv\TunerHosts\SatIp\Utils.cs" /> - <Compile Include="Localization\LocalizationManager.cs" /> - <Compile Include="Logging\PatternsLogger.cs" /> - <Compile Include="MediaEncoder\EncodingManager.cs" /> - <Compile Include="Notifications\IConfigurableNotificationService.cs" /> - <Compile Include="Persistence\BaseSqliteRepository.cs" /> - <Compile Include="Persistence\CleanDatabaseScheduledTask.cs" /> - <Compile Include="Persistence\DataExtensions.cs" /> - <Compile Include="Persistence\IDbConnector.cs" /> - <Compile Include="Persistence\MediaStreamColumns.cs" /> - <Compile Include="Social\SharingManager.cs" /> - <Compile Include="Social\SharingRepository.cs" /> - <Compile Include="Sorting\StartDateComparer.cs" /> - <Compile Include="Sync\SyncHelper.cs" /> - <Compile Include="Sync\SyncJobOptions.cs" /> - <Compile Include="Sync\SyncNotificationEntryPoint.cs" /> - <Compile Include="UserViews\CollectionFolderImageProvider.cs" /> - <Compile Include="UserViews\DynamicImageProvider.cs" /> - <Compile Include="News\NewsEntryPoint.cs" /> - <Compile Include="News\NewsService.cs" /> - <Compile Include="Notifications\CoreNotificationTypes.cs" /> - <Compile Include="Notifications\InternalNotificationService.cs" /> - <Compile Include="Notifications\NotificationConfigurationFactory.cs" /> - <Compile Include="Notifications\NotificationManager.cs" /> - <Compile Include="Persistence\SqliteFileOrganizationRepository.cs" /> - <Compile Include="Notifications\SqliteNotificationsRepository.cs" /> - <Compile Include="Persistence\TypeMapper.cs" /> - <Compile Include="Photos\BaseDynamicImageProvider.cs" /> <Compile Include="Playlists\ManualPlaylistsFolder.cs" /> - <Compile Include="Photos\PhotoAlbumImageProvider.cs" /> - <Compile Include="Playlists\PlaylistImageProvider.cs" /> - <Compile Include="Playlists\PlaylistManager.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="ScheduledTasks\PeopleValidationTask.cs" /> - <Compile Include="ScheduledTasks\ChapterImagesTask.cs" /> - <Compile Include="ScheduledTasks\PluginUpdateTask.cs" /> - <Compile Include="ScheduledTasks\RefreshIntrosTask.cs" /> - <Compile Include="ScheduledTasks\RefreshMediaLibraryTask.cs" /> - <Compile Include="ScheduledTasks\SystemUpdateTask.cs" /> - <Compile Include="Security\AuthenticationRepository.cs" /> - <Compile Include="Security\EncryptionManager.cs" /> - <Compile Include="ServerApplicationPaths.cs" /> - <Compile Include="ServerManager\ServerManager.cs" /> - <Compile Include="ServerManager\WebSocketConnection.cs" /> - <Compile Include="Session\HttpSessionController.cs" /> - <Compile Include="Session\SessionManager.cs"> - <SubType>Code</SubType> - </Compile> - <Compile Include="Session\SessionWebSocketListener.cs" /> - <Compile Include="Session\WebSocketController.cs" /> - <Compile Include="Sorting\AiredEpisodeOrderComparer.cs" /> - <Compile Include="Sorting\AirTimeComparer.cs" /> - <Compile Include="Sorting\AlbumArtistComparer.cs" /> - <Compile Include="Sorting\AlbumComparer.cs" /> - <Compile Include="Sorting\AlphanumComparator.cs" /> - <Compile Include="Sorting\ArtistComparer.cs" /> - <Compile Include="Sorting\BudgetComparer.cs" /> - <Compile Include="Sorting\CommunityRatingComparer.cs" /> - <Compile Include="Sorting\CriticRatingComparer.cs" /> - <Compile Include="Sorting\DateCreatedComparer.cs" /> - <Compile Include="Sorting\DateLastMediaAddedComparer.cs" /> - <Compile Include="Sorting\DatePlayedComparer.cs" /> - <Compile Include="Sorting\GameSystemComparer.cs" /> - <Compile Include="Sorting\IsFavoriteOrLikeComparer.cs" /> - <Compile Include="Sorting\IsFolderComparer.cs" /> - <Compile Include="Sorting\IsPlayedComparer.cs" /> - <Compile Include="Sorting\IsUnplayedComparer.cs" /> - <Compile Include="Sorting\MetascoreComparer.cs" /> - <Compile Include="Sorting\NameComparer.cs" /> - <Compile Include="Sorting\OfficialRatingComparer.cs" /> - <Compile Include="Sorting\PlayCountComparer.cs" /> - <Compile Include="Sorting\PlayersComparer.cs" /> - <Compile Include="Sorting\PremiereDateComparer.cs" /> - <Compile Include="Sorting\ProductionYearComparer.cs" /> - <Compile Include="Sorting\RandomComparer.cs" /> - <Compile Include="Sorting\RevenueComparer.cs" /> - <Compile Include="Sorting\RuntimeComparer.cs" /> - <Compile Include="Sorting\SeriesSortNameComparer.cs" /> - <Compile Include="Sorting\SortNameComparer.cs" /> - <Compile Include="Persistence\SqliteDisplayPreferencesRepository.cs" /> - <Compile Include="Persistence\SqliteItemRepository.cs" /> - <Compile Include="Persistence\SqliteUserDataRepository.cs" /> - <Compile Include="Persistence\SqliteUserRepository.cs" /> - <Compile Include="Sorting\StudioComparer.cs" /> - <Compile Include="Sorting\VideoBitRateComparer.cs" /> - <Compile Include="Sync\AppSyncProvider.cs" /> - <Compile Include="Sync\CloudSyncProfile.cs" /> - <Compile Include="Sync\IHasSyncQuality.cs" /> - <Compile Include="Sync\MediaSync.cs" /> - <Compile Include="Sync\MultiProviderSync.cs" /> - <Compile Include="Sync\ServerSyncScheduledTask.cs" /> - <Compile Include="Sync\SyncedMediaSourceProvider.cs" /> - <Compile Include="Sync\SyncRegistrationInfo.cs" /> - <Compile Include="Sync\SyncConfig.cs" /> - <Compile Include="Sync\SyncJobProcessor.cs" /> - <Compile Include="Sync\SyncManager.cs" /> - <Compile Include="Sync\SyncRepository.cs" /> - <Compile Include="Sync\SyncConvertScheduledTask.cs" /> - <Compile Include="Sync\TargetDataProvider.cs" /> - <Compile Include="TV\TVSeriesManager.cs" /> - <Compile Include="Udp\UdpMessageReceivedEventArgs.cs" /> - <Compile Include="Udp\UdpServer.cs" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\MediaBrowser.Common.Implementations\MediaBrowser.Common.Implementations.csproj"> - <Project>{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}</Project> - <Name>MediaBrowser.Common.Implementations</Name> - </ProjectReference> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> <Project>{9142EEFA-7570-41E1-BFCC-468BB571AF2F}</Project> <Name>MediaBrowser.Common</Name> @@ -391,395 +61,12 @@ <Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project> <Name>MediaBrowser.Model</Name> </ProjectReference> - <ProjectReference Include="..\Mono.Nat\Mono.Nat.csproj"> - <Project>{d7453b88-2266-4805-b39b-2b5a2a33e1ba}</Project> - <Name>Mono.Nat</Name> - </ProjectReference> </ItemGroup> <ItemGroup> - <EmbeddedResource Include="Localization\Ratings\us.txt" /> - <EmbeddedResource Include="Localization\Ratings\au.txt" /> - <EmbeddedResource Include="Localization\Ratings\gb.txt" /> - <EmbeddedResource Include="Localization\Ratings\nl.txt" /> - <EmbeddedResource Include="Localization\Ratings\br.txt" /> - <EmbeddedResource Include="Localization\Ratings\dk.txt" /> - <EmbeddedResource Include="Localization\Ratings\de.txt" /> - <EmbeddedResource Include="Localization\Ratings\mx.txt" /> - <EmbeddedResource Include="Localization\Ratings\co.txt" /> - <EmbeddedResource Include="Localization\Ratings\fr.txt" /> - <EmbeddedResource Include="Localization\Ratings\ie.txt" /> - <EmbeddedResource Include="Localization\Ratings\jp.txt" /> - <EmbeddedResource Include="Localization\Ratings\kz.txt" /> - <EmbeddedResource Include="Localization\Ratings\nz.txt" /> - <EmbeddedResource Include="Localization\Ratings\ru.txt" /> - </ItemGroup> - <ItemGroup> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\backbone-min.js"> - <Link>swagger-ui\lib\backbone-min.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\handlebars-2.0.0.js"> - <Link>swagger-ui\lib\handlebars-2.0.0.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\highlight.7.3.pack.js"> - <Link>swagger-ui\lib\highlight.7.3.pack.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\jquery-1.8.0.min.js"> - <Link>swagger-ui\lib\jquery-1.8.0.min.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\jquery.ba-bbq.min.js"> - <Link>swagger-ui\lib\jquery.ba-bbq.min.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\jquery.slideto.min.js"> - <Link>swagger-ui\lib\jquery.slideto.min.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\jquery.wiggle.min.js"> - <Link>swagger-ui\lib\jquery.wiggle.min.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\marked.js"> - <Link>swagger-ui\lib\marked.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\shred.bundle.js"> - <Link>swagger-ui\lib\shred.bundle.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\swagger-client.js"> - <Link>swagger-ui\lib\swagger-client.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\swagger-oauth.js"> - <Link>swagger-ui\lib\swagger-oauth.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\underscore-min.js"> - <Link>swagger-ui\lib\underscore-min.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\o2c.html"> - <Link>swagger-ui\o2c.html</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\patch.js"> - <Link>swagger-ui\patch.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\swagger-ui.js"> - <Link>swagger-ui\swagger-ui.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\swagger-ui.min.js"> - <Link>swagger-ui\swagger-ui.min.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <EmbeddedResource Include="Localization\countries.json" /> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\fonts\droid-sans-v6-latin-700.eot"> - <Link>swagger-ui\fonts\droid-sans-v6-latin-700.eot</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\fonts\droid-sans-v6-latin-700.ttf"> - <Link>swagger-ui\fonts\droid-sans-v6-latin-700.ttf</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\fonts\droid-sans-v6-latin-700.woff"> - <Link>swagger-ui\fonts\droid-sans-v6-latin-700.woff</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\fonts\droid-sans-v6-latin-700.woff2"> - <Link>swagger-ui\fonts\droid-sans-v6-latin-700.woff2</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\fonts\droid-sans-v6-latin-regular.eot"> - <Link>swagger-ui\fonts\droid-sans-v6-latin-regular.eot</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\fonts\droid-sans-v6-latin-regular.ttf"> - <Link>swagger-ui\fonts\droid-sans-v6-latin-regular.ttf</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\fonts\droid-sans-v6-latin-regular.woff"> - <Link>swagger-ui\fonts\droid-sans-v6-latin-regular.woff</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\fonts\droid-sans-v6-latin-regular.woff2"> - <Link>swagger-ui\fonts\droid-sans-v6-latin-regular.woff2</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> <None Include="app.config" /> - <EmbeddedResource Include="Localization\Core\core.json" /> - <EmbeddedResource Include="Localization\Core\ar.json" /> - <EmbeddedResource Include="Localization\Core\bg-BG.json" /> - <EmbeddedResource Include="Localization\Core\ca.json" /> - <EmbeddedResource Include="Localization\Core\cs.json" /> - <EmbeddedResource Include="Localization\Core\da.json" /> - <EmbeddedResource Include="Localization\Core\de.json" /> - <EmbeddedResource Include="Localization\Core\el.json" /> - <EmbeddedResource Include="Localization\Core\en-GB.json" /> - <EmbeddedResource Include="Localization\Core\en-US.json" /> - <EmbeddedResource Include="Localization\Core\es-AR.json" /> - <EmbeddedResource Include="Localization\Core\es-MX.json" /> - <EmbeddedResource Include="Localization\Core\es.json" /> - <EmbeddedResource Include="Localization\Core\fi.json" /> - <EmbeddedResource Include="Localization\Core\fr.json" /> - <EmbeddedResource Include="Localization\Core\gsw.json" /> - <EmbeddedResource Include="Localization\Core\he.json" /> - <EmbeddedResource Include="Localization\Core\hr.json" /> - <EmbeddedResource Include="Localization\Core\it.json" /> - <EmbeddedResource Include="Localization\Core\kk.json" /> - <EmbeddedResource Include="Localization\Core\ko.json" /> - <EmbeddedResource Include="Localization\Core\ms.json" /> - <EmbeddedResource Include="Localization\Core\nb.json" /> - <EmbeddedResource Include="Localization\Core\nl.json" /> - <EmbeddedResource Include="Localization\Core\pl.json" /> - <EmbeddedResource Include="Localization\Core\pt-BR.json" /> - <EmbeddedResource Include="Localization\Core\pt-PT.json" /> - <EmbeddedResource Include="Localization\Core\ro.json" /> - <EmbeddedResource Include="Localization\Core\ru.json" /> - <EmbeddedResource Include="Localization\Core\sl-SI.json" /> - <EmbeddedResource Include="Localization\Core\sv.json" /> - <EmbeddedResource Include="Localization\Core\tr.json" /> - <EmbeddedResource Include="Localization\Core\uk.json" /> - <EmbeddedResource Include="Localization\Core\vi.json" /> - <EmbeddedResource Include="Localization\Core\zh-CN.json" /> - <EmbeddedResource Include="Localization\Core\zh-TW.json" /> - <EmbeddedResource Include="Localization\Core\zh-HK.json" /> - <EmbeddedResource Include="Localization\Core\hu.json" /> - <EmbeddedResource Include="Localization\Core\id.json" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0030.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0049.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0070.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0090.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0100.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0130.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0160.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0170.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0192.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0200.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0215.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0235.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0255.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0260.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0282.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0305.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0308.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0310.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0315.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0330.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0360.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0380.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0390.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0400.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0420.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0435.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0450.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0460.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0475.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0480.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0490.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0505.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0510.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0520.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0525.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0530.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0549.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0560.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0570.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0600.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0620.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0642.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0650.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0660.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0685.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0705.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0721.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0740.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0750.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0765.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0785.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0830.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0851.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0865.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0875.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0880.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0900.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0915.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0922.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0935.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0950.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0965.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1005.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1030.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1055.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1082.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1100.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1105.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1130.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1155.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1160.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1180.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1195.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1222.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1240.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1250.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1280.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1320.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1340.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1380.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1400.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1440.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1500.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1520.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1540.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1560.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1590.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1600 OPTUS D1 FTA %28160.0E%29.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1600.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1620.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1640.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1660.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1690.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1720.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1800.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\1830.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2210.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2230.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2250.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2270.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2290.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2310.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2330.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2350.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2370.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2390.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2410.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2432.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2451.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2470.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2489.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2500.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2527.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2550.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2570.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2590.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2608.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2630.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2650.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2669.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2690.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2710.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2728.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2730.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2750.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2760.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2770.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2780.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2812.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2820.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2830.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2850.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2873.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2880.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2881.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2882.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2900.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2930.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2950.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2970.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2985.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\2990.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3020.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3045.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3070.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3100.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3125.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3150.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3169.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3195.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3225.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3255.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3285.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3300.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3325.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3355.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3380.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3400.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3420.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3450.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3460.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3475.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3490.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3520.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3527.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3550.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3560.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3592.ini" /> - <EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3594.ini" /> - <EmbeddedResource Include="Localization\Core\fr-CA.json" /> - <None Include="packages.config" /> - </ItemGroup> - <ItemGroup> - <EmbeddedResource Include="Localization\Ratings\ca.txt" /> - </ItemGroup> - <ItemGroup> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\css\reset.css"> - <Link>swagger-ui\css\reset.css</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\css\screen.css"> - <Link>swagger-ui\css\screen.css</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\css\typography.css"> - <Link>swagger-ui\css\typography.css</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\fonts\droid-sans-v6-latin-700.svg"> - <Link>swagger-ui\fonts\droid-sans-v6-latin-700.svg</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\fonts\droid-sans-v6-latin-regular.svg"> - <Link>swagger-ui\fonts\droid-sans-v6-latin-regular.svg</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\images\explorer_icons.png"> - <Link>swagger-ui\images\explorer_icons.png</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\images\logo_small.png"> - <Link>swagger-ui\images\logo_small.png</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\images\pet_store_api.png"> - <Link>swagger-ui\images\pet_store_api.png</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\images\throbber.gif"> - <Link>swagger-ui\images\throbber.gif</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\images\wordnik_api.png"> - <Link>swagger-ui\images\wordnik_api.png</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\index.html"> - <Link>swagger-ui\index.html</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\shred\content.js"> - <Link>swagger-ui\lib\shred\content.js</Link> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - <EmbeddedResource Include="Localization\iso6392.txt" /> - <EmbeddedResource Include="Localization\Ratings\be.txt" /> </ItemGroup> <ItemGroup /> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs deleted file mode 100644 index 21e847c680..0000000000 --- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs +++ /dev/null @@ -1,234 +0,0 @@ -using MediaBrowser.Controller.Chapters; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Controller.Library; - -namespace MediaBrowser.Server.Implementations.MediaEncoder -{ - public class EncodingManager : IEncodingManager - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; - private readonly IMediaEncoder _encoder; - private readonly IChapterManager _chapterManager; - private readonly ILibraryManager _libraryManager; - - public EncodingManager(IFileSystem fileSystem, - ILogger logger, - IMediaEncoder encoder, - IChapterManager chapterManager, ILibraryManager libraryManager) - { - _fileSystem = fileSystem; - _logger = logger; - _encoder = encoder; - _chapterManager = chapterManager; - _libraryManager = libraryManager; - } - - /// <summary> - /// Gets the chapter images data path. - /// </summary> - /// <value>The chapter images data path.</value> - private string GetChapterImagesPath(IHasImages item) - { - return Path.Combine(item.GetInternalMetadataPath(), "chapters"); - } - - /// <summary> - /// Determines whether [is eligible for chapter image extraction] [the specified video]. - /// </summary> - /// <param name="video">The video.</param> - /// <returns><c>true</c> if [is eligible for chapter image extraction] [the specified video]; otherwise, <c>false</c>.</returns> - private bool IsEligibleForChapterImageExtraction(Video video) - { - if (video.IsPlaceHolder) - { - return false; - } - - var libraryOptions = _libraryManager.GetLibraryOptions(video); - if (libraryOptions != null) - { - if (!libraryOptions.EnableChapterImageExtraction) - { - return false; - } - } - else - { - return false; - } - - // Can't extract images if there are no video streams - return video.DefaultVideoStreamIndex.HasValue; - } - - /// <summary> - /// The first chapter ticks - /// </summary> - private static readonly long FirstChapterTicks = TimeSpan.FromSeconds(15).Ticks; - - public async Task<bool> RefreshChapterImages(ChapterImageRefreshOptions options, CancellationToken cancellationToken) - { - var extractImages = options.ExtractImages; - var video = options.Video; - var chapters = options.Chapters; - var saveChapters = options.SaveChapters; - - if (!IsEligibleForChapterImageExtraction(video)) - { - extractImages = false; - } - - var success = true; - var changesMade = false; - - var runtimeTicks = video.RunTimeTicks ?? 0; - - var currentImages = GetSavedChapterImages(video); - - foreach (var chapter in chapters) - { - if (chapter.StartPositionTicks >= runtimeTicks) - { - _logger.Info("Stopping chapter extraction for {0} because a chapter was found with a position greater than the runtime.", video.Name); - break; - } - - var path = GetChapterImagePath(video, chapter.StartPositionTicks); - - if (!currentImages.Contains(path, StringComparer.OrdinalIgnoreCase)) - { - if (extractImages) - { - if (video.VideoType == VideoType.HdDvd || video.VideoType == VideoType.Iso) - { - continue; - } - if (video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd) - { - if (video.PlayableStreamFileNames.Count != 1) - { - continue; - } - } - - try - { - // Add some time for the first chapter to make sure we don't end up with a black image - var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); - - var protocol = MediaProtocol.File; - - var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames); - - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - - var container = video.Container; - - var tempFile = await _encoder.ExtractVideoImage(inputPath, container, protocol, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false); - File.Copy(tempFile, path, true); - - try - { - File.Delete(tempFile); - } - catch - { - - } - - chapter.ImagePath = path; - chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path); - changesMade = true; - } - catch (Exception ex) - { - _logger.ErrorException("Error extracting chapter images for {0}", ex, string.Join(",", video.Path)); - success = false; - break; - } - } - else if (!string.IsNullOrEmpty(chapter.ImagePath)) - { - chapter.ImagePath = null; - changesMade = true; - } - } - else if (!string.Equals(path, chapter.ImagePath, StringComparison.OrdinalIgnoreCase)) - { - chapter.ImagePath = path; - chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path); - changesMade = true; - } - } - - if (saveChapters && changesMade) - { - await _chapterManager.SaveChapters(video.Id.ToString(), chapters, cancellationToken).ConfigureAwait(false); - } - - DeleteDeadImages(currentImages, chapters); - - return success; - } - - private string GetChapterImagePath(Video video, long chapterPositionTicks) - { - var filename = video.DateModified.Ticks.ToString(_usCulture) + "_" + chapterPositionTicks.ToString(_usCulture) + ".jpg"; - - return Path.Combine(GetChapterImagesPath(video), filename); - } - - private List<string> GetSavedChapterImages(Video video) - { - var path = GetChapterImagesPath(video); - - try - { - return _fileSystem.GetFilePaths(path) - .ToList(); - } - catch (DirectoryNotFoundException) - { - return new List<string>(); - } - } - - private void DeleteDeadImages(IEnumerable<string> images, IEnumerable<ChapterInfo> chapters) - { - var deadImages = images - .Except(chapters.Select(i => i.ImagePath).Where(i => !string.IsNullOrEmpty(i)), StringComparer.OrdinalIgnoreCase) - .Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i), StringComparer.OrdinalIgnoreCase)) - .ToList(); - - foreach (var image in deadImages) - { - _logger.Debug("Deleting dead chapter image {0}", image); - - try - { - _fileSystem.DeleteFile(image); - } - catch (IOException ex) - { - _logger.ErrorException("Error deleting {0}.", ex, image); - } - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs b/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs deleted file mode 100644 index c15af6f701..0000000000 --- a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs +++ /dev/null @@ -1,168 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Notifications; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.News; -using MediaBrowser.Model.Notifications; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Xml; -using CommonIO; -using MediaBrowser.Common.Threading; - -namespace MediaBrowser.Server.Implementations.News -{ - public class NewsEntryPoint : IServerEntryPoint - { - private PeriodicTimer _timer; - private readonly IHttpClient _httpClient; - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; - private readonly IJsonSerializer _json; - - private readonly INotificationManager _notifications; - private readonly IUserManager _userManager; - - private readonly TimeSpan _frequency = TimeSpan.FromHours(24); - - public NewsEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IJsonSerializer json, INotificationManager notifications, IUserManager userManager) - { - _httpClient = httpClient; - _appPaths = appPaths; - _fileSystem = fileSystem; - _logger = logger; - _json = json; - _notifications = notifications; - _userManager = userManager; - } - - public void Run() - { - _timer = new PeriodicTimer(OnTimerFired, null, TimeSpan.FromMilliseconds(500), _frequency); - } - - /// <summary> - /// Called when [timer fired]. - /// </summary> - /// <param name="state">The state.</param> - private async void OnTimerFired(object state) - { - var path = Path.Combine(_appPaths.CachePath, "news.json"); - - try - { - await DownloadNews(path).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error downloading news", ex); - } - } - - private async Task DownloadNews(string path) - { - DateTime? lastUpdate = null; - - if (_fileSystem.FileExists(path)) - { - lastUpdate = _fileSystem.GetLastWriteTimeUtc(path); - } - - var requestOptions = new HttpRequestOptions - { - Url = "http://emby.media/community/index.php?/blog/rss/1-media-browser-developers-blog", - Progress = new Progress<double>(), - UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.42 Safari/537.36", - BufferContent = false - }; - - using (var stream = await _httpClient.Get(requestOptions).ConfigureAwait(false)) - { - var doc = new XmlDocument(); - doc.Load(stream); - - var news = ParseRssItems(doc).ToList(); - - _json.SerializeToFile(news, path); - - await CreateNotifications(news, lastUpdate, CancellationToken.None).ConfigureAwait(false); - } - } - - private Task CreateNotifications(List<NewsItem> items, DateTime? lastUpdate, CancellationToken cancellationToken) - { - if (lastUpdate.HasValue) - { - items = items.Where(i => i.Date.ToUniversalTime() >= lastUpdate.Value) - .ToList(); - } - - var tasks = items.Select(i => _notifications.SendNotification(new NotificationRequest - { - Date = i.Date, - Name = i.Title, - Description = i.Description, - Url = i.Link, - UserIds = _userManager.Users.Select(u => u.Id.ToString("N")).ToList() - - }, cancellationToken)); - - return Task.WhenAll(tasks); - } - - private IEnumerable<NewsItem> ParseRssItems(XmlDocument xmlDoc) - { - var nodes = xmlDoc.SelectNodes("rss/channel/item"); - - if (nodes != null) - { - foreach (XmlNode node in nodes) - { - var newsItem = new NewsItem(); - - newsItem.Title = ParseDocElements(node, "title"); - - newsItem.DescriptionHtml = ParseDocElements(node, "description"); - newsItem.Description = newsItem.DescriptionHtml.StripHtml(); - - newsItem.Link = ParseDocElements(node, "link"); - - var date = ParseDocElements(node, "pubDate"); - DateTime parsedDate; - - if (DateTime.TryParse(date, out parsedDate)) - { - newsItem.Date = parsedDate; - } - - yield return newsItem; - } - } - } - - private string ParseDocElements(XmlNode parent, string xPath) - { - var node = parent.SelectSingleNode(xPath); - - return node != null ? node.InnerText : string.Empty; - } - - public void Dispose() - { - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/News/NewsService.cs b/MediaBrowser.Server.Implementations/News/NewsService.cs deleted file mode 100644 index 684363d01a..0000000000 --- a/MediaBrowser.Server.Implementations/News/NewsService.cs +++ /dev/null @@ -1,78 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.News; -using MediaBrowser.Model.News; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Serialization; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace MediaBrowser.Server.Implementations.News -{ - public class NewsService : INewsService - { - private readonly IApplicationPaths _appPaths; - private readonly IJsonSerializer _json; - - public NewsService(IApplicationPaths appPaths, IJsonSerializer json) - { - _appPaths = appPaths; - _json = json; - } - - public QueryResult<NewsItem> GetProductNews(NewsQuery query) - { - try - { - return GetProductNewsInternal(query); - } - catch (DirectoryNotFoundException) - { - // No biggie - return new QueryResult<NewsItem> - { - Items = new NewsItem[] { } - }; - } - catch (FileNotFoundException) - { - // No biggie - return new QueryResult<NewsItem> - { - Items = new NewsItem[] { } - }; - } - } - - private QueryResult<NewsItem> GetProductNewsInternal(NewsQuery query) - { - var path = Path.Combine(_appPaths.CachePath, "news.json"); - - var items = GetNewsItems(path).OrderByDescending(i => i.Date); - - var itemsArray = items.ToArray(); - var count = itemsArray.Length; - - if (query.StartIndex.HasValue) - { - itemsArray = itemsArray.Skip(query.StartIndex.Value).ToArray(); - } - - if (query.Limit.HasValue) - { - itemsArray = itemsArray.Take(query.Limit.Value).ToArray(); - } - - return new QueryResult<NewsItem> - { - Items = itemsArray, - TotalRecordCount = count - }; - } - - private IEnumerable<NewsItem> GetNewsItems(string path) - { - return _json.DeserializeFromFile<List<NewsItem>>(path); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs b/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs deleted file mode 100644 index 8ca6677398..0000000000 --- a/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs +++ /dev/null @@ -1,198 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Localization; -using MediaBrowser.Controller.Notifications; -using MediaBrowser.Model.Notifications; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MediaBrowser.Server.Implementations.Notifications -{ - public class CoreNotificationTypes : INotificationTypeFactory - { - private readonly ILocalizationManager _localization; - private readonly IServerApplicationHost _appHost; - - public CoreNotificationTypes(ILocalizationManager localization, IServerApplicationHost appHost) - { - _localization = localization; - _appHost = appHost; - } - - public IEnumerable<NotificationTypeInfo> GetNotificationTypes() - { - var knownTypes = new List<NotificationTypeInfo> - { - new NotificationTypeInfo - { - Type = NotificationType.ApplicationUpdateInstalled.ToString(), - DefaultDescription = "{ReleaseNotes}", - DefaultTitle = "A new version of Emby Server has been installed.", - Variables = new List<string>{"Version"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.InstallationFailed.ToString(), - DefaultTitle = "{Name} installation failed.", - Variables = new List<string>{"Name", "Version"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.PluginInstalled.ToString(), - DefaultTitle = "{Name} was installed.", - Variables = new List<string>{"Name", "Version"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.PluginError.ToString(), - DefaultTitle = "{Name} has encountered an error.", - DefaultDescription = "{ErrorMessage}", - Variables = new List<string>{"Name", "ErrorMessage"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.PluginUninstalled.ToString(), - DefaultTitle = "{Name} was uninstalled.", - Variables = new List<string>{"Name", "Version"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.PluginUpdateInstalled.ToString(), - DefaultTitle = "{Name} was updated.", - DefaultDescription = "{ReleaseNotes}", - Variables = new List<string>{"Name", "ReleaseNotes", "Version"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.ServerRestartRequired.ToString(), - DefaultTitle = "Please restart Emby Server to finish updating." - }, - - new NotificationTypeInfo - { - Type = NotificationType.TaskFailed.ToString(), - DefaultTitle = "{Name} failed.", - DefaultDescription = "{ErrorMessage}", - Variables = new List<string>{"Name", "ErrorMessage"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.NewLibraryContent.ToString(), - DefaultTitle = "{Name} has been added to your media library.", - Variables = new List<string>{"Name"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.AudioPlayback.ToString(), - DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.", - Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.GamePlayback.ToString(), - DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.", - Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.VideoPlayback.ToString(), - DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.", - Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.AudioPlaybackStopped.ToString(), - DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.", - Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.GamePlaybackStopped.ToString(), - DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.", - Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.VideoPlaybackStopped.ToString(), - DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.", - Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.CameraImageUploaded.ToString(), - DefaultTitle = "A new camera image has been uploaded from {DeviceName}.", - Variables = new List<string>{"DeviceName"} - }, - - new NotificationTypeInfo - { - Type = NotificationType.UserLockedOut.ToString(), - DefaultTitle = "{UserName} has been locked out.", - Variables = new List<string>{"UserName"} - } - }; - - if (!_appHost.CanSelfUpdate) - { - knownTypes.Add(new NotificationTypeInfo - { - Type = NotificationType.ApplicationUpdateAvailable.ToString(), - DefaultTitle = "A new version of Emby Server is available for download." - }); - } - - foreach (var type in knownTypes) - { - Update(type); - } - - var systemName = _localization.GetLocalizedString("CategorySystem"); - - return knownTypes.OrderByDescending(i => string.Equals(i.Category, systemName, StringComparison.OrdinalIgnoreCase)) - .ThenBy(i => i.Category) - .ThenBy(i => i.Name); - } - - private void Update(NotificationTypeInfo note) - { - note.Name = _localization.GetLocalizedString("NotificationOption" + note.Type) ?? note.Type; - - note.IsBasedOnUserEvent = note.Type.IndexOf("Playback", StringComparison.OrdinalIgnoreCase) != -1; - - if (note.Type.IndexOf("Playback", StringComparison.OrdinalIgnoreCase) != -1) - { - note.Category = _localization.GetLocalizedString("CategoryUser"); - } - else if (note.Type.IndexOf("Plugin", StringComparison.OrdinalIgnoreCase) != -1) - { - note.Category = _localization.GetLocalizedString("CategoryPlugin"); - } - else if (note.Type.IndexOf("CameraImageUploaded", StringComparison.OrdinalIgnoreCase) != -1) - { - note.Category = _localization.GetLocalizedString("CategorySync"); - } - else if (note.Type.IndexOf("UserLockedOut", StringComparison.OrdinalIgnoreCase) != -1) - { - note.Category = _localization.GetLocalizedString("CategoryUser"); - } - else - { - note.Category = _localization.GetLocalizedString("CategorySystem"); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Notifications/IConfigurableNotificationService.cs b/MediaBrowser.Server.Implementations/Notifications/IConfigurableNotificationService.cs deleted file mode 100644 index cdfd0f640f..0000000000 --- a/MediaBrowser.Server.Implementations/Notifications/IConfigurableNotificationService.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace MediaBrowser.Server.Implementations.Notifications -{ - public interface IConfigurableNotificationService - { - bool IsHidden { get; } - bool IsEnabled(string notificationType); - } -} diff --git a/MediaBrowser.Server.Implementations/Notifications/InternalNotificationService.cs b/MediaBrowser.Server.Implementations/Notifications/InternalNotificationService.cs deleted file mode 100644 index 4a625f0fb0..0000000000 --- a/MediaBrowser.Server.Implementations/Notifications/InternalNotificationService.cs +++ /dev/null @@ -1,61 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Notifications; -using MediaBrowser.Model.Notifications; -using System.Threading; -using System.Threading.Tasks; -using System; - -namespace MediaBrowser.Server.Implementations.Notifications -{ - public class InternalNotificationService : INotificationService, IConfigurableNotificationService - { - private readonly INotificationsRepository _repo; - - public InternalNotificationService(INotificationsRepository repo) - { - _repo = repo; - } - - public string Name - { - get { return "Dashboard Notifications"; } - } - - public Task SendNotification(UserNotification request, CancellationToken cancellationToken) - { - return _repo.AddNotification(new Notification - { - Date = request.Date, - Description = request.Description, - Level = request.Level, - Name = request.Name, - Url = request.Url, - UserId = request.User.Id.ToString("N") - - }, cancellationToken); - } - - public bool IsEnabledForUser(User user) - { - return user.Policy.IsAdministrator; - } - - public bool IsHidden - { - get { return true; } - } - - public bool IsEnabled(string notificationType) - { - if (notificationType.IndexOf("playback", StringComparison.OrdinalIgnoreCase) != -1) - { - return false; - } - if (notificationType.IndexOf("newlibrarycontent", StringComparison.OrdinalIgnoreCase) != -1) - { - return false; - } - return true; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Notifications/NotificationConfigurationFactory.cs b/MediaBrowser.Server.Implementations/Notifications/NotificationConfigurationFactory.cs deleted file mode 100644 index a336eba0ed..0000000000 --- a/MediaBrowser.Server.Implementations/Notifications/NotificationConfigurationFactory.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Notifications; -using System.Collections.Generic; - -namespace MediaBrowser.Server.Implementations.Notifications -{ - public class NotificationConfigurationFactory : IConfigurationFactory - { - public IEnumerable<ConfigurationStore> GetConfigurations() - { - return new List<ConfigurationStore> - { - new ConfigurationStore - { - Key = "notifications", - ConfigurationType = typeof (NotificationOptions) - } - }; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs deleted file mode 100644 index f19ff8a5f2..0000000000 --- a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs +++ /dev/null @@ -1,296 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Notifications; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Notifications; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Server.Implementations.Notifications -{ - public class NotificationManager : INotificationManager - { - private readonly ILogger _logger; - private readonly IUserManager _userManager; - private readonly IServerConfigurationManager _config; - - private INotificationService[] _services; - private INotificationTypeFactory[] _typeFactories; - - public NotificationManager(ILogManager logManager, IUserManager userManager, IServerConfigurationManager config) - { - _userManager = userManager; - _config = config; - _logger = logManager.GetLogger(GetType().Name); - } - - private NotificationOptions GetConfiguration() - { - return _config.GetConfiguration<NotificationOptions>("notifications"); - } - - public Task SendNotification(NotificationRequest request, CancellationToken cancellationToken) - { - var notificationType = request.NotificationType; - - var options = string.IsNullOrWhiteSpace(notificationType) ? - null : - GetConfiguration().GetOptions(notificationType); - - var users = GetUserIds(request, options) - .Select(i => _userManager.GetUserById(i)); - - var title = GetTitle(request, options); - var description = GetDescription(request, options); - - var tasks = _services.Where(i => IsEnabled(i, notificationType)) - .Select(i => SendNotification(request, i, users, title, description, cancellationToken)); - - return Task.WhenAll(tasks); - } - - private Task SendNotification(NotificationRequest request, - INotificationService service, - IEnumerable<User> users, - string title, - string description, - CancellationToken cancellationToken) - { - users = users.Where(i => IsEnabledForUser(service, i)) - .ToList(); - - var tasks = users.Select(i => SendNotification(request, service, title, description, i, cancellationToken)); - - return Task.WhenAll(tasks); - - } - - private IEnumerable<string> GetUserIds(NotificationRequest request, NotificationOption options) - { - if (request.SendToUserMode.HasValue) - { - switch (request.SendToUserMode.Value) - { - case SendToUserType.Admins: - return _userManager.Users.Where(i => i.Policy.IsAdministrator) - .Select(i => i.Id.ToString("N")); - case SendToUserType.All: - return _userManager.Users.Select(i => i.Id.ToString("N")); - case SendToUserType.Custom: - return request.UserIds; - default: - throw new ArgumentException("Unrecognized SendToUserMode: " + request.SendToUserMode.Value); - } - } - - if (options != null && !string.IsNullOrWhiteSpace(request.NotificationType)) - { - var config = GetConfiguration(); - - return _userManager.Users - .Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N"), i.Policy)) - .Select(i => i.Id.ToString("N")); - } - - return request.UserIds; - } - - private async Task SendNotification(NotificationRequest request, - INotificationService service, - string title, - string description, - User user, - CancellationToken cancellationToken) - { - var notification = new UserNotification - { - Date = request.Date, - Description = description, - Level = request.Level, - Name = title, - Url = request.Url, - User = user - }; - - _logger.Debug("Sending notification via {0} to user {1}", service.Name, user.Name); - - try - { - await service.SendNotification(notification, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending notification to {0}", ex, service.Name); - } - } - - private string GetTitle(NotificationRequest request, NotificationOption options) - { - var title = request.Name; - - // If empty, grab from options - if (string.IsNullOrEmpty(title)) - { - if (!string.IsNullOrEmpty(request.NotificationType)) - { - if (options != null) - { - title = options.Title; - } - } - } - - // If still empty, grab default - if (string.IsNullOrEmpty(title)) - { - if (!string.IsNullOrEmpty(request.NotificationType)) - { - var info = GetNotificationTypes().FirstOrDefault(i => string.Equals(i.Type, request.NotificationType, StringComparison.OrdinalIgnoreCase)); - - if (info != null) - { - title = info.DefaultTitle; - } - } - } - - title = title ?? string.Empty; - - foreach (var pair in request.Variables) - { - var token = "{" + pair.Key + "}"; - - title = title.Replace(token, pair.Value, StringComparison.OrdinalIgnoreCase); - } - - return title; - } - - private string GetDescription(NotificationRequest request, NotificationOption options) - { - var text = request.Description; - - // If empty, grab from options - if (string.IsNullOrEmpty(text)) - { - if (!string.IsNullOrEmpty(request.NotificationType)) - { - if (options != null) - { - text = options.Description; - } - } - } - - // If still empty, grab default - if (string.IsNullOrEmpty(text)) - { - if (!string.IsNullOrEmpty(request.NotificationType)) - { - var info = GetNotificationTypes().FirstOrDefault(i => string.Equals(i.Type, request.NotificationType, StringComparison.OrdinalIgnoreCase)); - - if (info != null) - { - text = info.DefaultDescription; - } - } - } - - text = text ?? string.Empty; - - foreach (var pair in request.Variables) - { - var token = "{" + pair.Key + "}"; - - text = text.Replace(token, pair.Value, StringComparison.OrdinalIgnoreCase); - } - - return text; - } - - private bool IsEnabledForUser(INotificationService service, User user) - { - try - { - return service.IsEnabledForUser(user); - } - catch (Exception ex) - { - _logger.ErrorException("Error in IsEnabledForUser", ex); - return false; - } - } - - private bool IsEnabled(INotificationService service, string notificationType) - { - if (string.IsNullOrEmpty(notificationType)) - { - return true; - } - - var configurable = service as IConfigurableNotificationService; - - if (configurable != null) - { - return configurable.IsEnabled(notificationType); - } - - return GetConfiguration().IsServiceEnabled(service.Name, notificationType); - } - - public void AddParts(IEnumerable<INotificationService> services, IEnumerable<INotificationTypeFactory> notificationTypeFactories) - { - _services = services.ToArray(); - _typeFactories = notificationTypeFactories.ToArray(); - } - - public IEnumerable<NotificationTypeInfo> GetNotificationTypes() - { - var list = _typeFactories.Select(i => - { - try - { - return i.GetNotificationTypes().ToList(); - } - catch (Exception ex) - { - _logger.ErrorException("Error in GetNotificationTypes", ex); - return new List<NotificationTypeInfo>(); - } - - }).SelectMany(i => i).ToList(); - - var config = GetConfiguration(); - - foreach (var i in list) - { - i.Enabled = config.IsEnabled(i.Type); - } - - return list; - } - - public IEnumerable<NotificationServiceInfo> GetNotificationServices() - { - return _services.Where(i => - { - var configurable = i as IConfigurableNotificationService; - - return configurable == null || !configurable.IsHidden; - - }).Select(i => new NotificationServiceInfo - { - Name = i.Name, - Id = i.Name.GetMD5().ToString("N") - - }).OrderBy(i => i.Name); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs deleted file mode 100644 index f30ba3e542..0000000000 --- a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs +++ /dev/null @@ -1,470 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Notifications; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Notifications; -using MediaBrowser.Server.Implementations.Persistence; -using System; -using System.Collections.Generic; -using System.Data; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Notifications -{ - public class SqliteNotificationsRepository : BaseSqliteRepository, INotificationsRepository - { - public SqliteNotificationsRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector dbConnector) : base(logManager, dbConnector) - { - DbFilePath = Path.Combine(appPaths.DataPath, "notifications.db"); - } - - public event EventHandler<NotificationUpdateEventArgs> NotificationAdded; - public event EventHandler<NotificationReadEventArgs> NotificationsMarkedRead; - ////public event EventHandler<NotificationUpdateEventArgs> NotificationUpdated; - - public async Task Initialize() - { - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - string[] queries = { - - "create table if not exists Notifications (Id GUID NOT NULL, UserId GUID NOT NULL, Date DATETIME NOT NULL, Name TEXT NOT NULL, Description TEXT, Url TEXT, Level TEXT NOT NULL, IsRead BOOLEAN NOT NULL, Category TEXT NOT NULL, RelatedId TEXT, PRIMARY KEY (Id, UserId))", - "create index if not exists idx_Notifications1 on Notifications(Id)", - "create index if not exists idx_Notifications2 on Notifications(UserId)" - }; - - connection.RunQueries(queries, Logger); - } - } - - /// <summary> - /// Gets the notifications. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>NotificationResult.</returns> - public NotificationResult GetNotifications(NotificationQuery query) - { - var result = new NotificationResult(); - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - var clauses = new List<string>(); - - if (query.IsRead.HasValue) - { - clauses.Add("IsRead=@IsRead"); - cmd.Parameters.Add(cmd, "@IsRead", DbType.Boolean).Value = query.IsRead.Value; - } - - clauses.Add("UserId=@UserId"); - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(query.UserId); - - var whereClause = " where " + string.Join(" And ", clauses.ToArray()); - - cmd.CommandText = string.Format("select count(Id) from Notifications{0};select Id,UserId,Date,Name,Description,Url,Level,IsRead,Category,RelatedId from Notifications{0} order by IsRead asc, Date desc", whereClause); - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - if (reader.Read()) - { - result.TotalRecordCount = reader.GetInt32(0); - } - - if (reader.NextResult()) - { - var notifications = GetNotifications(reader); - - if (query.StartIndex.HasValue) - { - notifications = notifications.Skip(query.StartIndex.Value); - } - - if (query.Limit.HasValue) - { - notifications = notifications.Take(query.Limit.Value); - } - - result.Notifications = notifications.ToArray(); - } - } - - return result; - } - } - } - - public NotificationsSummary GetNotificationsSummary(string userId) - { - var result = new NotificationsSummary(); - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select Level from Notifications where UserId=@UserId and IsRead=@IsRead"; - - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(userId); - cmd.Parameters.Add(cmd, "@IsRead", DbType.Boolean).Value = false; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - var levels = new List<NotificationLevel>(); - - while (reader.Read()) - { - levels.Add(GetLevel(reader, 0)); - } - - result.UnreadCount = levels.Count; - - if (levels.Count > 0) - { - result.MaxUnreadNotificationLevel = levels.Max(); - } - } - - return result; - } - } - } - - /// <summary> - /// Gets the notifications. - /// </summary> - /// <param name="reader">The reader.</param> - /// <returns>IEnumerable{Notification}.</returns> - private IEnumerable<Notification> GetNotifications(IDataReader reader) - { - var list = new List<Notification>(); - - while (reader.Read()) - { - list.Add(GetNotification(reader)); - } - - return list; - } - - private Notification GetNotification(IDataReader reader) - { - var notification = new Notification - { - Id = reader.GetGuid(0).ToString("N"), - UserId = reader.GetGuid(1).ToString("N"), - Date = reader.GetDateTime(2).ToUniversalTime(), - Name = reader.GetString(3) - }; - - if (!reader.IsDBNull(4)) - { - notification.Description = reader.GetString(4); - } - - if (!reader.IsDBNull(5)) - { - notification.Url = reader.GetString(5); - } - - notification.Level = GetLevel(reader, 6); - notification.IsRead = reader.GetBoolean(7); - - return notification; - } - - /// <summary> - /// Gets the level. - /// </summary> - /// <param name="reader">The reader.</param> - /// <param name="index">The index.</param> - /// <returns>NotificationLevel.</returns> - private NotificationLevel GetLevel(IDataReader reader, int index) - { - NotificationLevel level; - - var val = reader.GetString(index); - - Enum.TryParse(val, true, out level); - - return level; - } - - /// <summary> - /// Adds the notification. - /// </summary> - /// <param name="notification">The notification.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task AddNotification(Notification notification, CancellationToken cancellationToken) - { - await ReplaceNotification(notification, cancellationToken).ConfigureAwait(false); - - if (NotificationAdded != null) - { - try - { - NotificationAdded(this, new NotificationUpdateEventArgs - { - Notification = notification - }); - } - catch (Exception ex) - { - Logger.ErrorException("Error in NotificationAdded event handler", ex); - } - } - } - - /// <summary> - /// Replaces the notification. - /// </summary> - /// <param name="notification">The notification.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - private async Task ReplaceNotification(Notification notification, CancellationToken cancellationToken) - { - if (string.IsNullOrEmpty(notification.Id)) - { - notification.Id = Guid.NewGuid().ToString("N"); - } - if (string.IsNullOrEmpty(notification.UserId)) - { - throw new ArgumentException("The notification must have a user id"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var replaceNotificationCommand = connection.CreateCommand()) - { - replaceNotificationCommand.CommandText = "replace into Notifications (Id, UserId, Date, Name, Description, Url, Level, IsRead, Category, RelatedId) values (@Id, @UserId, @Date, @Name, @Description, @Url, @Level, @IsRead, @Category, @RelatedId)"; - - replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Id"); - replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@UserId"); - replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Date"); - replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Name"); - replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Description"); - replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Url"); - replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Level"); - replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@IsRead"); - replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Category"); - replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@RelatedId"); - - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - replaceNotificationCommand.GetParameter(0).Value = new Guid(notification.Id); - replaceNotificationCommand.GetParameter(1).Value = new Guid(notification.UserId); - replaceNotificationCommand.GetParameter(2).Value = notification.Date.ToUniversalTime(); - replaceNotificationCommand.GetParameter(3).Value = notification.Name; - replaceNotificationCommand.GetParameter(4).Value = notification.Description; - replaceNotificationCommand.GetParameter(5).Value = notification.Url; - replaceNotificationCommand.GetParameter(6).Value = notification.Level.ToString(); - replaceNotificationCommand.GetParameter(7).Value = notification.IsRead; - replaceNotificationCommand.GetParameter(8).Value = string.Empty; - replaceNotificationCommand.GetParameter(9).Value = string.Empty; - - replaceNotificationCommand.Transaction = transaction; - - replaceNotificationCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save notification:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - - /// <summary> - /// Marks the read. - /// </summary> - /// <param name="notificationIdList">The notification id list.</param> - /// <param name="userId">The user id.</param> - /// <param name="isRead">if set to <c>true</c> [is read].</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task MarkRead(IEnumerable<string> notificationIdList, string userId, bool isRead, CancellationToken cancellationToken) - { - var list = notificationIdList.ToList(); - var idArray = list.Select(i => new Guid(i)).ToArray(); - - await MarkReadInternal(idArray, userId, isRead, cancellationToken).ConfigureAwait(false); - - if (NotificationsMarkedRead != null) - { - try - { - NotificationsMarkedRead(this, new NotificationReadEventArgs - { - IdList = list.ToArray(), - IsRead = isRead, - UserId = userId - }); - } - catch (Exception ex) - { - Logger.ErrorException("Error in NotificationsMarkedRead event handler", ex); - } - } - } - - public async Task MarkAllRead(string userId, bool isRead, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var markAllReadCommand = connection.CreateCommand()) - { - markAllReadCommand.CommandText = "update Notifications set IsRead=@IsRead where UserId=@UserId"; - - markAllReadCommand.Parameters.Add(markAllReadCommand, "@UserId"); - markAllReadCommand.Parameters.Add(markAllReadCommand, "@IsRead"); - - IDbTransaction transaction = null; - - try - { - cancellationToken.ThrowIfCancellationRequested(); - - transaction = connection.BeginTransaction(); - - markAllReadCommand.GetParameter(0).Value = new Guid(userId); - markAllReadCommand.GetParameter(1).Value = isRead; - - markAllReadCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save notification:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - - private async Task MarkReadInternal(IEnumerable<Guid> notificationIdList, string userId, bool isRead, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var markReadCommand = connection.CreateCommand()) - { - markReadCommand.CommandText = "update Notifications set IsRead=@IsRead where Id=@Id and UserId=@UserId"; - - markReadCommand.Parameters.Add(markReadCommand, "@UserId"); - markReadCommand.Parameters.Add(markReadCommand, "@IsRead"); - markReadCommand.Parameters.Add(markReadCommand, "@Id"); - - IDbTransaction transaction = null; - - try - { - cancellationToken.ThrowIfCancellationRequested(); - - transaction = connection.BeginTransaction(); - - markReadCommand.GetParameter(0).Value = new Guid(userId); - markReadCommand.GetParameter(1).Value = isRead; - - foreach (var id in notificationIdList) - { - markReadCommand.GetParameter(2).Value = id; - - markReadCommand.Transaction = transaction; - - markReadCommand.ExecuteNonQuery(); - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save notification:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs deleted file mode 100644 index 233ab56fed..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs +++ /dev/null @@ -1,114 +0,0 @@ -using MediaBrowser.Model.Logging; -using System; -using System.Data; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - public abstract class BaseSqliteRepository : IDisposable - { - protected SemaphoreSlim WriteLock = new SemaphoreSlim(1, 1); - protected readonly IDbConnector DbConnector; - protected ILogger Logger; - - protected string DbFilePath { get; set; } - - protected BaseSqliteRepository(ILogManager logManager, IDbConnector dbConnector) - { - DbConnector = dbConnector; - Logger = logManager.GetLogger(GetType().Name); - } - - protected virtual bool EnableConnectionPooling - { - get { return true; } - } - - protected virtual async Task<IDbConnection> CreateConnection(bool isReadOnly = false) - { - var connection = await DbConnector.Connect(DbFilePath, false, true).ConfigureAwait(false); - - connection.RunQueries(new[] - { - "pragma temp_store = memory" - - }, Logger); - - return connection; - } - - private bool _disposed; - protected void CheckDisposed() - { - if (_disposed) - { - throw new ObjectDisposedException(GetType().Name + " has been disposed and cannot be accessed."); - } - } - - public void Dispose() - { - _disposed = true; - Dispose(true); - GC.SuppressFinalize(this); - } - - protected async Task Vacuum(IDbConnection connection) - { - CheckDisposed(); - - await WriteLock.WaitAsync().ConfigureAwait(false); - - try - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "vacuum"; - cmd.ExecuteNonQuery(); - } - } - catch (Exception e) - { - Logger.ErrorException("Failed to vacuum:", e); - - throw; - } - finally - { - WriteLock.Release(); - } - } - - private readonly object _disposeLock = new object(); - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - try - { - lock (_disposeLock) - { - WriteLock.Wait(); - - CloseConnection(); - } - } - catch (Exception ex) - { - Logger.ErrorException("Error disposing database", ex); - } - } - } - - protected virtual void CloseConnection() - { - - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs deleted file mode 100644 index c1394ee1c3..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs +++ /dev/null @@ -1,348 +0,0 @@ -using MediaBrowser.Common.Progress; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Localization; -using MediaBrowser.Controller.Net; -using MediaBrowser.Server.Implementations.ScheduledTasks; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - public class CleanDatabaseScheduledTask : IScheduledTask - { - private readonly ILibraryManager _libraryManager; - private readonly IItemRepository _itemRepo; - private readonly ILogger _logger; - private readonly IServerConfigurationManager _config; - private readonly IFileSystem _fileSystem; - private readonly IHttpServer _httpServer; - private readonly ILocalizationManager _localization; - private readonly ITaskManager _taskManager; - - public const int MigrationVersion = 23; - public static bool EnableUnavailableMessage = false; - - public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IHttpServer httpServer, ILocalizationManager localization, ITaskManager taskManager) - { - _libraryManager = libraryManager; - _itemRepo = itemRepo; - _logger = logger; - _config = config; - _fileSystem = fileSystem; - _httpServer = httpServer; - _localization = localization; - _taskManager = taskManager; - } - - public string Name - { - get { return "Clean Database"; } - } - - public string Description - { - get { return "Deletes obsolete content from the database."; } - } - - public string Category - { - get { return "Library"; } - } - - public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - OnProgress(0); - - // Ensure these objects are lazy loaded. - // Without this there is a deadlock that will need to be investigated - var rootChildren = _libraryManager.RootFolder.Children.ToList(); - rootChildren = _libraryManager.GetUserRootFolder().Children.ToList(); - - var innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(p => - { - double newPercentCommplete = .4 * p; - OnProgress(newPercentCommplete); - - progress.Report(newPercentCommplete); - }); - - await UpdateToLatestSchema(cancellationToken, innerProgress).ConfigureAwait(false); - - innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(p => - { - double newPercentCommplete = 40 + .05 * p; - OnProgress(newPercentCommplete); - progress.Report(newPercentCommplete); - }); - await CleanDeadItems(cancellationToken, innerProgress).ConfigureAwait(false); - progress.Report(45); - - innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(p => - { - double newPercentCommplete = 45 + .55 * p; - OnProgress(newPercentCommplete); - progress.Report(newPercentCommplete); - }); - await CleanDeletedItems(cancellationToken, innerProgress).ConfigureAwait(false); - progress.Report(100); - - await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false); - - if (_config.Configuration.MigrationVersion < MigrationVersion) - { - _config.Configuration.MigrationVersion = MigrationVersion; - _config.SaveConfiguration(); - } - - if (_config.Configuration.SchemaVersion < SqliteItemRepository.LatestSchemaVersion) - { - _config.Configuration.SchemaVersion = SqliteItemRepository.LatestSchemaVersion; - _config.SaveConfiguration(); - } - - if (EnableUnavailableMessage) - { - EnableUnavailableMessage = false; - _httpServer.GlobalResponse = null; - _taskManager.QueueScheduledTask<RefreshMediaLibraryTask>(); - } - - _taskManager.SuspendTriggers = false; - } - - private void OnProgress(double newPercentCommplete) - { - if (EnableUnavailableMessage) - { - var html = "<!doctype html><html><head><title>Emby</title></head><body>"; - var text = _localization.GetLocalizedString("DbUpgradeMessage"); - html += string.Format(text, newPercentCommplete.ToString("N2", CultureInfo.InvariantCulture)); - - html += "<script>setTimeout(function(){window.location.reload(true);}, 5000);</script>"; - html += "</body></html>"; - - _httpServer.GlobalResponse = html; - } - } - - private async Task UpdateToLatestSchema(CancellationToken cancellationToken, IProgress<double> progress) - { - var itemIds = _libraryManager.GetItemIds(new InternalItemsQuery - { - IsCurrentSchema = false, - ExcludeItemTypes = new[] { typeof(LiveTvProgram).Name } - }); - - var numComplete = 0; - var numItems = itemIds.Count; - - _logger.Debug("Upgrading schema for {0} items", numItems); - - var list = new List<BaseItem>(); - - foreach (var itemId in itemIds) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (itemId != Guid.Empty) - { - // Somehow some invalid data got into the db. It probably predates the boundary checking - var item = _libraryManager.GetItemById(itemId); - - if (item != null) - { - list.Add(item); - } - } - - if (list.Count >= 1000) - { - try - { - await _itemRepo.SaveItems(list, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error saving item", ex); - } - - list.Clear(); - } - - numComplete++; - double percent = numComplete; - percent /= numItems; - progress.Report(percent * 100); - } - - if (list.Count > 0) - { - try - { - await _itemRepo.SaveItems(list, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error saving item", ex); - } - } - - progress.Report(100); - } - - private async Task CleanDeadItems(CancellationToken cancellationToken, IProgress<double> progress) - { - var itemIds = _libraryManager.GetItemIds(new InternalItemsQuery - { - HasDeadParentId = true - }); - - var numComplete = 0; - var numItems = itemIds.Count; - - _logger.Debug("Cleaning {0} items with dead parent links", numItems); - - foreach (var itemId in itemIds) - { - cancellationToken.ThrowIfCancellationRequested(); - - var item = _libraryManager.GetItemById(itemId); - - if (item != null) - { - _logger.Info("Cleaning item {0} type: {1} path: {2}", item.Name, item.GetType().Name, item.Path ?? string.Empty); - - await item.Delete(new DeleteOptions - { - DeleteFileLocation = false - - }).ConfigureAwait(false); - } - - numComplete++; - double percent = numComplete; - percent /= numItems; - progress.Report(percent * 100); - } - - progress.Report(100); - } - - private async Task CleanDeletedItems(CancellationToken cancellationToken, IProgress<double> progress) - { - var result = _itemRepo.GetItemIdsWithPath(new InternalItemsQuery - { - LocationTypes = new[] { LocationType.FileSystem }, - //Limit = limit, - - // These have their own cleanup routines - ExcludeItemTypes = new[] - { - typeof(Person).Name, - typeof(Genre).Name, - typeof(MusicGenre).Name, - typeof(GameGenre).Name, - typeof(Studio).Name, - typeof(Year).Name, - typeof(Channel).Name, - typeof(AggregateFolder).Name, - typeof(CollectionFolder).Name - } - }); - - var numComplete = 0; - var numItems = result.Items.Length; - - foreach (var item in result.Items) - { - cancellationToken.ThrowIfCancellationRequested(); - - var path = item.Item2; - - try - { - if (_fileSystem.FileExists(path) || _fileSystem.DirectoryExists(path)) - { - continue; - } - - var libraryItem = _libraryManager.GetItemById(item.Item1); - - if (libraryItem.IsTopParent) - { - continue; - } - - var hasDualAccess = libraryItem as IHasDualAccess; - if (hasDualAccess != null && hasDualAccess.IsAccessedByName) - { - continue; - } - - var libraryItemPath = libraryItem.Path; - if (!string.Equals(libraryItemPath, path, StringComparison.OrdinalIgnoreCase)) - { - _logger.Error("CleanDeletedItems aborting delete for item {0}-{1} because paths don't match. {2}---{3}", libraryItem.Id, libraryItem.Name, libraryItem.Path ?? string.Empty, path ?? string.Empty); - continue; - } - - if (Folder.IsPathOffline(path)) - { - await libraryItem.UpdateIsOffline(true).ConfigureAwait(false); - continue; - } - - _logger.Info("Deleting item from database {0} because path no longer exists. type: {1} path: {2}", libraryItem.Name, libraryItem.GetType().Name, libraryItemPath ?? string.Empty); - - await libraryItem.OnFileDeleted().ConfigureAwait(false); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error in CleanDeletedItems. File {0}", ex, path); - } - - numComplete++; - double percent = numComplete; - percent /= numItems; - progress.Report(percent * 100); - } - } - - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - return new ITaskTrigger[] - { - new IntervalTrigger{ Interval = TimeSpan.FromHours(24)} - }; - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs deleted file mode 100644 index 028465354c..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs +++ /dev/null @@ -1,181 +0,0 @@ -using System.Text; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.Data; -using System.IO; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - static class DataExtensions - { - /// <summary> - /// Determines whether the specified conn is open. - /// </summary> - /// <param name="conn">The conn.</param> - /// <returns><c>true</c> if the specified conn is open; otherwise, <c>false</c>.</returns> - public static bool IsOpen(this IDbConnection conn) - { - return conn.State == ConnectionState.Open; - } - - public static IDataParameter GetParameter(this IDbCommand cmd, int index) - { - return (IDataParameter)cmd.Parameters[index]; - } - - public static IDataParameter Add(this IDataParameterCollection paramCollection, IDbCommand cmd, string name, DbType type) - { - var param = cmd.CreateParameter(); - - param.ParameterName = name; - param.DbType = type; - - paramCollection.Add(param); - - return param; - } - - public static IDataParameter Add(this IDataParameterCollection paramCollection, IDbCommand cmd, string name) - { - var param = cmd.CreateParameter(); - - param.ParameterName = name; - - paramCollection.Add(param); - - return param; - } - - - /// <summary> - /// Gets a stream from a DataReader at a given ordinal - /// </summary> - /// <returns>Stream.</returns> - /// <exception cref="System.ArgumentNullException">reader</exception> - public static Stream GetMemoryStream(this IDataReader reader, int ordinal, IMemoryStreamProvider streamProvider) - { - if (reader == null) - { - throw new ArgumentNullException("reader"); - } - - var memoryStream = streamProvider.CreateNew(); - var num = 0L; - var array = new byte[4096]; - long bytes; - do - { - bytes = reader.GetBytes(ordinal, num, array, 0, array.Length); - memoryStream.Write(array, 0, (int)bytes); - num += bytes; - } - while (bytes > 0L); - memoryStream.Position = 0; - return memoryStream; - } - - /// <summary> - /// Runs the queries. - /// </summary> - /// <param name="connection">The connection.</param> - /// <param name="queries">The queries.</param> - /// <param name="logger">The logger.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - /// <exception cref="System.ArgumentNullException">queries</exception> - public static void RunQueries(this IDbConnection connection, string[] queries, ILogger logger) - { - if (queries == null) - { - throw new ArgumentNullException("queries"); - } - - using (var tran = connection.BeginTransaction()) - { - try - { - using (var cmd = connection.CreateCommand()) - { - foreach (var query in queries) - { - cmd.Transaction = tran; - cmd.CommandText = query; - cmd.ExecuteNonQuery(); - } - } - - tran.Commit(); - } - catch (Exception e) - { - logger.ErrorException("Error running queries", e); - tran.Rollback(); - throw; - } - } - } - - public static void Attach(IDbConnection db, string path, string alias) - { - using (var cmd = db.CreateCommand()) - { - cmd.CommandText = string.Format("attach @dbPath as {0};", alias); - cmd.Parameters.Add(cmd, "@dbPath", DbType.String); - cmd.GetParameter(0).Value = path; - - cmd.ExecuteNonQuery(); - } - } - - /// <summary> - /// Serializes to bytes. - /// </summary> - /// <returns>System.Byte[][].</returns> - /// <exception cref="System.ArgumentNullException">obj</exception> - public static byte[] SerializeToBytes(this IJsonSerializer json, object obj, IMemoryStreamProvider streamProvider) - { - if (obj == null) - { - throw new ArgumentNullException("obj"); - } - - using (var stream = streamProvider.CreateNew()) - { - json.SerializeToStream(obj, stream); - return stream.ToArray(); - } - } - - public static void AddColumn(this IDbConnection connection, ILogger logger, string table, string columnName, string type) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(" + table + ")"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, columnName, StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table " + table); - builder.AppendLine("add column " + columnName + " " + type); - - connection.RunQueries(new[] { builder.ToString() }, logger); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs deleted file mode 100644 index 596cf8407a..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Data; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - public interface IDbConnector - { - Task<IDbConnection> Connect(string dbPath, bool isReadOnly, bool enablePooling = false, int? cacheSize = null); - } -} diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs deleted file mode 100644 index 1d9be2e0d6..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs +++ /dev/null @@ -1,408 +0,0 @@ -using System; -using System.Data; -using System.Text; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - public class MediaStreamColumns - { - private readonly IDbConnection _connection; - private readonly ILogger _logger; - - public MediaStreamColumns(IDbConnection connection, ILogger logger) - { - _connection = connection; - _logger = logger; - } - - public void AddColumns() - { - AddPixelFormatColumnCommand(); - AddBitDepthCommand(); - AddIsAnamorphicColumn(); - AddKeyFramesColumn(); - AddRefFramesCommand(); - AddCodecTagColumn(); - AddCommentColumn(); - AddNalColumn(); - AddIsAvcColumn(); - AddTitleColumn(); - AddTimeBaseColumn(); - AddCodecTimeBaseColumn(); - } - - private void AddIsAvcColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "IsAvc", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column IsAvc BIT NULL"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - private void AddTimeBaseColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "TimeBase", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column TimeBase TEXT"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - private void AddCodecTimeBaseColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "CodecTimeBase", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column CodecTimeBase TEXT"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - private void AddTitleColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "Title", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column Title TEXT"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - private void AddNalColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "NalLengthSize", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column NalLengthSize TEXT"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - private void AddCommentColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "Comment", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column Comment TEXT"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - private void AddCodecTagColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "CodecTag", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column CodecTag TEXT"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - private void AddPixelFormatColumnCommand() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "PixelFormat", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column PixelFormat TEXT"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - private void AddBitDepthCommand() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "BitDepth", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column BitDepth INT NULL"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - private void AddRefFramesCommand() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "RefFrames", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column RefFrames INT NULL"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - private void AddKeyFramesColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "KeyFrames", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column KeyFrames TEXT NULL"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - private void AddIsAnamorphicColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "IsAnamorphic", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column IsAnamorphic BIT NULL"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - - } -} diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs deleted file mode 100644 index 1726a77a6b..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs +++ /dev/null @@ -1,312 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Data; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - /// <summary> - /// Class SQLiteDisplayPreferencesRepository - /// </summary> - public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository - { - private readonly IMemoryStreamProvider _memoryStreamProvider; - - public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IDbConnector dbConnector, IMemoryStreamProvider memoryStreamProvider) - : base(logManager, dbConnector) - { - _jsonSerializer = jsonSerializer; - _memoryStreamProvider = memoryStreamProvider; - DbFilePath = Path.Combine(appPaths.DataPath, "displaypreferences.db"); - } - - /// <summary> - /// Gets the name of the repository - /// </summary> - /// <value>The name.</value> - public string Name - { - get - { - return "SQLite"; - } - } - - /// <summary> - /// The _json serializer - /// </summary> - private readonly IJsonSerializer _jsonSerializer; - - /// <summary> - /// Opens the connection to the database - /// </summary> - /// <returns>Task.</returns> - public async Task Initialize() - { - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - string[] queries = { - - "create table if not exists userdisplaypreferences (id GUID, userId GUID, client text, data BLOB)", - "create unique index if not exists userdisplaypreferencesindex on userdisplaypreferences (id, userId, client)" - }; - - connection.RunQueries(queries, Logger); - } - } - - /// <summary> - /// Save the display preferences associated with an item in the repo - /// </summary> - /// <param name="displayPreferences">The display preferences.</param> - /// <param name="userId">The user id.</param> - /// <param name="client">The client.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">item</exception> - public async Task SaveDisplayPreferences(DisplayPreferences displayPreferences, Guid userId, string client, CancellationToken cancellationToken) - { - if (displayPreferences == null) - { - throw new ArgumentNullException("displayPreferences"); - } - if (string.IsNullOrWhiteSpace(displayPreferences.Id)) - { - throw new ArgumentNullException("displayPreferences.Id"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - var serialized = _jsonSerializer.SerializeToBytes(displayPreferences, _memoryStreamProvider); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "replace into userdisplaypreferences (id, userid, client, data) values (@1, @2, @3, @4)"; - - cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = new Guid(displayPreferences.Id); - cmd.Parameters.Add(cmd, "@2", DbType.Guid).Value = userId; - cmd.Parameters.Add(cmd, "@3", DbType.String).Value = client; - cmd.Parameters.Add(cmd, "@4", DbType.Binary).Value = serialized; - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save display preferences:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - - /// <summary> - /// Save all display preferences associated with a user in the repo - /// </summary> - /// <param name="displayPreferences">The display preferences.</param> - /// <param name="userId">The user id.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">item</exception> - public async Task SaveAllDisplayPreferences(IEnumerable<DisplayPreferences> displayPreferences, Guid userId, CancellationToken cancellationToken) - { - if (displayPreferences == null) - { - throw new ArgumentNullException("displayPreferences"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - foreach (var displayPreference in displayPreferences) - { - - var serialized = _jsonSerializer.SerializeToBytes(displayPreference, _memoryStreamProvider); - - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "replace into userdisplaypreferences (id, userid, client, data) values (@1, @2, @3, @4)"; - - cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = new Guid(displayPreference.Id); - cmd.Parameters.Add(cmd, "@2", DbType.Guid).Value = userId; - cmd.Parameters.Add(cmd, "@3", DbType.String).Value = displayPreference.Client; - cmd.Parameters.Add(cmd, "@4", DbType.Binary).Value = serialized; - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); - } - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save display preferences:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - - /// <summary> - /// Gets the display preferences. - /// </summary> - /// <param name="displayPreferencesId">The display preferences id.</param> - /// <param name="userId">The user id.</param> - /// <param name="client">The client.</param> - /// <returns>Task{DisplayPreferences}.</returns> - /// <exception cref="System.ArgumentNullException">item</exception> - public DisplayPreferences GetDisplayPreferences(string displayPreferencesId, Guid userId, string client) - { - if (string.IsNullOrWhiteSpace(displayPreferencesId)) - { - throw new ArgumentNullException("displayPreferencesId"); - } - - var guidId = displayPreferencesId.GetMD5(); - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select data from userdisplaypreferences where id = @id and userId=@userId and client=@client"; - - cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = guidId; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - cmd.Parameters.Add(cmd, "@client", DbType.String).Value = client; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) - { - using (var stream = reader.GetMemoryStream(0, _memoryStreamProvider)) - { - return _jsonSerializer.DeserializeFromStream<DisplayPreferences>(stream); - } - } - } - - return new DisplayPreferences - { - Id = guidId.ToString("N") - }; - } - } - } - - /// <summary> - /// Gets all display preferences for the given user. - /// </summary> - /// <param name="userId">The user id.</param> - /// <returns>Task{DisplayPreferences}.</returns> - /// <exception cref="System.ArgumentNullException">item</exception> - public IEnumerable<DisplayPreferences> GetAllDisplayPreferences(Guid userId) - { - var list = new List<DisplayPreferences>(); - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select data from userdisplaypreferences where userId=@userId"; - - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - using (var stream = reader.GetMemoryStream(0, _memoryStreamProvider)) - { - list.Add(_jsonSerializer.DeserializeFromStream<DisplayPreferences>(stream)); - } - } - } - } - } - - return list; - } - - public Task SaveDisplayPreferences(DisplayPreferences displayPreferences, string userId, string client, CancellationToken cancellationToken) - { - return SaveDisplayPreferences(displayPreferences, new Guid(userId), client, cancellationToken); - } - - public DisplayPreferences GetDisplayPreferences(string displayPreferencesId, string userId, string client) - { - return GetDisplayPreferences(displayPreferencesId, new Guid(userId), client); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs deleted file mode 100644 index c273d49458..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Data; -using System.Data.SQLite; -using System.Threading.Tasks; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - /// <summary> - /// Class SQLiteExtensions - /// </summary> - public static class SqliteExtensions - { - /// <summary> - /// Connects to db. - /// </summary> - public static async Task<IDbConnection> ConnectToDb(string dbPath, bool isReadOnly, bool enablePooling, int? cacheSize, ILogger logger) - { - if (string.IsNullOrEmpty(dbPath)) - { - throw new ArgumentNullException("dbPath"); - } - - SQLiteConnection.SetMemoryStatus(false); - - var connectionstr = new SQLiteConnectionStringBuilder - { - PageSize = 4096, - CacheSize = cacheSize ?? 2000, - SyncMode = SynchronizationModes.Normal, - DataSource = dbPath, - JournalMode = SQLiteJournalModeEnum.Wal, - - // This is causing crashing under linux - Pooling = enablePooling && Environment.OSVersion.Platform == PlatformID.Win32NT, - ReadOnly = isReadOnly - }; - - var connectionString = connectionstr.ConnectionString; - - if (!enablePooling) - { - logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, connectionString); - } - - var connection = new SQLiteConnection(connectionString); - - await connection.OpenAsync().ConfigureAwait(false); - - return connection; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs deleted file mode 100644 index 7a5e000905..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs +++ /dev/null @@ -1,408 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.FileOrganization; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using System; -using System.Collections.Generic; -using System.Data; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - public class SqliteFileOrganizationRepository : BaseSqliteRepository, IFileOrganizationRepository, IDisposable - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - public SqliteFileOrganizationRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector connector) : base(logManager, connector) - { - DbFilePath = Path.Combine(appPaths.DataPath, "fileorganization.db"); - } - - /// <summary> - /// Opens the connection to the database - /// </summary> - /// <returns>Task.</returns> - public async Task Initialize() - { - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - string[] queries = { - - "create table if not exists FileOrganizerResults (ResultId GUID PRIMARY KEY, OriginalPath TEXT, TargetPath TEXT, FileLength INT, OrganizationDate datetime, Status TEXT, OrganizationType TEXT, StatusMessage TEXT, ExtractedName TEXT, ExtractedYear int null, ExtractedSeasonNumber int null, ExtractedEpisodeNumber int null, ExtractedEndingEpisodeNumber, DuplicatePaths TEXT int null)", - "create index if not exists idx_FileOrganizerResults on FileOrganizerResults(ResultId)" - }; - - connection.RunQueries(queries, Logger); - } - } - - public async Task SaveResult(FileOrganizationResult result, CancellationToken cancellationToken) - { - if (result == null) - { - throw new ArgumentNullException("result"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var saveResultCommand = connection.CreateCommand()) - { - saveResultCommand.CommandText = "replace into FileOrganizerResults (ResultId, OriginalPath, TargetPath, FileLength, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths) values (@ResultId, @OriginalPath, @TargetPath, @FileLength, @OrganizationDate, @Status, @OrganizationType, @StatusMessage, @ExtractedName, @ExtractedYear, @ExtractedSeasonNumber, @ExtractedEpisodeNumber, @ExtractedEndingEpisodeNumber, @DuplicatePaths)"; - - saveResultCommand.Parameters.Add(saveResultCommand, "@ResultId"); - saveResultCommand.Parameters.Add(saveResultCommand, "@OriginalPath"); - saveResultCommand.Parameters.Add(saveResultCommand, "@TargetPath"); - saveResultCommand.Parameters.Add(saveResultCommand, "@FileLength"); - saveResultCommand.Parameters.Add(saveResultCommand, "@OrganizationDate"); - saveResultCommand.Parameters.Add(saveResultCommand, "@Status"); - saveResultCommand.Parameters.Add(saveResultCommand, "@OrganizationType"); - saveResultCommand.Parameters.Add(saveResultCommand, "@StatusMessage"); - saveResultCommand.Parameters.Add(saveResultCommand, "@ExtractedName"); - saveResultCommand.Parameters.Add(saveResultCommand, "@ExtractedYear"); - saveResultCommand.Parameters.Add(saveResultCommand, "@ExtractedSeasonNumber"); - saveResultCommand.Parameters.Add(saveResultCommand, "@ExtractedEpisodeNumber"); - saveResultCommand.Parameters.Add(saveResultCommand, "@ExtractedEndingEpisodeNumber"); - saveResultCommand.Parameters.Add(saveResultCommand, "@DuplicatePaths"); - - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - var index = 0; - - saveResultCommand.GetParameter(index++).Value = new Guid(result.Id); - saveResultCommand.GetParameter(index++).Value = result.OriginalPath; - saveResultCommand.GetParameter(index++).Value = result.TargetPath; - saveResultCommand.GetParameter(index++).Value = result.FileSize; - saveResultCommand.GetParameter(index++).Value = result.Date; - saveResultCommand.GetParameter(index++).Value = result.Status.ToString(); - saveResultCommand.GetParameter(index++).Value = result.Type.ToString(); - saveResultCommand.GetParameter(index++).Value = result.StatusMessage; - saveResultCommand.GetParameter(index++).Value = result.ExtractedName; - saveResultCommand.GetParameter(index++).Value = result.ExtractedYear; - saveResultCommand.GetParameter(index++).Value = result.ExtractedSeasonNumber; - saveResultCommand.GetParameter(index++).Value = result.ExtractedEpisodeNumber; - saveResultCommand.GetParameter(index++).Value = result.ExtractedEndingEpisodeNumber; - saveResultCommand.GetParameter(index).Value = string.Join("|", result.DuplicatePaths.ToArray()); - - saveResultCommand.Transaction = transaction; - - saveResultCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save FileOrganizationResult:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - - public async Task Delete(string id) - { - if (string.IsNullOrEmpty(id)) - { - throw new ArgumentNullException("id"); - } - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var deleteResultCommand = connection.CreateCommand()) - { - deleteResultCommand.CommandText = "delete from FileOrganizerResults where ResultId = @ResultId"; - - deleteResultCommand.Parameters.Add(deleteResultCommand, "@ResultId"); - - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - deleteResultCommand.GetParameter(0).Value = new Guid(id); - - deleteResultCommand.Transaction = transaction; - - deleteResultCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to delete FileOrganizationResult:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - - public async Task DeleteAll() - { - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "delete from FileOrganizerResults"; - - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to delete results", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - - public QueryResult<FileOrganizationResult> GetResults(FileOrganizationResultQuery query) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "SELECT ResultId, OriginalPath, TargetPath, FileLength, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths from FileOrganizerResults"; - - if (query.StartIndex.HasValue && query.StartIndex.Value > 0) - { - cmd.CommandText += string.Format(" WHERE ResultId NOT IN (SELECT ResultId FROM FileOrganizerResults ORDER BY OrganizationDate desc LIMIT {0})", - query.StartIndex.Value.ToString(_usCulture)); - } - - cmd.CommandText += " ORDER BY OrganizationDate desc"; - - if (query.Limit.HasValue) - { - cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); - } - - cmd.CommandText += "; select count (ResultId) from FileOrganizerResults"; - - var list = new List<FileOrganizationResult>(); - var count = 0; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (reader.Read()) - { - list.Add(GetResult(reader)); - } - - if (reader.NextResult() && reader.Read()) - { - count = reader.GetInt32(0); - } - } - - return new QueryResult<FileOrganizationResult>() - { - Items = list.ToArray(), - TotalRecordCount = count - }; - } - } - } - - public FileOrganizationResult GetResult(string id) - { - if (string.IsNullOrEmpty(id)) - { - throw new ArgumentNullException("id"); - } - - using (var connection = CreateConnection(true).Result) - { - var guid = new Guid(id); - - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select ResultId, OriginalPath, TargetPath, FileLength, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths from FileOrganizerResults where ResultId=@Id"; - - cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) - { - return GetResult(reader); - } - } - } - - return null; - } - } - - public FileOrganizationResult GetResult(IDataReader reader) - { - var index = 0; - - var result = new FileOrganizationResult - { - Id = reader.GetGuid(0).ToString("N") - }; - - index++; - if (!reader.IsDBNull(index)) - { - result.OriginalPath = reader.GetString(index); - } - - index++; - if (!reader.IsDBNull(index)) - { - result.TargetPath = reader.GetString(index); - } - - index++; - result.FileSize = reader.GetInt64(index); - - index++; - result.Date = reader.GetDateTime(index).ToUniversalTime(); - - index++; - result.Status = (FileSortingStatus)Enum.Parse(typeof(FileSortingStatus), reader.GetString(index), true); - - index++; - result.Type = (FileOrganizerType)Enum.Parse(typeof(FileOrganizerType), reader.GetString(index), true); - - index++; - if (!reader.IsDBNull(index)) - { - result.StatusMessage = reader.GetString(index); - } - - result.OriginalFileName = Path.GetFileName(result.OriginalPath); - - index++; - if (!reader.IsDBNull(index)) - { - result.ExtractedName = reader.GetString(index); - } - - index++; - if (!reader.IsDBNull(index)) - { - result.ExtractedYear = reader.GetInt32(index); - } - - index++; - if (!reader.IsDBNull(index)) - { - result.ExtractedSeasonNumber = reader.GetInt32(index); - } - - index++; - if (!reader.IsDBNull(index)) - { - result.ExtractedEpisodeNumber = reader.GetInt32(index); - } - - index++; - if (!reader.IsDBNull(index)) - { - result.ExtractedEndingEpisodeNumber = reader.GetInt32(index); - } - - index++; - if (!reader.IsDBNull(index)) - { - result.DuplicatePaths = reader.GetString(index).Split('|').Where(i => !string.IsNullOrEmpty(i)).ToList(); - } - - return result; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs deleted file mode 100644 index f33b18389a..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ /dev/null @@ -1,5382 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Data; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Runtime.Serialization; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Collections; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Playlists; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Server.Implementations.Devices; -using MediaBrowser.Server.Implementations.Playlists; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - /// <summary> - /// Class SQLiteItemRepository - /// </summary> - public class SqliteItemRepository : BaseSqliteRepository, IItemRepository - { - private IDbConnection _connection; - - private readonly TypeMapper _typeMapper = new TypeMapper(); - - /// <summary> - /// Gets the name of the repository - /// </summary> - /// <value>The name.</value> - public string Name - { - get - { - return "SQLite"; - } - } - - /// <summary> - /// Gets the json serializer. - /// </summary> - /// <value>The json serializer.</value> - private readonly IJsonSerializer _jsonSerializer; - - /// <summary> - /// The _app paths - /// </summary> - private readonly IServerConfigurationManager _config; - - /// <summary> - /// The _save item command - /// </summary> - private IDbCommand _saveItemCommand; - - private readonly string _criticReviewsPath; - - private IDbCommand _deleteItemCommand; - - private IDbCommand _deletePeopleCommand; - private IDbCommand _savePersonCommand; - - private IDbCommand _deleteChaptersCommand; - private IDbCommand _saveChapterCommand; - - private IDbCommand _deleteStreamsCommand; - private IDbCommand _saveStreamCommand; - - private IDbCommand _deleteAncestorsCommand; - private IDbCommand _saveAncestorCommand; - - private IDbCommand _deleteUserDataKeysCommand; - private IDbCommand _saveUserDataKeysCommand; - - private IDbCommand _deleteItemValuesCommand; - private IDbCommand _saveItemValuesCommand; - - private IDbCommand _deleteProviderIdsCommand; - private IDbCommand _saveProviderIdsCommand; - - private IDbCommand _deleteImagesCommand; - private IDbCommand _saveImagesCommand; - - private IDbCommand _updateInheritedTagsCommand; - - public const int LatestSchemaVersion = 109; - private readonly IMemoryStreamProvider _memoryStreamProvider; - - /// <summary> - /// Initializes a new instance of the <see cref="SqliteItemRepository"/> class. - /// </summary> - public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager, IDbConnector connector, IMemoryStreamProvider memoryStreamProvider) - : base(logManager, connector) - { - if (config == null) - { - throw new ArgumentNullException("config"); - } - if (jsonSerializer == null) - { - throw new ArgumentNullException("jsonSerializer"); - } - - _config = config; - _jsonSerializer = jsonSerializer; - _memoryStreamProvider = memoryStreamProvider; - - _criticReviewsPath = Path.Combine(_config.ApplicationPaths.DataPath, "critic-reviews"); - DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); - } - - private const string ChaptersTableName = "Chapters2"; - - protected override async Task<IDbConnection> CreateConnection(bool isReadOnly = false) - { - var cacheSize = _config.Configuration.SqliteCacheSize; - if (cacheSize <= 0) - { - cacheSize = Math.Min(Environment.ProcessorCount * 50000, 100000); - } - - var connection = await DbConnector.Connect(DbFilePath, false, false, 0 - cacheSize).ConfigureAwait(false); - - connection.RunQueries(new[] - { - "pragma temp_store = memory", - "pragma default_temp_store = memory", - "PRAGMA locking_mode=EXCLUSIVE" - - }, Logger); - - return connection; - } - - /// <summary> - /// Opens the connection to the database - /// </summary> - /// <returns>Task.</returns> - public async Task Initialize(SqliteUserDataRepository userDataRepo) - { - _connection = await CreateConnection(false).ConfigureAwait(false); - - var createMediaStreamsTableCommand - = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, Title TEXT NULL, TimeBase TEXT NULL, CodecTimeBase TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; - - string[] queries = { - - "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID, Path TEXT)", - - "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))", - "create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)", - "create index if not exists idx_AncestorIds2 on AncestorIds(AncestorIdText)", - - "create table if not exists UserDataKeys (ItemId GUID, UserDataKey TEXT Priority INT, PRIMARY KEY (ItemId, UserDataKey))", - - "create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT, CleanValue TEXT)", - - "create table if not exists ProviderIds (ItemId GUID, Name TEXT, Value TEXT, PRIMARY KEY (ItemId, Name))", - // covering index - "create index if not exists Idx_ProviderIds1 on ProviderIds(ItemId,Name,Value)", - - "create table if not exists Images (ItemId GUID NOT NULL, Path TEXT NOT NULL, ImageType INT NOT NULL, DateModified DATETIME, IsPlaceHolder BIT NOT NULL, SortOrder INT)", - "create index if not exists idx_Images on Images(ItemId)", - - "create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)", - - "drop index if exists idxPeopleItemId", - "create index if not exists idxPeopleItemId1 on People(ItemId,ListOrder)", - "create index if not exists idxPeopleName on People(Name)", - - "create table if not exists "+ChaptersTableName+" (ItemId GUID, ChapterIndex INT, StartPositionTicks BIGINT, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))", - - createMediaStreamsTableCommand, - - "create index if not exists idx_mediastreams1 on mediastreams(ItemId)", - - }; - - _connection.RunQueries(queries, Logger); - - _connection.AddColumn(Logger, "AncestorIds", "AncestorIdText", "Text"); - - _connection.AddColumn(Logger, "TypedBaseItems", "Path", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "StartDate", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "EndDate", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "ChannelId", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsMovie", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsSports", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsKids", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "CommunityRating", "Float"); - _connection.AddColumn(Logger, "TypedBaseItems", "CustomRating", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IndexNumber", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsLocked", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "Name", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "OfficialRating", "Text"); - - _connection.AddColumn(Logger, "TypedBaseItems", "MediaType", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "Overview", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ParentIndexNumber", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "PremiereDate", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "ProductionYear", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "ParentId", "GUID"); - _connection.AddColumn(Logger, "TypedBaseItems", "Genres", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "SchemaVersion", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "SortName", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "RunTimeTicks", "BIGINT"); - - _connection.AddColumn(Logger, "TypedBaseItems", "OfficialRatingDescription", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "HomePageUrl", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "VoteCount", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "DisplayMediaType", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "DateCreated", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "DateModified", "DATETIME"); - - _connection.AddColumn(Logger, "TypedBaseItems", "ForcedSortName", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsOffline", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "LocationType", "Text"); - - _connection.AddColumn(Logger, "TypedBaseItems", "IsSeries", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsLive", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsNews", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsPremiere", "BIT"); - - _connection.AddColumn(Logger, "TypedBaseItems", "EpisodeTitle", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsRepeat", "BIT"); - - _connection.AddColumn(Logger, "TypedBaseItems", "PreferredMetadataLanguage", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "PreferredMetadataCountryCode", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsHD", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "ExternalEtag", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "DateLastRefreshed", "DATETIME"); - - _connection.AddColumn(Logger, "TypedBaseItems", "DateLastSaved", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsInMixedFolder", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "LockedFields", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "Studios", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "Audio", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ExternalServiceId", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "Tags", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsFolder", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "InheritedParentalRatingValue", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "UnratedType", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "TopParentId", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsItemByName", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "SourceType", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "TrailerTypes", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "CriticRating", "Float"); - _connection.AddColumn(Logger, "TypedBaseItems", "CriticRatingSummary", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "CleanName", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "PresentationUniqueKey", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "SlugName", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "OriginalTitle", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "PrimaryVersionId", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "DateLastMediaAdded", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "Album", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsVirtualItem", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "SeriesName", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "UserDataKey", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "SeasonName", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "SeasonId", "GUID"); - _connection.AddColumn(Logger, "TypedBaseItems", "SeriesId", "GUID"); - _connection.AddColumn(Logger, "TypedBaseItems", "SeriesSortName", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ExternalSeriesId", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ShortOverview", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "Tagline", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "Keywords", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ProviderIds", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "Images", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ProductionLocations", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ThemeSongIds", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ThemeVideoIds", "Text"); - - _connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT"); - _connection.AddColumn(Logger, "ItemValues", "CleanValue", "Text"); - - _connection.AddColumn(Logger, ChaptersTableName, "ImageDateModified", "DATETIME"); - - string[] postQueries = - - { - // obsolete - "drop index if exists idx_TypedBaseItems", - "drop index if exists idx_mediastreams", - "drop index if exists idx_"+ChaptersTableName, - "drop index if exists idx_UserDataKeys1", - "drop index if exists idx_UserDataKeys2", - "drop index if exists idx_TypeTopParentId3", - "drop index if exists idx_TypeTopParentId2", - "drop index if exists idx_TypeTopParentId4", - "drop index if exists idx_Type", - "drop index if exists idx_TypeTopParentId", - "drop index if exists idx_GuidType", - "drop index if exists idx_TopParentId", - "drop index if exists idx_TypeTopParentId6", - "drop index if exists idx_ItemValues2", - "drop index if exists Idx_ProviderIds", - "drop index if exists idx_ItemValues3", - "drop index if exists idx_ItemValues4", - "drop index if exists idx_ItemValues5", - - "create index if not exists idx_PathTypedBaseItems on TypedBaseItems(Path)", - "create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)", - - "create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)", - "create index if not exists idx_GuidTypeIsFolderIsVirtualItem on TypedBaseItems(Guid,Type,IsFolder,IsVirtualItem)", - //"create index if not exists idx_GuidMediaTypeIsFolderIsVirtualItem on TypedBaseItems(Guid,MediaType,IsFolder,IsVirtualItem)", - "create index if not exists idx_CleanNameType on TypedBaseItems(CleanName,Type)", - - // covering index - "create index if not exists idx_TopParentIdGuid on TypedBaseItems(TopParentId,Guid)", - - // live tv programs - "create index if not exists idx_TypeTopParentIdStartDate on TypedBaseItems(Type,TopParentId,StartDate)", - - // covering index for getitemvalues - "create index if not exists idx_TypeTopParentIdGuid on TypedBaseItems(Type,TopParentId,Guid)", - - // used by movie suggestions - "create index if not exists idx_TypeTopParentIdGroup on TypedBaseItems(Type,TopParentId,PresentationUniqueKey)", - "create index if not exists idx_TypeTopParentId5 on TypedBaseItems(TopParentId,IsVirtualItem)", - - // latest items - "create index if not exists idx_TypeTopParentId9 on TypedBaseItems(TopParentId,Type,IsVirtualItem,PresentationUniqueKey,DateCreated)", - "create index if not exists idx_TypeTopParentId8 on TypedBaseItems(TopParentId,IsFolder,IsVirtualItem,PresentationUniqueKey,DateCreated)", - - // resume - "create index if not exists idx_TypeTopParentId7 on TypedBaseItems(TopParentId,MediaType,IsVirtualItem,PresentationUniqueKey)", - - // items by name - "create index if not exists idx_ItemValues6 on ItemValues(ItemId,Type,CleanValue)", - "create index if not exists idx_ItemValues7 on ItemValues(Type,CleanValue,ItemId)", - - // covering index - "create index if not exists idx_UserDataKeys3 on UserDataKeys(ItemId,Priority,UserDataKey)" - }; - - _connection.RunQueries(postQueries, Logger); - - PrepareStatements(); - - new MediaStreamColumns(_connection, Logger).AddColumns(); - - DataExtensions.Attach(_connection, Path.Combine(_config.ApplicationPaths.DataPath, "userdata_v2.db"), "UserDataDb"); - await userDataRepo.Initialize(_connection, WriteLock).ConfigureAwait(false); - //await Vacuum(_connection).ConfigureAwait(false); - } - - private readonly string[] _retriveItemColumns = - { - "type", - "data", - "StartDate", - "EndDate", - "IsOffline", - "ChannelId", - "IsMovie", - "IsSports", - "IsKids", - "IsSeries", - "IsLive", - "IsNews", - "IsPremiere", - "EpisodeTitle", - "IsRepeat", - "CommunityRating", - "CustomRating", - "IndexNumber", - "IsLocked", - "PreferredMetadataLanguage", - "PreferredMetadataCountryCode", - "IsHD", - "ExternalEtag", - "DateLastRefreshed", - "Name", - "Path", - "PremiereDate", - "Overview", - "ParentIndexNumber", - "ProductionYear", - "OfficialRating", - "OfficialRatingDescription", - "HomePageUrl", - "DisplayMediaType", - "ForcedSortName", - "RunTimeTicks", - "VoteCount", - "DateCreated", - "DateModified", - "guid", - "Genres", - "ParentId", - "Audio", - "ExternalServiceId", - "IsInMixedFolder", - "DateLastSaved", - "LockedFields", - "Studios", - "Tags", - "SourceType", - "TrailerTypes", - "OriginalTitle", - "PrimaryVersionId", - "DateLastMediaAdded", - "Album", - "CriticRating", - "CriticRatingSummary", - "IsVirtualItem", - "SeriesName", - "SeasonName", - "SeasonId", - "SeriesId", - "SeriesSortName", - "PresentationUniqueKey", - "InheritedParentalRatingValue", - "InheritedTags", - "ExternalSeriesId", - "ShortOverview", - "Tagline", - "Keywords", - "ProviderIds", - "Images", - "ProductionLocations", - "ThemeSongIds", - "ThemeVideoIds" - }; - - private readonly string[] _mediaStreamSaveColumns = - { - "ItemId", - "StreamIndex", - "StreamType", - "Codec", - "Language", - "ChannelLayout", - "Profile", - "AspectRatio", - "Path", - "IsInterlaced", - "BitRate", - "Channels", - "SampleRate", - "IsDefault", - "IsForced", - "IsExternal", - "Height", - "Width", - "AverageFrameRate", - "RealFrameRate", - "Level", - "PixelFormat", - "BitDepth", - "IsAnamorphic", - "RefFrames", - "CodecTag", - "Comment", - "NalLengthSize", - "IsAvc", - "Title", - "TimeBase", - "CodecTimeBase" - }; - - /// <summary> - /// Prepares the statements. - /// </summary> - private void PrepareStatements() - { - var saveColumns = new List<string> - { - "guid", - "type", - "data", - "Path", - "StartDate", - "EndDate", - "ChannelId", - "IsKids", - "IsMovie", - "IsSports", - "IsSeries", - "IsLive", - "IsNews", - "IsPremiere", - "EpisodeTitle", - "IsRepeat", - "CommunityRating", - "CustomRating", - "IndexNumber", - "IsLocked", - "Name", - "OfficialRating", - "MediaType", - "Overview", - "ParentIndexNumber", - "PremiereDate", - "ProductionYear", - "ParentId", - "Genres", - "InheritedParentalRatingValue", - "SchemaVersion", - "SortName", - "RunTimeTicks", - "OfficialRatingDescription", - "HomePageUrl", - "VoteCount", - "DisplayMediaType", - "DateCreated", - "DateModified", - "ForcedSortName", - "IsOffline", - "LocationType", - "PreferredMetadataLanguage", - "PreferredMetadataCountryCode", - "IsHD", - "ExternalEtag", - "DateLastRefreshed", - "DateLastSaved", - "IsInMixedFolder", - "LockedFields", - "Studios", - "Audio", - "ExternalServiceId", - "Tags", - "IsFolder", - "UnratedType", - "TopParentId", - "IsItemByName", - "SourceType", - "TrailerTypes", - "CriticRating", - "CriticRatingSummary", - "InheritedTags", - "CleanName", - "PresentationUniqueKey", - "SlugName", - "OriginalTitle", - "PrimaryVersionId", - "DateLastMediaAdded", - "Album", - "IsVirtualItem", - "SeriesName", - "UserDataKey", - "SeasonName", - "SeasonId", - "SeriesId", - "SeriesSortName", - "ExternalSeriesId", - "ShortOverview", - "Tagline", - "Keywords", - "ProviderIds", - "Images", - "ProductionLocations", - "ThemeSongIds", - "ThemeVideoIds" - }; - _saveItemCommand = _connection.CreateCommand(); - _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; - - for (var i = 1; i <= saveColumns.Count; i++) - { - if (i > 1) - { - _saveItemCommand.CommandText += ","; - } - _saveItemCommand.CommandText += "@" + i.ToString(CultureInfo.InvariantCulture); - - _saveItemCommand.Parameters.Add(_saveItemCommand, "@" + i.ToString(CultureInfo.InvariantCulture)); - } - _saveItemCommand.CommandText += ")"; - - _deleteItemCommand = _connection.CreateCommand(); - _deleteItemCommand.CommandText = "delete from TypedBaseItems where guid=@Id"; - _deleteItemCommand.Parameters.Add(_deleteItemCommand, "@Id"); - - // People - _deletePeopleCommand = _connection.CreateCommand(); - _deletePeopleCommand.CommandText = "delete from People where ItemId=@Id"; - _deletePeopleCommand.Parameters.Add(_deletePeopleCommand, "@Id"); - - _savePersonCommand = _connection.CreateCommand(); - _savePersonCommand.CommandText = "insert into People (ItemId, Name, Role, PersonType, SortOrder, ListOrder) values (@ItemId, @Name, @Role, @PersonType, @SortOrder, @ListOrder)"; - _savePersonCommand.Parameters.Add(_savePersonCommand, "@ItemId"); - _savePersonCommand.Parameters.Add(_savePersonCommand, "@Name"); - _savePersonCommand.Parameters.Add(_savePersonCommand, "@Role"); - _savePersonCommand.Parameters.Add(_savePersonCommand, "@PersonType"); - _savePersonCommand.Parameters.Add(_savePersonCommand, "@SortOrder"); - _savePersonCommand.Parameters.Add(_savePersonCommand, "@ListOrder"); - - // Ancestors - _deleteAncestorsCommand = _connection.CreateCommand(); - _deleteAncestorsCommand.CommandText = "delete from AncestorIds where ItemId=@Id"; - _deleteAncestorsCommand.Parameters.Add(_deleteAncestorsCommand, "@Id"); - - _saveAncestorCommand = _connection.CreateCommand(); - _saveAncestorCommand.CommandText = "insert into AncestorIds (ItemId, AncestorId, AncestorIdText) values (@ItemId, @AncestorId, @AncestorIdText)"; - _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@ItemId"); - _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorId"); - _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorIdText"); - - // Chapters - _deleteChaptersCommand = _connection.CreateCommand(); - _deleteChaptersCommand.CommandText = "delete from " + ChaptersTableName + " where ItemId=@ItemId"; - _deleteChaptersCommand.Parameters.Add(_deleteChaptersCommand, "@ItemId"); - - _saveChapterCommand = _connection.CreateCommand(); - _saveChapterCommand.CommandText = "replace into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath) values (@ItemId, @ChapterIndex, @StartPositionTicks, @Name, @ImagePath)"; - - _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@ItemId"); - _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@ChapterIndex"); - _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@StartPositionTicks"); - _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@Name"); - _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@ImagePath"); - _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@ImageDateModified"); - - // MediaStreams - _deleteStreamsCommand = _connection.CreateCommand(); - _deleteStreamsCommand.CommandText = "delete from mediastreams where ItemId=@ItemId"; - _deleteStreamsCommand.Parameters.Add(_deleteStreamsCommand, "@ItemId"); - - _saveStreamCommand = _connection.CreateCommand(); - - _saveStreamCommand.CommandText = string.Format("replace into mediastreams ({0}) values ({1})", - string.Join(",", _mediaStreamSaveColumns), - string.Join(",", _mediaStreamSaveColumns.Select(i => "@" + i).ToArray())); - - foreach (var col in _mediaStreamSaveColumns) - { - _saveStreamCommand.Parameters.Add(_saveStreamCommand, "@" + col); - } - - _updateInheritedTagsCommand = _connection.CreateCommand(); - _updateInheritedTagsCommand.CommandText = "Update TypedBaseItems set InheritedTags=@InheritedTags where Guid=@Guid"; - _updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@Guid"); - _updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@InheritedTags"); - - // user data - _deleteUserDataKeysCommand = _connection.CreateCommand(); - _deleteUserDataKeysCommand.CommandText = "delete from UserDataKeys where ItemId=@Id"; - _deleteUserDataKeysCommand.Parameters.Add(_deleteUserDataKeysCommand, "@Id"); - - _saveUserDataKeysCommand = _connection.CreateCommand(); - _saveUserDataKeysCommand.CommandText = "insert into UserDataKeys (ItemId, UserDataKey, Priority) values (@ItemId, @UserDataKey, @Priority)"; - _saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@ItemId"); - _saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@UserDataKey"); - _saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@Priority"); - - // item values - _deleteItemValuesCommand = _connection.CreateCommand(); - _deleteItemValuesCommand.CommandText = "delete from ItemValues where ItemId=@Id"; - _deleteItemValuesCommand.Parameters.Add(_deleteItemValuesCommand, "@Id"); - - _saveItemValuesCommand = _connection.CreateCommand(); - _saveItemValuesCommand.CommandText = "insert into ItemValues (ItemId, Type, Value, CleanValue) values (@ItemId, @Type, @Value, @CleanValue)"; - _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@ItemId"); - _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Type"); - _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Value"); - _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@CleanValue"); - - // provider ids - _deleteProviderIdsCommand = _connection.CreateCommand(); - _deleteProviderIdsCommand.CommandText = "delete from ProviderIds where ItemId=@Id"; - _deleteProviderIdsCommand.Parameters.Add(_deleteProviderIdsCommand, "@Id"); - - _saveProviderIdsCommand = _connection.CreateCommand(); - _saveProviderIdsCommand.CommandText = "insert into ProviderIds (ItemId, Name, Value) values (@ItemId, @Name, @Value)"; - _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@ItemId"); - _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@Name"); - _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@Value"); - - // images - _deleteImagesCommand = _connection.CreateCommand(); - _deleteImagesCommand.CommandText = "delete from Images where ItemId=@Id"; - _deleteImagesCommand.Parameters.Add(_deleteImagesCommand, "@Id"); - - _saveImagesCommand = _connection.CreateCommand(); - _saveImagesCommand.CommandText = "insert into Images (ItemId, ImageType, Path, DateModified, IsPlaceHolder, SortOrder) values (@ItemId, @ImageType, @Path, @DateModified, @IsPlaceHolder, @SortOrder)"; - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@ItemId"); - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@ImageType"); - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@Path"); - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@DateModified"); - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@IsPlaceHolder"); - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@SortOrder"); - } - - /// <summary> - /// Save a standard item in the repo - /// </summary> - /// <param name="item">The item.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">item</exception> - public Task SaveItem(BaseItem item, CancellationToken cancellationToken) - { - if (item == null) - { - throw new ArgumentNullException("item"); - } - - return SaveItems(new[] { item }, cancellationToken); - } - - /// <summary> - /// Saves the items. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"> - /// items - /// or - /// cancellationToken - /// </exception> - public async Task SaveItems(IEnumerable<BaseItem> items, CancellationToken cancellationToken) - { - if (items == null) - { - throw new ArgumentNullException("items"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - CheckDisposed(); - - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try - { - transaction = _connection.BeginTransaction(); - - foreach (var item in items) - { - cancellationToken.ThrowIfCancellationRequested(); - - var index = 0; - - _saveItemCommand.GetParameter(index++).Value = item.Id; - _saveItemCommand.GetParameter(index++).Value = item.GetType().FullName; - - if (TypeRequiresDeserialization(item.GetType())) - { - _saveItemCommand.GetParameter(index++).Value = _jsonSerializer.SerializeToBytes(item, _memoryStreamProvider); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.Path; - - var hasStartDate = item as IHasStartDate; - if (hasStartDate != null) - { - _saveItemCommand.GetParameter(index++).Value = hasStartDate.StartDate; - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.EndDate; - _saveItemCommand.GetParameter(index++).Value = item.ChannelId; - - var hasProgramAttributes = item as IHasProgramAttributes; - if (hasProgramAttributes != null) - { - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsKids; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsMovie; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsSports; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsSeries; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsLive; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsNews; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsPremiere; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.EpisodeTitle; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsRepeat; - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.CommunityRating; - _saveItemCommand.GetParameter(index++).Value = item.CustomRating; - - _saveItemCommand.GetParameter(index++).Value = item.IndexNumber; - _saveItemCommand.GetParameter(index++).Value = item.IsLocked; - - _saveItemCommand.GetParameter(index++).Value = item.Name; - _saveItemCommand.GetParameter(index++).Value = item.OfficialRating; - - _saveItemCommand.GetParameter(index++).Value = item.MediaType; - _saveItemCommand.GetParameter(index++).Value = item.Overview; - _saveItemCommand.GetParameter(index++).Value = item.ParentIndexNumber; - _saveItemCommand.GetParameter(index++).Value = item.PremiereDate; - _saveItemCommand.GetParameter(index++).Value = item.ProductionYear; - - if (item.ParentId == Guid.Empty) - { - _saveItemCommand.GetParameter(index++).Value = null; - } - else - { - _saveItemCommand.GetParameter(index++).Value = item.ParentId; - } - - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Genres.ToArray()); - _saveItemCommand.GetParameter(index++).Value = item.GetInheritedParentalRatingValue() ?? 0; - - _saveItemCommand.GetParameter(index++).Value = LatestSchemaVersion; - _saveItemCommand.GetParameter(index++).Value = item.SortName; - _saveItemCommand.GetParameter(index++).Value = item.RunTimeTicks; - - _saveItemCommand.GetParameter(index++).Value = item.OfficialRatingDescription; - _saveItemCommand.GetParameter(index++).Value = item.HomePageUrl; - _saveItemCommand.GetParameter(index++).Value = item.VoteCount; - _saveItemCommand.GetParameter(index++).Value = item.DisplayMediaType; - _saveItemCommand.GetParameter(index++).Value = item.DateCreated; - _saveItemCommand.GetParameter(index++).Value = item.DateModified; - - _saveItemCommand.GetParameter(index++).Value = item.ForcedSortName; - _saveItemCommand.GetParameter(index++).Value = item.IsOffline; - _saveItemCommand.GetParameter(index++).Value = item.LocationType.ToString(); - - _saveItemCommand.GetParameter(index++).Value = item.PreferredMetadataLanguage; - _saveItemCommand.GetParameter(index++).Value = item.PreferredMetadataCountryCode; - _saveItemCommand.GetParameter(index++).Value = item.IsHD; - _saveItemCommand.GetParameter(index++).Value = item.ExternalEtag; - - if (item.DateLastRefreshed == default(DateTime)) - { - _saveItemCommand.GetParameter(index++).Value = null; - } - else - { - _saveItemCommand.GetParameter(index++).Value = item.DateLastRefreshed; - } - - if (item.DateLastSaved == default(DateTime)) - { - _saveItemCommand.GetParameter(index++).Value = null; - } - else - { - _saveItemCommand.GetParameter(index++).Value = item.DateLastSaved; - } - - _saveItemCommand.GetParameter(index++).Value = item.IsInMixedFolder; - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()); - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Studios.ToArray()); - - if (item.Audio.HasValue) - { - _saveItemCommand.GetParameter(index++).Value = item.Audio.Value.ToString(); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.ServiceName; - - if (item.Tags.Count > 0) - { - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.IsFolder; - - _saveItemCommand.GetParameter(index++).Value = item.GetBlockUnratedType().ToString(); - - var topParent = item.GetTopParent(); - if (topParent != null) - { - //Logger.Debug("Item {0} has top parent {1}", item.Id, topParent.Id); - _saveItemCommand.GetParameter(index++).Value = topParent.Id.ToString("N"); - } - else - { - //Logger.Debug("Item {0} has null top parent", item.Id); - _saveItemCommand.GetParameter(index++).Value = null; - } - - var isByName = false; - var byName = item as IItemByName; - if (byName != null) - { - var dualAccess = item as IHasDualAccess; - isByName = dualAccess == null || dualAccess.IsAccessedByName; - } - _saveItemCommand.GetParameter(index++).Value = isByName; - - _saveItemCommand.GetParameter(index++).Value = item.SourceType.ToString(); - - var trailer = item as Trailer; - if (trailer != null && trailer.TrailerTypes.Count > 0) - { - _saveItemCommand.GetParameter(index++).Value = string.Join("|", trailer.TrailerTypes.Select(i => i.ToString()).ToArray()); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.CriticRating; - _saveItemCommand.GetParameter(index++).Value = item.CriticRatingSummary; - - var inheritedTags = item.GetInheritedTags(); - if (inheritedTags.Count > 0) - { - _saveItemCommand.GetParameter(index++).Value = string.Join("|", inheritedTags.ToArray()); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - if (string.IsNullOrWhiteSpace(item.Name)) - { - _saveItemCommand.GetParameter(index++).Value = null; - } - else - { - _saveItemCommand.GetParameter(index++).Value = GetCleanValue(item.Name); - } - - _saveItemCommand.GetParameter(index++).Value = item.GetPresentationUniqueKey(); - _saveItemCommand.GetParameter(index++).Value = item.SlugName; - _saveItemCommand.GetParameter(index++).Value = item.OriginalTitle; - - var video = item as Video; - if (video != null) - { - _saveItemCommand.GetParameter(index++).Value = video.PrimaryVersionId; - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - var folder = item as Folder; - if (folder != null && folder.DateLastMediaAdded.HasValue) - { - _saveItemCommand.GetParameter(index++).Value = folder.DateLastMediaAdded.Value; - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.Album; - - _saveItemCommand.GetParameter(index++).Value = item.IsVirtualItem; - - var hasSeries = item as IHasSeries; - if (hasSeries != null) - { - _saveItemCommand.GetParameter(index++).Value = hasSeries.FindSeriesName(); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.GetUserDataKeys().FirstOrDefault(); - - var episode = item as Episode; - if (episode != null) - { - _saveItemCommand.GetParameter(index++).Value = episode.FindSeasonName(); - _saveItemCommand.GetParameter(index++).Value = episode.FindSeasonId(); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - } - - if (hasSeries != null) - { - _saveItemCommand.GetParameter(index++).Value = hasSeries.FindSeriesId(); - _saveItemCommand.GetParameter(index++).Value = hasSeries.FindSeriesSortName(); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.ExternalSeriesId; - _saveItemCommand.GetParameter(index++).Value = item.ShortOverview; - _saveItemCommand.GetParameter(index++).Value = item.Tagline; - - if (item.Keywords.Count > 0) - { - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Keywords.ToArray()); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = SerializeProviderIds(item); - _saveItemCommand.GetParameter(index++).Value = SerializeImages(item); - - if (item.ProductionLocations.Count > 0) - { - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.ProductionLocations.ToArray()); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - if (item.ThemeSongIds.Count > 0) - { - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.ThemeSongIds.Select(i => i.ToString("N")).ToArray()); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - if (item.ThemeVideoIds.Count > 0) - { - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.ThemeVideoIds.Select(i => i.ToString("N")).ToArray()); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.Transaction = transaction; - - _saveItemCommand.ExecuteNonQuery(); - - if (item.SupportsAncestors) - { - UpdateAncestors(item.Id, item.GetAncestorIds().Distinct().ToList(), transaction); - } - - UpdateUserDataKeys(item.Id, item.GetUserDataKeys().Distinct(StringComparer.OrdinalIgnoreCase).ToList(), transaction); - UpdateImages(item.Id, item.ImageInfos, transaction); - UpdateProviderIds(item.Id, item.ProviderIds, transaction); - UpdateItemValues(item.Id, GetItemValuesToSave(item), transaction); - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save items:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - - WriteLock.Release(); - } - } - - private string SerializeProviderIds(BaseItem item) - { - var ids = item.ProviderIds.ToList(); - - if (ids.Count == 0) - { - return null; - } - - return string.Join("|", ids.Select(i => i.Key + "=" + i.Value).ToArray()); - } - - private void DeserializeProviderIds(string value, BaseItem item) - { - if (string.IsNullOrWhiteSpace(value)) - { - return; - } - - if (item.ProviderIds.Count > 0) - { - return; - } - - var parts = value.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); - - foreach (var part in parts) - { - var idParts = part.Split('='); - - item.SetProviderId(idParts[0], idParts[1]); - } - } - - private string SerializeImages(BaseItem item) - { - var images = item.ImageInfos.ToList(); - - if (images.Count == 0) - { - return null; - } - - return string.Join("|", images.Select(ToValueString).ToArray()); - } - - private void DeserializeImages(string value, BaseItem item) - { - if (string.IsNullOrWhiteSpace(value)) - { - return; - } - - if (item.ImageInfos.Count > 0) - { - return; - } - - var parts = value.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); - - foreach (var part in parts) - { - item.ImageInfos.Add(ItemImageInfoFromValueString(part)); - } - } - - public string ToValueString(ItemImageInfo image) - { - var delimeter = "*"; - - return (image.Path ?? string.Empty) + - delimeter + - image.DateModified.Ticks.ToString(CultureInfo.InvariantCulture) + - delimeter + - image.Type + - delimeter + - image.IsPlaceholder; - } - - public ItemImageInfo ItemImageInfoFromValueString(string value) - { - var parts = value.Split(new[] { '*' }, StringSplitOptions.None); - - var image = new ItemImageInfo(); - - image.Path = parts[0]; - image.DateModified = new DateTime(long.Parse(parts[1], CultureInfo.InvariantCulture), DateTimeKind.Utc); - image.Type = (ImageType)Enum.Parse(typeof(ImageType), parts[2], true); - image.IsPlaceholder = string.Equals(parts[3], true.ToString(), StringComparison.OrdinalIgnoreCase); - - return image; - } - - /// <summary> - /// Internal retrieve from items or users table - /// </summary> - /// <param name="id">The id.</param> - /// <returns>BaseItem.</returns> - /// <exception cref="System.ArgumentNullException">id</exception> - /// <exception cref="System.ArgumentException"></exception> - public BaseItem RetrieveItem(Guid id) - { - if (id == Guid.Empty) - { - throw new ArgumentNullException("id"); - } - - CheckDisposed(); - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems where guid = @guid"; - cmd.Parameters.Add(cmd, "@guid", DbType.Guid).Value = id; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) - { - return GetItem(reader); - } - } - return null; - } - } - - private BaseItem GetItem(IDataReader reader) - { - return GetItem(reader, new InternalItemsQuery()); - } - - private bool TypeRequiresDeserialization(Type type) - { - if (_config.Configuration.SkipDeserializationForBasicTypes) - { - if (type == typeof(MusicGenre)) - { - return false; - } - if (type == typeof(GameGenre)) - { - return false; - } - if (type == typeof(Genre)) - { - return false; - } - if (type == typeof(Studio)) - { - return false; - } - if (type == typeof(Year)) - { - return false; - } - if (type == typeof(Book)) - { - return false; - } - if (type == typeof(Person)) - { - return false; - } - if (type == typeof(RecordingGroup)) - { - return false; - } - if (type == typeof(Channel)) - { - return false; - } - if (type == typeof(ManualCollectionsFolder)) - { - return false; - } - if (type == typeof(CameraUploadsFolder)) - { - return false; - } - if (type == typeof(PlaylistsFolder)) - { - return false; - } - if (type == typeof(UserRootFolder)) - { - return false; - } - if (type == typeof(PhotoAlbum)) - { - return false; - } - if (type == typeof(Season)) - { - return false; - } - if (type == typeof(MusicArtist)) - { - return false; - } - } - if (_config.Configuration.SkipDeserializationForPrograms) - { - if (type == typeof(LiveTvProgram)) - { - return false; - } - } - - return true; - } - - private BaseItem GetItem(IDataReader reader, InternalItemsQuery query) - { - var typeString = reader.GetString(0); - - var type = _typeMapper.GetType(typeString); - - if (type == null) - { - //Logger.Debug("Unknown type {0}", typeString); - - return null; - } - - BaseItem item = null; - - if (TypeRequiresDeserialization(type)) - { - using (var stream = reader.GetMemoryStream(1, _memoryStreamProvider)) - { - try - { - item = _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem; - } - catch (SerializationException ex) - { - Logger.ErrorException("Error deserializing item", ex); - } - } - } - - if (item == null) - { - try - { - item = Activator.CreateInstance(type) as BaseItem; - } - catch - { - } - } - - if (item == null) - { - return null; - } - - if (!reader.IsDBNull(2)) - { - var hasStartDate = item as IHasStartDate; - if (hasStartDate != null) - { - hasStartDate.StartDate = reader.GetDateTime(2).ToUniversalTime(); - } - } - - if (!reader.IsDBNull(3)) - { - item.EndDate = reader.GetDateTime(3).ToUniversalTime(); - } - - if (!reader.IsDBNull(4)) - { - item.IsOffline = reader.GetBoolean(4); - } - - if (!reader.IsDBNull(5)) - { - item.ChannelId = reader.GetString(5); - } - - var hasProgramAttributes = item as IHasProgramAttributes; - if (hasProgramAttributes != null) - { - if (!reader.IsDBNull(6)) - { - hasProgramAttributes.IsMovie = reader.GetBoolean(6); - } - - if (!reader.IsDBNull(7)) - { - hasProgramAttributes.IsSports = reader.GetBoolean(7); - } - - if (!reader.IsDBNull(8)) - { - hasProgramAttributes.IsKids = reader.GetBoolean(8); - } - - if (!reader.IsDBNull(9)) - { - hasProgramAttributes.IsSeries = reader.GetBoolean(9); - } - - if (!reader.IsDBNull(10)) - { - hasProgramAttributes.IsLive = reader.GetBoolean(10); - } - - if (!reader.IsDBNull(11)) - { - hasProgramAttributes.IsNews = reader.GetBoolean(11); - } - - if (!reader.IsDBNull(12)) - { - hasProgramAttributes.IsPremiere = reader.GetBoolean(12); - } - - if (!reader.IsDBNull(13)) - { - hasProgramAttributes.EpisodeTitle = reader.GetString(13); - } - - if (!reader.IsDBNull(14)) - { - hasProgramAttributes.IsRepeat = reader.GetBoolean(14); - } - } - - var index = 15; - - if (!reader.IsDBNull(index)) - { - item.CommunityRating = reader.GetFloat(index); - } - index++; - - if (query.HasField(ItemFields.CustomRating)) - { - if (!reader.IsDBNull(index)) - { - item.CustomRating = reader.GetString(index); - } - index++; - } - - if (!reader.IsDBNull(index)) - { - item.IndexNumber = reader.GetInt32(index); - } - index++; - - if (query.HasField(ItemFields.Settings)) - { - if (!reader.IsDBNull(index)) - { - item.IsLocked = reader.GetBoolean(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.PreferredMetadataLanguage = reader.GetString(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.PreferredMetadataCountryCode = reader.GetString(index); - } - index++; - } - - if (!reader.IsDBNull(index)) - { - item.IsHD = reader.GetBoolean(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.ExternalEtag = reader.GetString(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.DateLastRefreshed = reader.GetDateTime(index).ToUniversalTime(); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.Name = reader.GetString(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.Path = reader.GetString(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.PremiereDate = reader.GetDateTime(index).ToUniversalTime(); - } - index++; - - if (query.HasField(ItemFields.Overview)) - { - if (!reader.IsDBNull(index)) - { - item.Overview = reader.GetString(index); - } - index++; - } - - if (!reader.IsDBNull(index)) - { - item.ParentIndexNumber = reader.GetInt32(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.ProductionYear = reader.GetInt32(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.OfficialRating = reader.GetString(index); - } - index++; - - if (query.HasField(ItemFields.OfficialRatingDescription)) - { - if (!reader.IsDBNull(index)) - { - item.OfficialRatingDescription = reader.GetString(index); - } - index++; - } - - if (query.HasField(ItemFields.HomePageUrl)) - { - if (!reader.IsDBNull(index)) - { - item.HomePageUrl = reader.GetString(index); - } - index++; - } - - if (query.HasField(ItemFields.DisplayMediaType)) - { - if (!reader.IsDBNull(index)) - { - item.DisplayMediaType = reader.GetString(index); - } - index++; - } - - if (query.HasField(ItemFields.SortName)) - { - if (!reader.IsDBNull(index)) - { - item.ForcedSortName = reader.GetString(index); - } - index++; - } - - if (!reader.IsDBNull(index)) - { - item.RunTimeTicks = reader.GetInt64(index); - } - index++; - - if (query.HasField(ItemFields.VoteCount)) - { - if (!reader.IsDBNull(index)) - { - item.VoteCount = reader.GetInt32(index); - } - index++; - } - - if (query.HasField(ItemFields.DateCreated)) - { - if (!reader.IsDBNull(index)) - { - item.DateCreated = reader.GetDateTime(index).ToUniversalTime(); - } - index++; - } - - if (!reader.IsDBNull(index)) - { - item.DateModified = reader.GetDateTime(index).ToUniversalTime(); - } - index++; - - item.Id = reader.GetGuid(index); - index++; - - if (query.HasField(ItemFields.Genres)) - { - if (!reader.IsDBNull(index)) - { - item.Genres = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); - } - index++; - } - - if (!reader.IsDBNull(index)) - { - item.ParentId = reader.GetGuid(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.Audio = (ProgramAudio)Enum.Parse(typeof(ProgramAudio), reader.GetString(index), true); - } - index++; - - // TODO: Even if not needed by apps, the server needs it internally - // But get this excluded from contexts where it is not needed - if (!reader.IsDBNull(index)) - { - item.ServiceName = reader.GetString(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.IsInMixedFolder = reader.GetBoolean(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.DateLastSaved = reader.GetDateTime(index).ToUniversalTime(); - } - index++; - - if (query.HasField(ItemFields.Settings)) - { - if (!reader.IsDBNull(index)) - { - item.LockedFields = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => (MetadataFields)Enum.Parse(typeof(MetadataFields), i, true)).ToList(); - } - index++; - } - - if (query.HasField(ItemFields.Studios)) - { - if (!reader.IsDBNull(index)) - { - item.Studios = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); - } - index++; - } - - if (query.HasField(ItemFields.Tags)) - { - if (!reader.IsDBNull(index)) - { - item.Tags = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); - } - index++; - } - - if (!reader.IsDBNull(index)) - { - item.SourceType = (SourceType)Enum.Parse(typeof(SourceType), reader.GetString(index), true); - } - index++; - - var trailer = item as Trailer; - if (trailer != null) - { - if (!reader.IsDBNull(index)) - { - trailer.TrailerTypes = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true)).ToList(); - } - } - index++; - - if (query.HasField(ItemFields.OriginalTitle)) - { - if (!reader.IsDBNull(index)) - { - item.OriginalTitle = reader.GetString(index); - } - index++; - } - - var video = item as Video; - if (video != null) - { - if (!reader.IsDBNull(index)) - { - video.PrimaryVersionId = reader.GetString(index); - } - } - index++; - - if (query.HasField(ItemFields.DateLastMediaAdded)) - { - var folder = item as Folder; - if (folder != null && !reader.IsDBNull(index)) - { - folder.DateLastMediaAdded = reader.GetDateTime(index).ToUniversalTime(); - } - index++; - } - - if (!reader.IsDBNull(index)) - { - item.Album = reader.GetString(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.CriticRating = reader.GetFloat(index); - } - index++; - - if (query.HasField(ItemFields.CriticRatingSummary)) - { - if (!reader.IsDBNull(index)) - { - item.CriticRatingSummary = reader.GetString(index); - } - index++; - } - - if (!reader.IsDBNull(index)) - { - item.IsVirtualItem = reader.GetBoolean(index); - } - index++; - - var hasSeries = item as IHasSeries; - if (hasSeries != null) - { - if (!reader.IsDBNull(index)) - { - hasSeries.SeriesName = reader.GetString(index); - } - } - index++; - - var episode = item as Episode; - if (episode != null) - { - if (!reader.IsDBNull(index)) - { - episode.SeasonName = reader.GetString(index); - } - index++; - if (!reader.IsDBNull(index)) - { - episode.SeasonId = reader.GetGuid(index); - } - } - else - { - index++; - } - index++; - - if (hasSeries != null) - { - if (!reader.IsDBNull(index)) - { - hasSeries.SeriesId = reader.GetGuid(index); - } - } - index++; - - if (hasSeries != null) - { - if (!reader.IsDBNull(index)) - { - hasSeries.SeriesSortName = reader.GetString(index); - } - } - index++; - - if (!reader.IsDBNull(index)) - { - item.PresentationUniqueKey = reader.GetString(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.InheritedParentalRatingValue = reader.GetInt32(index); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.InheritedTags = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); - } - index++; - - if (!reader.IsDBNull(index)) - { - item.ExternalSeriesId = reader.GetString(index); - } - index++; - - if (query.HasField(ItemFields.ShortOverview)) - { - if (!reader.IsDBNull(index)) - { - item.ShortOverview = reader.GetString(index); - } - index++; - } - - if (query.HasField(ItemFields.Taglines)) - { - if (!reader.IsDBNull(index)) - { - item.Tagline = reader.GetString(index); - } - index++; - } - - if (query.HasField(ItemFields.Keywords)) - { - if (!reader.IsDBNull(index)) - { - item.Keywords = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); - } - index++; - } - - if (!reader.IsDBNull(index)) - { - DeserializeProviderIds(reader.GetString(index), item); - } - index++; - - if (query.DtoOptions.EnableImages) - { - if (!reader.IsDBNull(index)) - { - DeserializeImages(reader.GetString(index), item); - } - index++; - } - - if (query.HasField(ItemFields.ProductionLocations)) - { - if (!reader.IsDBNull(index)) - { - item.ProductionLocations = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); - } - index++; - } - - if (query.HasField(ItemFields.ThemeSongIds)) - { - if (!reader.IsDBNull(index)) - { - item.ThemeSongIds = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToList(); - } - index++; - } - - if (query.HasField(ItemFields.ThemeVideoIds)) - { - if (!reader.IsDBNull(index)) - { - item.ThemeVideoIds = reader.GetString(index).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToList(); - } - index++; - } - - if (string.IsNullOrWhiteSpace(item.Tagline)) - { - var movie = item as Movie; - if (movie != null && movie.Taglines.Count > 0) - { - movie.Tagline = movie.Taglines[0]; - } - } - - if (type == typeof(Person) && item.ProductionLocations.Count == 0) - { - var person = (Person)item; - if (!string.IsNullOrWhiteSpace(person.PlaceOfBirth)) - { - item.ProductionLocations = new List<string> { person.PlaceOfBirth }; - } - } - - return item; - } - - /// <summary> - /// Gets the critic reviews. - /// </summary> - /// <param name="itemId">The item id.</param> - /// <returns>Task{IEnumerable{ItemReview}}.</returns> - public IEnumerable<ItemReview> GetCriticReviews(Guid itemId) - { - try - { - var path = Path.Combine(_criticReviewsPath, itemId + ".json"); - - return _jsonSerializer.DeserializeFromFile<List<ItemReview>>(path); - } - catch (DirectoryNotFoundException) - { - return new List<ItemReview>(); - } - catch (FileNotFoundException) - { - return new List<ItemReview>(); - } - } - - private readonly Task _cachedTask = Task.FromResult(true); - /// <summary> - /// Saves the critic reviews. - /// </summary> - /// <param name="itemId">The item id.</param> - /// <param name="criticReviews">The critic reviews.</param> - /// <returns>Task.</returns> - public Task SaveCriticReviews(Guid itemId, IEnumerable<ItemReview> criticReviews) - { - Directory.CreateDirectory(_criticReviewsPath); - - var path = Path.Combine(_criticReviewsPath, itemId + ".json"); - - _jsonSerializer.SerializeToFile(criticReviews.ToList(), path); - - return _cachedTask; - } - - /// <summary> - /// Gets chapters for an item - /// </summary> - /// <param name="id">The id.</param> - /// <returns>IEnumerable{ChapterInfo}.</returns> - /// <exception cref="System.ArgumentNullException">id</exception> - public IEnumerable<ChapterInfo> GetChapters(Guid id) - { - CheckDisposed(); - if (id == Guid.Empty) - { - throw new ArgumentNullException("id"); - } - var list = new List<ChapterInfo>(); - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId order by ChapterIndex asc"; - - cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = id; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - list.Add(GetChapter(reader)); - } - } - } - - return list; - } - - /// <summary> - /// Gets a single chapter for an item - /// </summary> - /// <param name="id">The id.</param> - /// <param name="index">The index.</param> - /// <returns>ChapterInfo.</returns> - /// <exception cref="System.ArgumentNullException">id</exception> - public ChapterInfo GetChapter(Guid id, int index) - { - CheckDisposed(); - if (id == Guid.Empty) - { - throw new ArgumentNullException("id"); - } - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select StartPositionTicks,Name,ImagePath,ImageDateModified from " + ChaptersTableName + " where ItemId = @ItemId and ChapterIndex=@ChapterIndex"; - - cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = id; - cmd.Parameters.Add(cmd, "@ChapterIndex", DbType.Int32).Value = index; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) - { - return GetChapter(reader); - } - } - return null; - } - } - - /// <summary> - /// Gets the chapter. - /// </summary> - /// <param name="reader">The reader.</param> - /// <returns>ChapterInfo.</returns> - private ChapterInfo GetChapter(IDataReader reader) - { - var chapter = new ChapterInfo - { - StartPositionTicks = reader.GetInt64(0) - }; - - if (!reader.IsDBNull(1)) - { - chapter.Name = reader.GetString(1); - } - - if (!reader.IsDBNull(2)) - { - chapter.ImagePath = reader.GetString(2); - } - - if (!reader.IsDBNull(3)) - { - chapter.ImageDateModified = reader.GetDateTime(3).ToUniversalTime(); - } - - return chapter; - } - - /// <summary> - /// Saves the chapters. - /// </summary> - /// <param name="id">The id.</param> - /// <param name="chapters">The chapters.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"> - /// id - /// or - /// chapters - /// or - /// cancellationToken - /// </exception> - public async Task SaveChapters(Guid id, List<ChapterInfo> chapters, CancellationToken cancellationToken) - { - CheckDisposed(); - - if (id == Guid.Empty) - { - throw new ArgumentNullException("id"); - } - - if (chapters == null) - { - throw new ArgumentNullException("chapters"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try - { - transaction = _connection.BeginTransaction(); - - // First delete chapters - _deleteChaptersCommand.GetParameter(0).Value = id; - - _deleteChaptersCommand.Transaction = transaction; - - _deleteChaptersCommand.ExecuteNonQuery(); - - var index = 0; - - foreach (var chapter in chapters) - { - cancellationToken.ThrowIfCancellationRequested(); - - _saveChapterCommand.GetParameter(0).Value = id; - _saveChapterCommand.GetParameter(1).Value = index; - _saveChapterCommand.GetParameter(2).Value = chapter.StartPositionTicks; - _saveChapterCommand.GetParameter(3).Value = chapter.Name; - _saveChapterCommand.GetParameter(4).Value = chapter.ImagePath; - _saveChapterCommand.GetParameter(5).Value = chapter.ImageDateModified; - - _saveChapterCommand.Transaction = transaction; - - _saveChapterCommand.ExecuteNonQuery(); - - index++; - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save chapters:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - - WriteLock.Release(); - } - } - - protected override void CloseConnection() - { - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - - _connection.Dispose(); - _connection = null; - } - } - - private bool EnableJoinUserData(InternalItemsQuery query) - { - if (query.User == null) - { - return false; - } - - if (query.SimilarTo != null && query.User != null) - { - return true; - } - - var sortingFields = query.SortBy.ToList(); - sortingFields.AddRange(query.OrderBy.Select(i => i.Item1)); - - if (sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - if (sortingFields.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - - if (query.IsFavoriteOrLiked.HasValue) - { - return true; - } - - if (query.IsFavorite.HasValue) - { - return true; - } - - if (query.IsResumable.HasValue) - { - return true; - } - - if (query.IsPlayed.HasValue) - { - return true; - } - - if (query.IsLiked.HasValue) - { - return true; - } - - return false; - } - - private List<ItemFields> allFields = Enum.GetNames(typeof(ItemFields)) - .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)) - .ToList(); - - private IEnumerable<string> GetColumnNamesFromField(ItemFields field) - { - if (field == ItemFields.Settings) - { - return new[] { "IsLocked", "PreferredMetadataCountryCode", "PreferredMetadataLanguage", "LockedFields" }; - } - if (field == ItemFields.ServiceName) - { - return new[] { "ExternalServiceId" }; - } - if (field == ItemFields.SortName) - { - return new[] { "ForcedSortName" }; - } - if (field == ItemFields.Taglines) - { - return new[] { "Tagline" }; - } - - return new[] { field.ToString() }; - } - - private string[] GetFinalColumnsToSelect(InternalItemsQuery query, string[] startColumns, IDbCommand cmd) - { - var list = startColumns.ToList(); - - foreach (var field in allFields) - { - if (!query.HasField(field)) - { - foreach (var fieldToRemove in GetColumnNamesFromField(field).ToList()) - { - list.Remove(fieldToRemove); - } - } - } - - if (!query.DtoOptions.EnableImages) - { - list.Remove("Images"); - } - - if (EnableJoinUserData(query)) - { - list.Add("UserDataDb.UserData.UserId"); - list.Add("UserDataDb.UserData.lastPlayedDate"); - list.Add("UserDataDb.UserData.playbackPositionTicks"); - list.Add("UserDataDb.UserData.playcount"); - list.Add("UserDataDb.UserData.isFavorite"); - list.Add("UserDataDb.UserData.played"); - list.Add("UserDataDb.UserData.rating"); - } - - if (query.SimilarTo != null) - { - var item = query.SimilarTo; - - var builder = new StringBuilder(); - builder.Append("("); - - builder.Append("((OfficialRating=@ItemOfficialRating) * 10)"); - //builder.Append("+ ((ProductionYear=@ItemProductionYear) * 10)"); - - builder.Append("+(Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 10 Then 2 Else 0 End )"); - builder.Append("+(Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 5 Then 2 Else 0 End )"); - - //// genres - builder.Append("+ ((Select count(CleanValue) from ItemValues where ItemId=Guid and Type=2 and CleanValue in (select CleanValue from itemvalues where ItemId=@SimilarItemId and type=2)) * 10)"); - - //// tags - builder.Append("+ ((Select count(CleanValue) from ItemValues where ItemId=Guid and Type=4 and CleanValue in (select CleanValue from itemvalues where ItemId=@SimilarItemId and type=4)) * 10)"); - - builder.Append("+ ((Select count(CleanValue) from ItemValues where ItemId=Guid and Type=5 and CleanValue in (select CleanValue from itemvalues where ItemId=@SimilarItemId and type=5)) * 10)"); - - builder.Append("+ ((Select count(CleanValue) from ItemValues where ItemId=Guid and Type=3 and CleanValue in (select CleanValue from itemvalues where ItemId=@SimilarItemId and type=3)) * 3)"); - - //builder.Append("+ ((Select count(Name) from People where ItemId=Guid and Name in (select Name from People where ItemId=@SimilarItemId)) * 3)"); - - ////builder.Append("(select group_concat((Select Name from People where ItemId=Guid and Name in (Select Name from People where ItemId=@SimilarItemId)), '|'))"); - - builder.Append(") as SimilarityScore"); - - list.Add(builder.ToString()); - cmd.Parameters.Add(cmd, "@ItemOfficialRating", DbType.String).Value = item.OfficialRating; - cmd.Parameters.Add(cmd, "@ItemProductionYear", DbType.Int32).Value = item.ProductionYear ?? 0; - cmd.Parameters.Add(cmd, "@SimilarItemId", DbType.Guid).Value = item.Id; - - var excludeIds = query.ExcludeItemIds.ToList(); - excludeIds.Add(item.Id.ToString("N")); - query.ExcludeItemIds = excludeIds.ToArray(); - - query.ExcludeProviderIds = item.ProviderIds; - } - - return list.ToArray(); - } - - private string GetJoinUserDataText(InternalItemsQuery query) - { - if (!EnableJoinUserData(query)) - { - return string.Empty; - } - - if (_config.Configuration.SchemaVersion >= 96) - { - return " left join UserDataDb.UserData on UserDataKey=UserDataDb.UserData.Key And (UserId=@UserId)"; - } - - return " left join UserDataDb.UserData on (select UserDataKey from UserDataKeys where ItemId=Guid order by Priority LIMIT 1)=UserDataDb.UserData.Key And (UserId=@UserId)"; - } - - private string GetGroupBy(InternalItemsQuery query) - { - var groups = new List<string>(); - - if (EnableGroupByPresentationUniqueKey(query)) - { - groups.Add("PresentationUniqueKey"); - } - - if (groups.Count > 0) - { - return " Group by " + string.Join(",", groups.ToArray()); - } - - return string.Empty; - } - - private string GetFromText(string alias = "A") - { - return " from TypedBaseItems " + alias; - } - - public List<BaseItem> GetItemList(InternalItemsQuery query) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - CheckDisposed(); - - var now = DateTime.UtcNow; - - var list = new List<BaseItem>(); - - // Hack for right now since we currently don't support filtering out these duplicates within a query - if (query.Limit.HasValue && query.EnableGroupByMetadataKey) - { - query.Limit = query.Limit.Value + 4; - } - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + GetFromText(); - cmd.CommandText += GetJoinUserDataText(query); - - if (EnableJoinUserData(query)) - { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; - } - - var whereClauses = GetWhereClauses(query, cmd); - - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - cmd.CommandText += whereText; - - cmd.CommandText += GetGroupBy(query); - - cmd.CommandText += GetOrderByText(query); - - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var offset = query.StartIndex ?? 0; - - if (query.Limit.HasValue || offset > 0) - { - cmd.CommandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture); - } - - if (offset > 0) - { - cmd.CommandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture); - } - } - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - LogQueryTime("GetItemList", cmd, now); - - while (reader.Read()) - { - var item = GetItem(reader, query); - if (item != null) - { - list.Add(item); - } - } - } - } - - // 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) - { - AddItem(newList, item); - - if (newList.Count >= limit) - { - break; - } - } - - list = newList; - } - - return list; - } - - private void AddItem(List<BaseItem> items, BaseItem newItem) - { - var providerIds = newItem.ProviderIds.ToList(); - - for (var i = 0; i < items.Count; i++) - { - var item = items[i]; - - foreach (var providerId in providerIds) - { - if (providerId.Key == MetadataProviders.TmdbCollection.ToString()) - { - continue; - } - if (item.GetProviderId(providerId.Key) == providerId.Value) - { - if (newItem.SourceType == SourceType.Library) - { - items[i] = newItem; - } - return; - } - } - } - - items.Add(newItem); - } - - private void LogQueryTime(string methodName, IDbCommand cmd, DateTime startDate) - { - var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds; - - var slowThreshold = 1000; - -#if DEBUG - slowThreshold = 50; -#endif - - if (elapsed >= slowThreshold) - { - Logger.Debug("{2} query time (slow): {0}ms. Query: {1}", - Convert.ToInt32(elapsed), - cmd.CommandText, - methodName); - } - else - { - //Logger.Debug("{2} query time: {0}ms. Query: {1}", - // Convert.ToInt32(elapsed), - // cmd.CommandText, - // methodName); - } - } - - public QueryResult<BaseItem> GetItems(InternalItemsQuery query) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - CheckDisposed(); - - if (!query.EnableTotalRecordCount || (!query.Limit.HasValue && (query.StartIndex ?? 0) == 0)) - { - var list = GetItemList(query); - return new QueryResult<BaseItem> - { - Items = list.ToArray(), - TotalRecordCount = list.Count - }; - } - - var now = DateTime.UtcNow; - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + GetFromText(); - cmd.CommandText += GetJoinUserDataText(query); - - if (EnableJoinUserData(query)) - { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; - } - - var whereClauses = GetWhereClauses(query, cmd); - - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - cmd.CommandText += whereText; - - cmd.CommandText += GetGroupBy(query); - - cmd.CommandText += GetOrderByText(query); - - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var offset = query.StartIndex ?? 0; - - if (query.Limit.HasValue || offset > 0) - { - cmd.CommandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture); - } - - if (offset > 0) - { - cmd.CommandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture); - } - } - - cmd.CommandText += ";"; - - var isReturningZeroItems = query.Limit.HasValue && query.Limit <= 0; - - if (isReturningZeroItems) - { - cmd.CommandText = ""; - } - - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " select count (distinct PresentationUniqueKey)" + GetFromText(); - } - else - { - cmd.CommandText += " select count (guid)" + GetFromText(); - } - - cmd.CommandText += GetJoinUserDataText(query); - cmd.CommandText += whereTextWithoutPaging; - - var list = new List<BaseItem>(); - var count = 0; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - LogQueryTime("GetItems", cmd, now); - - if (isReturningZeroItems) - { - if (reader.Read()) - { - count = reader.GetInt32(0); - } - } - else - { - while (reader.Read()) - { - var item = GetItem(reader, query); - if (item != null) - { - list.Add(item); - } - } - - if (reader.NextResult() && reader.Read()) - { - count = reader.GetInt32(0); - } - } - } - - return new QueryResult<BaseItem>() - { - Items = list.ToArray(), - TotalRecordCount = count - }; - } - } - - private string GetOrderByText(InternalItemsQuery query) - { - var orderBy = query.OrderBy.ToList(); - var enableOrderInversion = true; - - if (orderBy.Count == 0) - { - orderBy.AddRange(query.SortBy.Select(i => new Tuple<string, SortOrder>(i, query.SortOrder))); - } - else - { - enableOrderInversion = false; - } - - if (query.SimilarTo != null) - { - if (orderBy.Count == 0) - { - 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; - } - } - - query.OrderBy = orderBy; - - if (orderBy.Count == 0) - { - return string.Empty; - } - - return " ORDER BY " + string.Join(",", orderBy.Select(i => - { - var columnMap = MapOrderByField(i.Item1, query); - var columnAscending = i.Item2 == SortOrder.Ascending; - if (columnMap.Item2 && enableOrderInversion) - { - columnAscending = !columnAscending; - } - - var sortOrder = columnAscending ? "ASC" : "DESC"; - - return columnMap.Item1 + " " + sortOrder; - }).ToArray()); - } - - private Tuple<string, bool> MapOrderByField(string name, InternalItemsQuery query) - { - if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase)) - { - // TODO - return new Tuple<string, bool>("SortName", false); - } - if (string.Equals(name, ItemSortBy.Runtime, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("RuntimeTicks", false); - } - if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("RANDOM()", false); - } - if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("LastPlayedDate", false); - } - if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("PlayCount", false); - } - if (string.Equals(name, ItemSortBy.IsFavoriteOrLiked, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("IsFavorite", true); - } - if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("IsFolder", true); - } - if (string.Equals(name, ItemSortBy.IsPlayed, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("played", true); - } - if (string.Equals(name, ItemSortBy.IsUnplayed, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("played", false); - } - if (string.Equals(name, ItemSortBy.DateLastContentAdded, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("DateLastMediaAdded", false); - } - if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("(select CleanValue from itemvalues where ItemId=Guid and Type=0 LIMIT 1)", false); - } - if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("(select CleanValue from itemvalues where ItemId=Guid and Type=1 LIMIT 1)", false); - } - if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("InheritedParentalRatingValue", false); - } - if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("(select CleanValue from itemvalues where ItemId=Guid and Type=3 LIMIT 1)", false); - } - if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase)) - { - return new Tuple<string, bool>("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where B.Guid in (Select ItemId from AncestorIds where AncestorId in (select guid from typedbaseitems c where C.Type = 'MediaBrowser.Controller.Entities.TV.Series' And C.Guid in (Select AncestorId from AncestorIds where ItemId=A.Guid))))", false); - } - - return new Tuple<string, bool>(name, false); - } - - public List<Guid> GetItemIdsList(InternalItemsQuery query) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - CheckDisposed(); - - var now = DateTime.UtcNow; - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + GetFromText(); - cmd.CommandText += GetJoinUserDataText(query); - - if (EnableJoinUserData(query)) - { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; - } - - var whereClauses = GetWhereClauses(query, cmd); - - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - cmd.CommandText += whereText; - - cmd.CommandText += GetGroupBy(query); - - cmd.CommandText += GetOrderByText(query); - - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var offset = query.StartIndex ?? 0; - - if (query.Limit.HasValue || offset > 0) - { - cmd.CommandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture); - } - - if (offset > 0) - { - cmd.CommandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture); - } - } - - var list = new List<Guid>(); - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - LogQueryTime("GetItemIdsList", cmd, now); - - while (reader.Read()) - { - list.Add(reader.GetGuid(0)); - } - } - - return list; - } - } - - public QueryResult<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - CheckDisposed(); - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select guid,path from TypedBaseItems"; - - var whereClauses = GetWhereClauses(query, cmd); - - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - cmd.CommandText += whereText; - - cmd.CommandText += GetGroupBy(query); - - cmd.CommandText += GetOrderByText(query); - - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var offset = query.StartIndex ?? 0; - - if (query.Limit.HasValue || offset > 0) - { - cmd.CommandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture); - } - - if (offset > 0) - { - cmd.CommandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture); - } - } - - cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging; - - var list = new List<Tuple<Guid, string>>(); - var count = 0; - - Logger.Debug(cmd.CommandText); - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (reader.Read()) - { - var id = reader.GetGuid(0); - string path = null; - - if (!reader.IsDBNull(1)) - { - path = reader.GetString(1); - } - list.Add(new Tuple<Guid, string>(id, path)); - } - - if (reader.NextResult() && reader.Read()) - { - count = reader.GetInt32(0); - } - } - - return new QueryResult<Tuple<Guid, string>>() - { - Items = list.ToArray(), - TotalRecordCount = count - }; - } - } - - public QueryResult<Guid> GetItemIds(InternalItemsQuery query) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - CheckDisposed(); - - if (!query.EnableTotalRecordCount || (!query.Limit.HasValue && (query.StartIndex ?? 0) == 0)) - { - var list = GetItemIdsList(query); - return new QueryResult<Guid> - { - Items = list.ToArray(), - TotalRecordCount = list.Count - }; - } - - var now = DateTime.UtcNow; - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + GetFromText(); - - var whereClauses = GetWhereClauses(query, cmd); - cmd.CommandText += GetJoinUserDataText(query); - - if (EnableJoinUserData(query)) - { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; - } - - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - cmd.CommandText += whereText; - - cmd.CommandText += GetGroupBy(query); - - cmd.CommandText += GetOrderByText(query); - - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var offset = query.StartIndex ?? 0; - - if (query.Limit.HasValue || offset > 0) - { - cmd.CommandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture); - } - - if (offset > 0) - { - cmd.CommandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture); - } - } - - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += "; select count (distinct PresentationUniqueKey)" + GetFromText(); - } - else - { - cmd.CommandText += "; select count (guid)" + GetFromText(); - } - - cmd.CommandText += GetJoinUserDataText(query); - cmd.CommandText += whereText; - - var list = new List<Guid>(); - var count = 0; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - LogQueryTime("GetItemIds", cmd, now); - - while (reader.Read()) - { - list.Add(reader.GetGuid(0)); - } - - if (reader.NextResult() && reader.Read()) - { - count = reader.GetInt32(0); - } - } - - return new QueryResult<Guid>() - { - Items = list.ToArray(), - TotalRecordCount = count - }; - } - } - - private List<string> GetWhereClauses(InternalItemsQuery query, IDbCommand cmd, string paramSuffix = "") - { - var whereClauses = new List<string>(); - - if (EnableJoinUserData(query)) - { - //whereClauses.Add("(UserId is null or UserId=@UserId)"); - } - if (query.IsCurrentSchema.HasValue) - { - if (query.IsCurrentSchema.Value) - { - whereClauses.Add("(SchemaVersion not null AND SchemaVersion=@SchemaVersion)"); - } - else - { - whereClauses.Add("(SchemaVersion is null or SchemaVersion<>@SchemaVersion)"); - } - cmd.Parameters.Add(cmd, "@SchemaVersion", DbType.Int32).Value = LatestSchemaVersion; - } - if (query.IsHD.HasValue) - { - whereClauses.Add("IsHD=@IsHD"); - cmd.Parameters.Add(cmd, "@IsHD", DbType.Boolean).Value = query.IsHD; - } - if (query.IsLocked.HasValue) - { - whereClauses.Add("IsLocked=@IsLocked"); - cmd.Parameters.Add(cmd, "@IsLocked", DbType.Boolean).Value = query.IsLocked; - } - if (query.IsOffline.HasValue) - { - whereClauses.Add("IsOffline=@IsOffline"); - cmd.Parameters.Add(cmd, "@IsOffline", DbType.Boolean).Value = query.IsOffline; - } - - var exclusiveProgramAttribtues = !(query.IsMovie ?? true) || - !(query.IsSports ?? true) || - !(query.IsKids ?? true) || - !(query.IsNews ?? true) || - !(query.IsSeries ?? true); - - if (exclusiveProgramAttribtues) - { - if (query.IsMovie.HasValue) - { - var alternateTypes = new List<string>(); - if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Movie).Name)) - { - alternateTypes.Add(typeof(Movie).FullName); - } - if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Trailer).Name)) - { - alternateTypes.Add(typeof(Trailer).FullName); - } - - if (alternateTypes.Count == 0) - { - whereClauses.Add("IsMovie=@IsMovie"); - cmd.Parameters.Add(cmd, "@IsMovie", DbType.Boolean).Value = query.IsMovie; - } - else - { - whereClauses.Add("(IsMovie is null OR IsMovie=@IsMovie)"); - cmd.Parameters.Add(cmd, "@IsMovie", DbType.Boolean).Value = query.IsMovie; - } - } - if (query.IsSeries.HasValue) - { - whereClauses.Add("IsSeries=@IsSeries"); - cmd.Parameters.Add(cmd, "@IsSeries", DbType.Boolean).Value = query.IsSeries; - } - if (query.IsNews.HasValue) - { - whereClauses.Add("IsNews=@IsNews"); - cmd.Parameters.Add(cmd, "@IsNews", DbType.Boolean).Value = query.IsNews; - } - if (query.IsKids.HasValue) - { - whereClauses.Add("IsKids=@IsKids"); - cmd.Parameters.Add(cmd, "@IsKids", DbType.Boolean).Value = query.IsKids; - } - if (query.IsSports.HasValue) - { - whereClauses.Add("IsSports=@IsSports"); - cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = query.IsSports; - } - } - else - { - var programAttribtues = new List<string>(); - if (query.IsMovie ?? false) - { - var alternateTypes = new List<string>(); - if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Movie).Name)) - { - alternateTypes.Add(typeof(Movie).FullName); - } - if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Trailer).Name)) - { - alternateTypes.Add(typeof(Trailer).FullName); - } - - if (alternateTypes.Count == 0) - { - programAttribtues.Add("IsMovie=@IsMovie"); - } - else - { - programAttribtues.Add("(IsMovie is null OR IsMovie=@IsMovie)"); - } - - cmd.Parameters.Add(cmd, "@IsMovie", DbType.Boolean).Value = true; - } - if (query.IsSports ?? false) - { - programAttribtues.Add("IsSports=@IsSports"); - cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = true; - } - if (query.IsNews ?? false) - { - programAttribtues.Add("IsNews=@IsNews"); - cmd.Parameters.Add(cmd, "@IsNews", DbType.Boolean).Value = true; - } - if (query.IsSeries ?? false) - { - programAttribtues.Add("IsSeries=@IsSeries"); - cmd.Parameters.Add(cmd, "@IsSeries", DbType.Boolean).Value = true; - } - if (query.IsKids ?? false) - { - programAttribtues.Add("IsKids=@IsKids"); - cmd.Parameters.Add(cmd, "@IsKids", DbType.Boolean).Value = true; - } - if (programAttribtues.Count > 0) - { - whereClauses.Add("(" + string.Join(" OR ", programAttribtues.ToArray()) + ")"); - } - } - - if (query.SimilarTo != null) - { - whereClauses.Add("SimilarityScore > 0"); - } - - if (query.IsFolder.HasValue) - { - whereClauses.Add("IsFolder=@IsFolder"); - cmd.Parameters.Add(cmd, "@IsFolder", DbType.Boolean).Value = query.IsFolder; - } - - var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); - if (includeTypes.Length == 1) - { - whereClauses.Add("type=@type" + paramSuffix); - cmd.Parameters.Add(cmd, "@type" + paramSuffix, DbType.String).Value = includeTypes[0]; - } - else if (includeTypes.Length > 1) - { - var inClause = string.Join(",", includeTypes.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("type in ({0})", inClause)); - } - - var excludeTypes = query.ExcludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); - if (excludeTypes.Length == 1) - { - whereClauses.Add("type<>@type"); - cmd.Parameters.Add(cmd, "@type", DbType.String).Value = excludeTypes[0]; - } - else if (excludeTypes.Length > 1) - { - var inClause = string.Join(",", excludeTypes.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("type not in ({0})", inClause)); - } - - if (query.ChannelIds.Length == 1) - { - whereClauses.Add("ChannelId=@ChannelId"); - cmd.Parameters.Add(cmd, "@ChannelId", DbType.String).Value = query.ChannelIds[0]; - } - if (query.ChannelIds.Length > 1) - { - var inClause = string.Join(",", query.ChannelIds.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("ChannelId in ({0})", inClause)); - } - - if (query.ParentId.HasValue) - { - whereClauses.Add("ParentId=@ParentId"); - cmd.Parameters.Add(cmd, "@ParentId", DbType.Guid).Value = query.ParentId.Value; - } - - if (!string.IsNullOrWhiteSpace(query.Path)) - { - whereClauses.Add("Path=@Path"); - cmd.Parameters.Add(cmd, "@Path", DbType.String).Value = query.Path; - } - - if (!string.IsNullOrWhiteSpace(query.PresentationUniqueKey)) - { - whereClauses.Add("PresentationUniqueKey=@PresentationUniqueKey"); - cmd.Parameters.Add(cmd, "@PresentationUniqueKey", DbType.String).Value = query.PresentationUniqueKey; - } - - if (query.MinCommunityRating.HasValue) - { - whereClauses.Add("CommunityRating>=@MinCommunityRating"); - cmd.Parameters.Add(cmd, "@MinCommunityRating", DbType.Double).Value = query.MinCommunityRating.Value; - } - - if (query.MinIndexNumber.HasValue) - { - whereClauses.Add("IndexNumber>=@MinIndexNumber"); - cmd.Parameters.Add(cmd, "@MinIndexNumber", DbType.Int32).Value = query.MinIndexNumber.Value; - } - - if (query.MinDateCreated.HasValue) - { - whereClauses.Add("DateCreated>=@MinDateCreated"); - cmd.Parameters.Add(cmd, "@MinDateCreated", DbType.DateTime).Value = query.MinDateCreated.Value; - } - - if (query.MinDateLastSaved.HasValue) - { - whereClauses.Add("DateLastSaved>=@MinDateLastSaved"); - cmd.Parameters.Add(cmd, "@MinDateLastSaved", DbType.DateTime).Value = query.MinDateLastSaved.Value; - } - - //if (query.MinPlayers.HasValue) - //{ - // whereClauses.Add("Players>=@MinPlayers"); - // cmd.Parameters.Add(cmd, "@MinPlayers", DbType.Int32).Value = query.MinPlayers.Value; - //} - - //if (query.MaxPlayers.HasValue) - //{ - // whereClauses.Add("Players<=@MaxPlayers"); - // cmd.Parameters.Add(cmd, "@MaxPlayers", DbType.Int32).Value = query.MaxPlayers.Value; - //} - - if (query.IndexNumber.HasValue) - { - whereClauses.Add("IndexNumber=@IndexNumber"); - cmd.Parameters.Add(cmd, "@IndexNumber", DbType.Int32).Value = query.IndexNumber.Value; - } - if (query.ParentIndexNumber.HasValue) - { - whereClauses.Add("ParentIndexNumber=@ParentIndexNumber"); - cmd.Parameters.Add(cmd, "@ParentIndexNumber", DbType.Int32).Value = query.ParentIndexNumber.Value; - } - if (query.ParentIndexNumberNotEquals.HasValue) - { - whereClauses.Add("(ParentIndexNumber<>@ParentIndexNumberNotEquals or ParentIndexNumber is null)"); - cmd.Parameters.Add(cmd, "@ParentIndexNumberNotEquals", DbType.Int32).Value = query.ParentIndexNumberNotEquals.Value; - } - if (query.MinEndDate.HasValue) - { - whereClauses.Add("EndDate>=@MinEndDate"); - cmd.Parameters.Add(cmd, "@MinEndDate", DbType.Date).Value = query.MinEndDate.Value; - } - - if (query.MaxEndDate.HasValue) - { - whereClauses.Add("EndDate<=@MaxEndDate"); - cmd.Parameters.Add(cmd, "@MaxEndDate", DbType.Date).Value = query.MaxEndDate.Value; - } - - if (query.MinStartDate.HasValue) - { - whereClauses.Add("StartDate>=@MinStartDate"); - cmd.Parameters.Add(cmd, "@MinStartDate", DbType.Date).Value = query.MinStartDate.Value; - } - - if (query.MaxStartDate.HasValue) - { - whereClauses.Add("StartDate<=@MaxStartDate"); - cmd.Parameters.Add(cmd, "@MaxStartDate", DbType.Date).Value = query.MaxStartDate.Value; - } - - if (query.MinPremiereDate.HasValue) - { - whereClauses.Add("PremiereDate>=@MinPremiereDate"); - cmd.Parameters.Add(cmd, "@MinPremiereDate", DbType.Date).Value = query.MinPremiereDate.Value; - } - if (query.MaxPremiereDate.HasValue) - { - whereClauses.Add("PremiereDate<=@MaxPremiereDate"); - cmd.Parameters.Add(cmd, "@MaxPremiereDate", DbType.Date).Value = query.MaxPremiereDate.Value; - } - - if (query.SourceTypes.Length == 1) - { - whereClauses.Add("SourceType=@SourceType"); - cmd.Parameters.Add(cmd, "@SourceType", DbType.String).Value = query.SourceTypes[0]; - } - else if (query.SourceTypes.Length > 1) - { - var inClause = string.Join(",", query.SourceTypes.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("SourceType in ({0})", inClause)); - } - - if (query.ExcludeSourceTypes.Length == 1) - { - whereClauses.Add("SourceType<>@SourceType"); - cmd.Parameters.Add(cmd, "@SourceType", DbType.String).Value = query.SourceTypes[0]; - } - else if (query.ExcludeSourceTypes.Length > 1) - { - var inClause = string.Join(",", query.ExcludeSourceTypes.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("SourceType not in ({0})", inClause)); - } - - if (query.TrailerTypes.Length > 0) - { - var clauses = new List<string>(); - var index = 0; - foreach (var type in query.TrailerTypes) - { - clauses.Add("TrailerTypes like @TrailerTypes" + index); - cmd.Parameters.Add(cmd, "@TrailerTypes" + index, DbType.String).Value = "%" + type + "%"; - index++; - } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; - whereClauses.Add(clause); - } - - if (query.IsAiring.HasValue) - { - if (query.IsAiring.Value) - { - whereClauses.Add("StartDate<=@MaxStartDate"); - cmd.Parameters.Add(cmd, "@MaxStartDate", DbType.Date).Value = DateTime.UtcNow; - - whereClauses.Add("EndDate>=@MinEndDate"); - cmd.Parameters.Add(cmd, "@MinEndDate", DbType.Date).Value = DateTime.UtcNow; - } - else - { - whereClauses.Add("(StartDate>@IsAiringDate OR EndDate < @IsAiringDate)"); - cmd.Parameters.Add(cmd, "@IsAiringDate", DbType.Date).Value = DateTime.UtcNow; - } - } - - if (query.PersonIds.Length > 0) - { - // Todo: improve without having to do this - query.Person = query.PersonIds.Select(i => RetrieveItem(new Guid(i))).Where(i => i != null).Select(i => i.Name).FirstOrDefault(); - } - - if (!string.IsNullOrWhiteSpace(query.Person)) - { - whereClauses.Add("Guid in (select ItemId from People where Name=@PersonName)"); - cmd.Parameters.Add(cmd, "@PersonName", DbType.String).Value = query.Person; - } - - if (!string.IsNullOrWhiteSpace(query.SlugName)) - { - whereClauses.Add("SlugName=@SlugName"); - cmd.Parameters.Add(cmd, "@SlugName", DbType.String).Value = query.SlugName; - } - - if (!string.IsNullOrWhiteSpace(query.MinSortName)) - { - whereClauses.Add("SortName>=@MinSortName"); - cmd.Parameters.Add(cmd, "@MinSortName", DbType.String).Value = query.MinSortName; - } - - if (!string.IsNullOrWhiteSpace(query.ExternalSeriesId)) - { - whereClauses.Add("ExternalSeriesId=@ExternalSeriesId"); - cmd.Parameters.Add(cmd, "@ExternalSeriesId", DbType.String).Value = query.ExternalSeriesId; - } - - if (!string.IsNullOrWhiteSpace(query.Name)) - { - whereClauses.Add("CleanName=@Name"); - cmd.Parameters.Add(cmd, "@Name", DbType.String).Value = GetCleanValue(query.Name); - } - - if (!string.IsNullOrWhiteSpace(query.NameContains)) - { - whereClauses.Add("CleanName like @NameContains"); - cmd.Parameters.Add(cmd, "@NameContains", DbType.String).Value = "%" + GetCleanValue(query.NameContains) + "%"; - } - if (!string.IsNullOrWhiteSpace(query.NameStartsWith)) - { - whereClauses.Add("SortName like @NameStartsWith"); - cmd.Parameters.Add(cmd, "@NameStartsWith", DbType.String).Value = query.NameStartsWith + "%"; - } - if (!string.IsNullOrWhiteSpace(query.NameStartsWithOrGreater)) - { - whereClauses.Add("SortName >= @NameStartsWithOrGreater"); - // lowercase this because SortName is stored as lowercase - cmd.Parameters.Add(cmd, "@NameStartsWithOrGreater", DbType.String).Value = query.NameStartsWithOrGreater.ToLower(); - } - if (!string.IsNullOrWhiteSpace(query.NameLessThan)) - { - whereClauses.Add("SortName < @NameLessThan"); - // lowercase this because SortName is stored as lowercase - cmd.Parameters.Add(cmd, "@NameLessThan", DbType.String).Value = query.NameLessThan.ToLower(); - } - - if (query.ImageTypes.Length > 0 && _config.Configuration.SchemaVersion >= 87) - { - var requiredImageIndex = 0; - - foreach (var requiredImage in query.ImageTypes) - { - var paramName = "@RequiredImageType" + requiredImageIndex; - whereClauses.Add("(select path from images where ItemId=Guid and ImageType=" + paramName + " limit 1) not null"); - cmd.Parameters.Add(cmd, paramName, DbType.Int32).Value = (int)requiredImage; - requiredImageIndex++; - } - } - - if (query.IsLiked.HasValue) - { - if (query.IsLiked.Value) - { - whereClauses.Add("rating>=@UserRating"); - cmd.Parameters.Add(cmd, "@UserRating", DbType.Double).Value = UserItemData.MinLikeValue; - } - else - { - whereClauses.Add("(rating is null or rating<@UserRating)"); - cmd.Parameters.Add(cmd, "@UserRating", DbType.Double).Value = UserItemData.MinLikeValue; - } - } - - if (query.IsFavoriteOrLiked.HasValue) - { - if (query.IsFavoriteOrLiked.Value) - { - whereClauses.Add("IsFavorite=@IsFavoriteOrLiked"); - } - else - { - whereClauses.Add("(IsFavorite is null or IsFavorite=@IsFavoriteOrLiked)"); - } - cmd.Parameters.Add(cmd, "@IsFavoriteOrLiked", DbType.Boolean).Value = query.IsFavoriteOrLiked.Value; - } - - if (query.IsFavorite.HasValue) - { - if (query.IsFavorite.Value) - { - whereClauses.Add("IsFavorite=@IsFavorite"); - } - else - { - whereClauses.Add("(IsFavorite is null or IsFavorite=@IsFavorite)"); - } - cmd.Parameters.Add(cmd, "@IsFavorite", DbType.Boolean).Value = query.IsFavorite.Value; - } - - if (EnableJoinUserData(query)) - { - if (query.IsPlayed.HasValue) - { - if (query.IsPlayed.Value) - { - whereClauses.Add("(played=@IsPlayed)"); - } - else - { - whereClauses.Add("(played is null or played=@IsPlayed)"); - } - cmd.Parameters.Add(cmd, "@IsPlayed", DbType.Boolean).Value = query.IsPlayed.Value; - } - } - - if (query.IsResumable.HasValue) - { - if (query.IsResumable.Value) - { - whereClauses.Add("playbackPositionTicks > 0"); - } - else - { - whereClauses.Add("(playbackPositionTicks is null or playbackPositionTicks = 0)"); - } - } - - if (query.ArtistNames.Length > 0) - { - var clauses = new List<string>(); - var index = 0; - foreach (var artist in query.ArtistNames) - { - clauses.Add("@ArtistName" + index + " in (select CleanValue from itemvalues where ItemId=Guid and Type <= 1)"); - cmd.Parameters.Add(cmd, "@ArtistName" + index, DbType.String).Value = GetCleanValue(artist); - index++; - } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; - whereClauses.Add(clause); - } - - if (query.ExcludeArtistIds.Length > 0) - { - var clauses = new List<string>(); - var index = 0; - foreach (var artistId in query.ExcludeArtistIds) - { - var artistItem = RetrieveItem(new Guid(artistId)); - if (artistItem != null) - { - clauses.Add("@ExcludeArtistName" + index + " not in (select CleanValue from itemvalues where ItemId=Guid and Type <= 1)"); - cmd.Parameters.Add(cmd, "@ExcludeArtistName" + index, DbType.String).Value = GetCleanValue(artistItem.Name); - index++; - } - } - var clause = "(" + string.Join(" AND ", clauses.ToArray()) + ")"; - whereClauses.Add(clause); - } - - if (query.GenreIds.Length > 0) - { - // Todo: improve without having to do this - query.Genres = query.GenreIds.Select(i => RetrieveItem(new Guid(i))).Where(i => i != null).Select(i => i.Name).ToArray(); - } - - if (query.Genres.Length > 0) - { - var clauses = new List<string>(); - var index = 0; - foreach (var item in query.Genres) - { - clauses.Add("@Genre" + index + " in (select CleanValue from itemvalues where ItemId=Guid and Type=2)"); - cmd.Parameters.Add(cmd, "@Genre" + index, DbType.String).Value = GetCleanValue(item); - index++; - } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; - whereClauses.Add(clause); - } - - if (query.Tags.Length > 0) - { - var clauses = new List<string>(); - var index = 0; - foreach (var item in query.Tags) - { - clauses.Add("@Tag" + index + " in (select CleanValue from itemvalues where ItemId=Guid and Type=4)"); - cmd.Parameters.Add(cmd, "@Tag" + index, DbType.String).Value = GetCleanValue(item); - index++; - } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; - whereClauses.Add(clause); - } - - if (query.StudioIds.Length > 0) - { - // Todo: improve without having to do this - query.Studios = query.StudioIds.Select(i => RetrieveItem(new Guid(i))).Where(i => i != null).Select(i => i.Name).ToArray(); - } - - if (query.Studios.Length > 0) - { - var clauses = new List<string>(); - var index = 0; - foreach (var item in query.Studios) - { - clauses.Add("@Studio" + index + " in (select CleanValue from itemvalues where ItemId=Guid and Type=3)"); - cmd.Parameters.Add(cmd, "@Studio" + index, DbType.String).Value = GetCleanValue(item); - index++; - } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; - whereClauses.Add(clause); - } - - if (query.Keywords.Length > 0) - { - var clauses = new List<string>(); - var index = 0; - foreach (var item in query.Keywords) - { - clauses.Add("@Keyword" + index + " in (select CleanValue from itemvalues where ItemId=Guid and Type=5)"); - cmd.Parameters.Add(cmd, "@Keyword" + index, DbType.String).Value = GetCleanValue(item); - index++; - } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; - whereClauses.Add(clause); - } - - if (query.OfficialRatings.Length > 0) - { - var clauses = new List<string>(); - var index = 0; - foreach (var item in query.OfficialRatings) - { - clauses.Add("OfficialRating=@OfficialRating" + index); - cmd.Parameters.Add(cmd, "@OfficialRating" + index, DbType.String).Value = item; - index++; - } - var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; - whereClauses.Add(clause); - } - - if (query.MinParentalRating.HasValue) - { - whereClauses.Add("InheritedParentalRatingValue<=@MinParentalRating"); - cmd.Parameters.Add(cmd, "@MinParentalRating", DbType.Int32).Value = query.MinParentalRating.Value; - } - - if (query.MaxParentalRating.HasValue) - { - whereClauses.Add("InheritedParentalRatingValue<=@MaxParentalRating"); - cmd.Parameters.Add(cmd, "@MaxParentalRating", DbType.Int32).Value = query.MaxParentalRating.Value; - } - - if (query.HasParentalRating.HasValue) - { - if (query.HasParentalRating.Value) - { - whereClauses.Add("InheritedParentalRatingValue > 0"); - } - else - { - whereClauses.Add("InheritedParentalRatingValue = 0"); - } - } - - if (query.HasOverview.HasValue) - { - if (query.HasOverview.Value) - { - whereClauses.Add("(Overview not null AND Overview<>'')"); - } - else - { - whereClauses.Add("(Overview is null OR Overview='')"); - } - } - - if (query.HasDeadParentId.HasValue) - { - if (query.HasDeadParentId.Value) - { - whereClauses.Add("ParentId NOT NULL AND ParentId NOT IN (select guid from TypedBaseItems)"); - } - } - - if (query.Years.Length == 1) - { - whereClauses.Add("ProductionYear=@Years"); - cmd.Parameters.Add(cmd, "@Years", DbType.Int32).Value = query.Years[0].ToString(); - } - else if (query.Years.Length > 1) - { - var val = string.Join(",", query.Years.ToArray()); - - whereClauses.Add("ProductionYear in (" + val + ")"); - } - - if (query.LocationTypes.Length == 1) - { - if (query.LocationTypes[0] == LocationType.Virtual && _config.Configuration.SchemaVersion >= 90) - { - query.IsVirtualItem = true; - } - else - { - whereClauses.Add("LocationType=@LocationType"); - cmd.Parameters.Add(cmd, "@LocationType", DbType.String).Value = query.LocationTypes[0].ToString(); - } - } - else if (query.LocationTypes.Length > 1) - { - var val = string.Join(",", query.LocationTypes.Select(i => "'" + i + "'").ToArray()); - - 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"); - cmd.Parameters.Add(cmd, "@ExcludeLocationTypes", DbType.String).Value = 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) - { - if (_config.Configuration.SchemaVersion >= 90) - { - whereClauses.Add("IsVirtualItem=@IsVirtualItem"); - cmd.Parameters.Add(cmd, "@IsVirtualItem", DbType.Boolean).Value = query.IsVirtualItem.Value; - } - else if (!query.IsVirtualItem.Value) - { - whereClauses.Add("LocationType<>'Virtual'"); - } - } - if (query.IsSpecialSeason.HasValue) - { - if (query.IsSpecialSeason.Value) - { - whereClauses.Add("IndexNumber = 0"); - } - else - { - whereClauses.Add("IndexNumber <> 0"); - } - } - if (query.IsUnaired.HasValue) - { - if (query.IsUnaired.Value) - { - whereClauses.Add("PremiereDate >= DATETIME('now')"); - } - else - { - whereClauses.Add("PremiereDate < DATETIME('now')"); - } - } - if (query.IsMissing.HasValue && _config.Configuration.SchemaVersion >= 90) - { - if (query.IsMissing.Value) - { - whereClauses.Add("(IsVirtualItem=1 AND PremiereDate < DATETIME('now'))"); - } - else - { - whereClauses.Add("(IsVirtualItem=0 OR PremiereDate >= DATETIME('now'))"); - } - } - if (query.IsVirtualUnaired.HasValue && _config.Configuration.SchemaVersion >= 90) - { - if (query.IsVirtualUnaired.Value) - { - whereClauses.Add("(IsVirtualItem=1 AND PremiereDate >= DATETIME('now'))"); - } - else - { - whereClauses.Add("(IsVirtualItem=0 OR PremiereDate < DATETIME('now'))"); - } - } - if (query.MediaTypes.Length == 1) - { - whereClauses.Add("MediaType=@MediaTypes"); - cmd.Parameters.Add(cmd, "@MediaTypes", DbType.String).Value = query.MediaTypes[0]; - } - if (query.MediaTypes.Length > 1) - { - var val = string.Join(",", query.MediaTypes.Select(i => "'" + i + "'").ToArray()); - - whereClauses.Add("MediaType in (" + val + ")"); - } - if (query.ItemIds.Length > 0) - { - var includeIds = new List<string>(); - - var index = 0; - foreach (var id in query.ItemIds) - { - includeIds.Add("Guid = @IncludeId" + index); - cmd.Parameters.Add(cmd, "@IncludeId" + index, DbType.Guid).Value = new Guid(id); - index++; - } - - whereClauses.Add(string.Join(" OR ", includeIds.ToArray())); - } - if (query.ExcludeItemIds.Length > 0) - { - var excludeIds = new List<string>(); - - var index = 0; - foreach (var id in query.ExcludeItemIds) - { - excludeIds.Add("Guid <> @ExcludeId" + index); - cmd.Parameters.Add(cmd, "@ExcludeId" + index, DbType.Guid).Value = new Guid(id); - index++; - } - - whereClauses.Add(string.Join(" AND ", excludeIds.ToArray())); - } - - if (query.ExcludeProviderIds.Count > 0) - { - var excludeIds = new List<string>(); - - var index = 0; - foreach (var pair in query.ExcludeProviderIds) - { - if (string.Equals(pair.Key, MetadataProviders.TmdbCollection.ToString(), StringComparison.OrdinalIgnoreCase)) - { - continue; - } - - var paramName = "@ExcludeProviderId" + index; - excludeIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")"); - cmd.Parameters.Add(cmd, paramName, DbType.String).Value = pair.Value; - index++; - } - - whereClauses.Add(string.Join(" AND ", excludeIds.ToArray())); - } - - if (query.HasImdbId.HasValue) - { - var fn = query.HasImdbId.Value ? "<>" : "="; - whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Imdb'), '') " + fn + " '')"); - } - - if (query.HasTmdbId.HasValue) - { - var fn = query.HasTmdbId.Value ? "<>" : "="; - whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Tmdb'), '') " + fn + " '')"); - } - - if (query.HasTvdbId.HasValue) - { - var fn = query.HasTvdbId.Value ? "<>" : "="; - whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Tvdb'), '') " + fn + " '')"); - } - - if (query.AlbumNames.Length > 0) - { - var clause = "("; - - var index = 0; - foreach (var name in query.AlbumNames) - { - if (index > 0) - { - clause += " OR "; - } - clause += "Album=@AlbumName" + index; - cmd.Parameters.Add(cmd, "@AlbumName" + index, DbType.String).Value = name; - index++; - } - - clause += ")"; - whereClauses.Add(clause); - } - if (query.HasThemeSong.HasValue) - { - if (query.HasThemeSong.Value) - { - whereClauses.Add("ThemeSongIds not null"); - } - else - { - whereClauses.Add("ThemeSongIds is null"); - } - } - if (query.HasThemeVideo.HasValue) - { - if (query.HasThemeVideo.Value) - { - whereClauses.Add("ThemeVideoIds not null"); - } - else - { - whereClauses.Add("ThemeVideoIds is null"); - } - } - - //var enableItemsByName = query.IncludeItemsByName ?? query.IncludeItemTypes.Length > 0; - var enableItemsByName = query.IncludeItemsByName ?? false; - - if (query.TopParentIds.Length == 1) - { - if (enableItemsByName) - { - whereClauses.Add("(TopParentId=@TopParentId or IsItemByName=@IsItemByName)"); - cmd.Parameters.Add(cmd, "@IsItemByName", DbType.Boolean).Value = true; - } - else - { - whereClauses.Add("(TopParentId=@TopParentId)"); - } - cmd.Parameters.Add(cmd, "@TopParentId", DbType.String).Value = query.TopParentIds[0]; - } - if (query.TopParentIds.Length > 1) - { - var val = string.Join(",", query.TopParentIds.Select(i => "'" + i + "'").ToArray()); - - if (enableItemsByName) - { - whereClauses.Add("(IsItemByName=@IsItemByName or TopParentId in (" + val + "))"); - cmd.Parameters.Add(cmd, "@IsItemByName", DbType.Boolean).Value = true; - } - else - { - whereClauses.Add("(TopParentId in (" + val + "))"); - } - } - - if (query.AncestorIds.Length == 1) - { - whereClauses.Add("Guid in (select itemId from AncestorIds where AncestorId=@AncestorId)"); - cmd.Parameters.Add(cmd, "@AncestorId", DbType.Guid).Value = new Guid(query.AncestorIds[0]); - } - if (query.AncestorIds.Length > 1) - { - var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + new Guid(i).ToString("N") + "'").ToArray()); - whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorIdText in ({0}))", inClause)); - } - if (!string.IsNullOrWhiteSpace(query.AncestorWithPresentationUniqueKey)) - { - var inClause = "select guid from TypedBaseItems where PresentationUniqueKey=@AncestorWithPresentationUniqueKey"; - whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorId in ({0}))", inClause)); - cmd.Parameters.Add(cmd, "@AncestorWithPresentationUniqueKey", DbType.String).Value = query.AncestorWithPresentationUniqueKey; - } - - if (query.BlockUnratedItems.Length == 1) - { - whereClauses.Add("(InheritedParentalRatingValue > 0 or UnratedType <> @UnratedType)"); - cmd.Parameters.Add(cmd, "@UnratedType", DbType.String).Value = query.BlockUnratedItems[0].ToString(); - } - if (query.BlockUnratedItems.Length > 1) - { - var inClause = string.Join(",", query.BlockUnratedItems.Select(i => "'" + i.ToString() + "'").ToArray()); - whereClauses.Add(string.Format("(InheritedParentalRatingValue > 0 or UnratedType not in ({0}))", inClause)); - } - - var excludeTagIndex = 0; - foreach (var excludeTag in query.ExcludeTags) - { - whereClauses.Add("(Tags is null OR Tags not like @excludeTag" + excludeTagIndex + ")"); - cmd.Parameters.Add(cmd, "@excludeTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%"; - excludeTagIndex++; - } - - excludeTagIndex = 0; - foreach (var excludeTag in query.ExcludeInheritedTags) - { - whereClauses.Add("(InheritedTags is null OR InheritedTags not like @excludeInheritedTag" + excludeTagIndex + ")"); - cmd.Parameters.Add(cmd, "@excludeInheritedTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%"; - excludeTagIndex++; - } - - return whereClauses; - } - - private string GetCleanValue(string value) - { - if (string.IsNullOrWhiteSpace(value)) - { - return value; - } - - return value.RemoveDiacritics().ToLower(); - } - - private bool EnableGroupByPresentationUniqueKey(InternalItemsQuery query) - { - if (!query.GroupByPresentationUniqueKey) - { - return false; - } - - if (!string.IsNullOrWhiteSpace(query.PresentationUniqueKey)) - { - return false; - } - - if (query.User == null) - { - return false; - } - - if (query.IncludeItemTypes.Length == 0) - { - return true; - } - - var types = new[] { - typeof(Episode).Name, - typeof(Video).Name , - typeof(Movie).Name , - typeof(MusicVideo).Name , - typeof(Series).Name , - typeof(Season).Name }; - - if (types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase))) - { - return true; - } - - return false; - } - - private static readonly Type[] KnownTypes = - { - typeof(LiveTvProgram), - typeof(LiveTvChannel), - typeof(LiveTvVideoRecording), - typeof(LiveTvAudioRecording), - typeof(Series), - typeof(Audio), - typeof(MusicAlbum), - typeof(MusicArtist), - typeof(MusicGenre), - typeof(MusicVideo), - typeof(Movie), - typeof(Playlist), - typeof(AudioPodcast), - typeof(Trailer), - typeof(BoxSet), - typeof(Episode), - typeof(Season), - typeof(Series), - typeof(Book), - typeof(CollectionFolder), - typeof(Folder), - typeof(Game), - typeof(GameGenre), - typeof(GameSystem), - typeof(Genre), - typeof(Person), - typeof(Photo), - typeof(PhotoAlbum), - typeof(Studio), - typeof(UserRootFolder), - typeof(UserView), - typeof(Video), - typeof(Year), - typeof(Channel), - typeof(AggregateFolder) - }; - - public async Task UpdateInheritedValues(CancellationToken cancellationToken) - { - await UpdateInheritedTags(cancellationToken).ConfigureAwait(false); - } - - private async Task UpdateInheritedTags(CancellationToken cancellationToken) - { - var newValues = new List<Tuple<Guid, string>>(); - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select Guid,InheritedTags,(select group_concat(Tags, '|') from TypedBaseItems where (guid=outer.guid) OR (guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid))) as NewInheritedTags from typedbaseitems as Outer where NewInheritedTags <> InheritedTags"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - var id = reader.GetGuid(0); - string value = reader.IsDBNull(2) ? null : reader.GetString(2); - - newValues.Add(new Tuple<Guid, string>(id, value)); - } - } - } - - Logger.Debug("UpdateInheritedTags - {0} rows", newValues.Count); - if (newValues.Count == 0) - { - return; - } - - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try - { - transaction = _connection.BeginTransaction(); - - foreach (var item in newValues) - { - _updateInheritedTagsCommand.GetParameter(0).Value = item.Item1; - _updateInheritedTagsCommand.GetParameter(1).Value = item.Item2; - - _updateInheritedTagsCommand.Transaction = transaction; - _updateInheritedTagsCommand.ExecuteNonQuery(); - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Error running query:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - - WriteLock.Release(); - } - } - - private static Dictionary<string, string[]> GetTypeMapDictionary() - { - var dict = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase); - - foreach (var t in KnownTypes) - { - dict[t.Name] = new[] { t.FullName }; - } - - dict["Recording"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName }; - dict["Program"] = new[] { typeof(LiveTvProgram).FullName }; - dict["TvChannel"] = new[] { typeof(LiveTvChannel).FullName }; - - return dict; - } - - // Not crazy about having this all the way down here, but at least it's in one place - readonly Dictionary<string, string[]> _types = GetTypeMapDictionary(); - - private IEnumerable<string> MapIncludeItemTypes(string value) - { - string[] result; - if (_types.TryGetValue(value, out result)) - { - return result; - } - - return new[] { value }; - } - - public async Task DeleteItem(Guid id, CancellationToken cancellationToken) - { - if (id == Guid.Empty) - { - throw new ArgumentNullException("id"); - } - - CheckDisposed(); - - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try - { - transaction = _connection.BeginTransaction(); - - // Delete people - _deletePeopleCommand.GetParameter(0).Value = id; - _deletePeopleCommand.Transaction = transaction; - _deletePeopleCommand.ExecuteNonQuery(); - - // Delete chapters - _deleteChaptersCommand.GetParameter(0).Value = id; - _deleteChaptersCommand.Transaction = transaction; - _deleteChaptersCommand.ExecuteNonQuery(); - - // Delete media streams - _deleteStreamsCommand.GetParameter(0).Value = id; - _deleteStreamsCommand.Transaction = transaction; - _deleteStreamsCommand.ExecuteNonQuery(); - - // Delete ancestors - _deleteAncestorsCommand.GetParameter(0).Value = id; - _deleteAncestorsCommand.Transaction = transaction; - _deleteAncestorsCommand.ExecuteNonQuery(); - - // Delete user data keys - _deleteUserDataKeysCommand.GetParameter(0).Value = id; - _deleteUserDataKeysCommand.Transaction = transaction; - _deleteUserDataKeysCommand.ExecuteNonQuery(); - - // Delete item values - _deleteItemValuesCommand.GetParameter(0).Value = id; - _deleteItemValuesCommand.Transaction = transaction; - _deleteItemValuesCommand.ExecuteNonQuery(); - - // Delete provider ids - _deleteProviderIdsCommand.GetParameter(0).Value = id; - _deleteProviderIdsCommand.Transaction = transaction; - _deleteProviderIdsCommand.ExecuteNonQuery(); - - // Delete images - _deleteImagesCommand.GetParameter(0).Value = id; - _deleteImagesCommand.Transaction = transaction; - _deleteImagesCommand.ExecuteNonQuery(); - - // Delete the item - _deleteItemCommand.GetParameter(0).Value = id; - _deleteItemCommand.Transaction = transaction; - _deleteItemCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save children:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - - WriteLock.Release(); - } - } - - public List<string> GetPeopleNames(InternalPeopleQuery query) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - CheckDisposed(); - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select Distinct Name from People"; - - var whereClauses = GetPeopleWhereClauses(query, cmd); - - if (whereClauses.Count > 0) - { - cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); - } - - cmd.CommandText += " order by ListOrder"; - - var list = new List<string>(); - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - list.Add(reader.GetString(0)); - } - } - - return list; - } - } - - public List<PersonInfo> GetPeople(InternalPeopleQuery query) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - CheckDisposed(); - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select ItemId, Name, Role, PersonType, SortOrder from People"; - - var whereClauses = GetPeopleWhereClauses(query, cmd); - - if (whereClauses.Count > 0) - { - cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); - } - - cmd.CommandText += " order by ListOrder"; - - var list = new List<PersonInfo>(); - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - list.Add(GetPerson(reader)); - } - } - - return list; - } - } - - private List<string> GetPeopleWhereClauses(InternalPeopleQuery query, IDbCommand cmd) - { - var whereClauses = new List<string>(); - - if (query.ItemId != Guid.Empty) - { - whereClauses.Add("ItemId=@ItemId"); - cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = query.ItemId; - } - if (query.AppearsInItemId != Guid.Empty) - { - whereClauses.Add("Name in (Select Name from People where ItemId=@AppearsInItemId)"); - cmd.Parameters.Add(cmd, "@AppearsInItemId", DbType.Guid).Value = query.AppearsInItemId; - } - if (query.PersonTypes.Count == 1) - { - whereClauses.Add("PersonType=@PersonType"); - cmd.Parameters.Add(cmd, "@PersonType", DbType.String).Value = query.PersonTypes[0]; - } - if (query.PersonTypes.Count > 1) - { - var val = string.Join(",", query.PersonTypes.Select(i => "'" + i + "'").ToArray()); - - whereClauses.Add("PersonType in (" + val + ")"); - } - if (query.ExcludePersonTypes.Count == 1) - { - whereClauses.Add("PersonType<>@PersonType"); - cmd.Parameters.Add(cmd, "@PersonType", DbType.String).Value = query.ExcludePersonTypes[0]; - } - if (query.ExcludePersonTypes.Count > 1) - { - var val = string.Join(",", query.ExcludePersonTypes.Select(i => "'" + i + "'").ToArray()); - - whereClauses.Add("PersonType not in (" + val + ")"); - } - if (query.MaxListOrder.HasValue) - { - whereClauses.Add("ListOrder<=@MaxListOrder"); - cmd.Parameters.Add(cmd, "@MaxListOrder", DbType.Int32).Value = query.MaxListOrder.Value; - } - if (!string.IsNullOrWhiteSpace(query.NameContains)) - { - whereClauses.Add("Name like @NameContains"); - cmd.Parameters.Add(cmd, "@NameContains", DbType.String).Value = "%" + query.NameContains + "%"; - } - if (query.SourceTypes.Length == 1) - { - whereClauses.Add("(select sourcetype from typedbaseitems where guid=ItemId) = @SourceTypes"); - cmd.Parameters.Add(cmd, "@SourceTypes", DbType.String).Value = query.SourceTypes[0].ToString(); - } - - return whereClauses; - } - - private void UpdateAncestors(Guid itemId, List<Guid> ancestorIds, IDbTransaction transaction) - { - if (itemId == Guid.Empty) - { - throw new ArgumentNullException("itemId"); - } - - if (ancestorIds == null) - { - throw new ArgumentNullException("ancestorIds"); - } - - CheckDisposed(); - - // First delete - _deleteAncestorsCommand.GetParameter(0).Value = itemId; - _deleteAncestorsCommand.Transaction = transaction; - - _deleteAncestorsCommand.ExecuteNonQuery(); - - foreach (var ancestorId in ancestorIds) - { - _saveAncestorCommand.GetParameter(0).Value = itemId; - _saveAncestorCommand.GetParameter(1).Value = ancestorId; - _saveAncestorCommand.GetParameter(2).Value = ancestorId.ToString("N"); - - _saveAncestorCommand.Transaction = transaction; - - _saveAncestorCommand.ExecuteNonQuery(); - } - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetAllArtists(InternalItemsQuery query) - { - return GetItemValues(query, new[] { 0, 1 }, typeof(MusicArtist).FullName); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query) - { - return GetItemValues(query, new[] { 0 }, typeof(MusicArtist).FullName); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query) - { - return GetItemValues(query, new[] { 1 }, typeof(MusicArtist).FullName); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetStudios(InternalItemsQuery query) - { - return GetItemValues(query, new[] { 3 }, typeof(Studio).FullName); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query) - { - return GetItemValues(query, new[] { 2 }, typeof(Genre).FullName); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query) - { - return GetItemValues(query, new[] { 2 }, typeof(GameGenre).FullName); - } - - public QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query) - { - return GetItemValues(query, new[] { 2 }, typeof(MusicGenre).FullName); - } - - public List<string> GetStudioNames() - { - return GetItemValueNames(new[] { 3 }, new List<string>(), new List<string>()); - } - - public List<string> GetAllArtistNames() - { - return GetItemValueNames(new[] { 0, 1 }, new List<string>(), new List<string>()); - } - - public List<string> GetMusicGenreNames() - { - return GetItemValueNames(new[] { 2 }, new List<string> { "Audio", "MusicVideo", "MusicAlbum", "MusicArtist" }, new List<string>()); - } - - public List<string> GetGameGenreNames() - { - return GetItemValueNames(new[] { 2 }, new List<string> { "Game" }, new List<string>()); - } - - public List<string> GetGenreNames() - { - return GetItemValueNames(new[] { 2 }, new List<string>(), new List<string> { "Audio", "MusicVideo", "MusicAlbum", "MusicArtist", "Game", "GameSystem" }); - } - - private List<string> GetItemValueNames(int[] itemValueTypes, List<string> withItemTypes, List<string> excludeItemTypes) - { - CheckDisposed(); - - withItemTypes = withItemTypes.SelectMany(MapIncludeItemTypes).ToList(); - excludeItemTypes = excludeItemTypes.SelectMany(MapIncludeItemTypes).ToList(); - - var now = DateTime.UtcNow; - - var typeClause = itemValueTypes.Length == 1 ? - ("Type=" + itemValueTypes[0].ToString(CultureInfo.InvariantCulture)) : - ("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToArray()) + ")"); - - var list = new List<string>(); - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "Select Value From ItemValues where " + typeClause; - - if (withItemTypes.Count > 0) - { - var typeString = string.Join(",", withItemTypes.Select(i => "'" + i + "'").ToArray()); - cmd.CommandText += " AND ItemId In (select guid from typedbaseitems where type in (" + typeString + "))"; - } - if (excludeItemTypes.Count > 0) - { - var typeString = string.Join(",", excludeItemTypes.Select(i => "'" + i + "'").ToArray()); - cmd.CommandText += " AND ItemId not In (select guid from typedbaseitems where type in (" + typeString + "))"; - } - - cmd.CommandText += " Group By CleanValue"; - - var commandBehavior = CommandBehavior.SequentialAccess | CommandBehavior.SingleResult; - - using (var reader = cmd.ExecuteReader(commandBehavior)) - { - LogQueryTime("GetItemValueNames", cmd, now); - - while (reader.Read()) - { - if (!reader.IsDBNull(0)) - { - list.Add(reader.GetString(0)); - } - } - } - - } - - return list; - } - - private QueryResult<Tuple<BaseItem, ItemCounts>> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - if (!query.Limit.HasValue) - { - query.EnableTotalRecordCount = false; - } - - CheckDisposed(); - - var now = DateTime.UtcNow; - - var typeClause = itemValueTypes.Length == 1 ? - ("Type=" + itemValueTypes[0].ToString(CultureInfo.InvariantCulture)) : - ("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToArray()) + ")"); - - using (var cmd = _connection.CreateCommand()) - { - var itemCountColumns = new List<Tuple<string, string>>(); - - var typesToCount = query.IncludeItemTypes.ToList(); - - if (typesToCount.Count > 0) - { - var itemCountColumnQuery = "select group_concat(type, '|')" + GetFromText("B"); - - var typeSubQuery = new InternalItemsQuery(query.User) - { - ExcludeItemTypes = query.ExcludeItemTypes, - IncludeItemTypes = query.IncludeItemTypes, - MediaTypes = query.MediaTypes, - AncestorIds = query.AncestorIds, - ExcludeItemIds = query.ExcludeItemIds, - ItemIds = query.ItemIds, - TopParentIds = query.TopParentIds, - ParentId = query.ParentId, - IsPlayed = query.IsPlayed - }; - var whereClauses = GetWhereClauses(typeSubQuery, cmd, "itemTypes"); - - whereClauses.Add("guid in (select ItemId from ItemValues where ItemValues.CleanValue=A.CleanName AND " + typeClause + ")"); - - var typeWhereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - itemCountColumnQuery += typeWhereText; - - //itemCountColumnQuery += ")"; - - itemCountColumns.Add(new Tuple<string, string>("itemTypes", "(" + itemCountColumnQuery + ") as itemTypes")); - } - - var columns = _retriveItemColumns.ToList(); - columns.AddRange(itemCountColumns.Select(i => i.Item2).ToArray()); - - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, columns.ToArray(), cmd)) + GetFromText(); - cmd.CommandText += GetJoinUserDataText(query); - - var innerQuery = new InternalItemsQuery(query.User) - { - ExcludeItemTypes = query.ExcludeItemTypes, - IncludeItemTypes = query.IncludeItemTypes, - MediaTypes = query.MediaTypes, - AncestorIds = query.AncestorIds, - ExcludeItemIds = query.ExcludeItemIds, - ItemIds = query.ItemIds, - TopParentIds = query.TopParentIds, - ParentId = query.ParentId, - IsPlayed = query.IsPlayed - }; - - var innerWhereClauses = GetWhereClauses(innerQuery, cmd); - - var innerWhereText = innerWhereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", innerWhereClauses.ToArray()); - - var whereText = " where Type=@SelectType"; - - if (typesToCount.Count == 0) - { - whereText += " And CleanName In (Select CleanValue from ItemValues where " + typeClause + " AND ItemId in (select guid from TypedBaseItems" + innerWhereText + "))"; - } - else - { - //whereText += " And itemTypes not null"; - whereText += " And CleanName In (Select CleanValue from ItemValues where " + typeClause + " AND ItemId in (select guid from TypedBaseItems" + innerWhereText + "))"; - } - - var outerQuery = new InternalItemsQuery(query.User) - { - IsFavorite = query.IsFavorite, - IsFavoriteOrLiked = query.IsFavoriteOrLiked, - IsLiked = query.IsLiked, - IsLocked = query.IsLocked, - NameLessThan = query.NameLessThan, - NameStartsWith = query.NameStartsWith, - NameStartsWithOrGreater = query.NameStartsWithOrGreater, - AlbumArtistStartsWithOrGreater = query.AlbumArtistStartsWithOrGreater, - Tags = query.Tags, - OfficialRatings = query.OfficialRatings, - GenreIds = query.GenreIds, - Genres = query.Genres, - Years = query.Years - }; - - var outerWhereClauses = GetWhereClauses(outerQuery, cmd); - - whereText += outerWhereClauses.Count == 0 ? - string.Empty : - " AND " + string.Join(" AND ", outerWhereClauses.ToArray()); - //cmd.CommandText += GetGroupBy(query); - - cmd.CommandText += whereText; - cmd.CommandText += " group by PresentationUniqueKey"; - - cmd.Parameters.Add(cmd, "@SelectType", DbType.String).Value = returnType; - - if (EnableJoinUserData(query)) - { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; - } - - cmd.CommandText += " order by SortName"; - - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var offset = query.StartIndex ?? 0; - - if (query.Limit.HasValue || offset > 0) - { - cmd.CommandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture); - } - - if (offset > 0) - { - cmd.CommandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture); - } - } - - cmd.CommandText += ";"; - - var isReturningZeroItems = query.Limit.HasValue && query.Limit <= 0; - - if (isReturningZeroItems) - { - cmd.CommandText = ""; - } - - if (query.EnableTotalRecordCount) - { - cmd.CommandText += "select count (distinct PresentationUniqueKey)" + GetFromText(); - - cmd.CommandText += GetJoinUserDataText(query); - cmd.CommandText += whereText; - } - else - { - cmd.CommandText = cmd.CommandText.TrimEnd(';'); - } - - var list = new List<Tuple<BaseItem, ItemCounts>>(); - var count = 0; - - var commandBehavior = isReturningZeroItems || !query.EnableTotalRecordCount - ? (CommandBehavior.SequentialAccess | CommandBehavior.SingleResult) - : CommandBehavior.SequentialAccess; - - //Logger.Debug("GetItemValues: " + cmd.CommandText); - - using (var reader = cmd.ExecuteReader(commandBehavior)) - { - LogQueryTime("GetItemValues", cmd, now); - - if (isReturningZeroItems) - { - if (reader.Read()) - { - count = reader.GetInt32(0); - } - } - else - { - while (reader.Read()) - { - var item = GetItem(reader); - if (item != null) - { - var countStartColumn = columns.Count - 1; - - list.Add(new Tuple<BaseItem, ItemCounts>(item, GetItemCounts(reader, countStartColumn, typesToCount))); - } - } - - if (reader.NextResult() && reader.Read()) - { - count = reader.GetInt32(0); - } - } - } - - if (count == 0) - { - count = list.Count; - } - - return new QueryResult<Tuple<BaseItem, ItemCounts>> - { - Items = list.ToArray(), - TotalRecordCount = count - }; - - } - } - - private ItemCounts GetItemCounts(IDataReader reader, int countStartColumn, List<string> typesToCount) - { - var counts = new ItemCounts(); - - if (typesToCount.Count == 0) - { - return counts; - } - - var typeString = reader.IsDBNull(countStartColumn) ? null : reader.GetString(countStartColumn); - - if (string.IsNullOrWhiteSpace(typeString)) - { - return counts; - } - - var allTypes = typeString.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) - .ToLookup(i => i).ToList(); - - foreach (var type in allTypes) - { - var value = type.ToList().Count; - var typeName = type.Key; - - if (string.Equals(typeName, typeof(Series).FullName, StringComparison.OrdinalIgnoreCase)) - { - counts.SeriesCount = value; - } - else if (string.Equals(typeName, typeof(Episode).FullName, StringComparison.OrdinalIgnoreCase)) - { - counts.EpisodeCount = value; - } - else if (string.Equals(typeName, typeof(Movie).FullName, StringComparison.OrdinalIgnoreCase)) - { - counts.MovieCount = value; - } - else if (string.Equals(typeName, typeof(MusicAlbum).FullName, StringComparison.OrdinalIgnoreCase)) - { - counts.AlbumCount = value; - } - else if (string.Equals(typeName, typeof(MusicArtist).FullName, StringComparison.OrdinalIgnoreCase)) - { - counts.ArtistCount = value; - } - else if (string.Equals(typeName, typeof(Audio).FullName, StringComparison.OrdinalIgnoreCase)) - { - counts.SongCount = value; - } - else if (string.Equals(typeName, typeof(Game).FullName, StringComparison.OrdinalIgnoreCase)) - { - counts.GameCount = value; - } - else if (string.Equals(typeName, typeof(Trailer).FullName, StringComparison.OrdinalIgnoreCase)) - { - counts.TrailerCount = value; - } - counts.ItemCount += value; - } - - return counts; - } - - private List<Tuple<int, string>> GetItemValuesToSave(BaseItem item) - { - var list = new List<Tuple<int, string>>(); - - var hasArtist = item as IHasArtist; - if (hasArtist != null) - { - list.AddRange(hasArtist.Artists.Select(i => new Tuple<int, string>(0, i))); - } - - var hasAlbumArtist = item as IHasAlbumArtist; - if (hasAlbumArtist != null) - { - list.AddRange(hasAlbumArtist.AlbumArtists.Select(i => new Tuple<int, string>(1, i))); - } - - list.AddRange(item.Genres.Select(i => new Tuple<int, string>(2, i))); - list.AddRange(item.Studios.Select(i => new Tuple<int, string>(3, i))); - list.AddRange(item.Tags.Select(i => new Tuple<int, string>(4, i))); - list.AddRange(item.Keywords.Select(i => new Tuple<int, string>(5, i))); - - return list; - } - - private void UpdateImages(Guid itemId, List<ItemImageInfo> images, IDbTransaction transaction) - { - if (itemId == Guid.Empty) - { - throw new ArgumentNullException("itemId"); - } - - if (images == null) - { - throw new ArgumentNullException("images"); - } - - CheckDisposed(); - - // First delete - _deleteImagesCommand.GetParameter(0).Value = itemId; - _deleteImagesCommand.Transaction = transaction; - - _deleteImagesCommand.ExecuteNonQuery(); - - var index = 0; - foreach (var image in images) - { - if (string.IsNullOrWhiteSpace(image.Path)) - { - // Invalid - continue; - } - - _saveImagesCommand.GetParameter(0).Value = itemId; - _saveImagesCommand.GetParameter(1).Value = image.Type; - _saveImagesCommand.GetParameter(2).Value = image.Path; - - if (image.DateModified == default(DateTime)) - { - _saveImagesCommand.GetParameter(3).Value = null; - } - else - { - _saveImagesCommand.GetParameter(3).Value = image.DateModified; - } - - _saveImagesCommand.GetParameter(4).Value = image.IsPlaceholder; - _saveImagesCommand.GetParameter(5).Value = index; - - _saveImagesCommand.Transaction = transaction; - - _saveImagesCommand.ExecuteNonQuery(); - index++; - } - } - - private void UpdateProviderIds(Guid itemId, Dictionary<string, string> values, IDbTransaction transaction) - { - if (itemId == Guid.Empty) - { - throw new ArgumentNullException("itemId"); - } - - if (values == null) - { - throw new ArgumentNullException("values"); - } - - // Just in case there might be case-insensitive duplicates, strip them out now - var newValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - foreach (var pair in values) - { - newValues[pair.Key] = pair.Value; - } - - CheckDisposed(); - - // First delete - _deleteProviderIdsCommand.GetParameter(0).Value = itemId; - _deleteProviderIdsCommand.Transaction = transaction; - - _deleteProviderIdsCommand.ExecuteNonQuery(); - - foreach (var pair in newValues) - { - _saveProviderIdsCommand.GetParameter(0).Value = itemId; - _saveProviderIdsCommand.GetParameter(1).Value = pair.Key; - _saveProviderIdsCommand.GetParameter(2).Value = pair.Value; - _saveProviderIdsCommand.Transaction = transaction; - - _saveProviderIdsCommand.ExecuteNonQuery(); - } - } - - private void UpdateItemValues(Guid itemId, List<Tuple<int, string>> values, IDbTransaction transaction) - { - if (itemId == Guid.Empty) - { - throw new ArgumentNullException("itemId"); - } - - if (values == null) - { - throw new ArgumentNullException("keys"); - } - - CheckDisposed(); - - // First delete - _deleteItemValuesCommand.GetParameter(0).Value = itemId; - _deleteItemValuesCommand.Transaction = transaction; - - _deleteItemValuesCommand.ExecuteNonQuery(); - - foreach (var pair in values) - { - _saveItemValuesCommand.GetParameter(0).Value = itemId; - _saveItemValuesCommand.GetParameter(1).Value = pair.Item1; - _saveItemValuesCommand.GetParameter(2).Value = pair.Item2; - if (pair.Item2 == null) - { - _saveItemValuesCommand.GetParameter(3).Value = null; - } - else - { - _saveItemValuesCommand.GetParameter(3).Value = GetCleanValue(pair.Item2); - } - _saveItemValuesCommand.Transaction = transaction; - - _saveItemValuesCommand.ExecuteNonQuery(); - } - } - - private void UpdateUserDataKeys(Guid itemId, List<string> keys, IDbTransaction transaction) - { - if (itemId == Guid.Empty) - { - throw new ArgumentNullException("itemId"); - } - - if (keys == null) - { - throw new ArgumentNullException("keys"); - } - - CheckDisposed(); - - // First delete - _deleteUserDataKeysCommand.GetParameter(0).Value = itemId; - _deleteUserDataKeysCommand.Transaction = transaction; - - _deleteUserDataKeysCommand.ExecuteNonQuery(); - var index = 0; - - foreach (var key in keys) - { - _saveUserDataKeysCommand.GetParameter(0).Value = itemId; - _saveUserDataKeysCommand.GetParameter(1).Value = key; - _saveUserDataKeysCommand.GetParameter(2).Value = index; - index++; - _saveUserDataKeysCommand.Transaction = transaction; - - _saveUserDataKeysCommand.ExecuteNonQuery(); - } - } - - public async Task UpdatePeople(Guid itemId, List<PersonInfo> people) - { - if (itemId == Guid.Empty) - { - throw new ArgumentNullException("itemId"); - } - - if (people == null) - { - throw new ArgumentNullException("people"); - } - - CheckDisposed(); - - var cancellationToken = CancellationToken.None; - - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try - { - transaction = _connection.BeginTransaction(); - - // First delete - _deletePeopleCommand.GetParameter(0).Value = itemId; - _deletePeopleCommand.Transaction = transaction; - - _deletePeopleCommand.ExecuteNonQuery(); - - var listIndex = 0; - - foreach (var person in people) - { - cancellationToken.ThrowIfCancellationRequested(); - - _savePersonCommand.GetParameter(0).Value = itemId; - _savePersonCommand.GetParameter(1).Value = person.Name; - _savePersonCommand.GetParameter(2).Value = person.Role; - _savePersonCommand.GetParameter(3).Value = person.Type; - _savePersonCommand.GetParameter(4).Value = person.SortOrder; - _savePersonCommand.GetParameter(5).Value = listIndex; - - _savePersonCommand.Transaction = transaction; - - _savePersonCommand.ExecuteNonQuery(); - listIndex++; - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save people:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - - WriteLock.Release(); - } - } - - private PersonInfo GetPerson(IDataReader reader) - { - var item = new PersonInfo(); - - item.ItemId = reader.GetGuid(0); - item.Name = reader.GetString(1); - - if (!reader.IsDBNull(2)) - { - item.Role = reader.GetString(2); - } - - if (!reader.IsDBNull(3)) - { - item.Type = reader.GetString(3); - } - - if (!reader.IsDBNull(4)) - { - item.SortOrder = reader.GetInt32(4); - } - - return item; - } - - public IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query) - { - CheckDisposed(); - - if (query == null) - { - throw new ArgumentNullException("query"); - } - - var list = new List<MediaStream>(); - - using (var cmd = _connection.CreateCommand()) - { - var cmdText = "select " + string.Join(",", _mediaStreamSaveColumns) + " from mediastreams where"; - - cmdText += " ItemId=@ItemId"; - cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = query.ItemId; - - if (query.Type.HasValue) - { - cmdText += " AND StreamType=@StreamType"; - cmd.Parameters.Add(cmd, "@StreamType", DbType.String).Value = query.Type.Value.ToString(); - } - - if (query.Index.HasValue) - { - cmdText += " AND StreamIndex=@StreamIndex"; - cmd.Parameters.Add(cmd, "@StreamIndex", DbType.Int32).Value = query.Index.Value; - } - - cmdText += " order by StreamIndex ASC"; - - cmd.CommandText = cmdText; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - list.Add(GetMediaStream(reader)); - } - } - } - - return list; - } - - public async Task SaveMediaStreams(Guid id, List<MediaStream> streams, CancellationToken cancellationToken) - { - CheckDisposed(); - - if (id == Guid.Empty) - { - throw new ArgumentNullException("id"); - } - - if (streams == null) - { - throw new ArgumentNullException("streams"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try - { - transaction = _connection.BeginTransaction(); - - // First delete chapters - _deleteStreamsCommand.GetParameter(0).Value = id; - - _deleteStreamsCommand.Transaction = transaction; - - _deleteStreamsCommand.ExecuteNonQuery(); - - foreach (var stream in streams) - { - cancellationToken.ThrowIfCancellationRequested(); - - var index = 0; - - _saveStreamCommand.GetParameter(index++).Value = id; - _saveStreamCommand.GetParameter(index++).Value = stream.Index; - _saveStreamCommand.GetParameter(index++).Value = stream.Type.ToString(); - _saveStreamCommand.GetParameter(index++).Value = stream.Codec; - _saveStreamCommand.GetParameter(index++).Value = stream.Language; - _saveStreamCommand.GetParameter(index++).Value = stream.ChannelLayout; - _saveStreamCommand.GetParameter(index++).Value = stream.Profile; - _saveStreamCommand.GetParameter(index++).Value = stream.AspectRatio; - _saveStreamCommand.GetParameter(index++).Value = stream.Path; - - _saveStreamCommand.GetParameter(index++).Value = stream.IsInterlaced; - - _saveStreamCommand.GetParameter(index++).Value = stream.BitRate; - _saveStreamCommand.GetParameter(index++).Value = stream.Channels; - _saveStreamCommand.GetParameter(index++).Value = stream.SampleRate; - - _saveStreamCommand.GetParameter(index++).Value = stream.IsDefault; - _saveStreamCommand.GetParameter(index++).Value = stream.IsForced; - _saveStreamCommand.GetParameter(index++).Value = stream.IsExternal; - - _saveStreamCommand.GetParameter(index++).Value = stream.Width; - _saveStreamCommand.GetParameter(index++).Value = stream.Height; - _saveStreamCommand.GetParameter(index++).Value = stream.AverageFrameRate; - _saveStreamCommand.GetParameter(index++).Value = stream.RealFrameRate; - _saveStreamCommand.GetParameter(index++).Value = stream.Level; - _saveStreamCommand.GetParameter(index++).Value = stream.PixelFormat; - _saveStreamCommand.GetParameter(index++).Value = stream.BitDepth; - _saveStreamCommand.GetParameter(index++).Value = stream.IsAnamorphic; - _saveStreamCommand.GetParameter(index++).Value = stream.RefFrames; - - _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; - _saveStreamCommand.GetParameter(index++).Value = stream.Comment; - _saveStreamCommand.GetParameter(index++).Value = stream.NalLengthSize; - _saveStreamCommand.GetParameter(index++).Value = stream.IsAVC; - _saveStreamCommand.GetParameter(index++).Value = stream.Title; - - _saveStreamCommand.GetParameter(index++).Value = stream.TimeBase; - _saveStreamCommand.GetParameter(index++).Value = stream.CodecTimeBase; - - _saveStreamCommand.Transaction = transaction; - _saveStreamCommand.ExecuteNonQuery(); - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save media streams:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - - WriteLock.Release(); - } - } - - /// <summary> - /// Gets the chapter. - /// </summary> - /// <param name="reader">The reader.</param> - /// <returns>ChapterInfo.</returns> - private MediaStream GetMediaStream(IDataReader reader) - { - var item = new MediaStream - { - Index = reader.GetInt32(1) - }; - - item.Type = (MediaStreamType)Enum.Parse(typeof(MediaStreamType), reader.GetString(2), true); - - if (!reader.IsDBNull(3)) - { - item.Codec = reader.GetString(3); - } - - if (!reader.IsDBNull(4)) - { - item.Language = reader.GetString(4); - } - - if (!reader.IsDBNull(5)) - { - item.ChannelLayout = reader.GetString(5); - } - - if (!reader.IsDBNull(6)) - { - item.Profile = reader.GetString(6); - } - - if (!reader.IsDBNull(7)) - { - item.AspectRatio = reader.GetString(7); - } - - if (!reader.IsDBNull(8)) - { - item.Path = reader.GetString(8); - } - - item.IsInterlaced = reader.GetBoolean(9); - - if (!reader.IsDBNull(10)) - { - item.BitRate = reader.GetInt32(10); - } - - if (!reader.IsDBNull(11)) - { - item.Channels = reader.GetInt32(11); - } - - if (!reader.IsDBNull(12)) - { - item.SampleRate = reader.GetInt32(12); - } - - item.IsDefault = reader.GetBoolean(13); - item.IsForced = reader.GetBoolean(14); - item.IsExternal = reader.GetBoolean(15); - - if (!reader.IsDBNull(16)) - { - item.Width = reader.GetInt32(16); - } - - if (!reader.IsDBNull(17)) - { - item.Height = reader.GetInt32(17); - } - - if (!reader.IsDBNull(18)) - { - item.AverageFrameRate = reader.GetFloat(18); - } - - if (!reader.IsDBNull(19)) - { - item.RealFrameRate = reader.GetFloat(19); - } - - if (!reader.IsDBNull(20)) - { - item.Level = reader.GetFloat(20); - } - - if (!reader.IsDBNull(21)) - { - item.PixelFormat = reader.GetString(21); - } - - if (!reader.IsDBNull(22)) - { - item.BitDepth = reader.GetInt32(22); - } - - if (!reader.IsDBNull(23)) - { - item.IsAnamorphic = reader.GetBoolean(23); - } - - if (!reader.IsDBNull(24)) - { - item.RefFrames = reader.GetInt32(24); - } - - if (!reader.IsDBNull(25)) - { - item.CodecTag = reader.GetString(25); - } - - if (!reader.IsDBNull(26)) - { - item.Comment = reader.GetString(26); - } - - if (!reader.IsDBNull(27)) - { - item.NalLengthSize = reader.GetString(27); - } - - if (!reader.IsDBNull(28)) - { - item.IsAVC = reader.GetBoolean(28); - } - - if (!reader.IsDBNull(29)) - { - item.Title = reader.GetString(29); - } - - if (!reader.IsDBNull(30)) - { - item.TimeBase = reader.GetString(30); - } - - if (!reader.IsDBNull(31)) - { - item.CodecTimeBase = reader.GetString(31); - } - - return item; - } - - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs deleted file mode 100644 index 62d9e76347..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs +++ /dev/null @@ -1,453 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Data; -using System.Globalization; -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - public class SqliteUserDataRepository : BaseSqliteRepository, IUserDataRepository - { - private IDbConnection _connection; - - public SqliteUserDataRepository(ILogManager logManager, IApplicationPaths appPaths, IDbConnector connector) : base(logManager, connector) - { - DbFilePath = Path.Combine(appPaths.DataPath, "userdata_v2.db"); - } - - protected override bool EnableConnectionPooling - { - get { return false; } - } - - /// <summary> - /// Gets the name of the repository - /// </summary> - /// <value>The name.</value> - public string Name - { - get - { - return "SQLite"; - } - } - - protected override async Task<IDbConnection> CreateConnection(bool isReadOnly = false) - { - var connection = await DbConnector.Connect(DbFilePath, false, false, 10000).ConfigureAwait(false); - - connection.RunQueries(new[] - { - "pragma temp_store = memory" - - }, Logger); - - return connection; - } - - /// <summary> - /// Opens the connection to the database - /// </summary> - /// <returns>Task.</returns> - public async Task Initialize(IDbConnection connection, SemaphoreSlim writeLock) - { - WriteLock.Dispose(); - WriteLock = writeLock; - _connection = connection; - - string[] queries = { - - "create table if not exists UserDataDb.userdata (key nvarchar, userId GUID, rating float null, played bit, playCount int, isFavorite bit, playbackPositionTicks bigint, lastPlayedDate datetime null)", - - "drop index if exists UserDataDb.idx_userdata", - "drop index if exists UserDataDb.idx_userdata1", - "drop index if exists UserDataDb.idx_userdata2", - "drop index if exists UserDataDb.userdataindex1", - - "create unique index if not exists UserDataDb.userdataindex on userdata (key, userId)", - "create index if not exists UserDataDb.userdataindex2 on userdata (key, userId, played)", - "create index if not exists UserDataDb.userdataindex3 on userdata (key, userId, playbackPositionTicks)", - "create index if not exists UserDataDb.userdataindex4 on userdata (key, userId, isFavorite)", - - //pragmas - "pragma temp_store = memory", - - "pragma shrink_memory" - }; - - _connection.RunQueries(queries, Logger); - - _connection.AddColumn(Logger, "userdata", "AudioStreamIndex", "int"); - _connection.AddColumn(Logger, "userdata", "SubtitleStreamIndex", "int"); - } - - /// <summary> - /// Saves the user data. - /// </summary> - /// <param name="userId">The user id.</param> - /// <param name="key">The key.</param> - /// <param name="userData">The user data.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">userData - /// or - /// cancellationToken - /// or - /// userId - /// or - /// userDataId</exception> - public Task SaveUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken) - { - if (userData == null) - { - throw new ArgumentNullException("userData"); - } - if (userId == Guid.Empty) - { - throw new ArgumentNullException("userId"); - } - if (string.IsNullOrEmpty(key)) - { - throw new ArgumentNullException("key"); - } - - return PersistUserData(userId, key, userData, cancellationToken); - } - - public Task SaveAllUserData(Guid userId, IEnumerable<UserItemData> userData, CancellationToken cancellationToken) - { - if (userData == null) - { - throw new ArgumentNullException("userData"); - } - if (userId == Guid.Empty) - { - throw new ArgumentNullException("userId"); - } - - return PersistAllUserData(userId, userData, cancellationToken); - } - - /// <summary> - /// Persists the user data. - /// </summary> - /// <param name="userId">The user id.</param> - /// <param name="key">The key.</param> - /// <param name="userData">The user data.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task PersistUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try - { - transaction = _connection.BeginTransaction(); - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"; - - cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userData.Rating; - cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userData.Played; - cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userData.PlayCount; - cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userData.IsFavorite; - cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userData.PlaybackPositionTicks; - cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userData.LastPlayedDate; - cmd.Parameters.Add(cmd, "@AudioStreamIndex", DbType.Int32).Value = userData.AudioStreamIndex; - cmd.Parameters.Add(cmd, "@SubtitleStreamIndex", DbType.Int32).Value = userData.SubtitleStreamIndex; - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save user data:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - - WriteLock.Release(); - } - } - - /// <summary> - /// Persist all user data for the specified user - /// </summary> - /// <param name="userId"></param> - /// <param name="userData"></param> - /// <param name="cancellationToken"></param> - /// <returns></returns> - private async Task PersistAllUserData(Guid userId, IEnumerable<UserItemData> userData, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try - { - transaction = _connection.BeginTransaction(); - - foreach (var userItemData in userData) - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"; - - cmd.Parameters.Add(cmd, "@key", DbType.String).Value = userItemData.Key; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userItemData.Rating; - cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userItemData.Played; - cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userItemData.PlayCount; - cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userItemData.IsFavorite; - cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userItemData.PlaybackPositionTicks; - cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userItemData.LastPlayedDate; - cmd.Parameters.Add(cmd, "@AudioStreamIndex", DbType.Int32).Value = userItemData.AudioStreamIndex; - cmd.Parameters.Add(cmd, "@SubtitleStreamIndex", DbType.Int32).Value = userItemData.SubtitleStreamIndex; - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); - } - - cancellationToken.ThrowIfCancellationRequested(); - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save user data:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - - WriteLock.Release(); - } - } - - /// <summary> - /// Gets the user data. - /// </summary> - /// <param name="userId">The user id.</param> - /// <param name="key">The key.</param> - /// <returns>Task{UserItemData}.</returns> - /// <exception cref="System.ArgumentNullException"> - /// userId - /// or - /// key - /// </exception> - public UserItemData GetUserData(Guid userId, string key) - { - if (userId == Guid.Empty) - { - throw new ArgumentNullException("userId"); - } - if (string.IsNullOrEmpty(key)) - { - throw new ArgumentNullException("key"); - } - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where key = @key and userId=@userId"; - - cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) - { - return ReadRow(reader); - } - } - - return null; - } - } - - public UserItemData GetUserData(Guid userId, List<string> keys) - { - if (userId == Guid.Empty) - { - throw new ArgumentNullException("userId"); - } - if (keys == null) - { - throw new ArgumentNullException("keys"); - } - - using (var cmd = _connection.CreateCommand()) - { - var index = 0; - var userdataKeys = new List<string>(); - var builder = new StringBuilder(); - foreach (var key in keys) - { - var paramName = "@Key" + index; - userdataKeys.Add("Key =" + paramName); - cmd.Parameters.Add(cmd, paramName, DbType.String).Value = key; - builder.Append(" WHEN Key=" + paramName + " THEN " + index); - index++; - break; - } - - var keyText = string.Join(" OR ", userdataKeys.ToArray()); - - cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId AND (" + keyText + ") "; - - cmd.CommandText += " ORDER BY (Case " + builder + " Else " + keys.Count.ToString(CultureInfo.InvariantCulture) + " End )"; - cmd.CommandText += " LIMIT 1"; - - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) - { - return ReadRow(reader); - } - } - - return null; - } - } - - /// <summary> - /// Return all user-data associated with the given user - /// </summary> - /// <param name="userId"></param> - /// <returns></returns> - public IEnumerable<UserItemData> GetAllUserData(Guid userId) - { - if (userId == Guid.Empty) - { - throw new ArgumentNullException("userId"); - } - - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId"; - - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - yield return ReadRow(reader); - } - } - } - } - - /// <summary> - /// Read a row from the specified reader into the provided userData object - /// </summary> - /// <param name="reader"></param> - private UserItemData ReadRow(IDataReader reader) - { - var userData = new UserItemData(); - - userData.Key = reader.GetString(0); - userData.UserId = reader.GetGuid(1); - - if (!reader.IsDBNull(2)) - { - userData.Rating = reader.GetDouble(2); - } - - userData.Played = reader.GetBoolean(3); - userData.PlayCount = reader.GetInt32(4); - userData.IsFavorite = reader.GetBoolean(5); - userData.PlaybackPositionTicks = reader.GetInt64(6); - - if (!reader.IsDBNull(7)) - { - userData.LastPlayedDate = reader.GetDateTime(7).ToUniversalTime(); - } - - if (!reader.IsDBNull(8)) - { - userData.AudioStreamIndex = reader.GetInt32(8); - } - - if (!reader.IsDBNull(9)) - { - userData.SubtitleStreamIndex = reader.GetInt32(9); - } - - return userData; - } - - protected override void Dispose(bool dispose) - { - // handled by library database - } - - protected override void CloseConnection() - { - // handled by library database - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs deleted file mode 100644 index 31fa78806c..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs +++ /dev/null @@ -1,237 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Data; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - /// <summary> - /// Class SQLiteUserRepository - /// </summary> - public class SqliteUserRepository : BaseSqliteRepository, IUserRepository - { - private readonly IJsonSerializer _jsonSerializer; - private readonly IMemoryStreamProvider _memoryStreamProvider; - - public SqliteUserRepository(ILogManager logManager, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer, IDbConnector dbConnector, IMemoryStreamProvider memoryStreamProvider) : base(logManager, dbConnector) - { - _jsonSerializer = jsonSerializer; - _memoryStreamProvider = memoryStreamProvider; - - DbFilePath = Path.Combine(appPaths.DataPath, "users.db"); - } - - /// <summary> - /// Gets the name of the repository - /// </summary> - /// <value>The name.</value> - public string Name - { - get - { - return "SQLite"; - } - } - - /// <summary> - /// Opens the connection to the database - /// </summary> - /// <returns>Task.</returns> - public async Task Initialize() - { - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - string[] queries = { - - "create table if not exists users (guid GUID primary key, data BLOB)", - "create index if not exists idx_users on users(guid)", - "create table if not exists schema_version (table_name primary key, version)", - - "pragma shrink_memory" - }; - - connection.RunQueries(queries, Logger); - } - } - - /// <summary> - /// Save a user in the repo - /// </summary> - /// <param name="user">The user.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">user</exception> - public async Task SaveUser(User user, CancellationToken cancellationToken) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - var serialized = _jsonSerializer.SerializeToBytes(user, _memoryStreamProvider); - - cancellationToken.ThrowIfCancellationRequested(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "replace into users (guid, data) values (@1, @2)"; - cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = user.Id; - cmd.Parameters.Add(cmd, "@2", DbType.Binary).Value = serialized; - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save user:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - - /// <summary> - /// Retrieve all users from the database - /// </summary> - /// <returns>IEnumerable{User}.</returns> - public IEnumerable<User> RetrieveAllUsers() - { - var list = new List<User>(); - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select guid,data from users"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - var id = reader.GetGuid(0); - - using (var stream = reader.GetMemoryStream(1, _memoryStreamProvider)) - { - var user = _jsonSerializer.DeserializeFromStream<User>(stream); - user.Id = id; - list.Add(user); - } - } - } - } - } - - return list; - } - - /// <summary> - /// Deletes the user. - /// </summary> - /// <param name="user">The user.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">user</exception> - public async Task DeleteUser(User user, CancellationToken cancellationToken) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "delete from users where guid=@guid"; - - cmd.Parameters.Add(cmd, "@guid", DbType.Guid).Value = user.Id; - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to delete user:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/TypeMapper.cs b/MediaBrowser.Server.Implementations/Persistence/TypeMapper.cs deleted file mode 100644 index 2de02d8171..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/TypeMapper.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Linq; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - /// <summary> - /// Class TypeMapper - /// </summary> - public class TypeMapper - { - /// <summary> - /// This holds all the types in the running assemblies so that we can de-serialize properly when we don't have strong types - /// </summary> - private readonly ConcurrentDictionary<string, Type> _typeMap = new ConcurrentDictionary<string, Type>(); - - /// <summary> - /// Gets the type. - /// </summary> - /// <param name="typeName">Name of the type.</param> - /// <returns>Type.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public Type GetType(string typeName) - { - if (string.IsNullOrEmpty(typeName)) - { - throw new ArgumentNullException(); - } - - return _typeMap.GetOrAdd(typeName, LookupType); - } - - /// <summary> - /// Lookups the type. - /// </summary> - /// <param name="typeName">Name of the type.</param> - /// <returns>Type.</returns> - private Type LookupType(string typeName) - { - return AppDomain - .CurrentDomain - .GetAssemblies() - .Select(a => a.GetType(typeName, false)) - .FirstOrDefault(t => t != null); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs deleted file mode 100644 index 22d7ba3bec..0000000000 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ /dev/null @@ -1,359 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Playlists; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Model.Configuration; - -namespace MediaBrowser.Server.Implementations.Photos -{ - public abstract class BaseDynamicImageProvider<T> : IHasItemChangeMonitor, IForcedProvider, ICustomMetadataProvider<T>, IHasOrder - where T : IHasMetadata - { - protected IFileSystem FileSystem { get; private set; } - protected IProviderManager ProviderManager { get; private set; } - protected IApplicationPaths ApplicationPaths { get; private set; } - protected IImageProcessor ImageProcessor { get; set; } - - protected BaseDynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) - { - ApplicationPaths = applicationPaths; - ProviderManager = providerManager; - FileSystem = fileSystem; - ImageProcessor = imageProcessor; - } - - protected virtual bool Supports(IHasImages item) - { - return true; - } - - public virtual IEnumerable<ImageType> GetSupportedImages(IHasImages item) - { - return new List<ImageType> - { - ImageType.Primary, - ImageType.Thumb - }; - } - - private IEnumerable<ImageType> GetEnabledImages(IHasImages item) - { - //var options = ProviderManager.GetMetadataOptions(item); - - return GetSupportedImages(item); - //return GetSupportedImages(item).Where(i => IsEnabled(options, i, item)).ToList(); - } - - private bool IsEnabled(MetadataOptions options, ImageType type, IHasImages item) - { - if (type == ImageType.Backdrop) - { - if (item.LockedFields.Contains(MetadataFields.Backdrops)) - { - return false; - } - } - else if (type == ImageType.Screenshot) - { - if (item.LockedFields.Contains(MetadataFields.Screenshots)) - { - return false; - } - } - else - { - if (item.LockedFields.Contains(MetadataFields.Images)) - { - return false; - } - } - - return options.IsEnabled(type); - } - - public async Task<ItemUpdateType> FetchAsync(T item, MetadataRefreshOptions options, CancellationToken cancellationToken) - { - if (!Supports(item)) - { - return ItemUpdateType.None; - } - - var updateType = ItemUpdateType.None; - var supportedImages = GetEnabledImages(item).ToList(); - - if (supportedImages.Contains(ImageType.Primary)) - { - var primaryResult = await FetchAsync(item, ImageType.Primary, options, cancellationToken).ConfigureAwait(false); - updateType = updateType | primaryResult; - } - - if (supportedImages.Contains(ImageType.Thumb)) - { - var thumbResult = await FetchAsync(item, ImageType.Thumb, options, cancellationToken).ConfigureAwait(false); - updateType = updateType | thumbResult; - } - - return updateType; - } - - protected async Task<ItemUpdateType> FetchAsync(IHasImages item, ImageType imageType, MetadataRefreshOptions options, CancellationToken cancellationToken) - { - var image = item.GetImageInfo(imageType, 0); - - if (image != null) - { - if (!image.IsLocalFile) - { - return ItemUpdateType.None; - } - - if (!FileSystem.ContainsSubPath(item.GetInternalMetadataPath(), image.Path)) - { - return ItemUpdateType.None; - } - } - - var items = await GetItemsWithImages(item).ConfigureAwait(false); - - return await FetchToFileInternal(item, items, imageType, cancellationToken).ConfigureAwait(false); - } - - protected async Task<ItemUpdateType> FetchToFileInternal(IHasImages item, - List<BaseItem> itemsWithImages, - ImageType imageType, - CancellationToken cancellationToken) - { - var outputPathWithoutExtension = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid().ToString("N")); - FileSystem.CreateDirectory(Path.GetDirectoryName(outputPathWithoutExtension)); - string outputPath = await CreateImage(item, itemsWithImages, outputPathWithoutExtension, imageType, 0).ConfigureAwait(false); - - if (string.IsNullOrWhiteSpace(outputPath)) - { - return ItemUpdateType.None; - } - - await ProviderManager.SaveImage(item, outputPath, "image/png", imageType, null, false, cancellationToken).ConfigureAwait(false); - - return ItemUpdateType.ImageUpdate; - } - - protected abstract Task<List<BaseItem>> GetItemsWithImages(IHasImages item); - - protected Task<string> CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath) - { - return CreateCollage(primaryItem, items, outputPath, 640, 360); - } - - protected virtual IEnumerable<string> GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable<BaseItem> items) - { - return items - .Select(i => - { - var image = i.GetImageInfo(ImageType.Primary, 0); - - if (image != null && image.IsLocalFile) - { - return image.Path; - } - image = i.GetImageInfo(ImageType.Thumb, 0); - - if (image != null && image.IsLocalFile) - { - return image.Path; - } - return null; - }) - .Where(i => !string.IsNullOrWhiteSpace(i)); - } - - protected Task<string> CreatePosterCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath) - { - return CreateCollage(primaryItem, items, outputPath, 400, 600); - } - - protected Task<string> CreateSquareCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath) - { - return CreateCollage(primaryItem, items, outputPath, 600, 600); - } - - protected Task<string> CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height) - { - return CreateCollage(primaryItem, items, outputPath, width, height); - } - - private async Task<string> CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height) - { - FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); - - var options = new ImageCollageOptions - { - Height = height, - Width = width, - OutputPath = outputPath, - InputPaths = GetStripCollageImagePaths(primaryItem, items).ToArray() - }; - - if (options.InputPaths.Length == 0) - { - return null; - } - - if (!ImageProcessor.SupportsImageCollageCreation) - { - return null; - } - - await ImageProcessor.CreateImageCollage(options).ConfigureAwait(false); - return outputPath; - } - - public string Name - { - get { return "Dynamic Image Provider"; } - } - - protected virtual async Task<string> CreateImage(IHasImages item, - List<BaseItem> itemsWithImages, - string outputPathWithoutExtension, - ImageType imageType, - int imageIndex) - { - if (itemsWithImages.Count == 0) - { - return null; - } - - string outputPath = Path.ChangeExtension(outputPathWithoutExtension, ".png"); - - if (imageType == ImageType.Thumb) - { - return await CreateThumbCollage(item, itemsWithImages, outputPath).ConfigureAwait(false); - } - - if (imageType == ImageType.Primary) - { - if (item is UserView) - { - return await CreateSquareCollage(item, itemsWithImages, outputPath).ConfigureAwait(false); - } - if (item is Playlist || item is MusicGenre) - { - return await CreateSquareCollage(item, itemsWithImages, outputPath).ConfigureAwait(false); - } - return await CreatePosterCollage(item, itemsWithImages, outputPath).ConfigureAwait(false); - } - - throw new ArgumentException("Unexpected image type"); - } - - protected virtual int MaxImageAgeDays - { - get { return 7; } - } - - public bool HasChanged(IHasMetadata item, IDirectoryService directoryServicee) - { - if (!Supports(item)) - { - return false; - } - - var supportedImages = GetEnabledImages(item).ToList(); - - if (supportedImages.Contains(ImageType.Primary) && HasChanged(item, ImageType.Primary)) - { - return true; - } - if (supportedImages.Contains(ImageType.Thumb) && HasChanged(item, ImageType.Thumb)) - { - return true; - } - - return false; - } - - protected bool HasChanged(IHasImages item, ImageType type) - { - var image = item.GetImageInfo(type, 0); - - if (image != null) - { - if (!image.IsLocalFile) - { - return false; - } - - if (!FileSystem.ContainsSubPath(item.GetInternalMetadataPath(), image.Path)) - { - return false; - } - - var age = DateTime.UtcNow - image.DateModified; - if (age.TotalDays <= MaxImageAgeDays) - { - return false; - } - } - - return true; - } - - protected List<BaseItem> GetFinalItems(List<BaseItem> items) - { - return GetFinalItems(items, 4); - } - - protected virtual List<BaseItem> GetFinalItems(List<BaseItem> items, int limit) - { - // Rotate the images once every x days - var random = DateTime.Now.DayOfYear % MaxImageAgeDays; - - return items - .OrderBy(i => (random + string.Empty + items.IndexOf(i)).GetMD5()) - .Take(limit) - .OrderBy(i => i.Name) - .ToList(); - } - - public int Order - { - get - { - // Run before the default image provider which will download placeholders - return 0; - } - } - - protected async Task<string> CreateSingleImage(List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType) - { - var image = itemsWithImages - .Where(i => i.HasImage(imageType) && i.GetImageInfo(imageType, 0).IsLocalFile && Path.HasExtension(i.GetImagePath(imageType))) - .Select(i => i.GetImagePath(imageType)) - .FirstOrDefault(); - - if (string.IsNullOrWhiteSpace(image)) - { - return null; - } - - var ext = Path.GetExtension(image); - - var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ext); - File.Copy(image, outputPath); - - return outputPath; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs deleted file mode 100644 index fafb2f2685..0000000000 --- a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Model.Entities; - -namespace MediaBrowser.Server.Implementations.Photos -{ - public class PhotoAlbumImageProvider : BaseDynamicImageProvider<PhotoAlbum> - { - public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) - : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - } - - protected override Task<List<BaseItem>> GetItemsWithImages(IHasImages item) - { - var photoAlbum = (PhotoAlbum)item; - var items = GetFinalItems(photoAlbum.Children.ToList()); - - return Task.FromResult(items); - } - - protected override Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) - { - return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs index 63dfe20b2f..07773d846b 100644 --- a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs +++ b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs @@ -1,12 +1,13 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Playlists; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; -using CommonIO; -using MediaBrowser.Model.Querying; using System.Threading.Tasks; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Playlists; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Querying; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Server.Implementations.Playlists { @@ -27,6 +28,7 @@ namespace MediaBrowser.Server.Implementations.Playlists return base.GetEligibleChildrenForRecursiveChildren(user).OfType<Playlist>(); } + [IgnoreDataMember] public override bool IsHidden { get @@ -35,9 +37,10 @@ namespace MediaBrowser.Server.Implementations.Playlists } } + [IgnoreDataMember] public override string CollectionType { - get { return Model.Entities.CollectionType.Playlists; } + get { return MediaBrowser.Model.Entities.CollectionType.Playlists; } } protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query) @@ -46,29 +49,5 @@ namespace MediaBrowser.Server.Implementations.Playlists return base.GetItemsInternal(query); } } - - public class PlaylistsDynamicFolder : IVirtualFolderCreator - { - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - - public PlaylistsDynamicFolder(IApplicationPaths appPaths, IFileSystem fileSystem) - { - _appPaths = appPaths; - _fileSystem = fileSystem; - } - - public BasePluginFolder GetFolder() - { - var path = Path.Combine(_appPaths.DataPath, "playlists"); - - _fileSystem.CreateDirectory(path); - - return new PlaylistsFolder - { - Path = path - }; - } - } } diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs deleted file mode 100644 index 5b234d0c67..0000000000 --- a/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs +++ /dev/null @@ -1,102 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Playlists; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Server.Implementations.Photos; -using MoreLinq; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Playlists -{ - public class PlaylistImageProvider : BaseDynamicImageProvider<Playlist> - { - public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - } - - protected override Task<List<BaseItem>> GetItemsWithImages(IHasImages item) - { - var playlist = (Playlist)item; - - var items = playlist.GetManageableItems() - .Select(i => - { - var subItem = i.Item2; - - var episode = subItem as Episode; - - if (episode != null) - { - var series = episode.Series; - if (series != null && series.HasImage(ImageType.Primary)) - { - return series; - } - } - - if (subItem.HasImage(ImageType.Primary)) - { - return subItem; - } - - var parent = subItem.GetParent(); - - if (parent != null && parent.HasImage(ImageType.Primary)) - { - if (parent is MusicAlbum) - { - return parent; - } - } - - return null; - }) - .Where(i => i != null) - .DistinctBy(i => i.Id) - .ToList(); - - return Task.FromResult(GetFinalItems(items)); - } - } - - public class MusicGenreImageProvider : BaseDynamicImageProvider<MusicGenre> - { - private readonly ILibraryManager _libraryManager; - - public MusicGenreImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - _libraryManager = libraryManager; - } - - protected override Task<List<BaseItem>> GetItemsWithImages(IHasImages item) - { - var items = _libraryManager.GetItemList(new InternalItemsQuery - { - Genres = new[] { item.Name }, - IncludeItemTypes = new[] { typeof(MusicAlbum).Name, typeof(MusicVideo).Name, typeof(Audio).Name }, - SortBy = new[] { ItemSortBy.Random }, - Limit = 4, - Recursive = true, - ImageTypes = new[] { ImageType.Primary } - - }).ToList(); - - return Task.FromResult(GetFinalItems(items)); - } - - //protected override Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) - //{ - // return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary); - //} - } - -} diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs deleted file mode 100644 index ba1559bd03..0000000000 --- a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs +++ /dev/null @@ -1,273 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Playlists; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Playlists; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Playlists -{ - public class PlaylistManager : IPlaylistManager - { - private readonly ILibraryManager _libraryManager; - private readonly IFileSystem _fileSystem; - private readonly ILibraryMonitor _iLibraryMonitor; - private readonly ILogger _logger; - private readonly IUserManager _userManager; - private readonly IProviderManager _providerManager; - - public PlaylistManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor, ILogger logger, IUserManager userManager, IProviderManager providerManager) - { - _libraryManager = libraryManager; - _fileSystem = fileSystem; - _iLibraryMonitor = iLibraryMonitor; - _logger = logger; - _userManager = userManager; - _providerManager = providerManager; - } - - public IEnumerable<Playlist> GetPlaylists(string userId) - { - var user = _userManager.GetUserById(userId); - - return GetPlaylistsFolder(userId).GetChildren(user, true).OfType<Playlist>(); - } - - public async Task<PlaylistCreationResult> CreatePlaylist(PlaylistCreationRequest options) - { - var name = options.Name; - - var folderName = _fileSystem.GetValidFilename(name) + " [playlist]"; - - var parentFolder = GetPlaylistsFolder(null); - - if (parentFolder == null) - { - throw new ArgumentException(); - } - - if (string.IsNullOrWhiteSpace(options.MediaType)) - { - foreach (var itemId in options.ItemIdList) - { - var item = _libraryManager.GetItemById(itemId); - - if (item == null) - { - throw new ArgumentException("No item exists with the supplied Id"); - } - - if (!string.IsNullOrWhiteSpace(item.MediaType)) - { - options.MediaType = item.MediaType; - } - else if (item is MusicArtist || item is MusicAlbum || item is MusicGenre) - { - options.MediaType = MediaType.Audio; - } - else if (item is Genre) - { - options.MediaType = MediaType.Video; - } - else - { - var folder = item as Folder; - if (folder != null) - { - options.MediaType = folder.GetRecursiveChildren(i => !i.IsFolder && i.SupportsAddingToPlaylist) - .Select(i => i.MediaType) - .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); - } - } - - if (!string.IsNullOrWhiteSpace(options.MediaType)) - { - break; - } - } - } - - if (string.IsNullOrWhiteSpace(options.MediaType)) - { - throw new ArgumentException("A playlist media type is required."); - } - - var user = _userManager.GetUserById(options.UserId); - - var path = Path.Combine(parentFolder.Path, folderName); - path = GetTargetPath(path); - - _iLibraryMonitor.ReportFileSystemChangeBeginning(path); - - try - { - _fileSystem.CreateDirectory(path); - - var playlist = new Playlist - { - Name = name, - Path = path - }; - - playlist.Shares.Add(new Share - { - UserId = options.UserId, - CanEdit = true - }); - - playlist.SetMediaType(options.MediaType); - - await parentFolder.AddChild(playlist, CancellationToken.None).ConfigureAwait(false); - - await playlist.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) { ForceSave = true }, CancellationToken.None) - .ConfigureAwait(false); - - if (options.ItemIdList.Count > 0) - { - await AddToPlaylistInternal(playlist.Id.ToString("N"), options.ItemIdList, user); - } - - return new PlaylistCreationResult - { - Id = playlist.Id.ToString("N") - }; - } - finally - { - // Refresh handled internally - _iLibraryMonitor.ReportFileSystemChangeComplete(path, false); - } - } - - private string GetTargetPath(string path) - { - while (_fileSystem.DirectoryExists(path)) - { - path += "1"; - } - - return path; - } - - private Task<IEnumerable<BaseItem>> GetPlaylistItems(IEnumerable<string> itemIds, string playlistMediaType, User user) - { - var items = itemIds.Select(i => _libraryManager.GetItemById(i)).Where(i => i != null); - - return Playlist.GetPlaylistItems(playlistMediaType, items, user); - } - - public Task AddToPlaylist(string playlistId, IEnumerable<string> itemIds, string userId) - { - var user = string.IsNullOrWhiteSpace(userId) ? null : _userManager.GetUserById(userId); - - return AddToPlaylistInternal(playlistId, itemIds, user); - } - - private async Task AddToPlaylistInternal(string playlistId, IEnumerable<string> itemIds, User user) - { - var playlist = _libraryManager.GetItemById(playlistId) as Playlist; - - if (playlist == null) - { - throw new ArgumentException("No Playlist exists with the supplied Id"); - } - - var list = new List<LinkedChild>(); - - var items = (await GetPlaylistItems(itemIds, playlist.MediaType, user).ConfigureAwait(false)) - .Where(i => i.SupportsAddingToPlaylist) - .ToList(); - - foreach (var item in items) - { - list.Add(LinkedChild.Create(item)); - } - - playlist.LinkedChildren.AddRange(list); - - await playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - - _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem) - { - ForceSave = true - }); - } - - public async Task RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds) - { - var playlist = _libraryManager.GetItemById(playlistId) as Playlist; - - if (playlist == null) - { - throw new ArgumentException("No Playlist exists with the supplied Id"); - } - - var children = playlist.GetManageableItems().ToList(); - - var idList = entryIds.ToList(); - - var removals = children.Where(i => idList.Contains(i.Item1.Id)); - - playlist.LinkedChildren = children.Except(removals) - .Select(i => i.Item1) - .ToList(); - - await playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - - _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem) - { - ForceSave = true - }); - } - - public async Task MoveItem(string playlistId, string entryId, int newIndex) - { - var playlist = _libraryManager.GetItemById(playlistId) as Playlist; - - if (playlist == null) - { - throw new ArgumentException("No Playlist exists with the supplied Id"); - } - - var children = playlist.GetManageableItems().ToList(); - - var oldIndex = children.FindIndex(i => string.Equals(entryId, i.Item1.Id, StringComparison.OrdinalIgnoreCase)); - - if (oldIndex == newIndex) - { - return; - } - - var item = playlist.LinkedChildren[oldIndex]; - - playlist.LinkedChildren.Remove(item); - - if (newIndex >= playlist.LinkedChildren.Count) - { - playlist.LinkedChildren.Add(item); - } - else - { - playlist.LinkedChildren.Insert(newIndex, item); - } - - await playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - } - - public Folder GetPlaylistsFolder(string userId) - { - return _libraryManager.RootFolder.Children.OfType<PlaylistsFolder>() - .FirstOrDefault() ?? _libraryManager.GetUserRootFolder().Children.OfType<PlaylistsFolder>() - .FirstOrDefault(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs deleted file mode 100644 index 607a043a64..0000000000 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs +++ /dev/null @@ -1,197 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Model.Entities; - -namespace MediaBrowser.Server.Implementations.ScheduledTasks -{ - /// <summary> - /// Class ChapterImagesTask - /// </summary> - class ChapterImagesTask : IScheduledTask - { - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - - /// <summary> - /// The current new item timer - /// </summary> - /// <value>The new item timer.</value> - private Timer NewItemTimer { get; set; } - - private readonly IItemRepository _itemRepo; - - private readonly IApplicationPaths _appPaths; - - private readonly IEncodingManager _encodingManager; - private readonly IFileSystem _fileSystem; - - /// <summary> - /// Initializes a new instance of the <see cref="ChapterImagesTask" /> class. - /// </summary> - /// <param name="logManager">The log manager.</param> - /// <param name="libraryManager">The library manager.</param> - /// <param name="itemRepo">The item repo.</param> - public ChapterImagesTask(ILogManager logManager, ILibraryManager libraryManager, IItemRepository itemRepo, IApplicationPaths appPaths, IEncodingManager encodingManager, IFileSystem fileSystem) - { - _logger = logManager.GetLogger(GetType().Name); - _libraryManager = libraryManager; - _itemRepo = itemRepo; - _appPaths = appPaths; - _encodingManager = encodingManager; - _fileSystem = fileSystem; - } - - /// <summary> - /// Creates the triggers that define when the task will run - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - return new ITaskTrigger[] - { - new DailyTrigger - { - TimeOfDay = TimeSpan.FromHours(1), - TaskOptions = new TaskExecutionOptions - { - MaxRuntimeMs = Convert.ToInt32(TimeSpan.FromHours(4).TotalMilliseconds) - } - } - }; - } - - /// <summary> - /// Returns the task to be executed - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - var videos = _libraryManager.GetItemList(new InternalItemsQuery - { - MediaTypes = new[] { MediaType.Video }, - IsFolder = false, - Recursive = true - }) - .OfType<Video>() - .ToList(); - - var numComplete = 0; - - var failHistoryPath = Path.Combine(_appPaths.CachePath, "chapter-failures.txt"); - - List<string> previouslyFailedImages; - - try - { - previouslyFailedImages = _fileSystem.ReadAllText(failHistoryPath) - .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) - .ToList(); - } - catch (FileNotFoundException) - { - previouslyFailedImages = new List<string>(); - } - catch (DirectoryNotFoundException) - { - previouslyFailedImages = new List<string>(); - } - - foreach (var video in videos) - { - cancellationToken.ThrowIfCancellationRequested(); - - var key = video.Path + video.DateModified.Ticks; - - var extract = !previouslyFailedImages.Contains(key, StringComparer.OrdinalIgnoreCase); - - try - { - var chapters = _itemRepo.GetChapters(video.Id).ToList(); - - var success = await _encodingManager.RefreshChapterImages(new ChapterImageRefreshOptions - { - SaveChapters = true, - ExtractImages = extract, - Video = video, - Chapters = chapters - - }, CancellationToken.None); - - if (!success) - { - previouslyFailedImages.Add(key); - - var parentPath = Path.GetDirectoryName(failHistoryPath); - - _fileSystem.CreateDirectory(parentPath); - - _fileSystem.WriteAllText(failHistoryPath, string.Join("|", previouslyFailedImages.ToArray())); - } - - numComplete++; - double percent = numComplete; - percent /= videos.Count; - - progress.Report(100 * percent); - } - catch (ObjectDisposedException) - { - break; - } - } - } - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> - public string Name - { - get - { - return "Chapter image extraction"; - } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public string Description - { - get { return "Creates thumbnails for videos that have chapters."; } - } - - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> - public string Category - { - get - { - return "Library"; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/PeopleValidationTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/PeopleValidationTask.cs deleted file mode 100644 index 05c3db63c8..0000000000 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/PeopleValidationTask.cs +++ /dev/null @@ -1,89 +0,0 @@ -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Library; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller; - -namespace MediaBrowser.Server.Implementations.ScheduledTasks -{ - /// <summary> - /// Class PeopleValidationTask - /// </summary> - public class PeopleValidationTask : IScheduledTask - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - - private readonly IServerApplicationHost _appHost; - - /// <summary> - /// Initializes a new instance of the <see cref="PeopleValidationTask" /> class. - /// </summary> - /// <param name="libraryManager">The library manager.</param> - public PeopleValidationTask(ILibraryManager libraryManager, IServerApplicationHost appHost) - { - _libraryManager = libraryManager; - _appHost = appHost; - } - - /// <summary> - /// Creates the triggers that define when the task will run - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - // Randomize the default start hour because this operation can really hammer internet metadata providers - var startHour = new Random(_appHost.SystemId.GetHashCode()).Next(0, 8); - - return new ITaskTrigger[] - { - new DailyTrigger { TimeOfDay = TimeSpan.FromHours(startHour) }, - }; - } - - /// <summary> - /// Returns the task to be executed - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - return _libraryManager.ValidatePeople(cancellationToken, progress); - } - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return "Refresh people"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public string Description - { - get { return "Updates metadata for actors and directors in your media library."; } - } - - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> - public string Category - { - get - { - return "Library"; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs deleted file mode 100644 index ff0960259c..0000000000 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs +++ /dev/null @@ -1,135 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Common.Updates; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.ScheduledTasks -{ - /// <summary> - /// Plugin Update Task - /// </summary> - public class PluginUpdateTask : IScheduledTask - { - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - private readonly IInstallationManager _installationManager; - - private readonly IApplicationHost _appHost; - - public PluginUpdateTask(ILogger logger, IInstallationManager installationManager, IApplicationHost appHost) - { - _logger = logger; - _installationManager = installationManager; - _appHost = appHost; - } - - /// <summary> - /// Creates the triggers that define when the task will run - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - return new ITaskTrigger[] { - - // At startup - new StartupTrigger(), - - // Every so often - new IntervalTrigger { Interval = TimeSpan.FromHours(24)} - }; - } - - /// <summary> - /// Update installed plugins - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - progress.Report(0); - - var packagesToInstall = (await _installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, true, cancellationToken).ConfigureAwait(false)).ToList(); - - progress.Report(10); - - var numComplete = 0; - - // Create tasks for each one - var tasks = packagesToInstall.Select(i => Task.Run(async () => - { - cancellationToken.ThrowIfCancellationRequested(); - - try - { - await _installationManager.InstallPackage(i, true, new Progress<double>(), cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - // InstallPackage has it's own inner cancellation token, so only throw this if it's ours - if (cancellationToken.IsCancellationRequested) - { - throw; - } - } - catch (HttpException ex) - { - _logger.ErrorException("Error downloading {0}", ex, i.name); - } - catch (IOException ex) - { - _logger.ErrorException("Error updating {0}", ex, i.name); - } - - // Update progress - lock (progress) - { - numComplete++; - double percent = numComplete; - percent /= packagesToInstall.Count; - - progress.Report(90 * percent + 10); - } - })); - - cancellationToken.ThrowIfCancellationRequested(); - - await Task.WhenAll(tasks).ConfigureAwait(false); - - progress.Report(100); - } - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return "Check for plugin updates"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public string Description - { - get { return "Downloads and installs updates for plugins that are configured to update automatically."; } - } - - public string Category - { - get { return "Application"; } - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshIntrosTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshIntrosTask.cs deleted file mode 100644 index 3192c91f4a..0000000000 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshIntrosTask.cs +++ /dev/null @@ -1,103 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Logging; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.ScheduledTasks -{ - /// <summary> - /// Class RefreshIntrosTask - /// </summary> - public class RefreshIntrosTask : ILibraryPostScanTask - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - private readonly IFileSystem _fileSystem; - - /// <summary> - /// Initializes a new instance of the <see cref="RefreshIntrosTask" /> class. - /// </summary> - /// <param name="libraryManager">The library manager.</param> - /// <param name="logger">The logger.</param> - /// <param name="fileSystem">The file system.</param> - public RefreshIntrosTask(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem) - { - _libraryManager = libraryManager; - _logger = logger; - _fileSystem = fileSystem; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - var files = _libraryManager.GetAllIntroFiles().ToList(); - - var numComplete = 0; - - foreach (var file in files) - { - cancellationToken.ThrowIfCancellationRequested(); - - try - { - await RefreshIntro(file, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error refreshing intro {0}", ex, file); - } - - numComplete++; - double percent = numComplete; - percent /= files.Count; - progress.Report(percent * 100); - } - } - - /// <summary> - /// Refreshes the intro. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - private async Task RefreshIntro(string path, CancellationToken cancellationToken) - { - var item = _libraryManager.ResolvePath(_fileSystem.GetFileSystemInfo(path)); - - if (item == null) - { - _logger.Error("Intro resolver returned null for {0}", path); - return; - } - - var dbItem = _libraryManager.GetItemById(item.Id); - - if (dbItem != null) - { - item = dbItem; - } - - // Force the save if it's a new item - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); - } - } -} diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs deleted file mode 100644 index 64ae249cd4..0000000000 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.Linq; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; -using MediaBrowser.Server.Implementations.Library; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.ScheduledTasks -{ - /// <summary> - /// Class RefreshMediaLibraryTask - /// </summary> - public class RefreshMediaLibraryTask : IScheduledTask, IHasKey - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - private readonly IServerConfigurationManager _config; - - /// <summary> - /// Initializes a new instance of the <see cref="RefreshMediaLibraryTask" /> class. - /// </summary> - /// <param name="libraryManager">The library manager.</param> - public RefreshMediaLibraryTask(ILibraryManager libraryManager, IServerConfigurationManager config) - { - _libraryManager = libraryManager; - _config = config; - } - - /// <summary> - /// Gets the default triggers. - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - var list = new ITaskTrigger[] { - - new IntervalTrigger{ Interval = TimeSpan.FromHours(12)} - - }.ToList(); - - return list; - } - - /// <summary> - /// Executes the internal. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - cancellationToken.ThrowIfCancellationRequested(); - - progress.Report(0); - - return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken); - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return "Scan media library"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public string Description - { - get { return "Scans your media library and refreshes metatata based on configuration."; } - } - - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> - public string Category - { - get - { - return "Library"; - } - } - - public string Key - { - get { return "RefreshLibrary"; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/SystemUpdateTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/SystemUpdateTask.cs deleted file mode 100644 index 0ba9d4f324..0000000000 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/SystemUpdateTask.cs +++ /dev/null @@ -1,149 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.ScheduledTasks -{ - /// <summary> - /// Plugin Update Task - /// </summary> - public class SystemUpdateTask : IScheduledTask, IHasKey - { - /// <summary> - /// The _app host - /// </summary> - private readonly IApplicationHost _appHost; - - /// <summary> - /// Gets or sets the configuration manager. - /// </summary> - /// <value>The configuration manager.</value> - private IConfigurationManager ConfigurationManager { get; set; } - /// <summary> - /// Gets or sets the logger. - /// </summary> - /// <value>The logger.</value> - private ILogger Logger { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="SystemUpdateTask" /> class. - /// </summary> - /// <param name="appHost">The app host.</param> - /// <param name="configurationManager">The configuration manager.</param> - /// <param name="logger">The logger.</param> - public SystemUpdateTask(IApplicationHost appHost, IConfigurationManager configurationManager, ILogger logger) - { - _appHost = appHost; - ConfigurationManager = configurationManager; - Logger = logger; - } - - /// <summary> - /// Creates the triggers that define when the task will run - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - // Until we can vary these default triggers per server and MBT, we need something that makes sense for both - return new ITaskTrigger[] { - - // At startup - new StartupTrigger(), - - // Every so often - new IntervalTrigger { Interval = TimeSpan.FromHours(24)} - }; - } - - /// <summary> - /// Returns the task to be executed - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - EventHandler<double> innerProgressHandler = (sender, e) => progress.Report(e * .1); - - // Create a progress object for the update check - var innerProgress = new Progress<double>(); - innerProgress.ProgressChanged += innerProgressHandler; - - var updateInfo = await _appHost.CheckForApplicationUpdate(cancellationToken, innerProgress).ConfigureAwait(false); - - // Release the event handler - innerProgress.ProgressChanged -= innerProgressHandler; - - progress.Report(10); - - if (!updateInfo.IsUpdateAvailable) - { - Logger.Debug("No application update available."); - progress.Report(100); - return; - } - - cancellationToken.ThrowIfCancellationRequested(); - - if (!_appHost.CanSelfUpdate) return; - - if (ConfigurationManager.CommonConfiguration.EnableAutoUpdate) - { - Logger.Info("Update Revision {0} available. Updating...", updateInfo.AvailableVersion); - - innerProgressHandler = (sender, e) => progress.Report(e * .9 + .1); - - innerProgress = new Progress<double>(); - innerProgress.ProgressChanged += innerProgressHandler; - - await _appHost.UpdateApplication(updateInfo.Package, cancellationToken, innerProgress).ConfigureAwait(false); - - // Release the event handler - innerProgress.ProgressChanged -= innerProgressHandler; - } - else - { - Logger.Info("A new version of " + _appHost.Name + " is available."); - } - - progress.Report(100); - } - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return "Check for application updates"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public string Description - { - get { return "Downloads and installs application updates."; } - } - - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> - public string Category - { - get { return "Application"; } - } - - public string Key - { - get { return "SystemUpdateTask"; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs deleted file mode 100644 index 74a552dccc..0000000000 --- a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs +++ /dev/null @@ -1,317 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Security; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using MediaBrowser.Server.Implementations.Persistence; -using System; -using System.Collections.Generic; -using System.Data; -using System.Globalization; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Security -{ - public class AuthenticationRepository : BaseSqliteRepository, IAuthenticationRepository - { - private readonly IServerApplicationPaths _appPaths; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - public AuthenticationRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector connector) - : base(logManager, connector) - { - _appPaths = appPaths; - DbFilePath = Path.Combine(appPaths.DataPath, "authentication.db"); - } - - public async Task Initialize() - { - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - string[] queries = { - - "create table if not exists AccessTokens (Id GUID PRIMARY KEY, AccessToken TEXT NOT NULL, DeviceId TEXT, AppName TEXT, AppVersion TEXT, DeviceName TEXT, UserId TEXT, IsActive BIT, DateCreated DATETIME NOT NULL, DateRevoked DATETIME)", - "create index if not exists idx_AccessTokens on AccessTokens(Id)" - }; - - connection.RunQueries(queries, Logger); - - connection.AddColumn(Logger, "AccessTokens", "AppVersion", "TEXT"); - } - } - - public Task Create(AuthenticationInfo info, CancellationToken cancellationToken) - { - info.Id = Guid.NewGuid().ToString("N"); - - return Update(info, cancellationToken); - } - - public async Task Update(AuthenticationInfo info, CancellationToken cancellationToken) - { - if (info == null) - { - throw new ArgumentNullException("info"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var saveInfoCommand = connection.CreateCommand()) - { - saveInfoCommand.CommandText = "replace into AccessTokens (Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, IsActive, DateCreated, DateRevoked) values (@Id, @AccessToken, @DeviceId, @AppName, @AppVersion, @DeviceName, @UserId, @IsActive, @DateCreated, @DateRevoked)"; - - saveInfoCommand.Parameters.Add(saveInfoCommand, "@Id"); - saveInfoCommand.Parameters.Add(saveInfoCommand, "@AccessToken"); - saveInfoCommand.Parameters.Add(saveInfoCommand, "@DeviceId"); - saveInfoCommand.Parameters.Add(saveInfoCommand, "@AppName"); - saveInfoCommand.Parameters.Add(saveInfoCommand, "@AppVersion"); - saveInfoCommand.Parameters.Add(saveInfoCommand, "@DeviceName"); - saveInfoCommand.Parameters.Add(saveInfoCommand, "@UserId"); - saveInfoCommand.Parameters.Add(saveInfoCommand, "@IsActive"); - saveInfoCommand.Parameters.Add(saveInfoCommand, "@DateCreated"); - saveInfoCommand.Parameters.Add(saveInfoCommand, "@DateRevoked"); - - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - var index = 0; - - saveInfoCommand.GetParameter(index++).Value = new Guid(info.Id); - saveInfoCommand.GetParameter(index++).Value = info.AccessToken; - saveInfoCommand.GetParameter(index++).Value = info.DeviceId; - saveInfoCommand.GetParameter(index++).Value = info.AppName; - saveInfoCommand.GetParameter(index++).Value = info.AppVersion; - saveInfoCommand.GetParameter(index++).Value = info.DeviceName; - saveInfoCommand.GetParameter(index++).Value = info.UserId; - saveInfoCommand.GetParameter(index++).Value = info.IsActive; - saveInfoCommand.GetParameter(index++).Value = info.DateCreated; - saveInfoCommand.GetParameter(index++).Value = info.DateRevoked; - - saveInfoCommand.Transaction = transaction; - - saveInfoCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save record:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - - private const string BaseSelectText = "select Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens"; - - public QueryResult<AuthenticationInfo> Get(AuthenticationInfoQuery query) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = BaseSelectText; - - var whereClauses = new List<string>(); - - var startIndex = query.StartIndex ?? 0; - - if (!string.IsNullOrWhiteSpace(query.AccessToken)) - { - whereClauses.Add("AccessToken=@AccessToken"); - cmd.Parameters.Add(cmd, "@AccessToken", DbType.String).Value = query.AccessToken; - } - - if (!string.IsNullOrWhiteSpace(query.UserId)) - { - whereClauses.Add("UserId=@UserId"); - cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId; - } - - if (!string.IsNullOrWhiteSpace(query.DeviceId)) - { - whereClauses.Add("DeviceId=@DeviceId"); - cmd.Parameters.Add(cmd, "@DeviceId", DbType.String).Value = query.DeviceId; - } - - if (query.IsActive.HasValue) - { - whereClauses.Add("IsActive=@IsActive"); - cmd.Parameters.Add(cmd, "@IsActive", DbType.Boolean).Value = query.IsActive.Value; - } - - if (query.HasUser.HasValue) - { - if (query.HasUser.Value) - { - whereClauses.Add("UserId not null"); - } - else - { - whereClauses.Add("UserId is null"); - } - } - - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - if (startIndex > 0) - { - var pagingWhereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM AccessTokens {0} ORDER BY DateCreated LIMIT {1})", - pagingWhereText, - startIndex.ToString(_usCulture))); - } - - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - cmd.CommandText += whereText; - - cmd.CommandText += " ORDER BY DateCreated"; - - if (query.Limit.HasValue) - { - cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); - } - - cmd.CommandText += "; select count (Id) from AccessTokens" + whereTextWithoutPaging; - - var list = new List<AuthenticationInfo>(); - var count = 0; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (reader.Read()) - { - list.Add(Get(reader)); - } - - if (reader.NextResult() && reader.Read()) - { - count = reader.GetInt32(0); - } - } - - return new QueryResult<AuthenticationInfo>() - { - Items = list.ToArray(), - TotalRecordCount = count - }; - } - } - } - - public AuthenticationInfo Get(string id) - { - if (string.IsNullOrEmpty(id)) - { - throw new ArgumentNullException("id"); - } - - using (var connection = CreateConnection(true).Result) - { - var guid = new Guid(id); - - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = BaseSelectText + " where Id=@Id"; - - cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) - { - return Get(reader); - } - } - } - - return null; - } - } - - private AuthenticationInfo Get(IDataReader reader) - { - var info = new AuthenticationInfo - { - Id = reader.GetGuid(0).ToString("N"), - AccessToken = reader.GetString(1) - }; - - if (!reader.IsDBNull(2)) - { - info.DeviceId = reader.GetString(2); - } - - if (!reader.IsDBNull(3)) - { - info.AppName = reader.GetString(3); - } - - if (!reader.IsDBNull(4)) - { - info.AppVersion = reader.GetString(4); - } - - if (!reader.IsDBNull(5)) - { - info.DeviceName = reader.GetString(5); - } - - if (!reader.IsDBNull(6)) - { - info.UserId = reader.GetString(6); - } - - info.IsActive = reader.GetBoolean(7); - info.DateCreated = reader.GetDateTime(8).ToUniversalTime(); - - if (!reader.IsDBNull(9)) - { - info.DateRevoked = reader.GetDateTime(9).ToUniversalTime(); - } - - return info; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs b/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs deleted file mode 100644 index cd9b9651ec..0000000000 --- a/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs +++ /dev/null @@ -1,51 +0,0 @@ -using MediaBrowser.Controller.Security; -using System; -using System.Text; - -namespace MediaBrowser.Server.Implementations.Security -{ - public class EncryptionManager : IEncryptionManager - { - /// <summary> - /// Encrypts the string. - /// </summary> - /// <param name="value">The value.</param> - /// <returns>System.String.</returns> - /// <exception cref="System.ArgumentNullException">value</exception> - public string EncryptString(string value) - { - if (value == null) throw new ArgumentNullException("value"); - - return EncryptStringUniversal(value); - } - - /// <summary> - /// Decrypts the string. - /// </summary> - /// <param name="value">The value.</param> - /// <returns>System.String.</returns> - /// <exception cref="System.ArgumentNullException">value</exception> - public string DecryptString(string value) - { - if (value == null) throw new ArgumentNullException("value"); - - return DecryptStringUniversal(value); - } - - private string EncryptStringUniversal(string value) - { - // Yes, this isn't good, but ProtectedData in mono is throwing exceptions, so use this for now - - var bytes = Encoding.UTF8.GetBytes(value); - return Convert.ToBase64String(bytes); - } - - private string DecryptStringUniversal(string value) - { - // Yes, this isn't good, but ProtectedData in mono is throwing exceptions, so use this for now - - var bytes = Convert.FromBase64String(value); - return Encoding.UTF8.GetString(bytes); - } - } -} diff --git a/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs b/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs deleted file mode 100644 index 237d49fdae..0000000000 --- a/MediaBrowser.Server.Implementations/ServerApplicationPaths.cs +++ /dev/null @@ -1,233 +0,0 @@ -using MediaBrowser.Common.Implementations; -using MediaBrowser.Controller; -using System.IO; - -namespace MediaBrowser.Server.Implementations -{ - /// <summary> - /// Extends BaseApplicationPaths to add paths that are only applicable on the server - /// </summary> - public class ServerApplicationPaths : BaseApplicationPaths, IServerApplicationPaths - { - /// <summary> - /// Initializes a new instance of the <see cref="BaseApplicationPaths" /> class. - /// </summary> - public ServerApplicationPaths(string programDataPath, string applicationPath, string applicationResourcesPath) - : base(programDataPath, applicationPath) - { - ApplicationResourcesPath = applicationResourcesPath; - } - - public string ApplicationResourcesPath { get; private set; } - - /// <summary> - /// Gets the path to the base root media directory - /// </summary> - /// <value>The root folder path.</value> - public string RootFolderPath - { - get - { - return Path.Combine(ProgramDataPath, "root"); - } - } - - /// <summary> - /// Gets the path to the default user view directory. Used if no specific user view is defined. - /// </summary> - /// <value>The default user views path.</value> - public string DefaultUserViewsPath - { - get - { - return Path.Combine(RootFolderPath, "default"); - } - } - - /// <summary> - /// Gets the path to localization data. - /// </summary> - /// <value>The localization path.</value> - public string LocalizationPath - { - get - { - return Path.Combine(ProgramDataPath, "localization"); - } - } - - /// <summary> - /// The _ibn path - /// </summary> - private string _ibnPath; - /// <summary> - /// Gets the path to the Images By Name directory - /// </summary> - /// <value>The images by name path.</value> - public string ItemsByNamePath - { - get - { - return _ibnPath ?? (_ibnPath = Path.Combine(ProgramDataPath, "ImagesByName")); - } - set - { - _ibnPath = value; - } - } - - /// <summary> - /// Gets the path to the People directory - /// </summary> - /// <value>The people path.</value> - public string PeoplePath - { - get - { - return Path.Combine(ItemsByNamePath, "People"); - } - } - - public string ArtistsPath - { - get - { - return Path.Combine(ItemsByNamePath, "artists"); - } - } - - /// <summary> - /// Gets the path to the Genre directory - /// </summary> - /// <value>The genre path.</value> - public string GenrePath - { - get - { - return Path.Combine(ItemsByNamePath, "Genre"); - } - } - - /// <summary> - /// Gets the path to the Genre directory - /// </summary> - /// <value>The genre path.</value> - public string MusicGenrePath - { - get - { - return Path.Combine(ItemsByNamePath, "MusicGenre"); - } - } - - /// <summary> - /// Gets the path to the Studio directory - /// </summary> - /// <value>The studio path.</value> - public string StudioPath - { - get - { - return Path.Combine(ItemsByNamePath, "Studio"); - } - } - - /// <summary> - /// Gets the path to the Year directory - /// </summary> - /// <value>The year path.</value> - public string YearPath - { - get - { - return Path.Combine(ItemsByNamePath, "Year"); - } - } - - /// <summary> - /// Gets the path to the General IBN directory - /// </summary> - /// <value>The general path.</value> - public string GeneralPath - { - get - { - return Path.Combine(ItemsByNamePath, "general"); - } - } - - /// <summary> - /// Gets the path to the Ratings IBN directory - /// </summary> - /// <value>The ratings path.</value> - public string RatingsPath - { - get - { - return Path.Combine(ItemsByNamePath, "ratings"); - } - } - - /// <summary> - /// Gets the media info images path. - /// </summary> - /// <value>The media info images path.</value> - public string MediaInfoImagesPath - { - get - { - return Path.Combine(ItemsByNamePath, "mediainfo"); - } - } - - /// <summary> - /// Gets the path to the user configuration directory - /// </summary> - /// <value>The user configuration directory path.</value> - public string UserConfigurationDirectoryPath - { - get - { - return Path.Combine(ConfigurationDirectoryPath, "users"); - } - } - - private string _transcodingTempPath; - public string TranscodingTempPath - { - get - { - return _transcodingTempPath ?? (_transcodingTempPath = Path.Combine(ProgramDataPath, "transcoding-temp")); - } - set - { - _transcodingTempPath = value; - } - } - - /// <summary> - /// Gets the game genre path. - /// </summary> - /// <value>The game genre path.</value> - public string GameGenrePath - { - get - { - return Path.Combine(ItemsByNamePath, "GameGenre"); - } - } - - private string _internalMetadataPath; - public string InternalMetadataPath - { - get - { - return _internalMetadataPath ?? (_internalMetadataPath = Path.Combine(DataPath, "metadata")); - } - set - { - _internalMetadataPath = value; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs deleted file mode 100644 index 893592fa38..0000000000 --- a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs +++ /dev/null @@ -1,351 +0,0 @@ -using MediaBrowser.Common.Events; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.Server.Implementations.ServerManager -{ - /// <summary> - /// Manages the Http Server, Udp Server and WebSocket connections - /// </summary> - public class ServerManager : IServerManager - { - /// <summary> - /// Both the Ui and server will have a built-in HttpServer. - /// People will inevitably want remote control apps so it's needed in the Ui too. - /// </summary> - /// <value>The HTTP server.</value> - private IHttpServer HttpServer { get; set; } - - /// <summary> - /// Gets or sets the json serializer. - /// </summary> - /// <value>The json serializer.</value> - private readonly IJsonSerializer _jsonSerializer; - - /// <summary> - /// The web socket connections - /// </summary> - private readonly List<IWebSocketConnection> _webSocketConnections = new List<IWebSocketConnection>(); - /// <summary> - /// Gets the web socket connections. - /// </summary> - /// <value>The web socket connections.</value> - public IEnumerable<IWebSocketConnection> WebSocketConnections - { - get { return _webSocketConnections; } - } - - public event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected; - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - /// <summary> - /// The _application host - /// </summary> - private readonly IServerApplicationHost _applicationHost; - - /// <summary> - /// Gets or sets the configuration manager. - /// </summary> - /// <value>The configuration manager.</value> - private IServerConfigurationManager ConfigurationManager { get; set; } - - /// <summary> - /// Gets the web socket listeners. - /// </summary> - /// <value>The web socket listeners.</value> - private readonly List<IWebSocketListener> _webSocketListeners = new List<IWebSocketListener>(); - - private bool _disposed; - private readonly IMemoryStreamProvider _memoryStreamProvider; - - /// <summary> - /// Initializes a new instance of the <see cref="ServerManager" /> class. - /// </summary> - /// <param name="applicationHost">The application host.</param> - /// <param name="jsonSerializer">The json serializer.</param> - /// <param name="logger">The logger.</param> - /// <param name="configurationManager">The configuration manager.</param> - /// <exception cref="System.ArgumentNullException">applicationHost</exception> - public ServerManager(IServerApplicationHost applicationHost, IJsonSerializer jsonSerializer, ILogger logger, IServerConfigurationManager configurationManager, IMemoryStreamProvider memoryStreamProvider) - { - if (applicationHost == null) - { - throw new ArgumentNullException("applicationHost"); - } - if (jsonSerializer == null) - { - throw new ArgumentNullException("jsonSerializer"); - } - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - - _logger = logger; - _jsonSerializer = jsonSerializer; - _applicationHost = applicationHost; - ConfigurationManager = configurationManager; - _memoryStreamProvider = memoryStreamProvider; - } - - /// <summary> - /// Starts this instance. - /// </summary> - public void Start(IEnumerable<string> urlPrefixes, string certificatePath) - { - ReloadHttpServer(urlPrefixes, certificatePath); - } - - /// <summary> - /// Restarts the Http Server, or starts it if not currently running - /// </summary> - private void ReloadHttpServer(IEnumerable<string> urlPrefixes, string certificatePath) - { - _logger.Info("Loading Http Server"); - - try - { - HttpServer = _applicationHost.Resolve<IHttpServer>(); - HttpServer.StartServer(urlPrefixes, certificatePath); - } - catch (SocketException ex) - { - _logger.ErrorException("The http server is unable to start due to a Socket error. This can occasionally happen when the operating system takes longer than usual to release the IP bindings from the previous session. This can take up to five minutes. Please try waiting or rebooting the system.", ex); - - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error starting Http Server", ex); - - throw; - } - - HttpServer.WebSocketConnected += HttpServer_WebSocketConnected; - } - - /// <summary> - /// Handles the WebSocketConnected event of the HttpServer control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="WebSocketConnectEventArgs" /> instance containing the event data.</param> - void HttpServer_WebSocketConnected(object sender, WebSocketConnectEventArgs e) - { - if (_disposed) - { - return; - } - - var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, _jsonSerializer, _logger, _memoryStreamProvider) - { - OnReceive = ProcessWebSocketMessageReceived, - Url = e.Url, - QueryString = new NameValueCollection(e.QueryString ?? new NameValueCollection()) - }; - - _webSocketConnections.Add(connection); - - if (WebSocketConnected != null) - { - EventHelper.FireEventIfNotNull(WebSocketConnected, this, new GenericEventArgs<IWebSocketConnection> (connection), _logger); - } - } - - /// <summary> - /// Processes the web socket message received. - /// </summary> - /// <param name="result">The result.</param> - private async void ProcessWebSocketMessageReceived(WebSocketMessageInfo result) - { - if (_disposed) - { - return; - } - - //_logger.Debug("Websocket message received: {0}", result.MessageType); - - var tasks = _webSocketListeners.Select(i => Task.Run(async () => - { - try - { - await i.ProcessMessage(result).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("{0} failed processing WebSocket message {1}", ex, i.GetType().Name, result.MessageType ?? string.Empty); - } - })); - - await Task.WhenAll(tasks).ConfigureAwait(false); - } - - /// <summary> - /// Sends a message to all clients currently connected via a web socket - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="messageType">Type of the message.</param> - /// <param name="data">The data.</param> - /// <returns>Task.</returns> - public void SendWebSocketMessage<T>(string messageType, T data) - { - SendWebSocketMessage(messageType, () => data); - } - - /// <summary> - /// Sends a message to all clients currently connected via a web socket - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="messageType">Type of the message.</param> - /// <param name="dataFunction">The function that generates the data to send, if there are any connected clients</param> - public void SendWebSocketMessage<T>(string messageType, Func<T> dataFunction) - { - SendWebSocketMessageAsync(messageType, dataFunction, CancellationToken.None); - } - - /// <summary> - /// Sends a message to all clients currently connected via a web socket - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="messageType">Type of the message.</param> - /// <param name="dataFunction">The function that generates the data to send, if there are any connected clients</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">messageType</exception> - public Task SendWebSocketMessageAsync<T>(string messageType, Func<T> dataFunction, CancellationToken cancellationToken) - { - return SendWebSocketMessageAsync(messageType, dataFunction, _webSocketConnections, cancellationToken); - } - - /// <summary> - /// Sends the web socket message async. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="messageType">Type of the message.</param> - /// <param name="dataFunction">The data function.</param> - /// <param name="connections">The connections.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">messageType - /// or - /// dataFunction - /// or - /// cancellationToken</exception> - private async Task SendWebSocketMessageAsync<T>(string messageType, Func<T> dataFunction, IEnumerable<IWebSocketConnection> connections, CancellationToken cancellationToken) - { - if (string.IsNullOrEmpty(messageType)) - { - throw new ArgumentNullException("messageType"); - } - - if (dataFunction == null) - { - throw new ArgumentNullException("dataFunction"); - } - - if (_disposed) - { - throw new ObjectDisposedException(GetType().Name); - } - - cancellationToken.ThrowIfCancellationRequested(); - - var connectionsList = connections.Where(s => s.State == WebSocketState.Open).ToList(); - - if (connectionsList.Count > 0) - { - _logger.Info("Sending web socket message {0}", messageType); - - var message = new WebSocketMessage<T> { MessageType = messageType, Data = dataFunction() }; - var json = _jsonSerializer.SerializeToString(message); - - var tasks = connectionsList.Select(s => Task.Run(() => - { - try - { - s.SendAsync(json, cancellationToken); - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error sending web socket message {0} to {1}", ex, messageType, s.RemoteEndPoint); - } - - }, cancellationToken)); - - await Task.WhenAll(tasks).ConfigureAwait(false); - } - } - - /// <summary> - /// Disposes the current HttpServer - /// </summary> - private void DisposeHttpServer() - { - foreach (var socket in _webSocketConnections) - { - // Dispose the connection - socket.Dispose(); - } - - _webSocketConnections.Clear(); - - if (HttpServer != null) - { - HttpServer.WebSocketConnected -= HttpServer_WebSocketConnected; - HttpServer.Dispose(); - } - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - _disposed = true; - - Dispose(true); - GC.SuppressFinalize(this); - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - DisposeHttpServer(); - } - } - - /// <summary> - /// Adds the web socket listeners. - /// </summary> - /// <param name="listeners">The listeners.</param> - public void AddWebSocketListeners(IEnumerable<IWebSocketListener> listeners) - { - _webSocketListeners.AddRange(listeners); - } - } -} diff --git a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs deleted file mode 100644 index 60b04cf82f..0000000000 --- a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs +++ /dev/null @@ -1,290 +0,0 @@ -using System.Text; -using MediaBrowser.Common.Events; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Specialized; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.IO; -using UniversalDetector; - -namespace MediaBrowser.Server.Implementations.ServerManager -{ - /// <summary> - /// Class WebSocketConnection - /// </summary> - public class WebSocketConnection : IWebSocketConnection - { - public event EventHandler<EventArgs> Closed; - - /// <summary> - /// The _socket - /// </summary> - private readonly IWebSocket _socket; - - /// <summary> - /// The _remote end point - /// </summary> - public string RemoteEndPoint { get; private set; } - - /// <summary> - /// The _cancellation token source - /// </summary> - private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - - /// <summary> - /// The logger - /// </summary> - private readonly ILogger _logger; - - /// <summary> - /// The _json serializer - /// </summary> - private readonly IJsonSerializer _jsonSerializer; - - /// <summary> - /// Gets or sets the receive action. - /// </summary> - /// <value>The receive action.</value> - public Action<WebSocketMessageInfo> OnReceive { get; set; } - - /// <summary> - /// Gets the last activity date. - /// </summary> - /// <value>The last activity date.</value> - public DateTime LastActivityDate { get; private set; } - - /// <summary> - /// Gets the id. - /// </summary> - /// <value>The id.</value> - public Guid Id { get; private set; } - - /// <summary> - /// Gets or sets the URL. - /// </summary> - /// <value>The URL.</value> - public string Url { get; set; } - /// <summary> - /// Gets or sets the query string. - /// </summary> - /// <value>The query string.</value> - public NameValueCollection QueryString { get; set; } - private readonly IMemoryStreamProvider _memoryStreamProvider; - - /// <summary> - /// Initializes a new instance of the <see cref="WebSocketConnection" /> class. - /// </summary> - /// <param name="socket">The socket.</param> - /// <param name="remoteEndPoint">The remote end point.</param> - /// <param name="jsonSerializer">The json serializer.</param> - /// <param name="logger">The logger.</param> - /// <exception cref="System.ArgumentNullException">socket</exception> - public WebSocketConnection(IWebSocket socket, string remoteEndPoint, IJsonSerializer jsonSerializer, ILogger logger, IMemoryStreamProvider memoryStreamProvider) - { - if (socket == null) - { - throw new ArgumentNullException("socket"); - } - if (string.IsNullOrEmpty(remoteEndPoint)) - { - throw new ArgumentNullException("remoteEndPoint"); - } - if (jsonSerializer == null) - { - throw new ArgumentNullException("jsonSerializer"); - } - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - - Id = Guid.NewGuid(); - _jsonSerializer = jsonSerializer; - _socket = socket; - _socket.OnReceiveBytes = OnReceiveInternal; - _socket.OnReceive = OnReceiveInternal; - RemoteEndPoint = remoteEndPoint; - _logger = logger; - _memoryStreamProvider = memoryStreamProvider; - - socket.Closed += socket_Closed; - } - - void socket_Closed(object sender, EventArgs e) - { - EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger); - } - - /// <summary> - /// Called when [receive]. - /// </summary> - /// <param name="bytes">The bytes.</param> - private void OnReceiveInternal(byte[] bytes) - { - LastActivityDate = DateTime.UtcNow; - - if (OnReceive == null) - { - return; - } - var charset = DetectCharset(bytes); - - if (string.Equals(charset, "utf-8", StringComparison.OrdinalIgnoreCase)) - { - OnReceiveInternal(Encoding.UTF8.GetString(bytes)); - } - else - { - OnReceiveInternal(Encoding.ASCII.GetString(bytes)); - } - } - private string DetectCharset(byte[] bytes) - { - try - { - using (var ms = _memoryStreamProvider.CreateNew(bytes)) - { - var detector = new CharsetDetector(); - detector.Feed(ms); - detector.DataEnd(); - - var charset = detector.Charset; - - if (!string.IsNullOrWhiteSpace(charset)) - { - //_logger.Debug("UniversalDetector detected charset {0}", charset); - } - - return charset; - } - } - catch (IOException ex) - { - _logger.ErrorException("Error attempting to determine web socket message charset", ex); - } - - return null; - } - - private void OnReceiveInternal(string message) - { - LastActivityDate = DateTime.UtcNow; - - if (!message.StartsWith("{", StringComparison.OrdinalIgnoreCase)) - { - // This info is useful sometimes but also clogs up the log - //_logger.Error("Received web socket message that is not a json structure: " + message); - return; - } - - if (OnReceive == null) - { - return; - } - - try - { - var stub = (WebSocketMessage<object>)_jsonSerializer.DeserializeFromString(message, typeof(WebSocketMessage<object>)); - - var info = new WebSocketMessageInfo - { - MessageType = stub.MessageType, - Data = stub.Data == null ? null : stub.Data.ToString(), - Connection = this - }; - - OnReceive(info); - } - catch (Exception ex) - { - _logger.ErrorException("Error processing web socket message", ex); - } - } - - /// <summary> - /// Sends a message asynchronously. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="message">The message.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">message</exception> - public Task SendAsync<T>(WebSocketMessage<T> message, CancellationToken cancellationToken) - { - if (message == null) - { - throw new ArgumentNullException("message"); - } - - var json = _jsonSerializer.SerializeToString(message); - - return SendAsync(json, cancellationToken); - } - - /// <summary> - /// Sends a message asynchronously. - /// </summary> - /// <param name="buffer">The buffer.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task SendAsync(byte[] buffer, CancellationToken cancellationToken) - { - if (buffer == null) - { - throw new ArgumentNullException("buffer"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - return _socket.SendAsync(buffer, true, cancellationToken); - } - - public Task SendAsync(string text, CancellationToken cancellationToken) - { - if (string.IsNullOrWhiteSpace(text)) - { - throw new ArgumentNullException("text"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - return _socket.SendAsync(text, true, cancellationToken); - } - - /// <summary> - /// Gets the state. - /// </summary> - /// <value>The state.</value> - public WebSocketState State - { - get { return _socket.State; } - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - _cancellationTokenSource.Dispose(); - _socket.Dispose(); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs deleted file mode 100644 index f54c452cca..0000000000 --- a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs +++ /dev/null @@ -1,186 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Session; -using MediaBrowser.Model.System; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Session -{ - public class HttpSessionController : ISessionController, IDisposable - { - private readonly IHttpClient _httpClient; - private readonly IJsonSerializer _json; - private readonly ISessionManager _sessionManager; - - public SessionInfo Session { get; private set; } - - private readonly string _postUrl; - - public HttpSessionController(IHttpClient httpClient, - IJsonSerializer json, - SessionInfo session, - string postUrl, ISessionManager sessionManager) - { - _httpClient = httpClient; - _json = json; - Session = session; - _postUrl = postUrl; - _sessionManager = sessionManager; - } - - public void OnActivity() - { - } - - private string PostUrl - { - get - { - return string.Format("http://{0}{1}", Session.RemoteEndPoint, _postUrl); - } - } - - public bool IsSessionActive - { - get - { - return (DateTime.UtcNow - Session.LastActivityDate).TotalMinutes <= 10; - } - } - - public bool SupportsMediaControl - { - get { return true; } - } - - private Task SendMessage(string name, CancellationToken cancellationToken) - { - return SendMessage(name, new Dictionary<string, string>(), cancellationToken); - } - - private async Task SendMessage(string name, - Dictionary<string, string> args, - CancellationToken cancellationToken) - { - var url = PostUrl + "/" + name + ToQueryString(args); - - await _httpClient.Post(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - BufferContent = false - - }).ConfigureAwait(false); - } - - public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendPlaybackStartNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendPlaybackStoppedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken) - { - var dict = new Dictionary<string, string>(); - - dict["ItemIds"] = string.Join(",", command.ItemIds); - - if (command.StartPositionTicks.HasValue) - { - dict["StartPositionTicks"] = command.StartPositionTicks.Value.ToString(CultureInfo.InvariantCulture); - } - - return SendMessage(command.PlayCommand.ToString(), dict, cancellationToken); - } - - public Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken) - { - var args = new Dictionary<string, string>(); - - if (command.Command == PlaystateCommand.Seek) - { - if (!command.SeekPositionTicks.HasValue) - { - throw new ArgumentException("SeekPositionTicks cannot be null"); - } - - args["SeekPositionTicks"] = command.SeekPositionTicks.Value.ToString(CultureInfo.InvariantCulture); - } - - return SendMessage(command.Command.ToString(), args, cancellationToken); - } - - public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken) - { - return SendMessage("RestartRequired", cancellationToken); - } - - public Task SendUserDataChangeInfo(UserDataChangeInfo info, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendServerShutdownNotification(CancellationToken cancellationToken) - { - return SendMessage("ServerShuttingDown", cancellationToken); - } - - public Task SendServerRestartNotification(CancellationToken cancellationToken) - { - return SendMessage("ServerRestarting", cancellationToken); - } - - public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken) - { - return SendMessage(command.Name, command.Arguments, cancellationToken); - } - - public Task SendMessage<T>(string name, T data, CancellationToken cancellationToken) - { - // Not supported or needed right now - return Task.FromResult(true); - } - - private string ToQueryString(Dictionary<string, string> nvc) - { - var array = (from item in nvc - select string.Format("{0}={1}", WebUtility.UrlEncode(item.Key), WebUtility.UrlEncode(item.Value))) - .ToArray(); - - var args = string.Join("&", array); - - if (string.IsNullOrEmpty(args)) - { - return args; - } - - return "?" + args; - } - - public void Dispose() - { - } - } -} diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs deleted file mode 100644 index 9326c4f43e..0000000000 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ /dev/null @@ -1,1929 +0,0 @@ -using MediaBrowser.Common.Events; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Security; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Devices; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Library; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Session; -using MediaBrowser.Model.Users; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Net; - -namespace MediaBrowser.Server.Implementations.Session -{ - /// <summary> - /// Class SessionManager - /// </summary> - public class SessionManager : ISessionManager - { - /// <summary> - /// The _user data repository - /// </summary> - private readonly IUserDataManager _userDataManager; - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - private readonly ILibraryManager _libraryManager; - private readonly IUserManager _userManager; - private readonly IMusicManager _musicManager; - private readonly IDtoService _dtoService; - private readonly IImageProcessor _imageProcessor; - private readonly IMediaSourceManager _mediaSourceManager; - - private readonly IHttpClient _httpClient; - private readonly IJsonSerializer _jsonSerializer; - private readonly IServerApplicationHost _appHost; - - private readonly IAuthenticationRepository _authRepo; - private readonly IDeviceManager _deviceManager; - - /// <summary> - /// The _active connections - /// </summary> - private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections = - new ConcurrentDictionary<string, SessionInfo>(StringComparer.OrdinalIgnoreCase); - - public event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationFailed; - - public event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationSucceeded; - - /// <summary> - /// Occurs when [playback start]. - /// </summary> - public event EventHandler<PlaybackProgressEventArgs> PlaybackStart; - /// <summary> - /// Occurs when [playback progress]. - /// </summary> - public event EventHandler<PlaybackProgressEventArgs> PlaybackProgress; - /// <summary> - /// Occurs when [playback stopped]. - /// </summary> - public event EventHandler<PlaybackStopEventArgs> PlaybackStopped; - - public event EventHandler<SessionEventArgs> SessionStarted; - public event EventHandler<SessionEventArgs> CapabilitiesChanged; - public event EventHandler<SessionEventArgs> SessionEnded; - public event EventHandler<SessionEventArgs> SessionActivity; - - private IEnumerable<ISessionControllerFactory> _sessionFactories = new List<ISessionControllerFactory>(); - - private readonly SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1); - - public SessionManager(IUserDataManager userDataManager, ILogger logger, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager) - { - _userDataManager = userDataManager; - _logger = logger; - _libraryManager = libraryManager; - _userManager = userManager; - _musicManager = musicManager; - _dtoService = dtoService; - _imageProcessor = imageProcessor; - _jsonSerializer = jsonSerializer; - _appHost = appHost; - _httpClient = httpClient; - _authRepo = authRepo; - _deviceManager = deviceManager; - _mediaSourceManager = mediaSourceManager; - - _deviceManager.DeviceOptionsUpdated += _deviceManager_DeviceOptionsUpdated; - } - - void _deviceManager_DeviceOptionsUpdated(object sender, GenericEventArgs<DeviceInfo> e) - { - foreach (var session in Sessions) - { - if (string.Equals(session.DeviceId, e.Argument.Id)) - { - session.DeviceName = e.Argument.Name; - } - } - } - - /// <summary> - /// Adds the parts. - /// </summary> - /// <param name="sessionFactories">The session factories.</param> - public void AddParts(IEnumerable<ISessionControllerFactory> sessionFactories) - { - _sessionFactories = sessionFactories.ToList(); - } - - /// <summary> - /// Gets all connections. - /// </summary> - /// <value>All connections.</value> - public IEnumerable<SessionInfo> Sessions - { - get { return _activeConnections.Values.OrderByDescending(c => c.LastActivityDate).ToList(); } - } - - private void OnSessionStarted(SessionInfo info) - { - EventHelper.QueueEventIfNotNull(SessionStarted, this, new SessionEventArgs - { - SessionInfo = info - - }, _logger); - - if (!string.IsNullOrWhiteSpace(info.DeviceId)) - { - var capabilities = GetSavedCapabilities(info.DeviceId); - - if (capabilities != null) - { - info.AppIconUrl = capabilities.IconUrl; - ReportCapabilities(info, capabilities, false); - } - } - } - - private async void OnSessionEnded(SessionInfo info) - { - try - { - await SendSessionEndedNotification(info, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error in SendSessionEndedNotification", ex); - } - - EventHelper.QueueEventIfNotNull(SessionEnded, this, new SessionEventArgs - { - SessionInfo = info - - }, _logger); - - var disposable = info.SessionController as IDisposable; - - if (disposable != null) - { - _logger.Debug("Disposing session controller {0}", disposable.GetType().Name); - - try - { - disposable.Dispose(); - } - catch (Exception ex) - { - _logger.ErrorException("Error disposing session controller", ex); - } - } - } - - /// <summary> - /// Logs the user activity. - /// </summary> - /// <param name="appName">Type of the client.</param> - /// <param name="appVersion">The app version.</param> - /// <param name="deviceId">The device id.</param> - /// <param name="deviceName">Name of the device.</param> - /// <param name="remoteEndPoint">The remote end point.</param> - /// <param name="user">The user.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">user</exception> - /// <exception cref="System.UnauthorizedAccessException"></exception> - public async Task<SessionInfo> LogSessionActivity(string appName, - string appVersion, - string deviceId, - string deviceName, - string remoteEndPoint, - User user) - { - if (string.IsNullOrEmpty(appName)) - { - throw new ArgumentNullException("appName"); - } - if (string.IsNullOrEmpty(appVersion)) - { - throw new ArgumentNullException("appVersion"); - } - if (string.IsNullOrEmpty(deviceId)) - { - throw new ArgumentNullException("deviceId"); - } - if (string.IsNullOrEmpty(deviceName)) - { - throw new ArgumentNullException("deviceName"); - } - - var activityDate = DateTime.UtcNow; - var session = await GetSessionInfo(appName, appVersion, deviceId, deviceName, remoteEndPoint, user).ConfigureAwait(false); - var lastActivityDate = session.LastActivityDate; - session.LastActivityDate = activityDate; - - if (user != null) - { - var userLastActivityDate = user.LastActivityDate ?? DateTime.MinValue; - user.LastActivityDate = activityDate; - - if ((activityDate - userLastActivityDate).TotalSeconds > 60) - { - try - { - await _userManager.UpdateUser(user).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error updating user", ex); - } - } - } - - if ((activityDate - lastActivityDate).TotalSeconds > 10) - { - EventHelper.FireEventIfNotNull(SessionActivity, this, new SessionEventArgs - { - SessionInfo = session - - }, _logger); - } - - var controller = session.SessionController; - if (controller != null) - { - controller.OnActivity(); - } - - return session; - } - - public async void ReportSessionEnded(string sessionId) - { - await _sessionLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); - - try - { - var session = GetSession(sessionId, false); - - if (session != null) - { - var key = GetSessionKey(session.Client, session.DeviceId); - - SessionInfo removed; - _activeConnections.TryRemove(key, out removed); - - OnSessionEnded(session); - } - } - finally - { - _sessionLock.Release(); - } - } - - private Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, string liveStreamId) - { - return _mediaSourceManager.GetMediaSource(item, mediaSourceId, liveStreamId, false, CancellationToken.None); - } - - /// <summary> - /// Updates the now playing item id. - /// </summary> - /// <param name="session">The session.</param> - /// <param name="info">The information.</param> - /// <param name="libraryItem">The library item.</param> - private async Task UpdateNowPlayingItem(SessionInfo session, PlaybackProgressInfo info, BaseItem libraryItem) - { - if (string.IsNullOrWhiteSpace(info.MediaSourceId)) - { - info.MediaSourceId = info.ItemId; - } - - if (!string.IsNullOrWhiteSpace(info.ItemId) && info.Item == null && libraryItem != null) - { - var current = session.NowPlayingItem; - - if (current == null || !string.Equals(current.Id, info.ItemId, StringComparison.OrdinalIgnoreCase)) - { - var runtimeTicks = libraryItem.RunTimeTicks; - - MediaSourceInfo mediaSource = null; - var hasMediaSources = libraryItem as IHasMediaSources; - if (hasMediaSources != null) - { - mediaSource = await GetMediaSource(hasMediaSources, info.MediaSourceId, info.LiveStreamId).ConfigureAwait(false); - - if (mediaSource != null) - { - runtimeTicks = mediaSource.RunTimeTicks; - } - } - - info.Item = GetItemInfo(libraryItem, libraryItem, mediaSource); - - info.Item.RunTimeTicks = runtimeTicks; - } - else - { - info.Item = current; - } - } - - session.NowPlayingItem = info.Item; - session.LastActivityDate = DateTime.UtcNow; - session.LastPlaybackCheckIn = DateTime.UtcNow; - - session.PlayState.IsPaused = info.IsPaused; - session.PlayState.PositionTicks = info.PositionTicks; - session.PlayState.MediaSourceId = info.MediaSourceId; - session.PlayState.CanSeek = info.CanSeek; - session.PlayState.IsMuted = info.IsMuted; - session.PlayState.VolumeLevel = info.VolumeLevel; - session.PlayState.AudioStreamIndex = info.AudioStreamIndex; - session.PlayState.SubtitleStreamIndex = info.SubtitleStreamIndex; - session.PlayState.PlayMethod = info.PlayMethod; - session.PlayState.RepeatMode = info.RepeatMode; - } - - /// <summary> - /// Removes the now playing item id. - /// </summary> - /// <param name="session">The session.</param> - /// <exception cref="System.ArgumentNullException">item</exception> - private void RemoveNowPlayingItem(SessionInfo session) - { - session.NowPlayingItem = null; - session.PlayState = new PlayerStateInfo(); - - if (!string.IsNullOrEmpty(session.DeviceId)) - { - ClearTranscodingInfo(session.DeviceId); - } - } - - private string GetSessionKey(string appName, string deviceId) - { - return appName + deviceId; - } - - /// <summary> - /// Gets the connection. - /// </summary> - /// <param name="appName">Type of the client.</param> - /// <param name="appVersion">The app version.</param> - /// <param name="deviceId">The device id.</param> - /// <param name="deviceName">Name of the device.</param> - /// <param name="remoteEndPoint">The remote end point.</param> - /// <param name="user">The user.</param> - /// <returns>SessionInfo.</returns> - private async Task<SessionInfo> GetSessionInfo(string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user) - { - if (string.IsNullOrWhiteSpace(deviceId)) - { - throw new ArgumentNullException("deviceId"); - } - var key = GetSessionKey(appName, deviceId); - - await _sessionLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); - - var userId = user == null ? (Guid?)null : user.Id; - var username = user == null ? null : user.Name; - - try - { - SessionInfo sessionInfo; - DeviceInfo device = null; - - if (!_activeConnections.TryGetValue(key, out sessionInfo)) - { - sessionInfo = new SessionInfo - { - Client = appName, - DeviceId = deviceId, - ApplicationVersion = appVersion, - Id = key.GetMD5().ToString("N") - }; - - sessionInfo.DeviceName = deviceName; - sessionInfo.UserId = userId; - sessionInfo.UserName = username; - sessionInfo.RemoteEndPoint = remoteEndPoint; - - OnSessionStarted(sessionInfo); - - _activeConnections.TryAdd(key, sessionInfo); - - 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 = device ?? _deviceManager.GetDevice(deviceId); - - if (device == null) - { - var userIdString = userId.HasValue ? userId.Value.ToString("N") : null; - device = await _deviceManager.RegisterDevice(deviceId, deviceName, appName, appVersion, userIdString).ConfigureAwait(false); - } - - if (device != null) - { - if (!string.IsNullOrEmpty(device.CustomName)) - { - deviceName = device.CustomName; - } - } - - sessionInfo.DeviceName = deviceName; - sessionInfo.UserId = userId; - sessionInfo.UserName = username; - sessionInfo.RemoteEndPoint = remoteEndPoint; - sessionInfo.ApplicationVersion = appVersion; - - if (!userId.HasValue) - { - sessionInfo.AdditionalUsers.Clear(); - } - - if (sessionInfo.SessionController == null) - { - sessionInfo.SessionController = _sessionFactories - .Select(i => i.GetSessionController(sessionInfo)) - .FirstOrDefault(i => i != null); - } - - return sessionInfo; - } - finally - { - _sessionLock.Release(); - } - } - - private List<User> GetUsers(SessionInfo session) - { - var users = new List<User>(); - - if (session.UserId.HasValue) - { - var user = _userManager.GetUserById(session.UserId.Value); - - if (user == null) - { - throw new InvalidOperationException("User not found"); - } - - users.Add(user); - - var additionalUsers = session.AdditionalUsers - .Select(i => _userManager.GetUserById(i.UserId)) - .Where(i => i != null); - - users.AddRange(additionalUsers); - } - - return users; - } - - private Timer _idleTimer; - - private void StartIdleCheckTimer() - { - if (_idleTimer == null) - { - _idleTimer = new Timer(CheckForIdlePlayback, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); - } - } - private void StopIdleCheckTimer() - { - if (_idleTimer != null) - { - _idleTimer.Dispose(); - _idleTimer = null; - } - } - - private async void CheckForIdlePlayback(object state) - { - var playingSessions = Sessions.Where(i => i.NowPlayingItem != null) - .ToList(); - - if (playingSessions.Count > 0) - { - var idle = playingSessions - .Where(i => (DateTime.UtcNow - i.LastPlaybackCheckIn).TotalMinutes > 5) - .ToList(); - - foreach (var session in idle) - { - _logger.Debug("Session {0} has gone idle while playing", session.Id); - - try - { - await OnPlaybackStopped(new PlaybackStopInfo - { - Item = session.NowPlayingItem, - ItemId = session.NowPlayingItem == null ? null : session.NowPlayingItem.Id, - SessionId = session.Id, - MediaSourceId = session.PlayState == null ? null : session.PlayState.MediaSourceId, - PositionTicks = session.PlayState == null ? null : session.PlayState.PositionTicks - }); - } - catch (Exception ex) - { - _logger.Debug("Error calling OnPlaybackStopped", ex); - } - } - - playingSessions = Sessions.Where(i => i.NowPlayingItem != null) - .ToList(); - } - - if (playingSessions.Count == 0) - { - StopIdleCheckTimer(); - } - } - - /// <summary> - /// Used to report that playback has started for an item - /// </summary> - /// <param name="info">The info.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">info</exception> - public async Task OnPlaybackStart(PlaybackStartInfo info) - { - if (info == null) - { - throw new ArgumentNullException("info"); - } - - var session = GetSession(info.SessionId); - - var libraryItem = string.IsNullOrWhiteSpace(info.ItemId) - ? null - : _libraryManager.GetItemById(new Guid(info.ItemId)); - - await UpdateNowPlayingItem(session, info, libraryItem).ConfigureAwait(false); - - if (!string.IsNullOrEmpty(session.DeviceId) && info.PlayMethod != PlayMethod.Transcode) - { - ClearTranscodingInfo(session.DeviceId); - } - - session.QueueableMediaTypes = info.QueueableMediaTypes; - - var users = GetUsers(session); - - if (libraryItem != null) - { - foreach (var user in users) - { - await OnPlaybackStart(user.Id, libraryItem).ConfigureAwait(false); - } - } - - // Nothing to save here - // Fire events to inform plugins - EventHelper.QueueEventIfNotNull(PlaybackStart, this, new PlaybackProgressEventArgs - { - Item = libraryItem, - Users = users, - MediaSourceId = info.MediaSourceId, - MediaInfo = info.Item, - DeviceName = session.DeviceName, - ClientName = session.Client, - DeviceId = session.DeviceId - - }, _logger); - - await SendPlaybackStartNotification(session, CancellationToken.None).ConfigureAwait(false); - - StartIdleCheckTimer(); - } - - /// <summary> - /// Called when [playback start]. - /// </summary> - /// <param name="userId">The user identifier.</param> - /// <param name="item">The item.</param> - /// <returns>Task.</returns> - private async Task OnPlaybackStart(Guid userId, IHasUserData item) - { - var data = _userDataManager.GetUserData(userId, item); - - data.PlayCount++; - data.LastPlayedDate = DateTime.UtcNow; - - if (item.SupportsPlayedStatus) - { - if (!(item is Video)) - { - data.Played = true; - } - } - else - { - data.Played = false; - } - - await _userDataManager.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None).ConfigureAwait(false); - } - - /// <summary> - /// Used to report playback progress for an item - /// </summary> - /// <param name="info">The info.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - /// <exception cref="System.ArgumentOutOfRangeException">positionTicks</exception> - public async Task OnPlaybackProgress(PlaybackProgressInfo info) - { - if (info == null) - { - throw new ArgumentNullException("info"); - } - - var session = GetSession(info.SessionId); - - var libraryItem = string.IsNullOrWhiteSpace(info.ItemId) - ? null - : _libraryManager.GetItemById(new Guid(info.ItemId)); - - await UpdateNowPlayingItem(session, info, libraryItem).ConfigureAwait(false); - - var users = GetUsers(session); - - if (libraryItem != null) - { - foreach (var user in users) - { - await OnPlaybackProgress(user, libraryItem, info).ConfigureAwait(false); - } - } - - if (!string.IsNullOrWhiteSpace(info.LiveStreamId)) - { - try - { - await _mediaSourceManager.PingLiveStream(info.LiveStreamId, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error closing live stream", ex); - } - } - - EventHelper.FireEventIfNotNull(PlaybackProgress, this, new PlaybackProgressEventArgs - { - Item = libraryItem, - Users = users, - PlaybackPositionTicks = session.PlayState.PositionTicks, - MediaSourceId = session.PlayState.MediaSourceId, - MediaInfo = info.Item, - DeviceName = session.DeviceName, - ClientName = session.Client, - DeviceId = session.DeviceId, - IsPaused = info.IsPaused, - PlaySessionId = info.PlaySessionId - - }, _logger); - - StartIdleCheckTimer(); - } - - private async Task OnPlaybackProgress(User user, BaseItem item, PlaybackProgressInfo info) - { - var data = _userDataManager.GetUserData(user.Id, item); - - var positionTicks = info.PositionTicks; - - if (positionTicks.HasValue) - { - _userDataManager.UpdatePlayState(item, data, positionTicks.Value); - - UpdatePlaybackSettings(user, info, data); - - await _userDataManager.SaveUserData(user.Id, item, data, UserDataSaveReason.PlaybackProgress, CancellationToken.None).ConfigureAwait(false); - } - } - - private void UpdatePlaybackSettings(User user, PlaybackProgressInfo info, UserItemData data) - { - if (user.Configuration.RememberAudioSelections) - { - data.AudioStreamIndex = info.AudioStreamIndex; - } - else - { - data.AudioStreamIndex = null; - } - - if (user.Configuration.RememberSubtitleSelections) - { - data.SubtitleStreamIndex = info.SubtitleStreamIndex; - } - else - { - data.SubtitleStreamIndex = null; - } - } - - /// <summary> - /// Used to report that playback has ended for an item - /// </summary> - /// <param name="info">The info.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">info</exception> - /// <exception cref="System.ArgumentOutOfRangeException">positionTicks</exception> - public async Task OnPlaybackStopped(PlaybackStopInfo info) - { - if (info == null) - { - throw new ArgumentNullException("info"); - } - - if (info.PositionTicks.HasValue && info.PositionTicks.Value < 0) - { - throw new ArgumentOutOfRangeException("positionTicks"); - } - - var session = GetSession(info.SessionId); - - var libraryItem = string.IsNullOrWhiteSpace(info.ItemId) - ? null - : _libraryManager.GetItemById(new Guid(info.ItemId)); - - // Normalize - if (string.IsNullOrWhiteSpace(info.MediaSourceId)) - { - info.MediaSourceId = info.ItemId; - } - - if (!string.IsNullOrWhiteSpace(info.ItemId) && info.Item == null && libraryItem != null) - { - var current = session.NowPlayingItem; - - if (current == null || !string.Equals(current.Id, info.ItemId, StringComparison.OrdinalIgnoreCase)) - { - MediaSourceInfo mediaSource = null; - - var hasMediaSources = libraryItem as IHasMediaSources; - if (hasMediaSources != null) - { - mediaSource = await GetMediaSource(hasMediaSources, info.MediaSourceId, info.LiveStreamId).ConfigureAwait(false); - } - - info.Item = GetItemInfo(libraryItem, libraryItem, mediaSource); - } - else - { - info.Item = current; - } - } - - RemoveNowPlayingItem(session); - - var users = GetUsers(session); - var playedToCompletion = false; - - if (libraryItem != null) - { - foreach (var user in users) - { - playedToCompletion = await OnPlaybackStopped(user.Id, libraryItem, info.PositionTicks, info.Failed).ConfigureAwait(false); - } - } - - if (!string.IsNullOrWhiteSpace(info.LiveStreamId)) - { - try - { - await _mediaSourceManager.CloseLiveStream(info.LiveStreamId).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error closing live stream", ex); - } - } - - EventHelper.QueueEventIfNotNull(PlaybackStopped, this, new PlaybackStopEventArgs - { - Item = libraryItem, - Users = users, - PlaybackPositionTicks = info.PositionTicks, - PlayedToCompletion = playedToCompletion, - MediaSourceId = info.MediaSourceId, - MediaInfo = info.Item, - DeviceName = session.DeviceName, - ClientName = session.Client, - DeviceId = session.DeviceId - - }, _logger); - - await SendPlaybackStoppedNotification(session, CancellationToken.None).ConfigureAwait(false); - } - - private async Task<bool> OnPlaybackStopped(Guid userId, BaseItem item, long? positionTicks, bool playbackFailed) - { - bool playedToCompletion = false; - - if (!playbackFailed) - { - var data = _userDataManager.GetUserData(userId, item); - - if (positionTicks.HasValue) - { - playedToCompletion = _userDataManager.UpdatePlayState(item, data, positionTicks.Value); - } - else - { - // If the client isn't able to report this, then we'll just have to make an assumption - data.PlayCount++; - data.Played = item.SupportsPlayedStatus; - data.PlaybackPositionTicks = 0; - playedToCompletion = true; - } - - await _userDataManager.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackFinished, CancellationToken.None).ConfigureAwait(false); - } - - return playedToCompletion; - } - - /// <summary> - /// Gets the session. - /// </summary> - /// <param name="sessionId">The session identifier.</param> - /// <param name="throwOnMissing">if set to <c>true</c> [throw on missing].</param> - /// <returns>SessionInfo.</returns> - /// <exception cref="ResourceNotFoundException"></exception> - private SessionInfo GetSession(string sessionId, bool throwOnMissing = true) - { - var session = Sessions.FirstOrDefault(i => string.Equals(i.Id, sessionId)); - - if (session == null && throwOnMissing) - { - throw new ResourceNotFoundException(string.Format("Session {0} not found.", sessionId)); - } - - return session; - } - - private SessionInfo GetSessionToRemoteControl(string sessionId) - { - // Accept either device id or session id - var session = Sessions.FirstOrDefault(i => string.Equals(i.Id, sessionId)); - - if (session == null) - { - throw new ResourceNotFoundException(string.Format("Session {0} not found.", sessionId)); - } - - return session; - } - - public Task SendMessageCommand(string controllingSessionId, string sessionId, MessageCommand command, CancellationToken cancellationToken) - { - var generalCommand = new GeneralCommand - { - Name = GeneralCommandType.DisplayMessage.ToString() - }; - - generalCommand.Arguments["Header"] = command.Header; - generalCommand.Arguments["Text"] = command.Text; - - if (command.TimeoutMs.HasValue) - { - generalCommand.Arguments["TimeoutMs"] = command.TimeoutMs.Value.ToString(CultureInfo.InvariantCulture); - } - - return SendGeneralCommand(controllingSessionId, sessionId, generalCommand, cancellationToken); - } - - public Task SendGeneralCommand(string controllingSessionId, string sessionId, GeneralCommand command, CancellationToken cancellationToken) - { - var session = GetSessionToRemoteControl(sessionId); - - var controllingSession = GetSession(controllingSessionId); - AssertCanControl(session, controllingSession); - - return session.SessionController.SendGeneralCommand(command, cancellationToken); - } - - public async Task SendPlayCommand(string controllingSessionId, string sessionId, PlayRequest command, CancellationToken cancellationToken) - { - var session = GetSessionToRemoteControl(sessionId); - - var user = session.UserId.HasValue ? _userManager.GetUserById(session.UserId.Value) : null; - - List<BaseItem> items; - - if (command.PlayCommand == PlayCommand.PlayInstantMix) - { - items = command.ItemIds.SelectMany(i => TranslateItemForInstantMix(i, user)) - .Where(i => i.LocationType != LocationType.Virtual) - .ToList(); - - command.PlayCommand = PlayCommand.PlayNow; - } - else - { - var list = new List<BaseItem>(); - foreach (var itemId in command.ItemIds) - { - var subItems = await TranslateItemForPlayback(itemId, user).ConfigureAwait(false); - list.AddRange(subItems); - } - - items = list - .Where(i => i.LocationType != LocationType.Virtual) - .ToList(); - } - - if (command.PlayCommand == PlayCommand.PlayShuffle) - { - items = items.OrderBy(i => Guid.NewGuid()).ToList(); - command.PlayCommand = PlayCommand.PlayNow; - } - - command.ItemIds = items.Select(i => i.Id.ToString("N")).ToArray(); - - if (user != null) - { - if (items.Any(i => i.GetPlayAccess(user) != PlayAccess.Full)) - { - throw new ArgumentException(string.Format("{0} is not allowed to play media.", user.Name)); - } - } - - if (command.PlayCommand != PlayCommand.PlayNow) - { - if (items.Any(i => !session.QueueableMediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase))) - { - throw new ArgumentException(string.Format("{0} is unable to queue the requested media type.", session.DeviceName ?? session.Id)); - } - } - else - { - if (items.Any(i => !session.PlayableMediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase))) - { - throw new ArgumentException(string.Format("{0} is unable to play the requested media type.", session.DeviceName ?? session.Id)); - } - } - - if (user != null && command.ItemIds.Length == 1 && user.Configuration.EnableNextEpisodeAutoPlay) - { - var episode = _libraryManager.GetItemById(command.ItemIds[0]) as Episode; - if (episode != null) - { - var series = episode.Series; - if (series != null) - { - var episodes = series.GetEpisodes(user) - .Where(i => !i.IsVirtualItem) - .SkipWhile(i => i.Id != episode.Id) - .ToList(); - - if (episodes.Count > 0) - { - command.ItemIds = episodes.Select(i => i.Id.ToString("N")).ToArray(); - } - } - } - } - - var controllingSession = GetSession(controllingSessionId); - AssertCanControl(session, controllingSession); - if (controllingSession.UserId.HasValue) - { - command.ControllingUserId = controllingSession.UserId.Value.ToString("N"); - } - - await session.SessionController.SendPlayCommand(command, cancellationToken).ConfigureAwait(false); - } - - private async Task<List<BaseItem>> TranslateItemForPlayback(string id, User user) - { - var item = _libraryManager.GetItemById(id); - - if (item == null) - { - _logger.Error("A non-existant item Id {0} was passed into TranslateItemForPlayback", id); - return new List<BaseItem>(); - } - - var byName = item as IItemByName; - - if (byName != null) - { - var items = byName.GetTaggedItems(new InternalItemsQuery(user) - { - IsFolder = false, - Recursive = true - }); - - return FilterToSingleMediaType(items) - .OrderBy(i => i.SortName) - .ToList(); - } - - if (item.IsFolder) - { - var folder = (Folder)item; - - var itemsResult = await folder.GetItems(new InternalItemsQuery(user) - { - Recursive = true, - IsFolder = false - - }).ConfigureAwait(false); - - return FilterToSingleMediaType(itemsResult.Items) - .OrderBy(i => i.SortName) - .ToList(); - } - - return new List<BaseItem> { item }; - } - - private IEnumerable<BaseItem> FilterToSingleMediaType(IEnumerable<BaseItem> items) - { - return items - .Where(i => !string.IsNullOrWhiteSpace(i.MediaType)) - .ToLookup(i => i.MediaType, StringComparer.OrdinalIgnoreCase) - .OrderByDescending(i => i.Count()) - .FirstOrDefault(); - } - - private IEnumerable<BaseItem> TranslateItemForInstantMix(string id, User user) - { - var item = _libraryManager.GetItemById(id); - - if (item == null) - { - _logger.Error("A non-existant item Id {0} was passed into TranslateItemForInstantMix", id); - return new List<BaseItem>(); - } - - return _musicManager.GetInstantMixFromItem(item, user); - } - - public Task SendBrowseCommand(string controllingSessionId, string sessionId, BrowseRequest command, CancellationToken cancellationToken) - { - var generalCommand = new GeneralCommand - { - Name = GeneralCommandType.DisplayContent.ToString() - }; - - generalCommand.Arguments["ItemId"] = command.ItemId; - generalCommand.Arguments["ItemName"] = command.ItemName; - generalCommand.Arguments["ItemType"] = command.ItemType; - - return SendGeneralCommand(controllingSessionId, sessionId, generalCommand, cancellationToken); - } - - public Task SendPlaystateCommand(string controllingSessionId, string sessionId, PlaystateRequest command, CancellationToken cancellationToken) - { - var session = GetSessionToRemoteControl(sessionId); - - var controllingSession = GetSession(controllingSessionId); - AssertCanControl(session, controllingSession); - if (controllingSession.UserId.HasValue) - { - command.ControllingUserId = controllingSession.UserId.Value.ToString("N"); - } - - return session.SessionController.SendPlaystateCommand(command, cancellationToken); - } - - private void AssertCanControl(SessionInfo session, SessionInfo controllingSession) - { - if (session == null) - { - throw new ArgumentNullException("session"); - } - if (controllingSession == null) - { - throw new ArgumentNullException("controllingSession"); - } - } - - /// <summary> - /// Sends the restart required message. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task SendRestartRequiredNotification(CancellationToken cancellationToken) - { - var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList(); - - var info = await _appHost.GetSystemInfo().ConfigureAwait(false); - - var tasks = sessions.Select(session => Task.Run(async () => - { - try - { - await session.SessionController.SendRestartRequiredNotification(info, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error in SendRestartRequiredNotification.", ex); - } - - }, cancellationToken)); - - await Task.WhenAll(tasks).ConfigureAwait(false); - } - - /// <summary> - /// Sends the server shutdown notification. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task SendServerShutdownNotification(CancellationToken cancellationToken) - { - var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList(); - - var tasks = sessions.Select(session => Task.Run(async () => - { - try - { - await session.SessionController.SendServerShutdownNotification(cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error in SendServerShutdownNotification.", ex); - } - - }, cancellationToken)); - - return Task.WhenAll(tasks); - } - - /// <summary> - /// Sends the server restart notification. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task SendServerRestartNotification(CancellationToken cancellationToken) - { - _logger.Debug("Beginning SendServerRestartNotification"); - - var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList(); - - var tasks = sessions.Select(session => Task.Run(async () => - { - try - { - await session.SessionController.SendServerRestartNotification(cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error in SendServerRestartNotification.", ex); - } - - }, cancellationToken)); - - return Task.WhenAll(tasks); - } - - public Task SendSessionEndedNotification(SessionInfo sessionInfo, CancellationToken cancellationToken) - { - var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList(); - var dto = GetSessionInfoDto(sessionInfo); - - var tasks = sessions.Select(session => Task.Run(async () => - { - try - { - await session.SessionController.SendSessionEndedNotification(dto, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error in SendSessionEndedNotification.", ex); - } - - }, cancellationToken)); - - return Task.WhenAll(tasks); - } - - public Task SendPlaybackStartNotification(SessionInfo sessionInfo, CancellationToken cancellationToken) - { - var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList(); - var dto = GetSessionInfoDto(sessionInfo); - - var tasks = sessions.Select(session => Task.Run(async () => - { - try - { - await session.SessionController.SendPlaybackStartNotification(dto, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error in SendPlaybackStartNotification.", ex); - } - - }, cancellationToken)); - - return Task.WhenAll(tasks); - } - - public Task SendPlaybackStoppedNotification(SessionInfo sessionInfo, CancellationToken cancellationToken) - { - var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList(); - var dto = GetSessionInfoDto(sessionInfo); - - var tasks = sessions.Select(session => Task.Run(async () => - { - try - { - await session.SessionController.SendPlaybackStoppedNotification(dto, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error in SendPlaybackStoppedNotification.", ex); - } - - }, cancellationToken)); - - return Task.WhenAll(tasks); - } - - /// <summary> - /// Adds the additional user. - /// </summary> - /// <param name="sessionId">The session identifier.</param> - /// <param name="userId">The user identifier.</param> - /// <exception cref="System.UnauthorizedAccessException">Cannot modify additional users without authenticating first.</exception> - /// <exception cref="System.ArgumentException">The requested user is already the primary user of the session.</exception> - public void AddAdditionalUser(string sessionId, string userId) - { - var session = GetSession(sessionId); - - if (session.UserId.HasValue && session.UserId.Value == new Guid(userId)) - { - throw new ArgumentException("The requested user is already the primary user of the session."); - } - - if (session.AdditionalUsers.All(i => new Guid(i.UserId) != new Guid(userId))) - { - var user = _userManager.GetUserById(userId); - - session.AdditionalUsers.Add(new SessionUserInfo - { - UserId = userId, - UserName = user.Name - }); - } - } - - /// <summary> - /// Removes the additional user. - /// </summary> - /// <param name="sessionId">The session identifier.</param> - /// <param name="userId">The user identifier.</param> - /// <exception cref="System.UnauthorizedAccessException">Cannot modify additional users without authenticating first.</exception> - /// <exception cref="System.ArgumentException">The requested user is already the primary user of the session.</exception> - public void RemoveAdditionalUser(string sessionId, string userId) - { - var session = GetSession(sessionId); - - if (session.UserId.HasValue && session.UserId.Value == new Guid(userId)) - { - throw new ArgumentException("The requested user is already the primary user of the session."); - } - - var user = session.AdditionalUsers.FirstOrDefault(i => new Guid(i.UserId) == new Guid(userId)); - - if (user != null) - { - session.AdditionalUsers.Remove(user); - } - } - - /// <summary> - /// Authenticates the new session. - /// </summary> - /// <param name="request">The request.</param> - /// <returns>Task{SessionInfo}.</returns> - public Task<AuthenticationResult> AuthenticateNewSession(AuthenticationRequest request) - { - return AuthenticateNewSessionInternal(request, true); - } - - public Task<AuthenticationResult> CreateNewSession(AuthenticationRequest request) - { - return AuthenticateNewSessionInternal(request, false); - } - - private async Task<AuthenticationResult> AuthenticateNewSessionInternal(AuthenticationRequest request, bool enforcePassword) - { - User user = null; - if (!string.IsNullOrWhiteSpace(request.UserId)) - { - var idGuid = new Guid(request.UserId); - user = _userManager.Users - .FirstOrDefault(i => i.Id == idGuid); - } - - if (user == null) - { - user = _userManager.Users - .FirstOrDefault(i => string.Equals(request.Username, i.Name, StringComparison.OrdinalIgnoreCase)); - } - - if (user != null && !string.IsNullOrWhiteSpace(request.DeviceId)) - { - if (!_deviceManager.CanAccessDevice(user.Id.ToString("N"), request.DeviceId)) - { - throw new SecurityException("User is not allowed access from this device."); - } - } - - if (enforcePassword) - { - var result = await _userManager.AuthenticateUser(request.Username, request.PasswordSha1, request.PasswordMd5, request.RemoteEndPoint).ConfigureAwait(false); - - if (!result) - { - EventHelper.FireEventIfNotNull(AuthenticationFailed, this, new GenericEventArgs<AuthenticationRequest>(request), _logger); - - throw new SecurityException("Invalid user or password entered."); - } - } - - var token = await GetAuthorizationToken(user.Id.ToString("N"), request.DeviceId, request.App, request.AppVersion, request.DeviceName).ConfigureAwait(false); - - EventHelper.FireEventIfNotNull(AuthenticationSucceeded, this, new GenericEventArgs<AuthenticationRequest>(request), _logger); - - var session = await LogSessionActivity(request.App, - request.AppVersion, - request.DeviceId, - request.DeviceName, - request.RemoteEndPoint, - user) - .ConfigureAwait(false); - - return new AuthenticationResult - { - User = _userManager.GetUserDto(user, request.RemoteEndPoint), - SessionInfo = GetSessionInfoDto(session), - AccessToken = token, - ServerId = _appHost.SystemId - }; - } - - - private async Task<string> GetAuthorizationToken(string userId, string deviceId, string app, string appVersion, string deviceName) - { - var existing = _authRepo.Get(new AuthenticationInfoQuery - { - DeviceId = deviceId, - IsActive = true, - UserId = userId, - Limit = 1 - }); - - if (existing.Items.Length > 0) - { - var token = existing.Items[0].AccessToken; - _logger.Info("Reissuing access token: " + token); - return token; - } - - var newToken = new AuthenticationInfo - { - AppName = app, - AppVersion = appVersion, - DateCreated = DateTime.UtcNow, - DeviceId = deviceId, - DeviceName = deviceName, - UserId = userId, - IsActive = true, - AccessToken = Guid.NewGuid().ToString("N") - }; - - _logger.Info("Creating new access token for user {0}", userId); - await _authRepo.Create(newToken, CancellationToken.None).ConfigureAwait(false); - - return newToken.AccessToken; - } - - public async Task Logout(string accessToken) - { - if (string.IsNullOrWhiteSpace(accessToken)) - { - throw new ArgumentNullException("accessToken"); - } - - _logger.Info("Logging out access token {0}", accessToken); - - var existing = _authRepo.Get(new AuthenticationInfoQuery - { - Limit = 1, - AccessToken = accessToken - - }).Items.FirstOrDefault(); - - if (existing != null) - { - existing.IsActive = false; - - await _authRepo.Update(existing, CancellationToken.None).ConfigureAwait(false); - - var sessions = Sessions - .Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase)) - .ToList(); - - foreach (var session in sessions) - { - try - { - ReportSessionEnded(session.Id); - } - catch (Exception ex) - { - _logger.ErrorException("Error reporting session ended", ex); - } - } - } - } - - public async Task RevokeUserTokens(string userId, string currentAccessToken) - { - var existing = _authRepo.Get(new AuthenticationInfoQuery - { - IsActive = true, - UserId = userId - }); - - foreach (var info in existing.Items) - { - if (!string.Equals(currentAccessToken, info.AccessToken, StringComparison.OrdinalIgnoreCase)) - { - await Logout(info.AccessToken).ConfigureAwait(false); - } - } - } - - public Task RevokeToken(string token) - { - return Logout(token); - } - - /// <summary> - /// Reports the capabilities. - /// </summary> - /// <param name="sessionId">The session identifier.</param> - /// <param name="capabilities">The capabilities.</param> - public void ReportCapabilities(string sessionId, ClientCapabilities capabilities) - { - var session = GetSession(sessionId); - - ReportCapabilities(session, capabilities, true); - } - - private async void ReportCapabilities(SessionInfo session, - ClientCapabilities capabilities, - bool saveCapabilities) - { - session.Capabilities = capabilities; - - if (!string.IsNullOrWhiteSpace(capabilities.MessageCallbackUrl)) - { - var controller = session.SessionController as HttpSessionController; - - if (controller == null) - { - session.SessionController = new HttpSessionController(_httpClient, _jsonSerializer, session, capabilities.MessageCallbackUrl, this); - } - } - - EventHelper.FireEventIfNotNull(CapabilitiesChanged, this, new SessionEventArgs - { - SessionInfo = session - - }, _logger); - - if (saveCapabilities) - { - try - { - await SaveCapabilities(session.DeviceId, capabilities).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error saving device capabilities", ex); - } - } - } - - private ClientCapabilities GetSavedCapabilities(string deviceId) - { - return _deviceManager.GetCapabilities(deviceId); - } - - private Task SaveCapabilities(string deviceId, ClientCapabilities capabilities) - { - return _deviceManager.SaveCapabilities(deviceId, capabilities); - } - - public SessionInfoDto GetSessionInfoDto(SessionInfo session) - { - var dto = new SessionInfoDto - { - Client = session.Client, - DeviceId = session.DeviceId, - DeviceName = session.DeviceName, - Id = session.Id, - LastActivityDate = session.LastActivityDate, - NowViewingItem = session.NowViewingItem, - ApplicationVersion = session.ApplicationVersion, - QueueableMediaTypes = session.QueueableMediaTypes, - PlayableMediaTypes = session.PlayableMediaTypes, - AdditionalUsers = session.AdditionalUsers, - SupportedCommands = session.SupportedCommands, - UserName = session.UserName, - NowPlayingItem = session.NowPlayingItem, - SupportsRemoteControl = session.SupportsMediaControl, - PlayState = session.PlayState, - AppIconUrl = session.AppIconUrl, - TranscodingInfo = session.NowPlayingItem == null ? null : session.TranscodingInfo - }; - - if (session.UserId.HasValue) - { - dto.UserId = session.UserId.Value.ToString("N"); - - var user = _userManager.GetUserById(session.UserId.Value); - - if (user != null) - { - dto.UserPrimaryImageTag = GetImageCacheTag(user, ImageType.Primary); - } - } - - return dto; - } - - /// <summary> - /// Converts a BaseItem to a BaseItemInfo - /// </summary> - /// <param name="item">The item.</param> - /// <param name="chapterOwner">The chapter owner.</param> - /// <param name="mediaSource">The media source.</param> - /// <returns>BaseItemInfo.</returns> - /// <exception cref="System.ArgumentNullException">item</exception> - private BaseItemInfo GetItemInfo(BaseItem item, BaseItem chapterOwner, MediaSourceInfo mediaSource) - { - if (item == null) - { - throw new ArgumentNullException("item"); - } - - var info = new BaseItemInfo - { - Id = GetDtoId(item), - Name = item.Name, - MediaType = item.MediaType, - Type = item.GetClientTypeName(), - RunTimeTicks = item.RunTimeTicks, - IndexNumber = item.IndexNumber, - ParentIndexNumber = item.ParentIndexNumber, - PremiereDate = item.PremiereDate, - ProductionYear = item.ProductionYear - }; - - info.PrimaryImageTag = GetImageCacheTag(item, ImageType.Primary); - if (info.PrimaryImageTag != null) - { - info.PrimaryImageItemId = GetDtoId(item); - } - - var episode = item as Episode; - if (episode != null) - { - info.IndexNumberEnd = episode.IndexNumberEnd; - } - - var hasSeries = item as IHasSeries; - if (hasSeries != null) - { - info.SeriesName = hasSeries.SeriesName; - } - - var recording = item as ILiveTvRecording; - if (recording != null) - { - if (recording.IsSeries) - { - info.Name = recording.EpisodeTitle; - info.SeriesName = recording.Name; - - if (string.IsNullOrWhiteSpace(info.Name)) - { - info.Name = recording.Name; - } - } - } - - var audio = item as Audio; - if (audio != null) - { - info.Album = audio.Album; - info.Artists = audio.Artists; - - if (info.PrimaryImageTag == null) - { - var album = audio.AlbumEntity; - - if (album != null && album.HasImage(ImageType.Primary)) - { - info.PrimaryImageTag = GetImageCacheTag(album, ImageType.Primary); - if (info.PrimaryImageTag != null) - { - info.PrimaryImageItemId = GetDtoId(album); - } - } - } - } - - var musicVideo = item as MusicVideo; - if (musicVideo != null) - { - info.Album = musicVideo.Album; - info.Artists = musicVideo.Artists.ToList(); - } - - var backropItem = item.HasImage(ImageType.Backdrop) ? item : null; - var thumbItem = item.HasImage(ImageType.Thumb) ? item : null; - var logoItem = item.HasImage(ImageType.Logo) ? item : null; - - if (thumbItem == null) - { - if (episode != null) - { - var series = episode.Series; - - if (series != null && series.HasImage(ImageType.Thumb)) - { - thumbItem = series; - } - } - } - - if (backropItem == null) - { - if (episode != null) - { - var series = episode.Series; - - if (series != null && series.HasImage(ImageType.Backdrop)) - { - backropItem = series; - } - } - } - - if (backropItem == null) - { - backropItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Backdrop)); - } - - if (thumbItem == null) - { - thumbItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Thumb)); - } - - if (logoItem == null) - { - logoItem = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Logo)); - } - - if (thumbItem != null) - { - info.ThumbImageTag = GetImageCacheTag(thumbItem, ImageType.Thumb); - info.ThumbItemId = GetDtoId(thumbItem); - } - - if (backropItem != null) - { - info.BackdropImageTag = GetImageCacheTag(backropItem, ImageType.Backdrop); - info.BackdropItemId = GetDtoId(backropItem); - } - - if (logoItem != null) - { - info.LogoImageTag = GetImageCacheTag(logoItem, ImageType.Logo); - info.LogoItemId = GetDtoId(logoItem); - } - - if (chapterOwner != null) - { - info.ChapterImagesItemId = chapterOwner.Id.ToString("N"); - - info.Chapters = _dtoService.GetChapterInfoDtos(chapterOwner).ToList(); - } - - if (mediaSource != null) - { - info.MediaStreams = mediaSource.MediaStreams; - } - - return info; - } - - private string GetImageCacheTag(BaseItem item, ImageType type) - { - try - { - return _imageProcessor.GetImageCacheTag(item, type); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting {0} image info", ex, type); - return null; - } - } - - private string GetDtoId(BaseItem item) - { - return _dtoService.GetDtoId(item); - } - - public void ReportNowViewingItem(string sessionId, string itemId) - { - if (string.IsNullOrWhiteSpace(itemId)) - { - throw new ArgumentNullException("itemId"); - } - - var item = _libraryManager.GetItemById(new Guid(itemId)); - - var info = GetItemInfo(item, null, null); - - ReportNowViewingItem(sessionId, info); - } - - public void ReportNowViewingItem(string sessionId, BaseItemInfo item) - { - var session = GetSession(sessionId); - - session.NowViewingItem = item; - } - - public void ReportTranscodingInfo(string deviceId, TranscodingInfo info) - { - var session = Sessions.FirstOrDefault(i => string.Equals(i.DeviceId, deviceId)); - - if (session != null) - { - session.TranscodingInfo = info; - } - } - - public void ClearTranscodingInfo(string deviceId) - { - ReportTranscodingInfo(deviceId, null); - } - - public SessionInfo GetSession(string deviceId, string client, string version) - { - return Sessions.FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) && - string.Equals(i.Client, client)); - } - - public Task<SessionInfo> GetSessionByAuthenticationToken(AuthenticationInfo info, string deviceId, string remoteEndpoint, string appVersion) - { - if (info == null) - { - throw new ArgumentNullException("info"); - } - - var user = string.IsNullOrWhiteSpace(info.UserId) - ? null - : _userManager.GetUserById(info.UserId); - - appVersion = string.IsNullOrWhiteSpace(appVersion) - ? info.AppVersion - : appVersion; - - var deviceName = info.DeviceName; - var appName = info.AppName; - - if (!string.IsNullOrWhiteSpace(deviceId)) - { - // Replace the info from the token with more recent info - var device = _deviceManager.GetDevice(deviceId); - if (device != null) - { - deviceName = device.Name; - appName = device.AppName; - - if (!string.IsNullOrWhiteSpace(device.AppVersion)) - { - appVersion = device.AppVersion; - } - } - } - else - { - deviceId = info.DeviceId; - } - - // Prevent argument exception - if (string.IsNullOrWhiteSpace(appVersion)) - { - appVersion = "1"; - } - - return LogSessionActivity(appName, appVersion, deviceId, deviceName, remoteEndpoint, user); - } - - public Task<SessionInfo> GetSessionByAuthenticationToken(string token, string deviceId, string remoteEndpoint) - { - var result = _authRepo.Get(new AuthenticationInfoQuery - { - AccessToken = token - }); - - var info = result.Items.FirstOrDefault(); - - if (info == null) - { - return Task.FromResult<SessionInfo>(null); - } - - return GetSessionByAuthenticationToken(info, deviceId, remoteEndpoint, null); - } - - public Task SendMessageToAdminSessions<T>(string name, T data, CancellationToken cancellationToken) - { - var adminUserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id.ToString("N")).ToList(); - - return SendMessageToUserSessions(adminUserIds, name, data, cancellationToken); - } - - public Task SendMessageToUserSessions<T>(List<string> userIds, string name, T data, - CancellationToken cancellationToken) - { - var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null && userIds.Any(i.ContainsUser)).ToList(); - - var tasks = sessions.Select(session => Task.Run(async () => - { - try - { - await session.SessionController.SendMessage(name, data, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending message", ex); - } - - }, cancellationToken)); - - return Task.WhenAll(tasks); - } - - public Task SendMessageToUserDeviceSessions<T>(string deviceId, string name, T data, - CancellationToken cancellationToken) - { - var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null && string.Equals(i.DeviceId, deviceId, StringComparison.OrdinalIgnoreCase)).ToList(); - - var tasks = sessions.Select(session => Task.Run(async () => - { - try - { - await session.SessionController.SendMessage(name, data, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending message", ex); - } - - }, cancellationToken)); - - return Task.WhenAll(tasks); - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs deleted file mode 100644 index ddd7ba53a6..0000000000 --- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs +++ /dev/null @@ -1,484 +0,0 @@ -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Session; -using System; -using System.Collections.Specialized; -using System.Globalization; -using System.Linq; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Session -{ - /// <summary> - /// Class SessionWebSocketListener - /// </summary> - public class SessionWebSocketListener : IWebSocketListener, IDisposable - { - /// <summary> - /// The _true task result - /// </summary> - private readonly Task _trueTaskResult = Task.FromResult(true); - - /// <summary> - /// The _session manager - /// </summary> - private readonly ISessionManager _sessionManager; - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - /// <summary> - /// The _dto service - /// </summary> - private readonly IJsonSerializer _json; - - private readonly IHttpServer _httpServer; - private readonly IServerManager _serverManager; - - - /// <summary> - /// Initializes a new instance of the <see cref="SessionWebSocketListener" /> class. - /// </summary> - /// <param name="sessionManager">The session manager.</param> - /// <param name="logManager">The log manager.</param> - /// <param name="json">The json.</param> - /// <param name="httpServer">The HTTP server.</param> - /// <param name="serverManager">The server manager.</param> - public SessionWebSocketListener(ISessionManager sessionManager, ILogManager logManager, IJsonSerializer json, IHttpServer httpServer, IServerManager serverManager) - { - _sessionManager = sessionManager; - _logger = logManager.GetLogger(GetType().Name); - _json = json; - _httpServer = httpServer; - _serverManager = serverManager; - httpServer.WebSocketConnecting += _httpServer_WebSocketConnecting; - serverManager.WebSocketConnected += _serverManager_WebSocketConnected; - } - - async void _serverManager_WebSocketConnected(object sender, GenericEventArgs<IWebSocketConnection> e) - { - var session = await GetSession(e.Argument.QueryString, e.Argument.RemoteEndPoint).ConfigureAwait(false); - - if (session != null) - { - var controller = session.SessionController as WebSocketController; - - if (controller == null) - { - controller = new WebSocketController(session, _logger, _sessionManager); - } - - controller.AddWebSocket(e.Argument); - - session.SessionController = controller; - } - else - { - _logger.Warn("Unable to determine session based on url: {0}", e.Argument.Url); - } - } - - async void _httpServer_WebSocketConnecting(object sender, WebSocketConnectingEventArgs e) - { - //var token = e.QueryString["api_key"]; - //if (!string.IsNullOrWhiteSpace(token)) - //{ - // try - // { - // var session = await GetSession(e.QueryString, e.Endpoint).ConfigureAwait(false); - - // if (session == null) - // { - // e.AllowConnection = false; - // } - // } - // catch (Exception ex) - // { - // _logger.ErrorException("Error getting session info", ex); - // } - //} - } - - private Task<SessionInfo> GetSession(NameValueCollection queryString, string remoteEndpoint) - { - if (queryString == null) - { - throw new ArgumentNullException("queryString"); - } - - var token = queryString["api_key"]; - if (string.IsNullOrWhiteSpace(token)) - { - return Task.FromResult<SessionInfo>(null); - } - var deviceId = queryString["deviceId"]; - return _sessionManager.GetSessionByAuthenticationToken(token, deviceId, remoteEndpoint); - } - - public void Dispose() - { - _httpServer.WebSocketConnecting -= _httpServer_WebSocketConnecting; - _serverManager.WebSocketConnected -= _serverManager_WebSocketConnected; - } - - /// <summary> - /// Processes the message. - /// </summary> - /// <param name="message">The message.</param> - /// <returns>Task.</returns> - public Task ProcessMessage(WebSocketMessageInfo message) - { - if (string.Equals(message.MessageType, "Identity", StringComparison.OrdinalIgnoreCase)) - { - ProcessIdentityMessage(message); - } - else if (string.Equals(message.MessageType, "Context", StringComparison.OrdinalIgnoreCase)) - { - ProcessContextMessage(message); - } - else if (string.Equals(message.MessageType, "PlaybackStart", StringComparison.OrdinalIgnoreCase)) - { - OnPlaybackStart(message); - } - else if (string.Equals(message.MessageType, "PlaybackProgress", StringComparison.OrdinalIgnoreCase)) - { - OnPlaybackProgress(message); - } - else if (string.Equals(message.MessageType, "PlaybackStopped", StringComparison.OrdinalIgnoreCase)) - { - OnPlaybackStopped(message); - } - else if (string.Equals(message.MessageType, "ReportPlaybackStart", StringComparison.OrdinalIgnoreCase)) - { - ReportPlaybackStart(message); - } - else if (string.Equals(message.MessageType, "ReportPlaybackProgress", StringComparison.OrdinalIgnoreCase)) - { - ReportPlaybackProgress(message); - } - else if (string.Equals(message.MessageType, "ReportPlaybackStopped", StringComparison.OrdinalIgnoreCase)) - { - ReportPlaybackStopped(message); - } - - return _trueTaskResult; - } - - /// <summary> - /// Processes the identity message. - /// </summary> - /// <param name="message">The message.</param> - private async void ProcessIdentityMessage(WebSocketMessageInfo message) - { - _logger.Debug("Received Identity message: " + message.Data); - - var vals = message.Data.Split('|'); - - if (vals.Length < 3) - { - _logger.Error("Client sent invalid identity message."); - return; - } - - var client = vals[0]; - var deviceId = vals[1]; - var version = vals[2]; - var deviceName = vals.Length > 3 ? vals[3] : string.Empty; - - var session = _sessionManager.GetSession(deviceId, client, version); - - if (session == null && !string.IsNullOrEmpty(deviceName)) - { - _logger.Debug("Logging session activity"); - - session = await _sessionManager.LogSessionActivity(client, version, deviceId, deviceName, message.Connection.RemoteEndPoint, null).ConfigureAwait(false); - } - - if (session != null) - { - var controller = session.SessionController as WebSocketController; - - if (controller == null) - { - controller = new WebSocketController(session, _logger, _sessionManager); - } - - controller.AddWebSocket(message.Connection); - - session.SessionController = controller; - } - else - { - _logger.Warn("Unable to determine session based on identity message: {0}", message.Data); - } - } - - /// <summary> - /// Processes the context message. - /// </summary> - /// <param name="message">The message.</param> - private void ProcessContextMessage(WebSocketMessageInfo message) - { - var session = GetSessionFromMessage(message); - - if (session != null) - { - var vals = message.Data.Split('|'); - - var itemId = vals[1]; - - if (!string.IsNullOrWhiteSpace(itemId)) - { - _sessionManager.ReportNowViewingItem(session.Id, itemId); - } - } - } - - /// <summary> - /// Gets the session from message. - /// </summary> - /// <param name="message">The message.</param> - /// <returns>SessionInfo.</returns> - private SessionInfo GetSessionFromMessage(WebSocketMessageInfo message) - { - var result = _sessionManager.Sessions.FirstOrDefault(i => - { - var controller = i.SessionController as WebSocketController; - - if (controller != null) - { - if (controller.Sockets.Any(s => s.Id == message.Connection.Id)) - { - return true; - } - } - - return false; - - }); - - if (result == null) - { - _logger.Error("Unable to find session based on web socket message"); - } - - return result; - } - - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - /// <summary> - /// Reports the playback start. - /// </summary> - /// <param name="message">The message.</param> - private void OnPlaybackStart(WebSocketMessageInfo message) - { - _logger.Debug("Received PlaybackStart message"); - - var session = GetSessionFromMessage(message); - - if (session != null && session.UserId.HasValue) - { - var vals = message.Data.Split('|'); - - var itemId = vals[0]; - - var queueableMediaTypes = string.Empty; - var canSeek = true; - - if (vals.Length > 1) - { - canSeek = string.Equals(vals[1], "true", StringComparison.OrdinalIgnoreCase); - } - if (vals.Length > 2) - { - queueableMediaTypes = vals[2]; - } - - var info = new PlaybackStartInfo - { - CanSeek = canSeek, - ItemId = itemId, - SessionId = session.Id, - QueueableMediaTypes = queueableMediaTypes.Split(',').ToList() - }; - - if (vals.Length > 3) - { - info.MediaSourceId = vals[3]; - } - - if (vals.Length > 4 && !string.IsNullOrWhiteSpace(vals[4])) - { - info.AudioStreamIndex = int.Parse(vals[4], _usCulture); - } - - if (vals.Length > 5 && !string.IsNullOrWhiteSpace(vals[5])) - { - info.SubtitleStreamIndex = int.Parse(vals[5], _usCulture); - } - - _sessionManager.OnPlaybackStart(info); - } - } - - private void ReportPlaybackStart(WebSocketMessageInfo message) - { - _logger.Debug("Received ReportPlaybackStart message"); - - var session = GetSessionFromMessage(message); - - if (session != null && session.UserId.HasValue) - { - var info = _json.DeserializeFromString<PlaybackStartInfo>(message.Data); - - info.SessionId = session.Id; - - _sessionManager.OnPlaybackStart(info); - } - } - - private void ReportPlaybackProgress(WebSocketMessageInfo message) - { - //_logger.Debug("Received ReportPlaybackProgress message"); - - var session = GetSessionFromMessage(message); - - if (session != null && session.UserId.HasValue) - { - var info = _json.DeserializeFromString<PlaybackProgressInfo>(message.Data); - - info.SessionId = session.Id; - - _sessionManager.OnPlaybackProgress(info); - } - } - - /// <summary> - /// Reports the playback progress. - /// </summary> - /// <param name="message">The message.</param> - private void OnPlaybackProgress(WebSocketMessageInfo message) - { - var session = GetSessionFromMessage(message); - - if (session != null && session.UserId.HasValue) - { - var vals = message.Data.Split('|'); - - var itemId = vals[0]; - - long? positionTicks = null; - - if (vals.Length > 1) - { - long pos; - - if (long.TryParse(vals[1], out pos)) - { - positionTicks = pos; - } - } - - var isPaused = vals.Length > 2 && string.Equals(vals[2], "true", StringComparison.OrdinalIgnoreCase); - var isMuted = vals.Length > 3 && string.Equals(vals[3], "true", StringComparison.OrdinalIgnoreCase); - - var info = new PlaybackProgressInfo - { - ItemId = itemId, - PositionTicks = positionTicks, - IsMuted = isMuted, - IsPaused = isPaused, - SessionId = session.Id - }; - - if (vals.Length > 4) - { - info.MediaSourceId = vals[4]; - } - - if (vals.Length > 5 && !string.IsNullOrWhiteSpace(vals[5])) - { - info.VolumeLevel = int.Parse(vals[5], _usCulture); - } - - if (vals.Length > 5 && !string.IsNullOrWhiteSpace(vals[6])) - { - info.AudioStreamIndex = int.Parse(vals[6], _usCulture); - } - - if (vals.Length > 7 && !string.IsNullOrWhiteSpace(vals[7])) - { - info.SubtitleStreamIndex = int.Parse(vals[7], _usCulture); - } - - _sessionManager.OnPlaybackProgress(info); - } - } - - private void ReportPlaybackStopped(WebSocketMessageInfo message) - { - _logger.Debug("Received ReportPlaybackStopped message"); - - var session = GetSessionFromMessage(message); - - if (session != null && session.UserId.HasValue) - { - var info = _json.DeserializeFromString<PlaybackStopInfo>(message.Data); - - info.SessionId = session.Id; - - _sessionManager.OnPlaybackStopped(info); - } - } - - /// <summary> - /// Reports the playback stopped. - /// </summary> - /// <param name="message">The message.</param> - private void OnPlaybackStopped(WebSocketMessageInfo message) - { - _logger.Debug("Received PlaybackStopped message"); - - var session = GetSessionFromMessage(message); - - if (session != null && session.UserId.HasValue) - { - var vals = message.Data.Split('|'); - - var itemId = vals[0]; - - long? positionTicks = null; - - if (vals.Length > 1) - { - long pos; - - if (long.TryParse(vals[1], out pos)) - { - positionTicks = pos; - } - } - - var info = new PlaybackStopInfo - { - ItemId = itemId, - PositionTicks = positionTicks, - SessionId = session.Id - }; - - if (vals.Length > 2) - { - info.MediaSourceId = vals[2]; - } - - _sessionManager.OnPlaybackStopped(info); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs deleted file mode 100644 index 765664299e..0000000000 --- a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs +++ /dev/null @@ -1,288 +0,0 @@ -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Session; -using MediaBrowser.Model.System; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Session -{ - public class WebSocketController : ISessionController, IDisposable - { - public SessionInfo Session { get; private set; } - public IReadOnlyList<IWebSocketConnection> Sockets { get; private set; } - - private readonly ILogger _logger; - - private readonly ISessionManager _sessionManager; - - public WebSocketController(SessionInfo session, ILogger logger, ISessionManager sessionManager) - { - Session = session; - _logger = logger; - _sessionManager = sessionManager; - Sockets = new List<IWebSocketConnection>(); - } - - private bool HasOpenSockets - { - get { return GetActiveSockets().Any(); } - } - - public bool SupportsMediaControl - { - get { return HasOpenSockets; } - } - - private bool _isActive; - private DateTime _lastActivityDate; - public bool IsSessionActive - { - get - { - if (HasOpenSockets) - { - return true; - } - - //return false; - return _isActive && (DateTime.UtcNow - _lastActivityDate).TotalMinutes <= 10; - } - } - - public void OnActivity() - { - _isActive = true; - _lastActivityDate = DateTime.UtcNow; - } - - private IEnumerable<IWebSocketConnection> GetActiveSockets() - { - return Sockets - .OrderByDescending(i => i.LastActivityDate) - .Where(i => i.State == WebSocketState.Open); - } - - public void AddWebSocket(IWebSocketConnection connection) - { - var sockets = Sockets.ToList(); - sockets.Add(connection); - - Sockets = sockets; - - connection.Closed += connection_Closed; - } - - void connection_Closed(object sender, EventArgs e) - { - if (!GetActiveSockets().Any()) - { - _isActive = false; - - try - { - _sessionManager.ReportSessionEnded(Session.Id); - } - catch (Exception ex) - { - _logger.ErrorException("Error reporting session ended.", ex); - } - } - } - - private IWebSocketConnection GetActiveSocket() - { - var socket = GetActiveSockets() - .FirstOrDefault(); - - if (socket == null) - { - throw new InvalidOperationException("The requested session does not have an open web socket."); - } - - return socket; - } - - public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken) - { - return SendMessageInternal(new WebSocketMessage<PlayRequest> - { - MessageType = "Play", - Data = command - - }, cancellationToken); - } - - public Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken) - { - return SendMessageInternal(new WebSocketMessage<PlaystateRequest> - { - MessageType = "Playstate", - Data = command - - }, cancellationToken); - } - - public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken) - { - return SendMessagesInternal(new WebSocketMessage<LibraryUpdateInfo> - { - MessageType = "LibraryChanged", - Data = info - - }, cancellationToken); - } - - /// <summary> - /// Sends the restart required message. - /// </summary> - /// <param name="info">The information.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken) - { - return SendMessagesInternal(new WebSocketMessage<SystemInfo> - { - MessageType = "RestartRequired", - Data = info - - }, cancellationToken); - } - - - /// <summary> - /// Sends the user data change info. - /// </summary> - /// <param name="info">The info.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task SendUserDataChangeInfo(UserDataChangeInfo info, CancellationToken cancellationToken) - { - return SendMessagesInternal(new WebSocketMessage<UserDataChangeInfo> - { - MessageType = "UserDataChanged", - Data = info - - }, cancellationToken); - } - - /// <summary> - /// Sends the server shutdown notification. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task SendServerShutdownNotification(CancellationToken cancellationToken) - { - return SendMessagesInternal(new WebSocketMessage<string> - { - MessageType = "ServerShuttingDown", - Data = string.Empty - - }, cancellationToken); - } - - /// <summary> - /// Sends the server restart notification. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task SendServerRestartNotification(CancellationToken cancellationToken) - { - return SendMessagesInternal(new WebSocketMessage<string> - { - MessageType = "ServerRestarting", - Data = string.Empty - - }, cancellationToken); - } - - public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken) - { - return SendMessageInternal(new WebSocketMessage<GeneralCommand> - { - MessageType = "GeneralCommand", - Data = command - - }, cancellationToken); - } - - public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) - { - return SendMessagesInternal(new WebSocketMessage<SessionInfoDto> - { - MessageType = "SessionEnded", - Data = sessionInfo - - }, cancellationToken); - } - - public Task SendPlaybackStartNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) - { - return SendMessagesInternal(new WebSocketMessage<SessionInfoDto> - { - MessageType = "PlaybackStart", - Data = sessionInfo - - }, cancellationToken); - } - - public Task SendPlaybackStoppedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) - { - return SendMessagesInternal(new WebSocketMessage<SessionInfoDto> - { - MessageType = "PlaybackStopped", - Data = sessionInfo - - }, cancellationToken); - } - - public Task SendMessage<T>(string name, T data, CancellationToken cancellationToken) - { - return SendMessagesInternal(new WebSocketMessage<T> - { - Data = data, - MessageType = name - - }, cancellationToken); - } - - private Task SendMessageInternal<T>(WebSocketMessage<T> message, CancellationToken cancellationToken) - { - var socket = GetActiveSocket(); - - return socket.SendAsync(message, cancellationToken); - } - - private Task SendMessagesInternal<T>(WebSocketMessage<T> message, CancellationToken cancellationToken) - { - var tasks = GetActiveSockets().Select(i => Task.Run(async () => - { - try - { - await i.SendAsync(message, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending web socket message", ex); - } - - }, cancellationToken)); - - return Task.WhenAll(tasks); - } - - public void Dispose() - { - foreach (var socket in Sockets.ToList()) - { - socket.Closed -= connection_Closed; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Social/SharingManager.cs b/MediaBrowser.Server.Implementations/Social/SharingManager.cs deleted file mode 100644 index 95f0ece0c2..0000000000 --- a/MediaBrowser.Server.Implementations/Social/SharingManager.cs +++ /dev/null @@ -1,101 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Social; -using MediaBrowser.Model.Social; -using System; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Social -{ - public class SharingManager : ISharingManager - { - private readonly SharingRepository _repository; - private readonly IServerConfigurationManager _config; - private readonly ILibraryManager _libraryManager; - private readonly IServerApplicationHost _appHost; - - public SharingManager(SharingRepository repository, IServerConfigurationManager config, ILibraryManager libraryManager, IServerApplicationHost appHost) - { - _repository = repository; - _config = config; - _libraryManager = libraryManager; - _appHost = appHost; - } - - public async Task<SocialShareInfo> CreateShare(string itemId, string userId) - { - if (string.IsNullOrWhiteSpace(itemId)) - { - throw new ArgumentNullException("itemId"); - } - if (string.IsNullOrWhiteSpace(userId)) - { - throw new ArgumentNullException("userId"); - } - - var item = _libraryManager.GetItemById(itemId); - - if (item == null) - { - throw new ResourceNotFoundException(); - } - - var externalUrl = (await _appHost.GetSystemInfo().ConfigureAwait(false)).WanAddress; - - if (string.IsNullOrWhiteSpace(externalUrl)) - { - throw new InvalidOperationException("No external server address is currently available."); - } - - var info = new SocialShareInfo - { - Id = Guid.NewGuid().ToString("N"), - ExpirationDate = DateTime.UtcNow.AddDays(_config.Configuration.SharingExpirationDays), - ItemId = itemId, - UserId = userId - }; - - AddShareInfo(info, externalUrl); - - await _repository.CreateShare(info).ConfigureAwait(false); - - return info; - } - - private string GetTitle(BaseItem item) - { - return item.Name; - } - - public SocialShareInfo GetShareInfo(string id) - { - var info = _repository.GetShareInfo(id); - - AddShareInfo(info, _appHost.GetSystemInfo().Result.WanAddress); - - return info; - } - - private void AddShareInfo(SocialShareInfo info, string externalUrl) - { - info.ImageUrl = externalUrl + "/Social/Shares/Public/" + info.Id + "/Image"; - info.Url = externalUrl + "/emby/web/shared.html?id=" + info.Id; - - var item = _libraryManager.GetItemById(info.ItemId); - - if (item != null) - { - info.Overview = item.Overview; - info.Name = GetTitle(item); - } - } - - public Task DeleteShare(string id) - { - return _repository.DeleteShare(id); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs b/MediaBrowser.Server.Implementations/Social/SharingRepository.cs deleted file mode 100644 index c4243c1a76..0000000000 --- a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs +++ /dev/null @@ -1,158 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Social; -using MediaBrowser.Server.Implementations.Persistence; -using System; -using System.Data; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Social -{ - public class SharingRepository : BaseSqliteRepository - { - public SharingRepository(ILogManager logManager, IApplicationPaths appPaths, IDbConnector dbConnector) - : base(logManager, dbConnector) - { - DbFilePath = Path.Combine(appPaths.DataPath, "shares.db"); - } - - /// <summary> - /// Opens the connection to the database - /// </summary> - /// <returns>Task.</returns> - public async Task Initialize() - { - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - string[] queries = { - - "create table if not exists Shares (Id GUID, ItemId TEXT, UserId TEXT, ExpirationDate DateTime, PRIMARY KEY (Id))", - "create index if not exists idx_Shares on Shares(Id)", - - "pragma shrink_memory" - }; - - connection.RunQueries(queries, Logger); - } - } - - public async Task CreateShare(SocialShareInfo info) - { - if (info == null) - { - throw new ArgumentNullException("info"); - } - if (string.IsNullOrWhiteSpace(info.Id)) - { - throw new ArgumentNullException("info.Id"); - } - - var cancellationToken = CancellationToken.None; - - cancellationToken.ThrowIfCancellationRequested(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var saveShareCommand = connection.CreateCommand()) - { - saveShareCommand.CommandText = "replace into Shares (Id, ItemId, UserId, ExpirationDate) values (@Id, @ItemId, @UserId, @ExpirationDate)"; - - saveShareCommand.Parameters.Add(saveShareCommand, "@Id"); - saveShareCommand.Parameters.Add(saveShareCommand, "@ItemId"); - saveShareCommand.Parameters.Add(saveShareCommand, "@UserId"); - saveShareCommand.Parameters.Add(saveShareCommand, "@ExpirationDate"); - - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - saveShareCommand.GetParameter(0).Value = new Guid(info.Id); - saveShareCommand.GetParameter(1).Value = info.ItemId; - saveShareCommand.GetParameter(2).Value = info.UserId; - saveShareCommand.GetParameter(3).Value = info.ExpirationDate; - - saveShareCommand.Transaction = transaction; - - saveShareCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save share:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - - public SocialShareInfo GetShareInfo(string id) - { - if (string.IsNullOrWhiteSpace(id)) - { - throw new ArgumentNullException("id"); - } - - using (var connection = CreateConnection(true).Result) - { - var cmd = connection.CreateCommand(); - cmd.CommandText = "select Id, ItemId, UserId, ExpirationDate from Shares where id = @id"; - - cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = new Guid(id); - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) - { - return GetSocialShareInfo(reader); - } - } - - return null; - } - } - - private SocialShareInfo GetSocialShareInfo(IDataReader reader) - { - var info = new SocialShareInfo(); - - info.Id = reader.GetGuid(0).ToString("N"); - info.ItemId = reader.GetString(1); - info.UserId = reader.GetString(2); - info.ExpirationDate = reader.GetDateTime(3).ToUniversalTime(); - - return info; - } - - public async Task DeleteShare(string id) - { - - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs deleted file mode 100644 index 7e6a252cdc..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs +++ /dev/null @@ -1,71 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class AirTimeComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return DateTime.Compare(GetValue(x), GetValue(y)); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private DateTime GetValue(BaseItem x) - { - var series = x as Series; - - if (series == null) - { - var season = x as Season; - - if (season != null) - { - series = season.Series; - } - else - { - var episode = x as Episode; - - if (episode != null) - { - series = episode.Series; - } - } - } - - if (series != null) - { - DateTime result; - if (DateTime.TryParse(series.AirTime, out result)) - { - return result; - } - } - - return DateTime.MinValue; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.AirTime; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs deleted file mode 100644 index 91abbe34c9..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ /dev/null @@ -1,160 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - class AiredEpisodeOrderComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - if (x.PremiereDate.HasValue && y.PremiereDate.HasValue) - { - var val = DateTime.Compare(x.PremiereDate.Value, y.PremiereDate.Value); - - if (val != 0) - { - //return val; - } - } - - var episode1 = x as Episode; - var episode2 = y as Episode; - - if (episode1 == null) - { - if (episode2 == null) - { - return 0; - } - - return 1; - } - - if (episode2 == null) - { - return -1; - } - - return Compare(episode1, episode2); - } - - private int Compare(Episode x, Episode y) - { - var isXSpecial = (x.ParentIndexNumber ?? -1) == 0; - var isYSpecial = (y.ParentIndexNumber ?? -1) == 0; - - if (isXSpecial && isYSpecial) - { - return CompareSpecials(x, y); - } - - if (!isXSpecial && !isYSpecial) - { - return CompareEpisodes(x, y); - } - - if (!isXSpecial) - { - return CompareEpisodeToSpecial(x, y); - } - - return CompareEpisodeToSpecial(y, x) * -1; - } - - private int CompareEpisodeToSpecial(Episode x, Episode y) - { - // http://thetvdb.com/wiki/index.php?title=Special_Episodes - - var xSeason = x.ParentIndexNumber ?? -1; - var ySeason = y.AirsAfterSeasonNumber ?? y.AirsBeforeSeasonNumber ?? -1; - - if (xSeason != ySeason) - { - return xSeason.CompareTo(ySeason); - } - - // Special comes after episode - if (y.AirsAfterSeasonNumber.HasValue) - { - return -1; - } - - var yEpisode = y.AirsBeforeEpisodeNumber; - - // Special comes before the season - if (!yEpisode.HasValue) - { - return 1; - } - - // Compare episode number - var xEpisode = x.IndexNumber; - - if (!xEpisode.HasValue) - { - // Can't really compare if this happens - return 0; - } - - // Special comes before episode - if (xEpisode.Value == yEpisode.Value) - { - return 1; - } - - return xEpisode.Value.CompareTo(yEpisode.Value); - } - - private int CompareSpecials(Episode x, Episode y) - { - return GetSpecialCompareValue(x).CompareTo(GetSpecialCompareValue(y)); - } - - private int GetSpecialCompareValue(Episode item) - { - // First sort by season number - // Since there are three sort orders, pad with 9 digits (3 for each, figure 1000 episode buffer should be enough) - var val = (item.AirsAfterSeasonNumber ?? item.AirsBeforeSeasonNumber ?? 0) * 1000000000; - - // Second sort order is if it airs after the season - if (item.AirsAfterSeasonNumber.HasValue) - { - val += 1000000; - } - - // Third level is the episode number - val += (item.AirsBeforeEpisodeNumber ?? 0) * 1000; - - // Finally, if that's still the same, last resort is the special number itself - val += item.IndexNumber ?? 0; - - return val; - } - - private int CompareEpisodes(Episode x, Episode y) - { - var xValue = (x.ParentIndexNumber ?? -1) * 1000 + (x.IndexNumber ?? -1); - var yValue = (y.ParentIndexNumber ?? -1) * 1000 + (y.IndexNumber ?? -1); - - return xValue.CompareTo(yValue); - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.AiredEpisodeOrder; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/AlbumArtistComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AlbumArtistComparer.cs deleted file mode 100644 index 3c79b0c326..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/AlbumArtistComparer.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Linq; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class AlbumArtistComparer - /// </summary> - public class AlbumArtistComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private string GetValue(BaseItem x) - { - var audio = x as IHasAlbumArtist; - - return audio != null ? audio.AlbumArtists.FirstOrDefault() : null; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.AlbumArtist; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/AlbumComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AlbumComparer.cs deleted file mode 100644 index f455d5c2bd..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/AlbumComparer.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class AlbumComparer - /// </summary> - public class AlbumComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private string GetValue(BaseItem x) - { - var audio = x as Audio; - - return audio == null ? string.Empty : audio.Album; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.Album; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/AlphanumComparator.cs b/MediaBrowser.Server.Implementations/Sorting/AlphanumComparator.cs deleted file mode 100644 index 232bdb3b58..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/AlphanumComparator.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.Collections.Generic; -using System.Text; -using MediaBrowser.Controller.Sorting; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class AlphanumComparator : IComparer<string> - { - public static int CompareValues(string s1, string s2) - { - if (s1 == null || s2 == null) - { - return 0; - } - - int thisMarker = 0, thisNumericChunk = 0; - int thatMarker = 0, thatNumericChunk = 0; - - while ((thisMarker < s1.Length) || (thatMarker < s2.Length)) - { - if (thisMarker >= s1.Length) - { - return -1; - } - else if (thatMarker >= s2.Length) - { - return 1; - } - char thisCh = s1[thisMarker]; - char thatCh = s2[thatMarker]; - - StringBuilder thisChunk = new StringBuilder(); - StringBuilder thatChunk = new StringBuilder(); - - while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || SortHelper.InChunk(thisCh, thisChunk[0]))) - { - thisChunk.Append(thisCh); - thisMarker++; - - if (thisMarker < s1.Length) - { - thisCh = s1[thisMarker]; - } - } - - while ((thatMarker < s2.Length) && (thatChunk.Length == 0 || SortHelper.InChunk(thatCh, thatChunk[0]))) - { - thatChunk.Append(thatCh); - thatMarker++; - - if (thatMarker < s2.Length) - { - thatCh = s2[thatMarker]; - } - } - - int result = 0; - // If both chunks contain numeric characters, sort them numerically - if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0])) - { - if (!int.TryParse(thisChunk.ToString(), out thisNumericChunk)) - { - return 0; - } - if (!int.TryParse(thatChunk.ToString(), out thatNumericChunk)) - { - return 0; - } - - if (thisNumericChunk < thatNumericChunk) - { - result = -1; - } - - if (thisNumericChunk > thatNumericChunk) - { - result = 1; - } - } - else - { - result = thisChunk.ToString().CompareTo(thatChunk.ToString()); - } - - if (result != 0) - { - return result; - } - } - - return 0; - } - - public int Compare(string x, string y) - { - return CompareValues(x, y); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/ArtistComparer.cs b/MediaBrowser.Server.Implementations/Sorting/ArtistComparer.cs deleted file mode 100644 index 9ff8a5ace3..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/ArtistComparer.cs +++ /dev/null @@ -1,51 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class ArtistComparer - /// </summary> - public class ArtistComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private string GetValue(BaseItem x) - { - var audio = x as Audio; - - if (audio == null) - { - return string.Empty; - } - - return audio.Artists.Count == 0 ? null : audio.Artists[0]; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.Artist; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/BudgetComparer.cs b/MediaBrowser.Server.Implementations/Sorting/BudgetComparer.cs deleted file mode 100644 index 87a7325c63..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/BudgetComparer.cs +++ /dev/null @@ -1,39 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class BudgetComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - private double GetValue(BaseItem x) - { - var hasBudget = x as IHasBudget; - if (hasBudget != null) - { - return hasBudget.Budget ?? 0; - } - return 0; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.Budget; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/CommunityRatingComparer.cs b/MediaBrowser.Server.Implementations/Sorting/CommunityRatingComparer.cs deleted file mode 100644 index bdd18a648b..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/CommunityRatingComparer.cs +++ /dev/null @@ -1,29 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class CommunityRatingComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return (x.CommunityRating ?? 0).CompareTo(y.CommunityRating ?? 0); - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.CommunityRating; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/CriticRatingComparer.cs b/MediaBrowser.Server.Implementations/Sorting/CriticRatingComparer.cs deleted file mode 100644 index 9484130cbc..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/CriticRatingComparer.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class CriticRatingComparer - /// </summary> - public class CriticRatingComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - private float GetValue(BaseItem x) - { - return x.CriticRating ?? 0; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.CriticRating; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/DateCreatedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DateCreatedComparer.cs deleted file mode 100644 index 9862f0a8a6..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/DateCreatedComparer.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class DateCreatedComparer - /// </summary> - public class DateCreatedComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return DateTime.Compare(x.DateCreated, y.DateCreated); - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.DateCreated; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs deleted file mode 100644 index 5080edffd5..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs +++ /dev/null @@ -1,69 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class DateLastMediaAddedComparer : IUserBaseItemComparer - { - /// <summary> - /// Gets or sets the user. - /// </summary> - /// <value>The user.</value> - public User User { get; set; } - - /// <summary> - /// Gets or sets the user manager. - /// </summary> - /// <value>The user manager.</value> - public IUserManager UserManager { get; set; } - - /// <summary> - /// Gets or sets the user data repository. - /// </summary> - /// <value>The user data repository.</value> - public IUserDataManager UserDataRepository { get; set; } - - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetDate(x).CompareTo(GetDate(y)); - } - - /// <summary> - /// Gets the date. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>DateTime.</returns> - private DateTime GetDate(BaseItem x) - { - var folder = x as Folder; - - if (folder != null) - { - if (folder.DateLastMediaAdded.HasValue) - { - return folder.DateLastMediaAdded.Value; - } - } - - return DateTime.MinValue; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.DateLastContentAdded; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs deleted file mode 100644 index 3edf23020a..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs +++ /dev/null @@ -1,69 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class DatePlayedComparer - /// </summary> - public class DatePlayedComparer : IUserBaseItemComparer - { - /// <summary> - /// Gets or sets the user. - /// </summary> - /// <value>The user.</value> - public User User { get; set; } - - /// <summary> - /// Gets or sets the user manager. - /// </summary> - /// <value>The user manager.</value> - public IUserManager UserManager { get; set; } - - /// <summary> - /// Gets or sets the user data repository. - /// </summary> - /// <value>The user data repository.</value> - public IUserDataManager UserDataRepository { get; set; } - - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetDate(x).CompareTo(GetDate(y)); - } - - /// <summary> - /// Gets the date. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>DateTime.</returns> - private DateTime GetDate(BaseItem x) - { - var userdata = UserDataRepository.GetUserData(User, x); - - if (userdata != null && userdata.LastPlayedDate.HasValue) - { - return userdata.LastPlayedDate.Value; - } - - return DateTime.MinValue; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.DatePlayed; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/GameSystemComparer.cs b/MediaBrowser.Server.Implementations/Sorting/GameSystemComparer.cs deleted file mode 100644 index eb83b98e97..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/GameSystemComparer.cs +++ /dev/null @@ -1,54 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class GameSystemComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private string GetValue(BaseItem x) - { - var game = x as Game; - - if (game != null) - { - return game.GameSystem; - } - - var system = x as GameSystem; - - if (system != null) - { - return system.GameSystemName; - } - - return string.Empty; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.GameSystem; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs b/MediaBrowser.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs deleted file mode 100644 index 658708dba5..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs +++ /dev/null @@ -1,58 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class IsFavoriteOrLikeComparer : IUserBaseItemComparer - { - /// <summary> - /// Gets or sets the user. - /// </summary> - /// <value>The user.</value> - public User User { get; set; } - - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - /// <summary> - /// Gets the date. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>DateTime.</returns> - private int GetValue(BaseItem x) - { - return x.IsFavoriteOrLiked(User) ? 0 : 1; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.IsFavoriteOrLiked; } - } - - /// <summary> - /// Gets or sets the user data repository. - /// </summary> - /// <value>The user data repository.</value> - public IUserDataManager UserDataRepository { get; set; } - - /// <summary> - /// Gets or sets the user manager. - /// </summary> - /// <value>The user manager.</value> - public IUserManager UserManager { get; set; } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Sorting/IsFolderComparer.cs b/MediaBrowser.Server.Implementations/Sorting/IsFolderComparer.cs deleted file mode 100644 index d2341d0651..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/IsFolderComparer.cs +++ /dev/null @@ -1,39 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class IsFolderComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private int GetValue(BaseItem x) - { - return x.IsFolder ? 0 : 1; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.IsFolder; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/IsPlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/IsPlayedComparer.cs deleted file mode 100644 index aebfbdb1c4..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/IsPlayedComparer.cs +++ /dev/null @@ -1,58 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class IsPlayedComparer : IUserBaseItemComparer - { - /// <summary> - /// Gets or sets the user. - /// </summary> - /// <value>The user.</value> - public User User { get; set; } - - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - /// <summary> - /// Gets the date. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>DateTime.</returns> - private int GetValue(BaseItem x) - { - return x.IsPlayed(User) ? 0 : 1; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.IsUnplayed; } - } - - /// <summary> - /// Gets or sets the user data repository. - /// </summary> - /// <value>The user data repository.</value> - public IUserDataManager UserDataRepository { get; set; } - - /// <summary> - /// Gets or sets the user manager. - /// </summary> - /// <value>The user manager.</value> - public IUserManager UserManager { get; set; } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Sorting/IsUnplayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/IsUnplayedComparer.cs deleted file mode 100644 index f1c6a5a4eb..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/IsUnplayedComparer.cs +++ /dev/null @@ -1,58 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class IsUnplayedComparer : IUserBaseItemComparer - { - /// <summary> - /// Gets or sets the user. - /// </summary> - /// <value>The user.</value> - public User User { get; set; } - - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - /// <summary> - /// Gets the date. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>DateTime.</returns> - private int GetValue(BaseItem x) - { - return x.IsUnplayed(User) ? 0 : 1; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.IsUnplayed; } - } - - /// <summary> - /// Gets or sets the user data repository. - /// </summary> - /// <value>The user data repository.</value> - public IUserDataManager UserDataRepository { get; set; } - - /// <summary> - /// Gets or sets the user manager. - /// </summary> - /// <value>The user manager.</value> - public IUserManager UserManager { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/MetascoreComparer.cs b/MediaBrowser.Server.Implementations/Sorting/MetascoreComparer.cs deleted file mode 100644 index bfd1626615..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/MetascoreComparer.cs +++ /dev/null @@ -1,41 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class MetascoreComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - private float GetValue(BaseItem x) - { - var hasMetascore = x as IHasMetascore; - - if (hasMetascore != null) - { - return hasMetascore.Metascore ?? 0; - } - - return 0; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.Metascore; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/NameComparer.cs b/MediaBrowser.Server.Implementations/Sorting/NameComparer.cs deleted file mode 100644 index 49f86c485a..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/NameComparer.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class NameComparer - /// </summary> - public class NameComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(x.Name, y.Name, StringComparison.CurrentCultureIgnoreCase); - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.Name; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/OfficialRatingComparer.cs b/MediaBrowser.Server.Implementations/Sorting/OfficialRatingComparer.cs deleted file mode 100644 index dd31109daf..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/OfficialRatingComparer.cs +++ /dev/null @@ -1,40 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Localization; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class OfficialRatingComparer : IBaseItemComparer - { - private readonly ILocalizationManager _localization; - - public OfficialRatingComparer(ILocalizationManager localization) - { - _localization = localization; - } - - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - var levelX = string.IsNullOrEmpty(x.OfficialRating) ? 0 : _localization.GetRatingLevel(x.OfficialRating) ?? 0; - var levelY = string.IsNullOrEmpty(y.OfficialRating) ? 0 : _localization.GetRatingLevel(y.OfficialRating) ?? 0; - - return levelX.CompareTo(levelY); - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.OfficialRating; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs deleted file mode 100644 index 8b14efffcf..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs +++ /dev/null @@ -1,63 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class PlayCountComparer - /// </summary> - public class PlayCountComparer : IUserBaseItemComparer - { - /// <summary> - /// Gets or sets the user. - /// </summary> - /// <value>The user.</value> - public User User { get; set; } - - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - /// <summary> - /// Gets the date. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>DateTime.</returns> - private int GetValue(BaseItem x) - { - var userdata = UserDataRepository.GetUserData(User, x); - - return userdata == null ? 0 : userdata.PlayCount; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.PlayCount; } - } - - /// <summary> - /// Gets or sets the user data repository. - /// </summary> - /// <value>The user data repository.</value> - public IUserDataManager UserDataRepository { get; set; } - - /// <summary> - /// Gets or sets the user manager. - /// </summary> - /// <value>The user manager.</value> - public IUserManager UserManager { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/PlayersComparer.cs b/MediaBrowser.Server.Implementations/Sorting/PlayersComparer.cs deleted file mode 100644 index 5bcd080d7b..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/PlayersComparer.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class PlayersComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private int GetValue(BaseItem x) - { - var game = x as Game; - - if (game != null) - { - return game.PlayersSupported ?? 0; - } - - return 0; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.Players; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/PremiereDateComparer.cs b/MediaBrowser.Server.Implementations/Sorting/PremiereDateComparer.cs deleted file mode 100644 index ffe1fc24a1..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/PremiereDateComparer.cs +++ /dev/null @@ -1,59 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class PremiereDateComparer - /// </summary> - public class PremiereDateComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetDate(x).CompareTo(GetDate(y)); - } - - /// <summary> - /// Gets the date. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>DateTime.</returns> - private DateTime GetDate(BaseItem x) - { - if (x.PremiereDate.HasValue) - { - return x.PremiereDate.Value; - } - - if (x.ProductionYear.HasValue) - { - try - { - return new DateTime(x.ProductionYear.Value, 1, 1, 0, 0, 0, DateTimeKind.Utc); - } - catch (ArgumentOutOfRangeException) - { - // Don't blow up if the item has a bad ProductionYear, just return MinValue - } - } - return DateTime.MinValue; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.PremiereDate; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/ProductionYearComparer.cs b/MediaBrowser.Server.Implementations/Sorting/ProductionYearComparer.cs deleted file mode 100644 index 16d5313347..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/ProductionYearComparer.cs +++ /dev/null @@ -1,52 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class ProductionYearComparer - /// </summary> - public class ProductionYearComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - /// <summary> - /// Gets the date. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>DateTime.</returns> - private int GetValue(BaseItem x) - { - if (x.ProductionYear.HasValue) - { - return x.ProductionYear.Value; - } - - if (x.PremiereDate.HasValue) - { - return x.PremiereDate.Value.Year; - } - - return 0; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.ProductionYear; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/RandomComparer.cs b/MediaBrowser.Server.Implementations/Sorting/RandomComparer.cs deleted file mode 100644 index b1677331ac..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/RandomComparer.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class RandomComparer - /// </summary> - public class RandomComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return Guid.NewGuid().CompareTo(Guid.NewGuid()); - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.Random; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/RevenueComparer.cs b/MediaBrowser.Server.Implementations/Sorting/RevenueComparer.cs deleted file mode 100644 index 6caa27ac39..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/RevenueComparer.cs +++ /dev/null @@ -1,39 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class RevenueComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - private double GetValue(BaseItem x) - { - var hasBudget = x as IHasBudget; - if (hasBudget != null) - { - return hasBudget.Revenue ?? 0; - } - return 0; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.Revenue; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/RuntimeComparer.cs b/MediaBrowser.Server.Implementations/Sorting/RuntimeComparer.cs deleted file mode 100644 index 793cb265e8..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/RuntimeComparer.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class RuntimeComparer - /// </summary> - public class RuntimeComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return (x.RunTimeTicks ?? 0).CompareTo(y.RunTimeTicks ?? 0); - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.Runtime; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/SeriesSortNameComparer.cs b/MediaBrowser.Server.Implementations/Sorting/SeriesSortNameComparer.cs deleted file mode 100644 index 6bc1264a48..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/SeriesSortNameComparer.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - class SeriesSortNameComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); - } - - private string GetValue(BaseItem item) - { - var hasSeries = item as IHasSeries; - - return hasSeries != null ? hasSeries.SeriesSortName : null; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.SeriesSortName; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/SortNameComparer.cs b/MediaBrowser.Server.Implementations/Sorting/SortNameComparer.cs deleted file mode 100644 index 873753a2b2..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/SortNameComparer.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - /// <summary> - /// Class SortNameComparer - /// </summary> - public class SortNameComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(x.SortName, y.SortName, StringComparison.CurrentCultureIgnoreCase); - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.SortName; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/StartDateComparer.cs b/MediaBrowser.Server.Implementations/Sorting/StartDateComparer.cs deleted file mode 100644 index 7e6f24ec1c..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/StartDateComparer.cs +++ /dev/null @@ -1,47 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class StartDateComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetDate(x).CompareTo(GetDate(y)); - } - - /// <summary> - /// Gets the date. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>DateTime.</returns> - private DateTime GetDate(BaseItem x) - { - var hasStartDate = x as LiveTvProgram; - - if (hasStartDate != null) - { - return hasStartDate.StartDate; - } - return DateTime.MinValue; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.StartDate; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/StudioComparer.cs b/MediaBrowser.Server.Implementations/Sorting/StudioComparer.cs deleted file mode 100644 index 83ab4dfc26..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/StudioComparer.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; -using System.Linq; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - public class StudioComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return AlphanumComparator.CompareValues(x.Studios.FirstOrDefault() ?? string.Empty, y.Studios.FirstOrDefault() ?? string.Empty); - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.Studio; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sorting/VideoBitRateComparer.cs b/MediaBrowser.Server.Implementations/Sorting/VideoBitRateComparer.cs deleted file mode 100644 index cbf6ebac66..0000000000 --- a/MediaBrowser.Server.Implementations/Sorting/VideoBitRateComparer.cs +++ /dev/null @@ -1,41 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.Sorting -{ - class VideoBitRateComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - private int GetValue(BaseItem item) - { - var video = item as Video; - - if (video != null) - { - return video.VideoBitRate ?? 0; - } - - return 0; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return ItemSortBy.VideoBitRate; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs deleted file mode 100644 index 408ec717eb..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs +++ /dev/null @@ -1,118 +0,0 @@ -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Devices; -using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Sync; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class AppSyncProvider : ISyncProvider, IHasUniqueTargetIds, IHasSyncQuality, IHasDuplicateCheck - { - private readonly IDeviceManager _deviceManager; - - public AppSyncProvider(IDeviceManager deviceManager) - { - _deviceManager = deviceManager; - } - - public IEnumerable<SyncTarget> GetSyncTargets(string userId) - { - return _deviceManager.GetDevices(new DeviceQuery - { - SupportsSync = true, - UserId = userId - - }).Items.Select(i => new SyncTarget - { - Id = i.Id, - Name = i.Name - }); - } - - public DeviceProfile GetDeviceProfile(SyncTarget target, string profile, string quality) - { - var caps = _deviceManager.GetCapabilities(target.Id); - - var deviceProfile = caps == null || caps.DeviceProfile == null ? new DeviceProfile() : caps.DeviceProfile; - deviceProfile.MaxStaticBitrate = SyncHelper.AdjustBitrate(deviceProfile.MaxStaticBitrate, quality); - - return deviceProfile; - } - - public string Name - { - get { return "Mobile Sync"; } - } - - public IEnumerable<SyncTarget> GetAllSyncTargets() - { - return _deviceManager.GetDevices(new DeviceQuery - { - SupportsSync = true - - }).Items.Select(i => new SyncTarget - { - Id = i.Id, - Name = i.Name - }); - } - - public IEnumerable<SyncQualityOption> GetQualityOptions(SyncTarget target) - { - return new List<SyncQualityOption> - { - new SyncQualityOption - { - Name = "Original", - Id = "original", - Description = "Syncs original files as-is, regardless of whether the device is capable of playing them or not." - }, - new SyncQualityOption - { - Name = "High", - Id = "high", - IsDefault = true - }, - new SyncQualityOption - { - Name = "Medium", - Id = "medium" - }, - new SyncQualityOption - { - Name = "Low", - Id = "low" - }, - new SyncQualityOption - { - Name = "Custom", - Id = "custom" - } - }; - } - - public IEnumerable<SyncProfileOption> GetProfileOptions(SyncTarget target) - { - return new List<SyncProfileOption>(); - } - - public SyncJobOptions GetSyncJobOptions(SyncTarget target, string profile, string quality) - { - var isConverting = !string.Equals(quality, "original", StringComparison.OrdinalIgnoreCase); - - return new SyncJobOptions - { - DeviceProfile = GetDeviceProfile(target, profile, quality), - IsConverting = isConverting - }; - } - - public bool AllowDuplicateJobItem(SyncJobItem original, SyncJobItem duplicate) - { - return false; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs b/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs deleted file mode 100644 index f40b644989..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs +++ /dev/null @@ -1,302 +0,0 @@ -using MediaBrowser.Model.Dlna; -using System.Collections.Generic; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class CloudSyncProfile : DeviceProfile - { - public CloudSyncProfile(bool supportsAc3, bool supportsDca) - { - Name = "Cloud Sync"; - - MaxStreamingBitrate = 20000000; - MaxStaticBitrate = 20000000; - - var mkvAudio = "aac,mp3"; - var mp4Audio = "aac"; - - if (supportsAc3) - { - mkvAudio += ",ac3"; - mp4Audio += ",ac3"; - } - - if (supportsDca) - { - mkvAudio += ",dca,dts"; - } - - var videoProfile = "high|main|baseline|constrained baseline"; - var videoLevel = "40"; - - DirectPlayProfiles = new[] - { - //new DirectPlayProfile - //{ - // Container = "mkv", - // VideoCodec = "h264,mpeg4", - // AudioCodec = mkvAudio, - // Type = DlnaProfileType.Video - //}, - new DirectPlayProfile - { - Container = "mp4,mov,m4v", - VideoCodec = "h264,mpeg4", - AudioCodec = mp4Audio, - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mp3", - Type = DlnaProfileType.Audio - } - }; - - ContainerProfiles = new[] - { - new ContainerProfile - { - Type = DlnaProfileType.Video, - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.NotEquals, - Property = ProfileConditionValue.NumAudioStreams, - Value = "0", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.EqualsAny, - Property = ProfileConditionValue.NumVideoStreams, - Value = "1", - IsRequired = false - } - } - } - }; - - var codecProfiles = new List<CodecProfile> - { - new CodecProfile - { - Type = CodecType.Video, - Codec = "h264", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoBitDepth, - Value = "8", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Width, - Value = "1920", - IsRequired = true - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Height, - Value = "1080", - IsRequired = true - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.RefFrames, - Value = "4", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoFramerate, - Value = "30", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.Equals, - Property = ProfileConditionValue.IsAnamorphic, - Value = "false", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoLevel, - Value = videoLevel, - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.EqualsAny, - Property = ProfileConditionValue.VideoProfile, - Value = videoProfile, - IsRequired = false - } - } - }, - new CodecProfile - { - Type = CodecType.Video, - Codec = "mpeg4", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoBitDepth, - Value = "8", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Width, - Value = "1920", - IsRequired = true - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Height, - Value = "1080", - IsRequired = true - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.RefFrames, - Value = "4", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoFramerate, - Value = "30", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.Equals, - Property = ProfileConditionValue.IsAnamorphic, - Value = "false", - IsRequired = false - } - } - } - }; - - codecProfiles.Add(new CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "ac3", - Conditions = new[] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioChannels, - Value = "6", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioBitrate, - Value = "320000", - IsRequired = true - }, - new ProfileCondition - { - Condition = ProfileConditionType.Equals, - Property = ProfileConditionValue.IsSecondaryAudio, - Value = "false", - IsRequired = false - } - } - }); - codecProfiles.Add(new CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "aac,mp3", - Conditions = new[] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioChannels, - Value = "2", - IsRequired = true - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioBitrate, - Value = "320000", - IsRequired = true - }, - new ProfileCondition - { - Condition = ProfileConditionType.Equals, - Property = ProfileConditionValue.IsSecondaryAudio, - Value = "false", - IsRequired = false - } - } - }); - - CodecProfiles = codecProfiles.ToArray(); - - SubtitleProfiles = new[] - { - new SubtitleProfile - { - Format = "srt", - Method = SubtitleDeliveryMethod.External - }, - new SubtitleProfile - { - Format = "vtt", - Method = SubtitleDeliveryMethod.External - } - }; - - TranscodingProfiles = new[] - { - new TranscodingProfile - { - Container = "mp3", - AudioCodec = "mp3", - Type = DlnaProfileType.Audio, - Context = EncodingContext.Static - }, - - new TranscodingProfile - { - Container = "mp4", - Type = DlnaProfileType.Video, - AudioCodec = "aac", - VideoCodec = "h264", - Context = EncodingContext.Static - }, - - new TranscodingProfile - { - Container = "jpeg", - Type = DlnaProfileType.Photo, - Context = EncodingContext.Static - } - }; - - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/IHasSyncQuality.cs b/MediaBrowser.Server.Implementations/Sync/IHasSyncQuality.cs deleted file mode 100644 index e7eee09232..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/IHasSyncQuality.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MediaBrowser.Model.Sync; -using System.Collections.Generic; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public interface IHasSyncQuality - { - /// <summary> - /// Gets the device profile. - /// </summary> - /// <param name="target">The target.</param> - /// <param name="profile">The profile.</param> - /// <param name="quality">The quality.</param> - /// <returns>DeviceProfile.</returns> - SyncJobOptions GetSyncJobOptions(SyncTarget target, string profile, string quality); - - /// <summary> - /// Gets the quality options. - /// </summary> - /// <param name="target">The target.</param> - /// <returns>IEnumerable<SyncQualityOption>.</returns> - IEnumerable<SyncQualityOption> GetQualityOptions(SyncTarget target); - - /// <summary> - /// Gets the profile options. - /// </summary> - /// <param name="target">The target.</param> - /// <returns>IEnumerable<SyncQualityOption>.</returns> - IEnumerable<SyncProfileOption> GetProfileOptions(SyncTarget target); - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs deleted file mode 100644 index 3218ac5e76..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs +++ /dev/null @@ -1,501 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Progress; -using MediaBrowser.Controller; -using MediaBrowser.Controller.IO; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Sync; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using Interfaces.IO; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class MediaSync - { - private readonly ISyncManager _syncManager; - private readonly IServerApplicationHost _appHost; - private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly IConfigurationManager _config; - - public const string PathSeparatorString = "/"; - public const char PathSeparatorChar = '/'; - - public MediaSync(ILogger logger, ISyncManager syncManager, IServerApplicationHost appHost, IFileSystem fileSystem, IConfigurationManager config) - { - _logger = logger; - _syncManager = syncManager; - _appHost = appHost; - _fileSystem = fileSystem; - _config = config; - } - - public async Task Sync(IServerSyncProvider provider, - ISyncDataProvider dataProvider, - SyncTarget target, - IProgress<double> progress, - CancellationToken cancellationToken) - { - var serverId = _appHost.SystemId; - var serverName = _appHost.FriendlyName; - - await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false); - progress.Report(3); - - var innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(pct => - { - var totalProgress = pct * .97; - totalProgress += 1; - progress.Report(totalProgress); - }); - await GetNewMedia(provider, dataProvider, target, serverId, serverName, innerProgress, cancellationToken); - - // Do the data sync twice so the server knows what was removed from the device - await SyncData(provider, dataProvider, serverId, target, cancellationToken).ConfigureAwait(false); - - progress.Report(100); - } - - private async Task SyncData(IServerSyncProvider provider, - ISyncDataProvider dataProvider, - string serverId, - SyncTarget target, - CancellationToken cancellationToken) - { - var localItems = await dataProvider.GetLocalItems(target, serverId).ConfigureAwait(false); - var remoteFiles = await provider.GetFiles(new FileQuery(), target, cancellationToken).ConfigureAwait(false); - var remoteIds = remoteFiles.Items.Select(i => i.Id).ToList(); - - var jobItemIds = new List<string>(); - - foreach (var localItem in localItems) - { - if (remoteIds.Contains(localItem.FileId, StringComparer.OrdinalIgnoreCase)) - { - jobItemIds.Add(localItem.SyncJobItemId); - } - } - - var result = await _syncManager.SyncData(new SyncDataRequest - { - TargetId = target.Id, - SyncJobItemIds = jobItemIds - - }).ConfigureAwait(false); - - cancellationToken.ThrowIfCancellationRequested(); - - foreach (var itemIdToRemove in result.ItemIdsToRemove) - { - try - { - await RemoveItem(provider, dataProvider, serverId, itemIdToRemove, target, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error deleting item from device. Id: {0}", ex, itemIdToRemove); - } - } - } - - private async Task GetNewMedia(IServerSyncProvider provider, - ISyncDataProvider dataProvider, - SyncTarget target, - string serverId, - string serverName, - IProgress<double> progress, - CancellationToken cancellationToken) - { - var jobItems = await _syncManager.GetReadySyncItems(target.Id).ConfigureAwait(false); - - var numComplete = 0; - double startingPercent = 0; - double percentPerItem = 1; - if (jobItems.Count > 0) - { - percentPerItem /= jobItems.Count; - } - - foreach (var jobItem in jobItems) - { - cancellationToken.ThrowIfCancellationRequested(); - - var currentPercent = startingPercent; - var innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(pct => - { - var totalProgress = pct * percentPerItem; - totalProgress += currentPercent; - progress.Report(totalProgress); - }); - - try - { - await GetItem(provider, dataProvider, target, serverId, serverName, jobItem, innerProgress, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error syncing item", ex); - } - - numComplete++; - startingPercent = numComplete; - startingPercent /= jobItems.Count; - startingPercent *= 100; - progress.Report(startingPercent); - } - } - - private async Task GetItem(IServerSyncProvider provider, - ISyncDataProvider dataProvider, - SyncTarget target, - string serverId, - string serverName, - SyncedItem jobItem, - IProgress<double> progress, - CancellationToken cancellationToken) - { - var libraryItem = jobItem.Item; - var internalSyncJobItem = _syncManager.GetJobItem(jobItem.SyncJobItemId); - var internalSyncJob = _syncManager.GetJob(jobItem.SyncJobId); - - var localItem = CreateLocalItem(provider, jobItem, internalSyncJob, target, libraryItem, serverId, serverName, jobItem.OriginalFileName); - - await _syncManager.ReportSyncJobItemTransferBeginning(internalSyncJobItem.Id); - - var transferSuccess = false; - Exception transferException = null; - - var options = _config.GetSyncOptions(); - - try - { - var fileTransferProgress = new ActionableProgress<double>(); - fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92)); - - var sendFileResult = await SendFile(provider, internalSyncJobItem.OutputPath, localItem.LocalPath.Split(PathSeparatorChar), target, options, fileTransferProgress, cancellationToken).ConfigureAwait(false); - - if (localItem.Item.MediaSources != null) - { - var mediaSource = localItem.Item.MediaSources.FirstOrDefault(); - if (mediaSource != null) - { - mediaSource.Path = sendFileResult.Path; - mediaSource.Protocol = sendFileResult.Protocol; - mediaSource.RequiredHttpHeaders = sendFileResult.RequiredHttpHeaders; - mediaSource.SupportsTranscoding = false; - } - } - - localItem.FileId = sendFileResult.Id; - - // Create db record - await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false); - - if (localItem.Item.MediaSources != null) - { - var mediaSource = localItem.Item.MediaSources.FirstOrDefault(); - if (mediaSource != null) - { - await SendSubtitles(localItem, mediaSource, provider, dataProvider, target, options, cancellationToken).ConfigureAwait(false); - } - } - - progress.Report(92); - - transferSuccess = true; - - progress.Report(99); - } - catch (Exception ex) - { - _logger.ErrorException("Error transferring sync job file", ex); - transferException = ex; - } - - if (transferSuccess) - { - await _syncManager.ReportSyncJobItemTransferred(jobItem.SyncJobItemId).ConfigureAwait(false); - } - else - { - await _syncManager.ReportSyncJobItemTransferFailed(jobItem.SyncJobItemId).ConfigureAwait(false); - - throw transferException; - } - } - - private async Task SendSubtitles(LocalItem localItem, MediaSourceInfo mediaSource, IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, SyncOptions options, CancellationToken cancellationToken) - { - var failedSubtitles = new List<MediaStream>(); - var requiresSave = false; - - foreach (var mediaStream in mediaSource.MediaStreams - .Where(i => i.Type == MediaStreamType.Subtitle && i.IsExternal) - .ToList()) - { - try - { - var remotePath = GetRemoteSubtitlePath(localItem, mediaStream, provider, target); - var sendFileResult = await SendFile(provider, mediaStream.Path, remotePath, target, options, new Progress<double>(), cancellationToken).ConfigureAwait(false); - - // This is the path that will be used when talking to the provider - mediaStream.ExternalId = sendFileResult.Id; - - // Keep track of all additional files for cleanup later. - localItem.AdditionalFiles.Add(sendFileResult.Id); - - // This is the public path clients will use - mediaStream.Path = sendFileResult.Path; - requiresSave = true; - } - catch (Exception ex) - { - _logger.ErrorException("Error sending subtitle stream", ex); - failedSubtitles.Add(mediaStream); - } - } - - if (failedSubtitles.Count > 0) - { - mediaSource.MediaStreams = mediaSource.MediaStreams.Except(failedSubtitles).ToList(); - requiresSave = true; - } - - if (requiresSave) - { - await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false); - } - } - - private string[] GetRemoteSubtitlePath(LocalItem item, MediaStream stream, IServerSyncProvider provider, SyncTarget target) - { - var filename = GetSubtitleSaveFileName(item, stream.Language, stream.IsForced) + "." + stream.Codec.ToLower(); - - var pathParts = item.LocalPath.Split(PathSeparatorChar); - var list = pathParts.Take(pathParts.Length - 1).ToList(); - list.Add(filename); - - return list.ToArray(); - } - - private string GetSubtitleSaveFileName(LocalItem item, string language, bool isForced) - { - var path = item.LocalPath; - - var name = Path.GetFileNameWithoutExtension(path); - - if (!string.IsNullOrWhiteSpace(language)) - { - name += "." + language.ToLower(); - } - - if (isForced) - { - name += ".foreign"; - } - - return name; - } - - private async Task RemoveItem(IServerSyncProvider provider, - ISyncDataProvider dataProvider, - string serverId, - string syncJobItemId, - SyncTarget target, - CancellationToken cancellationToken) - { - var localItems = await dataProvider.GetItemsBySyncJobItemId(target, serverId, syncJobItemId); - - foreach (var localItem in localItems) - { - var files = localItem.AdditionalFiles.ToList(); - - foreach (var file in files) - { - _logger.Debug("Removing {0} from {1}.", file, target.Name); - await provider.DeleteFile(file, target, cancellationToken).ConfigureAwait(false); - } - - _logger.Debug("Removing {0} from {1}.", localItem.FileId, target.Name); - await provider.DeleteFile(localItem.FileId, target, cancellationToken).ConfigureAwait(false); - - await dataProvider.Delete(target, localItem.Id).ConfigureAwait(false); - } - } - - private async Task<SyncedFileInfo> SendFile(IServerSyncProvider provider, string inputPath, string[] pathParts, SyncTarget target, SyncOptions options, IProgress<double> progress, CancellationToken cancellationToken) - { - _logger.Debug("Sending {0} to {1}. Remote path: {2}", inputPath, provider.Name, string.Join("/", pathParts)); - var supportsDirectCopy = provider as ISupportsDirectCopy; - if (supportsDirectCopy != null) - { - return await supportsDirectCopy.SendFile(inputPath, pathParts, target, progress, cancellationToken).ConfigureAwait(false); - } - - using (var fileStream = _fileSystem.GetFileStream(inputPath, FileMode.Open, FileAccess.Read, FileShare.Read, true)) - { - Stream stream = fileStream; - - if (options.UploadSpeedLimitBytes > 0 && provider is IRemoteSyncProvider) - { - stream = new ThrottledStream(stream, options.UploadSpeedLimitBytes); - } - - return await provider.SendFile(stream, pathParts, target, progress, cancellationToken).ConfigureAwait(false); - } - } - - private static string GetLocalId(string jobItemId, string itemId) - { - var bytes = Encoding.UTF8.GetBytes(jobItemId + itemId); - bytes = CreateMd5(bytes); - return BitConverter.ToString(bytes, 0, bytes.Length).Replace("-", string.Empty); - } - - private static byte[] CreateMd5(byte[] value) - { - using (var provider = MD5.Create()) - { - return provider.ComputeHash(value); - } - } - - public LocalItem CreateLocalItem(IServerSyncProvider provider, SyncedItem syncedItem, SyncJob job, SyncTarget target, BaseItemDto libraryItem, string serverId, string serverName, string originalFileName) - { - var path = GetDirectoryPath(provider, job, syncedItem, libraryItem, serverName); - path.Add(GetLocalFileName(provider, libraryItem, originalFileName)); - - var localPath = string.Join(PathSeparatorString, path.ToArray()); - - foreach (var mediaSource in libraryItem.MediaSources) - { - mediaSource.Path = localPath; - mediaSource.Protocol = MediaProtocol.File; - } - - return new LocalItem - { - Item = libraryItem, - ItemId = libraryItem.Id, - ServerId = serverId, - LocalPath = localPath, - Id = GetLocalId(syncedItem.SyncJobItemId, libraryItem.Id), - SyncJobItemId = syncedItem.SyncJobItemId - }; - } - - private List<string> GetDirectoryPath(IServerSyncProvider provider, SyncJob job, SyncedItem syncedItem, BaseItemDto item, string serverName) - { - var parts = new List<string> - { - serverName - }; - - var profileOption = _syncManager.GetProfileOptions(job.TargetId) - .FirstOrDefault(i => string.Equals(i.Id, job.Profile, StringComparison.OrdinalIgnoreCase)); - - string name; - - if (profileOption != null && !string.IsNullOrWhiteSpace(profileOption.Name)) - { - name = profileOption.Name; - - if (job.Bitrate.HasValue) - { - name += "-" + job.Bitrate.Value.ToString(CultureInfo.InvariantCulture); - } - else - { - var qualityOption = _syncManager.GetQualityOptions(job.TargetId) - .FirstOrDefault(i => string.Equals(i.Id, job.Quality, StringComparison.OrdinalIgnoreCase)); - - if (qualityOption != null && !string.IsNullOrWhiteSpace(qualityOption.Name)) - { - name += "-" + qualityOption.Name; - } - } - } - else - { - name = syncedItem.SyncJobName + "-" + syncedItem.SyncJobDateCreated - .ToLocalTime() - .ToString("g") - .Replace(" ", "-"); - } - - name = GetValidFilename(provider, name); - parts.Add(name); - - if (item.IsType("episode")) - { - parts.Add("TV"); - if (!string.IsNullOrWhiteSpace(item.SeriesName)) - { - parts.Add(item.SeriesName); - } - } - else if (item.IsVideo) - { - parts.Add("Videos"); - parts.Add(item.Name); - } - else if (item.IsAudio) - { - parts.Add("Music"); - - if (!string.IsNullOrWhiteSpace(item.AlbumArtist)) - { - parts.Add(item.AlbumArtist); - } - - if (!string.IsNullOrWhiteSpace(item.Album)) - { - parts.Add(item.Album); - } - } - else if (string.Equals(item.MediaType, MediaType.Photo, StringComparison.OrdinalIgnoreCase)) - { - parts.Add("Photos"); - - if (!string.IsNullOrWhiteSpace(item.Album)) - { - parts.Add(item.Album); - } - } - - return parts.Select(i => GetValidFilename(provider, i)).ToList(); - } - - private string GetLocalFileName(IServerSyncProvider provider, BaseItemDto item, string originalFileName) - { - var filename = originalFileName; - - if (string.IsNullOrWhiteSpace(filename)) - { - filename = item.Name; - } - - return GetValidFilename(provider, filename); - } - - private string GetValidFilename(IServerSyncProvider provider, string filename) - { - // We can always add this method to the sync provider if it's really needed - return _fileSystem.GetValidFilename(filename); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs b/MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs deleted file mode 100644 index 97b2b1eb8b..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs +++ /dev/null @@ -1,74 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Progress; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Sync; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class MultiProviderSync - { - private readonly SyncManager _syncManager; - private readonly IServerApplicationHost _appHost; - private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly IConfigurationManager _config; - - public MultiProviderSync(SyncManager syncManager, IServerApplicationHost appHost, ILogger logger, IFileSystem fileSystem, IConfigurationManager config) - { - _syncManager = syncManager; - _appHost = appHost; - _logger = logger; - _fileSystem = fileSystem; - _config = config; - } - - public async Task Sync(IEnumerable<IServerSyncProvider> providers, IProgress<double> progress, CancellationToken cancellationToken) - { - var targets = providers - .SelectMany(i => i.GetAllSyncTargets().Select(t => new Tuple<IServerSyncProvider, SyncTarget>(i, t))) - .ToList(); - - var numComplete = 0; - double startingPercent = 0; - double percentPerItem = 1; - if (targets.Count > 0) - { - percentPerItem /= targets.Count; - } - - foreach (var target in targets) - { - cancellationToken.ThrowIfCancellationRequested(); - - var currentPercent = startingPercent; - var innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(pct => - { - var totalProgress = pct * percentPerItem; - totalProgress += currentPercent; - progress.Report(totalProgress); - }); - - var dataProvider = _syncManager.GetDataProvider(target.Item1, target.Item2); - - await new MediaSync(_logger, _syncManager, _appHost, _fileSystem, _config) - .Sync(target.Item1, dataProvider, target.Item2, innerProgress, cancellationToken) - .ConfigureAwait(false); - - numComplete++; - startingPercent = numComplete; - startingPercent /= targets.Count; - startingPercent *= 100; - progress.Report(startingPercent); - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/ServerSyncScheduledTask.cs b/MediaBrowser.Server.Implementations/Sync/ServerSyncScheduledTask.cs deleted file mode 100644 index 28813c715d..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/ServerSyncScheduledTask.cs +++ /dev/null @@ -1,84 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Sync -{ - class ServerSyncScheduledTask : IScheduledTask, IConfigurableScheduledTask, IHasKey - { - private readonly ISyncManager _syncManager; - private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly IServerApplicationHost _appHost; - private readonly IConfigurationManager _config; - - public ServerSyncScheduledTask(ISyncManager syncManager, ILogger logger, IFileSystem fileSystem, IServerApplicationHost appHost, IConfigurationManager config) - { - _syncManager = syncManager; - _logger = logger; - _fileSystem = fileSystem; - _appHost = appHost; - _config = config; - } - - public string Name - { - get { return "Cloud & Folder Sync"; } - } - - public string Description - { - get { return "Sync media to the cloud"; } - } - - public string Category - { - get - { - return "Sync"; - } - } - - public Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - return new MultiProviderSync((SyncManager)_syncManager, _appHost, _logger, _fileSystem, _config) - .Sync(ServerSyncProviders, progress, cancellationToken); - } - - public IEnumerable<IServerSyncProvider> ServerSyncProviders - { - get { return ((SyncManager)_syncManager).ServerSyncProviders; } - } - - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - return new ITaskTrigger[] - { - new IntervalTrigger { Interval = TimeSpan.FromHours(3) } - }; - } - - public bool IsHidden - { - get { return !IsEnabled; } - } - - public bool IsEnabled - { - get { return ServerSyncProviders.Any(); } - } - - public string Key - { - get { return "ServerSync"; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncConfig.cs b/MediaBrowser.Server.Implementations/Sync/SyncConfig.cs deleted file mode 100644 index 52c7743307..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/SyncConfig.cs +++ /dev/null @@ -1,29 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Sync; -using System.Collections.Generic; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class SyncConfigurationFactory : IConfigurationFactory - { - public IEnumerable<ConfigurationStore> GetConfigurations() - { - return new List<ConfigurationStore> - { - new ConfigurationStore - { - ConfigurationType = typeof(SyncOptions), - Key = "sync" - } - }; - } - } - - public static class SyncExtensions - { - public static SyncOptions GetSyncOptions(this IConfigurationManager config) - { - return config.GetConfiguration<SyncOptions>("sync"); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncConvertScheduledTask.cs b/MediaBrowser.Server.Implementations/Sync/SyncConvertScheduledTask.cs deleted file mode 100644 index 3f9eb76918..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/SyncConvertScheduledTask.cs +++ /dev/null @@ -1,92 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Controller.TV; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class SyncConvertScheduledTask : IScheduledTask, IConfigurableScheduledTask, IHasKey - { - private readonly ILibraryManager _libraryManager; - private readonly ISyncRepository _syncRepo; - private readonly ISyncManager _syncManager; - private readonly ILogger _logger; - private readonly IUserManager _userManager; - private readonly ITVSeriesManager _tvSeriesManager; - private readonly IMediaEncoder _mediaEncoder; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfigurationManager _config; - private readonly IFileSystem _fileSystem; - private readonly IMediaSourceManager _mediaSourceManager; - - public SyncConvertScheduledTask(ILibraryManager libraryManager, ISyncRepository syncRepo, ISyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager) - { - _libraryManager = libraryManager; - _syncRepo = syncRepo; - _syncManager = syncManager; - _logger = logger; - _userManager = userManager; - _tvSeriesManager = tvSeriesManager; - _mediaEncoder = mediaEncoder; - _subtitleEncoder = subtitleEncoder; - _config = config; - _fileSystem = fileSystem; - _mediaSourceManager = mediaSourceManager; - } - - public string Name - { - get { return "Convert media"; } - } - - public string Description - { - get { return "Runs scheduled sync jobs"; } - } - - public string Category - { - get - { - return "Sync"; - } - } - - public Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - return new SyncJobProcessor(_libraryManager, _syncRepo, (SyncManager)_syncManager, _logger, _userManager, _tvSeriesManager, _mediaEncoder, _subtitleEncoder, _config, _fileSystem, _mediaSourceManager) - .Sync(progress, cancellationToken); - } - - public IEnumerable<ITaskTrigger> GetDefaultTriggers() - { - return new ITaskTrigger[] - { - new IntervalTrigger { Interval = TimeSpan.FromHours(3) } - }; - } - - public bool IsHidden - { - get { return false; } - } - - public bool IsEnabled - { - get { return true; } - } - - public string Key - { - get { return "SyncPrepare"; } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncHelper.cs b/MediaBrowser.Server.Implementations/Sync/SyncHelper.cs deleted file mode 100644 index fb4e0c6be0..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/SyncHelper.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class SyncHelper - { - public static int? AdjustBitrate(int? profileBitrate, string quality) - { - if (profileBitrate.HasValue) - { - if (string.Equals(quality, "medium", StringComparison.OrdinalIgnoreCase)) - { - profileBitrate = Math.Min(profileBitrate.Value, 4000000); - } - else if (string.Equals(quality, "low", StringComparison.OrdinalIgnoreCase)) - { - profileBitrate = Math.Min(profileBitrate.Value, 1500000); - } - } - - return profileBitrate; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobOptions.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobOptions.cs deleted file mode 100644 index cb8141c895..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobOptions.cs +++ /dev/null @@ -1,18 +0,0 @@ -using MediaBrowser.Model.Dlna; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class SyncJobOptions - { - /// <summary> - /// Gets or sets the conversion options. - /// </summary> - /// <value>The conversion options.</value> - public DeviceProfile DeviceProfile { get; set; } - /// <summary> - /// Gets or sets a value indicating whether this instance is converting. - /// </summary> - /// <value><c>true</c> if this instance is converting; otherwise, <c>false</c>.</value> - public bool IsConverting { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs deleted file mode 100644 index d5dfd38569..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ /dev/null @@ -1,986 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Progress; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Controller.TV; -using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Session; -using MediaBrowser.Model.Sync; -using MoreLinq; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class SyncJobProcessor - { - private readonly ILibraryManager _libraryManager; - private readonly ISyncRepository _syncRepo; - private readonly SyncManager _syncManager; - private readonly ILogger _logger; - private readonly IUserManager _userManager; - private readonly ITVSeriesManager _tvSeriesManager; - private readonly IMediaEncoder _mediaEncoder; - private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IConfigurationManager _config; - private readonly IFileSystem _fileSystem; - private readonly IMediaSourceManager _mediaSourceManager; - - public SyncJobProcessor(ILibraryManager libraryManager, ISyncRepository syncRepo, SyncManager syncManager, ILogger logger, IUserManager userManager, ITVSeriesManager tvSeriesManager, IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder, IConfigurationManager config, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager) - { - _libraryManager = libraryManager; - _syncRepo = syncRepo; - _syncManager = syncManager; - _logger = logger; - _userManager = userManager; - _tvSeriesManager = tvSeriesManager; - _mediaEncoder = mediaEncoder; - _subtitleEncoder = subtitleEncoder; - _config = config; - _fileSystem = fileSystem; - _mediaSourceManager = mediaSourceManager; - } - - public async Task EnsureJobItems(SyncJob job) - { - 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(); - - var jobItems = _syncManager.GetJobItems(new SyncJobItemQuery - { - JobId = job.Id, - AddMetadata = false - - }).Items.ToList(); - - foreach (var item in items) - { - // Respect ItemLimit, if set - if (job.ItemLimit.HasValue) - { - if (jobItems.Count(j => j.Status != SyncJobItemStatus.RemovedFromDevice && j.Status != SyncJobItemStatus.Failed) >= job.ItemLimit.Value) - { - break; - } - } - - var itemId = item.Id.ToString("N"); - - var jobItem = jobItems.FirstOrDefault(i => string.Equals(i.ItemId, itemId, StringComparison.OrdinalIgnoreCase)); - - if (jobItem != null) - { - continue; - } - - var index = jobItems.Count == 0 ? - 0 : - jobItems.Select(i => i.JobItemIndex).Max() + 1; - - jobItem = new SyncJobItem - { - Id = Guid.NewGuid().ToString("N"), - ItemId = itemId, - ItemName = GetSyncJobItemName(item), - JobId = job.Id, - TargetId = job.TargetId, - DateCreated = DateTime.UtcNow, - JobItemIndex = index - }; - - await _syncRepo.Create(jobItem).ConfigureAwait(false); - _syncManager.OnSyncJobItemCreated(jobItem); - - jobItems.Add(jobItem); - } - - jobItems = jobItems - .OrderBy(i => i.DateCreated) - .ToList(); - - await UpdateJobStatus(job, jobItems).ConfigureAwait(false); - } - - private string GetSyncJobItemName(BaseItem item) - { - var name = item.Name; - var episode = item as Episode; - - if (episode != null) - { - if (episode.IndexNumber.HasValue) - { - name = "E" + episode.IndexNumber.Value.ToString(CultureInfo.InvariantCulture) + " - " + name; - } - - if (episode.ParentIndexNumber.HasValue) - { - name = "S" + episode.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture) + ", " + name; - } - } - - return name; - } - - public Task UpdateJobStatus(string id) - { - var job = _syncRepo.GetJob(id); - - if (job == null) - { - return Task.FromResult(true); - } - - var result = _syncManager.GetJobItems(new SyncJobItemQuery - { - JobId = job.Id, - AddMetadata = false - }); - - return UpdateJobStatus(job, result.Items.ToList()); - } - - private async Task UpdateJobStatus(SyncJob job, List<SyncJobItem> jobItems) - { - job.ItemCount = jobItems.Count; - - double pct = 0; - - foreach (var item in jobItems) - { - if (item.Status == SyncJobItemStatus.Failed || item.Status == SyncJobItemStatus.Synced || item.Status == SyncJobItemStatus.RemovedFromDevice || item.Status == SyncJobItemStatus.Cancelled) - { - pct += 100; - } - else - { - pct += item.Progress ?? 0; - } - } - - if (job.ItemCount > 0) - { - pct /= job.ItemCount; - job.Progress = pct; - } - else - { - job.Progress = null; - } - - if (jobItems.Any(i => i.Status == SyncJobItemStatus.Transferring)) - { - job.Status = SyncJobStatus.Transferring; - } - else if (jobItems.Any(i => i.Status == SyncJobItemStatus.Converting)) - { - job.Status = SyncJobStatus.Converting; - } - else if (jobItems.All(i => i.Status == SyncJobItemStatus.Failed)) - { - job.Status = SyncJobStatus.Failed; - } - else if (jobItems.All(i => i.Status == SyncJobItemStatus.Cancelled)) - { - job.Status = SyncJobStatus.Cancelled; - } - else if (jobItems.All(i => i.Status == SyncJobItemStatus.ReadyToTransfer)) - { - job.Status = SyncJobStatus.ReadyToTransfer; - } - else if (jobItems.All(i => i.Status == SyncJobItemStatus.Cancelled || i.Status == SyncJobItemStatus.Failed || i.Status == SyncJobItemStatus.Synced || i.Status == SyncJobItemStatus.RemovedFromDevice)) - { - if (jobItems.Any(i => i.Status == SyncJobItemStatus.Failed)) - { - job.Status = SyncJobStatus.CompletedWithError; - } - else - { - job.Status = SyncJobStatus.Completed; - } - } - else - { - job.Status = SyncJobStatus.Queued; - } - - await _syncRepo.Update(job).ConfigureAwait(false); - - _syncManager.OnSyncJobUpdated(job); - } - - public async Task<IEnumerable<BaseItem>> GetItemsForSync(SyncCategory? category, string parentId, IEnumerable<string> itemIds, User user, bool unwatchedOnly) - { - var list = new List<BaseItem>(); - - if (category.HasValue) - { - list = (await GetItemsForSync(category.Value, parentId, user).ConfigureAwait(false)).ToList(); - } - else - { - foreach (var itemId in itemIds) - { - var subList = await GetItemsForSync(itemId, user).ConfigureAwait(false); - list.AddRange(subList); - } - } - - IEnumerable<BaseItem> items = list; - items = items.Where(_syncManager.SupportsSync); - - if (unwatchedOnly) - { - // Avoid implicitly captured closure - var currentUser = user; - - items = items.Where(i => - { - var video = i as Video; - - if (video != null) - { - return !video.IsPlayed(currentUser); - } - - return true; - }); - } - - return items.DistinctBy(i => i.Id); - } - - private async Task<IEnumerable<BaseItem>> GetItemsForSync(SyncCategory category, string parentId, User user) - { - var parent = string.IsNullOrWhiteSpace(parentId) - ? user.RootFolder - : (Folder)_libraryManager.GetItemById(parentId); - - InternalItemsQuery query; - - switch (category) - { - case SyncCategory.Latest: - query = new InternalItemsQuery - { - IsFolder = false, - SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }, - SortOrder = SortOrder.Descending, - Recursive = true - }; - break; - case SyncCategory.Resume: - query = new InternalItemsQuery - { - IsFolder = false, - SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }, - SortOrder = SortOrder.Descending, - Recursive = true, - IsResumable = true, - MediaTypes = new[] { MediaType.Video } - }; - break; - - case SyncCategory.NextUp: - return _tvSeriesManager.GetNextUp(new NextUpQuery - { - ParentId = parentId, - UserId = user.Id.ToString("N") - }).Items; - - default: - throw new ArgumentException("Unrecognized category: " + category); - } - - if (parent == null) - { - return new List<BaseItem>(); - } - - query.User = user; - - var result = await parent.GetItems(query).ConfigureAwait(false); - return result.Items; - } - - private async Task<List<BaseItem>> GetItemsForSync(string id, User user) - { - var item = _libraryManager.GetItemById(id); - - if (item == null) - { - return new List<BaseItem>(); - } - - var itemByName = item as IItemByName; - if (itemByName != null) - { - return itemByName.GetTaggedItems(new InternalItemsQuery(user) - { - IsFolder = false, - Recursive = true - }).ToList(); - } - - if (item.IsFolder) - { - var folder = (Folder)item; - var itemsResult = await folder.GetItems(new InternalItemsQuery(user) - { - Recursive = true, - IsFolder = false - - }).ConfigureAwait(false); - - var items = itemsResult.Items; - - if (!folder.IsPreSorted) - { - items = _libraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending) - .ToArray(); - } - - return items.ToList(); - } - - return new List<BaseItem> { item }; - } - - private async Task EnsureSyncJobItems(string targetId, CancellationToken cancellationToken) - { - var jobResult = _syncRepo.GetJobs(new SyncJobQuery - { - SyncNewContent = true, - TargetId = targetId - }); - - foreach (var job in jobResult.Items) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (job.SyncNewContent) - { - await EnsureJobItems(job).ConfigureAwait(false); - } - } - } - - public async Task Sync(IProgress<double> progress, CancellationToken cancellationToken) - { - await EnsureSyncJobItems(null, cancellationToken).ConfigureAwait(false); - - // Look job items that are supposedly transfering, but need to be requeued because the synced files have been deleted somehow - await HandleDeletedSyncFiles(cancellationToken).ConfigureAwait(false); - - // If it already has a converting status then is must have been aborted during conversion - var result = _syncManager.GetJobItems(new SyncJobItemQuery - { - Statuses = new[] { SyncJobItemStatus.Queued, SyncJobItemStatus.Converting }, - AddMetadata = false - }); - - await SyncJobItems(result.Items, true, progress, cancellationToken).ConfigureAwait(false); - - CleanDeadSyncFiles(); - } - - private async Task HandleDeletedSyncFiles(CancellationToken cancellationToken) - { - // Look job items that are supposedly transfering, but need to be requeued because the synced files have been deleted somehow - var result = _syncManager.GetJobItems(new SyncJobItemQuery - { - Statuses = new[] { SyncJobItemStatus.ReadyToTransfer, SyncJobItemStatus.Transferring }, - AddMetadata = false - }); - - foreach (var item in result.Items) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (string.IsNullOrWhiteSpace(item.OutputPath) || !_fileSystem.FileExists(item.OutputPath)) - { - item.Status = SyncJobItemStatus.Queued; - await _syncManager.UpdateSyncJobItemInternal(item).ConfigureAwait(false); - await UpdateJobStatus(item.JobId).ConfigureAwait(false); - } - } - } - - private void CleanDeadSyncFiles() - { - // TODO - // Clean files in sync temp folder that are not linked to any sync jobs - } - - public async Task SyncJobItems(string targetId, bool enableConversion, IProgress<double> progress, - CancellationToken cancellationToken) - { - await EnsureSyncJobItems(targetId, cancellationToken).ConfigureAwait(false); - - // If it already has a converting status then is must have been aborted during conversion - var result = _syncManager.GetJobItems(new SyncJobItemQuery - { - Statuses = new[] { SyncJobItemStatus.Queued, SyncJobItemStatus.Converting }, - TargetId = targetId, - AddMetadata = false - }); - - await SyncJobItems(result.Items, enableConversion, progress, cancellationToken).ConfigureAwait(false); - } - - public async Task SyncJobItems(SyncJobItem[] items, bool enableConversion, IProgress<double> progress, CancellationToken cancellationToken) - { - if (items.Length > 0) - { - if (!SyncRegistrationInfo.Instance.IsRegistered) - { - _logger.Debug("Cancelling sync job processing. Please obtain a supporter membership."); - return; - } - } - - var numComplete = 0; - - foreach (var item in items) - { - cancellationToken.ThrowIfCancellationRequested(); - - double percentPerItem = 1; - percentPerItem /= items.Length; - var startingPercent = numComplete * percentPerItem * 100; - - var innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(p => progress.Report(startingPercent + percentPerItem * p)); - - // Pull it fresh from the db just to make sure it wasn't deleted or cancelled while another item was converting - var jobItem = enableConversion ? _syncRepo.GetJobItem(item.Id) : item; - - if (jobItem != null) - { - if (jobItem.Status != SyncJobItemStatus.Cancelled) - { - await ProcessJobItem(jobItem, enableConversion, innerProgress, cancellationToken).ConfigureAwait(false); - } - - await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); - } - - numComplete++; - double percent = numComplete; - percent /= items.Length; - progress.Report(100 * percent); - } - } - - private async Task ProcessJobItem(SyncJobItem jobItem, bool enableConversion, IProgress<double> progress, CancellationToken cancellationToken) - { - if (jobItem == null) - { - throw new ArgumentNullException("jobItem"); - } - - var item = _libraryManager.GetItemById(jobItem.ItemId); - if (item == null) - { - jobItem.Status = SyncJobItemStatus.Failed; - _logger.Error("Unable to locate library item for JobItem {0}, ItemId {1}", jobItem.Id, jobItem.ItemId); - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - return; - } - - jobItem.Progress = 0; - - var syncOptions = _config.GetSyncOptions(); - var job = _syncManager.GetJob(jobItem.JobId); - var user = _userManager.GetUserById(job.UserId); - if (user == null) - { - jobItem.Status = SyncJobItemStatus.Failed; - _logger.Error("User not found. Cannot complete the sync job."); - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - return; - } - - // See if there's already another active job item for the same target - var existingJobItems = _syncManager.GetJobItems(new SyncJobItemQuery - { - AddMetadata = false, - ItemId = jobItem.ItemId, - TargetId = jobItem.TargetId, - Statuses = new[] { SyncJobItemStatus.Converting, SyncJobItemStatus.Queued, SyncJobItemStatus.ReadyToTransfer, SyncJobItemStatus.Synced, SyncJobItemStatus.Transferring } - }); - - var duplicateJobItems = existingJobItems.Items - .Where(i => !string.Equals(i.Id, jobItem.Id, StringComparison.OrdinalIgnoreCase)) - .ToList(); - - if (duplicateJobItems.Count > 0) - { - var syncProvider = _syncManager.GetSyncProvider(jobItem) as IHasDuplicateCheck; - - if (!duplicateJobItems.Any(i => AllowDuplicateJobItem(syncProvider, i, jobItem))) - { - _logger.Debug("Cancelling sync job item because there is already another active job for the same target."); - jobItem.Status = SyncJobItemStatus.Cancelled; - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - return; - } - } - - var video = item as Video; - if (video != null) - { - await Sync(jobItem, video, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false); - } - - else if (item is Audio) - { - await Sync(jobItem, (Audio)item, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false); - } - - else if (item is Photo) - { - await Sync(jobItem, (Photo)item, cancellationToken).ConfigureAwait(false); - } - - else - { - await SyncGeneric(jobItem, item, cancellationToken).ConfigureAwait(false); - } - } - - private bool AllowDuplicateJobItem(IHasDuplicateCheck provider, SyncJobItem original, SyncJobItem duplicate) - { - if (provider != null) - { - return provider.AllowDuplicateJobItem(original, duplicate); - } - - return true; - } - - private async Task Sync(SyncJobItem jobItem, Video item, User user, bool enableConversion, SyncOptions syncOptions, IProgress<double> progress, CancellationToken cancellationToken) - { - var job = _syncManager.GetJob(jobItem.JobId); - var jobOptions = _syncManager.GetVideoOptions(jobItem, job); - var conversionOptions = new VideoOptions - { - Profile = jobOptions.DeviceProfile - }; - - conversionOptions.DeviceId = jobItem.TargetId; - conversionOptions.Context = EncodingContext.Static; - conversionOptions.ItemId = item.Id.ToString("N"); - conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList(); - - var streamInfo = new StreamBuilder(_mediaEncoder, _logger).BuildVideoItem(conversionOptions); - var mediaSource = streamInfo.MediaSource; - - // No sense creating external subs if we're already burning one into the video - var externalSubs = streamInfo.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode ? - new List<SubtitleStreamInfo>() : - streamInfo.GetExternalSubtitles(false, true, null, null); - - // Mark as requiring conversion if transcoding the video, or if any subtitles need to be extracted - var requiresVideoTranscoding = streamInfo.PlayMethod == PlayMethod.Transcode && jobOptions.IsConverting; - var requiresConversion = requiresVideoTranscoding || externalSubs.Any(i => RequiresExtraction(i, mediaSource)); - - if (requiresConversion && !enableConversion) - { - return; - } - - jobItem.MediaSourceId = streamInfo.MediaSourceId; - jobItem.TemporaryPath = GetTemporaryPath(jobItem); - - if (requiresConversion) - { - jobItem.Status = SyncJobItemStatus.Converting; - } - - if (requiresVideoTranscoding) - { - // Save the job item now since conversion could take a while - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); - - try - { - var lastJobUpdate = DateTime.MinValue; - var innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(async pct => - { - progress.Report(pct); - - if ((DateTime.UtcNow - lastJobUpdate).TotalSeconds >= DatabaseProgressUpdateIntervalSeconds) - { - jobItem.Progress = pct / 2; - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); - } - }); - - jobItem.OutputPath = await _mediaEncoder.EncodeVideo(new EncodingJobOptions(streamInfo, conversionOptions.Profile) - { - OutputDirectory = jobItem.TemporaryPath, - CpuCoreLimit = syncOptions.TranscodingCpuCoreLimit, - ReadInputAtNativeFramerate = !syncOptions.EnableFullSpeedTranscoding - - }, innerProgress, cancellationToken); - - jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; - _syncManager.OnConversionComplete(jobItem); - } - catch (OperationCanceledException) - { - jobItem.Status = SyncJobItemStatus.Queued; - jobItem.Progress = 0; - } - catch (Exception ex) - { - jobItem.Status = SyncJobItemStatus.Failed; - _logger.ErrorException("Error during sync transcoding", ex); - } - - if (jobItem.Status == SyncJobItemStatus.Failed || jobItem.Status == SyncJobItemStatus.Queued) - { - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - return; - } - - jobItem.MediaSource = await GetEncodedMediaSource(jobItem.OutputPath, user, true).ConfigureAwait(false); - } - else - { - if (mediaSource.Protocol == MediaProtocol.File) - { - jobItem.OutputPath = mediaSource.Path; - } - else if (mediaSource.Protocol == MediaProtocol.Http) - { - jobItem.OutputPath = await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false); - } - else - { - throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); - } - - jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; - jobItem.MediaSource = mediaSource; - } - - jobItem.MediaSource.SupportsTranscoding = false; - - if (externalSubs.Count > 0) - { - // Save the job item now since conversion could take a while - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - - await ConvertSubtitles(jobItem, externalSubs, streamInfo, cancellationToken).ConfigureAwait(false); - } - - jobItem.Progress = 50; - jobItem.Status = SyncJobItemStatus.ReadyToTransfer; - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - } - - private bool RequiresExtraction(SubtitleStreamInfo stream, MediaSourceInfo mediaSource) - { - var originalStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Subtitle && i.Index == stream.Index); - - return originalStream != null && !originalStream.IsExternal; - } - - private async Task ConvertSubtitles(SyncJobItem jobItem, - IEnumerable<SubtitleStreamInfo> subtitles, - StreamInfo streamInfo, - CancellationToken cancellationToken) - { - var files = new List<ItemFileInfo>(); - - var mediaStreams = jobItem.MediaSource.MediaStreams - .Where(i => i.Type != MediaStreamType.Subtitle || !i.IsExternal) - .ToList(); - - var startingIndex = mediaStreams.Count == 0 ? - 0 : - mediaStreams.Select(i => i.Index).Max() + 1; - - foreach (var subtitle in subtitles) - { - var fileInfo = await ConvertSubtitles(jobItem.TemporaryPath, streamInfo, subtitle, cancellationToken).ConfigureAwait(false); - - // Reset this to a value that will be based on the output media - fileInfo.Index = startingIndex; - files.Add(fileInfo); - - mediaStreams.Add(new MediaStream - { - Index = startingIndex, - Codec = subtitle.Format, - IsForced = subtitle.IsForced, - IsExternal = true, - Language = subtitle.Language, - Path = fileInfo.Path, - SupportsExternalStream = true, - Type = MediaStreamType.Subtitle - }); - - startingIndex++; - } - - jobItem.AdditionalFiles.AddRange(files); - - jobItem.MediaSource.MediaStreams = mediaStreams; - } - - private async Task<ItemFileInfo> ConvertSubtitles(string temporaryPath, StreamInfo streamInfo, SubtitleStreamInfo subtitleStreamInfo, CancellationToken cancellationToken) - { - var subtitleStreamIndex = subtitleStreamInfo.Index; - - var filename = Guid.NewGuid() + "." + subtitleStreamInfo.Format.ToLower(); - - var path = Path.Combine(temporaryPath, filename); - - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - - using (var stream = await _subtitleEncoder.GetSubtitles(streamInfo.ItemId, streamInfo.MediaSourceId, subtitleStreamIndex, subtitleStreamInfo.Format, 0, null, false, cancellationToken).ConfigureAwait(false)) - { - using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) - { - await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false); - } - } - - return new ItemFileInfo - { - Name = Path.GetFileName(path), - Path = path, - Type = ItemFileType.Subtitles, - Index = subtitleStreamIndex - }; - } - - private const int DatabaseProgressUpdateIntervalSeconds = 2; - - private async Task Sync(SyncJobItem jobItem, Audio item, User user, bool enableConversion, SyncOptions syncOptions, IProgress<double> progress, CancellationToken cancellationToken) - { - var job = _syncManager.GetJob(jobItem.JobId); - var jobOptions = _syncManager.GetAudioOptions(jobItem, job); - var conversionOptions = new AudioOptions - { - Profile = jobOptions.DeviceProfile - }; - - conversionOptions.DeviceId = jobItem.TargetId; - conversionOptions.Context = EncodingContext.Static; - conversionOptions.ItemId = item.Id.ToString("N"); - conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList(); - - var streamInfo = new StreamBuilder(_mediaEncoder, _logger).BuildAudioItem(conversionOptions); - var mediaSource = streamInfo.MediaSource; - - jobItem.MediaSourceId = streamInfo.MediaSourceId; - jobItem.TemporaryPath = GetTemporaryPath(jobItem); - - if (streamInfo.PlayMethod == PlayMethod.Transcode && jobOptions.IsConverting) - { - if (!enableConversion) - { - return; - } - - jobItem.Status = SyncJobItemStatus.Converting; - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); - - try - { - var lastJobUpdate = DateTime.MinValue; - var innerProgress = new ActionableProgress<double>(); - innerProgress.RegisterAction(async pct => - { - progress.Report(pct); - - if ((DateTime.UtcNow - lastJobUpdate).TotalSeconds >= DatabaseProgressUpdateIntervalSeconds) - { - jobItem.Progress = pct / 2; - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); - } - }); - - jobItem.OutputPath = await _mediaEncoder.EncodeAudio(new EncodingJobOptions(streamInfo, conversionOptions.Profile) - { - OutputDirectory = jobItem.TemporaryPath, - CpuCoreLimit = syncOptions.TranscodingCpuCoreLimit - - }, innerProgress, cancellationToken); - - jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; - _syncManager.OnConversionComplete(jobItem); - } - catch (OperationCanceledException) - { - jobItem.Status = SyncJobItemStatus.Queued; - jobItem.Progress = 0; - } - catch (Exception ex) - { - jobItem.Status = SyncJobItemStatus.Failed; - _logger.ErrorException("Error during sync transcoding", ex); - } - - if (jobItem.Status == SyncJobItemStatus.Failed || jobItem.Status == SyncJobItemStatus.Queued) - { - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - return; - } - - jobItem.MediaSource = await GetEncodedMediaSource(jobItem.OutputPath, user, false).ConfigureAwait(false); - } - else - { - if (mediaSource.Protocol == MediaProtocol.File) - { - jobItem.OutputPath = mediaSource.Path; - } - else if (mediaSource.Protocol == MediaProtocol.Http) - { - jobItem.OutputPath = await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false); - } - else - { - throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); - } - - jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; - jobItem.MediaSource = mediaSource; - } - - jobItem.MediaSource.SupportsTranscoding = false; - - jobItem.Progress = 50; - jobItem.Status = SyncJobItemStatus.ReadyToTransfer; - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - } - - private async Task Sync(SyncJobItem jobItem, Photo item, CancellationToken cancellationToken) - { - jobItem.OutputPath = item.Path; - - jobItem.Progress = 50; - jobItem.Status = SyncJobItemStatus.ReadyToTransfer; - jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - } - - private async Task SyncGeneric(SyncJobItem jobItem, BaseItem item, CancellationToken cancellationToken) - { - jobItem.OutputPath = item.Path; - - jobItem.Progress = 50; - jobItem.Status = SyncJobItemStatus.ReadyToTransfer; - jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; - await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - } - - private async Task<string> DownloadFile(SyncJobItem jobItem, MediaSourceInfo mediaSource, CancellationToken cancellationToken) - { - // TODO: Download - return mediaSource.Path; - } - - public string GetTemporaryPath(SyncJob job) - { - return GetTemporaryPath(job.Id); - } - - public string GetTemporaryPath(string jobId) - { - var basePath = _config.GetSyncOptions().TemporaryPath; - - if (string.IsNullOrWhiteSpace(basePath)) - { - basePath = Path.Combine(_config.CommonApplicationPaths.ProgramDataPath, "sync"); - } - - return Path.Combine(basePath, jobId); - } - - public string GetTemporaryPath(SyncJobItem jobItem) - { - return Path.Combine(GetTemporaryPath(jobItem.JobId), jobItem.Id); - } - - private async Task<MediaSourceInfo> GetEncodedMediaSource(string path, User user, bool isVideo) - { - var item = _libraryManager.ResolvePath(_fileSystem.GetFileSystemInfo(path)); - - await item.RefreshMetadata(CancellationToken.None).ConfigureAwait(false); - - var hasMediaSources = item as IHasMediaSources; - - var mediaSources = _mediaSourceManager.GetStaticMediaSources(hasMediaSources, false).ToList(); - - var preferredAudio = string.IsNullOrEmpty(user.Configuration.AudioLanguagePreference) - ? new string[] { } - : new[] { user.Configuration.AudioLanguagePreference }; - - var preferredSubs = string.IsNullOrEmpty(user.Configuration.SubtitleLanguagePreference) - ? new List<string>() : new List<string> { user.Configuration.SubtitleLanguagePreference }; - - foreach (var source in mediaSources) - { - if (isVideo) - { - source.DefaultAudioStreamIndex = - MediaStreamSelector.GetDefaultAudioStreamIndex(source.MediaStreams, preferredAudio, user.Configuration.PlayDefaultAudioTrack); - - var defaultAudioIndex = source.DefaultAudioStreamIndex; - var audioLangage = defaultAudioIndex == null - ? null - : source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault(); - - source.DefaultAudioStreamIndex = - MediaStreamSelector.GetDefaultSubtitleStreamIndex(source.MediaStreams, preferredSubs, user.Configuration.SubtitleMode, audioLangage); - } - else - { - var audio = source.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio); - - if (audio != null) - { - source.DefaultAudioStreamIndex = audio.Index; - } - - } - } - - return mediaSources.FirstOrDefault(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs deleted file mode 100644 index c523ec7bde..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ /dev/null @@ -1,1360 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Events; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Playlists; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Controller.TV; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Sync; -using MediaBrowser.Model.Users; -using MoreLinq; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class SyncManager : ISyncManager - { - private readonly ILibraryManager _libraryManager; - private readonly ISyncRepository _repo; - private readonly IImageProcessor _imageProcessor; - private readonly ILogger _logger; - private readonly IUserManager _userManager; - private readonly Func<IDtoService> _dtoService; - private readonly IServerApplicationHost _appHost; - private readonly ITVSeriesManager _tvSeriesManager; - private readonly Func<IMediaEncoder> _mediaEncoder; - private readonly IFileSystem _fileSystem; - private readonly Func<ISubtitleEncoder> _subtitleEncoder; - private readonly IConfigurationManager _config; - private readonly IUserDataManager _userDataManager; - private readonly Func<IMediaSourceManager> _mediaSourceManager; - private readonly IJsonSerializer _json; - private readonly ITaskManager _taskManager; - private readonly IMemoryStreamProvider _memoryStreamProvider; - - private ISyncProvider[] _providers = { }; - - public event EventHandler<GenericEventArgs<SyncJobCreationResult>> SyncJobCreated; - public event EventHandler<GenericEventArgs<SyncJob>> SyncJobCancelled; - public event EventHandler<GenericEventArgs<SyncJob>> SyncJobUpdated; - public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemUpdated; - public event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemCreated; - - public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IServerApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func<IMediaEncoder> mediaEncoder, IFileSystem fileSystem, Func<ISubtitleEncoder> subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func<IMediaSourceManager> mediaSourceManager, IJsonSerializer json, ITaskManager taskManager, IMemoryStreamProvider memoryStreamProvider) - { - _libraryManager = libraryManager; - _repo = repo; - _imageProcessor = imageProcessor; - _logger = logger; - _userManager = userManager; - _dtoService = dtoService; - _appHost = appHost; - _tvSeriesManager = tvSeriesManager; - _mediaEncoder = mediaEncoder; - _fileSystem = fileSystem; - _subtitleEncoder = subtitleEncoder; - _config = config; - _userDataManager = userDataManager; - _mediaSourceManager = mediaSourceManager; - _json = json; - _taskManager = taskManager; - _memoryStreamProvider = memoryStreamProvider; - } - - public void AddParts(IEnumerable<ISyncProvider> providers) - { - _providers = providers.ToArray(); - } - - public IEnumerable<IServerSyncProvider> ServerSyncProviders - { - get { return _providers.OfType<IServerSyncProvider>(); } - } - - private readonly ConcurrentDictionary<string, ISyncDataProvider> _dataProviders = - new ConcurrentDictionary<string, ISyncDataProvider>(StringComparer.OrdinalIgnoreCase); - - public ISyncDataProvider GetDataProvider(IServerSyncProvider provider, SyncTarget target) - { - return _dataProviders.GetOrAdd(target.Id, key => new TargetDataProvider(provider, target, _appHost, _logger, _json, _fileSystem, _config.CommonApplicationPaths, _memoryStreamProvider)); - } - - public async Task<SyncJobCreationResult> CreateJob(SyncJobRequest request) - { - var processor = GetSyncJobProcessor(); - - var user = _userManager.GetUserById(request.UserId); - - var items = (await processor - .GetItemsForSync(request.Category, request.ParentId, request.ItemIds, user, request.UnwatchedOnly).ConfigureAwait(false)) - .ToList(); - - if (items.Any(i => !SupportsSync(i))) - { - throw new ArgumentException("Item does not support sync."); - } - - if (string.IsNullOrWhiteSpace(request.Name)) - { - if (request.ItemIds.Count == 1) - { - request.Name = GetDefaultName(_libraryManager.GetItemById(request.ItemIds[0])); - } - } - - if (string.IsNullOrWhiteSpace(request.Name)) - { - request.Name = DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString(); - } - - var target = GetSyncTargets(request.UserId) - .FirstOrDefault(i => string.Equals(request.TargetId, i.Id)); - - if (target == null) - { - throw new ArgumentException("Sync target not found."); - } - - var jobId = Guid.NewGuid().ToString("N"); - - if (string.IsNullOrWhiteSpace(request.Quality)) - { - request.Quality = GetQualityOptions(request.TargetId) - .Where(i => i.IsDefault) - .Select(i => i.Id) - .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); - } - - var job = new SyncJob - { - Id = jobId, - Name = request.Name, - TargetId = target.Id, - UserId = request.UserId, - UnwatchedOnly = request.UnwatchedOnly, - ItemLimit = request.ItemLimit, - RequestedItemIds = request.ItemIds ?? new List<string>(), - DateCreated = DateTime.UtcNow, - DateLastModified = DateTime.UtcNow, - SyncNewContent = request.SyncNewContent, - ItemCount = items.Count, - Category = request.Category, - ParentId = request.ParentId, - Quality = request.Quality, - Profile = request.Profile, - Bitrate = request.Bitrate - }; - - if (!request.Category.HasValue && request.ItemIds != null) - { - var requestedItems = request.ItemIds - .Select(_libraryManager.GetItemById) - .Where(i => i != null); - - // It's just a static list - if (!requestedItems.Any(i => i.IsFolder || i is IItemByName)) - { - job.SyncNewContent = false; - } - } - - await _repo.Create(job).ConfigureAwait(false); - - await processor.EnsureJobItems(job).ConfigureAwait(false); - - // If it already has a converting status then is must have been aborted during conversion - var jobItemsResult = GetJobItems(new SyncJobItemQuery - { - Statuses = new[] { SyncJobItemStatus.Queued, SyncJobItemStatus.Converting }, - JobId = jobId, - AddMetadata = false - }); - - await processor.SyncJobItems(jobItemsResult.Items, false, new Progress<double>(), CancellationToken.None) - .ConfigureAwait(false); - - jobItemsResult = GetJobItems(new SyncJobItemQuery - { - Statuses = new[] { SyncJobItemStatus.Queued, SyncJobItemStatus.Converting }, - JobId = jobId, - AddMetadata = false - }); - - var returnResult = new SyncJobCreationResult - { - Job = GetJob(jobId), - JobItems = jobItemsResult.Items.ToList() - }; - - if (SyncJobCreated != null) - { - EventHelper.FireEventIfNotNull(SyncJobCreated, this, new GenericEventArgs<SyncJobCreationResult> - { - Argument = returnResult - - }, _logger); - } - - if (returnResult.JobItems.Any(i => i.Status == SyncJobItemStatus.Queued || i.Status == SyncJobItemStatus.Converting)) - { - _taskManager.QueueScheduledTask<SyncConvertScheduledTask>(); - } - - return returnResult; - } - - public async Task UpdateJob(SyncJob job) - { - // Get fresh from the db and only update the fields that are supported to be changed. - var instance = _repo.GetJob(job.Id); - - instance.Name = job.Name; - instance.Quality = job.Quality; - instance.Profile = job.Profile; - instance.UnwatchedOnly = job.UnwatchedOnly; - instance.SyncNewContent = job.SyncNewContent; - instance.ItemLimit = job.ItemLimit; - - await _repo.Update(instance).ConfigureAwait(false); - - OnSyncJobUpdated(instance); - } - - internal void OnSyncJobUpdated(SyncJob job) - { - if (SyncJobUpdated != null) - { - EventHelper.FireEventIfNotNull(SyncJobUpdated, this, new GenericEventArgs<SyncJob> - { - Argument = job - - }, _logger); - } - } - - internal async Task UpdateSyncJobItemInternal(SyncJobItem jobItem) - { - await _repo.Update(jobItem).ConfigureAwait(false); - - if (SyncJobUpdated != null) - { - EventHelper.FireEventIfNotNull(SyncJobItemUpdated, this, new GenericEventArgs<SyncJobItem> - { - Argument = jobItem - - }, _logger); - } - } - - internal void OnSyncJobItemCreated(SyncJobItem job) - { - if (SyncJobUpdated != null) - { - EventHelper.FireEventIfNotNull(SyncJobItemCreated, this, new GenericEventArgs<SyncJobItem> - { - Argument = job - - }, _logger); - } - } - - public async Task<QueryResult<SyncJob>> GetJobs(SyncJobQuery query) - { - var result = _repo.GetJobs(query); - - foreach (var item in result.Items) - { - await FillMetadata(item).ConfigureAwait(false); - } - - return result; - } - - private async Task FillMetadata(SyncJob job) - { - var user = _userManager.GetUserById(job.UserId); - - if (user == null) - { - return; - } - - var target = GetSyncTargets(job.UserId) - .FirstOrDefault(i => string.Equals(i.Id, job.TargetId, StringComparison.OrdinalIgnoreCase)); - - if (target != null) - { - job.TargetName = target.Name; - } - - var item = job.RequestedItemIds - .Select(_libraryManager.GetItemById) - .FirstOrDefault(i => i != null); - - if (item == null) - { - var processor = GetSyncJobProcessor(); - - item = (await processor - .GetItemsForSync(job.Category, job.ParentId, job.RequestedItemIds, user, job.UnwatchedOnly).ConfigureAwait(false)) - .FirstOrDefault(); - } - - if (item != null) - { - var hasSeries = item as IHasSeries; - if (hasSeries != null) - { - job.ParentName = hasSeries.SeriesName; - } - - var hasAlbumArtist = item as IHasAlbumArtist; - if (hasAlbumArtist != null) - { - job.ParentName = hasAlbumArtist.AlbumArtists.FirstOrDefault(); - } - - var primaryImage = item.GetImageInfo(ImageType.Primary, 0); - var itemWithImage = item; - - if (primaryImage == null) - { - var parentWithImage = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Primary)); - - if (parentWithImage != null) - { - itemWithImage = parentWithImage; - primaryImage = parentWithImage.GetImageInfo(ImageType.Primary, 0); - } - } - - if (primaryImage != null) - { - try - { - job.PrimaryImageTag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Primary); - job.PrimaryImageItemId = itemWithImage.Id.ToString("N"); - - } - catch (Exception ex) - { - _logger.ErrorException("Error getting image info", ex); - } - } - } - } - - private void FillMetadata(SyncJobItem jobItem) - { - var item = _libraryManager.GetItemById(jobItem.ItemId); - - if (item == null) - { - return; - } - - var primaryImage = item.GetImageInfo(ImageType.Primary, 0); - var itemWithImage = item; - - if (primaryImage == null) - { - var parentWithImage = item.GetParents().FirstOrDefault(i => i.HasImage(ImageType.Primary)); - - if (parentWithImage != null) - { - itemWithImage = parentWithImage; - primaryImage = parentWithImage.GetImageInfo(ImageType.Primary, 0); - } - } - - if (primaryImage != null) - { - try - { - jobItem.PrimaryImageTag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Primary); - jobItem.PrimaryImageItemId = itemWithImage.Id.ToString("N"); - - } - catch (Exception ex) - { - _logger.ErrorException("Error getting image info", ex); - } - } - } - - public async Task CancelJob(string id) - { - var job = GetJob(id); - - if (job == null) - { - throw new ArgumentException("Job not found."); - } - - await _repo.DeleteJob(id).ConfigureAwait(false); - - var path = GetSyncJobProcessor().GetTemporaryPath(id); - - try - { - _fileSystem.DeleteDirectory(path, true); - } - catch (DirectoryNotFoundException) - { - - } - catch (Exception ex) - { - _logger.ErrorException("Error deleting directory {0}", ex, path); - } - - if (SyncJobCancelled != null) - { - EventHelper.FireEventIfNotNull(SyncJobCancelled, this, new GenericEventArgs<SyncJob> - { - Argument = job - - }, _logger); - } - } - - public SyncJob GetJob(string id) - { - return _repo.GetJob(id); - } - - public IEnumerable<SyncTarget> GetSyncTargets(string userId) - { - return _providers - .SelectMany(i => GetSyncTargets(i, userId)) - .OrderBy(i => i.Name); - } - - private IEnumerable<SyncTarget> GetSyncTargets(ISyncProvider provider) - { - return provider.GetAllSyncTargets().Select(i => new SyncTarget - { - Name = i.Name, - Id = GetSyncTargetId(provider, i) - }); - } - - private IEnumerable<SyncTarget> GetSyncTargets(ISyncProvider provider, string userId) - { - return provider.GetSyncTargets(userId).Select(i => new SyncTarget - { - Name = i.Name, - Id = GetSyncTargetId(provider, i) - }); - } - - private string GetSyncTargetId(ISyncProvider provider, SyncTarget target) - { - var hasUniqueId = provider as IHasUniqueTargetIds; - - if (hasUniqueId != null) - { - return target.Id; - } - - return target.Id; - //var providerId = GetSyncProviderId(provider); - //return (providerId + "-" + target.Id).GetMD5().ToString("N"); - } - - private string GetSyncProviderId(ISyncProvider provider) - { - return provider.GetType().Name.GetMD5().ToString("N"); - } - - public bool SupportsSync(BaseItem item) - { - if (item == null) - { - throw new ArgumentNullException("item"); - } - - if (item is Playlist) - { - return true; - } - - if (item is Person) - { - return false; - } - - if (item is Year) - { - return false; - } - - if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase) || - string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) || - string.Equals(item.MediaType, MediaType.Photo, StringComparison.OrdinalIgnoreCase) || - string.Equals(item.MediaType, MediaType.Game, StringComparison.OrdinalIgnoreCase) || - string.Equals(item.MediaType, MediaType.Book, StringComparison.OrdinalIgnoreCase)) - { - if (item.LocationType == LocationType.Virtual) - { - return false; - } - - var video = item as Video; - if (video != null) - { - if (video.IsPlaceHolder) - { - return false; - } - - if (video.IsShortcut) - { - return false; - } - } - - if (item.SourceType != SourceType.Library) - { - return false; - } - - return true; - } - - if (item.SourceType == SourceType.Channel) - { - return BaseItem.ChannelManager.SupportsSync(item.ChannelId); - } - - return item.LocationType == LocationType.FileSystem || item is Season; - } - - private string GetDefaultName(BaseItem item) - { - return item.Name; - } - - public async Task ReportSyncJobItemTransferred(string id) - { - var jobItem = _repo.GetJobItem(id); - - jobItem.Status = SyncJobItemStatus.Synced; - jobItem.Progress = 100; - - await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - - var processor = GetSyncJobProcessor(); - - await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); - - if (!string.IsNullOrWhiteSpace(jobItem.TemporaryPath)) - { - try - { - _fileSystem.DeleteDirectory(jobItem.TemporaryPath, true); - } - catch (DirectoryNotFoundException) - { - } - catch (Exception ex) - { - _logger.ErrorException("Error deleting temporary job file: {0}", ex, jobItem.OutputPath); - } - } - } - - private SyncJobProcessor GetSyncJobProcessor() - { - return new SyncJobProcessor(_libraryManager, _repo, this, _logger, _userManager, _tvSeriesManager, _mediaEncoder(), _subtitleEncoder(), _config, _fileSystem, _mediaSourceManager()); - } - - public SyncJobItem GetJobItem(string id) - { - return _repo.GetJobItem(id); - } - - public QueryResult<SyncJobItem> GetJobItems(SyncJobItemQuery query) - { - var result = _repo.GetJobItems(query); - - if (query.AddMetadata) - { - result.Items.ForEach(FillMetadata); - } - - return result; - } - - private SyncedItem GetJobItemInfo(SyncJobItem jobItem) - { - var job = _repo.GetJob(jobItem.JobId); - - if (job == null) - { - _logger.Error("GetJobItemInfo job id {0} no longer exists", jobItem.JobId); - return null; - } - - var libraryItem = _libraryManager.GetItemById(jobItem.ItemId); - - if (libraryItem == null) - { - _logger.Error("GetJobItemInfo library item with id {0} no longer exists", jobItem.ItemId); - return null; - } - - var syncedItem = new SyncedItem - { - SyncJobId = jobItem.JobId, - SyncJobItemId = jobItem.Id, - ServerId = _appHost.SystemId, - UserId = job.UserId, - SyncJobName = job.Name, - SyncJobDateCreated = job.DateCreated, - AdditionalFiles = jobItem.AdditionalFiles.Select(i => new ItemFileInfo - { - ImageType = i.ImageType, - Name = i.Name, - Type = i.Type, - Index = i.Index - - }).ToList() - }; - - var dtoOptions = new DtoOptions(); - - // Remove some bloat - dtoOptions.Fields.Remove(ItemFields.MediaStreams); - dtoOptions.Fields.Remove(ItemFields.IndexOptions); - dtoOptions.Fields.Remove(ItemFields.MediaSourceCount); - dtoOptions.Fields.Remove(ItemFields.Path); - dtoOptions.Fields.Remove(ItemFields.SeriesGenres); - dtoOptions.Fields.Remove(ItemFields.Settings); - dtoOptions.Fields.Remove(ItemFields.SyncInfo); - dtoOptions.Fields.Remove(ItemFields.BasicSyncInfo); - - syncedItem.Item = _dtoService().GetBaseItemDto(libraryItem, dtoOptions); - - var mediaSource = jobItem.MediaSource; - - syncedItem.Item.MediaSources = new List<MediaSourceInfo>(); - - syncedItem.OriginalFileName = Path.GetFileName(libraryItem.Path); - if (string.IsNullOrWhiteSpace(syncedItem.OriginalFileName)) - { - syncedItem.OriginalFileName = Path.GetFileName(mediaSource.Path); - } - - // This will be null for items that are not audio/video - if (mediaSource != null) - { - syncedItem.OriginalFileName = Path.ChangeExtension(syncedItem.OriginalFileName, Path.GetExtension(mediaSource.Path)); - syncedItem.Item.MediaSources.Add(mediaSource); - } - if (string.IsNullOrWhiteSpace(syncedItem.OriginalFileName)) - { - syncedItem.OriginalFileName = libraryItem.Name; - } - - return syncedItem; - } - - public Task ReportOfflineAction(UserAction action) - { - switch (action.Type) - { - case UserActionType.PlayedItem: - return ReportOfflinePlayedItem(action); - default: - throw new ArgumentException("Unexpected action type"); - } - } - - private Task ReportOfflinePlayedItem(UserAction action) - { - var item = _libraryManager.GetItemById(action.ItemId); - var userData = _userDataManager.GetUserData(action.UserId, item); - - userData.LastPlayedDate = action.Date; - _userDataManager.UpdatePlayState(item, userData, action.PositionTicks); - - return _userDataManager.SaveUserData(new Guid(action.UserId), item, userData, UserDataSaveReason.Import, CancellationToken.None); - } - - public async Task<List<SyncedItem>> GetReadySyncItems(string targetId) - { - var processor = GetSyncJobProcessor(); - - await processor.SyncJobItems(targetId, false, new Progress<double>(), CancellationToken.None).ConfigureAwait(false); - - var jobItemResult = GetJobItems(new SyncJobItemQuery - { - TargetId = targetId, - Statuses = new[] - { - SyncJobItemStatus.ReadyToTransfer, - SyncJobItemStatus.Transferring - } - }); - - var readyItems = jobItemResult.Items - .Select(GetJobItemInfo) - .Where(i => i != null) - .ToList(); - - _logger.Debug("Returning {0} ready sync items for targetId {1}", readyItems.Count, targetId); - - return readyItems; - } - - public async Task<SyncDataResponse> SyncData(SyncDataRequest request) - { - if (request.SyncJobItemIds != null) - { - return await SyncDataUsingSyncJobItemIds(request).ConfigureAwait(false); - } - - var jobItemResult = GetJobItems(new SyncJobItemQuery - { - TargetId = request.TargetId, - Statuses = new[] { SyncJobItemStatus.Synced } - }); - - var response = new SyncDataResponse(); - - foreach (var jobItem in jobItemResult.Items) - { - var requiresSaving = false; - var removeFromDevice = false; - - if (request.LocalItemIds.Contains(jobItem.ItemId, StringComparer.OrdinalIgnoreCase)) - { - var libraryItem = _libraryManager.GetItemById(jobItem.ItemId); - - var job = _repo.GetJob(jobItem.JobId); - var user = _userManager.GetUserById(job.UserId); - - if (jobItem.IsMarkedForRemoval) - { - // Tell the device to remove it since it has been marked for removal - _logger.Info("Adding ItemIdsToRemove {0} because IsMarkedForRemoval is set.", jobItem.ItemId); - removeFromDevice = true; - } - else if (user == null) - { - // Tell the device to remove it since the user is gone now - _logger.Info("Adding ItemIdsToRemove {0} because the user is no longer valid.", jobItem.ItemId); - removeFromDevice = true; - } - else if (!IsLibraryItemAvailable(libraryItem)) - { - // Tell the device to remove it since it's no longer available - _logger.Info("Adding ItemIdsToRemove {0} because it is no longer available.", jobItem.ItemId); - removeFromDevice = true; - } - else if (job.UnwatchedOnly) - { - if (libraryItem is Video && libraryItem.IsPlayed(user)) - { - // Tell the device to remove it since it has been played - _logger.Info("Adding ItemIdsToRemove {0} because it has been marked played.", jobItem.ItemId); - removeFromDevice = true; - } - } - else if (libraryItem != null && libraryItem.DateModified.Ticks != jobItem.ItemDateModifiedTicks && jobItem.ItemDateModifiedTicks > 0) - { - _logger.Info("Setting status to Queued for {0} because the media has been modified since the original sync.", jobItem.ItemId); - jobItem.Status = SyncJobItemStatus.Queued; - jobItem.Progress = 0; - requiresSaving = true; - } - } - else - { - // Content is no longer on the device - if (jobItem.IsMarkedForRemoval) - { - jobItem.Status = SyncJobItemStatus.RemovedFromDevice; - } - else - { - _logger.Info("Setting status to Queued for {0} because it is no longer on the device.", jobItem.ItemId); - jobItem.Status = SyncJobItemStatus.Queued; - jobItem.Progress = 0; - } - requiresSaving = true; - } - - if (removeFromDevice) - { - response.ItemIdsToRemove.Add(jobItem.ItemId); - jobItem.IsMarkedForRemoval = true; - requiresSaving = true; - } - - if (requiresSaving) - { - await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - } - } - - // Now check each item that's on the device - foreach (var itemId in request.LocalItemIds) - { - // See if it's already marked for removal - if (response.ItemIdsToRemove.Contains(itemId, StringComparer.OrdinalIgnoreCase)) - { - continue; - } - - // If there isn't a sync job for this item, mark it for removal - if (!jobItemResult.Items.Any(i => string.Equals(itemId, i.ItemId, StringComparison.OrdinalIgnoreCase))) - { - response.ItemIdsToRemove.Add(itemId); - } - } - - response.ItemIdsToRemove = response.ItemIdsToRemove.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); - - var itemsOnDevice = request.LocalItemIds - .Except(response.ItemIdsToRemove) - .ToList(); - - SetUserAccess(request, response, itemsOnDevice); - - return response; - } - - private async Task<SyncDataResponse> SyncDataUsingSyncJobItemIds(SyncDataRequest request) - { - var jobItemResult = GetJobItems(new SyncJobItemQuery - { - TargetId = request.TargetId, - Statuses = new[] { SyncJobItemStatus.Synced } - }); - - var response = new SyncDataResponse(); - - foreach (var jobItem in jobItemResult.Items) - { - var requiresSaving = false; - var removeFromDevice = false; - - if (request.SyncJobItemIds.Contains(jobItem.Id, StringComparer.OrdinalIgnoreCase)) - { - var libraryItem = _libraryManager.GetItemById(jobItem.ItemId); - - var job = _repo.GetJob(jobItem.JobId); - var user = _userManager.GetUserById(job.UserId); - - if (jobItem.IsMarkedForRemoval) - { - // Tell the device to remove it since it has been marked for removal - _logger.Info("Adding ItemIdsToRemove {0} because IsMarkedForRemoval is set.", jobItem.Id); - removeFromDevice = true; - } - else if (user == null) - { - // Tell the device to remove it since the user is gone now - _logger.Info("Adding ItemIdsToRemove {0} because the user is no longer valid.", jobItem.Id); - removeFromDevice = true; - } - else if (!IsLibraryItemAvailable(libraryItem)) - { - // Tell the device to remove it since it's no longer available - _logger.Info("Adding ItemIdsToRemove {0} because it is no longer available.", jobItem.Id); - removeFromDevice = true; - } - else if (job.UnwatchedOnly) - { - if (libraryItem is Video && libraryItem.IsPlayed(user)) - { - // Tell the device to remove it since it has been played - _logger.Info("Adding ItemIdsToRemove {0} because it has been marked played.", jobItem.Id); - removeFromDevice = true; - } - } - else if (libraryItem != null && libraryItem.DateModified.Ticks != jobItem.ItemDateModifiedTicks && jobItem.ItemDateModifiedTicks > 0) - { - _logger.Info("Setting status to Queued for {0} because the media has been modified since the original sync.", jobItem.ItemId); - jobItem.Status = SyncJobItemStatus.Queued; - jobItem.Progress = 0; - requiresSaving = true; - } - } - else - { - // Content is no longer on the device - if (jobItem.IsMarkedForRemoval) - { - jobItem.Status = SyncJobItemStatus.RemovedFromDevice; - } - else - { - _logger.Info("Setting status to Queued for {0} because it is no longer on the device.", jobItem.Id); - jobItem.Status = SyncJobItemStatus.Queued; - jobItem.Progress = 0; - } - requiresSaving = true; - } - - if (removeFromDevice) - { - response.ItemIdsToRemove.Add(jobItem.Id); - jobItem.IsMarkedForRemoval = true; - requiresSaving = true; - } - - if (requiresSaving) - { - await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - } - } - - // Now check each item that's on the device - foreach (var syncJobItemId in request.SyncJobItemIds) - { - // See if it's already marked for removal - if (response.ItemIdsToRemove.Contains(syncJobItemId, StringComparer.OrdinalIgnoreCase)) - { - continue; - } - - // If there isn't a sync job for this item, mark it for removal - if (!jobItemResult.Items.Any(i => string.Equals(syncJobItemId, i.Id, StringComparison.OrdinalIgnoreCase))) - { - response.ItemIdsToRemove.Add(syncJobItemId); - } - } - - response.ItemIdsToRemove = response.ItemIdsToRemove.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); - - return response; - } - - private void SetUserAccess(SyncDataRequest request, SyncDataResponse response, List<string> itemIds) - { - var users = request.OfflineUserIds - .Select(_userManager.GetUserById) - .Where(i => i != null) - .ToList(); - - foreach (var itemId in itemIds) - { - var item = _libraryManager.GetItemById(itemId); - - if (item != null) - { - response.ItemUserAccess[itemId] = users - .Where(i => IsUserVisible(item, i)) - .Select(i => i.Id.ToString("N")) - .OrderBy(i => i) - .ToList(); - } - } - } - - private bool IsUserVisible(BaseItem item, User user) - { - return item.IsVisibleStandalone(user); - } - - private bool IsLibraryItemAvailable(BaseItem item) - { - if (item == null) - { - return false; - } - - return true; - } - - public async Task ReEnableJobItem(string id) - { - var jobItem = _repo.GetJobItem(id); - - if (jobItem.Status != SyncJobItemStatus.Failed && jobItem.Status != SyncJobItemStatus.Cancelled) - { - throw new ArgumentException("Operation is not valid for this job item"); - } - - jobItem.Status = SyncJobItemStatus.Queued; - jobItem.Progress = 0; - jobItem.IsMarkedForRemoval = false; - - await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - - var processor = GetSyncJobProcessor(); - - await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); - } - - public async Task CancelItems(string targetId, IEnumerable<string> itemIds) - { - foreach (var item in itemIds) - { - var syncJobItemResult = GetJobItems(new SyncJobItemQuery - { - AddMetadata = false, - ItemId = item, - TargetId = targetId, - Statuses = new[] { SyncJobItemStatus.Queued, SyncJobItemStatus.ReadyToTransfer, SyncJobItemStatus.Converting, SyncJobItemStatus.Synced, SyncJobItemStatus.Failed } - }); - - foreach (var jobItem in syncJobItemResult.Items) - { - await CancelJobItem(jobItem.Id).ConfigureAwait(false); - } - } - } - - public async Task CancelJobItem(string id) - { - var jobItem = _repo.GetJobItem(id); - - if (jobItem.Status != SyncJobItemStatus.Queued && jobItem.Status != SyncJobItemStatus.ReadyToTransfer && jobItem.Status != SyncJobItemStatus.Converting && jobItem.Status != SyncJobItemStatus.Failed && jobItem.Status != SyncJobItemStatus.Synced && jobItem.Status != SyncJobItemStatus.Transferring) - { - throw new ArgumentException("Operation is not valid for this job item"); - } - - if (jobItem.Status != SyncJobItemStatus.Synced) - { - jobItem.Status = SyncJobItemStatus.Cancelled; - } - - jobItem.Progress = 0; - jobItem.IsMarkedForRemoval = true; - - await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - - var processor = GetSyncJobProcessor(); - - await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); - - var path = processor.GetTemporaryPath(jobItem); - - try - { - _fileSystem.DeleteDirectory(path, true); - } - catch (DirectoryNotFoundException) - { - - } - catch (Exception ex) - { - _logger.ErrorException("Error deleting directory {0}", ex, path); - } - - //var jobItemsResult = GetJobItems(new SyncJobItemQuery - //{ - // AddMetadata = false, - // JobId = jobItem.JobId, - // Limit = 0, - // Statuses = new[] { SyncJobItemStatus.Converting, SyncJobItemStatus.Failed, SyncJobItemStatus.Queued, SyncJobItemStatus.ReadyToTransfer, SyncJobItemStatus.Synced, SyncJobItemStatus.Transferring } - //}); - - //if (jobItemsResult.TotalRecordCount == 0) - //{ - // await CancelJob(jobItem.JobId).ConfigureAwait(false); - //} - } - - public Task MarkJobItemForRemoval(string id) - { - return CancelJobItem(id); - } - - public async Task UnmarkJobItemForRemoval(string id) - { - var jobItem = _repo.GetJobItem(id); - - if (jobItem.Status != SyncJobItemStatus.Synced) - { - throw new ArgumentException("Operation is not valid for this job item"); - } - - jobItem.IsMarkedForRemoval = false; - - await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - - var processor = GetSyncJobProcessor(); - - await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); - } - - public async Task ReportSyncJobItemTransferBeginning(string id) - { - var jobItem = _repo.GetJobItem(id); - - jobItem.Status = SyncJobItemStatus.Transferring; - - await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - - var processor = GetSyncJobProcessor(); - - await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); - } - - public async Task ReportSyncJobItemTransferFailed(string id) - { - var jobItem = _repo.GetJobItem(id); - - jobItem.Status = SyncJobItemStatus.ReadyToTransfer; - - await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - - var processor = GetSyncJobProcessor(); - - await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); - } - - public Dictionary<string, SyncedItemProgress> GetSyncedItemProgresses(SyncJobItemQuery query) - { - return _repo.GetSyncedItemProgresses(query); - } - - public SyncJobOptions GetAudioOptions(SyncJobItem jobItem, SyncJob job) - { - var options = GetSyncJobOptions(jobItem.TargetId, null, null); - - if (job.Bitrate.HasValue) - { - options.DeviceProfile.MaxStaticBitrate = job.Bitrate.Value; - } - - return options; - } - - public ISyncProvider GetSyncProvider(SyncJobItem jobItem) - { - foreach (var provider in _providers) - { - foreach (var target in GetSyncTargets(provider)) - { - if (string.Equals(target.Id, jobItem.TargetId, StringComparison.OrdinalIgnoreCase)) - { - return provider; - } - } - } - return null; - } - - public SyncJobOptions GetVideoOptions(SyncJobItem jobItem, SyncJob job) - { - var options = GetSyncJobOptions(jobItem.TargetId, job.Profile, job.Quality); - - if (job.Bitrate.HasValue) - { - options.DeviceProfile.MaxStaticBitrate = job.Bitrate.Value; - } - - return options; - } - - private SyncJobOptions GetSyncJobOptions(string targetId, string profile, string quality) - { - foreach (var provider in _providers) - { - foreach (var target in GetSyncTargets(provider)) - { - if (string.Equals(target.Id, targetId, StringComparison.OrdinalIgnoreCase)) - { - return GetSyncJobOptions(provider, target, profile, quality); - } - } - } - - return GetDefaultSyncJobOptions(profile, quality); - } - - private SyncJobOptions GetSyncJobOptions(ISyncProvider provider, SyncTarget target, string profile, string quality) - { - var hasProfile = provider as IHasSyncQuality; - - if (hasProfile != null) - { - return hasProfile.GetSyncJobOptions(target, profile, quality); - } - - return GetDefaultSyncJobOptions(profile, quality); - } - - private SyncJobOptions GetDefaultSyncJobOptions(string profile, string quality) - { - var supportsAc3 = string.Equals(profile, "general", StringComparison.OrdinalIgnoreCase); - - var deviceProfile = new CloudSyncProfile(supportsAc3, false); - deviceProfile.MaxStaticBitrate = SyncHelper.AdjustBitrate(deviceProfile.MaxStaticBitrate, quality); - - return new SyncJobOptions - { - DeviceProfile = deviceProfile, - IsConverting = IsConverting(profile, quality) - }; - } - - private bool IsConverting(string profile, string quality) - { - return !string.Equals(profile, "original", StringComparison.OrdinalIgnoreCase); - } - - public IEnumerable<SyncQualityOption> GetQualityOptions(string targetId) - { - return GetQualityOptions(targetId, null); - } - - public IEnumerable<SyncQualityOption> GetQualityOptions(string targetId, User user) - { - foreach (var provider in _providers) - { - foreach (var target in GetSyncTargets(provider)) - { - if (string.Equals(target.Id, targetId, StringComparison.OrdinalIgnoreCase)) - { - return GetQualityOptions(provider, target, user); - } - } - } - - return new List<SyncQualityOption>(); - } - - private IEnumerable<SyncQualityOption> GetQualityOptions(ISyncProvider provider, SyncTarget target, User user) - { - var hasQuality = provider as IHasSyncQuality; - if (hasQuality != null) - { - var options = hasQuality.GetQualityOptions(target); - - if (user != null && !user.Policy.EnableSyncTranscoding) - { - options = options.Where(i => i.IsOriginalQuality); - } - - return options; - } - - // Default options for providers that don't override - return new List<SyncQualityOption> - { - new SyncQualityOption - { - Name = "High", - Id = "high", - IsDefault = true - }, - new SyncQualityOption - { - Name = "Medium", - Id = "medium" - }, - new SyncQualityOption - { - Name = "Low", - Id = "low" - }, - new SyncQualityOption - { - Name = "Custom", - Id = "custom" - } - }; - } - - public IEnumerable<SyncProfileOption> GetProfileOptions(string targetId, User user) - { - foreach (var provider in _providers) - { - foreach (var target in GetSyncTargets(provider)) - { - if (string.Equals(target.Id, targetId, StringComparison.OrdinalIgnoreCase)) - { - return GetProfileOptions(provider, target, user); - } - } - } - - return new List<SyncProfileOption>(); - } - - public IEnumerable<SyncProfileOption> GetProfileOptions(string targetId) - { - return GetProfileOptions(targetId, null); - } - - private IEnumerable<SyncProfileOption> GetProfileOptions(ISyncProvider provider, SyncTarget target, User user) - { - var hasQuality = provider as IHasSyncQuality; - if (hasQuality != null) - { - return hasQuality.GetProfileOptions(target); - } - - var list = new List<SyncProfileOption>(); - - list.Add(new SyncProfileOption - { - Name = "Original", - Id = "Original", - Description = "Syncs original files as-is.", - EnableQualityOptions = false - }); - - if (user == null || user.Policy.EnableSyncTranscoding) - { - list.Add(new SyncProfileOption - { - Name = "Baseline", - Id = "baseline", - Description = "Designed for compatibility with all devices, including web browsers. Targets H264/AAC video and MP3 audio." - }); - - list.Add(new SyncProfileOption - { - Name = "General", - Id = "general", - Description = "Designed for compatibility with Chromecast, Roku, Smart TV's, and other similar devices. Targets H264/AAC/AC3 video and MP3 audio.", - IsDefault = true - }); - } - - return list; - } - - protected internal void OnConversionComplete(SyncJobItem item) - { - var syncProvider = GetSyncProvider(item); - if (syncProvider is AppSyncProvider) - { - return; - } - - _taskManager.QueueIfNotRunning<ServerSyncScheduledTask>(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncNotificationEntryPoint.cs b/MediaBrowser.Server.Implementations/Sync/SyncNotificationEntryPoint.cs deleted file mode 100644 index 7017b422ee..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/SyncNotificationEntryPoint.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Threading; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.Sync; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class SyncNotificationEntryPoint : IServerEntryPoint - { - private readonly ISessionManager _sessionManager; - private readonly ISyncManager _syncManager; - - public SyncNotificationEntryPoint(ISyncManager syncManager, ISessionManager sessionManager) - { - _syncManager = syncManager; - _sessionManager = sessionManager; - } - - public void Run() - { - _syncManager.SyncJobItemUpdated += _syncManager_SyncJobItemUpdated; - } - - private async void _syncManager_SyncJobItemUpdated(object sender, GenericEventArgs<SyncJobItem> e) - { - var item = e.Argument; - - if (item.Status == SyncJobItemStatus.ReadyToTransfer) - { - try - { - await _sessionManager.SendMessageToUserDeviceSessions(item.TargetId, "SyncJobItemReady", item, CancellationToken.None).ConfigureAwait(false); - } - catch - { - - } - } - } - - public void Dispose() - { - _syncManager.SyncJobItemUpdated -= _syncManager_SyncJobItemUpdated; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRegistrationInfo.cs b/MediaBrowser.Server.Implementations/Sync/SyncRegistrationInfo.cs deleted file mode 100644 index 40b84b1c21..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/SyncRegistrationInfo.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MediaBrowser.Common.Security; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class SyncRegistrationInfo : IRequiresRegistration - { - private readonly ISecurityManager _securityManager; - - public static SyncRegistrationInfo Instance; - - public SyncRegistrationInfo(ISecurityManager securityManager) - { - _securityManager = securityManager; - Instance = this; - } - - private bool _registered; - public bool IsRegistered - { - get { return _registered; } - } - - public async Task LoadRegistrationInfoAsync() - { - var info = await _securityManager.GetRegistrationStatus("sync").ConfigureAwait(false); - - _registered = info.IsValid; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs deleted file mode 100644 index 64ed00ded1..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ /dev/null @@ -1,976 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Sync; -using MediaBrowser.Server.Implementations.Persistence; -using System; -using System.Collections.Generic; -using System.Data; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class SyncRepository : BaseSqliteRepository, ISyncRepository - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - private readonly IJsonSerializer _json; - - public SyncRepository(ILogManager logManager, IJsonSerializer json, IServerApplicationPaths appPaths, IDbConnector connector) - : base(logManager, connector) - { - _json = json; - DbFilePath = Path.Combine(appPaths.DataPath, "sync14.db"); - } - - private class SyncSummary - { - public Dictionary<string, int> Items { get; set; } - - public SyncSummary() - { - Items = new Dictionary<string, int>(); - } - } - - - public async Task Initialize() - { - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - string[] queries = { - - "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Profile TEXT, Quality TEXT, Bitrate INT, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)", - - "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, TemporaryPath TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT, AdditionalFiles TEXT, MediaSource TEXT, IsMarkedForRemoval BIT, JobItemIndex INT, ItemDateModifiedTicks BIGINT)", - - "drop index if exists idx_SyncJobItems2", - "drop index if exists idx_SyncJobItems3", - "drop index if exists idx_SyncJobs1", - "drop index if exists idx_SyncJobs", - "drop index if exists idx_SyncJobItems1", - "create index if not exists idx_SyncJobItems4 on SyncJobItems(TargetId,ItemId,Status,Progress,DateCreated)", - "create index if not exists idx_SyncJobItems5 on SyncJobItems(TargetId,Status,ItemId,Progress)", - - "create index if not exists idx_SyncJobs2 on SyncJobs(TargetId,Status,ItemIds,Progress)", - - "pragma shrink_memory" - }; - - connection.RunQueries(queries, Logger); - - connection.AddColumn(Logger, "SyncJobs", "Profile", "TEXT"); - connection.AddColumn(Logger, "SyncJobs", "Bitrate", "INT"); - connection.AddColumn(Logger, "SyncJobItems", "ItemDateModifiedTicks", "BIGINT"); - } - } - - private const string BaseJobSelectText = "select Id, TargetId, Name, Profile, Quality, Bitrate, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs"; - private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex, ItemDateModifiedTicks from SyncJobItems"; - - public SyncJob GetJob(string id) - { - if (string.IsNullOrEmpty(id)) - { - throw new ArgumentNullException("id"); - } - - CheckDisposed(); - - var guid = new Guid(id); - - if (guid == Guid.Empty) - { - throw new ArgumentNullException("id"); - } - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = BaseJobSelectText + " where Id=@Id"; - - cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) - { - return GetJob(reader); - } - } - } - - return null; - } - } - - private SyncJob GetJob(IDataReader reader) - { - var info = new SyncJob - { - Id = reader.GetGuid(0).ToString("N"), - TargetId = reader.GetString(1), - Name = reader.GetString(2) - }; - - if (!reader.IsDBNull(3)) - { - info.Profile = reader.GetString(3); - } - - if (!reader.IsDBNull(4)) - { - info.Quality = reader.GetString(4); - } - - if (!reader.IsDBNull(5)) - { - info.Bitrate = reader.GetInt32(5); - } - - if (!reader.IsDBNull(6)) - { - info.Status = (SyncJobStatus)Enum.Parse(typeof(SyncJobStatus), reader.GetString(6), true); - } - - if (!reader.IsDBNull(7)) - { - info.Progress = reader.GetDouble(7); - } - - if (!reader.IsDBNull(8)) - { - info.UserId = reader.GetString(8); - } - - if (!reader.IsDBNull(9)) - { - info.RequestedItemIds = reader.GetString(9).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); - } - - if (!reader.IsDBNull(10)) - { - info.Category = (SyncCategory)Enum.Parse(typeof(SyncCategory), reader.GetString(10), true); - } - - if (!reader.IsDBNull(11)) - { - info.ParentId = reader.GetString(11); - } - - if (!reader.IsDBNull(12)) - { - info.UnwatchedOnly = reader.GetBoolean(12); - } - - if (!reader.IsDBNull(13)) - { - info.ItemLimit = reader.GetInt32(13); - } - - info.SyncNewContent = reader.GetBoolean(14); - - info.DateCreated = reader.GetDateTime(15).ToUniversalTime(); - info.DateLastModified = reader.GetDateTime(16).ToUniversalTime(); - info.ItemCount = reader.GetInt32(17); - - return info; - } - - public Task Create(SyncJob job) - { - return InsertOrUpdate(job, true); - } - - public Task Update(SyncJob job) - { - return InsertOrUpdate(job, false); - } - - private async Task InsertOrUpdate(SyncJob job, bool insert) - { - if (job == null) - { - throw new ArgumentNullException("job"); - } - - CheckDisposed(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var cmd = connection.CreateCommand()) - { - if (insert) - { - cmd.CommandText = "insert into SyncJobs (Id, TargetId, Name, Profile, Quality, Bitrate, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount) values (@Id, @TargetId, @Name, @Profile, @Quality, @Bitrate, @Status, @Progress, @UserId, @ItemIds, @Category, @ParentId, @UnwatchedOnly, @ItemLimit, @SyncNewContent, @DateCreated, @DateLastModified, @ItemCount)"; - - cmd.Parameters.Add(cmd, "@Id"); - cmd.Parameters.Add(cmd, "@TargetId"); - cmd.Parameters.Add(cmd, "@Name"); - cmd.Parameters.Add(cmd, "@Profile"); - cmd.Parameters.Add(cmd, "@Quality"); - cmd.Parameters.Add(cmd, "@Bitrate"); - cmd.Parameters.Add(cmd, "@Status"); - cmd.Parameters.Add(cmd, "@Progress"); - cmd.Parameters.Add(cmd, "@UserId"); - cmd.Parameters.Add(cmd, "@ItemIds"); - cmd.Parameters.Add(cmd, "@Category"); - cmd.Parameters.Add(cmd, "@ParentId"); - cmd.Parameters.Add(cmd, "@UnwatchedOnly"); - cmd.Parameters.Add(cmd, "@ItemLimit"); - cmd.Parameters.Add(cmd, "@SyncNewContent"); - cmd.Parameters.Add(cmd, "@DateCreated"); - cmd.Parameters.Add(cmd, "@DateLastModified"); - cmd.Parameters.Add(cmd, "@ItemCount"); - } - else - { - cmd.CommandText = "update SyncJobs set TargetId=@TargetId,Name=@Name,Profile=@Profile,Quality=@Quality,Bitrate=@Bitrate,Status=@Status,Progress=@Progress,UserId=@UserId,ItemIds=@ItemIds,Category=@Category,ParentId=@ParentId,UnwatchedOnly=@UnwatchedOnly,ItemLimit=@ItemLimit,SyncNewContent=@SyncNewContent,DateCreated=@DateCreated,DateLastModified=@DateLastModified,ItemCount=@ItemCount where Id=@Id"; - - cmd.Parameters.Add(cmd, "@Id"); - cmd.Parameters.Add(cmd, "@TargetId"); - cmd.Parameters.Add(cmd, "@Name"); - cmd.Parameters.Add(cmd, "@Profile"); - cmd.Parameters.Add(cmd, "@Quality"); - cmd.Parameters.Add(cmd, "@Bitrate"); - cmd.Parameters.Add(cmd, "@Status"); - cmd.Parameters.Add(cmd, "@Progress"); - cmd.Parameters.Add(cmd, "@UserId"); - cmd.Parameters.Add(cmd, "@ItemIds"); - cmd.Parameters.Add(cmd, "@Category"); - cmd.Parameters.Add(cmd, "@ParentId"); - cmd.Parameters.Add(cmd, "@UnwatchedOnly"); - cmd.Parameters.Add(cmd, "@ItemLimit"); - cmd.Parameters.Add(cmd, "@SyncNewContent"); - cmd.Parameters.Add(cmd, "@DateCreated"); - cmd.Parameters.Add(cmd, "@DateLastModified"); - cmd.Parameters.Add(cmd, "@ItemCount"); - } - - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - var index = 0; - - cmd.GetParameter(index++).Value = new Guid(job.Id); - cmd.GetParameter(index++).Value = job.TargetId; - cmd.GetParameter(index++).Value = job.Name; - cmd.GetParameter(index++).Value = job.Profile; - cmd.GetParameter(index++).Value = job.Quality; - cmd.GetParameter(index++).Value = job.Bitrate; - cmd.GetParameter(index++).Value = job.Status.ToString(); - cmd.GetParameter(index++).Value = job.Progress; - cmd.GetParameter(index++).Value = job.UserId; - cmd.GetParameter(index++).Value = string.Join(",", job.RequestedItemIds.ToArray()); - cmd.GetParameter(index++).Value = job.Category; - cmd.GetParameter(index++).Value = job.ParentId; - cmd.GetParameter(index++).Value = job.UnwatchedOnly; - cmd.GetParameter(index++).Value = job.ItemLimit; - cmd.GetParameter(index++).Value = job.SyncNewContent; - cmd.GetParameter(index++).Value = job.DateCreated; - cmd.GetParameter(index++).Value = job.DateLastModified; - cmd.GetParameter(index++).Value = job.ItemCount; - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save record:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - - public async Task DeleteJob(string id) - { - if (string.IsNullOrWhiteSpace(id)) - { - throw new ArgumentNullException("id"); - } - - CheckDisposed(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var deleteJobCommand = connection.CreateCommand()) - { - using (var deleteJobItemsCommand = connection.CreateCommand()) - { - IDbTransaction transaction = null; - - try - { - // _deleteJobCommand - deleteJobCommand.CommandText = "delete from SyncJobs where Id=@Id"; - deleteJobCommand.Parameters.Add(deleteJobCommand, "@Id"); - - transaction = connection.BeginTransaction(); - - deleteJobCommand.GetParameter(0).Value = new Guid(id); - deleteJobCommand.Transaction = transaction; - deleteJobCommand.ExecuteNonQuery(); - - // _deleteJobItemsCommand - deleteJobItemsCommand.CommandText = "delete from SyncJobItems where JobId=@JobId"; - deleteJobItemsCommand.Parameters.Add(deleteJobItemsCommand, "@JobId"); - - deleteJobItemsCommand.GetParameter(0).Value = id; - deleteJobItemsCommand.Transaction = transaction; - deleteJobItemsCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save record:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - } - - public QueryResult<SyncJob> GetJobs(SyncJobQuery query) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - CheckDisposed(); - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = BaseJobSelectText; - - var whereClauses = new List<string>(); - - if (query.Statuses.Length > 0) - { - var statuses = string.Join(",", query.Statuses.Select(i => "'" + i.ToString() + "'").ToArray()); - - whereClauses.Add(string.Format("Status in ({0})", statuses)); - } - if (!string.IsNullOrWhiteSpace(query.TargetId)) - { - whereClauses.Add("TargetId=@TargetId"); - cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId; - } - if (!string.IsNullOrWhiteSpace(query.ExcludeTargetIds)) - { - var excludeIds = (query.ExcludeTargetIds ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - if (excludeIds.Length == 1) - { - whereClauses.Add("TargetId<>@ExcludeTargetId"); - cmd.Parameters.Add(cmd, "@ExcludeTargetId", DbType.String).Value = excludeIds[0]; - } - else if (excludeIds.Length > 1) - { - whereClauses.Add("TargetId<>@ExcludeTargetId"); - cmd.Parameters.Add(cmd, "@ExcludeTargetId", DbType.String).Value = excludeIds[0]; - } - } - if (!string.IsNullOrWhiteSpace(query.UserId)) - { - whereClauses.Add("UserId=@UserId"); - cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId; - } - if (query.SyncNewContent.HasValue) - { - whereClauses.Add("SyncNewContent=@SyncNewContent"); - cmd.Parameters.Add(cmd, "@SyncNewContent", DbType.Boolean).Value = query.SyncNewContent.Value; - } - - cmd.CommandText += " mainTable"; - - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - var startIndex = query.StartIndex ?? 0; - if (startIndex > 0) - { - whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM SyncJobs ORDER BY (Select Max(DateLastModified) from SyncJobs where TargetId=mainTable.TargetId) DESC, DateLastModified DESC LIMIT {0})", - startIndex.ToString(_usCulture))); - } - - if (whereClauses.Count > 0) - { - cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); - } - - cmd.CommandText += " ORDER BY (Select Max(DateLastModified) from SyncJobs where TargetId=mainTable.TargetId) DESC, DateLastModified DESC"; - - if (query.Limit.HasValue) - { - cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); - } - - cmd.CommandText += "; select count (Id) from SyncJobs" + whereTextWithoutPaging; - - var list = new List<SyncJob>(); - var count = 0; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (reader.Read()) - { - list.Add(GetJob(reader)); - } - - if (reader.NextResult() && reader.Read()) - { - count = reader.GetInt32(0); - } - } - - return new QueryResult<SyncJob>() - { - Items = list.ToArray(), - TotalRecordCount = count - }; - } - } - } - - public SyncJobItem GetJobItem(string id) - { - if (string.IsNullOrEmpty(id)) - { - throw new ArgumentNullException("id"); - } - - CheckDisposed(); - - var guid = new Guid(id); - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = BaseJobItemSelectText + " where Id=@Id"; - - cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) - { - return GetJobItem(reader); - } - } - } - - return null; - } - } - - private QueryResult<T> GetJobItemReader<T>(SyncJobItemQuery query, string baseSelectText, Func<IDataReader, T> itemFactory) - { - if (query == null) - { - throw new ArgumentNullException("query"); - } - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = baseSelectText; - - var whereClauses = new List<string>(); - - if (!string.IsNullOrWhiteSpace(query.JobId)) - { - whereClauses.Add("JobId=@JobId"); - cmd.Parameters.Add(cmd, "@JobId", DbType.String).Value = query.JobId; - } - if (!string.IsNullOrWhiteSpace(query.ItemId)) - { - whereClauses.Add("ItemId=@ItemId"); - cmd.Parameters.Add(cmd, "@ItemId", DbType.String).Value = query.ItemId; - } - if (!string.IsNullOrWhiteSpace(query.TargetId)) - { - whereClauses.Add("TargetId=@TargetId"); - cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId; - } - - if (query.Statuses.Length > 0) - { - var statuses = string.Join(",", query.Statuses.Select(i => "'" + i.ToString() + "'").ToArray()); - - whereClauses.Add(string.Format("Status in ({0})", statuses)); - } - - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - var startIndex = query.StartIndex ?? 0; - if (startIndex > 0) - { - whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM SyncJobItems ORDER BY JobItemIndex, DateCreated LIMIT {0})", - startIndex.ToString(_usCulture))); - } - - if (whereClauses.Count > 0) - { - cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); - } - - cmd.CommandText += " ORDER BY JobItemIndex, DateCreated"; - - if (query.Limit.HasValue) - { - cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); - } - - cmd.CommandText += "; select count (Id) from SyncJobItems" + whereTextWithoutPaging; - - var list = new List<T>(); - var count = 0; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (reader.Read()) - { - list.Add(itemFactory(reader)); - } - - if (reader.NextResult() && reader.Read()) - { - count = reader.GetInt32(0); - } - } - - return new QueryResult<T>() - { - Items = list.ToArray(), - TotalRecordCount = count - }; - } - } - } - - public Dictionary<string, SyncedItemProgress> GetSyncedItemProgresses(SyncJobItemQuery query) - { - var result = new Dictionary<string, SyncedItemProgress>(); - - var now = DateTime.UtcNow; - - using (var connection = CreateConnection(true).Result) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select ItemId,Status,Progress from SyncJobItems"; - - var whereClauses = new List<string>(); - - if (!string.IsNullOrWhiteSpace(query.TargetId)) - { - whereClauses.Add("TargetId=@TargetId"); - cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId; - } - - if (query.Statuses.Length > 0) - { - var statuses = string.Join(",", query.Statuses.Select(i => "'" + i.ToString() + "'").ToArray()); - - whereClauses.Add(string.Format("Status in ({0})", statuses)); - } - - if (whereClauses.Count > 0) - { - cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); - } - - cmd.CommandText += ";" + cmd.CommandText - .Replace("select ItemId,Status,Progress from SyncJobItems", "select ItemIds,Status,Progress from SyncJobs") - .Replace("'Synced'", "'Completed','CompletedWithError'"); - - //Logger.Debug(cmd.CommandText); - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - LogQueryTime("GetSyncedItemProgresses", cmd, now); - - while (reader.Read()) - { - AddStatusResult(reader, result, false); - } - - if (reader.NextResult()) - { - while (reader.Read()) - { - AddStatusResult(reader, result, true); - } - } - } - } - } - - return result; - } - - private void LogQueryTime(string methodName, IDbCommand cmd, DateTime startDate) - { - var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds; - - var slowThreshold = 1000; - -#if DEBUG - slowThreshold = 50; -#endif - - if (elapsed >= slowThreshold) - { - Logger.Debug("{2} query time (slow): {0}ms. Query: {1}", - Convert.ToInt32(elapsed), - cmd.CommandText, - methodName); - } - else - { - //Logger.Debug("{2} query time: {0}ms. Query: {1}", - // Convert.ToInt32(elapsed), - // cmd.CommandText, - // methodName); - } - } - - private void AddStatusResult(IDataReader reader, Dictionary<string, SyncedItemProgress> result, bool multipleIds) - { - if (reader.IsDBNull(0)) - { - return; - } - - var itemIds = new List<string>(); - - var ids = reader.GetString(0); - - if (multipleIds) - { - itemIds = ids.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); - } - else - { - itemIds.Add(ids); - } - - if (!reader.IsDBNull(1)) - { - SyncJobItemStatus status; - var statusString = reader.GetString(1); - if (string.Equals(statusString, "Completed", StringComparison.OrdinalIgnoreCase) || - string.Equals(statusString, "CompletedWithError", StringComparison.OrdinalIgnoreCase)) - { - status = SyncJobItemStatus.Synced; - } - else - { - status = (SyncJobItemStatus)Enum.Parse(typeof(SyncJobItemStatus), statusString, true); - } - - if (status == SyncJobItemStatus.Synced) - { - foreach (var itemId in itemIds) - { - result[itemId] = new SyncedItemProgress - { - Status = SyncJobItemStatus.Synced - }; - } - } - else - { - double progress = reader.IsDBNull(2) ? 0.0 : reader.GetDouble(2); - - foreach (var itemId in itemIds) - { - SyncedItemProgress currentStatus; - if (!result.TryGetValue(itemId, out currentStatus) || (currentStatus.Status != SyncJobItemStatus.Synced && progress >= currentStatus.Progress)) - { - result[itemId] = new SyncedItemProgress - { - Status = status, - Progress = progress - }; - } - } - } - } - } - - public QueryResult<SyncJobItem> GetJobItems(SyncJobItemQuery query) - { - return GetJobItemReader(query, BaseJobItemSelectText, GetJobItem); - } - - public Task Create(SyncJobItem jobItem) - { - return InsertOrUpdate(jobItem, true); - } - - public Task Update(SyncJobItem jobItem) - { - return InsertOrUpdate(jobItem, false); - } - - private async Task InsertOrUpdate(SyncJobItem jobItem, bool insert) - { - if (jobItem == null) - { - throw new ArgumentNullException("jobItem"); - } - - CheckDisposed(); - - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - using (var cmd = connection.CreateCommand()) - { - if (insert) - { - cmd.CommandText = "insert into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex, ItemDateModifiedTicks) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @TemporaryPath, @OutputPath, @Status, @TargetId, @DateCreated, @Progress, @AdditionalFiles, @MediaSource, @IsMarkedForRemoval, @JobItemIndex, @ItemDateModifiedTicks)"; - - cmd.Parameters.Add(cmd, "@Id"); - cmd.Parameters.Add(cmd, "@ItemId"); - cmd.Parameters.Add(cmd, "@ItemName"); - cmd.Parameters.Add(cmd, "@MediaSourceId"); - cmd.Parameters.Add(cmd, "@JobId"); - cmd.Parameters.Add(cmd, "@TemporaryPath"); - cmd.Parameters.Add(cmd, "@OutputPath"); - cmd.Parameters.Add(cmd, "@Status"); - cmd.Parameters.Add(cmd, "@TargetId"); - cmd.Parameters.Add(cmd, "@DateCreated"); - cmd.Parameters.Add(cmd, "@Progress"); - cmd.Parameters.Add(cmd, "@AdditionalFiles"); - cmd.Parameters.Add(cmd, "@MediaSource"); - cmd.Parameters.Add(cmd, "@IsMarkedForRemoval"); - cmd.Parameters.Add(cmd, "@JobItemIndex"); - cmd.Parameters.Add(cmd, "@ItemDateModifiedTicks"); - } - else - { - // cmd - cmd.CommandText = "update SyncJobItems set ItemId=@ItemId,ItemName=@ItemName,MediaSourceId=@MediaSourceId,JobId=@JobId,TemporaryPath=@TemporaryPath,OutputPath=@OutputPath,Status=@Status,TargetId=@TargetId,DateCreated=@DateCreated,Progress=@Progress,AdditionalFiles=@AdditionalFiles,MediaSource=@MediaSource,IsMarkedForRemoval=@IsMarkedForRemoval,JobItemIndex=@JobItemIndex,ItemDateModifiedTicks=@ItemDateModifiedTicks where Id=@Id"; - - cmd.Parameters.Add(cmd, "@Id"); - cmd.Parameters.Add(cmd, "@ItemId"); - cmd.Parameters.Add(cmd, "@ItemName"); - cmd.Parameters.Add(cmd, "@MediaSourceId"); - cmd.Parameters.Add(cmd, "@JobId"); - cmd.Parameters.Add(cmd, "@TemporaryPath"); - cmd.Parameters.Add(cmd, "@OutputPath"); - cmd.Parameters.Add(cmd, "@Status"); - cmd.Parameters.Add(cmd, "@TargetId"); - cmd.Parameters.Add(cmd, "@DateCreated"); - cmd.Parameters.Add(cmd, "@Progress"); - cmd.Parameters.Add(cmd, "@AdditionalFiles"); - cmd.Parameters.Add(cmd, "@MediaSource"); - cmd.Parameters.Add(cmd, "@IsMarkedForRemoval"); - cmd.Parameters.Add(cmd, "@JobItemIndex"); - cmd.Parameters.Add(cmd, "@ItemDateModifiedTicks"); - } - - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - var index = 0; - - cmd.GetParameter(index++).Value = new Guid(jobItem.Id); - cmd.GetParameter(index++).Value = jobItem.ItemId; - cmd.GetParameter(index++).Value = jobItem.ItemName; - cmd.GetParameter(index++).Value = jobItem.MediaSourceId; - cmd.GetParameter(index++).Value = jobItem.JobId; - cmd.GetParameter(index++).Value = jobItem.TemporaryPath; - cmd.GetParameter(index++).Value = jobItem.OutputPath; - cmd.GetParameter(index++).Value = jobItem.Status.ToString(); - cmd.GetParameter(index++).Value = jobItem.TargetId; - cmd.GetParameter(index++).Value = jobItem.DateCreated; - cmd.GetParameter(index++).Value = jobItem.Progress; - cmd.GetParameter(index++).Value = _json.SerializeToString(jobItem.AdditionalFiles); - cmd.GetParameter(index++).Value = jobItem.MediaSource == null ? null : _json.SerializeToString(jobItem.MediaSource); - cmd.GetParameter(index++).Value = jobItem.IsMarkedForRemoval; - cmd.GetParameter(index++).Value = jobItem.JobItemIndex; - cmd.GetParameter(index++).Value = jobItem.ItemDateModifiedTicks; - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save record:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } - } - } - } - - private SyncJobItem GetJobItem(IDataReader reader) - { - var info = new SyncJobItem - { - Id = reader.GetGuid(0).ToString("N"), - ItemId = reader.GetString(1) - }; - - if (!reader.IsDBNull(2)) - { - info.ItemName = reader.GetString(2); - } - - if (!reader.IsDBNull(3)) - { - info.MediaSourceId = reader.GetString(3); - } - - info.JobId = reader.GetString(4); - - if (!reader.IsDBNull(5)) - { - info.TemporaryPath = reader.GetString(5); - } - if (!reader.IsDBNull(6)) - { - info.OutputPath = reader.GetString(6); - } - - if (!reader.IsDBNull(7)) - { - info.Status = (SyncJobItemStatus)Enum.Parse(typeof(SyncJobItemStatus), reader.GetString(7), true); - } - - info.TargetId = reader.GetString(8); - - info.DateCreated = reader.GetDateTime(9).ToUniversalTime(); - - if (!reader.IsDBNull(10)) - { - info.Progress = reader.GetDouble(10); - } - - if (!reader.IsDBNull(11)) - { - var json = reader.GetString(11); - - if (!string.IsNullOrWhiteSpace(json)) - { - info.AdditionalFiles = _json.DeserializeFromString<List<ItemFileInfo>>(json); - } - } - - if (!reader.IsDBNull(12)) - { - var json = reader.GetString(12); - - if (!string.IsNullOrWhiteSpace(json)) - { - info.MediaSource = _json.DeserializeFromString<MediaSourceInfo>(json); - } - } - - info.IsMarkedForRemoval = reader.GetBoolean(13); - info.JobItemIndex = reader.GetInt32(14); - - if (!reader.IsDBNull(15)) - { - info.ItemDateModifiedTicks = reader.GetInt64(15); - } - - return info; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs deleted file mode 100644 index e0553b1b16..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs +++ /dev/null @@ -1,158 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Sync; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class SyncedMediaSourceProvider : IMediaSourceProvider - { - private readonly SyncManager _syncManager; - private readonly IServerApplicationHost _appHost; - private readonly ILogger _logger; - - public SyncedMediaSourceProvider(ISyncManager syncManager, IServerApplicationHost appHost, ILogger logger) - { - _appHost = appHost; - _logger = logger; - _syncManager = (SyncManager)syncManager; - } - - public async Task<IEnumerable<MediaSourceInfo>> GetMediaSources(IHasMediaSources item, CancellationToken cancellationToken) - { - var jobItemResult = _syncManager.GetJobItems(new SyncJobItemQuery - { - AddMetadata = false, - Statuses = new[] { SyncJobItemStatus.Synced }, - ItemId = item.Id.ToString("N") - }); - - var list = new List<MediaSourceInfo>(); - - if (jobItemResult.Items.Length > 0) - { - var targets = _syncManager.ServerSyncProviders - .SelectMany(i => i.GetAllSyncTargets().Select(t => new Tuple<IServerSyncProvider, SyncTarget>(i, t))) - .ToList(); - - var serverId = _appHost.SystemId; - - foreach (var jobItem in jobItemResult.Items) - { - var targetTuple = targets.FirstOrDefault(i => string.Equals(i.Item2.Id, jobItem.TargetId, StringComparison.OrdinalIgnoreCase)); - - if (targetTuple != null) - { - var syncTarget = targetTuple.Item2; - var syncProvider = targetTuple.Item1; - var dataProvider = _syncManager.GetDataProvider(targetTuple.Item1, syncTarget); - - var localItems = await dataProvider.GetItems(syncTarget, serverId, item.Id.ToString("N")).ConfigureAwait(false); - - foreach (var localItem in localItems) - { - foreach (var mediaSource in localItem.Item.MediaSources) - { - AddMediaSource(list, localItem, mediaSource, syncProvider, syncTarget); - } - } - } - } - } - - return list; - } - - private void AddMediaSource(List<MediaSourceInfo> list, - LocalItem item, - MediaSourceInfo mediaSource, - IServerSyncProvider provider, - SyncTarget target) - { - SetStaticMediaSourceInfo(item, mediaSource); - - var requiresDynamicAccess = provider as IHasDynamicAccess; - - if (requiresDynamicAccess != null) - { - mediaSource.RequiresOpening = true; - - var keyList = new List<string>(); - keyList.Add(provider.GetType().FullName.GetMD5().ToString("N")); - keyList.Add(target.Id.GetMD5().ToString("N")); - keyList.Add(item.Id); - mediaSource.OpenToken = string.Join(StreamIdDelimeterString, keyList.ToArray()); - } - - list.Add(mediaSource); - } - - // Do not use a pipe here because Roku http requests to the server will fail, without any explicit error message. - private const string StreamIdDelimeterString = "_"; - - public async Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> OpenMediaSource(string openToken, CancellationToken cancellationToken) - { - var openKeys = openToken.Split(new[] { StreamIdDelimeterString[0] }, 3); - - var provider = _syncManager.ServerSyncProviders - .FirstOrDefault(i => string.Equals(openKeys[0], i.GetType().FullName.GetMD5().ToString("N"), StringComparison.OrdinalIgnoreCase)); - - var target = provider.GetAllSyncTargets() - .FirstOrDefault(i => string.Equals(openKeys[1], i.Id.GetMD5().ToString("N"), StringComparison.OrdinalIgnoreCase)); - - var dataProvider = _syncManager.GetDataProvider(provider, target); - var localItem = await dataProvider.Get(target, openKeys[2]).ConfigureAwait(false); - - var fileId = localItem.FileId; - if (string.IsNullOrWhiteSpace(fileId)) - { - } - - var requiresDynamicAccess = (IHasDynamicAccess)provider; - var dynamicInfo = await requiresDynamicAccess.GetSyncedFileInfo(fileId, target, cancellationToken).ConfigureAwait(false); - - var mediaSource = localItem.Item.MediaSources.First(); - mediaSource.LiveStreamId = Guid.NewGuid().ToString(); - SetStaticMediaSourceInfo(localItem, mediaSource); - - foreach (var stream in mediaSource.MediaStreams) - { - if (!string.IsNullOrWhiteSpace(stream.ExternalId)) - { - var dynamicStreamInfo = await requiresDynamicAccess.GetSyncedFileInfo(stream.ExternalId, target, cancellationToken).ConfigureAwait(false); - stream.Path = dynamicStreamInfo.Path; - } - } - - mediaSource.Path = dynamicInfo.Path; - mediaSource.Protocol = dynamicInfo.Protocol; - mediaSource.RequiredHttpHeaders = dynamicInfo.RequiredHttpHeaders; - - return new Tuple<MediaSourceInfo, IDirectStreamProvider>(mediaSource, null); - } - - private void SetStaticMediaSourceInfo(LocalItem item, MediaSourceInfo mediaSource) - { - mediaSource.Id = item.Id; - mediaSource.SupportsTranscoding = false; - if (mediaSource.Protocol == Model.MediaInfo.MediaProtocol.File) - { - mediaSource.ETag = item.Id; - } - } - - public Task CloseMediaSource(string liveStreamId) - { - throw new NotImplementedException(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs b/MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs deleted file mode 100644 index 32a6003719..0000000000 --- a/MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs +++ /dev/null @@ -1,195 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Sync; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Sync; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using Interfaces.IO; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.Server.Implementations.Sync -{ - public class TargetDataProvider : ISyncDataProvider - { - private readonly SyncTarget _target; - private readonly IServerSyncProvider _provider; - - private readonly SemaphoreSlim _dataLock = new SemaphoreSlim(1, 1); - private List<LocalItem> _items; - - private readonly ILogger _logger; - private readonly IJsonSerializer _json; - private readonly IFileSystem _fileSystem; - private readonly IApplicationPaths _appPaths; - private readonly IServerApplicationHost _appHost; - private readonly IMemoryStreamProvider _memoryStreamProvider; - - public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, IServerApplicationHost appHost, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths, IMemoryStreamProvider memoryStreamProvider) - { - _logger = logger; - _json = json; - _provider = provider; - _target = target; - _fileSystem = fileSystem; - _appPaths = appPaths; - _memoryStreamProvider = memoryStreamProvider; - _appHost = appHost; - } - - private string[] GetRemotePath() - { - var parts = new List<string> - { - _appHost.FriendlyName, - "data.json" - }; - - parts = parts.Select(i => GetValidFilename(_provider, i)).ToList(); - - return parts.ToArray(); - } - - private string GetValidFilename(IServerSyncProvider provider, string filename) - { - // We can always add this method to the sync provider if it's really needed - return _fileSystem.GetValidFilename(filename); - } - - private async Task<List<LocalItem>> RetrieveItems(CancellationToken cancellationToken) - { - _logger.Debug("Getting {0} from {1}", string.Join(MediaSync.PathSeparatorString, GetRemotePath().ToArray()), _provider.Name); - - var fileResult = await _provider.GetFiles(new FileQuery - { - FullPath = GetRemotePath().ToArray() - - }, _target, cancellationToken).ConfigureAwait(false); - - if (fileResult.Items.Length > 0) - { - using (var stream = await _provider.GetFile(fileResult.Items[0].Id, _target, new Progress<double>(), cancellationToken)) - { - return _json.DeserializeFromStream<List<LocalItem>>(stream); - } - } - - return new List<LocalItem>(); - } - - private async Task EnsureData(CancellationToken cancellationToken) - { - if (_items == null) - { - _items = await RetrieveItems(cancellationToken).ConfigureAwait(false); - } - } - - private async Task SaveData(List<LocalItem> items, CancellationToken cancellationToken) - { - using (var stream = _memoryStreamProvider.CreateNew()) - { - _json.SerializeToStream(items, stream); - - // 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); - } - } - - private async Task<T> GetData<T>(bool enableCache, Func<List<LocalItem>, T> dataFactory) - { - if (!enableCache) - { - var items = await RetrieveItems(CancellationToken.None).ConfigureAwait(false); - var newCache = items.ToList(); - var result = dataFactory(items); - await UpdateCache(newCache).ConfigureAwait(false); - return result; - } - - await _dataLock.WaitAsync().ConfigureAwait(false); - - try - { - await EnsureData(CancellationToken.None).ConfigureAwait(false); - - return dataFactory(_items); - } - finally - { - _dataLock.Release(); - } - } - - private async Task UpdateData(Func<List<LocalItem>, List<LocalItem>> action) - { - var items = await RetrieveItems(CancellationToken.None).ConfigureAwait(false); - items = action(items); - await SaveData(items.ToList(), CancellationToken.None).ConfigureAwait(false); - - await UpdateCache(null).ConfigureAwait(false); - } - - private async Task UpdateCache(List<LocalItem> list) - { - await _dataLock.WaitAsync().ConfigureAwait(false); - - try - { - _items = list; - } - finally - { - _dataLock.Release(); - } - } - - public Task<List<LocalItem>> GetLocalItems(SyncTarget target, string serverId) - { - return GetData(false, items => items.Where(i => string.Equals(i.ServerId, serverId, StringComparison.OrdinalIgnoreCase)).ToList()); - } - - public Task AddOrUpdate(SyncTarget target, LocalItem item) - { - return UpdateData(items => - { - var list = items.Where(i => !string.Equals(i.Id, item.Id, StringComparison.OrdinalIgnoreCase)) - .ToList(); - - list.Add(item); - - return list; - }); - } - - public Task Delete(SyncTarget target, string id) - { - return UpdateData(items => items.Where(i => !string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)).ToList()); - } - - public Task<LocalItem> Get(SyncTarget target, string id) - { - return GetData(true, items => items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase))); - } - - public Task<List<LocalItem>> GetItems(SyncTarget target, string serverId, string itemId) - { - return GetData(true, items => items.Where(i => string.Equals(i.ServerId, serverId, StringComparison.OrdinalIgnoreCase) && string.Equals(i.ItemId, itemId, StringComparison.OrdinalIgnoreCase)).ToList()); - } - - public Task<List<LocalItem>> GetItemsBySyncJobItemId(SyncTarget target, string serverId, string syncJobItemId) - { - return GetData(false, items => items.Where(i => string.Equals(i.ServerId, serverId, StringComparison.OrdinalIgnoreCase) && string.Equals(i.SyncJobItemId, syncJobItemId, StringComparison.OrdinalIgnoreCase)).ToList()); - } - } -} diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs deleted file mode 100644 index 03e8a9178e..0000000000 --- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs +++ /dev/null @@ -1,226 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.TV; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Querying; -using System; -using System.Collections.Generic; -using System.Linq; -using MediaBrowser.Controller.Configuration; - -namespace MediaBrowser.Server.Implementations.TV -{ - public class TVSeriesManager : ITVSeriesManager - { - private readonly IUserManager _userManager; - private readonly IUserDataManager _userDataManager; - private readonly ILibraryManager _libraryManager; - private readonly IServerConfigurationManager _config; - - public TVSeriesManager(IUserManager userManager, IUserDataManager userDataManager, ILibraryManager libraryManager, IServerConfigurationManager config) - { - _userManager = userManager; - _userDataManager = userDataManager; - _libraryManager = libraryManager; - _config = config; - } - - public QueryResult<BaseItem> GetNextUp(NextUpQuery request) - { - var user = _userManager.GetUserById(request.UserId); - - if (user == null) - { - throw new ArgumentException("User not found"); - } - - var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId); - - string presentationUniqueKey = null; - int? limit = null; - if (!string.IsNullOrWhiteSpace(request.SeriesId)) - { - var series = _libraryManager.GetItemById(request.SeriesId); - - if (series != null) - { - presentationUniqueKey = GetUniqueSeriesKey(series); - limit = 1; - } - } - - if (string.IsNullOrWhiteSpace(presentationUniqueKey) && limit.HasValue) - { - limit = limit.Value + 10; - } - - var items = _libraryManager.GetItemList(new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Series).Name }, - SortOrder = SortOrder.Ascending, - PresentationUniqueKey = presentationUniqueKey, - Limit = limit, - ParentId = parentIdGuid, - Recursive = true - - }).Cast<Series>(); - - // Avoid implicitly captured closure - var episodes = GetNextUpEpisodes(request, user, items); - - return GetResult(episodes, null, request); - } - - public QueryResult<BaseItem> GetNextUp(NextUpQuery request, IEnumerable<Folder> parentsFolders) - { - var user = _userManager.GetUserById(request.UserId); - - if (user == null) - { - throw new ArgumentException("User not found"); - } - - string presentationUniqueKey = null; - int? limit = null; - if (!string.IsNullOrWhiteSpace(request.SeriesId)) - { - var series = _libraryManager.GetItemById(request.SeriesId); - - if (series != null) - { - presentationUniqueKey = GetUniqueSeriesKey(series); - limit = 1; - } - } - - if (string.IsNullOrWhiteSpace(presentationUniqueKey) && limit.HasValue) - { - limit = limit.Value + 10; - } - - var items = _libraryManager.GetItemList(new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Series).Name }, - SortOrder = SortOrder.Ascending, - PresentationUniqueKey = presentationUniqueKey, - Limit = limit - - }, parentsFolders.Select(i => i.Id.ToString("N"))).Cast<Series>(); - - // Avoid implicitly captured closure - var episodes = GetNextUpEpisodes(request, user, items); - - return GetResult(episodes, null, request); - } - - public IEnumerable<Episode> GetNextUpEpisodes(NextUpQuery request, User user, IEnumerable<Series> series) - { - // Avoid implicitly captured closure - var currentUser = user; - - var allNextUp = series - .Select(i => GetNextUp(i, currentUser)) - .Where(i => i.Item1 != null) - // Include if an episode was found, and either the series is not unwatched or the specific series was requested - .OrderByDescending(i => i.Item2) - .ThenByDescending(i => i.Item1.PremiereDate ?? DateTime.MinValue) - .ToList(); - - // If viewing all next up for all series, remove first episodes - if (string.IsNullOrWhiteSpace(request.SeriesId)) - { - var withoutFirstEpisode = allNextUp - .Where(i => !i.Item3) - .ToList(); - - // But if that returns empty, keep those first episodes (avoid completely empty view) - if (withoutFirstEpisode.Count > 0) - { - allNextUp = withoutFirstEpisode; - } - } - - return allNextUp - .Select(i => i.Item1) - .Take(request.Limit ?? int.MaxValue); - } - - private string GetUniqueSeriesKey(BaseItem series) - { - if (_config.Configuration.SchemaVersion < 97) - { - return series.Id.ToString("N"); - } - return series.GetPresentationUniqueKey(); - } - - /// <summary> - /// Gets the next up. - /// </summary> - /// <param name="series">The series.</param> - /// <param name="user">The user.</param> - /// <returns>Task{Episode}.</returns> - private Tuple<Episode, DateTime, bool> GetNextUp(Series series, User user) - { - var lastWatchedEpisode = _libraryManager.GetItemList(new InternalItemsQuery(user) - { - AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(series), - IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { ItemSortBy.SortName }, - SortOrder = SortOrder.Descending, - IsPlayed = true, - Limit = 1, - ParentIndexNumberNotEquals = 0 - - }).FirstOrDefault(); - - var firstUnwatchedEpisode = _libraryManager.GetItemList(new InternalItemsQuery(user) - { - AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(series), - IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { ItemSortBy.SortName }, - SortOrder = SortOrder.Ascending, - Limit = 1, - IsPlayed = false, - IsVirtualItem = false, - ParentIndexNumberNotEquals = 0, - MinSortName = lastWatchedEpisode == null ? null : lastWatchedEpisode.SortName - - }).Cast<Episode>().FirstOrDefault(); - - if (lastWatchedEpisode != null && firstUnwatchedEpisode != null) - { - var userData = _userDataManager.GetUserData(user, lastWatchedEpisode); - - var lastWatchedDate = userData.LastPlayedDate ?? DateTime.MinValue.AddDays(1); - - return new Tuple<Episode, DateTime, bool>(firstUnwatchedEpisode, lastWatchedDate, false); - } - - // Return the first episode - return new Tuple<Episode, DateTime, bool>(firstUnwatchedEpisode, DateTime.MinValue, true); - } - - private QueryResult<BaseItem> GetResult(IEnumerable<BaseItem> items, int? totalRecordLimit, NextUpQuery query) - { - var itemsArray = totalRecordLimit.HasValue ? items.Take(totalRecordLimit.Value).ToArray() : items.ToArray(); - var totalCount = itemsArray.Length; - - if (query.Limit.HasValue) - { - itemsArray = itemsArray.Skip(query.StartIndex ?? 0).Take(query.Limit.Value).ToArray(); - } - else if (query.StartIndex.HasValue) - { - itemsArray = itemsArray.Skip(query.StartIndex.Value).ToArray(); - } - - return new QueryResult<BaseItem> - { - TotalRecordCount = totalCount, - Items = itemsArray - }; - } - } -} diff --git a/MediaBrowser.Server.Implementations/Udp/UdpMessageReceivedEventArgs.cs b/MediaBrowser.Server.Implementations/Udp/UdpMessageReceivedEventArgs.cs deleted file mode 100644 index 5c83a13007..0000000000 --- a/MediaBrowser.Server.Implementations/Udp/UdpMessageReceivedEventArgs.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace MediaBrowser.Server.Implementations.Udp -{ - /// <summary> - /// Class UdpMessageReceivedEventArgs - /// </summary> - public class UdpMessageReceivedEventArgs : EventArgs - { - /// <summary> - /// Gets or sets the bytes. - /// </summary> - /// <value>The bytes.</value> - public byte[] Bytes { get; set; } - /// <summary> - /// Gets or sets the remote end point. - /// </summary> - /// <value>The remote end point.</value> - public string RemoteEndPoint { get; set; } - } -} diff --git a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs deleted file mode 100644 index 6dd5de5480..0000000000 --- a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs +++ /dev/null @@ -1,324 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Model.ApiClient; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Udp -{ - /// <summary> - /// Provides a Udp Server - /// </summary> - public class UdpServer : IDisposable - { - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - /// <summary> - /// The _network manager - /// </summary> - private readonly INetworkManager _networkManager; - - private bool _isDisposed; - - private readonly List<Tuple<string, bool, Func<string, string, Encoding, Task>>> _responders = new List<Tuple<string, bool, Func<string, string, Encoding, Task>>>(); - - private readonly IServerApplicationHost _appHost; - private readonly IJsonSerializer _json; - - /// <summary> - /// Initializes a new instance of the <see cref="UdpServer" /> class. - /// </summary> - /// <param name="logger">The logger.</param> - /// <param name="networkManager">The network manager.</param> - /// <param name="appHost">The application host.</param> - /// <param name="json">The json.</param> - public UdpServer(ILogger logger, INetworkManager networkManager, IServerApplicationHost appHost, IJsonSerializer json) - { - _logger = logger; - _networkManager = networkManager; - _appHost = appHost; - _json = json; - - AddMessageResponder("who is EmbyServer?", true, RespondToV2Message); - AddMessageResponder("who is MediaBrowserServer_v2?", false, RespondToV2Message); - } - - private void AddMessageResponder(string message, bool isSubstring, Func<string, string, Encoding, Task> responder) - { - _responders.Add(new Tuple<string, bool, Func<string, string, Encoding, Task>>(message, isSubstring, responder)); - } - - /// <summary> - /// Raises the <see cref="E:MessageReceived" /> event. - /// </summary> - /// <param name="e">The <see cref="UdpMessageReceivedEventArgs"/> instance containing the event data.</param> - private async void OnMessageReceived(UdpMessageReceivedEventArgs e) - { - var encoding = Encoding.UTF8; - var responder = GetResponder(e.Bytes, encoding); - - if (responder == null) - { - encoding = Encoding.Unicode; - responder = GetResponder(e.Bytes, encoding); - } - - if (responder != null) - { - try - { - await responder.Item2.Item3(responder.Item1, e.RemoteEndPoint, encoding).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error in OnMessageReceived", ex); - } - } - } - - private Tuple<string, Tuple<string, bool, Func<string, string, Encoding, Task>>> GetResponder(byte[] bytes, Encoding encoding) - { - var text = encoding.GetString(bytes); - var responder = _responders.FirstOrDefault(i => - { - if (i.Item2) - { - return text.IndexOf(i.Item1, StringComparison.OrdinalIgnoreCase) != -1; - } - return string.Equals(i.Item1, text, StringComparison.OrdinalIgnoreCase); - }); - - if (responder == null) - { - return null; - } - return new Tuple<string, Tuple<string, bool, Func<string, string, Encoding, Task>>>(text, responder); - } - - private async Task RespondToV2Message(string messageText, string endpoint, Encoding encoding) - { - var parts = messageText.Split('|'); - - var localUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false); - - if (!string.IsNullOrEmpty(localUrl)) - { - var response = new ServerDiscoveryInfo - { - Address = localUrl, - Id = _appHost.SystemId, - Name = _appHost.FriendlyName - }; - - await SendAsync(encoding.GetBytes(_json.SerializeToString(response)), endpoint).ConfigureAwait(false); - - if (parts.Length > 1) - { - _appHost.EnableLoopback(parts[1]); - } - } - else - { - _logger.Warn("Unable to respond to udp request because the local ip address could not be determined."); - } - } - - /// <summary> - /// The _udp client - /// </summary> - private UdpClient _udpClient; - - /// <summary> - /// Starts the specified port. - /// </summary> - /// <param name="port">The port.</param> - public void Start(int port) - { - _udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, port)); - - _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - - Task.Run(() => StartListening()); - } - - private async void StartListening() - { - while (!_isDisposed) - { - try - { - var result = await GetResult().ConfigureAwait(false); - - OnMessageReceived(result); - } - catch (ObjectDisposedException) - { - break; - } - catch (Exception ex) - { - _logger.ErrorException("Error in StartListening", ex); - } - } - } - - private Task<UdpReceiveResult> GetResult() - { - try - { - return _udpClient.ReceiveAsync(); - } - catch (ObjectDisposedException) - { - return Task.FromResult(new UdpReceiveResult(new byte[] { }, new IPEndPoint(IPAddress.Any, 0))); - } - catch (Exception ex) - { - _logger.ErrorException("Error receiving udp message", ex); - return Task.FromResult(new UdpReceiveResult(new byte[] { }, new IPEndPoint(IPAddress.Any, 0))); - } - } - - /// <summary> - /// Called when [message received]. - /// </summary> - /// <param name="message">The message.</param> - private void OnMessageReceived(UdpReceiveResult message) - { - if (message.RemoteEndPoint.Port == 0) - { - return; - } - var bytes = message.Buffer; - - try - { - OnMessageReceived(new UdpMessageReceivedEventArgs - { - Bytes = bytes, - RemoteEndPoint = message.RemoteEndPoint.ToString() - }); - } - catch (Exception ex) - { - _logger.ErrorException("Error handling UDP message", ex); - } - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// <summary> - /// Stops this instance. - /// </summary> - public void Stop() - { - _isDisposed = true; - - if (_udpClient != null) - { - _udpClient.Close(); - } - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - Stop(); - } - } - - /// <summary> - /// Sends the async. - /// </summary> - /// <param name="data">The data.</param> - /// <param name="ipAddress">The ip address.</param> - /// <param name="port">The port.</param> - /// <returns>Task{System.Int32}.</returns> - /// <exception cref="System.ArgumentNullException">data</exception> - public Task SendAsync(string data, string ipAddress, int port) - { - return SendAsync(Encoding.UTF8.GetBytes(data), ipAddress, port); - } - - /// <summary> - /// Sends the async. - /// </summary> - /// <param name="bytes">The bytes.</param> - /// <param name="ipAddress">The ip address.</param> - /// <param name="port">The port.</param> - /// <returns>Task{System.Int32}.</returns> - /// <exception cref="System.ArgumentNullException">bytes</exception> - public Task SendAsync(byte[] bytes, string ipAddress, int port) - { - if (bytes == null) - { - throw new ArgumentNullException("bytes"); - } - - if (string.IsNullOrEmpty(ipAddress)) - { - throw new ArgumentNullException("ipAddress"); - } - - return _udpClient.SendAsync(bytes, bytes.Length, ipAddress, port); - } - - /// <summary> - /// Sends the async. - /// </summary> - /// <param name="bytes">The bytes.</param> - /// <param name="remoteEndPoint">The remote end point.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"> - /// bytes - /// or - /// remoteEndPoint - /// </exception> - public async Task SendAsync(byte[] bytes, string remoteEndPoint) - { - if (bytes == null) - { - throw new ArgumentNullException("bytes"); - } - - if (string.IsNullOrEmpty(remoteEndPoint)) - { - throw new ArgumentNullException("remoteEndPoint"); - } - - try - { - await _udpClient.SendAsync(bytes, bytes.Length, _networkManager.Parse(remoteEndPoint)).ConfigureAwait(false); - - _logger.Info("Udp message sent to {0}", remoteEndPoint); - } - catch (Exception ex) - { - _logger.ErrorException("Error sending message to {0}", ex, remoteEndPoint); - } - } - } - -} diff --git a/MediaBrowser.Server.Implementations/UserViews/CollectionFolderImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/CollectionFolderImageProvider.cs deleted file mode 100644 index 2cff4a14f0..0000000000 --- a/MediaBrowser.Server.Implementations/UserViews/CollectionFolderImageProvider.cs +++ /dev/null @@ -1,174 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Server.Implementations.Photos; -using MoreLinq; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Controller.Collections; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Server.Implementations.UserViews -{ - public class CollectionFolderImageProvider : BaseDynamicImageProvider<CollectionFolder> - { - public CollectionFolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - } - - public override IEnumerable<ImageType> GetSupportedImages(IHasImages item) - { - return new List<ImageType> - { - ImageType.Primary - }; - } - - protected override async Task<List<BaseItem>> GetItemsWithImages(IHasImages item) - { - var view = (CollectionFolder)item; - - var recursive = !new[] { CollectionType.Playlists, CollectionType.Channels }.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); - - var result = await view.GetItems(new InternalItemsQuery - { - CollapseBoxSetItems = false, - Recursive = recursive, - ExcludeItemTypes = new[] { "UserView", "CollectionFolder", "Playlist" } - - }).ConfigureAwait(false); - - var items = result.Items.Select(i => - { - var episode = i as Episode; - if (episode != null) - { - var series = episode.Series; - if (series != null) - { - return series; - } - - return episode; - } - - var season = i as Season; - if (season != null) - { - var series = season.Series; - if (series != null) - { - return series; - } - - return season; - } - - var audio = i as Audio; - if (audio != null) - { - var album = audio.AlbumEntity; - if (album != null && album.HasImage(ImageType.Primary)) - { - return album; - } - } - - return i; - - }).DistinctBy(i => i.Id); - - return GetFinalItems(items.Where(i => i.HasImage(ImageType.Primary) || i.HasImage(ImageType.Thumb)).ToList(), 8); - } - - protected override bool Supports(IHasImages item) - { - return item is CollectionFolder; - } - - protected override async Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) - { - var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ".png"); - - if (imageType == ImageType.Primary) - { - if (itemsWithImages.Count == 0) - { - return null; - } - - return await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540).ConfigureAwait(false); - } - - return await base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex).ConfigureAwait(false); - } - } - - public class ManualCollectionFolderImageProvider : BaseDynamicImageProvider<ManualCollectionsFolder> - { - private readonly ILibraryManager _libraryManager; - - public ManualCollectionFolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - _libraryManager = libraryManager; - } - - public override IEnumerable<ImageType> GetSupportedImages(IHasImages item) - { - return new List<ImageType> - { - ImageType.Primary - }; - } - - protected override async Task<List<BaseItem>> GetItemsWithImages(IHasImages item) - { - var view = (ManualCollectionsFolder)item; - - var recursive = !new[] { CollectionType.Playlists, CollectionType.Channels }.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); - - var items = _libraryManager.GetItemList(new InternalItemsQuery - { - Recursive = recursive, - IncludeItemTypes = new[] { typeof(BoxSet).Name }, - Limit = 20, - SortBy = new[] { ItemSortBy.Random } - }); - - return GetFinalItems(items.Where(i => i.HasImage(ImageType.Primary) || i.HasImage(ImageType.Thumb)).ToList(), 8); - } - - protected override bool Supports(IHasImages item) - { - return item is ManualCollectionsFolder; - } - - protected override async Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) - { - var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ".png"); - - if (imageType == ImageType.Primary) - { - if (itemsWithImages.Count == 0) - { - return null; - } - - return await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540).ConfigureAwait(false); - } - - return await base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex).ConfigureAwait(false); - } - } - -} diff --git a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs deleted file mode 100644 index f400728971..0000000000 --- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs +++ /dev/null @@ -1,188 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Server.Implementations.Photos; -using MoreLinq; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Controller.LiveTv; - -namespace MediaBrowser.Server.Implementations.UserViews -{ - public class DynamicImageProvider : BaseDynamicImageProvider<UserView> - { - private readonly IUserManager _userManager; - private readonly ILibraryManager _libraryManager; - - public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, IUserManager userManager, ILibraryManager libraryManager) - : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - _userManager = userManager; - _libraryManager = libraryManager; - } - - public override IEnumerable<ImageType> GetSupportedImages(IHasImages item) - { - var view = (UserView)item; - if (IsUsingCollectionStrip(view)) - { - return new List<ImageType> - { - ImageType.Primary - }; - } - - return new List<ImageType> - { - ImageType.Primary - }; - } - - protected override async Task<List<BaseItem>> GetItemsWithImages(IHasImages item) - { - var view = (UserView)item; - - if (string.Equals(view.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase)) - { - var programs = _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(LiveTvProgram).Name }, - ImageTypes = new[] { ImageType.Primary }, - Limit = 30, - IsMovie = true - }).ToList(); - - return GetFinalItems(programs).ToList(); - } - - if (string.Equals(view.ViewType, SpecialFolder.MovieGenre, StringComparison.OrdinalIgnoreCase) || - string.Equals(view.ViewType, SpecialFolder.TvGenre, StringComparison.OrdinalIgnoreCase)) - { - var userItemsResult = await view.GetItems(new InternalItemsQuery - { - CollapseBoxSetItems = false - }); - - return userItemsResult.Items.ToList(); - } - - var isUsingCollectionStrip = IsUsingCollectionStrip(view); - var recursive = isUsingCollectionStrip && !new[] { CollectionType.Channels, CollectionType.BoxSets, CollectionType.Playlists }.Contains(view.ViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); - - var result = await view.GetItems(new InternalItemsQuery - { - User = view.UserId.HasValue ? _userManager.GetUserById(view.UserId.Value) : null, - CollapseBoxSetItems = false, - Recursive = recursive, - ExcludeItemTypes = new[] { "UserView", "CollectionFolder", "Person" }, - - }).ConfigureAwait(false); - - var items = result.Items.Select(i => - { - var episode = i as Episode; - if (episode != null) - { - var series = episode.Series; - if (series != null) - { - return series; - } - - return episode; - } - - var season = i as Season; - if (season != null) - { - var series = season.Series; - if (series != null) - { - return series; - } - - return season; - } - - var audio = i as Audio; - if (audio != null) - { - var album = audio.AlbumEntity; - if (album != null && album.HasImage(ImageType.Primary)) - { - return album; - } - } - - return i; - - }).DistinctBy(i => i.Id); - - if (isUsingCollectionStrip) - { - return GetFinalItems(items.Where(i => i.HasImage(ImageType.Primary) || i.HasImage(ImageType.Thumb)).ToList(), 8); - } - - return GetFinalItems(items.Where(i => i.HasImage(ImageType.Primary)).ToList()); - } - - protected override bool Supports(IHasImages item) - { - var view = item as UserView; - if (view != null) - { - return IsUsingCollectionStrip(view); - } - - return false; - } - - private bool IsUsingCollectionStrip(UserView view) - { - string[] collectionStripViewTypes = - { - CollectionType.Movies, - CollectionType.TvShows, - CollectionType.Music, - CollectionType.Games, - CollectionType.Books, - CollectionType.MusicVideos, - CollectionType.HomeVideos, - CollectionType.BoxSets, - CollectionType.LiveTv, - CollectionType.Playlists, - CollectionType.Photos, - string.Empty - }; - - return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty); - } - - protected override async Task<string> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) - { - var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ".png"); - - var view = (UserView)item; - if (imageType == ImageType.Primary && IsUsingCollectionStrip(view)) - { - if (itemsWithImages.Count == 0) - { - return null; - } - - return await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540).ConfigureAwait(false); - } - - return await base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex).ConfigureAwait(false); - } - } -} diff --git a/MediaBrowser.Server.Implementations/app.config b/MediaBrowser.Server.Implementations/app.config index 77b8b9218c..9d8c1ac93a 100644 --- a/MediaBrowser.Server.Implementations/app.config +++ b/MediaBrowser.Server.Implementations/app.config @@ -8,4 +8,4 @@ </dependentAssembly> </assemblyBinding> </runtime> -<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/></startup></configuration> +<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/></startup></configuration> diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config deleted file mode 100644 index 043257fc8a..0000000000 --- a/MediaBrowser.Server.Implementations/packages.config +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
- <package id="Emby.XmlTv" version="1.0.0.56" targetFramework="net45" />
- <package id="ini-parser" version="2.3.0" targetFramework="net45" />
- <package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
- <package id="MediaBrowser.Naming" version="1.0.0.55" targetFramework="net45" />
- <package id="morelinq" version="1.4.0" targetFramework="net45" />
- <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
- <package id="SimpleInjector" version="3.2.2" targetFramework="net45" />
- <package id="SocketHttpListener" version="1.0.0.40" targetFramework="net45" />
-</packages>
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/project.json b/MediaBrowser.Server.Implementations/project.json new file mode 100644 index 0000000000..fbbe9eaf32 --- /dev/null +++ b/MediaBrowser.Server.Implementations/project.json @@ -0,0 +1,17 @@ +{ + "frameworks":{ + "netstandard1.6":{ + "dependencies":{ + "NETStandard.Library":"1.6.0", + } + }, + ".NETPortable,Version=v4.5,Profile=Profile7":{ + "buildOptions": { + "define": [ ] + }, + "frameworkAssemblies":{ + + } + } + } +}
\ No newline at end of file |
