update emby tv

pull/702/head
Luke Pulverenti 9 years ago
parent f7c1a88166
commit ba9ed26c4a

@ -924,7 +924,7 @@ namespace MediaBrowser.Api.Playback
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
{

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

@ -47,6 +47,14 @@ namespace MediaBrowser.Controller.LiveTv
/// <returns>Task&lt;MediaSourceInfo&gt;.</returns>
Task<MediaSourceInfo> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken);
/// <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.
/// </summary>
/// <param name="info">The information.</param>

@ -436,7 +436,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
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
{

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

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

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

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

@ -1,5 +1,6 @@
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.LiveTv;
@ -74,20 +75,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
var status = new LiveTvServiceStatusInfo();
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 host.GetTunerInfos(hostInstance, cancellationToken).ConfigureAwait(false);
var tuners = await hostInstance.Item1.GetTunerInfos(hostInstance.Item2, cancellationToken).ConfigureAwait(false);
list.AddRange(tuners);
}
catch (Exception ex)
{
_logger.ErrorException("Error getting tuners", ex);
}
list.AddRange(tuners);
}
catch (Exception ex)
{
_logger.ErrorException("Error getting tuners", ex);
}
}
@ -102,20 +100,23 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
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 host.GetChannels(hostInstance, cancellationToken).ConfigureAwait(false);
var channels = await hostInstance.Item1.GetChannels(hostInstance.Item2, cancellationToken).ConfigureAwait(false);
var newChannels = channels.ToList();
list.AddRange(channels);
}
catch (Exception ex)
foreach (var channel in newChannels)
{
_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;
}
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)
{
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());
}
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)
{
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);
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)
{
return list;
@ -290,14 +317,67 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
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)

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

@ -218,7 +218,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
private ProgramInfo GetProgram(string channel, ScheduleDirect.Program programInfo,
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'",
CultureInfo.InvariantCulture);
DateTime endAt = startAt.AddSeconds(programInfo.duration);
@ -401,7 +401,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
_logger.Info("Headends on account ");
var countryParam = string.Equals("ca", country, StringComparison.OrdinalIgnoreCase)
? "Canada"
? "can"
: "USA";
var options = new HttpRequestOptions()
@ -562,6 +562,44 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
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 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);
}
}
}

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

@ -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.
private const char StreamIdDelimeter = '_';
private const string StreamIdDelimeterString = "|";
private const string StreamIdDelimeterString = "_";
private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(ILiveTvItem item, CancellationToken cancellationToken)
{
@ -86,14 +86,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv
foreach (var source in list)
{
source.Type = MediaSourceType.Default;
source.RequiresOpening = true;
source.BufferMs = source.BufferMs ?? 1500;
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());
if (!source.RequiresOpening.HasValue)
{
source.RequiresOpening = true;
}
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
if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http)

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

@ -51,7 +51,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
var options = new HttpRequestOptions
{
Url = string.Format("{0}/lineup.json", GetApiUrl(info)),
Url = string.Format("{0}/lineup.json", GetApiUrl(info, false)),
CancellationToken = cancellationToken
};
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()
{
Url = string.Format("{0}/", GetApiUrl(info)),
Url = string.Format("{0}/", GetApiUrl(info, false)),
CancellationToken = cancellationToken
}))
{
@ -97,7 +97,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
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
}))
{
@ -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;
@ -137,7 +137,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
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)
@ -187,21 +196,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
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 tuners = await GetTunerInfos(info, cancellationToken).ConfigureAwait(false);
var channel = channels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase));
if (channel != null)
var mediaSource = new MediaSourceInfo
{
if (tuners.FindIndex(t => t.Status == LiveTvTunerStatus.Available) >= 0)
{
return new MediaSourceInfo
{
Path = GetApiUrl(info) + "/auto/v" + channelId,
Protocol = MediaProtocol.Http,
MediaStreams = new List<MediaStream>
Path = GetApiUrl(info, true) + "/auto/v" + channelId,
Protocol = MediaProtocol.Http,
MediaStreams = new List<MediaStream>
{
new MediaStream
{
@ -217,15 +218,28 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
Index = -1
}
}
};
}
},
RequiresOpening = false,
RequiresClosing = false,
BufferMs = 1000
};
throw new ApplicationException("No tuners avaliable.");
}
throw new ApplicationException("Channel not found.");
return mediaSource;
}
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)
{

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

@ -1489,5 +1489,5 @@
"GuideProviderListingsStep": "Step 2: Select Listings",
"GuideProviderLoginStep": "Step 1: Login",
"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."
}

Loading…
Cancel
Save