aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS.md45
-rw-r--r--MediaBrowser.Api/ItemUpdateService.cs7
-rw-r--r--MediaBrowser.Api/NotificationsService.cs56
-rw-r--r--MediaBrowser.Api/PackageService.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/ItemByNameUserDataService.cs40
-rw-r--r--MediaBrowser.Api/UserLibrary/UserLibraryService.cs136
-rw-r--r--MediaBrowser.Controller/Dto/DtoBuilder.cs10
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs6
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs25
-rw-r--r--MediaBrowser.Controller/Entities/CollectionFolder.cs19
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs44
-rw-r--r--MediaBrowser.Controller/IO/FileData.cs6
-rw-r--r--MediaBrowser.Controller/Providers/BaseItemXmlParser.cs36
-rw-r--r--MediaBrowser.Model/ApiClient/ApiClientExtensions.cs6
-rw-r--r--MediaBrowser.Model/ApiClient/IApiClient.cs28
-rw-r--r--MediaBrowser.Model/Entities/MetadataProviders.cs3
-rw-r--r--MediaBrowser.Providers/ImageFromMediaLocationProvider.cs3
-rw-r--r--MediaBrowser.Providers/Movies/FanArtMovieProvider.cs31
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbProvider.cs310
-rw-r--r--MediaBrowser.Providers/Movies/MovieProviderFromXml.cs11
-rw-r--r--MediaBrowser.Providers/Movies/TmdbPersonProvider.cs5
-rw-r--r--MediaBrowser.Providers/Music/FanArtAlbumProvider.cs15
-rw-r--r--MediaBrowser.Providers/Savers/MovieXmlSaver.cs11
-rw-r--r--MediaBrowser.Providers/Savers/XmlSaverHelpers.cs11
-rw-r--r--MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs50
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs2
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj2
-rw-r--r--MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs80
-rw-r--r--MediaBrowser.Server.Implementations/MediaEncoder/fonts/fonts.conf9
-rw-r--r--MediaBrowser.ServerApplication/ApplicationHost.cs6
-rw-r--r--MediaBrowser.WebDashboard/Api/DashboardService.cs4
-rw-r--r--MediaBrowser.WebDashboard/ApiClient.js66
-rw-r--r--MediaBrowser.WebDashboard/packages.config2
-rw-r--r--MediaBrowser.sln3
-rw-r--r--Nuget/MediaBrowser.Common.Internal.nuspec4
-rw-r--r--Nuget/MediaBrowser.Common.nuspec2
-rw-r--r--Nuget/MediaBrowser.Server.Core.nuspec4
-rw-r--r--README.md2
38 files changed, 483 insertions, 619 deletions
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
new file mode 100644
index 000000000..035939f70
--- /dev/null
+++ b/CONTRIBUTORS.md
@@ -0,0 +1,45 @@
+# Contributors
+
+ - [LukePulverenti](https://github.com/LukePulverenti)
+ - [ebr11](https://github.com/ebr11)
+ - [lalmanzar](https://github.com/lalmanzar)
+ - [schneifu](https://github.com/schneifu)
+ - [Mark2xv](https://github.com/Mark2xv)
+ - [ScottRapsey](https://github.com/ScottRapsey)
+ - [skynet600](https://github.com/skynet600)
+ - [Cheesegeezer](https://githum.com/Cheesegeezer)
+ - [Radeon](https://github.com/radeonorama)
+ - [gcw07](https://github.com/gcw07)
+ - [SivaramAdhiappan](https://github.com/shivaram1190)
+ - [CWatkinsNash](https://github.com/CWatkinsNash)
+ - [sfnetwork](https://github.com/sfnetwork)
+ - [Logos302] (https://github.com/Logos302)
+ - [TheWorkz](https://github.com/TheWorkz)
+ - [mboehler](https://github.com/mboehler)
+ - [KaHooli](https://github.com/KaHooli)
+ - [xzener](https://github.com/xzener)
+ - [CBers] (https://github.com/CBers)
+ - [Sagaia] (https://github.com/Sagaia)
+ - [JHawk111](https://github.com/JHawk111)
+ - [David3663](https://github.com/david3663)
+ - [Smyken](https://github.com/Smyken)
+ - [doron1] (https://github.com/doron1)
+ - [brainfryd] (https://github.com/brainfryd)
+ - [DGMayor] (http://github.com/DGMayor)
+ - [Jon-theHTPC] (https://github.com/Jon-theHTPC)
+ - [aspdend] (https://github.com/aspdend)
+ - [RedshirtMB](https://github.com/RedshirtMB)
+ - [thealienamongus](https://github.com/thealienamongus)
+ - [brocass](https://github.com/brocass)
+ - [pjrollo2000](https://github.com/pjrollo2000)
+ - [abobader](https://github.com/abobader)
+ - [milli260876](https://github.com/milli260876)
+ - [vileboy] (https://github.com/vileboy)
+ - [starkadius] (https://github.com/starkadius)
+ - [wraslor](https://github.com/wraslor)
+ - [mrwebsmith](https://github.com/mrwebsmith)
+ - [rickster53](https://github.com/rickster53)
+ - [Tharnax] (https://github.com/Tharnax)
+ - [0sm0] (https://github.com/0sm0)
+ - [swhitmore](https://github.com/swhitmore)
+ - [DigiTM](https://github.com/DigiTM) \ No newline at end of file
diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs
index 54b2c0ea7..09e175e30 100644
--- a/MediaBrowser.Api/ItemUpdateService.cs
+++ b/MediaBrowser.Api/ItemUpdateService.cs
@@ -273,13 +273,6 @@ namespace MediaBrowser.Api
song.Artist = request.Artists[0];
}
- var musicAlbum = item as MusicAlbum;
-
- if (musicAlbum != null)
- {
- musicAlbum.MusicBrainzReleaseGroupId = request.GetProviderId("MusicBrainzReleaseGroupId");
- }
-
var musicVideo = item as MusicVideo;
if (musicVideo != null)
diff --git a/MediaBrowser.Api/NotificationsService.cs b/MediaBrowser.Api/NotificationsService.cs
index 2d1ecc231..319cb996b 100644
--- a/MediaBrowser.Api/NotificationsService.cs
+++ b/MediaBrowser.Api/NotificationsService.cs
@@ -52,36 +52,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Url", Description = "The notification's info url", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public string Url { get; set; }
- [ApiMember(Name = "Category", Description = "The notification's category", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Category { get; set; }
-
- [ApiMember(Name = "RelatedId", Description = "The notification's related id (item)", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string RelatedId { get; set; }
-
- [ApiMember(Name = "Level", Description = "The notification level", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public NotificationLevel Level { get; set; }
- }
-
- [Route("/Notifications/{UserId}/{Id}", "POST")]
- [Api(Description = "Updates a notifications")]
- public class UpdateNotification : IReturnVoid
- {
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
-
- [ApiMember(Name = "Name", Description = "The notification's name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Name { get; set; }
-
- [ApiMember(Name = "Description", Description = "The notification's description", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Description { get; set; }
-
- [ApiMember(Name = "Url", Description = "The notification's info url", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Url { get; set; }
-
- [ApiMember(Name = "Category", Description = "The notification's category", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ [ApiMember(Name = "Category", Description = "The notification's category", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
public string Category { get; set; }
[ApiMember(Name = "RelatedId", Description = "The notification's related id (item)", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
@@ -129,13 +100,6 @@ namespace MediaBrowser.Api
return ToOptimizedResult(task.Result);
}
- public void Post(UpdateNotification request)
- {
- var task = UpdateNotification(request);
-
- Task.WaitAll(task);
- }
-
public object Get(GetNotificationsSummary request)
{
var result = _notificationsRepo.GetNotificationsSummary(request.UserId);
@@ -163,24 +127,6 @@ namespace MediaBrowser.Api
return notification;
}
- private Task UpdateNotification(UpdateNotification request)
- {
- var notification = _notificationsRepo.GetNotification(request.Id, request.UserId);
-
- notification.Description = request.Description;
- notification.Level = request.Level;
- notification.Url = request.Url;
-
- notification.Date = DateTime.UtcNow;
-
- notification.RelatedId = request.RelatedId;
- notification.Category = request.Category;
-
- notification.Name = request.Name;
-
- return _notificationsRepo.UpdateNotification(notification, CancellationToken.None);
- }
-
public void Post(MarkRead request)
{
var task = MarkRead(request.Ids, request.UserId, true);
diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs
index 7e6444e16..563625a54 100644
--- a/MediaBrowser.Api/PackageService.cs
+++ b/MediaBrowser.Api/PackageService.cs
@@ -43,7 +43,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "TargetSystems", Description = "Optional. Filter by target system type. Allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET", AllowMultiple = true)]
public string TargetSystems { get; set; }
- [ApiMember(Name = "IsPremium", Description = "Optiona. Filter by premium status", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
+ [ApiMember(Name = "IsPremium", Description = "Optional. Filter by premium status", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
public bool? IsPremium { get; set; }
}
diff --git a/MediaBrowser.Api/UserLibrary/ItemByNameUserDataService.cs b/MediaBrowser.Api/UserLibrary/ItemByNameUserDataService.cs
index 4196db497..1e990b3e9 100644
--- a/MediaBrowser.Api/UserLibrary/ItemByNameUserDataService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemByNameUserDataService.cs
@@ -1,5 +1,7 @@
-using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Dto;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using System;
@@ -18,7 +20,7 @@ namespace MediaBrowser.Api.UserLibrary
[Route("/Users/{UserId}/Favorites/MusicGenres/{Name}", "POST")]
[Route("/Users/{UserId}/Favorites/GameGenres/{Name}", "POST")]
[Api(Description = "Marks something as a favorite")]
- public class MarkItemByNameFavorite : IReturnVoid
+ public class MarkItemByNameFavorite : IReturn<UserItemDataDto>
{
/// <summary>
/// Gets or sets the user id.
@@ -45,7 +47,7 @@ namespace MediaBrowser.Api.UserLibrary
[Route("/Users/{UserId}/Favorites/MusicGenres/{Name}", "DELETE")]
[Route("/Users/{UserId}/Favorites/GameGenres/{Name}", "DELETE")]
[Api(Description = "Unmarks something as a favorite")]
- public class UnmarkItemByNameFavorite : IReturnVoid
+ public class UnmarkItemByNameFavorite : IReturn<UserItemDataDto>
{
/// <summary>
/// Gets or sets the user id.
@@ -71,7 +73,7 @@ namespace MediaBrowser.Api.UserLibrary
[Route("/Users/{UserId}/Ratings/Genres/{Name}", "POST")]
[Route("/Users/{UserId}/Ratings/MusicGenres/{Name}", "POST")]
[Api(Description = "Updates a user's rating for an item")]
- public class UpdateItemByNameRating : IReturnVoid
+ public class UpdateItemByNameRating : IReturn<UserItemDataDto>
{
/// <summary>
/// Gets or sets the user id.
@@ -105,7 +107,7 @@ namespace MediaBrowser.Api.UserLibrary
[Route("/Users/{UserId}/Ratings/MusicGenres/{Name}", "DELETE")]
[Route("/Users/{UserId}/Ratings/GameGenres/{Name}", "DELETE")]
[Api(Description = "Deletes a user's saved personal rating for an item")]
- public class DeleteItemByNameRating : IReturnVoid
+ public class DeleteItemByNameRating : IReturn<UserItemDataDto>
{
/// <summary>
/// Gets or sets the user id.
@@ -152,56 +154,56 @@ namespace MediaBrowser.Api.UserLibrary
/// Posts the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(MarkItemByNameFavorite request)
+ public object Post(MarkItemByNameFavorite request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var type = pathInfo.GetArgumentValue<string>(3);
var task = MarkFavorite(request.UserId, type, request.Name, true);
- Task.WaitAll(task);
+ return ToOptimizedResult(task.Result);
}
/// <summary>
/// Posts the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(UpdateItemByNameRating request)
+ public object Post(UpdateItemByNameRating request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var type = pathInfo.GetArgumentValue<string>(3);
var task = MarkLike(request.UserId, type, request.Name, request.Likes);
- Task.WaitAll(task);
+ return ToOptimizedResult(task.Result);
}
/// <summary>
/// Deletes the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Delete(UnmarkItemByNameFavorite request)
+ public object Delete(UnmarkItemByNameFavorite request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var type = pathInfo.GetArgumentValue<string>(3);
var task = MarkFavorite(request.UserId, type, request.Name, false);
- Task.WaitAll(task);
+ return ToOptimizedResult(task.Result);
}
/// <summary>
/// Deletes the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Delete(DeleteItemByNameRating request)
+ public object Delete(DeleteItemByNameRating request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var type = pathInfo.GetArgumentValue<string>(3);
var task = MarkLike(request.UserId, type, request.Name, null);
- Task.WaitAll(task);
+ return ToOptimizedResult(task.Result);
}
/// <summary>
@@ -212,7 +214,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <param name="name">The name.</param>
/// <param name="isFavorite">if set to <c>true</c> [is favorite].</param>
/// <returns>Task.</returns>
- protected async Task MarkFavorite(Guid userId, string type, string name, bool isFavorite)
+ protected async Task<UserItemDataDto> MarkFavorite(Guid userId, string type, string name, bool isFavorite)
{
var item = await GetItemByName(name, type, LibraryManager).ConfigureAwait(false);
@@ -225,6 +227,10 @@ namespace MediaBrowser.Api.UserLibrary
data.IsFavorite = isFavorite;
await UserDataRepository.SaveUserData(userId, key, data, CancellationToken.None).ConfigureAwait(false);
+
+ data = UserDataRepository.GetUserData(userId, key);
+
+ return DtoBuilder.GetUserItemDataDto(data);
}
/// <summary>
@@ -235,7 +241,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <param name="name">The name.</param>
/// <param name="likes">if set to <c>true</c> [likes].</param>
/// <returns>Task.</returns>
- protected async Task MarkLike(Guid userId, string type, string name, bool? likes)
+ protected async Task<UserItemDataDto> MarkLike(Guid userId, string type, string name, bool? likes)
{
var item = await GetItemByName(name, type, LibraryManager).ConfigureAwait(false);
@@ -247,6 +253,10 @@ namespace MediaBrowser.Api.UserLibrary
data.Likes = likes;
await UserDataRepository.SaveUserData(userId, key, data, CancellationToken.None).ConfigureAwait(false);
+
+ data = UserDataRepository.GetUserData(userId, key);
+
+ return DtoBuilder.GetUserItemDataDto(data);
}
}
}
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index 46254435f..304ff27d0 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -79,7 +79,7 @@ namespace MediaBrowser.Api.UserLibrary
/// </summary>
[Route("/Users/{UserId}/FavoriteItems/{Id}", "POST")]
[Api(Description = "Marks an item as a favorite")]
- public class MarkFavoriteItem : IReturnVoid
+ public class MarkFavoriteItem : IReturn<UserItemDataDto>
{
/// <summary>
/// Gets or sets the user id.
@@ -101,7 +101,7 @@ namespace MediaBrowser.Api.UserLibrary
/// </summary>
[Route("/Users/{UserId}/FavoriteItems/{Id}", "DELETE")]
[Api(Description = "Unmarks an item as a favorite")]
- public class UnmarkFavoriteItem : IReturnVoid
+ public class UnmarkFavoriteItem : IReturn<UserItemDataDto>
{
/// <summary>
/// Gets or sets the user id.
@@ -123,7 +123,7 @@ namespace MediaBrowser.Api.UserLibrary
/// </summary>
[Route("/Users/{UserId}/Items/{Id}/Rating", "DELETE")]
[Api(Description = "Deletes a user's saved personal rating for an item")]
- public class DeleteUserItemRating : IReturnVoid
+ public class DeleteUserItemRating : IReturn<UserItemDataDto>
{
/// <summary>
/// Gets or sets the user id.
@@ -145,7 +145,7 @@ namespace MediaBrowser.Api.UserLibrary
/// </summary>
[Route("/Users/{UserId}/Items/{Id}/Rating", "POST")]
[Api(Description = "Updates a user's rating for an item")]
- public class UpdateUserItemRating : IReturnVoid
+ public class UpdateUserItemRating : IReturn<UserItemDataDto>
{
/// <summary>
/// Gets or sets the user id.
@@ -174,7 +174,7 @@ namespace MediaBrowser.Api.UserLibrary
/// </summary>
[Route("/Users/{UserId}/PlayedItems/{Id}", "POST")]
[Api(Description = "Marks an item as played")]
- public class MarkPlayedItem : IReturnVoid
+ public class MarkPlayedItem : IReturn<UserItemDataDto>
{
/// <summary>
/// Gets or sets the user id.
@@ -196,7 +196,7 @@ namespace MediaBrowser.Api.UserLibrary
/// </summary>
[Route("/Users/{UserId}/PlayedItems/{Id}", "DELETE")]
[Api(Description = "Marks an item as unplayed")]
- public class MarkUnplayedItem : IReturnVoid
+ public class MarkUnplayedItem : IReturn<UserItemDataDto>
{
/// <summary>
/// Gets or sets the user id.
@@ -372,7 +372,6 @@ namespace MediaBrowser.Api.UserLibrary
/// <param name="itemRepo">The item repo.</param>
/// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
public UserLibraryService(IUserManager userManager, ILibraryManager libraryManager, IUserDataRepository userDataRepository, IItemRepository itemRepo, ISessionManager sessionManager)
- : base()
{
_userManager = userManager;
_libraryManager = libraryManager;
@@ -388,6 +387,13 @@ namespace MediaBrowser.Api.UserLibrary
/// <returns>System.Object.</returns>
public object Get(GetSpecialFeatures request)
{
+ var result = GetAsync(request).Result;
+
+ return ToOptimizedResult(result);
+ }
+
+ private Task<BaseItemDto[]> GetAsync(GetSpecialFeatures request)
+ {
var user = _userManager.GetUserById(request.UserId);
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
@@ -399,14 +405,12 @@ namespace MediaBrowser.Api.UserLibrary
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userDataRepository, _itemRepo);
- var items = movie.SpecialFeatureIds
+ var tasks = movie.SpecialFeatureIds
.Select(_itemRepo.RetrieveItem)
.OrderBy(i => i.SortName)
- .Select(i => dtoBuilder.GetBaseItemDto(i, fields, user, movie))
- .Select(t => t.Result)
- .ToList();
+ .Select(i => dtoBuilder.GetBaseItemDto(i, fields, user, movie));
- return ToOptimizedResult(items);
+ return Task.WhenAll(tasks);
}
/// <summary>
@@ -416,6 +420,13 @@ namespace MediaBrowser.Api.UserLibrary
/// <returns>System.Object.</returns>
public object Get(GetLocalTrailers request)
{
+ var result = GetAsync(request).Result;
+
+ return ToOptimizedResult(result);
+ }
+
+ private Task<BaseItemDto[]> GetAsync(GetLocalTrailers request)
+ {
var user = _userManager.GetUserById(request.UserId);
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
@@ -425,14 +436,12 @@ namespace MediaBrowser.Api.UserLibrary
var dtoBuilder = new DtoBuilder(Logger, _libraryManager, _userDataRepository, _itemRepo);
- var items = item.LocalTrailerIds
+ var tasks = item.LocalTrailerIds
.Select(_itemRepo.RetrieveItem)
.OrderBy(i => i.SortName)
- .Select(i => dtoBuilder.GetBaseItemDto(i, fields, user, item))
- .Select(t => t.Result)
- .ToList();
+ .Select(i => dtoBuilder.GetBaseItemDto(i, fields, user, item));
- return ToOptimizedResult(items);
+ return Task.WhenAll(tasks);
}
/// <summary>
@@ -497,34 +506,29 @@ namespace MediaBrowser.Api.UserLibrary
/// Posts the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(MarkFavoriteItem request)
+ public object Post(MarkFavoriteItem request)
{
- var user = _userManager.GetUserById(request.UserId);
+ var dto = MarkFavorite(request.UserId, request.Id, true).Result;
- var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
-
- // Get the user data for this item
- var key = item.GetUserDataKey();
-
- var data = _userDataRepository.GetUserData(user.Id, key);
-
- // Set favorite status
- data.IsFavorite = true;
-
- var task = _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None);
-
- Task.WaitAll(task);
+ return ToOptimizedResult(dto);
}
/// <summary>
/// Deletes the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Delete(UnmarkFavoriteItem request)
+ public object Delete(UnmarkFavoriteItem request)
{
- var user = _userManager.GetUserById(request.UserId);
+ var dto = MarkFavorite(request.UserId, request.Id, false).Result;
- var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
+ return ToOptimizedResult(dto);
+ }
+
+ private async Task<UserItemDataDto> MarkFavorite(Guid userId, string itemId, bool isFavorite)
+ {
+ var user = _userManager.GetUserById(userId);
+
+ var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : DtoBuilder.GetItemByClientId(itemId, _userManager, _libraryManager, user.Id);
var key = item.GetUserDataKey();
@@ -532,68 +536,68 @@ namespace MediaBrowser.Api.UserLibrary
var data = _userDataRepository.GetUserData(user.Id, key);
// Set favorite status
- data.IsFavorite = false;
+ data.IsFavorite = isFavorite;
- var task = _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None);
+ await _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false);
- Task.WaitAll(task);
+ data = _userDataRepository.GetUserData(user.Id, key);
+
+ return DtoBuilder.GetUserItemDataDto(data);
}
/// <summary>
/// Deletes the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Delete(DeleteUserItemRating request)
+ public object Delete(DeleteUserItemRating request)
{
- var user = _userManager.GetUserById(request.UserId);
-
- var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
-
- var key = item.GetUserDataKey();
-
- // Get the user data for this item
- var data = _userDataRepository.GetUserData(user.Id, key);
-
- data.Rating = null;
-
- var task = _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None);
+ var dto = UpdateUserItemRating(request.UserId, request.Id, null).Result;
- Task.WaitAll(task);
+ return ToOptimizedResult(dto);
}
/// <summary>
/// Posts the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(UpdateUserItemRating request)
+ public object Post(UpdateUserItemRating request)
{
- var user = _userManager.GetUserById(request.UserId);
+ var dto = UpdateUserItemRating(request.UserId, request.Id, request.Likes).Result;
- var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
+ return ToOptimizedResult(dto);
+ }
+
+ private async Task<UserItemDataDto> UpdateUserItemRating(Guid userId, string itemId, bool? likes)
+ {
+ var user = _userManager.GetUserById(userId);
+
+ var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : DtoBuilder.GetItemByClientId(itemId, _userManager, _libraryManager, user.Id);
var key = item.GetUserDataKey();
// Get the user data for this item
var data = _userDataRepository.GetUserData(user.Id, key);
- data.Likes = request.Likes;
+ data.Likes = likes;
- var task = _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None);
+ await _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false);
- Task.WaitAll(task);
- }
+ data = _userDataRepository.GetUserData(user.Id, key);
+ return DtoBuilder.GetUserItemDataDto(data);
+ }
+
/// <summary>
/// Posts the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(MarkPlayedItem request)
+ public object Post(MarkPlayedItem request)
{
var user = _userManager.GetUserById(request.UserId);
var task = UpdatePlayedStatus(user, request.Id, true);
- Task.WaitAll(task);
+ return ToOptimizedResult(task.Result);
}
private SessionInfo GetSession()
@@ -660,13 +664,13 @@ namespace MediaBrowser.Api.UserLibrary
/// Deletes the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Delete(MarkUnplayedItem request)
+ public object Delete(MarkUnplayedItem request)
{
var user = _userManager.GetUserById(request.UserId);
var task = UpdatePlayedStatus(user, request.Id, false);
- Task.WaitAll(task);
+ return ToOptimizedResult(task.Result);
}
/// <summary>
@@ -676,11 +680,13 @@ namespace MediaBrowser.Api.UserLibrary
/// <param name="itemId">The item id.</param>
/// <param name="wasPlayed">if set to <c>true</c> [was played].</param>
/// <returns>Task.</returns>
- private Task UpdatePlayedStatus(User user, string itemId, bool wasPlayed)
+ private async Task<UserItemDataDto> UpdatePlayedStatus(User user, string itemId, bool wasPlayed)
{
var item = DtoBuilder.GetItemByClientId(itemId, _userManager, _libraryManager, user.Id);
- return item.SetPlayedStatus(user, wasPlayed, _userDataRepository);
+ await item.SetPlayedStatus(user, wasPlayed, _userDataRepository).ConfigureAwait(false);
+
+ return DtoBuilder.GetUserItemDataDto(_userDataRepository.GetUserData(user.Id, item.GetUserDataKey()));
}
}
}
diff --git a/MediaBrowser.Controller/Dto/DtoBuilder.cs b/MediaBrowser.Controller/Dto/DtoBuilder.cs
index 85d2a2003..b2b858b6d 100644
--- a/MediaBrowser.Controller/Dto/DtoBuilder.cs
+++ b/MediaBrowser.Controller/Dto/DtoBuilder.cs
@@ -90,6 +90,11 @@ namespace MediaBrowser.Controller.Dto
}
}
+ if (fields.Contains(ItemFields.DisplayPreferencesId))
+ {
+ dto.DisplayPreferencesId = item.DisplayPreferencesId.ToString("N");
+ }
+
if (user != null)
{
AttachUserSpecificInfo(dto, item, user, fields);
@@ -272,11 +277,6 @@ namespace MediaBrowser.Controller.Dto
/// <param name="fields">The fields.</param>
private void AttachUserSpecificInfo(BaseItemDto dto, BaseItem item, User user, List<ItemFields> fields)
{
- if (item.IsFolder && fields.Contains(ItemFields.DisplayPreferencesId))
- {
- dto.DisplayPreferencesId = ((Folder) item).DisplayPreferencesId.ToString("N");
- }
-
if (item.IsFolder)
{
var hasItemCounts = fields.Contains(ItemFields.ItemCounts);
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index 1526cf46a..1668b91d4 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -91,11 +91,5 @@ namespace MediaBrowser.Controller.Entities.Audio
{
return RecursiveChildren.OfType<Audio>().Any(i => i.HasArtist(artist));
}
-
- /// <summary>
- /// Gets or sets the music brainz release group id.
- /// </summary>
- /// <value>The music brainz release group id.</value>
- public string MusicBrainzReleaseGroupId { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index cc2e82b1f..a75dc47e1 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization;
@@ -84,6 +85,21 @@ namespace MediaBrowser.Controller.Entities
public Guid Id { get; set; }
/// <summary>
+ /// Return the id that should be used to key display prefs for this item.
+ /// Default is based on the type for everything except actual generic folders.
+ /// </summary>
+ /// <value>The display prefs id.</value>
+ [IgnoreDataMember]
+ public virtual Guid DisplayPreferencesId
+ {
+ get
+ {
+ var thisType = GetType();
+ return thisType == typeof(Folder) ? Id : thisType.FullName.GetMD5();
+ }
+ }
+
+ /// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
@@ -393,7 +409,12 @@ namespace MediaBrowser.Controller.Entities
{
get
{
- return ForcedSortName ?? _sortName ?? (_sortName = CreateSortName());
+ if (!string.IsNullOrEmpty(ForcedSortName))
+ {
+ return ForcedSortName;
+ }
+
+ return _sortName ?? (_sortName = CreateSortName());
}
}
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index b080478b8..9682ea8c2 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Controller.Library;
-using System;
+using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
@@ -75,11 +74,11 @@ namespace MediaBrowser.Controller.Entities
{
get
{
- ItemResolveArgs resolveArgs;
+ Dictionary<string, string> locationsDicionary;
try
{
- resolveArgs = ResolveArgs;
+ locationsDicionary = ResolveArgs.PhysicalLocations.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
}
catch (IOException ex)
{
@@ -87,9 +86,9 @@ namespace MediaBrowser.Controller.Entities
return new List<LinkedChild>();
}
- return LibraryManager.RootFolder.RecursiveChildren
+ return LibraryManager.RootFolder.Children
.OfType<Folder>()
- .Where(i => i.Path != null && resolveArgs.PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase))
+ .Where(i => i.Path != null && locationsDicionary.ContainsKey(i.Path))
.SelectMany(c => c.LinkedChildren).ToList();
}
@@ -107,11 +106,11 @@ namespace MediaBrowser.Controller.Entities
{
get
{
- ItemResolveArgs resolveArgs;
+ Dictionary<string, string> locationsDicionary;
try
{
- resolveArgs = ResolveArgs;
+ locationsDicionary = ResolveArgs.PhysicalLocations.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
}
catch (IOException ex)
{
@@ -120,9 +119,9 @@ namespace MediaBrowser.Controller.Entities
}
var ourChildren =
- LibraryManager.RootFolder.RecursiveChildren
+ LibraryManager.RootFolder.Children
.OfType<Folder>()
- .Where(i => i.Path != null && resolveArgs.PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase))
+ .Where(i => i.Path != null && locationsDicionary.ContainsKey(i.Path))
.SelectMany(c => c.Children);
return new ConcurrentDictionary<Guid, BaseItem>(ourChildren.ToDictionary(i => i.Id));
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index ca43ca616..91f4504c2 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -16,6 +16,7 @@ using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using MoreLinq;
namespace MediaBrowser.Controller.Entities
{
@@ -66,21 +67,6 @@ namespace MediaBrowser.Controller.Entities
}
}
- /// <summary>
- /// Return the id that should be used to key display prefs for this item.
- /// Default is based on the type for everything except actual generic folders.
- /// </summary>
- /// <value>The display prefs id.</value>
- [IgnoreDataMember]
- public virtual Guid DisplayPreferencesId
- {
- get
- {
- var thisType = GetType();
- return thisType == typeof(Folder) ? Id : thisType.FullName.GetMD5();
- }
- }
-
public virtual List<LinkedChild> LinkedChildren { get; set; }
protected virtual bool SupportsShortcutChildren
@@ -974,7 +960,31 @@ namespace MediaBrowser.Controller.Entities
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <returns>IEnumerable{BaseItem}.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
- public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = false)
+ public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
+ {
+ if (user == null)
+ {
+ throw new ArgumentNullException();
+ }
+
+ var children = GetRecursiveChildrenInternal(user, includeLinkedChildren);
+
+ if (includeLinkedChildren)
+ {
+ children = children.DistinctBy(i => i.Id);
+ }
+
+ return children;
+ }
+
+ /// <summary>
+ /// Gets allowed recursive children of an item
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
+ /// <returns>IEnumerable{BaseItem}.</returns>
+ /// <exception cref="System.ArgumentNullException"></exception>
+ private IEnumerable<BaseItem> GetRecursiveChildrenInternal(User user, bool includeLinkedChildren)
{
if (user == null)
{
@@ -989,7 +999,7 @@ namespace MediaBrowser.Controller.Entities
if (subFolder != null)
{
- foreach (var subitem in subFolder.GetRecursiveChildren(user, includeLinkedChildren))
+ foreach (var subitem in subFolder.GetRecursiveChildrenInternal(user, includeLinkedChildren))
{
yield return subitem;
}
diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs
index c1ca5336b..dc2b49c75 100644
--- a/MediaBrowser.Controller/IO/FileData.cs
+++ b/MediaBrowser.Controller/IO/FileData.cs
@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using MoreLinq;
namespace MediaBrowser.Controller.IO
{
@@ -38,7 +39,10 @@ namespace MediaBrowser.Controller.IO
if (!resolveShortcuts && flattenFolderDepth == 0)
{
- return entries.ToDictionary(i => i.FullName, StringComparer.OrdinalIgnoreCase);
+ // Seeing dupes on some users file system for some reason
+ return entries
+ .DistinctBy(i => i.FullName, StringComparer.OrdinalIgnoreCase)
+ .ToDictionary(i => i.FullName, StringComparer.OrdinalIgnoreCase);
}
var dict = new Dictionary<string, FileSystemInfo>(StringComparer.OrdinalIgnoreCase);
diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
index 2761c51e0..ba4f84ac2 100644
--- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
+++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
@@ -173,8 +173,16 @@ namespace MediaBrowser.Controller.Providers
break;
}
case "SortTitle":
- item.ForcedSortName = reader.ReadElementContentAsString();
- break;
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.ForcedSortName = val;
+ }
+
+ break;
+ }
case "Overview":
case "Description":
@@ -503,7 +511,7 @@ namespace MediaBrowser.Controller.Providers
{
DateTime airDate;
- if (DateTime.TryParse(firstAired, out airDate) && airDate.Year > 1850)
+ if (DateTime.TryParseExact(firstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out airDate) && airDate.Year > 1850)
{
item.PremiereDate = airDate.ToUniversalTime();
item.ProductionYear = airDate.Year;
@@ -522,7 +530,7 @@ namespace MediaBrowser.Controller.Providers
{
DateTime airDate;
- if (DateTime.TryParse(firstAired, out airDate) && airDate.Year > 1850)
+ if (DateTime.TryParseExact(firstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out airDate) && airDate.Year > 1850)
{
item.EndDate = airDate.ToUniversalTime();
}
@@ -548,13 +556,23 @@ namespace MediaBrowser.Controller.Providers
break;
case "MusicbrainzId":
- var mbz = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(mbz))
{
- item.SetProviderId(MetadataProviders.Musicbrainz, mbz);
+ var mbz = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(mbz))
+ {
+ item.SetProviderId(MetadataProviders.Musicbrainz, mbz);
+ }
+ break;
+ }
+ case "MusicBrainzReleaseGroupId":
+ {
+ var mbz = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(mbz))
+ {
+ item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, mbz);
+ }
+ break;
}
- break;
-
case "RottenTomatoesId":
var rtId = reader.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(rtId))
diff --git a/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs b/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs
index 20b707edd..0c4dbfd65 100644
--- a/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs
+++ b/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs
@@ -1,6 +1,7 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Dto;
namespace MediaBrowser.Model.ApiClient
{
@@ -19,5 +20,10 @@ namespace MediaBrowser.Model.ApiClient
{
return apiClient.GetImageStreamAsync(url, CancellationToken.None);
}
+
+ public static Task<UserDto[]> GetPublicUsersAsync(this IApiClient apiClient)
+ {
+ return apiClient.GetPublicUsersAsync(CancellationToken.None);
+ }
}
}
diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs
index 02589d7ea..f919c2c83 100644
--- a/MediaBrowser.Model/ApiClient/IApiClient.cs
+++ b/MediaBrowser.Model/ApiClient/IApiClient.cs
@@ -33,7 +33,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="startIndex">The start index.</param>
/// <param name="limit">The limit.</param>
/// <returns>Task{ItemReviewsResult}.</returns>
- Task<ItemReviewsResult> GetCriticReviews(string itemId, int? startIndex = null, int? limit = null);
+ Task<ItemReviewsResult> GetCriticReviews(string itemId, CancellationToken cancellationToken, int? startIndex = null, int? limit = null);
/// <summary>
/// Gets the theme songs async.
@@ -42,7 +42,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="itemId">The item id.</param>
/// <param name="inheritFromParents">if set to <c>true</c> [inherit from parents].</param>
/// <returns>Task{ThemeMediaResult}.</returns>
- Task<ThemeMediaResult> GetThemeSongsAsync(string userId, string itemId, bool inheritFromParents);
+ Task<ThemeMediaResult> GetThemeSongsAsync(string userId, string itemId, bool inheritFromParents, CancellationToken cancellationToken);
/// <summary>
/// Gets the search hints async.
@@ -62,7 +62,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="itemId">The item id.</param>
/// <param name="inheritFromParents">if set to <c>true</c> [inherit from parents].</param>
/// <returns>Task{ThemeMediaResult}.</returns>
- Task<ThemeMediaResult> GetThemeVideosAsync(string userId, string itemId, bool inheritFromParents);
+ Task<ThemeMediaResult> GetThemeVideosAsync(string userId, string itemId, bool inheritFromParents, CancellationToken cancellationToken);
/// <summary>
/// Gets all theme media async.
@@ -71,7 +71,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="itemId">The item id.</param>
/// <param name="inheritFromParents">if set to <c>true</c> [inherit from parents].</param>
/// <returns>Task{AllThemeMediaResult}.</returns>
- Task<AllThemeMediaResult> GetAllThemeMediaAsync(string userId, string itemId, bool inheritFromParents);
+ Task<AllThemeMediaResult> GetAllThemeMediaAsync(string userId, string itemId, bool inheritFromParents, CancellationToken cancellationToken);
/// <summary>
/// Marks the notifications read.
@@ -155,7 +155,7 @@ namespace MediaBrowser.Model.ApiClient
/// Gets the public users async.
/// </summary>
/// <returns>Task{UserDto[]}.</returns>
- Task<UserDto[]> GetPublicUsersAsync();
+ Task<UserDto[]> GetPublicUsersAsync(CancellationToken cancellationToken);
/// <summary>
/// Gets active client sessions.
@@ -205,7 +205,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <returns>Task{ItemsResult}.</returns>
Task<ItemsResult> GetInstantMixFromMusicGenreAsync(SimilarItemsByNameQuery query);
-
+
/// <summary>
/// Gets the similar movies async.
/// </summary>
@@ -309,7 +309,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <returns>Task{ItemsResult}.</returns>
Task<ItemsResult> GetStudiosAsync(ItemsByNameQuery query);
-
+
/// <summary>
/// Gets the music genre async.
/// </summary>
@@ -325,7 +325,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="userId">The user id.</param>
/// <returns>Task{BaseItemDto}.</returns>
Task<BaseItemDto> GetGameGenreAsync(string name, string userId);
-
+
/// <summary>
/// Gets the artist async.
/// </summary>
@@ -437,7 +437,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="wasPlayed">if set to <c>true</c> [was played].</param>
/// <returns>Task.</returns>
/// <exception cref="ArgumentNullException">itemId</exception>
- Task UpdatePlayedStatusAsync(string itemId, string userId, bool wasPlayed);
+ Task<UserItemDataDto> UpdatePlayedStatusAsync(string itemId, string userId, bool wasPlayed);
/// <summary>
/// Updates the favorite status async.
@@ -447,7 +447,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="isFavorite">if set to <c>true</c> [is favorite].</param>
/// <returns>Task.</returns>
/// <exception cref="ArgumentNullException">itemId</exception>
- Task UpdateFavoriteStatusAsync(string itemId, string userId, bool isFavorite);
+ Task<UserItemDataDto> UpdateFavoriteStatusAsync(string itemId, string userId, bool isFavorite);
/// <summary>
/// Reports to the server that the user has begun playing an item
@@ -518,7 +518,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="userId">The user id.</param>
/// <returns>Task{UserItemDataDto}.</returns>
/// <exception cref="ArgumentNullException">itemId</exception>
- Task ClearUserItemRatingAsync(string itemId, string userId);
+ Task<UserItemDataDto> ClearUserItemRatingAsync(string itemId, string userId);
/// <summary>
/// Updates a user's rating for an item, based on likes or dislikes
@@ -528,7 +528,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="likes">if set to <c>true</c> [likes].</param>
/// <returns>Task.</returns>
/// <exception cref="ArgumentNullException">itemId</exception>
- Task UpdateUserItemRatingAsync(string itemId, string userId, bool likes);
+ Task<UserItemDataDto> UpdateUserItemRatingAsync(string itemId, string userId, bool likes);
/// <summary>
/// Authenticates a user and returns the result
@@ -563,7 +563,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="userId">The user id.</param>
/// <param name="client">The client.</param>
/// <returns>Task{BaseItemDto}.</returns>
- Task<DisplayPreferences> GetDisplayPreferencesAsync(string id, string userId, string client);
+ Task<DisplayPreferences> GetDisplayPreferencesAsync(string id, string userId, string client, CancellationToken cancellationToken);
/// <summary>
/// Updates display preferences for a user
@@ -728,7 +728,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="options">The options.</param>
/// <returns>System.String.</returns>
string GetGameGenreImageUrl(string name, ImageOptions options);
-
+
/// <summary>
/// Gets an image url that can be used to download an image from the api
/// </summary>
diff --git a/MediaBrowser.Model/Entities/MetadataProviders.cs b/MediaBrowser.Model/Entities/MetadataProviders.cs
index b089b668c..db784a35f 100644
--- a/MediaBrowser.Model/Entities/MetadataProviders.cs
+++ b/MediaBrowser.Model/Entities/MetadataProviders.cs
@@ -34,6 +34,7 @@ namespace MediaBrowser.Model.Entities
/// <summary>
/// Tmdb Collection Id
/// </summary>
- TmdbCollection
+ TmdbCollection,
+ MusicBrainzReleaseGroup
}
}
diff --git a/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs b/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs
index 38030cffa..dc8c30bc5 100644
--- a/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs
+++ b/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs
@@ -284,7 +284,8 @@ namespace MediaBrowser.Providers
}
// Disc
- image = GetImage(item, args, "disc");
+ image = GetImage(item, args, "disc") ??
+ GetImage(item, args, "cdart");
if (image != null)
{
diff --git a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs
index f0e696a06..52d5791ae 100644
--- a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs
+++ b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs
@@ -229,28 +229,23 @@ namespace MediaBrowser.Providers.Movies
{
cancellationToken.ThrowIfCancellationRequested();
- BaseProviderInfo data;
-
- if (!item.ProviderData.TryGetValue(Id, out data))
- {
- data = new BaseProviderInfo();
- item.ProviderData[Id] = data;
- }
-
var movieId = item.GetProviderId(MetadataProviders.Tmdb);
- var movieDataPath = GetMovieDataPath(ConfigurationManager.ApplicationPaths, movieId);
- var xmlPath = Path.Combine(movieDataPath, "fanart.xml");
-
- // Only download the xml if it doesn't already exist. The prescan task will take care of getting updates
- if (!File.Exists(xmlPath))
+ if (!string.IsNullOrEmpty(movieId))
{
- await DownloadMovieXml(movieDataPath, movieId, cancellationToken).ConfigureAwait(false);
- }
+ var movieDataPath = GetMovieDataPath(ConfigurationManager.ApplicationPaths, movieId);
+ var xmlPath = Path.Combine(movieDataPath, "fanart.xml");
- if (File.Exists(xmlPath))
- {
- await FetchFromXml(item, xmlPath, cancellationToken).ConfigureAwait(false);
+ // Only download the xml if it doesn't already exist. The prescan task will take care of getting updates
+ if (!File.Exists(xmlPath))
+ {
+ await DownloadMovieXml(movieDataPath, movieId, cancellationToken).ConfigureAwait(false);
+ }
+
+ if (File.Exists(xmlPath))
+ {
+ await FetchFromXml(item, xmlPath, cancellationToken).ConfigureAwait(false);
+ }
}
SetLastRefreshed(item, DateTime.UtcNow);
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
index 37b4ce386..69a23b84f 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
@@ -180,8 +180,7 @@ namespace MediaBrowser.Providers.Movies
}
private const string TmdbConfigUrl = "http://api.themoviedb.org/3/configuration?api_key={0}";
- private const string Search3 = @"http://api.themoviedb.org/3/search/movie?api_key={1}&query={0}&language={2}";
- private const string AltTitleSearch = @"http://api.themoviedb.org/3/movie/{0}/alternative_titles?api_key={1}&country={2}";
+ private const string Search3 = @"http://api.themoviedb.org/3/search/{3}?api_key={1}&query={0}&language={2}";
private const string GetMovieInfo3 = @"http://api.themoviedb.org/3/movie/{0}?api_key={1}&language={2}&append_to_response=casts,releases,images,keywords,trailers";
private const string GetBoxSetInfo3 = @"http://api.themoviedb.org/3/collection/{0}?api_key={1}&language={2}&append_to_response=images";
@@ -193,8 +192,6 @@ namespace MediaBrowser.Providers.Movies
new Regex(@"(?<name>.*)") // last resort matches the whole string as the name
};
- public const string AltMetaFileName = "movie.xml";
-
protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
{
if (HasAltMeta(item))
@@ -237,7 +234,10 @@ namespace MediaBrowser.Providers.Movies
{
return item.LocationType == LocationType.FileSystem && item.ResolveArgs.ContainsMetaFileByName("collection.xml");
}
- return item.LocationType == LocationType.FileSystem && item.ResolveArgs.ContainsMetaFileByName(AltMetaFileName);
+
+ var xmlFileName = MovieProviderFromXml.GetXmlFilename(item);
+
+ return item.LocationType == LocationType.FileSystem && item.ResolveArgs.ContainsMetaFileByName(xmlFileName);
}
/// <summary>
@@ -248,8 +248,19 @@ namespace MediaBrowser.Providers.Movies
/// <returns>Task.</returns>
private async Task FetchMovieData(BaseItem item, CancellationToken cancellationToken)
{
- string id = item.GetProviderId(MetadataProviders.Tmdb) ?? await FindId(item, item.ProductionYear, cancellationToken).ConfigureAwait(false);
- if (id != null)
+ var id = item.GetProviderId(MetadataProviders.Tmdb);
+
+ if (string.IsNullOrEmpty(id))
+ {
+ id = item.GetProviderId(MetadataProviders.Imdb);
+ }
+
+ if (string.IsNullOrEmpty(id))
+ {
+ id = await FindId(item, cancellationToken).ConfigureAwait(false);
+ }
+
+ if (!string.IsNullOrEmpty(id))
{
Logger.Debug("MovieDbProvider - getting movie info with id: " + id);
@@ -291,21 +302,17 @@ namespace MediaBrowser.Providers.Movies
/// Finds the id.
/// </summary>
/// <param name="item">The item.</param>
- /// <param name="productionYear">The production year.</param>
/// <param name="cancellationToken">The cancellation token</param>
/// <returns>Task{System.String}.</returns>
- public async Task<string> FindId(BaseItem item, int? productionYear, CancellationToken cancellationToken)
+ public async Task<string> FindId(BaseItem item, CancellationToken cancellationToken)
{
- int? year;
+ int? yearInName;
string name = item.Name;
- ParseName(name, out name, out year);
+ ParseName(name, out name, out yearInName);
- if (year == null && productionYear != null)
- {
- year = productionYear;
- }
+ var year = item.ProductionYear ?? yearInName;
- Logger.Info("MovieDbProvider: Finding id for movie: " + name);
+ Logger.Info("MovieDbProvider: Finding id for item: " + name);
string language = ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower();
//if we are a boxset - look at our first child
@@ -313,19 +320,23 @@ namespace MediaBrowser.Providers.Movies
if (boxset != null)
{
// See if any movies have a collection id already
- return boxset.Children.Concat(boxset.GetLinkedChildren()).OfType<Video>()
+ var collId = boxset.Children.Concat(boxset.GetLinkedChildren()).OfType<Video>()
.Select(i => i.GetProviderId(MetadataProviders.TmdbCollection))
.FirstOrDefault(i => i != null);
+
+ if (collId != null) return collId;
+
}
//nope - search for it
- var id = await AttemptFindId(name, year, language, cancellationToken).ConfigureAwait(false);
+ var searchType = item is BoxSet ? "collection" : "movie";
+ var id = await AttemptFindId(name, searchType, year, language, cancellationToken).ConfigureAwait(false);
if (id == null)
{
//try in english if wasn't before
if (language != "en")
{
- id = await AttemptFindId(name, year, "en", cancellationToken).ConfigureAwait(false);
+ id = await AttemptFindId(name, searchType, year, "en", cancellationToken).ConfigureAwait(false);
}
else
{
@@ -340,12 +351,12 @@ namespace MediaBrowser.Providers.Movies
// Search again if the new name is different
if (!string.Equals(name, originalName))
{
- id = await AttemptFindId(name, year, language, cancellationToken).ConfigureAwait(false);
+ id = await AttemptFindId(name, searchType, year, language, cancellationToken).ConfigureAwait(false);
if (id == null && language != "en")
{
//one more time, in english
- id = await AttemptFindId(name, year, "en", cancellationToken).ConfigureAwait(false);
+ id = await AttemptFindId(name, searchType, year, "en", cancellationToken).ConfigureAwait(false);
}
}
@@ -359,7 +370,7 @@ namespace MediaBrowser.Providers.Movies
if (!string.Equals(pathName, name, StringComparison.OrdinalIgnoreCase)
&& !string.Equals(pathName, originalName, StringComparison.OrdinalIgnoreCase))
{
- id = await AttemptFindId(pathName, year, "en", cancellationToken).ConfigureAwait(false);
+ id = await AttemptFindId(pathName, searchType, year, "en", cancellationToken).ConfigureAwait(false);
}
}
}
@@ -372,13 +383,14 @@ namespace MediaBrowser.Providers.Movies
/// Attempts the find id.
/// </summary>
/// <param name="name">The name.</param>
+ /// <param name="type">movie or collection</param>
/// <param name="year">The year.</param>
/// <param name="language">The language.</param>
/// <param name="cancellationToken">The cancellation token</param>
/// <returns>Task{System.String}.</returns>
- private async Task<string> AttemptFindId(string name, int? year, string language, CancellationToken cancellationToken)
+ private async Task<string> AttemptFindId(string name, string type, int? year, string language, CancellationToken cancellationToken)
{
- string url3 = string.Format(Search3, UrlEncode(name), ApiKey, language);
+ string url3 = string.Format(Search3, UrlEncode(name), ApiKey, language, type);
TmdbMovieSearchResults searchResult = null;
using (Stream json = await GetMovieDbResponse(new HttpRequestOptions
@@ -392,95 +404,12 @@ namespace MediaBrowser.Providers.Movies
searchResult = JsonSerializer.DeserializeFromStream<TmdbMovieSearchResults>(json);
}
- if (searchResult == null || searchResult.results.Count == 0)
- {
- //try replacing numbers
- foreach (var pair in ReplaceStartNumbers)
- {
- if (name.StartsWith(pair.Key))
- {
- name = name.Remove(0, pair.Key.Length);
- name = pair.Value + name;
- }
- }
- foreach (var pair in ReplaceEndNumbers)
- {
- if (name.EndsWith(pair.Key))
- {
- name = name.Remove(name.IndexOf(pair.Key), pair.Key.Length);
- name = name + pair.Value;
- }
- }
- Logger.Info("MovieDBProvider - No results. Trying replacement numbers: " + name);
- url3 = string.Format(Search3, UrlEncode(name), ApiKey, language);
-
- using (var json = await GetMovieDbResponse(new HttpRequestOptions
- {
- Url = url3,
- CancellationToken = cancellationToken,
- AcceptHeader = AcceptHeader
-
- }).ConfigureAwait(false))
- {
- searchResult = JsonSerializer.DeserializeFromStream<TmdbMovieSearchResults>(json);
- }
- }
if (searchResult != null)
{
- string compName = GetComparableName(name, Logger);
foreach (var possible in searchResult.results)
{
- string matchedName = null;
+ string matchedName = possible.title ?? possible.name;
string id = possible.id.ToString(CultureInfo.InvariantCulture);
- string n = possible.title;
- if (GetComparableName(n, Logger) == compName)
- {
- matchedName = n;
- }
- else
- {
- n = possible.original_title;
- if (GetComparableName(n, Logger) == compName)
- {
- matchedName = n;
- }
- }
-
- Logger.Debug("MovieDbProvider - " + compName + " didn't match " + n);
- //if main title matches we don't have to look for alternatives
- if (matchedName == null)
- {
- //that title didn't match - look for alternatives
- url3 = string.Format(AltTitleSearch, id, ApiKey, ConfigurationManager.Configuration.MetadataCountryCode);
-
- using (var json = await GetMovieDbResponse(new HttpRequestOptions
- {
- Url = url3,
- CancellationToken = cancellationToken,
- AcceptHeader = AcceptHeader
-
- }).ConfigureAwait(false))
- {
- var response = JsonSerializer.DeserializeFromStream<TmdbAltTitleResults>(json);
-
- if (response != null && response.titles != null)
- {
- foreach (var title in response.titles)
- {
- var t = GetComparableName(title.title, Logger);
- if (t == compName)
- {
- Logger.Debug("MovieDbProvider - " + compName +
- " matched " + t);
- matchedName = t;
- break;
- }
- Logger.Debug("MovieDbProvider - " + compName +
- " did not match " + t);
- }
- }
- }
- }
if (matchedName != null)
{
@@ -520,45 +449,6 @@ namespace MediaBrowser.Providers.Movies
}
/// <summary>
- /// Gets the boxset id from movie.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <param name="year">The year.</param>
- /// <param name="language">The language.</param>
- /// <param name="cancellationToken">The cancellation token</param>
- /// <returns>Task{System.String}.</returns>
- protected async Task<string> GetBoxsetIdFromMovie(string name, int? year, string language, CancellationToken cancellationToken)
- {
- string id = null;
- string childId = await AttemptFindId(name, year, language, cancellationToken).ConfigureAwait(false);
- if (childId != null)
- {
- string url = string.Format(GetMovieInfo3, childId, ApiKey, language);
-
- using (Stream json = await GetMovieDbResponse(new HttpRequestOptions
- {
- Url = url,
- CancellationToken = cancellationToken,
- AcceptHeader = AcceptHeader
-
- }).ConfigureAwait(false))
- {
- var movieResult = JsonSerializer.DeserializeFromStream<CompleteMovieData>(json);
-
- if (movieResult != null && movieResult.belongs_to_collection != null)
- {
- id = movieResult.belongs_to_collection.id.ToString(CultureInfo.InvariantCulture);
- }
- else
- {
- Logger.Error("Unable to obtain boxset id.");
- }
- }
- }
- return id;
- }
-
- /// <summary>
/// Fetches the movie data.
/// </summary>
/// <param name="item">The item.</param>
@@ -658,8 +548,8 @@ namespace MediaBrowser.Providers.Movies
if (!movie.LockedFields.Contains(MetadataFields.Overview))
{
movie.Overview = WebUtility.HtmlDecode(movieData.overview);
+ movie.Overview = movie.Overview != null ? movie.Overview.Replace("\n\n", "\n") : null;
}
- movie.Overview = movie.Overview != null ? movie.Overview.Replace("\n\n", "\n") : null;
movie.HomePageUrl = movieData.homepage;
movie.Budget = movieData.budget;
movie.Revenue = movieData.revenue;
@@ -850,126 +740,6 @@ namespace MediaBrowser.Providers.Movies
}
}
- /// <summary>
- /// The remove
- /// </summary>
- const string Remove = "\"'!`?";
- // "Face/Off" support.
- /// <summary>
- /// The spacers
- /// </summary>
- const string Spacers = "/,.:;\\(){}[]+-_=–*"; // (there are not actually two - in the they are different char codes)
- /// <summary>
- /// The replace start numbers
- /// </summary>
- static readonly Dictionary<string, string> ReplaceStartNumbers = new Dictionary<string, string> {
- {"1 ","one "},
- {"2 ","two "},
- {"3 ","three "},
- {"4 ","four "},
- {"5 ","five "},
- {"6 ","six "},
- {"7 ","seven "},
- {"8 ","eight "},
- {"9 ","nine "},
- {"10 ","ten "},
- {"11 ","eleven "},
- {"12 ","twelve "},
- {"13 ","thirteen "},
- {"100 ","one hundred "},
- {"101 ","one hundred one "}
- };
-
- /// <summary>
- /// The replace end numbers
- /// </summary>
- static readonly Dictionary<string, string> ReplaceEndNumbers = new Dictionary<string, string> {
- {" 1"," i"},
- {" 2"," ii"},
- {" 3"," iii"},
- {" 4"," iv"},
- {" 5"," v"},
- {" 6"," vi"},
- {" 7"," vii"},
- {" 8"," viii"},
- {" 9"," ix"},
- {" 10"," x"}
- };
-
- /// <summary>
- /// Gets the name of the comparable.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <param name="logger">The logger.</param>
- /// <returns>System.String.</returns>
- internal static string GetComparableName(string name, ILogger logger)
- {
- name = name.ToLower();
- name = name.Replace("á", "a");
- name = name.Replace("é", "e");
- name = name.Replace("í", "i");
- name = name.Replace("ó", "o");
- name = name.Replace("ú", "u");
- name = name.Replace("ü", "u");
- name = name.Replace("ñ", "n");
- foreach (var pair in ReplaceStartNumbers)
- {
- if (name.StartsWith(pair.Key))
- {
- name = name.Remove(0, pair.Key.Length);
- name = pair.Value + name;
- logger.Info("MovieDbProvider - Replaced Start Numbers: " + name);
- }
- }
- foreach (var pair in ReplaceEndNumbers)
- {
- if (name.EndsWith(pair.Key))
- {
- name = name.Remove(name.IndexOf(pair.Key), pair.Key.Length);
- name = name + pair.Value;
- logger.Info("MovieDbProvider - Replaced End Numbers: " + name);
- }
- }
- name = name.Normalize(NormalizationForm.FormKD);
- var sb = new StringBuilder();
- foreach (var c in name)
- {
- if (c >= 0x2B0 && c <= 0x0333)
- {
- // skip char modifier and diacritics
- }
- else if (Remove.IndexOf(c) > -1)
- {
- // skip chars we are removing
- }
- else if (Spacers.IndexOf(c) > -1)
- {
- sb.Append(" ");
- }
- else if (c == '&')
- {
- sb.Append(" and ");
- }
- else
- {
- sb.Append(c);
- }
- }
- name = sb.ToString();
- name = name.Replace(", the", "");
- name = name.Replace(" the ", " ");
- name = name.Replace("the ", "");
-
- string prev_name;
- do
- {
- prev_name = name;
- name = name.Replace(" ", " ");
- } while (name.Length != prev_name.Length);
-
- return name.Trim();
- }
-
#region Result Objects
@@ -1058,6 +828,10 @@ namespace MediaBrowser.Providers.Movies
/// <value>The vote_average.</value>
public double vote_average { get; set; }
/// <summary>
+ /// For collection search results
+ /// </summary>
+ public string name { get; set; }
+ /// <summary>
/// Gets or sets the vote_count.
/// </summary>
/// <value>The vote_count.</value>
diff --git a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs
index 76fee746c..762920955 100644
--- a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs
+++ b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs
@@ -52,6 +52,13 @@ namespace MediaBrowser.Providers.Movies
get { return MetadataProviderPriority.First; }
}
+ internal static string GetXmlFilename(BaseItem item)
+ {
+ var filename = "movie.xml";
+
+ return Path.Combine(item.MetaLocation, filename);
+ }
+
/// <summary>
/// Override this to return the date that should be compared to the last refresh date
/// to determine if this provider should be re-fetched.
@@ -60,7 +67,7 @@ namespace MediaBrowser.Providers.Movies
/// <returns>DateTime.</returns>
protected override DateTime CompareDate(BaseItem item)
{
- var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "movie.xml"));
+ var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, GetXmlFilename(item)));
return entry != null ? entry.LastWriteTimeUtc : DateTime.MinValue;
}
@@ -86,7 +93,7 @@ namespace MediaBrowser.Providers.Movies
{
cancellationToken.ThrowIfCancellationRequested();
- var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "movie.xml"));
+ var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, GetXmlFilename(item)));
if (metadataFile != null)
{
diff --git a/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs b/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs
index 25f39d32f..fdc4b86c5 100644
--- a/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs
+++ b/MediaBrowser.Providers/Movies/TmdbPersonProvider.cs
@@ -214,7 +214,10 @@ namespace MediaBrowser.Providers.Movies
/// <param name="searchResult">The search result.</param>
protected void ProcessInfo(Person person, PersonResult searchResult)
{
- person.Overview = searchResult.biography;
+ if (!person.LockedFields.Contains(MetadataFields.Overview))
+ {
+ person.Overview = searchResult.biography;
+ }
DateTime date;
diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
index b02128a37..fa7daaf25 100644
--- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
@@ -182,10 +182,13 @@ namespace MediaBrowser.Providers.Music
var releaseEntryId = item.GetProviderId(MetadataProviders.Musicbrainz);
+ var musicBrainzReleaseGroupId = album.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
// Fanart uses the release group id so we'll have to get that now using the release entry id
- if (string.IsNullOrEmpty(album.MusicBrainzReleaseGroupId))
+ if (string.IsNullOrEmpty(musicBrainzReleaseGroupId))
{
- album.MusicBrainzReleaseGroupId = await GetReleaseGroupId(releaseEntryId, cancellationToken).ConfigureAwait(false);
+ musicBrainzReleaseGroupId = await GetReleaseGroupId(releaseEntryId, cancellationToken).ConfigureAwait(false);
+
+ album.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, musicBrainzReleaseGroupId);
}
var doc = new XmlDocument();
@@ -199,9 +202,9 @@ namespace MediaBrowser.Providers.Music
// Try try with the release entry Id, if that doesn't produce anything try the release group id
var node = doc.SelectSingleNode("//fanart/music/albums/album[@id=\"" + releaseEntryId + "\"]/cdart/@url");
- if (node == null && !string.IsNullOrEmpty(album.MusicBrainzReleaseGroupId))
+ if (node == null && !string.IsNullOrEmpty(musicBrainzReleaseGroupId))
{
- node = doc.SelectSingleNode("//fanart/music/albums/album[@id=\"" + album.MusicBrainzReleaseGroupId + "\"]/cdart/@url");
+ node = doc.SelectSingleNode("//fanart/music/albums/album[@id=\"" + musicBrainzReleaseGroupId + "\"]/cdart/@url");
}
var path = node != null ? node.Value : null;
@@ -218,9 +221,9 @@ namespace MediaBrowser.Providers.Music
// Try try with the release entry Id, if that doesn't produce anything try the release group id
var node = doc.SelectSingleNode("//fanart/music/albums/album[@id=\"" + releaseEntryId + "\"]/albumcover/@url");
- if (node == null && !string.IsNullOrEmpty(album.MusicBrainzReleaseGroupId))
+ if (node == null && !string.IsNullOrEmpty(musicBrainzReleaseGroupId))
{
- node = doc.SelectSingleNode("//fanart/music/albums/album[@id=\"" + album.MusicBrainzReleaseGroupId + "\"]/albumcover/@url");
+ node = doc.SelectSingleNode("//fanart/music/albums/album[@id=\"" + musicBrainzReleaseGroupId + "\"]/albumcover/@url");
}
var path = node != null ? node.Value : null;
diff --git a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs b/MediaBrowser.Providers/Savers/MovieXmlSaver.cs
index 9a4899cba..154b4ab60 100644
--- a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs
+++ b/MediaBrowser.Providers/Savers/MovieXmlSaver.cs
@@ -119,11 +119,14 @@ namespace MediaBrowser.Providers.Savers
public string GetSavePath(BaseItem item)
{
- var video = (Video)item;
+ if (item.IsInMixedFolder)
+ {
+ return Path.ChangeExtension(item.Path, ".xml");
+ }
+
+ var filename = MovieProviderFromXml.GetXmlFilename(item);
- return video.IsInMixedFolder ?
- Path.ChangeExtension(item.Path, ".xml") :
- Path.Combine(item.MetaLocation, "movie.xml");
+ return Path.Combine(item.MetaLocation, filename);
}
}
}
diff --git a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs
index 5c9e90312..edeea611a 100644
--- a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs
+++ b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs
@@ -65,6 +65,7 @@ namespace MediaBrowser.Providers.Savers
"IMDbId",
"TMDbId",
"TVcomId",
+ "TvDbId",
"RottenTomatoesId",
"MusicbrainzId",
"TMDbCollectionId",
@@ -81,7 +82,8 @@ namespace MediaBrowser.Providers.Savers
"BirthDate",
"DeathDate",
"LockedFields",
- "Chapters"
+ "Chapters",
+ "MusicBrainzReleaseGroupId"
});
var position = xml.ToString().LastIndexOf("</", StringComparison.OrdinalIgnoreCase);
@@ -332,6 +334,13 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<MusicbrainzId>" + SecurityElement.Escape(mbz) + "</MusicbrainzId>");
}
+ mbz = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+
+ if (!string.IsNullOrEmpty(mbz))
+ {
+ builder.Append("<MusicBrainzReleaseGroupId>" + SecurityElement.Escape(mbz) + "</MusicBrainzReleaseGroupId>");
+ }
+
var gamesdb = item.GetProviderId(MetadataProviders.Gamesdb);
if (!string.IsNullOrEmpty(gamesdb))
diff --git a/MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs b/MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs
index 9ccbd3eb7..9099d10d6 100644
--- a/MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/RemoteEpisodeProvider.cs
@@ -69,7 +69,7 @@ namespace MediaBrowser.Providers.TV
return ItemUpdateType.ImageUpdate | ItemUpdateType.MetadataDownload;
}
}
-
+
/// <summary>
/// Gets the priority.
/// </summary>
@@ -147,7 +147,7 @@ namespace MediaBrowser.Providers.TV
return seriesXmlFileInfo.LastWriteTimeUtc;
}
}
-
+
return base.CompareDate(item);
}
@@ -240,7 +240,7 @@ namespace MediaBrowser.Providers.TV
{
return status;
}
- IEnumerable<XmlDocument> extraEpisodesNode = new XmlDocument[]{};
+ IEnumerable<XmlDocument> extraEpisodesNode = new XmlDocument[] { };
if (episode.IndexNumberEnd.HasValue)
{
@@ -262,7 +262,7 @@ namespace MediaBrowser.Providers.TV
var xElements = all.Where(x => int.Parse(x.Element("EpisodeNumber").Value) > episode.IndexNumber && int.Parse(x.Element("EpisodeNumber").Value) <= episode.IndexNumberEnd.Value);
extraEpisodesNode = xElements.OrderBy(x => x.Element("EpisodeNumber").Value).Select(x => x.ToXmlDocument());
}
-
+
}
var doc = new XmlDocument();
doc.LoadXml(episodeNode.OuterXml);
@@ -320,14 +320,15 @@ namespace MediaBrowser.Providers.TV
var persons = Regex.Matches(actors, @"([^|()]|\([^)]*\)*)+")
.Cast<Match>()
.Select(m => m.Value).Where(i => !string.IsNullOrWhiteSpace(i) && !string.IsNullOrEmpty(i));
- foreach (var person in persons.Select(str => {
- var nameGroup = str.Split(new[] {'('}, 2, StringSplitOptions.RemoveEmptyEntries);
- var name = nameGroup[0].Trim();
- var roles = nameGroup.Count() > 1 ? nameGroup[1].Trim() : null;
- if (roles != null)
- roles = roles.EndsWith(")") ? roles.Substring(0, roles.Length - 1) : roles;
- return new PersonInfo {Type = PersonType.GuestStar, Name = name, Role = roles};
- }))
+ foreach (var person in persons.Select(str =>
+ {
+ var nameGroup = str.Split(new[] { '(' }, 2, StringSplitOptions.RemoveEmptyEntries);
+ var name = nameGroup[0].Trim();
+ var roles = nameGroup.Count() > 1 ? nameGroup[1].Trim() : null;
+ if (roles != null)
+ roles = roles.EndsWith(")") ? roles.Substring(0, roles.Length - 1) : roles;
+ return new PersonInfo { Type = PersonType.GuestStar, Name = name, Role = roles };
+ }))
{
episode.AddPerson(person);
}
@@ -340,14 +341,15 @@ namespace MediaBrowser.Providers.TV
var persons = Regex.Matches(extraActors, @"([^|()]|\([^)]*\)*)+")
.Cast<Match>()
.Select(m => m.Value).Where(i => !string.IsNullOrWhiteSpace(i) && !string.IsNullOrEmpty(i));
- foreach (var person in persons.Select(str => {
- var nameGroup = str.Split(new[] {'('}, 2, StringSplitOptions.RemoveEmptyEntries);
- var name = nameGroup[0].Trim();
- var roles = nameGroup.Count() > 1 ? nameGroup[1].Trim() : null;
- if (roles != null)
- roles = roles.EndsWith(")") ? roles.Substring(0, roles.Length - 1) : roles;
- return new PersonInfo {Type = PersonType.GuestStar, Name = name, Role = roles};
- }).Where(person => !episode.People.Any(x => x.Type == person.Type && x.Name == person.Name))
+ foreach (var person in persons.Select(str =>
+ {
+ var nameGroup = str.Split(new[] { '(' }, 2, StringSplitOptions.RemoveEmptyEntries);
+ var name = nameGroup[0].Trim();
+ var roles = nameGroup.Count() > 1 ? nameGroup[1].Trim() : null;
+ if (roles != null)
+ roles = roles.EndsWith(")") ? roles.Substring(0, roles.Length - 1) : roles;
+ return new PersonInfo { Type = PersonType.GuestStar, Name = name, Role = roles };
+ }).Where(person => !episode.People.Any(x => x.Type == person.Type && x.Name == person.Name))
)
{
episode.AddPerson(person);
@@ -358,9 +360,9 @@ namespace MediaBrowser.Providers.TV
if (directors != null)
{
// Sometimes tvdb actors have leading spaces
- foreach (var person in directors.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries)
+ foreach (var person in directors.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries)
.Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(str => new PersonInfo {Type = PersonType.Director, Name = str.Trim()}))
+ .Select(str => new PersonInfo { Type = PersonType.Director, Name = str.Trim() }))
{
episode.AddPerson(person);
}
@@ -371,9 +373,9 @@ namespace MediaBrowser.Providers.TV
if (writers != null)
{
// Sometimes tvdb actors have leading spaces
- foreach (var person in writers.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries)
+ foreach (var person in writers.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries)
.Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(str => new PersonInfo {Type = PersonType.Writer, Name = str.Trim()}))
+ .Select(str => new PersonInfo { Type = PersonType.Writer, Name = str.Trim() }))
{
episode.AddPerson(person);
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs
index e98a0a2c5..cb6097504 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs
@@ -27,7 +27,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
private readonly INotificationsRepository _notificationsRepo;
private readonly IUserManager _userManager;
- private readonly TimeSpan _frequency = TimeSpan.FromHours(3);
+ private readonly TimeSpan _frequency = TimeSpan.FromHours(6);
private readonly TimeSpan _maxAge = TimeSpan.FromDays(31);
public RemoteNotifications(IApplicationPaths appPaths, ILogger logger, IHttpClient httpClient, IJsonSerializer json, INotificationsRepository notificationsRepo, IUserManager userManager)
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index d408e082a..4991db8e2 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -230,8 +230,6 @@
<EmbeddedResource Include="MediaEncoder\readme.txt" />
</ItemGroup>
<ItemGroup>
- <EmbeddedResource Include="MediaEncoder\fonts\ARIALUNI.TTF" />
- <EmbeddedResource Include="MediaEncoder\fonts\fonts.conf" />
<EmbeddedResource Include="MediaEncoder\ffmpeg20130813.zip" />
<None Include="packages.config" />
</ItemGroup>
diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
index f5b5ea6c0..2ce49aabb 100644
--- a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
+++ b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.MediaInfo;
+using MediaBrowser.Common.Net;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
@@ -47,6 +48,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <value>The json serializer.</value>
private readonly IJsonSerializer _jsonSerializer;
+ private readonly IHttpClient _httpClient;
+
/// <summary>
/// The video image resource pool
/// </summary>
@@ -81,12 +84,13 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <param name="appPaths">The app paths.</param>
/// <param name="jsonSerializer">The json serializer.</param>
public MediaEncoder(ILogger logger, IZipClient zipClient, IApplicationPaths appPaths,
- IJsonSerializer jsonSerializer)
+ IJsonSerializer jsonSerializer, IHttpClient httpClient)
{
_logger = logger;
_zipClient = zipClient;
_appPaths = appPaths;
_jsonSerializer = jsonSerializer;
+ _httpClient = httpClient;
// Not crazy about this but it's the only way to suppress ffmpeg crash dialog boxes
SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOALIGNMENTFAULTEXCEPT |
@@ -194,22 +198,30 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <param name="assembly">The assembly.</param>
/// <param name="zipFileResourcePath">The zip file resource path.</param>
/// <param name="targetPath">The target path.</param>
- private void ExtractTools(Assembly assembly, string zipFileResourcePath, string targetPath)
+ private async void ExtractTools(Assembly assembly, string zipFileResourcePath, string targetPath)
{
using (var resourceStream = assembly.GetManifestResourceStream(zipFileResourcePath))
{
_zipClient.ExtractAll(resourceStream, targetPath, false);
}
- ExtractFonts(assembly, targetPath);
+ try
+ {
+ await DownloadFonts(targetPath).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting ffmpeg font files", ex);
+ }
}
+ private const string FontUrl = "https://www.dropbox.com/s/9nb76tybcsw5xrk/ARIALUNI.zip?dl=1";
+
/// <summary>
/// Extracts the fonts.
/// </summary>
- /// <param name="assembly">The assembly.</param>
/// <param name="targetPath">The target path.</param>
- private async void ExtractFonts(Assembly assembly, string targetPath)
+ private async Task DownloadFonts(string targetPath)
{
var fontsDirectory = Path.Combine(targetPath, "fonts");
@@ -224,54 +236,44 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
if (!File.Exists(fontFile))
{
- using (var stream = assembly.GetManifestResourceStream(GetType().Namespace + ".fonts." + fontFilename))
+ var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
{
- using (
- var fileStream = new FileStream(fontFile, FileMode.Create, FileAccess.Write, FileShare.Read,
- StreamDefaults.DefaultFileStreamBufferSize,
- FileOptions.Asynchronous))
- {
- await stream.CopyToAsync(fileStream).ConfigureAwait(false);
- }
+ Url = FontUrl,
+ Progress = new Progress<double>()
+ });
+
+ _zipClient.ExtractAll(tempFile, fontsDirectory, true);
+
+ try
+ {
+ File.Delete(tempFile);
+ }
+ catch (IOException ex)
+ {
+ // Log this, but don't let it fail the operation
+ _logger.ErrorException("Error deleting temp file {0}", ex, tempFile);
}
}
- await ExtractFontConfigFile(assembly, fontsDirectory).ConfigureAwait(false);
+ await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
}
- /// <summary>
- /// Extracts the font config file.
- /// </summary>
- /// <param name="assembly">The assembly.</param>
- /// <param name="fontsDirectory">The fonts directory.</param>
- /// <returns>Task.</returns>
- private async Task ExtractFontConfigFile(Assembly assembly, string fontsDirectory)
+ private async Task WriteFontConfigFile(string fontsDirectory)
{
const string fontConfigFilename = "fonts.conf";
var fontConfigFile = Path.Combine(fontsDirectory, fontConfigFilename);
if (!File.Exists(fontConfigFile))
{
- using (
- var stream = assembly.GetManifestResourceStream(GetType().Namespace + ".fonts." + fontConfigFilename)
- )
- {
- using (var streamReader = new StreamReader(stream))
- {
- var contents = await streamReader.ReadToEndAsync().ConfigureAwait(false);
+ var contents = string.Format("<?xml version=\"1.0\"?><fontconfig><dir>{0}</dir><alias><family>Arial</family><prefer>Arial Unicode MS</prefer></alias></fontconfig>", fontsDirectory);
- contents = contents.Replace("<dir></dir>", "<dir>" + fontsDirectory + "</dir>");
+ var bytes = Encoding.UTF8.GetBytes(contents);
- var bytes = Encoding.UTF8.GetBytes(contents);
-
- using (
- var fileStream = new FileStream(fontConfigFile, FileMode.Create, FileAccess.Write,
- FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize,
- FileOptions.Asynchronous))
- {
- await fileStream.WriteAsync(bytes, 0, bytes.Length);
- }
- }
+ using (var fileStream = new FileStream(fontConfigFile, FileMode.Create, FileAccess.Write,
+ FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize,
+ FileOptions.Asynchronous))
+ {
+ await fileStream.WriteAsync(bytes, 0, bytes.Length);
}
}
}
diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/fonts/fonts.conf b/MediaBrowser.Server.Implementations/MediaEncoder/fonts/fonts.conf
deleted file mode 100644
index 648bdb7b2..000000000
--- a/MediaBrowser.Server.Implementations/MediaEncoder/fonts/fonts.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0"?>
-<fontconfig>
-
-<dir></dir>
- <alias>
- <family>Arial</family>
- <prefer>Arial Unicode MS</prefer>
- </alias>
-</fontconfig> \ No newline at end of file
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index 2ee8a0577..eb8a73049 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -24,6 +24,7 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.Sorting;
+using MediaBrowser.IsoMounter;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.System;
@@ -271,7 +272,7 @@ namespace MediaBrowser.ServerApplication
RegisterSingleInstance<ILibrarySearchEngine>(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager));
- MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ZipClient, ApplicationPaths, JsonSerializer);
+ MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ZipClient, ApplicationPaths, JsonSerializer, HttpClient);
RegisterSingleInstance(MediaEncoder);
var clientConnectionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository);
@@ -559,6 +560,9 @@ namespace MediaBrowser.ServerApplication
// Server implementations
yield return typeof(ServerApplicationPaths).Assembly;
+ // Pismo
+ yield return typeof(PismoIsoManager).Assembly;
+
// Include composable parts in the running assembly
yield return GetType().Assembly;
}
diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs
index 32cec1793..ceed8d6c7 100644
--- a/MediaBrowser.WebDashboard/Api/DashboardService.cs
+++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs
@@ -395,7 +395,7 @@ namespace MediaBrowser.WebDashboard.Api
var files = new[]
{
- "http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css",
+ "http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css",
"thirdparty/jqm-icon-pack-3.0/font-awesome/jqm-icon-pack-3.0.0-fa.css" + versionString,
"css/all.css" + versionString
};
@@ -417,7 +417,7 @@ namespace MediaBrowser.WebDashboard.Api
var files = new[]
{
"http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js",
- "http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js",
+ "http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js",
"scripts/all.js" + versionString,
"thirdparty/jstree1.0fix2/jquery.jstree.js"
};
diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js
index a0d4b399d..8a7db8b76 100644
--- a/MediaBrowser.WebDashboard/ApiClient.js
+++ b/MediaBrowser.WebDashboard/ApiClient.js
@@ -2695,7 +2695,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: method,
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2721,7 +2722,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: method,
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2747,7 +2749,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "POST",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2773,7 +2776,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: method,
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2793,7 +2797,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: method,
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2813,7 +2818,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: method,
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2833,7 +2839,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: method,
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2853,7 +2860,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: method,
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2873,7 +2881,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: method,
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2899,7 +2908,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "POST",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2919,7 +2929,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "POST",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2939,7 +2950,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "POST",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2959,7 +2971,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "POST",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2979,7 +2992,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "POST",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -2999,7 +3013,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "POST",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -3022,7 +3037,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "DELETE",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -3040,7 +3056,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "DELETE",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -3058,7 +3075,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "DELETE",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -3076,7 +3094,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "DELETE",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -3094,7 +3113,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "DELETE",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -3112,7 +3132,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "DELETE",
- url: url
+ url: url,
+ dataType: "json"
});
};
@@ -3290,7 +3311,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return self.ajax({
type: "DELETE",
- url: url
+ url: url,
+ dataType: "json"
});
};
diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config
index 517b8c1d2..11c76e205 100644
--- a/MediaBrowser.WebDashboard/packages.config
+++ b/MediaBrowser.WebDashboard/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="MediaBrowser.ApiClient.Javascript" version="3.0.160" targetFramework="net45" />
+ <package id="MediaBrowser.ApiClient.Javascript" version="3.0.164" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.58" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.58" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index 0c5360b49..744debbcd 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -237,7 +237,4 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
- GlobalSection(Performance) = preSolution
- HasPerformanceSessions = true
- EndGlobalSection
EndGlobal
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index 0d497627b..8bfd28da1 100644
--- a/Nuget/MediaBrowser.Common.Internal.nuspec
+++ b/Nuget/MediaBrowser.Common.Internal.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
- <version>3.0.181</version>
+ <version>3.0.184</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.181" />
+ <dependency id="MediaBrowser.Common" version="3.0.184" />
<dependency id="NLog" version="2.0.1.2" />
<dependency id="ServiceStack.Text" version="3.9.55" />
<dependency id="SimpleInjector" version="2.3.0" />
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index 21025135a..2ec4ebd58 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
- <version>3.0.181</version>
+ <version>3.0.184</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index 1ca7f6a11..14a401282 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
- <version>3.0.181</version>
+ <version>3.0.184</version>
<title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.181" />
+ <dependency id="MediaBrowser.Common" version="3.0.184" />
</dependencies>
</metadata>
<files>
diff --git a/README.md b/README.md
index 130151f20..532c8c5ad 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
Media Browser
============
-Media Browser Server is a media cataloging and transcoding server built on top of other popular open source technologies such as **Service Stack**, **jQuery** and **jQuery mobile**.
+Media Browser Server is a home media server built on top of other popular open source technologies such as **Service Stack**, **jQuery**, **jQuery mobile** and **Lucene .NET**.
It features a REST-based api with built-in documention to facilitate plugin development.