aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Dlna/PlayTo/Device.cs18
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlayToController.cs233
2 files changed, 187 insertions, 64 deletions
diff --git a/MediaBrowser.Dlna/PlayTo/Device.cs b/MediaBrowser.Dlna/PlayTo/Device.cs
index 3e5e877cd..fae0742bc 100644
--- a/MediaBrowser.Dlna/PlayTo/Device.cs
+++ b/MediaBrowser.Dlna/PlayTo/Device.cs
@@ -30,7 +30,7 @@ namespace MediaBrowser.Dlna.PlayTo
public int Volume { get; set; }
- public TimeSpan Duration { get; set; }
+ public TimeSpan? Duration { get; set; }
private TimeSpan _position = TimeSpan.FromSeconds(0);
public TimeSpan Position
@@ -270,8 +270,6 @@ namespace MediaBrowser.Dlna.PlayTo
public async Task SetAvTransport(string url, string header, string metaData)
{
- //await SetStop().ConfigureAwait(false);
-
var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetAVTransportURI");
if (command == null)
return;
@@ -598,10 +596,15 @@ namespace MediaBrowser.Dlna.PlayTo
var durationElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackDuration")).FirstOrDefault(i => i != null);
var duration = durationElem == null ? null : durationElem.Value;
- if (!string.IsNullOrWhiteSpace(duration) && !string.Equals(duration, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase))
+ if (!string.IsNullOrWhiteSpace(duration) &&
+ !string.Equals(duration, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase))
{
Duration = TimeSpan.Parse(duration, UsCulture);
}
+ else
+ {
+ Duration = null;
+ }
var positionElem = result.Document.Descendants(uPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("RelTime")).FirstOrDefault(i => i != null);
var position = positionElem == null ? null : positionElem.Value;
@@ -891,13 +894,14 @@ namespace MediaBrowser.Dlna.PlayTo
public event EventHandler<PlaybackProgressEventArgs> PlaybackProgress;
public event EventHandler<PlaybackStoppedEventArgs> PlaybackStopped;
- private uBaseObject _lastMediaInfo;
+ public uBaseObject CurrentMediaInfo { get; private set; }
+
private void UpdateMediaInfo(uBaseObject mediaInfo, TRANSPORTSTATE state)
{
TransportState = state;
- var previousMediaInfo = _lastMediaInfo;
- _lastMediaInfo = mediaInfo;
+ var previousMediaInfo = CurrentMediaInfo;
+ CurrentMediaInfo = mediaInfo;
if (previousMediaInfo == null && mediaInfo != null)
{
diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
index f9f90034c..54045a3d5 100644
--- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
@@ -106,13 +106,13 @@ namespace MediaBrowser.Dlna.PlayTo
e.Headers.TryGetValue("NTS", out nts);
string usn;
- if (!e.Headers.TryGetValue("USN", out usn)) usn = string.Empty;
+ if (!e.Headers.TryGetValue("USN", out usn)) usn = String.Empty;
string nt;
- if (!e.Headers.TryGetValue("NT", out nt)) nt = string.Empty;
+ if (!e.Headers.TryGetValue("NT", out nt)) nt = String.Empty;
- if (string.Equals(e.Method, "NOTIFY", StringComparison.OrdinalIgnoreCase) &&
- string.Equals(nts, "ssdp:byebye", StringComparison.OrdinalIgnoreCase) &&
+ if (String.Equals(e.Method, "NOTIFY", StringComparison.OrdinalIgnoreCase) &&
+ String.Equals(nts, "ssdp:byebye", StringComparison.OrdinalIgnoreCase) &&
usn.IndexOf(_device.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1 &&
!_disposed)
{
@@ -153,53 +153,41 @@ namespace MediaBrowser.Dlna.PlayTo
async void _device_PlaybackStart(object sender, PlaybackStartEventArgs e)
{
- var playlistItem = Playlist.FirstOrDefault(p => p.PlayState == 1);
+ var info = GetProgressInfo(e.MediaInfo);
- if (playlistItem != null)
+ try
{
- var streamInfo = playlistItem.StreamInfo;
-
- var info = GetProgressInfo(streamInfo, e.MediaInfo);
-
- try
- {
- await _sessionManager.OnPlaybackStart(info).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error reporting progress", ex);
- }
+ await _sessionManager.OnPlaybackStart(info).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error reporting progress", ex);
}
}
async void _device_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
{
- var playlistItem = Playlist.FirstOrDefault(p => p.PlayState == 1);
+ var info = GetProgressInfo(e.MediaInfo);
- if (playlistItem != null)
+ try
{
- var streamInfo = playlistItem.StreamInfo;
-
- var info = GetProgressInfo(streamInfo, e.MediaInfo);
-
- try
- {
- await _sessionManager.OnPlaybackProgress(info).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error reporting progress", ex);
- }
+ await _sessionManager.OnPlaybackProgress(info).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error reporting progress", ex);
}
}
- private PlaybackStartInfo GetProgressInfo(StreamInfo streamInfo, uBaseObject mediaInfo)
+ private PlaybackStartInfo GetProgressInfo(uBaseObject mediaInfo)
{
var ticks = _device.Position.Ticks;
- if (!streamInfo.IsDirectStream)
+ var info = StreamParams.ParseFromUrl(mediaInfo.Url, _libraryManager);
+
+ if (!info.IsDirectStream)
{
- ticks += streamInfo.StartPositionTicks;
+ ticks += info.StartPositionTicks;
}
return new PlaybackStartInfo
@@ -209,12 +197,14 @@ namespace MediaBrowser.Dlna.PlayTo
PositionTicks = ticks,
IsMuted = _device.IsMuted,
IsPaused = _device.IsPaused,
- MediaSourceId = streamInfo.MediaSourceId,
- AudioStreamIndex = streamInfo.AudioStreamIndex,
- SubtitleStreamIndex = streamInfo.SubtitleStreamIndex,
+ MediaSourceId = info.MediaSourceId,
+ AudioStreamIndex = info.AudioStreamIndex,
+ SubtitleStreamIndex = info.SubtitleStreamIndex,
VolumeLevel = _device.Volume,
- CanSeek = streamInfo.RunTimeTicks.HasValue,
- PlayMethod = streamInfo.IsDirectStream ? PlayMethod.DirectStream : PlayMethod.Transcode,
+
+ CanSeek = info.MediaSource == null ? _device.Duration.HasValue : info.MediaSource.RunTimeTicks.HasValue,
+
+ PlayMethod = info.IsDirectStream ? PlayMethod.DirectStream : PlayMethod.Transcode,
QueueableMediaTypes = new List<string> { mediaInfo.MediaType }
};
}
@@ -225,7 +215,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
_logger.Debug("{0} - Received PlayRequest: {1}", this._session.DeviceName, command.PlayCommand);
- var user = string.IsNullOrEmpty(command.ControllingUserId) ? null : _userManager.GetUserById(new Guid(command.ControllingUserId));
+ var user = String.IsNullOrEmpty(command.ControllingUserId) ? null : _userManager.GetUserById(new Guid(command.ControllingUserId));
var items = new List<BaseItem>();
foreach (string id in command.ItemIds)
@@ -264,7 +254,7 @@ namespace MediaBrowser.Dlna.PlayTo
_logger.Debug("{0} - Playing {1} items", _session.DeviceName, playlist.Count);
- if (!string.IsNullOrWhiteSpace(command.ControllingUserId))
+ if (!String.IsNullOrWhiteSpace(command.ControllingUserId))
{
await _sessionManager.LogSessionActivity(_session.Client, _session.ApplicationVersion, _session.DeviceId,
_session.DeviceName, _session.RemoteEndPoint, user).ConfigureAwait(false);
@@ -288,18 +278,23 @@ namespace MediaBrowser.Dlna.PlayTo
return _device.SetPlay();
case PlaystateCommand.Seek:
- //var playlistItem = Playlist.FirstOrDefault(p => p.PlayState == 1);
- //if (playlistItem != null && playlistItem.Transcode && _currentItem != null)
- //{
- // var newItem = CreatePlaylistItem(_currentItem, command.SeekPositionTicks ?? 0, GetServerAddress());
- // playlistItem.StartPositionTicks = newItem.StartPositionTicks;
- // playlistItem.StreamUrl = newItem.StreamUrl;
- // playlistItem.Didl = newItem.Didl;
- // return _device.SetAvTransport(playlistItem.StreamUrl, GetDlnaHeaders(playlistItem), playlistItem.Didl);
+ {
+ var media = _device.CurrentMediaInfo;
- //}
- return _device.Seek(TimeSpan.FromTicks(command.SeekPositionTicks ?? 0));
+ if (media != null)
+ {
+ var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
+ if (info.Item != null && !info.IsDirectStream)
+ {
+ var user = _session.UserId.HasValue ? _userManager.GetUserById(_session.UserId.Value) : null;
+ var newItem = CreatePlaylistItem(info.Item, user, command.SeekPositionTicks ?? 0, GetServerAddress(), info.MediaSourceId, info.AudioStreamIndex, info.SubtitleStreamIndex);
+
+ return _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl);
+ }
+ }
+ return _device.Seek(TimeSpan.FromTicks(command.SeekPositionTicks ?? 0));
+ }
case PlaystateCommand.NextTrack:
return SetNext();
@@ -385,6 +380,11 @@ namespace MediaBrowser.Dlna.PlayTo
private PlaylistItem CreatePlaylistItem(BaseItem item, User user, long startPostionTicks, string serverAddress)
{
+ return CreatePlaylistItem(item, user, startPostionTicks, serverAddress, null, null, null);
+ }
+
+ private PlaylistItem CreatePlaylistItem(BaseItem item, User user, long startPostionTicks, string serverAddress, string mediaSourceId, int? audioStreamIndex, int? subtitleStreamIndex)
+ {
var deviceInfo = _device.Properties;
var profile = _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification()) ??
@@ -395,7 +395,7 @@ namespace MediaBrowser.Dlna.PlayTo
? (user == null ? hasMediaSources.GetMediaSources(true) : hasMediaSources.GetMediaSources(true, user)).ToList()
: new List<MediaSourceInfo>();
- var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId);
+ var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
playlistItem.StreamInfo.StartPositionTicks = startPostionTicks;
playlistItem.StreamUrl = playlistItem.StreamInfo.ToUrl(serverAddress);
@@ -450,7 +450,7 @@ namespace MediaBrowser.Dlna.PlayTo
return null;
}
- private PlaylistItem GetPlaylistItem(BaseItem item, List<MediaSourceInfo> mediaSources, DeviceProfile profile, string deviceId)
+ private PlaylistItem GetPlaylistItem(BaseItem item, List<MediaSourceInfo> mediaSources, DeviceProfile profile, string deviceId, string mediaSourceId, int? audioStreamIndex, int? subtitleStreamIndex)
{
var video = item as Video;
@@ -464,7 +464,10 @@ namespace MediaBrowser.Dlna.PlayTo
MediaSources = mediaSources,
Profile = profile,
DeviceId = deviceId,
- MaxBitrate = profile.MaxBitrate
+ MaxBitrate = profile.MaxBitrate,
+ MediaSourceId = mediaSourceId,
+ AudioStreamIndex = audioStreamIndex,
+ SubtitleStreamIndex = subtitleStreamIndex
}),
Profile = profile
@@ -483,7 +486,8 @@ namespace MediaBrowser.Dlna.PlayTo
MediaSources = mediaSources,
Profile = profile,
DeviceId = deviceId,
- MaxBitrate = profile.MaxBitrate
+ MaxBitrate = profile.MaxBitrate,
+ MediaSourceId = mediaSourceId
}),
Profile = profile
@@ -626,7 +630,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
int volume;
- if (int.TryParse(volumeArg, NumberStyles.Any, _usCulture, out volume))
+ if (Int32.TryParse(volumeArg, NumberStyles.Any, _usCulture, out volume))
{
return _device.SetVolume(volume);
}
@@ -643,5 +647,120 @@ namespace MediaBrowser.Dlna.PlayTo
return Task.FromResult(true);
}
+
+ private class StreamParams
+ {
+ public string ItemId { get; set; }
+
+ public bool IsDirectStream { get; set; }
+
+ public long StartPositionTicks { get; set; }
+
+ public int? AudioStreamIndex { get; set; }
+
+ public int? SubtitleStreamIndex { get; set; }
+
+ public string DeviceProfileId { get; set; }
+ public string DeviceId { get; set; }
+
+ public string MediaSourceId { get; set; }
+
+ public BaseItem Item { get; set; }
+ public MediaSourceInfo MediaSource { get; set; }
+
+ private static string GetItemId(string url)
+ {
+ var parts = url.Split('/');
+
+ for (var i = 0; i < parts.Length; i++)
+ {
+ var part = parts[i];
+
+ if (string.Equals(part, "audio", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(part, "videos", StringComparison.OrdinalIgnoreCase))
+ {
+ if (parts.Length > i + 1)
+ {
+ return parts[i + 1];
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public static StreamParams ParseFromUrl(string url, ILibraryManager libraryManager)
+ {
+ var request = new StreamParams
+ {
+ ItemId = GetItemId(url)
+ };
+
+ if (string.IsNullOrWhiteSpace(request.ItemId))
+ {
+ return request;
+ }
+
+ const string srch = "params=";
+ var index = url.IndexOf(srch, StringComparison.OrdinalIgnoreCase);
+
+ if (index == -1) return request;
+
+ var vals = url.Substring(index + srch.Length).Split(';');
+
+ for (var i = 0; i < vals.Length; i++)
+ {
+ var val = vals[i];
+
+ if (string.IsNullOrWhiteSpace(val))
+ {
+ continue;
+ }
+
+ if (i == 0)
+ {
+ request.DeviceProfileId = val;
+ }
+ else if (i == 1)
+ {
+ request.DeviceId = val;
+ }
+ else if (i == 2)
+ {
+ request.MediaSourceId = val;
+ }
+ else if (i == 3)
+ {
+ request.IsDirectStream = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+ }
+ else if (i == 6)
+ {
+ request.AudioStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
+ }
+ else if (i == 7)
+ {
+ request.SubtitleStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
+ }
+ else if (i == 14)
+ {
+ request.StartPositionTicks = long.Parse(val, CultureInfo.InvariantCulture);
+ }
+ }
+
+ request.Item = string.IsNullOrWhiteSpace(request.ItemId)
+ ? null
+ : libraryManager.GetItemById(new Guid(request.ItemId));
+
+ var hasMediaSources = request.Item as IHasMediaSources;
+
+ request.MediaSource = hasMediaSources == null ?
+ null :
+ hasMediaSources.GetMediaSources(false).FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId, StringComparison.OrdinalIgnoreCase));
+
+
+
+ return request;
+ }
+ }
}
}