diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index b5bef1ce9..0e91c0b9e 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -819,10 +819,10 @@ namespace MediaBrowser.Api.Playback
{
if (state.PlayableStreamFileNames.Count > 0)
{
- return MediaEncoder.GetProbeSizeArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol);
+ return MediaEncoder.GetProbeSizeAndAnalyzeDurationArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol);
}
- return MediaEncoder.GetProbeSizeArgument(new[] { state.MediaPath }, state.InputProtocol);
+ return MediaEncoder.GetProbeSizeAndAnalyzeDurationArgument(new[] { state.MediaPath }, state.InputProtocol);
}
///
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs
index 9709813dc..7b769deb3 100644
--- a/MediaBrowser.Controller/Entities/AggregateFolder.cs
+++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs
@@ -45,6 +45,15 @@ namespace MediaBrowser.Controller.Entities
return false;
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return false;
+ }
+ }
+
///
/// The _virtual children
///
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index 1f3b0c92a..3f457d89a 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -17,6 +17,9 @@ namespace MediaBrowser.Controller.Entities.Audio
///
public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo, IMetadataContainer
{
+ public List AlbumArtists { get; set; }
+ public List Artists { get; set; }
+
public MusicAlbum()
{
Artists = new List();
@@ -48,6 +51,15 @@ namespace MediaBrowser.Controller.Entities.Audio
}
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return false;
+ }
+ }
+
[IgnoreDataMember]
public override bool SupportsCumulativeRunTimeTicks
{
@@ -83,8 +95,6 @@ namespace MediaBrowser.Controller.Entities.Audio
get { return false; }
}
- public List AlbumArtists { get; set; }
-
///
/// Gets the tracks.
///
@@ -103,8 +113,6 @@ namespace MediaBrowser.Controller.Entities.Audio
return Tracks;
}
- public List Artists { get; set; }
-
public override List GetUserDataKeys()
{
var list = base.GetUserDataKeys();
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index 076a7031a..a31f04fc4 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -48,6 +48,15 @@ namespace MediaBrowser.Controller.Entities.Audio
get { return true; }
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return false;
+ }
+ }
+
public override bool CanDelete()
{
return !IsAccessedByName;
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index cc4a8fdb9..7eb84fc80 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -129,6 +129,15 @@ namespace MediaBrowser.Controller.Entities
get { return false; }
}
+ [IgnoreDataMember]
+ public virtual bool SupportsPlayedStatus
+ {
+ get
+ {
+ return false;
+ }
+ }
+
public bool DetectIsInMixedFolder()
{
if (SupportsIsInMixedFolderDetection)
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index 04ba53263..41e277b7c 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -38,6 +38,15 @@ namespace MediaBrowser.Controller.Entities
}
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return false;
+ }
+ }
+
public override bool CanDelete()
{
return false;
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index e5994fde5..993e36fd8 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -61,6 +61,15 @@ namespace MediaBrowser.Controller.Entities
get { return false; }
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return true;
+ }
+ }
+
///
/// Gets a value indicating whether this instance is folder.
///
diff --git a/MediaBrowser.Controller/Entities/GameSystem.cs b/MediaBrowser.Controller/Entities/GameSystem.cs
index 1c09ee507..9e00ab260 100644
--- a/MediaBrowser.Controller/Entities/GameSystem.cs
+++ b/MediaBrowser.Controller/Entities/GameSystem.cs
@@ -26,6 +26,15 @@ namespace MediaBrowser.Controller.Entities
}
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return false;
+ }
+ }
+
///
/// Gets or sets the game system.
///
diff --git a/MediaBrowser.Controller/Entities/IHasUserData.cs b/MediaBrowser.Controller/Entities/IHasUserData.cs
index 2495b0ccd..c21e170ae 100644
--- a/MediaBrowser.Controller/Entities/IHasUserData.cs
+++ b/MediaBrowser.Controller/Entities/IHasUserData.cs
@@ -20,5 +20,7 @@ namespace MediaBrowser.Controller.Entities
Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user);
bool EnableRememberingTrackSelections { get; }
+
+ bool SupportsPlayedStatus { get; }
}
}
diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs
index 41e25e406..a42fce8bb 100644
--- a/MediaBrowser.Controller/Entities/Photo.cs
+++ b/MediaBrowser.Controller/Entities/Photo.cs
@@ -29,13 +29,13 @@ namespace MediaBrowser.Controller.Entities
{
get
{
- return Album;
+ return AlbumEntity;
}
}
[IgnoreDataMember]
- public PhotoAlbum Album
+ public PhotoAlbum AlbumEntity
{
get
{
diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
index b0ddcfb8c..cb5c5c453 100644
--- a/MediaBrowser.Controller/Entities/PhotoAlbum.cs
+++ b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
@@ -16,6 +16,15 @@ namespace MediaBrowser.Controller.Entities
}
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return false;
+ }
+ }
+
protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Other);
diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs
index aff1f5e28..b67817846 100644
--- a/MediaBrowser.Controller/Entities/UserRootFolder.cs
+++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs
@@ -33,6 +33,15 @@ namespace MediaBrowser.Controller.Entities
}
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return false;
+ }
+ }
+
private void ClearCache()
{
lock (_childIdsLock)
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index 92f8e8a9d..a689e0d09 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -44,6 +44,15 @@ namespace MediaBrowser.Controller.Entities
return list;
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return false;
+ }
+ }
+
public override int GetChildCount(User user)
{
return GetChildren(user, true).Count();
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index baf9293bf..e83d1298e 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -44,6 +44,15 @@ namespace MediaBrowser.Controller.Entities
}
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return true;
+ }
+ }
+
public override string CreatePresentationUniqueKey()
{
if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
index e26dd6a77..635df5dc7 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
@@ -54,6 +54,15 @@ namespace MediaBrowser.Controller.LiveTv
}
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return Status == RecordingStatus.Completed && base.SupportsPlayedStatus;
+ }
+ }
+
[IgnoreDataMember]
public override LocationType LocationType
{
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index f97fe9560..866a08aa1 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -84,7 +84,7 @@ namespace MediaBrowser.Controller.MediaEncoding
/// The input files.
/// The protocol.
/// System.String.
- string GetProbeSizeArgument(string[] inputFiles, MediaProtocol protocol);
+ string GetProbeSizeAndAnalyzeDurationArgument(string[] inputFiles, MediaProtocol protocol);
///
/// Gets the input argument.
diff --git a/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs
index ca0c2fdbb..9ff7567d4 100644
--- a/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs
+++ b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs
@@ -15,6 +15,7 @@ namespace MediaBrowser.Controller.MediaEncoding
public IIsoMount MountedIso { get; set; }
public VideoType VideoType { get; set; }
public List PlayableStreamFileNames { get; set; }
+ public int AnalyzeDurationSections { get; set; }
public MediaInfoRequest()
{
diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs
index 654b97d7d..8e0ac7ea8 100644
--- a/MediaBrowser.Controller/Playlists/Playlist.cs
+++ b/MediaBrowser.Controller/Playlists/Playlist.cs
@@ -31,6 +31,15 @@ namespace MediaBrowser.Controller.Playlists
}
}
+ [IgnoreDataMember]
+ public override bool SupportsPlayedStatus
+ {
+ get
+ {
+ return string.Equals(MediaType, "Video", StringComparison.OrdinalIgnoreCase);
+ }
+ }
+
[IgnoreDataMember]
public override bool AlwaysScanInternalMetadataPath
{
diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
index f1e2f7241..c7b78aae3 100644
--- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
@@ -431,10 +431,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
if (state.PlayableStreamFileNames.Count > 0)
{
- return MediaEncoder.GetProbeSizeArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol);
+ return MediaEncoder.GetProbeSizeAndAnalyzeDurationArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol);
}
- return MediaEncoder.GetProbeSizeArgument(new[] { state.MediaPath }, state.InputProtocol);
+ return MediaEncoder.GetProbeSizeAndAnalyzeDurationArgument(new[] { state.MediaPath }, state.InputProtocol);
}
///
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
index 5d0f1f075..cec272b39 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
@@ -26,6 +26,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
return string.Format("\"{0}\"", url);
}
+ if (protocol == MediaProtocol.Udp)
+ {
+ var url = inputFiles.First();
+
+ return string.Format("\"{0}\"", url);
+ }
return GetConcatInputArgument(inputFiles);
}
@@ -74,9 +80,14 @@ namespace MediaBrowser.MediaEncoding.Encoder
return path.Replace("\"", "\\\"");
}
- public static string GetProbeSizeArgument(bool isDvd)
+ public static string GetProbeSizeArgument(int numInputFiles)
{
- return isDvd ? "-probesize 1G -analyzeduration 200M" : "";
+ return numInputFiles > 1 ? "-probesize 1G" : "";
+ }
+
+ public static string GetAnalyzeDurationArgument(int numInputFiles)
+ {
+ return numInputFiles > 1 ? "-analyzeduration 200M" : "";
}
}
}
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 5c3345008..fc1444e1b 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -426,10 +426,24 @@ namespace MediaBrowser.MediaEncoding.Encoder
var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.InputPath, request.Protocol, request.MountedIso, request.PlayableStreamFileNames);
- var probeSizeArgument = GetProbeSizeArgument(inputFiles, request.Protocol);
+ var probeSize = EncodingUtils.GetProbeSizeArgument(inputFiles.Length);
+ string analyzeDuration;
+
+ if (request.AnalyzeDurationSections > 0)
+ {
+ analyzeDuration = "-analyzeduration " +
+ (request.AnalyzeDurationSections*1000000).ToString(CultureInfo.InvariantCulture);
+ }
+ else
+ {
+ analyzeDuration = EncodingUtils.GetAnalyzeDurationArgument(inputFiles.Length);
+ }
+
+ probeSize = probeSize + " " + analyzeDuration;
+ probeSize = probeSize.Trim();
return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters,
- probeSizeArgument, request.MediaType == DlnaProfileType.Audio, request.VideoType, cancellationToken);
+ probeSize, request.MediaType == DlnaProfileType.Audio, request.VideoType, cancellationToken);
}
///
@@ -450,9 +464,23 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// The input files.
/// The protocol.
/// System.String.
- public string GetProbeSizeArgument(string[] inputFiles, MediaProtocol protocol)
+ public string GetProbeSizeAndAnalyzeDurationArgument(string[] inputFiles, MediaProtocol protocol)
{
- return EncodingUtils.GetProbeSizeArgument(inputFiles.Length > 1);
+ var results = new List();
+
+ var probeSize = EncodingUtils.GetProbeSizeArgument(inputFiles.Length);
+ var analyzeDuration = EncodingUtils.GetAnalyzeDurationArgument(inputFiles.Length);
+
+ if (!string.IsNullOrWhiteSpace(probeSize))
+ {
+ results.Add(probeSize);
+ }
+
+ if (!string.IsNullOrWhiteSpace(analyzeDuration))
+ {
+ results.Add(analyzeDuration);
+ }
+ return string.Join(" ", results.ToArray());
}
///
@@ -871,7 +899,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
var args = useIFrame ? string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail) :
string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg);
- var probeSize = GetProbeSizeArgument(new[] { inputPath }, protocol);
+ var probeSize = GetProbeSizeAndAnalyzeDurationArgument(new[] { inputPath }, protocol);
if (!string.IsNullOrEmpty(probeSize))
{
@@ -982,7 +1010,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
var args = string.Format("-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf);
- var probeSize = GetProbeSizeArgument(new[] { inputArgument }, protocol);
+ var probeSize = GetProbeSizeAndAnalyzeDurationArgument(new[] { inputArgument }, protocol);
if (!string.IsNullOrEmpty(probeSize))
{
diff --git a/MediaBrowser.Model/MediaInfo/MediaProtocol.cs b/MediaBrowser.Model/MediaInfo/MediaProtocol.cs
index 880310814..1474e6d96 100644
--- a/MediaBrowser.Model/MediaInfo/MediaProtocol.cs
+++ b/MediaBrowser.Model/MediaInfo/MediaProtocol.cs
@@ -5,6 +5,7 @@ namespace MediaBrowser.Model.MediaInfo
File = 0,
Http = 1,
Rtmp = 2,
- Rtsp = 3
+ Rtsp = 3,
+ Udp = 4
}
}
\ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index b878226de..a0f7aa999 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -598,7 +598,7 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.Altitude = item.Altitude;
dto.IsoSpeedRating = item.IsoSpeedRating;
- var album = item.Album;
+ var album = item.AlbumEntity;
if (album != null)
{
diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
index ec8ac1a42..139ea0ab6 100644
--- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
@@ -269,9 +269,10 @@ namespace MediaBrowser.Server.Implementations.Library
positionTicks = 0;
}
- if (item is Audio)
+ if (!item.SupportsPlayedStatus)
{
positionTicks = 0;
+ data.Played = false;
}
data.PlaybackPositionTicks = positionTicks;
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 9781775d5..136a9e195 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -27,6 +27,7 @@ using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using CommonIO;
+using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
@@ -59,8 +60,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public static EmbyTV Current;
- public event EventHandler DataSourceChanged { add { } remove { } }
- public event EventHandler RecordingStatusChanged { add { } remove { } }
+ public event EventHandler DataSourceChanged;
+ public event EventHandler RecordingStatusChanged;
private readonly ConcurrentDictionary _activeRecordings =
new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase);
@@ -1009,7 +1010,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
throw new NotImplementedException();
}
- public Task> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken)
+ public async Task> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken)
{
ActiveRecordingInfo info;
@@ -1017,22 +1018,27 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
if (_activeRecordings.TryGetValue(recordingId, out info))
{
- return Task.FromResult(new List
+ var stream = new MediaSourceInfo
{
- new MediaSourceInfo
- {
- Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveRecordings/" + recordingId + "/stream",
- Id = recordingId,
- SupportsDirectPlay = false,
- SupportsDirectStream = true,
- SupportsTranscoding = true,
- IsInfiniteStream = true,
- RequiresOpening = false,
- RequiresClosing = false,
- Protocol = Model.MediaInfo.MediaProtocol.Http,
- BufferMs = 0
- }
- });
+ Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveRecordings/" + recordingId + "/stream",
+ Id = recordingId,
+ SupportsDirectPlay = false,
+ SupportsDirectStream = true,
+ SupportsTranscoding = true,
+ IsInfiniteStream = true,
+ RequiresOpening = false,
+ RequiresClosing = false,
+ Protocol = Model.MediaInfo.MediaProtocol.Http,
+ BufferMs = 0
+ };
+
+ var isAudio = false;
+ await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false);
+
+ return new List
+ {
+ stream
+ };
}
throw new FileNotFoundException();
@@ -1258,6 +1264,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
string liveStreamId = null;
+ OnRecordingStatusChanged();
+
try
{
var allMediaSources = await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false);
@@ -1353,6 +1361,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
_timerProvider.Delete(timer);
}
+
+ OnRecordingStatusChanged();
+ }
+
+ private void OnRecordingStatusChanged()
+ {
+ EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs
+ {
+
+ }, _logger);
}
private async void EnforceKeepUpTo(TimerInfo timer)
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveStreamHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveStreamHelper.cs
new file mode 100644
index 000000000..336c32bae
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveStreamHelper.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.MediaEncoding;
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Logging;
+
+namespace MediaBrowser.Server.Implementations.LiveTv
+{
+ public class LiveStreamHelper
+ {
+ private readonly IMediaEncoder _mediaEncoder;
+ private readonly ILogger _logger;
+
+ public LiveStreamHelper(IMediaEncoder mediaEncoder, ILogger logger)
+ {
+ _mediaEncoder = mediaEncoder;
+ _logger = logger;
+ }
+
+ public async Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
+ {
+ var originalRuntime = mediaSource.RunTimeTicks;
+
+ var now = DateTime.UtcNow;
+
+ var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
+ {
+ InputPath = mediaSource.Path,
+ Protocol = mediaSource.Protocol,
+ MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
+ ExtractChapters = false,
+ AnalyzeDurationSections = 2
+
+ }, cancellationToken).ConfigureAwait(false);
+
+ _logger.Info("Live tv media info probe took {0} seconds", (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture));
+
+ mediaSource.Bitrate = info.Bitrate;
+ mediaSource.Container = info.Container;
+ mediaSource.Formats = info.Formats;
+ mediaSource.MediaStreams = info.MediaStreams;
+ mediaSource.RunTimeTicks = info.RunTimeTicks;
+ mediaSource.Size = info.Size;
+ mediaSource.Timestamp = info.Timestamp;
+ mediaSource.Video3DFormat = info.Video3DFormat;
+ mediaSource.VideoType = info.VideoType;
+
+ mediaSource.DefaultSubtitleStreamIndex = null;
+
+ // Null this out so that it will be treated like a live stream
+ if (!originalRuntime.HasValue)
+ {
+ mediaSource.RunTimeTicks = null;
+ }
+
+ var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio);
+
+ if (audioStream == null || audioStream.Index == -1)
+ {
+ mediaSource.DefaultAudioStreamIndex = null;
+ }
+ else
+ {
+ mediaSource.DefaultAudioStreamIndex = audioStream.Index;
+ }
+
+ var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video);
+ if (videoStream != null)
+ {
+ if (!videoStream.BitRate.HasValue)
+ {
+ var width = videoStream.Width ?? 1920;
+
+ if (width >= 1900)
+ {
+ videoStream.BitRate = 8000000;
+ }
+
+ else if (width >= 1260)
+ {
+ videoStream.BitRate = 3000000;
+ }
+
+ else if (width >= 700)
+ {
+ videoStream.BitRate = 1000000;
+ }
+ }
+
+ // This is coming up false and preventing stream copy
+ videoStream.IsAVC = null;
+ }
+
+ // Try to estimate this
+ if (!mediaSource.Bitrate.HasValue)
+ {
+ var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
+
+ if (total > 0)
+ {
+ mediaSource.Bitrate = total;
+ }
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index a295320ec..bac9789b5 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -121,9 +121,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv
foreach (var service in _services)
{
service.DataSourceChanged += service_DataSourceChanged;
+ service.RecordingStatusChanged += Service_RecordingStatusChanged;
}
}
+ private void Service_RecordingStatusChanged(object sender, RecordingStatusChangedEventArgs e)
+ {
+ _lastRecordingRefreshTime = DateTime.MinValue;
+ }
+
public List TunerHosts
{
get { return _tunerHosts; }
@@ -2299,6 +2305,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false);
+ info.RecordAnyChannel = true;
+ info.RecordAnyTime = true;
+ info.Days = new List
+ {
+ DayOfWeek.Sunday,
+ DayOfWeek.Monday,
+ DayOfWeek.Tuesday,
+ DayOfWeek.Wednesday,
+ DayOfWeek.Thursday,
+ DayOfWeek.Friday,
+ DayOfWeek.Saturday
+ };
+
info.Id = null;
return new Tuple(info, service);
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
index 521f33e1c..a62796036 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
@@ -146,7 +146,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
else
{
- await AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false);
+ await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false);
}
}
catch (Exception ex)
@@ -216,92 +216,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
}
- private async Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
- {
- var originalRuntime = mediaSource.RunTimeTicks;
-
- var now = DateTime.UtcNow;
-
- var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
- {
- InputPath = mediaSource.Path,
- Protocol = mediaSource.Protocol,
- MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
- ExtractChapters = false
-
- }, cancellationToken).ConfigureAwait(false);
-
- _logger.Info("Live tv media info probe took {0} seconds", (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture));
-
- mediaSource.Bitrate = info.Bitrate;
- mediaSource.Container = info.Container;
- mediaSource.Formats = info.Formats;
- mediaSource.MediaStreams = info.MediaStreams;
- mediaSource.RunTimeTicks = info.RunTimeTicks;
- mediaSource.Size = info.Size;
- mediaSource.Timestamp = info.Timestamp;
- mediaSource.Video3DFormat = info.Video3DFormat;
- mediaSource.VideoType = info.VideoType;
-
- mediaSource.DefaultSubtitleStreamIndex = null;
-
- // Null this out so that it will be treated like a live stream
- if (!originalRuntime.HasValue)
- {
- mediaSource.RunTimeTicks = null;
- }
-
- var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio);
-
- if (audioStream == null || audioStream.Index == -1)
- {
- mediaSource.DefaultAudioStreamIndex = null;
- }
- else
- {
- mediaSource.DefaultAudioStreamIndex = audioStream.Index;
- }
-
- var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video);
- if (videoStream != null)
- {
- if (!videoStream.BitRate.HasValue)
- {
- var width = videoStream.Width ?? 1920;
-
- if (width >= 1900)
- {
- videoStream.BitRate = 8000000;
- }
-
- else if (width >= 1260)
- {
- videoStream.BitRate = 3000000;
- }
-
- else if (width >= 700)
- {
- videoStream.BitRate = 1000000;
- }
- }
-
- // This is coming up false and preventing stream copy
- videoStream.IsAVC = null;
- }
-
- // Try to estimate this
- if (!mediaSource.Bitrate.HasValue)
- {
- var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
-
- if (total > 0)
- {
- mediaSource.Bitrate = total;
- }
- }
- }
-
-
public Task CloseMediaSource(string liveStreamId)
{
return _liveTvManager.CloseLiveStream(liveStreamId);
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 73e6ce1a5..f01a107df 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -234,6 +234,7 @@
+
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index 2fcc76588..e898a6abd 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -633,10 +633,14 @@ namespace MediaBrowser.Server.Implementations.Session
data.PlayCount++;
data.LastPlayedDate = DateTime.UtcNow;
- if (!(item is Video))
+ if (!(item is Video) && item.SupportsPlayedStatus)
{
data.Played = true;
}
+ else
+ {
+ data.Played = false;
+ }
await _userDataManager.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None).ConfigureAwait(false);
}
@@ -847,11 +851,11 @@ namespace MediaBrowser.Server.Implementations.Session
{
playedToCompletion = _userDataManager.UpdatePlayState(item, data, positionTicks.Value);
}
- else
+ else
{
// If the client isn't able to report this, then we'll just have to make an assumption
data.PlayCount++;
- data.Played = true;
+ data.Played = item.SupportsPlayedStatus;
data.PlaybackPositionTicks = 0;
playedToCompletion = true;
}
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index 2e4584fd4..1259a759b 100644
--- a/Nuget/MediaBrowser.Common.Internal.nuspec
+++ b/Nuget/MediaBrowser.Common.Internal.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common.Internal
- 3.0.661
+ 3.0.662
MediaBrowser.Common.Internal
Luke
ebr,Luke,scottisafool
@@ -12,7 +12,7 @@
Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.
Copyright © Emby 2013
-
+
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index 56c616bd1..931db69fa 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common
- 3.0.661
+ 3.0.662
MediaBrowser.Common
Emby Team
ebr,Luke,scottisafool
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index 98a070c78..b3d929f59 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Server.Core
- 3.0.661
+ 3.0.662
Media Browser.Server.Core
Emby Team
ebr,Luke,scottisafool
@@ -12,7 +12,7 @@
Contains core components required to build plugins for Emby Server.
Copyright © Emby 2013
-
+