make metadata path configurable

This commit is contained in:
Luke Pulverenti 2014-03-25 17:13:55 -04:00
parent 7c94203d05
commit 31e8288393
33 changed files with 204 additions and 339 deletions

View File

@ -9,16 +9,14 @@ using System.Linq;
namespace MediaBrowser.Api
{
[Route("/Themes", "GET")]
[Api(Description = "Gets a list of available themes for an app")]
[Route("/Themes", "GET", Summary = "Gets a list of available themes for an app")]
public class GetAppThemes : IReturn<List<AppThemeInfo>>
{
[ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string App { get; set; }
}
[Route("/Themes/Info", "GET")]
[Api(Description = "Gets an app theme")]
[Route("/Themes/Info", "GET", Summary = "Gets an app theme")]
public class GetAppTheme : IReturn<AppTheme>
{
[ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -28,8 +26,7 @@ namespace MediaBrowser.Api
public string Name { get; set; }
}
[Route("/Themes/Images", "GET")]
[Api(Description = "Gets an app theme")]
[Route("/Themes/Images", "GET", Summary = "Gets an app theme")]
public class GetAppThemeImage
{
[ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -45,8 +42,7 @@ namespace MediaBrowser.Api
public string CacheTag { get; set; }
}
[Route("/Themes", "POST")]
[Api(Description = "Saves a theme")]
[Route("/Themes", "POST", Summary = "Saves a theme")]
public class SaveTheme : AppTheme, IReturnVoid
{
}

View File

@ -2,6 +2,7 @@
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
using ServiceStack.Web;
using System;
@ -78,6 +79,20 @@ namespace MediaBrowser.Api
return ToOptimizedResult(result);
}
/// <summary>
/// Gets the session.
/// </summary>
/// <param name="sessionManager">The session manager.</param>
/// <returns>SessionInfo.</returns>
protected SessionInfo GetSession(ISessionManager sessionManager)
{
var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
return sessionManager.Sessions.First(i => string.Equals(i.DeviceId, auth.DeviceId) &&
string.Equals(i.Client, auth.Client) &&
string.Equals(i.ApplicationVersion, auth.Version));
}
/// <summary>
/// To the cached result.
/// </summary>

View File

@ -17,8 +17,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GetConfiguration
/// </summary>
[Route("/System/Configuration", "GET")]
[Api(("Gets application configuration"))]
[Route("/System/Configuration", "GET", Summary = "Gets application configuration")]
public class GetConfiguration : IReturn<ServerConfiguration>
{
@ -27,28 +26,24 @@ namespace MediaBrowser.Api
/// <summary>
/// Class UpdateConfiguration
/// </summary>
[Route("/System/Configuration", "POST")]
[Api(("Updates application configuration"))]
[Route("/System/Configuration", "POST", Summary = "Updates application configuration")]
public class UpdateConfiguration : ServerConfiguration, IReturnVoid
{
}
[Route("/System/Configuration/MetadataOptions/Default", "GET")]
[Api(("Gets a default MetadataOptions object"))]
[Route("/System/Configuration/MetadataOptions/Default", "GET", Summary = "Gets a default MetadataOptions object")]
public class GetDefaultMetadataOptions : IReturn<MetadataOptions>
{
}
[Route("/System/Configuration/MetadataPlugins", "GET")]
[Api(("Gets all available metadata plugins"))]
[Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")]
public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>>
{
}
[Route("/System/Configuration/VideoImageExtraction", "POST")]
[Api(("Updates image extraction for all types"))]
[Route("/System/Configuration/VideoImageExtraction", "POST", Summary = "Updates image extraction for all types")]
public class UpdateVideoImageExtraction : IReturnVoid
{
public bool Enabled { get; set; }

View File

@ -7,6 +7,7 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@ -245,12 +246,13 @@ namespace MediaBrowser.Api.Library
private readonly IDtoService _dtoService;
private readonly IChannelManager _channelManager;
private readonly ISessionManager _sessionManager;
/// <summary>
/// Initializes a new instance of the <see cref="LibraryService" /> class.
/// </summary>
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
IDtoService dtoService, IUserDataManager userDataManager, IChannelManager channelManager)
IDtoService dtoService, IUserDataManager userDataManager, IChannelManager channelManager, ISessionManager sessionManager)
{
_itemRepo = itemRepo;
_libraryManager = libraryManager;
@ -258,6 +260,7 @@ namespace MediaBrowser.Api.Library
_dtoService = dtoService;
_userDataManager = userDataManager;
_channelManager = channelManager;
_sessionManager = sessionManager;
}
public object Get(GetMediaFolders request)
@ -504,6 +507,13 @@ namespace MediaBrowser.Api.Library
{
var item = _dtoService.GetItemByDtoId(request.Id);
var session = GetSession(_sessionManager);
if (!session.UserId.HasValue || !_userManager.GetUserById(session.UserId.Value).Configuration.EnableContentDeletion)
{
throw new UnauthorizedAccessException("This operation requires a logged in user with delete access.");
}
return _libraryManager.DeleteItem(item);
}

View File

@ -17,8 +17,7 @@ namespace MediaBrowser.Api.Movies
/// <summary>
/// Class GetSimilarMovies
/// </summary>
[Route("/Movies/{Id}/Similar", "GET")]
[Api(Description = "Finds movies and trailers similar to a given movie.")]
[Route("/Movies/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given movie.")]
public class GetSimilarMovies : BaseGetSimilarItemsFromItem
{
[ApiMember(Name = "IncludeTrailers", Description = "Whether or not to include trailers within the results. Defaults to true.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
@ -30,8 +29,7 @@ namespace MediaBrowser.Api.Movies
}
}
[Route("/Movies/Recommendations", "GET")]
[Api(Description = "Gets movie recommendations")]
[Route("/Movies/Recommendations", "GET", Summary = "Gets movie recommendations")]
public class GetMovieRecommendations : IReturn<RecommendationDto[]>, IHasItemFields
{
[ApiMember(Name = "CategoryLimit", Description = "The max number of categories to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]

View File

@ -10,8 +10,7 @@ namespace MediaBrowser.Api.Movies
/// <summary>
/// Class GetSimilarTrailers
/// </summary>
[Route("/Trailers/{Id}/Similar", "GET")]
[Api(Description = "Finds movies and trailers similar to a given trailer.")]
[Route("/Trailers/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given trailer.")]
public class GetSimilarTrailers : BaseGetSimilarItemsFromItem
{
}

View File

@ -9,28 +9,24 @@ using System.Linq;
namespace MediaBrowser.Api.Music
{
[Route("/Songs/{Id}/InstantMix", "GET")]
[Api(Description = "Creates an instant playlist based on a given song")]
[Route("/Songs/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given song")]
public class GetInstantMixFromSong : BaseGetSimilarItemsFromItem
{
}
[Route("/Albums/{Id}/InstantMix", "GET")]
[Api(Description = "Creates an instant playlist based on a given album")]
[Route("/Albums/{Id}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given album")]
public class GetInstantMixFromAlbum : BaseGetSimilarItemsFromItem
{
}
[Route("/Artists/{Name}/InstantMix", "GET")]
[Api(Description = "Creates an instant playlist based on a given artist")]
[Route("/Artists/{Name}/InstantMix", "GET", Summary = "Creates an instant playlist based on a given artist")]
public class GetInstantMixFromArtist : BaseGetSimilarItems
{
[ApiMember(Name = "Name", Description = "The artist name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Name { get; set; }
}
[Route("/MusicGenres/{Name}/InstantMix", "GET")]
[Api(Description = "Creates an instant playlist based on a music genre")]
[Route("/MusicGenres/{Name}/InstantMix", "GET", Summary = "Creates an instant playlist based on a music genre")]
public class GetInstantMixFromMusicGenre : BaseGetSimilarItems
{
[ApiMember(Name = "Name", Description = "The genre name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]

View File

@ -2,18 +2,17 @@
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Model.Tasks;
using ServiceStack;
using ServiceStack.Text.Controller;
using System;
using System.Collections.Generic;
using System.Linq;
using ServiceStack.Text.Controller;
namespace MediaBrowser.Api.ScheduledTasks
{
/// <summary>
/// Class GetScheduledTask
/// </summary>
[Route("/ScheduledTasks/{Id}", "GET")]
[Api(Description = "Gets a scheduled task, by Id")]
[Route("/ScheduledTasks/{Id}", "GET", Summary = "Gets a scheduled task, by Id")]
public class GetScheduledTask : IReturn<TaskInfo>
{
/// <summary>
@ -27,8 +26,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <summary>
/// Class GetScheduledTasks
/// </summary>
[Route("/ScheduledTasks", "GET")]
[Api(Description = "Gets scheduled tasks")]
[Route("/ScheduledTasks", "GET", Summary = "Gets scheduled tasks")]
public class GetScheduledTasks : IReturn<List<TaskInfo>>
{
[ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
@ -38,8 +36,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <summary>
/// Class StartScheduledTask
/// </summary>
[Route("/ScheduledTasks/Running/{Id}", "POST")]
[Api(Description = "Starts a scheduled task")]
[Route("/ScheduledTasks/Running/{Id}", "POST", Summary = "Starts a scheduled task")]
public class StartScheduledTask : IReturnVoid
{
/// <summary>
@ -53,8 +50,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <summary>
/// Class StopScheduledTask
/// </summary>
[Route("/ScheduledTasks/Running/{Id}", "DELETE")]
[Api(Description = "Stops a scheduled task")]
[Route("/ScheduledTasks/Running/{Id}", "DELETE", Summary = "Stops a scheduled task")]
public class StopScheduledTask : IReturnVoid
{
/// <summary>
@ -68,8 +64,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <summary>
/// Class UpdateScheduledTaskTriggers
/// </summary>
[Route("/ScheduledTasks/{Id}/Triggers", "POST")]
[Api(Description = "Updates the triggers for a scheduled task")]
[Route("/ScheduledTasks/{Id}/Triggers", "POST", Summary = "Updates the triggers for a scheduled task")]
public class UpdateScheduledTaskTriggers : List<TaskTriggerInfo>, IReturnVoid
{
/// <summary>

View File

@ -8,15 +8,13 @@ using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Api.UserLibrary
{
/// <summary>
/// Class GetStudios
/// </summary>
[Route("/Studios", "GET")]
[Api(Description = "Gets all studios from a given item, folder, or the entire library")]
[Route("/Studios", "GET", Summary = "Gets all studios from a given item, folder, or the entire library")]
public class GetStudios : GetItemsByName
{
}
@ -24,8 +22,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary>
/// Class GetStudio
/// </summary>
[Route("/Studios/{Name}", "GET")]
[Api(Description = "Gets a studio, by name")]
[Route("/Studios/{Name}", "GET", Summary = "Gets a studio, by name")]
public class GetStudio : IReturn<BaseItemDto>
{
/// <summary>

View File

@ -705,7 +705,7 @@ namespace MediaBrowser.Api.UserLibrary
datePlayed = DateTime.ParseExact(request.DatePlayed, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
}
var session = GetSession();
var session = GetSession(_sessionManager);
var dto = await UpdatePlayedStatus(user, request.Id, true, datePlayed).ConfigureAwait(false);
@ -719,15 +719,6 @@ namespace MediaBrowser.Api.UserLibrary
return dto;
}
private SessionInfo GetSession()
{
var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
return _sessionManager.Sessions.First(i => string.Equals(i.DeviceId, auth.DeviceId) &&
string.Equals(i.Client, auth.Client) &&
string.Equals(i.ApplicationVersion, auth.Version));
}
/// <summary>
/// Posts the specified request.
/// </summary>
@ -744,7 +735,7 @@ namespace MediaBrowser.Api.UserLibrary
{
CanSeek = request.CanSeek,
Item = item,
SessionId = GetSession().Id,
SessionId = GetSession(_sessionManager).Id,
QueueableMediaTypes = queueableMediaTypes.Split(',').ToList(),
MediaSourceId = request.MediaSourceId
};
@ -768,7 +759,7 @@ namespace MediaBrowser.Api.UserLibrary
PositionTicks = request.PositionTicks,
IsMuted = request.IsMuted,
IsPaused = request.IsPaused,
SessionId = GetSession().Id,
SessionId = GetSession(_sessionManager).Id,
MediaSourceId = request.MediaSourceId
};
@ -787,7 +778,7 @@ namespace MediaBrowser.Api.UserLibrary
var item = _dtoService.GetItemByDtoId(request.Id, user.Id);
var session = GetSession();
var session = GetSession(_sessionManager);
var info = new PlaybackStopInfo
{
@ -817,7 +808,7 @@ namespace MediaBrowser.Api.UserLibrary
{
var user = _userManager.GetUserById(request.UserId);
var session = GetSession();
var session = GetSession(_sessionManager);
var dto = await UpdatePlayedStatus(user, request.Id, false, null).ConfigureAwait(false);

View File

@ -49,7 +49,7 @@ namespace MediaBrowser.Api.WebSocket
/// <returns>Task{SystemInfo}.</returns>
protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(object state)
{
return Task.FromResult(_sessionManager.Sessions.Select(_dtoService.GetSessionInfoDto));
return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_dtoService.GetSessionInfoDto));
}
}
}

View File

@ -69,8 +69,6 @@ namespace MediaBrowser.Controller.Dlna
VideoBitrate,
VideoFramerate,
VideoLevel,
VideoPacketLength,
VideoProfile,
VideoTimestamp
VideoProfile
}
}

View File

@ -121,10 +121,7 @@ namespace MediaBrowser.Controller.Entities
{
_configuration = value;
if (value == null)
{
_configurationInitialized = false;
}
_configurationInitialized = value != null;
}
}

View File

@ -241,7 +241,13 @@ namespace MediaBrowser.Dlna.PlayTo
_sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities
{
PlayableMediaTypes = new[] { MediaType.Audio, MediaType.Video, MediaType.Photo },
PlayableMediaTypes = new[]
{
MediaType.Audio,
MediaType.Video,
MediaType.Photo
},
SupportsFullscreenToggle = false
});

View File

@ -191,9 +191,7 @@ namespace MediaBrowser.Dlna.PlayTo
case ProfileConditionValue.AudioProfile:
case ProfileConditionValue.Has64BitOffsets:
case ProfileConditionValue.VideoBitDepth:
case ProfileConditionValue.VideoPacketLength:
case ProfileConditionValue.VideoProfile:
case ProfileConditionValue.VideoTimestamp:
{
// Not supported yet
break;
@ -461,12 +459,6 @@ namespace MediaBrowser.Dlna.PlayTo
return videoStream == null ? null : videoStream.Width;
case ProfileConditionValue.VideoLevel:
return videoStream == null ? null : ConvertToLong(videoStream.Level);
case ProfileConditionValue.VideoPacketLength:
// TODO: Determine how to get this
return null;
case ProfileConditionValue.VideoTimestamp:
// TODO: Determine how to get this
return null;
default:
throw new InvalidOperationException("Unexpected Property");
}

View File

@ -22,7 +22,11 @@ namespace MediaBrowser.Dlna.PlayTo
_config = config;
}
public async Task<XDocument> SendCommandAsync(string baseUrl, DeviceService service, string command, string postData, string header = null)
public async Task<XDocument> SendCommandAsync(string baseUrl,
DeviceService service,
string command,
string postData,
string header = null)
{
var serviceUrl = service.ControlUrl;
if (!serviceUrl.StartsWith("/"))
@ -40,7 +44,12 @@ namespace MediaBrowser.Dlna.PlayTo
}
}
public async Task SubscribeAsync(string url, string ip, int port, string localIp, int eventport, int timeOut = 3600)
public async Task SubscribeAsync(string url,
string ip,
int port,
string localIp,
int eventport,
int timeOut = 3600)
{
var options = new HttpRequestOptions
{
@ -59,7 +68,11 @@ namespace MediaBrowser.Dlna.PlayTo
}
}
public async Task RespondAsync(Uri url, string ip, int port, string localIp, int eventport, int timeOut = 20000)
public async Task RespondAsync(Uri url,
string ip,
int port,
string localIp,
int eventport)
{
var options = new HttpRequestOptions
{
@ -97,7 +110,10 @@ namespace MediaBrowser.Dlna.PlayTo
}
}
private Task<HttpResponseInfo> PostSoapDataAsync(string url, string soapAction, string postData, string header = null)
private Task<HttpResponseInfo> PostSoapDataAsync(string url,
string soapAction,
string postData,
string header = null)
{
if (!soapAction.StartsWith("\""))
soapAction = "\"" + soapAction + "\"";

View File

@ -1,8 +1,6 @@
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace MediaBrowser.Dlna.PlayTo
{

View File

@ -6,7 +6,7 @@ namespace MediaBrowser.Dlna.Profiles
{
public DefaultProfile()
{
Name = "Generic Device";
Name = "Media Browser";
ProtocolInfo = "DLNA";

View File

@ -96,13 +96,7 @@ namespace MediaBrowser.Dlna.Profiles
AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts",
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
Type = DlnaProfileType.Video,
Conditions = new []
{
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
}
Type = DlnaProfileType.Video
},
new MediaProfile
@ -112,12 +106,7 @@ namespace MediaBrowser.Dlna.Profiles
AudioCodec="ac3,aac,mp3",
MimeType = "video/mpeg",
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
Type = DlnaProfileType.Video,
Conditions = new []
{
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
}
Type = DlnaProfileType.Video
},
new MediaProfile

View File

@ -138,13 +138,7 @@ namespace MediaBrowser.Dlna.Profiles
AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts",
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
Type = DlnaProfileType.Video,
Conditions = new []
{
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
}
Type = DlnaProfileType.Video
},
new MediaProfile
@ -154,12 +148,7 @@ namespace MediaBrowser.Dlna.Profiles
AudioCodec="ac3,aac,mp3",
MimeType = "video/mpeg",
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
Type = DlnaProfileType.Video,
Conditions = new []
{
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
}
Type = DlnaProfileType.Video
},
new MediaProfile

View File

@ -126,13 +126,7 @@ namespace MediaBrowser.Dlna.Profiles
AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts",
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
Type = DlnaProfileType.Video,
Conditions = new []
{
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
}
Type = DlnaProfileType.Video
},
new MediaProfile
@ -142,12 +136,7 @@ namespace MediaBrowser.Dlna.Profiles
AudioCodec="ac3,aac,mp3",
MimeType = "video/mpeg",
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
Type = DlnaProfileType.Video,
Conditions = new []
{
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
}
Type = DlnaProfileType.Video
},
new MediaProfile

View File

@ -182,13 +182,7 @@ namespace MediaBrowser.Dlna.Profiles
AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts",
OrgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T",
Type = DlnaProfileType.Video,
Conditions = new []
{
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="192"},
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoTimestamp, Value="1"}
}
Type = DlnaProfileType.Video
},
new MediaProfile
@ -198,12 +192,7 @@ namespace MediaBrowser.Dlna.Profiles
AudioCodec="ac3,aac,mp3",
MimeType = "video/mpeg",
OrgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO",
Type = DlnaProfileType.Video,
Conditions = new []
{
new ProfileCondition{ Condition= ProfileConditionType.Equals, Property= ProfileConditionValue.VideoPacketLength, Value="188"}
}
Type = DlnaProfileType.Video
},
new MediaProfile

View File

@ -57,6 +57,12 @@ namespace MediaBrowser.Model.Configuration
/// <value>The item by name path.</value>
public string ItemsByNamePath { get; set; }
/// <summary>
/// Gets or sets the metadata path.
/// </summary>
/// <value>The metadata path.</value>
public string MetadataPath { get; set; }
/// <summary>
/// Gets or sets the display name of the season zero.
/// </summary>

View File

@ -52,6 +52,7 @@ namespace MediaBrowser.Model.Configuration
public bool EnableLiveTvAccess { get; set; }
public bool EnableMediaPlayback { get; set; }
public bool EnableContentDeletion { get; set; }
public string[] BlockedMediaFolders { get; set; }
@ -63,8 +64,9 @@ namespace MediaBrowser.Model.Configuration
public UserConfiguration()
{
IsAdministrator = true;
EnableRemoteControlOfOtherUsers = true;
EnableRemoteControlOfOtherUsers = true;
EnableContentDeletion = true;
EnableLiveTvManagement = true;
EnableMediaPlayback = true;
EnableLiveTvAccess = true;

View File

@ -148,7 +148,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (!string.IsNullOrWhiteSpace(composer))
{
foreach (var person in Split(composer))
foreach (var person in Split(composer, false))
{
audio.AddPerson(new PersonInfo { Name = person, Type = PersonType.Composer });
}
@ -221,12 +221,15 @@ namespace MediaBrowser.Providers.MediaInfo
/// Splits the specified val.
/// </summary>
/// <param name="val">The val.</param>
/// <param name="allowCommaDelimiter">if set to <c>true</c> [allow comma delimiter].</param>
/// <returns>System.String[][].</returns>
private IEnumerable<string> Split(string val)
private IEnumerable<string> Split(string val, bool allowCommaDelimiter)
{
// Only use the comma as a delimeter if there are no slashes or pipes.
// We want to be careful not to split names that have commas in them
var delimeter = _nameDelimiters.Any(i => val.IndexOf(i) != -1) ? _nameDelimiters : new[] { ',' };
var delimeter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i) != -1) ?
_nameDelimiters :
new[] { ',' };
return val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries)
.Where(i => !string.IsNullOrWhiteSpace(i))
@ -312,7 +315,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (!string.IsNullOrEmpty(val))
{
// Sometimes the artist name is listed here, account for that
var studios = Split(val).Where(i => !audio.HasArtist(i));
var studios = Split(val, true).Where(i => !audio.HasArtist(i));
foreach (var studio in studios)
{
@ -334,7 +337,7 @@ namespace MediaBrowser.Providers.MediaInfo
{
audio.Genres.Clear();
foreach (var genre in Split(val))
foreach (var genre in Split(val, true))
{
audio.AddGenre(genre);
}

View File

@ -26,6 +26,7 @@ namespace MediaBrowser.Server.Implementations.Configuration
{
UpdateItemsByNamePath();
UpdateTranscodingTempPath();
UpdateMetadataPath();
}
/// <summary>
@ -76,6 +77,16 @@ namespace MediaBrowser.Server.Implementations.Configuration
Configuration.ItemsByNamePath;
}
/// <summary>
/// Updates the metadata path.
/// </summary>
private void UpdateMetadataPath()
{
((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = string.IsNullOrEmpty(Configuration.MetadataPath) ?
null :
Configuration.MetadataPath;
}
/// <summary>
/// Updates the transcoding temporary path.
/// </summary>
@ -98,6 +109,7 @@ namespace MediaBrowser.Server.Implementations.Configuration
ValidateItemByNamePath(newConfig);
ValidateTranscodingTempPath(newConfig);
ValidatePathSubstitutions(newConfig);
ValidateMetadataPath(newConfig);
base.ReplaceConfiguration(newConfiguration);
}
@ -166,5 +178,25 @@ namespace MediaBrowser.Server.Implementations.Configuration
}
}
}
/// <summary>
/// Validates the metadata path.
/// </summary>
/// <param name="newConfig">The new configuration.</param>
/// <exception cref="System.IO.DirectoryNotFoundException"></exception>
private void ValidateMetadataPath(ServerConfiguration newConfig)
{
var newPath = newConfig.MetadataPath;
if (!string.IsNullOrWhiteSpace(newPath)
&& !string.Equals(Configuration.MetadataPath ?? string.Empty, newPath))
{
// Validate
if (!Directory.Exists(newPath))
{
throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath));
}
}
}
}
}

View File

@ -260,6 +260,8 @@ namespace MediaBrowser.Server.Implementations.Library
public event EventHandler<GenericEventArgs<User>> UserCreated;
private readonly SemaphoreSlim _userListLock = new SemaphoreSlim(1, 1);
/// <summary>
/// Creates the user.
/// </summary>
@ -279,6 +281,10 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentException(string.Format("A user with the name '{0}' already exists.", name));
}
await _userListLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
try
{
var user = InstantiateNewUser(name);
var list = Users.ToList();
@ -293,6 +299,11 @@ namespace MediaBrowser.Server.Implementations.Library
return user;
}
finally
{
_userListLock.Release();
}
}
/// <summary>
/// Deletes the user.
@ -325,6 +336,10 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentException(string.Format("The user '{0}' cannot be deleted because there must be at least one admin user in the system.", user.Name));
}
await _userListLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
try
{
await UserRepository.DeleteUser(user, CancellationToken.None).ConfigureAwait(false);
var path = user.ConfigurationFilePath;
@ -343,6 +358,11 @@ namespace MediaBrowser.Server.Implementations.Library
OnUserDeleted(user);
}
finally
{
_userListLock.Release();
}
}
/// <summary>
/// Resets the password by clearing it.

View File

@ -1,6 +1,6 @@
using System;
using MediaBrowser.Common.Implementations;
using MediaBrowser.Common.Implementations;
using MediaBrowser.Controller;
using System;
using System.IO;
namespace MediaBrowser.Server.Implementations
@ -239,14 +239,20 @@ namespace MediaBrowser.Server.Implementations
}
}
private string _internalMetadataPath;
public string InternalMetadataPath
{
get
{
return Path.Combine(DataPath, "metadata");
return _internalMetadataPath ?? (_internalMetadataPath = Path.Combine(DataPath, "metadata"));
}
set
{
_internalMetadataPath = value;
}
}
public string GetInternalMetadataPath(Guid id)
{
var idString = id.ToString("N");

View File

@ -795,7 +795,7 @@ namespace MediaBrowser.ServerApplication
list.Add(typeof(ApiEntryPoint).Assembly);
// Include composable parts in the Dashboard assembly
list.Add(typeof(DashboardInfo).Assembly);
list.Add(typeof(DashboardService).Assembly);
// Include composable parts in the Model assembly
list.Add(typeof(SystemInfo).Assembly);

View File

@ -1,39 +0,0 @@
using MediaBrowser.Model.Session;
using MediaBrowser.Model.System;
using MediaBrowser.Model.Tasks;
using System;
using System.Collections.Generic;
namespace MediaBrowser.WebDashboard.Api
{
/// <summary>
/// Class DashboardInfo
/// </summary>
public class DashboardInfo
{
/// <summary>
/// Gets or sets the system info.
/// </summary>
/// <value>The system info.</value>
public SystemInfo SystemInfo { get; set; }
/// <summary>
/// Gets or sets the running tasks.
/// </summary>
/// <value>The running tasks.</value>
public List<TaskInfo> RunningTasks { get; set; }
/// <summary>
/// Gets or sets the application update task id.
/// </summary>
/// <value>The application update task id.</value>
public Guid ApplicationUpdateTaskId { get; set; }
/// <summary>
/// Gets or sets the active connections.
/// </summary>
/// <value>The active connections.</value>
public List<SessionInfoDto> ActiveConnections { get; set; }
}
}

View File

@ -1,62 +0,0 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
using System.Threading.Tasks;
namespace MediaBrowser.WebDashboard.Api
{
/// <summary>
/// Class DashboardInfoWebSocketListener
/// </summary>
class DashboardInfoWebSocketListener : BasePeriodicWebSocketListener<DashboardInfo, object>
{
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
protected override string Name
{
get { return "DashboardInfo"; }
}
private readonly IServerApplicationHost _appHost;
/// <summary>
/// Gets or sets the task manager.
/// </summary>
/// <value>The task manager.</value>
private readonly ITaskManager _taskManager;
private readonly ISessionManager _sessionManager;
private readonly IDtoService _dtoService;
/// <summary>
/// Initializes a new instance of the <see cref="DashboardInfoWebSocketListener" /> class.
/// </summary>
/// <param name="appHost">The app host.</param>
/// <param name="logger">The logger.</param>
/// <param name="taskManager">The task manager.</param>
/// <param name="sessionManager">The session manager.</param>
public DashboardInfoWebSocketListener(IServerApplicationHost appHost, ILogger logger, ITaskManager taskManager, ISessionManager sessionManager, IDtoService dtoService)
: base(logger)
{
_appHost = appHost;
_taskManager = taskManager;
_sessionManager = sessionManager;
_dtoService = dtoService;
}
/// <summary>
/// Gets the data to send.
/// </summary>
/// <param name="state">The state.</param>
/// <returns>Task{IEnumerable{TaskInfo}}.</returns>
protected override Task<DashboardInfo> GetDataToSend(object state)
{
return Task.FromResult(DashboardService.GetDashboardInfo(_appHost, _taskManager, _sessionManager, _dtoService));
}
}
}

View File

@ -1,16 +1,13 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Tasks;
using ServiceStack;
using ServiceStack.Web;
using System;
using System.Collections.Generic;
using System.IO;
@ -18,7 +15,6 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using ServiceStack.Web;
namespace MediaBrowser.WebDashboard.Api
{
@ -66,14 +62,6 @@ namespace MediaBrowser.WebDashboard.Api
public string V { get; set; }
}
/// <summary>
/// Class GetDashboardInfo
/// </summary>
[Route("/dashboard/dashboardInfo", "GET")]
public class GetDashboardInfo : IReturn<DashboardInfo>
{
}
/// <summary>
/// Class DashboardService
/// </summary>
@ -97,12 +85,6 @@ namespace MediaBrowser.WebDashboard.Api
/// <value>The request context.</value>
public IRequest Request { get; set; }
/// <summary>
/// Gets or sets the task manager.
/// </summary>
/// <value>The task manager.</value>
private readonly ITaskManager _taskManager;
/// <summary>
/// The _app host
/// </summary>
@ -113,24 +95,18 @@ namespace MediaBrowser.WebDashboard.Api
/// </summary>
private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly ISessionManager _sessionManager;
private readonly IDtoService _dtoService;
private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="DashboardService" /> class.
/// </summary>
/// <param name="taskManager">The task manager.</param>
/// <param name="appHost">The app host.</param>
/// <param name="serverConfigurationManager">The server configuration manager.</param>
/// <param name="sessionManager">The session manager.</param>
public DashboardService(ITaskManager taskManager, IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, ISessionManager sessionManager, IDtoService dtoService, IFileSystem fileSystem)
/// <param name="fileSystem">The file system.</param>
public DashboardService(IServerApplicationHost appHost, IServerConfigurationManager serverConfigurationManager, IFileSystem fileSystem)
{
_taskManager = taskManager;
_appHost = appHost;
_serverConfigurationManager = serverConfigurationManager;
_sessionManager = sessionManager;
_dtoService = dtoService;
_fileSystem = fileSystem;
}
@ -163,45 +139,6 @@ namespace MediaBrowser.WebDashboard.Api
return Path.Combine(DashboardUIPath, virtualPath.Replace('/', Path.DirectorySeparatorChar));
}
/// <summary>
/// Gets the specified request.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>System.Object.</returns>
public object Get(GetDashboardInfo request)
{
var result = GetDashboardInfo(_appHost, _taskManager, _sessionManager, _dtoService);
return ResultFactory.GetOptimizedResult(Request, result);
}
/// <summary>
/// Gets the dashboard info.
/// </summary>
/// <param name="appHost">The app host.</param>
/// <param name="taskManager">The task manager.</param>
/// <param name="connectionManager">The connection manager.</param>
/// <returns>DashboardInfo.</returns>
public static DashboardInfo GetDashboardInfo(IServerApplicationHost appHost,
ITaskManager taskManager,
ISessionManager connectionManager, IDtoService dtoService)
{
var connections = connectionManager.Sessions.Where(i => i.IsActive).ToList();
return new DashboardInfo
{
SystemInfo = appHost.GetSystemInfo(),
RunningTasks = taskManager.ScheduledTasks.Where(i => i.State == TaskState.Running || i.State == TaskState.Cancelling)
.Select(ScheduledTaskHelpers.GetTaskInfo)
.ToList(),
ApplicationUpdateTaskId = taskManager.ScheduledTasks.First(t => t.ScheduledTask.GetType().Name.Equals("SystemUpdateTask", StringComparison.OrdinalIgnoreCase)).Id,
ActiveConnections = connections.Select(dtoService.GetSessionInfoDto).ToList()
};
}
/// <summary>
/// Gets the specified request.
/// </summary>
@ -473,6 +410,7 @@ namespace MediaBrowser.WebDashboard.Api
"alphapicker.js",
"addpluginpage.js",
"advancedconfigurationpage.js",
"advancedpaths.js",
"advancedserversettings.js",
"metadataadvanced.js",
"appsplayback.js",

View File

@ -63,9 +63,7 @@
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="Api\ConfigurationPageInfo.cs" />
<Compile Include="Api\DashboardInfo.cs" />
<Compile Include="Api\DashboardService.cs" />
<Compile Include="Api\DashboardInfoWebSocketListener.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServerEntryPoint.cs" />
</ItemGroup>
@ -85,6 +83,9 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ApiClient.js" />
<Content Include="dashboard-ui\advancedpaths.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\advancedserversettings.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -483,6 +484,9 @@
<Content Include="dashboard-ui\livetvrecordings.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\advancedpaths.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\advancedserversettings.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>