commit
ee9c6c5664
|
@ -1207,7 +1207,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int? GetVideoBitrateParamValue(VideoStreamRequest request, MediaStream videoStream)
|
private int? GetVideoBitrateParamValue(VideoStreamRequest request, MediaStream videoStream, string outputVideoCodec)
|
||||||
{
|
{
|
||||||
var bitrate = request.VideoBitRate;
|
var bitrate = request.VideoBitRate;
|
||||||
|
|
||||||
|
@ -1232,6 +1232,12 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bitrate.HasValue)
|
||||||
|
{
|
||||||
|
var inputVideoCodec = videoStream == null ? null : videoStream.Codec;
|
||||||
|
bitrate = ResolutionNormalizer.ScaleBitrate(bitrate.Value, inputVideoCodec, outputVideoCodec);
|
||||||
|
}
|
||||||
|
|
||||||
return bitrate;
|
return bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1692,7 +1698,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
if (videoRequest != null)
|
if (videoRequest != null)
|
||||||
{
|
{
|
||||||
state.OutputVideoCodec = state.VideoRequest.VideoCodec;
|
state.OutputVideoCodec = state.VideoRequest.VideoCodec;
|
||||||
state.OutputVideoBitrate = GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream);
|
state.OutputVideoBitrate = GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec);
|
||||||
|
|
||||||
if (state.OutputVideoBitrate.HasValue)
|
if (state.OutputVideoBitrate.HasValue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -221,7 +221,7 @@ namespace MediaBrowser.Api.Subtitles
|
||||||
|
|
||||||
if (string.Equals(request.Format, "vtt", StringComparison.OrdinalIgnoreCase) && request.AddVttTimeMap)
|
if (string.Equals(request.Format, "vtt", StringComparison.OrdinalIgnoreCase) && request.AddVttTimeMap)
|
||||||
{
|
{
|
||||||
text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000");
|
//text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultFactory.GetResult(text, MimeTypes.GetMimeType("file." + request.Format));
|
return ResultFactory.GetResult(text, MimeTypes.GetMimeType("file." + request.Format));
|
||||||
|
|
|
@ -385,7 +385,7 @@ namespace MediaBrowser.Api
|
||||||
throw new ResourceNotFoundException("User not found");
|
throw new ResourceNotFoundException("User not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N")).ConfigureAwait(false);
|
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), null).ConfigureAwait(false);
|
||||||
|
|
||||||
await _userManager.DeleteUser(user).ConfigureAwait(false);
|
await _userManager.DeleteUser(user).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -465,6 +465,10 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
|
|
||||||
await _userManager.ChangePassword(user, request.NewPassword).ConfigureAwait(false);
|
await _userManager.ChangePassword(user, request.NewPassword).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var currentToken = AuthorizationContext.GetAuthorizationInfo(Request).Token;
|
||||||
|
|
||||||
|
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), currentToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,7 +606,8 @@ namespace MediaBrowser.Api
|
||||||
throw new ArgumentException("There must be at least one enabled user in the system.");
|
throw new ArgumentException("There must be at least one enabled user in the system.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N")).ConfigureAwait(false);
|
var currentToken = AuthorizationContext.GetAuthorizationInfo(Request).Token;
|
||||||
|
await _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), currentToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _userManager.UpdateUserPolicy(request.Id, request).ConfigureAwait(false);
|
await _userManager.UpdateUserPolicy(request.Id, request).ConfigureAwait(false);
|
||||||
|
|
|
@ -875,7 +875,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User))
|
if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User, ConfigurationManager))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems");
|
Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems");
|
||||||
return true;
|
return true;
|
||||||
|
@ -983,7 +983,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
|
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager);
|
return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager, ConfigurationManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent;
|
parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager, PlaylistManager)
|
return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, ConfigurationManager, PlaylistManager)
|
||||||
.GetUserItems(parent, this, ViewType, query);
|
.GetUserItems(parent, this, ViewType, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
|
@ -30,10 +32,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IUserDataManager _userDataManager;
|
private readonly IUserDataManager _userDataManager;
|
||||||
private readonly ITVSeriesManager _tvSeriesManager;
|
private readonly ITVSeriesManager _tvSeriesManager;
|
||||||
private readonly ICollectionManager _collectionManager;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IPlaylistManager _playlistManager;
|
private readonly IPlaylistManager _playlistManager;
|
||||||
|
|
||||||
public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, ICollectionManager collectionManager, IPlaylistManager playlistManager)
|
public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, IServerConfigurationManager config, IPlaylistManager playlistManager)
|
||||||
{
|
{
|
||||||
_userViewManager = userViewManager;
|
_userViewManager = userViewManager;
|
||||||
_liveTvManager = liveTvManager;
|
_liveTvManager = liveTvManager;
|
||||||
|
@ -42,7 +44,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_userDataManager = userDataManager;
|
_userDataManager = userDataManager;
|
||||||
_tvSeriesManager = tvSeriesManager;
|
_tvSeriesManager = tvSeriesManager;
|
||||||
_collectionManager = collectionManager;
|
_config = config;
|
||||||
_playlistManager = playlistManager;
|
_playlistManager = playlistManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +161,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return await GetTvGenres(queryParent, user, query).ConfigureAwait(false);
|
return await GetTvGenres(queryParent, user, query).ConfigureAwait(false);
|
||||||
|
|
||||||
case SpecialFolder.TvGenre:
|
case SpecialFolder.TvGenre:
|
||||||
return await GetTvGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
|
return GetTvGenreItems(queryParent, displayParent, user, query);
|
||||||
|
|
||||||
case SpecialFolder.TvResume:
|
case SpecialFolder.TvResume:
|
||||||
return GetTvResume(queryParent, user, query);
|
return GetTvResume(queryParent, user, query);
|
||||||
|
@ -740,7 +742,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
return GetResult(genres, parent, query);
|
return GetResult(genres, parent, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<QueryResult<BaseItem>> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
|
private QueryResult<BaseItem> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.Recursive = true;
|
query.Recursive = true;
|
||||||
query.ParentId = queryParent.Id;
|
query.ParentId = queryParent.Id;
|
||||||
|
@ -769,7 +771,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager));
|
items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager));
|
||||||
|
|
||||||
return PostFilterAndSort(items, queryParent, null, query, _libraryManager);
|
return PostFilterAndSort(items, queryParent, null, query, _libraryManager, _config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool FilterItem(BaseItem item, InternalItemsQuery query)
|
public static bool FilterItem(BaseItem item, InternalItemsQuery query)
|
||||||
|
@ -782,14 +784,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
int? totalRecordLimit,
|
int? totalRecordLimit,
|
||||||
InternalItemsQuery query)
|
InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager);
|
return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager, _config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
|
public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
|
||||||
BaseItem queryParent,
|
BaseItem queryParent,
|
||||||
int? totalRecordLimit,
|
int? totalRecordLimit,
|
||||||
InternalItemsQuery query,
|
InternalItemsQuery query,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager,
|
||||||
|
IServerConfigurationManager configurationManager)
|
||||||
{
|
{
|
||||||
var user = query.User;
|
var user = query.User;
|
||||||
|
|
||||||
|
@ -798,7 +801,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
query.IsVirtualUnaired,
|
query.IsVirtualUnaired,
|
||||||
query.IsUnaired);
|
query.IsUnaired);
|
||||||
|
|
||||||
items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user);
|
items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user, configurationManager);
|
||||||
|
|
||||||
// This must be the last filter
|
// This must be the last filter
|
||||||
if (!string.IsNullOrEmpty(query.AdjacentTo))
|
if (!string.IsNullOrEmpty(query.AdjacentTo))
|
||||||
|
@ -812,14 +815,15 @@ namespace MediaBrowser.Controller.Entities
|
||||||
public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
|
public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
|
||||||
InternalItemsQuery query,
|
InternalItemsQuery query,
|
||||||
BaseItem queryParent,
|
BaseItem queryParent,
|
||||||
User user)
|
User user,
|
||||||
|
IServerConfigurationManager configurationManager)
|
||||||
{
|
{
|
||||||
if (items == null)
|
if (items == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("items");
|
throw new ArgumentNullException("items");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CollapseBoxSetItems(query, queryParent, user))
|
if (CollapseBoxSetItems(query, queryParent, user, configurationManager))
|
||||||
{
|
{
|
||||||
items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user);
|
items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user);
|
||||||
}
|
}
|
||||||
|
@ -852,7 +856,8 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public static bool CollapseBoxSetItems(InternalItemsQuery query,
|
public static bool CollapseBoxSetItems(InternalItemsQuery query,
|
||||||
BaseItem queryParent,
|
BaseItem queryParent,
|
||||||
User user)
|
User user,
|
||||||
|
IServerConfigurationManager configurationManager)
|
||||||
{
|
{
|
||||||
// Could end up stuck in a loop like this
|
// Could end up stuck in a loop like this
|
||||||
if (queryParent is BoxSet)
|
if (queryParent is BoxSet)
|
||||||
|
@ -864,7 +869,7 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
if (!param.HasValue)
|
if (!param.HasValue)
|
||||||
{
|
{
|
||||||
if (user != null && !user.Configuration.GroupMoviesIntoBoxSets)
|
if (user != null && !configurationManager.Configuration.EnableGroupingIntoCollections)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -315,9 +315,8 @@ namespace MediaBrowser.Controller.Session
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Revokes the user tokens.
|
/// Revokes the user tokens.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId">The user identifier.</param>
|
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task RevokeUserTokens(string userId);
|
Task RevokeUserTokens(string userId, string currentAccessToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Revokes the token.
|
/// Revokes the token.
|
||||||
|
|
|
@ -99,7 +99,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
if (videoRequest != null)
|
if (videoRequest != null)
|
||||||
{
|
{
|
||||||
state.OutputVideoCodec = state.Options.VideoCodec;
|
state.OutputVideoCodec = state.Options.VideoCodec;
|
||||||
state.OutputVideoBitrate = GetVideoBitrateParamValue(state.Options, state.VideoStream);
|
state.OutputVideoBitrate = GetVideoBitrateParamValue(state.Options, state.VideoStream, state.OutputVideoCodec);
|
||||||
|
|
||||||
if (state.OutputVideoBitrate.HasValue)
|
if (state.OutputVideoBitrate.HasValue)
|
||||||
{
|
{
|
||||||
|
@ -396,7 +396,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
return request.AudioChannels;
|
return request.AudioChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int? GetVideoBitrateParamValue(EncodingJobOptions request, MediaStream videoStream)
|
private int? GetVideoBitrateParamValue(EncodingJobOptions request, MediaStream videoStream, string outputVideoCodec)
|
||||||
{
|
{
|
||||||
var bitrate = request.VideoBitRate;
|
var bitrate = request.VideoBitRate;
|
||||||
|
|
||||||
|
@ -421,6 +421,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bitrate.HasValue)
|
||||||
|
{
|
||||||
|
var inputVideoCodec = videoStream == null ? null : videoStream.Codec;
|
||||||
|
bitrate = ResolutionNormalizer.ScaleBitrate(bitrate.Value, inputVideoCodec, outputVideoCodec);
|
||||||
|
}
|
||||||
|
|
||||||
return bitrate;
|
return bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
public bool EnableStandaloneMusicKeys { get; set; }
|
public bool EnableStandaloneMusicKeys { get; set; }
|
||||||
public bool EnableLocalizedGuids { get; set; }
|
public bool EnableLocalizedGuids { get; set; }
|
||||||
public bool EnableFolderView { get; set; }
|
public bool EnableFolderView { get; set; }
|
||||||
|
public bool EnableGroupingIntoCollections { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
|
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
|
||||||
|
|
|
@ -56,5 +56,25 @@ namespace MediaBrowser.Model.Dlna
|
||||||
MaxHeight = maxHeight
|
MaxHeight = maxHeight
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static double GetVideoBitrateScaleFactor(string codec)
|
||||||
|
{
|
||||||
|
if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return .5;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ScaleBitrate(int bitrate, string inputVideoCodec, string outputVideoCodec)
|
||||||
|
{
|
||||||
|
var inputScaleFactor = GetVideoBitrateScaleFactor(inputVideoCodec);
|
||||||
|
var outputScaleFactor = GetVideoBitrateScaleFactor(outputVideoCodec);
|
||||||
|
var scaleFactor = outputScaleFactor/inputScaleFactor;
|
||||||
|
var newBitrate = scaleFactor*bitrate;
|
||||||
|
|
||||||
|
return Convert.ToInt32(newBitrate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.LiveTv
|
namespace MediaBrowser.Model.LiveTv
|
||||||
{
|
{
|
||||||
|
@ -73,17 +74,21 @@ namespace MediaBrowser.Model.LiveTv
|
||||||
|
|
||||||
public string[] EnabledTuners { get; set; }
|
public string[] EnabledTuners { get; set; }
|
||||||
public bool EnableAllTuners { get; set; }
|
public bool EnableAllTuners { get; set; }
|
||||||
public string[] NewsGenres { get; set; }
|
public string[] NewsCategories { get; set; }
|
||||||
public string[] SportsGenres { get; set; }
|
public string[] SportsCategories { get; set; }
|
||||||
public string[] KidsGenres { get; set; }
|
public string[] KidsCategories { get; set; }
|
||||||
|
public string[] MovieCategories { get; set; }
|
||||||
|
public NameValuePair[] ChannelMappings { get; set; }
|
||||||
|
|
||||||
public ListingsProviderInfo()
|
public ListingsProviderInfo()
|
||||||
{
|
{
|
||||||
NewsGenres = new string[] { "news" };
|
NewsCategories = new string[] { "news", "journalism", "documentary", "current affairs" };
|
||||||
SportsGenres = new string[] { "sports", "basketball", "baseball", "football" };
|
SportsCategories = new string[] { "sports", "basketball", "baseball", "football" };
|
||||||
KidsGenres = new string[] { "kids", "family", "children" };
|
KidsCategories = new string[] { "kids", "family", "children", "childrens", "disney" };
|
||||||
|
MovieCategories = new string[] { "movie" };
|
||||||
EnabledTuners = new string[] { };
|
EnabledTuners = new string[] { };
|
||||||
EnableAllTuners = true;
|
EnableAllTuners = true;
|
||||||
|
ChannelMappings = new NameValuePair[] {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,6 @@ namespace MediaBrowser.Server.Implementations.Connect
|
||||||
{
|
{
|
||||||
return new ConnectUserPreferences
|
return new ConnectUserPreferences
|
||||||
{
|
{
|
||||||
GroupMoviesIntoBoxSets = config.GroupMoviesIntoBoxSets,
|
|
||||||
PlayDefaultAudioTrack = config.PlayDefaultAudioTrack,
|
PlayDefaultAudioTrack = config.PlayDefaultAudioTrack,
|
||||||
SubtitleMode = config.SubtitleMode,
|
SubtitleMode = config.SubtitleMode,
|
||||||
PreferredAudioLanguages = string.IsNullOrWhiteSpace(config.AudioLanguagePreference) ? new string[] { } : new[] { config.AudioLanguagePreference },
|
PreferredAudioLanguages = string.IsNullOrWhiteSpace(config.AudioLanguagePreference) ? new string[] { } : new[] { config.AudioLanguagePreference },
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
|
|
||||||
var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, liveTvItem.ServiceName, StringComparison.OrdinalIgnoreCase));
|
var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, liveTvItem.ServiceName, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (service != null)
|
if (service != null && !item.HasImage(ImageType.Primary))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -625,7 +625,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||||
|
|
||||||
_logger.Debug("Getting programs for channel {0}-{1} from {2}-{3}", channel.Number, channel.Name, provider.Item1.Name, provider.Item2.ListingsId ?? string.Empty);
|
_logger.Debug("Getting programs for channel {0}-{1} from {2}-{3}", channel.Number, channel.Name, provider.Item1.Name, provider.Item2.ListingsId ?? string.Empty);
|
||||||
|
|
||||||
var programs = await provider.Item1.GetProgramsAsync(provider.Item2, channel.Number, channel.Name, startDateUtc, endDateUtc, cancellationToken)
|
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);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var list = programs.ToList();
|
var list = programs.ToList();
|
||||||
|
@ -647,6 +656,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||||
return new List<ProgramInfo>();
|
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()
|
private List<Tuple<IListingsProvider, ListingsProviderInfo>> GetListingProviders()
|
||||||
{
|
{
|
||||||
return GetConfiguration().ListingProviders
|
return GetConfiguration().ListingProviders
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
using MediaBrowser.Controller.LiveTv;
|
|
||||||
using MediaBrowser.Model.Dto;
|
|
||||||
using MediaBrowser.Model.LiveTv;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
|
||||||
{
|
|
||||||
public class XmlTv : IListingsProvider
|
|
||||||
{
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get { return "XmlTV"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Type
|
|
||||||
{
|
|
||||||
get { return "xmltv"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
// Might not be needed
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings)
|
|
||||||
{
|
|
||||||
// Check that the path or url is valid. If not, throw a file not found exception
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location)
|
|
||||||
{
|
|
||||||
// In theory this should never be called because there is always only one lineup
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
using MediaBrowser.Controller.LiveTv;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Emby.XmlTv.Classes;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
||||||
|
{
|
||||||
|
public class XmlTvListingsProvider : IListingsProvider
|
||||||
|
{
|
||||||
|
private readonly IServerConfigurationManager _config;
|
||||||
|
|
||||||
|
public XmlTvListingsProvider(IServerConfigurationManager config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "XmlTV"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Type
|
||||||
|
{
|
||||||
|
get { return "xmltv"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetLanguage()
|
||||||
|
{
|
||||||
|
return _config.Configuration.PreferredMetadataLanguage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Should this method be async?
|
||||||
|
public Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var reader = new XmlTvReader(info.Path, GetLanguage(), null);
|
||||||
|
string mappedChannel = channelNumber;
|
||||||
|
|
||||||
|
var results = reader.GetProgrammes(mappedChannel, startDateUtc, endDateUtc, cancellationToken);
|
||||||
|
return Task.FromResult(results.Select(p => new ProgramInfo()
|
||||||
|
{
|
||||||
|
ChannelId = p.ChannelId,
|
||||||
|
EndDate = 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 = 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.IsSeries,
|
||||||
|
IsRepeat = p.IsRepeat,
|
||||||
|
// IsPremiere = !p.PreviouslyShown.HasValue,
|
||||||
|
IsKids = p.Categories.Any(info.KidsCategories.Contains),
|
||||||
|
IsMovie = p.Categories.Any(info.MovieCategories.Contains),
|
||||||
|
IsNews = p.Categories.Any(info.NewsCategories.Contains),
|
||||||
|
IsSports = p.Categories.Any(info.SportsCategories.Contains),
|
||||||
|
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
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// Add the channel image url
|
||||||
|
var reader = new XmlTvReader(info.Path, GetLanguage(), null);
|
||||||
|
var results = reader.GetChannels().ToList();
|
||||||
|
|
||||||
|
if (channels != null && channels.Count > 0)
|
||||||
|
{
|
||||||
|
channels.ForEach(c => {
|
||||||
|
var match = results.FirstOrDefault(r => r.Id == c.Id);
|
||||||
|
if (match != null && match.Icon != null && !String.IsNullOrEmpty(match.Icon.Source))
|
||||||
|
{
|
||||||
|
c.ImageUrl = match.Icon.Source;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings)
|
||||||
|
{
|
||||||
|
// Check that the path or url is valid. If not, throw a file not found exception
|
||||||
|
if (!File.Exists(info.Path))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("Could not find the XmlTv file specified:", info.Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public 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 reader = new XmlTvReader(info.Path, GetLanguage(), null);
|
||||||
|
var results = reader.GetChannels();
|
||||||
|
|
||||||
|
// Should this method be async?
|
||||||
|
return Task.FromResult(results.Select(c => new NameIdPair() { Id = c.Id, Name = c.DisplayName }).ToList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -233,7 +233,7 @@
|
||||||
<Compile Include="LiveTv\EmbyTV\SeriesTimerManager.cs" />
|
<Compile Include="LiveTv\EmbyTV\SeriesTimerManager.cs" />
|
||||||
<Compile Include="LiveTv\EmbyTV\TimerManager.cs" />
|
<Compile Include="LiveTv\EmbyTV\TimerManager.cs" />
|
||||||
<Compile Include="LiveTv\Listings\SchedulesDirect.cs" />
|
<Compile Include="LiveTv\Listings\SchedulesDirect.cs" />
|
||||||
<Compile Include="LiveTv\Listings\XmlTv.cs" />
|
<Compile Include="LiveTv\Listings\XmlTvListingsProvider.cs" />
|
||||||
<Compile Include="LiveTv\LiveTvConfigurationFactory.cs" />
|
<Compile Include="LiveTv\LiveTvConfigurationFactory.cs" />
|
||||||
<Compile Include="LiveTv\LiveTvDtoService.cs" />
|
<Compile Include="LiveTv\LiveTvDtoService.cs" />
|
||||||
<Compile Include="LiveTv\LiveTvManager.cs" />
|
<Compile Include="LiveTv\LiveTvManager.cs" />
|
||||||
|
|
|
@ -1451,7 +1451,7 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RevokeUserTokens(string userId)
|
public async Task RevokeUserTokens(string userId, string currentAccessToken)
|
||||||
{
|
{
|
||||||
var existing = _authRepo.Get(new AuthenticationInfoQuery
|
var existing = _authRepo.Get(new AuthenticationInfoQuery
|
||||||
{
|
{
|
||||||
|
@ -1461,7 +1461,10 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||||
|
|
||||||
foreach (var info in existing.Items)
|
foreach (var info in existing.Items)
|
||||||
{
|
{
|
||||||
await Logout(info.AccessToken).ConfigureAwait(false);
|
if (!string.Equals(currentAccessToken, info.AccessToken, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
await Logout(info.AccessToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@
|
||||||
<Compile Include="FFMpeg\FFmpegValidator.cs" />
|
<Compile Include="FFMpeg\FFmpegValidator.cs" />
|
||||||
<Compile Include="INativeApp.cs" />
|
<Compile Include="INativeApp.cs" />
|
||||||
<Compile Include="MbLinkShortcutHandler.cs" />
|
<Compile Include="MbLinkShortcutHandler.cs" />
|
||||||
|
<Compile Include="Migrations\CollectionGroupingMigration.cs" />
|
||||||
<Compile Include="Migrations\FolderViewSettingMigration.cs" />
|
<Compile Include="Migrations\FolderViewSettingMigration.cs" />
|
||||||
<Compile Include="Migrations\IVersionMigration.cs" />
|
<Compile Include="Migrations\IVersionMigration.cs" />
|
||||||
<Compile Include="Migrations\DbMigration.cs" />
|
<Compile Include="Migrations\DbMigration.cs" />
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Library;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Server.Startup.Common.Migrations
|
||||||
|
{
|
||||||
|
public class CollectionGroupingMigration : IVersionMigration
|
||||||
|
{
|
||||||
|
private readonly IServerConfigurationManager _config;
|
||||||
|
private readonly IUserManager _userManager;
|
||||||
|
|
||||||
|
public CollectionGroupingMigration(IServerConfigurationManager config, IUserManager userManager)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
_userManager = userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
var migrationKey = this.GetType().Name;
|
||||||
|
var migrationKeyList = _config.Configuration.Migrations.ToList();
|
||||||
|
|
||||||
|
if (!migrationKeyList.Contains(migrationKey))
|
||||||
|
{
|
||||||
|
if (_config.Configuration.IsStartupWizardCompleted)
|
||||||
|
{
|
||||||
|
if (_userManager.Users.Any(i => i.Configuration.GroupMoviesIntoBoxSets))
|
||||||
|
{
|
||||||
|
_config.Configuration.EnableGroupingIntoCollections = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
migrationKeyList.Add(migrationKey);
|
||||||
|
_config.Configuration.Migrations = migrationKeyList.ToArray();
|
||||||
|
_config.SaveConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -152,9 +152,6 @@
|
||||||
<Content Include="dashboard-ui\css\images\logo.png">
|
<Content Include="dashboard-ui\css\images\logo.png">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\css\polymer\paper-icon-button-light.css">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\devices\windowsphone\wp.css">
|
<Content Include="dashboard-ui\devices\windowsphone\wp.css">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user