add device upload options

pull/702/head
Luke Pulverenti 10 years ago
parent 2486cffa71
commit f3539686bd

@ -0,0 +1,107 @@
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Devices;
using ServiceStack;
using ServiceStack.Web;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Api.Devices
{
[Route("/Devices", "GET", Summary = "Gets all devices")]
public class GetDevices : IReturn<List<DeviceInfo>>
{
[ApiMember(Name = "SupportsContentUploading", Description = "SupportsContentUploading", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public bool? SupportsContentUploading { get; set; }
}
[Route("/Devices", "DELETE", Summary = "Deletes a device")]
public class DeleteDevice
{
[ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
public string Id { get; set; }
}
[Route("/Devices/CameraUploads", "GET", Summary = "Gets camera upload history for a device")]
public class GetCameraUploads : IReturn<ContentUploadHistory>
{
[ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string DeviceId { get; set; }
}
[Route("/Devices/CameraUploads", "POST", Summary = "Uploads content")]
public class PostCameraUpload : IRequiresRequestStream, IReturnVoid
{
[ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string DeviceId { get; set; }
[ApiMember(Name = "Album", Description = "Album", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string Album { get; set; }
[ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string Name { get; set; }
[ApiMember(Name = "FullPath", Description = "FullPath", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string FullPath { get; set; }
public Stream RequestStream { get; set; }
}
[Authenticated]
public class DeviceService : BaseApiService
{
private readonly IDeviceManager _deviceManager;
public DeviceService(IDeviceManager deviceManager)
{
_deviceManager = deviceManager;
}
public object Get(GetDevices request)
{
var devices = _deviceManager.GetDevices();
if (request.SupportsContentUploading.HasValue)
{
var val = request.SupportsContentUploading.Value;
devices = devices.Where(i => i.Capabilities.SupportsContentUploading == val);
}
return ToOptimizedResult(devices.ToList());
}
public object Get(GetCameraUploads request)
{
return ToOptimizedResult(_deviceManager.GetCameraUploadHistory(request.DeviceId));
}
public void Delete(DeleteDevice request)
{
var task = _deviceManager.DeleteDevice(request.Id);
Task.WaitAll(task);
}
public void Post(PostCameraUpload request)
{
var deviceId = request.DeviceId;
var album = Request.QueryString["Album"];
var fullPath = Request.QueryString["FullPath"];
var name = Request.QueryString["Name"];
var task = _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
{
MimeType = Request.ContentType,
Album = album,
Name = name,
FullPath = fullPath
});
Task.WaitAll(task);
}
}
}

@ -71,6 +71,7 @@
<Compile Include="BrandingService.cs" />
<Compile Include="ChannelService.cs" />
<Compile Include="ConnectService.cs" />
<Compile Include="Devices\DeviceService.cs" />
<Compile Include="Dlna\DlnaServerService.cs" />
<Compile Include="Dlna\DlnaService.cs" />
<Compile Include="Library\ChapterService.cs" />

@ -316,17 +316,22 @@ namespace MediaBrowser.Api.Playback.Progressive
CancellationToken = cancellationTokenSource.Token
};
var response = await HttpClient.GetResponse(options).ConfigureAwait(false);
responseHeaders["Accept-Ranges"] = "none";
if (!string.IsNullOrWhiteSpace(Request.QueryString["Range"]))
{
options.RequestHeaders["Range"] = Request.QueryString["Range"];
}
var length = response.Headers["Content-Length"];
var response = await HttpClient.GetResponse(options).ConfigureAwait(false);
if (!string.IsNullOrEmpty(length))
foreach (var name in new[] { "Content-Length", "Content-Range", "Accept-Ranges" })
{
responseHeaders["Content-Length"] = length;
var val = response.Headers[name];
if (!string.IsNullOrWhiteSpace(val))
{
responseHeaders[name] = val;
}
}
if (isHeadRequest)
{
using (response.Content)

@ -32,6 +32,7 @@ namespace MediaBrowser.Api.Playback.Progressive
[Route("/Videos/{Id}/stream.3gp", "GET")]
[Route("/Videos/{Id}/stream.wmv", "GET")]
[Route("/Videos/{Id}/stream.wtv", "GET")]
[Route("/Videos/{Id}/stream.mov", "GET")]
[Route("/Videos/{Id}/stream", "GET")]
[Route("/Videos/{Id}/stream.ts", "HEAD")]
[Route("/Videos/{Id}/stream.webm", "HEAD")]
@ -48,6 +49,7 @@ namespace MediaBrowser.Api.Playback.Progressive
[Route("/Videos/{Id}/stream.wmv", "HEAD")]
[Route("/Videos/{Id}/stream.wtv", "HEAD")]
[Route("/Videos/{Id}/stream.m2ts", "HEAD")]
[Route("/Videos/{Id}/stream.mov", "HEAD")]
[Route("/Videos/{Id}/stream", "HEAD")]
[Api(Description = "Gets a video stream")]
public class GetVideoStream : VideoStreamRequest

@ -235,6 +235,9 @@ namespace MediaBrowser.Api.Session
[ApiMember(Name = "SupportsMediaControl", Description = "Determines whether media can be played remotely.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
public bool SupportsMediaControl { get; set; }
[ApiMember(Name = "SupportsContentUploading", Description = "Determines whether camera upload is supported.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
public bool SupportsContentUploading { get; set; }
}
[Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")]
@ -494,7 +497,7 @@ namespace MediaBrowser.Api.Session
{
request.Id = GetSession().Id;
}
_sessionManager.ReportCapabilities(request.Id, new SessionCapabilities
_sessionManager.ReportCapabilities(request.Id, new ClientCapabilities
{
PlayableMediaTypes = request.PlayableMediaTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
@ -502,7 +505,9 @@ namespace MediaBrowser.Api.Session
SupportsMediaControl = request.SupportsMediaControl,
MessageCallbackUrl = request.MessageCallbackUrl
MessageCallbackUrl = request.MessageCallbackUrl,
SupportsContentUploading = request.SupportsContentUploading
});
}
}

@ -179,7 +179,6 @@ namespace MediaBrowser.Api
/// <param name="userManager">The user manager.</param>
/// <param name="dtoService">The dto service.</param>
/// <param name="sessionMananger">The session mananger.</param>
/// <exception cref="System.ArgumentNullException">xmlSerializer</exception>
public UserService(IUserManager userManager, IDtoService dtoService, ISessionManager sessionMananger, IServerConfigurationManager config, INetworkManager networkManager)
{
_userManager = userManager;

@ -315,5 +315,20 @@ namespace MediaBrowser.Common.Net
throw new ArgumentException("Argument not supported: " + path);
}
private static readonly Dictionary<string, string> MimeExtensions =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{"image/jpeg", "jpg"},
{"image/jpg", "jpg"},
{"image/png", "png"},
{"image/gif", "gif"},
{"image/webp", "webp"}
};
public static string ToExtension(string mimeType)
{
return "." + MimeExtensions[mimeType];
}
}
}

@ -0,0 +1,71 @@
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Session;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Devices
{
public interface IDeviceManager
{
/// <summary>
/// Registers the device.
/// </summary>
/// <param name="reportedId">The reported identifier.</param>
/// <param name="name">The name.</param>
/// <param name="usedByUserId">The used by user identifier.</param>
/// <returns>Task.</returns>
Task RegisterDevice(string reportedId, string name, string usedByUserId);
/// <summary>
/// Saves the capabilities.
/// </summary>
/// <param name="reportedId">The reported identifier.</param>
/// <param name="capabilities">The capabilities.</param>
/// <returns>Task.</returns>
Task SaveCapabilities(string reportedId, ClientCapabilities capabilities);
/// <summary>
/// Gets the capabilities.
/// </summary>
/// <param name="reportedId">The reported identifier.</param>
/// <returns>ClientCapabilities.</returns>
ClientCapabilities GetCapabilities(string reportedId);
/// <summary>
/// Gets the device information.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>DeviceInfo.</returns>
DeviceInfo GetDevice(string id);
/// <summary>
/// Gets the devices.
/// </summary>
/// <returns>IEnumerable&lt;DeviceInfo&gt;.</returns>
IEnumerable<DeviceInfo> GetDevices();
/// <summary>
/// Deletes the device.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>Task.</returns>
Task DeleteDevice(string id);
/// <summary>
/// Gets the upload history.
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <returns>ContentUploadHistory.</returns>
ContentUploadHistory GetCameraUploadHistory(string deviceId);
/// <summary>
/// Accepts the upload.
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <param name="stream">The stream.</param>
/// <param name="file">The file.</param>
/// <returns>Task.</returns>
Task AcceptCameraUpload(string deviceId, Stream stream, LocalFileInfo file);
}
}

@ -0,0 +1,66 @@
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Session;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Devices
{
public interface IDeviceRepository
{
/// <summary>
/// Registers the device.
/// </summary>
/// <param name="device">The device.</param>
/// <returns>Task.</returns>
Task SaveDevice(DeviceInfo device);
/// <summary>
/// Saves the capabilities.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="capabilities">The capabilities.</param>
/// <returns>Task.</returns>
Task SaveCapabilities(string id, ClientCapabilities capabilities);
/// <summary>
/// Gets the capabilities.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>ClientCapabilities.</returns>
ClientCapabilities GetCapabilities(string id);
/// <summary>
/// Gets the device information.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>DeviceInfo.</returns>
DeviceInfo GetDevice(string id);
/// <summary>
/// Gets the devices.
/// </summary>
/// <returns>IEnumerable&lt;DeviceInfo&gt;.</returns>
IEnumerable<DeviceInfo> GetDevices();
/// <summary>
/// Deletes the device.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>Task.</returns>
Task DeleteDevice(string id);
/// <summary>
/// Gets the upload history.
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <returns>ContentUploadHistory.</returns>
ContentUploadHistory GetCameraUploadHistory(string deviceId);
/// <summary>
/// Saves the camera upload history.
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <param name="file">The file.</param>
void AddCameraUpload(string deviceId, LocalFileInfo file);
}
}

@ -102,6 +102,8 @@
<Compile Include="Connect\ConnectUser.cs" />
<Compile Include="Connect\IConnectManager.cs" />
<Compile Include="Connect\UserLinkResult.cs" />
<Compile Include="Devices\IDeviceManager.cs" />
<Compile Include="Devices\IDeviceRepository.cs" />
<Compile Include="Dlna\ControlRequest.cs" />
<Compile Include="Dlna\ControlResponse.cs" />
<Compile Include="Dlna\DlnaIconResponse.cs" />

@ -232,7 +232,7 @@ namespace MediaBrowser.Controller.Session
/// </summary>
/// <param name="sessionId">The session identifier.</param>
/// <param name="capabilities">The capabilities.</param>
void ReportCapabilities(string sessionId, SessionCapabilities capabilities);
void ReportCapabilities(string sessionId, ClientCapabilities capabilities);
/// <summary>
/// Reports the transcoding information.

@ -1,4 +1,6 @@
using MediaBrowser.Controller.Entities;
using System.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Sync;
using System.Collections.Generic;

@ -79,7 +79,7 @@ namespace MediaBrowser.Dlna
new Windows81Profile(),
//new WindowsMediaCenterProfile(),
new WindowsPhoneProfile(),
new AndroidProfile(true, true),
new AndroidProfile(true, true, new[]{"baseline", "constrained baseline"}),
new DirectTvProfile(),
new DishHopperJoeyProfile(),
new DefaultProfile()

@ -117,21 +117,21 @@ namespace MediaBrowser.Dlna.PlayTo
var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ??
_dlnaManager.GetDefaultProfile();
_sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities
_sessionManager.ReportCapabilities(sessionInfo.Id, new ClientCapabilities
{
PlayableMediaTypes = profile.GetSupportedMediaTypes(),
SupportedCommands = new List<string>
{
GeneralCommandType.VolumeDown.ToString(),
GeneralCommandType.VolumeUp.ToString(),
GeneralCommandType.Mute.ToString(),
GeneralCommandType.Unmute.ToString(),
GeneralCommandType.ToggleMute.ToString(),
GeneralCommandType.SetVolume.ToString(),
GeneralCommandType.SetAudioStreamIndex.ToString(),
GeneralCommandType.SetSubtitleStreamIndex.ToString()
},
{
GeneralCommandType.VolumeDown.ToString(),
GeneralCommandType.VolumeUp.ToString(),
GeneralCommandType.Mute.ToString(),
GeneralCommandType.Unmute.ToString(),
GeneralCommandType.ToggleMute.ToString(),
GeneralCommandType.SetVolume.ToString(),
GeneralCommandType.SetAudioStreamIndex.ToString(),
GeneralCommandType.SetSubtitleStreamIndex.ToString()
},
SupportsMediaControl = true
});

@ -95,6 +95,9 @@
<Compile Include="..\MediaBrowser.Model\ApiClient\IConnectionManager.cs">
<Link>ApiClient\IConnectionManager.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\ApiClient\IDevice.cs">
<Link>ApiClient\IDevice.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\ApiClient\IServerEvents.cs">
<Link>ApiClient\IServerEvents.cs</Link>
</Compile>
@ -212,6 +215,18 @@
<Compile Include="..\MediaBrowser.Model\Connect\UserLinkType.cs">
<Link>Connect\UserLinkType.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Devices\ContentUploadHistory.cs">
<Link>Devices\ContentUploadHistory.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Devices\DeviceInfo.cs">
<Link>Devices\DeviceInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Devices\DevicesOptions.cs">
<Link>Devices\DevicesOptions.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Devices\LocalFileInfo.cs">
<Link>Devices\LocalFileInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\AudioOptions.cs">
<Link>Dlna\AudioOptions.cs</Link>
</Compile>
@ -932,9 +947,6 @@
<Compile Include="..\MediaBrowser.Model\Session\PlaystateRequest.cs">
<Link>Session\PlaystateRequest.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Session\SessionCapabilities.cs">
<Link>Session\SessionCapabilities.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Session\SessionInfoDto.cs">
<Link>Session\SessionInfoDto.cs</Link>
</Compile>

@ -184,6 +184,18 @@
<Compile Include="..\mediabrowser.model\connect\UserLinkType.cs">
<Link>Connect\UserLinkType.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Devices\ContentUploadHistory.cs">
<Link>Devices\ContentUploadHistory.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Devices\DeviceInfo.cs">
<Link>Devices\DeviceInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Devices\DevicesOptions.cs">
<Link>Devices\DevicesOptions.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Devices\LocalFileInfo.cs">
<Link>Devices\LocalFileInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\AudioOptions.cs">
<Link>Dlna\AudioOptions.cs</Link>
</Compile>
@ -898,9 +910,6 @@
<Compile Include="..\MediaBrowser.Model\Session\PlaystateRequest.cs">
<Link>Session\PlaystateRequest.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Session\SessionCapabilities.cs">
<Link>Session\SessionCapabilities.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Session\SessionInfoDto.cs">
<Link>Session\SessionInfoDto.cs</Link>
</Compile>

@ -1,5 +1,6 @@
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Events;
@ -793,17 +794,23 @@ namespace MediaBrowser.Model.ApiClient
/// <value>The type of the client.</value>
string ClientName { get; set; }
/// <summary>
/// Gets the device.
/// </summary>
/// <value>The device.</value>
IDevice Device { get; }
/// <summary>
/// Gets or sets the name of the device.
/// </summary>
/// <value>The name of the device.</value>
string DeviceName { get; set; }
string DeviceName { get; }
/// <summary>
/// Gets or sets the device id.
/// </summary>
/// <value>The device id.</value>
string DeviceId { get; set; }
string DeviceId { get; }
/// <summary>
/// Gets or sets the current user id.
@ -1319,5 +1326,29 @@ namespace MediaBrowser.Model.ApiClient
/// <returns>Task.</returns>
Task SendContextMessageAsync(string itemType, string itemId, string itemName, string context,
CancellationToken cancellationToken);
/// <summary>
/// Gets the content upload history.
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <returns>Task&lt;ContentUploadHistory&gt;.</returns>
Task<ContentUploadHistory> GetContentUploadHistory(string deviceId);
/// <summary>
/// Uploads the file.
/// </summary>
/// <param name="stream">The stream.</param>
/// <param name="file">The file.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task UploadFile(Stream stream,
LocalFileInfo file,
CancellationToken cancellationToken);
/// <summary>
/// Gets the devices options options.
/// </summary>
/// <returns>Task&lt;DevicesOptions&gt;.</returns>
Task<DevicesOptions> GetDevicesOptions();
}
}

@ -0,0 +1,44 @@
using MediaBrowser.Model.Devices;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Model.ApiClient
{
public interface IDevice
{
/// <summary>
/// Occurs when [resume from sleep].
/// </summary>
event EventHandler<EventArgs> ResumeFromSleep;
/// <summary>
/// Gets the name of the device.
/// </summary>
/// <value>The name of the device.</value>
string DeviceName { get; }
/// <summary>
/// Gets the device identifier.
/// </summary>
/// <value>The device identifier.</value>
string DeviceId { get; }
/// <summary>
/// Gets the local images.
/// </summary>
/// <returns>IEnumerable&lt;LocalFileInfo&gt;.</returns>
IEnumerable<LocalFileInfo> GetLocalPhotos();
/// <summary>
/// Gets the local videos.
/// </summary>
/// <returns>IEnumerable&lt;LocalFileInfo&gt;.</returns>
IEnumerable<LocalFileInfo> GetLocalVideos();
/// <summary>
/// Uploads the file.
/// </summary>
/// <param name="file">The file.</param>
/// <param name="apiClient">The API client.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task UploadFile(LocalFileInfo file, IApiClient apiClient, CancellationToken cancellationToken);
}
}

@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace MediaBrowser.Model.Devices
{
public class ContentUploadHistory
{
public string DeviceId { get; set; }
public List<LocalFileInfo> FilesUploaded { get; set; }
public ContentUploadHistory()
{
FilesUploaded = new List<LocalFileInfo>();
}
}
}

@ -0,0 +1,44 @@
using System;
using MediaBrowser.Model.Session;
namespace MediaBrowser.Model.Devices
{
public class DeviceInfo
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the identifier.
/// </summary>
/// <value>The identifier.</value>
public string Id { get; set; }
/// <summary>
/// Gets or sets the last name of the user.
/// </summary>
/// <value>The last name of the user.</value>
public string LastUserName { get; set; }
/// <summary>
/// Gets or sets the last user identifier.
/// </summary>
/// <value>The last user identifier.</value>
public string LastUserId { get; set; }
/// <summary>
/// Gets or sets the date last modified.
/// </summary>
/// <value>The date last modified.</value>
public DateTime DateLastModified { get; set; }
/// <summary>
/// Gets or sets the capabilities.
/// </summary>
/// <value>The capabilities.</value>
public ClientCapabilities Capabilities { get; set; }
public DeviceInfo()
{
Capabilities = new ClientCapabilities();
}
}
}

@ -0,0 +1,14 @@

namespace MediaBrowser.Model.Devices
{
public class DevicesOptions
{
public string[] EnabledCameraUploadDevices { get; set; }
public string CameraUploadPath { get; set; }
public DevicesOptions()
{
EnabledCameraUploadDevices = new string[] { };
}
}
}

@ -0,0 +1,11 @@

namespace MediaBrowser.Model.Devices
{
public class LocalFileInfo
{
public string Name { get; set; }
public string FullPath { get; set; }
public string Album { get; set; }
public string MimeType { get; set; }
}
}

@ -6,7 +6,9 @@ namespace MediaBrowser.Model.Dlna.Profiles
[XmlRoot("Profile")]
public class AndroidProfile : DefaultProfile
{
public AndroidProfile(bool supportsHls, bool supportsMpegDash)
public AndroidProfile(bool supportsHls,
bool supportsMpegDash,
string[] supportedH264Profiles)
{
Name = "Android";
@ -102,7 +104,7 @@ namespace MediaBrowser.Model.Dlna.Profiles
Conditions = new []
{
new ProfileCondition(ProfileConditionType.EqualsAny, ProfileConditionValue.VideoProfile, "baseline|constrained baseline"),
new ProfileCondition(ProfileConditionType.EqualsAny, ProfileConditionValue.VideoProfile, string.Join("|", supportedH264Profiles)),
new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.Width, "1920"),
new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.Height, "1080"),
new ProfileCondition(ProfileConditionType.LessThanEqual, ProfileConditionValue.VideoBitDepth, "8"),

@ -733,12 +733,6 @@ namespace MediaBrowser.Model.Dlna
private bool IsVideoDirectPlaySupported(DirectPlayProfile profile, MediaSourceInfo item, MediaStream videoStream, MediaStream audioStream)
{
// Only plain video files can be direct played
if (item.VideoType != VideoType.VideoFile)
{
return false;
}
if (profile.Container.Length > 0)
{
// Check container type

@ -76,7 +76,10 @@ namespace MediaBrowser.Model.Dlna
public bool IsDirectStream
{
get { return PlayMethod == PlayMethod.DirectStream; }
get {
return PlayMethod == PlayMethod.DirectStream ||
PlayMethod == PlayMethod.DirectPlay;
}
}
public string ToUrl(string baseUrl)
@ -91,13 +94,6 @@ namespace MediaBrowser.Model.Dlna
throw new ArgumentNullException(baseUrl);
}
if (IsDirectStream && MediaSource != null && MediaSource.Protocol == MediaProtocol.Http)
{
if (MediaSource.RequiredHttpHeaders.Count == 0)
{
}
}
string dlnaCommand = BuildDlnaParam(this);
string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container;

@ -67,6 +67,7 @@
<Compile Include="ApiClient\IApiClient.cs" />
<Compile Include="ApiClient\ApiClientExtensions.cs" />
<Compile Include="ApiClient\IConnectionManager.cs" />
<Compile Include="ApiClient\IDevice.cs" />
<Compile Include="ApiClient\IServerEvents.cs" />
<Compile Include="ApiClient\GeneralCommandEventArgs.cs" />
<Compile Include="ApiClient\ServerDiscoveryInfo.cs" />
@ -95,6 +96,9 @@
<Compile Include="Configuration\XbmcMetadataOptions.cs" />
<Compile Include="Configuration\SubtitlePlaybackMode.cs" />
<Compile Include="Connect\UserLinkType.cs" />
<Compile Include="Devices\LocalFileInfo.cs" />
<Compile Include="Devices\DeviceInfo.cs" />
<Compile Include="Devices\DevicesOptions.cs" />
<Compile Include="Dlna\EncodingContext.cs" />
<Compile Include="Dlna\Profiles\AndroidProfile.cs" />
<Compile Include="Dlna\Profiles\DefaultProfile.cs" />
@ -331,11 +335,11 @@
<Compile Include="Serialization\IJsonSerializer.cs" />
<Compile Include="Serialization\IXmlSerializer.cs" />
<Compile Include="Session\PlaystateRequest.cs" />
<Compile Include="Session\SessionCapabilities.cs" />
<Compile Include="Session\SessionInfoDto.cs" />
<Compile Include="Session\SessionUserInfo.cs" />
<Compile Include="Session\TranscodingInfo.cs" />
<Compile Include="Session\UserDataChangeInfo.cs" />
<Compile Include="Devices\ContentUploadHistory.cs" />
<Compile Include="Sync\SyncJob.cs" />
<Compile Include="Sync\SyncJobCreationResult.cs" />
<Compile Include="Sync\SyncJobItem.cs" />

@ -5,8 +5,15 @@ namespace MediaBrowser.Model.Session
public class ClientCapabilities
{
public List<string> PlayableMediaTypes { get; set; }
public List<string> SupportedCommands { get; set; }
public bool SupportsMediaControl { get; set; }
public string MessageCallbackUrl { get; set; }
public bool SupportsContentUploading { get; set; }
public ClientCapabilities()
{
PlayableMediaTypes = new List<string>();

@ -1,21 +0,0 @@
using System.Collections.Generic;
namespace MediaBrowser.Model.Session
{
public class SessionCapabilities
{
public List<string> PlayableMediaTypes { get; set; }
public List<string> SupportedCommands { get; set; }
public bool SupportsMediaControl { get; set; }
public string MessageCallbackUrl { get; set; }
public SessionCapabilities()
{
PlayableMediaTypes = new List<string>();
SupportedCommands = new List<string>();
}
}
}

@ -264,10 +264,6 @@ namespace MediaBrowser.Providers.Music
return node != null ? node.Value : null;
}
/// <summary>
/// The _last music brainz request
/// </summary>
private DateTime _lastRequestDate = DateTime.MinValue;
/// <summary>
/// The _music brainz resource pool
/// </summary>
@ -282,51 +278,35 @@ namespace MediaBrowser.Providers.Music
/// <returns>Task{XmlDocument}.</returns>
internal async Task<XmlDocument> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
{
await _musicBrainzResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
var diff = 1500 - (DateTime.Now - _lastRequestDate).TotalMilliseconds;
// MusicBrainz is extremely adamant about limiting to one request per second
// MusicBrainz is extremely adamant about limiting to one request per second
if (diff > 0)
{
_logger.Debug("Throttling musicbrainz by {0} ms", diff);
await Task.Delay(Convert.ToInt32(diff), cancellationToken).ConfigureAwait(false);
}
await Task.Delay(800, cancellationToken).ConfigureAwait(false);
var doc = new XmlDocument();
var doc = new XmlDocument();
var options = new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion
};
var options = new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion,
ResourcePool = _musicBrainzResourcePool
};
if (!isSearch)
{
options.CacheMode = CacheMode.Unconditional;
options.CacheLength = TimeSpan.FromDays(7);
}
if (!isSearch)
{
options.CacheMode = CacheMode.Unconditional;
options.CacheLength = TimeSpan.FromDays(7);
}
using (var xml = await _httpClient.Get(options).ConfigureAwait(false))
using (var xml = await _httpClient.Get(options).ConfigureAwait(false))
{
using (var oReader = new StreamReader(xml, Encoding.UTF8))
{
using (var oReader = new StreamReader(xml, Encoding.UTF8))
{
doc.Load(oReader);
}
doc.Load(oReader);
}
return doc;
}
finally
{
_lastRequestDate = DateTime.Now;
_musicBrainzResourcePool.Release();
}
return doc;
}
public int Order

@ -0,0 +1,68 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities;
using System.IO;
using System.Linq;
namespace MediaBrowser.Server.Implementations.Devices
{
public class CameraUploadsFolder : BasePluginFolder
{
public CameraUploadsFolder()
{
Name = "Camera Uploads";
DisplayMediaType = "CollectionFolder";
}
public override bool IsVisible(User user)
{
return GetChildren(user, true).Any() &&
base.IsVisible(user);
}
public override bool IsHidden
{
get
{
return true;
}
}
public override bool IsHiddenFromUser(User user)
{
return false;
}
public override string CollectionType
{
get { return Model.Entities.CollectionType.Photos; }
}
public override string GetClientTypeName()
{
return typeof(CollectionFolder).Name;
}
}
public class CameraUploadsDynamicFolder : IVirtualFolderCreator
{
private readonly IApplicationPaths _appPaths;
public CameraUploadsDynamicFolder(IApplicationPaths appPaths)
{
_appPaths = appPaths;
}
public BasePluginFolder GetFolder()
{
var path = Path.Combine(_appPaths.DataPath, "camerauploads");
Directory.CreateDirectory(path);
return new CameraUploadsFolder
{
Path = path
};
}
}
}

@ -0,0 +1,149 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Session;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Devices
{
public class DeviceManager : IDeviceManager
{
private readonly IDeviceRepository _repo;
private readonly IUserManager _userManager;
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _libraryMonitor;
private readonly IConfigurationManager _config;
public DeviceManager(IDeviceRepository repo, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IConfigurationManager config)
{
_repo = repo;
_userManager = userManager;
_fileSystem = fileSystem;
_libraryMonitor = libraryMonitor;
_config = config;
}
public Task RegisterDevice(string reportedId, string name, string usedByUserId)
{
var device = GetDevice(reportedId) ?? new DeviceInfo
{
Id = reportedId
};
device.Name = name;
if (!string.IsNullOrWhiteSpace(usedByUserId))
{
var user = _userManager.GetUserById(usedByUserId);
device.LastUserId = user.Id.ToString("N");
device.LastUserName = user.Name;
}
device.DateLastModified = DateTime.UtcNow;
return _repo.SaveDevice(device);
}
public Task SaveCapabilities(string reportedId, ClientCapabilities capabilities)
{
return _repo.SaveCapabilities(reportedId, capabilities);
}
public ClientCapabilities GetCapabilities(string reportedId)
{
return _repo.GetCapabilities(reportedId);
}
public DeviceInfo GetDevice(string id)
{
return _repo.GetDevice(id);
}
public IEnumerable<DeviceInfo> GetDevices()
{
return _repo.GetDevices().OrderByDescending(i => i.DateLastModified);
}
public Task DeleteDevice(string id)
{
return _repo.DeleteDevice(id);
}
public ContentUploadHistory GetCameraUploadHistory(string deviceId)
{
return _repo.GetCameraUploadHistory(deviceId);
}
public async Task AcceptCameraUpload(string deviceId, Stream stream, LocalFileInfo file)
{
var path = GetUploadPath(deviceId);
if (!string.IsNullOrWhiteSpace(file.Album))
{
path = Path.Combine(path, _fileSystem.GetValidFilename(file.Album));
}
Directory.CreateDirectory(path);
path = Path.Combine(path, file.Name);
_libraryMonitor.ReportFileSystemChangeBeginning(path);
try
{
using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
{
await stream.CopyToAsync(fs).ConfigureAwait(false);
}
_repo.AddCameraUpload(deviceId, file);
}
finally
{
_libraryMonitor.ReportFileSystemChangeComplete(path, true);
}
}
private string GetUploadPath(string deviceId)
{
var config = _config.GetUploadOptions();
if (!string.IsNullOrWhiteSpace(config.CameraUploadPath))
{
return config.CameraUploadPath;
}
return Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads");
}
}
public class DevicesConfigStore : IConfigurationFactory
{
public IEnumerable<ConfigurationStore> GetConfigurations()
{
return new List<ConfigurationStore>
{
new ConfigurationStore
{
Key = "devices",
ConfigurationType = typeof(DevicesOptions)
}
};
}
}
public static class UploadConfigExtension
{
public static DevicesOptions GetUploadOptions(this IConfigurationManager config)
{
return config.GetConfiguration<DevicesOptions>("devices");
}
}
}

@ -0,0 +1,176 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Devices
{
public class DeviceRepository : IDeviceRepository
{
private readonly object _syncLock = new object();
private readonly IApplicationPaths _appPaths;
private readonly IJsonSerializer _json;
private ConcurrentBag<DeviceInfo> _devices;
public DeviceRepository(IApplicationPaths appPaths, IJsonSerializer json)
{
_appPaths = appPaths;
_json = json;
}
private string GetDevicesPath()
{
return Path.Combine(_appPaths.DataPath, "devices");
}
private string GetDevicePath(string id)
{
return Path.Combine(GetDevicesPath(), id.GetMD5().ToString("N"));
}
public Task SaveDevice(DeviceInfo device)
{
var path = Path.Combine(GetDevicePath(device.Id), "device.json");
Directory.CreateDirectory(Path.GetDirectoryName(path));
lock (_syncLock)
{
_json.SerializeToFile(device, path);
_devices = null;
}
return Task.FromResult(true);
}
public Task SaveCapabilities(string reportedId, ClientCapabilities capabilities)
{
var device = GetDevice(reportedId);
device.Capabilities = capabilities;
SaveDevice(device);
return Task.FromResult(true);
}
public ClientCapabilities GetCapabilities(string reportedId)
{
var device = GetDevice(reportedId);
return device == null ? null : device.Capabilities;
}
public DeviceInfo GetDevice(string id)
{
return GetDevices().FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase));
}
public IEnumerable<DeviceInfo> GetDevices()
{
if (_devices == null)
{
lock (_syncLock)
{
if (_devices == null)
{
_devices = new ConcurrentBag<DeviceInfo>(LoadDevices());
}
}
}
return _devices.ToList();
}
private IEnumerable<DeviceInfo> LoadDevices()
{
var path = GetDevicesPath();
try
{
return new DirectoryInfo(path)
.EnumerateFiles("*", SearchOption.AllDirectories)
.Where(i => string.Equals(i.Name, "device.json", StringComparison.OrdinalIgnoreCase))
.Select(i => _json.DeserializeFromFile<DeviceInfo>(i.FullName))
.ToList();
}
catch (IOException)
{
return new List<DeviceInfo>();
}
}
public Task DeleteDevice(string id)
{
var path = GetDevicePath(id);
lock (_syncLock)
{
try
{
Directory.Delete(path, true);
}
catch (DirectoryNotFoundException)
{
}
_devices = null;
}
return Task.FromResult(true);
}
public ContentUploadHistory GetCameraUploadHistory(string deviceId)
{
var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
lock (_syncLock)
{
try
{
return _json.DeserializeFromFile<ContentUploadHistory>(path);
}
catch (IOException)
{
return new ContentUploadHistory
{
DeviceId = deviceId
};
}
}
}
public void AddCameraUpload(string deviceId, LocalFileInfo file)
{
var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
Directory.CreateDirectory(Path.GetDirectoryName(path));
lock (_syncLock)
{
ContentUploadHistory history;
try
{
history = _json.DeserializeFromFile<ContentUploadHistory>(path);
}
catch (IOException)
{
history = new ContentUploadHistory
{
DeviceId = deviceId
};
}
history.DeviceId = deviceId;
history.FilesUploaded.Add(file);
_json.SerializeToFile(history, path);
}
}
}
}

@ -60,41 +60,45 @@ namespace MediaBrowser.Server.Implementations.Library
var standaloneFolders = folders.Where(i => UserView.IsExcludedFromGrouping(i) || excludeFolderIds.Contains(i.Id)).ToList();
list.AddRange(standaloneFolders);
var recursiveChildren = folders
var foldersWithViewTypes = folders
.Except(standaloneFolders)
.SelectMany(i => i.GetRecursiveChildren(user, false))
.OfType<ICollectionFolder>()
.ToList();
if (recursiveChildren.OfType<Series>().Any())
list.AddRange(standaloneFolders);
if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) ||
foldersWithViewTypes.Any(i => string.IsNullOrWhiteSpace(i.CollectionType)))
{
list.Add(await GetUserView(CollectionType.TvShows, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
if (recursiveChildren.OfType<MusicAlbum>().Any() ||
recursiveChildren.OfType<MusicVideo>().Any())
if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase)) ||
foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)))
{
list.Add(await GetUserView(CollectionType.Music, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
if (recursiveChildren.OfType<Movie>().Any())
if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) ||
foldersWithViewTypes.Any(i => string.IsNullOrWhiteSpace(i.CollectionType)))
{
list.Add(await GetUserView(CollectionType.Movies, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
if (recursiveChildren.OfType<Game>().Any())
if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.Games, StringComparison.OrdinalIgnoreCase)))
{
list.Add(await GetUserView(CollectionType.Games, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
if (user.Configuration.DisplayCollectionsView &&
recursiveChildren.OfType<BoxSet>().Any())
folders
.Except(standaloneFolders)
.SelectMany(i => i.GetRecursiveChildren(user, false)).OfType<BoxSet>().Any())
{
list.Add(await GetUserView(CollectionType.BoxSets, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
if (recursiveChildren.OfType<Playlist>().Any())
if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase)))
{
list.Add(_playlists.GetPlaylistsFolder(user.Id.ToString("N")));
}

@ -602,5 +602,12 @@
"DashboardTourNotifications": "Automatically send notifications of server events to your mobile device, email and more.",
"DashboardTourScheduledTasks": "Easily manage long running operations with scheduled tasks. Decide when they run, and how often.",
"DashboardTourMobile": "The Media Browser dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.",
"MessageRefreshQueued": "Refresh queued"
"MessageRefreshQueued": "Refresh queued",
"TabDevices": "Devices",
"DeviceLastUsedByUserName": "Last used by {0}",
"HeaderDeleteDevice": "Delete Device",
"DeleteDeviceConfirmation": "Are you sure you with to delete this device? It will reappear the next time a user signs in with it.",
"LabelEnableCameraUploadFor": "Enable camera upload for:",
"HeaderSelectUploadPath": "Select Upload Path",
"LabelEnableCameraUploadForHelp": "Uploads will occur automatically in the background when signed into Media Browser."
}

@ -1215,5 +1215,13 @@
"OptionDateAddedImportTime": "Use date scanned into the library",
"OptionDateAddedFileTime": "Use file creation date",
"LabelDateAddedBehaviorHelp": "If a metadata value is present it will always be used before either of these options.",
"LabelNumberTrailerToPlay": "Number of trailers to play:"
"LabelNumberTrailerToPlay": "Number of trailers to play:",
"TitleDevices": "Devices",
"TabCameraUpload": "Camera Upload",
"TabDevices": "Devices",
"TitleDevices": "Devices",
"HeaderCameraUploadHelp": "Automatically upload photos and videos taken from your mobile devices into Media Browser.",
"MessageNoDevicesSupportCameraUpload": "You currently don't have any devices that support camera upload.",
"LabelUploadPath": "Upload path:",
"LabelUploadPathHelp": "Select a custom upload path, if desired. If unspecified an internal data folder will be used."
}

@ -119,6 +119,9 @@
<Compile Include="Connect\ConnectData.cs" />
<Compile Include="Connect\ConnectManager.cs" />
<Compile Include="Connect\Responses.cs" />
<Compile Include="Devices\DeviceManager.cs" />
<Compile Include="Devices\DeviceRepository.cs" />
<Compile Include="Devices\CameraUploadsFolder.cs" />
<Compile Include="Drawing\ImageHeader.cs" />
<Compile Include="Drawing\PercentPlayedDrawer.cs" />
<Compile Include="Drawing\PlayedIndicatorDrawer.cs" />

@ -3,6 +3,7 @@ using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
@ -64,6 +65,7 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly IServerApplicationHost _appHost;
private readonly IAuthenticationRepository _authRepo;
private readonly IDeviceManager _deviceManager;
/// <summary>
/// Gets or sets the configuration manager.
@ -80,7 +82,7 @@ namespace MediaBrowser.Server.Implementations.Session
public event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationFailed;
public event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationSucceeded;
/// <summary>
/// Occurs when [playback start].
/// </summary>
@ -111,7 +113,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// <param name="logger">The logger.</param>
/// <param name="userRepository">The user repository.</param>
/// <param name="libraryManager">The library manager.</param>
public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo)
public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo, IDeviceManager deviceManager)
{
_userDataRepository = userDataRepository;
_configurationManager = configurationManager;
@ -127,6 +129,7 @@ namespace MediaBrowser.Server.Implementations.Session
_appHost = appHost;
_httpClient = httpClient;
_authRepo = authRepo;
_deviceManager = deviceManager;
}
/// <summary>
@ -394,7 +397,9 @@ namespace MediaBrowser.Server.Implementations.Session
try
{
var connection = _activeConnections.GetOrAdd(key, keyName =>
SessionInfo connection;
if (!_activeConnections.TryGetValue(key, out connection))
{
var sessionInfo = new SessionInfo
{
@ -411,8 +416,15 @@ namespace MediaBrowser.Server.Implementations.Session
OnSessionStarted(sessionInfo);
return sessionInfo;
});
_activeConnections.TryAdd(key, sessionInfo);
connection = sessionInfo;
if (!string.IsNullOrEmpty(deviceId))
{
var userIdString = userId.HasValue ? userId.Value.ToString("N") : null;
await _deviceManager.RegisterDevice(deviceId, deviceName, userIdString).ConfigureAwait(false);
}
}
connection.DeviceName = deviceName;
connection.UserId = userId;
@ -1226,7 +1238,7 @@ namespace MediaBrowser.Server.Implementations.Session
var token = await GetAuthorizationToken(user.Id.ToString("N"), request.DeviceId, request.App, request.DeviceName).ConfigureAwait(false);
EventHelper.FireEventIfNotNull(AuthenticationSucceeded, this, new GenericEventArgs<AuthenticationRequest>(request), _logger);
var session = await LogSessionActivity(request.App,
request.AppVersion,
request.DeviceId,
@ -1234,7 +1246,7 @@ namespace MediaBrowser.Server.Implementations.Session
request.RemoteEndPoint,
user)
.ConfigureAwait(false);
return new AuthenticationResult
{
User = _userManager.GetUserDto(user, request.RemoteEndPoint),
@ -1339,7 +1351,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// </summary>
/// <param name="sessionId">The session identifier.</param>
/// <param name="capabilities">The capabilities.</param>
public void ReportCapabilities(string sessionId, SessionCapabilities capabilities)
public void ReportCapabilities(string sessionId, ClientCapabilities capabilities)
{
var session = GetSession(sessionId);
@ -1347,7 +1359,7 @@ namespace MediaBrowser.Server.Implementations.Session
}
private async void ReportCapabilities(SessionInfo session,
SessionCapabilities capabilities,
ClientCapabilities capabilities,
bool saveCapabilities)
{
session.PlayableMediaTypes = capabilities.PlayableMediaTypes;
@ -1375,56 +1387,14 @@ namespace MediaBrowser.Server.Implementations.Session
}
}
private string GetCapabilitiesFilePath(string deviceId)
private ClientCapabilities GetSavedCapabilities(string deviceId)
{
var filename = deviceId.GetMD5().ToString("N") + ".json";
return Path.Combine(_configurationManager.ApplicationPaths.CachePath, "devices", filename);
}
private SessionCapabilities GetSavedCapabilities(string deviceId)
{
var path = GetCapabilitiesFilePath(deviceId);
try
{
return _jsonSerializer.DeserializeFromFile<SessionCapabilities>(path);
}
catch (DirectoryNotFoundException)
{
return null;
}
catch (FileNotFoundException)
{
return null;
}
catch (Exception ex)
{
_logger.ErrorException("Error getting saved capabilities", ex);
return null;
}
return _deviceManager.GetCapabilities(deviceId);
}
private readonly SemaphoreSlim _capabilitiesLock = new SemaphoreSlim(1, 1);
private async Task SaveCapabilities(string deviceId, SessionCapabilities capabilities)
private Task SaveCapabilities(string deviceId, ClientCapabilities capabilities)
{
var path = GetCapabilitiesFilePath(deviceId);
Directory.CreateDirectory(Path.GetDirectoryName(path));
await _capabilitiesLock.WaitAsync().ConfigureAwait(false);
try
{
_jsonSerializer.SerializeToFile(capabilities, path);
}
catch (Exception ex)
{
_logger.ErrorException("Error saving to {0}", ex, path);
}
finally
{
_capabilitiesLock.Release();
}
return _deviceManager.SaveCapabilities(deviceId, capabilities);
}
public SessionInfoDto GetSessionInfoDto(SessionInfo session)

@ -75,7 +75,7 @@ namespace MediaBrowser.Server.Implementations.Session
}
else
{
var capabilities = new SessionCapabilities
var capabilities = new ClientCapabilities
{
PlayableMediaTypes = Session.PlayableMediaTypes,
SupportedCommands = Session.SupportedCommands,

@ -1,9 +1,11 @@
using MediaBrowser.Common.Extensions;
using System.IO;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sync;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
@ -10,4 +10,12 @@
<add key="DebugProgramDataPath" value="ProgramData-Server" />
<add key="ReleaseProgramDataPath" value="ProgramData-Server" />
</appSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.91.0" newVersion="1.0.91.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -14,6 +14,7 @@ using MediaBrowser.Controller.Chapters;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Connect;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
@ -59,6 +60,7 @@ using MediaBrowser.Server.Implementations.Channels;
using MediaBrowser.Server.Implementations.Collections;
using MediaBrowser.Server.Implementations.Configuration;
using MediaBrowser.Server.Implementations.Connect;
using MediaBrowser.Server.Implementations.Devices;
using MediaBrowser.Server.Implementations.Drawing;
using MediaBrowser.Server.Implementations.Dto;
using MediaBrowser.Server.Implementations.EntryPoints;
@ -212,6 +214,7 @@ namespace MediaBrowser.ServerApplication
private INotificationManager NotificationManager { get; set; }
private ISubtitleManager SubtitleManager { get; set; }
private IChapterManager ChapterManager { get; set; }
private IDeviceManager DeviceManager { get; set; }
internal IUserViewManager UserViewManager { get; set; }
@ -316,8 +319,6 @@ namespace MediaBrowser.ServerApplication
PerformVersionMigration();
await base.Init(progress).ConfigureAwait(false);
MigrateModularConfigurations();
}
private void PerformVersionMigration()
@ -325,16 +326,6 @@ namespace MediaBrowser.ServerApplication
DeleteDeprecatedModules();
}
private void MigrateModularConfigurations()
{
var saveConfig = false;
if (saveConfig)
{
ServerConfigurationManager.SaveConfiguration();
}
}
private void DeleteDeprecatedModules()
{
try
@ -469,7 +460,10 @@ namespace MediaBrowser.ServerApplication
ConnectManager = new ConnectManager(LogManager.GetLogger("Connect"), ApplicationPaths, JsonSerializer, encryptionManager, HttpClient, this, ServerConfigurationManager, UserManager);
RegisterSingleInstance(ConnectManager);
SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient, AuthenticationRepository);
DeviceManager = new DeviceManager(new DeviceRepository(ApplicationPaths, JsonSerializer), UserManager, FileSystemManager, LibraryMonitor, ConfigurationManager);
RegisterSingleInstance(DeviceManager);
SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager);
RegisterSingleInstance(SessionManager);
var newsService = new Server.Implementations.News.NewsService(ApplicationPaths, JsonSerializer);

@ -564,6 +564,8 @@ namespace MediaBrowser.WebDashboard.Api
"dashboardgeneral.js",
"dashboardpage.js",
"dashboardsync.js",
"devices.js",
"devicesupload.js",
"directorybrowser.js",
"dlnaprofile.js",
"dlnaprofiles.js",

@ -58,8 +58,7 @@
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="WebMarkupMin.Core">
<HintPath>..\packages\WebMarkupMin.Core.0.9.6\lib\net40\WebMarkupMin.Core.dll</HintPath>
<Private>True</Private>
<HintPath>..\packages\WebMarkupMin.Core.0.9.7\lib\net40\WebMarkupMin.Core.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@ -368,6 +367,12 @@
<Content Include="dashboard-ui\dashboardsync.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\devices.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\devicesupload.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\dlnaprofile.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -692,6 +697,12 @@
<Content Include="dashboard-ui\scripts\dashboardsync.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\devices.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\devicesupload.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\dlnaprofile.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

@ -9,6 +9,7 @@
<webMarkupMin xmlns="http://tempuri.org/WebMarkupMin.Configuration.xsd">
<core>
<css>

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.249" targetFramework="net45" />
<package id="WebMarkupMin.Core" version="0.9.6" targetFramework="net45" />
<package id="WebMarkupMin.Core" version="0.9.7" targetFramework="net45" />
</packages>

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
<version>3.0.467</version>
<version>3.0.476</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.467" />
<dependency id="MediaBrowser.Common" version="3.0.476" />
<dependency id="NLog" version="3.1.0.0" />
<dependency id="SimpleInjector" version="2.5.2" />
<dependency id="sharpcompress" version="0.10.2" />

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

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Model.Signed</id>
<version>3.0.467</version>
<version>3.0.476</version>
<title>MediaBrowser.Model - Signed Edition</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>

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

@ -3,5 +3,6 @@
#if (DEBUG)
[assembly: AssemblyVersion("3.0.*")]
#else
[assembly: AssemblyVersion("3.0.5395.0")]
[assembly: AssemblyVersion("3.0.*")]
//[assembly: AssemblyVersion("3.0.5395.0")]
#endif

Loading…
Cancel
Save