update emby tv

This commit is contained in:
Luke Pulverenti 2015-07-23 19:40:54 -04:00
parent f7c1a88166
commit ba9ed26c4a
17 changed files with 236 additions and 87 deletions

View file

@ -924,7 +924,7 @@ namespace MediaBrowser.Api.Playback
state.IsoMount = await IsoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false); state.IsoMount = await IsoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false);
} }
if (state.MediaSource.RequiresOpening) if (state.MediaSource.RequiresOpening ?? false)
{ {
var liveStreamResponse = await MediaSourceManager.OpenLiveStream(new LiveStreamRequest var liveStreamResponse = await MediaSourceManager.OpenLiveStream(new LiveStreamRequest
{ {

View file

@ -185,7 +185,7 @@ namespace MediaBrowser.Api.Playback
private async void DisposeLiveStream() private async void DisposeLiveStream()
{ {
if (MediaSource.RequiresClosing && string.IsNullOrWhiteSpace(Request.LiveStreamId)) if ((MediaSource.RequiresClosing ?? false) && string.IsNullOrWhiteSpace(Request.LiveStreamId))
{ {
try try
{ {

View file

@ -47,6 +47,14 @@ namespace MediaBrowser.Controller.LiveTv
/// <returns>Task&lt;MediaSourceInfo&gt;.</returns> /// <returns>Task&lt;MediaSourceInfo&gt;.</returns>
Task<MediaSourceInfo> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken); Task<MediaSourceInfo> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Gets the channel stream media sources.
/// </summary>
/// <param name="info">The information.</param>
/// <param name="channelId">The channel identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;List&lt;MediaSourceInfo&gt;&gt;.</returns>
Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, string channelId, CancellationToken cancellationToken);
/// <summary>
/// Validates the specified information. /// Validates the specified information.
/// </summary> /// </summary>
/// <param name="info">The information.</param> /// <param name="info">The information.</param>

View file

@ -436,7 +436,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
state.IsoMount = await IsoManager.Mount(state.MediaPath, cancellationToken).ConfigureAwait(false); state.IsoMount = await IsoManager.Mount(state.MediaPath, cancellationToken).ConfigureAwait(false);
} }
if (state.MediaSource.RequiresOpening) if (state.MediaSource.RequiresOpening ?? false)
{ {
var liveStreamResponse = await MediaSourceManager.OpenLiveStream(new LiveStreamRequest var liveStreamResponse = await MediaSourceManager.OpenLiveStream(new LiveStreamRequest
{ {

View file

@ -137,7 +137,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
private async void DisposeLiveStream() private async void DisposeLiveStream()
{ {
if (MediaSource.RequiresClosing) if (MediaSource.RequiresClosing ?? false)
{ {
try try
{ {

View file

@ -26,9 +26,9 @@ namespace MediaBrowser.Model.Dto
public bool SupportsDirectStream { get; set; } public bool SupportsDirectStream { get; set; }
public bool SupportsDirectPlay { get; set; } public bool SupportsDirectPlay { get; set; }
public bool RequiresOpening { get; set; } public bool? RequiresOpening { get; set; }
public string OpenToken { get; set; } public string OpenToken { get; set; }
public bool RequiresClosing { get; set; } public bool? RequiresClosing { get; set; }
public string LiveStreamId { get; set; } public string LiveStreamId { get; set; }
public int? BufferMs { get; set; } public int? BufferMs { get; set; }

View file

@ -34,5 +34,6 @@ namespace MediaBrowser.Model.LiveTv
public string Password { get; set; } public string Password { get; set; }
public string ListingsId { get; set; } public string ListingsId { get; set; }
public string ZipCode { get; set; } public string ZipCode { get; set; }
public string Country { get; set; }
} }
} }

View file

@ -439,7 +439,7 @@ namespace MediaBrowser.Server.Implementations.Library
LiveStreamInfo current; LiveStreamInfo current;
if (_openStreams.TryGetValue(id, out current)) if (_openStreams.TryGetValue(id, out current))
{ {
if (current.MediaSource.RequiresClosing) if (current.MediaSource.RequiresClosing ?? false)
{ {
var tuple = GetProvider(id); var tuple = GetProvider(id);

View file

@ -1,5 +1,6 @@
using MediaBrowser.Common; using MediaBrowser.Common;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
@ -74,20 +75,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
var status = new LiveTvServiceStatusInfo(); var status = new LiveTvServiceStatusInfo();
var list = new List<LiveTvTunerInfo>(); var list = new List<LiveTvTunerInfo>();
foreach (var host in _liveTvManager.TunerHosts) foreach (var hostInstance in GetTunerHosts())
{ {
foreach (var hostInstance in host.GetTunerHosts()) try
{ {
try var tuners = await hostInstance.Item1.GetTunerInfos(hostInstance.Item2, cancellationToken).ConfigureAwait(false);
{
var tuners = await host.GetTunerInfos(hostInstance, cancellationToken).ConfigureAwait(false);
list.AddRange(tuners); list.AddRange(tuners);
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.ErrorException("Error getting tuners", ex); _logger.ErrorException("Error getting tuners", ex);
}
} }
} }
@ -102,20 +100,23 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{ {
var list = new List<ChannelInfo>(); var list = new List<ChannelInfo>();
foreach (var host in _liveTvManager.TunerHosts) foreach (var hostInstance in GetTunerHosts())
{ {
foreach (var hostInstance in host.GetTunerHosts()) try
{ {
try var channels = await hostInstance.Item1.GetChannels(hostInstance.Item2, cancellationToken).ConfigureAwait(false);
{ var newChannels = channels.ToList();
var channels = await host.GetChannels(hostInstance, cancellationToken).ConfigureAwait(false);
list.AddRange(channels); foreach (var channel in newChannels)
}
catch (Exception ex)
{ {
_logger.ErrorException("Error getting channels", ex); channel.Id = hostInstance.Item1.Type.GetMD5().ToString("N") + "-" + channel.Id;
} }
list.AddRange(newChannels);
}
catch (Exception ex)
{
_logger.ErrorException("Error getting channels", ex);
} }
} }
@ -130,6 +131,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return list; return list;
} }
private List<Tuple<ITunerHost, TunerHostInfo>> GetTunerHosts()
{
return GetConfiguration().TunerHosts
.Select(i =>
{
var provider = _liveTvManager.TunerHosts.FirstOrDefault(l => string.Equals(l.Type, i.Type, StringComparison.OrdinalIgnoreCase));
return provider == null ? null : new Tuple<ITunerHost, TunerHostInfo>(provider, i);
})
.Where(i => i != null)
.ToList();
}
public Task CancelSeriesTimerAsync(string timerId, CancellationToken cancellationToken) public Task CancelSeriesTimerAsync(string timerId, CancellationToken cancellationToken)
{ {
var remove = _seriesTimerProvider.GetAll().SingleOrDefault(r => r.Id == timerId); var remove = _seriesTimerProvider.GetAll().SingleOrDefault(r => r.Id == timerId);
@ -255,14 +269,27 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return Task.FromResult((IEnumerable<SeriesTimerInfo>)_seriesTimerProvider.GetAll()); return Task.FromResult((IEnumerable<SeriesTimerInfo>)_seriesTimerProvider.GetAll());
} }
private string GetOriginalChannelId(string channelId)
{
var parts = channelId.Split('-');
return string.Join("-", parts.Skip(1).ToArray());
}
public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
{ {
foreach (var provider in GetListingProviders()) foreach (var provider in GetListingProviders())
{ {
var programs = await provider.Item1.GetProgramsAsync(provider.Item2, channelId, startDateUtc, endDateUtc, cancellationToken) var programs = await provider.Item1.GetProgramsAsync(provider.Item2, GetOriginalChannelId(channelId), startDateUtc, endDateUtc, cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
var list = programs.ToList(); var list = programs.ToList();
// Replace the value that came from the provider with a normalized value
foreach (var program in list)
{
program.ChannelId = channelId;
}
if (list.Count > 0) if (list.Count > 0)
{ {
return list; return list;
@ -290,14 +317,67 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<MediaSourceInfo> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken) public async Task<MediaSourceInfo> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken)
{ {
throw new NotImplementedException(); _logger.Info("Streaming Channel " + channelId);
var configurationId = channelId.Split('-')[0];
foreach (var hostInstance in GetTunerHosts())
{
if (!string.Equals(configurationId, hostInstance.Item1.Type.GetMD5().ToString("N"), StringComparison.OrdinalIgnoreCase))
{
continue;
}
if (!string.IsNullOrWhiteSpace(streamId))
{
var originalStreamId = string.Join("-", streamId.Split('-').Skip(1).ToArray());
if (!string.Equals(hostInstance.Item2.Id, originalStreamId, StringComparison.OrdinalIgnoreCase))
{
continue;
}
}
MediaSourceInfo mediaSourceInfo = null;
try
{
mediaSourceInfo = await hostInstance.Item1.GetChannelStream(hostInstance.Item2, GetOriginalChannelId(channelId), streamId, cancellationToken).ConfigureAwait(false);
}
catch (ApplicationException e)
{
_logger.Info(e.Message);
continue;
}
mediaSourceInfo.Id = Guid.NewGuid().ToString("N");
return mediaSourceInfo;
}
throw new ApplicationException("Tuner not found.");
} }
public Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken) public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken)
{ {
throw new NotImplementedException(); var configurationId = channelId.Split('-')[0];
foreach (var hostInstance in GetTunerHosts())
{
if (string.Equals(configurationId, hostInstance.Item1.Type.GetMD5().ToString("N"), StringComparison.OrdinalIgnoreCase))
{
var sources = await hostInstance.Item1.GetChannelStreamMediaSources(hostInstance.Item2, GetOriginalChannelId(channelId), cancellationToken).ConfigureAwait(false);
foreach (var source in sources)
{
source.Id = hostInstance.Item2.Id + "-" + source.Id;
}
return sources;
}
}
throw new ApplicationException("Tuner not found.");
} }
public Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken) public Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken)

View file

@ -68,9 +68,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
private void UpdateList(List<T> newList) private void UpdateList(List<T> newList)
{ {
var file = _dataPath + ".json";
Directory.CreateDirectory(Path.GetDirectoryName(file));
lock (_fileDataLock) lock (_fileDataLock)
{ {
_jsonSerializer.SerializeToFile(newList, _dataPath + ".json"); _jsonSerializer.SerializeToFile(newList, file);
_items = newList; _items = newList;
} }
} }

View file

@ -218,7 +218,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
private ProgramInfo GetProgram(string channel, ScheduleDirect.Program programInfo, private ProgramInfo GetProgram(string channel, ScheduleDirect.Program programInfo,
ScheduleDirect.ProgramDetails details) ScheduleDirect.ProgramDetails details)
{ {
_logger.Debug("Show type is: " + (details.showType ?? "No ShowType")); //_logger.Debug("Show type is: " + (details.showType ?? "No ShowType"));
DateTime startAt = DateTime.ParseExact(programInfo.airDateTime, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", DateTime startAt = DateTime.ParseExact(programInfo.airDateTime, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'",
CultureInfo.InvariantCulture); CultureInfo.InvariantCulture);
DateTime endAt = startAt.AddSeconds(programInfo.duration); DateTime endAt = startAt.AddSeconds(programInfo.duration);
@ -401,7 +401,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
_logger.Info("Headends on account "); _logger.Info("Headends on account ");
var countryParam = string.Equals("ca", country, StringComparison.OrdinalIgnoreCase) var countryParam = string.Equals("ca", country, StringComparison.OrdinalIgnoreCase)
? "Canada" ? "can"
: "USA"; : "USA";
var options = new HttpRequestOptions() var options = new HttpRequestOptions()
@ -562,6 +562,44 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
get { return "SchedulesDirect"; } get { return "SchedulesDirect"; }
} }
private async Task<bool> HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken)
{
var token = await GetToken(info, cancellationToken);
_logger.Info("Headends on account ");
var options = new HttpRequestOptions()
{
Url = ApiUrl + "/lineups",
UserAgent = UserAgent,
CancellationToken = cancellationToken
};
options.RequestHeaders["token"] = token;
using (Stream responce = await _httpClient.Get(options).ConfigureAwait(false))
{
var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Lineups>(responce);
return root.lineups.Any(i => string.Equals(info.ListingsId, i.lineup, StringComparison.OrdinalIgnoreCase));
}
}
public async Task Validate(ListingsProviderInfo info)
{
var hasLineup = await HasLineup(info, CancellationToken.None).ConfigureAwait(false);
if (!hasLineup)
{
await AddLineupToAccount(info, CancellationToken.None).ConfigureAwait(false);
}
}
public Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location)
{
return GetHeadends(info, country, location, CancellationToken.None);
}
public class ScheduleDirect public class ScheduleDirect
{ {
public class Token public class Token
@ -841,14 +879,5 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
} }
public async Task Validate(ListingsProviderInfo info)
{
//await AddLineupToAccount(info, CancellationToken.None).ConfigureAwait(false);
}
public Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location)
{
return GetHeadends(info, country, location, CancellationToken.None);
}
} }
} }

View file

@ -367,7 +367,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
info = await service.GetChannelStream(channel.ExternalId, mediaSourceId, cancellationToken).ConfigureAwait(false); info = await service.GetChannelStream(channel.ExternalId, mediaSourceId, cancellationToken).ConfigureAwait(false);
info.RequiresClosing = true; info.RequiresClosing = true;
if (info.RequiresClosing) if (info.RequiresClosing ?? false)
{ {
var idPrefix = service.GetType().FullName.GetMD5().ToString("N") + "_"; var idPrefix = service.GetType().FullName.GetMD5().ToString("N") + "_";
@ -384,7 +384,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
info = await service.GetRecordingStream(recording.ExternalId, null, cancellationToken).ConfigureAwait(false); info = await service.GetRecordingStream(recording.ExternalId, null, cancellationToken).ConfigureAwait(false);
info.RequiresClosing = true; info.RequiresClosing = true;
if (info.RequiresClosing) if (info.RequiresClosing ?? false)
{ {
var idPrefix = service.GetType().FullName.GetMD5().ToString("N") + "_"; var idPrefix = service.GetType().FullName.GetMD5().ToString("N") + "_";

View file

@ -53,7 +53,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
// Do not use a pipe here because Roku http requests to the server will fail, without any explicit error message. // Do not use a pipe here because Roku http requests to the server will fail, without any explicit error message.
private const char StreamIdDelimeter = '_'; private const char StreamIdDelimeter = '_';
private const string StreamIdDelimeterString = "|"; private const string StreamIdDelimeterString = "_";
private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(ILiveTvItem item, CancellationToken cancellationToken) private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(ILiveTvItem item, CancellationToken cancellationToken)
{ {
@ -86,14 +86,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv
foreach (var source in list) foreach (var source in list)
{ {
source.Type = MediaSourceType.Default; source.Type = MediaSourceType.Default;
source.RequiresOpening = true;
source.BufferMs = source.BufferMs ?? 1500;
var openKeys = new List<string>(); if (!source.RequiresOpening.HasValue)
openKeys.Add(item.GetType().Name); {
openKeys.Add(item.Id.ToString("N")); source.RequiresOpening = true;
openKeys.Add(source.Id ?? string.Empty); }
source.OpenToken = string.Join(StreamIdDelimeterString, openKeys.ToArray());
if (source.RequiresOpening.HasValue && source.RequiresOpening.Value)
{
var openKeys = new List<string>();
openKeys.Add(item.GetType().Name);
openKeys.Add(item.Id.ToString("N"));
openKeys.Add(source.Id ?? string.Empty);
source.OpenToken = string.Join(StreamIdDelimeterString, openKeys.ToArray());
}
source.BufferMs = source.BufferMs ?? 1500;
// Dummy this up so that direct play checks can still run // Dummy this up so that direct play checks can still run
if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http) if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http)

View file

@ -72,6 +72,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
return; return;
} }
// Strip off the port
url = new Uri(url).GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped);
await _liveTvManager.SaveTunerHost(new TunerHostInfo await _liveTvManager.SaveTunerHost(new TunerHostInfo
{ {
Type = HdHomerunHost.DeviceType, Type = HdHomerunHost.DeviceType,
@ -103,13 +106,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
url = url.TrimEnd('/'); url = url.TrimEnd('/');
// If there isn't a port, add the default port of 80 // Strip off the port
if (url.Split(':').Length < 3) return new Uri(url).GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped);
{
url += ":80";
}
return url;
} }
private LiveTvOptions GetConfiguration() private LiveTvOptions GetConfiguration()

View file

@ -51,7 +51,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{ {
var options = new HttpRequestOptions var options = new HttpRequestOptions
{ {
Url = string.Format("{0}/lineup.json", GetApiUrl(info)), Url = string.Format("{0}/lineup.json", GetApiUrl(info, false)),
CancellationToken = cancellationToken CancellationToken = cancellationToken
}; };
using (var stream = await _httpClient.Get(options)) using (var stream = await _httpClient.Get(options))
@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
using (var stream = await _httpClient.Get(new HttpRequestOptions() using (var stream = await _httpClient.Get(new HttpRequestOptions()
{ {
Url = string.Format("{0}/", GetApiUrl(info)), Url = string.Format("{0}/", GetApiUrl(info, false)),
CancellationToken = cancellationToken CancellationToken = cancellationToken
})) }))
{ {
@ -97,7 +97,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
using (var stream = await _httpClient.Get(new HttpRequestOptions() using (var stream = await _httpClient.Get(new HttpRequestOptions()
{ {
Url = string.Format("{0}/tuners.html", GetApiUrl(info)), Url = string.Format("{0}/tuners.html", GetApiUrl(info, false)),
CancellationToken = cancellationToken CancellationToken = cancellationToken
})) }))
{ {
@ -128,7 +128,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
} }
} }
public string GetApiUrl(TunerHostInfo info) private string GetApiUrl(TunerHostInfo info, bool isPlayback)
{ {
var url = info.Url; var url = info.Url;
@ -137,7 +137,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
url = "http://" + url; url = "http://" + url;
} }
return url.TrimEnd('/'); var uri = new Uri(url);
if (isPlayback)
{
var builder = new UriBuilder(uri);
builder.Port = 5004;
uri = builder.Uri;
}
return uri.AbsoluteUri.TrimEnd('/');
} }
private static string StripXML(string source) private static string StripXML(string source)
@ -187,21 +196,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
return GetConfiguration().TunerHosts.Where(i => string.Equals(i.Type, Type, StringComparison.OrdinalIgnoreCase)).ToList(); return GetConfiguration().TunerHosts.Where(i => string.Equals(i.Type, Type, StringComparison.OrdinalIgnoreCase)).ToList();
} }
public async Task<MediaSourceInfo> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken) private MediaSourceInfo GetMediaSource(TunerHostInfo info, string channelId, string profile)
{ {
var channels = await GetChannels(info, cancellationToken).ConfigureAwait(false); var mediaSource = new MediaSourceInfo
var tuners = await GetTunerInfos(info, cancellationToken).ConfigureAwait(false);
var channel = channels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase));
if (channel != null)
{ {
if (tuners.FindIndex(t => t.Status == LiveTvTunerStatus.Available) >= 0) Path = GetApiUrl(info, true) + "/auto/v" + channelId,
{ Protocol = MediaProtocol.Http,
return new MediaSourceInfo MediaStreams = new List<MediaStream>
{
Path = GetApiUrl(info) + "/auto/v" + channelId,
Protocol = MediaProtocol.Http,
MediaStreams = new List<MediaStream>
{ {
new MediaStream new MediaStream
{ {
@ -217,15 +218,28 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
Index = -1 Index = -1
} }
} },
}; RequiresOpening = false,
} RequiresClosing = false,
BufferMs = 1000
};
throw new ApplicationException("No tuners avaliable."); return mediaSource;
}
throw new ApplicationException("Channel not found.");
} }
public Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, string channelId, CancellationToken cancellationToken)
{
var list = new List<MediaSourceInfo>();
list.Add(GetMediaSource(info, channelId, null));
return Task.FromResult(list);
}
public async Task<MediaSourceInfo> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken)
{
return GetMediaSource(info, channelId, null);
}
public async Task Validate(TunerHostInfo info) public async Task Validate(TunerHostInfo info)
{ {

View file

@ -171,7 +171,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
Index = -1 Index = -1
} }
} },
RequiresOpening = false,
RequiresClosing = false
}; };
} }
throw new ApplicationException("Host doesnt provide this channel"); throw new ApplicationException("Host doesnt provide this channel");
@ -193,5 +195,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
throw new FileNotFoundException(); throw new FileNotFoundException();
} }
} }
public Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, string channelId, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
} }
} }

View file

@ -1489,5 +1489,5 @@
"GuideProviderListingsStep": "Step 2: Select Listings", "GuideProviderListingsStep": "Step 2: Select Listings",
"GuideProviderLoginStep": "Step 1: Login", "GuideProviderLoginStep": "Step 1: Login",
"LabelLineup": "Lineup", "LabelLineup": "Lineup",
"MessageTunerDeviceNotListed": "Is your tuner device not listed? Try installing an external service plugin for more Live TV options." "MessageTunerDeviceNotListed": "Is your tuner device not listed? Try installing an external service provider for more Live TV options."
} }