aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2017-08-20 15:10:00 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2017-08-20 15:10:00 -0400
commitf4765a87cc15efb06331aaeeff3c695be4e77f07 (patch)
tree8c84da8138e8cb7ad2ef9d64bb8f8f9eeb768110
parent1573cc24916239530536c84d4d6a14c5aa351e22 (diff)
update m3u tuner
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs12
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs127
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs18
-rw-r--r--Emby.Server.Implementations/Updates/InstallationManager.cs8
-rw-r--r--MediaBrowser.Controller/Entities/AggregateFolder.cs8
-rw-r--r--MediaBrowser.Controller/Entities/CollectionFolder.cs8
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs38
-rw-r--r--MediaBrowser.Controller/IO/FileData.cs10
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs2
-rw-r--r--MediaBrowser.Controller/Library/ItemResolveArgs.cs29
-rw-r--r--MediaBrowser.Controller/LiveTv/ChannelInfo.cs2
-rw-r--r--MediaBrowser.Model/LiveTv/LiveTvOptions.cs1
12 files changed, 106 insertions, 157 deletions
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index bf3afd050..1bfc93e79 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -353,7 +353,7 @@ namespace Emby.Server.Implementations.Library
}
else
{
- if (item is Photo)
+ if (!(item is Video))
{
return;
}
@@ -599,18 +599,16 @@ namespace Emby.Server.Implementations.Library
// When resolving the root, we need it's grandchildren (children of user views)
var flattenFolderDepth = isPhysicalRoot ? 2 : 0;
- var fileSystemDictionary = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, _fileSystem, _logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
+ var files = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, _fileSystem, _logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
// Need to remove subpaths that may have been resolved from shortcuts
// Example: if \\server\movies exists, then strip out \\server\movies\action
if (isPhysicalRoot)
{
- var paths = NormalizeRootPathList(fileSystemDictionary.Values);
-
- fileSystemDictionary = paths.ToDictionary(i => i.FullName);
+ files = NormalizeRootPathList(files).ToArray();
}
- args.FileSystemDictionary = fileSystemDictionary;
+ args.FileSystemChildren = files;
}
// Check to see if we should resolve based on our contents
@@ -656,7 +654,7 @@ namespace Emby.Server.Implementations.Library
return false;
}
- public IEnumerable<FileSystemMetadata> NormalizeRootPathList(IEnumerable<FileSystemMetadata> paths)
+ public List<FileSystemMetadata> NormalizeRootPathList(IEnumerable<FileSystemMetadata> paths)
{
var originalList = paths.ToList();
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
index 2c12f4ca1..1bc334f06 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
@@ -25,12 +25,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
private readonly IHttpClient _httpClient;
private readonly IServerApplicationHost _appHost;
private readonly IEnvironmentInfo _environment;
+ private readonly INetworkManager _networkManager;
- public M3UTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost, IEnvironmentInfo environment) : base(config, logger, jsonSerializer, mediaEncoder, fileSystem)
+ public M3UTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost, IEnvironmentInfo environment, INetworkManager networkManager) : base(config, logger, jsonSerializer, mediaEncoder, fileSystem)
{
_httpClient = httpClient;
_appHost = appHost;
_environment = environment;
+ _networkManager = networkManager;
}
public override string Type
@@ -38,7 +40,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
get { return "m3u"; }
}
- public string Name
+ public virtual string Name
{
get { return "M3U Tuner"; }
}
@@ -99,72 +101,83 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
}
var channels = await GetChannels(info, true, cancellationToken).ConfigureAwait(false);
- var m3uchannels = channels.Cast<M3UChannel>();
- var channel = m3uchannels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase));
+ var channel = channels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase));
if (channel != null)
{
- var path = channel.Path;
- MediaProtocol protocol = MediaProtocol.File;
- if (path.StartsWith("http", StringComparison.OrdinalIgnoreCase))
- {
- protocol = MediaProtocol.Http;
- }
- else if (path.StartsWith("rtmp", StringComparison.OrdinalIgnoreCase))
- {
- protocol = MediaProtocol.Rtmp;
- }
- else if (path.StartsWith("rtsp", StringComparison.OrdinalIgnoreCase))
- {
- protocol = MediaProtocol.Rtsp;
- }
- else if (path.StartsWith("udp", StringComparison.OrdinalIgnoreCase))
- {
- protocol = MediaProtocol.Udp;
- }
- else if (path.StartsWith("rtp", StringComparison.OrdinalIgnoreCase))
- {
- protocol = MediaProtocol.Rtmp;
- }
+ return new List<MediaSourceInfo> { CreateMediaSourceInfo(info, channel) };
+ }
+ return new List<MediaSourceInfo>();
+ }
+
+ protected virtual MediaSourceInfo CreateMediaSourceInfo(TunerHostInfo info, ChannelInfo channel)
+ {
+ var path = channel.Path;
+ MediaProtocol protocol = MediaProtocol.File;
+ if (path.StartsWith("http", StringComparison.OrdinalIgnoreCase))
+ {
+ protocol = MediaProtocol.Http;
+ }
+ else if (path.StartsWith("rtmp", StringComparison.OrdinalIgnoreCase))
+ {
+ protocol = MediaProtocol.Rtmp;
+ }
+ else if (path.StartsWith("rtsp", StringComparison.OrdinalIgnoreCase))
+ {
+ protocol = MediaProtocol.Rtsp;
+ }
+ else if (path.StartsWith("udp", StringComparison.OrdinalIgnoreCase))
+ {
+ protocol = MediaProtocol.Udp;
+ }
+ else if (path.StartsWith("rtp", StringComparison.OrdinalIgnoreCase))
+ {
+ protocol = MediaProtocol.Rtmp;
+ }
+
+ Uri uri;
+ var isRemote = true;
+ if (Uri.TryCreate(path, UriKind.Absolute, out uri))
+ {
+ isRemote = !_networkManager.IsInLocalNetwork(uri.Host);
+ }
- var mediaSource = new MediaSourceInfo
+ var mediaSource = new MediaSourceInfo
+ {
+ Path = path,
+ Protocol = protocol,
+ MediaStreams = new List<MediaStream>
{
- Path = channel.Path,
- Protocol = protocol,
- MediaStreams = new List<MediaStream>
+ new MediaStream
{
- new MediaStream
- {
- Type = MediaStreamType.Video,
- // Set the index to -1 because we don't know the exact index of the video stream within the container
- Index = -1,
- IsInterlaced = true
- },
- new MediaStream
- {
- Type = MediaStreamType.Audio,
- // Set the index to -1 because we don't know the exact index of the audio stream within the container
- Index = -1
-
- }
+ Type = MediaStreamType.Video,
+ // Set the index to -1 because we don't know the exact index of the video stream within the container
+ Index = -1,
+ IsInterlaced = true
},
- RequiresOpening = true,
- RequiresClosing = true,
- RequiresLooping = info.EnableStreamLooping,
+ new MediaStream
+ {
+ Type = MediaStreamType.Audio,
+ // Set the index to -1 because we don't know the exact index of the audio stream within the container
+ Index = -1
- ReadAtNativeFramerate = false,
+ }
+ },
+ RequiresOpening = true,
+ RequiresClosing = true,
+ RequiresLooping = info.EnableStreamLooping,
- Id = channel.Path.GetMD5().ToString("N"),
- IsInfiniteStream = true,
- IsRemote = true,
+ ReadAtNativeFramerate = false,
- IgnoreDts = true
- };
+ Id = channel.Path.GetMD5().ToString("N"),
+ IsInfiniteStream = true,
+ IsRemote = isRemote,
- mediaSource.InferTotalBitrate();
+ IgnoreDts = true
+ };
- return new List<MediaSourceInfo> { mediaSource };
- }
- return new List<MediaSourceInfo>();
+ mediaSource.InferTotalBitrate();
+
+ return mediaSource;
}
protected override Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
index 113e691b6..ca744b615 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
@@ -32,7 +32,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
_appHost = appHost;
}
- public async Task<List<M3UChannel>> Parse(string url, string channelIdPrefix, string tunerHostId, CancellationToken cancellationToken)
+ public async Task<List<ChannelInfo>> Parse(string url, string channelIdPrefix, string tunerHostId, CancellationToken cancellationToken)
{
// Read the file and display it line by line.
using (var reader = new StreamReader(await GetListingsStream(url, cancellationToken).ConfigureAwait(false)))
@@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
}
}
- public List<M3UChannel> ParseString(string text, string channelIdPrefix, string tunerHostId)
+ public List<ChannelInfo> ParseString(string text, string channelIdPrefix, string tunerHostId)
{
// Read the file and display it line by line.
using (var reader = new StringReader(text))
@@ -66,9 +66,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
}
const string ExtInfPrefix = "#EXTINF:";
- private List<M3UChannel> GetChannels(TextReader reader, string channelIdPrefix, string tunerHostId)
+ private List<ChannelInfo> GetChannels(TextReader reader, string channelIdPrefix, string tunerHostId)
{
- var channels = new List<M3UChannel>();
+ var channels = new List<ChannelInfo>();
string line;
string extInf = "";
@@ -111,9 +111,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return channels;
}
- private M3UChannel GetChannelnfo(string extInf, string tunerHostId, string mediaUrl)
+ private ChannelInfo GetChannelnfo(string extInf, string tunerHostId, string mediaUrl)
{
- var channel = new M3UChannel();
+ var channel = new ChannelInfo();
channel.TunerHostId = tunerHostId;
extInf = extInf.Trim();
@@ -335,10 +335,4 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return dict;
}
}
-
-
- public class M3UChannel : ChannelInfo
- {
- public string Path { get; set; }
- }
} \ No newline at end of file
diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs
index 6f9c85671..ab1255b57 100644
--- a/Emby.Server.Implementations/Updates/InstallationManager.cs
+++ b/Emby.Server.Implementations/Updates/InstallationManager.cs
@@ -308,9 +308,11 @@ namespace Emby.Server.Implementations.Updates
.OrderByDescending(GetPackageVersion).ToArray();
}
+ IEnumerable<PackageInfo> packagesList = packages;
+
if (!string.IsNullOrWhiteSpace(packageType))
{
- packages = packages.Where(p => string.Equals(p.type, packageType, StringComparison.OrdinalIgnoreCase)).ToArray();
+ packagesList = packagesList.Where(p => string.Equals(p.type, packageType, StringComparison.OrdinalIgnoreCase));
}
// If an app version was supplied, filter the versions for each package to only include supported versions
@@ -323,7 +325,9 @@ namespace Emby.Server.Implementations.Updates
}
// Remove packages with no versions
- return packages.Where(p => p.versions.Any()).ToArray();
+ packagesList = packagesList.Where(p => p.versions.Any());
+
+ return packagesList.ToArray();
}
/// <summary>
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs
index f88522f78..db84d6e2f 100644
--- a/MediaBrowser.Controller/Entities/AggregateFolder.cs
+++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs
@@ -148,18 +148,16 @@ namespace MediaBrowser.Controller.Entities
// When resolving the root, we need it's grandchildren (children of user views)
var flattenFolderDepth = isPhysicalRoot ? 2 : 0;
- var fileSystemDictionary = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
+ var files = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
// Need to remove subpaths that may have been resolved from shortcuts
// Example: if \\server\movies exists, then strip out \\server\movies\action
if (isPhysicalRoot)
{
- var paths = LibraryManager.NormalizeRootPathList(fileSystemDictionary.Values);
-
- fileSystemDictionary = paths.ToDictionary(i => i.FullName);
+ files = LibraryManager.NormalizeRootPathList(files).ToArray();
}
- args.FileSystemDictionary = fileSystemDictionary;
+ args.FileSystemChildren = files;
}
_requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations);
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index d02e469d4..3e2c501b4 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -292,18 +292,16 @@ namespace MediaBrowser.Controller.Entities
// When resolving the root, we need it's grandchildren (children of user views)
var flattenFolderDepth = isPhysicalRoot ? 2 : 0;
- var fileSystemDictionary = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
+ var files = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf);
// Need to remove subpaths that may have been resolved from shortcuts
// Example: if \\server\movies exists, then strip out \\server\movies\action
if (isPhysicalRoot)
{
- var paths = LibraryManager.NormalizeRootPathList(fileSystemDictionary.Values);
-
- fileSystemDictionary = paths.ToDictionary(i => i.FullName);
+ files = LibraryManager.NormalizeRootPathList(files).ToArray();
}
- args.FileSystemDictionary = fileSystemDictionary;
+ args.FileSystemChildren = files;
}
_requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations);
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index 376f65d60..2768d8465 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -8,7 +8,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using MediaBrowser.Model.Serialization;
-using MediaBrowser.Controller.Entities.Audio;
namespace MediaBrowser.Controller.Entities.Movies
{
@@ -82,20 +81,11 @@ namespace MediaBrowser.Controller.Entities.Movies
protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
{
- if (IsLegacyBoxSet)
- {
- return base.GetNonCachedChildren(directoryService);
- }
return new List<BaseItem>();
}
protected override List<BaseItem> LoadChildren()
{
- if (IsLegacyBoxSet)
- {
- return base.LoadChildren();
- }
-
// Save a trip to the database
return new List<BaseItem>();
}
@@ -109,34 +99,6 @@ namespace MediaBrowser.Controller.Entities.Movies
}
}
- [IgnoreDataMember]
- protected override bool SupportsShortcutChildren
- {
- get
- {
- if (IsLegacyBoxSet)
- {
- return false;
- }
-
- return false;
- }
- }
-
- [IgnoreDataMember]
- private bool IsLegacyBoxSet
- {
- get
- {
- if (string.IsNullOrWhiteSpace(Path))
- {
- return false;
- }
-
- return !FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, Path);
- }
- }
-
public override bool IsAuthorizedToDelete(User user)
{
return true;
diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs
index 64a7610fe..27af60700 100644
--- a/MediaBrowser.Controller/IO/FileData.cs
+++ b/MediaBrowser.Controller/IO/FileData.cs
@@ -3,7 +3,7 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
-
+using System.Linq;
using MediaBrowser.Model.IO;
namespace MediaBrowser.Controller.IO
@@ -36,7 +36,7 @@ namespace MediaBrowser.Controller.IO
/// <param name="resolveShortcuts">if set to <c>true</c> [resolve shortcuts].</param>
/// <returns>Dictionary{System.StringFileSystemInfo}.</returns>
/// <exception cref="System.ArgumentNullException">path</exception>
- public static Dictionary<string, FileSystemMetadata> GetFilteredFileSystemEntries(IDirectoryService directoryService,
+ public static FileSystemMetadata[] GetFilteredFileSystemEntries(IDirectoryService directoryService,
string path,
IFileSystem fileSystem,
ILogger logger,
@@ -57,7 +57,7 @@ namespace MediaBrowser.Controller.IO
if (!resolveShortcuts && flattenFolderDepth == 0)
{
- return GetFileSystemDictionary(entries);
+ return entries;
}
var dict = new Dictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase);
@@ -98,7 +98,7 @@ namespace MediaBrowser.Controller.IO
{
foreach (var child in GetFilteredFileSystemEntries(directoryService, fullName, fileSystem, logger, args, flattenFolderDepth: flattenFolderDepth - 1, resolveShortcuts: resolveShortcuts))
{
- dict[child.Key] = child.Value;
+ dict[child.FullName] = child;
}
}
else
@@ -107,7 +107,7 @@ namespace MediaBrowser.Controller.IO
}
}
- return dict;
+ return dict.Values.ToArray();
}
}
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index 025254d4b..cd1781220 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -277,7 +277,7 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="paths">The paths.</param>
/// <returns>IEnumerable{System.String}.</returns>
- IEnumerable<FileSystemMetadata> NormalizeRootPathList(IEnumerable<FileSystemMetadata> paths);
+ List<FileSystemMetadata> NormalizeRootPathList(IEnumerable<FileSystemMetadata> paths);
/// <summary>
/// Registers the item.
diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
index 76b6d8768..963e4b71b 100644
--- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs
+++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
@@ -40,20 +40,7 @@ namespace MediaBrowser.Controller.Library
/// Gets the file system children.
/// </summary>
/// <value>The file system children.</value>
- public IEnumerable<FileSystemMetadata> FileSystemChildren
- {
- get
- {
- var dict = FileSystemDictionary;
-
- if (dict == null)
- {
- return new List<FileSystemMetadata>();
- }
-
- return dict.Values;
- }
- }
+ public FileSystemMetadata[] FileSystemChildren { get; set; }
public LibraryOptions LibraryOptions { get; set; }
@@ -63,12 +50,6 @@ namespace MediaBrowser.Controller.Library
}
/// <summary>
- /// Gets or sets the file system dictionary.
- /// </summary>
- /// <value>The file system dictionary.</value>
- public Dictionary<string, FileSystemMetadata> FileSystemDictionary { get; set; }
-
- /// <summary>
/// Gets or sets the parent.
/// </summary>
/// <value>The parent.</value>
@@ -224,13 +205,11 @@ namespace MediaBrowser.Controller.Library
throw new ArgumentNullException();
}
- if (FileSystemDictionary != null)
+ foreach (var file in FileSystemChildren)
{
- FileSystemMetadata entry;
-
- if (FileSystemDictionary.TryGetValue(path, out entry))
+ if (string.Equals(file.FullName, path, StringComparison.Ordinal))
{
- return entry;
+ return file;
}
}
diff --git a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs
index 6682942ad..892a7d5b7 100644
--- a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs
+++ b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs
@@ -25,6 +25,8 @@ namespace MediaBrowser.Controller.LiveTv
/// <value>The id of the channel.</value>
public string Id { get; set; }
+ public string Path { get; set; }
+
public string TunerChannelId { get; set; }
public string CallSign { get; set; }
diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs
index 64b628a13..15f60d831 100644
--- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs
+++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs
@@ -48,6 +48,7 @@ namespace MediaBrowser.Model.LiveTv
public bool AllowHWTranscoding { get; set; }
public bool EnableStreamLooping { get; set; }
public bool EnableNewHdhrChannelIds { get; set; }
+ public string Source { get; set; }
public TunerHostInfo()
{