Merge pull request #3055 from MediaBrowser/beta

Beta
pull/1154/head
Luke 7 years ago committed by GitHub
commit c32d865638

@ -24,6 +24,7 @@ using MediaBrowser.Model.System;
using MediaBrowser.Model.Threading; using MediaBrowser.Model.Threading;
using Rssdp; using Rssdp;
using Rssdp.Infrastructure; using Rssdp.Infrastructure;
using System.Threading;
namespace Emby.Dlna.Main namespace Emby.Dlna.Main
{ {
@ -252,7 +253,7 @@ namespace Emby.Dlna.Main
var cacheLength = _config.GetDlnaConfiguration().BlastAliveMessageIntervalSeconds; var cacheLength = _config.GetDlnaConfiguration().BlastAliveMessageIntervalSeconds;
_Publisher.SupportPnpRootDevice = false; _Publisher.SupportPnpRootDevice = false;
var addresses = (await _appHost.GetLocalIpAddresses().ConfigureAwait(false)).ToList(); var addresses = (await _appHost.GetLocalIpAddresses(CancellationToken.None).ConfigureAwait(false)).ToList();
var udn = CreateUuid(_appHost.SystemId); var udn = CreateUuid(_appHost.SystemId);

@ -831,7 +831,7 @@ namespace Emby.Dlna.PlayTo
#region From XML #region From XML
private async Task GetAVProtocolAsync() private async Task GetAVProtocolAsync(CancellationToken cancellationToken)
{ {
if (_disposed) if (_disposed)
{ {
@ -845,12 +845,12 @@ namespace Emby.Dlna.PlayTo
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl); string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
var httpClient = new SsdpHttpClient(_httpClient, _config); var httpClient = new SsdpHttpClient(_httpClient, _config);
var document = await httpClient.GetDataAsync(url).ConfigureAwait(false); var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
AvCommands = TransportCommands.Create(document); AvCommands = TransportCommands.Create(document);
} }
private async Task GetRenderingProtocolAsync() private async Task GetRenderingProtocolAsync(CancellationToken cancellationToken)
{ {
if (_disposed) if (_disposed)
{ {
@ -864,7 +864,7 @@ namespace Emby.Dlna.PlayTo
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl); string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
var httpClient = new SsdpHttpClient(_httpClient, _config); var httpClient = new SsdpHttpClient(_httpClient, _config);
var document = await httpClient.GetDataAsync(url).ConfigureAwait(false); var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
RendererCommands = TransportCommands.Create(document); RendererCommands = TransportCommands.Create(document);
} }
@ -897,11 +897,11 @@ namespace Emby.Dlna.PlayTo
set; set;
} }
public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, IServerConfigurationManager config, ILogger logger, ITimerFactory timerFactory) public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, IServerConfigurationManager config, ILogger logger, ITimerFactory timerFactory, CancellationToken cancellationToken)
{ {
var ssdpHttpClient = new SsdpHttpClient(httpClient, config); var ssdpHttpClient = new SsdpHttpClient(httpClient, config);
var document = await ssdpHttpClient.GetDataAsync(url.ToString()).ConfigureAwait(false); var document = await ssdpHttpClient.GetDataAsync(url.ToString(), cancellationToken).ConfigureAwait(false);
var deviceProperties = new DeviceInfo(); var deviceProperties = new DeviceInfo();
@ -987,8 +987,8 @@ namespace Emby.Dlna.PlayTo
if (device.GetAvTransportService() != null) if (device.GetAvTransportService() != null)
{ {
await device.GetRenderingProtocolAsync().ConfigureAwait(false); await device.GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
await device.GetAVProtocolAsync().ConfigureAwait(false); await device.GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
} }
return device; return device;

@ -321,6 +321,12 @@ namespace Emby.Dlna.PlayTo
AddItemFromId(Guid.Parse(id), items); AddItemFromId(Guid.Parse(id), items);
} }
var startIndex = command.StartIndex ?? 0;
if (startIndex > 0)
{
items = items.Skip(startIndex).ToList();
}
var playlist = new List<PlaylistItem>(); var playlist = new List<PlaylistItem>();
var isFirst = true; var isFirst = true;
@ -424,7 +430,7 @@ namespace Emby.Dlna.PlayTo
return Task.FromResult(true); return Task.FromResult(true);
} }
public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken) public Task SendRestartRequiredNotification(CancellationToken cancellationToken)
{ {
return Task.FromResult(true); return Task.FromResult(true);
} }

@ -18,6 +18,7 @@ using MediaBrowser.Model.Events;
using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using MediaBrowser.Model.Threading; using MediaBrowser.Model.Threading;
using System.Threading;
namespace Emby.Dlna.PlayTo namespace Emby.Dlna.PlayTo
{ {
@ -44,6 +45,8 @@ namespace Emby.Dlna.PlayTo
private readonly List<string> _nonRendererUrls = new List<string>(); private readonly List<string> _nonRendererUrls = new List<string>();
private DateTime _lastRendererClear; private DateTime _lastRendererClear;
private bool _disposed; private bool _disposed;
private SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1);
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, ITimerFactory timerFactory) public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, ITimerFactory timerFactory)
{ {
@ -90,6 +93,7 @@ namespace Emby.Dlna.PlayTo
if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1 && if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1 &&
nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1) nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1)
{ {
//_logger.Debug("Upnp device {0} does not contain a MediaRenderer device (0).", location);
return; return;
} }
@ -98,92 +102,105 @@ namespace Emby.Dlna.PlayTo
return; return;
} }
var cancellationToken = _disposeCancellationTokenSource.Token;
await _sessionLock.WaitAsync(cancellationToken).ConfigureAwait(false);
try try
{ {
lock (_nonRendererUrls) if (_disposed)
{ {
if ((DateTime.UtcNow - _lastRendererClear).TotalMinutes >= 10) return;
{
_nonRendererUrls.Clear();
_lastRendererClear = DateTime.UtcNow;
}
if (_nonRendererUrls.Contains(location, StringComparer.OrdinalIgnoreCase))
{
return;
}
} }
var uri = info.Location; await AddDevice(info, location, cancellationToken).ConfigureAwait(false);
_logger.Debug("Attempting to create PlayToController from location {0}", location); }
var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, _timerFactory).ConfigureAwait(false); catch (OperationCanceledException)
{
}
catch (Exception ex)
{
_logger.ErrorException("Error creating PlayTo device.", ex);
_nonRendererUrls.Add(location);
}
finally
{
_sessionLock.Release();
}
}
private async Task AddDevice(UpnpDeviceInfo info, string location, CancellationToken cancellationToken)
{
if ((DateTime.UtcNow - _lastRendererClear).TotalMinutes >= 10)
{
_nonRendererUrls.Clear();
_lastRendererClear = DateTime.UtcNow;
}
if (_nonRendererUrls.Contains(location, StringComparer.OrdinalIgnoreCase))
{
return;
}
var uri = info.Location;
_logger.Debug("Attempting to create PlayToController from location {0}", location);
var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, _timerFactory, cancellationToken).ConfigureAwait(false);
if (device.RendererCommands == null)
{
//_logger.Debug("Upnp device {0} does not contain a MediaRenderer device (1).", location);
_nonRendererUrls.Add(location);
return;
}
_logger.Debug("Logging session activity from location {0}", location);
var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null).ConfigureAwait(false);
var controller = sessionInfo.SessionController as PlayToController;
if (device.RendererCommands == null) if (controller == null)
{
string serverAddress;
if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IpAddressInfo.Any) || info.LocalIpAddress.Equals(IpAddressInfo.IPv6Loopback))
{ {
lock (_nonRendererUrls) serverAddress = await GetServerAddress(null, cancellationToken).ConfigureAwait(false);
{
_nonRendererUrls.Add(location);
return;
}
} }
else
if (_disposed)
{ {
return; serverAddress = await GetServerAddress(info.LocalIpAddress, cancellationToken).ConfigureAwait(false);
} }
_logger.Debug("Logging session activity from location {0}", location); string accessToken = null;
var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null)
.ConfigureAwait(false); sessionInfo.SessionController = controller = new PlayToController(sessionInfo,
_sessionManager,
var controller = sessionInfo.SessionController as PlayToController; _libraryManager,
_logger,
if (controller == null) _dlnaManager,
_userManager,
_imageProcessor,
serverAddress,
accessToken,
_deviceDiscovery,
_userDataManager,
_localization,
_mediaSourceManager,
_config,
_mediaEncoder);
controller.Init(device);
var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ??
_dlnaManager.GetDefaultProfile();
_sessionManager.ReportCapabilities(sessionInfo.Id, new ClientCapabilities
{ {
if (_disposed) PlayableMediaTypes = profile.GetSupportedMediaTypes(),
{
return;
}
string serverAddress; SupportedCommands = new string[]
if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IpAddressInfo.Any) || info.LocalIpAddress.Equals(IpAddressInfo.IPv6Loopback))
{ {
serverAddress = await GetServerAddress(null).ConfigureAwait(false);
}
else
{
serverAddress = await GetServerAddress(info.LocalIpAddress).ConfigureAwait(false);
}
string accessToken = null;
sessionInfo.SessionController = controller = new PlayToController(sessionInfo,
_sessionManager,
_libraryManager,
_logger,
_dlnaManager,
_userManager,
_imageProcessor,
serverAddress,
accessToken,
_deviceDiscovery,
_userDataManager,
_localization,
_mediaSourceManager,
_config,
_mediaEncoder);
controller.Init(device);
var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ??
_dlnaManager.GetDefaultProfile();
_sessionManager.ReportCapabilities(sessionInfo.Id, new ClientCapabilities
{
PlayableMediaTypes = profile.GetSupportedMediaTypes(),
SupportedCommands = new string[]
{
GeneralCommandType.VolumeDown.ToString(), GeneralCommandType.VolumeDown.ToString(),
GeneralCommandType.VolumeUp.ToString(), GeneralCommandType.VolumeUp.ToString(),
GeneralCommandType.Mute.ToString(), GeneralCommandType.Mute.ToString(),
@ -192,33 +209,23 @@ namespace Emby.Dlna.PlayTo
GeneralCommandType.SetVolume.ToString(), GeneralCommandType.SetVolume.ToString(),
GeneralCommandType.SetAudioStreamIndex.ToString(), GeneralCommandType.SetAudioStreamIndex.ToString(),
GeneralCommandType.SetSubtitleStreamIndex.ToString() GeneralCommandType.SetSubtitleStreamIndex.ToString()
}, },
SupportsMediaControl = true, SupportsMediaControl = true,
// xbox one creates a new uuid everytime it restarts // xbox one creates a new uuid everytime it restarts
SupportsPersistentIdentifier = (device.Properties.ModelName ?? string.Empty).IndexOf("xbox", StringComparison.OrdinalIgnoreCase) == -1 SupportsPersistentIdentifier = (device.Properties.ModelName ?? string.Empty).IndexOf("xbox", StringComparison.OrdinalIgnoreCase) == -1
}); });
_logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName); _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
}
}
catch (Exception ex)
{
_logger.ErrorException("Error creating PlayTo device.", ex);
lock (_nonRendererUrls)
{
_nonRendererUrls.Add(location);
}
} }
} }
private Task<string> GetServerAddress(IpAddressInfo address) private Task<string> GetServerAddress(IpAddressInfo address, CancellationToken cancellationToken)
{ {
if (address == null) if (address == null)
{ {
return _appHost.GetLocalApiUrl(); return _appHost.GetLocalApiUrl(cancellationToken);
} }
return Task.FromResult(_appHost.GetLocalApiUrl(address)); return Task.FromResult(_appHost.GetLocalApiUrl(address));
@ -226,6 +233,15 @@ namespace Emby.Dlna.PlayTo
public void Dispose() public void Dispose()
{ {
try
{
_disposeCancellationTokenSource.Cancel();
}
catch
{
}
_disposed = true; _disposed = true;
_deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered; _deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered;
GC.SuppressFinalize(this); GC.SuppressFinalize(this);

@ -7,6 +7,7 @@ using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml.Linq; using System.Xml.Linq;
using System.Threading;
namespace Emby.Dlna.PlayTo namespace Emby.Dlna.PlayTo
{ {
@ -89,7 +90,7 @@ namespace Emby.Dlna.PlayTo
} }
} }
public async Task<XDocument> GetDataAsync(string url) public async Task<XDocument> GetDataAsync(string url, CancellationToken cancellationToken)
{ {
var options = new HttpRequestOptions var options = new HttpRequestOptions
{ {
@ -99,7 +100,9 @@ namespace Emby.Dlna.PlayTo
BufferContent = false, BufferContent = false,
// The periodic requests may keep some devices awake // The periodic requests may keep some devices awake
LogRequestAsDebug = true LogRequestAsDebug = true,
CancellationToken = cancellationToken
}; };
options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName; options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;

@ -208,7 +208,7 @@ namespace Emby.Dlna.Profiles
{ {
new ResponseProfile new ResponseProfile
{ {
Container = "mkv,ts", Container = "mkv,ts,mpegts",
Type = DlnaProfileType.Video, Type = DlnaProfileType.Video,
MimeType = "video/mp4" MimeType = "video/mp4"
} }

@ -26,7 +26,7 @@ namespace Emby.Dlna.Profiles
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "avi,mp4,mkv,ts,m4v", Container = "avi,mp4,mkv,ts,mpegts,m4v",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
} }
}; };

@ -72,7 +72,7 @@ namespace Emby.Dlna.Profiles
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "h264,mpeg2video", VideoCodec = "h264,mpeg2video",
AudioCodec = "aac,mp3,mp2", AudioCodec = "aac,mp3,mp2",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
@ -205,7 +205,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Type = DlnaProfileType.Video, Type = DlnaProfileType.Video,
Container = "ts", Container = "ts,mpegts",
OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO", OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
MimeType = "video/vnd.dlna.mpeg-tts" MimeType = "video/vnd.dlna.mpeg-tts"
}, },

@ -46,7 +46,7 @@ namespace Emby.Dlna.Profiles
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
Type = DlnaProfileType.Video, Type = DlnaProfileType.Video,
VideoCodec = "h264", VideoCodec = "h264",
AudioCodec = "aac,ac3,eac3,mp3,mp2,pcm" AudioCodec = "aac,ac3,eac3,mp3,mp2,pcm"

@ -12,6 +12,9 @@ namespace Emby.Dlna.Profiles
EnableAlbumArtInDidl = true; EnableAlbumArtInDidl = true;
// Without this, older samsungs fail to browse
EnableSingleAlbumArtLimit = true;
Identification = new DeviceIdentification Identification = new DeviceIdentification
{ {
ModelUrl = "samsung.com", ModelUrl = "samsung.com",
@ -39,7 +42,7 @@ namespace Emby.Dlna.Profiles
}, },
new TranscodingProfile new TranscodingProfile
{ {
Container = "ts", Container = "ts,mpegts",
AudioCodec = "ac3", AudioCodec = "ac3",
VideoCodec = "h264", VideoCodec = "h264",
Type = DlnaProfileType.Video, Type = DlnaProfileType.Video,
@ -300,7 +303,7 @@ namespace Emby.Dlna.Profiles
new CodecProfile new CodecProfile
{ {
Type = CodecType.VideoAudio, Type = CodecType.VideoAudio,
Codec = "ac3,wmav2,dca,aac,mp3,dts", Codec = "wmav2,dca,aac,mp3,dts",
Conditions = new[] Conditions = new[]
{ {

@ -69,7 +69,7 @@ namespace Emby.Dlna.Profiles
{ {
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "mpeg1video,mpeg2video,h264", VideoCodec = "mpeg1video,mpeg2video,h264",
AudioCodec = "ac3,aac,mp3,pcm", AudioCodec = "ac3,aac,mp3,pcm",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
@ -212,7 +212,7 @@ namespace Emby.Dlna.Profiles
{ {
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "h264,mpeg4,vc1", VideoCodec = "h264,mpeg4,vc1",
AudioCodec = "ac3,aac,mp3", AudioCodec = "ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
@ -236,7 +236,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
}, },

@ -69,14 +69,14 @@ namespace Emby.Dlna.Profiles
{ {
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "h264", VideoCodec = "h264",
AudioCodec = "ac3,aac,mp3", AudioCodec = "ac3,aac,mp3",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
}, },
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "mpeg1video,mpeg2video", VideoCodec = "mpeg1video,mpeg2video",
AudioCodec = "mp3,mp2", AudioCodec = "mp3,mp2",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
@ -100,7 +100,7 @@ namespace Emby.Dlna.Profiles
{ {
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
@ -126,7 +126,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/mpeg", MimeType = "video/mpeg",
@ -146,7 +146,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
@ -156,7 +156,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="mpeg2video", VideoCodec="mpeg2video",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO", OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",

@ -66,14 +66,14 @@ namespace Emby.Dlna.Profiles
{ {
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "h264", VideoCodec = "h264",
AudioCodec = "ac3,aac,mp3", AudioCodec = "ac3,aac,mp3",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
}, },
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "mpeg2video", VideoCodec = "mpeg2video",
AudioCodec = "mp3", AudioCodec = "mp3",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
@ -141,7 +141,7 @@ namespace Emby.Dlna.Profiles
{ {
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
@ -167,7 +167,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/mpeg", MimeType = "video/mpeg",
@ -187,7 +187,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
@ -197,7 +197,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="mpeg2video", VideoCodec="mpeg2video",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO", OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",

@ -66,14 +66,14 @@ namespace Emby.Dlna.Profiles
{ {
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "h264", VideoCodec = "h264",
AudioCodec = "ac3,aac,mp3", AudioCodec = "ac3,aac,mp3",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
}, },
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "mpeg2video", VideoCodec = "mpeg2video",
AudioCodec = "mp3,mp2", AudioCodec = "mp3,mp2",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
@ -129,7 +129,7 @@ namespace Emby.Dlna.Profiles
{ {
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
@ -155,7 +155,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/mpeg", MimeType = "video/mpeg",
@ -175,7 +175,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
@ -185,7 +185,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="mpeg2video", VideoCodec="mpeg2video",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO", OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",

@ -65,14 +65,14 @@ namespace Emby.Dlna.Profiles
{ {
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "h264", VideoCodec = "h264",
AudioCodec = "ac3,eac3,aac,mp3", AudioCodec = "ac3,eac3,aac,mp3",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
}, },
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "mpeg2video", VideoCodec = "mpeg2video",
AudioCodec = "mp3,mp2", AudioCodec = "mp3,mp2",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
@ -185,7 +185,7 @@ namespace Emby.Dlna.Profiles
{ {
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
@ -211,7 +211,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/mpeg", MimeType = "video/mpeg",
@ -231,7 +231,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
@ -241,7 +241,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="mpeg2video", VideoCodec="mpeg2video",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO", OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",

@ -65,14 +65,14 @@ namespace Emby.Dlna.Profiles
{ {
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "h264", VideoCodec = "h264",
AudioCodec = "ac3,eac3,aac,mp3", AudioCodec = "ac3,eac3,aac,mp3",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
}, },
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "mpeg2video", VideoCodec = "mpeg2video",
AudioCodec = "mp3,mp2", AudioCodec = "mp3,mp2",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
@ -185,7 +185,7 @@ namespace Emby.Dlna.Profiles
{ {
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
@ -211,7 +211,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/mpeg", MimeType = "video/mpeg",
@ -231,7 +231,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="h264", VideoCodec="h264",
AudioCodec="ac3,aac,mp3", AudioCodec="ac3,aac,mp3",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
@ -241,7 +241,7 @@ namespace Emby.Dlna.Profiles
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec="mpeg2video", VideoCodec="mpeg2video",
MimeType = "video/vnd.dlna.mpeg-tts", MimeType = "video/vnd.dlna.mpeg-tts",
OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO", OrgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",

@ -49,7 +49,7 @@ namespace Emby.Dlna.Profiles
}, },
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
Type = DlnaProfileType.Video, Type = DlnaProfileType.Video,
VideoCodec = "mpeg1video,mpeg2video,h264", VideoCodec = "mpeg1video,mpeg2video,h264",
AudioCodec = "ac3,mp2,mp3,aac" AudioCodec = "ac3,mp2,mp3,aac"

@ -49,7 +49,7 @@ namespace Emby.Dlna.Profiles
}, },
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
Type = DlnaProfileType.Video, Type = DlnaProfileType.Video,
VideoCodec = "mpeg1video,mpeg2video,h264", VideoCodec = "mpeg1video,mpeg2video,h264",
AudioCodec = "ac3,mp2,mp3,aac" AudioCodec = "ac3,mp2,mp3,aac"

@ -79,7 +79,7 @@ namespace Emby.Dlna.Profiles
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts,m2ts", Container = "ts,m2ts,mpegts",
Type = DlnaProfileType.Video, Type = DlnaProfileType.Video,
VideoCodec = "mpeg1video,mpeg2video,h264,vc1", VideoCodec = "mpeg1video,mpeg2video,h264,vc1",
AudioCodec = "ac3,eac3,dca,mp2,mp3,aac,dts" AudioCodec = "ac3,eac3,dca,mp2,mp3,aac,dts"
@ -155,7 +155,7 @@ namespace Emby.Dlna.Profiles
{ {
new ResponseProfile new ResponseProfile
{ {
Container = "ts", Container = "ts,mpegts",
OrgPn = "MPEG_TS_SD_NA", OrgPn = "MPEG_TS_SD_NA",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
} }

@ -59,7 +59,7 @@ namespace Emby.Dlna.Profiles
{ {
new DirectPlayProfile new DirectPlayProfile
{ {
Container = "ts", Container = "ts,mpegts",
VideoCodec = "h264,mpeg2video,hevc", VideoCodec = "h264,mpeg2video,hevc",
AudioCodec = "ac3,aac,mp3", AudioCodec = "ac3,aac,mp3",
Type = DlnaProfileType.Video Type = DlnaProfileType.Video

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Generic Device</Name> <Name>Generic Device</Name>
<Manufacturer>Emby</Manufacturer> <Manufacturer>Emby</Manufacturer>
<ManufacturerUrl>http://emby.media/</ManufacturerUrl> <ManufacturerUrl>http://emby.media/</ManufacturerUrl>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Denon AVR</Name> <Name>Denon AVR</Name>
<Identification> <Identification>
<FriendlyName>Denon:\[AVR:.*</FriendlyName> <FriendlyName>Denon:\[AVR:.*</FriendlyName>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>DirecTV HD-DVR</Name> <Name>DirecTV HD-DVR</Name>
<Identification> <Identification>
<FriendlyName>^DIRECTV.*$</FriendlyName> <FriendlyName>^DIRECTV.*$</FriendlyName>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Dish Hopper-Joey</Name> <Name>Dish Hopper-Joey</Name>
<Identification> <Identification>
<Manufacturer>Echostar Technologies LLC</Manufacturer> <Manufacturer>Echostar Technologies LLC</Manufacturer>
@ -86,7 +86,7 @@
</CodecProfile> </CodecProfile>
</CodecProfiles> </CodecProfiles>
<ResponseProfiles> <ResponseProfiles>
<ResponseProfile container="mkv,ts" type="Video" mimeType="video/mp4"> <ResponseProfile container="mkv,ts,mpegts" type="Video" mimeType="video/mp4">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
</ResponseProfiles> </ResponseProfiles>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>LG Smart TV</Name> <Name>LG Smart TV</Name>
<Identification> <Identification>
<FriendlyName>LG.*</FriendlyName> <FriendlyName>LG.*</FriendlyName>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Linksys DMA2100</Name> <Name>Linksys DMA2100</Name>
<Identification> <Identification>
<ModelName>DMA2100us</ModelName> <ModelName>DMA2100us</ModelName>
@ -34,7 +34,7 @@
<XmlRootAttributes /> <XmlRootAttributes />
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" /> <DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
<DirectPlayProfile container="avi,mp4,mkv,ts,m4v" type="Video" /> <DirectPlayProfile container="avi,mp4,mkv,ts,mpegts,m4v" type="Video" />
</DirectPlayProfiles> </DirectPlayProfiles>
<TranscodingProfiles> <TranscodingProfiles>
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" /> <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Marantz</Name> <Name>Marantz</Name>
<Identification> <Identification>
<Manufacturer>Marantz</Manufacturer> <Manufacturer>Marantz</Manufacturer>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>MediaMonkey</Name> <Name>MediaMonkey</Name>
<Identification> <Identification>
<FriendlyName>MediaMonkey</FriendlyName> <FriendlyName>MediaMonkey</FriendlyName>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Panasonic Viera</Name> <Name>Panasonic Viera</Name>
<Identification> <Identification>
<FriendlyName>VIERA</FriendlyName> <FriendlyName>VIERA</FriendlyName>
@ -40,7 +40,7 @@
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="mpeg,mpg" audioCodec="ac3,mp3,pcm_dvd" videoCodec="mpeg2video,mpeg4" type="Video" /> <DirectPlayProfile container="mpeg,mpg" audioCodec="ac3,mp3,pcm_dvd" videoCodec="mpeg2video,mpeg4" type="Video" />
<DirectPlayProfile container="mkv" audioCodec="aac,ac3,dca,mp3,mp2,pcm,dts" videoCodec="h264,mpeg2video" type="Video" /> <DirectPlayProfile container="mkv" audioCodec="aac,ac3,dca,mp3,mp2,pcm,dts" videoCodec="h264,mpeg2video" type="Video" />
<DirectPlayProfile container="ts" audioCodec="aac,mp3,mp2" videoCodec="h264,mpeg2video" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="aac,mp3,mp2" videoCodec="h264,mpeg2video" type="Video" />
<DirectPlayProfile container="mp4,m4v" audioCodec="aac,ac3,mp3,pcm" videoCodec="h264" type="Video" /> <DirectPlayProfile container="mp4,m4v" audioCodec="aac,ac3,mp3,pcm" videoCodec="h264" type="Video" />
<DirectPlayProfile container="mov" audioCodec="aac,pcm" videoCodec="h264" type="Video" /> <DirectPlayProfile container="mov" audioCodec="aac,pcm" videoCodec="h264" type="Video" />
<DirectPlayProfile container="avi" audioCodec="pcm" videoCodec="mpeg4" type="Video" /> <DirectPlayProfile container="avi" audioCodec="pcm" videoCodec="mpeg4" type="Video" />
@ -73,7 +73,7 @@
</CodecProfile> </CodecProfile>
</CodecProfiles> </CodecProfiles>
<ResponseProfiles> <ResponseProfiles>
<ResponseProfile container="ts" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4"> <ResponseProfile container="m4v" type="Video" mimeType="video/mp4">

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Popcorn Hour</Name> <Name>Popcorn Hour</Name>
<Manufacturer>Emby</Manufacturer> <Manufacturer>Emby</Manufacturer>
<ManufacturerUrl>http://emby.media/</ManufacturerUrl> <ManufacturerUrl>http://emby.media/</ManufacturerUrl>
@ -30,7 +30,7 @@
<XmlRootAttributes /> <XmlRootAttributes />
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="mp4,mov,m4v" audioCodec="aac" videoCodec="h264,mpeg4" type="Video" /> <DirectPlayProfile container="mp4,mov,m4v" audioCodec="aac" videoCodec="h264,mpeg4" type="Video" />
<DirectPlayProfile container="ts" audioCodec="aac,ac3,eac3,mp3,mp2,pcm" videoCodec="h264" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="aac,ac3,eac3,mp3,mp2,pcm" videoCodec="h264" type="Video" />
<DirectPlayProfile container="asf,wmv" audioCodec="wmav2,wmapro" videoCodec="wmv3,vc1" type="Video" /> <DirectPlayProfile container="asf,wmv" audioCodec="wmav2,wmapro" videoCodec="wmv3,vc1" type="Video" />
<DirectPlayProfile container="avi" audioCodec="mp3,ac3,eac3,mp2,pcm" videoCodec="mpeg4,msmpeg4" type="Video" /> <DirectPlayProfile container="avi" audioCodec="mp3,ac3,eac3,mp2,pcm" videoCodec="mpeg4,msmpeg4" type="Video" />
<DirectPlayProfile container="mkv" audioCodec="aac,mp3,ac3,eac3,mp2,pcm" videoCodec="h264" type="Video" /> <DirectPlayProfile container="mkv" audioCodec="aac,mp3,ac3,eac3,mp2,pcm" videoCodec="h264" type="Video" />

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Samsung Smart TV</Name> <Name>Samsung Smart TV</Name>
<Identification> <Identification>
<ModelUrl>samsung.com</ModelUrl> <ModelUrl>samsung.com</ModelUrl>
@ -14,7 +14,7 @@
<ModelNumber>Emby</ModelNumber> <ModelNumber>Emby</ModelNumber>
<ModelUrl>http://emby.media/</ModelUrl> <ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>true</EnableAlbumArtInDidl> <EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit>
<EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit> <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn> <AlbumArtPn>JPEG_SM</AlbumArtPn>
@ -51,7 +51,7 @@
</DirectPlayProfiles> </DirectPlayProfiles>
<TranscodingProfiles> <TranscodingProfiles>
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" /> <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" /> <TranscodingProfile container="ts,mpegts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" /> <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
</TranscodingProfiles> </TranscodingProfiles>
<ContainerProfiles> <ContainerProfiles>
@ -100,7 +100,7 @@
</Conditions> </Conditions>
<ApplyConditions /> <ApplyConditions />
</CodecProfile> </CodecProfile>
<CodecProfile type="VideoAudio" codec="ac3,wmav2,dca,aac,mp3,dts"> <CodecProfile type="VideoAudio" codec="wmav2,dca,aac,mp3,dts">
<Conditions> <Conditions>
<ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="true" /> <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="true" />
</Conditions> </Conditions>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sharp Smart TV</Name> <Name>Sharp Smart TV</Name>
<Identification> <Identification>
<Manufacturer>Sharp</Manufacturer> <Manufacturer>Sharp</Manufacturer>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony Blu-ray Player 2013</Name> <Name>Sony Blu-ray Player 2013</Name>
<Identification> <Identification>
<ModelNumber>BDP-2013</ModelNumber> <ModelNumber>BDP-2013</ModelNumber>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony Blu-ray Player 2014</Name> <Name>Sony Blu-ray Player 2014</Name>
<Identification> <Identification>
<ModelNumber>BDP-2014</ModelNumber> <ModelNumber>BDP-2014</ModelNumber>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony Blu-ray Player 2015</Name> <Name>Sony Blu-ray Player 2015</Name>
<Identification> <Identification>
<ModelNumber>BDP-2015</ModelNumber> <ModelNumber>BDP-2015</ModelNumber>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony Blu-ray Player 2016</Name> <Name>Sony Blu-ray Player 2016</Name>
<Identification> <Identification>
<ModelNumber>BDP-2016</ModelNumber> <ModelNumber>BDP-2016</ModelNumber>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony Blu-ray Player</Name> <Name>Sony Blu-ray Player</Name>
<Identification> <Identification>
<FriendlyName>Blu-ray Disc Player</FriendlyName> <FriendlyName>Blu-ray Disc Player</FriendlyName>
@ -39,7 +39,7 @@
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" /> <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
</XmlRootAttributes> </XmlRootAttributes>
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3,pcm" videoCodec="mpeg1video,mpeg2video,h264" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="ac3,aac,mp3,pcm" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
<DirectPlayProfile container="mpeg" audioCodec="ac3,mp3,pcm" videoCodec="mpeg1video,mpeg2video" type="Video" /> <DirectPlayProfile container="mpeg" audioCodec="ac3,mp3,pcm" videoCodec="mpeg1video,mpeg2video" type="Video" />
<DirectPlayProfile container="avi,mp4,m4v" audioCodec="ac3,aac,mp3,pcm" videoCodec="mpeg4,h264" type="Video" /> <DirectPlayProfile container="avi,mp4,m4v" audioCodec="ac3,aac,mp3,pcm" videoCodec="mpeg4,h264" type="Video" />
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" /> <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
@ -84,7 +84,7 @@
</CodecProfile> </CodecProfile>
</CodecProfiles> </CodecProfiles>
<ResponseProfiles> <ResponseProfiles>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg4,vc1" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg4,vc1" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="avi" type="Video" mimeType="video/mpeg"> <ResponseProfile container="avi" type="Video" mimeType="video/mpeg">
@ -93,7 +93,7 @@
<ResponseProfile container="mkv" type="Video" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="mkv" type="Video" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" type="Video" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" type="Video" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="mp4" type="Video" mimeType="video/mpeg"> <ResponseProfile container="mp4" type="Video" mimeType="video/mpeg">

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony Bravia (2010)</Name> <Name>Sony Bravia (2010)</Name>
<Identification> <Identification>
<FriendlyName>KDL-\d{2}[EHLNPB]X\d[01]\d.*</FriendlyName> <FriendlyName>KDL-\d{2}[EHLNPB]X\d[01]\d.*</FriendlyName>
@ -39,8 +39,8 @@
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" /> <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
</XmlRootAttributes> </XmlRootAttributes>
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
<DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg1video,mpeg2video" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="mp3,mp2" videoCodec="mpeg1video,mpeg2video" type="Video" />
<DirectPlayProfile container="mpeg" audioCodec="mp3,mp2" videoCodec="mpeg2video,mpeg1video" type="Video" /> <DirectPlayProfile container="mpeg" audioCodec="mp3,mp2" videoCodec="mpeg2video,mpeg1video" type="Video" />
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" /> <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
</DirectPlayProfiles> </DirectPlayProfiles>
@ -106,21 +106,21 @@
</CodecProfile> </CodecProfile>
</CodecProfiles> </CodecProfiles>
<ResponseProfiles> <ResponseProfiles>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions> <Conditions>
<ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" /> <ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" />
<ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" /> <ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" />
</Conditions> </Conditions>
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg">
<Conditions> <Conditions>
<ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" /> <ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" />
</Conditions> </Conditions>
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg"> <ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony Bravia (2011)</Name> <Name>Sony Bravia (2011)</Name>
<Identification> <Identification>
<FriendlyName>KDL-\d{2}([A-Z]X\d2\d|CX400).*</FriendlyName> <FriendlyName>KDL-\d{2}([A-Z]X\d2\d|CX400).*</FriendlyName>
@ -39,8 +39,8 @@
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" /> <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
</XmlRootAttributes> </XmlRootAttributes>
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
<DirectPlayProfile container="ts" audioCodec="mp3" videoCodec="mpeg2video" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="mp3" videoCodec="mpeg2video" type="Video" />
<DirectPlayProfile container="mp4,m4v" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg4" type="Video" /> <DirectPlayProfile container="mp4,m4v" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg4" type="Video" />
<DirectPlayProfile container="mpeg" audioCodec="mp3" videoCodec="mpeg2video,mpeg1video" type="Video" /> <DirectPlayProfile container="mpeg" audioCodec="mp3" videoCodec="mpeg2video,mpeg1video" type="Video" />
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" /> <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" />
@ -109,21 +109,21 @@
</CodecProfile> </CodecProfile>
</CodecProfiles> </CodecProfiles>
<ResponseProfiles> <ResponseProfiles>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions> <Conditions>
<ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" /> <ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" />
<ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" /> <ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" />
</Conditions> </Conditions>
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg">
<Conditions> <Conditions>
<ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" /> <ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" />
</Conditions> </Conditions>
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg"> <ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony Bravia (2012)</Name> <Name>Sony Bravia (2012)</Name>
<Identification> <Identification>
<FriendlyName>KDL-\d{2}[A-Z]X\d5(\d|G).*</FriendlyName> <FriendlyName>KDL-\d{2}[A-Z]X\d5(\d|G).*</FriendlyName>
@ -39,8 +39,8 @@
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" /> <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
</XmlRootAttributes> </XmlRootAttributes>
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
<DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
<DirectPlayProfile container="mp4,m4v" audioCodec="ac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" /> <DirectPlayProfile container="mp4,m4v" audioCodec="ac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" /> <DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
<DirectPlayProfile container="mpeg" audioCodec="mp3,mp2" videoCodec="mpeg2video,mpeg1video" type="Video" /> <DirectPlayProfile container="mpeg" audioCodec="mp3,mp2" videoCodec="mpeg2video,mpeg1video" type="Video" />
@ -85,21 +85,21 @@
</CodecProfile> </CodecProfile>
</CodecProfiles> </CodecProfiles>
<ResponseProfiles> <ResponseProfiles>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions> <Conditions>
<ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" /> <ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" />
<ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" /> <ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" />
</Conditions> </Conditions>
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg">
<Conditions> <Conditions>
<ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" /> <ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" />
</Conditions> </Conditions>
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg"> <ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony Bravia (2013)</Name> <Name>Sony Bravia (2013)</Name>
<Identification> <Identification>
<FriendlyName>KDL-\d{2}[WR][5689]\d{2}A.*</FriendlyName> <FriendlyName>KDL-\d{2}[WR][5689]\d{2}A.*</FriendlyName>
@ -39,8 +39,8 @@
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" /> <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
</XmlRootAttributes> </XmlRootAttributes>
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,eac3,aac,mp3" videoCodec="h264" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="ac3,eac3,aac,mp3" videoCodec="h264" type="Video" />
<DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
<DirectPlayProfile container="mp4,m4v" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" /> <DirectPlayProfile container="mp4,m4v" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
<DirectPlayProfile container="mov" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4,mjpeg" type="Video" /> <DirectPlayProfile container="mov" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4,mjpeg" type="Video" />
<DirectPlayProfile container="mkv" audioCodec="ac3,eac3,aac,mp3,mp2,pcm,vorbis" videoCodec="h264,mpeg4,vp8" type="Video" /> <DirectPlayProfile container="mkv" audioCodec="ac3,eac3,aac,mp3,mp2,pcm,vorbis" videoCodec="h264,mpeg4,vp8" type="Video" />
@ -84,21 +84,21 @@
</CodecProfile> </CodecProfile>
</CodecProfiles> </CodecProfiles>
<ResponseProfiles> <ResponseProfiles>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions> <Conditions>
<ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" /> <ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" />
<ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" /> <ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" />
</Conditions> </Conditions>
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg">
<Conditions> <Conditions>
<ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" /> <ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" />
</Conditions> </Conditions>
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg"> <ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony Bravia (2014)</Name> <Name>Sony Bravia (2014)</Name>
<Identification> <Identification>
<FriendlyName>(KDL-\d{2}W[5-9]\d{2}B|KDL-\d{2}R480|XBR-\d{2}X[89]\d{2}B|KD-\d{2}[SX][89]\d{3}B).*</FriendlyName> <FriendlyName>(KDL-\d{2}W[5-9]\d{2}B|KDL-\d{2}R480|XBR-\d{2}X[89]\d{2}B|KD-\d{2}[SX][89]\d{3}B).*</FriendlyName>
@ -39,8 +39,8 @@
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" /> <XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
</XmlRootAttributes> </XmlRootAttributes>
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,eac3,aac,mp3" videoCodec="h264" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="ac3,eac3,aac,mp3" videoCodec="h264" type="Video" />
<DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
<DirectPlayProfile container="mp4,m4v" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" /> <DirectPlayProfile container="mp4,m4v" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
<DirectPlayProfile container="mov" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4,mjpeg" type="Video" /> <DirectPlayProfile container="mov" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4,mjpeg" type="Video" />
<DirectPlayProfile container="mkv" audioCodec="ac3,eac3,aac,mp3,mp2,pcm,vorbis" videoCodec="h264,mpeg4,vp8" type="Video" /> <DirectPlayProfile container="mkv" audioCodec="ac3,eac3,aac,mp3,mp2,pcm,vorbis" videoCodec="h264,mpeg4,vp8" type="Video" />
@ -84,21 +84,21 @@
</CodecProfile> </CodecProfile>
</CodecProfiles> </CodecProfiles>
<ResponseProfiles> <ResponseProfiles>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_T,AVC_TS_HD_50_AC3_T,AVC_TS_HD_60_AC3_T,AVC_TS_HD_EU_T" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions> <Conditions>
<ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" /> <ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" />
<ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" /> <ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" />
</Conditions> </Conditions>
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3_ISO,AVC_TS_HD_50_AC3_ISO,AVC_TS_HD_60_AC3_ISO,AVC_TS_HD_EU_ISO" mimeType="video/mpeg">
<Conditions> <Conditions>
<ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" /> <ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" />
</Conditions> </Conditions>
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" orgPn="AVC_TS_HD_24_AC3,AVC_TS_HD_50_AC3,AVC_TS_HD_60_AC3,AVC_TS_HD_EU" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="ts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts"> <ResponseProfile container="ts,mpegts" videoCodec="mpeg2video" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg"> <ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony PlayStation 3</Name> <Name>Sony PlayStation 3</Name>
<Identification> <Identification>
<FriendlyName>PLAYSTATION 3</FriendlyName> <FriendlyName>PLAYSTATION 3</FriendlyName>
@ -38,7 +38,7 @@
<XmlRootAttributes /> <XmlRootAttributes />
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" /> <DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" />
<DirectPlayProfile container="ts" audioCodec="ac3,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="ac3,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
<DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg1video,mpeg2video" type="Video" /> <DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg1video,mpeg2video" type="Video" />
<DirectPlayProfile container="mp4" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" /> <DirectPlayProfile container="mp4" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" />
<DirectPlayProfile container="aac,mp3,wav" type="Audio" /> <DirectPlayProfile container="aac,mp3,wav" type="Audio" />

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Sony PlayStation 4</Name> <Name>Sony PlayStation 4</Name>
<Identification> <Identification>
<FriendlyName>PLAYSTATION 4</FriendlyName> <FriendlyName>PLAYSTATION 4</FriendlyName>
@ -38,7 +38,7 @@
<XmlRootAttributes /> <XmlRootAttributes />
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" /> <DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" />
<DirectPlayProfile container="ts" audioCodec="ac3,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="ac3,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
<DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg1video,mpeg2video" type="Video" /> <DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg1video,mpeg2video" type="Video" />
<DirectPlayProfile container="mp4,mkv,m4v" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" /> <DirectPlayProfile container="mp4,mkv,m4v" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" />
<DirectPlayProfile container="aac,mp3,wav" type="Audio" /> <DirectPlayProfile container="aac,mp3,wav" type="Audio" />

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>WDTV Live</Name> <Name>WDTV Live</Name>
<Identification> <Identification>
<ModelName>WD TV</ModelName> <ModelName>WD TV</ModelName>
@ -39,7 +39,7 @@
<DirectPlayProfile container="avi" audioCodec="ac3,eac3,dca,mp2,mp3,pcm,dts" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" /> <DirectPlayProfile container="avi" audioCodec="ac3,eac3,dca,mp2,mp3,pcm,dts" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
<DirectPlayProfile container="mpeg" audioCodec="ac3,eac3,dca,mp2,mp3,pcm,dts" videoCodec="mpeg1video,mpeg2video" type="Video" /> <DirectPlayProfile container="mpeg" audioCodec="ac3,eac3,dca,mp2,mp3,pcm,dts" videoCodec="mpeg1video,mpeg2video" type="Video" />
<DirectPlayProfile container="mkv" audioCodec="ac3,eac3,dca,aac,mp2,mp3,pcm,dts" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" /> <DirectPlayProfile container="mkv" audioCodec="ac3,eac3,dca,aac,mp2,mp3,pcm,dts" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
<DirectPlayProfile container="ts,m2ts" audioCodec="ac3,eac3,dca,mp2,mp3,aac,dts" videoCodec="mpeg1video,mpeg2video,h264,vc1" type="Video" /> <DirectPlayProfile container="ts,m2ts,mpegts" audioCodec="ac3,eac3,dca,mp2,mp3,aac,dts" videoCodec="mpeg1video,mpeg2video,h264,vc1" type="Video" />
<DirectPlayProfile container="mp4,mov,m4v" audioCodec="ac3,eac3,aac,mp2,mp3,dca,dts" videoCodec="h264,mpeg4" type="Video" /> <DirectPlayProfile container="mp4,mov,m4v" audioCodec="ac3,eac3,aac,mp2,mp3,dca,dts" videoCodec="h264,mpeg4" type="Video" />
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="vc1" type="Video" /> <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="vc1" type="Video" />
<DirectPlayProfile container="asf" audioCodec="mp2,ac3" videoCodec="mpeg2video" type="Video" /> <DirectPlayProfile container="asf" audioCodec="mp2,ac3" videoCodec="mpeg2video" type="Video" />
@ -80,7 +80,7 @@
</CodecProfile> </CodecProfile>
</CodecProfiles> </CodecProfiles>
<ResponseProfiles> <ResponseProfiles>
<ResponseProfile container="ts" type="Video" orgPn="MPEG_TS_SD_NA"> <ResponseProfile container="ts,mpegts" type="Video" orgPn="MPEG_TS_SD_NA">
<Conditions /> <Conditions />
</ResponseProfile> </ResponseProfile>
</ResponseProfiles> </ResponseProfiles>

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Xbox One</Name> <Name>Xbox One</Name>
<Identification> <Identification>
<ModelName>Xbox One</ModelName> <ModelName>Xbox One</ModelName>
@ -36,7 +36,7 @@
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<XmlRootAttributes /> <XmlRootAttributes />
<DirectPlayProfiles> <DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg2video,hevc" type="Video" /> <DirectPlayProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg2video,hevc" type="Video" />
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" /> <DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
<DirectPlayProfile container="avi" audioCodec="aac" videoCodec="h264" type="Video" /> <DirectPlayProfile container="avi" audioCodec="aac" videoCodec="h264" type="Video" />
<DirectPlayProfile container="mp4,mov,mkv,m4v" audioCodec="aac,ac3" videoCodec="h264,mpeg4,mpeg2video,hevc" type="Video" /> <DirectPlayProfile container="mp4,mov,mkv,m4v" audioCodec="aac,ac3" videoCodec="h264,mpeg4,mpeg2video,hevc" type="Video" />

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>foobar2000</Name> <Name>foobar2000</Name>
<Identification> <Identification>
<FriendlyName>foobar</FriendlyName> <FriendlyName>foobar</FriendlyName>

@ -173,6 +173,8 @@ namespace Emby.Drawing.ImageMagick
originalImage.CurrentImage.CompressionQuality = quality; originalImage.CurrentImage.CompressionQuality = quality;
originalImage.CurrentImage.StripImage(); originalImage.CurrentImage.StripImage();
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath));
originalImage.SaveImage(outputPath); originalImage.SaveImage(outputPath);
} }
} }

@ -59,9 +59,6 @@
<Compile Include="StripCollageBuilder.cs" /> <Compile Include="StripCollageBuilder.cs" />
<Compile Include="UnplayedCountIndicator.cs" /> <Compile Include="UnplayedCountIndicator.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="fonts\robotoregular.ttf" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="SkiaSharp, Version=1.58.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL"> <Reference Include="SkiaSharp, Version=1.58.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\SkiaSharp.1.58.1\lib\portable-net45+win8+wpa81+wp8\SkiaSharp.dll</HintPath> <HintPath>..\packages\SkiaSharp.1.58.1\lib\portable-net45+win8+wpa81+wp8\SkiaSharp.dll</HintPath>

@ -15,7 +15,6 @@ namespace Emby.Drawing.Skia
{ {
public class PlayedIndicatorDrawer public class PlayedIndicatorDrawer
{ {
private const int FontSize = 42;
private const int OffsetFromTopRightCorner = 38; private const int OffsetFromTopRightCorner = 38;
private readonly IApplicationPaths _appPaths; private readonly IApplicationPaths _appPaths;
@ -44,48 +43,23 @@ namespace Emby.Drawing.Skia
{ {
paint.Color = new SKColor(255, 255, 255, 255); paint.Color = new SKColor(255, 255, 255, 255);
paint.Style = SKPaintStyle.Fill; paint.Style = SKPaintStyle.Fill;
paint.Typeface = SKTypeface.FromFile(await DownloadFont("webdings.ttf", "https://github.com/MediaBrowser/Emby.Resources/raw/master/fonts/webdings.ttf",
_appPaths, _iHttpClient, _fileSystem).ConfigureAwait(false));
paint.TextSize = FontSize;
paint.IsAntialias = true;
canvas.DrawText("a", (float)x-20, OffsetFromTopRightCorner + 12, paint);
}
}
internal static string ExtractFont(string name, IApplicationPaths paths, IFileSystem fileSystem)
{
var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name);
if (fileSystem.FileExists(filePath))
{
return filePath;
}
var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name; paint.TextSize = 30;
var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf"); paint.IsAntialias = true;
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(tempPath));
using (var stream = typeof(PlayedIndicatorDrawer).GetTypeInfo().Assembly.GetManifestResourceStream(namespacePath)) var text = "✔️";
{ var emojiChar = StringUtilities.GetUnicodeCharacterCode(text, SKTextEncoding.Utf32);
using (var fileStream = fileSystem.GetFileStream(tempPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) // or:
{ //var emojiChar = 0x1F680;
stream.CopyTo(fileStream);
}
}
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath)); // ask the font manager for a font with that character
var fontManager = SKFontManager.Default;
var emojiTypeface = fontManager.MatchCharacter(emojiChar);
try paint.Typeface = emojiTypeface;
{
fileSystem.CopyFile(tempPath, filePath, false);
}
catch (IOException)
{
canvas.DrawText(text, (float)x-20, OffsetFromTopRightCorner + 12, paint);
} }
return tempPath;
} }
internal static async Task<string> DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient, IFileSystem fileSystem) internal static async Task<string> DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient, IFileSystem fileSystem)

@ -528,6 +528,7 @@ namespace Emby.Drawing.Skia
// If all we're doing is resizing then we can stop now // If all we're doing is resizing then we can stop now
if (!hasBackgroundColor && !hasForegroundColor && blur == 0 && !hasIndicator) if (!hasBackgroundColor && !hasForegroundColor && blur == 0 && !hasIndicator)
{ {
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath));
using (var outputStream = new SKFileWStream(outputPath)) using (var outputStream = new SKFileWStream(outputPath))
{ {
resizedBitmap.Encode(outputStream, skiaOutputFormat, quality); resizedBitmap.Encode(outputStream, skiaOutputFormat, quality);
@ -580,6 +581,7 @@ namespace Emby.Drawing.Skia
DrawIndicator(canvas, width, height, options); DrawIndicator(canvas, width, height, options);
} }
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath));
using (var outputStream = new SKFileWStream(outputPath)) using (var outputStream = new SKFileWStream(outputPath))
{ {
saveBitmap.Encode(outputStream, skiaOutputFormat, quality); saveBitmap.Encode(outputStream, skiaOutputFormat, quality);

@ -40,7 +40,7 @@ namespace Emby.Drawing.Skia
{ {
paint.Color = new SKColor(255, 255, 255, 255); paint.Color = new SKColor(255, 255, 255, 255);
paint.Style = SKPaintStyle.Fill; paint.Style = SKPaintStyle.Fill;
paint.Typeface = SKTypeface.FromFile(PlayedIndicatorDrawer.ExtractFont("robotoregular.ttf", _appPaths, _fileSystem));
paint.TextSize = 24; paint.TextSize = 24;
paint.IsAntialias = true; paint.IsAntialias = true;

@ -220,7 +220,7 @@ namespace Emby.Drawing
Type = originalImage.Type, Type = originalImage.Type,
Path = originalImagePath Path = originalImagePath
}, requiresTransparency, item, options.ImageIndex, options.Enhancers).ConfigureAwait(false); }, requiresTransparency, item, options.ImageIndex, options.Enhancers, CancellationToken.None).ConfigureAwait(false);
originalImagePath = tuple.Item1; originalImagePath = tuple.Item1;
dateModified = tuple.Item2; dateModified = tuple.Item2;
@ -256,31 +256,29 @@ namespace Emby.Drawing
var outputFormat = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency); var outputFormat = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency);
var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.Blur, options.BackgroundColor, options.ForegroundLayer); var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.Blur, options.BackgroundColor, options.ForegroundLayer);
CheckDisposed();
var lockInfo = GetLock(cacheFilePath);
await lockInfo.Lock.WaitAsync().ConfigureAwait(false);
try try
{ {
CheckDisposed();
if (!_fileSystem.FileExists(cacheFilePath)) if (!_fileSystem.FileExists(cacheFilePath))
{ {
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
if (options.CropWhiteSpace && !SupportsTransparency(originalImagePath)) if (options.CropWhiteSpace && !SupportsTransparency(originalImagePath))
{ {
options.CropWhiteSpace = false; options.CropWhiteSpace = false;
} }
var resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, tmpPath, autoOrient, orientation, quality, options, outputFormat); var resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat);
if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase)) if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
{ {
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
} }
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath)); return new Tuple<string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath));
CopyFile(tmpPath, cacheFilePath);
return new Tuple<string, string, DateTime>(tmpPath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(tmpPath));
} }
return new Tuple<string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath)); return new Tuple<string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath));
@ -302,6 +300,10 @@ namespace Emby.Drawing
// Just spit out the original file if all the options are default // Just spit out the original file if all the options are default
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
} }
finally
{
ReleaseLock(cacheFilePath, lockInfo);
}
} }
private ImageFormat GetOutputFormat(ImageFormat[] clientSupportedFormats, bool requiresTransparency) private ImageFormat GetOutputFormat(ImageFormat[] clientSupportedFormats, bool requiresTransparency)
@ -667,7 +669,7 @@ namespace Emby.Drawing
var inputImageSupportsTransparency = SupportsTransparency(imageInfo.Path); var inputImageSupportsTransparency = SupportsTransparency(imageInfo.Path);
var result = await GetEnhancedImage(imageInfo, inputImageSupportsTransparency, item, imageIndex, enhancers); var result = await GetEnhancedImage(imageInfo, inputImageSupportsTransparency, item, imageIndex, enhancers, CancellationToken.None);
return result.Item1; return result.Item1;
} }
@ -676,7 +678,8 @@ namespace Emby.Drawing
bool inputImageSupportsTransparency, bool inputImageSupportsTransparency,
IHasMetadata item, IHasMetadata item,
int imageIndex, int imageIndex,
List<IImageEnhancer> enhancers) List<IImageEnhancer> enhancers,
CancellationToken cancellationToken)
{ {
var originalImagePath = image.Path; var originalImagePath = image.Path;
var dateModified = image.DateModified; var dateModified = image.DateModified;
@ -687,7 +690,7 @@ namespace Emby.Drawing
var cacheGuid = GetImageCacheTag(item, image, enhancers); var cacheGuid = GetImageCacheTag(item, image, enhancers);
// Enhance if we have enhancers // Enhance if we have enhancers
var ehnancedImageInfo = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid).ConfigureAwait(false); var ehnancedImageInfo = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid, cancellationToken).ConfigureAwait(false);
var ehnancedImagePath = ehnancedImageInfo.Item1; var ehnancedImagePath = ehnancedImageInfo.Item1;
@ -727,7 +730,8 @@ namespace Emby.Drawing
ImageType imageType, ImageType imageType,
int imageIndex, int imageIndex,
List<IImageEnhancer> supportedEnhancers, List<IImageEnhancer> supportedEnhancers,
string cacheGuid) string cacheGuid,
CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(originalImagePath)) if (string.IsNullOrEmpty(originalImagePath))
{ {
@ -755,29 +759,28 @@ namespace Emby.Drawing
var enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + cacheExtension); var enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + cacheExtension);
// Check again in case of contention var lockInfo = GetLock(enhancedImagePath);
if (_fileSystem.FileExists(enhancedImagePath))
{
return new Tuple<string, bool>(enhancedImagePath, treatmentRequiresTransparency);
}
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath)); await lockInfo.Lock.WaitAsync(cancellationToken).ConfigureAwait(false);
var tmpPath = Path.Combine(_appPaths.TempDirectory, Path.ChangeExtension(Guid.NewGuid().ToString(), Path.GetExtension(enhancedImagePath)));
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, tmpPath, item, imageType, imageIndex).ConfigureAwait(false);
try try
{ {
_fileSystem.CopyFile(tmpPath, enhancedImagePath, true); // Check again in case of contention
if (_fileSystem.FileExists(enhancedImagePath))
{
return new Tuple<string, bool>(enhancedImagePath, treatmentRequiresTransparency);
}
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath));
await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, enhancedImagePath, item, imageType, imageIndex).ConfigureAwait(false);
return new Tuple<string, bool>(enhancedImagePath, treatmentRequiresTransparency);
} }
catch finally
{ {
ReleaseLock(enhancedImagePath, lockInfo);
} }
return new Tuple<string, bool>(tmpPath, treatmentRequiresTransparency);
} }
/// <summary> /// <summary>
@ -896,6 +899,45 @@ namespace Emby.Drawing
return list; return list;
} }
private Dictionary<string, LockInfo> _locks = new Dictionary<string, LockInfo>();
private class LockInfo
{
public SemaphoreSlim Lock = new SemaphoreSlim(1, 1);
public int Count = 1;
}
private LockInfo GetLock(string key)
{
lock (_locks)
{
LockInfo info;
if (_locks.TryGetValue(key, out info))
{
info.Count++;
}
else
{
info = new LockInfo();
_locks[key] = info;
}
return info;
}
}
private void ReleaseLock(string key, LockInfo info)
{
info.Lock.Release();
lock (_locks)
{
info.Count--;
if (info.Count <= 0)
{
_locks.Remove(key);
info.Lock.Dispose();
}
}
}
private bool _disposed; private bool _disposed;
public void Dispose() public void Dispose()
{ {

@ -148,6 +148,34 @@ namespace Emby.Server.Implementations
} }
} }
public virtual bool CanLaunchWebBrowser
{
get
{
if (!Environment.UserInteractive)
{
return false;
}
if (StartupOptions.ContainsOption("-service"))
{
return false;
}
if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows)
{
return true;
}
if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.OSX)
{
return true;
}
return false;
}
}
/// <summary> /// <summary>
/// Occurs when [has pending restart changed]. /// Occurs when [has pending restart changed].
/// </summary> /// </summary>
@ -361,7 +389,7 @@ namespace Emby.Server.Implementations
protected IAuthService AuthService { get; private set; } protected IAuthService AuthService { get; private set; }
protected readonly StartupOptions StartupOptions; public StartupOptions StartupOptions { get; private set; }
protected readonly string ReleaseAssetFilename; protected readonly string ReleaseAssetFilename;
internal IPowerManagement PowerManagement { get; private set; } internal IPowerManagement PowerManagement { get; private set; }
@ -393,6 +421,7 @@ namespace Emby.Server.Implementations
ISystemEvents systemEvents, ISystemEvents systemEvents,
INetworkManager networkManager) INetworkManager networkManager)
{ {
// hack alert, until common can target .net core // hack alert, until common can target .net core
BaseExtensions.CryptographyProvider = CryptographyProvider; BaseExtensions.CryptographyProvider = CryptographyProvider;
@ -423,6 +452,13 @@ namespace Emby.Server.Implementations
SetBaseExceptionMessage(); SetBaseExceptionMessage();
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
NetworkManager.NetworkChanged += NetworkManager_NetworkChanged;
}
private void NetworkManager_NetworkChanged(object sender, EventArgs e)
{
_validAddressResults.Clear();
} }
private Version _version; private Version _version;
@ -1901,9 +1937,9 @@ namespace Emby.Server.Implementations
/// Gets the system status. /// Gets the system status.
/// </summary> /// </summary>
/// <returns>SystemInfo.</returns> /// <returns>SystemInfo.</returns>
public async Task<SystemInfo> GetSystemInfo() public async Task<SystemInfo> GetSystemInfo(CancellationToken cancellationToken)
{ {
var localAddress = await GetLocalApiUrl().ConfigureAwait(false); var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
return new SystemInfo return new SystemInfo
{ {
@ -1928,6 +1964,7 @@ namespace Emby.Server.Implementations
OperatingSystemDisplayName = OperatingSystemDisplayName, OperatingSystemDisplayName = OperatingSystemDisplayName,
CanSelfRestart = CanSelfRestart, CanSelfRestart = CanSelfRestart,
CanSelfUpdate = CanSelfUpdate, CanSelfUpdate = CanSelfUpdate,
CanLaunchWebBrowser = CanLaunchWebBrowser,
WanAddress = ConnectManager.WanApiAddress, WanAddress = ConnectManager.WanApiAddress,
HasUpdateAvailable = HasUpdateAvailable, HasUpdateAvailable = HasUpdateAvailable,
SupportsAutoRunAtStartup = SupportsAutoRunAtStartup, SupportsAutoRunAtStartup = SupportsAutoRunAtStartup,
@ -1942,6 +1979,21 @@ namespace Emby.Server.Implementations
}; };
} }
public async Task<PublicSystemInfo> GetPublicSystemInfo(CancellationToken cancellationToken)
{
var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
return new PublicSystemInfo
{
Version = ApplicationVersion.ToString(),
Id = SystemId,
OperatingSystem = EnvironmentInfo.OperatingSystem.ToString(),
WanAddress = ConnectManager.WanApiAddress,
ServerName = FriendlyName,
LocalAddress = localAddress
};
}
public bool EnableHttps public bool EnableHttps
{ {
get get
@ -1955,14 +2007,14 @@ namespace Emby.Server.Implementations
get { return Certificate != null || ServerConfigurationManager.Configuration.IsBehindProxy; } get { return Certificate != null || ServerConfigurationManager.Configuration.IsBehindProxy; }
} }
public async Task<string> GetLocalApiUrl() public async Task<string> GetLocalApiUrl(CancellationToken cancellationToken)
{ {
try try
{ {
// Return the first matched address, if found, or the first known local address // Return the first matched address, if found, or the first known local address
var address = (await GetLocalIpAddresses().ConfigureAwait(false)).FirstOrDefault(i => !i.Equals(IpAddressInfo.Loopback) && !i.Equals(IpAddressInfo.IPv6Loopback)); var addresses = await GetLocalIpAddressesInternal(false, 1, cancellationToken).ConfigureAwait(false);
if (address != null) foreach (var address in addresses)
{ {
return GetLocalApiUrl(address); return GetLocalApiUrl(address);
} }
@ -1994,7 +2046,12 @@ namespace Emby.Server.Implementations
HttpPort.ToString(CultureInfo.InvariantCulture)); HttpPort.ToString(CultureInfo.InvariantCulture));
} }
public async Task<List<IpAddressInfo>> GetLocalIpAddresses() public Task<List<IpAddressInfo>> GetLocalIpAddresses(CancellationToken cancellationToken)
{
return GetLocalIpAddressesInternal(true, 0, cancellationToken);
}
private async Task<List<IpAddressInfo>> GetLocalIpAddressesInternal(bool allowLoopback, int limit, CancellationToken cancellationToken)
{ {
var addresses = ServerConfigurationManager var addresses = ServerConfigurationManager
.Configuration .Configuration
@ -2006,22 +2063,33 @@ namespace Emby.Server.Implementations
if (addresses.Count == 0) if (addresses.Count == 0)
{ {
addresses.AddRange(NetworkManager.GetLocalIpAddresses()); addresses.AddRange(NetworkManager.GetLocalIpAddresses());
}
var list = new List<IpAddressInfo>(); var resultList = new List<IpAddressInfo>();
foreach (var address in addresses) foreach (var address in addresses)
{
if (!allowLoopback)
{ {
var valid = await IsIpAddressValidAsync(address).ConfigureAwait(false); if (address.Equals(IpAddressInfo.Loopback) || address.Equals(IpAddressInfo.IPv6Loopback))
if (valid)
{ {
list.Add(address); continue;
} }
} }
addresses = list; var valid = await IsIpAddressValidAsync(address, cancellationToken).ConfigureAwait(false);
if (valid)
{
resultList.Add(address);
if (limit > 0 && resultList.Count >= limit)
{
return resultList;
}
}
} }
return addresses; return resultList;
} }
private IpAddressInfo NormalizeConfiguredLocalAddress(string address) private IpAddressInfo NormalizeConfiguredLocalAddress(string address)
@ -2042,8 +2110,7 @@ namespace Emby.Server.Implementations
} }
private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase); private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
private DateTime _lastAddressCacheClear; private async Task<bool> IsIpAddressValidAsync(IpAddressInfo address, CancellationToken cancellationToken)
private async Task<bool> IsIpAddressValidAsync(IpAddressInfo address)
{ {
if (address.Equals(IpAddressInfo.Loopback) || if (address.Equals(IpAddressInfo.Loopback) ||
address.Equals(IpAddressInfo.IPv6Loopback)) address.Equals(IpAddressInfo.IPv6Loopback))
@ -2054,12 +2121,6 @@ namespace Emby.Server.Implementations
var apiUrl = GetLocalApiUrl(address); var apiUrl = GetLocalApiUrl(address);
apiUrl += "/system/ping"; apiUrl += "/system/ping";
if ((DateTime.UtcNow - _lastAddressCacheClear).TotalMinutes >= 15)
{
_lastAddressCacheClear = DateTime.UtcNow;
_validAddressResults.Clear();
}
bool cachedResult; bool cachedResult;
if (_validAddressResults.TryGetValue(apiUrl, out cachedResult)) if (_validAddressResults.TryGetValue(apiUrl, out cachedResult))
{ {
@ -2075,7 +2136,9 @@ namespace Emby.Server.Implementations
LogErrors = false, LogErrors = false,
LogRequest = false, LogRequest = false,
TimeoutMs = 30000, TimeoutMs = 30000,
BufferContent = false BufferContent = false,
CancellationToken = cancellationToken
}, "POST").ConfigureAwait(false)) }, "POST").ConfigureAwait(false))
{ {
@ -2085,14 +2148,19 @@ namespace Emby.Server.Implementations
var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase); var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase);
_validAddressResults.AddOrUpdate(apiUrl, valid, (k, v) => valid); _validAddressResults.AddOrUpdate(apiUrl, valid, (k, v) => valid);
//Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, valid); Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, valid);
return valid; return valid;
} }
} }
} }
catch (OperationCanceledException)
{
Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, "Cancelled");
throw;
}
catch catch
{ {
//Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, false); Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, false);
_validAddressResults.AddOrUpdate(apiUrl, false, (k, v) => false); _validAddressResults.AddOrUpdate(apiUrl, false, (k, v) => false);
return false; return false;
@ -2317,12 +2385,11 @@ namespace Emby.Server.Implementations
} }
} }
public void LaunchUrl(string url) public virtual void LaunchUrl(string url)
{ {
if (EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows && if (!CanLaunchWebBrowser)
EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.OSX)
{ {
throw new NotImplementedException(); throw new NotSupportedException();
} }
var process = ProcessFactory.Create(new ProcessOptions var process = ProcessFactory.Create(new ProcessOptions

@ -89,6 +89,24 @@ namespace Emby.Server.Implementations.Archiving
} }
} }
public void ExtractFirstFileFromGz(Stream source, string targetPath, string defaultFileName)
{
using (var reader = GZipReader.Open(source))
{
if (reader.MoveToNextEntry())
{
var entry = reader.Entry;
var filename = entry.Key;
if (string.IsNullOrWhiteSpace(filename))
{
filename = defaultFileName;
}
reader.WriteEntryToFile(Path.Combine(targetPath, filename));
}
}
}
/// <summary> /// <summary>
/// Extracts all from7z. /// Extracts all from7z.
/// </summary> /// </summary>

@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.Browser
{ {
appHost.LaunchUrl(url); appHost.LaunchUrl(url);
} }
catch (NotImplementedException) catch (NotSupportedException)
{ {
} }

@ -4286,7 +4286,7 @@ namespace Emby.Server.Implementations.Data
if (query.MinParentalRating.HasValue) if (query.MinParentalRating.HasValue)
{ {
whereClauses.Add("InheritedParentalRatingValue<=@MinParentalRating"); whereClauses.Add("InheritedParentalRatingValue>=@MinParentalRating");
if (statement != null) if (statement != null)
{ {
statement.TryBind("@MinParentalRating", query.MinParentalRating.Value); statement.TryBind("@MinParentalRating", query.MinParentalRating.Value);
@ -5264,7 +5264,13 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
ItemIds = query.ItemIds, ItemIds = query.ItemIds,
TopParentIds = query.TopParentIds, TopParentIds = query.TopParentIds,
ParentId = query.ParentId, ParentId = query.ParentId,
IsPlayed = query.IsPlayed IsPlayed = query.IsPlayed,
IsAiring = query.IsAiring,
IsMovie = query.IsMovie,
IsSports = query.IsSports,
IsKids = query.IsKids,
IsNews = query.IsNews,
IsSeries = query.IsSeries
}; };
var innerWhereClauses = GetWhereClauses(innerQuery, null); var innerWhereClauses = GetWhereClauses(innerQuery, null);

@ -708,6 +708,8 @@
<EmbeddedResource Include="Localization\Core\zh-CN.json" /> <EmbeddedResource Include="Localization\Core\zh-CN.json" />
<EmbeddedResource Include="Localization\Core\zh-HK.json" /> <EmbeddedResource Include="Localization\Core\zh-HK.json" />
<EmbeddedResource Include="Localization\Core\en-US.json" /> <EmbeddedResource Include="Localization\Core\en-US.json" />
<EmbeddedResource Include="Localization\Core\el.json" />
<EmbeddedResource Include="Localization\Core\gsw.json" />
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="TextEncoding\NLangDetect\Profiles\afr" /> <None Include="TextEncoding\NLangDetect\Profiles\afr" />
<None Include="TextEncoding\NLangDetect\Profiles\ara" /> <None Include="TextEncoding\NLangDetect\Profiles\ara" />

@ -13,6 +13,7 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Threading; using MediaBrowser.Model.Threading;
using Mono.Nat; using Mono.Nat;
using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Extensions;
using System.Threading;
namespace Emby.Server.Implementations.EntryPoints namespace Emby.Server.Implementations.EntryPoints
{ {
@ -158,7 +159,7 @@ namespace Emby.Server.Implementations.EntryPoints
try try
{ {
var localAddressString = await _appHost.GetLocalApiUrl().ConfigureAwait(false); var localAddressString = await _appHost.GetLocalApiUrl(CancellationToken.None).ConfigureAwait(false);
Uri uri; Uri uri;
if (Uri.TryCreate(localAddressString, UriKind.Absolute, out uri)) if (Uri.TryCreate(localAddressString, UriKind.Absolute, out uri))

@ -260,7 +260,7 @@ namespace Emby.Server.Implementations.EntryPoints
LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
} }
var parent = e.Item.GetParent() as Folder; var parent = e.Parent as Folder;
if (parent != null) if (parent != null)
{ {
_foldersRemovedFrom.Add(parent); _foldersRemovedFrom.Add(parent);
@ -363,10 +363,16 @@ namespace Emby.Server.Implementations.EntryPoints
/// <param name="foldersRemovedFrom">The folders removed from.</param> /// <param name="foldersRemovedFrom">The folders removed from.</param>
/// <param name="userId">The user id.</param> /// <param name="userId">The user id.</param>
/// <returns>LibraryUpdateInfo.</returns> /// <returns>LibraryUpdateInfo.</returns>
private LibraryUpdateInfo GetLibraryUpdateInfo(IEnumerable<BaseItem> itemsAdded, IEnumerable<BaseItem> itemsUpdated, IEnumerable<BaseItem> itemsRemoved, IEnumerable<Folder> foldersAddedTo, IEnumerable<Folder> foldersRemovedFrom, Guid userId) private LibraryUpdateInfo GetLibraryUpdateInfo(List<BaseItem> itemsAdded, List<BaseItem> itemsUpdated, List<BaseItem> itemsRemoved, List<Folder> foldersAddedTo, List<Folder> foldersRemovedFrom, Guid userId)
{ {
var user = _userManager.GetUserById(userId); var user = _userManager.GetUserById(userId);
var newAndRemoved = new List<BaseItem>();
newAndRemoved.AddRange(foldersAddedTo);
newAndRemoved.AddRange(foldersRemovedFrom);
var allUserRootChildren = _libraryManager.GetUserRootFolder().GetChildren(user, true).OfType<Folder>().ToList();
return new LibraryUpdateInfo return new LibraryUpdateInfo
{ {
ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(), ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
@ -377,7 +383,9 @@ namespace Emby.Server.Implementations.EntryPoints
FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(), FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray() FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToArray(),
CollectionFolders = GetTopParentIds(newAndRemoved, user, allUserRootChildren).ToArray()
}; };
} }
@ -396,6 +404,28 @@ namespace Emby.Server.Implementations.EntryPoints
return item.SourceType == SourceType.Library; return item.SourceType == SourceType.Library;
} }
private IEnumerable<string> GetTopParentIds(List<BaseItem> items, User user, List<Folder> allUserRootChildren)
{
var list = new List<string>();
foreach (var item in items)
{
// If the physical root changed, return the user root
if (item is AggregateFolder)
{
continue;
}
var collectionFolders = _libraryManager.GetCollectionFolders(item, allUserRootChildren);
foreach (var folder in allUserRootChildren)
{
list.Add(folder.Id.ToString("N"));
}
}
return list.Distinct(StringComparer.Ordinal);
}
/// <summary> /// <summary>
/// Translates the physical item to user library. /// Translates the physical item to user library.
/// </summary> /// </summary>

@ -3,6 +3,7 @@ using Emby.Server.Implementations.Browser;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Controller.Configuration;
namespace Emby.Server.Implementations.EntryPoints namespace Emby.Server.Implementations.EntryPoints
{ {
@ -20,15 +21,13 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary> /// </summary>
private readonly ILogger _logger; private readonly ILogger _logger;
/// <summary> private IServerConfigurationManager _config;
/// Initializes a new instance of the <see cref="StartupWizard" /> class.
/// </summary> public StartupWizard(IServerApplicationHost appHost, ILogger logger, IServerConfigurationManager config)
/// <param name="appHost">The app host.</param>
/// <param name="logger">The logger.</param>
public StartupWizard(IServerApplicationHost appHost, ILogger logger)
{ {
_appHost = appHost; _appHost = appHost;
_logger = logger; _logger = logger;
_config = config;
} }
/// <summary> /// <summary>
@ -36,18 +35,24 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary> /// </summary>
public void Run() public void Run()
{ {
if (!_appHost.CanLaunchWebBrowser)
{
return;
}
if (_appHost.IsFirstRun) if (_appHost.IsFirstRun)
{ {
LaunchStartupWizard(); BrowserLauncher.OpenDashboardPage("wizardstart.html", _appHost);
} }
} else if (_config.Configuration.IsStartupWizardCompleted && _config.Configuration.AutoRunWebApp)
{
var options = ((ApplicationHost)_appHost).StartupOptions;
/// <summary> if (!options.ContainsOption("-noautorunwebapp"))
/// Launches the startup wizard. {
/// </summary> BrowserLauncher.OpenDashboardPage("index.html", _appHost);
private void LaunchStartupWizard() }
{ }
BrowserLauncher.OpenDashboardPage("wizardstart.html", _appHost);
} }
/// <summary> /// <summary>

@ -237,7 +237,7 @@ namespace Emby.Server.Implementations.IO
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param> /// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
void LibraryManager_ItemRemoved(object sender, ItemChangeEventArgs e) void LibraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
{ {
if (e.Item.GetParent() is AggregateFolder) if (e.Parent is AggregateFolder)
{ {
StopWatchingPath(e.Item.Path); StopWatchingPath(e.Item.Path);
} }
@ -250,7 +250,7 @@ namespace Emby.Server.Implementations.IO
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param> /// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
void LibraryManager_ItemAdded(object sender, ItemChangeEventArgs e) void LibraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
{ {
if (e.Item.GetParent() is AggregateFolder) if (e.Parent is AggregateFolder)
{ {
StartWatching(e.Item); StartWatching(e.Item);
} }
@ -320,7 +320,8 @@ namespace Emby.Server.Implementations.IO
IncludeSubdirectories = true IncludeSubdirectories = true
}; };
if (_environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows) if (_environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows ||
_environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.OSX)
{ {
newWatcher.InternalBufferSize = 32767; newWatcher.InternalBufferSize = 32767;
} }

@ -473,6 +473,11 @@ namespace Emby.Server.Implementations.IO
public void SetHidden(string path, bool isHidden) public void SetHidden(string path, bool isHidden)
{ {
if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows)
{
return;
}
if (_sharpCifsFileSystem.IsEnabledForPath(path)) if (_sharpCifsFileSystem.IsEnabledForPath(path))
{ {
_sharpCifsFileSystem.SetHidden(path, isHidden); _sharpCifsFileSystem.SetHidden(path, isHidden);
@ -498,6 +503,11 @@ namespace Emby.Server.Implementations.IO
public void SetReadOnly(string path, bool isReadOnly) public void SetReadOnly(string path, bool isReadOnly)
{ {
if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows)
{
return;
}
if (_sharpCifsFileSystem.IsEnabledForPath(path)) if (_sharpCifsFileSystem.IsEnabledForPath(path))
{ {
_sharpCifsFileSystem.SetReadOnly(path, isReadOnly); _sharpCifsFileSystem.SetReadOnly(path, isReadOnly);
@ -523,6 +533,11 @@ namespace Emby.Server.Implementations.IO
public void SetAttributes(string path, bool isHidden, bool isReadOnly) public void SetAttributes(string path, bool isHidden, bool isReadOnly)
{ {
if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows)
{
return;
}
if (_sharpCifsFileSystem.IsEnabledForPath(path)) if (_sharpCifsFileSystem.IsEnabledForPath(path))
{ {
_sharpCifsFileSystem.SetAttributes(path, isHidden, isReadOnly); _sharpCifsFileSystem.SetAttributes(path, isHidden, isReadOnly);

@ -141,17 +141,6 @@ namespace Emby.Server.Implementations.Library
return true; return true;
} }
} }
// Ignore samples
var sampleFilename = " " + filename.Replace(".", " ", StringComparison.OrdinalIgnoreCase)
.Replace("-", " ", StringComparison.OrdinalIgnoreCase)
.Replace("_", " ", StringComparison.OrdinalIgnoreCase)
.Replace("!", " ", StringComparison.OrdinalIgnoreCase);
if (sampleFilename.IndexOf(" sample ", StringComparison.OrdinalIgnoreCase) != -1)
{
return true;
}
} }
return false; return false;

@ -443,7 +443,7 @@ namespace Emby.Server.Implementations.Library
BaseItem removed; BaseItem removed;
_libraryItemsCache.TryRemove(item.Id, out removed); _libraryItemsCache.TryRemove(item.Id, out removed);
ReportItemRemoved(item); ReportItemRemoved(item, parent);
} }
private IEnumerable<string> GetMetadataPaths(BaseItem item, IEnumerable<BaseItem> children) private IEnumerable<string> GetMetadataPaths(BaseItem item, IEnumerable<BaseItem> children)
@ -1804,7 +1804,7 @@ namespace Emby.Server.Implementations.Library
/// <returns>Task.</returns> /// <returns>Task.</returns>
public void CreateItem(BaseItem item, CancellationToken cancellationToken) public void CreateItem(BaseItem item, CancellationToken cancellationToken)
{ {
CreateItems(new[] { item }, cancellationToken); CreateItems(new[] { item }, item.GetParent(), cancellationToken);
} }
/// <summary> /// <summary>
@ -1813,7 +1813,7 @@ namespace Emby.Server.Implementations.Library
/// <param name="items">The items.</param> /// <param name="items">The items.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
public void CreateItems(IEnumerable<BaseItem> items, CancellationToken cancellationToken) public void CreateItems(IEnumerable<BaseItem> items, BaseItem parent, CancellationToken cancellationToken)
{ {
var list = items.ToList(); var list = items.ToList();
@ -1830,7 +1830,11 @@ namespace Emby.Server.Implementations.Library
{ {
try try
{ {
ItemAdded(this, new ItemChangeEventArgs { Item = item }); ItemAdded(this, new ItemChangeEventArgs
{
Item = item,
Parent = parent ?? item.GetParent()
});
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -1878,6 +1882,7 @@ namespace Emby.Server.Implementations.Library
ItemUpdated(this, new ItemChangeEventArgs ItemUpdated(this, new ItemChangeEventArgs
{ {
Item = item, Item = item,
Parent = item.GetParent(),
UpdateReason = updateReason UpdateReason = updateReason
}); });
} }
@ -1892,13 +1897,17 @@ namespace Emby.Server.Implementations.Library
/// Reports the item removed. /// Reports the item removed.
/// </summary> /// </summary>
/// <param name="item">The item.</param> /// <param name="item">The item.</param>
public void ReportItemRemoved(BaseItem item) public void ReportItemRemoved(BaseItem item, BaseItem parent)
{ {
if (ItemRemoved != null) if (ItemRemoved != null)
{ {
try try
{ {
ItemRemoved(this, new ItemChangeEventArgs { Item = item }); ItemRemoved(this, new ItemChangeEventArgs
{
Item = item,
Parent = parent
});
} }
catch (Exception ex) catch (Exception ex)
{ {

@ -125,10 +125,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
if (child.IsDirectory) if (child.IsDirectory)
{ {
leftOver.Add(child); leftOver.Add(child);
}
else if (IsIgnored(child.Name))
{
} }
else else
{ {
@ -298,22 +294,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
return item; return item;
} }
private bool IsIgnored(string filename)
{
// Ignore samples
var sampleFilename = " " + filename.Replace(".", " ", StringComparison.OrdinalIgnoreCase)
.Replace("-", " ", StringComparison.OrdinalIgnoreCase)
.Replace("_", " ", StringComparison.OrdinalIgnoreCase)
.Replace("!", " ", StringComparison.OrdinalIgnoreCase);
if (sampleFilename.IndexOf(" sample ", StringComparison.OrdinalIgnoreCase) != -1)
{
return true;
}
return false;
}
/// <summary> /// <summary>
/// Sets the initial item values. /// Sets the initial item values.
/// </summary> /// </summary>

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Globalization;
using Emby.Naming.Common; using Emby.Naming.Common;
using Emby.Naming.TV; using Emby.Naming.TV;
using MediaBrowser.Model.Logging;
namespace Emby.Server.Implementations.Library.Resolvers.TV namespace Emby.Server.Implementations.Library.Resolvers.TV
{ {
@ -21,16 +22,18 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
private readonly ILocalizationManager _localization; private readonly ILocalizationManager _localization;
private readonly ILogger _logger;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SeasonResolver"/> class. /// Initializes a new instance of the <see cref="SeasonResolver"/> class.
/// </summary> /// </summary>
/// <param name="config">The config.</param> /// <param name="config">The config.</param>
public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization) public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, ILogger logger)
{ {
_config = config; _config = config;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_localization = localization; _localization = localization;
_logger = logger;
} }
/// <summary> /// <summary>
@ -45,20 +48,40 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
var series = ((Series)args.Parent); var series = ((Series)args.Parent);
var path = args.Path;
var season = new Season var season = new Season
{ {
IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber, IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(path, true, true).SeasonNumber,
SeriesId = series.Id, SeriesId = series.Id,
SeriesName = series.Name SeriesName = series.Name
}; };
if (season.IndexNumber.HasValue) if (season.IndexNumber.HasValue)
{ {
var resolver = new Emby.Naming.TV.EpisodeResolver(namingOptions);
var episodeInfo = resolver.Resolve(path, true);
if (episodeInfo != null)
{
if (episodeInfo.EpisodeNumber.HasValue && episodeInfo.SeasonNumber.HasValue)
{
_logger.Info("Found folder underneath series with episode number: {0}. Season {1}. Episode {2}",
path,
episodeInfo.SeasonNumber.Value,
episodeInfo.EpisodeNumber.Value);
return null;
}
}
var seasonNumber = season.IndexNumber.Value; var seasonNumber = season.IndexNumber.Value;
season.Name = seasonNumber == 0 ? season.Name = seasonNumber == 0 ?
args.LibraryOptions.SeasonZeroDisplayName : args.LibraryOptions.SeasonZeroDisplayName :
string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture), args.GetLibraryOptions().PreferredMetadataLanguage); string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture), args.GetLibraryOptions().PreferredMetadataLanguage);
} }
return season; return season;

@ -191,7 +191,8 @@ namespace Emby.Server.Implementations.Library
{ {
ItemFields.AirTime, ItemFields.AirTime,
ItemFields.DateCreated, ItemFields.DateCreated,
ItemFields.ChannelInfo ItemFields.ChannelInfo,
ItemFields.ParentId
} }
} }
}; };

@ -218,7 +218,7 @@ namespace Emby.Server.Implementations.Library
return builder.ToString(); return builder.ToString();
} }
public async Task<User> AuthenticateUser(string username, string password, string hashedPassword, string passwordMd5, string remoteEndPoint) public async Task<User> AuthenticateUser(string username, string password, string hashedPassword, string passwordMd5, string remoteEndPoint, bool isUserSession)
{ {
if (string.IsNullOrWhiteSpace(username)) if (string.IsNullOrWhiteSpace(username))
{ {
@ -288,8 +288,11 @@ namespace Emby.Server.Implementations.Library
// Update LastActivityDate and LastLoginDate, then save // Update LastActivityDate and LastLoginDate, then save
if (success) if (success)
{ {
user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow; if (isUserSession)
UpdateUser(user); {
user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow;
UpdateUser(user);
}
UpdateInvalidLoginAttemptCount(user, 0); UpdateInvalidLoginAttemptCount(user, 0);
} }
else else
@ -812,7 +815,7 @@ namespace Emby.Server.Implementations.Library
var text = new StringBuilder(); var text = new StringBuilder();
var localAddress = _appHost.GetLocalApiUrl().Result ?? string.Empty; var localAddress = _appHost.GetLocalApiUrl(CancellationToken.None).Result ?? string.Empty;
text.AppendLine("Use your web browser to visit:"); text.AppendLine("Use your web browser to visit:");
text.AppendLine(string.Empty); text.AppendLine(string.Empty);

@ -1512,6 +1512,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
} }
} }
DeleteFileIfEmpty(recordPath);
TriggerRefresh(recordPath); TriggerRefresh(recordPath);
_libraryMonitor.ReportFileSystemChangeComplete(recordPath, false); _libraryMonitor.ReportFileSystemChangeComplete(recordPath, false);
@ -1542,6 +1544,23 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
} }
} }
private void DeleteFileIfEmpty(string path)
{
var file = _fileSystem.GetFileInfo(path);
if (file.Exists && file.Length == 0)
{
try
{
_fileSystem.DeleteFile(path);
}
catch (Exception ex)
{
_logger.ErrorException("Error deleting 0-byte failed recording file {0}", ex, path);
}
}
}
private void TriggerRefresh(string path) private void TriggerRefresh(string path)
{ {
_logger.Info("Triggering refresh on {0}", path); _logger.Info("Triggering refresh on {0}", path);
@ -1897,7 +1916,15 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
imageSaveFilenameWithoutExtension = "logo"; imageSaveFilenameWithoutExtension = "logo";
break; break;
case ImageType.Thumb: case ImageType.Thumb:
imageSaveFilenameWithoutExtension = "landscape"; if (program.IsSeries)
{
imageSaveFilenameWithoutExtension = Path.GetFileNameWithoutExtension(recordingPath) + "-thumb";
}
else
{
imageSaveFilenameWithoutExtension = "landscape";
}
break; break;
case ImageType.Backdrop: case ImageType.Backdrop:
imageSaveFilenameWithoutExtension = "fanart"; imageSaveFilenameWithoutExtension = "fanart";
@ -1921,9 +1948,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private async Task SaveRecordingImages(string recordingPath, LiveTvProgram program) private async Task SaveRecordingImages(string recordingPath, LiveTvProgram program)
{ {
var image = program.GetImageInfo(ImageType.Primary, 0); var image = program.IsSeries ?
(program.GetImageInfo(ImageType.Thumb, 0) ?? program.GetImageInfo(ImageType.Primary, 0)) :
(program.GetImageInfo(ImageType.Primary, 0) ?? program.GetImageInfo(ImageType.Thumb, 0));
if (image != null && program.IsMovie) if (image != null)
{ {
try try
{ {

@ -105,31 +105,64 @@ namespace Emby.Server.Implementations.LiveTv.Listings
if (string.Equals(ext, ".gz", StringComparison.OrdinalIgnoreCase)) if (string.Equals(ext, ".gz", StringComparison.OrdinalIgnoreCase))
{ {
using (var stream = _fileSystem.OpenRead(file)) try
{ {
var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString()); var tempFolder = ExtractGz(file);
_fileSystem.CreateDirectory(tempFolder); return FindXmlFile(tempFolder);
}
try catch (Exception ex)
{ {
_zipClient.ExtractAllFromGz(stream, tempFolder, true); //_logger.ErrorException("Error extracting from gz file {0}", ex, file);
} }
catch
{
// If the extraction fails just return the original file, it could be a gz
return file;
}
return _fileSystem.GetFiles(tempFolder, true) try
.Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase)) {
.Select(i => i.FullName) var tempFolder = ExtractFirstFileFromGz(file);
.FirstOrDefault(); return FindXmlFile(tempFolder);
}
catch (Exception ex)
{
//_logger.ErrorException("Error extracting from zip file {0}", ex, file);
} }
} }
return file; return file;
} }
private string ExtractFirstFileFromGz(string file)
{
using (var stream = _fileSystem.OpenRead(file))
{
var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString());
_fileSystem.CreateDirectory(tempFolder);
_zipClient.ExtractFirstFileFromGz(stream, tempFolder, "data.xml");
return tempFolder;
}
}
private string ExtractGz(string file)
{
using (var stream = _fileSystem.OpenRead(file))
{
var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString());
_fileSystem.CreateDirectory(tempFolder);
_zipClient.ExtractAllFromGz(stream, tempFolder, true);
return tempFolder;
}
}
private string FindXmlFile(string directory)
{
return _fileSystem.GetFiles(directory, true)
.Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase))
.Select(i => i.FullName)
.FirstOrDefault();
}
public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
{ {
if (string.IsNullOrWhiteSpace(channelId)) if (string.IsNullOrWhiteSpace(channelId))
@ -149,6 +182,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
_logger.Debug("Getting xmltv programs for channel {0}", channelId); _logger.Debug("Getting xmltv programs for channel {0}", channelId);
var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false);
_logger.Debug("Opening XmlTvReader for {0}", path);
var reader = new XmlTvReader(path, GetLanguage(info)); var reader = new XmlTvReader(path, GetLanguage(info));
var results = reader.GetProgrammes(channelId, startDateUtc, endDateUtc, cancellationToken); var results = reader.GetProgrammes(channelId, startDateUtc, endDateUtc, cancellationToken);
@ -251,6 +285,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
{ {
// In theory this should never be called because there is always only one lineup // In theory this should never be called because there is always only one lineup
var path = await GetXml(info.Path, CancellationToken.None).ConfigureAwait(false); var path = await GetXml(info.Path, CancellationToken.None).ConfigureAwait(false);
_logger.Debug("Opening XmlTvReader for {0}", path);
var reader = new XmlTvReader(path, GetLanguage(info)); var reader = new XmlTvReader(path, GetLanguage(info));
var results = reader.GetChannels(); var results = reader.GetChannels();
@ -262,6 +297,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
{ {
// In theory this should never be called because there is always only one lineup // In theory this should never be called because there is always only one lineup
var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false);
_logger.Debug("Opening XmlTvReader for {0}", path);
var reader = new XmlTvReader(path, GetLanguage(info)); var reader = new XmlTvReader(path, GetLanguage(info));
var results = reader.GetChannels(); var results = reader.GetChannels();

@ -125,7 +125,7 @@ namespace Emby.Server.Implementations.LiveTv
public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders) public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders)
{ {
_services = services.ToArray(); _services = services.ToArray();
_tunerHosts.AddRange(tunerHosts); _tunerHosts.AddRange(tunerHosts.Where(i => i.IsSupported));
_listingProviders.AddRange(listingProviders); _listingProviders.AddRange(listingProviders);
foreach (var service in _services) foreach (var service in _services)
@ -947,6 +947,7 @@ namespace Emby.Server.Implementations.LiveTv
IsKids = query.IsKids, IsKids = query.IsKids,
IsNews = query.IsNews, IsNews = query.IsNews,
Genres = query.Genres, Genres = query.Genres,
GenreIds = query.GenreIds,
StartIndex = query.StartIndex, StartIndex = query.StartIndex,
Limit = query.Limit, Limit = query.Limit,
OrderBy = query.OrderBy, OrderBy = query.OrderBy,
@ -1020,7 +1021,8 @@ namespace Emby.Server.Implementations.LiveTv
EnableTotalRecordCount = query.EnableTotalRecordCount, EnableTotalRecordCount = query.EnableTotalRecordCount,
OrderBy = new[] { new Tuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending) }, OrderBy = new[] { new Tuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending) },
TopParentIds = new[] { topFolder.Id.ToString("N") }, TopParentIds = new[] { topFolder.Id.ToString("N") },
DtoOptions = options DtoOptions = options,
GenreIds = query.GenreIds
}; };
if (query.Limit.HasValue) if (query.Limit.HasValue)
@ -1421,7 +1423,7 @@ namespace Emby.Server.Implementations.LiveTv
if (newPrograms.Count > 0) if (newPrograms.Count > 0)
{ {
_libraryManager.CreateItems(newPrograms, cancellationToken); _libraryManager.CreateItems(newPrograms, null, cancellationToken);
} }
// TODO: Do this in bulk // TODO: Do this in bulk

@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.LiveTv
} }
var list = sources.ToList(); var list = sources.ToList();
var serverUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false); var serverUrl = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
foreach (var source in list) foreach (var source in list)
{ {

@ -39,6 +39,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
FileSystem = fileSystem; FileSystem = fileSystem;
} }
public virtual bool IsSupported
{
get
{
return true;
}
}
protected abstract Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken); protected abstract Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken);
public abstract string Type { get; } public abstract string Type { get; }

@ -17,6 +17,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;
using System.IO;
namespace Emby.Server.Implementations.LiveTv.TunerHosts namespace Emby.Server.Implementations.LiveTv.TunerHosts
{ {
@ -75,6 +76,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return Task.FromResult(list); return Task.FromResult(list);
} }
private string[] _disallowedSharedStreamExtensions = new string[]
{
".mkv",
".mp4",
".m3u8",
".mpd"
};
protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken) protected override async Task<ILiveStream> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken)
{ {
var tunerCount = info.TunerCount; var tunerCount = info.TunerCount;
@ -95,7 +104,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
if (mediaSource.Protocol == MediaProtocol.Http && !mediaSource.RequiresLooping) if (mediaSource.Protocol == MediaProtocol.Http && !mediaSource.RequiresLooping)
{ {
return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _environment); var extension = Path.GetExtension(mediaSource.Path) ?? string.Empty;
if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{
return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _environment);
}
} }
return new LiveStream(mediaSource, info, _environment, FileSystem, Logger, Config.ApplicationPaths); return new LiveStream(mediaSource, info, _environment, FileSystem, Logger, Config.ApplicationPaths);
@ -152,6 +166,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
isRemote = !_networkManager.IsInLocalNetwork(uri.Host); isRemote = !_networkManager.IsInLocalNetwork(uri.Host);
} }
var supportsDirectPlay = !info.EnableStreamLooping && info.TunerCount == 0;
var mediaSource = new MediaSourceInfo var mediaSource = new MediaSourceInfo
{ {
Path = path, Path = path,
@ -183,7 +199,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
IsInfiniteStream = true, IsInfiniteStream = true,
IsRemote = isRemote, IsRemote = isRemote,
IgnoreDts = true IgnoreDts = true,
SupportsDirectPlay = supportsDirectPlay
}; };
mediaSource.InferTotalBitrate(); mediaSource.InferTotalBitrate();

@ -71,7 +71,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
} }
else if (contentType.IndexOf("mp4", StringComparison.OrdinalIgnoreCase) != -1 || else if (contentType.IndexOf("mp4", StringComparison.OrdinalIgnoreCase) != -1 ||
contentType.IndexOf("dash", StringComparison.OrdinalIgnoreCase) != -1 || contentType.IndexOf("dash", StringComparison.OrdinalIgnoreCase) != -1 ||
contentType.IndexOf("mpegURL", StringComparison.OrdinalIgnoreCase) != -1) contentType.IndexOf("mpegURL", StringComparison.OrdinalIgnoreCase) != -1 ||
contentType.IndexOf("text/", StringComparison.OrdinalIgnoreCase) != -1)
{ {
requiresRemux = true; requiresRemux = true;
} }
@ -88,6 +89,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
SetTempFilePath(extension); SetTempFilePath(extension);
var taskCompletionSource = new TaskCompletionSource<bool>(); var taskCompletionSource = new TaskCompletionSource<bool>();
var now = DateTime.UtcNow;
StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token);
//OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.Protocol = MediaProtocol.File;
@ -97,11 +101,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
OpenedMediaSource.Protocol = MediaProtocol.Http; OpenedMediaSource.Protocol = MediaProtocol.Http;
if (OpenedMediaSource.SupportsProbing)
{
await Task.Delay(3000).ConfigureAwait(false);
}
//OpenedMediaSource.Path = TempFilePath; //OpenedMediaSource.Path = TempFilePath;
//OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.Protocol = MediaProtocol.File;
@ -111,6 +110,20 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
//OpenedMediaSource.SupportsDirectStream = true; //OpenedMediaSource.SupportsDirectStream = true;
//OpenedMediaSource.SupportsTranscoding = true; //OpenedMediaSource.SupportsTranscoding = true;
await taskCompletionSource.Task.ConfigureAwait(false); await taskCompletionSource.Task.ConfigureAwait(false);
if (OpenedMediaSource.SupportsProbing)
{
var elapsed = (DateTime.UtcNow - now).TotalMilliseconds;
var delay = Convert.ToInt32(3000 - elapsed);
if (delay > 0)
{
Logger.Info("Delaying shared stream by {0}ms to allow the buffer to build.", delay);
await Task.Delay(delay).ConfigureAwait(false);
}
}
} }
protected override void CloseInternal() protected override void CloseInternal()

@ -1,74 +1,74 @@
{ {
"Latest": "Darreres", "Latest": "Darreres",
"ValueSpecialEpisodeName": "Especial - {0}", "ValueSpecialEpisodeName": "Especial - {0}",
"Inherit": "Inherit", "Inherit": "Heretat",
"Books": "Books", "Books": "Llibres",
"Music": "Music", "Music": "M\u00fasica",
"Games": "Games", "Games": "Jocs",
"Photos": "Photos", "Photos": "Fotos",
"MixedContent": "Mixed content", "MixedContent": "Contingut mesclat",
"MusicVideos": "Music videos", "MusicVideos": "V\u00eddeos musicals",
"HomeVideos": "Home videos", "HomeVideos": "V\u00eddeos dom\u00e8stics",
"Playlists": "Playlists", "Playlists": "Llistes de reproducci\u00f3",
"HeaderRecordingGroups": "Recording Groups", "HeaderRecordingGroups": "Grups d'Enregistrament",
"HeaderContinueWatching": "Continua Veient", "HeaderContinueWatching": "Continua Veient",
"HeaderFavoriteArtists": "Favorite Artists", "HeaderFavoriteArtists": "Artistes Preferits",
"HeaderFavoriteSongs": "Favorite Songs", "HeaderFavoriteSongs": "Can\u00e7ons Preferides",
"HeaderAlbumArtists": "Album Artists", "HeaderAlbumArtists": "Album Artists",
"HeaderFavoriteAlbums": "Favorite Albums", "HeaderFavoriteAlbums": "\u00c0lbums Preferits",
"HeaderFavoriteEpisodes": "Favorite Episodes", "HeaderFavoriteEpisodes": "Episodis Preferits",
"HeaderFavoriteShows": "Programes Preferits", "HeaderFavoriteShows": "Programes Preferits",
"HeaderNextUp": "A continuaci\u00f3", "HeaderNextUp": "A continuaci\u00f3",
"Favorites": "Favorites", "Favorites": "Preferits",
"Collections": "Collections", "Collections": "Col\u00b7leccions",
"Channels": "Channels", "Channels": "Canals",
"Movies": "Movies", "Movies": "Pel\u00b7l\u00edcules",
"Albums": "Albums", "Albums": "\u00c0lbums",
"Artists": "Artists", "Artists": "Artistes",
"Folders": "Folders", "Folders": "Directoris",
"Songs": "Songs", "Songs": "Can\u00e7ons",
"TvShows": "TV Shows", "TvShows": "Espectacles de TV",
"Shows": "Shows", "Shows": "Espectacles",
"Genres": "G\u00e8neres", "Genres": "G\u00e8neres",
"NameSeasonNumber": "Season {0}", "NameSeasonNumber": "Temporada {0}",
"AppDeviceValues": "App: {0}, Device: {1}", "AppDeviceValues": "App: {0}, Dispositiu: {1}",
"UserDownloadingItemWithValues": "{0} is downloading {1}", "UserDownloadingItemWithValues": "{0} est\u00e0 descarregant {1}",
"HeaderLiveTV": "Live TV", "HeaderLiveTV": "TV en Directe",
"ChapterNameValue": "Chapter {0}", "ChapterNameValue": "Episodi {0}",
"ScheduledTaskFailedWithName": "{0} failed", "ScheduledTaskFailedWithName": "{0} ha fallat",
"LabelRunningTimeValue": "Running time: {0}", "LabelRunningTimeValue": "Temps en marxa: {0}",
"ScheduledTaskStartedWithName": "{0} started", "ScheduledTaskStartedWithName": "{0} iniciat",
"VersionNumber": "Version {0}", "VersionNumber": "Versi\u00f3 {0}",
"PluginInstalledWithName": "{0} was installed", "PluginInstalledWithName": "{0} ha estat instal\u00b7lat",
"StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly.", "StartupEmbyServerIsLoading": "El Servidor d'Emby est&agrave; carregant. Si et plau, prova de nou en breus.",
"PluginUpdatedWithName": "{0} was updated", "PluginUpdatedWithName": "{0} ha estat actualitzat",
"PluginUninstalledWithName": "{0} was uninstalled", "PluginUninstalledWithName": "{0} ha estat desinstal\u00b7lat",
"ItemAddedWithName": "{0} was added to the library", "ItemAddedWithName": "{0} afegit a la biblioteca",
"ItemRemovedWithName": "{0} was removed from the library", "ItemRemovedWithName": "{0} eliminat de la biblioteca",
"LabelIpAddressValue": "Ip address: {0}", "LabelIpAddressValue": "Adre\u00e7a IP: {0}",
"DeviceOnlineWithName": "{0} is connected", "DeviceOnlineWithName": "{0} est\u00e0 connectat",
"UserOnlineFromDevice": "{0} is online from {1}", "UserOnlineFromDevice": "{0} est\u00e0 connectat des de {1}",
"ProviderValue": "Provider: {0}", "ProviderValue": "Prove\u00efdor: {0}",
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", "SubtitlesDownloadedForItem": "Subt\u00edtols descarregats per a {0}",
"UserCreatedWithName": "User {0} has been created", "UserCreatedWithName": "S'ha creat l'usuari {0}",
"UserPasswordChangedWithName": "Password has been changed for user {0}", "UserPasswordChangedWithName": "La contrasenya ha estat canviada per a l'usuari {0}",
"UserDeletedWithName": "User {0} has been deleted", "UserDeletedWithName": "L'usuari {0} ha estat eliminat",
"UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", "UserConfigurationUpdatedWithName": "La configuraci\u00f3 d'usuari ha estat actualitzada per a {0}",
"MessageServerConfigurationUpdated": "Server configuration has been updated", "MessageServerConfigurationUpdated": "S'ha actualitzat la configuraci\u00f3 del servidor",
"MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", "MessageNamedServerConfigurationUpdatedWithValue": "La secci\u00f3 de configuraci\u00f3 {0} ha estat actualitzada",
"MessageApplicationUpdated": "Emby Server has been updated", "MessageApplicationUpdated": "El Servidor d'Emby ha estat actualitzat",
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "FailedLoginAttemptWithUserName": "Intent de connexi\u00f3 fallit des de {0}",
"AuthenticationSucceededWithUserName": "{0} successfully authenticated", "AuthenticationSucceededWithUserName": "{0} s'ha autenticat correctament",
"UserOfflineFromDevice": "{0} has disconnected from {1}", "UserOfflineFromDevice": "{0} s'ha desconnectat de {1}",
"DeviceOfflineWithName": "{0} has disconnected", "DeviceOfflineWithName": "{0} s'ha desconnectat",
"UserStartedPlayingItemWithValues": "{0} has started playing {1}", "UserStartedPlayingItemWithValues": "{0} ha comen\u00e7at a reproduir {1}",
"UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", "UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1}",
"NotificationOptionPluginError": "Plugin failure", "NotificationOptionPluginError": "Un component ha fallat",
"NotificationOptionApplicationUpdateAvailable": "Application update available", "NotificationOptionApplicationUpdateAvailable": "Actualitzaci\u00f3 d'aplicaci\u00f3 disponible",
"NotificationOptionApplicationUpdateInstalled": "Application update installed", "NotificationOptionApplicationUpdateInstalled": "Actualitzaci\u00f3 d'aplicaci\u00f3 instal\u00b7lada",
"NotificationOptionPluginUpdateInstalled": "Plugin update installed", "NotificationOptionPluginUpdateInstalled": "Actualitzaci\u00f3 de complement instal\u00b7lada",
"NotificationOptionPluginInstalled": "Plugin installed", "NotificationOptionPluginInstalled": "Complement instal\u00b7lat",
"NotificationOptionPluginUninstalled": "Plugin uninstalled", "NotificationOptionPluginUninstalled": "Complement desinstal\u00b7lat",
"NotificationOptionVideoPlayback": "Video playback started", "NotificationOptionVideoPlayback": "Video playback started",
"NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionGamePlayback": "Game playback started", "NotificationOptionGamePlayback": "Game playback started",

@ -7,7 +7,7 @@
"Games": "Spiele", "Games": "Spiele",
"Photos": "Fotos", "Photos": "Fotos",
"MixedContent": "Gemischte Inhalte", "MixedContent": "Gemischte Inhalte",
"MusicVideos": "Musik-Videos", "MusicVideos": "Musikvideos",
"HomeVideos": "Heimvideos", "HomeVideos": "Heimvideos",
"Playlists": "Wiedergabelisten", "Playlists": "Wiedergabelisten",
"HeaderRecordingGroups": "Aufnahme-Gruppen", "HeaderRecordingGroups": "Aufnahme-Gruppen",
@ -27,7 +27,7 @@
"Artists": "Interpreten", "Artists": "Interpreten",
"Folders": "Verzeichnisse", "Folders": "Verzeichnisse",
"Songs": "Songs", "Songs": "Songs",
"TvShows": "TV Shows", "TvShows": "TV Sendungen",
"Shows": "Serien", "Shows": "Serien",
"Genres": "Genres", "Genres": "Genres",
"NameSeasonNumber": "Staffel {0}", "NameSeasonNumber": "Staffel {0}",

@ -0,0 +1,91 @@
{
"Latest": "\u03a4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03b1",
"ValueSpecialEpisodeName": "\u0395\u03b9\u03b4\u03b9\u03ba\u03ac - {0} ",
"Inherit": "Inherit",
"Books": "\u0392\u03b9\u03b2\u03bb\u03af\u03b1",
"Music": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae",
"Games": "\u03a0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9\u03b1",
"Photos": "\u03a6\u03c9\u03c4\u03bf\u03b3\u03c1\u03b1\u03c6\u03af\u03b5\u03c2",
"MixedContent": "\u0391\u03bd\u03ac\u03bc\u03b5\u03b9\u03ba\u03c4\u03bf \u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03bf",
"MusicVideos": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ac \u03b2\u03af\u03bd\u03c4\u03b5\u03bf",
"HomeVideos": "\u03a0\u03c1\u03bf\u03c3\u03c9\u03c0\u03b9\u03ba\u03ac \u0392\u03af\u03bd\u03c4\u03b5\u03bf",
"Playlists": "\u039b\u03af\u03c3\u03c4\u03b5\u03c2 \u03b1\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2",
"HeaderRecordingGroups": "\u0393\u03ba\u03c1\u03bf\u03c5\u03c0 \u0395\u03b3\u03b3\u03c1\u03b1\u03c6\u03ce\u03bd",
"HeaderContinueWatching": "\u03a3\u03c5\u03bd\u03b5\u03c7\u03af\u03c3\u03c4\u03b5 \u03c4\u03b7\u03bd \u03c0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03cd\u03b8\u03b7\u03c3\u03b7",
"HeaderFavoriteArtists": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03bf\u03b9 \u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03ad\u03c7\u03bd\u03b5\u03c2",
"HeaderFavoriteSongs": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b1 \u03a4\u03c1\u03b1\u03b3\u03bf\u03cd\u03b4\u03b9\u03b1",
"HeaderAlbumArtists": "\u0386\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc \u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03b5\u03c7\u03bd\u03ce\u03bd",
"HeaderFavoriteAlbums": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b1 \u0386\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc",
"HeaderFavoriteEpisodes": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b1 \u03b5\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
"HeaderFavoriteShows": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b5\u03c2 \u03a3\u03b5\u03b9\u03c1\u03ad\u03c2",
"HeaderNextUp": "\u0395\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf",
"Favorites": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b1",
"Collections": "\u03a3\u03c5\u03bb\u03bb\u03bf\u03b3\u03ad\u03c2",
"Channels": "\u039a\u03b1\u03bd\u03ac\u03bb\u03b9\u03b1",
"Movies": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2",
"Albums": "\u0386\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc",
"Artists": "\u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03ad\u03c7\u03bd\u03b5\u03c2",
"Folders": "\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03b9",
"Songs": "\u03a4\u03c1\u03b1\u03b3\u03bf\u03cd\u03b4\u03b9\u03b1",
"TvShows": "\u03a4\u03b7\u03bb\u03b5\u03bf\u03c0\u03c4\u03b9\u03ba\u03ac \u03c0\u03c1\u03bf\u03b3\u03c1\u03ac\u03bc\u03bc\u03b1\u03c4\u03b1",
"Shows": "\u03a3\u03b5\u03b9\u03c1\u03ad\u03c2",
"Genres": "\u0395\u03af\u03b4\u03b7",
"NameSeasonNumber": "\u039a\u03cd\u03ba\u03bb\u03bf\u03c2 {0}",
"AppDeviceValues": "\u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae: {0}, \u03a3\u03c5\u03c3\u03ba\u03b5\u03c5\u03ae: {1}",
"UserDownloadingItemWithValues": "{0} \u03ba\u03b1\u03c4\u03b5\u03b2\u03ac\u03b6\u03b5\u03b9 {1}",
"HeaderLiveTV": "\u0396\u03c9\u03bd\u03c4\u03b1\u03bd\u03ae \u03a4\u03b7\u03bb\u03b5\u03cc\u03c1\u03b1\u03c3\u03b7",
"ChapterNameValue": "\u039a\u03b5\u03c6\u03ac\u03bb\u03b1\u03b9\u03bf {0}",
"ScheduledTaskFailedWithName": "{0} \u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1",
"LabelRunningTimeValue": "\u0394\u03b9\u03ac\u03c1\u03ba\u03b5\u03b9\u03b1: {0}",
"ScheduledTaskStartedWithName": "{0} \u03ad\u03bd\u03b1\u03c1\u03be\u03b7",
"VersionNumber": "\u0388\u03ba\u03b4\u03bf\u03c3\u03b7 {0}",
"PluginInstalledWithName": "{0} \u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03ae\u03b8\u03b7\u03ba\u03b5",
"StartupEmbyServerIsLoading": "\u039f \u03a3\u03ad\u03c1\u03b2\u03b5\u03c1 \u03c6\u03bf\u03c1\u03c4\u03ce\u03bd\u03b5\u03b9. \u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03ce \u03b4\u03bf\u03ba\u03b9\u03bc\u03ac\u03c3\u03c4\u03b5 \u03c3\u03b5 \u03bb\u03af\u03b3\u03bf",
"PluginUpdatedWithName": "{0} \u03ad\u03c7\u03b5\u03b9 \u03b1\u03bd\u03b1\u03b2\u03b1\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af",
"PluginUninstalledWithName": "{0} \u03ad\u03c7\u03b5\u03b9 \u03b1\u03c0\u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03b1\u03b8\u03b5\u03af",
"ItemAddedWithName": "{0} \u03c0\u03c1\u03bf\u03c3\u03c4\u03ad\u03b8\u03b7\u03ba\u03b5 \u03c3\u03c4\u03b7 \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7",
"ItemRemovedWithName": "{0} \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c6\u03b7\u03ba\u03b5 \u03b1\u03c0\u03cc \u03c4\u03b7 \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7",
"LabelIpAddressValue": "\u0394\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 IP: {0}",
"DeviceOnlineWithName": "{0} \u03c3\u03c5\u03bd\u03b4\u03ad\u03b8\u03b7\u03ba\u03b5",
"UserOnlineFromDevice": "{0} \u03b5\u03af\u03bd\u03b1\u03b9 \u03c3\u03c5\u03bd\u03b4\u03b5\u03b4\u03b5\u03bc\u03ad\u03bd\u03bf\u03c2 \u03b1\u03c0\u03bf {1}",
"ProviderValue": "\u03a0\u03ac\u03c1\u03bf\u03c7\u03bf\u03c2: {0}",
"SubtitlesDownloadedForItem": "\u03a5\u03c0\u03cc\u03c4\u03b9\u03c4\u03bb\u03bf\u03b9 \u03bb\u03ae\u03c6\u03b8\u03b7\u03ba\u03b1\u03bd \u03b1\u03c0\u03cc {0}",
"UserCreatedWithName": "\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03b8\u03b7\u03ba\u03b5 \u03bf \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2 {0}",
"UserPasswordChangedWithName": "\u039f \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c4\u03bf\u03c5 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7 {0} \u03b1\u03bb\u03bb\u03ac\u03c7\u03b8\u03b7\u03ba\u03b5",
"UserDeletedWithName": "\u039f \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2 {0} \u03b4\u03b9\u03b5\u03b3\u03c1\u03ac\u03c6\u03b5\u03b9",
"UserConfigurationUpdatedWithName": "\u039f\u03b9 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u03c4\u03bf\u03c5 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7 {0} \u03ad\u03c7\u03bf\u03c5\u03bd \u03b1\u03bb\u03bb\u03ac\u03be\u03b5\u03b9",
"MessageServerConfigurationUpdated": "Server configuration has been updated",
"MessageNamedServerConfigurationUpdatedWithValue": "\u039f\u03b9 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u03c4\u03bf\u03bc\u03ad\u03b1 \u03c4\u03bf\u03c5 \u03b4\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae {0} \u03ad\u03c7\u03bf\u03c5\u03bd \u03b1\u03bb\u03bb\u03ac\u03be\u03b5\u03b9",
"MessageApplicationUpdated": "\u039f \u03a3\u03ad\u03c1\u03b2\u03b5\u03c1 \u03ad\u03c7\u03b5\u03b9 \u03b1\u03bd\u03b1\u03b2\u03b1\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af",
"FailedLoginAttemptWithUserName": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b5\u03b9\u03b1 \u03b5\u03b9\u03c3\u03cc\u03b4\u03bf\u03c5 \u03b1\u03c0\u03cc {0}",
"AuthenticationSucceededWithUserName": "{0} \u03b5\u03c0\u03b9\u03c4\u03c5\u03c7\u03b5\u03af\u03c2 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7",
"UserOfflineFromDevice": "{0} \u03b1\u03c0\u03bf\u03c3\u03c5\u03bd\u03b4\u03ad\u03b8\u03b7\u03ba\u03b5 \u03b1\u03c0\u03cc {1}",
"DeviceOfflineWithName": "{0} \u03b1\u03c0\u03bf\u03c3\u03c5\u03bd\u03b4\u03ad\u03b8\u03b7\u03ba\u03b5",
"UserStartedPlayingItemWithValues": "{0} \u03be\u03b5\u03ba\u03af\u03bd\u03b7\u03c3\u03b5 \u03bd\u03b1 \u03c0\u03b1\u03af\u03b6\u03b5\u03b9 {1}",
"UserStoppedPlayingItemWithValues": "{0} \u03c3\u03c4\u03b1\u03bc\u03ac\u03c4\u03b7\u03c3\u03b5 \u03bd\u03b1 \u03c0\u03b1\u03af\u03b6\u03b5\u03b9 {1}",
"NotificationOptionPluginError": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c0\u03c1\u03bf\u03c3\u03b8\u03ad\u03c4\u03bf\u03c5",
"NotificationOptionApplicationUpdateAvailable": "\u03a5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03b1\u03bd\u03b1\u03b2\u03ac\u03b8\u03bc\u03b9\u03c3\u03b7",
"NotificationOptionApplicationUpdateInstalled": "\u0397 \u03b1\u03bd\u03b1\u03b2\u03ac\u03b8\u03bc\u03b9\u03c3\u03b7 \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5",
"NotificationOptionPluginUpdateInstalled": "\u0397 \u03b1\u03bd\u03b1\u03b2\u03ac\u03b8\u03bc\u03b9\u03c3\u03b7 \u03c4\u03bf\u03c5 plugin \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5",
"NotificationOptionPluginInstalled": "\u03a4\u03bf plugin \u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03ac\u03b8\u03b7\u03ba\u03b5",
"NotificationOptionPluginUninstalled": "\u03a4\u03bf plugin \u03b1\u03c0\u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03ac\u03b8\u03b7\u03ba\u03b5",
"NotificationOptionVideoPlayback": "\u03a4\u03bf \u03b2\u03af\u03bd\u03c4\u03b5\u03bf \u03c0\u03c1\u03bf\u03b2\u03ac\u03bb\u03bb\u03b5\u03c4\u03b1\u03b9",
"NotificationOptionAudioPlayback": "\u0397 \u03bc\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae \u03c0\u03b1\u03af\u03b6\u03b5\u03b9",
"NotificationOptionGamePlayback": "\u03a4\u03bf \u03c0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9 \u03be\u03b5\u03ba\u03af\u03bd\u03b7\u03c3\u03b5",
"NotificationOptionVideoPlaybackStopped": "\u03a4\u03bf \u03b2\u03af\u03bd\u03c4\u03b5\u03bf \u03c3\u03c4\u03b1\u03bc\u03ac\u03c4\u03b7\u03c3\u03b5",
"NotificationOptionAudioPlaybackStopped": "\u0397 \u03bc\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae \u03c3\u03c4\u03b1\u03bc\u03ac\u03c4\u03b7\u03c3\u03b5",
"NotificationOptionGamePlaybackStopped": "\u03a4\u03bf \u03c0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9 \u03c3\u03c4\u03b1\u03bc\u03ac\u03c4\u03b7\u03c3\u03b5",
"NotificationOptionTaskFailed": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c0\u03c1\u03bf\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03ad\u03bd\u03b7\u03c2 \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1\u03c2",
"NotificationOptionInstallationFailed": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03b5\u03b3\u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7\u03c2",
"NotificationOptionNewLibraryContent": "\u03a0\u03c1\u03bf\u03c3\u03c4\u03ad\u03b8\u03b7\u03ba\u03b5 \u03bd\u03ad\u03bf \u03c0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03bf",
"NotificationOptionCameraImageUploaded": "Camera image uploaded",
"NotificationOptionUserLockedOut": "\u039f \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2 \u03b1\u03c0\u03bf\u03ba\u03bb\u03b5\u03af\u03c3\u03c4\u03b7\u03ba\u03b5",
"NotificationOptionServerRestartRequired": "\u0391\u03c0\u03b1\u03b9\u03c4\u03b5\u03af\u03c4\u03b1\u03b9 \u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03b4\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae",
"UserLockedOutWithName": "\u039f \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2 {0} \u03b1\u03c0\u03bf\u03ba\u03bb\u03b5\u03af\u03c3\u03c4\u03b7\u03ba\u03b5",
"SubtitleDownloadFailureForItem": "\u0391\u03b4\u03c5\u03bd\u03b1\u03bc\u03af\u03b1 \u03bb\u03ae\u03c8\u03b7\u03c2 \u03c5\u03c0\u03bf\u03c4\u03af\u03c4\u03bb\u03c9\u03bd \u03b1\u03c0\u03cc {0}",
"Sync": "\u03a3\u03c5\u03b3\u03c7\u03c1\u03bf\u03bd\u03b9\u03c3\u03bc\u03cc\u03c2",
"User": "\u03a7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2",
"System": "\u03a3\u03cd\u03c3\u03c4\u03b7\u03bc\u03b1",
"Application": "\u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae",
"Plugin": "\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf"
}

@ -83,7 +83,7 @@
"NotificationOptionServerRestartRequired": "Se necesita reiniciar el Servidor", "NotificationOptionServerRestartRequired": "Se necesita reiniciar el Servidor",
"UserLockedOutWithName": "El usuario {0} ha sido bloqueado", "UserLockedOutWithName": "El usuario {0} ha sido bloqueado",
"SubtitleDownloadFailureForItem": "Fall\u00f3 la descarga de subt\u00edtulos para {0}", "SubtitleDownloadFailureForItem": "Fall\u00f3 la descarga de subt\u00edtulos para {0}",
"Sync": "Sinc.", "Sync": "Sincronizar",
"User": "Usuario", "User": "Usuario",
"System": "Sistema", "System": "Sistema",
"Application": "Aplicaci\u00f3n", "Application": "Aplicaci\u00f3n",

@ -0,0 +1,91 @@
{
"Latest": "Letschte",
"ValueSpecialEpisodeName": "Spezial - {0}",
"Inherit": "Hinzuef\u00fcege",
"Books": "B\u00fcecher",
"Music": "Musig",
"Games": "Spiel",
"Photos": "Fotis",
"MixedContent": "Gmischte Inhalt",
"MusicVideos": "Musigfilm",
"HomeVideos": "Heimfilmli",
"Playlists": "Abspielliste",
"HeaderRecordingGroups": "Ufnahmegruppe",
"HeaderContinueWatching": "Wiiterluege",
"HeaderFavoriteArtists": "Besti Interpret",
"HeaderFavoriteSongs": "Besti Lieder",
"HeaderAlbumArtists": "Albuminterprete",
"HeaderFavoriteAlbums": "Favorite Albums",
"HeaderFavoriteEpisodes": "Favorite Episodes",
"HeaderFavoriteShows": "Favorite Shows",
"HeaderNextUp": "Next Up",
"Favorites": "Favorites",
"Collections": "Collections",
"Channels": "Channels",
"Movies": "Movies",
"Albums": "Albums",
"Artists": "Artists",
"Folders": "Folders",
"Songs": "Songs",
"TvShows": "TV Shows",
"Shows": "Shows",
"Genres": "Genres",
"NameSeasonNumber": "Season {0}",
"AppDeviceValues": "App: {0}, Device: {1}",
"UserDownloadingItemWithValues": "{0} is downloading {1}",
"HeaderLiveTV": "Live TV",
"ChapterNameValue": "Chapter {0}",
"ScheduledTaskFailedWithName": "{0} failed",
"LabelRunningTimeValue": "Running time: {0}",
"ScheduledTaskStartedWithName": "{0} started",
"VersionNumber": "Version {0}",
"PluginInstalledWithName": "{0} was installed",
"StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly.",
"PluginUpdatedWithName": "{0} was updated",
"PluginUninstalledWithName": "{0} was uninstalled",
"ItemAddedWithName": "{0} was added to the library",
"ItemRemovedWithName": "{0} was removed from the library",
"LabelIpAddressValue": "Ip address: {0}",
"DeviceOnlineWithName": "{0} is connected",
"UserOnlineFromDevice": "{0} is online from {1}",
"ProviderValue": "Provider: {0}",
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
"UserCreatedWithName": "User {0} has been created",
"UserPasswordChangedWithName": "Password has been changed for user {0}",
"UserDeletedWithName": "User {0} has been deleted",
"UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
"MessageServerConfigurationUpdated": "Server configuration has been updated",
"MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
"MessageApplicationUpdated": "Emby Server has been updated",
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
"AuthenticationSucceededWithUserName": "{0} successfully authenticated",
"UserOfflineFromDevice": "{0} has disconnected from {1}",
"DeviceOfflineWithName": "{0} has disconnected",
"UserStartedPlayingItemWithValues": "{0} has started playing {1}",
"UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
"NotificationOptionPluginError": "Plugin failure",
"NotificationOptionApplicationUpdateAvailable": "Application update available",
"NotificationOptionApplicationUpdateInstalled": "Application update installed",
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
"NotificationOptionPluginInstalled": "Plugin installed",
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
"NotificationOptionVideoPlayback": "Video playback started",
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionGamePlayback": "Game playback started",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionInstallationFailed": "Installation failure",
"NotificationOptionNewLibraryContent": "New content added",
"NotificationOptionCameraImageUploaded": "Camera image uploaded",
"NotificationOptionUserLockedOut": "User locked out",
"NotificationOptionServerRestartRequired": "Server restart required",
"UserLockedOutWithName": "User {0} has been locked out",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"Sync": "Sync",
"User": "User",
"System": "System",
"Application": "Application",
"Plugin": "Plugin"
}

@ -27,7 +27,7 @@
"Artists": "Artistas", "Artists": "Artistas",
"Folders": "Pastas", "Folders": "Pastas",
"Songs": "M\u00fasicas", "Songs": "M\u00fasicas",
"TvShows": "TV Shows", "TvShows": "S\u00e9ries de TV",
"Shows": "S\u00e9ries", "Shows": "S\u00e9ries",
"Genres": "G\u00eaneros", "Genres": "G\u00eaneros",
"NameSeasonNumber": "Temporada {0}", "NameSeasonNumber": "Temporada {0}",

@ -76,6 +76,21 @@ namespace Emby.Server.Implementations.MediaEncoder
return false; return false;
} }
if (video.VideoType == VideoType.Iso)
{
return false;
}
if (video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd)
{
return false;
}
if (video.IsShortcut)
{
return false;
}
if (!video.IsCompleteMedia) if (!video.IsCompleteMedia)
{ {
return false; return false;
@ -118,16 +133,6 @@ namespace Emby.Server.Implementations.MediaEncoder
{ {
if (extractImages) if (extractImages)
{ {
if (video.VideoType == VideoType.Iso)
{
continue;
}
if (video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd)
{
continue;
}
try try
{ {
// Add some time for the first chapter to make sure we don't end up with a black image // Add some time for the first chapter to make sure we don't end up with a black image

@ -17,11 +17,54 @@ namespace Emby.Server.Implementations.Networking
public class NetworkManager : INetworkManager public class NetworkManager : INetworkManager
{ {
protected ILogger Logger { get; private set; } protected ILogger Logger { get; private set; }
private DateTime _lastRefresh;
public event EventHandler NetworkChanged;
public NetworkManager(ILogger logger) public NetworkManager(ILogger logger)
{ {
Logger = logger; Logger = logger;
try
{
NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;
}
catch (Exception ex)
{
Logger.ErrorException("Error binding to NetworkAddressChanged event", ex);
}
try
{
NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged;
}
catch (Exception ex)
{
Logger.ErrorException("Error binding to NetworkChange_NetworkAvailabilityChanged event", ex);
}
}
private void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
Logger.Debug("NetworkAvailabilityChanged");
OnNetworkChanged();
}
private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
{
Logger.Debug("NetworkAddressChanged");
OnNetworkChanged();
}
private void OnNetworkChanged()
{
lock (_localIpAddressSyncLock)
{
_localIpAddresses = null;
}
if (NetworkChanged != null)
{
NetworkChanged(this, EventArgs.Empty);
}
} }
private List<IpAddressInfo> _localIpAddresses; private List<IpAddressInfo> _localIpAddresses;
@ -29,34 +72,28 @@ namespace Emby.Server.Implementations.Networking
public List<IpAddressInfo> GetLocalIpAddresses() public List<IpAddressInfo> GetLocalIpAddresses()
{ {
const int cacheMinutes = 10;
lock (_localIpAddressSyncLock) lock (_localIpAddressSyncLock)
{ {
var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes; if (_localIpAddresses == null)
if (_localIpAddresses == null || forceRefresh)
{ {
var addresses = GetLocalIpAddressesInternal().Select(ToIpAddressInfo).ToList(); var addresses = GetLocalIpAddressesInternal().Result.Select(ToIpAddressInfo).ToList();
_localIpAddresses = addresses; _localIpAddresses = addresses;
_lastRefresh = DateTime.UtcNow;
return addresses; return addresses;
} }
return _localIpAddresses;
} }
return _localIpAddresses;
} }
private IEnumerable<IPAddress> GetLocalIpAddressesInternal() private async Task<List<IPAddress>> GetLocalIpAddressesInternal()
{ {
var list = GetIPsDefault() var list = GetIPsDefault()
.ToList(); .ToList();
if (list.Count == 0) if (list.Count == 0)
{ {
list.AddRange(GetLocalIpAddressesFallback().Result); list.AddRange(await GetLocalIpAddressesFallback().ConfigureAwait(false));
} }
var listClone = list.ToList(); var listClone = list.ToList();
@ -65,7 +102,8 @@ namespace Emby.Server.Implementations.Networking
.OrderBy(i => i.AddressFamily == AddressFamily.InterNetwork ? 0 : 1) .OrderBy(i => i.AddressFamily == AddressFamily.InterNetwork ? 0 : 1)
.ThenBy(i => listClone.IndexOf(i)) .ThenBy(i => listClone.IndexOf(i))
.Where(FilterIpAddress) .Where(FilterIpAddress)
.DistinctBy(i => i.ToString()); .DistinctBy(i => i.ToString())
.ToList();
} }
private bool FilterIpAddress(IPAddress address) private bool FilterIpAddress(IPAddress address)

@ -117,6 +117,10 @@ namespace Emby.Server.Implementations.Session
{ {
dict["SubtitleStreamIndex"] = command.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture); dict["SubtitleStreamIndex"] = command.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture);
} }
if (command.StartIndex.HasValue)
{
dict["StartIndex"] = command.StartIndex.Value.ToString(CultureInfo.InvariantCulture);
}
if (!string.IsNullOrWhiteSpace(command.MediaSourceId)) if (!string.IsNullOrWhiteSpace(command.MediaSourceId))
{ {
dict["MediaSourceId"] = command.MediaSourceId; dict["MediaSourceId"] = command.MediaSourceId;
@ -147,7 +151,7 @@ namespace Emby.Server.Implementations.Session
return SendMessage("LibraryChanged", info, cancellationToken); return SendMessage("LibraryChanged", info, cancellationToken);
} }
public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken) public Task SendRestartRequiredNotification(CancellationToken cancellationToken)
{ {
return SendMessage("RestartRequired", cancellationToken); return SendMessage("RestartRequired", cancellationToken);
} }

@ -1182,13 +1182,11 @@ namespace Emby.Server.Implementations.Session
{ {
var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList(); var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList();
var info = await _appHost.GetSystemInfo().ConfigureAwait(false);
var tasks = sessions.Select(session => Task.Run(async () => var tasks = sessions.Select(session => Task.Run(async () =>
{ {
try try
{ {
await session.SessionController.SendRestartRequiredNotification(info, cancellationToken).ConfigureAwait(false); await session.SessionController.SendRestartRequiredNotification(cancellationToken).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -1423,7 +1421,7 @@ namespace Emby.Server.Implementations.Session
if (enforcePassword) if (enforcePassword)
{ {
var result = await _userManager.AuthenticateUser(request.Username, request.Password, request.PasswordSha1, request.PasswordMd5, request.RemoteEndPoint).ConfigureAwait(false); var result = await _userManager.AuthenticateUser(request.Username, request.Password, request.PasswordSha1, request.PasswordMd5, request.RemoteEndPoint, true).ConfigureAwait(false);
if (result == null) if (result == null)
{ {

@ -145,12 +145,12 @@ namespace Emby.Server.Implementations.Session
/// <param name="info">The information.</param> /// <param name="info">The information.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken) public Task SendRestartRequiredNotification(CancellationToken cancellationToken)
{ {
return SendMessagesInternal(new WebSocketMessage<SystemInfo> return SendMessagesInternal(new WebSocketMessage<string>
{ {
MessageType = "RestartRequired", MessageType = "RestartRequired",
Data = info Data = string.Empty
}, cancellationToken); }, cancellationToken);
} }

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Social; using MediaBrowser.Model.Social;
using System; using System;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Emby.Server.Implementations.Social namespace Emby.Server.Implementations.Social
@ -42,7 +43,7 @@ namespace Emby.Server.Implementations.Social
throw new ResourceNotFoundException(); throw new ResourceNotFoundException();
} }
var externalUrl = (await _appHost.GetSystemInfo().ConfigureAwait(false)).WanAddress; var externalUrl = (await _appHost.GetPublicSystemInfo(CancellationToken.None).ConfigureAwait(false)).WanAddress;
if (string.IsNullOrWhiteSpace(externalUrl)) if (string.IsNullOrWhiteSpace(externalUrl))
{ {
@ -73,7 +74,7 @@ namespace Emby.Server.Implementations.Social
{ {
var info = _repository.GetShareInfo(id); var info = _repository.GetShareInfo(id);
AddShareInfo(info, _appHost.GetSystemInfo().Result.WanAddress); AddShareInfo(info, _appHost.GetPublicSystemInfo(CancellationToken.None).Result.WanAddress);
return info; return info;
} }

@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Udp
private bool _isDisposed; private bool _isDisposed;
private readonly List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, Task>>> _responders = new List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, Task>>>(); private readonly List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>> _responders = new List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>>();
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
private readonly IJsonSerializer _json; private readonly IJsonSerializer _json;
@ -44,9 +44,9 @@ namespace Emby.Server.Implementations.Udp
AddMessageResponder("who is MediaBrowserServer_v2?", false, RespondToV2Message); AddMessageResponder("who is MediaBrowserServer_v2?", false, RespondToV2Message);
} }
private void AddMessageResponder(string message, bool isSubstring, Func<string, IpEndPointInfo, Encoding, Task> responder) private void AddMessageResponder(string message, bool isSubstring, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task> responder)
{ {
_responders.Add(new Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, Task>>(message, isSubstring, responder)); _responders.Add(new Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>(message, isSubstring, responder));
} }
/// <summary> /// <summary>
@ -67,9 +67,15 @@ namespace Emby.Server.Implementations.Udp
if (responder != null) if (responder != null)
{ {
var cancellationToken = CancellationToken.None;
try try
{ {
await responder.Item2.Item3(responder.Item1, message.RemoteEndPoint, encoding).ConfigureAwait(false); await responder.Item2.Item3(responder.Item1, message.RemoteEndPoint, encoding, cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -78,7 +84,7 @@ namespace Emby.Server.Implementations.Udp
} }
} }
private Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, Task>>> GetResponder(byte[] buffer, int bytesReceived, Encoding encoding) private Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>> GetResponder(byte[] buffer, int bytesReceived, Encoding encoding)
{ {
var text = encoding.GetString(buffer, 0, bytesReceived); var text = encoding.GetString(buffer, 0, bytesReceived);
var responder = _responders.FirstOrDefault(i => var responder = _responders.FirstOrDefault(i =>
@ -94,14 +100,14 @@ namespace Emby.Server.Implementations.Udp
{ {
return null; return null;
} }
return new Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, Task>>>(text, responder); return new Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>>(text, responder);
} }
private async Task RespondToV2Message(string messageText, IpEndPointInfo endpoint, Encoding encoding) private async Task RespondToV2Message(string messageText, IpEndPointInfo endpoint, Encoding encoding, CancellationToken cancellationToken)
{ {
var parts = messageText.Split('|'); var parts = messageText.Split('|');
var localUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false); var localUrl = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
if (!string.IsNullOrEmpty(localUrl)) if (!string.IsNullOrEmpty(localUrl))
{ {
@ -112,7 +118,7 @@ namespace Emby.Server.Implementations.Udp
Name = _appHost.FriendlyName Name = _appHost.FriendlyName
}; };
await SendAsync(encoding.GetBytes(_json.SerializeToString(response)), endpoint).ConfigureAwait(false); await SendAsync(encoding.GetBytes(_json.SerializeToString(response)), endpoint, cancellationToken).ConfigureAwait(false);
if (parts.Length > 1) if (parts.Length > 1)
{ {
@ -248,7 +254,7 @@ namespace Emby.Server.Implementations.Udp
} }
} }
public async Task SendAsync(byte[] bytes, IpEndPointInfo remoteEndPoint) public async Task SendAsync(byte[] bytes, IpEndPointInfo remoteEndPoint, CancellationToken cancellationToken)
{ {
if (_isDisposed) if (_isDisposed)
{ {
@ -267,7 +273,7 @@ namespace Emby.Server.Implementations.Udp
try try
{ {
await _udpClient.SendToAsync(bytes, 0, bytes.Length, remoteEndPoint, CancellationToken.None).ConfigureAwait(false); await _udpClient.SendToAsync(bytes, 0, bytes.Length, remoteEndPoint, cancellationToken).ConfigureAwait(false);
_logger.Info("Udp message sent to {0}", remoteEndPoint); _logger.Info("Udp message sent to {0}", remoteEndPoint);
} }

@ -2,6 +2,7 @@
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Dto;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -11,6 +12,36 @@ using MediaBrowser.Model.Services;
namespace MediaBrowser.Api namespace MediaBrowser.Api
{ {
[Route("/Items/Filters", "GET", Summary = "Gets branding configuration")] [Route("/Items/Filters", "GET", Summary = "Gets branding configuration")]
public class GetQueryFiltersLegacy : IReturn<QueryFiltersLegacy>
{
/// <summary>
/// Gets or sets the user id.
/// </summary>
/// <value>The user id.</value>
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string UserId { get; set; }
[ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ParentId { get; set; }
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string IncludeItemTypes { get; set; }
[ApiMember(Name = "MediaTypes", Description = "Optional filter by MediaType. Allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string MediaTypes { get; set; }
public string[] GetMediaTypes()
{
return (MediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
public string[] GetIncludeItemTypes()
{
return (IncludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
}
[Route("/Items/Filters2", "GET", Summary = "Gets branding configuration")]
public class GetQueryFilters : IReturn<QueryFilters> public class GetQueryFilters : IReturn<QueryFilters>
{ {
/// <summary> /// <summary>
@ -38,6 +69,13 @@ namespace MediaBrowser.Api
{ {
return (IncludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return (IncludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
} }
public bool? IsAiring { get; set; }
public bool? IsMovie { get; set; }
public bool? IsSports { get; set; }
public bool? IsKids { get; set; }
public bool? IsNews { get; set; }
public bool? IsSeries { get; set; }
} }
[Authenticated] [Authenticated]
@ -57,18 +95,96 @@ namespace MediaBrowser.Api
var parentItem = string.IsNullOrEmpty(request.ParentId) ? null : _libraryManager.GetItemById(request.ParentId); var parentItem = string.IsNullOrEmpty(request.ParentId) ? null : _libraryManager.GetItemById(request.ParentId);
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase) ||
string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase) ||
string.Equals(request.IncludeItemTypes, typeof(Trailer).Name, StringComparison.OrdinalIgnoreCase) ||
string.Equals(request.IncludeItemTypes, "Program", StringComparison.OrdinalIgnoreCase))
{
parentItem = null;
}
var filters = new QueryFilters();
var genreQuery = new InternalItemsQuery(user)
{
AncestorIds = parentItem == null ? new string[] { } : new string[] { parentItem.Id.ToString("N") },
IncludeItemTypes = request.GetIncludeItemTypes(),
DtoOptions = new Controller.Dto.DtoOptions
{
Fields = new ItemFields[] { },
EnableImages = false,
EnableUserData = false
},
IsAiring = request.IsAiring,
IsMovie = request.IsMovie,
IsSports = request.IsSports,
IsKids = request.IsKids,
IsNews = request.IsNews,
IsSeries = request.IsSeries
};
if (string.Equals(request.IncludeItemTypes, "MusicAlbum", StringComparison.OrdinalIgnoreCase) ||
string.Equals(request.IncludeItemTypes, "MusicVideo", StringComparison.OrdinalIgnoreCase) ||
string.Equals(request.IncludeItemTypes, "MusicArtist", StringComparison.OrdinalIgnoreCase) ||
string.Equals(request.IncludeItemTypes, "Audio", StringComparison.OrdinalIgnoreCase))
{
filters.Genres = _libraryManager.GetMusicGenres(genreQuery).Items.Select(i => new NameIdPair
{
Name = i.Item1.Name,
Id = i.Item1.Id.ToString("N")
}).ToArray();
}
else if (string.Equals(request.IncludeItemTypes, "Game", StringComparison.OrdinalIgnoreCase) ||
string.Equals(request.IncludeItemTypes, "GameSystem", StringComparison.OrdinalIgnoreCase))
{
filters.Genres = _libraryManager.GetGameGenres(genreQuery).Items.Select(i => new NameIdPair
{
Name = i.Item1.Name,
Id = i.Item1.Id.ToString("N")
}).ToArray();
}
else
{
filters.Genres = _libraryManager.GetGenres(genreQuery).Items.Select(i => new NameIdPair
{
Name = i.Item1.Name,
Id = i.Item1.Id.ToString("N")
}).ToArray();
}
return ToOptimizedResult(filters);
}
public object Get(GetQueryFiltersLegacy request)
{
var parentItem = string.IsNullOrEmpty(request.ParentId) ? null : _libraryManager.GetItemById(request.ParentId);
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase) ||
string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase) ||
string.Equals(request.IncludeItemTypes, typeof(Trailer).Name, StringComparison.OrdinalIgnoreCase) ||
string.Equals(request.IncludeItemTypes, "Program", StringComparison.OrdinalIgnoreCase))
{
parentItem = null;
}
var item = string.IsNullOrEmpty(request.ParentId) ? var item = string.IsNullOrEmpty(request.ParentId) ?
user == null ? _libraryManager.RootFolder : user.RootFolder : user == null ? _libraryManager.RootFolder : user.RootFolder :
parentItem; parentItem;
var result = ((Folder)item).GetItemList(GetItemsQuery(request, user)); var result = ((Folder)item).GetItemList(GetItemsQuery(request, user));
return ToOptimizedResult(GetFilters(result)); var filters = GetFilters(result);
return ToOptimizedResult(filters);
} }
private QueryFilters GetFilters(BaseItem[] items) private QueryFiltersLegacy GetFilters(BaseItem[] items)
{ {
var result = new QueryFilters(); var result = new QueryFiltersLegacy();
result.Years = items.Select(i => i.ProductionYear ?? -1) result.Years = items.Select(i => i.ProductionYear ?? -1)
.Where(i => i > 0) .Where(i => i > 0)
@ -97,7 +213,7 @@ namespace MediaBrowser.Api
return result; return result;
} }
private InternalItemsQuery GetItemsQuery(GetQueryFilters request, User user) private InternalItemsQuery GetItemsQuery(GetQueryFiltersLegacy request, User user)
{ {
var query = new InternalItemsQuery var query = new InternalItemsQuery
{ {

@ -379,6 +379,9 @@ namespace MediaBrowser.Api.LiveTv
[ApiMember(Name = "Genres", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")] [ApiMember(Name = "Genres", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
public string Genres { get; set; } public string Genres { get; set; }
[ApiMember(Name = "GenreIds", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
public string GenreIds { get; set; }
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
public bool? EnableImages { get; set; } public bool? EnableImages { get; set; }
@ -456,6 +459,9 @@ namespace MediaBrowser.Api.LiveTv
[ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string EnableImageTypes { get; set; } public string EnableImageTypes { get; set; }
[ApiMember(Name = "GenreIds", Description = "The genres to return guide information for.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
public string GenreIds { get; set; }
/// <summary> /// <summary>
/// Fields to return within the items, in addition to basic information /// Fields to return within the items, in addition to basic information
/// </summary> /// </summary>
@ -1003,6 +1009,7 @@ namespace MediaBrowser.Api.LiveTv
query.IsSports = request.IsSports; query.IsSports = request.IsSports;
query.SeriesTimerId = request.SeriesTimerId; query.SeriesTimerId = request.SeriesTimerId;
query.Genres = (request.Genres ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); query.Genres = (request.Genres ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
query.GenreIds = (request.GenreIds ?? String.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
if (!string.IsNullOrWhiteSpace(request.LibrarySeriesId)) if (!string.IsNullOrWhiteSpace(request.LibrarySeriesId))
{ {
@ -1036,6 +1043,8 @@ namespace MediaBrowser.Api.LiveTv
EnableTotalRecordCount = request.EnableTotalRecordCount EnableTotalRecordCount = request.EnableTotalRecordCount
}; };
query.GenreIds = (request.GenreIds ?? String.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
var result = _liveTvManager.GetRecommendedPrograms(query, GetDtoOptions(_authContext, request), CancellationToken.None); var result = _liveTvManager.GetRecommendedPrograms(query, GetDtoOptions(_authContext, request), CancellationToken.None);
return ToOptimizedResult(result); return ToOptimizedResult(result);

@ -3,9 +3,10 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Tasks;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Threading; using MediaBrowser.Model.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Api.ScheduledTasks namespace MediaBrowser.Api.ScheduledTasks
{ {
@ -63,7 +64,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// </summary> /// </summary>
/// <param name="state">The state.</param> /// <param name="state">The state.</param>
/// <returns>Task{IEnumerable{TaskInfo}}.</returns> /// <returns>Task{IEnumerable{TaskInfo}}.</returns>
protected override Task<IEnumerable<TaskInfo>> GetDataToSend(WebSocketListenerState state) protected override Task<IEnumerable<TaskInfo>> GetDataToSend(WebSocketListenerState state, CancellationToken cancellationToken)
{ {
return Task.FromResult(TaskManager.ScheduledTasks return Task.FromResult(TaskManager.ScheduledTasks
.OrderBy(i => i.Name) .OrderBy(i => i.Name)

@ -248,9 +248,20 @@ namespace MediaBrowser.Api
if (song != null) if (song != null)
{ {
result.Album = song.Album;
result.AlbumArtist = song.AlbumArtists.FirstOrDefault(); result.AlbumArtist = song.AlbumArtists.FirstOrDefault();
result.Artists = song.Artists; result.Artists = song.Artists;
album = song.AlbumEntity;
if (album != null)
{
result.Album = album.Name;
result.AlbumId = album.Id.ToString("N");
}
else
{
result.Album = song.Album;
}
} }
if (!string.IsNullOrWhiteSpace(item.ChannelId)) if (!string.IsNullOrWhiteSpace(item.ChannelId))

@ -5,8 +5,9 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Session; using MediaBrowser.Model.Session;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading;
using MediaBrowser.Model.Threading; using MediaBrowser.Model.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Api.Session namespace MediaBrowser.Api.Session
{ {
@ -86,7 +87,7 @@ namespace MediaBrowser.Api.Session
/// </summary> /// </summary>
/// <param name="state">The state.</param> /// <param name="state">The state.</param>
/// <returns>Task{SystemInfo}.</returns> /// <returns>Task{SystemInfo}.</returns>
protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(WebSocketListenerState state) protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(WebSocketListenerState state, CancellationToken cancellationToken)
{ {
return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto)); return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto));
} }

@ -67,6 +67,7 @@ namespace MediaBrowser.Api
public void Post(ReportStartupWizardComplete request) public void Post(ReportStartupWizardComplete request)
{ {
_config.Configuration.IsStartupWizardCompleted = true; _config.Configuration.IsStartupWizardCompleted = true;
_config.Configuration.AutoRunWebApp = true;
_config.SetOptimalValues(); _config.SetOptimalValues();
_config.SaveConfiguration(); _config.SaveConfiguration();

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Threading; using MediaBrowser.Model.Threading;
using System.Threading;
namespace MediaBrowser.Api.System namespace MediaBrowser.Api.System
{ {
@ -43,7 +44,7 @@ namespace MediaBrowser.Api.System
/// </summary> /// </summary>
/// <param name="state">The state.</param> /// <param name="state">The state.</param>
/// <returns>Task{SystemInfo}.</returns> /// <returns>Task{SystemInfo}.</returns>
protected override Task<List<ActivityLogEntry>> GetDataToSend(WebSocketListenerState state) protected override Task<List<ActivityLogEntry>> GetDataToSend(WebSocketListenerState state, CancellationToken CancellationToken)
{ {
return Task.FromResult(new List<ActivityLogEntry>()); return Task.FromResult(new List<ActivityLogEntry>());
} }

@ -4,6 +4,7 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Model.Threading; using MediaBrowser.Model.Threading;
using System.Threading;
namespace MediaBrowser.Api.System namespace MediaBrowser.Api.System
{ {
@ -40,9 +41,9 @@ namespace MediaBrowser.Api.System
/// </summary> /// </summary>
/// <param name="state">The state.</param> /// <param name="state">The state.</param>
/// <returns>Task{SystemInfo}.</returns> /// <returns>Task{SystemInfo}.</returns>
protected override Task<SystemInfo> GetDataToSend(WebSocketListenerState state) protected override Task<SystemInfo> GetDataToSend(WebSocketListenerState state, CancellationToken cancellationToken)
{ {
return _appHost.GetSystemInfo(); return _appHost.GetSystemInfo(cancellationToken);
} }
} }
} }

@ -14,6 +14,7 @@ using MediaBrowser.Controller.IO;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
using System.Threading;
namespace MediaBrowser.Api.System namespace MediaBrowser.Api.System
{ {
@ -164,26 +165,16 @@ namespace MediaBrowser.Api.System
/// <returns>System.Object.</returns> /// <returns>System.Object.</returns>
public async Task<object> Get(GetSystemInfo request) public async Task<object> Get(GetSystemInfo request)
{ {
var result = await _appHost.GetSystemInfo().ConfigureAwait(false); var result = await _appHost.GetSystemInfo(CancellationToken.None).ConfigureAwait(false);
return ToOptimizedResult(result); return ToOptimizedResult(result);
} }
public async Task<object> Get(GetPublicSystemInfo request) public async Task<object> Get(GetPublicSystemInfo request)
{ {
var result = await _appHost.GetSystemInfo().ConfigureAwait(false); var result = await _appHost.GetPublicSystemInfo(CancellationToken.None).ConfigureAwait(false);
var publicInfo = new PublicSystemInfo return ToOptimizedResult(result);
{
Id = result.Id,
ServerName = result.ServerName,
Version = result.Version,
LocalAddress = result.LocalAddress,
WanAddress = result.WanAddress,
OperatingSystem = result.OperatingSystem
};
return ToOptimizedResult(publicInfo);
} }
/// <summary> /// <summary>

@ -473,7 +473,7 @@ namespace MediaBrowser.Api
} }
else else
{ {
var success = await _userManager.AuthenticateUser(user.Name, request.CurrentPw, request.CurrentPassword, null, Request.RemoteIp).ConfigureAwait(false); var success = await _userManager.AuthenticateUser(user.Name, request.CurrentPw, request.CurrentPassword, null, Request.RemoteIp, false).ConfigureAwait(false);
if (success == null) if (success == null)
{ {

@ -1,13 +1,15 @@
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace MediaBrowser.Common.Net namespace MediaBrowser.Common.Net
{ {
public interface INetworkManager public interface INetworkManager
{ {
event EventHandler NetworkChanged;
/// <summary> /// <summary>
/// Gets a random port number that is currently available /// Gets a random port number that is currently available
/// </summary> /// </summary>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save