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 Rssdp;
using Rssdp.Infrastructure;
using System.Threading;
namespace Emby.Dlna.Main
{
@ -252,7 +253,7 @@ namespace Emby.Dlna.Main
var cacheLength = _config.GetDlnaConfiguration().BlastAliveMessageIntervalSeconds;
_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);

@ -831,7 +831,7 @@ namespace Emby.Dlna.PlayTo
#region From XML
private async Task GetAVProtocolAsync()
private async Task GetAVProtocolAsync(CancellationToken cancellationToken)
{
if (_disposed)
{
@ -845,12 +845,12 @@ namespace Emby.Dlna.PlayTo
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
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);
}
private async Task GetRenderingProtocolAsync()
private async Task GetRenderingProtocolAsync(CancellationToken cancellationToken)
{
if (_disposed)
{
@ -864,7 +864,7 @@ namespace Emby.Dlna.PlayTo
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
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);
}
@ -897,11 +897,11 @@ namespace Emby.Dlna.PlayTo
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 document = await ssdpHttpClient.GetDataAsync(url.ToString()).ConfigureAwait(false);
var document = await ssdpHttpClient.GetDataAsync(url.ToString(), cancellationToken).ConfigureAwait(false);
var deviceProperties = new DeviceInfo();
@ -987,8 +987,8 @@ namespace Emby.Dlna.PlayTo
if (device.GetAvTransportService() != null)
{
await device.GetRenderingProtocolAsync().ConfigureAwait(false);
await device.GetAVProtocolAsync().ConfigureAwait(false);
await device.GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
await device.GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
}
return device;

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

@ -18,6 +18,7 @@ using MediaBrowser.Model.Events;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Threading;
using System.Threading;
namespace Emby.Dlna.PlayTo
{
@ -44,6 +45,8 @@ namespace Emby.Dlna.PlayTo
private readonly List<string> _nonRendererUrls = new List<string>();
private DateTime _lastRendererClear;
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)
{
@ -90,6 +93,7 @@ namespace Emby.Dlna.PlayTo
if (usn.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;
}
@ -98,92 +102,105 @@ namespace Emby.Dlna.PlayTo
return;
}
var cancellationToken = _disposeCancellationTokenSource.Token;
await _sessionLock.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
lock (_nonRendererUrls)
if (_disposed)
{
if ((DateTime.UtcNow - _lastRendererClear).TotalMinutes >= 10)
{
_nonRendererUrls.Clear();
_lastRendererClear = DateTime.UtcNow;
}
if (_nonRendererUrls.Contains(location, StringComparer.OrdinalIgnoreCase))
{
return;
}
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).ConfigureAwait(false);
await AddDevice(info, location, cancellationToken).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)
{
_nonRendererUrls.Add(location);
return;
}
serverAddress = await GetServerAddress(null, cancellationToken).ConfigureAwait(false);
}
if (_disposed)
else
{
return;
serverAddress = await GetServerAddress(info.LocalIpAddress, cancellationToken).ConfigureAwait(false);
}
_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 (controller == null)
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
{
if (_disposed)
{
return;
}
PlayableMediaTypes = profile.GetSupportedMediaTypes(),
string serverAddress;
if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IpAddressInfo.Any) || info.LocalIpAddress.Equals(IpAddressInfo.IPv6Loopback))
SupportedCommands = new string[]
{
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.VolumeUp.ToString(),
GeneralCommandType.Mute.ToString(),
@ -192,33 +209,23 @@ namespace Emby.Dlna.PlayTo
GeneralCommandType.SetVolume.ToString(),
GeneralCommandType.SetAudioStreamIndex.ToString(),
GeneralCommandType.SetSubtitleStreamIndex.ToString()
},
},
SupportsMediaControl = true,
SupportsMediaControl = true,
// xbox one creates a new uuid everytime it restarts
SupportsPersistentIdentifier = (device.Properties.ModelName ?? string.Empty).IndexOf("xbox", StringComparison.OrdinalIgnoreCase) == -1
});
// xbox one creates a new uuid everytime it restarts
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);
}
}
catch (Exception ex)
{
_logger.ErrorException("Error creating PlayTo device.", ex);
lock (_nonRendererUrls)
{
_nonRendererUrls.Add(location);
}
_logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
}
}
private Task<string> GetServerAddress(IpAddressInfo address)
private Task<string> GetServerAddress(IpAddressInfo address, CancellationToken cancellationToken)
{
if (address == null)
{
return _appHost.GetLocalApiUrl();
return _appHost.GetLocalApiUrl(cancellationToken);
}
return Task.FromResult(_appHost.GetLocalApiUrl(address));
@ -226,6 +233,15 @@ namespace Emby.Dlna.PlayTo
public void Dispose()
{
try
{
_disposeCancellationTokenSource.Cancel();
}
catch
{
}
_disposed = true;
_deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered;
GC.SuppressFinalize(this);

@ -7,6 +7,7 @@ using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.Threading;
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
{
@ -99,7 +100,9 @@ namespace Emby.Dlna.PlayTo
BufferContent = false,
// The periodic requests may keep some devices awake
LogRequestAsDebug = true
LogRequestAsDebug = true,
CancellationToken = cancellationToken
};
options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -1,5 +1,5 @@
<?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>
<Manufacturer>Emby</Manufacturer>
<ManufacturerUrl>http://emby.media/</ManufacturerUrl>

@ -1,5 +1,5 @@
<?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>
<Identification>
<FriendlyName>Denon:\[AVR:.*</FriendlyName>

@ -1,5 +1,5 @@
<?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>
<Identification>
<FriendlyName>^DIRECTV.*$</FriendlyName>

@ -1,5 +1,5 @@
<?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>
<Identification>
<Manufacturer>Echostar Technologies LLC</Manufacturer>
@ -86,7 +86,7 @@
</CodecProfile>
</CodecProfiles>
<ResponseProfiles>
<ResponseProfile container="mkv,ts" type="Video" mimeType="video/mp4">
<ResponseProfile container="mkv,ts,mpegts" type="Video" mimeType="video/mp4">
<Conditions />
</ResponseProfile>
</ResponseProfiles>

@ -1,5 +1,5 @@
<?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>
<Identification>
<FriendlyName>LG.*</FriendlyName>

@ -1,5 +1,5 @@
<?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>
<Identification>
<ModelName>DMA2100us</ModelName>
@ -34,7 +34,7 @@
<XmlRootAttributes />
<DirectPlayProfiles>
<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>
<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" />

@ -1,5 +1,5 @@
<?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>
<Identification>
<Manufacturer>Marantz</Manufacturer>

@ -1,5 +1,5 @@
<?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>
<Identification>
<FriendlyName>MediaMonkey</FriendlyName>

@ -1,5 +1,5 @@
<?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>
<Identification>
<FriendlyName>VIERA</FriendlyName>
@ -40,7 +40,7 @@
<DirectPlayProfiles>
<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="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="mov" audioCodec="aac,pcm" videoCodec="h264" type="Video" />
<DirectPlayProfile container="avi" audioCodec="pcm" videoCodec="mpeg4" type="Video" />
@ -73,7 +73,7 @@
</CodecProfile>
</CodecProfiles>
<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 />
</ResponseProfile>
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">

@ -1,5 +1,5 @@
<?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>
<Manufacturer>Emby</Manufacturer>
<ManufacturerUrl>http://emby.media/</ManufacturerUrl>
@ -30,7 +30,7 @@
<XmlRootAttributes />
<DirectPlayProfiles>
<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="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" />

@ -1,5 +1,5 @@
<?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>
<Identification>
<ModelUrl>samsung.com</ModelUrl>
@ -14,7 +14,7 @@
<ModelNumber>Emby</ModelNumber>
<ModelUrl>http://emby.media/</ModelUrl>
<EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
<EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
<EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit>
<EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
@ -51,7 +51,7 @@
</DirectPlayProfiles>
<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="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" />
</TranscodingProfiles>
<ContainerProfiles>
@ -100,7 +100,7 @@
</Conditions>
<ApplyConditions />
</CodecProfile>
<CodecProfile type="VideoAudio" codec="ac3,wmav2,dca,aac,mp3,dts">
<CodecProfile type="VideoAudio" codec="wmav2,dca,aac,mp3,dts">
<Conditions>
<ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="true" />
</Conditions>

@ -1,5 +1,5 @@
<?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>
<Identification>
<Manufacturer>Sharp</Manufacturer>

@ -1,5 +1,5 @@
<?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>
<Identification>
<ModelNumber>BDP-2013</ModelNumber>

@ -1,5 +1,5 @@
<?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>
<Identification>
<ModelNumber>BDP-2014</ModelNumber>

@ -1,5 +1,5 @@
<?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>
<Identification>
<ModelNumber>BDP-2015</ModelNumber>

@ -1,5 +1,5 @@
<?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>
<Identification>
<ModelNumber>BDP-2016</ModelNumber>

@ -1,5 +1,5 @@
<?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>
<Identification>
<FriendlyName>Blu-ray Disc Player</FriendlyName>
@ -39,7 +39,7 @@
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
</XmlRootAttributes>
<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="avi,mp4,m4v" audioCodec="ac3,aac,mp3,pcm" videoCodec="mpeg4,h264" type="Video" />
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
@ -84,7 +84,7 @@
</CodecProfile>
</CodecProfiles>
<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 />
</ResponseProfile>
<ResponseProfile container="avi" type="Video" mimeType="video/mpeg">
@ -93,7 +93,7 @@
<ResponseProfile container="mkv" type="Video" mimeType="video/vnd.dlna.mpeg-tts">
<Conditions />
</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 />
</ResponseProfile>
<ResponseProfile container="mp4" type="Video" mimeType="video/mpeg">

@ -1,5 +1,5 @@
<?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>
<Identification>
<FriendlyName>KDL-\d{2}[EHLNPB]X\d[01]\d.*</FriendlyName>
@ -39,8 +39,8 @@
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
</XmlRootAttributes>
<DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
<DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg1video,mpeg2video" type="Video" />
<DirectPlayProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" 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="mp3" audioCodec="mp3" type="Audio" />
</DirectPlayProfiles>
@ -106,21 +106,21 @@
</CodecProfile>
</CodecProfiles>
<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>
<ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" />
<ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" />
</Conditions>
</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>
<ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" />
</Conditions>
</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 />
</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 />
</ResponseProfile>
<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"?>
<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>
<Identification>
<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" />
</XmlRootAttributes>
<DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
<DirectPlayProfile container="ts" audioCodec="mp3" videoCodec="mpeg2video" type="Video" />
<DirectPlayProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" 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="mpeg" audioCodec="mp3" videoCodec="mpeg2video,mpeg1video" type="Video" />
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" />
@ -109,21 +109,21 @@
</CodecProfile>
</CodecProfiles>
<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>
<ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" />
<ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" />
</Conditions>
</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>
<ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" />
</Conditions>
</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 />
</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 />
</ResponseProfile>
<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"?>
<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>
<Identification>
<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" />
</XmlRootAttributes>
<DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
<DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
<DirectPlayProfile container="ts,mpegts" audioCodec="ac3,aac,mp3" videoCodec="h264" 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="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
<DirectPlayProfile container="mpeg" audioCodec="mp3,mp2" videoCodec="mpeg2video,mpeg1video" type="Video" />
@ -85,21 +85,21 @@
</CodecProfile>
</CodecProfiles>
<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>
<ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" />
<ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" />
</Conditions>
</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>
<ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" />
</Conditions>
</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 />
</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 />
</ResponseProfile>
<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"?>
<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>
<Identification>
<FriendlyName>KDL-\d{2}[WR][5689]\d{2}A.*</FriendlyName>
@ -39,8 +39,8 @@
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
</XmlRootAttributes>
<DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,eac3,aac,mp3" videoCodec="h264" type="Video" />
<DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
<DirectPlayProfile container="ts,mpegts" audioCodec="ac3,eac3,aac,mp3" videoCodec="h264" 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="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" />
@ -84,21 +84,21 @@
</CodecProfile>
</CodecProfiles>
<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>
<ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" />
<ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" />
</Conditions>
</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>
<ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" />
</Conditions>
</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 />
</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 />
</ResponseProfile>
<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"?>
<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>
<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>
@ -39,8 +39,8 @@
<XmlAttribute name="xmlns:av" value="urn:schemas-sony-com:av" />
</XmlRootAttributes>
<DirectPlayProfiles>
<DirectPlayProfile container="ts" audioCodec="ac3,eac3,aac,mp3" videoCodec="h264" type="Video" />
<DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
<DirectPlayProfile container="ts,mpegts" audioCodec="ac3,eac3,aac,mp3" videoCodec="h264" 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="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" />
@ -84,21 +84,21 @@
</CodecProfile>
</CodecProfiles>
<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>
<ProfileCondition condition="Equals" property="PacketLength" value="192" isRequired="true" />
<ProfileCondition condition="Equals" property="VideoTimestamp" value="Valid" isRequired="true" />
</Conditions>
</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>
<ProfileCondition condition="Equals" property="PacketLength" value="188" isRequired="true" />
</Conditions>
</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 />
</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 />
</ResponseProfile>
<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"?>
<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>
<Identification>
<FriendlyName>PLAYSTATION 3</FriendlyName>
@ -38,7 +38,7 @@
<XmlRootAttributes />
<DirectPlayProfiles>
<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="mp4" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" />
<DirectPlayProfile container="aac,mp3,wav" type="Audio" />

@ -1,5 +1,5 @@
<?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>
<Identification>
<FriendlyName>PLAYSTATION 4</FriendlyName>
@ -38,7 +38,7 @@
<XmlRootAttributes />
<DirectPlayProfiles>
<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="mp4,mkv,m4v" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" />
<DirectPlayProfile container="aac,mp3,wav" type="Audio" />

@ -1,5 +1,5 @@
<?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>
<Identification>
<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="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="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="asf" audioCodec="wmav2,wmapro" videoCodec="vc1" type="Video" />
<DirectPlayProfile container="asf" audioCodec="mp2,ac3" videoCodec="mpeg2video" type="Video" />
@ -80,7 +80,7 @@
</CodecProfile>
</CodecProfiles>
<ResponseProfiles>
<ResponseProfile container="ts" type="Video" orgPn="MPEG_TS_SD_NA">
<ResponseProfile container="ts,mpegts" type="Video" orgPn="MPEG_TS_SD_NA">
<Conditions />
</ResponseProfile>
</ResponseProfiles>

@ -1,5 +1,5 @@
<?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>
<Identification>
<ModelName>Xbox One</ModelName>
@ -36,7 +36,7 @@
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<XmlRootAttributes />
<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="aac" videoCodec="h264" 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"?>
<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>
<Identification>
<FriendlyName>foobar</FriendlyName>

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

@ -59,9 +59,6 @@
<Compile Include="StripCollageBuilder.cs" />
<Compile Include="UnplayedCountIndicator.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="fonts\robotoregular.ttf" />
</ItemGroup>
<ItemGroup>
<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>

@ -15,7 +15,6 @@ namespace Emby.Drawing.Skia
{
public class PlayedIndicatorDrawer
{
private const int FontSize = 42;
private const int OffsetFromTopRightCorner = 38;
private readonly IApplicationPaths _appPaths;
@ -44,48 +43,23 @@ namespace Emby.Drawing.Skia
{
paint.Color = new SKColor(255, 255, 255, 255);
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;
var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf");
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(tempPath));
paint.TextSize = 30;
paint.IsAntialias = true;
using (var stream = typeof(PlayedIndicatorDrawer).GetTypeInfo().Assembly.GetManifestResourceStream(namespacePath))
{
using (var fileStream = fileSystem.GetFileStream(tempPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
{
stream.CopyTo(fileStream);
}
}
var text = "✔️";
var emojiChar = StringUtilities.GetUnicodeCharacterCode(text, SKTextEncoding.Utf32);
// or:
//var emojiChar = 0x1F680;
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
{
fileSystem.CopyFile(tempPath, filePath, false);
}
catch (IOException)
{
paint.Typeface = emojiTypeface;
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)

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

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

@ -220,7 +220,7 @@ namespace Emby.Drawing
Type = originalImage.Type,
Path = originalImagePath
}, requiresTransparency, item, options.ImageIndex, options.Enhancers).ConfigureAwait(false);
}, requiresTransparency, item, options.ImageIndex, options.Enhancers, CancellationToken.None).ConfigureAwait(false);
originalImagePath = tuple.Item1;
dateModified = tuple.Item2;
@ -256,31 +256,29 @@ namespace Emby.Drawing
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);
CheckDisposed();
var lockInfo = GetLock(cacheFilePath);
await lockInfo.Lock.WaitAsync().ConfigureAwait(false);
try
{
CheckDisposed();
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))
{
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))
{
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(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
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
finally
{
ReleaseLock(cacheFilePath, lockInfo);
}
}
private ImageFormat GetOutputFormat(ImageFormat[] clientSupportedFormats, bool requiresTransparency)
@ -667,7 +669,7 @@ namespace Emby.Drawing
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;
}
@ -676,7 +678,8 @@ namespace Emby.Drawing
bool inputImageSupportsTransparency,
IHasMetadata item,
int imageIndex,
List<IImageEnhancer> enhancers)
List<IImageEnhancer> enhancers,
CancellationToken cancellationToken)
{
var originalImagePath = image.Path;
var dateModified = image.DateModified;
@ -687,7 +690,7 @@ namespace Emby.Drawing
var cacheGuid = GetImageCacheTag(item, image, 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;
@ -727,7 +730,8 @@ namespace Emby.Drawing
ImageType imageType,
int imageIndex,
List<IImageEnhancer> supportedEnhancers,
string cacheGuid)
string cacheGuid,
CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(originalImagePath))
{
@ -755,29 +759,28 @@ namespace Emby.Drawing
var enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + cacheExtension);
// Check again in case of contention
if (_fileSystem.FileExists(enhancedImagePath))
{
return new Tuple<string, bool>(enhancedImagePath, treatmentRequiresTransparency);
}
var lockInfo = GetLock(enhancedImagePath);
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath));
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);
await lockInfo.Lock.WaitAsync(cancellationToken).ConfigureAwait(false);
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>
@ -896,6 +899,45 @@ namespace Emby.Drawing
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;
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>
/// Occurs when [has pending restart changed].
/// </summary>
@ -361,7 +389,7 @@ namespace Emby.Server.Implementations
protected IAuthService AuthService { get; private set; }
protected readonly StartupOptions StartupOptions;
public StartupOptions StartupOptions { get; private set; }
protected readonly string ReleaseAssetFilename;
internal IPowerManagement PowerManagement { get; private set; }
@ -393,6 +421,7 @@ namespace Emby.Server.Implementations
ISystemEvents systemEvents,
INetworkManager networkManager)
{
// hack alert, until common can target .net core
BaseExtensions.CryptographyProvider = CryptographyProvider;
@ -423,6 +452,13 @@ namespace Emby.Server.Implementations
SetBaseExceptionMessage();
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
NetworkManager.NetworkChanged += NetworkManager_NetworkChanged;
}
private void NetworkManager_NetworkChanged(object sender, EventArgs e)
{
_validAddressResults.Clear();
}
private Version _version;
@ -1901,9 +1937,9 @@ namespace Emby.Server.Implementations
/// Gets the system status.
/// </summary>
/// <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
{
@ -1928,6 +1964,7 @@ namespace Emby.Server.Implementations
OperatingSystemDisplayName = OperatingSystemDisplayName,
CanSelfRestart = CanSelfRestart,
CanSelfUpdate = CanSelfUpdate,
CanLaunchWebBrowser = CanLaunchWebBrowser,
WanAddress = ConnectManager.WanApiAddress,
HasUpdateAvailable = HasUpdateAvailable,
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
{
get
@ -1955,14 +2007,14 @@ namespace Emby.Server.Implementations
get { return Certificate != null || ServerConfigurationManager.Configuration.IsBehindProxy; }
}
public async Task<string> GetLocalApiUrl()
public async Task<string> GetLocalApiUrl(CancellationToken cancellationToken)
{
try
{
// 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);
}
@ -1994,7 +2046,12 @@ namespace Emby.Server.Implementations
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
.Configuration
@ -2006,22 +2063,33 @@ namespace Emby.Server.Implementations
if (addresses.Count == 0)
{
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 (valid)
if (address.Equals(IpAddressInfo.Loopback) || address.Equals(IpAddressInfo.IPv6Loopback))
{
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)
@ -2042,8 +2110,7 @@ namespace Emby.Server.Implementations
}
private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
private DateTime _lastAddressCacheClear;
private async Task<bool> IsIpAddressValidAsync(IpAddressInfo address)
private async Task<bool> IsIpAddressValidAsync(IpAddressInfo address, CancellationToken cancellationToken)
{
if (address.Equals(IpAddressInfo.Loopback) ||
address.Equals(IpAddressInfo.IPv6Loopback))
@ -2054,12 +2121,6 @@ namespace Emby.Server.Implementations
var apiUrl = GetLocalApiUrl(address);
apiUrl += "/system/ping";
if ((DateTime.UtcNow - _lastAddressCacheClear).TotalMinutes >= 15)
{
_lastAddressCacheClear = DateTime.UtcNow;
_validAddressResults.Clear();
}
bool cachedResult;
if (_validAddressResults.TryGetValue(apiUrl, out cachedResult))
{
@ -2075,7 +2136,9 @@ namespace Emby.Server.Implementations
LogErrors = false,
LogRequest = false,
TimeoutMs = 30000,
BufferContent = false
BufferContent = false,
CancellationToken = cancellationToken
}, "POST").ConfigureAwait(false))
{
@ -2085,14 +2148,19 @@ namespace Emby.Server.Implementations
var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase);
_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;
}
}
}
catch (OperationCanceledException)
{
Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, "Cancelled");
throw;
}
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);
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 &&
EnvironmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.OSX)
if (!CanLaunchWebBrowser)
{
throw new NotImplementedException();
throw new NotSupportedException();
}
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>
/// Extracts all from7z.
/// </summary>

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

@ -4286,7 +4286,7 @@ namespace Emby.Server.Implementations.Data
if (query.MinParentalRating.HasValue)
{
whereClauses.Add("InheritedParentalRatingValue<=@MinParentalRating");
whereClauses.Add("InheritedParentalRatingValue>=@MinParentalRating");
if (statement != null)
{
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,
TopParentIds = query.TopParentIds,
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);

@ -708,6 +708,8 @@
<EmbeddedResource Include="Localization\Core\zh-CN.json" />
<EmbeddedResource Include="Localization\Core\zh-HK.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="TextEncoding\NLangDetect\Profiles\afr" />
<None Include="TextEncoding\NLangDetect\Profiles\ara" />

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

@ -260,7 +260,7 @@ namespace Emby.Server.Implementations.EntryPoints
LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
}
var parent = e.Item.GetParent() as Folder;
var parent = e.Parent as Folder;
if (parent != null)
{
_foldersRemovedFrom.Add(parent);
@ -363,10 +363,16 @@ namespace Emby.Server.Implementations.EntryPoints
/// <param name="foldersRemovedFrom">The folders removed from.</param>
/// <param name="userId">The user id.</param>
/// <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 newAndRemoved = new List<BaseItem>();
newAndRemoved.AddRange(foldersAddedTo);
newAndRemoved.AddRange(foldersRemovedFrom);
var allUserRootChildren = _libraryManager.GetUserRootFolder().GetChildren(user, true).OfType<Folder>().ToList();
return new LibraryUpdateInfo
{
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(),
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;
}
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>
/// Translates the physical item to user library.
/// </summary>

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

@ -237,7 +237,7 @@ namespace Emby.Server.Implementations.IO
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
void LibraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
{
if (e.Item.GetParent() is AggregateFolder)
if (e.Parent is AggregateFolder)
{
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>
void LibraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
{
if (e.Item.GetParent() is AggregateFolder)
if (e.Parent is AggregateFolder)
{
StartWatching(e.Item);
}
@ -320,7 +320,8 @@ namespace Emby.Server.Implementations.IO
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;
}

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

@ -141,17 +141,6 @@ namespace Emby.Server.Implementations.Library
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;

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

@ -125,10 +125,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
if (child.IsDirectory)
{
leftOver.Add(child);
}
else if (IsIgnored(child.Name))
{
}
else
{
@ -298,22 +294,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
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>
/// Sets the initial item values.
/// </summary>

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Globalization;
using Emby.Naming.Common;
using Emby.Naming.TV;
using MediaBrowser.Model.Logging;
namespace Emby.Server.Implementations.Library.Resolvers.TV
{
@ -21,16 +22,18 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
private readonly ILibraryManager _libraryManager;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
private readonly ILocalizationManager _localization;
private readonly ILogger _logger;
/// <summary>
/// Initializes a new instance of the <see cref="SeasonResolver"/> class.
/// </summary>
/// <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;
_libraryManager = libraryManager;
_localization = localization;
_logger = logger;
}
/// <summary>
@ -45,20 +48,40 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
var series = ((Series)args.Parent);
var path = args.Path;
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,
SeriesName = series.Name
};
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;
season.Name = seasonNumber == 0 ?
args.LibraryOptions.SeasonZeroDisplayName :
string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture), args.GetLibraryOptions().PreferredMetadataLanguage);
}
return season;

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

@ -218,7 +218,7 @@ namespace Emby.Server.Implementations.Library
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))
{
@ -288,8 +288,11 @@ namespace Emby.Server.Implementations.Library
// Update LastActivityDate and LastLoginDate, then save
if (success)
{
user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow;
UpdateUser(user);
if (isUserSession)
{
user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow;
UpdateUser(user);
}
UpdateInvalidLoginAttemptCount(user, 0);
}
else
@ -812,7 +815,7 @@ namespace Emby.Server.Implementations.Library
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(string.Empty);

@ -1512,6 +1512,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
DeleteFileIfEmpty(recordPath);
TriggerRefresh(recordPath);
_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)
{
_logger.Info("Triggering refresh on {0}", path);
@ -1897,7 +1916,15 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
imageSaveFilenameWithoutExtension = "logo";
break;
case ImageType.Thumb:
imageSaveFilenameWithoutExtension = "landscape";
if (program.IsSeries)
{
imageSaveFilenameWithoutExtension = Path.GetFileNameWithoutExtension(recordingPath) + "-thumb";
}
else
{
imageSaveFilenameWithoutExtension = "landscape";
}
break;
case ImageType.Backdrop:
imageSaveFilenameWithoutExtension = "fanart";
@ -1921,9 +1948,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
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
{

@ -105,31 +105,64 @@ namespace Emby.Server.Implementations.LiveTv.Listings
if (string.Equals(ext, ".gz", StringComparison.OrdinalIgnoreCase))
{
using (var stream = _fileSystem.OpenRead(file))
try
{
var tempFolder = Path.Combine(_config.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString());
_fileSystem.CreateDirectory(tempFolder);
try
{
_zipClient.ExtractAllFromGz(stream, tempFolder, true);
}
catch
{
// If the extraction fails just return the original file, it could be a gz
return file;
}
var tempFolder = ExtractGz(file);
return FindXmlFile(tempFolder);
}
catch (Exception ex)
{
//_logger.ErrorException("Error extracting from gz file {0}", ex, file);
}
return _fileSystem.GetFiles(tempFolder, true)
.Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase))
.Select(i => i.FullName)
.FirstOrDefault();
try
{
var tempFolder = ExtractFirstFileFromGz(file);
return FindXmlFile(tempFolder);
}
catch (Exception ex)
{
//_logger.ErrorException("Error extracting from zip file {0}", ex, 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)
{
if (string.IsNullOrWhiteSpace(channelId))
@ -149,6 +182,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
_logger.Debug("Getting xmltv programs for channel {0}", channelId);
var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false);
_logger.Debug("Opening XmlTvReader for {0}", path);
var reader = new XmlTvReader(path, GetLanguage(info));
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
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 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
var path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false);
_logger.Debug("Opening XmlTvReader for {0}", path);
var reader = new XmlTvReader(path, GetLanguage(info));
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)
{
_services = services.ToArray();
_tunerHosts.AddRange(tunerHosts);
_tunerHosts.AddRange(tunerHosts.Where(i => i.IsSupported));
_listingProviders.AddRange(listingProviders);
foreach (var service in _services)
@ -947,6 +947,7 @@ namespace Emby.Server.Implementations.LiveTv
IsKids = query.IsKids,
IsNews = query.IsNews,
Genres = query.Genres,
GenreIds = query.GenreIds,
StartIndex = query.StartIndex,
Limit = query.Limit,
OrderBy = query.OrderBy,
@ -1020,7 +1021,8 @@ namespace Emby.Server.Implementations.LiveTv
EnableTotalRecordCount = query.EnableTotalRecordCount,
OrderBy = new[] { new Tuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending) },
TopParentIds = new[] { topFolder.Id.ToString("N") },
DtoOptions = options
DtoOptions = options,
GenreIds = query.GenreIds
};
if (query.Limit.HasValue)
@ -1421,7 +1423,7 @@ namespace Emby.Server.Implementations.LiveTv
if (newPrograms.Count > 0)
{
_libraryManager.CreateItems(newPrograms, cancellationToken);
_libraryManager.CreateItems(newPrograms, null, cancellationToken);
}
// TODO: Do this in bulk

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

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

@ -17,6 +17,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.System;
using System.IO;
namespace Emby.Server.Implementations.LiveTv.TunerHosts
{
@ -75,6 +76,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
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)
{
var tunerCount = info.TunerCount;
@ -95,7 +104,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
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);
@ -152,6 +166,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
isRemote = !_networkManager.IsInLocalNetwork(uri.Host);
}
var supportsDirectPlay = !info.EnableStreamLooping && info.TunerCount == 0;
var mediaSource = new MediaSourceInfo
{
Path = path,
@ -183,7 +199,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
IsInfiniteStream = true,
IsRemote = isRemote,
IgnoreDts = true
IgnoreDts = true,
SupportsDirectPlay = supportsDirectPlay
};
mediaSource.InferTotalBitrate();

@ -71,7 +71,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
}
else if (contentType.IndexOf("mp4", 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;
}
@ -88,6 +89,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
SetTempFilePath(extension);
var taskCompletionSource = new TaskCompletionSource<bool>();
var now = DateTime.UtcNow;
StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token);
//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.Protocol = MediaProtocol.Http;
if (OpenedMediaSource.SupportsProbing)
{
await Task.Delay(3000).ConfigureAwait(false);
}
//OpenedMediaSource.Path = TempFilePath;
//OpenedMediaSource.Protocol = MediaProtocol.File;
@ -111,6 +110,20 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
//OpenedMediaSource.SupportsDirectStream = true;
//OpenedMediaSource.SupportsTranscoding = true;
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()

@ -1,74 +1,74 @@
{
"Latest": "Darreres",
"ValueSpecialEpisodeName": "Especial - {0}",
"Inherit": "Inherit",
"Books": "Books",
"Music": "Music",
"Games": "Games",
"Photos": "Photos",
"MixedContent": "Mixed content",
"MusicVideos": "Music videos",
"HomeVideos": "Home videos",
"Playlists": "Playlists",
"HeaderRecordingGroups": "Recording Groups",
"Inherit": "Heretat",
"Books": "Llibres",
"Music": "M\u00fasica",
"Games": "Jocs",
"Photos": "Fotos",
"MixedContent": "Contingut mesclat",
"MusicVideos": "V\u00eddeos musicals",
"HomeVideos": "V\u00eddeos dom\u00e8stics",
"Playlists": "Llistes de reproducci\u00f3",
"HeaderRecordingGroups": "Grups d'Enregistrament",
"HeaderContinueWatching": "Continua Veient",
"HeaderFavoriteArtists": "Favorite Artists",
"HeaderFavoriteSongs": "Favorite Songs",
"HeaderFavoriteArtists": "Artistes Preferits",
"HeaderFavoriteSongs": "Can\u00e7ons Preferides",
"HeaderAlbumArtists": "Album Artists",
"HeaderFavoriteAlbums": "Favorite Albums",
"HeaderFavoriteEpisodes": "Favorite Episodes",
"HeaderFavoriteAlbums": "\u00c0lbums Preferits",
"HeaderFavoriteEpisodes": "Episodis Preferits",
"HeaderFavoriteShows": "Programes Preferits",
"HeaderNextUp": "A continuaci\u00f3",
"Favorites": "Favorites",
"Collections": "Collections",
"Channels": "Channels",
"Movies": "Movies",
"Albums": "Albums",
"Artists": "Artists",
"Folders": "Folders",
"Songs": "Songs",
"TvShows": "TV Shows",
"Shows": "Shows",
"Favorites": "Preferits",
"Collections": "Col\u00b7leccions",
"Channels": "Canals",
"Movies": "Pel\u00b7l\u00edcules",
"Albums": "\u00c0lbums",
"Artists": "Artistes",
"Folders": "Directoris",
"Songs": "Can\u00e7ons",
"TvShows": "Espectacles de TV",
"Shows": "Espectacles",
"Genres": "G\u00e8neres",
"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",
"NameSeasonNumber": "Temporada {0}",
"AppDeviceValues": "App: {0}, Dispositiu: {1}",
"UserDownloadingItemWithValues": "{0} est\u00e0 descarregant {1}",
"HeaderLiveTV": "TV en Directe",
"ChapterNameValue": "Episodi {0}",
"ScheduledTaskFailedWithName": "{0} ha fallat",
"LabelRunningTimeValue": "Temps en marxa: {0}",
"ScheduledTaskStartedWithName": "{0} iniciat",
"VersionNumber": "Versi\u00f3 {0}",
"PluginInstalledWithName": "{0} ha estat instal\u00b7lat",
"StartupEmbyServerIsLoading": "El Servidor d'Emby est&agrave; carregant. Si et plau, prova de nou en breus.",
"PluginUpdatedWithName": "{0} ha estat actualitzat",
"PluginUninstalledWithName": "{0} ha estat desinstal\u00b7lat",
"ItemAddedWithName": "{0} afegit a la biblioteca",
"ItemRemovedWithName": "{0} eliminat de la biblioteca",
"LabelIpAddressValue": "Adre\u00e7a IP: {0}",
"DeviceOnlineWithName": "{0} est\u00e0 connectat",
"UserOnlineFromDevice": "{0} est\u00e0 connectat des de {1}",
"ProviderValue": "Prove\u00efdor: {0}",
"SubtitlesDownloadedForItem": "Subt\u00edtols descarregats per a {0}",
"UserCreatedWithName": "S'ha creat l'usuari {0}",
"UserPasswordChangedWithName": "La contrasenya ha estat canviada per a l'usuari {0}",
"UserDeletedWithName": "L'usuari {0} ha estat eliminat",
"UserConfigurationUpdatedWithName": "La configuraci\u00f3 d'usuari ha estat actualitzada per a {0}",
"MessageServerConfigurationUpdated": "S'ha actualitzat la configuraci\u00f3 del servidor",
"MessageNamedServerConfigurationUpdatedWithValue": "La secci\u00f3 de configuraci\u00f3 {0} ha estat actualitzada",
"MessageApplicationUpdated": "El Servidor d'Emby ha estat actualitzat",
"FailedLoginAttemptWithUserName": "Intent de connexi\u00f3 fallit des de {0}",
"AuthenticationSucceededWithUserName": "{0} s'ha autenticat correctament",
"UserOfflineFromDevice": "{0} s'ha desconnectat de {1}",
"DeviceOfflineWithName": "{0} s'ha desconnectat",
"UserStartedPlayingItemWithValues": "{0} ha comen\u00e7at a reproduir {1}",
"UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1}",
"NotificationOptionPluginError": "Un component ha fallat",
"NotificationOptionApplicationUpdateAvailable": "Actualitzaci\u00f3 d'aplicaci\u00f3 disponible",
"NotificationOptionApplicationUpdateInstalled": "Actualitzaci\u00f3 d'aplicaci\u00f3 instal\u00b7lada",
"NotificationOptionPluginUpdateInstalled": "Actualitzaci\u00f3 de complement instal\u00b7lada",
"NotificationOptionPluginInstalled": "Complement instal\u00b7lat",
"NotificationOptionPluginUninstalled": "Complement desinstal\u00b7lat",
"NotificationOptionVideoPlayback": "Video playback started",
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionGamePlayback": "Game playback started",

@ -7,7 +7,7 @@
"Games": "Spiele",
"Photos": "Fotos",
"MixedContent": "Gemischte Inhalte",
"MusicVideos": "Musik-Videos",
"MusicVideos": "Musikvideos",
"HomeVideos": "Heimvideos",
"Playlists": "Wiedergabelisten",
"HeaderRecordingGroups": "Aufnahme-Gruppen",
@ -27,7 +27,7 @@
"Artists": "Interpreten",
"Folders": "Verzeichnisse",
"Songs": "Songs",
"TvShows": "TV Shows",
"TvShows": "TV Sendungen",
"Shows": "Serien",
"Genres": "Genres",
"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",
"UserLockedOutWithName": "El usuario {0} ha sido bloqueado",
"SubtitleDownloadFailureForItem": "Fall\u00f3 la descarga de subt\u00edtulos para {0}",
"Sync": "Sinc.",
"Sync": "Sincronizar",
"User": "Usuario",
"System": "Sistema",
"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",
"Folders": "Pastas",
"Songs": "M\u00fasicas",
"TvShows": "TV Shows",
"TvShows": "S\u00e9ries de TV",
"Shows": "S\u00e9ries",
"Genres": "G\u00eaneros",
"NameSeasonNumber": "Temporada {0}",

@ -76,6 +76,21 @@ namespace Emby.Server.Implementations.MediaEncoder
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)
{
return false;
@ -118,16 +133,6 @@ namespace Emby.Server.Implementations.MediaEncoder
{
if (extractImages)
{
if (video.VideoType == VideoType.Iso)
{
continue;
}
if (video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd)
{
continue;
}
try
{
// 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
{
protected ILogger Logger { get; private set; }
private DateTime _lastRefresh;
public event EventHandler NetworkChanged;
public NetworkManager(ILogger 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;
@ -29,34 +72,28 @@ namespace Emby.Server.Implementations.Networking
public List<IpAddressInfo> GetLocalIpAddresses()
{
const int cacheMinutes = 10;
lock (_localIpAddressSyncLock)
{
var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes;
if (_localIpAddresses == null || forceRefresh)
if (_localIpAddresses == null)
{
var addresses = GetLocalIpAddressesInternal().Select(ToIpAddressInfo).ToList();
var addresses = GetLocalIpAddressesInternal().Result.Select(ToIpAddressInfo).ToList();
_localIpAddresses = addresses;
_lastRefresh = DateTime.UtcNow;
return addresses;
}
return _localIpAddresses;
}
return _localIpAddresses;
}
private IEnumerable<IPAddress> GetLocalIpAddressesInternal()
private async Task<List<IPAddress>> GetLocalIpAddressesInternal()
{
var list = GetIPsDefault()
.ToList();
if (list.Count == 0)
{
list.AddRange(GetLocalIpAddressesFallback().Result);
list.AddRange(await GetLocalIpAddressesFallback().ConfigureAwait(false));
}
var listClone = list.ToList();
@ -65,7 +102,8 @@ namespace Emby.Server.Implementations.Networking
.OrderBy(i => i.AddressFamily == AddressFamily.InterNetwork ? 0 : 1)
.ThenBy(i => listClone.IndexOf(i))
.Where(FilterIpAddress)
.DistinctBy(i => i.ToString());
.DistinctBy(i => i.ToString())
.ToList();
}
private bool FilterIpAddress(IPAddress address)

@ -117,6 +117,10 @@ namespace Emby.Server.Implementations.Session
{
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))
{
dict["MediaSourceId"] = command.MediaSourceId;
@ -147,7 +151,7 @@ namespace Emby.Server.Implementations.Session
return SendMessage("LibraryChanged", info, cancellationToken);
}
public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken)
public Task SendRestartRequiredNotification(CancellationToken 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 info = await _appHost.GetSystemInfo().ConfigureAwait(false);
var tasks = sessions.Select(session => Task.Run(async () =>
{
try
{
await session.SessionController.SendRestartRequiredNotification(info, cancellationToken).ConfigureAwait(false);
await session.SessionController.SendRestartRequiredNotification(cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
@ -1423,7 +1421,7 @@ namespace Emby.Server.Implementations.Session
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)
{

@ -145,12 +145,12 @@ namespace Emby.Server.Implementations.Session
/// <param name="info">The information.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <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",
Data = info
Data = string.Empty
}, cancellationToken);
}

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Social;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Emby.Server.Implementations.Social
@ -42,7 +43,7 @@ namespace Emby.Server.Implementations.Social
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))
{
@ -73,7 +74,7 @@ namespace Emby.Server.Implementations.Social
{
var info = _repository.GetShareInfo(id);
AddShareInfo(info, _appHost.GetSystemInfo().Result.WanAddress);
AddShareInfo(info, _appHost.GetPublicSystemInfo(CancellationToken.None).Result.WanAddress);
return info;
}

@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Udp
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 IJsonSerializer _json;
@ -44,9 +44,9 @@ namespace Emby.Server.Implementations.Udp
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>
@ -67,9 +67,15 @@ namespace Emby.Server.Implementations.Udp
if (responder != null)
{
var cancellationToken = CancellationToken.None;
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)
{
@ -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 responder = _responders.FirstOrDefault(i =>
@ -94,14 +100,14 @@ namespace Emby.Server.Implementations.Udp
{
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 localUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false);
var localUrl = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
if (!string.IsNullOrEmpty(localUrl))
{
@ -112,7 +118,7 @@ namespace Emby.Server.Implementations.Udp
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)
{
@ -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)
{
@ -267,7 +273,7 @@ namespace Emby.Server.Implementations.Udp
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);
}

@ -2,6 +2,7 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
@ -11,6 +12,36 @@ using MediaBrowser.Model.Services;
namespace MediaBrowser.Api
{
[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>
{
/// <summary>
@ -38,6 +69,13 @@ namespace MediaBrowser.Api
{
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]
@ -57,18 +95,96 @@ namespace MediaBrowser.Api
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 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) ?
user == null ? _libraryManager.RootFolder : user.RootFolder :
parentItem;
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)
.Where(i => i > 0)
@ -97,7 +213,7 @@ namespace MediaBrowser.Api
return result;
}
private InternalItemsQuery GetItemsQuery(GetQueryFilters request, User user)
private InternalItemsQuery GetItemsQuery(GetQueryFiltersLegacy request, User user)
{
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")]
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")]
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")]
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>
/// Fields to return within the items, in addition to basic information
/// </summary>
@ -1003,6 +1009,7 @@ namespace MediaBrowser.Api.LiveTv
query.IsSports = request.IsSports;
query.SeriesTimerId = request.SeriesTimerId;
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))
{
@ -1036,6 +1043,8 @@ namespace MediaBrowser.Api.LiveTv
EnableTotalRecordCount = request.EnableTotalRecordCount
};
query.GenreIds = (request.GenreIds ?? String.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
var result = _liveTvManager.GetRecommendedPrograms(query, GetDtoOptions(_authContext, request), CancellationToken.None);
return ToOptimizedResult(result);

@ -3,9 +3,10 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Tasks;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Api.ScheduledTasks
{
@ -63,7 +64,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// </summary>
/// <param name="state">The state.</param>
/// <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
.OrderBy(i => i.Name)

@ -248,9 +248,20 @@ namespace MediaBrowser.Api
if (song != null)
{
result.Album = song.Album;
result.AlbumArtist = song.AlbumArtists.FirstOrDefault();
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))

@ -5,8 +5,9 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Session;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;
using MediaBrowser.Model.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Api.Session
{
@ -86,7 +87,7 @@ namespace MediaBrowser.Api.Session
/// </summary>
/// <param name="state">The state.</param>
/// <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));
}

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

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Threading;
using System.Threading;
namespace MediaBrowser.Api.System
{
@ -43,7 +44,7 @@ namespace MediaBrowser.Api.System
/// </summary>
/// <param name="state">The state.</param>
/// <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>());
}

@ -4,6 +4,7 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.System;
using System.Threading.Tasks;
using MediaBrowser.Model.Threading;
using System.Threading;
namespace MediaBrowser.Api.System
{
@ -40,9 +41,9 @@ namespace MediaBrowser.Api.System
/// </summary>
/// <param name="state">The state.</param>
/// <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.Net;
using MediaBrowser.Model.Services;
using System.Threading;
namespace MediaBrowser.Api.System
{
@ -164,26 +165,16 @@ namespace MediaBrowser.Api.System
/// <returns>System.Object.</returns>
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);
}
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
{
Id = result.Id,
ServerName = result.ServerName,
Version = result.Version,
LocalAddress = result.LocalAddress,
WanAddress = result.WanAddress,
OperatingSystem = result.OperatingSystem
};
return ToOptimizedResult(publicInfo);
return ToOptimizedResult(result);
}
/// <summary>

@ -473,7 +473,7 @@ namespace MediaBrowser.Api
}
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)
{

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

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

Loading…
Cancel
Save