commit
0a202a58f8
|
@ -176,6 +176,18 @@ namespace Emby.Dlna.Didl
|
||||||
return new NullLogger();
|
return new NullLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetMimeType(string input)
|
||||||
|
{
|
||||||
|
var mime = MimeTypes.GetMimeType(input);
|
||||||
|
|
||||||
|
if (string.Equals(mime, "video/mp2t", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
mime = "video/mpeg";
|
||||||
|
}
|
||||||
|
|
||||||
|
return mime;
|
||||||
|
}
|
||||||
|
|
||||||
private void AddVideoResource(DlnaOptions options, XmlWriter writer, IHasMediaSources video, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
private void AddVideoResource(DlnaOptions options, XmlWriter writer, IHasMediaSources video, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
||||||
{
|
{
|
||||||
if (streamInfo == null)
|
if (streamInfo == null)
|
||||||
|
@ -360,7 +372,7 @@ namespace Emby.Dlna.Didl
|
||||||
var filename = url.Substring(0, url.IndexOf('?'));
|
var filename = url.Substring(0, url.IndexOf('?'));
|
||||||
|
|
||||||
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
|
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
|
||||||
? MimeTypes.GetMimeType(filename)
|
? GetMimeType(filename)
|
||||||
: mediaProfile.MimeType;
|
: mediaProfile.MimeType;
|
||||||
|
|
||||||
writer.WriteAttributeString("protocolInfo", String.Format(
|
writer.WriteAttributeString("protocolInfo", String.Format(
|
||||||
|
@ -481,7 +493,7 @@ namespace Emby.Dlna.Didl
|
||||||
var filename = url.Substring(0, url.IndexOf('?'));
|
var filename = url.Substring(0, url.IndexOf('?'));
|
||||||
|
|
||||||
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
|
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
|
||||||
? MimeTypes.GetMimeType(filename)
|
? GetMimeType(filename)
|
||||||
: mediaProfile.MimeType;
|
: mediaProfile.MimeType;
|
||||||
|
|
||||||
var contentFeatures = new ContentFeatureBuilder(_profile).BuildAudioHeader(streamInfo.Container,
|
var contentFeatures = new ContentFeatureBuilder(_profile).BuildAudioHeader(streamInfo.Container,
|
||||||
|
@ -760,7 +772,7 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
// Seeing some LG models locking up due content with large lists of people
|
// Seeing some LG models locking up due content with large lists of people
|
||||||
// The actual issue might just be due to processing a more metadata than it can handle
|
// The actual issue might just be due to processing a more metadata than it can handle
|
||||||
var limit = 10;
|
var limit = 6;
|
||||||
|
|
||||||
foreach (var actor in people)
|
foreach (var actor in people)
|
||||||
{
|
{
|
||||||
|
@ -1007,7 +1019,7 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
writer.WriteAttributeString("protocolInfo", String.Format(
|
writer.WriteAttributeString("protocolInfo", String.Format(
|
||||||
"http-get:*:{0}:{1}",
|
"http-get:*:{0}:{1}",
|
||||||
MimeTypes.GetMimeType("file." + format),
|
GetMimeType("file." + format),
|
||||||
contentFeatures
|
contentFeatures
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Emby.Dlna.Profiles
|
||||||
{
|
{
|
||||||
Match = HeaderMatchType.Substring,
|
Match = HeaderMatchType.Substring,
|
||||||
Name = "User-Agent",
|
Name = "User-Agent",
|
||||||
Value ="XiP"
|
Value ="Zip_"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -63,22 +63,7 @@ namespace Emby.Dlna.Profiles
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp3",
|
Container = "mp3,alac,flac",
|
||||||
AudioCodec = "mp3",
|
|
||||||
Type = DlnaProfileType.Audio
|
|
||||||
},
|
|
||||||
|
|
||||||
new DirectPlayProfile
|
|
||||||
{
|
|
||||||
Container = "alac",
|
|
||||||
AudioCodec = "alac",
|
|
||||||
Type = DlnaProfileType.Audio
|
|
||||||
},
|
|
||||||
|
|
||||||
new DirectPlayProfile
|
|
||||||
{
|
|
||||||
Container = "flac",
|
|
||||||
AudioCodec = "flac",
|
|
||||||
Type = DlnaProfileType.Audio
|
Type = DlnaProfileType.Audio
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,9 @@ namespace Emby.Dlna.Profiles
|
||||||
{
|
{
|
||||||
Container = "mp3",
|
Container = "mp3",
|
||||||
AudioCodec = "mp3",
|
AudioCodec = "mp3",
|
||||||
Type = DlnaProfileType.Audio
|
Type = DlnaProfileType.Audio,
|
||||||
|
// Transcoded audio won't be playable at all without this
|
||||||
|
TranscodeSeekInfo = TranscodeSeekInfo.Bytes
|
||||||
},
|
},
|
||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<Manufacturer>Echostar Technologies LLC</Manufacturer>
|
<Manufacturer>Echostar Technologies LLC</Manufacturer>
|
||||||
<ManufacturerUrl>http://www.echostar.com</ManufacturerUrl>
|
<ManufacturerUrl>http://www.echostar.com</ManufacturerUrl>
|
||||||
<Headers>
|
<Headers>
|
||||||
<HttpHeaderInfo name="User-Agent" value="XiP" match="Substring" />
|
<HttpHeaderInfo name="User-Agent" value="Zip_" match="Substring" />
|
||||||
</Headers>
|
</Headers>
|
||||||
</Identification>
|
</Identification>
|
||||||
<Manufacturer>Emby</Manufacturer>
|
<Manufacturer>Emby</Manufacturer>
|
||||||
|
@ -37,9 +37,7 @@
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mp4,mkv,mpeg,ts" audioCodec="mp3,ac3,aac,he-aac,pcm" videoCodec="h264,mpeg2video" type="Video" />
|
<DirectPlayProfile container="mp4,mkv,mpeg,ts" audioCodec="mp3,ac3,aac,he-aac,pcm" videoCodec="h264,mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
|
<DirectPlayProfile container="mp3,alac,flac" type="Audio" />
|
||||||
<DirectPlayProfile container="alac" audioCodec="alac" type="Audio" />
|
|
||||||
<DirectPlayProfile container="flac" audioCodec="flac" type="Audio" />
|
|
||||||
<DirectPlayProfile container="jpeg" type="Photo" />
|
<DirectPlayProfile container="jpeg" type="Photo" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
<DirectPlayProfile container="jpeg,png,gif,bmp,tiff" type="Photo" />
|
<DirectPlayProfile container="jpeg,png,gif,bmp,tiff" type="Photo" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Bytes" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
||||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
||||||
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
||||||
</TranscodingProfiles>
|
</TranscodingProfiles>
|
||||||
|
|
|
@ -106,6 +106,11 @@ namespace Emby.Server.Core.EntryPoints
|
||||||
|
|
||||||
private async void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs<UpnpDeviceInfo> e)
|
private async void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs<UpnpDeviceInfo> e)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var info = e.Argument;
|
var info = e.Argument;
|
||||||
|
|
||||||
string usn;
|
string usn;
|
||||||
|
@ -169,6 +174,11 @@ namespace Emby.Server.Core.EntryPoints
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_logger.Debug("Calling Nat.Handle on " + identifier);
|
_logger.Debug("Calling Nat.Handle on " + identifier);
|
||||||
NatUtility.Handle(localAddress, info, endpoint, NatProtocol.Upnp);
|
NatUtility.Handle(localAddress, info, endpoint, NatProtocol.Upnp);
|
||||||
}
|
}
|
||||||
|
@ -185,6 +195,11 @@ namespace Emby.Server.Core.EntryPoints
|
||||||
|
|
||||||
void NatUtility_DeviceFound(object sender, DeviceEventArgs e)
|
void NatUtility_DeviceFound(object sender, DeviceEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var device = e.Device;
|
var device = e.Device;
|
||||||
|
@ -210,6 +225,11 @@ namespace Emby.Server.Core.EntryPoints
|
||||||
private List<string> _usnsHandled = new List<string>();
|
private List<string> _usnsHandled = new List<string>();
|
||||||
private void CreateRules(INatDevice device)
|
private void CreateRules(INatDevice device)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException("PortMapper");
|
||||||
|
}
|
||||||
|
|
||||||
// On some systems the device discovered event seems to fire repeatedly
|
// On some systems the device discovered event seems to fire repeatedly
|
||||||
// This check will help ensure we're not trying to port map the same device over and over
|
// This check will help ensure we're not trying to port map the same device over and over
|
||||||
|
|
||||||
|
@ -249,8 +269,10 @@ namespace Emby.Server.Core.EntryPoints
|
||||||
_logger.Debug("NAT device lost: {0}", device.LocalAddress.ToString());
|
_logger.Debug("NAT device lost: {0}", device.LocalAddress.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _disposed = false;
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
_disposed = true;
|
||||||
DisposeNat();
|
DisposeNat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -288,6 +288,13 @@ namespace Emby.Server.Core.IO
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (!_fileSystem.DirectoryExists(path))
|
||||||
|
{
|
||||||
|
// Seeing a crash in the mono runtime due to an exception being thrown on a different thread
|
||||||
|
Logger.Info("Skipping realtime monitor for {0} because the path does not exist", path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var newWatcher = new FileSystemWatcher(path, "*")
|
var newWatcher = new FileSystemWatcher(path, "*")
|
||||||
{
|
{
|
||||||
IncludeSubdirectories = true
|
IncludeSubdirectories = true
|
||||||
|
|
|
@ -9,6 +9,7 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.Security;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
|
|
||||||
|
@ -26,8 +27,9 @@ namespace Emby.Server.Implementations.Connect
|
||||||
private readonly IApplicationHost _appHost;
|
private readonly IApplicationHost _appHost;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly ITimerFactory _timerFactory;
|
private readonly ITimerFactory _timerFactory;
|
||||||
|
private readonly IEncryptionManager _encryption;
|
||||||
|
|
||||||
public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost, IFileSystem fileSystem, ITimerFactory timerFactory)
|
public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost, IFileSystem fileSystem, ITimerFactory timerFactory, IEncryptionManager encryption)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_appPaths = appPaths;
|
_appPaths = appPaths;
|
||||||
|
@ -37,6 +39,7 @@ namespace Emby.Server.Implementations.Connect
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_timerFactory = timerFactory;
|
_timerFactory = timerFactory;
|
||||||
|
_encryption = encryption;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run()
|
public void Run()
|
||||||
|
@ -143,7 +146,7 @@ namespace Emby.Server.Implementations.Connect
|
||||||
|
|
||||||
private string CacheFilePath
|
private string CacheFilePath
|
||||||
{
|
{
|
||||||
get { return Path.Combine(_appPaths.DataPath, "wan.txt"); }
|
get { return Path.Combine(_appPaths.DataPath, "wan.dat"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CacheAddress(IpAddressInfo address)
|
private void CacheAddress(IpAddressInfo address)
|
||||||
|
@ -153,7 +156,14 @@ namespace Emby.Server.Implementations.Connect
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
|
||||||
_fileSystem.WriteAllText(path, address.ToString(), Encoding.UTF8);
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_fileSystem.WriteAllText(path, _encryption.EncryptString(address.ToString()), Encoding.UTF8);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -169,7 +179,7 @@ namespace Emby.Server.Implementations.Connect
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var endpoint = _fileSystem.ReadAllText(path, Encoding.UTF8);
|
var endpoint = _encryption.DecryptString(_fileSystem.ReadAllText(path, Encoding.UTF8));
|
||||||
IpAddressInfo ipAddress;
|
IpAddressInfo ipAddress;
|
||||||
|
|
||||||
if (_networkManager.TryParseIpAddress(endpoint, out ipAddress))
|
if (_networkManager.TryParseIpAddress(endpoint, out ipAddress))
|
||||||
|
|
|
@ -2548,57 +2548,53 @@ namespace Emby.Server.Implementations.Data
|
||||||
{
|
{
|
||||||
using (var connection = CreateConnection(true))
|
using (var connection = CreateConnection(true))
|
||||||
{
|
{
|
||||||
return connection.RunInTransaction(db =>
|
var list = new List<BaseItem>();
|
||||||
|
|
||||||
|
using (var statement = PrepareStatementSafe(connection, commandText))
|
||||||
{
|
{
|
||||||
var list = new List<BaseItem>();
|
if (EnableJoinUserData(query))
|
||||||
|
|
||||||
using (var statement = PrepareStatementSafe(db, commandText))
|
|
||||||
{
|
{
|
||||||
if (EnableJoinUserData(query))
|
statement.TryBind("@UserId", query.User.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
BindSimilarParams(query, statement);
|
||||||
|
|
||||||
|
// Running this again will bind the params
|
||||||
|
GetWhereClauses(query, statement);
|
||||||
|
|
||||||
|
foreach (var row in statement.ExecuteQuery())
|
||||||
|
{
|
||||||
|
var item = GetItem(row, query);
|
||||||
|
if (item != null)
|
||||||
{
|
{
|
||||||
statement.TryBind("@UserId", query.User.Id);
|
list.Add(item);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BindSimilarParams(query, statement);
|
// Hack for right now since we currently don't support filtering out these duplicates within a query
|
||||||
|
if (query.EnableGroupByMetadataKey)
|
||||||
|
{
|
||||||
|
var limit = query.Limit ?? int.MaxValue;
|
||||||
|
limit -= 4;
|
||||||
|
var newList = new List<BaseItem>();
|
||||||
|
|
||||||
// Running this again will bind the params
|
foreach (var item in list)
|
||||||
GetWhereClauses(query, statement);
|
{
|
||||||
|
AddItem(newList, item);
|
||||||
|
|
||||||
foreach (var row in statement.ExecuteQuery())
|
if (newList.Count >= limit)
|
||||||
{
|
{
|
||||||
var item = GetItem(row, query);
|
break;
|
||||||
if (item != null)
|
|
||||||
{
|
|
||||||
list.Add(item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hack for right now since we currently don't support filtering out these duplicates within a query
|
list = newList;
|
||||||
if (query.EnableGroupByMetadataKey)
|
}
|
||||||
{
|
|
||||||
var limit = query.Limit ?? int.MaxValue;
|
|
||||||
limit -= 4;
|
|
||||||
var newList = new List<BaseItem>();
|
|
||||||
|
|
||||||
foreach (var item in list)
|
LogQueryTime("GetItemList", commandText, now);
|
||||||
{
|
|
||||||
AddItem(newList, item);
|
|
||||||
|
|
||||||
if (newList.Count >= limit)
|
return list;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list = newList;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogQueryTime("GetItemList", commandText, now);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
|
|
||||||
}, ReadTransactionMode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,7 +182,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
|
|
||||||
programsInfo.Add(GetProgram(channelNumber, schedule, programDict[schedule.programID]));
|
programsInfo.Add(GetProgram(channelNumber, schedule, programDict[schedule.programID]));
|
||||||
}
|
}
|
||||||
_logger.Info("Finished with EPGData");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,8 +321,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
using (var response = await Get(httpOptions, true, info).ConfigureAwait(false))
|
using (var response = await Get(httpOptions, true, info).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response);
|
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response);
|
||||||
_logger.Info("Found " + root.map.Count + " channels on the lineup on ScheduleDirect");
|
|
||||||
_logger.Info("Mapping Stations to Channel");
|
|
||||||
foreach (ScheduleDirect.Map map in root.map)
|
foreach (ScheduleDirect.Map map in root.map)
|
||||||
{
|
{
|
||||||
var channelNumber = map.logicalChannelNumber;
|
var channelNumber = map.logicalChannelNumber;
|
||||||
|
@ -353,7 +351,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_logger.Info("Added " + GetChannelPairCacheCount(listingsId) + " channels to the dictionary");
|
|
||||||
|
|
||||||
foreach (ChannelInfo channel in channels)
|
foreach (ChannelInfo channel in channels)
|
||||||
{
|
{
|
||||||
|
|
|
@ -103,7 +103,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
TunerHostId = info.Id,
|
TunerHostId = info.Id,
|
||||||
IsHD = i.HD == 1,
|
IsHD = i.HD == 1,
|
||||||
AudioCodec = i.AudioCodec,
|
AudioCodec = i.AudioCodec,
|
||||||
VideoCodec = i.VideoCodec
|
VideoCodec = i.VideoCodec,
|
||||||
|
ChannelType = ChannelType.TV
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace Emby.Server.Implementations.Sync
|
||||||
{
|
{
|
||||||
public class SyncHelper
|
public class SyncHelper
|
||||||
{
|
{
|
||||||
public static int? AdjustBitrate(int? profileBitrate, string quality)
|
public static long? AdjustBitrate(long? profileBitrate, string quality)
|
||||||
{
|
{
|
||||||
if (profileBitrate.HasValue)
|
if (profileBitrate.HasValue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,15 +59,8 @@ namespace Emby.Server.Implementations.Sync
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task EnsureJobItems(SyncJob job)
|
public async Task EnsureJobItems(SyncJob job, User user)
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(job.UserId);
|
|
||||||
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Cannot proceed with sync because user no longer exists.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var items = (await GetItemsForSync(job.Category, job.ParentId, job.RequestedItemIds, user, job.UnwatchedOnly).ConfigureAwait(false))
|
var items = (await GetItemsForSync(job.Category, job.ParentId, job.RequestedItemIds, user, job.UnwatchedOnly).ConfigureAwait(false))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
@ -385,7 +378,16 @@ namespace Emby.Server.Implementations.Sync
|
||||||
|
|
||||||
if (job.SyncNewContent)
|
if (job.SyncNewContent)
|
||||||
{
|
{
|
||||||
await EnsureJobItems(job).ConfigureAwait(false);
|
var user = _userManager.GetUserById(job.UserId);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
await _syncManager.CancelJob(job.Id).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await EnsureJobItems(job, user).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,7 +181,7 @@ namespace Emby.Server.Implementations.Sync
|
||||||
|
|
||||||
await _repo.Create(job).ConfigureAwait(false);
|
await _repo.Create(job).ConfigureAwait(false);
|
||||||
|
|
||||||
await processor.EnsureJobItems(job).ConfigureAwait(false);
|
await processor.EnsureJobItems(job, user).ConfigureAwait(false);
|
||||||
|
|
||||||
// If it already has a converting status then is must have been aborted during conversion
|
// If it already has a converting status then is must have been aborted during conversion
|
||||||
var jobItemsResult = GetJobItems(new SyncJobItemQuery
|
var jobItemsResult = GetJobItems(new SyncJobItemQuery
|
||||||
|
|
|
@ -205,7 +205,8 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
args += "-map -0:v";
|
// No known video stream
|
||||||
|
args += "-vn";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.AudioStream != null)
|
if (state.AudioStream != null)
|
||||||
|
@ -395,8 +396,6 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
param += " -crf 23";
|
param += " -crf 23";
|
||||||
}
|
}
|
||||||
|
|
||||||
param += " -tune zerolatency";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
|
||||||
|
@ -536,6 +535,11 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
param += " -x264opts:0 subme=0:rc_lookahead=10:me_range=4:me=dia:no_chroma_me:8x8dct=0:partitions=none";
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
|
!string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||||
|
@ -1492,8 +1496,16 @@ namespace MediaBrowser.Api.Playback
|
||||||
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
|
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// h264
|
||||||
|
return string.Format(" -maxrate {0} -bufsize {1}",
|
||||||
|
bitrate.Value.ToString(UsCulture),
|
||||||
|
(bitrate.Value * 2).ToString(UsCulture));
|
||||||
|
}
|
||||||
|
|
||||||
// h264
|
// h264
|
||||||
return string.Format(" -maxrate {0} -bufsize {1}",
|
return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}",
|
||||||
bitrate.Value.ToString(UsCulture),
|
bitrate.Value.ToString(UsCulture),
|
||||||
(bitrate.Value * 2).ToString(UsCulture));
|
(bitrate.Value * 2).ToString(UsCulture));
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
var waitForSegments = state.SegmentLength >= 10 ? 2 : (state.SegmentLength > 3 || !isLive ? 3 : 3);
|
var waitForSegments = state.SegmentLength >= 10 ? 2 : 3;
|
||||||
await WaitForMinimumSegmentCount(playlist, waitForSegments, cancellationTokenSource.Token).ConfigureAwait(false);
|
await WaitForMinimumSegmentCount(playlist, waitForSegments, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,9 +265,15 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
double startSeconds = 0;
|
double startSeconds = 0;
|
||||||
var lengths = GetSegmentLengths(state);
|
var lengths = GetSegmentLengths(state);
|
||||||
|
|
||||||
|
if (requestedIndex >= lengths.Length)
|
||||||
|
{
|
||||||
|
var msg = string.Format("Invalid segment index requested: {0} - Segment count: {1}", requestedIndex, lengths.Length);
|
||||||
|
throw new ArgumentException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < requestedIndex; i++)
|
for (var i = 0; i < requestedIndex; i++)
|
||||||
{
|
{
|
||||||
startSeconds += lengths[requestedIndex];
|
startSeconds += lengths[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
var position = TimeSpan.FromSeconds(startSeconds).Ticks;
|
var position = TimeSpan.FromSeconds(startSeconds).Ticks;
|
||||||
|
@ -279,9 +285,15 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
double startSeconds = 0;
|
double startSeconds = 0;
|
||||||
var lengths = GetSegmentLengths(state);
|
var lengths = GetSegmentLengths(state);
|
||||||
|
|
||||||
|
if (requestedIndex >= lengths.Length)
|
||||||
|
{
|
||||||
|
var msg = string.Format("Invalid segment index requested: {0} - Segment count: {1}", requestedIndex, lengths.Length);
|
||||||
|
throw new ArgumentException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i <= requestedIndex; i++)
|
for (var i = 0; i <= requestedIndex; i++)
|
||||||
{
|
{
|
||||||
startSeconds += lengths[requestedIndex];
|
startSeconds += lengths[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
var position = TimeSpan.FromSeconds(startSeconds).Ticks;
|
var position = TimeSpan.FromSeconds(startSeconds).Ticks;
|
||||||
|
@ -348,6 +360,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.Debug("Deleting partial HLS file {0}", file.FullName);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FileSystem.DeleteFile(file.FullName);
|
FileSystem.DeleteFile(file.FullName);
|
||||||
|
@ -723,7 +737,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
foreach (var length in segmentLengths)
|
foreach (var length in segmentLengths)
|
||||||
{
|
{
|
||||||
builder.AppendLine("#EXTINF:" + length.ToString("0.0000", UsCulture) + ",");
|
builder.AppendLine("#EXTINF:" + length.ToString("0.0000", UsCulture) + ", nodesc");
|
||||||
|
|
||||||
builder.AppendLine(string.Format("hls1/{0}/{1}{2}{3}",
|
builder.AppendLine(string.Format("hls1/{0}/{1}{2}{3}",
|
||||||
|
|
||||||
|
@ -826,7 +840,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
args += " -bsf:v h264_mp4toannexb";
|
args += " -bsf:v h264_mp4toannexb";
|
||||||
}
|
}
|
||||||
|
|
||||||
args += " -flags -global_header";
|
//args += " -flags -global_header";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -851,7 +865,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
args += GetGraphicalSubtitleParam(state, codec);
|
args += GetGraphicalSubtitleParam(state, codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
args += " -flags -global_header";
|
//args += " -flags -global_header";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EnableCopyTs(state) && args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
|
if (EnableCopyTs(state) && args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
|
||||||
|
@ -875,27 +889,25 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
var inputModifier = GetInputModifier(state, false);
|
var inputModifier = GetInputModifier(state, false);
|
||||||
|
|
||||||
// If isEncoding is true we're actually starting ffmpeg
|
// If isEncoding is true we're actually starting ffmpeg
|
||||||
var startNumberParam = isEncoding ? GetStartNumber(state).ToString(UsCulture) : "0";
|
var startNumber = GetStartNumber(state);
|
||||||
|
var startNumberParam = isEncoding ? startNumber.ToString(UsCulture) : "0";
|
||||||
var toTimeParam = string.Empty;
|
|
||||||
var timestampOffsetParam = string.Empty;
|
|
||||||
|
|
||||||
if (state.IsOutputVideo && !EnableCopyTs(state) && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && (state.Request.StartTimeTicks ?? 0) > 0)
|
|
||||||
{
|
|
||||||
timestampOffsetParam = " -output_ts_offset " + MediaEncoder.GetTimeParameter(state.Request.StartTimeTicks ?? 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty;
|
var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty;
|
||||||
var enableSplittingOnNonKeyFrames = string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && false;
|
var useGenericSegmenter = true;
|
||||||
|
|
||||||
// TODO: check libavformat version for 57 50.100 and use -hls_flags split_by_time
|
if (useGenericSegmenter)
|
||||||
var hlsProtocolSupportsSplittingByTime = false;
|
|
||||||
|
|
||||||
if (enableSplittingOnNonKeyFrames && !hlsProtocolSupportsSplittingByTime)
|
|
||||||
{
|
{
|
||||||
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state);
|
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state);
|
||||||
|
|
||||||
return string.Format("{0} {10} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} -break_non_keyframes 1 -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
|
var timeDeltaParam = String.Empty;
|
||||||
|
|
||||||
|
if (isEncoding && startNumber > 0)
|
||||||
|
{
|
||||||
|
var startTime = state.SegmentLength * startNumber;
|
||||||
|
timeDeltaParam = string.Format("-segment_time_delta -{0}", startTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
|
||||||
inputModifier,
|
inputModifier,
|
||||||
GetInputArgument(state),
|
GetInputArgument(state),
|
||||||
threads,
|
threads,
|
||||||
|
@ -906,27 +918,21 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
startNumberParam,
|
startNumberParam,
|
||||||
outputPath,
|
outputPath,
|
||||||
outputTsArg,
|
outputTsArg,
|
||||||
toTimeParam
|
timeDeltaParam
|
||||||
).Trim();
|
).Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
var splitByTime = hlsProtocolSupportsSplittingByTime && enableSplittingOnNonKeyFrames;
|
return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {6} -individual_header_trailer 0 -start_number {7} -hls_list_size {8} -y \"{9}\"",
|
||||||
var splitByTimeArg = splitByTime ? " -hls_flags split_by_time" : "";
|
|
||||||
|
|
||||||
return string.Format("{0}{12} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7}{8} -start_number {9} -hls_list_size {10} -y \"{11}\"",
|
|
||||||
inputModifier,
|
inputModifier,
|
||||||
GetInputArgument(state),
|
GetInputArgument(state),
|
||||||
threads,
|
threads,
|
||||||
mapArgs,
|
mapArgs,
|
||||||
GetVideoArguments(state),
|
GetVideoArguments(state),
|
||||||
timestampOffsetParam,
|
|
||||||
GetAudioArguments(state),
|
GetAudioArguments(state),
|
||||||
state.SegmentLength.ToString(UsCulture),
|
state.SegmentLength.ToString(UsCulture),
|
||||||
splitByTimeArg,
|
|
||||||
startNumberParam,
|
startNumberParam,
|
||||||
state.HlsListSize.ToString(UsCulture),
|
state.HlsListSize.ToString(UsCulture),
|
||||||
outputPath,
|
outputPath
|
||||||
toTimeParam
|
|
||||||
).Trim();
|
).Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
PlaybackInfoResponse result,
|
PlaybackInfoResponse result,
|
||||||
DeviceProfile profile,
|
DeviceProfile profile,
|
||||||
AuthorizationInfo auth,
|
AuthorizationInfo auth,
|
||||||
int? maxBitrate,
|
long? maxBitrate,
|
||||||
long startTimeTicks,
|
long startTimeTicks,
|
||||||
string mediaSourceId,
|
string mediaSourceId,
|
||||||
int? audioStreamIndex,
|
int? audioStreamIndex,
|
||||||
|
@ -249,7 +249,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
MediaSourceInfo mediaSource,
|
MediaSourceInfo mediaSource,
|
||||||
DeviceProfile profile,
|
DeviceProfile profile,
|
||||||
AuthorizationInfo auth,
|
AuthorizationInfo auth,
|
||||||
int? maxBitrate,
|
long? maxBitrate,
|
||||||
long startTimeTicks,
|
long startTimeTicks,
|
||||||
string mediaSourceId,
|
string mediaSourceId,
|
||||||
int? audioStreamIndex,
|
int? audioStreamIndex,
|
||||||
|
@ -383,7 +383,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int? GetMaxBitrate(int? clientMaxBitrate)
|
private long? GetMaxBitrate(long? clientMaxBitrate)
|
||||||
{
|
{
|
||||||
var maxBitrate = clientMaxBitrate;
|
var maxBitrate = clientMaxBitrate;
|
||||||
var remoteClientMaxBitrate = _config.Configuration.RemoteClientBitrateLimit;
|
var remoteClientMaxBitrate = _config.Configuration.RemoteClientBitrateLimit;
|
||||||
|
@ -425,7 +425,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SortMediaSources(PlaybackInfoResponse result, int? maxBitrate)
|
private void SortMediaSources(PlaybackInfoResponse result, long? maxBitrate)
|
||||||
{
|
{
|
||||||
var originalList = result.MediaSources.ToList();
|
var originalList = result.MediaSources.ToList();
|
||||||
|
|
||||||
|
|
|
@ -93,13 +93,9 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RunTimeTicks.HasValue)
|
|
||||||
{
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,6 +243,8 @@ namespace MediaBrowser.Api.Session
|
||||||
[ApiMember(Name = "SupportsPersistentIdentifier", Description = "Determines whether the device supports a unique identifier.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
|
[ApiMember(Name = "SupportsPersistentIdentifier", Description = "Determines whether the device supports a unique identifier.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
|
||||||
public bool SupportsPersistentIdentifier { get; set; }
|
public bool SupportsPersistentIdentifier { get; set; }
|
||||||
|
|
||||||
|
public bool SupportsContentUploading { get; set; }
|
||||||
|
|
||||||
public PostCapabilities()
|
public PostCapabilities()
|
||||||
{
|
{
|
||||||
SupportsPersistentIdentifier = true;
|
SupportsPersistentIdentifier = true;
|
||||||
|
@ -559,6 +561,8 @@ namespace MediaBrowser.Api.Session
|
||||||
|
|
||||||
SupportsSync = request.SupportsSync,
|
SupportsSync = request.SupportsSync,
|
||||||
|
|
||||||
|
SupportsContentUploading = request.SupportsContentUploading,
|
||||||
|
|
||||||
SupportsPersistentIdentifier = request.SupportsPersistentIdentifier
|
SupportsPersistentIdentifier = request.SupportsPersistentIdentifier
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -827,8 +827,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
|
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// h264
|
||||||
|
return string.Format(" -maxrate {0} -bufsize {1}",
|
||||||
|
bitrate.Value.ToString(UsCulture),
|
||||||
|
(bitrate.Value * 2).ToString(UsCulture));
|
||||||
|
}
|
||||||
|
|
||||||
// h264
|
// h264
|
||||||
return string.Format(" -maxrate {0} -bufsize {1}",
|
return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}",
|
||||||
bitrate.Value.ToString(UsCulture),
|
bitrate.Value.ToString(UsCulture),
|
||||||
(bitrate.Value * 2).ToString(UsCulture));
|
(bitrate.Value * 2).ToString(UsCulture));
|
||||||
}
|
}
|
||||||
|
@ -896,7 +904,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
args += "-map -0:v";
|
// No known video stream
|
||||||
|
args += "-vn";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.AudioStream != null)
|
if (state.AudioStream != null)
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The application's configured quality setting
|
/// The application's configured quality setting
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? MaxBitrate { get; set; }
|
public long? MaxBitrate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the context.
|
/// Gets or sets the context.
|
||||||
|
@ -59,7 +59,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
/// Gets the maximum bitrate.
|
/// Gets the maximum bitrate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>System.Nullable<System.Int32>.</returns>
|
/// <returns>System.Nullable<System.Int32>.</returns>
|
||||||
public int? GetMaxBitrate(bool isAudio)
|
public long? GetMaxBitrate(bool isAudio)
|
||||||
{
|
{
|
||||||
if (MaxBitrate.HasValue)
|
if (MaxBitrate.HasValue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,8 +51,8 @@ namespace MediaBrowser.Model.Dlna
|
||||||
public int? MaxIconWidth { get; set; }
|
public int? MaxIconWidth { get; set; }
|
||||||
public int? MaxIconHeight { get; set; }
|
public int? MaxIconHeight { get; set; }
|
||||||
|
|
||||||
public int? MaxStreamingBitrate { get; set; }
|
public long? MaxStreamingBitrate { get; set; }
|
||||||
public int? MaxStaticBitrate { get; set; }
|
public long? MaxStaticBitrate { get; set; }
|
||||||
|
|
||||||
public int? MusicStreamingTranscodingBitrate { get; set; }
|
public int? MusicStreamingTranscodingBitrate { get; set; }
|
||||||
public int? MaxStaticMusicBitrate { get; set; }
|
public int? MaxStaticMusicBitrate { get; set; }
|
||||||
|
|
|
@ -93,7 +93,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
return GetOptimalStream(streams, options.GetMaxBitrate(false));
|
return GetOptimalStream(streams, options.GetMaxBitrate(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private StreamInfo GetOptimalStream(List<StreamInfo> streams, int? maxBitrate)
|
private StreamInfo GetOptimalStream(List<StreamInfo> streams, long? maxBitrate)
|
||||||
{
|
{
|
||||||
streams = StreamInfoSorter.SortMediaSources(streams, maxBitrate);
|
streams = StreamInfoSorter.SortMediaSources(streams, maxBitrate);
|
||||||
|
|
||||||
|
@ -277,25 +277,26 @@ namespace MediaBrowser.Model.Dlna
|
||||||
playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
|
playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
int transcodingBitrate = options.AudioTranscodingBitrate ??
|
long transcodingBitrate = options.AudioTranscodingBitrate ??
|
||||||
options.Profile.MusicStreamingTranscodingBitrate ??
|
options.Profile.MusicStreamingTranscodingBitrate ??
|
||||||
128000;
|
128000;
|
||||||
|
|
||||||
int? configuredBitrate = options.GetMaxBitrate(true);
|
var configuredBitrate = options.GetMaxBitrate(true);
|
||||||
|
|
||||||
if (configuredBitrate.HasValue)
|
if (configuredBitrate.HasValue)
|
||||||
{
|
{
|
||||||
transcodingBitrate = Math.Min(configuredBitrate.Value, transcodingBitrate);
|
transcodingBitrate = Math.Min(configuredBitrate.Value, transcodingBitrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
playlistItem.AudioBitrate = Math.Min(transcodingBitrate, playlistItem.AudioBitrate ?? transcodingBitrate);
|
var longBitrate = Math.Min(transcodingBitrate, playlistItem.AudioBitrate ?? transcodingBitrate);
|
||||||
|
playlistItem.AudioBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return playlistItem;
|
return playlistItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int? GetBitrateForDirectPlayCheck(MediaSourceInfo item, AudioOptions options, bool isAudio)
|
private long? GetBitrateForDirectPlayCheck(MediaSourceInfo item, AudioOptions options, bool isAudio)
|
||||||
{
|
{
|
||||||
if (item.Protocol == MediaProtocol.File)
|
if (item.Protocol == MediaProtocol.File)
|
||||||
{
|
{
|
||||||
|
@ -583,11 +584,11 @@ namespace MediaBrowser.Model.Dlna
|
||||||
int audioBitrate = GetAudioBitrate(playlistItem.SubProtocol, options.GetMaxBitrate(false), playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec, audioStream);
|
int audioBitrate = GetAudioBitrate(playlistItem.SubProtocol, options.GetMaxBitrate(false), playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec, audioStream);
|
||||||
playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate);
|
playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate);
|
||||||
|
|
||||||
int? maxBitrateSetting = options.GetMaxBitrate(false);
|
var maxBitrateSetting = options.GetMaxBitrate(false);
|
||||||
// Honor max rate
|
// Honor max rate
|
||||||
if (maxBitrateSetting.HasValue)
|
if (maxBitrateSetting.HasValue)
|
||||||
{
|
{
|
||||||
int videoBitrate = maxBitrateSetting.Value;
|
var videoBitrate = maxBitrateSetting.Value;
|
||||||
|
|
||||||
if (playlistItem.AudioBitrate.HasValue)
|
if (playlistItem.AudioBitrate.HasValue)
|
||||||
{
|
{
|
||||||
|
@ -595,15 +596,16 @@ namespace MediaBrowser.Model.Dlna
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the video bitrate is lower than bitrate settings but at least 64k
|
// Make sure the video bitrate is lower than bitrate settings but at least 64k
|
||||||
int currentValue = playlistItem.VideoBitrate ?? videoBitrate;
|
long currentValue = playlistItem.VideoBitrate ?? videoBitrate;
|
||||||
playlistItem.VideoBitrate = Math.Max(Math.Min(videoBitrate, currentValue), 64000);
|
var longBitrate = Math.Max(Math.Min(videoBitrate, currentValue), 64000);
|
||||||
|
playlistItem.VideoBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return playlistItem;
|
return playlistItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetAudioBitrate(string subProtocol, int? maxTotalBitrate, int? targetAudioChannels, string targetAudioCodec, MediaStream audioStream)
|
private int GetAudioBitrate(string subProtocol, long? maxTotalBitrate, int? targetAudioChannels, string targetAudioCodec, MediaStream audioStream)
|
||||||
{
|
{
|
||||||
int defaultBitrate = audioStream == null ? 192000 : audioStream.BitRate ?? 192000;
|
int defaultBitrate = audioStream == null ? 192000 : audioStream.BitRate ?? 192000;
|
||||||
// Reduce the bitrate if we're downmixing
|
// Reduce the bitrate if we're downmixing
|
||||||
|
@ -865,7 +867,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsEligibleForDirectPlay(MediaSourceInfo item,
|
private bool IsEligibleForDirectPlay(MediaSourceInfo item,
|
||||||
int? maxBitrate,
|
long? maxBitrate,
|
||||||
MediaStream subtitleStream,
|
MediaStream subtitleStream,
|
||||||
VideoOptions options,
|
VideoOptions options,
|
||||||
PlayMethod playMethod)
|
PlayMethod playMethod)
|
||||||
|
@ -960,7 +962,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, int? maxBitrate)
|
private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, long? maxBitrate)
|
||||||
{
|
{
|
||||||
if (!maxBitrate.HasValue)
|
if (!maxBitrate.HasValue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
{
|
{
|
||||||
public class StreamInfoSorter
|
public class StreamInfoSorter
|
||||||
{
|
{
|
||||||
public static List<StreamInfo> SortMediaSources(List<StreamInfo> streams, int? maxBitrate)
|
public static List<StreamInfo> SortMediaSources(List<StreamInfo> streams, long? maxBitrate)
|
||||||
{
|
{
|
||||||
return streams.OrderBy(i =>
|
return streams.OrderBy(i =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace MediaBrowser.Model.MediaInfo
|
||||||
public string OpenToken { get; set; }
|
public string OpenToken { get; set; }
|
||||||
public string UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
public string PlaySessionId { get; set; }
|
public string PlaySessionId { get; set; }
|
||||||
public int? MaxStreamingBitrate { get; set; }
|
public long? MaxStreamingBitrate { get; set; }
|
||||||
public long? StartTimeTicks { get; set; }
|
public long? StartTimeTicks { get; set; }
|
||||||
public int? AudioStreamIndex { get; set; }
|
public int? AudioStreamIndex { get; set; }
|
||||||
public int? SubtitleStreamIndex { get; set; }
|
public int? SubtitleStreamIndex { get; set; }
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace MediaBrowser.Model.MediaInfo
|
||||||
|
|
||||||
public string UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
|
|
||||||
public int? MaxStreamingBitrate { get; set; }
|
public long? MaxStreamingBitrate { get; set; }
|
||||||
|
|
||||||
public long? StartTimeTicks { get; set; }
|
public long? StartTimeTicks { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace MediaBrowser.Model.Session
|
||||||
public List<string> SupportedCommands { get; set; }
|
public List<string> SupportedCommands { get; set; }
|
||||||
|
|
||||||
public bool SupportsMediaControl { get; set; }
|
public bool SupportsMediaControl { get; set; }
|
||||||
|
public bool SupportsContentUploading { get; set; }
|
||||||
public string MessageCallbackUrl { get; set; }
|
public string MessageCallbackUrl { get; set; }
|
||||||
|
|
||||||
public bool SupportsPersistentIdentifier { get; set; }
|
public bool SupportsPersistentIdentifier { get; set; }
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
DisplayMessage = 28,
|
DisplayMessage = 28,
|
||||||
SetRepeatMode = 29,
|
SetRepeatMode = 29,
|
||||||
ChannelUp = 30,
|
ChannelUp = 30,
|
||||||
ChannelDown = 31
|
ChannelDown = 31,
|
||||||
|
SetMaxStreamingBitrate = 31
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -93,6 +93,12 @@ namespace MediaBrowser.Providers.TV
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check this in order to avoid logging an exception due to directory not existing
|
||||||
|
if (!_fileSystem.DirectoryExists(seriesDataPath))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var episodeFiles = _fileSystem.GetFilePaths(seriesDataPath)
|
var episodeFiles = _fileSystem.GetFilePaths(seriesDataPath)
|
||||||
.Where(i => string.Equals(Path.GetExtension(i), ".xml", StringComparison.OrdinalIgnoreCase))
|
.Where(i => string.Equals(Path.GetExtension(i), ".xml", StringComparison.OrdinalIgnoreCase))
|
||||||
.Select(Path.GetFileNameWithoutExtension)
|
.Select(Path.GetFileNameWithoutExtension)
|
||||||
|
|
|
@ -143,7 +143,8 @@ namespace MediaBrowser.Providers.TV
|
||||||
Url = ServerTimeUrl,
|
Url = ServerTimeUrl,
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
EnableHttpCompression = true,
|
EnableHttpCompression = true,
|
||||||
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
|
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool,
|
||||||
|
BufferContent = false
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
@ -239,7 +240,8 @@ namespace MediaBrowser.Providers.TV
|
||||||
Url = string.Format(UpdatesUrl, lastUpdateTime),
|
Url = string.Format(UpdatesUrl, lastUpdateTime),
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
EnableHttpCompression = true,
|
EnableHttpCompression = true,
|
||||||
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
|
ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool,
|
||||||
|
BufferContent = false
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
|
|
@ -237,7 +237,8 @@ namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = TvDbResourcePool,
|
ResourcePool = TvDbResourcePool,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = false
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
@ -281,7 +282,8 @@ namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = TvDbResourcePool,
|
ResourcePool = TvDbResourcePool,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = false
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
@ -535,7 +537,8 @@ namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = TvDbResourcePool,
|
ResourcePool = TvDbResourcePool,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken,
|
||||||
|
BufferContent = false
|
||||||
|
|
||||||
}).ConfigureAwait(false))
|
}).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
@ -1664,7 +1667,8 @@ namespace MediaBrowser.Providers.TV
|
||||||
{
|
{
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
Url = url,
|
Url = url,
|
||||||
ResourcePool = TvDbResourcePool
|
ResourcePool = TvDbResourcePool,
|
||||||
|
BufferContent = false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,9 +162,6 @@
|
||||||
<Content Include="dashboard-ui\components\remotecontrol.js">
|
<Content Include="dashboard-ui\components\remotecontrol.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\components\remotecontrolautoplay.js">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\components\tvproviders\xmltv.js">
|
<Content Include="dashboard-ui\components\tvproviders\xmltv.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -258,6 +255,9 @@
|
||||||
<Content Include="dashboard-ui\css\images\empty.png">
|
<Content Include="dashboard-ui\css\images\empty.png">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="dashboard-ui\scripts\videoosd.js">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="dashboard-ui\touchicon144.png">
|
<Content Include="dashboard-ui\touchicon144.png">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -420,9 +420,6 @@
|
||||||
<Content Include="dashboard-ui\devices\ios\ios.css">
|
<Content Include="dashboard-ui\devices\ios\ios.css">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\scripts\htmlmediarenderer.js">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\scripts\sections.js">
|
<Content Include="dashboard-ui\scripts\sections.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -648,9 +645,6 @@
|
||||||
<Content Include="dashboard-ui\css\livetv.css">
|
<Content Include="dashboard-ui\css\livetv.css">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\css\mediaplayer-video.css">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\css\nowplaying.css">
|
<Content Include="dashboard-ui\css\nowplaying.css">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -816,9 +810,6 @@
|
||||||
<Content Include="dashboard-ui\scripts\channelslatest.js">
|
<Content Include="dashboard-ui\scripts\channelslatest.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\scripts\chromecast.js">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\dashboard\cinemamodeconfiguration.js">
|
<Content Include="dashboard-ui\dashboard\cinemamodeconfiguration.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -903,9 +894,6 @@
|
||||||
<Content Include="dashboard-ui\scripts\mediacontroller.js">
|
<Content Include="dashboard-ui\scripts\mediacontroller.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\scripts\mediaplayer-video.js">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\scripts\metadatasubtitles.js">
|
<Content Include="dashboard-ui\scripts\metadatasubtitles.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -978,6 +966,9 @@
|
||||||
<Content Include="dashboard-ui\userpassword.html">
|
<Content Include="dashboard-ui\userpassword.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="dashboard-ui\videoosd.html">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="dashboard-ui\wizardagreement.html">
|
<Content Include="dashboard-ui\wizardagreement.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -1027,9 +1018,6 @@
|
||||||
<Content Include="dashboard-ui\scripts\notifications.js">
|
<Content Include="dashboard-ui\scripts\notifications.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\scripts\remotecontrol.js">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\scripts\moviecollections.js">
|
<Content Include="dashboard-ui\scripts\moviecollections.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -1388,9 +1376,6 @@
|
||||||
<Content Include="dashboard-ui\css\images\clients\dlna.png">
|
<Content Include="dashboard-ui\css\images\clients\dlna.png">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\scripts\mediaplayer.js">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="dashboard-ui\strings\ar.json">
|
<Content Include="dashboard-ui\strings\ar.json">
|
||||||
|
|
|
@ -245,7 +245,7 @@ namespace Rssdp.Infrastructure
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteTrace(String.Format("Search Request Received From {0}, Target = {1}", remoteEndPoint.ToString(), searchTarget));
|
//WriteTrace(String.Format("Search Request Received From {0}, Target = {1}", remoteEndPoint.ToString(), searchTarget));
|
||||||
|
|
||||||
if (IsDuplicateSearchRequest(searchTarget, remoteEndPoint))
|
if (IsDuplicateSearchRequest(searchTarget, remoteEndPoint))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user