Merge pull request #3034 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2017-11-21 17:15:36 -05:00 committed by GitHub
commit bfe88d5057
19 changed files with 113 additions and 97 deletions

View File

@ -321,6 +321,12 @@ namespace Emby.Dlna.PlayTo
AddItemFromId(Guid.Parse(id), items); AddItemFromId(Guid.Parse(id), items);
} }
var startIndex = command.StartIndex ?? 0;
if (startIndex > 0)
{
items = items.Skip(startIndex).ToList();
}
var playlist = new List<PlaylistItem>(); var playlist = new List<PlaylistItem>();
var isFirst = true; var isFirst = true;

View File

@ -59,9 +59,6 @@
<Compile Include="StripCollageBuilder.cs" /> <Compile Include="StripCollageBuilder.cs" />
<Compile Include="UnplayedCountIndicator.cs" /> <Compile Include="UnplayedCountIndicator.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="fonts\robotoregular.ttf" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="SkiaSharp, Version=1.58.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL"> <Reference Include="SkiaSharp, Version=1.58.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\SkiaSharp.1.58.1\lib\portable-net45+win8+wpa81+wp8\SkiaSharp.dll</HintPath> <HintPath>..\packages\SkiaSharp.1.58.1\lib\portable-net45+win8+wpa81+wp8\SkiaSharp.dll</HintPath>

View File

@ -15,7 +15,6 @@ namespace Emby.Drawing.Skia
{ {
public class PlayedIndicatorDrawer public class PlayedIndicatorDrawer
{ {
private const int FontSize = 42;
private const int OffsetFromTopRightCorner = 38; private const int OffsetFromTopRightCorner = 38;
private readonly IApplicationPaths _appPaths; private readonly IApplicationPaths _appPaths;
@ -44,50 +43,25 @@ namespace Emby.Drawing.Skia
{ {
paint.Color = new SKColor(255, 255, 255, 255); paint.Color = new SKColor(255, 255, 255, 255);
paint.Style = SKPaintStyle.Fill; paint.Style = SKPaintStyle.Fill;
paint.Typeface = SKTypeface.FromFile(await DownloadFont("webdings.ttf", "https://github.com/MediaBrowser/Emby.Resources/raw/master/fonts/webdings.ttf",
_appPaths, _iHttpClient, _fileSystem).ConfigureAwait(false)); paint.TextSize = 30;
paint.TextSize = FontSize;
paint.IsAntialias = true; paint.IsAntialias = true;
canvas.DrawText("a", (float)x-20, OffsetFromTopRightCorner + 12, paint); var text = "✔️";
var emojiChar = StringUtilities.GetUnicodeCharacterCode(text, SKTextEncoding.Utf32);
// or:
//var emojiChar = 0x1F680;
// ask the font manager for a font with that character
var fontManager = SKFontManager.Default;
var emojiTypeface = fontManager.MatchCharacter(emojiChar);
paint.Typeface = emojiTypeface;
canvas.DrawText(text, (float)x-20, OffsetFromTopRightCorner + 12, paint);
} }
} }
internal static string ExtractFont(string name, IApplicationPaths paths, IFileSystem fileSystem)
{
var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name);
if (fileSystem.FileExists(filePath))
{
return filePath;
}
var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name;
var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf");
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(tempPath));
using (var stream = typeof(PlayedIndicatorDrawer).GetTypeInfo().Assembly.GetManifestResourceStream(namespacePath))
{
using (var fileStream = fileSystem.GetFileStream(tempPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
{
stream.CopyTo(fileStream);
}
}
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
try
{
fileSystem.CopyFile(tempPath, filePath, false);
}
catch (IOException)
{
}
return tempPath;
}
internal static async Task<string> DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient, IFileSystem fileSystem) internal static async Task<string> DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient, IFileSystem fileSystem)
{ {
var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name); var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name);

View File

@ -40,7 +40,7 @@ namespace Emby.Drawing.Skia
{ {
paint.Color = new SKColor(255, 255, 255, 255); paint.Color = new SKColor(255, 255, 255, 255);
paint.Style = SKPaintStyle.Fill; paint.Style = SKPaintStyle.Fill;
paint.Typeface = SKTypeface.FromFile(PlayedIndicatorDrawer.ExtractFont("robotoregular.ttf", _appPaths, _fileSystem));
paint.TextSize = 24; paint.TextSize = 24;
paint.IsAntialias = true; paint.IsAntialias = true;

View File

@ -2317,12 +2317,17 @@ namespace Emby.Server.Implementations
} }
} }
public void LaunchUrl(string url) public virtual void LaunchUrl(string url)
{ {
if (EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows && if (EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows &&
EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.OSX) EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.OSX)
{ {
throw new NotImplementedException(); throw new NotSupportedException();
}
if (!Environment.UserInteractive)
{
throw new NotSupportedException();
} }
var process = ProcessFactory.Create(new ProcessOptions var process = ProcessFactory.Create(new ProcessOptions

View File

@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.Browser
{ {
appHost.LaunchUrl(url); appHost.LaunchUrl(url);
} }
catch (NotImplementedException) catch (NotSupportedException)
{ {
} }

View File

@ -3,6 +3,7 @@ using Emby.Server.Implementations.Browser;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Controller.Configuration;
namespace Emby.Server.Implementations.EntryPoints namespace Emby.Server.Implementations.EntryPoints
{ {
@ -20,15 +21,13 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary> /// </summary>
private readonly ILogger _logger; private readonly ILogger _logger;
/// <summary> private IServerConfigurationManager _config;
/// Initializes a new instance of the <see cref="StartupWizard" /> class.
/// </summary> public StartupWizard(IServerApplicationHost appHost, ILogger logger, IServerConfigurationManager config)
/// <param name="appHost">The app host.</param>
/// <param name="logger">The logger.</param>
public StartupWizard(IServerApplicationHost appHost, ILogger logger)
{ {
_appHost = appHost; _appHost = appHost;
_logger = logger; _logger = logger;
_config = config;
} }
/// <summary> /// <summary>
@ -37,18 +36,14 @@ namespace Emby.Server.Implementations.EntryPoints
public void Run() public void Run()
{ {
if (_appHost.IsFirstRun) if (_appHost.IsFirstRun)
{
LaunchStartupWizard();
}
}
/// <summary>
/// Launches the startup wizard.
/// </summary>
private void LaunchStartupWizard()
{ {
BrowserLauncher.OpenDashboardPage("wizardstart.html", _appHost); BrowserLauncher.OpenDashboardPage("wizardstart.html", _appHost);
} }
else if (_config.Configuration.IsStartupWizardCompleted)
{
BrowserLauncher.OpenDashboardPage("index.html", _appHost);
}
}
/// <summary> /// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

View File

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Globalization;
using Emby.Naming.Common; using Emby.Naming.Common;
using Emby.Naming.TV; using Emby.Naming.TV;
using MediaBrowser.Model.Logging;
namespace Emby.Server.Implementations.Library.Resolvers.TV namespace Emby.Server.Implementations.Library.Resolvers.TV
{ {
@ -21,16 +22,18 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
private readonly ILocalizationManager _localization; private readonly ILocalizationManager _localization;
private readonly ILogger _logger;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SeasonResolver"/> class. /// Initializes a new instance of the <see cref="SeasonResolver"/> class.
/// </summary> /// </summary>
/// <param name="config">The config.</param> /// <param name="config">The config.</param>
public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization) public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, ILogger logger)
{ {
_config = config; _config = config;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_localization = localization; _localization = localization;
_logger = logger;
} }
/// <summary> /// <summary>
@ -45,20 +48,40 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
var series = ((Series)args.Parent); var series = ((Series)args.Parent);
var path = args.Path;
var season = new Season var season = new Season
{ {
IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber, IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(path, true, true).SeasonNumber,
SeriesId = series.Id, SeriesId = series.Id,
SeriesName = series.Name SeriesName = series.Name
}; };
if (season.IndexNumber.HasValue) if (season.IndexNumber.HasValue)
{ {
var resolver = new Emby.Naming.TV.EpisodeResolver(namingOptions);
var episodeInfo = resolver.Resolve(path, true);
if (episodeInfo != null)
{
if (episodeInfo.EpisodeNumber.HasValue && episodeInfo.SeasonNumber.HasValue)
{
_logger.Info("Found folder underneath series with episode number: {0}. Season {1}. Episode {2}",
path,
episodeInfo.SeasonNumber.Value,
episodeInfo.EpisodeNumber.Value);
return null;
}
}
var seasonNumber = season.IndexNumber.Value; var seasonNumber = season.IndexNumber.Value;
season.Name = seasonNumber == 0 ? season.Name = seasonNumber == 0 ?
args.LibraryOptions.SeasonZeroDisplayName : args.LibraryOptions.SeasonZeroDisplayName :
string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture), args.GetLibraryOptions().PreferredMetadataLanguage); string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture), args.GetLibraryOptions().PreferredMetadataLanguage);
} }
return season; return season;

View File

@ -218,7 +218,7 @@ namespace Emby.Server.Implementations.Library
return builder.ToString(); return builder.ToString();
} }
public async Task<User> AuthenticateUser(string username, string password, string hashedPassword, string passwordMd5, string remoteEndPoint) public async Task<User> AuthenticateUser(string username, string password, string hashedPassword, string passwordMd5, string remoteEndPoint, bool isUserSession)
{ {
if (string.IsNullOrWhiteSpace(username)) if (string.IsNullOrWhiteSpace(username))
{ {
@ -287,9 +287,12 @@ namespace Emby.Server.Implementations.Library
// Update LastActivityDate and LastLoginDate, then save // Update LastActivityDate and LastLoginDate, then save
if (success) if (success)
{
if (isUserSession)
{ {
user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow; user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow;
UpdateUser(user); UpdateUser(user);
}
UpdateInvalidLoginAttemptCount(user, 0); UpdateInvalidLoginAttemptCount(user, 0);
} }
else else

View File

@ -1897,7 +1897,15 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
imageSaveFilenameWithoutExtension = "logo"; imageSaveFilenameWithoutExtension = "logo";
break; break;
case ImageType.Thumb: case ImageType.Thumb:
if (program.IsSeries)
{
imageSaveFilenameWithoutExtension = Path.GetFileNameWithoutExtension(recordingPath) + "-thumb";
}
else
{
imageSaveFilenameWithoutExtension = "landscape"; imageSaveFilenameWithoutExtension = "landscape";
}
break; break;
case ImageType.Backdrop: case ImageType.Backdrop:
imageSaveFilenameWithoutExtension = "fanart"; imageSaveFilenameWithoutExtension = "fanart";
@ -1921,9 +1929,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private async Task SaveRecordingImages(string recordingPath, LiveTvProgram program) private async Task SaveRecordingImages(string recordingPath, LiveTvProgram program)
{ {
var image = program.GetImageInfo(ImageType.Primary, 0); var image = program.IsSeries ?
(program.GetImageInfo(ImageType.Thumb, 0) ?? program.GetImageInfo(ImageType.Primary, 0)) :
(program.GetImageInfo(ImageType.Primary, 0) ?? program.GetImageInfo(ImageType.Thumb, 0));
if (image != null && program.IsMovie) if (image != null)
{ {
try try
{ {

View File

@ -152,6 +152,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
isRemote = !_networkManager.IsInLocalNetwork(uri.Host); isRemote = !_networkManager.IsInLocalNetwork(uri.Host);
} }
var supportsDirectPlay = !info.EnableStreamLooping && info.TunerCount == 0;
var mediaSource = new MediaSourceInfo var mediaSource = new MediaSourceInfo
{ {
Path = path, Path = path,
@ -183,7 +185,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
IsInfiniteStream = true, IsInfiniteStream = true,
IsRemote = isRemote, IsRemote = isRemote,
IgnoreDts = true IgnoreDts = true,
SupportsDirectPlay = supportsDirectPlay
}; };
mediaSource.InferTotalBitrate(); mediaSource.InferTotalBitrate();

View File

@ -88,6 +88,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
SetTempFilePath(extension); SetTempFilePath(extension);
var taskCompletionSource = new TaskCompletionSource<bool>(); var taskCompletionSource = new TaskCompletionSource<bool>();
var now = DateTime.UtcNow;
StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token);
//OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.Protocol = MediaProtocol.File;
@ -97,11 +100,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
OpenedMediaSource.Protocol = MediaProtocol.Http; OpenedMediaSource.Protocol = MediaProtocol.Http;
if (OpenedMediaSource.SupportsProbing)
{
await Task.Delay(3000).ConfigureAwait(false);
}
//OpenedMediaSource.Path = TempFilePath; //OpenedMediaSource.Path = TempFilePath;
//OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.Protocol = MediaProtocol.File;
@ -111,6 +109,20 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
//OpenedMediaSource.SupportsDirectStream = true; //OpenedMediaSource.SupportsDirectStream = true;
//OpenedMediaSource.SupportsTranscoding = true; //OpenedMediaSource.SupportsTranscoding = true;
await taskCompletionSource.Task.ConfigureAwait(false); await taskCompletionSource.Task.ConfigureAwait(false);
if (OpenedMediaSource.SupportsProbing)
{
var elapsed = (DateTime.UtcNow - now).TotalMilliseconds;
var delay = Convert.ToInt32(3000 - elapsed);
if (delay > 0)
{
Logger.Info("Delaying shared stream by {0}ms to allow the buffer to build.", delay);
await Task.Delay(delay).ConfigureAwait(false);
}
}
} }
protected override void CloseInternal() protected override void CloseInternal()

View File

@ -117,6 +117,10 @@ namespace Emby.Server.Implementations.Session
{ {
dict["SubtitleStreamIndex"] = command.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture); dict["SubtitleStreamIndex"] = command.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture);
} }
if (command.StartIndex.HasValue)
{
dict["StartIndex"] = command.StartIndex.Value.ToString(CultureInfo.InvariantCulture);
}
if (!string.IsNullOrWhiteSpace(command.MediaSourceId)) if (!string.IsNullOrWhiteSpace(command.MediaSourceId))
{ {
dict["MediaSourceId"] = command.MediaSourceId; dict["MediaSourceId"] = command.MediaSourceId;

View File

@ -1423,7 +1423,7 @@ namespace Emby.Server.Implementations.Session
if (enforcePassword) if (enforcePassword)
{ {
var result = await _userManager.AuthenticateUser(request.Username, request.Password, request.PasswordSha1, request.PasswordMd5, request.RemoteEndPoint).ConfigureAwait(false); var result = await _userManager.AuthenticateUser(request.Username, request.Password, request.PasswordSha1, request.PasswordMd5, request.RemoteEndPoint, true).ConfigureAwait(false);
if (result == null) if (result == null)
{ {

View File

@ -473,7 +473,7 @@ namespace MediaBrowser.Api
} }
else else
{ {
var success = await _userManager.AuthenticateUser(user.Name, request.CurrentPw, request.CurrentPassword, null, Request.RemoteIp).ConfigureAwait(false); var success = await _userManager.AuthenticateUser(user.Name, request.CurrentPw, request.CurrentPassword, null, Request.RemoteIp, false).ConfigureAwait(false);
if (success == null) if (success == null)
{ {

View File

@ -215,23 +215,6 @@ namespace MediaBrowser.Controller.Entities.TV
return list; return list;
} }
[IgnoreDataMember]
public bool ContainsEpisodesWithoutSeasonFolders
{
get
{
var children = Children;
foreach (var child in children)
{
if (child is Video)
{
return true;
}
}
return false;
}
}
public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren) public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{ {
return GetSeasons(user, new DtoOptions(true)); return GetSeasons(user, new DtoOptions(true));

View File

@ -143,7 +143,7 @@ namespace MediaBrowser.Controller.Library
/// <summary> /// <summary>
/// Authenticates the user. /// Authenticates the user.
/// </summary> /// </summary>
Task<User> AuthenticateUser(string username, string password, string passwordSha1, string passwordMd5, string remoteEndPoint); Task<User> AuthenticateUser(string username, string password, string passwordSha1, string passwordMd5, string remoteEndPoint, bool isUserSession);
/// <summary> /// <summary>
/// Starts the forgot password process. /// Starts the forgot password process.

View File

@ -37,5 +37,6 @@ namespace MediaBrowser.Model.Session
public int? SubtitleStreamIndex { get; set; } public int? SubtitleStreamIndex { get; set; }
public int? AudioStreamIndex { get; set; } public int? AudioStreamIndex { get; set; }
public string MediaSourceId { get; set; } public string MediaSourceId { get; set; }
public int? StartIndex { get; set; }
} }
} }

View File

@ -1,3 +1,3 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("3.2.40.0")] [assembly: AssemblyVersion("3.2.40.1")]