diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index a6171ff2c3..8d07b10ce5 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Dto;
@@ -25,7 +26,6 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Api.Playback
{
@@ -71,6 +71,7 @@ namespace MediaBrowser.Api.Playback
protected IItemRepository ItemRepository { get; private set; }
protected ILiveTvManager LiveTvManager { get; private set; }
protected IDlnaManager DlnaManager { get; private set; }
+ protected IChannelManager ChannelManager { get; private set; }
///
/// Initializes a new instance of the class.
@@ -83,8 +84,9 @@ namespace MediaBrowser.Api.Playback
/// The dto service.
/// The file system.
/// The item repository.
- protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager)
+ protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager)
{
+ ChannelManager = channelManager;
DlnaManager = dlnaManager;
EncodingManager = encodingManager;
LiveTvManager = liveTvManager;
@@ -169,13 +171,28 @@ namespace MediaBrowser.Api.Playback
/// System.String.
protected virtual string GetMapArgs(StreamState state)
{
- var args = string.Empty;
+ // If we don't have known media info
+ // If input is video, use -sn to drop subtitles
+ // Otherwise just return empty
+ if (state.VideoStream == null && state.AudioStream == null)
+ {
+ return state.IsInputVideo ? "-sn" : string.Empty;
+ }
- if (!state.HasMediaStreams)
+ // We have media info, but we don't know the stream indexes
+ if (state.VideoStream != null && state.VideoStream.Index == -1)
+ {
+ return "-sn";
+ }
+
+ // We have media info, but we don't know the stream indexes
+ if (state.AudioStream != null && state.AudioStream.Index == -1)
{
return state.IsInputVideo ? "-sn" : string.Empty;
}
+ var args = string.Empty;
+
if (state.VideoStream != null)
{
args += string.Format("-map 0:{0}", state.VideoStream.Index);
@@ -1329,13 +1346,14 @@ namespace MediaBrowser.Api.Playback
throw new ArgumentException(string.Format("{0} is not allowed to play media.", user.Name));
}
+ List mediaStreams = null;
+
if (item is ILiveTvRecording)
{
var recording = await LiveTvManager.GetInternalRecording(request.Id, cancellationToken).ConfigureAwait(false);
state.VideoType = VideoType.VideoFile;
state.IsInputVideo = string.Equals(recording.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
- state.PlayableStreamFileNames = new List();
var path = recording.RecordingInfo.Path;
var mediaUrl = recording.RecordingInfo.Url;
@@ -1345,6 +1363,7 @@ namespace MediaBrowser.Api.Playback
var streamInfo = await LiveTvManager.GetRecordingStream(request.Id, cancellationToken).ConfigureAwait(false);
state.LiveTvStreamId = streamInfo.Id;
+ mediaStreams = streamInfo.MediaStreams;
path = streamInfo.Path;
mediaUrl = streamInfo.Url;
@@ -1381,11 +1400,11 @@ namespace MediaBrowser.Api.Playback
state.VideoType = VideoType.VideoFile;
state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
- state.PlayableStreamFileNames = new List();
var streamInfo = await LiveTvManager.GetChannelStream(request.Id, cancellationToken).ConfigureAwait(false);
state.LiveTvStreamId = streamInfo.Id;
+ mediaStreams = streamInfo.MediaStreams;
if (!string.IsNullOrEmpty(streamInfo.Path))
{
@@ -1406,6 +1425,16 @@ namespace MediaBrowser.Api.Playback
state.InputVideoSync = "-1";
state.InputAudioSync = "1";
}
+ else if (item is IChannelMediaItem)
+ {
+ var channelMediaSources = await ChannelManager.GetChannelItemMediaSources(request.Id, CancellationToken.None).ConfigureAwait(false);
+
+ var source = channelMediaSources.First();
+ state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
+ state.IsRemote = source.IsRemote;
+ state.MediaPath = source.Path;
+ state.RunTimeTicks = item.RunTimeTicks;
+ }
else
{
state.MediaPath = item.Path;
@@ -1424,7 +1453,11 @@ namespace MediaBrowser.Api.Playback
: video.PlayableStreamFileNames.ToList();
state.DeInterlace = string.Equals(video.Container, "wtv", StringComparison.OrdinalIgnoreCase);
- state.InputTimestamp = video.Timestamp ?? TransportStreamTimestamp.None;
+
+ if (video.Timestamp.HasValue)
+ {
+ state.InputTimestamp = video.Timestamp.Value;
+ }
state.InputContainer = video.Container;
}
@@ -1440,7 +1473,7 @@ namespace MediaBrowser.Api.Playback
var videoRequest = request as VideoStreamRequest;
- var mediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery
+ mediaStreams = mediaStreams ?? ItemRepository.GetMediaStreams(new MediaStreamQuery
{
ItemId = item.Id
@@ -1469,8 +1502,6 @@ namespace MediaBrowser.Api.Playback
state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true);
}
- state.HasMediaStreams = mediaStreams.Count > 0;
-
state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10;
state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 2852d2489f..553f023684 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Dto;
@@ -24,8 +25,7 @@ namespace MediaBrowser.Api.Playback.Hls
///
public abstract class BaseHlsService : BaseStreamingService
{
- protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager)
- : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
+ protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager)
{
}
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index fd93ef6852..c5405a3b5d 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Dto;
@@ -59,7 +60,7 @@ namespace MediaBrowser.Api.Playback.Hls
public class DynamicHlsService : BaseHlsService
{
- public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
+ public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager)
{
}
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index 77ac95815d..162ab741aa 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Dto;
@@ -53,7 +54,7 @@ namespace MediaBrowser.Api.Playback.Hls
///
public class VideoHlsService : BaseHlsService
{
- public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
+ public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager)
{
}
diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
index d746b265df..2e002cc9be 100644
--- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
@@ -43,8 +44,7 @@ namespace MediaBrowser.Api.Playback.Progressive
///
public class AudioService : BaseProgressiveStreamingService
{
- public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor)
- : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, httpClient, imageProcessor)
+ public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager, imageProcessor, httpClient)
{
}
diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
index f39169dbd8..06e8f7b2c9 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
@@ -26,11 +27,10 @@ namespace MediaBrowser.Api.Playback.Progressive
protected readonly IImageProcessor ImageProcessor;
protected readonly IHttpClient HttpClient;
- protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor)
- : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
+ protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager)
{
- HttpClient = httpClient;
ImageProcessor = imageProcessor;
+ HttpClient = httpClient;
}
///
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index d7061ae754..29bc3f8978 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
@@ -59,7 +60,7 @@ namespace MediaBrowser.Api.Playback.Progressive
///
public class VideoService : BaseProgressiveStreamingService
{
- public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, httpClient, imageProcessor)
+ public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager, imageProcessor, httpClient)
{
}
@@ -183,7 +184,7 @@ namespace MediaBrowser.Api.Playback.Progressive
private string GetAudioArguments(StreamState state)
{
// If the video doesn't have an audio stream, return a default.
- if (state.AudioStream == null && state.HasMediaStreams)
+ if (state.AudioStream == null && state.VideoStream != null)
{
return string.Empty;
}
diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs
index cc733dfaf3..f9e861e8d4 100644
--- a/MediaBrowser.Api/Playback/StreamState.cs
+++ b/MediaBrowser.Api/Playback/StreamState.cs
@@ -28,6 +28,11 @@ namespace MediaBrowser.Api.Playback
get { return Request as VideoStreamRequest; }
}
+ public StreamState()
+ {
+ PlayableStreamFileNames = new List();
+ }
+
///
/// Gets or sets the log file stream.
///
@@ -57,8 +62,6 @@ namespace MediaBrowser.Api.Playback
public List PlayableStreamFileNames { get; set; }
- public bool HasMediaStreams { get; set; }
-
public string LiveTvStreamId { get; set; }
public int SegmentLength = 10;
diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs
index 0e69c96d19..4cb48e9fe8 100644
--- a/MediaBrowser.Api/SessionsService.cs
+++ b/MediaBrowser.Api/SessionsService.cs
@@ -218,6 +218,9 @@ namespace MediaBrowser.Api
[ApiMember(Name = "SupportedCommands", Description = "A list of supported remote control commands, comma delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public string SupportedCommands { get; set; }
+ [ApiMember(Name = "MessageCallbackUrl", Description = "A url to post messages to, including remote control commands.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string MessageCallbackUrl { get; set; }
+
[ApiMember(Name = "SupportsMediaControl", Description = "Determines whether media can be played remotely.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
public bool SupportsMediaControl { get; set; }
}
@@ -414,7 +417,9 @@ namespace MediaBrowser.Api
SupportedCommands = request.SupportedCommands.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
- SupportsMediaControl = request.SupportsMediaControl
+ SupportsMediaControl = request.SupportsMediaControl,
+
+ MessageCallbackUrl = request.MessageCallbackUrl
});
}
diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
index 72a996b193..6d32f7d356 100644
--- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
@@ -1,6 +1,8 @@
-using System.Linq;
-using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Entities;
+using System.Collections.Generic;
+using System.Linq;
namespace MediaBrowser.Controller.Channels
{
@@ -18,6 +20,8 @@ namespace MediaBrowser.Controller.Channels
public string OriginalImageUrl { get; set; }
+ public List ChannelMediaSources { get; set; }
+
protected override bool GetBlockUnratedValue(UserConfiguration config)
{
return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent);
@@ -30,5 +34,23 @@ namespace MediaBrowser.Controller.Channels
return false;
}
}
+
+ public ChannelAudioItem()
+ {
+ ChannelMediaSources = new List();
+ }
+
+ public override LocationType LocationType
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(Path))
+ {
+ return LocationType.Remote;
+ }
+
+ return base.LocationType;
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs b/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs
index b20dcf6204..c18f748563 100644
--- a/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
+using System.Collections.Generic;
namespace MediaBrowser.Controller.Channels
{
@@ -8,10 +9,11 @@ namespace MediaBrowser.Controller.Channels
public string ExternalId { get; set; }
public string ChannelId { get; set; }
-
+
public ChannelItemType ChannelItemType { get; set; }
public string OriginalImageUrl { get; set; }
+ public List Tags { get; set; }
protected override bool GetBlockUnratedValue(UserConfiguration config)
{
@@ -26,5 +28,10 @@ namespace MediaBrowser.Controller.Channels
return false;
}
}
+
+ public ChannelCategoryItem()
+ {
+ Tags = new List();
+ }
}
}
diff --git a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
index 7bb8d15fc3..948754e49e 100644
--- a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
+++ b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
@@ -19,6 +19,7 @@ namespace MediaBrowser.Controller.Channels
public List Genres { get; set; }
public List Studios { get; set; }
+ public List Tags { get; set; }
public List People { get; set; }
@@ -49,6 +50,7 @@ namespace MediaBrowser.Controller.Channels
Genres = new List();
Studios = new List();
People = new List();
+ Tags = new List();
ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase);
}
}
diff --git a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
index 8105bf43cd..3630342679 100644
--- a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
+++ b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
@@ -18,9 +18,12 @@ namespace MediaBrowser.Controller.Channels
public int? Height { get; set; }
public int? AudioChannels { get; set; }
+ public bool IsRemote { get; set; }
+
public ChannelMediaInfo()
{
RequiredHttpHeaders = new Dictionary();
+ IsRemote = true;
}
}
}
\ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
index 0d2bd933be..01438bfad6 100644
--- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
+using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@@ -20,6 +21,8 @@ namespace MediaBrowser.Controller.Channels
public string OriginalImageUrl { get; set; }
+ public List ChannelMediaSources { get; set; }
+
public override string GetUserDataKey()
{
if (ContentType == ChannelMediaContentType.Trailer)
@@ -55,5 +58,23 @@ namespace MediaBrowser.Controller.Channels
return false;
}
}
+
+ public ChannelVideoItem()
+ {
+ ChannelMediaSources = new List();
+ }
+
+ public override LocationType LocationType
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(Path))
+ {
+ return LocationType.Remote;
+ }
+
+ return base.LocationType;
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/Channels/IChannel.cs b/MediaBrowser.Controller/Channels/IChannel.cs
index bd0bd64ea6..8a21179b11 100644
--- a/MediaBrowser.Controller/Channels/IChannel.cs
+++ b/MediaBrowser.Controller/Channels/IChannel.cs
@@ -59,4 +59,15 @@ namespace MediaBrowser.Controller.Channels
/// IEnumerable{ImageType}.
IEnumerable GetSupportedChannelImages();
}
+
+ public interface IRequiresMediaInfoCallback
+ {
+ ///
+ /// Gets the channel item media information.
+ ///
+ /// The identifier.
+ /// The cancellation token.
+ /// Task{IEnumerable{ChannelMediaInfo}}.
+ Task> GetChannelItemMediaInfo(string id, CancellationToken cancellationToken);
+ }
}
diff --git a/MediaBrowser.Controller/Channels/IChannelItem.cs b/MediaBrowser.Controller/Channels/IChannelItem.cs
index fc088b8886..8b97701138 100644
--- a/MediaBrowser.Controller/Channels/IChannelItem.cs
+++ b/MediaBrowser.Controller/Channels/IChannelItem.cs
@@ -2,7 +2,7 @@
namespace MediaBrowser.Controller.Channels
{
- public interface IChannelItem : IHasImages
+ public interface IChannelItem : IHasImages, IHasTags
{
string ChannelId { get; set; }
diff --git a/MediaBrowser.Controller/Channels/IChannelManager.cs b/MediaBrowser.Controller/Channels/IChannelManager.cs
index 05f9afcf00..a47f6e6aee 100644
--- a/MediaBrowser.Controller/Channels/IChannelManager.cs
+++ b/MediaBrowser.Controller/Channels/IChannelManager.cs
@@ -31,5 +31,13 @@ namespace MediaBrowser.Controller.Channels
/// The cancellation token.
/// Task{QueryResult{BaseItemDto}}.
Task> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken);
+
+ ///
+ /// Gets the channel item media sources.
+ ///
+ /// The identifier.
+ /// The cancellation token.
+ /// Task{IEnumerable{ChannelMediaInfo}}.
+ Task> GetChannelItemMediaSources(string id, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Channels/IChannelMediaItem.cs b/MediaBrowser.Controller/Channels/IChannelMediaItem.cs
index 3a2c076e0a..1e634027f0 100644
--- a/MediaBrowser.Controller/Channels/IChannelMediaItem.cs
+++ b/MediaBrowser.Controller/Channels/IChannelMediaItem.cs
@@ -1,9 +1,13 @@
-namespace MediaBrowser.Controller.Channels
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Channels
{
public interface IChannelMediaItem : IChannelItem
{
bool IsInfiniteStream { get; set; }
ChannelMediaContentType ContentType { get; set; }
+
+ List ChannelMediaSources { get; set; }
}
}
\ No newline at end of file
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 40b52b8861..dca645a750 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -10,16 +10,18 @@ namespace MediaBrowser.Controller.Entities.Audio
///
/// Class Audio
///
- public class Audio : BaseItem, IHasMediaStreams, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo
+ public class Audio : BaseItem, IHasMediaStreams, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo, IHasTags
{
public string FormatName { get; set; }
public long? Size { get; set; }
public string Container { get; set; }
public int? TotalBitrate { get; set; }
+ public List Tags { get; set; }
public Audio()
{
Artists = new List();
+ Tags = new List();
}
///
diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs
index 5f07b9ff80..d6dd7698e6 100644
--- a/MediaBrowser.Controller/Session/ISessionController.cs
+++ b/MediaBrowser.Controller/Session/ISessionController.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Session;
+using MediaBrowser.Model.System;
using System.Threading;
using System.Threading.Tasks;
@@ -54,9 +55,10 @@ namespace MediaBrowser.Controller.Session
///
/// Sends the restart required message.
///
+ /// The information.
/// The cancellation token.
/// Task.
- Task SendRestartRequiredNotification(CancellationToken cancellationToken);
+ Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken);
///
/// Sends the user data change info.
diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
index 9312b84421..bcbd2a9c7c 100644
--- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
@@ -19,6 +19,7 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.System;
namespace MediaBrowser.Dlna.PlayTo
{
@@ -320,7 +321,7 @@ namespace MediaBrowser.Dlna.PlayTo
return Task.FromResult(true);
}
- public Task SendRestartRequiredNotification(CancellationToken cancellationToken)
+ public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken)
{
return Task.FromResult(true);
}
diff --git a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs
deleted file mode 100644
index 08b7fbe492..0000000000
--- a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Logging;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.MediaEncoding.Encoder
-{
- public class AudioEncoder
- {
- private readonly string _ffmpegPath;
- private readonly ILogger _logger;
- private readonly IFileSystem _fileSystem;
- private readonly IApplicationPaths _appPaths;
- private readonly IIsoManager _isoManager;
- private readonly ILiveTvManager _liveTvManager;
-
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
-
- public AudioEncoder(string ffmpegPath, ILogger logger, IFileSystem fileSystem, IApplicationPaths appPaths, IIsoManager isoManager, ILiveTvManager liveTvManager)
- {
- _ffmpegPath = ffmpegPath;
- _logger = logger;
- _fileSystem = fileSystem;
- _appPaths = appPaths;
- _isoManager = isoManager;
- _liveTvManager = liveTvManager;
- }
-
- public Task BeginEncoding(InternalEncodingTask task)
- {
- return new FFMpegProcess(_ffmpegPath, _logger, _fileSystem, _appPaths, _isoManager, _liveTvManager).Start(task, GetArguments);
- }
-
- private string GetArguments(InternalEncodingTask task, string mountedPath)
- {
- var options = task.Request;
-
- return string.Format("{0} -i {1} {2} -id3v2_version 3 -write_id3v1 1 \"{3}\"",
- GetInputModifier(task),
- GetInputArgument(task),
- GetOutputModifier(task),
- options.OutputPath).Trim();
- }
-
- private string GetInputModifier(InternalEncodingTask task)
- {
- return EncodingUtils.GetInputModifier(task);
- }
-
- private string GetInputArgument(InternalEncodingTask task)
- {
- return EncodingUtils.GetInputArgument(new List { task.MediaPath }, task.IsInputRemote);
- }
-
- private string GetOutputModifier(InternalEncodingTask task)
- {
- var options = task.Request;
-
- var audioTranscodeParams = new List
- {
- "-threads " + EncodingUtils.GetNumberOfThreads(task, false).ToString(_usCulture),
- "-vn"
- };
-
- var bitrate = EncodingUtils.GetAudioBitrateParam(task);
-
- if (bitrate.HasValue)
- {
- audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(_usCulture));
- }
-
- var channels = EncodingUtils.GetNumAudioChannelsParam(options, task.AudioStream);
-
- if (channels.HasValue)
- {
- audioTranscodeParams.Add("-ac " + channels.Value);
- }
-
- if (options.AudioSampleRate.HasValue)
- {
- audioTranscodeParams.Add("-ar " + options.AudioSampleRate.Value);
- }
-
- return string.Join(" ", audioTranscodeParams.ToArray());
- }
- }
-}
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
index 2316518566..9bd2e92709 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
@@ -64,77 +64,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
return string.Format("\"{0}\"", url);
}
- public static string GetAudioInputModifier(InternalEncodingTask options)
- {
- return GetCommonInputModifier(options);
- }
-
- public static string GetInputModifier(InternalEncodingTask options)
- {
- var inputModifier = GetCommonInputModifier(options);
-
- //if (state.VideoRequest != null)
- //{
- // inputModifier += " -fflags genpts";
- //}
-
- //if (!string.IsNullOrEmpty(state.InputVideoCodec))
- //{
- // inputModifier += " -vcodec " + state.InputVideoCodec;
- //}
-
- //if (!string.IsNullOrEmpty(state.InputVideoSync))
- //{
- // inputModifier += " -vsync " + state.InputVideoSync;
- //}
-
- return inputModifier;
- }
-
- private static string GetCommonInputModifier(InternalEncodingTask options)
- {
- var inputModifier = string.Empty;
-
- if (options.EnableDebugLogging)
- {
- inputModifier += "-loglevel debug";
- }
-
- var probeSize = GetProbeSizeArgument(options.InputVideoType.HasValue && options.InputVideoType.Value == VideoType.Dvd);
- inputModifier += " " + probeSize;
- inputModifier = inputModifier.Trim();
-
- if (!string.IsNullOrWhiteSpace(options.UserAgent))
- {
- inputModifier += " -user-agent \"" + options.UserAgent + "\"";
- }
-
- inputModifier += " " + GetFastSeekValue(options.Request);
- inputModifier = inputModifier.Trim();
-
- if (!string.IsNullOrEmpty(options.InputFormat))
- {
- inputModifier += " -f " + options.InputFormat;
- }
-
- if (!string.IsNullOrEmpty(options.InputAudioCodec))
- {
- inputModifier += " -acodec " + options.InputAudioCodec;
- }
-
- if (!string.IsNullOrEmpty(options.InputAudioSync))
- {
- inputModifier += " -async " + options.InputAudioSync;
- }
-
- if (options.ReadInputAtNativeFramerate)
- {
- inputModifier += " -re";
- }
-
- return inputModifier;
- }
-
private static string GetFastSeekValue(EncodingOptions options)
{
var time = options.StartTimeTicks;
@@ -157,19 +86,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
return isDvd ? "-probesize 1G -analyzeduration 200M" : string.Empty;
}
- public static int? GetAudioBitrateParam(InternalEncodingTask task)
- {
- if (task.Request.AudioBitRate.HasValue)
- {
- // Make sure we don't request a bitrate higher than the source
- var currentBitrate = task.AudioStream == null ? task.Request.AudioBitRate.Value : task.AudioStream.BitRate ?? task.Request.AudioBitRate.Value;
-
- return Math.Min(currentBitrate, task.Request.AudioBitRate.Value);
- }
-
- return null;
- }
-
///
/// Gets the number of audio channels to specify on the command line
///
@@ -201,35 +117,5 @@ namespace MediaBrowser.MediaEncoding.Encoder
return request.AudioChannels;
}
-
- public static int GetNumberOfThreads(InternalEncodingTask state, bool isWebm)
- {
- // Use more when this is true. -re will keep cpu usage under control
- if (state.ReadInputAtNativeFramerate)
- {
- if (isWebm)
- {
- return Math.Max(Environment.ProcessorCount - 1, 2);
- }
-
- return 0;
- }
-
- // Webm: http://www.webmproject.org/docs/encoder-parameters/
- // The decoder will usually automatically use an appropriate number of threads according to how many cores are available but it can only use multiple threads
- // for the coefficient data if the encoder selected --token-parts > 0 at encode time.
-
- switch (state.QualitySetting)
- {
- case EncodingQuality.HighSpeed:
- return 2;
- case EncodingQuality.HighQuality:
- return 2;
- case EncodingQuality.MaxQuality:
- return isWebm ? Math.Max(Environment.ProcessorCount - 1, 2) : 0;
- default:
- throw new Exception("Unrecognized MediaEncodingQuality value.");
- }
- }
}
}
diff --git a/MediaBrowser.MediaEncoding/Encoder/FFMpegProcess.cs b/MediaBrowser.MediaEncoding/Encoder/FFMpegProcess.cs
deleted file mode 100644
index 05733aef03..0000000000
--- a/MediaBrowser.MediaEncoding/Encoder/FFMpegProcess.cs
+++ /dev/null
@@ -1,168 +0,0 @@
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.MediaEncoding.Encoder
-{
- public class FFMpegProcess : IDisposable
- {
- private readonly string _ffmpegPath;
- private readonly ILogger _logger;
- private readonly IFileSystem _fileSystem;
- private readonly IApplicationPaths _appPaths;
- private readonly IIsoManager _isoManager;
- private readonly ILiveTvManager _liveTvManager;
-
- private Stream _logFileStream;
- private InternalEncodingTask _task;
- private IIsoMount _isoMount;
-
- public FFMpegProcess(string ffmpegPath, ILogger logger, IFileSystem fileSystem, IApplicationPaths appPaths, IIsoManager isoManager, ILiveTvManager liveTvManager)
- {
- _ffmpegPath = ffmpegPath;
- _logger = logger;
- _fileSystem = fileSystem;
- _appPaths = appPaths;
- _isoManager = isoManager;
- _liveTvManager = liveTvManager;
- }
-
- public async Task Start(InternalEncodingTask task, Func argumentsFactory)
- {
- _task = task;
- if (!File.Exists(_ffmpegPath))
- {
- throw new InvalidOperationException("ffmpeg was not found at " + _ffmpegPath);
- }
-
- Directory.CreateDirectory(Path.GetDirectoryName(task.Request.OutputPath));
-
- string mountedPath = null;
- if (task.InputVideoType.HasValue && task.InputVideoType == VideoType.Iso && task.IsoType.HasValue)
- {
- if (_isoManager.CanMount(task.MediaPath))
- {
- _isoMount = await _isoManager.Mount(task.MediaPath, CancellationToken.None).ConfigureAwait(false);
- mountedPath = _isoMount.MountedPath;
- }
- }
-
- var process = new Process
- {
- StartInfo = new ProcessStartInfo
- {
- CreateNoWindow = true,
- UseShellExecute = false,
-
- // Must consume both stdout and stderr or deadlocks may occur
- RedirectStandardOutput = true,
- RedirectStandardError = true,
-
- FileName = _ffmpegPath,
- WorkingDirectory = Path.GetDirectoryName(_ffmpegPath),
- Arguments = argumentsFactory(task, mountedPath),
-
- WindowStyle = ProcessWindowStyle.Hidden,
- ErrorDialog = false
- },
-
- EnableRaisingEvents = true
- };
-
- _logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments);
-
- var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-" + task.Id + ".txt");
- Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
-
- // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
- _logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true);
-
- process.Exited += process_Exited;
-
- try
- {
- process.Start();
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error starting ffmpeg", ex);
-
- task.OnError();
-
- DisposeLogFileStream();
-
- process.Dispose();
-
- throw;
- }
-
- task.OnBegin();
-
- // MUST read both stdout and stderr asynchronously or a deadlock may occurr
- process.BeginOutputReadLine();
-
-#pragma warning disable 4014
- // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
- process.StandardError.BaseStream.CopyToAsync(_logFileStream);
-#pragma warning restore 4014
- }
-
- async void process_Exited(object sender, EventArgs e)
- {
- var process = (Process)sender;
-
- if (_isoMount != null)
- {
- _isoMount.Dispose();
- _isoMount = null;
- }
-
- DisposeLogFileStream();
-
- try
- {
- _logger.Info("FFMpeg exited with code {0} for {1}", process.ExitCode, _task.Request.OutputPath);
- }
- catch
- {
- _logger.Info("FFMpeg exited with an error for {0}", _task.Request.OutputPath);
- }
-
- _task.OnCompleted();
-
- if (!string.IsNullOrEmpty(_task.LiveTvStreamId))
- {
- try
- {
- await _liveTvManager.CloseLiveStream(_task.LiveTvStreamId, CancellationToken.None).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error closing live tv stream", ex);
- }
- }
- }
-
- public void Dispose()
- {
- DisposeLogFileStream();
- }
-
- private void DisposeLogFileStream()
- {
- if (_logFileStream != null)
- {
- _logFileStream.Dispose();
- _logFileStream = null;
- }
- }
- }
-}
diff --git a/MediaBrowser.MediaEncoding/Encoder/ImageEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/ImageEncoder.cs
deleted file mode 100644
index e0ca86c41a..0000000000
--- a/MediaBrowser.MediaEncoding/Encoder/ImageEncoder.cs
+++ /dev/null
@@ -1,235 +0,0 @@
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.MediaEncoding.Encoder
-{
- public class ImageEncoder
- {
- private readonly string _ffmpegPath;
- private readonly ILogger _logger;
- private readonly IFileSystem _fileSystem;
- private readonly IApplicationPaths _appPaths;
-
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
-
- private static readonly SemaphoreSlim ResourcePool = new SemaphoreSlim(10, 10);
-
- public ImageEncoder(string ffmpegPath, ILogger logger, IFileSystem fileSystem, IApplicationPaths appPaths)
- {
- _ffmpegPath = ffmpegPath;
- _logger = logger;
- _fileSystem = fileSystem;
- _appPaths = appPaths;
- }
-
- public async Task EncodeImage(ImageEncodingOptions options, CancellationToken cancellationToken)
- {
- ValidateInput(options);
-
- await ResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- try
- {
- return await EncodeImageInternal(options, cancellationToken).ConfigureAwait(false);
- }
- finally
- {
- ResourcePool.Release();
- }
- }
-
- private async Task EncodeImageInternal(ImageEncodingOptions options, CancellationToken cancellationToken)
- {
- ValidateInput(options);
-
- var inputPath = options.InputPath;
- var filename = Path.GetFileName(inputPath);
-
- if (HasDiacritics(filename))
- {
- inputPath = GetTempFile(inputPath);
- filename = Path.GetFileName(inputPath);
- }
-
- var process = new Process
- {
- StartInfo = new ProcessStartInfo
- {
- CreateNoWindow = true,
- UseShellExecute = false,
- FileName = _ffmpegPath,
- Arguments = GetArguments(options, filename),
- WindowStyle = ProcessWindowStyle.Hidden,
- ErrorDialog = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- WorkingDirectory = Path.GetDirectoryName(inputPath)
- }
- };
-
- _logger.Debug("ffmpeg " + process.StartInfo.Arguments);
-
- process.Start();
-
- var memoryStream = new MemoryStream();
-
-#pragma warning disable 4014
- // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
- process.StandardOutput.BaseStream.CopyToAsync(memoryStream);
-#pragma warning restore 4014
-
- // MUST read both stdout and stderr asynchronously or a deadlock may occurr
- process.BeginErrorReadLine();
-
- var ranToCompletion = process.WaitForExit(5000);
-
- if (!ranToCompletion)
- {
- try
- {
- _logger.Info("Killing ffmpeg process");
-
- process.Kill();
-
- process.WaitForExit(1000);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error killing process", ex);
- }
- }
-
- var exitCode = ranToCompletion ? process.ExitCode : -1;
-
- process.Dispose();
-
- if (exitCode == -1 || memoryStream.Length == 0)
- {
- memoryStream.Dispose();
-
- var msg = string.Format("ffmpeg image encoding failed for {0}", options.InputPath);
-
- _logger.Error(msg);
-
- throw new ApplicationException(msg);
- }
-
- memoryStream.Position = 0;
- return memoryStream;
- }
-
- private string GetTempFile(string path)
- {
- var extension = Path.GetExtension(path) ?? string.Empty;
-
- var tempPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N") + extension);
-
- File.Copy(path, tempPath);
-
- return tempPath;
- }
-
- private string GetArguments(ImageEncodingOptions options, string inputFilename)
- {
- var vfScale = GetFilterGraph(options);
- var outputFormat = GetOutputFormat(options.Format);
-
- var quality = (options.Quality ?? 100) * .3;
- quality = 31 - quality;
- var qualityValue = Convert.ToInt32(Math.Max(quality, 1));
-
- return string.Format("-f image2 -i file:\"{3}\" -q:v {0} {1} -f image2pipe -vcodec {2} -",
- qualityValue.ToString(_usCulture),
- vfScale,
- outputFormat,
- inputFilename);
- }
-
- private string GetFilterGraph(ImageEncodingOptions options)
- {
- if (!options.Width.HasValue &&
- !options.Height.HasValue &&
- !options.MaxHeight.HasValue &&
- !options.MaxWidth.HasValue)
- {
- return string.Empty;
- }
-
- var widthScale = "-1";
- var heightScale = "-1";
-
- if (options.MaxWidth.HasValue)
- {
- widthScale = "min(iw\\," + options.MaxWidth.Value.ToString(_usCulture) + ")";
- }
- else if (options.Width.HasValue)
- {
- widthScale = options.Width.Value.ToString(_usCulture);
- }
-
- if (options.MaxHeight.HasValue)
- {
- heightScale = "min(ih\\," + options.MaxHeight.Value.ToString(_usCulture) + ")";
- }
- else if (options.Height.HasValue)
- {
- heightScale = options.Height.Value.ToString(_usCulture);
- }
-
- var scaleMethod = "lanczos";
-
- return string.Format("-vf scale=\"{0}:{1}\"",
- widthScale,
- heightScale);
- }
-
- private string GetOutputFormat(string format)
- {
- if (string.Equals(format, "jpeg", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(format, "jpg", StringComparison.OrdinalIgnoreCase))
- {
- return "mjpeg";
- }
- return format;
- }
-
- private void ValidateInput(ImageEncodingOptions options)
- {
-
- }
-
- ///
- /// Determines whether the specified text has diacritics.
- ///
- /// The text.
- /// true if the specified text has diacritics; otherwise, false.
- private bool HasDiacritics(string text)
- {
- return !String.Equals(text, RemoveDiacritics(text), StringComparison.Ordinal);
- }
-
- ///
- /// Removes the diacritics.
- ///
- /// The text.
- /// System.String.
- private string RemoveDiacritics(string text)
- {
- return String.Concat(
- text.Normalize(NormalizationForm.FormD)
- .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) !=
- UnicodeCategory.NonSpacingMark)
- ).Normalize(NormalizationForm.FormC);
- }
- }
-}
diff --git a/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTask.cs b/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTask.cs
deleted file mode 100644
index 826525aef2..0000000000
--- a/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTask.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Entities;
-using System;
-using System.Collections.Generic;
-using System.Threading;
-
-namespace MediaBrowser.MediaEncoding.Encoder
-{
- public class InternalEncodingTask
- {
- public string Id { get; set; }
-
- public CancellationTokenSource CancellationTokenSource { get; set; }
-
- public double ProgressPercentage { get; set; }
-
- public EncodingOptions Request { get; set; }
-
- public VideoEncodingOptions VideoRequest
- {
- get { return Request as VideoEncodingOptions; }
- }
-
- public string MediaPath { get; set; }
- public List StreamFileNames { get; set; }
- public bool IsInputRemote { get; set; }
-
- public VideoType? InputVideoType { get; set; }
- public IsoType? IsoType { get; set; }
- public long? InputRunTimeTicks;
-
- public string AudioSync = "1";
- public string VideoSync = "vfr";
-
- public string InputAudioSync { get; set; }
- public string InputVideoSync { get; set; }
-
- public bool DeInterlace { get; set; }
-
- public bool ReadInputAtNativeFramerate { get; set; }
-
- public string InputFormat { get; set; }
-
- public string InputVideoCodec { get; set; }
-
- public string InputAudioCodec { get; set; }
-
- public string LiveTvStreamId { get; set; }
-
- public MediaStream AudioStream { get; set; }
- public MediaStream VideoStream { get; set; }
- public MediaStream SubtitleStream { get; set; }
- public bool HasMediaStreams { get; set; }
-
- public int SegmentLength = 10;
- public int HlsListSize;
-
- public string MimeType { get; set; }
- public string OrgPn { get; set; }
- public bool EnableMpegtsM2TsMode { get; set; }
-
- ///
- /// Gets or sets the user agent.
- ///
- /// The user agent.
- public string UserAgent { get; set; }
-
- public EncodingQuality QualitySetting { get; set; }
-
- public InternalEncodingTask()
- {
- Id = Guid.NewGuid().ToString("N");
- CancellationTokenSource = new CancellationTokenSource();
- StreamFileNames = new List();
- }
-
- public bool EnableDebugLogging { get; set; }
-
- internal void OnBegin()
- {
-
- }
-
- internal void OnCompleted()
- {
-
- }
-
- internal void OnError()
- {
-
- }
- }
-}
diff --git a/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTaskFactory.cs b/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTaskFactory.cs
deleted file mode 100644
index f52f072dff..0000000000
--- a/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTaskFactory.cs
+++ /dev/null
@@ -1,311 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dlna;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.LiveTv;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.MediaEncoding.Encoder
-{
- public class InternalEncodingTaskFactory
- {
- private readonly ILibraryManager _libraryManager;
- private readonly ILiveTvManager _liveTvManager;
- private readonly IItemRepository _itemRepo;
- private readonly IServerConfigurationManager _config;
-
- public InternalEncodingTaskFactory(ILibraryManager libraryManager, ILiveTvManager liveTvManager, IItemRepository itemRepo, IServerConfigurationManager config)
- {
- _libraryManager = libraryManager;
- _liveTvManager = liveTvManager;
- _itemRepo = itemRepo;
- _config = config;
- }
-
- public async Task Create(EncodingOptions request, CancellationToken cancellationToken)
- {
- ValidateInput(request);
-
- var state = new InternalEncodingTask
- {
- Request = request
- };
-
- var item = string.IsNullOrEmpty(request.MediaSourceId) ?
- _libraryManager.GetItemById(new Guid(request.ItemId)) :
- _libraryManager.GetItemById(new Guid(request.MediaSourceId));
-
- if (item is ILiveTvRecording)
- {
- var recording = await _liveTvManager.GetInternalRecording(request.ItemId, cancellationToken).ConfigureAwait(false);
-
- if (string.Equals(recording.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
- {
- state.InputVideoType = VideoType.VideoFile;
- }
-
- var path = recording.RecordingInfo.Path;
- var mediaUrl = recording.RecordingInfo.Url;
-
- if (string.IsNullOrWhiteSpace(path) && string.IsNullOrWhiteSpace(mediaUrl))
- {
- var streamInfo = await _liveTvManager.GetRecordingStream(request.ItemId, cancellationToken).ConfigureAwait(false);
-
- state.LiveTvStreamId = streamInfo.Id;
-
- path = streamInfo.Path;
- mediaUrl = streamInfo.Url;
- }
-
- if (!string.IsNullOrEmpty(path) && File.Exists(path))
- {
- state.MediaPath = path;
- state.IsInputRemote = false;
- }
- else if (!string.IsNullOrEmpty(mediaUrl))
- {
- state.MediaPath = mediaUrl;
- state.IsInputRemote = true;
- }
-
- state.InputRunTimeTicks = recording.RunTimeTicks;
- if (recording.RecordingInfo.Status == RecordingStatus.InProgress && !state.IsInputRemote)
- {
- await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
- }
-
- state.ReadInputAtNativeFramerate = recording.RecordingInfo.Status == RecordingStatus.InProgress;
- state.AudioSync = "1000";
- state.DeInterlace = true;
- state.InputVideoSync = "-1";
- state.InputAudioSync = "1";
- }
- else if (item is LiveTvChannel)
- {
- var channel = _liveTvManager.GetInternalChannel(request.ItemId);
-
- if (string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
- {
- state.InputVideoType = VideoType.VideoFile;
- }
-
- var streamInfo = await _liveTvManager.GetChannelStream(request.ItemId, cancellationToken).ConfigureAwait(false);
-
- state.LiveTvStreamId = streamInfo.Id;
-
- if (!string.IsNullOrEmpty(streamInfo.Path) && File.Exists(streamInfo.Path))
- {
- state.MediaPath = streamInfo.Path;
- state.IsInputRemote = false;
-
- await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
- }
- else if (!string.IsNullOrEmpty(streamInfo.Url))
- {
- state.MediaPath = streamInfo.Url;
- state.IsInputRemote = true;
- }
-
- state.ReadInputAtNativeFramerate = true;
- state.AudioSync = "1000";
- state.DeInterlace = true;
- state.InputVideoSync = "-1";
- state.InputAudioSync = "1";
- }
- else
- {
- state.MediaPath = item.Path;
- state.IsInputRemote = item.LocationType == LocationType.Remote;
-
- var video = item as Video;
-
- if (video != null)
- {
- state.InputVideoType = video.VideoType;
- state.IsoType = video.IsoType;
-
- state.StreamFileNames = video.PlayableStreamFileNames.ToList();
- }
-
- state.InputRunTimeTicks = item.RunTimeTicks;
- }
-
- var videoRequest = request as VideoEncodingOptions;
-
- var mediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery
- {
- ItemId = item.Id
-
- }).ToList();
-
- if (videoRequest != null)
- {
- state.VideoStream = GetMediaStream(mediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video);
- state.SubtitleStream = GetMediaStream(mediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false);
- state.AudioStream = GetMediaStream(mediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio);
-
- if (state.VideoStream != null && state.VideoStream.IsInterlaced)
- {
- state.DeInterlace = true;
- }
- }
- else
- {
- state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true);
- }
-
- state.HasMediaStreams = mediaStreams.Count > 0;
-
- state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10;
- state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;
-
- state.QualitySetting = GetQualitySetting();
-
- ApplyDeviceProfileSettings(state);
-
- return state;
- }
-
- private void ValidateInput(EncodingOptions request)
- {
- if (string.IsNullOrWhiteSpace(request.ItemId))
- {
- throw new ArgumentException("ItemId is required.");
- }
- if (string.IsNullOrWhiteSpace(request.OutputPath))
- {
- throw new ArgumentException("OutputPath is required.");
- }
- if (string.IsNullOrWhiteSpace(request.Container))
- {
- throw new ArgumentException("Container is required.");
- }
- if (string.IsNullOrWhiteSpace(request.AudioCodec))
- {
- throw new ArgumentException("AudioCodec is required.");
- }
-
- var videoRequest = request as VideoEncodingOptions;
-
- if (videoRequest == null)
- {
- return;
- }
- }
-
- ///
- /// Determines which stream will be used for playback
- ///
- /// All stream.
- /// Index of the desired.
- /// The type.
- /// if set to true [return first if no index].
- /// MediaStream.
- private MediaStream GetMediaStream(IEnumerable allStream, int? desiredIndex, MediaStreamType type, bool returnFirstIfNoIndex = true)
- {
- var streams = allStream.Where(s => s.Type == type).OrderBy(i => i.Index).ToList();
-
- if (desiredIndex.HasValue)
- {
- var stream = streams.FirstOrDefault(s => s.Index == desiredIndex.Value);
-
- if (stream != null)
- {
- return stream;
- }
- }
-
- if (returnFirstIfNoIndex && type == MediaStreamType.Audio)
- {
- return streams.FirstOrDefault(i => i.Channels.HasValue && i.Channels.Value > 0) ??
- streams.FirstOrDefault();
- }
-
- // Just return the first one
- return returnFirstIfNoIndex ? streams.FirstOrDefault() : null;
- }
-
- private void ApplyDeviceProfileSettings(InternalEncodingTask state)
- {
- var profile = state.Request.DeviceProfile;
-
- if (profile == null)
- {
- // Don't use settings from the default profile.
- // Only use a specific profile if it was requested.
- return;
- }
-
- var container = state.Request.Container;
-
- var audioCodec = state.Request.AudioCodec;
-
- if (string.Equals(audioCodec, "copy", StringComparison.OrdinalIgnoreCase) && state.AudioStream != null)
- {
- audioCodec = state.AudioStream.Codec;
- }
-
- var videoCodec = state.VideoRequest == null ? null : state.VideoRequest.VideoCodec;
-
- if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase) && state.VideoStream != null)
- {
- videoCodec = state.VideoStream.Codec;
- }
-
- //var mediaProfile = state.VideoRequest == null ?
- // profile.GetAudioMediaProfile(container, audioCodec) :
- // profile.GetVideoMediaProfile(container, audioCodec, videoCodec, state.AudioStream, state.VideoStream);
-
- //if (mediaProfile != null)
- //{
- // state.MimeType = mediaProfile.MimeType;
- // state.OrgPn = mediaProfile.OrgPn;
- //}
-
- //var transcodingProfile = state.VideoRequest == null ?
- // profile.GetAudioTranscodingProfile(container, audioCodec) :
- // profile.GetVideoTranscodingProfile(container, audioCodec, videoCodec);
-
- //if (transcodingProfile != null)
- //{
- // //state.EstimateContentLength = transcodingProfile.EstimateContentLength;
- // state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode;
- // //state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo;
-
- // if (state.VideoRequest != null && string.IsNullOrWhiteSpace(state.VideoRequest.VideoProfile))
- // {
- // state.VideoRequest.VideoProfile = transcodingProfile.VideoProfile;
- // }
- //}
- }
-
- private EncodingQuality GetQualitySetting()
- {
- var quality = _config.Configuration.MediaEncodingQuality;
-
- if (quality == EncodingQuality.Auto)
- {
- var cpuCount = Environment.ProcessorCount;
-
- if (cpuCount >= 4)
- {
- //return EncodingQuality.HighQuality;
- }
-
- return EncodingQuality.HighSpeed;
- }
-
- return quality;
- }
- }
-}
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 389046c9e2..9ff28dda21 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -853,7 +853,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
public Task EncodeImage(ImageEncodingOptions options, CancellationToken cancellationToken)
{
- return new ImageEncoder(FFMpegPath, _logger, _fileSystem, _appPaths).EncodeImage(options, cancellationToken);
+ throw new NotImplementedException();
}
///
diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
index 2343d97185..5abc509d0c 100644
--- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
+++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
@@ -53,12 +53,7 @@
-
-
-
-
-
diff --git a/MediaBrowser.Model/Session/SessionCapabilities.cs b/MediaBrowser.Model/Session/SessionCapabilities.cs
index 5eeede1261..767df8f1c1 100644
--- a/MediaBrowser.Model/Session/SessionCapabilities.cs
+++ b/MediaBrowser.Model/Session/SessionCapabilities.cs
@@ -10,6 +10,8 @@ namespace MediaBrowser.Model.Session
public bool SupportsMediaControl { get; set; }
+ public string MessageCallbackUrl { get; set; }
+
public SessionCapabilities()
{
PlayableMediaTypes = new List();
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index cfa642add2..538e6a0fdf 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -98,7 +98,7 @@ namespace MediaBrowser.Server.Implementations.Channels
{
all = all.Take(query.Limit.Value).ToList();
}
-
+
// Get everything
var fields = Enum.GetNames(typeof(ItemFields))
.Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
@@ -156,6 +156,23 @@ namespace MediaBrowser.Server.Implementations.Channels
progress.Report(100);
}
+ public Task> GetChannelItemMediaSources(string id, CancellationToken cancellationToken)
+ {
+ var item = (IChannelMediaItem)_libraryManager.GetItemById(id);
+
+ var channelGuid = new Guid(item.ChannelId);
+ var channel = _channelEntities.First(i => i.Id == channelGuid);
+
+ var requiresCallback = channel as IRequiresMediaInfoCallback;
+
+ if (requiresCallback != null)
+ {
+ return requiresCallback.GetChannelItemMediaInfo(item.ExternalId, cancellationToken);
+ }
+
+ return Task.FromResult>(item.ChannelMediaSources);
+ }
+
private async Task GetChannel(IChannel channelInfo, CancellationToken cancellationToken)
{
var path = Path.Combine(_config.ApplicationPaths.ItemsByNamePath, "channels", _fileSystem.GetValidFilename(channelInfo.Name));
@@ -303,10 +320,16 @@ namespace MediaBrowser.Server.Implementations.Channels
var query = new InternalChannelItemQuery
{
- User = user,
- CategoryId = categoryId
+ User = user
};
+ if (!string.IsNullOrWhiteSpace(categoryId))
+ {
+ var categoryItem = (IChannelItem)_libraryManager.GetItemById(new Guid(categoryId));
+
+ query.CategoryId = categoryItem.ExternalId;
+ }
+
var result = await channel.GetChannelItems(query, cancellationToken).ConfigureAwait(false);
CacheResponse(result, cachePath);
@@ -380,7 +403,7 @@ namespace MediaBrowser.Server.Implementations.Channels
private string GetIdToHash(string externalId)
{
// Increment this as needed to force new downloads
- return externalId + "4";
+ return externalId + "7";
}
private async Task GetChannelItemEntity(ChannelItemInfo info, string internalChannnelId, CancellationToken cancellationToken)
@@ -434,10 +457,6 @@ namespace MediaBrowser.Server.Implementations.Channels
item.Id = id;
item.RunTimeTicks = info.RunTimeTicks;
- var mediaSource = info.MediaSources.FirstOrDefault();
-
- item.Path = mediaSource == null ? null : mediaSource.Path;
-
if (isNew)
{
item.Name = info.Name;
@@ -464,12 +483,22 @@ namespace MediaBrowser.Server.Implementations.Channels
channelItem.ChannelId = internalChannnelId;
channelItem.ChannelItemType = info.Type;
+ if (isNew)
+ {
+ channelItem.Tags = info.Tags;
+ }
+
var channelMediaItem = item as IChannelMediaItem;
if (channelMediaItem != null)
{
channelMediaItem.IsInfiniteStream = info.IsInfiniteStream;
channelMediaItem.ContentType = info.ContentType;
+ channelMediaItem.ChannelMediaSources = info.MediaSources;
+
+ var mediaSource = info.MediaSources.FirstOrDefault();
+
+ item.Path = mediaSource == null ? null : mediaSource.Path;
}
if (isNew)
diff --git a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs
index 236963b9b8..0b0f21e2c9 100644
--- a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs
+++ b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs
@@ -1,5 +1,8 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Net;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Net;
@@ -16,23 +19,18 @@ namespace MediaBrowser.Server.Implementations.Session
{
private readonly IHttpClient _httpClient;
private readonly IJsonSerializer _json;
- private readonly IServerApplicationHost _appHost;
public SessionInfo Session { get; private set; }
- //var postUrl = string.Format("http://{0}/mediabrowser/message", session.RemoteEndPoint);
-
private readonly string _postUrl;
- public HttpSessionController(IHttpClient httpClient,
- IJsonSerializer json,
- IServerApplicationHost appHost,
- SessionInfo session,
+ public HttpSessionController(IHttpClient httpClient,
+ IJsonSerializer json,
+ SessionInfo session,
string postUrl)
{
_httpClient = httpClient;
_json = json;
- _appHost = appHost;
Session = session;
_postUrl = postUrl;
}
@@ -63,6 +61,21 @@ namespace MediaBrowser.Server.Implementations.Session
});
}
+ private Task SendMessage(string name, CancellationToken cancellationToken)
+ {
+ return SendMessage(name, new NameValueCollection(), cancellationToken);
+ }
+
+ private Task SendMessage(string name, NameValueCollection args, CancellationToken cancellationToken)
+ {
+ return SendMessage(new WebSocketMessage
+ {
+ MessageType = name,
+ Data = string.Empty
+
+ }, cancellationToken);
+ }
+
public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken)
{
return Task.FromResult(true);
@@ -80,22 +93,25 @@ namespace MediaBrowser.Server.Implementations.Session
public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken)
{
- return SendMessage(new WebSocketMessage
- {
- MessageType = "Play",
- Data = command
+ return Task.FromResult(true);
+ //return SendMessage(new WebSocketMessage
+ //{
+ // MessageType = "Play",
+ // Data = command
- }, cancellationToken);
+ //}, cancellationToken);
}
public Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken)
{
- return SendMessage(new WebSocketMessage
+ var args = new Dictionary();
+
+ if (command.Command == PlaystateCommand.Seek)
{
- MessageType = "Playstate",
- Data = command
- }, cancellationToken);
+ }
+
+ return SendMessage(command.Command.ToString(), cancellationToken);
}
public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken)
@@ -103,14 +119,9 @@ namespace MediaBrowser.Server.Implementations.Session
return Task.FromResult(true);
}
- public Task SendRestartRequiredNotification(CancellationToken cancellationToken)
+ public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken)
{
- return SendMessage(new WebSocketMessage
- {
- MessageType = "RestartRequired",
- Data = _appHost.GetSystemInfo()
-
- }, cancellationToken);
+ return SendMessage("RestartRequired", cancellationToken);
}
public Task SendUserDataChangeInfo(UserDataChangeInfo info, CancellationToken cancellationToken)
@@ -120,22 +131,12 @@ namespace MediaBrowser.Server.Implementations.Session
public Task SendServerShutdownNotification(CancellationToken cancellationToken)
{
- return SendMessage(new WebSocketMessage
- {
- MessageType = "ServerShuttingDown",
- Data = string.Empty
-
- }, cancellationToken);
+ return SendMessage("ServerShuttingDown", cancellationToken);
}
public Task SendServerRestartNotification(CancellationToken cancellationToken)
{
- return SendMessage(new WebSocketMessage
- {
- MessageType = "ServerRestarting",
- Data = string.Empty
-
- }, cancellationToken);
+ return SendMessage("ServerRestarting", cancellationToken);
}
public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken)
@@ -147,5 +148,13 @@ namespace MediaBrowser.Server.Implementations.Session
}, cancellationToken);
}
+
+ private string ToQueryString(Dictionary nvc)
+ {
+ var array = (from item in nvc
+ select string.Format("{0}={1}", WebUtility.UrlEncode(item.Key), WebUtility.UrlEncode(item.Value)))
+ .ToArray();
+ return "?" + string.Join("&", array);
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index cfa7cef671..d78fae87b2 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -1,6 +1,7 @@
-using System.Globalization;
-using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
@@ -14,10 +15,12 @@ using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -51,6 +54,10 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly IImageProcessor _imageProcessor;
private readonly IItemRepository _itemRepo;
+ private readonly IHttpClient _httpClient;
+ private readonly IJsonSerializer _jsonSerializer;
+ private readonly IServerApplicationHost _appHost;
+
///
/// Gets or sets the configuration manager.
///
@@ -93,7 +100,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// The logger.
/// The user repository.
/// The library manager.
- public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo)
+ public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient)
{
_userDataRepository = userDataRepository;
_configurationManager = configurationManager;
@@ -105,6 +112,9 @@ namespace MediaBrowser.Server.Implementations.Session
_dtoService = dtoService;
_imageProcessor = imageProcessor;
_itemRepo = itemRepo;
+ _jsonSerializer = jsonSerializer;
+ _appHost = appHost;
+ _httpClient = httpClient;
}
///
@@ -908,11 +918,13 @@ namespace MediaBrowser.Server.Implementations.Session
{
var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList();
+ var info = _appHost.GetSystemInfo();
+
var tasks = sessions.Select(session => Task.Run(async () =>
{
try
{
- await session.SessionController.SendRestartRequiredNotification(cancellationToken).ConfigureAwait(false);
+ await session.SessionController.SendRestartRequiredNotification(info, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -1135,6 +1147,18 @@ namespace MediaBrowser.Server.Implementations.Session
session.PlayableMediaTypes = capabilities.PlayableMediaTypes;
session.SupportedCommands = capabilities.SupportedCommands;
+ if (!string.IsNullOrWhiteSpace(capabilities.MessageCallbackUrl))
+ {
+ var postUrl = string.Format("http://{0}{1}", session.RemoteEndPoint, capabilities.MessageCallbackUrl);
+
+ var controller = session.SessionController as HttpSessionController;
+
+ if (controller == null)
+ {
+ session.SessionController = new HttpSessionController(_httpClient, _jsonSerializer, session, postUrl);
+ }
+ }
+
EventHelper.FireEventIfNotNull(CapabilitiesChanged, this, new SessionEventArgs
{
SessionInfo = session
diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
index 1a042ede69..365845f416 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
@@ -35,19 +35,17 @@ namespace MediaBrowser.Server.Implementations.Session
/// The _dto service
///
private readonly IJsonSerializer _json;
- private readonly IServerApplicationHost _appHost;
///
/// Initializes a new instance of the class.
///
/// The session manager.
/// The log manager.
- /// The application host.
- public SessionWebSocketListener(ISessionManager sessionManager, ILogManager logManager, IServerApplicationHost appHost, IJsonSerializer json)
+ /// The json.
+ public SessionWebSocketListener(ISessionManager sessionManager, ILogManager logManager, IJsonSerializer json)
{
_sessionManager = sessionManager;
_logger = logManager.GetLogger(GetType().Name);
- _appHost = appHost;
_json = json;
}
@@ -138,7 +136,7 @@ namespace MediaBrowser.Server.Implementations.Session
if (controller == null)
{
- controller = new WebSocketController(session, _appHost, _logger, _sessionManager);
+ controller = new WebSocketController(session, _logger, _sessionManager);
}
controller.AddWebSocket(message.Connection);
diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
index 05eef611f5..5fc28e81b0 100644
--- a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
+++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Common.Net;
-using MediaBrowser.Controller;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -19,15 +18,13 @@ namespace MediaBrowser.Server.Implementations.Session
public SessionInfo Session { get; private set; }
public IReadOnlyList Sockets { get; private set; }
- private readonly IServerApplicationHost _appHost;
private readonly ILogger _logger;
private readonly ISessionManager _sessionManager;
- public WebSocketController(SessionInfo session, IServerApplicationHost appHost, ILogger logger, ISessionManager sessionManager)
+ public WebSocketController(SessionInfo session, ILogger logger, ISessionManager sessionManager)
{
Session = session;
- _appHost = appHost;
_logger = logger;
_sessionManager = sessionManager;
Sockets = new List();
@@ -121,14 +118,15 @@ namespace MediaBrowser.Server.Implementations.Session
///
/// Sends the restart required message.
///
+ /// The information.
/// The cancellation token.
/// Task.
- public Task SendRestartRequiredNotification(CancellationToken cancellationToken)
+ public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken)
{
return SendMessages(new WebSocketMessage
{
MessageType = "RestartRequired",
- Data = _appHost.GetSystemInfo()
+ Data = info
}, cancellationToken);
}
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index 831067a9ef..1cfc80f1c5 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -496,7 +496,7 @@ namespace MediaBrowser.ServerApplication
DtoService = new DtoService(Logger, LibraryManager, UserManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager);
RegisterSingleInstance(DtoService);
- SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository);
+ SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient);
RegisterSingleInstance(SessionManager);
var newsService = new Server.Implementations.News.NewsService(ApplicationPaths, JsonSerializer);
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index 6dd8fb458c..798d7169de 100644
--- a/Nuget/MediaBrowser.Common.Internal.nuspec
+++ b/Nuget/MediaBrowser.Common.Internal.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common.Internal
- 3.0.367
+ 3.0.369
MediaBrowser.Common.Internal
Luke
ebr,Luke,scottisafool
@@ -12,7 +12,7 @@
Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.
Copyright © Media Browser 2013
-
+
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index 2a98209256..bc1fb3896f 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common
- 3.0.367
+ 3.0.369
MediaBrowser.Common
Media Browser Team
ebr,Luke,scottisafool
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index 7df46236c2..ba28896035 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Server.Core
- 3.0.367
+ 3.0.369
Media Browser.Server.Core
Media Browser Team
ebr,Luke,scottisafool
@@ -12,7 +12,7 @@
Contains core components required to build plugins for Media Browser Server.
Copyright © Media Browser 2013
-
+