commit
1cd5e20871
|
@ -161,12 +161,6 @@ namespace Emby.Common.Implementations
|
||||||
/// <value>The name.</value>
|
/// <value>The name.</value>
|
||||||
public abstract string Name { get; }
|
public abstract string Name { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this instance is running as service.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance is running as service; otherwise, <c>false</c>.</value>
|
|
||||||
public abstract bool IsRunningAsService { get; }
|
|
||||||
|
|
||||||
protected ICryptoProvider CryptographyProvider = new CryptographyProvider();
|
protected ICryptoProvider CryptographyProvider = new CryptographyProvider();
|
||||||
|
|
||||||
protected IEnvironmentInfo EnvironmentInfo { get; private set; }
|
protected IEnvironmentInfo EnvironmentInfo { get; private set; }
|
||||||
|
|
|
@ -20,10 +20,13 @@ namespace Emby.Common.Implementations.IO
|
||||||
private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>();
|
private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>();
|
||||||
private bool EnableFileSystemRequestConcat = true;
|
private bool EnableFileSystemRequestConcat = true;
|
||||||
|
|
||||||
public ManagedFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars, bool enableFileSystemRequestConcat)
|
private string _tempPath;
|
||||||
|
|
||||||
|
public ManagedFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars, bool enableFileSystemRequestConcat, string tempPath)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
_supportsAsyncFileStreams = supportsAsyncFileStreams;
|
_supportsAsyncFileStreams = supportsAsyncFileStreams;
|
||||||
|
_tempPath = tempPath;
|
||||||
EnableFileSystemRequestConcat = enableFileSystemRequestConcat;
|
EnableFileSystemRequestConcat = enableFileSystemRequestConcat;
|
||||||
SetInvalidFileNameChars(enableManagedInvalidFileNameChars);
|
SetInvalidFileNameChars(enableManagedInvalidFileNameChars);
|
||||||
}
|
}
|
||||||
|
@ -487,18 +490,37 @@ namespace Emby.Common.Implementations.IO
|
||||||
throw new ArgumentNullException("file2");
|
throw new ArgumentNullException("file2");
|
||||||
}
|
}
|
||||||
|
|
||||||
var temp1 = Path.GetTempFileName();
|
var temp1 = Path.Combine(_tempPath, Guid.NewGuid().ToString("N"));
|
||||||
|
|
||||||
// Copying over will fail against hidden files
|
// Copying over will fail against hidden files
|
||||||
SetHidden(file1, false);
|
SetHidden(file1, false);
|
||||||
SetHidden(file2, false);
|
SetHidden(file2, false);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(_tempPath);
|
||||||
CopyFile(file1, temp1, true);
|
CopyFile(file1, temp1, true);
|
||||||
|
|
||||||
CopyFile(file2, file1, true);
|
CopyFile(file2, file1, true);
|
||||||
CopyFile(temp1, file2, true);
|
CopyFile(temp1, file2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool AreEqual(string path1, string path2)
|
||||||
|
{
|
||||||
|
if (path1 == null && path2 == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path1 == null || path2 == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
path1 = path1.TrimEnd(DirectorySeparatorChar);
|
||||||
|
path2 = path2.TrimEnd(DirectorySeparatorChar);
|
||||||
|
|
||||||
|
return string.Equals(path1, path2, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
public bool ContainsSubPath(string parentPath, string path)
|
public bool ContainsSubPath(string parentPath, string path)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(parentPath))
|
if (string.IsNullOrEmpty(parentPath))
|
||||||
|
@ -656,21 +678,7 @@ namespace Emby.Common.Implementations.IO
|
||||||
|
|
||||||
private IEnumerable<FileSystemMetadata> ToMetadata(string parentPath, IEnumerable<FileSystemInfo> infos)
|
private IEnumerable<FileSystemMetadata> ToMetadata(string parentPath, IEnumerable<FileSystemInfo> infos)
|
||||||
{
|
{
|
||||||
return infos.Select(i =>
|
return infos.Select(GetFileSystemMetadata);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return GetFileSystemMetadata(i);
|
|
||||||
}
|
|
||||||
catch (PathTooLongException)
|
|
||||||
{
|
|
||||||
// Can't log using the FullName because it will throw the PathTooLongExceptiona again
|
|
||||||
//Logger.Warn("Path too long: {0}", i.FullName);
|
|
||||||
Logger.Warn("File or directory path too long. Parent folder: {0}", parentPath);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}).Where(i => i != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string[] ReadAllLines(string path)
|
public string[] ReadAllLines(string path)
|
||||||
|
|
|
@ -260,7 +260,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
{
|
{
|
||||||
totalCount = 1;
|
totalCount = 1;
|
||||||
|
|
||||||
if (item.IsFolder || serverItem.StubType.HasValue)
|
if (item.IsDisplayedAsFolder || serverItem.StubType.HasValue)
|
||||||
{
|
{
|
||||||
var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount).ConfigureAwait(false));
|
var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount).ConfigureAwait(false));
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
var childItem = i.Item;
|
var childItem = i.Item;
|
||||||
var displayStubType = i.StubType;
|
var displayStubType = i.StubType;
|
||||||
|
|
||||||
if (childItem.IsFolder || displayStubType.HasValue)
|
if (childItem.IsDisplayedAsFolder || displayStubType.HasValue)
|
||||||
{
|
{
|
||||||
var childCount = (await GetUserItems(childItem, displayStubType, user, sortCriteria, null, 0).ConfigureAwait(false))
|
var childCount = (await GetUserItems(childItem, displayStubType, user, sortCriteria, null, 0).ConfigureAwait(false))
|
||||||
.TotalRecordCount;
|
.TotalRecordCount;
|
||||||
|
@ -381,7 +381,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
|
|
||||||
foreach (var i in childrenResult.Items)
|
foreach (var i in childrenResult.Items)
|
||||||
{
|
{
|
||||||
if (i.IsFolder)
|
if (i.IsDisplayedAsFolder)
|
||||||
{
|
{
|
||||||
var childCount = (await GetChildrenSorted(i, user, searchCriteria, sortCriteria, null, 0).ConfigureAwait(false))
|
var childCount = (await GetChildrenSorted(i, user, searchCriteria, sortCriteria, null, 0).ConfigureAwait(false))
|
||||||
.TotalRecordCount;
|
.TotalRecordCount;
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -674,7 +686,7 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
writer.WriteStartElement("upnp", "class", NS_UPNP);
|
writer.WriteStartElement("upnp", "class", NS_UPNP);
|
||||||
|
|
||||||
if (item.IsFolder || stubType.HasValue)
|
if (item.IsDisplayedAsFolder || stubType.HasValue)
|
||||||
{
|
{
|
||||||
string classType = null;
|
string classType = null;
|
||||||
|
|
||||||
|
@ -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
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -595,6 +595,7 @@ namespace Emby.Dlna
|
||||||
new LinksysDMA2100Profile(),
|
new LinksysDMA2100Profile(),
|
||||||
new LgTvProfile(),
|
new LgTvProfile(),
|
||||||
new Foobar2000Profile(),
|
new Foobar2000Profile(),
|
||||||
|
new SharpSmartTvProfile(),
|
||||||
new MediaMonkeyProfile(),
|
new MediaMonkeyProfile(),
|
||||||
//new Windows81Profile(),
|
//new Windows81Profile(),
|
||||||
//new WindowsMediaCenterProfile(),
|
//new WindowsMediaCenterProfile(),
|
||||||
|
|
|
@ -92,6 +92,7 @@
|
||||||
<Compile Include="Profiles\PanasonicVieraProfile.cs" />
|
<Compile Include="Profiles\PanasonicVieraProfile.cs" />
|
||||||
<Compile Include="Profiles\PopcornHourProfile.cs" />
|
<Compile Include="Profiles\PopcornHourProfile.cs" />
|
||||||
<Compile Include="Profiles\SamsungSmartTvProfile.cs" />
|
<Compile Include="Profiles\SamsungSmartTvProfile.cs" />
|
||||||
|
<Compile Include="Profiles\SharpSmartTvProfile.cs" />
|
||||||
<Compile Include="Profiles\SonyBlurayPlayer2013.cs" />
|
<Compile Include="Profiles\SonyBlurayPlayer2013.cs" />
|
||||||
<Compile Include="Profiles\SonyBlurayPlayer2014.cs" />
|
<Compile Include="Profiles\SonyBlurayPlayer2014.cs" />
|
||||||
<Compile Include="Profiles\SonyBlurayPlayer2015.cs" />
|
<Compile Include="Profiles\SonyBlurayPlayer2015.cs" />
|
||||||
|
@ -148,7 +149,9 @@
|
||||||
<Name>RSSDP</Name>
|
<Name>RSSDP</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Profiles\Xml\Sharp Smart TV.xml" />
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Profiles\Xml\BubbleUPnp.xml" />
|
<EmbeddedResource Include="Profiles\Xml\BubbleUPnp.xml" />
|
||||||
<EmbeddedResource Include="Profiles\Xml\Default.xml" />
|
<EmbeddedResource Include="Profiles\Xml\Default.xml" />
|
||||||
|
|
|
@ -112,7 +112,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
private int GetInactiveTimerIntervalMs()
|
private int GetInactiveTimerIntervalMs()
|
||||||
{
|
{
|
||||||
return 20000;
|
return 30000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
|
@ -440,6 +440,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
var transportState = await GetTransportInfo().ConfigureAwait(false);
|
var transportState = await GetTransportInfo().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DateLastActivity = DateTime.UtcNow;
|
DateLastActivity = DateTime.UtcNow;
|
||||||
|
|
||||||
if (transportState.HasValue)
|
if (transportState.HasValue)
|
||||||
|
@ -530,6 +535,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
private async Task GetVolume()
|
private async Task GetVolume()
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var command = RendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetVolume");
|
var command = RendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetVolume");
|
||||||
if (command == null)
|
if (command == null)
|
||||||
return;
|
return;
|
||||||
|
@ -563,6 +573,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
private async Task GetMute()
|
private async Task GetMute()
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var command = RendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetMute");
|
var command = RendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetMute");
|
||||||
if (command == null)
|
if (command == null)
|
||||||
return;
|
return;
|
||||||
|
@ -793,6 +808,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
private async Task GetAVProtocolAsync()
|
private async Task GetAVProtocolAsync()
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var avService = GetAvTransportService();
|
var avService = GetAvTransportService();
|
||||||
if (avService == null)
|
if (avService == null)
|
||||||
return;
|
return;
|
||||||
|
@ -807,6 +827,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
private async Task GetRenderingProtocolAsync()
|
private async Task GetRenderingProtocolAsync()
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var avService = GetServiceRenderingControl();
|
var avService = GetServiceRenderingControl();
|
||||||
|
|
||||||
if (avService == null)
|
if (avService == null)
|
||||||
|
|
|
@ -149,6 +149,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
async void _device_MediaChanged(object sender, MediaChangedEventArgs e)
|
async void _device_MediaChanged(object sender, MediaChangedEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var streamInfo = await StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager, _mediaSourceManager).ConfigureAwait(false);
|
var streamInfo = await StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager, _mediaSourceManager).ConfigureAwait(false);
|
||||||
|
@ -176,6 +181,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
async void _device_PlaybackStopped(object sender, PlaybackStoppedEventArgs e)
|
async void _device_PlaybackStopped(object sender, PlaybackStoppedEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var streamInfo = await StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager)
|
var streamInfo = await StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager)
|
||||||
|
@ -239,6 +249,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
async void _device_PlaybackStart(object sender, PlaybackStartEventArgs e)
|
async void _device_PlaybackStart(object sender, PlaybackStartEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var info = await StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager).ConfigureAwait(false);
|
var info = await StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager).ConfigureAwait(false);
|
||||||
|
@ -258,6 +273,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
async void _device_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
|
async void _device_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var info = await StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager).ConfigureAwait(false);
|
var info = await StreamParams.ParseFromUrl(e.MediaInfo.Url, _libraryManager, _mediaSourceManager).ConfigureAwait(false);
|
||||||
|
|
|
@ -43,6 +43,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
private readonly List<string> _nonRendererUrls = new List<string>();
|
private readonly List<string> _nonRendererUrls = new List<string>();
|
||||||
private DateTime _lastRendererClear;
|
private DateTime _lastRendererClear;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, ITimerFactory timerFactory)
|
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, ITimerFactory timerFactory)
|
||||||
{
|
{
|
||||||
|
@ -70,6 +71,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
async void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs<UpnpDeviceInfo> e)
|
async void _deviceDiscovery_DeviceDiscovered(object sender, GenericEventArgs<UpnpDeviceInfo> e)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var info = e.Argument;
|
var info = e.Argument;
|
||||||
|
|
||||||
string usn;
|
string usn;
|
||||||
|
@ -121,6 +127,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_logger.Debug("Logging session activity from location {0}", location);
|
_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)
|
var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
@ -129,6 +140,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
if (controller == null)
|
if (controller == null)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
string serverAddress;
|
string serverAddress;
|
||||||
if (info.LocalIpAddress == null)
|
if (info.LocalIpAddress == null)
|
||||||
{
|
{
|
||||||
|
@ -187,6 +203,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.ErrorException("Error creating PlayTo device.", ex);
|
_logger.ErrorException("Error creating PlayTo device.", ex);
|
||||||
|
|
||||||
|
lock (_nonRendererUrls)
|
||||||
|
{
|
||||||
|
_nonRendererUrls.Add(location);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +223,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
_disposed = true;
|
||||||
_deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered;
|
_deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace Emby.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "m4v,ts,mkv,avi,mpg,mpeg,mp4",
|
Container = "m4v,ts,mpegts,mkv,avi,mpg,mpeg,mp4,mov",
|
||||||
VideoCodec = "h264",
|
VideoCodec = "h264",
|
||||||
AudioCodec = "aac,mp3,ac3",
|
AudioCodec = "aac,mp3,ac3",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
@ -72,7 +72,7 @@ namespace Emby.Dlna.Profiles
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp3,wma,aac,wav",
|
Container = "mp3,wma,aac,wav,flac",
|
||||||
Type = DlnaProfileType.Audio
|
Type = DlnaProfileType.Audio
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace Emby.Dlna.Profiles
|
||||||
},
|
},
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4",
|
Container = "mp4,m4v",
|
||||||
VideoCodec = "h264,mpeg4",
|
VideoCodec = "h264,mpeg4",
|
||||||
AudioCodec = "aac,ac3,mp3,dca,dts",
|
AudioCodec = "aac,ac3,mp3,dca,dts",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
@ -203,7 +203,15 @@ namespace Emby.Dlna.Profiles
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ResponseProfiles = new ResponseProfile[] { };
|
ResponseProfiles = new ResponseProfile[]
|
||||||
|
{
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,12 +26,20 @@ namespace Emby.Dlna.Profiles
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "avi,mp4,mkv,ts",
|
Container = "avi,mp4,mkv,ts,m4v",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ResponseProfiles = new ResponseProfile[] { };
|
ResponseProfiles = new ResponseProfile[]
|
||||||
|
{
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace Emby.Dlna.Profiles
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4",
|
Container = "mp4,m4v",
|
||||||
VideoCodec = "h264",
|
VideoCodec = "h264",
|
||||||
AudioCodec = "aac,ac3,mp3,pcm",
|
AudioCodec = "aac,ac3,mp3,pcm",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
@ -208,6 +208,12 @@ namespace Emby.Dlna.Profiles
|
||||||
Container = "ts",
|
Container = "ts",
|
||||||
OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
|
OrgPn = "MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO",
|
||||||
MimeType = "video/vnd.dlna.mpeg-tts"
|
MimeType = "video/vnd.dlna.mpeg-tts"
|
||||||
|
},
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace Emby.Dlna.Profiles
|
||||||
{
|
{
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4,mov",
|
Container = "mp4,mov,m4v",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video,
|
||||||
VideoCodec = "h264,mpeg4",
|
VideoCodec = "h264,mpeg4",
|
||||||
AudioCodec = "aac"
|
AudioCodec = "aac"
|
||||||
|
@ -201,7 +201,15 @@ namespace Emby.Dlna.Profiles
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ResponseProfiles = new ResponseProfile[] { };
|
ResponseProfiles = new ResponseProfile[]
|
||||||
|
{
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace Emby.Dlna.Profiles
|
||||||
AudioCodec = "ac3",
|
AudioCodec = "ac3",
|
||||||
VideoCodec = "h264",
|
VideoCodec = "h264",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video,
|
||||||
EstimateContentLength = true
|
EstimateContentLength = false
|
||||||
},
|
},
|
||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
|
@ -77,7 +77,7 @@ namespace Emby.Dlna.Profiles
|
||||||
},
|
},
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4",
|
Container = "mp4,m4v",
|
||||||
VideoCodec = "h264,mpeg4",
|
VideoCodec = "h264,mpeg4",
|
||||||
AudioCodec = "mp3,aac",
|
AudioCodec = "mp3,aac",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
@ -335,6 +335,12 @@ namespace Emby.Dlna.Profiles
|
||||||
Container = "flac",
|
Container = "flac",
|
||||||
MimeType = "audio/x-flac",
|
MimeType = "audio/x-flac",
|
||||||
Type = DlnaProfileType.Audio
|
Type = DlnaProfileType.Audio
|
||||||
|
},
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
120
Emby.Dlna/Profiles/SharpSmartTvProfile.cs
Normal file
120
Emby.Dlna/Profiles/SharpSmartTvProfile.cs
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
namespace Emby.Dlna.Profiles
|
||||||
|
{
|
||||||
|
[XmlRoot("Profile")]
|
||||||
|
public class SharpSmartTvProfile : DefaultProfile
|
||||||
|
{
|
||||||
|
public SharpSmartTvProfile()
|
||||||
|
{
|
||||||
|
Name = "Sharp Smart TV";
|
||||||
|
|
||||||
|
RequiresPlainFolders = true;
|
||||||
|
RequiresPlainVideoItems = true;
|
||||||
|
|
||||||
|
Identification = new DeviceIdentification
|
||||||
|
{
|
||||||
|
Manufacturer = "Sharp",
|
||||||
|
|
||||||
|
Headers = new[]
|
||||||
|
{
|
||||||
|
new HttpHeaderInfo
|
||||||
|
{
|
||||||
|
Name = "User-Agent",
|
||||||
|
Value = "Sharp",
|
||||||
|
Match = HeaderMatchType.Substring
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TranscodingProfiles = new[]
|
||||||
|
{
|
||||||
|
new TranscodingProfile
|
||||||
|
{
|
||||||
|
Container = "mp3",
|
||||||
|
AudioCodec = "mp3",
|
||||||
|
Type = DlnaProfileType.Audio
|
||||||
|
},
|
||||||
|
|
||||||
|
new TranscodingProfile
|
||||||
|
{
|
||||||
|
Container = "ts",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
AudioCodec = "ac3,aac,mp3,dts,dca",
|
||||||
|
VideoCodec = "h264",
|
||||||
|
EnableMpegtsM2TsMode = true
|
||||||
|
},
|
||||||
|
|
||||||
|
new TranscodingProfile
|
||||||
|
{
|
||||||
|
Container = "jpeg",
|
||||||
|
Type = DlnaProfileType.Photo
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DirectPlayProfiles = new[]
|
||||||
|
{
|
||||||
|
new DirectPlayProfile
|
||||||
|
{
|
||||||
|
Container = "m4v,mkv,avi,mov,mp4",
|
||||||
|
VideoCodec = "h264,mpeg4",
|
||||||
|
AudioCodec = "aac,mp3,ac3,dts,dca",
|
||||||
|
Type = DlnaProfileType.Video
|
||||||
|
},
|
||||||
|
|
||||||
|
new DirectPlayProfile
|
||||||
|
{
|
||||||
|
Container = "asf,wmv",
|
||||||
|
Type = DlnaProfileType.Video
|
||||||
|
},
|
||||||
|
|
||||||
|
new DirectPlayProfile
|
||||||
|
{
|
||||||
|
Container = "mpg,mpeg",
|
||||||
|
VideoCodec = "mpeg2video",
|
||||||
|
AudioCodec = "mp3,aac",
|
||||||
|
Type = DlnaProfileType.Video
|
||||||
|
},
|
||||||
|
|
||||||
|
new DirectPlayProfile
|
||||||
|
{
|
||||||
|
Container = "flv",
|
||||||
|
VideoCodec = "h264",
|
||||||
|
AudioCodec = "mp3,aac",
|
||||||
|
Type = DlnaProfileType.Video
|
||||||
|
},
|
||||||
|
|
||||||
|
new DirectPlayProfile
|
||||||
|
{
|
||||||
|
Container = "mp3,wav",
|
||||||
|
Type = DlnaProfileType.Audio
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SubtitleProfiles = new[]
|
||||||
|
{
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "srt",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed
|
||||||
|
},
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "srt",
|
||||||
|
Method = SubtitleDeliveryMethod.External
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ResponseProfiles = new[]
|
||||||
|
{
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -83,7 +83,7 @@ namespace Emby.Dlna.Profiles
|
||||||
},
|
},
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "avi,mp4",
|
Container = "avi,mp4,m4v",
|
||||||
VideoCodec = "mpeg4,h264",
|
VideoCodec = "mpeg4,h264",
|
||||||
AudioCodec = "ac3,aac,mp3,pcm",
|
AudioCodec = "ac3,aac,mp3,pcm",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
@ -248,6 +248,13 @@ namespace Emby.Dlna.Profiles
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
|
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
MimeType = "video/mpeg",
|
||||||
|
Type = DlnaProfileType.Video
|
||||||
|
},
|
||||||
|
|
||||||
new ResponseProfile
|
new ResponseProfile
|
||||||
{
|
{
|
||||||
Container = "mpeg",
|
Container = "mpeg",
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace Emby.Dlna.Profiles
|
||||||
},
|
},
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4",
|
Container = "mp4,m4v",
|
||||||
VideoCodec = "h264,mpeg4",
|
VideoCodec = "h264,mpeg4",
|
||||||
AudioCodec = "ac3,aac,mp3",
|
AudioCodec = "ac3,aac,mp3",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
@ -211,6 +211,12 @@ namespace Emby.Dlna.Profiles
|
||||||
MimeType = "video/mpeg",
|
MimeType = "video/mpeg",
|
||||||
OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
|
OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
},
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace Emby.Dlna.Profiles
|
||||||
},
|
},
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4",
|
Container = "mp4,m4v",
|
||||||
VideoCodec = "h264,mpeg4",
|
VideoCodec = "h264,mpeg4",
|
||||||
AudioCodec = "ac3,aac,mp3,mp2",
|
AudioCodec = "ac3,aac,mp3,mp2",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
@ -199,6 +199,12 @@ namespace Emby.Dlna.Profiles
|
||||||
MimeType = "video/mpeg",
|
MimeType = "video/mpeg",
|
||||||
OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
|
OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
},
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace Emby.Dlna.Profiles
|
||||||
},
|
},
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4",
|
Container = "mp4,m4v",
|
||||||
VideoCodec = "h264,mpeg4",
|
VideoCodec = "h264,mpeg4",
|
||||||
AudioCodec = "ac3,eac3,aac,mp3,mp2",
|
AudioCodec = "ac3,eac3,aac,mp3,mp2",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
@ -255,6 +255,12 @@ namespace Emby.Dlna.Profiles
|
||||||
MimeType = "video/mpeg",
|
MimeType = "video/mpeg",
|
||||||
OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
|
OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
},
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace Emby.Dlna.Profiles
|
||||||
},
|
},
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4",
|
Container = "mp4,m4v",
|
||||||
VideoCodec = "h264,mpeg4",
|
VideoCodec = "h264,mpeg4",
|
||||||
AudioCodec = "ac3,eac3,aac,mp3,mp2",
|
AudioCodec = "ac3,eac3,aac,mp3,mp2",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
@ -255,6 +255,12 @@ namespace Emby.Dlna.Profiles
|
||||||
MimeType = "video/mpeg",
|
MimeType = "video/mpeg",
|
||||||
OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
|
OrgPn="MPEG_PS_NTSC,MPEG_PS_PAL",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
},
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace Emby.Dlna.Profiles
|
||||||
},
|
},
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4,mkv",
|
Container = "mp4,mkv,m4v",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video,
|
||||||
VideoCodec = "h264,mpeg4",
|
VideoCodec = "h264,mpeg4",
|
||||||
AudioCodec = "aac,ac3"
|
AudioCodec = "aac,ac3"
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -253,6 +255,13 @@ namespace Emby.Dlna.Profiles
|
||||||
Container = "wav",
|
Container = "wav",
|
||||||
MimeType = "audio/wav",
|
MimeType = "audio/wav",
|
||||||
Type = DlnaProfileType.Audio
|
Type = DlnaProfileType.Audio
|
||||||
|
},
|
||||||
|
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace Emby.Dlna.Profiles
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4,mov",
|
Container = "mp4,mov,m4v",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video,
|
||||||
VideoCodec = "h264,mpeg4",
|
VideoCodec = "h264,mpeg4",
|
||||||
AudioCodec = "ac3,aac,mp2,mp3,dca,dts"
|
AudioCodec = "ac3,aac,mp2,mp3,dca,dts"
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace Emby.Dlna.Profiles
|
||||||
},
|
},
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp4,mov,mkv",
|
Container = "mp4,mov,mkv,m4v",
|
||||||
VideoCodec = "h264,mpeg4,mpeg2video",
|
VideoCodec = "h264,mpeg4,mpeg2video",
|
||||||
AudioCodec = "aac,ac3",
|
AudioCodec = "aac,ac3",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
@ -349,6 +349,12 @@ namespace Emby.Dlna.Profiles
|
||||||
Container = "avi",
|
Container = "avi",
|
||||||
MimeType = "video/avi",
|
MimeType = "video/avi",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
|
},
|
||||||
|
new ResponseProfile
|
||||||
|
{
|
||||||
|
Container = "m4v",
|
||||||
|
Type = DlnaProfileType.Video,
|
||||||
|
MimeType = "video/mp4"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="m4v,ts,mkv,avi,mpg,mpeg,mp4" audioCodec="aac,mp3,ac3" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="m4v,ts,mpegts,mkv,avi,mpg,mpeg,mp4,mov" audioCodec="aac,mp3,ac3" videoCodec="h264" type="Video" />
|
||||||
<DirectPlayProfile container="mp3,wma,aac,wav" type="Audio" />
|
<DirectPlayProfile container="mp3,wma,aac,wav,flac" type="Audio" />
|
||||||
</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="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="ts" audioCodec="aac,ac3,mp3,dca,dts" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="aac,ac3,mp3,dca,dts" videoCodec="h264" type="Video" />
|
||||||
<DirectPlayProfile container="mkv" audioCodec="aac,ac3,mp3,dca,dts" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="mkv" audioCodec="aac,ac3,mp3,dca,dts" videoCodec="h264" type="Video" />
|
||||||
<DirectPlayProfile container="mp4" audioCodec="aac,ac3,mp3,dca,dts" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="mp4,m4v" audioCodec="aac,ac3,mp3,dca,dts" videoCodec="h264,mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="mp3" type="Audio" />
|
<DirectPlayProfile container="mp3" type="Audio" />
|
||||||
<DirectPlayProfile container="jpeg" type="Photo" />
|
<DirectPlayProfile container="jpeg" type="Photo" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
|
@ -79,7 +79,11 @@
|
||||||
<ApplyConditions />
|
<ApplyConditions />
|
||||||
</CodecProfile>
|
</CodecProfile>
|
||||||
</CodecProfiles>
|
</CodecProfiles>
|
||||||
<ResponseProfiles />
|
<ResponseProfiles>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
|
</ResponseProfiles>
|
||||||
<SubtitleProfiles>
|
<SubtitleProfiles>
|
||||||
<SubtitleProfile format="srt" method="Embed" />
|
<SubtitleProfile format="srt" method="Embed" />
|
||||||
<SubtitleProfile format="srt" method="External" />
|
<SubtitleProfile format="srt" method="External" />
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
|
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
|
||||||
<DirectPlayProfile container="avi,mp4,mkv,ts" type="Video" />
|
<DirectPlayProfile container="avi,mp4,mkv,ts,m4v" type="Video" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
||||||
|
@ -43,7 +43,11 @@
|
||||||
</TranscodingProfiles>
|
</TranscodingProfiles>
|
||||||
<ContainerProfiles />
|
<ContainerProfiles />
|
||||||
<CodecProfiles />
|
<CodecProfiles />
|
||||||
<ResponseProfiles />
|
<ResponseProfiles>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
|
</ResponseProfiles>
|
||||||
<SubtitleProfiles>
|
<SubtitleProfiles>
|
||||||
<SubtitleProfile format="srt" method="Embed" />
|
<SubtitleProfile format="srt" method="Embed" />
|
||||||
</SubtitleProfiles>
|
</SubtitleProfiles>
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
<DirectPlayProfile container="mpeg,mpg" audioCodec="ac3,mp3,pcm_dvd" videoCodec="mpeg2video,mpeg4" type="Video" />
|
<DirectPlayProfile container="mpeg,mpg" audioCodec="ac3,mp3,pcm_dvd" videoCodec="mpeg2video,mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="mkv" audioCodec="aac,ac3,dca,mp3,mp2,pcm,dts" videoCodec="h264,mpeg2video" type="Video" />
|
<DirectPlayProfile container="mkv" audioCodec="aac,ac3,dca,mp3,mp2,pcm,dts" videoCodec="h264,mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="ts" audioCodec="aac,mp3,mp2" videoCodec="h264,mpeg2video" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="aac,mp3,mp2" videoCodec="h264,mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="mp4" audioCodec="aac,ac3,mp3,pcm" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="mp4,m4v" audioCodec="aac,ac3,mp3,pcm" videoCodec="h264" type="Video" />
|
||||||
<DirectPlayProfile container="mov" audioCodec="aac,pcm" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="mov" audioCodec="aac,pcm" videoCodec="h264" type="Video" />
|
||||||
<DirectPlayProfile container="avi" audioCodec="pcm" videoCodec="mpeg4" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="pcm" videoCodec="mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="flv" audioCodec="aac" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="flv" audioCodec="aac" videoCodec="h264" type="Video" />
|
||||||
|
@ -76,6 +76,9 @@
|
||||||
<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" type="Video" orgPn="MPEG_TS_SD_EU,MPEG_TS_SD_NA,MPEG_TS_SD_KO" mimeType="video/vnd.dlna.mpeg-tts">
|
||||||
<Conditions />
|
<Conditions />
|
||||||
</ResponseProfile>
|
</ResponseProfile>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
</ResponseProfiles>
|
</ResponseProfiles>
|
||||||
<SubtitleProfiles>
|
<SubtitleProfiles>
|
||||||
<SubtitleProfile format="srt" method="Embed" />
|
<SubtitleProfile format="srt" method="Embed" />
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
|
||||||
<XmlRootAttributes />
|
<XmlRootAttributes />
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="mp4,mov" audioCodec="aac" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="mp4,mov,m4v" audioCodec="aac" videoCodec="h264,mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="ts" audioCodec="aac,ac3,eac3,mp3,mp2,pcm" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="aac,ac3,eac3,mp3,mp2,pcm" videoCodec="h264" type="Video" />
|
||||||
<DirectPlayProfile container="asf,wmv" audioCodec="wmav2,wmapro" videoCodec="wmv3,vc1" type="Video" />
|
<DirectPlayProfile container="asf,wmv" audioCodec="wmav2,wmapro" videoCodec="wmv3,vc1" type="Video" />
|
||||||
<DirectPlayProfile container="avi" audioCodec="mp3,ac3,eac3,mp2,pcm" videoCodec="mpeg4,msmpeg4" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="mp3,ac3,eac3,mp2,pcm" videoCodec="mpeg4,msmpeg4" type="Video" />
|
||||||
|
@ -81,7 +81,11 @@
|
||||||
<ApplyConditions />
|
<ApplyConditions />
|
||||||
</CodecProfile>
|
</CodecProfile>
|
||||||
</CodecProfiles>
|
</CodecProfiles>
|
||||||
<ResponseProfiles />
|
<ResponseProfiles>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
|
</ResponseProfiles>
|
||||||
<SubtitleProfiles>
|
<SubtitleProfiles>
|
||||||
<SubtitleProfile format="srt" method="Embed" />
|
<SubtitleProfile format="srt" method="Embed" />
|
||||||
</SubtitleProfiles>
|
</SubtitleProfiles>
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
<DirectPlayProfile container="asf" audioCodec="mp3,ac3,wmav2,wmapro,wmavoice" videoCodec="h264,mpeg4,mjpeg" type="Video" />
|
<DirectPlayProfile container="asf" audioCodec="mp3,ac3,wmav2,wmapro,wmavoice" videoCodec="h264,mpeg4,mjpeg" type="Video" />
|
||||||
<DirectPlayProfile container="avi" audioCodec="mp3,ac3,dca,dts" videoCodec="h264,mpeg4,mjpeg" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="mp3,ac3,dca,dts" videoCodec="h264,mpeg4,mjpeg" type="Video" />
|
||||||
<DirectPlayProfile container="mkv" audioCodec="mp3,ac3,dca,aac,dts" videoCodec="h264,mpeg4,mjpeg4" type="Video" />
|
<DirectPlayProfile container="mkv" audioCodec="mp3,ac3,dca,aac,dts" videoCodec="h264,mpeg4,mjpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="mp4" audioCodec="mp3,aac" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="mp4,m4v" audioCodec="mp3,aac" videoCodec="h264,mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="3gp" audioCodec="aac,he-aac" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="3gp" audioCodec="aac,he-aac" videoCodec="h264,mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="mpg,mpeg" audioCodec="ac3,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
|
<DirectPlayProfile container="mpg,mpeg" audioCodec="ac3,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
|
||||||
<DirectPlayProfile container="vro,vob" audioCodec="ac3,mp2,mp3" videoCodec="mpeg1video,mpeg2video" type="Video" />
|
<DirectPlayProfile container="vro,vob" audioCodec="ac3,mp2,mp3" videoCodec="mpeg1video,mpeg2video" type="Video" />
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
||||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="true" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" />
|
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" 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>
|
||||||
<ContainerProfiles>
|
<ContainerProfiles>
|
||||||
|
@ -117,6 +117,9 @@
|
||||||
<ResponseProfile container="flac" type="Audio" mimeType="audio/x-flac">
|
<ResponseProfile container="flac" type="Audio" mimeType="audio/x-flac">
|
||||||
<Conditions />
|
<Conditions />
|
||||||
</ResponseProfile>
|
</ResponseProfile>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
</ResponseProfiles>
|
</ResponseProfiles>
|
||||||
<SubtitleProfiles>
|
<SubtitleProfiles>
|
||||||
<SubtitleProfile format="srt" method="Embed" />
|
<SubtitleProfile format="srt" method="Embed" />
|
||||||
|
|
60
Emby.Dlna/Profiles/Xml/Sharp Smart TV.xml
Normal file
60
Emby.Dlna/Profiles/Xml/Sharp Smart TV.xml
Normal file
File diff suppressed because one or more lines are too long
|
@ -41,7 +41,7 @@
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3,pcm" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3,pcm" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
|
||||||
<DirectPlayProfile container="mpeg" audioCodec="ac3,mp3,pcm" videoCodec="mpeg1video,mpeg2video" type="Video" />
|
<DirectPlayProfile container="mpeg" audioCodec="ac3,mp3,pcm" videoCodec="mpeg1video,mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="avi,mp4" audioCodec="ac3,aac,mp3,pcm" videoCodec="mpeg4,h264" type="Video" />
|
<DirectPlayProfile container="avi,mp4,m4v" audioCodec="ac3,aac,mp3,pcm" videoCodec="mpeg4,h264" type="Video" />
|
||||||
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
|
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
|
||||||
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
|
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
|
||||||
<DirectPlayProfile container="jpeg" type="Photo" />
|
<DirectPlayProfile container="jpeg" type="Photo" />
|
||||||
|
@ -99,6 +99,9 @@
|
||||||
<ResponseProfile container="mp4" type="Video" mimeType="video/mpeg">
|
<ResponseProfile container="mp4" type="Video" mimeType="video/mpeg">
|
||||||
<Conditions />
|
<Conditions />
|
||||||
</ResponseProfile>
|
</ResponseProfile>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mpeg">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
<ResponseProfile container="mpeg" type="Video" mimeType="video/mpeg">
|
<ResponseProfile container="mpeg" type="Video" mimeType="video/mpeg">
|
||||||
<Conditions />
|
<Conditions />
|
||||||
</ResponseProfile>
|
</ResponseProfile>
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
|
||||||
<DirectPlayProfile container="ts" audioCodec="mp3" videoCodec="mpeg2video" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="mp3" videoCodec="mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="mp4" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="mp4,m4v" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="mpeg" audioCodec="mp3" videoCodec="mpeg2video,mpeg1video" type="Video" />
|
<DirectPlayProfile container="mpeg" audioCodec="mp3" videoCodec="mpeg2video,mpeg1video" type="Video" />
|
||||||
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" />
|
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" />
|
||||||
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
|
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
|
||||||
|
@ -129,6 +129,9 @@
|
||||||
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
|
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
|
||||||
<Conditions />
|
<Conditions />
|
||||||
</ResponseProfile>
|
</ResponseProfile>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
</ResponseProfiles>
|
</ResponseProfiles>
|
||||||
<SubtitleProfiles>
|
<SubtitleProfiles>
|
||||||
<SubtitleProfile format="srt" method="Embed" />
|
<SubtitleProfile format="srt" method="Embed" />
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264" type="Video" />
|
||||||
<DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="mp4" audioCodec="ac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="mp4,m4v" audioCodec="ac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="mpeg" audioCodec="mp3,mp2" videoCodec="mpeg2video,mpeg1video" type="Video" />
|
<DirectPlayProfile container="mpeg" audioCodec="mp3,mp2" videoCodec="mpeg2video,mpeg1video" type="Video" />
|
||||||
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" />
|
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" />
|
||||||
|
@ -105,6 +105,9 @@
|
||||||
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
|
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
|
||||||
<Conditions />
|
<Conditions />
|
||||||
</ResponseProfile>
|
</ResponseProfile>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
</ResponseProfiles>
|
</ResponseProfiles>
|
||||||
<SubtitleProfiles>
|
<SubtitleProfiles>
|
||||||
<SubtitleProfile format="srt" method="Embed" />
|
<SubtitleProfile format="srt" method="Embed" />
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="ts" audioCodec="ac3,eac3,aac,mp3" videoCodec="h264" type="Video" />
|
<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" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="mp4" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="mp4,m4v" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="mov" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4,mjpeg" type="Video" />
|
<DirectPlayProfile container="mov" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4,mjpeg" type="Video" />
|
||||||
<DirectPlayProfile container="mkv" audioCodec="ac3,eac3,aac,mp3,mp2,pcm,vorbis" videoCodec="h264,mpeg4,vp8" type="Video" />
|
<DirectPlayProfile container="mkv" audioCodec="ac3,eac3,aac,mp3,mp2,pcm,vorbis" videoCodec="h264,mpeg4,vp8" type="Video" />
|
||||||
<DirectPlayProfile container="avi" audioCodec="ac3,eac3,mp3" videoCodec="mpeg4" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="ac3,eac3,mp3" videoCodec="mpeg4" type="Video" />
|
||||||
|
@ -104,6 +104,9 @@
|
||||||
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
|
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
|
||||||
<Conditions />
|
<Conditions />
|
||||||
</ResponseProfile>
|
</ResponseProfile>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
</ResponseProfiles>
|
</ResponseProfiles>
|
||||||
<SubtitleProfiles>
|
<SubtitleProfiles>
|
||||||
<SubtitleProfile format="srt" method="Embed" />
|
<SubtitleProfile format="srt" method="Embed" />
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
<DirectPlayProfiles>
|
<DirectPlayProfiles>
|
||||||
<DirectPlayProfile container="ts" audioCodec="ac3,eac3,aac,mp3" videoCodec="h264" type="Video" />
|
<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" audioCodec="mp3,mp2" videoCodec="mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="mp4" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="mp4,m4v" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="mov" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4,mjpeg" type="Video" />
|
<DirectPlayProfile container="mov" audioCodec="ac3,eac3,aac,mp3,mp2" videoCodec="h264,mpeg4,mjpeg" type="Video" />
|
||||||
<DirectPlayProfile container="mkv" audioCodec="ac3,eac3,aac,mp3,mp2,pcm,vorbis" videoCodec="h264,mpeg4,vp8" type="Video" />
|
<DirectPlayProfile container="mkv" audioCodec="ac3,eac3,aac,mp3,mp2,pcm,vorbis" videoCodec="h264,mpeg4,vp8" type="Video" />
|
||||||
<DirectPlayProfile container="avi" audioCodec="ac3,eac3,mp3" videoCodec="mpeg4" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="ac3,eac3,mp3" videoCodec="mpeg4" type="Video" />
|
||||||
|
@ -104,6 +104,9 @@
|
||||||
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
|
<ResponseProfile container="mpeg" videoCodec="mpeg1video,mpeg2video" type="Video" orgPn="MPEG_PS_NTSC,MPEG_PS_PAL" mimeType="video/mpeg">
|
||||||
<Conditions />
|
<Conditions />
|
||||||
</ResponseProfile>
|
</ResponseProfile>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
</ResponseProfiles>
|
</ResponseProfiles>
|
||||||
<SubtitleProfiles>
|
<SubtitleProfiles>
|
||||||
<SubtitleProfile format="srt" method="Embed" />
|
<SubtitleProfile format="srt" method="Embed" />
|
||||||
|
|
|
@ -40,12 +40,12 @@
|
||||||
<DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="mp2,mp3" videoCodec="mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="ts" audioCodec="ac3,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="ac3,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264" type="Video" />
|
||||||
<DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg1video,mpeg2video" type="Video" />
|
<DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg1video,mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="mp4,mkv" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="mp4,mkv,m4v" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="aac,mp3,wav" type="Audio" />
|
<DirectPlayProfile container="aac,mp3,wav" type="Audio" />
|
||||||
<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>
|
||||||
|
@ -98,6 +98,9 @@
|
||||||
<ResponseProfile container="wav" type="Audio" mimeType="audio/wav">
|
<ResponseProfile container="wav" type="Audio" mimeType="audio/wav">
|
||||||
<Conditions />
|
<Conditions />
|
||||||
</ResponseProfile>
|
</ResponseProfile>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
</ResponseProfiles>
|
</ResponseProfiles>
|
||||||
<SubtitleProfiles>
|
<SubtitleProfiles>
|
||||||
<SubtitleProfile format="srt" method="Embed" />
|
<SubtitleProfile format="srt" method="Embed" />
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
<DirectPlayProfile container="mpeg" audioCodec="ac3,dca,mp2,mp3,pcm,dts" videoCodec="mpeg1video,mpeg2video" type="Video" />
|
<DirectPlayProfile container="mpeg" audioCodec="ac3,dca,mp2,mp3,pcm,dts" videoCodec="mpeg1video,mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="mkv" audioCodec="ac3,dca,aac,mp2,mp3,pcm,dts" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
|
<DirectPlayProfile container="mkv" audioCodec="ac3,dca,aac,mp2,mp3,pcm,dts" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
|
||||||
<DirectPlayProfile container="ts,m2ts" audioCodec="ac3,dca,mp2,mp3,aac,dts" videoCodec="mpeg1video,mpeg2video,h264,vc1" type="Video" />
|
<DirectPlayProfile container="ts,m2ts" audioCodec="ac3,dca,mp2,mp3,aac,dts" videoCodec="mpeg1video,mpeg2video,h264,vc1" type="Video" />
|
||||||
<DirectPlayProfile container="mp4,mov" audioCodec="ac3,aac,mp2,mp3,dca,dts" videoCodec="h264,mpeg4" type="Video" />
|
<DirectPlayProfile container="mp4,mov,m4v" audioCodec="ac3,aac,mp2,mp3,dca,dts" videoCodec="h264,mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="vc1" type="Video" />
|
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="vc1" type="Video" />
|
||||||
<DirectPlayProfile container="asf" audioCodec="mp2,ac3" videoCodec="mpeg2video" type="Video" />
|
<DirectPlayProfile container="asf" audioCodec="mp2,ac3" videoCodec="mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
|
<DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" />
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg2video" type="Video" />
|
<DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
|
||||||
<DirectPlayProfile container="avi" audioCodec="aac" videoCodec="h264" type="Video" />
|
<DirectPlayProfile container="avi" audioCodec="aac" videoCodec="h264" type="Video" />
|
||||||
<DirectPlayProfile container="mp4,mov,mkv" audioCodec="aac,ac3" videoCodec="h264,mpeg4,mpeg2video" type="Video" />
|
<DirectPlayProfile container="mp4,mov,mkv,m4v" audioCodec="aac,ac3" videoCodec="h264,mpeg4,mpeg2video" type="Video" />
|
||||||
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="wmv2,wmv3,vc1" type="Video" />
|
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="wmv2,wmv3,vc1" type="Video" />
|
||||||
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
|
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
|
||||||
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
|
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
|
||||||
|
@ -116,6 +116,9 @@
|
||||||
<ResponseProfile container="avi" type="Video" mimeType="video/avi">
|
<ResponseProfile container="avi" type="Video" mimeType="video/avi">
|
||||||
<Conditions />
|
<Conditions />
|
||||||
</ResponseProfile>
|
</ResponseProfile>
|
||||||
|
<ResponseProfile container="m4v" type="Video" mimeType="video/mp4">
|
||||||
|
<Conditions />
|
||||||
|
</ResponseProfile>
|
||||||
</ResponseProfiles>
|
</ResponseProfiles>
|
||||||
<SubtitleProfiles>
|
<SubtitleProfiles>
|
||||||
<SubtitleProfile format="srt" method="Embed" />
|
<SubtitleProfile format="srt" method="Embed" />
|
||||||
|
|
|
@ -104,7 +104,8 @@ namespace Emby.Dlna.Ssdp
|
||||||
Argument = new UpnpDeviceInfo
|
Argument = new UpnpDeviceInfo
|
||||||
{
|
{
|
||||||
Location = e.DiscoveredDevice.DescriptionLocation,
|
Location = e.DiscoveredDevice.DescriptionLocation,
|
||||||
Headers = headers
|
Headers = headers,
|
||||||
|
LocalIpAddress = e.LocalIpAddress
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -326,6 +326,8 @@ namespace Emby.Server.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract bool IsRunningAsService { get; }
|
||||||
|
|
||||||
private Assembly GetAssembly(Type type)
|
private Assembly GetAssembly(Type type)
|
||||||
{
|
{
|
||||||
return type.GetTypeInfo().Assembly;
|
return type.GetTypeInfo().Assembly;
|
||||||
|
@ -489,7 +491,8 @@ namespace Emby.Server.Core
|
||||||
{
|
{
|
||||||
var migrations = new List<IVersionMigration>
|
var migrations = new List<IVersionMigration>
|
||||||
{
|
{
|
||||||
new LibraryScanMigration(ServerConfigurationManager, TaskManager)
|
new LibraryScanMigration(ServerConfigurationManager, TaskManager),
|
||||||
|
new GuideMigration(ServerConfigurationManager, TaskManager)
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var task in migrations)
|
foreach (var task in migrations)
|
||||||
|
@ -1247,7 +1250,6 @@ namespace Emby.Server.Core
|
||||||
HasUpdateAvailable = HasUpdateAvailable,
|
HasUpdateAvailable = HasUpdateAvailable,
|
||||||
SupportsAutoRunAtStartup = SupportsAutoRunAtStartup,
|
SupportsAutoRunAtStartup = SupportsAutoRunAtStartup,
|
||||||
TranscodingTempPath = ApplicationPaths.TranscodingTempPath,
|
TranscodingTempPath = ApplicationPaths.TranscodingTempPath,
|
||||||
IsRunningAsService = IsRunningAsService,
|
|
||||||
SupportsRunningAsService = SupportsRunningAsService,
|
SupportsRunningAsService = SupportsRunningAsService,
|
||||||
ServerName = FriendlyName,
|
ServerName = FriendlyName,
|
||||||
LocalAddress = localAddress,
|
LocalAddress = localAddress,
|
||||||
|
@ -1476,6 +1478,10 @@ namespace Emby.Server.Core
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AuthorizeServer();
|
AuthorizeServer();
|
||||||
|
}
|
||||||
|
catch (NotImplementedException)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,6 +11,7 @@ using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
using Mono.Nat;
|
using Mono.Nat;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Emby.Server.Core.EntryPoints
|
namespace Emby.Server.Core.EntryPoints
|
||||||
{
|
{
|
||||||
|
@ -106,6 +107,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 +175,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 +196,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;
|
||||||
|
@ -208,8 +224,13 @@ namespace Emby.Server.Core.EntryPoints
|
||||||
|
|
||||||
private List<string> _createdRules = new List<string>();
|
private List<string> _createdRules = new List<string>();
|
||||||
private List<string> _usnsHandled = new List<string>();
|
private List<string> _usnsHandled = new List<string>();
|
||||||
private void CreateRules(INatDevice device)
|
private async 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
|
||||||
|
|
||||||
|
@ -219,12 +240,16 @@ namespace Emby.Server.Core.EntryPoints
|
||||||
{
|
{
|
||||||
_createdRules.Add(address);
|
_createdRules.Add(address);
|
||||||
|
|
||||||
CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort);
|
var success = await CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort).ConfigureAwait(false);
|
||||||
CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort);
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
await CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void CreatePortMap(INatDevice device, int privatePort, int publicPort)
|
private async Task<bool> CreatePortMap(INatDevice device, int privatePort, int publicPort)
|
||||||
{
|
{
|
||||||
_logger.Debug("Creating port map on port {0}", privatePort);
|
_logger.Debug("Creating port map on port {0}", privatePort);
|
||||||
|
|
||||||
|
@ -235,10 +260,14 @@ namespace Emby.Server.Core.EntryPoints
|
||||||
Description = _appHost.Name
|
Description = _appHost.Name
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Error("Error creating port map: " + ex.Message);
|
_logger.Error("Error creating port map: " + ex.Message);
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,8 +278,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace Emby.Server.Core.IO
|
||||||
public bool IsPathLocked(string path)
|
public bool IsPathLocked(string path)
|
||||||
{
|
{
|
||||||
var lockedPaths = _tempIgnoredPaths.Keys.ToList();
|
var lockedPaths = _tempIgnoredPaths.Keys.ToList();
|
||||||
return lockedPaths.Any(i => string.Equals(i, path, StringComparison.OrdinalIgnoreCase) || _fileSystem.ContainsSubPath(i, path));
|
return lockedPaths.Any(i => _fileSystem.AreEqual(i, path) || _fileSystem.ContainsSubPath(i, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void ReportFileSystemChangeComplete(string path, bool refreshPath)
|
public async void ReportFileSystemChangeComplete(string path, bool refreshPath)
|
||||||
|
@ -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
|
||||||
|
|
|
@ -138,7 +138,7 @@ namespace Emby.Server.Implementations.Activity
|
||||||
|
|
||||||
CreateLogEntry(new ActivityLogEntry
|
CreateLogEntry(new ActivityLogEntry
|
||||||
{
|
{
|
||||||
Name = string.Format(_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), user.Name, item.Name),
|
Name = string.Format(_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), user.Name, Notifications.Notifications.GetItemName(item)),
|
||||||
Type = "PlaybackStopped",
|
Type = "PlaybackStopped",
|
||||||
ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName),
|
ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName),
|
||||||
UserId = user.Id.ToString("N")
|
UserId = user.Id.ToString("N")
|
||||||
|
@ -170,7 +170,7 @@ namespace Emby.Server.Implementations.Activity
|
||||||
|
|
||||||
CreateLogEntry(new ActivityLogEntry
|
CreateLogEntry(new ActivityLogEntry
|
||||||
{
|
{
|
||||||
Name = string.Format(_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), user.Name, item.Name),
|
Name = string.Format(_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), user.Name, Notifications.Notifications.GetItemName(item)),
|
||||||
Type = "PlaybackStart",
|
Type = "PlaybackStart",
|
||||||
ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName),
|
ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName),
|
||||||
UserId = user.Id.ToString("N")
|
UserId = user.Id.ToString("N")
|
||||||
|
@ -235,10 +235,6 @@ namespace Emby.Server.Implementations.Activity
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _logManager_LoggerLoaded(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
|
void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
|
||||||
{
|
{
|
||||||
CreateLogEntry(new ActivityLogEntry
|
CreateLogEntry(new ActivityLogEntry
|
||||||
|
|
|
@ -343,7 +343,7 @@ namespace Emby.Server.Implementations.Channels
|
||||||
|
|
||||||
private MediaSourceInfo GetMediaSource(BaseItem item, ChannelMediaInfo info)
|
private MediaSourceInfo GetMediaSource(BaseItem item, ChannelMediaInfo info)
|
||||||
{
|
{
|
||||||
var source = info.ToMediaSource();
|
var source = info.ToMediaSource(item.Id);
|
||||||
|
|
||||||
source.RunTimeTicks = source.RunTimeTicks ?? item.RunTimeTicks;
|
source.RunTimeTicks = source.RunTimeTicks ?? item.RunTimeTicks;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ namespace Emby.Server.Implementations.Connect
|
||||||
public class ConnectEntryPoint : IServerEntryPoint
|
public class ConnectEntryPoint : IServerEntryPoint
|
||||||
{
|
{
|
||||||
private ITimer _timer;
|
private ITimer _timer;
|
||||||
|
private IpAddressInfo _cachedIpAddress;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
@ -26,8 +28,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 +40,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,17 +147,31 @@ 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)
|
||||||
{
|
{
|
||||||
|
if (_cachedIpAddress != null && _cachedIpAddress.Equals(address))
|
||||||
|
{
|
||||||
|
// no need to update the file if the address has not changed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var path = CacheFilePath;
|
var path = CacheFilePath;
|
||||||
|
|
||||||
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);
|
||||||
|
_cachedIpAddress = address;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -169,11 +187,12 @@ 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))
|
||||||
{
|
{
|
||||||
|
_cachedIpAddress = ipAddress;
|
||||||
((ConnectManager)_connectManager).OnWanAddressResolved(ipAddress);
|
((ConnectManager)_connectManager).OnWanAddressResolved(ipAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -925,7 +925,11 @@ namespace Emby.Server.Implementations.Connect
|
||||||
}
|
}
|
||||||
|
|
||||||
_data.PendingAuthorizations = newPendingList;
|
_data.PendingAuthorizations = newPendingList;
|
||||||
|
|
||||||
|
if (!newPendingList.Select(i => i.Id).SequenceEqual(currentPendingList.Select(i => i.Id), StringComparer.Ordinal))
|
||||||
|
{
|
||||||
CacheData();
|
CacheData();
|
||||||
|
}
|
||||||
|
|
||||||
await RefreshGuestNames(list, refreshImages).ConfigureAwait(false);
|
await RefreshGuestNames(list, refreshImages).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -1118,7 +1122,7 @@ namespace Emby.Server.Implementations.Connect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Authenticate(string username, string passwordMd5)
|
public async Task<ConnectAuthenticationResult> Authenticate(string username, string passwordMd5)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(username))
|
if (string.IsNullOrWhiteSpace(username))
|
||||||
{
|
{
|
||||||
|
@ -1147,6 +1151,7 @@ namespace Emby.Server.Implementations.Connect
|
||||||
// No need to examine the response
|
// No need to examine the response
|
||||||
using (var response = (await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)).Content)
|
using (var response = (await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)).Content)
|
||||||
{
|
{
|
||||||
|
return _json.DeserializeFromStream<ConnectAuthenticationResult>(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,11 @@ namespace Emby.Server.Implementations.Data
|
||||||
var numComplete = 0;
|
var numComplete = 0;
|
||||||
var numItems = result.Count;
|
var numItems = result.Count;
|
||||||
|
|
||||||
|
var allLibraryPaths = _libraryManager
|
||||||
|
.GetVirtualFolders()
|
||||||
|
.SelectMany(i => i.Locations)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
foreach (var item in result)
|
foreach (var item in result)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
@ -170,9 +175,8 @@ namespace Emby.Server.Implementations.Data
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Folder.IsPathOffline(path))
|
if (Folder.IsPathOffline(path, allLibraryPaths))
|
||||||
{
|
{
|
||||||
await libraryItem.UpdateIsOffline(true).ConfigureAwait(false);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -372,7 +372,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
userDataRepo.Initialize(WriteLock, _connection);
|
userDataRepo.Initialize(WriteLock, _connection);
|
||||||
|
|
||||||
_shrinkMemoryTimer = _timerFactory.Create(OnShrinkMemoryTimerCallback, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(15));
|
_shrinkMemoryTimer = _timerFactory.Create(OnShrinkMemoryTimerCallback, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(30));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnShrinkMemoryTimerCallback(object state)
|
private void OnShrinkMemoryTimerCallback(object state)
|
||||||
|
@ -2384,8 +2384,17 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
var excludeIds = query.ExcludeItemIds.ToList();
|
var excludeIds = query.ExcludeItemIds.ToList();
|
||||||
excludeIds.Add(item.Id.ToString("N"));
|
excludeIds.Add(item.Id.ToString("N"));
|
||||||
query.ExcludeItemIds = excludeIds.ToArray();
|
|
||||||
|
|
||||||
|
if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Trailer).Name))
|
||||||
|
{
|
||||||
|
var hasTrailers = item as IHasTrailers;
|
||||||
|
if (hasTrailers != null)
|
||||||
|
{
|
||||||
|
excludeIds.AddRange(hasTrailers.GetTrailerIds().Select(i => i.ToString("N")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query.ExcludeItemIds = excludeIds.ToArray();
|
||||||
query.ExcludeProviderIds = item.ProviderIds;
|
query.ExcludeProviderIds = item.ProviderIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2547,12 +2556,10 @@ namespace Emby.Server.Implementations.Data
|
||||||
using (WriteLock.Read())
|
using (WriteLock.Read())
|
||||||
{
|
{
|
||||||
using (var connection = CreateConnection(true))
|
using (var connection = CreateConnection(true))
|
||||||
{
|
|
||||||
return connection.RunInTransaction(db =>
|
|
||||||
{
|
{
|
||||||
var list = new List<BaseItem>();
|
var list = new List<BaseItem>();
|
||||||
|
|
||||||
using (var statement = PrepareStatementSafe(db, commandText))
|
using (var statement = PrepareStatementSafe(connection, commandText))
|
||||||
{
|
{
|
||||||
if (EnableJoinUserData(query))
|
if (EnableJoinUserData(query))
|
||||||
{
|
{
|
||||||
|
@ -2597,8 +2604,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
LogQueryTime("GetItemList", commandText, now);
|
LogQueryTime("GetItemList", commandText, now);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
}, ReadTransactionMode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2652,7 +2657,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
{
|
{
|
||||||
//Logger.Debug("{2} query time: {0}ms. Query: {1}",
|
//Logger.Debug("{2} query time: {0}ms. Query: {1}",
|
||||||
// Convert.ToInt32(elapsed),
|
// Convert.ToInt32(elapsed),
|
||||||
// cmd.CommandText,
|
// commandText,
|
||||||
// methodName);
|
// methodName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2825,8 +2830,9 @@ namespace Emby.Server.Implementations.Data
|
||||||
{
|
{
|
||||||
if (orderBy.Count == 0)
|
if (orderBy.Count == 0)
|
||||||
{
|
{
|
||||||
orderBy.Add(new Tuple<string, SortOrder>("SimilarityScore", SortOrder.Descending));
|
|
||||||
orderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending));
|
orderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending));
|
||||||
|
orderBy.Add(new Tuple<string, SortOrder>("SimilarityScore", SortOrder.Descending));
|
||||||
|
//orderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending));
|
||||||
query.SortOrder = SortOrder.Descending;
|
query.SortOrder = SortOrder.Descending;
|
||||||
enableOrderInversion = false;
|
enableOrderInversion = false;
|
||||||
}
|
}
|
||||||
|
@ -3212,6 +3218,11 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
private List<string> GetWhereClauses(InternalItemsQuery query, IStatement statement, string paramSuffix = "")
|
private List<string> GetWhereClauses(InternalItemsQuery query, IStatement statement, string paramSuffix = "")
|
||||||
{
|
{
|
||||||
|
if (query.IsResumable ?? false)
|
||||||
|
{
|
||||||
|
query.IsVirtualItem = false;
|
||||||
|
}
|
||||||
|
|
||||||
var whereClauses = new List<string>();
|
var whereClauses = new List<string>();
|
||||||
|
|
||||||
if (EnableJoinUserData(query))
|
if (EnableJoinUserData(query))
|
||||||
|
@ -3372,9 +3383,9 @@ namespace Emby.Server.Implementations.Data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.SimilarTo != null)
|
if (query.SimilarTo != null && query.MinSimilarityScore > 0)
|
||||||
{
|
{
|
||||||
whereClauses.Add("SimilarityScore > 0");
|
whereClauses.Add("SimilarityScore > " + (query.MinSimilarityScore - 1).ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IsFolder.HasValue)
|
if (query.IsFolder.HasValue)
|
||||||
|
@ -3616,10 +3627,12 @@ namespace Emby.Server.Implementations.Data
|
||||||
var index = 0;
|
var index = 0;
|
||||||
foreach (var type in query.TrailerTypes)
|
foreach (var type in query.TrailerTypes)
|
||||||
{
|
{
|
||||||
clauses.Add("TrailerTypes like @TrailerTypes" + index);
|
var paramName = "@TrailerTypes" + index;
|
||||||
|
|
||||||
|
clauses.Add("TrailerTypes like " + paramName);
|
||||||
if (statement != null)
|
if (statement != null)
|
||||||
{
|
{
|
||||||
statement.TryBind("@TrailerTypes" + index, "%" + type + "%");
|
statement.TryBind(paramName, "%" + type + "%");
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
@ -4085,27 +4098,6 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
whereClauses.Add("LocationType in (" + val + ")");
|
whereClauses.Add("LocationType in (" + val + ")");
|
||||||
}
|
}
|
||||||
if (query.ExcludeLocationTypes.Length == 1)
|
|
||||||
{
|
|
||||||
if (query.ExcludeLocationTypes[0] == LocationType.Virtual && _config.Configuration.SchemaVersion >= 90)
|
|
||||||
{
|
|
||||||
query.IsVirtualItem = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
whereClauses.Add("LocationType<>@ExcludeLocationTypes");
|
|
||||||
if (statement != null)
|
|
||||||
{
|
|
||||||
statement.TryBind("@ExcludeLocationTypes", query.ExcludeLocationTypes[0].ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (query.ExcludeLocationTypes.Length > 1)
|
|
||||||
{
|
|
||||||
var val = string.Join(",", query.ExcludeLocationTypes.Select(i => "'" + i + "'").ToArray());
|
|
||||||
|
|
||||||
whereClauses.Add("LocationType not in (" + val + ")");
|
|
||||||
}
|
|
||||||
if (query.IsVirtualItem.HasValue)
|
if (query.IsVirtualItem.HasValue)
|
||||||
{
|
{
|
||||||
whereClauses.Add("IsVirtualItem=@IsVirtualItem");
|
whereClauses.Add("IsVirtualItem=@IsVirtualItem");
|
||||||
|
@ -4221,7 +4213,7 @@ namespace Emby.Server.Implementations.Data
|
||||||
|
|
||||||
var paramName = "@ExcludeProviderId" + index;
|
var paramName = "@ExcludeProviderId" + index;
|
||||||
//excludeIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")");
|
//excludeIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")");
|
||||||
excludeIds.Add("ProviderIds not like " + paramName);
|
excludeIds.Add("(ProviderIds is null or ProviderIds not like " + paramName + ")");
|
||||||
if (statement != null)
|
if (statement != null)
|
||||||
{
|
{
|
||||||
statement.TryBind(paramName, "%" + pair.Key + "=" + pair.Value + "%");
|
statement.TryBind(paramName, "%" + pair.Key + "=" + pair.Value + "%");
|
||||||
|
|
|
@ -361,10 +361,7 @@ namespace Emby.Server.Implementations.Dto
|
||||||
if (collectionFolder != null)
|
if (collectionFolder != null)
|
||||||
{
|
{
|
||||||
dto.OriginalCollectionType = collectionFolder.CollectionType;
|
dto.OriginalCollectionType = collectionFolder.CollectionType;
|
||||||
|
dto.CollectionType = collectionFolder.CollectionType;
|
||||||
dto.CollectionType = user == null ?
|
|
||||||
collectionFolder.CollectionType :
|
|
||||||
collectionFolder.GetViewType(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fields.Contains(ItemFields.CanDelete))
|
if (fields.Contains(ItemFields.CanDelete))
|
||||||
|
@ -1515,7 +1512,8 @@ namespace Emby.Server.Implementations.Dto
|
||||||
return artist;
|
return artist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return item.GetParent();
|
|
||||||
|
return item.DisplayParent ?? item.GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddInheritedImages(BaseItemDto dto, BaseItem item, DtoOptions options, BaseItem owner)
|
private void AddInheritedImages(BaseItemDto dto, BaseItem item, DtoOptions options, BaseItem owner)
|
||||||
|
|
|
@ -182,6 +182,7 @@
|
||||||
<Compile Include="MediaEncoder\EncodingManager.cs" />
|
<Compile Include="MediaEncoder\EncodingManager.cs" />
|
||||||
<Compile Include="Migrations\IVersionMigration.cs" />
|
<Compile Include="Migrations\IVersionMigration.cs" />
|
||||||
<Compile Include="Migrations\LibraryScanMigration.cs" />
|
<Compile Include="Migrations\LibraryScanMigration.cs" />
|
||||||
|
<Compile Include="Migrations\GuideMigration.cs" />
|
||||||
<Compile Include="Migrations\UpdateLevelMigration.cs" />
|
<Compile Include="Migrations\UpdateLevelMigration.cs" />
|
||||||
<Compile Include="News\NewsEntryPoint.cs" />
|
<Compile Include="News\NewsEntryPoint.cs" />
|
||||||
<Compile Include="News\NewsService.cs" />
|
<Compile Include="News\NewsService.cs" />
|
||||||
|
|
|
@ -6,15 +6,16 @@ using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.System;
|
using MediaBrowser.Model.System;
|
||||||
using MediaBrowser.Controller.Plugins;
|
using MediaBrowser.Controller.Plugins;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
|
using MediaBrowser.Controller;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.EntryPoints
|
namespace Emby.Server.Implementations.EntryPoints
|
||||||
{
|
{
|
||||||
public class SystemEvents : IServerEntryPoint
|
public class SystemEvents : IServerEntryPoint
|
||||||
{
|
{
|
||||||
private readonly ISystemEvents _systemEvents;
|
private readonly ISystemEvents _systemEvents;
|
||||||
private readonly IApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
|
|
||||||
public SystemEvents(ISystemEvents systemEvents, IApplicationHost appHost)
|
public SystemEvents(ISystemEvents systemEvents, IServerApplicationHost appHost)
|
||||||
{
|
{
|
||||||
_systemEvents = systemEvents;
|
_systemEvents = systemEvents;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
|
|
|
@ -10,6 +10,7 @@ using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.EntryPoints
|
namespace Emby.Server.Implementations.EntryPoints
|
||||||
|
@ -19,7 +20,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UsageEntryPoint : IServerEntryPoint
|
public class UsageEntryPoint : IServerEntryPoint
|
||||||
{
|
{
|
||||||
private readonly IApplicationHost _applicationHost;
|
private readonly IServerApplicationHost _applicationHost;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
|
@ -28,7 +29,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<Guid, ClientInfo> _apps = new ConcurrentDictionary<Guid, ClientInfo>();
|
private readonly ConcurrentDictionary<Guid, ClientInfo> _apps = new ConcurrentDictionary<Guid, ClientInfo>();
|
||||||
|
|
||||||
public UsageEntryPoint(ILogger logger, IApplicationHost applicationHost, IHttpClient httpClient, ISessionManager sessionManager, IUserManager userManager, IServerConfigurationManager config)
|
public UsageEntryPoint(ILogger logger, IServerApplicationHost applicationHost, IHttpClient httpClient, ISessionManager sessionManager, IUserManager userManager, IServerConfigurationManager config)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_applicationHost = applicationHost;
|
_applicationHost = applicationHost;
|
||||||
|
|
|
@ -8,19 +8,20 @@ using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.EntryPoints
|
namespace Emby.Server.Implementations.EntryPoints
|
||||||
{
|
{
|
||||||
public class UsageReporter
|
public class UsageReporter
|
||||||
{
|
{
|
||||||
private readonly IApplicationHost _applicationHost;
|
private readonly IServerApplicationHost _applicationHost;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private const string MbAdminUrl = "https://www.mb3admin.com/admin/";
|
private const string MbAdminUrl = "https://www.mb3admin.com/admin/";
|
||||||
|
|
||||||
public UsageReporter(IApplicationHost applicationHost, IHttpClient httpClient, IUserManager userManager, ILogger logger)
|
public UsageReporter(IServerApplicationHost applicationHost, IHttpClient httpClient, IUserManager userManager, ILogger logger)
|
||||||
{
|
{
|
||||||
_applicationHost = applicationHost;
|
_applicationHost = applicationHost;
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
|
|
|
@ -188,11 +188,13 @@ namespace Emby.Server.Implementations.FileOrganization
|
||||||
seriesFolderName = string.Format("{0} ({1})", seriesFolderName, series.ProductionYear);
|
seriesFolderName = string.Format("{0} ({1})", seriesFolderName, series.ProductionYear);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seriesFolderName = _fileSystem.GetValidFilename(seriesFolderName);
|
||||||
|
|
||||||
series.Path = Path.Combine(request.TargetFolder, seriesFolderName);
|
series.Path = Path.Combine(request.TargetFolder, seriesFolderName);
|
||||||
|
|
||||||
series.ProviderIds = request.NewSeriesProviderIds;
|
series.ProviderIds = request.NewSeriesProviderIds;
|
||||||
|
|
||||||
await series.RefreshMetadata(refreshOptions, cancellationToken);
|
await series.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (series == null)
|
if (series == null)
|
||||||
|
|
|
@ -49,6 +49,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
string device = null;
|
string device = null;
|
||||||
string client = null;
|
string client = null;
|
||||||
string version = null;
|
string version = null;
|
||||||
|
string token = null;
|
||||||
|
|
||||||
if (auth != null)
|
if (auth != null)
|
||||||
{
|
{
|
||||||
|
@ -56,9 +57,13 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
auth.TryGetValue("Device", out device);
|
auth.TryGetValue("Device", out device);
|
||||||
auth.TryGetValue("Client", out client);
|
auth.TryGetValue("Client", out client);
|
||||||
auth.TryGetValue("Version", out version);
|
auth.TryGetValue("Version", out version);
|
||||||
|
auth.TryGetValue("Token", out token);
|
||||||
}
|
}
|
||||||
|
|
||||||
var token = httpReq.Headers["X-Emby-Token"];
|
if (string.IsNullOrWhiteSpace(token))
|
||||||
|
{
|
||||||
|
token = httpReq.Headers["X-Emby-Token"];
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(token))
|
if (string.IsNullOrWhiteSpace(token))
|
||||||
{
|
{
|
||||||
|
@ -156,8 +161,10 @@ namespace Emby.Server.Implementations.HttpServer.Security
|
||||||
// There should be at least to parts
|
// There should be at least to parts
|
||||||
if (parts.Length != 2) return null;
|
if (parts.Length != 2) return null;
|
||||||
|
|
||||||
|
var acceptedNames = new[] { "MediaBrowser", "Emby"};
|
||||||
|
|
||||||
// It has to be a digest request
|
// It has to be a digest request
|
||||||
if (!string.Equals(parts[0], "MediaBrowser", StringComparison.OrdinalIgnoreCase))
|
if (!acceptedNames.Contains(parts[0] ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,10 +261,11 @@ namespace Emby.Server.Implementations.IO
|
||||||
// In order to determine if the file is being written to, we have to request write access
|
// In order to determine if the file is being written to, we have to request write access
|
||||||
// But if the server only has readonly access, this is going to cause this entire algorithm to fail
|
// But if the server only has readonly access, this is going to cause this entire algorithm to fail
|
||||||
// So we'll take a best guess about our access level
|
// So we'll take a best guess about our access level
|
||||||
var requestedFileAccess = ConfigurationManager.Configuration.SaveLocalMeta
|
//var requestedFileAccess = ConfigurationManager.Configuration.SaveLocalMeta
|
||||||
? FileAccessMode.ReadWrite
|
// ? FileAccessMode.ReadWrite
|
||||||
: FileAccessMode.Read;
|
// : FileAccessMode.Read;
|
||||||
|
|
||||||
|
var requestedFileAccess = FileAccessMode.Read;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (_fileSystem.GetFileStream(path, FileOpenMode.Open, requestedFileAccess, FileShareMode.ReadWrite))
|
using (_fileSystem.GetFileStream(path, FileOpenMode.Open, requestedFileAccess, FileShareMode.ReadWrite))
|
||||||
|
|
|
@ -100,20 +100,30 @@ namespace Emby.Server.Implementations.Intros
|
||||||
|
|
||||||
if (trailerTypes.Count > 0)
|
if (trailerTypes.Count > 0)
|
||||||
{
|
{
|
||||||
|
if (trailerTypes.Count >= 5)
|
||||||
|
{
|
||||||
|
trailerTypes.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// hack - can't filter by user library because local trailers get TopParentId =null in the db.
|
||||||
|
// for now we have to use a post-query filter afterwards to solve that
|
||||||
var trailerResult = _libraryManager.GetItemList(new InternalItemsQuery
|
var trailerResult = _libraryManager.GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(Trailer).Name },
|
IncludeItemTypes = new[] { typeof(Trailer).Name },
|
||||||
TrailerTypes = trailerTypes.ToArray(),
|
TrailerTypes = trailerTypes.ToArray(),
|
||||||
SimilarTo = item,
|
SimilarTo = item,
|
||||||
IsPlayed = config.EnableIntrosForWatchedContent ? (bool?)null : false,
|
//IsPlayed = config.EnableIntrosForWatchedContent ? (bool?)null : false,
|
||||||
MaxParentalRating = config.EnableIntrosParentalControl ? ratingLevel : null,
|
MaxParentalRating = config.EnableIntrosParentalControl ? ratingLevel : null,
|
||||||
BlockUnratedItems = config.EnableIntrosParentalControl ? new[] { UnratedItem.Trailer } : new UnratedItem[] { },
|
BlockUnratedItems = config.EnableIntrosParentalControl ? new[] { UnratedItem.Trailer } : new UnratedItem[] { },
|
||||||
|
|
||||||
// Account for duplicates by imdb id, since the database doesn't support this yet
|
// Account for duplicates by imdb id, since the database doesn't support this yet
|
||||||
Limit = config.TrailerLimit * 2,
|
Limit = config.TrailerLimit * 4,
|
||||||
SourceTypes = sourceTypes.ToArray()
|
SourceTypes = sourceTypes.ToArray()
|
||||||
|
})
|
||||||
}).Where(i => string.IsNullOrWhiteSpace(i.GetProviderId(MetadataProviders.Imdb)) || !string.Equals(i.GetProviderId(MetadataProviders.Imdb), item.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase)).Take(config.TrailerLimit);
|
.Where(i => string.IsNullOrWhiteSpace(i.GetProviderId(MetadataProviders.Imdb)) || !string.Equals(i.GetProviderId(MetadataProviders.Imdb), item.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Where(i => i.IsVisibleStandalone(user))
|
||||||
|
.Where(i => config.EnableIntrosForWatchedContent || !i.IsPlayed(user))
|
||||||
|
.Take(config.TrailerLimit);
|
||||||
|
|
||||||
candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer
|
candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer
|
||||||
{
|
{
|
||||||
|
|
|
@ -1956,30 +1956,6 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
var options = collectionFolder == null ? new LibraryOptions() : collectionFolder.GetLibraryOptions();
|
var options = collectionFolder == null ? new LibraryOptions() : collectionFolder.GetLibraryOptions();
|
||||||
|
|
||||||
if (options.SchemaVersion < 3)
|
|
||||||
{
|
|
||||||
options.SaveLocalMetadata = ConfigurationManager.Configuration.SaveLocalMeta;
|
|
||||||
options.EnableInternetProviders = ConfigurationManager.Configuration.EnableInternetProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.SchemaVersion < 2)
|
|
||||||
{
|
|
||||||
var chapterOptions = ConfigurationManager.GetConfiguration<ChapterOptions>("chapters");
|
|
||||||
options.ExtractChapterImagesDuringLibraryScan = chapterOptions.ExtractDuringLibraryScan;
|
|
||||||
|
|
||||||
if (collectionFolder != null)
|
|
||||||
{
|
|
||||||
if (string.Equals(collectionFolder.CollectionType, "movies", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
options.EnableChapterImageExtraction = chapterOptions.EnableMovieChapterImageExtraction;
|
|
||||||
}
|
|
||||||
else if (string.Equals(collectionFolder.CollectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
options.EnableChapterImageExtraction = chapterOptions.EnableEpisodeChapterImageExtraction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2034,7 +2010,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
private string GetContentTypeOverride(string path, bool inherit)
|
private string GetContentTypeOverride(string path, bool inherit)
|
||||||
{
|
{
|
||||||
var nameValuePair = ConfigurationManager.Configuration.ContentTypes.FirstOrDefault(i => string.Equals(i.Name, path, StringComparison.OrdinalIgnoreCase) || (inherit && !string.IsNullOrWhiteSpace(i.Name) && _fileSystem.ContainsSubPath(i.Name, path)));
|
var nameValuePair = ConfigurationManager.Configuration.ContentTypes.FirstOrDefault(i => _fileSystem.AreEqual(i.Name, path) || (inherit && !string.IsNullOrWhiteSpace(i.Name) && _fileSystem.ContainsSubPath(i.Name, path)));
|
||||||
if (nameValuePair != null)
|
if (nameValuePair != null)
|
||||||
{
|
{
|
||||||
return nameValuePair.Value;
|
return nameValuePair.Value;
|
||||||
|
@ -2505,6 +2481,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
options.VideoFileExtensions.Remove(".zip");
|
options.VideoFileExtensions.Remove(".zip");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options.VideoFileExtensions.Add(".tp");
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2615,7 +2593,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
foreach (var pathInfo in libraryOptions.PathInfos)
|
foreach (var pathInfo in libraryOptions.PathInfos)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(pathInfo.NetworkPath))
|
if (string.IsNullOrWhiteSpace(pathInfo.Path) || string.IsNullOrWhiteSpace(pathInfo.NetworkPath))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2642,6 +2620,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var map in ConfigurationManager.Configuration.PathSubstitutions)
|
foreach (var map in ConfigurationManager.Configuration.PathSubstitutions)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(map.From))
|
||||||
{
|
{
|
||||||
var substitutionResult = SubstitutePathInternal(path, map.From, map.To);
|
var substitutionResult = SubstitutePathInternal(path, map.From, map.To);
|
||||||
if (substitutionResult.Item2)
|
if (substitutionResult.Item2)
|
||||||
|
@ -2649,6 +2629,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
return substitutionResult.Item1;
|
return substitutionResult.Item1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
@ -3088,7 +3069,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
removeList.Add(contentType);
|
removeList.Add(contentType);
|
||||||
}
|
}
|
||||||
else if (string.Equals(path, contentType.Name, StringComparison.OrdinalIgnoreCase)
|
else if (_fileSystem.AreEqual(path, contentType.Name)
|
||||||
|| _fileSystem.ContainsSubPath(path, contentType.Name))
|
|| _fileSystem.ContainsSubPath(path, contentType.Name))
|
||||||
{
|
{
|
||||||
removeList.Add(contentType);
|
removeList.Add(contentType);
|
||||||
|
|
|
@ -199,6 +199,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
foreach (var mediaSource in list)
|
foreach (var mediaSource in list)
|
||||||
{
|
{
|
||||||
|
mediaSource.InferTotalBitrate();
|
||||||
|
|
||||||
SetKeyProperties(provider, mediaSource);
|
SetKeyProperties(provider, mediaSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,11 +105,10 @@ namespace Emby.Server.Implementations.Library
|
||||||
return inputItems
|
return inputItems
|
||||||
.Cast<Audio>()
|
.Cast<Audio>()
|
||||||
.Select(i => new Tuple<Audio, int>(i, i.Genres.Count(genresDictionary.ContainsKey)))
|
.Select(i => new Tuple<Audio, int>(i, i.Genres.Count(genresDictionary.ContainsKey)))
|
||||||
.Where(i => i.Item2 > 0)
|
|
||||||
.OrderByDescending(i => i.Item2)
|
.OrderByDescending(i => i.Item2)
|
||||||
.ThenBy(i => Guid.NewGuid())
|
.ThenBy(i => Guid.NewGuid())
|
||||||
.Select(i => i.Item1)
|
.Select(i => i.Item1)
|
||||||
.Take(100)
|
.Take(200)
|
||||||
.OrderBy(i => Guid.NewGuid());
|
.OrderBy(i => Guid.NewGuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
var fullName = fileSystemInfo.FullName;
|
var fullName = fileSystemInfo.FullName;
|
||||||
|
|
||||||
if (libraryManager.IsAudioFile(fullName, libraryOptions))
|
if (libraryManager.IsAudioFile(fullName, libraryOptions))
|
||||||
|
@ -150,6 +151,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (notMultiDisc)
|
if (notMultiDisc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -157,6 +157,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
|
|
||||||
AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name);
|
AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name);
|
||||||
|
AddIfMissing(excludeItemTypes, typeof(Folder).Name);
|
||||||
|
|
||||||
var mediaItems = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var mediaItems = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
|
@ -164,8 +165,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
ExcludeItemTypes = excludeItemTypes.ToArray(),
|
ExcludeItemTypes = excludeItemTypes.ToArray(),
|
||||||
IncludeItemTypes = includeItemTypes.ToArray(),
|
IncludeItemTypes = includeItemTypes.ToArray(),
|
||||||
Limit = query.Limit,
|
Limit = query.Limit,
|
||||||
IncludeItemsByName = true,
|
IncludeItemsByName = true
|
||||||
IsVirtualItem = false
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add search hints based on item name
|
// Add search hints based on item name
|
||||||
|
|
|
@ -236,18 +236,10 @@ namespace Emby.Server.Implementations.Library
|
||||||
var user = Users
|
var user = Users
|
||||||
.FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
|
.FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
throw new SecurityException("Invalid username or password entered.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.Policy.IsDisabled)
|
|
||||||
{
|
|
||||||
throw new SecurityException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
var success = false;
|
var success = false;
|
||||||
|
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
// Authenticate using local credentials if not a guest
|
// Authenticate using local credentials if not a guest
|
||||||
if (!user.ConnectLinkType.HasValue || user.ConnectLinkType.Value != UserLinkType.Guest)
|
if (!user.ConnectLinkType.HasValue || user.ConnectLinkType.Value != UserLinkType.Guest)
|
||||||
{
|
{
|
||||||
|
@ -259,6 +251,48 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maybe user accidently entered connect credentials. let's be flexible
|
||||||
|
if (!success && user.ConnectLinkType.HasValue && !string.IsNullOrWhiteSpace(passwordMd5) && !string.IsNullOrWhiteSpace(user.ConnectUserName))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _connectFactory().Authenticate(user.ConnectUserName, passwordMd5).ConfigureAwait(false);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try originally entered username
|
||||||
|
if (!success && (user == null || !string.Equals(user.ConnectUserName, username, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var connectAuthResult = await _connectFactory().Authenticate(username, passwordMd5).ConfigureAwait(false);
|
||||||
|
|
||||||
|
user = Users.FirstOrDefault(i => string.Equals(i.ConnectUserId, connectAuthResult.User.Id, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
success = user != null;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new SecurityException("Invalid username or password entered.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.Policy.IsDisabled)
|
||||||
|
{
|
||||||
|
throw new SecurityException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
|
||||||
|
}
|
||||||
|
|
||||||
// Update LastActivityDate and LastLoginDate, then save
|
// Update LastActivityDate and LastLoginDate, then save
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,8 +55,6 @@ namespace Emby.Server.Implementations.Library
|
||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
var plainFolderIds = user.Configuration.PlainFolderViews.Select(i => new Guid(i)).ToList();
|
|
||||||
|
|
||||||
var groupedFolders = new List<ICollectionFolder>();
|
var groupedFolders = new List<ICollectionFolder>();
|
||||||
|
|
||||||
var list = new List<Folder>();
|
var list = new List<Folder>();
|
||||||
|
@ -72,12 +70,6 @@ namespace Emby.Server.Implementations.Library
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plainFolderIds.Contains(folder.Id) && UserView.IsEligibleForEnhancedView(folderViewType))
|
|
||||||
{
|
|
||||||
list.Add(folder);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (collectionFolder != null && UserView.IsEligibleForGrouping(folder) && user.IsFolderGrouped(folder.Id))
|
if (collectionFolder != null && UserView.IsEligibleForGrouping(folder) && user.IsFolderGrouped(folder.Id))
|
||||||
{
|
{
|
||||||
groupedFolders.Add(collectionFolder);
|
groupedFolders.Add(collectionFolder);
|
||||||
|
@ -287,7 +279,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
SortBy = new[] { ItemSortBy.DateCreated },
|
SortBy = new[] { ItemSortBy.DateCreated },
|
||||||
IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null,
|
IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null,
|
||||||
ExcludeItemTypes = excludeItemTypes,
|
ExcludeItemTypes = excludeItemTypes,
|
||||||
ExcludeLocationTypes = new[] { LocationType.Virtual },
|
IsVirtualItem = false,
|
||||||
Limit = limit * 5,
|
Limit = limit * 5,
|
||||||
SourceTypes = parents.Count == 0 ? new[] { SourceType.Library } : new SourceType[] { },
|
SourceTypes = parents.Count == 0 ? new[] { SourceType.Library } : new SourceType[] { },
|
||||||
IsPlayed = request.IsPlayed
|
IsPlayed = request.IsPlayed
|
||||||
|
|
|
@ -150,7 +150,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
foreach (var recordingFolder in recordingFolders)
|
foreach (var recordingFolder in recordingFolders)
|
||||||
{
|
{
|
||||||
var pathsToCreate = recordingFolder.Locations
|
var pathsToCreate = recordingFolder.Locations
|
||||||
.Where(i => !allExistingPaths.Contains(i, StringComparer.OrdinalIgnoreCase))
|
.Where(i => !allExistingPaths.Any(p => _fileSystem.AreEqual(p, i)))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (pathsToCreate.Count == 0)
|
if (pathsToCreate.Count == 0)
|
||||||
|
@ -1370,13 +1370,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
ActiveRecordingInfo removed;
|
ActiveRecordingInfo removed;
|
||||||
_activeRecordings.TryRemove(timer.Id, out removed);
|
_activeRecordings.TryRemove(timer.Id, out removed);
|
||||||
|
|
||||||
if (recordingStatus != RecordingStatus.Completed && DateTime.UtcNow < timer.EndDate)
|
if (recordingStatus != RecordingStatus.Completed && DateTime.UtcNow < timer.EndDate && timer.RetryCount < 10)
|
||||||
{
|
{
|
||||||
const int retryIntervalSeconds = 60;
|
const int retryIntervalSeconds = 60;
|
||||||
_logger.Info("Retrying recording in {0} seconds.", retryIntervalSeconds);
|
_logger.Info("Retrying recording in {0} seconds.", retryIntervalSeconds);
|
||||||
|
|
||||||
timer.Status = RecordingStatus.New;
|
timer.Status = RecordingStatus.New;
|
||||||
timer.StartDate = DateTime.UtcNow.AddSeconds(retryIntervalSeconds);
|
timer.StartDate = DateTime.UtcNow.AddSeconds(retryIntervalSeconds);
|
||||||
|
timer.RetryCount++;
|
||||||
_timerProvider.AddOrUpdate(timer);
|
_timerProvider.AddOrUpdate(timer);
|
||||||
}
|
}
|
||||||
else if (_fileSystem.FileExists(recordPath))
|
else if (_fileSystem.FileExists(recordPath))
|
||||||
|
@ -2106,12 +2107,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!seriesTimer.Days.Contains(timer.StartDate.ToLocalTime().DayOfWeek))
|
//if (!seriesTimer.Days.Contains(timer.StartDate.ToLocalTime().DayOfWeek))
|
||||||
{
|
//{
|
||||||
return true;
|
// return true;
|
||||||
}
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
if (seriesTimer.RecordNewOnly && timer.IsRepeat)
|
if (seriesTimer.RecordNewOnly && timer.IsRepeat)
|
||||||
{
|
{
|
||||||
|
|
|
@ -240,14 +240,49 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.Info("Killing ffmpeg recording process for {0}", _targetPath);
|
_logger.Info("Stopping ffmpeg recording process for {0}", _targetPath);
|
||||||
|
|
||||||
//process.Kill();
|
//process.Kill();
|
||||||
_process.StandardInput.WriteLine("q");
|
_process.StandardInput.WriteLine("q");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.ErrorException("Error killing transcoding job for {0}", ex, _targetPath);
|
_logger.ErrorException("Error stopping recording transcoding job for {0}", ex, _targetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_hasExited)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.Info("Calling recording process.WaitForExit for {0}", _targetPath);
|
||||||
|
|
||||||
|
if (_process.WaitForExit(5000))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error waiting for recording process to exit for {0}", ex, _targetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_hasExited)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.Info("Killing ffmpeg recording process for {0}", _targetPath);
|
||||||
|
|
||||||
|
_process.Kill();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error killing recording transcoding job for {0}", ex, _targetPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,15 +96,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to estimate this
|
// Try to estimate this
|
||||||
if (!mediaSource.Bitrate.HasValue)
|
mediaSource.InferTotalBitrate(true);
|
||||||
{
|
|
||||||
var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
|
|
||||||
|
|
||||||
if (total > 0)
|
|
||||||
{
|
|
||||||
mediaSource.Bitrate = total;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -459,15 +459,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the total bitrate if not already supplied
|
// Set the total bitrate if not already supplied
|
||||||
if (!mediaSource.Bitrate.HasValue)
|
mediaSource.InferTotalBitrate();
|
||||||
{
|
|
||||||
var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
|
|
||||||
|
|
||||||
if (total > 0)
|
|
||||||
{
|
|
||||||
mediaSource.Bitrate = total;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(service is EmbyTV.EmbyTV))
|
if (!(service is EmbyTV.EmbyTV))
|
||||||
{
|
{
|
||||||
|
@ -1602,7 +1594,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(),
|
AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(),
|
||||||
IsFolder = false,
|
IsFolder = false,
|
||||||
ExcludeLocationTypes = new[] { LocationType.Virtual },
|
IsVirtualItem = false,
|
||||||
Limit = query.Limit,
|
Limit = query.Limit,
|
||||||
SortBy = new[] { ItemSortBy.DateCreated },
|
SortBy = new[] { ItemSortBy.DateCreated },
|
||||||
SortOrder = SortOrder.Descending,
|
SortOrder = SortOrder.Descending,
|
||||||
|
|
|
@ -200,15 +200,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to estimate this
|
// Try to estimate this
|
||||||
if (!mediaSource.Bitrate.HasValue)
|
mediaSource.InferTotalBitrate();
|
||||||
{
|
|
||||||
var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
|
|
||||||
|
|
||||||
if (total > 0)
|
|
||||||
{
|
|
||||||
mediaSource.Bitrate = total;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task CloseMediaSource(string liveStreamId)
|
public Task CloseMediaSource(string liveStreamId)
|
||||||
|
|
|
@ -104,7 +104,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
{
|
{
|
||||||
Type = HdHomerunHost.DeviceType,
|
Type = HdHomerunHost.DeviceType,
|
||||||
Url = url,
|
Url = url,
|
||||||
DataVersion = 1,
|
|
||||||
DeviceId = response.DeviceID
|
DeviceId = response.DeviceID
|
||||||
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
|
@ -61,10 +61,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
{
|
{
|
||||||
var id = ChannelIdPrefix + i.GuideNumber;
|
var id = ChannelIdPrefix + i.GuideNumber;
|
||||||
|
|
||||||
if (info.DataVersion >= 1)
|
|
||||||
{
|
|
||||||
id += '_' + (i.GuideName ?? string.Empty).GetMD5().ToString("N");
|
id += '_' + (i.GuideName ?? string.Empty).GetMD5().ToString("N");
|
||||||
}
|
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +100,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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,6 +428,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
IsInfiniteStream = true
|
IsInfiniteStream = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mediaSource.InferTotalBitrate();
|
||||||
|
|
||||||
return mediaSource;
|
return mediaSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
private readonly TaskCompletionSource<bool> _liveStreamTaskCompletionSource = new TaskCompletionSource<bool>();
|
private readonly TaskCompletionSource<bool> _liveStreamTaskCompletionSource = new TaskCompletionSource<bool>();
|
||||||
private readonly MulticastStream _multicastStream;
|
private readonly MulticastStream _multicastStream;
|
||||||
|
|
||||||
|
|
||||||
public HdHomerunLiveStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost)
|
public HdHomerunLiveStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost)
|
||||||
: base(mediaSource)
|
: base(mediaSource)
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
|
|
||||||
protected override async Task<IEnumerable<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken)
|
protected override async Task<IEnumerable<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).Parse(info.Url, ChannelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false);
|
return await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).Parse(info.Url, ChannelIdPrefix, info.Id, !info.EnableTvgId, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<LiveTvTunerInfo>> GetTunerInfos(CancellationToken cancellationToken)
|
public Task<List<LiveTvTunerInfo>> GetTunerInfos(CancellationToken cancellationToken)
|
||||||
|
@ -127,6 +127,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
{
|
{
|
||||||
protocol = MediaProtocol.Udp;
|
protocol = MediaProtocol.Udp;
|
||||||
}
|
}
|
||||||
|
else if (path.StartsWith("rtp", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
protocol = MediaProtocol.Rtmp;
|
||||||
|
}
|
||||||
|
|
||||||
var mediaSource = new MediaSourceInfo
|
var mediaSource = new MediaSourceInfo
|
||||||
{
|
{
|
||||||
|
@ -155,9 +159,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
ReadAtNativeFramerate = false,
|
ReadAtNativeFramerate = false,
|
||||||
|
|
||||||
Id = channel.Path.GetMD5().ToString("N"),
|
Id = channel.Path.GetMD5().ToString("N"),
|
||||||
IsInfiniteStream = true
|
IsInfiniteStream = true,
|
||||||
|
SupportsDirectStream = false,
|
||||||
|
IsRemote = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mediaSource.InferTotalBitrate();
|
||||||
|
|
||||||
return new List<MediaSourceInfo> { mediaSource };
|
return new List<MediaSourceInfo> { mediaSource };
|
||||||
}
|
}
|
||||||
return new List<MediaSourceInfo>();
|
return new List<MediaSourceInfo>();
|
||||||
|
|
|
@ -14,6 +14,7 @@ using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.IO;
|
using MediaBrowser.Controller.IO;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
|
using MediaBrowser.Model.Extensions;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
{
|
{
|
||||||
|
@ -32,14 +33,25 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<M3UChannel>> Parse(string url, string channelIdPrefix, string tunerHostId, CancellationToken cancellationToken)
|
public async Task<List<M3UChannel>> Parse(string url, string channelIdPrefix, string tunerHostId, bool enableStreamUrlAsIdentifier, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var urlHash = url.GetMD5().ToString("N");
|
var urlHash = url.GetMD5().ToString("N");
|
||||||
|
|
||||||
// Read the file and display it line by line.
|
// Read the file and display it line by line.
|
||||||
using (var reader = new StreamReader(await GetListingsStream(url, cancellationToken).ConfigureAwait(false)))
|
using (var reader = new StreamReader(await GetListingsStream(url, cancellationToken).ConfigureAwait(false)))
|
||||||
{
|
{
|
||||||
return GetChannels(reader, urlHash, channelIdPrefix, tunerHostId);
|
return GetChannels(reader, urlHash, channelIdPrefix, tunerHostId, enableStreamUrlAsIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<M3UChannel> ParseString(string text, string channelIdPrefix, string tunerHostId)
|
||||||
|
{
|
||||||
|
var urlHash = "text".GetMD5().ToString("N");
|
||||||
|
|
||||||
|
// Read the file and display it line by line.
|
||||||
|
using (var reader = new StringReader(text))
|
||||||
|
{
|
||||||
|
return GetChannels(reader, urlHash, channelIdPrefix, tunerHostId, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +71,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
}
|
}
|
||||||
|
|
||||||
const string ExtInfPrefix = "#EXTINF:";
|
const string ExtInfPrefix = "#EXTINF:";
|
||||||
private List<M3UChannel> GetChannels(StreamReader reader, string urlHash, string channelIdPrefix, string tunerHostId)
|
private List<M3UChannel> GetChannels(TextReader reader, string urlHash, string channelIdPrefix, string tunerHostId, bool enableStreamUrlAsIdentifier)
|
||||||
{
|
{
|
||||||
var channels = new List<M3UChannel>();
|
var channels = new List<M3UChannel>();
|
||||||
string line;
|
string line;
|
||||||
|
@ -85,7 +97,15 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
else if (!string.IsNullOrWhiteSpace(extInf) && !line.StartsWith("#", StringComparison.OrdinalIgnoreCase))
|
else if (!string.IsNullOrWhiteSpace(extInf) && !line.StartsWith("#", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var channel = GetChannelnfo(extInf, tunerHostId, line);
|
var channel = GetChannelnfo(extInf, tunerHostId, line);
|
||||||
|
if (string.IsNullOrWhiteSpace(channel.Id) || enableStreamUrlAsIdentifier)
|
||||||
|
{
|
||||||
channel.Id = channelIdPrefix + urlHash + line.GetMD5().ToString("N");
|
channel.Id = channelIdPrefix + urlHash + line.GetMD5().ToString("N");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
channel.Id = channelIdPrefix + urlHash + channel.Id.GetMD5().ToString("N");
|
||||||
|
}
|
||||||
|
|
||||||
channel.Path = line;
|
channel.Path = line;
|
||||||
channels.Add(channel);
|
channels.Add(channel);
|
||||||
extInf = "";
|
extInf = "";
|
||||||
|
@ -114,6 +134,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
channel.Name = GetChannelName(extInf, attributes);
|
channel.Name = GetChannelName(extInf, attributes);
|
||||||
channel.Number = GetChannelNumber(extInf, attributes, mediaUrl);
|
channel.Number = GetChannelNumber(extInf, attributes, mediaUrl);
|
||||||
|
|
||||||
|
if (attributes.TryGetValue("tvg-id", out value))
|
||||||
|
{
|
||||||
|
channel.Id = value;
|
||||||
|
}
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,18 +147,22 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null;
|
var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null;
|
||||||
|
|
||||||
var numberString = nameParts[0];
|
string numberString = null;
|
||||||
|
|
||||||
// Check for channel number with the format from SatIp
|
// Check for channel number with the format from SatIp
|
||||||
int number;
|
// #EXTINF:0,84. VOX Schweiz
|
||||||
|
// #EXTINF:0,84.0 - VOX Schweiz
|
||||||
if (!string.IsNullOrWhiteSpace(nameInExtInf))
|
if (!string.IsNullOrWhiteSpace(nameInExtInf))
|
||||||
{
|
{
|
||||||
var numberIndex = nameInExtInf.IndexOf('.');
|
var numberIndex = nameInExtInf.IndexOf(' ');
|
||||||
if (numberIndex > 0)
|
if (numberIndex > 0)
|
||||||
{
|
{
|
||||||
if (int.TryParse(nameInExtInf.Substring(0, numberIndex), out number))
|
var numberPart = nameInExtInf.Substring(0, numberIndex).Trim(new[] { ' ', '.' });
|
||||||
|
|
||||||
|
double number;
|
||||||
|
if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out number))
|
||||||
{
|
{
|
||||||
numberString = number.ToString();
|
numberString = numberPart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,10 +178,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
{
|
{
|
||||||
string value;
|
string value;
|
||||||
if (attributes.TryGetValue("tvg-id", out value))
|
if (attributes.TryGetValue("tvg-id", out value))
|
||||||
|
{
|
||||||
|
double doubleValue;
|
||||||
|
if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue))
|
||||||
{
|
{
|
||||||
numberString = value;
|
numberString = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(numberString))
|
if (!string.IsNullOrWhiteSpace(numberString))
|
||||||
{
|
{
|
||||||
|
@ -209,16 +242,20 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null;
|
var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null;
|
||||||
|
|
||||||
// Check for channel number with the format from SatIp
|
// Check for channel number with the format from SatIp
|
||||||
int number;
|
// #EXTINF:0,84. VOX Schweiz
|
||||||
|
// #EXTINF:0,84.0 - VOX Schweiz
|
||||||
if (!string.IsNullOrWhiteSpace(nameInExtInf))
|
if (!string.IsNullOrWhiteSpace(nameInExtInf))
|
||||||
{
|
{
|
||||||
var numberIndex = nameInExtInf.IndexOf('.');
|
var numberIndex = nameInExtInf.IndexOf(' ');
|
||||||
if (numberIndex > 0)
|
if (numberIndex > 0)
|
||||||
{
|
{
|
||||||
if (int.TryParse(nameInExtInf.Substring(0, numberIndex), out number))
|
var numberPart = nameInExtInf.Substring(0, numberIndex).Trim(new[] { ' ', '.' });
|
||||||
|
|
||||||
|
double number;
|
||||||
|
if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out number))
|
||||||
{
|
{
|
||||||
//channel.Number = number.ToString();
|
//channel.Number = number.ToString();
|
||||||
nameInExtInf = nameInExtInf.Substring(numberIndex + 1);
|
nameInExtInf = nameInExtInf.Substring(numberIndex + 1).Trim(new[] { ' ', '-' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,20 +287,18 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
|
|
||||||
var reg = new Regex(@"([a-z0-9\-_]+)=\""([^""]+)\""", RegexOptions.IgnoreCase);
|
var reg = new Regex(@"([a-z0-9\-_]+)=\""([^""]+)\""", RegexOptions.IgnoreCase);
|
||||||
var matches = reg.Matches(line);
|
var matches = reg.Matches(line);
|
||||||
var minIndex = int.MaxValue;
|
|
||||||
foreach (Match match in matches)
|
|
||||||
{
|
|
||||||
dict[match.Groups[1].Value] = match.Groups[2].Value;
|
|
||||||
minIndex = Math.Min(minIndex, match.Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (minIndex > 0 && minIndex < line.Length)
|
|
||||||
{
|
|
||||||
line = line.Substring(0, minIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
remaining = line;
|
remaining = line;
|
||||||
|
|
||||||
|
foreach (Match match in matches)
|
||||||
|
{
|
||||||
|
var key = match.Groups[1].Value;
|
||||||
|
var value = match.Groups[2].Value;
|
||||||
|
|
||||||
|
dict[match.Groups[1].Value] = match.Groups[2].Value;
|
||||||
|
remaining = remaining.Replace(key + "=\"" + value + "\"", string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,6 +137,7 @@ fon|||Fon|fon
|
||||||
fre|fra|fr|French|français
|
fre|fra|fr|French|français
|
||||||
frm|||French, Middle (ca.1400-1600)|français moyen (1400-1600)
|
frm|||French, Middle (ca.1400-1600)|français moyen (1400-1600)
|
||||||
fro|||French, Old (842-ca.1400)|français ancien (842-ca.1400)
|
fro|||French, Old (842-ca.1400)|français ancien (842-ca.1400)
|
||||||
|
frc||fr-ca|French (Canada)|french
|
||||||
frr|||Northern Frisian|frison septentrional
|
frr|||Northern Frisian|frison septentrional
|
||||||
frs|||Eastern Frisian|frison oriental
|
frs|||Eastern Frisian|frison oriental
|
||||||
fry||fy|Western Frisian|frison occidental
|
fry||fy|Western Frisian|frison occidental
|
||||||
|
|
47
Emby.Server.Implementations/Migrations/GuideMigration.cs
Normal file
47
Emby.Server.Implementations/Migrations/GuideMigration.cs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
using MediaBrowser.Common.Updates;
|
||||||
|
using MediaBrowser.Controller;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
using MediaBrowser.Model.Serialization;
|
||||||
|
using MediaBrowser.Model.Tasks;
|
||||||
|
using MediaBrowser.Model.Updates;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Emby.Server.Implementations.Migrations
|
||||||
|
{
|
||||||
|
public class GuideMigration : IVersionMigration
|
||||||
|
{
|
||||||
|
private readonly IServerConfigurationManager _config;
|
||||||
|
private readonly ITaskManager _taskManager;
|
||||||
|
|
||||||
|
public GuideMigration(IServerConfigurationManager config, ITaskManager taskManager)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
_taskManager = taskManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Run()
|
||||||
|
{
|
||||||
|
var name = "GuideRefresh2";
|
||||||
|
|
||||||
|
if (!_config.Configuration.Migrations.Contains(name, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
_taskManager.QueueScheduledTask(_taskManager.ScheduledTasks.Select(i => i.ScheduledTask)
|
||||||
|
.First(i => string.Equals(i.Key, "RefreshGuide", StringComparison.OrdinalIgnoreCase)));
|
||||||
|
});
|
||||||
|
|
||||||
|
var list = _config.Configuration.Migrations.ToList();
|
||||||
|
list.Add(name);
|
||||||
|
_config.Configuration.Migrations = list.ToArray();
|
||||||
|
_config.SaveConfiguration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,8 +35,6 @@ namespace Emby.Server.Implementations.Migrations
|
||||||
{
|
{
|
||||||
_taskManager.QueueScheduledTask(_taskManager.ScheduledTasks.Select(i => i.ScheduledTask)
|
_taskManager.QueueScheduledTask(_taskManager.ScheduledTasks.Select(i => i.ScheduledTask)
|
||||||
.First(i => string.Equals(i.Key, "RefreshLibrary", StringComparison.OrdinalIgnoreCase)));
|
.First(i => string.Equals(i.Key, "RefreshLibrary", StringComparison.OrdinalIgnoreCase)));
|
||||||
_taskManager.QueueScheduledTask(_taskManager.ScheduledTasks.Select(i => i.ScheduledTask)
|
|
||||||
.First(i => string.Equals(i.Key, "RefreshGuide", StringComparison.OrdinalIgnoreCase)));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var list = _config.Configuration.Migrations.ToList();
|
var list = _config.Configuration.Migrations.ToList();
|
||||||
|
|
|
@ -430,6 +430,23 @@ namespace Emby.Server.Implementations.Notifications
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetItemName(BaseItemInfo item)
|
||||||
|
{
|
||||||
|
var name = item.Name;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(item.SeriesName))
|
||||||
|
{
|
||||||
|
name = item.SeriesName + " - " + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.Artists != null && item.Artists.Count > 0)
|
||||||
|
{
|
||||||
|
name = item.Artists[0] + " - " + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
async void _userManager_UserCreated(object sender, GenericEventArgs<User> e)
|
async void _userManager_UserCreated(object sender, GenericEventArgs<User> e)
|
||||||
{
|
{
|
||||||
var notification = new NotificationRequest
|
var notification = new NotificationRequest
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace Emby.Server.Implementations.Playlists
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(options.MediaType))
|
if (string.IsNullOrWhiteSpace(options.MediaType))
|
||||||
{
|
{
|
||||||
throw new ArgumentException("A playlist media type is required.");
|
options.MediaType = "Audio";
|
||||||
}
|
}
|
||||||
|
|
||||||
var user = _userManager.GetUserById(options.UserId);
|
var user = _userManager.GetUserById(options.UserId);
|
||||||
|
|
|
@ -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
|
||||||
|
@ -560,6 +560,12 @@ namespace Emby.Server.Implementations.Sync
|
||||||
{
|
{
|
||||||
var jobItem = _repo.GetJobItem(id);
|
var jobItem = _repo.GetJobItem(id);
|
||||||
|
|
||||||
|
if (jobItem == null)
|
||||||
|
{
|
||||||
|
_logger.Debug("ReportSyncJobItemTransferred: SyncJobItem {0} doesn't exist anymore", id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
jobItem.Status = SyncJobItemStatus.Synced;
|
jobItem.Status = SyncJobItemStatus.Synced;
|
||||||
jobItem.Progress = 100;
|
jobItem.Progress = 100;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace Emby.Server.Implementations.Sync
|
||||||
private readonly IServerSyncProvider _provider;
|
private readonly IServerSyncProvider _provider;
|
||||||
|
|
||||||
private readonly SemaphoreSlim _dataLock = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim _dataLock = new SemaphoreSlim(1, 1);
|
||||||
|
private readonly SemaphoreSlim _remoteDataLock = new SemaphoreSlim(1, 1);
|
||||||
private List<LocalItem> _items;
|
private List<LocalItem> _items;
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
@ -63,6 +64,10 @@ namespace Emby.Server.Implementations.Sync
|
||||||
{
|
{
|
||||||
_logger.Debug("Getting {0} from {1}", string.Join(MediaSync.PathSeparatorString, GetRemotePath().ToArray()), _provider.Name);
|
_logger.Debug("Getting {0} from {1}", string.Join(MediaSync.PathSeparatorString, GetRemotePath().ToArray()), _provider.Name);
|
||||||
|
|
||||||
|
await _remoteDataLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
var fileResult = await _provider.GetFiles(GetRemotePath().ToArray(), _target, cancellationToken).ConfigureAwait(false);
|
var fileResult = await _provider.GetFiles(GetRemotePath().ToArray(), _target, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (fileResult.Items.Length > 0)
|
if (fileResult.Items.Length > 0)
|
||||||
|
@ -72,6 +77,11 @@ namespace Emby.Server.Implementations.Sync
|
||||||
return _json.DeserializeFromStream<List<LocalItem>>(stream);
|
return _json.DeserializeFromStream<List<LocalItem>>(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_remoteDataLock.Release();
|
||||||
|
}
|
||||||
|
|
||||||
return new List<LocalItem>();
|
return new List<LocalItem>();
|
||||||
}
|
}
|
||||||
|
@ -93,10 +103,20 @@ namespace Emby.Server.Implementations.Sync
|
||||||
// Save to sync provider
|
// Save to sync provider
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
var remotePath = GetRemotePath();
|
var remotePath = GetRemotePath();
|
||||||
|
|
||||||
|
await _remoteDataLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
_logger.Debug("Saving data.json to {0}. Remote path: {1}", _provider.Name, string.Join("/", remotePath));
|
_logger.Debug("Saving data.json to {0}. Remote path: {1}", _provider.Name, string.Join("/", remotePath));
|
||||||
|
|
||||||
await _provider.SendFile(stream, remotePath, _target, new Progress<double>(), cancellationToken).ConfigureAwait(false);
|
await _provider.SendFile(stream, remotePath, _target, new Progress<double>(), cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_remoteDataLock.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<T> GetData<T>(bool enableCache, Func<List<LocalItem>, T> dataFactory)
|
private async Task<T> GetData<T>(bool enableCache, Func<List<LocalItem>, T> dataFactory)
|
||||||
|
|
|
@ -151,7 +151,9 @@ namespace Emby.Server.Implementations.UserViews
|
||||||
string[] collectionStripViewTypes =
|
string[] collectionStripViewTypes =
|
||||||
{
|
{
|
||||||
CollectionType.Movies,
|
CollectionType.Movies,
|
||||||
CollectionType.TvShows
|
CollectionType.TvShows,
|
||||||
|
CollectionType.Playlists,
|
||||||
|
CollectionType.Photos
|
||||||
};
|
};
|
||||||
|
|
||||||
return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty);
|
return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty);
|
||||||
|
|
|
@ -666,7 +666,7 @@ namespace MediaBrowser.Api.Library
|
||||||
IncludeItemTypes = new[] { type.Name },
|
IncludeItemTypes = new[] { type.Name },
|
||||||
Limit = 0,
|
Limit = 0,
|
||||||
Recursive = true,
|
Recursive = true,
|
||||||
ExcludeLocationTypes = new[] { LocationType.Virtual },
|
IsVirtualItem = false,
|
||||||
SourceTypes = new[] { SourceType.Library },
|
SourceTypes = new[] { SourceType.Library },
|
||||||
IsFavorite = request.IsFavorite
|
IsFavorite = request.IsFavorite
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,12 +1496,20 @@ 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
|
// h264
|
||||||
return string.Format(" -maxrate {0} -bufsize {1}",
|
return string.Format(" -maxrate {0} -bufsize {1}",
|
||||||
bitrate.Value.ToString(UsCulture),
|
bitrate.Value.ToString(UsCulture),
|
||||||
(bitrate.Value * 2).ToString(UsCulture));
|
(bitrate.Value * 2).ToString(UsCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// h264
|
||||||
|
return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}",
|
||||||
|
bitrate.Value.ToString(UsCulture),
|
||||||
|
(bitrate.Value * 2).ToString(UsCulture));
|
||||||
|
}
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1873,7 +1885,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
request.AudioCodec = InferAudioCodec(url);
|
request.AudioCodec = InferAudioCodec(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
var state = new StreamState(MediaSourceManager, Logger)
|
var state = new StreamState(MediaSourceManager, Logger, TranscodingJobType)
|
||||||
{
|
{
|
||||||
Request = request,
|
Request = request,
|
||||||
RequestedUrl = url,
|
RequestedUrl = url,
|
||||||
|
@ -2691,11 +2703,52 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
//inputModifier += " -noaccurate_seek";
|
//inputModifier += " -noaccurate_seek";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var stream in state.MediaSource.MediaStreams)
|
||||||
|
{
|
||||||
|
if (!stream.IsExternal && stream.Type != MediaStreamType.Subtitle)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(stream.Codec) && stream.Index != -1)
|
||||||
|
{
|
||||||
|
var decoder = GetDecoderFromCodec(stream.Codec);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(decoder))
|
||||||
|
{
|
||||||
|
inputModifier += " -codec:" + stream.Index.ToString(UsCulture) + " " + decoder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//var videoStream = state.VideoStream;
|
||||||
|
//if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
|
||||||
|
//{
|
||||||
|
// inputModifier += " -codec:0 " + videoStream.Codec;
|
||||||
|
|
||||||
|
// var audioStream = state.AudioStream;
|
||||||
|
// if (audioStream != null && !string.IsNullOrWhiteSpace(audioStream.Codec))
|
||||||
|
// {
|
||||||
|
// inputModifier += " -codec:1 " + audioStream.Codec;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
return inputModifier;
|
return inputModifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetDecoderFromCodec(string codec)
|
||||||
|
{
|
||||||
|
if (string.Equals(codec, "mp2", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (string.Equals(codec, "aac_latm", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return codec;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Infers the audio codec based on the url
|
/// Infers the audio codec based on the url
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,6 +223,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
protected Stream GetPlaylistFileStream(string path)
|
protected Stream GetPlaylistFileStream(string path)
|
||||||
{
|
{
|
||||||
var tmpPath = path + ".tmp";
|
var tmpPath = path + ".tmp";
|
||||||
|
tmpPath = path;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -242,7 +243,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
var threads = GetNumberOfThreads(state, false);
|
var threads = GetNumberOfThreads(state, false);
|
||||||
|
|
||||||
var inputModifier = GetInputModifier(state);
|
var inputModifier = GetInputModifier(state, true);
|
||||||
|
|
||||||
// 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 startNumberParam = isEncoding ? GetStartNumber(state).ToString(UsCulture) : "0";
|
||||||
|
@ -255,10 +256,32 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
"hls/" + Path.GetFileNameWithoutExtension(outputPath));
|
"hls/" + Path.GetFileNameWithoutExtension(outputPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var useGenericSegmenter = false;
|
||||||
|
if (useGenericSegmenter)
|
||||||
|
{
|
||||||
|
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state);
|
||||||
|
|
||||||
|
var timeDeltaParam = String.Empty;
|
||||||
|
|
||||||
|
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,
|
||||||
|
GetInputArgument(state),
|
||||||
|
threads,
|
||||||
|
GetMapArgs(state),
|
||||||
|
GetVideoArguments(state),
|
||||||
|
GetAudioArguments(state),
|
||||||
|
state.SegmentLength.ToString(UsCulture),
|
||||||
|
startNumberParam,
|
||||||
|
outputPath,
|
||||||
|
outputTsArg,
|
||||||
|
timeDeltaParam
|
||||||
|
).Trim();
|
||||||
|
}
|
||||||
|
|
||||||
// add when stream copying?
|
// add when stream copying?
|
||||||
// -avoid_negative_ts make_zero -fflags +genpts
|
// -avoid_negative_ts make_zero -fflags +genpts
|
||||||
|
|
||||||
var args = string.Format("{0} {1} {2} -map_metadata -1 -map_chapters -1 -threads {3} {4} {5} -fflags +genpts -sc_threshold 0 {6} -hls_time {7} -start_number {8} -hls_list_size {9}{10} -y \"{11}\"",
|
var args = string.Format("{0} {1} {2} -map_metadata -1 -map_chapters -1 -threads {3} {4} {5} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero {6} -hls_time {7} -individual_header_trailer 0 -start_number {8} -hls_list_size {9}{10} -y \"{11}\"",
|
||||||
itsOffset,
|
itsOffset,
|
||||||
inputModifier,
|
inputModifier,
|
||||||
GetInputArgument(state),
|
GetInputArgument(state),
|
||||||
|
@ -286,13 +309,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool IsLiveStream(StreamState state)
|
|
||||||
{
|
|
||||||
var isLiveStream = (state.RunTimeTicks ?? 0) == 0;
|
|
||||||
|
|
||||||
return isLiveStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext)
|
public BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -507,7 +521,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
builder.AppendLine("#EXTM3U");
|
builder.AppendLine("#EXTM3U");
|
||||||
|
|
||||||
var isLiveStream = IsLiveStream(state);
|
var isLiveStream = state.IsSegmentedLiveStream;
|
||||||
|
|
||||||
var queryStringIndex = Request.RawUrl.IndexOf('?');
|
var queryStringIndex = Request.RawUrl.IndexOf('?');
|
||||||
var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex);
|
var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex);
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,6 +175,15 @@ namespace MediaBrowser.Api.Playback
|
||||||
return ToOptimizedResult(info);
|
return ToOptimizedResult(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private T Clone<T>(T obj)
|
||||||
|
{
|
||||||
|
// Since we're going to be setting properties on MediaSourceInfos that come out of _mediaSourceManager, we should clone it
|
||||||
|
// Should we move this directly into MediaSourceManager?
|
||||||
|
|
||||||
|
var json = _json.SerializeToString(obj);
|
||||||
|
return _json.DeserializeFromString<T>(json);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<PlaybackInfoResponse> GetPlaybackInfo(string id, string userId, string[] supportedLiveMediaTypes, string mediaSourceId = null, string liveStreamId = null)
|
private async Task<PlaybackInfoResponse> GetPlaybackInfo(string id, string userId, string[] supportedLiveMediaTypes, string mediaSourceId = null, string liveStreamId = null)
|
||||||
{
|
{
|
||||||
var result = new PlaybackInfoResponse();
|
var result = new PlaybackInfoResponse();
|
||||||
|
@ -217,6 +226,8 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
result.MediaSources = Clone(result.MediaSources);
|
||||||
|
|
||||||
result.PlaySessionId = Guid.NewGuid().ToString("N");
|
result.PlaySessionId = Guid.NewGuid().ToString("N");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +238,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 +260,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 +394,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 +436,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();
|
||||||
|
|
||||||
|
|
|
@ -89,18 +89,22 @@ namespace MediaBrowser.Api.Playback
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RunTimeTicks.HasValue)
|
if (IsSegmentedLiveStream)
|
||||||
{
|
{
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RunTimeTicks.HasValue)
|
|
||||||
{
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
return 3;
|
}
|
||||||
|
|
||||||
|
public bool IsSegmentedLiveStream
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return TranscodingType != TranscodingJobType.Progressive && !RunTimeTicks.HasValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,8 +127,9 @@ namespace MediaBrowser.Api.Playback
|
||||||
public List<string> SupportedAudioCodecs { get; set; }
|
public List<string> SupportedAudioCodecs { get; set; }
|
||||||
public List<string> SupportedVideoCodecs { get; set; }
|
public List<string> SupportedVideoCodecs { get; set; }
|
||||||
public string UserAgent { get; set; }
|
public string UserAgent { get; set; }
|
||||||
|
public TranscodingJobType TranscodingType { get; set; }
|
||||||
|
|
||||||
public StreamState(IMediaSourceManager mediaSourceManager, ILogger logger)
|
public StreamState(IMediaSourceManager mediaSourceManager, ILogger logger, TranscodingJobType transcodingType)
|
||||||
{
|
{
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -132,6 +137,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
SupportedVideoCodecs = new List<string>();
|
SupportedVideoCodecs = new List<string>();
|
||||||
PlayableStreamFileNames = new List<string>();
|
PlayableStreamFileNames = new List<string>();
|
||||||
RemoteHttpHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
RemoteHttpHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
TranscodingType = transcodingType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string InputAudioSync { get; set; }
|
public string InputAudioSync { get; set; }
|
||||||
|
|
|
@ -293,7 +293,11 @@ namespace MediaBrowser.Api.Reports
|
||||||
// ExcludeLocationTypes
|
// ExcludeLocationTypes
|
||||||
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
|
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
|
||||||
{
|
{
|
||||||
query.ExcludeLocationTypes = request.ExcludeLocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
|
var excludeLocationTypes = request.ExcludeLocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
|
||||||
|
if (excludeLocationTypes.Contains(LocationType.Virtual))
|
||||||
|
{
|
||||||
|
query.IsVirtualItem = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.LocationTypes))
|
if (!string.IsNullOrEmpty(request.LocationTypes))
|
||||||
|
|
|
@ -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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,7 +318,11 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
// ExcludeLocationTypes
|
// ExcludeLocationTypes
|
||||||
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
|
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
|
||||||
{
|
{
|
||||||
query.ExcludeLocationTypes = request.ExcludeLocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
|
var excludeLocationTypes = request.ExcludeLocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
|
||||||
|
if (excludeLocationTypes.Contains(LocationType.Virtual))
|
||||||
|
{
|
||||||
|
query.IsVirtualItem = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.LocationTypes))
|
if (!string.IsNullOrEmpty(request.LocationTypes))
|
||||||
|
|
|
@ -404,13 +404,6 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetLocalTrailers request)
|
public object Get(GetLocalTrailers request)
|
||||||
{
|
|
||||||
var result = GetAsync(request);
|
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<BaseItemDto> GetAsync(GetLocalTrailers request)
|
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(request.UserId);
|
var user = _userManager.GetUserById(request.UserId);
|
||||||
|
|
||||||
|
@ -430,7 +423,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
.Select(_libraryManager.GetItemById)
|
.Select(_libraryManager.GetItemById)
|
||||||
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
|
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
|
||||||
|
|
||||||
return dtos.ToList();
|
return ToOptimizedSerializedResultUsingCache(dtos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -36,12 +36,6 @@ namespace MediaBrowser.Common
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event EventHandler<GenericEventArgs<PackageVersionInfo>> ApplicationUpdated;
|
event EventHandler<GenericEventArgs<PackageVersionInfo>> ApplicationUpdated;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this instance is running as service.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance is running as service; otherwise, <c>false</c>.</value>
|
|
||||||
bool IsRunningAsService { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this instance has pending kernel reload.
|
/// Gets or sets a value indicating whether this instance has pending kernel reload.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -49,9 +49,11 @@ namespace MediaBrowser.Controller.Channels
|
||||||
SupportsDirectPlay = true;
|
SupportsDirectPlay = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MediaSourceInfo ToMediaSource()
|
public MediaSourceInfo ToMediaSource(Guid itemId)
|
||||||
{
|
{
|
||||||
var id = Path.GetMD5().ToString("N");
|
var id = string.IsNullOrWhiteSpace(Path) ?
|
||||||
|
itemId.ToString("N") :
|
||||||
|
Path.GetMD5().ToString("N");
|
||||||
|
|
||||||
var source = new MediaSourceInfo
|
var source = new MediaSourceInfo
|
||||||
{
|
{
|
||||||
|
@ -65,16 +67,12 @@ namespace MediaBrowser.Controller.Channels
|
||||||
Name = id,
|
Name = id,
|
||||||
Id = id,
|
Id = id,
|
||||||
ReadAtNativeFramerate = ReadAtNativeFramerate,
|
ReadAtNativeFramerate = ReadAtNativeFramerate,
|
||||||
SupportsDirectStream = Protocol == MediaProtocol.File,
|
SupportsDirectStream = false,
|
||||||
SupportsDirectPlay = SupportsDirectPlay
|
SupportsDirectPlay = SupportsDirectPlay,
|
||||||
|
IsRemote = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var bitrate = (AudioBitrate ?? 0) + (VideoBitrate ?? 0);
|
source.InferTotalBitrate();
|
||||||
|
|
||||||
if (bitrate > 0)
|
|
||||||
{
|
|
||||||
source.Bitrate = bitrate;
|
|
||||||
}
|
|
||||||
|
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user