update live tv image

This commit is contained in:
Luke Pulverenti 2015-08-28 00:19:08 -04:00
parent 64945eb171
commit a0c3bb0380
23 changed files with 262 additions and 81 deletions

View File

@ -54,6 +54,11 @@ namespace MediaBrowser.Api.Music
public string Id { get; set; } public string Id { get; set; }
} }
[Route("/Items/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given item")]
public class GetInstantMixFromItem : BaseGetSimilarItemsFromItem
{
}
[Authenticated] [Authenticated]
public class InstantMixService : BaseApiService public class InstantMixService : BaseApiService
{ {
@ -71,6 +76,17 @@ namespace MediaBrowser.Api.Music
_libraryManager = libraryManager; _libraryManager = libraryManager;
} }
public object Get(GetInstantMixFromItem request)
{
var item = _libraryManager.GetItemById(request.Id);
var user = _userManager.GetUserById(request.UserId);
var items = _musicManager.GetInstantMixFromItem(item, user);
return GetResult(items, user, request);
}
public object Get(GetInstantMixFromArtistId request) public object Get(GetInstantMixFromArtistId request)
{ {
var item = _libraryManager.GetItemById(request.Id); var item = _libraryManager.GetItemById(request.Id);

View File

@ -1,5 +1,4 @@
using System.Linq; using MediaBrowser.Common.IO;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
@ -317,6 +316,7 @@ namespace MediaBrowser.Api.Playback.Hls
{ {
if (videoStream.KeyFrames == null || videoStream.KeyFrames.Count == 0) if (videoStream.KeyFrames == null || videoStream.KeyFrames.Count == 0)
{ {
Logger.Debug("Cannot stream copy video due to missing keyframe info");
return false; return false;
} }
@ -326,8 +326,9 @@ namespace MediaBrowser.Api.Playback.Hls
var length = frame - previousSegment; var length = frame - previousSegment;
// Don't allow really long segments because this could result in long download times // Don't allow really long segments because this could result in long download times
if (length > 10000) if (length > 12000)
{ {
Logger.Debug("Cannot stream copy video due to long segment length of {0}ms", length);
return false; return false;
} }
previousSegment = frame; previousSegment = frame;

View File

@ -419,6 +419,10 @@ namespace MediaBrowser.Controller.Entities
return _sortName ?? (_sortName = CreateSortName()); return _sortName ?? (_sortName = CreateSortName());
} }
set
{
_sortName = value;
}
} }
public string GetInternalMetadataPath() public string GetInternalMetadataPath()

View File

@ -97,6 +97,7 @@ namespace MediaBrowser.Controller.Entities
public int? MaxParentalRating { get; set; } public int? MaxParentalRating { get; set; }
public bool? IsCurrentSchema { get; set; } public bool? IsCurrentSchema { get; set; }
public bool? HasDeadParentId { get; set; }
public InternalItemsQuery() public InternalItemsQuery()
{ {

View File

@ -244,7 +244,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{ {
foreach (var stream in mediaInfo.MediaStreams) foreach (var stream in mediaInfo.MediaStreams)
{ {
if (stream.Type == MediaStreamType.Video && string.Equals(stream.Codec, "h264", StringComparison.OrdinalIgnoreCase)) if (stream.Type == MediaStreamType.Video && string.Equals(stream.Codec, "h264", StringComparison.OrdinalIgnoreCase) && !stream.IsInterlaced)
{ {
try try
{ {
@ -282,7 +282,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
private async Task<List<int>> GetKeyFrames(string inputPath, int videoStreamIndex, CancellationToken cancellationToken) private async Task<List<int>> GetKeyFrames(string inputPath, int videoStreamIndex, CancellationToken cancellationToken)
{ {
const string args = "-i {0} -select_streams v:{1} -show_packets -print_format compact -show_entries packet=flags -show_entries packet=pts_time"; inputPath = inputPath.Split(new[] { ':' }, 2).Last().Trim('"');
const string args = "-show_packets -print_format compact -select_streams v:{1} -show_entries packet=flags -show_entries packet=pts_time \"{0}\"";
var process = new Process var process = new Process
{ {
@ -330,7 +332,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{ {
StopProcess(processWrapper, 100, true); StopProcess(processWrapper, 100, true);
} }
//_logger.Debug("Found keyframes {0}", string.Join(",", lines.ToArray()));
return lines; return lines;
} }
} }
@ -347,7 +349,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
var line = await reader.ReadLineAsync().ConfigureAwait(false); var line = await reader.ReadLineAsync().ConfigureAwait(false);
var values = (line ?? string.Empty).Split('|') if (string.IsNullOrWhiteSpace(line))
{
continue;
}
var values = line.Split('|')
.Where(i => !string.IsNullOrWhiteSpace(i)) .Where(i => !string.IsNullOrWhiteSpace(i))
.Select(i => i.Split('=')) .Select(i => i.Split('='))
.Where(i => i.Length == 2) .Where(i => i.Length == 2)

View File

@ -320,32 +320,11 @@ namespace MediaBrowser.Model.ApiClient
Task<ItemsResult> GetUserViews(string userId, CancellationToken cancellationToken = default(CancellationToken)); Task<ItemsResult> GetUserViews(string userId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary> /// <summary>
/// Gets the instant mix from song async. /// Gets the instant mix from item asynchronous.
/// </summary> /// </summary>
/// <param name="query">The query.</param> /// <param name="query">The query.</param>
/// <returns>Task{ItemsResult}.</returns> /// <returns>Task&lt;ItemsResult&gt;.</returns>
Task<ItemsResult> GetInstantMixFromSongAsync(SimilarItemsQuery query); Task<ItemsResult> GetInstantMixFromItemAsync(SimilarItemsQuery query);
/// <summary>
/// Gets the instant mix from album async.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>Task{ItemsResult}.</returns>
Task<ItemsResult> GetInstantMixFromAlbumAsync(SimilarItemsQuery query);
/// <summary>
/// Gets the instant mix from artist async.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>Task{ItemsResult}.</returns>
Task<ItemsResult> GetInstantMixFromArtistAsync(SimilarItemsQuery query);
/// <summary>
/// Gets the instant mix from music genre async.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>Task{ItemsResult}.</returns>
Task<ItemsResult> GetInstantMixFromMusicGenreAsync(SimilarItemsQuery query);
/// <summary> /// <summary>
/// Gets the similar movies async. /// Gets the similar movies async.

View File

@ -0,0 +1,147 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using MediaBrowser.Providers.Genres;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.Folders
{
public class DefaultImageProvider : IRemoteImageProvider, IHasItemChangeMonitor
{
private readonly IHttpClient _httpClient;
public DefaultImageProvider(IHttpClient httpClient)
{
_httpClient = httpClient;
}
public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
return new List<ImageType>
{
ImageType.Primary,
ImageType.Thumb
};
}
public Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
{
var view = item as UserView;
if (view != null)
{
return GetImages(view.ViewType, cancellationToken);
}
var folder = (ICollectionFolder)item;
return GetImages(folder.CollectionType, cancellationToken);
}
private Task<IEnumerable<RemoteImageInfo>> GetImages(string viewType, CancellationToken cancellationToken)
{
var url = GetImageUrl(viewType);
var list = new List<RemoteImageInfo>();
if (!string.IsNullOrWhiteSpace(url))
{
list.AddRange(new List<RemoteImageInfo>{
new RemoteImageInfo
{
ProviderName = Name,
Url = url,
Type = ImageType.Primary
},
new RemoteImageInfo
{
ProviderName = Name,
Url = url,
Type = ImageType.Thumb
}
});
}
return Task.FromResult<IEnumerable<RemoteImageInfo>>(list);
}
private string GetImageUrl(string viewType)
{
const string urlPrefix = "https://raw.githubusercontent.com/MediaBrowser/Emby.Resources/master/images/folders/";
if (string.Equals(viewType, CollectionType.Books, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "books.png";
}
if (string.Equals(viewType, CollectionType.Games, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "games.png";
}
if (string.Equals(viewType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "music.png";
}
if (string.Equals(viewType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "photos.png";
}
if (string.Equals(viewType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "tv.png";
}
if (string.Equals(viewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "channels.png";
}
if (string.Equals(viewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
{
return urlPrefix + "livetv.png";
}
if (string.Equals(viewType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
{
//return urlPrefix + "movies.png";
}
return null;
//return urlPrefix + "generic.png";
}
public string Name
{
get { return "Default Image Provider"; }
}
public bool Supports(IHasImages item)
{
var view = item as UserView;
if (view != null)
{
return !view.UserId.HasValue;
}
return item is ICollectionFolder;
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
Url = url,
ResourcePool = GenreImageProvider.ImageDownloadResourcePool
});
}
public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService)
{
return GetSupportedImages(item).Any(i => !item.HasImage(i));
}
}
}

View File

@ -83,6 +83,7 @@
<Compile Include="BoxSets\MovieDbBoxSetProvider.cs" /> <Compile Include="BoxSets\MovieDbBoxSetProvider.cs" />
<Compile Include="Channels\ChannelMetadataService.cs" /> <Compile Include="Channels\ChannelMetadataService.cs" />
<Compile Include="Chapters\ChapterManager.cs" /> <Compile Include="Chapters\ChapterManager.cs" />
<Compile Include="Folders\DefaultImageProvider.cs" />
<Compile Include="Folders\FolderMetadataService.cs" /> <Compile Include="Folders\FolderMetadataService.cs" />
<Compile Include="Channels\AudioChannelItemMetadataService.cs" /> <Compile Include="Channels\AudioChannelItemMetadataService.cs" />
<Compile Include="Folders\UserViewMetadataService.cs" /> <Compile Include="Folders\UserViewMetadataService.cs" />

View File

@ -41,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Connect
_timer = new Timer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(3)); _timer = new Timer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(3));
} }
private readonly string[] _ipLookups = { "http://bot.whatismyipaddress.com", "https://connect.mediabrowser.tv/service/ip" }; private readonly string[] _ipLookups = { "http://bot.whatismyipaddress.com", "https://connect.emby.media/service/ip" };
private async void TimerCallback(object state) private async void TimerCallback(object state)
{ {

View File

@ -371,7 +371,7 @@ namespace MediaBrowser.Server.Implementations.Connect
private string GetConnectUrl(string handler) private string GetConnectUrl(string handler)
{ {
return "https://connect.mediabrowser.tv/service/" + handler; return "https://connect.emby.media/service/" + handler;
} }
public async Task<UserLinkResult> LinkUser(string userId, string connectUsername) public async Task<UserLinkResult> LinkUser(string userId, string connectUsername)

View File

@ -52,6 +52,18 @@ namespace MediaBrowser.Server.Implementations.Library
return GetInstantMixFromGenres(genres, user); return GetInstantMixFromGenres(genres, user);
} }
public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user)
{
var genres = item
.GetRecursiveChildren(user, i => i is Audio)
.Cast<Audio>()
.SelectMany(i => i.Genres)
.Concat(item.Genres)
.DistinctNames();
return GetInstantMixFromGenres(genres, user);
}
public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user) public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user)
{ {
var genres = item var genres = item
@ -114,6 +126,12 @@ namespace MediaBrowser.Server.Implementations.Library
return GetInstantMixFromSong(song, user); return GetInstantMixFromSong(song, user);
} }
var folder = item as Folder;
if (folder != null)
{
return GetInstantMixFromFolder(folder, user);
}
return new Audio[] { }; return new Audio[] { };
} }
} }

View File

@ -495,14 +495,6 @@
<Link>swagger-ui\swagger-ui.min.js</Link> <Link>swagger-ui\swagger-ui.min.js</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<EmbeddedResource Include="UserViews\livetv\1.jpg" />
<EmbeddedResource Include="UserViews\livetv\2.jpg" />
<EmbeddedResource Include="UserViews\livetv\3.jpg" />
<EmbeddedResource Include="UserViews\livetv\4.jpg" />
<EmbeddedResource Include="UserViews\livetv\5.jpg" />
<EmbeddedResource Include="UserViews\livetv\6.jpg" />
<EmbeddedResource Include="UserViews\livetv\7.jpg" />
<EmbeddedResource Include="UserViews\livetv\8.jpg" />
<EmbeddedResource Include="Localization\iso6392.txt" /> <EmbeddedResource Include="Localization\iso6392.txt" />
<EmbeddedResource Include="Localization\Ratings\be.txt" /> <EmbeddedResource Include="Localization\Ratings\be.txt" />
</ItemGroup> </ItemGroup>

View File

@ -46,9 +46,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{ {
var innerProgress = new ActionableProgress<double>(); var innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(progress.Report); innerProgress.RegisterAction(p => progress.Report(.95 * p));
await UpdateToLatestSchema(cancellationToken, innerProgress).ConfigureAwait(false); await UpdateToLatestSchema(cancellationToken, innerProgress).ConfigureAwait(false);
innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(p => progress.Report(95 + (.05 * p)));
//await CleanDeadItems(cancellationToken, innerProgress).ConfigureAwait(false);
progress.Report(100);
} }
private async Task UpdateToLatestSchema(CancellationToken cancellationToken, IProgress<double> progress) private async Task UpdateToLatestSchema(CancellationToken cancellationToken, IProgress<double> progress)
@ -92,6 +99,43 @@ namespace MediaBrowser.Server.Implementations.Persistence
progress.Report(100); 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.Debug("Cleaning item {0} type: {1} path: {2}", item.Name, item.GetType().Name, item.Path ?? string.Empty);
await _libraryManager.DeleteItem(item, new DeleteOptions
{
DeleteFileLocation = false
});
}
numComplete++;
double percent = numComplete;
percent /= numItems;
progress.Report(percent * 100);
}
progress.Report(100);
}
public IEnumerable<ITaskTrigger> GetDefaultTriggers() public IEnumerable<ITaskTrigger> GetDefaultTriggers()
{ {
return new ITaskTrigger[] return new ITaskTrigger[]

View File

@ -1096,6 +1096,14 @@ namespace MediaBrowser.Server.Implementations.Persistence
} }
} }
if (query.HasDeadParentId.HasValue)
{
if (query.HasDeadParentId.Value)
{
whereClauses.Add("ParentId NOT NULL AND ParentId NOT IN (select guid from TypedBaseItems)");
}
}
if (addPaging) if (addPaging)
{ {
if (query.StartIndex.HasValue && query.StartIndex.Value > 0) if (query.StartIndex.HasValue && query.StartIndex.Value > 0)

View File

@ -11,8 +11,6 @@ using MediaBrowser.Server.Implementations.Photos;
using MoreLinq; using MoreLinq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -154,7 +152,6 @@ namespace MediaBrowser.Server.Implementations.UserViews
CollectionType.BoxSets, CollectionType.BoxSets,
CollectionType.Playlists, CollectionType.Playlists,
CollectionType.Channels, CollectionType.Channels,
CollectionType.LiveTv,
CollectionType.Books, CollectionType.Books,
CollectionType.Photos, CollectionType.Photos,
CollectionType.HomeVideos, CollectionType.HomeVideos,
@ -170,7 +167,7 @@ namespace MediaBrowser.Server.Implementations.UserViews
var view = (UserView)item; var view = (UserView)item;
if (imageType == ImageType.Primary && IsUsingCollectionStrip(view)) if (imageType == ImageType.Primary && IsUsingCollectionStrip(view))
{ {
if (itemsWithImages.Count == 0 && !string.Equals(view.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase)) if (itemsWithImages.Count == 0)
{ {
return false; return false;
} }
@ -180,39 +177,5 @@ namespace MediaBrowser.Server.Implementations.UserViews
return await base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex).ConfigureAwait(false); return await base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex).ConfigureAwait(false);
} }
protected override IEnumerable<String> GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable<BaseItem> items)
{
var userView = primaryItem as UserView;
if (userView != null && string.Equals(userView.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
{
var list = new List<string>();
for (int i = 1; i <= 8; i++)
{
list.Add(ExtractLiveTvResource(i.ToString(CultureInfo.InvariantCulture), ApplicationPaths));
}
return list;
}
return base.GetStripCollageImagePaths(primaryItem, items);
}
private string ExtractLiveTvResource(string name, IApplicationPaths paths)
{
var namespacePath = GetType().Namespace + ".livetv." + name + ".jpg";
var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".jpg");
Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
using (var stream = GetType().Assembly.GetManifestResourceStream(namespacePath))
{
using (var fileStream = new FileStream(tempPath, FileMode.Create, FileAccess.Write, FileShare.Read))
{
stream.CopyTo(fileStream);
}
}
return tempPath;
}
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB