This commit is contained in:
Techywarrior 2013-04-05 19:45:32 -07:00
commit 51b71afd5c
30 changed files with 491 additions and 332 deletions

View File

@ -12,7 +12,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class UpdateDisplayPreferences
/// </summary>
[Route("/Users/{UserId}/DisplayPreferences/{Id}", "POST")]
[Route("/DisplayPreferences/{DisplayPreferencesId}", "POST")]
[Api(("Updates a user's display preferences for an item"))]
public class UpdateDisplayPreferences : DisplayPreferences, IReturnVoid
{
@ -20,22 +20,19 @@ namespace MediaBrowser.Api
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public Guid Id { get; set; }
[ApiMember(Name = "DisplayPreferencesId", Description = "DisplayPreferences Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public Guid DisplayPreferencesId { get; set; }
}
[Route("/Users/{UserId}/DisplayPreferences/{Id}", "GET")]
[Route("/DisplayPreferences/{Id}", "GET")]
[Api(("Gets a user's display preferences for an item"))]
public class GetDisplayPreferences : IReturn<DisplayPreferences>
{
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public Guid UserId { get; set; }
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public Guid Id { get; set; }
}
@ -45,9 +42,9 @@ namespace MediaBrowser.Api
public class DisplayPreferencesService : BaseApiService
{
/// <summary>
/// The _user manager
/// The _display preferences manager
/// </summary>
private readonly IUserManager _userManager;
private readonly IDisplayPreferencesManager _displayPreferencesManager;
/// <summary>
/// The _json serializer
/// </summary>
@ -56,12 +53,12 @@ namespace MediaBrowser.Api
/// <summary>
/// Initializes a new instance of the <see cref="DisplayPreferencesService" /> class.
/// </summary>
/// <param name="userManager">The user manager.</param>
/// <param name="jsonSerializer">The json serializer.</param>
public DisplayPreferencesService(IUserManager userManager, IJsonSerializer jsonSerializer)
/// <param name="displayPreferencesManager">The display preferences manager.</param>
public DisplayPreferencesService(IJsonSerializer jsonSerializer, IDisplayPreferencesManager displayPreferencesManager)
{
_userManager = userManager;
_jsonSerializer = jsonSerializer;
_displayPreferencesManager = displayPreferencesManager;
}
/// <summary>
@ -70,7 +67,7 @@ namespace MediaBrowser.Api
/// <param name="request">The request.</param>
public object Get(GetDisplayPreferences request)
{
var task = _userManager.GetDisplayPreferences(request.UserId, request.Id);
var task = _displayPreferencesManager.GetDisplayPreferences(request.Id);
return ToOptimizedResult(task.Result);
}
@ -84,15 +81,12 @@ namespace MediaBrowser.Api
// We need to parse this manually because we told service stack not to with IRequiresRequestStream
// https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var userId = new Guid(pathInfo.GetArgumentValue<string>(1));
var displayPreferencesId = new Guid(pathInfo.GetArgumentValue<string>(3));
var user = _userManager.GetUserById(userId);
var displayPreferencesId = new Guid(pathInfo.GetArgumentValue<string>(1));
// Serialize to json and then back so that the core doesn't see the request dto type
var displayPreferences = _jsonSerializer.DeserializeFromString<DisplayPreferences>(_jsonSerializer.SerializeToString(request));
var task = _userManager.SaveDisplayPreferences(user.Id, displayPreferencesId, displayPreferences, CancellationToken.None);
var task = _displayPreferencesManager.SaveDisplayPreferences(displayPreferences, CancellationToken.None);
Task.WaitAll(task);
}

View File

@ -1,6 +1,5 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Tasks;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@ -35,7 +34,7 @@ namespace MediaBrowser.Controller.Entities
/// Allow different display preferences for each collection folder
/// </summary>
/// <value>The display prefs id.</value>
public override Guid DisplayPreferencesId
protected override Guid DisplayPreferencesId
{
get
{

View File

@ -65,7 +65,7 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value>The display prefs id.</value>
[IgnoreDataMember]
public virtual Guid DisplayPreferencesId
protected virtual Guid DisplayPreferencesId
{
get
{
@ -74,6 +74,16 @@ namespace MediaBrowser.Controller.Entities
}
}
/// <summary>
/// Gets the display preferences id.
/// </summary>
/// <param name="userId">The user id.</param>
/// <returns>Guid.</returns>
public Guid GetDisplayPreferencesId(Guid userId)
{
return (userId + DisplayPreferencesId.ToString()).GetMD5();
}
#region Indexing
/// <summary>

View File

@ -88,12 +88,6 @@ namespace MediaBrowser.Controller
/// <value>The user repository.</value>
public IUserRepository UserRepository { get; set; }
/// <summary>
/// Gets the active user repository
/// </summary>
/// <value>The display preferences repository.</value>
public IDisplayPreferencesRepository DisplayPreferencesRepository { get; set; }
/// <summary>
/// Gets the list of available item repositories
/// </summary>
@ -106,12 +100,6 @@ namespace MediaBrowser.Controller
/// <value>The item repository.</value>
public IItemRepository ItemRepository { get; set; }
/// <summary>
/// Gets the list of available DisplayPreferencesRepositories
/// </summary>
/// <value>The display preferences repositories.</value>
public IEnumerable<IDisplayPreferencesRepository> DisplayPreferencesRepositories { get; set; }
/// <summary>
/// Gets the list of available item repositories
/// </summary>
@ -155,11 +143,7 @@ namespace MediaBrowser.Controller
UserDataRepository = GetRepository(UserDataRepositories, configurationManager.Configuration.UserDataRepository);
var userDataRepoTask = UserDataRepository.Initialize();
// Get the current display preferences repository
DisplayPreferencesRepository = GetRepository(DisplayPreferencesRepositories, configurationManager.Configuration.DisplayPreferencesRepository);
var displayPreferencesRepoTask = DisplayPreferencesRepository.Initialize();
return Task.WhenAll(itemRepoTask, userRepoTask, userDataRepoTask, displayPreferencesRepoTask);
return Task.WhenAll(itemRepoTask, userRepoTask, userDataRepoTask);
}
/// <summary>

View File

@ -174,7 +174,7 @@ namespace MediaBrowser.Controller.Library
if (item.IsFolder && fields.Contains(ItemFields.DisplayPreferencesId))
{
dto.DisplayPreferencesId = ((Folder)item).DisplayPreferencesId.ToString();
dto.DisplayPreferencesId = ((Folder) item).GetDisplayPreferencesId(user.Id).ToString();
}
if (item.IsFolder)

View File

@ -0,0 +1,28 @@
using MediaBrowser.Model.Entities;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Interface IDisplayPreferencesManager
/// </summary>
public interface IDisplayPreferencesManager
{
/// <summary>
/// Gets the display preferences.
/// </summary>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <returns>DisplayPreferences.</returns>
Task<DisplayPreferences> GetDisplayPreferences(Guid displayPreferencesId);
/// <summary>
/// Saves display preferences for an item
/// </summary>
/// <param name="displayPreferences">The display preferences.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveDisplayPreferences(DisplayPreferences displayPreferences, CancellationToken cancellationToken);
}
}

View File

@ -1,7 +1,6 @@
using MediaBrowser.Common.Events;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Connectivity;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Threading;
@ -9,6 +8,9 @@ using System.Threading.Tasks;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Interface IUserManager
/// </summary>
public interface IUserManager
{
/// <summary>
@ -173,7 +175,7 @@ namespace MediaBrowser.Controller.Library
Task ChangePassword(User user, string newPassword);
/// <summary>
/// Saves display preferences for an item
/// Saves the user data.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="userDataId">The user data id.</param>
@ -184,29 +186,11 @@ namespace MediaBrowser.Controller.Library
CancellationToken cancellationToken);
/// <summary>
/// Gets the display preferences.
/// Gets the user data.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="userDataId">The user data id.</param>
/// <returns>Task{DisplayPreferences}.</returns>
/// <returns>Task{UserItemData}.</returns>
Task<UserItemData> GetUserData(Guid userId, Guid userDataId);
/// <summary>
/// Gets the display preferences.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <returns>DisplayPreferences.</returns>
Task<DisplayPreferences> GetDisplayPreferences(Guid userId, Guid displayPreferencesId);
/// <summary>
/// Saves display preferences for an item
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <param name="displayPreferences">The display preferences.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveDisplayPreferences(Guid userId, Guid displayPreferencesId, DisplayPreferences displayPreferences, CancellationToken cancellationToken);
}
}

View File

@ -88,6 +88,7 @@
<Compile Include="Entities\Movies\BoxSet.cs" />
<Compile Include="Entities\Movies\Movie.cs" />
<Compile Include="Entities\Person.cs" />
<Compile Include="Library\IDisplayPreferencesManager.cs" />
<Compile Include="Library\ILibrarySearchEngine.cs" />
<Compile Include="Library\PlaybackProgressEventArgs.cs" />
<Compile Include="Entities\Studio.cs" />

View File

@ -13,20 +13,17 @@ namespace MediaBrowser.Controller.Persistence
/// <summary>
/// Saves display preferences for an item
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <param name="displayPreferences">The display preferences.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveDisplayPreferences(Guid userId, Guid displayPreferencesId, DisplayPreferences displayPreferences,
Task SaveDisplayPreferences(DisplayPreferences displayPreferences,
CancellationToken cancellationToken);
/// <summary>
/// Gets the display preferences.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <returns>Task{DisplayPreferences}.</returns>
Task<DisplayPreferences> GetDisplayPreferences(Guid userId, Guid displayPreferencesId);
Task<DisplayPreferences> GetDisplayPreferences(Guid displayPreferencesId);
}
}

View File

@ -93,7 +93,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
cancellationToken.ThrowIfCancellationRequested();
await Fetch(myItem, cancellationToken, result, isoMount).ConfigureAwait(false);
Fetch(myItem, cancellationToken, result, isoMount);
cancellationToken.ThrowIfCancellationRequested();
@ -180,7 +180,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
/// <param name="result">The result.</param>
/// <param name="isoMount">The iso mount.</param>
/// <returns>Task.</returns>
protected abstract Task Fetch(T item, CancellationToken cancellationToken, FFProbeResult result, IIsoMount isoMount);
protected abstract void Fetch(T item, CancellationToken cancellationToken, FFProbeResult result, IIsoMount isoMount);
/// <summary>
/// Converts ffprobe stream info to our MediaStream class

View File

@ -57,12 +57,6 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
if (video != null)
{
// Can't extract images if there are no video streams
if (video.MediaStreams == null || video.MediaStreams.All(m => m.Type != MediaStreamType.Video))
{
return false;
}
if (video.VideoType == VideoType.Iso && video.IsoType.HasValue && _isoManager.CanMount(item.Path))
{
return true;
@ -93,6 +87,9 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
{
var video = (Video)item;
// We can only extract images from videos if we know there's an embedded video stream
if (video.MediaStreams != null && video.MediaStreams.Any(m => m.Type == MediaStreamType.Video))
{
var filename = item.Id + "_" + item.DateModified.Ticks + "_primary";
var path = Kernel.Instance.FFMpegManager.VideoImageCache.GetResourcePath(filename, ".jpg");
@ -105,6 +102,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
// Image is already in the cache
item.PrimaryImagePath = path;
}
}
SetLastRefreshed(item, DateTime.UtcNow);
return TrueTaskResult;

View File

@ -42,9 +42,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
/// <param name="data">The data.</param>
/// <param name="isoMount">The iso mount.</param>
/// <returns>Task.</returns>
protected override Task Fetch(Audio audio, CancellationToken cancellationToken, FFProbeResult data, IIsoMount isoMount)
{
return Task.Run(() =>
protected override void Fetch(Audio audio, CancellationToken cancellationToken, FFProbeResult data, IIsoMount isoMount)
{
if (data.streams == null)
{
@ -76,7 +74,6 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
{
FetchDataFromTags(audio, data.format.tags);
}
});
}
/// <summary>

View File

@ -187,9 +187,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
/// <param name="data">The data.</param>
/// <param name="isoMount">The iso mount.</param>
/// <returns>Task.</returns>
protected override Task Fetch(Video video, CancellationToken cancellationToken, FFProbeResult data, IIsoMount isoMount)
{
return Task.Run(() =>
protected override void Fetch(Video video, CancellationToken cancellationToken, FFProbeResult data, IIsoMount isoMount)
{
if (data.format != null)
{
@ -224,7 +222,6 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
}
AddExternalSubtitles(video);
});
}
/// <summary>

View File

@ -32,7 +32,7 @@ namespace MediaBrowser.Model.Entities
/// </summary>
/// <value>The user id.</value>
[ProtoMember(1)]
public Guid UserId { get; set; }
public Guid Id { get; set; }
/// <summary>
/// Gets or sets the type of the view.
/// </summary>

View File

@ -0,0 +1,99 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Library
{
/// <summary>
/// Class DisplayPreferencesManager
/// </summary>
public class DisplayPreferencesManager : IDisplayPreferencesManager
{
/// <summary>
/// The _logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// The _display preferences
/// </summary>
private readonly ConcurrentDictionary<Guid, Task<DisplayPreferences>> _displayPreferences = new ConcurrentDictionary<Guid, Task<DisplayPreferences>>();
/// <summary>
/// Gets the active user repository
/// </summary>
/// <value>The display preferences repository.</value>
public IDisplayPreferencesRepository Repository { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="DisplayPreferencesManager"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
public DisplayPreferencesManager(ILogger logger)
{
_logger = logger;
}
/// <summary>
/// Gets the display preferences.
/// </summary>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <returns>DisplayPreferences.</returns>
public Task<DisplayPreferences> GetDisplayPreferences(Guid displayPreferencesId)
{
return _displayPreferences.GetOrAdd(displayPreferencesId, keyName => RetrieveDisplayPreferences(displayPreferencesId));
}
/// <summary>
/// Retrieves the display preferences.
/// </summary>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <returns>DisplayPreferences.</returns>
private async Task<DisplayPreferences> RetrieveDisplayPreferences(Guid displayPreferencesId)
{
var displayPreferences = await Repository.GetDisplayPreferences(displayPreferencesId).ConfigureAwait(false);
return displayPreferences ?? new DisplayPreferences { Id = displayPreferencesId };
}
/// <summary>
/// Saves display preferences for an item
/// </summary>
/// <param name="displayPreferences">The display preferences.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task SaveDisplayPreferences(DisplayPreferences displayPreferences, CancellationToken cancellationToken)
{
if (displayPreferences == null)
{
throw new ArgumentNullException("displayPreferences");
}
if (displayPreferences.Id == Guid.Empty)
{
throw new ArgumentNullException("displayPreferences.Id");
}
try
{
await Repository.SaveDisplayPreferences(displayPreferences,
cancellationToken).ConfigureAwait(false);
var newValue = Task.FromResult(displayPreferences);
// Once it succeeds, put it into the dictionary to make it available to everyone else
_displayPreferences.AddOrUpdate(displayPreferences.Id, newValue, delegate { return newValue; });
}
catch (Exception ex)
{
_logger.ErrorException("Error saving display preferences", ex);
throw;
}
}
}
}

View File

@ -5,7 +5,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Connectivity;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Concurrent;
@ -26,8 +25,8 @@ namespace MediaBrowser.Server.Implementations.Library
/// <summary>
/// The _active connections
/// </summary>
private readonly List<ClientConnectionInfo> _activeConnections =
new List<ClientConnectionInfo>();
private readonly ConcurrentDictionary<string, ClientConnectionInfo> _activeConnections =
new ConcurrentDictionary<string, ClientConnectionInfo>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// The _users
@ -70,7 +69,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <value>All connections.</value>
public IEnumerable<ClientConnectionInfo> AllConnections
{
get { return _activeConnections.Where(c => GetUserById(c.UserId) != null).OrderByDescending(c => c.LastActivityDate); }
get { return _activeConnections.Values.OrderByDescending(c => c.LastActivityDate); }
}
/// <summary>
@ -99,11 +98,6 @@ namespace MediaBrowser.Server.Implementations.Library
/// <value>The configuration manager.</value>
private IServerConfigurationManager ConfigurationManager { get; set; }
/// <summary>
/// The _user data
/// </summary>
private readonly ConcurrentDictionary<string, Task<DisplayPreferences>> _displayPreferences = new ConcurrentDictionary<string, Task<DisplayPreferences>>();
private readonly ConcurrentDictionary<string, Task<UserItemData>> _userData = new ConcurrentDictionary<string, Task<UserItemData>>();
/// <summary>
@ -165,63 +159,6 @@ namespace MediaBrowser.Server.Implementations.Library
}
#endregion
/// <summary>
/// Gets the display preferences.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <returns>DisplayPreferences.</returns>
public Task<DisplayPreferences> GetDisplayPreferences(Guid userId, Guid displayPreferencesId)
{
var key = userId + displayPreferencesId.ToString();
return _displayPreferences.GetOrAdd(key, keyName => RetrieveDisplayPreferences(userId, displayPreferencesId));
}
/// <summary>
/// Retrieves the display preferences.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <returns>DisplayPreferences.</returns>
private async Task<DisplayPreferences> RetrieveDisplayPreferences(Guid userId, Guid displayPreferencesId)
{
var displayPreferences = await Kernel.Instance.DisplayPreferencesRepository.GetDisplayPreferences(userId, displayPreferencesId).ConfigureAwait(false);
return displayPreferences ?? new DisplayPreferences();
}
/// <summary>
/// Saves display preferences for an item
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <param name="displayPreferences">The display preferences.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task SaveDisplayPreferences(Guid userId, Guid displayPreferencesId, DisplayPreferences displayPreferences, CancellationToken cancellationToken)
{
var key = userId + displayPreferencesId.ToString();
try
{
await Kernel.Instance.DisplayPreferencesRepository.SaveDisplayPreferences(userId, displayPreferencesId,
displayPreferences,
cancellationToken).ConfigureAwait(false);
var newValue = Task.FromResult(displayPreferences);
// Once it succeeds, put it into the dictionary to make it available to everyone else
_displayPreferences.AddOrUpdate(key, newValue, delegate { return newValue; });
}
catch (Exception ex)
{
_logger.ErrorException("Error saving display preferences", ex);
throw;
}
}
/// <summary>
/// Gets a User by Id
/// </summary>
@ -232,7 +169,7 @@ namespace MediaBrowser.Server.Implementations.Library
{
if (id == Guid.Empty)
{
throw new ArgumentNullException();
throw new ArgumentNullException("id");
}
return Users.FirstOrDefault(u => u.Id == id);
@ -376,29 +313,19 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>ClientConnectionInfo.</returns>
private ClientConnectionInfo GetConnection(Guid userId, string clientType, string deviceId, string deviceName)
{
lock (_activeConnections)
{
var conn = _activeConnections.FirstOrDefault(c => string.Equals(c.Client, clientType, StringComparison.OrdinalIgnoreCase) && string.Equals(deviceId, c.DeviceId));
var key = clientType + deviceId;
if (conn == null)
{
conn = new ClientConnectionInfo
var connection = _activeConnections.GetOrAdd(key, keyName => new ClientConnectionInfo
{
UserId = userId,
Client = clientType,
DeviceName = deviceName,
DeviceId = deviceId
};
});
_activeConnections.Add(conn);
}
else
{
conn.UserId = userId;
}
connection.UserId = userId;
return conn;
}
return connection;
}
/// <summary>
@ -802,11 +729,11 @@ namespace MediaBrowser.Server.Implementations.Library
}
/// <summary>
/// Gets the display preferences.
/// Gets the user data.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="userDataId">The user data id.</param>
/// <returns>Task{DisplayPreferences}.</returns>
/// <returns>Task{UserItemData}.</returns>
public Task<UserItemData> GetUserData(Guid userId, Guid userDataId)
{
var key = userId + userDataId.ToString();
@ -815,11 +742,11 @@ namespace MediaBrowser.Server.Implementations.Library
}
/// <summary>
/// Retrieves the display preferences.
/// Retrieves the user data.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="userDataId">The user data id.</param>
/// <returns>DisplayPreferences.</returns>
/// <returns>Task{UserItemData}.</returns>
private async Task<UserItemData> RetrieveUserData(Guid userId, Guid userDataId)
{
var userdata = await Kernel.Instance.UserDataRepository.GetUserData(userId, userDataId).ConfigureAwait(false);

View File

@ -130,6 +130,7 @@
<Compile Include="HttpServer\SwaggerService.cs" />
<Compile Include="IO\DirectoryWatchers.cs" />
<Compile Include="Library\CoreResolutionIgnoreRule.cs" />
<Compile Include="Library\DisplayPreferencesManager.cs" />
<Compile Include="Library\LibraryManager.cs" />
<Compile Include="Library\LuceneSearchEngine.cs" />
<Compile Include="Library\ResolverHelper.cs" />

View File

@ -104,7 +104,7 @@ namespace MediaBrowser.Server.Implementations.Providers
/// <param name="providers">The providers.</param>
public void AddMetadataProviders(IEnumerable<BaseMetadataProvider> providers)
{
MetadataProviders = providers.ToArray();
MetadataProviders = providers.OrderBy(e => e.Priority).ToArray();
}
/// <summary>

View File

@ -33,6 +33,18 @@ namespace MediaBrowser.Server.Implementations.Sqlite
}
}
/// <summary>
/// Gets a value indicating whether [enable delayed commands].
/// </summary>
/// <value><c>true</c> if [enable delayed commands]; otherwise, <c>false</c>.</value>
protected override bool EnableDelayedCommands
{
get
{
return false;
}
}
/// <summary>
/// The _protobuf serializer
/// </summary>
@ -78,8 +90,8 @@ namespace MediaBrowser.Server.Implementations.Sqlite
string[] queries = {
"create table if not exists displaypreferences (id GUID, userId GUID, data BLOB)",
"create unique index if not exists displaypreferencesindex on displaypreferences (id, userId)",
"create table if not exists displaypreferences (id GUID, data BLOB)",
"create unique index if not exists displaypreferencesindex on displaypreferences (id)",
"create table if not exists schema_version (table_name primary key, version)",
//pragmas
"pragma temp_store = memory"
@ -91,75 +103,77 @@ namespace MediaBrowser.Server.Implementations.Sqlite
/// <summary>
/// Save the display preferences associated with an item in the repo
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <param name="displayPreferences">The display preferences.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
public Task SaveDisplayPreferences(Guid userId, Guid displayPreferencesId, DisplayPreferences displayPreferences, CancellationToken cancellationToken)
public async Task SaveDisplayPreferences(DisplayPreferences displayPreferences, CancellationToken cancellationToken)
{
if (displayPreferences == null)
{
throw new ArgumentNullException("displayPreferences");
}
if (displayPreferences.Id == Guid.Empty)
{
throw new ArgumentNullException("displayPreferences.Id");
}
if (cancellationToken == null)
{
throw new ArgumentNullException("cancellationToken");
}
if (userId == Guid.Empty)
{
throw new ArgumentNullException("userId");
}
if (displayPreferencesId == Guid.Empty)
{
throw new ArgumentNullException("displayPreferencesId");
}
cancellationToken.ThrowIfCancellationRequested();
return Task.Run(() =>
{
var serialized = _protobufSerializer.SerializeToBytes(displayPreferences);
cancellationToken.ThrowIfCancellationRequested();
var cmd = connection.CreateCommand();
cmd.CommandText = "replace into displaypreferences (id, userId, data) values (@1, @2, @3)";
cmd.AddParam("@1", displayPreferencesId);
cmd.AddParam("@2", userId);
cmd.AddParam("@3", serialized);
QueueCommand(cmd);
});
cmd.CommandText = "replace into displaypreferences (id, data) values (@1, @2)";
cmd.AddParam("@1", displayPreferences.Id);
cmd.AddParam("@2", serialized);
using (var tran = connection.BeginTransaction())
{
try
{
cmd.Transaction = tran;
await cmd.ExecuteNonQueryAsync(cancellationToken);
tran.Commit();
}
catch (OperationCanceledException)
{
tran.Rollback();
}
catch (Exception e)
{
Logger.ErrorException("Failed to commit transaction.", e);
tran.Rollback();
}
}
}
/// <summary>
/// Gets the display preferences.
/// </summary>
/// <param name="userId">The user id.</param>
/// <param name="displayPreferencesId">The display preferences id.</param>
/// <returns>Task{DisplayPreferences}.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
public async Task<DisplayPreferences> GetDisplayPreferences(Guid userId, Guid displayPreferencesId)
public async Task<DisplayPreferences> GetDisplayPreferences(Guid displayPreferencesId)
{
if (userId == Guid.Empty)
{
throw new ArgumentNullException("userId");
}
if (displayPreferencesId == Guid.Empty)
{
throw new ArgumentNullException("displayPreferencesId");
}
var cmd = connection.CreateCommand();
cmd.CommandText = "select data from displaypreferences where id = @id and userId=@userId";
cmd.CommandText = "select data from displaypreferences where id = @id";
var idParam = cmd.Parameters.Add("@id", DbType.Guid);
idParam.Value = displayPreferencesId;
var userIdParam = cmd.Parameters.Add("@userId", DbType.Guid);
userIdParam.Value = userId;
using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow).ConfigureAwait(false))
{
if (reader.Read())

View File

@ -30,7 +30,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
/// <summary>
/// The flush interval
/// </summary>
private const int FlushInterval = 5000;
private const int FlushInterval = 2000;
/// <summary>
/// The flush timer
@ -43,6 +43,18 @@ namespace MediaBrowser.Server.Implementations.Sqlite
/// <value>The logger.</value>
protected ILogger Logger { get; private set; }
/// <summary>
/// Gets a value indicating whether [enable delayed commands].
/// </summary>
/// <value><c>true</c> if [enable delayed commands]; otherwise, <c>false</c>.</value>
protected virtual bool EnableDelayedCommands
{
get
{
return true;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="SqliteRepository" /> class.
/// </summary>
@ -85,9 +97,12 @@ namespace MediaBrowser.Server.Implementations.Sqlite
await connection.OpenAsync().ConfigureAwait(false);
if (EnableDelayedCommands)
{
// Run once
FlushTimer = new Timer(Flush, null, TimeSpan.FromMilliseconds(FlushInterval), TimeSpan.FromMilliseconds(-1));
}
}
/// <summary>
/// Runs the queries.
@ -147,16 +162,9 @@ namespace MediaBrowser.Server.Implementations.Sqlite
{
if (connection != null)
{
// If we're not already flushing, do it now
if (!IsFlushing)
if (EnableDelayedCommands)
{
Flush(null);
}
// Don't dispose in the middle of a flush
while (IsFlushing)
{
Thread.Sleep(25);
FlushOnDispose();
}
if (connection.IsOpen())
@ -181,6 +189,24 @@ namespace MediaBrowser.Server.Implementations.Sqlite
}
}
/// <summary>
/// Flushes the on dispose.
/// </summary>
private void FlushOnDispose()
{
// If we're not already flushing, do it now
if (!IsFlushing)
{
Flush(null);
}
// Don't dispose in the middle of a flush
while (IsFlushing)
{
Thread.Sleep(25);
}
}
/// <summary>
/// Queues the command.
/// </summary>

View File

@ -34,6 +34,18 @@ namespace MediaBrowser.Server.Implementations.Sqlite
}
}
/// <summary>
/// Gets a value indicating whether [enable delayed commands].
/// </summary>
/// <value><c>true</c> if [enable delayed commands]; otherwise, <c>false</c>.</value>
protected override bool EnableDelayedCommands
{
get
{
return false;
}
}
/// <summary>
/// The _protobuf serializer
/// </summary>
@ -106,7 +118,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
/// or
/// userDataId
/// </exception>
public Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData, CancellationToken cancellationToken)
public async Task SaveUserData(Guid userId, Guid userDataId, UserItemData userData, CancellationToken cancellationToken)
{
if (userData == null)
{
@ -127,8 +139,6 @@ namespace MediaBrowser.Server.Implementations.Sqlite
cancellationToken.ThrowIfCancellationRequested();
return Task.Run(() =>
{
var serialized = _protobufSerializer.SerializeToBytes(userData);
cancellationToken.ThrowIfCancellationRequested();
@ -138,8 +148,27 @@ namespace MediaBrowser.Server.Implementations.Sqlite
cmd.AddParam("@1", userDataId);
cmd.AddParam("@2", userId);
cmd.AddParam("@3", serialized);
QueueCommand(cmd);
});
using (var tran = connection.BeginTransaction())
{
try
{
cmd.Transaction = tran;
await cmd.ExecuteNonQueryAsync(cancellationToken);
tran.Commit();
}
catch (OperationCanceledException)
{
tran.Rollback();
}
catch (Exception e)
{
Logger.ErrorException("Failed to commit transaction.", e);
tran.Rollback();
}
}
}
/// <summary>

View File

@ -45,6 +45,18 @@ namespace MediaBrowser.Server.Implementations.Sqlite
/// </summary>
private readonly IApplicationPaths _appPaths;
/// <summary>
/// Gets a value indicating whether [enable delayed commands].
/// </summary>
/// <value><c>true</c> if [enable delayed commands]; otherwise, <c>false</c>.</value>
protected override bool EnableDelayedCommands
{
get
{
return false;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="SQLiteUserDataRepository" /> class.
/// </summary>
@ -97,7 +109,7 @@ namespace MediaBrowser.Server.Implementations.Sqlite
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">user</exception>
public Task SaveUser(User user, CancellationToken cancellationToken)
public async Task SaveUser(User user, CancellationToken cancellationToken)
{
if (user == null)
{
@ -109,8 +121,6 @@ namespace MediaBrowser.Server.Implementations.Sqlite
throw new ArgumentNullException("cancellationToken");
}
return Task.Run(() =>
{
cancellationToken.ThrowIfCancellationRequested();
var serialized = _jsonSerializer.SerializeToBytes(user);
@ -121,8 +131,27 @@ namespace MediaBrowser.Server.Implementations.Sqlite
cmd.CommandText = "replace into users (guid, data) values (@1, @2)";
cmd.AddParam("@1", user.Id);
cmd.AddParam("@2", serialized);
QueueCommand(cmd);
});
using (var tran = connection.BeginTransaction())
{
try
{
cmd.Transaction = tran;
await cmd.ExecuteNonQueryAsync(cancellationToken);
tran.Commit();
}
catch (OperationCanceledException)
{
tran.Rollback();
}
catch (Exception e)
{
Logger.ErrorException("Failed to commit transaction.", e);
tran.Rollback();
}
}
}
/// <summary>

View File

@ -165,7 +165,7 @@ namespace MediaBrowser.ServerApplication
await CompositionRoot.Init();
var win = new MainWindow(CompositionRoot.LogManager, CompositionRoot, CompositionRoot.ServerConfigurationManager, CompositionRoot.UserManager, CompositionRoot.LibraryManager, CompositionRoot.JsonSerializer);
var win = new MainWindow(CompositionRoot.LogManager, CompositionRoot, CompositionRoot.ServerConfigurationManager, CompositionRoot.UserManager, CompositionRoot.LibraryManager, CompositionRoot.JsonSerializer, CompositionRoot.DisplayPreferencesManager);
win.Show();
}

View File

@ -1,8 +1,4 @@
using System.Diagnostics;
using System.Net.Cache;
using System.Net.Http;
using System.Net.Sockets;
using MediaBrowser.Api;
using MediaBrowser.Api;
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Constants;
@ -46,8 +42,10 @@ using MediaBrowser.ServerApplication.Implementations;
using MediaBrowser.WebDashboard.Api;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
@ -140,6 +138,11 @@ namespace MediaBrowser.ServerApplication
/// </summary>
/// <value>The UDP server.</value>
private UdpServer UdpServer { get; set; }
/// <summary>
/// Gets or sets the display preferences manager.
/// </summary>
/// <value>The display preferences manager.</value>
internal IDisplayPreferencesManager DisplayPreferencesManager { get; set; }
/// <summary>
/// The full path to our startmenu shortcut
@ -212,8 +215,12 @@ namespace MediaBrowser.ServerApplication
ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, DirectoryWatchers, LogManager);
RegisterSingleInstance(ProviderManager);
DisplayPreferencesManager = new DisplayPreferencesManager(LogManager.GetLogger("DisplayPreferencesManager"));
RegisterSingleInstance(DisplayPreferencesManager);
RegisterSingleInstance<ILibrarySearchEngine>(() => new LuceneSearchEngine());
await ConfigureRepositories().ConfigureAwait(false);
SetKernelProperties();
SetStaticProperties();
}
@ -229,7 +236,6 @@ namespace MediaBrowser.ServerApplication
Parallel.Invoke(
() => ServerKernel.UserDataRepositories = GetExports<IUserDataRepository>(),
() => ServerKernel.UserRepositories = GetExports<IUserRepository>(),
() => ServerKernel.DisplayPreferencesRepositories = GetExports<IDisplayPreferencesRepository>(),
() => ServerKernel.ItemRepositories = GetExports<IItemRepository>(),
() => ServerKernel.WeatherProviders = GetExports<IWeatherProvider>(),
() => ServerKernel.ImageEnhancers = GetExports<IImageEnhancer>().OrderBy(e => e.Priority).ToArray(),
@ -237,6 +243,21 @@ namespace MediaBrowser.ServerApplication
);
}
/// <summary>
/// Configures the repositories.
/// </summary>
/// <returns>Task.</returns>
private async Task ConfigureRepositories()
{
var displayPreferencesRepositories = GetExports<IDisplayPreferencesRepository>();
var repo = GetRepository(displayPreferencesRepositories, ServerConfigurationManager.Configuration.DisplayPreferencesRepository);
await repo.Initialize().ConfigureAwait(false);
((DisplayPreferencesManager)DisplayPreferencesManager).Repository = repo;
}
/// <summary>
/// Dirty hacks
/// </summary>
@ -277,7 +298,7 @@ namespace MediaBrowser.ServerApplication
() => LibraryManager.AddParts(GetExports<IResolverIgnoreRule>(), GetExports<IVirtualFolderCreator>(), GetExports<IItemResolver>(), GetExports<IIntroProvider>(), GetExports<IBaseItemComparer>()),
() => ProviderManager.AddMetadataProviders(GetExports<BaseMetadataProvider>().OrderBy(e => e.Priority).ToArray())
() => ProviderManager.AddMetadataProviders(GetExports<BaseMetadataProvider>().ToArray())
);
UdpServer = new UdpServer(Logger, NetworkManager, ServerConfigurationManager);
@ -450,5 +471,21 @@ namespace MediaBrowser.ServerApplication
process.WaitForExit();
}
}
/// <summary>
/// Gets the repository.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="repositories">The repositories.</param>
/// <param name="name">The name.</param>
/// <returns>``0.</returns>
private T GetRepository<T>(IEnumerable<T> repositories, string name)
where T : class, IRepository
{
var enumerable = repositories as T[] ?? repositories.ToArray();
return enumerable.FirstOrDefault(r => string.Equals(r.Name, name, StringComparison.OrdinalIgnoreCase)) ??
enumerable.FirstOrDefault();
}
}
}

View File

@ -33,7 +33,7 @@ namespace MediaBrowser.ServerApplication
private readonly IJsonSerializer _jsonSerializer;
private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager;
private readonly IDisplayPreferencesManager _displayPreferencesManager;
/// <summary>
/// The current user
@ -42,12 +42,18 @@ namespace MediaBrowser.ServerApplication
/// <summary>
/// Initializes a new instance of the <see cref="LibraryExplorer" /> class.
/// </summary>
public LibraryExplorer(IJsonSerializer jsonSerializer, ILogger logger, IApplicationHost appHost, IUserManager userManager, ILibraryManager libraryManager)
/// <param name="jsonSerializer">The json serializer.</param>
/// <param name="logger">The logger.</param>
/// <param name="appHost">The app host.</param>
/// <param name="userManager">The user manager.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="displayPreferencesManager">The display preferences manager.</param>
public LibraryExplorer(IJsonSerializer jsonSerializer, ILogger logger, IApplicationHost appHost, IUserManager userManager, ILibraryManager libraryManager, IDisplayPreferencesManager displayPreferencesManager)
{
_logger = logger;
_jsonSerializer = jsonSerializer;
_libraryManager = libraryManager;
_userManager = userManager;
_displayPreferencesManager = displayPreferencesManager;
InitializeComponent();
lblVersion.Content = "Version: " + appHost.ApplicationVersion;
@ -91,7 +97,7 @@ namespace MediaBrowser.ServerApplication
var currentFolder = folder;
Task.Factory.StartNew(() =>
{
var prefs = ddlProfile.SelectedItem != null ? _userManager.GetDisplayPreferences((ddlProfile.SelectedItem as User).Id, currentFolder.DisplayPreferencesId).Result ?? new DisplayPreferences { SortBy = ItemSortBy.SortName } : new DisplayPreferences { SortBy = ItemSortBy.SortName };
var prefs = ddlProfile.SelectedItem != null ? _displayPreferencesManager.GetDisplayPreferences(currentFolder.GetDisplayPreferencesId((ddlProfile.SelectedItem as User).Id)).Result ?? new DisplayPreferences { SortBy = ItemSortBy.SortName } : new DisplayPreferences { SortBy = ItemSortBy.SortName };
var node = new TreeViewItem { Tag = currentFolder };
var subChildren = currentFolder.GetChildren(CurrentUser, prefs.IndexBy);
@ -144,7 +150,7 @@ namespace MediaBrowser.ServerApplication
var subFolder = item as Folder;
if (subFolder != null)
{
var prefs = _userManager.GetDisplayPreferences(user.Id, subFolder.DisplayPreferencesId).Result;
var prefs = _displayPreferencesManager.GetDisplayPreferences(subFolder.GetDisplayPreferencesId(user.Id)).Result;
AddChildren(node, OrderBy(subFolder.GetChildren(user), user, prefs.SortBy), user);
node.Header = item.Name + " (" + node.Items.Count + ")";
@ -201,8 +207,8 @@ namespace MediaBrowser.ServerApplication
var prefs =
await
_userManager.GetDisplayPreferences((ddlProfile.SelectedItem as User).Id,
folder.DisplayPreferencesId);
_displayPreferencesManager.GetDisplayPreferences(folder.GetDisplayPreferencesId((ddlProfile.SelectedItem as User).Id));
ddlIndexBy.SelectedItem = prefs != null
? prefs.IndexBy ?? LocalizedStrings.Instance.GetString("NoneDispPref")
: LocalizedStrings.Instance.GetString("NoneDispPref");
@ -360,7 +366,7 @@ namespace MediaBrowser.ServerApplication
var folder = treeItem != null
? treeItem.Tag as Folder
: null;
var prefs = folder != null ? _userManager.GetDisplayPreferences(CurrentUser.Id, folder.DisplayPreferencesId).Result : new DisplayPreferences {SortBy = ItemSortBy.SortName};
var prefs = folder != null ? _displayPreferencesManager.GetDisplayPreferences(folder.GetDisplayPreferencesId(CurrentUser.Id)).Result : new DisplayPreferences { SortBy = ItemSortBy.SortName };
if (folder != null && prefs.IndexBy != ddlIndexBy.SelectedItem as string)
{
//grab UI context so we can update within the below task
@ -401,7 +407,7 @@ namespace MediaBrowser.ServerApplication
var folder = treeItem != null
? treeItem.Tag as Folder
: null;
var prefs = folder != null ? _userManager.GetDisplayPreferences(CurrentUser.Id, folder.DisplayPreferencesId).Result : new DisplayPreferences();
var prefs = folder != null ? _displayPreferencesManager.GetDisplayPreferences(folder.GetDisplayPreferencesId(CurrentUser.Id)).Result : new DisplayPreferences();
if (folder != null && prefs.SortBy != ddlSortBy.SelectedItem as string)
{
//grab UI context so we can update within the below task

View File

@ -43,6 +43,7 @@ namespace MediaBrowser.ServerApplication
private readonly IUserManager _userManager;
private readonly ILibraryManager _libraryManager;
private readonly IJsonSerializer _jsonSerializer;
private readonly IDisplayPreferencesManager _displayPreferencesManager;
/// <summary>
/// Initializes a new instance of the <see cref="MainWindow" /> class.
@ -51,7 +52,7 @@ namespace MediaBrowser.ServerApplication
/// <param name="logger">The logger.</param>
/// <param name="appHost">The app host.</param>
/// <exception cref="System.ArgumentNullException">logger</exception>
public MainWindow(ILogManager logManager, IApplicationHost appHost, IServerConfigurationManager configurationManager, IUserManager userManager, ILibraryManager libraryManager, IJsonSerializer jsonSerializer)
public MainWindow(ILogManager logManager, IApplicationHost appHost, IServerConfigurationManager configurationManager, IUserManager userManager, ILibraryManager libraryManager, IJsonSerializer jsonSerializer, IDisplayPreferencesManager displayPreferencesManager)
{
if (logManager == null)
{
@ -73,6 +74,7 @@ namespace MediaBrowser.ServerApplication
_userManager = userManager;
_libraryManager = libraryManager;
_jsonSerializer = jsonSerializer;
_displayPreferencesManager = displayPreferencesManager;
InitializeComponent();
@ -223,7 +225,7 @@ namespace MediaBrowser.ServerApplication
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
private void cmOpenExplorer_click(object sender, RoutedEventArgs e)
{
new LibraryExplorer(_jsonSerializer, _logger, _appHost, _userManager, _libraryManager).Show();
new LibraryExplorer(_jsonSerializer, _logger, _appHost, _userManager, _libraryManager, _displayPreferencesManager).Show();
}
/// <summary>

View File

@ -436,6 +436,6 @@ del "$(SolutionDir)..\Deploy\MBServer.zip"
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="CurrentAssembly" />
</GetAssemblyIdentity>
<Exec Command="copy $(SolutionDir)..\Deploy\MBServer.zip $(SolutionDir)..\Deploy\MBServer_%(CurrentAssembly.Version).zip /y" Condition="'$(ConfigurationName)' == 'Release'" />
<Exec Command="copy &quot;$(SolutionDir)..\Deploy\MBServer.zip&quot; &quot;$(SolutionDir)..\Deploy\MBServer_%(CurrentAssembly.Version).zip&quot; /y" Condition="'$(ConfigurationName)' == 'Release'" />
</Target>
</Project>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
<version>3.0.66</version>
<version>3.0.67</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 Theatre 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.66" />
<dependency id="MediaBrowser.Common" version="3.0.67" />
<dependency id="NLog" version="2.0.0.2000" />
<dependency id="ServiceStack.Text" version="3.9.38" />
<dependency id="protobuf-net" version="2.0.0.621" />

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
<version>3.0.66</version>
<version>3.0.67</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
<version>3.0.66</version>
<version>3.0.67</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.66" />
<dependency id="MediaBrowser.Common" version="3.0.67" />
</dependencies>
</metadata>
<files>