aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/LiveTv
diff options
context:
space:
mode:
authorT. Adams <t.adams88@gmail.com>2015-04-03 11:04:25 -0700
committerT. Adams <t.adams88@gmail.com>2015-04-03 11:04:25 -0700
commitabf12569ba2aa31ea3a00e4faf3adad2f740cbd9 (patch)
tree47c57c6361825491d38e3def6b716926ddd9aa59 /MediaBrowser.Server.Implementations/LiveTv
parent46c92107490263f8e6abefbd2259780013fa195d (diff)
parentef505c8e9e2b8f348aeaa89be6bc446014b72996 (diff)
Merging in latest dev
Diffstat (limited to 'MediaBrowser.Server.Implementations/LiveTv')
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs6
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs2
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs153
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs108
4 files changed, 228 insertions, 41 deletions
diff --git a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs
index ed67df01e..7c3af0a54 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs
@@ -51,11 +51,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var response = await _httpClient.GetResponse(options).ConfigureAwait(false);
- if (response.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
+ var contentType = response.ContentType;
+
+ if (contentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
{
imageResponse.HasImage = true;
imageResponse.Stream = response.Content;
- imageResponse.SetFormatFromMimeType(response.ContentType);
+ imageResponse.SetFormatFromMimeType(contentType);
}
else
{
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
index 7f4440fbc..401cf8765 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
@@ -373,7 +373,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
StartDate = item.StartDate,
OfficialRating = item.OfficialRating,
IsHD = item.IsHD,
- OriginalAirDate = item.PremiereDate,
+ OriginalAirDate = item.OriginalAirDate,
Audio = item.Audio,
CommunityRating = GetClientCommunityRating(item.CommunityRating),
IsRepeat = item.IsRepeat,
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index 2bc6cbadf..cb9bb7711 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -1,10 +1,8 @@
-using System.Globalization;
-using MediaBrowser.Common;
+using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress;
using MediaBrowser.Common.ScheduledTasks;
-using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
@@ -15,7 +13,6 @@ using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Sorting;
-using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
@@ -88,8 +85,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
get { return _services; }
}
- public ILiveTvService ActiveService { get; private set; }
-
private LiveTvOptions GetConfiguration()
{
return _config.GetConfiguration<LiveTvOptions>("livetv");
@@ -103,8 +98,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
_services.AddRange(services);
- ActiveService = _services.FirstOrDefault();
-
foreach (var service in _services)
{
service.DataSourceChanged += service_DataSourceChanged;
@@ -316,6 +309,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return await GetLiveStream(id, true, cancellationToken).ConfigureAwait(false);
}
+ public async Task<IEnumerable<MediaSourceInfo>> GetRecordingMediaSources(string id, CancellationToken cancellationToken)
+ {
+ var item = await GetInternalRecording(id, cancellationToken).ConfigureAwait(false);
+ var service = GetService(item);
+
+ return await service.GetRecordingStreamMediaSources(id, cancellationToken).ConfigureAwait(false);
+ }
+
+ public async Task<IEnumerable<MediaSourceInfo>> GetChannelMediaSources(string id, CancellationToken cancellationToken)
+ {
+ var item = GetInternalChannel(id);
+ var service = GetService(item);
+
+ return await service.GetChannelStreamMediaSources(id, cancellationToken).ConfigureAwait(false);
+ }
+
private ILiveTvService GetService(ILiveTvItem item)
{
return GetService(item.ServiceName);
@@ -333,30 +342,48 @@ namespace MediaBrowser.Server.Implementations.LiveTv
try
{
MediaSourceInfo info;
+ bool isVideo;
if (isChannel)
{
var channel = GetInternalChannel(id);
+ isVideo = channel.ChannelType == ChannelType.TV;
var service = GetService(channel);
_logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId);
info = await service.GetChannelStream(channel.ExternalId, null, cancellationToken).ConfigureAwait(false);
+ info.RequiresClosing = true;
+
+ if (info.RequiresClosing)
+ {
+ var idPrefix = service.GetType().FullName.GetMD5().ToString("N") + "_";
+
+ info.LiveStreamId = idPrefix + info.Id;
+ }
}
else
{
var recording = await GetInternalRecording(id, cancellationToken).ConfigureAwait(false);
+ isVideo = !string.Equals(recording.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase);
var service = GetService(recording);
_logger.Info("Opening recording stream from {0}, external recording Id: {1}", service.Name, recording.RecordingInfo.Id);
info = await service.GetRecordingStream(recording.RecordingInfo.Id, null, cancellationToken).ConfigureAwait(false);
+ info.RequiresClosing = true;
+
+ if (info.RequiresClosing)
+ {
+ var idPrefix = service.GetType().FullName.GetMD5().ToString("N") + "_";
+
+ info.LiveStreamId = idPrefix + info.Id;
+ }
}
_logger.Info("Live stream info: {0}", _jsonSerializer.SerializeToString(info));
- Sanitize(info);
+ Normalize(info, isVideo);
var data = new LiveStreamData
{
Info = info,
- ConsumerCount = 1,
IsChannel = isChannel,
ItemId = id
};
@@ -377,25 +404,43 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
}
- private void Sanitize(MediaSourceInfo mediaSource)
+ private void Normalize(MediaSourceInfo mediaSource, bool isVideo)
{
if (mediaSource.MediaStreams.Count == 0)
{
- mediaSource.MediaStreams.AddRange(new List<MediaStream>
+ if (isVideo)
{
- new MediaStream
+ mediaSource.MediaStreams.AddRange(new List<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
- },
- 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,
+
+ // Set to true if unknown to enable deinterlacing
+ 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
+ }
+ });
+ }
+ else
+ {
+ mediaSource.MediaStreams.AddRange(new List<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
- }
- });
+ 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
+ }
+ });
+ }
}
// Clean some bad data coming from providers
@@ -544,13 +589,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv
item.Name = info.Name;
item.OfficialRating = info.OfficialRating;
item.Overview = info.Overview;
- item.PremiereDate = info.OriginalAirDate;
+ item.OriginalAirDate = info.OriginalAirDate;
item.ProviderImagePath = info.ImagePath;
item.ProviderImageUrl = info.ImageUrl;
item.RunTimeTicks = (info.EndDate - info.StartDate).Ticks;
item.StartDate = info.StartDate;
- item.ProductionYear = info.ProductionYear;
+ item.ProductionYear = info.ProductionYear;
+ item.PremiereDate = item.PremiereDate ?? info.OriginalAirDate;
+
await item.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
return item;
@@ -714,6 +761,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
programs = programs.Where(p => p.IsMovie == query.IsMovie);
}
+ if (query.IsSports.HasValue)
+ {
+ programs = programs.Where(p => p.IsSports == query.IsSports);
+ }
+
programs = _libraryManager.Sort(programs, user, query.SortBy, query.SortOrder ?? SortOrder.Ascending)
.Cast<LiveTvProgram>();
@@ -779,6 +831,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
programs = programs.Where(p => p.IsMovie == query.IsMovie.Value);
}
+ if (query.IsSports.HasValue)
+ {
+ programs = programs.Where(p => p.IsSports == query.IsSports.Value);
+ }
+
var programList = programs.ToList();
var genres = programList.SelectMany(i => i.Genres)
@@ -949,6 +1006,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(p => progress.Report(90 + (p * .1)));
await CleanDatabaseInternal(progress, cancellationToken).ConfigureAwait(false);
+
+ foreach (var program in _programs.Values
+ .Where(i => (i.StartDate - DateTime.UtcNow).TotalDays <= 1)
+ .ToList())
+ {
+ RefreshIfNeeded(program);
+ }
}
finally
{
@@ -1742,7 +1806,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
class LiveStreamData
{
internal MediaSourceInfo Info;
- internal int ConsumerCount;
internal string ItemId;
internal bool IsChannel;
}
@@ -1753,19 +1816,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv
try
{
- var service = ActiveService;
+ var parts = id.Split(new[] { '_' }, 2);
- LiveStreamData data;
- if (_openStreams.TryGetValue(id, out data))
- {
- if (data.ConsumerCount > 1)
- {
- data.ConsumerCount--;
- _logger.Info("Decrementing live stream client count.");
- return;
- }
+ var service = _services.FirstOrDefault(i => string.Equals(i.GetType().FullName.GetMD5().ToString("N"), parts[0], StringComparison.OrdinalIgnoreCase));
+ if (service == null)
+ {
+ throw new ArgumentException("Service not found.");
}
+
+ id = parts[1];
+
+ LiveStreamData data;
_openStreams.TryRemove(id, out data);
_logger.Info("Closing live stream from {0}, stream Id: {1}", service.Name, id);
@@ -1846,6 +1908,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
Name = service.Name
};
+ var tunerIdPrefix = service.GetType().FullName.GetMD5().ToString("N") + "_";
+
try
{
var statusInfo = await service.GetStatusInfoAsync(cancellationToken).ConfigureAwait(false);
@@ -1867,7 +1931,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
channelName = channel == null ? null : channel.Name;
}
- return _tvDtoService.GetTunerInfoDto(service.Name, i, channelName);
+ var dto = _tvDtoService.GetTunerInfoDto(service.Name, i, channelName);
+
+ dto.Id = tunerIdPrefix + dto.Id;
+
+ return dto;
}).ToList();
}
@@ -1920,7 +1988,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv
/// <returns>Task.</returns>
public Task ResetTuner(string id, CancellationToken cancellationToken)
{
- return ActiveService.ResetTuner(id, cancellationToken);
+ var parts = id.Split(new[] { '_' }, 2);
+
+ var service = _services.FirstOrDefault(i => string.Equals(i.GetType().FullName.GetMD5().ToString("N"), parts[0], StringComparison.OrdinalIgnoreCase));
+
+ if (service == null)
+ {
+ throw new ArgumentException("Service not found.");
+ }
+
+ return service.ResetTuner(parts[1], cancellationToken);
}
public async Task<BaseItemDto> GetLiveTvFolder(string userId, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
new file mode 100644
index 000000000..d549cad46
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
@@ -0,0 +1,108 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.LiveTv
+{
+ public class LiveTvMediaSourceProvider : IMediaSourceProvider
+ {
+ private readonly ILiveTvManager _liveTvManager;
+ private readonly IJsonSerializer _jsonSerializer;
+ private readonly ILogger _logger;
+ private readonly IMediaSourceManager _mediaSourceManager;
+
+ public LiveTvMediaSourceProvider(ILiveTvManager liveTvManager, IJsonSerializer jsonSerializer, ILogManager logManager, IMediaSourceManager mediaSourceManager)
+ {
+ _liveTvManager = liveTvManager;
+ _jsonSerializer = jsonSerializer;
+ _mediaSourceManager = mediaSourceManager;
+ _logger = logManager.GetLogger(GetType().Name);
+ }
+
+ public Task<IEnumerable<MediaSourceInfo>> GetMediaSources(IHasMediaSources item, CancellationToken cancellationToken)
+ {
+ var channelItem = item as ILiveTvItem;
+
+ if (channelItem != null)
+ {
+ var hasMetadata = (IHasMetadata)channelItem;
+
+ if (string.IsNullOrWhiteSpace(hasMetadata.Path))
+ {
+ return GetMediaSourcesInternal(channelItem, cancellationToken);
+ }
+ }
+
+ return Task.FromResult<IEnumerable<MediaSourceInfo>>(new List<MediaSourceInfo>());
+ }
+
+ private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(ILiveTvItem item, CancellationToken cancellationToken)
+ {
+ IEnumerable<MediaSourceInfo> sources;
+
+ try
+ {
+ if (item is ILiveTvRecording)
+ {
+ sources = await _liveTvManager.GetRecordingMediaSources(item.Id.ToString("N"), cancellationToken)
+ .ConfigureAwait(false);
+ }
+ else
+ {
+ sources = await _liveTvManager.GetChannelMediaSources(item.Id.ToString("N"), cancellationToken)
+ .ConfigureAwait(false);
+ }
+ }
+ catch (NotImplementedException)
+ {
+ var hasMediaSources = (IHasMediaSources)item;
+
+ sources = _mediaSourceManager.GetStaticMediaSources(hasMediaSources, false)
+ .ToList();
+ }
+
+ var list = sources.ToList();
+
+ 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"));
+ source.OpenToken = string.Join("|", openKeys.ToArray());
+ }
+
+ _logger.Debug("MediaSources: {0}", _jsonSerializer.SerializeToString(list));
+
+ return list;
+ }
+
+ public async Task<MediaSourceInfo> OpenMediaSource(string openToken, CancellationToken cancellationToken)
+ {
+ var keys = openToken.Split(new[] { '|' }, 2);
+
+ if (string.Equals(keys[0], typeof(LiveTvChannel).Name, StringComparison.OrdinalIgnoreCase))
+ {
+ return await _liveTvManager.GetChannelStream(keys[1], cancellationToken).ConfigureAwait(false);
+ }
+
+ return await _liveTvManager.GetRecordingStream(keys[1], cancellationToken).ConfigureAwait(false);
+ }
+
+ public Task CloseMediaSource(string liveStreamId, CancellationToken cancellationToken)
+ {
+ return _liveTvManager.CloseLiveStream(liveStreamId, cancellationToken);
+ }
+ }
+}