Merge pull request #3 from MediaBrowser/master

Sync with Master
This commit is contained in:
7illusions 2014-05-12 16:55:07 +02:00
commit baf5cf2544
468 changed files with 16587 additions and 4034 deletions

View file

@ -71,8 +71,7 @@ namespace MediaBrowser.Api
/// </summary>
private void DeleteEncodedMediaCache()
{
foreach (var file in Directory.EnumerateFiles(_appPaths.TranscodingTempPath)
.Where(i => EntityResolutionHelper.VideoFileExtensions.Contains(Path.GetExtension(i)))
foreach (var file in Directory.EnumerateFiles(_appPaths.TranscodingTempPath, "*", SearchOption.AllDirectories)
.ToList())
{
File.Delete(file);
@ -116,11 +115,10 @@ namespace MediaBrowser.Api
/// <param name="path">The path.</param>
/// <param name="type">The type.</param>
/// <param name="process">The process.</param>
/// <param name="isVideo">if set to <c>true</c> [is video].</param>
/// <param name="startTimeTicks">The start time ticks.</param>
/// <param name="sourcePath">The source path.</param>
/// <param name="deviceId">The device id.</param>
public void OnTranscodeBeginning(string path, TranscodingJobType type, Process process, bool isVideo, long? startTimeTicks, string sourcePath, string deviceId)
public void OnTranscodeBeginning(string path, TranscodingJobType type, Process process, long? startTimeTicks, string sourcePath, string deviceId)
{
lock (_activeTranscodingJobs)
{
@ -130,7 +128,6 @@ namespace MediaBrowser.Api
Path = path,
Process = process,
ActiveRequestCount = 1,
IsVideo = isVideo,
StartTimeTicks = startTimeTicks,
SourcePath = sourcePath,
DeviceId = deviceId
@ -261,7 +258,7 @@ namespace MediaBrowser.Api
{
// This is really only needed for HLS.
// Progressive streams can stop on their own reliably
jobs.AddRange(_activeTranscodingJobs.Where(i => isVideo == i.IsVideo && string.Equals(deviceId, i.DeviceId, StringComparison.OrdinalIgnoreCase)));
jobs.AddRange(_activeTranscodingJobs.Where(i => string.Equals(deviceId, i.DeviceId, StringComparison.OrdinalIgnoreCase)));
}
foreach (var job in jobs)
@ -325,37 +322,15 @@ namespace MediaBrowser.Api
}
}
// Determine if it exited successfully
var hasExitedSuccessfully = false;
try
{
hasExitedSuccessfully = process.ExitCode == 0;
}
catch (InvalidOperationException)
{
}
catch (NotSupportedException)
{
}
// Dispose the process
process.Dispose();
// If it didn't complete successfully cleanup the partial files
// Also don't cache output from resume points
// Also don't cache video
if (!hasExitedSuccessfully || job.StartTimeTicks.HasValue || job.IsVideo)
{
DeletePartialStreamFiles(job.Path, job.Type, 0, 1500);
}
DeletePartialStreamFiles(job.Path, job.Type, 0, 1500);
}
private async void DeletePartialStreamFiles(string path, TranscodingJobType jobType, int retryCount, int delayMs)
{
if (retryCount >= 5)
if (retryCount >= 10)
{
return;
}
@ -455,7 +430,6 @@ namespace MediaBrowser.Api
/// <value>The kill timer.</value>
public Timer KillTimer { get; set; }
public bool IsVideo { get; set; }
public long? StartTimeTicks { get; set; }
public string SourcePath { get; set; }
public string DeviceId { get; set; }

View file

@ -67,7 +67,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public SortOrder? SortOrder { get; set; }
[ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsRecentlyAdded, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
[ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Filters { get; set; }
[ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]

View file

@ -24,6 +24,8 @@ namespace MediaBrowser.Api.DefaultTheme
[ApiMember(Name = "RecentlyPlayedGamesLimit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int RecentlyPlayedGamesLimit { get; set; }
public string ParentId { get; set; }
}
[Route("/MBT/DefaultTheme/TV", "GET")]
@ -49,6 +51,8 @@ namespace MediaBrowser.Api.DefaultTheme
[ApiMember(Name = "LatestEpisodeLimit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int LatestEpisodeLimit { get; set; }
public string ParentId { get; set; }
}
[Route("/MBT/DefaultTheme/Movies", "GET")]
@ -71,6 +75,8 @@ namespace MediaBrowser.Api.DefaultTheme
[ApiMember(Name = "LatestTrailersLimit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int LatestTrailersLimit { get; set; }
public string ParentId { get; set; }
}
[Route("/MBT/DefaultTheme/Favorites", "GET")]
@ -224,7 +230,7 @@ namespace MediaBrowser.Api.DefaultTheme
{
var user = _userManager.GetUserById(request.UserId);
var items = user.RootFolder.GetRecursiveChildren(user, i => i is Game || i is GameSystem)
var items = GetAllLibraryItems(user.Id, _userManager, _libraryManager, request.ParentId).Where(i => i is Game || i is GameSystem)
.ToList();
var gamesWithImages = items.OfType<Game>().Where(i => !string.IsNullOrEmpty(i.PrimaryImagePath)).ToList();
@ -280,7 +286,7 @@ namespace MediaBrowser.Api.DefaultTheme
var user = _userManager.GetUserById(request.UserId);
var series = user.RootFolder.GetRecursiveChildren(user)
var series = GetAllLibraryItems(user.Id, _userManager, _libraryManager, request.ParentId)
.OfType<Series>()
.ToList();
@ -403,7 +409,8 @@ namespace MediaBrowser.Api.DefaultTheme
{
var user = _userManager.GetUserById(request.UserId);
var items = user.RootFolder.GetRecursiveChildren(user, i => i is Movie || i is Trailer || i is BoxSet)
var items = GetAllLibraryItems(user.Id, _userManager, _libraryManager, request.ParentId)
.Where(i => i is Movie || i is Trailer || i is BoxSet)
.ToList();
var view = new MoviesView();
@ -556,7 +563,7 @@ namespace MediaBrowser.Api.DefaultTheme
// Avoid implicitly captured closure
var currentUserId1 = user.Id;
view.LatestMovies = movies
.OrderByDescending(i => i.DateCreated)
.Where(i => !_userDataManager.GetUserData(currentUserId1, i.GetUserDataKey()).Played)
@ -622,9 +629,9 @@ namespace MediaBrowser.Api.DefaultTheme
{
var tag = _imageProcessor.GetImageCacheTag(item, imageType);
if (tag.HasValue)
if (tag != null)
{
stub.ImageTag = tag.Value;
stub.ImageTag = tag;
}
}
catch (Exception ex)

View file

@ -9,7 +9,7 @@ namespace MediaBrowser.Api.DefaultTheme
{
public string Name { get; set; }
public string Id { get; set; }
public Guid ImageTag { get; set; }
public string ImageTag { get; set; }
public ImageType ImageType { get; set; }
}

View file

@ -1,5 +1,4 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Serialization;
using ServiceStack;
@ -77,14 +76,7 @@ namespace MediaBrowser.Api
/// <param name="request">The request.</param>
public object Get(GetDisplayPreferences request)
{
Guid displayPreferencesId;
if (!Guid.TryParse(request.Id, out displayPreferencesId))
{
displayPreferencesId = request.Id.GetMD5();
}
var result = _displayPreferencesManager.GetDisplayPreferences(displayPreferencesId, request.UserId, request.Client);
var result = _displayPreferencesManager.GetDisplayPreferences(request.Id, request.UserId, request.Client);
return ToOptimizedSerializedResultUsingCache(result);
}

View file

@ -1,8 +1,10 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -70,6 +72,32 @@ namespace MediaBrowser.Api.Images
public string Theme { get; set; }
}
[Route("/Images/MediaInfo", "GET")]
[Api(Description = "Gets all media info image by name")]
public class GetMediaInfoImages : IReturn<List<ImageByNameInfo>>
{
}
[Route("/Images/Ratings", "GET")]
[Api(Description = "Gets all rating images by name")]
public class GetRatingImages : IReturn<List<ImageByNameInfo>>
{
}
[Route("/Images/General", "GET")]
[Api(Description = "Gets all general images by name")]
public class GetGeneralImages : IReturn<List<ImageByNameInfo>>
{
}
public class ImageByNameInfo
{
public string Name { get; set; }
public string Theme { get; set; }
public long FileLength { get; set; }
public string Format { get; set; }
}
/// <summary>
/// Class ImageByNameService
/// </summary>
@ -89,6 +117,60 @@ namespace MediaBrowser.Api.Images
_appPaths = appPaths;
}
public object Get(GetMediaInfoImages request)
{
return ToOptimizedResult(GetImageList(_appPaths.MediaInfoImagesPath));
}
public object Get(GetRatingImages request)
{
return ToOptimizedResult(GetImageList(_appPaths.RatingsPath));
}
public object Get(GetGeneralImages request)
{
return ToOptimizedResult(GetImageList(_appPaths.GeneralPath));
}
private List<ImageByNameInfo> GetImageList(string path)
{
try
{
return new DirectoryInfo(path)
.GetFiles("*", SearchOption.AllDirectories)
.Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.Ordinal))
.Select(i => new ImageByNameInfo
{
Name = Path.GetFileNameWithoutExtension(i.FullName),
FileLength = i.Length,
Theme = GetThemeName(i.FullName, path),
Format = i.Extension.ToLower().TrimStart('.')
})
.OrderBy(i => i.Name)
.ToList();
}
catch (DirectoryNotFoundException)
{
return new List<ImageByNameInfo>();
}
}
private string GetThemeName(string path, string rootImagePath)
{
var parentName = Path.GetDirectoryName(path);
if (string.Equals(parentName, rootImagePath, StringComparison.OrdinalIgnoreCase))
{
return null;
}
parentName = Path.GetFileName(parentName);
return string.Equals(parentName, "all", StringComparison.OrdinalIgnoreCase) ?
null :
parentName;
}
/// <summary>
/// Gets the specified request.
/// </summary>
@ -118,7 +200,8 @@ namespace MediaBrowser.Api.Images
if (Directory.Exists(themeFolder))
{
var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(themeFolder, request.Name + i))
var path = BaseItem.SupportedImageExtensions
.Select(i => Path.Combine(themeFolder, request.Name + i))
.FirstOrDefault(File.Exists);
if (!string.IsNullOrEmpty(path))
@ -134,7 +217,8 @@ namespace MediaBrowser.Api.Images
// Avoid implicitly captured closure
var currentRequest = request;
var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, currentRequest.Name + i))
var path = BaseItem.SupportedImageExtensions
.Select(i => Path.Combine(allFolder, currentRequest.Name + i))
.FirstOrDefault(File.Exists);
if (!string.IsNullOrEmpty(path))
@ -175,7 +259,7 @@ namespace MediaBrowser.Api.Images
var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, currentRequest.Name + i))
.FirstOrDefault(File.Exists);
if (!string.IsNullOrEmpty(path))
{
return ToStaticFileResult(path);

View file

@ -1,5 +1,4 @@
using System.Globalization;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
@ -14,6 +13,7 @@ using ServiceStack.Text.Controller;
using ServiceStack.Web;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
@ -548,7 +548,7 @@ namespace MediaBrowser.Api.Images
var contentType = GetMimeType(request.Format, imageInfo.Path);
var cacheGuid = _imageProcessor.GetImageCacheTag(item, request.Type, imageInfo.Path, originalFileImageDateModified, supportedImageEnhancers);
var cacheGuid = new Guid(_imageProcessor.GetImageCacheTag(item, request.Type, imageInfo.Path, originalFileImageDateModified, supportedImageEnhancers));
TimeSpan? cacheDuration = null;

View file

@ -1,13 +1,13 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
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.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using ServiceStack;
@ -32,6 +32,16 @@ namespace MediaBrowser.Api
public string Id { get; set; }
}
[Route("/Items/{Id}/RemoteSearch/Subtitles/{Language}", "GET")]
public class SearchRemoteSubtitles : IReturn<List<RemoteSubtitleInfo>>
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
[ApiMember(Name = "Language", Description = "Language", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Language { get; set; }
}
[Route("/Items/RemoteSearch/Movie", "POST")]
[Api(Description = "Gets external id infos for an item")]
public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>>
@ -107,19 +117,28 @@ namespace MediaBrowser.Api
public class ItemLookupService : BaseApiService
{
private readonly IDtoService _dtoService;
private readonly IProviderManager _providerManager;
private readonly IServerApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem;
private readonly ILibraryManager _libraryManager;
private readonly ISubtitleManager _subtitleManager;
public ItemLookupService(IDtoService dtoService, IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem, ILibraryManager libraryManager)
public ItemLookupService(IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem, ILibraryManager libraryManager, ISubtitleManager subtitleManager)
{
_dtoService = dtoService;
_providerManager = providerManager;
_appPaths = appPaths;
_fileSystem = fileSystem;
_libraryManager = libraryManager;
_subtitleManager = subtitleManager;
}
public object Get(SearchRemoteSubtitles request)
{
var video = (Video)_libraryManager.GetItemById(request.Id);
var response = _subtitleManager.SearchSubtitles(video, request.Language, CancellationToken.None).Result;
return ToOptimizedResult(response);
}
public object Get(GetExternalIdInfos request)

View file

@ -67,14 +67,14 @@ namespace MediaBrowser.Api
{
var result = _localization.GetParentalRatings().ToList();
return ToOptimizedSerializedResultUsingCache(result);
return ToOptimizedResult(result);
}
public object Get(GetLocalizationOptions request)
{
var result = _localization.GetLocalizationOptions().ToList();
return ToOptimizedSerializedResultUsingCache(result);
return ToOptimizedResult(result);
}
/// <summary>
@ -86,7 +86,7 @@ namespace MediaBrowser.Api
{
var result = _localization.GetCountries().ToList();
return ToOptimizedSerializedResultUsingCache(result);
return ToOptimizedResult(result);
}
/// <summary>
@ -98,7 +98,7 @@ namespace MediaBrowser.Api
{
var result = _localization.GetCultures().ToList();
return ToOptimizedSerializedResultUsingCache(result);
return ToOptimizedResult(result);
}
}

View file

@ -112,7 +112,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", Description = "Installation Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
public Guid Id { get; set; }
public string Id { get; set; }
}
/// <summary>
@ -221,7 +221,7 @@ namespace MediaBrowser.Api
/// <param name="request">The request.</param>
public void Delete(CancelPackageInstallation request)
{
var info = _installationManager.CurrentInstallations.FirstOrDefault(i => i.Item1.Id == request.Id);
var info = _installationManager.CurrentInstallations.FirstOrDefault(i => string.Equals(i.Item1.Id, request.Id));
if (info != null)
{

View file

@ -542,7 +542,7 @@ namespace MediaBrowser.Api.Playback
var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture);
return isH264Output ?
string.Format("{3} -vf \"{0}scale=min(iw\\,{1}):trunc(ow/a/2)*2{2}\"", yadifParam, maxWidthParam, assSubtitleParam, copyTsParam) :
string.Format("{3} -vf \"{0}scale=min(iw\\,{1}):trunc(ow/dar/2)*2{2}\"", yadifParam, maxWidthParam, assSubtitleParam, copyTsParam) :
string.Format("{3} -vf \"{0}scale=min(iw\\,{1}):-1{2}\"", yadifParam, maxWidthParam, assSubtitleParam, copyTsParam);
}
@ -903,7 +903,7 @@ namespace MediaBrowser.Api.Playback
EnableRaisingEvents = true
};
ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath, TranscodingJobType, process, state.IsInputVideo, state.Request.StartTimeTicks, state.MediaPath, state.Request.DeviceId);
ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath, TranscodingJobType, process, state.Request.StartTimeTicks, state.MediaPath, state.Request.DeviceId);
var commandLineLogMessage = process.StartInfo.FileName + " " + process.StartInfo.Arguments;
Logger.Info(commandLineLogMessage);

View file

@ -273,9 +273,7 @@ namespace MediaBrowser.Api.Playback.Hls
const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsExternal &&
(state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 ||
state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1);
var hasGraphicalSubs = state.SubtitleStream != null && state.SubtitleStream.IsGraphicalSubtitleStream;
var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg;

View file

@ -168,9 +168,7 @@ namespace MediaBrowser.Api.Playback.Hls
" -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+1))" :
" -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsExternal &&
(state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 ||
state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1);
var hasGraphicalSubs = state.SubtitleStream != null && state.SubtitleStream.IsGraphicalSubtitleStream;
var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg;

View file

@ -131,24 +131,22 @@ namespace MediaBrowser.Api.Playback.Progressive
{
var args = "-vcodec " + codec;
if (state.EnableMpegtsM2TsMode)
{
args += " -mpegts_m2ts_mode 1";
}
// See if we can save come cpu cycles by avoiding encoding
if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
{
return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args;
}
if (state.EnableMpegtsM2TsMode)
{
args += " -mpegts_m2ts_mode 1";
}
const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
args += keyFrameArg;
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsExternal &&
(state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 ||
state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1);
var hasGraphicalSubs = state.SubtitleStream != null && state.SubtitleStream.IsGraphicalSubtitleStream;
var request = state.VideoRequest;

View file

@ -20,7 +20,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public Guid Id { get; set; }
public string Id { get; set; }
}
/// <summary>
@ -44,7 +44,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public Guid Id { get; set; }
public string Id { get; set; }
}
/// <summary>
@ -58,7 +58,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
public Guid Id { get; set; }
public string Id { get; set; }
}
/// <summary>
@ -72,7 +72,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// </summary>
/// <value>The task id.</value>
[ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public Guid Id { get; set; }
public string Id { get; set; }
}
/// <summary>
@ -145,7 +145,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <exception cref="MediaBrowser.Common.Extensions.ResourceNotFoundException">Task not found</exception>
public object Get(GetScheduledTask request)
{
var task = TaskManager.ScheduledTasks.FirstOrDefault(i => i.Id == request.Id);
var task = TaskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
if (task == null)
{
@ -164,7 +164,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <exception cref="MediaBrowser.Common.Extensions.ResourceNotFoundException">Task not found</exception>
public void Post(StartScheduledTask request)
{
var task = TaskManager.ScheduledTasks.FirstOrDefault(i => i.Id == request.Id);
var task = TaskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
if (task == null)
{
@ -181,7 +181,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <exception cref="MediaBrowser.Common.Extensions.ResourceNotFoundException">Task not found</exception>
public void Delete(StopScheduledTask request)
{
var task = TaskManager.ScheduledTasks.FirstOrDefault(i => i.Id == request.Id);
var task = TaskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
if (task == null)
{
@ -201,9 +201,9 @@ namespace MediaBrowser.Api.ScheduledTasks
// We need to parse this manually because we told service stack not to with IRequiresRequestStream
// https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
var pathInfo = PathInfo.Parse(Request.PathInfo);
var id = new Guid(pathInfo.GetArgumentValue<string>(1));
var id = pathInfo.GetArgumentValue<string>(1);
var task = TaskManager.ScheduledTasks.FirstOrDefault(i => i.Id == id);
var task = TaskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, id));
if (task == null)
{

View file

@ -1,5 +1,6 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Tasks;
using System.Collections.Generic;
@ -11,7 +12,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <summary>
/// Class ScheduledTasksWebSocketListener
/// </summary>
public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<TaskInfo>, object>
public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<TaskInfo>, WebSocketListenerState>
{
/// <summary>
/// Gets or sets the task manager.
@ -37,39 +38,47 @@ namespace MediaBrowser.Api.ScheduledTasks
: base(logger)
{
TaskManager = taskManager;
TaskManager.TaskExecuting += TaskManager_TaskExecuting;
TaskManager.TaskCompleted += TaskManager_TaskCompleted;
}
private bool _lastResponseHadTasksRunning = true;
void TaskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
{
SendData(true);
e.Task.TaskProgress -= Argument_TaskProgress;
}
void TaskManager_TaskExecuting(object sender, GenericEventArgs<IScheduledTaskWorker> e)
{
SendData(true);
e.Argument.TaskProgress += Argument_TaskProgress;
}
void Argument_TaskProgress(object sender, GenericEventArgs<double> e)
{
SendData(false);
}
/// <summary>
/// Gets the data to send.
/// </summary>
/// <param name="state">The state.</param>
/// <returns>Task{IEnumerable{TaskInfo}}.</returns>
protected override Task<IEnumerable<TaskInfo>> GetDataToSend(object state)
protected override Task<IEnumerable<TaskInfo>> GetDataToSend(WebSocketListenerState state)
{
var tasks = TaskManager.ScheduledTasks.ToList();
var anyRunning = tasks.Any(i => i.State != TaskState.Idle);
if (anyRunning)
{
_lastResponseHadTasksRunning = true;
}
else
{
if (!_lastResponseHadTasksRunning)
{
return Task.FromResult<IEnumerable<TaskInfo>>(null);
}
_lastResponseHadTasksRunning = false;
}
return Task.FromResult(tasks
return Task.FromResult(TaskManager.ScheduledTasks
.OrderBy(i => i.Name)
.Select(ScheduledTaskHelpers.GetTaskInfo)
.Where(i => !i.IsHidden));
}
protected override bool SendOnTimer
{
get
{
return false;
}
}
}
}

View file

@ -171,9 +171,9 @@ namespace MediaBrowser.Api
var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
if (primaryImageTag.HasValue)
if (primaryImageTag != null)
{
result.PrimaryImageTag = primaryImageTag.Value;
result.PrimaryImageTag = primaryImageTag;
}
SetThumbImageInfo(result, item);
@ -250,9 +250,9 @@ namespace MediaBrowser.Api
{
var tag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Thumb);
if (tag.HasValue)
if (tag != null)
{
hint.ThumbImageTag = tag.Value;
hint.ThumbImageTag = tag;
hint.ThumbImageItemId = itemWithImage.Id.ToString("N");
}
}
@ -271,9 +271,9 @@ namespace MediaBrowser.Api
{
var tag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Backdrop);
if (tag.HasValue)
if (tag != null)
{
hint.BackdropImageTag = tag.Value;
hint.BackdropImageTag = tag;
hint.BackdropImageItemId = itemWithImage.Id.ToString("N");
}
}

View file

@ -69,7 +69,7 @@ namespace MediaBrowser.Api.UserLibrary
/// Filters to apply to the results
/// </summary>
/// <value>The filters.</value>
[ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsRecentlyAdded, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
[ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Filters { get; set; }
/// <summary>

View file

@ -521,6 +521,9 @@ namespace MediaBrowser.Api.UserLibrary
case ItemFilter.IsNotFolder:
return items.Where(item => !item.IsFolder);
case ItemFilter.IsRecentlyAdded:
return items.Where(item => (DateTime.UtcNow - item.DateCreated).TotalDays <= 10);
}
return items;

View file

@ -1,5 +1,4 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@ -8,7 +7,6 @@ using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
using ServiceStack;
using System;

View file

@ -133,7 +133,7 @@ namespace MediaBrowser.Api.WebSocket
/// <summary>
/// Class LogFileWebSocketState
/// </summary>
public class LogFileWebSocketState
public class LogFileWebSocketState : WebSocketListenerState
{
/// <summary>
/// Gets or sets the last log file path.

View file

@ -11,7 +11,7 @@ namespace MediaBrowser.Api.WebSocket
/// <summary>
/// Class SessionInfoWebSocketListener
/// </summary>
class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfoDto>, object>
class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfoDto>, WebSocketListenerState>
{
/// <summary>
/// Gets the name.
@ -43,7 +43,7 @@ namespace MediaBrowser.Api.WebSocket
/// </summary>
/// <param name="state">The state.</param>
/// <returns>Task{SystemInfo}.</returns>
protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(object state)
protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(WebSocketListenerState state)
{
return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto));
}

View file

@ -9,7 +9,7 @@ namespace MediaBrowser.Api.WebSocket
/// <summary>
/// Class SystemInfoWebSocketListener
/// </summary>
public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener<SystemInfo, object>
public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener<SystemInfo, WebSocketListenerState>
{
/// <summary>
/// Gets the name.
@ -41,7 +41,7 @@ namespace MediaBrowser.Api.WebSocket
/// </summary>
/// <param name="state">The state.</param>
/// <returns>Task{SystemInfo}.</returns>
protected override Task<SystemInfo> GetDataToSend(object state)
protected override Task<SystemInfo> GetDataToSend(WebSocketListenerState state)
{
return Task.FromResult(_appHost.GetSystemInfo());
}

View file

@ -13,6 +13,7 @@ using MediaBrowser.Common.Progress;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Common.Security;
using MediaBrowser.Common.Updates;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;

View file

@ -114,9 +114,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
request.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;
request.CachePolicy = options.CachePolicy == Net.HttpRequestCachePolicy.None ?
new RequestCachePolicy(RequestCacheLevel.BypassCache) :
new RequestCachePolicy(RequestCacheLevel.Revalidate);
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
request.ConnectionGroupName = GetHostFromUrl(options.Url);
request.KeepAlive = true;
@ -124,6 +122,11 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
request.Pipelined = true;
request.Timeout = 20000;
if (!string.IsNullOrEmpty(options.Host))
{
request.Host = options.Host;
}
#if !__MonoCS__
// This is a hack to prevent KeepAlive from getting disabled internally by the HttpWebRequest
// May need to remove this for mono
@ -230,12 +233,15 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
var httpWebRequest = GetRequest(options, httpMethod, options.EnableHttpCompression);
if (!string.IsNullOrEmpty(options.RequestContent) || string.Equals(httpMethod, "post", StringComparison.OrdinalIgnoreCase))
if (options.RequestContentBytes != null ||
!string.IsNullOrEmpty(options.RequestContent) ||
string.Equals(httpMethod, "post", StringComparison.OrdinalIgnoreCase))
{
var content = options.RequestContent ?? string.Empty;
var bytes = Encoding.UTF8.GetBytes(content);
var bytes = options.RequestContentBytes ??
Encoding.UTF8.GetBytes(options.RequestContent ?? string.Empty);
httpWebRequest.ContentType = options.RequestContentType ?? "application/x-www-form-urlencoded";
httpWebRequest.ContentLength = bytes.Length;
httpWebRequest.GetRequestStream().Write(bytes, 0, bytes.Length);
}

View file

@ -95,11 +95,12 @@
<Compile Include="ScheduledTasks\Tasks\DeleteCacheFileTask.cs" />
<Compile Include="ScheduledTasks\Tasks\DeleteLogFileTask.cs" />
<Compile Include="ScheduledTasks\Tasks\PluginUpdateTask.cs" />
<Compile Include="ScheduledTasks\Tasks\ReloadLoggerTask.cs" />
<Compile Include="ScheduledTasks\Tasks\ReloadLoggerFileTask.cs" />
<Compile Include="ScheduledTasks\Tasks\SystemUpdateTask.cs" />
<Compile Include="Security\MBLicenseFile.cs" />
<Compile Include="Security\MBRegistration.cs" />
<Compile Include="Security\PluginSecurityManager.cs" />
<Compile Include="Security\RegRecord.cs" />
<Compile Include="Serialization\JsonSerializer.cs" />
<Compile Include="Serialization\XmlSerializer.cs" />
<Compile Include="Updates\InstallationManager.cs" />

View file

@ -1,6 +1,8 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Tasks;
@ -18,6 +20,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// </summary>
public class ScheduledTaskWorker : IScheduledTaskWorker
{
public event EventHandler<GenericEventArgs<double>> TaskProgress;
/// <summary>
/// Gets or sets the scheduled task.
/// </summary>
@ -269,22 +273,22 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <summary>
/// The _id
/// </summary>
private Guid? _id;
private string _id;
/// <summary>
/// Gets the unique id.
/// </summary>
/// <value>The unique id.</value>
public Guid Id
public string Id
{
get
{
if (!_id.HasValue)
if (_id == null)
{
_id = ScheduledTask.GetType().FullName.GetMD5();
_id = ScheduledTask.GetType().FullName.GetMD5().ToString("N");
}
return _id.Value;
return _id;
}
}
@ -344,13 +348,13 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
throw new InvalidOperationException("Cannot execute a Task that is already running");
}
var progress = new Progress<double>();
CurrentCancellationTokenSource = new CancellationTokenSource();
Logger.Info("Executing {0}", Name);
((TaskManager)TaskManager).OnTaskExecuting(ScheduledTask);
var progress = new Progress<double>();
((TaskManager)TaskManager).OnTaskExecuting(this);
progress.ProgressChanged += progress_ProgressChanged;
@ -412,6 +416,12 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
void progress_ProgressChanged(object sender, double e)
{
CurrentProgress = e;
EventHelper.FireEventIfNotNull(TaskProgress, this, new GenericEventArgs<double>
{
Argument = e
}, Logger);
}
/// <summary>
@ -464,7 +474,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <value>The history file path.</value>
private string GetHistoryFilePath()
{
return Path.Combine(GetScheduledTasksDataDirectory(), Id + ".js");
return Path.Combine(GetScheduledTasksDataDirectory(), new Guid(Id) + ".js");
}
/// <summary>
@ -473,7 +483,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <returns>System.String.</returns>
private string GetConfigurationFilePath()
{
return Path.Combine(GetScheduledTasksConfigurationDirectory(), Id + ".js");
return Path.Combine(GetScheduledTasksConfigurationDirectory(), new Guid(Id) + ".js");
}
/// <summary>
@ -546,7 +556,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
LastExecutionResult = result;
((TaskManager) TaskManager).OnTaskCompleted(ScheduledTask, result);
((TaskManager)TaskManager).OnTaskCompleted(this, result);
}
/// <summary>

View file

@ -1,6 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Tasks;
@ -16,8 +17,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// </summary>
public class TaskManager : ITaskManager
{
public event EventHandler<EventArgs> TaskExecuting;
public event EventHandler<GenericEventArgs<TaskResult>> TaskCompleted;
public event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting;
public event EventHandler<TaskCompletionEventArgs> TaskCompleted;
/// <summary>
/// Gets the list of Scheduled Tasks
@ -124,7 +125,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
// If it's idle just execute immediately
if (task.State == TaskState.Idle)
{
((ScheduledTaskWorker)task).Execute();
Execute(task);
return;
}
@ -148,7 +149,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
{
var myTasks = ScheduledTasks.ToList();
myTasks.AddRange(tasks.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger)));
var list = tasks.ToList();
myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger)));
ScheduledTasks = myTasks.ToArray();
}
@ -188,9 +190,13 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// Called when [task executing].
/// </summary>
/// <param name="task">The task.</param>
internal void OnTaskExecuting(IScheduledTask task)
internal void OnTaskExecuting(IScheduledTaskWorker task)
{
EventHelper.QueueEventIfNotNull(TaskExecuting, task, EventArgs.Empty, Logger);
EventHelper.QueueEventIfNotNull(TaskExecuting, this, new GenericEventArgs<IScheduledTaskWorker>
{
Argument = task
}, Logger);
}
/// <summary>
@ -198,9 +204,15 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// </summary>
/// <param name="task">The task.</param>
/// <param name="result">The result.</param>
internal void OnTaskCompleted(IScheduledTask task, TaskResult result)
internal void OnTaskCompleted(IScheduledTaskWorker task, TaskResult result)
{
EventHelper.QueueEventIfNotNull(TaskCompleted, task, new GenericEventArgs<TaskResult> { Argument = result }, Logger);
EventHelper.QueueEventIfNotNull(TaskCompleted, task, new TaskCompletionEventArgs
{
Result = result,
Task = task
}, Logger);
ExecuteQueuedTasks();
}
@ -218,7 +230,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
if (scheduledTask.State == TaskState.Idle)
{
((ScheduledTaskWorker)scheduledTask).Execute();
Execute(scheduledTask);
_taskQueue.Remove(type);
}

View file

@ -25,7 +25,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
/// </summary>
@ -74,9 +74,11 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
progress.Report(90);
minDateModified = DateTime.UtcNow.AddDays(-3);
try
{
DeleteCacheFilesFromDirectory(cancellationToken, ApplicationPaths.TempDirectory, DateTime.MaxValue, progress);
DeleteCacheFilesFromDirectory(cancellationToken, ApplicationPaths.TempDirectory, minDateModified, progress);
}
catch (DirectoryNotFoundException)
{

View file

@ -94,11 +94,4 @@ namespace MediaBrowser.Common.Implementations.Security
return new MBRegistrationRecord { IsRegistered = reg.registered, ExpirationDate = reg.expDate, RegChecked = true };
}
}
class RegRecord
{
public string featId { get; set; }
public bool registered { get; set; }
public DateTime expDate { get; set; }
}
}

View file

@ -0,0 +1,11 @@
using System;
namespace MediaBrowser.Common.Implementations.Security
{
class RegRecord
{
public string featId { get; set; }
public bool registered { get; set; }
public DateTime expDate { get; set; }
}
}

View file

@ -5,6 +5,7 @@ using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Progress;
using MediaBrowser.Common.Security;
using MediaBrowser.Common.Updates;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Updates;
@ -328,14 +329,14 @@ namespace MediaBrowser.Common.Implementations.Updates
if (withAutoUpdateEnabled)
{
plugins = plugins
.Where(p => p.Configuration.EnableAutoUpdate)
.Where(p => _config.CommonConfiguration.EnableAutoUpdate)
.ToList();
}
// Figure out what needs to be installed
var packages = plugins.Select(p =>
{
var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, p.Configuration.UpdateClass);
var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, _config.CommonConfiguration.SystemUpdateLevel);
return latestPluginInfo != null && latestPluginInfo.version != null && latestPluginInfo.version > p.Version ? latestPluginInfo : null;
@ -367,7 +368,7 @@ namespace MediaBrowser.Common.Implementations.Updates
var installationInfo = new InstallationInfo
{
Id = Guid.NewGuid(),
Id = Guid.NewGuid().ToString("N"),
Name = package.name,
AssemblyGuid = package.guid,
UpdateClass = package.classification,
@ -510,13 +511,14 @@ namespace MediaBrowser.Common.Implementations.Updates
cancellationToken.ThrowIfCancellationRequested();
// Validate with a checksum
if (package.checksum != Guid.Empty) // support for legacy uploads for now
var packageChecksum = string.IsNullOrWhiteSpace(package.checksum) ? Guid.Empty : new Guid(package.checksum);
if (packageChecksum != Guid.Empty) // support for legacy uploads for now
{
using (var crypto = new MD5CryptoServiceProvider())
using (var stream = new BufferedStream(File.OpenRead(tempFile), 100000))
{
var check = Guid.Parse(BitConverter.ToString(crypto.ComputeHash(stream)).Replace("-", String.Empty));
if (check != package.checksum)
if (check != packageChecksum)
{
throw new ApplicationException(string.Format("Download validation failed for {0}. Probably corrupted during transfer.", package.name));
}

View file

@ -1,5 +1,5 @@
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Updates;
using System;
using System.Collections.Generic;
@ -152,15 +152,4 @@ namespace MediaBrowser.Common
/// <returns>System.Object.</returns>
object CreateInstance(Type type);
}
public interface IDependencyContainer
{
void RegisterSingleInstance<T>(T obj, bool manageLifetime = true)
where T : class;
void RegisterSingleInstance<T>(Func<T> func)
where T : class;
void Register(Type typeInterface, Type typeImplementation);
}
}

View file

@ -0,0 +1,15 @@
using System;
namespace MediaBrowser.Common
{
public interface IDependencyContainer
{
void RegisterSingleInstance<T>(T obj, bool manageLifetime = true)
where T : class;
void RegisterSingleInstance<T>(Func<T> func)
where T : class;
void Register(Type typeInterface, Type typeImplementation);
}
}

View file

@ -59,8 +59,8 @@
<Compile Include="Constants\Constants.cs" />
<Compile Include="Events\EventHelper.cs" />
<Compile Include="Extensions\BaseExtensions.cs" />
<Compile Include="Events\GenericEventArgs.cs" />
<Compile Include="Extensions\ResourceNotFoundException.cs" />
<Compile Include="IDependencyContainer.cs" />
<Compile Include="IO\FileSystemRepository.cs" />
<Compile Include="IO\IFileSystem.cs" />
<Compile Include="IO\ProgressStream.cs" />
@ -79,9 +79,12 @@
<Compile Include="Net\IWebSocketServer.cs" />
<Compile Include="Net\MimeTypes.cs" />
<Compile Include="Net\WebSocketConnectEventArgs.cs" />
<Compile Include="Net\WebSocketMessageInfo.cs" />
<Compile Include="Plugins\IDependencyModule.cs" />
<Compile Include="Plugins\IPlugin.cs" />
<Compile Include="Progress\ActionableProgress.cs" />
<Compile Include="ScheduledTasks\IConfigurableScheduledTask.cs" />
<Compile Include="ScheduledTasks\IHasKey.cs" />
<Compile Include="ScheduledTasks\IScheduledTask.cs" />
<Compile Include="ScheduledTasks\IScheduledTaskWorker.cs" />
<Compile Include="ScheduledTasks\ITaskManager.cs" />
@ -99,6 +102,7 @@
<Compile Include="Security\ISecurityManager.cs" />
<Compile Include="Updates\IInstallationManager.cs" />
<Compile Include="Updates\InstallationEventArgs.cs" />
<Compile Include="Updates\InstallationFailedEventArgs.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />

View file

@ -15,7 +15,7 @@ namespace MediaBrowser.Common.Net
/// <typeparam name="TReturnDataType">The type of the T return data type.</typeparam>
/// <typeparam name="TStateType">The type of the T state type.</typeparam>
public abstract class BasePeriodicWebSocketListener<TReturnDataType, TStateType> : IWebSocketListener, IDisposable
where TStateType : class, new()
where TStateType : WebSocketListenerState, new()
where TReturnDataType : class
{
/// <summary>
@ -83,7 +83,15 @@ namespace MediaBrowser.Common.Net
}
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
protected virtual bool SendOnTimer
{
get
{
return true;
}
}
/// <summary>
/// Starts sending messages over a web socket
/// </summary>
@ -99,9 +107,15 @@ namespace MediaBrowser.Common.Net
Logger.Info("{1} Begin transmitting over websocket to {0}", message.Connection.RemoteEndPoint, GetType().Name);
var timer = new Timer(TimerCallback, message.Connection, Timeout.Infinite, Timeout.Infinite);
var timer = SendOnTimer ?
new Timer(TimerCallback, message.Connection, Timeout.Infinite, Timeout.Infinite) :
null;
var state = new TStateType();
var state = new TStateType
{
IntervalMs = periodMs,
InitialDelayMs = dueTimeMs
};
var semaphore = new SemaphoreSlim(1, 1);
@ -110,14 +124,17 @@ namespace MediaBrowser.Common.Net
ActiveConnections.Add(new Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim>(message.Connection, cancellationTokenSource, timer, state, semaphore));
}
timer.Change(TimeSpan.FromMilliseconds(dueTimeMs), TimeSpan.FromMilliseconds(periodMs));
if (timer != null)
{
timer.Change(TimeSpan.FromMilliseconds(dueTimeMs), TimeSpan.FromMilliseconds(periodMs));
}
}
/// <summary>
/// Timers the callback.
/// </summary>
/// <param name="state">The state.</param>
private async void TimerCallback(object state)
private void TimerCallback(object state)
{
var connection = (IWebSocketConnection)state;
@ -139,11 +156,50 @@ namespace MediaBrowser.Common.Net
return;
}
SendData(tuple);
}
protected void SendData(bool force)
{
List<Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim>> tuples;
lock (ActiveConnections)
{
tuples = ActiveConnections
.Where(c =>
{
if (c.Item1.State == WebSocketState.Open && !c.Item2.IsCancellationRequested)
{
var state = c.Item4;
if (force || (DateTime.UtcNow - state.DateLastSendUtc).TotalMilliseconds >= state.IntervalMs)
{
return true;
}
}
return false;
})
.ToList();
}
foreach (var tuple in tuples)
{
SendData(tuple);
}
}
private async void SendData(Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim> tuple)
{
var connection = tuple.Item1;
try
{
await tuple.Item5.WaitAsync(tuple.Item2.Token).ConfigureAwait(false);
var data = await GetDataToSend(tuple.Item4).ConfigureAwait(false);
var state = tuple.Item4;
var data = await GetDataToSend(state).ConfigureAwait(false);
if (data != null)
{
@ -153,6 +209,8 @@ namespace MediaBrowser.Common.Net
Data = data
}, tuple.Item2.Token).ConfigureAwait(false);
state.DateLastSendUtc = DateTime.UtcNow;
}
tuple.Item5.Release();
@ -196,13 +254,18 @@ namespace MediaBrowser.Common.Net
{
Logger.Info("{1} stop transmitting over websocket to {0}", connection.Item1.RemoteEndPoint, GetType().Name);
try
{
connection.Item3.Dispose();
}
catch (ObjectDisposedException)
{
var timer = connection.Item3;
if (timer != null)
{
try
{
timer.Dispose();
}
catch (ObjectDisposedException)
{
}
}
try
@ -212,7 +275,7 @@ namespace MediaBrowser.Common.Net
}
catch (ObjectDisposedException)
{
}
try
@ -223,7 +286,7 @@ namespace MediaBrowser.Common.Net
{
}
ActiveConnections.Remove(connection);
}
@ -253,4 +316,11 @@ namespace MediaBrowser.Common.Net
Dispose(true);
}
}
public class WebSocketListenerState
{
public DateTime DateLastSendUtc { get; set; }
public long InitialDelayMs { get; set; }
public long IntervalMs { get; set; }
}
}

View file

@ -52,6 +52,12 @@ namespace MediaBrowser.Common.Net
}
}
/// <summary>
/// Gets or sets the host.
/// </summary>
/// <value>The host.</value>
public string Host { get; set; }
/// <summary>
/// Gets or sets the progress.
/// </summary>
@ -69,14 +75,13 @@ namespace MediaBrowser.Common.Net
public string RequestContentType { get; set; }
public string RequestContent { get; set; }
public byte[] RequestContentBytes { get; set; }
public bool BufferContent { get; set; }
public bool LogRequest { get; set; }
public bool LogErrorResponseBody { get; set; }
public HttpRequestCachePolicy CachePolicy { get; set; }
private string GetHeaderValue(string name)
{
@ -95,17 +100,9 @@ namespace MediaBrowser.Common.Net
EnableHttpCompression = true;
BufferContent = true;
CachePolicy = HttpRequestCachePolicy.None;
RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
LogRequest = true;
}
}
public enum HttpRequestCachePolicy
{
None = 1,
Validate = 2
}
}

View file

@ -65,16 +65,4 @@ namespace MediaBrowser.Common.Net
/// <exception cref="System.ArgumentNullException">buffer</exception>
Task SendAsync(byte[] buffer, WebSocketMessageType type, CancellationToken cancellationToken);
}
/// <summary>
/// Class WebSocketMessageInfo
/// </summary>
public class WebSocketMessageInfo : WebSocketMessage<string>
{
/// <summary>
/// Gets or sets the connection.
/// </summary>
/// <value>The connection.</value>
public IWebSocketConnection Connection { get; set; }
}
}

View file

@ -0,0 +1,16 @@
using MediaBrowser.Model.Net;
namespace MediaBrowser.Common.Net
{
/// <summary>
/// Class WebSocketMessageInfo
/// </summary>
public class WebSocketMessageInfo : WebSocketMessage<string>
{
/// <summary>
/// Gets or sets the connection.
/// </summary>
/// <value>The connection.</value>
public IWebSocketConnection Connection { get; set; }
}
}

View file

@ -305,8 +305,6 @@ namespace MediaBrowser.Common.Plugins
ConfigurationDateLastModified = ConfigurationDateLastModified,
Description = Description,
Id = Id.ToString("N"),
EnableAutoUpdate = Configuration.EnableAutoUpdate,
UpdateClass = Configuration.UpdateClass,
ConfigurationFileName = ConfigurationFileName
};

View file

@ -0,0 +1,16 @@
namespace MediaBrowser.Common.ScheduledTasks
{
public interface IConfigurableScheduledTask
{
/// <summary>
/// Gets a value indicating whether this instance is hidden.
/// </summary>
/// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
bool IsHidden { get; }
/// <summary>
/// Gets a value indicating whether this instance is enabled.
/// </summary>
/// <value><c>true</c> if this instance is enabled; otherwise, <c>false</c>.</value>
bool IsEnabled { get; }
}
}

View file

@ -0,0 +1,7 @@
namespace MediaBrowser.Common.ScheduledTasks
{
public interface IHasKey
{
string Key { get; }
}
}

View file

@ -42,23 +42,4 @@ namespace MediaBrowser.Common.ScheduledTasks
/// <returns>IEnumerable{BaseTaskTrigger}.</returns>
IEnumerable<ITaskTrigger> GetDefaultTriggers();
}
public interface IConfigurableScheduledTask
{
/// <summary>
/// Gets a value indicating whether this instance is hidden.
/// </summary>
/// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
bool IsHidden { get; }
/// <summary>
/// Gets a value indicating whether this instance is enabled.
/// </summary>
/// <value><c>true</c> if this instance is enabled; otherwise, <c>false</c>.</value>
bool IsEnabled { get; }
}
public interface IHasKey
{
string Key { get; }
}
}

View file

@ -1,4 +1,5 @@
using MediaBrowser.Model.Tasks;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Tasks;
using System;
using System.Collections.Generic;
@ -9,6 +10,11 @@ namespace MediaBrowser.Common.ScheduledTasks
/// </summary>
public interface IScheduledTaskWorker : IDisposable
{
/// <summary>
/// Occurs when [task progress].
/// </summary>
event EventHandler<GenericEventArgs<double>> TaskProgress;
/// <summary>
/// Gets or sets the scheduled task.
/// </summary>
@ -62,6 +68,6 @@ namespace MediaBrowser.Common.ScheduledTasks
/// Gets the unique id.
/// </summary>
/// <value>The unique id.</value>
Guid Id { get; }
string Id { get; }
}
}

View file

@ -1,5 +1,4 @@
using MediaBrowser.Common.Events;
using MediaBrowser.Model.Tasks;
using MediaBrowser.Model.Events;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
@ -50,7 +49,7 @@ namespace MediaBrowser.Common.ScheduledTasks
void Cancel(IScheduledTaskWorker task);
Task Execute(IScheduledTaskWorker task);
event EventHandler<EventArgs> TaskExecuting;
event EventHandler<GenericEventArgs<TaskResult>> TaskCompleted;
event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting;
event EventHandler<TaskCompletionEventArgs> TaskCompleted;
}
}

View file

@ -5,7 +5,7 @@ namespace MediaBrowser.Common.ScheduledTasks
{
public class TaskCompletionEventArgs : EventArgs
{
public IScheduledTask Task { get; set; }
public IScheduledTaskWorker Task { get; set; }
public TaskResult Result { get; set; }
}

View file

@ -1,5 +1,5 @@
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Updates;
using System;
using System.Collections.Concurrent;

View file

@ -1,5 +1,4 @@
using MediaBrowser.Model.Updates;
using System;
namespace MediaBrowser.Common.Updates
{
@ -9,9 +8,4 @@ namespace MediaBrowser.Common.Updates
public PackageVersionInfo PackageVersionInfo { get; set; }
}
public class InstallationFailedEventArgs : InstallationEventArgs
{
public Exception Exception { get; set; }
}
}

View file

@ -0,0 +1,9 @@
using System;
namespace MediaBrowser.Common.Updates
{
public class InstallationFailedEventArgs : InstallationEventArgs
{
public Exception Exception { get; set; }
}
}

View file

@ -8,6 +8,8 @@ namespace MediaBrowser.Controller.Channels
{
public string ExternalId { get; set; }
public string ChannelId { get; set; }
public ChannelItemType ChannelItemType { get; set; }
public bool IsInfiniteStream { get; set; }

View file

@ -7,6 +7,8 @@ namespace MediaBrowser.Controller.Channels
{
public string ExternalId { get; set; }
public string ChannelId { get; set; }
public ChannelItemType ChannelItemType { get; set; }
public string OriginalImageUrl { get; set; }

View file

@ -0,0 +1,30 @@
using System.Collections.Generic;
namespace MediaBrowser.Controller.Channels
{
public class ChannelInfo
{
/// <summary>
/// Gets the home page URL.
/// </summary>
/// <value>The home page URL.</value>
public string HomePageUrl { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance can search.
/// </summary>
/// <value><c>true</c> if this instance can search; otherwise, <c>false</c>.</value>
public bool CanSearch { get; set; }
public List<ChannelMediaType> MediaTypes { get; set; }
public List<ChannelMediaContentType> ContentTypes { get; set; }
public ChannelInfo()
{
MediaTypes = new List<ChannelMediaType>();
ContentTypes = new List<ChannelMediaContentType>();
}
}
}

View file

@ -52,45 +52,4 @@ namespace MediaBrowser.Controller.Channels
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
public enum ChannelItemType
{
Media = 0,
Category = 1
}
public enum ChannelMediaType
{
Audio = 0,
Video = 1
}
public enum ChannelMediaContentType
{
Clip = 0,
Podcast = 1,
Trailer = 2,
Movie = 3,
Episode = 4,
Song = 5
}
public class ChannelMediaInfo
{
public string Path { get; set; }
public Dictionary<string, string> RequiredHttpHeaders { get; set; }
public ChannelMediaInfo()
{
RequiredHttpHeaders = new Dictionary<string, string>();
}
}
}

View file

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Channels
{
public class ChannelItemResult
{
public List<ChannelItemInfo> Items { get; set; }
public TimeSpan CacheLength { get; set; }
}
}

View file

@ -0,0 +1,9 @@
namespace MediaBrowser.Controller.Channels
{
public enum ChannelItemType
{
Media = 0,
Category = 1
}
}

View file

@ -0,0 +1,17 @@
namespace MediaBrowser.Controller.Channels
{
public enum ChannelMediaContentType
{
Clip = 0,
Podcast = 1,
Trailer = 2,
Movie = 3,
Episode = 4,
Song = 5
}
}

View file

@ -0,0 +1,26 @@
using System.Collections.Generic;
namespace MediaBrowser.Controller.Channels
{
public class ChannelMediaInfo
{
public string Path { get; set; }
public Dictionary<string, string> RequiredHttpHeaders { get; set; }
public string Container { get; set; }
public string AudioCodec { get; set; }
public string VideoCodec { get; set; }
public int? AudioBitrate { get; set; }
public int? VideoBitrate { get; set; }
public int? Width { get; set; }
public int? Height { get; set; }
public int? AudioChannels { get; set; }
public ChannelMediaInfo()
{
RequiredHttpHeaders = new Dictionary<string, string>();
}
}
}

View file

@ -0,0 +1,9 @@
namespace MediaBrowser.Controller.Channels
{
public enum ChannelMediaType
{
Audio = 0,
Video = 1
}
}

View file

@ -0,0 +1,7 @@
namespace MediaBrowser.Controller.Channels
{
public class ChannelSearchInfo
{
public string SearchTerm { get; set; }
}
}

View file

@ -10,6 +10,8 @@ namespace MediaBrowser.Controller.Channels
{
public string ExternalId { get; set; }
public string ChannelId { get; set; }
public ChannelItemType ChannelItemType { get; set; }
public bool IsInfiniteStream { get; set; }

View file

@ -1,7 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -60,48 +59,4 @@ namespace MediaBrowser.Controller.Channels
/// <returns>IEnumerable{ImageType}.</returns>
IEnumerable<ImageType> GetSupportedChannelImages();
}
public class ChannelInfo
{
/// <summary>
/// Gets the home page URL.
/// </summary>
/// <value>The home page URL.</value>
public string HomePageUrl { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance can search.
/// </summary>
/// <value><c>true</c> if this instance can search; otherwise, <c>false</c>.</value>
public bool CanSearch { get; set; }
public List<ChannelMediaType> MediaTypes { get; set; }
public List<ChannelMediaContentType> ContentTypes { get; set; }
public ChannelInfo()
{
MediaTypes = new List<ChannelMediaType>();
ContentTypes = new List<ChannelMediaContentType>();
}
}
public class ChannelSearchInfo
{
public string SearchTerm { get; set; }
}
public class InternalChannelItemQuery
{
public string CategoryId { get; set; }
public User User { get; set; }
}
public class ChannelItemResult
{
public List<ChannelItemInfo> Items { get; set; }
public TimeSpan CacheLength { get; set; }
}
}

View file

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace MediaBrowser.Controller.Channels
{
public interface IChannelFactory
{
IEnumerable<IChannel> GetChannels();
}
}

View file

@ -4,17 +4,12 @@ namespace MediaBrowser.Controller.Channels
{
public interface IChannelItem : IHasImages
{
string ChannelId { get; set; }
string ExternalId { get; set; }
ChannelItemType ChannelItemType { get; set; }
string OriginalImageUrl { get; set; }
}
public interface IChannelMediaItem : IChannelItem
{
bool IsInfiniteStream { get; set; }
ChannelMediaContentType ContentType { get; set; }
}
}

View file

@ -13,7 +13,8 @@ namespace MediaBrowser.Controller.Channels
/// Adds the parts.
/// </summary>
/// <param name="channels">The channels.</param>
void AddParts(IEnumerable<IChannel> channels);
/// <param name="factories">The factories.</param>
void AddParts(IEnumerable<IChannel> channels, IEnumerable<IChannelFactory> factories);
/// <summary>
/// Gets the channels.

View file

@ -0,0 +1,9 @@
namespace MediaBrowser.Controller.Channels
{
public interface IChannelMediaItem : IChannelItem
{
bool IsInfiniteStream { get; set; }
ChannelMediaContentType ContentType { get; set; }
}
}

View file

@ -0,0 +1,11 @@
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Channels
{
public class InternalChannelItemQuery
{
public string CategoryId { get; set; }
public User User { get; set; }
}
}

View file

@ -0,0 +1,19 @@
using MediaBrowser.Model.Chapters;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Chapters
{
public class ChapterResponse
{
/// <summary>
/// Gets or sets the chapters.
/// </summary>
/// <value>The chapters.</value>
public List<RemoteChapterInfo> Chapters { get; set; }
public ChapterResponse()
{
Chapters = new List<RemoteChapterInfo>();
}
}
}

View file

@ -0,0 +1,29 @@
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Chapters
{
public class ChapterSearchRequest : IHasProviderIds
{
public string Language { get; set; }
public VideoContentType ContentType { get; set; }
public string MediaPath { get; set; }
public string SeriesName { get; set; }
public string Name { get; set; }
public int? IndexNumber { get; set; }
public int? IndexNumberEnd { get; set; }
public int? ParentIndexNumber { get; set; }
public int? ProductionYear { get; set; }
public long? RuntimeTicks { get; set; }
public Dictionary<string, string> ProviderIds { get; set; }
public ChapterSearchRequest()
{
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
}

View file

@ -0,0 +1,39 @@
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Chapters;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Chapters
{
public interface IChapterProvider
{
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
string Name { get; }
/// <summary>
/// Gets the supported media types.
/// </summary>
/// <value>The supported media types.</value>
IEnumerable<VideoContentType> SupportedMediaTypes { get; }
/// <summary>
/// Searches the specified request.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{RemoteChapterResult}}.</returns>
Task<IEnumerable<RemoteChapterResult>> Search(ChapterSearchRequest request, CancellationToken cancellationToken);
/// <summary>
/// Gets the chapters.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ChapterResponse}.</returns>
Task<ChapterResponse> GetChapters(string id, CancellationToken cancellationToken);
}
}

View file

@ -1,5 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Events;
using System;
namespace MediaBrowser.Controller.Configuration
{
@ -8,6 +10,11 @@ namespace MediaBrowser.Controller.Configuration
/// </summary>
public interface IServerConfigurationManager : IConfigurationManager
{
/// <summary>
/// Occurs when [configuration updating].
/// </summary>
event EventHandler<GenericEventArgs<ServerConfiguration>> ConfigurationUpdating;
/// <summary>
/// Gets the application paths.
/// </summary>

View file

@ -17,18 +17,4 @@ namespace MediaBrowser.Controller.Dlna
Headers = new Dictionary<string, string>();
}
}
public class ControlResponse
{
public IDictionary<string, string> Headers { get; set; }
public string Xml { get; set; }
public bool IsSuccessful { get; set; }
public ControlResponse()
{
Headers = new Dictionary<string, string>();
}
}
}

View file

@ -0,0 +1,18 @@
using System.Collections.Generic;
namespace MediaBrowser.Controller.Dlna
{
public class ControlResponse
{
public IDictionary<string, string> Headers { get; set; }
public string Xml { get; set; }
public bool IsSuccessful { get; set; }
public ControlResponse()
{
Headers = new Dictionary<string, string>();
}
}
}

View file

@ -55,7 +55,7 @@ namespace MediaBrowser.Controller.Drawing
/// <param name="item">The item.</param>
/// <param name="image">The image.</param>
/// <returns>Guid.</returns>
Guid GetImageCacheTag(IHasImages item, ItemImageInfo image);
string GetImageCacheTag(IHasImages item, ItemImageInfo image);
/// <summary>
/// Gets the image cache tag.
@ -66,7 +66,7 @@ namespace MediaBrowser.Controller.Drawing
/// <param name="dateModified">The date modified.</param>
/// <param name="imageEnhancers">The image enhancers.</param>
/// <returns>Guid.</returns>
Guid GetImageCacheTag(IHasImages item, ImageType imageType, string originalImagePath, DateTime dateModified,
string GetImageCacheTag(IHasImages item, ImageType imageType, string originalImagePath, DateTime dateModified,
List<IImageEnhancer> imageEnhancers);
/// <summary>
@ -86,24 +86,4 @@ namespace MediaBrowser.Controller.Drawing
/// <returns>Task{System.String}.</returns>
Task<string> GetEnhancedImage(IHasImages item, ImageType imageType, int imageIndex);
}
public static class ImageProcessorExtensions
{
public static Guid? GetImageCacheTag(this IImageProcessor processor, IHasImages item, ImageType imageType)
{
return processor.GetImageCacheTag(item, imageType, 0);
}
public static Guid? GetImageCacheTag(this IImageProcessor processor, IHasImages item, ImageType imageType, int imageIndex)
{
var imageInfo = item.GetImageInfo(imageType, imageIndex);
if (imageInfo == null)
{
return null;
}
return processor.GetImageCacheTag(item, imageInfo);
}
}
}

View file

@ -0,0 +1,25 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Drawing
{
public static class ImageProcessorExtensions
{
public static string GetImageCacheTag(this IImageProcessor processor, IHasImages item, ImageType imageType)
{
return processor.GetImageCacheTag(item, imageType, 0);
}
public static string GetImageCacheTag(this IImageProcessor processor, IHasImages item, ImageType imageType, int imageIndex)
{
var imageInfo = item.GetImageInfo(imageType, imageIndex);
if (imageInfo == null)
{
return null;
}
return processor.GetImageCacheTag(item, imageInfo);
}
}
}

View file

@ -305,13 +305,7 @@ namespace MediaBrowser.Controller.Entities.TV
if (!ParentIndexNumber.HasValue && !string.IsNullOrEmpty(Path))
{
ParentIndexNumber = TVUtils.GetSeasonNumberFromPath(Path);
// If a change was made record it
if (ParentIndexNumber.HasValue)
{
hasChanges = true;
}
ParentIndexNumber = TVUtils.GetSeasonNumberFromEpisodeFile(Path);
}
// If a change was made record it

View file

@ -1,5 +1,4 @@
using MediaBrowser.Controller.Entities;
using System;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Library
@ -23,19 +22,4 @@ namespace MediaBrowser.Controller.Library
/// <returns>IEnumerable{System.String}.</returns>
IEnumerable<string> GetAllIntroFiles();
}
public class IntroInfo
{
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
public string Path { get; set; }
/// <summary>
/// Gets or sets the item id.
/// </summary>
/// <value>The item id.</value>
public Guid? ItemId { get; set; }
}
}

View file

@ -333,20 +333,4 @@ namespace MediaBrowser.Controller.Library
/// <returns>IEnumerable{BaseItem}.</returns>
IEnumerable<BaseItem> ReplaceVideosWithPrimaryVersions(IEnumerable<BaseItem> items);
}
public static class LibraryManagerExtensions
{
public static Task DeleteItem(this ILibraryManager manager, BaseItem item)
{
return manager.DeleteItem(item, new DeleteOptions
{
DeleteFileLocation = true
});
}
public static BaseItem GetItemById(this ILibraryManager manager, string id)
{
return manager.GetItemById(new Guid(id));
}
}
}

View file

@ -0,0 +1,14 @@
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
public interface IMetadataFileSaver : IMetadataSaver
{
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
string GetSavePath(IHasMetadata item);
}
}

View file

@ -31,14 +31,4 @@ namespace MediaBrowser.Controller.Library
/// <returns>Task.</returns>
void Save(IHasMetadata item, CancellationToken cancellationToken);
}
public interface IMetadataFileSaver : IMetadataSaver
{
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
string GetSavePath(IHasMetadata item);
}
}

View file

@ -1,5 +1,5 @@
using MediaBrowser.Common.Events;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Events;
using System;
using System.Collections.Generic;
using System.Threading;

View file

@ -0,0 +1,19 @@
using System;
namespace MediaBrowser.Controller.Library
{
public class IntroInfo
{
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
public string Path { get; set; }
/// <summary>
/// Gets or sets the item id.
/// </summary>
/// <value>The item id.</value>
public Guid? ItemId { get; set; }
}
}

View file

@ -0,0 +1,22 @@
using System;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
public static class LibraryManagerExtensions
{
public static Task DeleteItem(this ILibraryManager manager, BaseItem item)
{
return manager.DeleteItem(item, new DeleteOptions
{
DeleteFileLocation = true
});
}
public static BaseItem GetItemById(this ILibraryManager manager, string id)
{
return manager.GetItemById(new Guid(id));
}
}
}

View file

@ -24,13 +24,4 @@ namespace MediaBrowser.Controller.Library
Users = new List<User>();
}
}
public class PlaybackStopEventArgs : PlaybackProgressEventArgs
{
/// <summary>
/// Gets or sets a value indicating whether [played to completion].
/// </summary>
/// <value><c>true</c> if [played to completion]; otherwise, <c>false</c>.</value>
public bool PlayedToCompletion { get; set; }
}
}

View file

@ -0,0 +1,11 @@
namespace MediaBrowser.Controller.Library
{
public class PlaybackStopEventArgs : PlaybackProgressEventArgs
{
/// <summary>
/// Gets or sets a value indicating whether [played to completion].
/// </summary>
/// <value><c>true</c> if [played to completion]; otherwise, <c>false</c>.</value>
public bool PlayedToCompletion { get; set; }
}
}

View file

@ -0,0 +1,9 @@
namespace MediaBrowser.Controller.LiveTv
{
/// <summary>
/// Class LiveTvConflictException.
/// </summary>
public class LiveTvConflictException : LiveTvException
{
}
}

View file

@ -8,11 +8,4 @@ namespace MediaBrowser.Controller.LiveTv
public class LiveTvException : Exception
{
}
/// <summary>
/// Class LiveTvConflictException.
/// </summary>
public class LiveTvConflictException : LiveTvException
{
}
}

View file

@ -40,60 +40,4 @@ namespace MediaBrowser.Controller.LiveTv
Tuners = new List<LiveTvTunerInfo>();
}
}
public class LiveTvTunerInfo
{
/// <summary>
/// Gets or sets the type of the source.
/// </summary>
/// <value>The type of the source.</value>
public string SourceType { get; set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the identifier.
/// </summary>
/// <value>The identifier.</value>
public string Id { get; set; }
/// <summary>
/// Gets or sets the status.
/// </summary>
/// <value>The status.</value>
public LiveTvTunerStatus Status { get; set; }
/// <summary>
/// Gets or sets the channel identifier.
/// </summary>
/// <value>The channel identifier.</value>
public string ChannelId { get; set; }
/// <summary>
/// Gets or sets the recording identifier.
/// </summary>
/// <value>The recording identifier.</value>
public string RecordingId { get; set; }
/// <summary>
/// Gets or sets the name of the program.
/// </summary>
/// <value>The name of the program.</value>
public string ProgramName { get; set; }
/// <summary>
/// Gets or sets the clients.
/// </summary>
/// <value>The clients.</value>
public List<string> Clients { get; set; }
public LiveTvTunerInfo()
{
Clients = new List<string>();
}
}
}

View file

@ -0,0 +1,61 @@
using System.Collections.Generic;
using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Controller.LiveTv
{
public class LiveTvTunerInfo
{
/// <summary>
/// Gets or sets the type of the source.
/// </summary>
/// <value>The type of the source.</value>
public string SourceType { get; set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the identifier.
/// </summary>
/// <value>The identifier.</value>
public string Id { get; set; }
/// <summary>
/// Gets or sets the status.
/// </summary>
/// <value>The status.</value>
public LiveTvTunerStatus Status { get; set; }
/// <summary>
/// Gets or sets the channel identifier.
/// </summary>
/// <value>The channel identifier.</value>
public string ChannelId { get; set; }
/// <summary>
/// Gets or sets the recording identifier.
/// </summary>
/// <value>The recording identifier.</value>
public string RecordingId { get; set; }
/// <summary>
/// Gets or sets the name of the program.
/// </summary>
/// <value>The name of the program.</value>
public string ProgramName { get; set; }
/// <summary>
/// Gets or sets the clients.
/// </summary>
/// <value>The clients.</value>
public List<string> Clients { get; set; }
public LiveTvTunerInfo()
{
Clients = new List<string>();
}
}
}

View file

@ -69,16 +69,30 @@
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="Channels\ChannelCategoryItem.cs" />
<Compile Include="Channels\ChannelInfo.cs" />
<Compile Include="Channels\ChannelItemInfo.cs" />
<Compile Include="Channels\ChannelItemResult.cs" />
<Compile Include="Channels\ChannelItemType.cs" />
<Compile Include="Channels\ChannelMediaContentType.cs" />
<Compile Include="Channels\ChannelMediaInfo.cs" />
<Compile Include="Channels\ChannelMediaType.cs" />
<Compile Include="Channels\ChannelSearchInfo.cs" />
<Compile Include="Channels\IChannel.cs" />
<Compile Include="Channels\IChannelFactory.cs" />
<Compile Include="Channels\IChannelManager.cs" />
<Compile Include="Channels\IChannelItem.cs" />
<Compile Include="Channels\ChannelAudioItem.cs" />
<Compile Include="Channels\ChannelVideoItem.cs" />
<Compile Include="Channels\Channel.cs" />
<Compile Include="Channels\IChannelMediaItem.cs" />
<Compile Include="Channels\InternalChannelItemQuery.cs" />
<Compile Include="Chapters\ChapterSearchRequest.cs" />
<Compile Include="Chapters\IChapterProvider.cs" />
<Compile Include="Chapters\ChapterResponse.cs" />
<Compile Include="Collections\CollectionCreationOptions.cs" />
<Compile Include="Collections\ICollectionManager.cs" />
<Compile Include="Dlna\ControlRequest.cs" />
<Compile Include="Dlna\ControlResponse.cs" />
<Compile Include="Dlna\DlnaIconResponse.cs" />
<Compile Include="Dlna\EventSubscriptionResponse.cs" />
<Compile Include="Dlna\IContentDirectory.cs" />
@ -87,6 +101,7 @@
<Compile Include="Drawing\IImageProcessor.cs" />
<Compile Include="Drawing\ImageFormat.cs" />
<Compile Include="Drawing\ImageProcessingOptions.cs" />
<Compile Include="Drawing\ImageProcessorExtensions.cs" />
<Compile Include="Dto\IDtoService.cs" />
<Compile Include="Entities\AdultVideo.cs" />
<Compile Include="Entities\Audio\IHasAlbumArtist.cs" />
@ -131,12 +146,16 @@
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
<Compile Include="Library\DeleteOptions.cs" />
<Compile Include="Library\ILibraryPostScanTask.cs" />
<Compile Include="Library\IMetadataFileSaver.cs" />
<Compile Include="Library\IMetadataSaver.cs" />
<Compile Include="Library\IMusicManager.cs" />
<Compile Include="Library\IntroInfo.cs" />
<Compile Include="Library\ItemUpdateType.cs" />
<Compile Include="Library\IUserDataManager.cs" />
<Compile Include="Library\LibraryManagerExtensions.cs" />
<Compile Include="Library\PlaybackStopEventArgs.cs" />
<Compile Include="Library\UserDataSaveEventArgs.cs" />
<Compile Include="LiveTv\EventArgs.cs" />
<Compile Include="LiveTv\RecordingStatusChangedEventArgs.cs" />
<Compile Include="LiveTv\ILiveTvRecording.cs" />
<Compile Include="LiveTv\LiveStreamInfo.cs" />
<Compile Include="LiveTv\LiveTvAudioRecording.cs" />
@ -144,8 +163,10 @@
<Compile Include="LiveTv\ChannelInfo.cs" />
<Compile Include="LiveTv\ILiveTvManager.cs" />
<Compile Include="LiveTv\ILiveTvService.cs" />
<Compile Include="LiveTv\LiveTvConflictException.cs" />
<Compile Include="LiveTv\LiveTvException.cs" />
<Compile Include="LiveTv\LiveTvServiceStatusInfo.cs" />
<Compile Include="LiveTv\LiveTvTunerInfo.cs" />
<Compile Include="LiveTv\StreamResponseInfo.cs" />
<Compile Include="LiveTv\LiveTvProgram.cs" />
<Compile Include="LiveTv\LiveTvVideoRecording.cs" />
@ -190,6 +211,10 @@
<Compile Include="Providers\IMetadataProvider.cs" />
<Compile Include="Providers\IMetadataService.cs" />
<Compile Include="Providers\IRemoteMetadataProvider.cs" />
<Compile Include="Providers\VideoContentType.cs" />
<Compile Include="Security\IEncryptionManager.cs" />
<Compile Include="Subtitles\ISubtitleManager.cs" />
<Compile Include="Subtitles\ISubtitleProvider.cs" />
<Compile Include="Providers\ItemLookupInfo.cs" />
<Compile Include="Providers\MetadataRefreshOptions.cs" />
<Compile Include="Providers\NameParser.cs" />
@ -265,6 +290,8 @@
<Compile Include="Sorting\IUserBaseItemComparer.cs" />
<Compile Include="Providers\BaseItemXmlParser.cs" />
<Compile Include="Sorting\SortExtensions.cs" />
<Compile Include="Subtitles\SubtitleResponse.cs" />
<Compile Include="Subtitles\SubtitleSearchRequest.cs" />
<Compile Include="Themes\IAppThemeManager.cs" />
<Compile Include="Themes\InternalThemeImage.cs" />
</ItemGroup>

View file

@ -187,7 +187,9 @@ namespace MediaBrowser.Controller.MediaEncoding
}
else if (string.Equals(streamInfo.codec_type, "video", StringComparison.OrdinalIgnoreCase))
{
stream.Type = MediaStreamType.Video;
stream.Type = (streamInfo.codec_name ?? string.Empty).IndexOf("mjpeg", StringComparison.OrdinalIgnoreCase) != -1
? MediaStreamType.EmbeddedImage
: MediaStreamType.Video;
stream.Width = streamInfo.width;
stream.Height = streamInfo.height;

View file

@ -34,6 +34,6 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="userId">The user id.</param>
/// <param name="client">The client.</param>
/// <returns>Task{DisplayPreferences}.</returns>
DisplayPreferences GetDisplayPreferences(Guid displayPreferencesId, Guid userId, string client);
DisplayPreferences GetDisplayPreferences(string displayPreferencesId, Guid userId, string client);
}
}

View file

@ -11,6 +11,7 @@ namespace MediaBrowser.Controller.Providers
{
List<FileSystemInfo> GetFileSystemEntries(string path);
IEnumerable<FileSystemInfo> GetFiles(string path);
IEnumerable<FileSystemInfo> GetFiles(string path, bool clearCache);
FileSystemInfo GetFile(string path);
}
@ -26,9 +27,21 @@ namespace MediaBrowser.Controller.Providers
}
public List<FileSystemInfo> GetFileSystemEntries(string path)
{
return GetFileSystemEntries(path, false);
}
private List<FileSystemInfo> GetFileSystemEntries(string path, bool clearCache)
{
List<FileSystemInfo> entries;
if (clearCache)
{
List<FileSystemInfo> removed;
_cache.TryRemove(path, out removed);
}
if (!_cache.TryGetValue(path, out entries))
{
//_logger.Debug("Getting files for " + path);
@ -50,7 +63,12 @@ namespace MediaBrowser.Controller.Providers
public IEnumerable<FileSystemInfo> GetFiles(string path)
{
return GetFileSystemEntries(path).Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory);
return GetFiles(path, false);
}
public IEnumerable<FileSystemInfo> GetFiles(string path, bool clearCache)
{
return GetFileSystemEntries(path, clearCache).Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory);
}
public FileSystemInfo GetFile(string path)

View file

@ -0,0 +1,19 @@

namespace MediaBrowser.Controller.Providers
{
/// <summary>
/// Enum VideoContentType
/// </summary>
public enum VideoContentType
{
/// <summary>
/// The episode
/// </summary>
Episode = 0,
/// <summary>
/// The movie
/// </summary>
Movie = 1
}
}

View file

@ -0,0 +1,20 @@

namespace MediaBrowser.Controller.Security
{
public interface IEncryptionManager
{
/// <summary>
/// Encrypts the string.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>System.String.</returns>
string EncryptString(string value);
/// <summary>
/// Decrypts the string.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>System.String.</returns>
string DecryptString(string value);
}
}

View file

@ -19,14 +19,6 @@ namespace MediaBrowser.Controller.Session
/// <value><c>true</c> if this instance is session active; otherwise, <c>false</c>.</value>
bool IsSessionActive { get; }
/// <summary>
/// Sends the message command.
/// </summary>
/// <param name="command">The command.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SendMessageCommand(MessageCommand command, CancellationToken cancellationToken);
/// <summary>
/// Sends the play command.
/// </summary>

View file

@ -0,0 +1,50 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Providers;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Subtitles
{
public interface ISubtitleManager
{
/// <summary>
/// Adds the parts.
/// </summary>
/// <param name="subtitleProviders">The subtitle providers.</param>
void AddParts(IEnumerable<ISubtitleProvider> subtitleProviders);
/// <summary>
/// Searches the subtitles.
/// </summary>
/// <param name="video">The video.</param>
/// <param name="language">The language.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{RemoteSubtitleInfo}}.</returns>
Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(Video video,
string language,
CancellationToken cancellationToken);
/// <summary>
/// Searches the subtitles.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{RemoteSubtitleInfo}}.</returns>
Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(SubtitleSearchRequest request,
CancellationToken cancellationToken);
/// <summary>
/// Downloads the subtitles.
/// </summary>
/// <param name="video">The video.</param>
/// <param name="subtitleId">The subtitle identifier.</param>
/// <param name="providerName">Name of the provider.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task DownloadSubtitles(Video video,
string subtitleId,
string providerName,
CancellationToken cancellationToken);
}
}

View file

@ -0,0 +1,39 @@
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Providers;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Subtitles
{
public interface ISubtitleProvider
{
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
string Name { get; }
/// <summary>
/// Gets the supported media types.
/// </summary>
/// <value>The supported media types.</value>
IEnumerable<VideoContentType> SupportedMediaTypes { get; }
/// <summary>
/// Searches the subtitles.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{RemoteSubtitleInfo}}.</returns>
Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken);
/// <summary>
/// Gets the subtitles.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{SubtitleResponse}.</returns>
Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken);
}
}

View file

@ -0,0 +1,11 @@
using System.IO;
namespace MediaBrowser.Controller.Subtitles
{
public class SubtitleResponse
{
public string Language { get; set; }
public string Format { get; set; }
public Stream Stream { get; set; }
}
}

Some files were not shown because too many files have changed in this diff Show more