dlna fixes

This commit is contained in:
Luke Pulverenti 2014-06-22 01:52:31 -04:00
parent 5ce3ed2fb4
commit 414b1251c7
41 changed files with 204 additions and 102 deletions

View File

@ -406,7 +406,7 @@ namespace MediaBrowser.Api
Task.WaitAll(task); Task.WaitAll(task);
user.UpdateConfiguration(dtoUser.Configuration, _xmlSerializer); user.UpdateConfiguration(dtoUser.Configuration);
} }
/// <summary> /// <summary>
@ -420,7 +420,7 @@ namespace MediaBrowser.Api
var newUser = _userManager.CreateUser(dtoUser.Name).Result; var newUser = _userManager.CreateUser(dtoUser.Name).Result;
newUser.UpdateConfiguration(dtoUser.Configuration, _xmlSerializer); newUser.UpdateConfiguration(dtoUser.Configuration);
var result = _dtoService.GetUserDto(newUser); var result = _dtoService.GetUserDto(newUser);

View File

@ -74,7 +74,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
progress.Report(90); progress.Report(90);
minDateModified = DateTime.UtcNow.AddDays(-3); minDateModified = DateTime.UtcNow.AddDays(-2);
try try
{ {

View File

@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
DisplayMediaType = "CollectionFolder"; DisplayMediaType = "CollectionFolder";
} }
public string CollectionType public virtual string CollectionType
{ {
get { return Model.Entities.CollectionType.BoxSets; } get { return Model.Entities.CollectionType.BoxSets; }
} }

View File

@ -4,7 +4,6 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Threading; using System.Threading;
@ -221,23 +220,12 @@ namespace MediaBrowser.Controller.Entities
} }
} }
/// <summary>
/// Saves the current configuration to the file system
/// </summary>
public void SaveConfiguration()
{
var xmlPath = ConfigurationFilePath;
Directory.CreateDirectory(System.IO.Path.GetDirectoryName(xmlPath));
XmlSerializer.SerializeToFile(Configuration, xmlPath);
}
/// <summary> /// <summary>
/// Updates the configuration. /// Updates the configuration.
/// </summary> /// </summary>
/// <param name="config">The config.</param> /// <param name="config">The config.</param>
/// <param name="serializer">The serializer.</param>
/// <exception cref="System.ArgumentNullException">config</exception> /// <exception cref="System.ArgumentNullException">config</exception>
public void UpdateConfiguration(UserConfiguration config, IXmlSerializer serializer) public void UpdateConfiguration(UserConfiguration config)
{ {
if (config == null) if (config == null)
{ {
@ -245,7 +233,7 @@ namespace MediaBrowser.Controller.Entities
} }
Configuration = config; Configuration = config;
SaveConfiguration(); UserManager.UpdateConfiguration(this, Configuration);
} }
} }
} }

View File

@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Events; using MediaBrowser.Model.Events;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -29,6 +30,14 @@ namespace MediaBrowser.Controller.Library
event EventHandler<GenericEventArgs<User>> UserDeleted; event EventHandler<GenericEventArgs<User>> UserDeleted;
event EventHandler<GenericEventArgs<User>> UserCreated; event EventHandler<GenericEventArgs<User>> UserCreated;
event EventHandler<GenericEventArgs<User>> UserConfigurationUpdated;
/// <summary>
/// Updates the configuration.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="newConfiguration">The new configuration.</param>
void UpdateConfiguration(User user, UserConfiguration newConfiguration);
/// <summary> /// <summary>
/// Gets a User by Id /// Gets a User by Id

View File

@ -4,6 +4,7 @@ using MediaBrowser.Dlna.Server;
using MediaBrowser.Dlna.Service; using MediaBrowser.Dlna.Service;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
@ -22,9 +23,21 @@ namespace MediaBrowser.Dlna.ConnectionManager
protected override IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, Headers methodParams) protected override IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, Headers methodParams)
{ {
var deviceId = "test"; if (string.Equals(methodName, "GetProtocolInfo", StringComparison.OrdinalIgnoreCase))
{
return HandleGetProtocolInfo();
}
throw new ResourceNotFoundException("Unexpected control request name: " + methodName); throw new ResourceNotFoundException("Unexpected control request name: " + methodName);
} }
private IEnumerable<KeyValuePair<string, string>> HandleGetProtocolInfo()
{
return new Headers(true)
{
{ "Source", _profile.ProtocolInfo },
{ "Sink", "" }
};
}
} }
} }

View File

@ -103,12 +103,12 @@ namespace MediaBrowser.Dlna.ContentDirectory
private IEnumerable<KeyValuePair<string, string>> HandleGetSearchCapabilities() private IEnumerable<KeyValuePair<string, string>> HandleGetSearchCapabilities()
{ {
return new Headers { { "SearchCaps", string.Empty } }; return new Headers(true) { { "SearchCaps", "upnp:class,dc:title,upnp:artist" } };
} }
private IEnumerable<KeyValuePair<string, string>> HandleGetSortCapabilities() private IEnumerable<KeyValuePair<string, string>> HandleGetSortCapabilities()
{ {
return new Headers { { "SortCaps", string.Empty } }; return new Headers(true) { { "SortCaps", string.Empty } };
} }
private IEnumerable<KeyValuePair<string, string>> HandleGetSystemUpdateID() private IEnumerable<KeyValuePair<string, string>> HandleGetSystemUpdateID()
@ -120,7 +120,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private IEnumerable<KeyValuePair<string, string>> HandleXGetFeatureList() private IEnumerable<KeyValuePair<string, string>> HandleXGetFeatureList()
{ {
return new Headers { { "FeatureList", GetFeatureListXml() } }; return new Headers(true) { { "FeatureList", GetFeatureListXml() } };
} }
private string GetFeatureListXml() private string GetFeatureListXml()
@ -386,7 +386,21 @@ namespace MediaBrowser.Dlna.ContentDirectory
|| string.Equals(id, "1", StringComparison.OrdinalIgnoreCase) || string.Equals(id, "1", StringComparison.OrdinalIgnoreCase)
? user.RootFolder ? user.RootFolder
: _libraryManager.GetItemById(new Guid(id)); : ParseItemId(id, user);
}
private BaseItem ParseItemId(string id, User user)
{
Guid itemId;
if (Guid.TryParse(id, out itemId))
{
return _libraryManager.GetItemById(itemId);
}
Logger.Error("Error parsing item Id: {0}. Returning user root folder.", id);
return user.RootFolder;
} }
} }
} }

View File

@ -132,7 +132,7 @@ namespace MediaBrowser.Dlna.PlayTo
} }
} }
void _device_MediaChanged(object sender, MediaChangedEventArgs e) async void _device_MediaChanged(object sender, MediaChangedEventArgs e)
{ {
var streamInfo = StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager); var streamInfo = StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager);
var progress = GetProgressInfo(e.OldMediaInfo, streamInfo); var progress = GetProgressInfo(e.OldMediaInfo, streamInfo);
@ -140,6 +140,18 @@ namespace MediaBrowser.Dlna.PlayTo
var positionTicks = progress.PositionTicks; var positionTicks = progress.PositionTicks;
ReportPlaybackStopped(e.OldMediaInfo, streamInfo, positionTicks); ReportPlaybackStopped(e.OldMediaInfo, streamInfo, positionTicks);
try
{
streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager);
progress = GetProgressInfo(e.NewMediaInfo, streamInfo);
await _sessionManager.OnPlaybackStart(progress).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error reporting progress", ex);
}
} }
async void _device_PlaybackStopped(object sender, PlaybackStoppedEventArgs e) async void _device_PlaybackStopped(object sender, PlaybackStoppedEventArgs e)

View File

@ -118,7 +118,7 @@ namespace MediaBrowser.Dlna.PlayTo
socket.Bind(endPoint); socket.Bind(endPoint);
_logger.Info("Creating SSDP listener"); _logger.Info("Creating SSDP listener on {0}, network interface index {1}", localIp, networkInterfaceIndex);
var receiveBuffer = new byte[64000]; var receiveBuffer = new byte[64000];
@ -210,6 +210,33 @@ namespace MediaBrowser.Dlna.PlayTo
}); });
} }
private void CreateNotifier(IPAddress localIp)
{
Task.Factory.StartNew(async (o) =>
{
try
{
while (true)
{
_ssdpHandler.SendRendererSearchMessage(new IPEndPoint(localIp, 1900));
var delay = _config.Configuration.DlnaOptions.ClientDiscoveryIntervalSeconds * 1000;
await Task.Delay(delay, _tokenSource.Token).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
{
}
catch (Exception ex)
{
_logger.ErrorException("Error in notifier", ex);
}
}, _tokenSource.Token, TaskCreationOptions.LongRunning);
}
private void CreateNotifier(Socket socket) private void CreateNotifier(Socket socket)
{ {
Task.Factory.StartNew(async (o) => Task.Factory.StartNew(async (o) =>

View File

@ -1,7 +1,6 @@
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Dlna.Common; using MediaBrowser.Dlna.Common;
using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Text; using System.Text;
@ -68,34 +67,7 @@ namespace MediaBrowser.Dlna.PlayTo
options.RequestHeaders["NT"] = "upnp:event"; options.RequestHeaders["NT"] = "upnp:event";
options.RequestHeaders["TIMEOUT"] = "Second-" + timeOut.ToString(_usCulture); options.RequestHeaders["TIMEOUT"] = "Second-" + timeOut.ToString(_usCulture);
// TODO: Method should be SUBSCRIBE await _httpClient.SendAsync(options, "SUBSCRIBE").ConfigureAwait(false);
// https://github.com/stormboy/node-upnp-controlpoint/blob/master/lib/upnp-service.js#L106
using (await _httpClient.Get(options).ConfigureAwait(false))
{
}
}
public async Task RespondAsync(Uri url,
string ip,
int port,
string localIp,
int eventport,
int timeOut = 3600)
{
var options = new HttpRequestOptions
{
Url = url.ToString(),
UserAgent = USERAGENT
};
options.RequestHeaders["HOST"] = ip + ":" + port.ToString(_usCulture);
options.RequestHeaders["CALLBACK"] = "<" + localIp + ":" + eventport.ToString(_usCulture) + ">";
options.RequestHeaders["NT"] = "upnp:event";
options.RequestHeaders["TIMEOUT"] = "Second-" + timeOut.ToString(_usCulture);
using (await _httpClient.Get(options).ConfigureAwait(false))
{
}
} }
public async Task<XDocument> GetDataAsync(string url) public async Task<XDocument> GetDataAsync(string url)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,5 @@
using MediaBrowser.Controller.Configuration; using System.Security;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
using MediaBrowser.Dlna.Server; using MediaBrowser.Dlna.Server;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
@ -63,7 +64,7 @@ namespace MediaBrowser.Dlna.Service
Logger.Debug("Received control request {0}", method.LocalName); Logger.Debug("Received control request {0}", method.LocalName);
IEnumerable<KeyValuePair<string, string>> result = GetResult(method.LocalName, sparams); var result = GetResult(method.LocalName, sparams);
var env = new XmlDocument(); var env = new XmlDocument();
env.AppendChild(env.CreateXmlDeclaration("1.0", "utf-8", string.Empty)); env.AppendChild(env.CreateXmlDeclaration("1.0", "utf-8", string.Empty));
@ -84,12 +85,14 @@ namespace MediaBrowser.Dlna.Service
response.AppendChild(ri); response.AppendChild(ri);
} }
var xml = env.OuterXml.Replace("xmlns:m=", "xmlns:u=");
var controlResponse = new ControlResponse var controlResponse = new ControlResponse
{ {
Xml = env.OuterXml, Xml = xml,
IsSuccessful = true IsSuccessful = true
}; };
Logger.Debug(xml);
controlResponse.Headers.Add("EXT", string.Empty); controlResponse.Headers.Add("EXT", string.Empty);
return controlResponse; return controlResponse;

View File

@ -9,7 +9,7 @@ namespace MediaBrowser.Dlna.Ssdp
public class Datagram public class Datagram
{ {
public IPEndPoint ToEndPoint { get; private set; } public IPEndPoint ToEndPoint { get; private set; }
public IPAddress FromEndPoint { get; private set; } public IPEndPoint FromEndPoint { get; private set; }
public string Message { get; private set; } public string Message { get; private set; }
/// <summary> /// <summary>
@ -24,7 +24,7 @@ namespace MediaBrowser.Dlna.Ssdp
private readonly ILogger _logger; private readonly ILogger _logger;
public Datagram(IPEndPoint toEndPoint, IPAddress fromEndPoint, ILogger logger, string message, int totalSendCount) public Datagram(IPEndPoint toEndPoint, IPEndPoint fromEndPoint, ILogger logger, string message, int totalSendCount)
{ {
Message = message; Message = message;
_logger = logger; _logger = logger;
@ -42,7 +42,7 @@ namespace MediaBrowser.Dlna.Ssdp
if (FromEndPoint != null) if (FromEndPoint != null)
{ {
client.Bind(new IPEndPoint(FromEndPoint, 0)); client.Bind(FromEndPoint);
} }
client.BeginSendTo(msg, 0, msg.Length, SocketFlags.None, ToEndPoint, result => client.BeginSendTo(msg, 0, msg.Length, SocketFlags.None, ToEndPoint, result =>
@ -53,7 +53,7 @@ namespace MediaBrowser.Dlna.Ssdp
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.ErrorException("Error sending Datagram", ex); _logger.ErrorException("Error sending Datagram to {0} from {1}: " + Message, ex, ToEndPoint, FromEndPoint == null ? "" : FromEndPoint.ToString());
} }
finally finally
{ {
@ -69,7 +69,7 @@ namespace MediaBrowser.Dlna.Ssdp
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.ErrorException("Error sending Datagram", ex); _logger.ErrorException("Error sending Datagram: " + Message, ex);
} }
++SendCount; ++SendCount;
} }

View File

@ -1,4 +1,5 @@
using MediaBrowser.Common.Events; using System.Text;
using MediaBrowser.Common.Events;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Dlna.Server; using MediaBrowser.Dlna.Server;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
@ -79,9 +80,27 @@ namespace MediaBrowser.Dlna.Ssdp
ReloadAliveNotifier(); ReloadAliveNotifier();
} }
public void SendRendererSearchMessage(IPEndPoint localIp)
{
SendSearchMessage("urn:schemas-upnp-org:device:MediaRenderer:1", "3", localIp);
}
public void SendSearchMessage(string deviceSearchType, string mx, IPEndPoint localIp)
{
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
values["HOST"] = "239.255.255.250:1900";
values["USER-AGENT"] = "UPnP/1.0 DLNADOC/1.50 Platinum/1.0.4.2";
values["ST"] = deviceSearchType;
values["MAN"] = "\"ssdp:discover\"";
values["MX"] = mx;
SendDatagram("M-SEARCH * HTTP/1.1", values, localIp);
}
public void SendDatagram(string header, public void SendDatagram(string header,
Dictionary<string, string> values, Dictionary<string, string> values,
IPAddress localAddress, IPEndPoint localAddress,
int sendCount = 1) int sendCount = 1)
{ {
SendDatagram(header, values, _ssdpEndp, localAddress, sendCount); SendDatagram(header, values, _ssdpEndp, localAddress, sendCount);
@ -90,7 +109,7 @@ namespace MediaBrowser.Dlna.Ssdp
public void SendDatagram(string header, public void SendDatagram(string header,
Dictionary<string, string> values, Dictionary<string, string> values,
IPEndPoint endpoint, IPEndPoint endpoint,
IPAddress localAddress, IPEndPoint localAddress,
int sendCount = 1) int sendCount = 1)
{ {
var msg = new SsdpMessageBuilder().BuildMessage(header, values); var msg = new SsdpMessageBuilder().BuildMessage(header, values);
@ -116,7 +135,7 @@ namespace MediaBrowser.Dlna.Ssdp
if (string.Equals(deviceType, "ssdp:all", StringComparison.OrdinalIgnoreCase) || if (string.Equals(deviceType, "ssdp:all", StringComparison.OrdinalIgnoreCase) ||
string.Equals(deviceType, d.Type, StringComparison.OrdinalIgnoreCase)) string.Equals(deviceType, d.Type, StringComparison.OrdinalIgnoreCase))
{ {
SendDatagram(header, values, endpoint, d.Address); SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0));
} }
} }
} }
@ -231,9 +250,16 @@ namespace MediaBrowser.Dlna.Ssdp
try try
{ {
EndPoint endpoint = new IPEndPoint(IPAddress.Any, SSDPPort); EndPoint endpoint = new IPEndPoint(IPAddress.Any, SSDPPort);
var receivedCount = _socket.EndReceiveFrom(result, ref endpoint);
var length = _socket.EndReceiveFrom(result, ref endpoint);
var received = (byte[])result.AsyncState; var received = (byte[])result.AsyncState;
if (_config.Configuration.DlnaOptions.EnableDebugLogging)
{
_logger.Debug(Encoding.ASCII.GetString(received));
}
var args = SsdpHelper.ParseSsdpResponse(received, (IPEndPoint)endpoint); var args = SsdpHelper.ParseSsdpResponse(received, (IPEndPoint)endpoint);
if (_config.Configuration.DlnaOptions.EnableDebugLogging) if (_config.Configuration.DlnaOptions.EnableDebugLogging)
@ -341,7 +367,7 @@ namespace MediaBrowser.Dlna.Ssdp
_logger.Debug("{0} said {1}", dev.USN, type); _logger.Debug("{0} said {1}", dev.USN, type);
} }
SendDatagram(header, values, dev.Address, sendCount); SendDatagram(header, values, new IPEndPoint(dev.Address, 0), sendCount);
} }
public void RegisterNotification(Guid uuid, Uri descriptionUri, IPAddress address, IEnumerable<string> services) public void RegisterNotification(Guid uuid, Uri descriptionUri, IPAddress address, IEnumerable<string> services)

View File

@ -18,7 +18,7 @@ namespace MediaBrowser.Dlna.Ssdp
{ {
builder.AppendFormat(argFormat, pair.Key, pair.Value); builder.AppendFormat(argFormat, pair.Key, pair.Value);
} }
builder.Append("\r\n"); builder.Append("\r\n");
return builder.ToString(); return builder.ToString();

View File

@ -20,7 +20,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
writer.WriteLine(index.ToString(CultureInfo.InvariantCulture)); writer.WriteLine(index.ToString(CultureInfo.InvariantCulture));
writer.WriteLine(@"{0:hh\:mm\:ss\.fff} --> {1:hh\:mm\:ss\.fff}", TimeSpan.FromTicks(trackEvent.StartPositionTicks), TimeSpan.FromTicks(trackEvent.EndPositionTicks)); writer.WriteLine(@"{0:hh\:mm\:ss\,fff} --> {1:hh\:mm\:ss\,fff}", TimeSpan.FromTicks(trackEvent.StartPositionTicks), TimeSpan.FromTicks(trackEvent.EndPositionTicks));
var text = trackEvent.Text; var text = trackEvent.Text;

View File

@ -27,7 +27,9 @@ namespace MediaBrowser.Model.Dlna
public bool Contains(string field) public bool Contains(string field)
{ {
return _all || ListHelper.ContainsIgnoreCase(_fields, field); // Don't bother with this. Some clients (media monkey) use the filter and then don't display very well when very little data comes back.
return true;
//return _all || ListHelper.ContainsIgnoreCase(_fields, field);
} }
} }
} }

View File

@ -111,7 +111,7 @@ namespace MediaBrowser.Providers.FolderImages
public bool Supports(IHasImages item) public bool Supports(IHasImages item)
{ {
return item is UserView || item is CollectionFolder; return item is UserView || item is ICollectionFolder;
} }
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)

View File

@ -232,12 +232,23 @@ namespace MediaBrowser.Server.Implementations.Channels
} }
else else
{ {
File.Delete(response.TempFilePath);
throw new ApplicationException("Unexpected response type encountered: " + response.ContentType); throw new ApplicationException("Unexpected response type encountered: " + response.ContentType);
} }
File.Move(response.TempFilePath, destination); File.Move(response.TempFilePath, destination);
await RefreshMediaSourceItem(destination, cancellationToken).ConfigureAwait(false); await RefreshMediaSourceItem(destination, cancellationToken).ConfigureAwait(false);
try
{
File.Delete(response.TempFilePath);
}
catch
{
}
} }
private async Task RefreshMediaSourceItems(IEnumerable<MediaSourceInfo> items, CancellationToken cancellationToken) private async Task RefreshMediaSourceItems(IEnumerable<MediaSourceInfo> items, CancellationToken cancellationToken)
@ -265,7 +276,7 @@ namespace MediaBrowser.Server.Implementations.Channels
{ {
return new ITaskTrigger[] return new ITaskTrigger[]
{ {
new IntervalTrigger{ Interval = TimeSpan.FromHours(4)}, new IntervalTrigger{ Interval = TimeSpan.FromHours(6)},
}; };
} }

View File

@ -27,5 +27,10 @@ namespace MediaBrowser.Server.Implementations.Collections
return !ActualChildren.Any() || base.IsHidden; return !ActualChildren.Any() || base.IsHidden;
} }
} }
public override string CollectionType
{
get { return Model.Entities.CollectionType.BoxSets; }
}
} }
} }

View File

@ -9,7 +9,6 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Events; using MediaBrowser.Model.Events;
using MediaBrowser.Model.Tasks;
using System; using System;
using System.Threading; using System.Threading;
@ -74,6 +73,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{ {
_userManager.UserDeleted += userManager_UserDeleted; _userManager.UserDeleted += userManager_UserDeleted;
_userManager.UserUpdated += userManager_UserUpdated; _userManager.UserUpdated += userManager_UserUpdated;
_userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated;
_appHost.HasPendingRestartChanged += kernel_HasPendingRestartChanged; _appHost.HasPendingRestartChanged += kernel_HasPendingRestartChanged;
@ -86,6 +86,13 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
_taskManager.TaskCompleted += _taskManager_TaskCompleted; _taskManager.TaskCompleted += _taskManager_TaskCompleted;
} }
void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs<User> e)
{
var dto = _dtoService.GetUserDto(e.Argument);
_serverManager.SendWebSocketMessage("UserConfigurationUpdated", dto);
}
void _installationManager_PackageInstalling(object sender, InstallationEventArgs e) void _installationManager_PackageInstalling(object sender, InstallationEventArgs e)
{ {
_serverManager.SendWebSocketMessage("PackageInstalling", e.InstallationInfo); _serverManager.SendWebSocketMessage("PackageInstalling", e.InstallationInfo);
@ -171,6 +178,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{ {
_userManager.UserDeleted -= userManager_UserDeleted; _userManager.UserDeleted -= userManager_UserDeleted;
_userManager.UserUpdated -= userManager_UserUpdated; _userManager.UserUpdated -= userManager_UserUpdated;
_userManager.UserConfigurationUpdated -= _userManager_UserConfigurationUpdated;
_installationManager.PluginUninstalled -= InstallationManager_PluginUninstalled; _installationManager.PluginUninstalled -= InstallationManager_PluginUninstalled;
_installationManager.PackageInstalling -= _installationManager_PackageInstalling; _installationManager.PackageInstalling -= _installationManager_PackageInstalling;

View File

@ -5,8 +5,10 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Events; using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -46,16 +48,19 @@ namespace MediaBrowser.Server.Implementations.Library
/// <value>The user repository.</value> /// <value>The user repository.</value>
private IUserRepository UserRepository { get; set; } private IUserRepository UserRepository { get; set; }
private readonly IXmlSerializer _xmlSerializer;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UserManager" /> class. /// Initializes a new instance of the <see cref="UserManager" /> class.
/// </summary> /// </summary>
/// <param name="logger">The logger.</param> /// <param name="logger">The logger.</param>
/// <param name="configurationManager">The configuration manager.</param> /// <param name="configurationManager">The configuration manager.</param>
/// <param name="userRepository">The user repository.</param> /// <param name="userRepository">The user repository.</param>
public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository) public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer)
{ {
_logger = logger; _logger = logger;
UserRepository = userRepository; UserRepository = userRepository;
_xmlSerializer = xmlSerializer;
ConfigurationManager = configurationManager; ConfigurationManager = configurationManager;
Users = new List<User>(); Users = new List<User>();
} }
@ -65,7 +70,8 @@ namespace MediaBrowser.Server.Implementations.Library
/// Occurs when [user updated]. /// Occurs when [user updated].
/// </summary> /// </summary>
public event EventHandler<GenericEventArgs<User>> UserUpdated; public event EventHandler<GenericEventArgs<User>> UserUpdated;
public event EventHandler<GenericEventArgs<User>> UserConfigurationUpdated;
/// <summary> /// <summary>
/// Called when [user updated]. /// Called when [user updated].
/// </summary> /// </summary>
@ -408,6 +414,13 @@ namespace MediaBrowser.Server.Implementations.Library
}; };
} }
public void UpdateConfiguration(User user, UserConfiguration newConfiguration)
{
var xmlPath = user.ConfigurationFilePath;
Directory.CreateDirectory(Path.GetDirectoryName(xmlPath));
_xmlSerializer.SerializeToFile(newConfiguration, xmlPath);
EventHelper.FireEventIfNotNull(UserConfigurationUpdated, this, new GenericEventArgs<User> { Argument = user }, _logger);
}
} }
} }

View File

@ -186,5 +186,6 @@
"LabelUnknownLanaguage": "Unknown language", "LabelUnknownLanaguage": "Unknown language",
"HeaderCurrentSubtitles": "Current Subtitles", "HeaderCurrentSubtitles": "Current Subtitles",
"MessageDownloadQueued": "The download has been queued.", "MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?" "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control"
} }

View File

@ -832,5 +832,6 @@
"LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:", "LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:",
"LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.", "LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.",
"OptionDisplayAdultContent": "Display adult content", "OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Folder view" "OptionLibraryFolders": "Folder view",
"TitleRemoteControl": "Remote Control"
} }

View File

@ -462,7 +462,7 @@ namespace MediaBrowser.ServerApplication
FileOrganizationRepository = await GetFileOrganizationRepository().ConfigureAwait(false); FileOrganizationRepository = await GetFileOrganizationRepository().ConfigureAwait(false);
RegisterSingleInstance(FileOrganizationRepository); RegisterSingleInstance(FileOrganizationRepository);
UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository); UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer);
RegisterSingleInstance(UserManager); RegisterSingleInstance(UserManager);
LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager); LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager);

View File

@ -176,6 +176,9 @@
<Content Include="dashboard-ui\css\images\headersearch.png"> <Content Include="dashboard-ui\css\images\headersearch.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\css\images\icons\remote.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\images\items\folders\edit.png"> <Content Include="dashboard-ui\css\images\items\folders\edit.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -278,9 +281,6 @@
<Content Include="dashboard-ui\css\images\media\tvflyout.png"> <Content Include="dashboard-ui\css\images\media\tvflyout.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\css\images\remote.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\librarymenu.css"> <Content Include="dashboard-ui\css\librarymenu.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -479,9 +479,6 @@
<Content Include="dashboard-ui\css\images\rotten.png"> <Content Include="dashboard-ui\css\images\rotten.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\css\images\currentuserdefaultblack.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\images\currentuserdefaultwhite.png"> <Content Include="dashboard-ui\css\images\currentuserdefaultwhite.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>