From dce9093ba1f67a41c3bb9bca59ec9df77c5bd4bd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 8 May 2014 17:23:24 -0400 Subject: split files into separate classes --- .../MediaBrowser.Common.Implementations.csproj | 3 +- .../ScheduledTasks/Tasks/ReloadLoggerFileTask.cs | 105 ++++ .../ScheduledTasks/Tasks/ReloadLoggerTask.cs | 105 ---- .../Security/MBRegistration.cs | 7 - .../Security/RegRecord.cs | 11 + MediaBrowser.Common/IApplicationHost.cs | 11 - MediaBrowser.Common/IDependencyContainer.cs | 15 + MediaBrowser.Common/MediaBrowser.Common.csproj | 5 + MediaBrowser.Common/Net/IWebSocketConnection.cs | 12 - MediaBrowser.Common/Net/WebSocketMessageInfo.cs | 16 + .../ScheduledTasks/IConfigurableScheduledTask.cs | 16 + MediaBrowser.Common/ScheduledTasks/IHasKey.cs | 7 + .../ScheduledTasks/IScheduledTask.cs | 19 - .../Updates/InstallationEventArgs.cs | 6 - .../Updates/InstallationFailedEventArgs.cs | 9 + MediaBrowser.Dlna/MediaBrowser.Dlna.csproj | 8 +- MediaBrowser.Dlna/PlayTo/DeviceEventArgs.cs | 28 - MediaBrowser.Dlna/PlayTo/DlnaController.cs | 650 --------------------- MediaBrowser.Dlna/PlayTo/PlayToController.cs | 650 +++++++++++++++++++++ .../PlayTo/PlaybackProgressEventArgs.cs | 9 + MediaBrowser.Dlna/PlayTo/PlaybackStartEventArgs.cs | 9 + .../PlayTo/PlaybackStoppedEventArgs.cs | 9 + MediaBrowser.Dlna/PlayTo/TRANSPORTSTATE.cs | 11 + MediaBrowser.Dlna/PlayTo/uParser.cs | 5 - MediaBrowser.Dlna/PlayTo/uParserObject.cs | 9 + MediaBrowser.Dlna/Profiles/DefaultProfile.cs | 4 +- MediaBrowser.Dlna/Profiles/Xml/Default.xml | 4 +- MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml | 4 +- MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml | 4 +- MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml | 4 +- MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml | 4 +- .../Profiles/Xml/Samsung Smart TV.xml | 4 +- .../Profiles/Xml/Sony Blu-ray Player 2013.xml | 4 +- .../Profiles/Xml/Sony Blu-ray Player.xml | 4 +- .../Profiles/Xml/Sony PlayStation 3.xml | 4 +- MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml | 4 +- MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml | 4 +- MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml | 4 +- MediaBrowser.Model/Dlna/CodecProfile.cs | 7 +- MediaBrowser.Model/Dlna/ContainerProfile.cs | 8 +- MediaBrowser.Model/Dlna/DeviceProfile.cs | 7 +- MediaBrowser.Model/Dlna/DirectPlayProfile.cs | 22 +- MediaBrowser.Model/Dlna/ResponseProfile.cs | 24 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 65 ++- MediaBrowser.Model/Dlna/StreamInfo.cs | 28 +- MediaBrowser.Model/Dlna/TranscodingProfile.cs | 7 +- .../EntryPoints/Notifications/Notifications.cs | 2 +- .../Native/BrowserLauncher.cs | 2 +- 48 files changed, 1048 insertions(+), 911 deletions(-) create mode 100644 MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs delete mode 100644 MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerTask.cs create mode 100644 MediaBrowser.Common.Implementations/Security/RegRecord.cs create mode 100644 MediaBrowser.Common/IDependencyContainer.cs create mode 100644 MediaBrowser.Common/Net/WebSocketMessageInfo.cs create mode 100644 MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs create mode 100644 MediaBrowser.Common/ScheduledTasks/IHasKey.cs create mode 100644 MediaBrowser.Common/Updates/InstallationFailedEventArgs.cs delete mode 100644 MediaBrowser.Dlna/PlayTo/DeviceEventArgs.cs delete mode 100644 MediaBrowser.Dlna/PlayTo/DlnaController.cs create mode 100644 MediaBrowser.Dlna/PlayTo/PlayToController.cs create mode 100644 MediaBrowser.Dlna/PlayTo/PlaybackProgressEventArgs.cs create mode 100644 MediaBrowser.Dlna/PlayTo/PlaybackStartEventArgs.cs create mode 100644 MediaBrowser.Dlna/PlayTo/PlaybackStoppedEventArgs.cs create mode 100644 MediaBrowser.Dlna/PlayTo/TRANSPORTSTATE.cs create mode 100644 MediaBrowser.Dlna/PlayTo/uParserObject.cs diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index f6f800f4a..fcb66d0bd 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -95,11 +95,12 @@ - + + diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs new file mode 100644 index 000000000..78f60632f --- /dev/null +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs @@ -0,0 +1,105 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks +{ + /// + /// Class ReloadLoggerFileTask + /// + public class ReloadLoggerFileTask : IScheduledTask, IConfigurableScheduledTask + { + /// + /// Gets or sets the log manager. + /// + /// The log manager. + private ILogManager LogManager { get; set; } + /// + /// Gets or sets the configuration manager. + /// + /// The configuration manager. + private IConfigurationManager ConfigurationManager { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The logManager. + /// The configuration manager. + public ReloadLoggerFileTask(ILogManager logManager, IConfigurationManager configurationManager) + { + LogManager = logManager; + ConfigurationManager = configurationManager; + } + + /// + /// Gets the default triggers. + /// + /// IEnumerable{BaseTaskTrigger}. + public IEnumerable GetDefaultTriggers() + { + var trigger = new DailyTrigger { TimeOfDay = TimeSpan.FromHours(0) }; //12am + + return new[] { trigger }; + } + + /// + /// Executes the internal. + /// + /// The cancellation token. + /// The progress. + /// Task. + public Task Execute(CancellationToken cancellationToken, IProgress progress) + { + cancellationToken.ThrowIfCancellationRequested(); + + progress.Report(0); + + LogManager.ReloadLogger(ConfigurationManager.CommonConfiguration.EnableDebugLevelLogging + ? LogSeverity.Debug + : LogSeverity.Info); + + return Task.FromResult(true); + } + + /// + /// Gets the name. + /// + /// The name. + public string Name + { + get { return "Start new log file"; } + } + + /// + /// Gets the description. + /// + /// The description. + public string Description + { + get { return "Moves logging to a new file to help reduce log file sizes."; } + } + + /// + /// Gets the category. + /// + /// The category. + public string Category + { + get { return "Application"; } + } + + public bool IsHidden + { + get { return true; } + } + + public bool IsEnabled + { + get { return true; } + } + } +} diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerTask.cs deleted file mode 100644 index 78f60632f..000000000 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerTask.cs +++ /dev/null @@ -1,105 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks -{ - /// - /// Class ReloadLoggerFileTask - /// - public class ReloadLoggerFileTask : IScheduledTask, IConfigurableScheduledTask - { - /// - /// Gets or sets the log manager. - /// - /// The log manager. - private ILogManager LogManager { get; set; } - /// - /// Gets or sets the configuration manager. - /// - /// The configuration manager. - private IConfigurationManager ConfigurationManager { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The logManager. - /// The configuration manager. - public ReloadLoggerFileTask(ILogManager logManager, IConfigurationManager configurationManager) - { - LogManager = logManager; - ConfigurationManager = configurationManager; - } - - /// - /// Gets the default triggers. - /// - /// IEnumerable{BaseTaskTrigger}. - public IEnumerable GetDefaultTriggers() - { - var trigger = new DailyTrigger { TimeOfDay = TimeSpan.FromHours(0) }; //12am - - return new[] { trigger }; - } - - /// - /// Executes the internal. - /// - /// The cancellation token. - /// The progress. - /// Task. - public Task Execute(CancellationToken cancellationToken, IProgress progress) - { - cancellationToken.ThrowIfCancellationRequested(); - - progress.Report(0); - - LogManager.ReloadLogger(ConfigurationManager.CommonConfiguration.EnableDebugLevelLogging - ? LogSeverity.Debug - : LogSeverity.Info); - - return Task.FromResult(true); - } - - /// - /// Gets the name. - /// - /// The name. - public string Name - { - get { return "Start new log file"; } - } - - /// - /// Gets the description. - /// - /// The description. - public string Description - { - get { return "Moves logging to a new file to help reduce log file sizes."; } - } - - /// - /// Gets the category. - /// - /// The category. - public string Category - { - get { return "Application"; } - } - - public bool IsHidden - { - get { return true; } - } - - public bool IsEnabled - { - get { return true; } - } - } -} diff --git a/MediaBrowser.Common.Implementations/Security/MBRegistration.cs b/MediaBrowser.Common.Implementations/Security/MBRegistration.cs index 1d64b5ea1..ca000df19 100644 --- a/MediaBrowser.Common.Implementations/Security/MBRegistration.cs +++ b/MediaBrowser.Common.Implementations/Security/MBRegistration.cs @@ -94,11 +94,4 @@ namespace MediaBrowser.Common.Implementations.Security return new MBRegistrationRecord { IsRegistered = reg.registered, ExpirationDate = reg.expDate, RegChecked = true }; } } - - class RegRecord - { - public string featId { get; set; } - public bool registered { get; set; } - public DateTime expDate { get; set; } - } } diff --git a/MediaBrowser.Common.Implementations/Security/RegRecord.cs b/MediaBrowser.Common.Implementations/Security/RegRecord.cs new file mode 100644 index 000000000..f4e4337bf --- /dev/null +++ b/MediaBrowser.Common.Implementations/Security/RegRecord.cs @@ -0,0 +1,11 @@ +using System; + +namespace MediaBrowser.Common.Implementations.Security +{ + class RegRecord + { + public string featId { get; set; } + public bool registered { get; set; } + public DateTime expDate { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index 0e2fef1e6..709a8e927 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -152,15 +152,4 @@ namespace MediaBrowser.Common /// System.Object. object CreateInstance(Type type); } - - public interface IDependencyContainer - { - void RegisterSingleInstance(T obj, bool manageLifetime = true) - where T : class; - - void RegisterSingleInstance(Func func) - where T : class; - - void Register(Type typeInterface, Type typeImplementation); - } } diff --git a/MediaBrowser.Common/IDependencyContainer.cs b/MediaBrowser.Common/IDependencyContainer.cs new file mode 100644 index 000000000..423c1740a --- /dev/null +++ b/MediaBrowser.Common/IDependencyContainer.cs @@ -0,0 +1,15 @@ +using System; + +namespace MediaBrowser.Common +{ + public interface IDependencyContainer + { + void RegisterSingleInstance(T obj, bool manageLifetime = true) + where T : class; + + void RegisterSingleInstance(Func func) + where T : class; + + void Register(Type typeInterface, Type typeImplementation); + } +} \ No newline at end of file diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 1da144649..2e7db5c35 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -60,6 +60,7 @@ + @@ -78,9 +79,12 @@ + + + @@ -98,6 +102,7 @@ + diff --git a/MediaBrowser.Common/Net/IWebSocketConnection.cs b/MediaBrowser.Common/Net/IWebSocketConnection.cs index 482da131e..514a52d96 100644 --- a/MediaBrowser.Common/Net/IWebSocketConnection.cs +++ b/MediaBrowser.Common/Net/IWebSocketConnection.cs @@ -65,16 +65,4 @@ namespace MediaBrowser.Common.Net /// buffer Task SendAsync(byte[] buffer, WebSocketMessageType type, CancellationToken cancellationToken); } - - /// - /// Class WebSocketMessageInfo - /// - public class WebSocketMessageInfo : WebSocketMessage - { - /// - /// Gets or sets the connection. - /// - /// The connection. - public IWebSocketConnection Connection { get; set; } - } } \ No newline at end of file diff --git a/MediaBrowser.Common/Net/WebSocketMessageInfo.cs b/MediaBrowser.Common/Net/WebSocketMessageInfo.cs new file mode 100644 index 000000000..c1f935a7b --- /dev/null +++ b/MediaBrowser.Common/Net/WebSocketMessageInfo.cs @@ -0,0 +1,16 @@ +using MediaBrowser.Model.Net; + +namespace MediaBrowser.Common.Net +{ + /// + /// Class WebSocketMessageInfo + /// + public class WebSocketMessageInfo : WebSocketMessage + { + /// + /// Gets or sets the connection. + /// + /// The connection. + public IWebSocketConnection Connection { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs new file mode 100644 index 000000000..fc6963070 --- /dev/null +++ b/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs @@ -0,0 +1,16 @@ +namespace MediaBrowser.Common.ScheduledTasks +{ + public interface IConfigurableScheduledTask + { + /// + /// Gets a value indicating whether this instance is hidden. + /// + /// true if this instance is hidden; otherwise, false. + bool IsHidden { get; } + /// + /// Gets a value indicating whether this instance is enabled. + /// + /// true if this instance is enabled; otherwise, false. + bool IsEnabled { get; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/IHasKey.cs b/MediaBrowser.Common/ScheduledTasks/IHasKey.cs new file mode 100644 index 000000000..5736cb616 --- /dev/null +++ b/MediaBrowser.Common/ScheduledTasks/IHasKey.cs @@ -0,0 +1,7 @@ +namespace MediaBrowser.Common.ScheduledTasks +{ + public interface IHasKey + { + string Key { get; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs index e150f7f4e..351e96c7d 100644 --- a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs @@ -42,23 +42,4 @@ namespace MediaBrowser.Common.ScheduledTasks /// IEnumerable{BaseTaskTrigger}. IEnumerable GetDefaultTriggers(); } - - public interface IConfigurableScheduledTask - { - /// - /// Gets a value indicating whether this instance is hidden. - /// - /// true if this instance is hidden; otherwise, false. - bool IsHidden { get; } - /// - /// Gets a value indicating whether this instance is enabled. - /// - /// true if this instance is enabled; otherwise, false. - bool IsEnabled { get; } - } - - public interface IHasKey - { - string Key { get; } - } } diff --git a/MediaBrowser.Common/Updates/InstallationEventArgs.cs b/MediaBrowser.Common/Updates/InstallationEventArgs.cs index 2c3a805de..9dc8ead83 100644 --- a/MediaBrowser.Common/Updates/InstallationEventArgs.cs +++ b/MediaBrowser.Common/Updates/InstallationEventArgs.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Updates; -using System; namespace MediaBrowser.Common.Updates { @@ -9,9 +8,4 @@ namespace MediaBrowser.Common.Updates public PackageVersionInfo PackageVersionInfo { get; set; } } - - public class InstallationFailedEventArgs : InstallationEventArgs - { - public Exception Exception { get; set; } - } } diff --git a/MediaBrowser.Common/Updates/InstallationFailedEventArgs.cs b/MediaBrowser.Common/Updates/InstallationFailedEventArgs.cs new file mode 100644 index 000000000..69dc1ee98 --- /dev/null +++ b/MediaBrowser.Common/Updates/InstallationFailedEventArgs.cs @@ -0,0 +1,9 @@ +using System; + +namespace MediaBrowser.Common.Updates +{ + public class InstallationFailedEventArgs : InstallationEventArgs + { + public Exception Exception { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index fa609843b..d39bcbefe 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -59,18 +59,22 @@ Code - + - + + + Code + + diff --git a/MediaBrowser.Dlna/PlayTo/DeviceEventArgs.cs b/MediaBrowser.Dlna/PlayTo/DeviceEventArgs.cs deleted file mode 100644 index 67230c189..000000000 --- a/MediaBrowser.Dlna/PlayTo/DeviceEventArgs.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; - -namespace MediaBrowser.Dlna.PlayTo -{ - public class PlaybackStartEventArgs : EventArgs - { - public uBaseObject MediaInfo { get; set; } - } - - public class PlaybackProgressEventArgs : EventArgs - { - public uBaseObject MediaInfo { get; set; } - } - - public class PlaybackStoppedEventArgs : EventArgs - { - public uBaseObject MediaInfo { get; set; } - } - - public enum TRANSPORTSTATE - { - STOPPED, - PLAYING, - TRANSITIONING, - PAUSED_PLAYBACK, - PAUSED - } -} diff --git a/MediaBrowser.Dlna/PlayTo/DlnaController.cs b/MediaBrowser.Dlna/PlayTo/DlnaController.cs deleted file mode 100644 index ab342d635..000000000 --- a/MediaBrowser.Dlna/PlayTo/DlnaController.cs +++ /dev/null @@ -1,650 +0,0 @@ -using MediaBrowser.Controller.Dlna; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Session; -using MediaBrowser.Dlna.Didl; -using MediaBrowser.Dlna.Ssdp; -using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Session; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Dlna.PlayTo -{ - public class PlayToController : ISessionController, IDisposable - { - private Device _device; - private readonly SessionInfo _session; - private readonly ISessionManager _sessionManager; - private readonly IItemRepository _itemRepository; - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IDlnaManager _dlnaManager; - private readonly IUserManager _userManager; - private readonly IDtoService _dtoService; - private readonly IImageProcessor _imageProcessor; - - private readonly SsdpHandler _ssdpHandler; - private readonly string _serverAddress; - - public bool SupportsMediaRemoteControl - { - get { return true; } - } - - public bool IsSessionActive - { - get - { - return _device != null; - } - } - - private Timer _updateTimer; - - public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IDtoService dtoService, IImageProcessor imageProcessor, SsdpHandler ssdpHandler, string serverAddress) - { - _session = session; - _itemRepository = itemRepository; - _sessionManager = sessionManager; - _libraryManager = libraryManager; - _dlnaManager = dlnaManager; - _userManager = userManager; - _dtoService = dtoService; - _imageProcessor = imageProcessor; - _ssdpHandler = ssdpHandler; - _serverAddress = serverAddress; - _logger = logger; - } - - public void Init(Device device) - { - _device = device; - _device.PlaybackStart += _device_PlaybackStart; - _device.PlaybackProgress += _device_PlaybackProgress; - _device.PlaybackStopped += _device_PlaybackStopped; - _device.Start(); - - _ssdpHandler.MessageReceived += _SsdpHandler_MessageReceived; - - _updateTimer = new Timer(updateTimer_Elapsed, null, 60000, 60000); - } - - private async void updateTimer_Elapsed(object state) - { - if (DateTime.UtcNow >= _device.DateLastActivity.AddSeconds(60)) - { - try - { - // Session is inactive, mark it for Disposal and don't start the elapsed timer. - await _sessionManager.ReportSessionEnded(_session.Id).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error in ReportSessionEnded", ex); - } - } - } - - private string GetServerAddress() - { - return _serverAddress; - } - - async void _SsdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e) - { - string nts; - e.Headers.TryGetValue("NTS", out nts); - - string usn; - if (!e.Headers.TryGetValue("USN", out usn)) usn = string.Empty; - - string nt; - 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) && - usn.IndexOf(_device.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1 && - !_disposed) - { - if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) != -1 || - nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) != -1) - { - try - { - await _sessionManager.ReportSessionEnded(_session.Id).ConfigureAwait(false); - } - catch - { - // Could throw if the session is already gone - } - } - } - } - - async void _device_PlaybackStopped(object sender, PlaybackStoppedEventArgs e) - { - try - { - await _sessionManager.OnPlaybackStopped(new PlaybackStopInfo - { - ItemId = e.MediaInfo.Id, - SessionId = _session.Id, - PositionTicks = _device.Position.Ticks - - }).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error reporting progress", ex); - } - - await SetNext().ConfigureAwait(false); - } - - async void _device_PlaybackStart(object sender, PlaybackStartEventArgs e) - { - var playlistItem = Playlist.FirstOrDefault(p => p.PlayState == 1); - - if (playlistItem != null) - { - 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); - } - } - } - - async void _device_PlaybackProgress(object sender, PlaybackProgressEventArgs e) - { - var playlistItem = Playlist.FirstOrDefault(p => p.PlayState == 1); - - if (playlistItem != null) - { - 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); - } - } - } - - private PlaybackStartInfo GetProgressInfo(StreamInfo streamInfo, uBaseObject mediaInfo) - { - var ticks = _device.Position.Ticks; - - if (!streamInfo.IsDirectStream) - { - ticks += streamInfo.StartPositionTicks; - } - - return new PlaybackStartInfo - { - ItemId = mediaInfo.Id, - SessionId = _session.Id, - PositionTicks = ticks, - IsMuted = _device.IsMuted, - IsPaused = _device.IsPaused, - MediaSourceId = streamInfo.MediaSourceId, - AudioStreamIndex = streamInfo.AudioStreamIndex, - SubtitleStreamIndex = streamInfo.SubtitleStreamIndex, - VolumeLevel = _device.Volume, - CanSeek = streamInfo.RunTimeTicks.HasValue, - PlayMethod = streamInfo.IsDirectStream ? PlayMethod.DirectStream : PlayMethod.Transcode, - QueueableMediaTypes = new List { mediaInfo.MediaType } - }; - } - - #region SendCommands - - public async Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken) - { - _logger.Debug("{0} - Received PlayRequest: {1}", this._session.DeviceName, command.PlayCommand); - - var items = new List(); - foreach (string id in command.ItemIds) - { - AddItemFromId(Guid.Parse(id), items); - } - - var playlist = new List(); - var isFirst = true; - - var serverAddress = GetServerAddress(); - - foreach (var item in items) - { - if (isFirst && command.StartPositionTicks.HasValue) - { - playlist.Add(CreatePlaylistItem(item, command.StartPositionTicks.Value, serverAddress)); - isFirst = false; - } - else - { - playlist.Add(CreatePlaylistItem(item, 0, serverAddress)); - } - } - - _logger.Debug("{0} - Playlist created", _session.DeviceName); - - if (command.PlayCommand == PlayCommand.PlayLast) - { - Playlist.AddRange(playlist); - } - if (command.PlayCommand == PlayCommand.PlayNext) - { - Playlist.AddRange(playlist); - } - - _logger.Debug("{0} - Playing {1} items", _session.DeviceName, playlist.Count); - - if (!string.IsNullOrWhiteSpace(command.ControllingUserId)) - { - var userId = new Guid(command.ControllingUserId); - - var user = _userManager.GetUserById(userId); - - await _sessionManager.LogSessionActivity(_session.Client, _session.ApplicationVersion, _session.DeviceId, - _session.DeviceName, _session.RemoteEndPoint, user).ConfigureAwait(false); - } - - await PlayItems(playlist).ConfigureAwait(false); - } - - public Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken) - { - switch (command.Command) - { - case PlaystateCommand.Stop: - Playlist.Clear(); - return _device.SetStop(); - - case PlaystateCommand.Pause: - return _device.SetPause(); - - case PlaystateCommand.Unpause: - 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); - - //} - return _device.Seek(TimeSpan.FromTicks(command.SeekPositionTicks ?? 0)); - - - case PlaystateCommand.NextTrack: - return SetNext(); - - case PlaystateCommand.PreviousTrack: - return SetPrevious(); - } - - return Task.FromResult(true); - } - - public Task SendUserDataChangeInfo(UserDataChangeInfo info, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendRestartRequiredNotification(CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendServerRestartNotification(CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendPlaybackStartNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendPlaybackStoppedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendServerShutdownNotification(CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken) - { - return Task.FromResult(true); - } - - #endregion - - #region Playlist - - private readonly List _playlist = new List(); - private List Playlist - { - get - { - return _playlist; - } - } - - private void AddItemFromId(Guid id, List list) - { - var item = _libraryManager.GetItemById(id); - if (item.IsFolder) - { - foreach (var childId in _itemRepository.GetChildren(item.Id)) - { - AddItemFromId(childId, list); - } - } - else - { - if (item.MediaType == MediaType.Audio || item.MediaType == MediaType.Video) - { - list.Add(item); - } - } - } - - private PlaylistItem CreatePlaylistItem(BaseItem item, long startPostionTicks, string serverAddress) - { - var deviceInfo = _device.Properties; - - var profile = _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification()) ?? - _dlnaManager.GetDefaultProfile(); - - var mediaSources = item is Audio || item is Video - ? _dtoService.GetMediaSources(item) - : new List(); - - var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId); - playlistItem.StreamInfo.StartPositionTicks = startPostionTicks; - - playlistItem.StreamUrl = playlistItem.StreamInfo.ToUrl(serverAddress); - - var itemXml = - new DidlBuilder(profile, _imageProcessor, serverAddress, _dtoService).GetItemDidl(item, _session.DeviceId, - new Filter()); - - playlistItem.Didl = itemXml; - - return playlistItem; - } - - private string GetDlnaHeaders(PlaylistItem item) - { - var profile = item.Profile; - var streamInfo = item.StreamInfo; - - if (streamInfo.MediaType == DlnaProfileType.Audio) - { - return new ContentFeatureBuilder(profile) - .BuildAudioHeader(streamInfo.Container, - streamInfo.AudioCodec, - streamInfo.TargetAudioBitrate, - streamInfo.TargetAudioSampleRate, - streamInfo.TargetAudioChannels, - streamInfo.IsDirectStream, - streamInfo.RunTimeTicks, - streamInfo.TranscodeSeekInfo); - } - - if (streamInfo.MediaType == DlnaProfileType.Video) - { - return new ContentFeatureBuilder(profile) - .BuildVideoHeader(streamInfo.Container, - streamInfo.VideoCodec, - streamInfo.AudioCodec, - streamInfo.TargetWidth, - streamInfo.TargetHeight, - streamInfo.TargetVideoBitDepth, - streamInfo.TargetVideoBitrate, - streamInfo.TargetAudioChannels, - streamInfo.TargetAudioBitrate, - streamInfo.TargetTimestamp, - streamInfo.IsDirectStream, - streamInfo.RunTimeTicks, - streamInfo.TargetVideoProfile, - streamInfo.TargetVideoLevel, - streamInfo.TargetFramerate, - streamInfo.TargetPacketLength, - streamInfo.TranscodeSeekInfo); - } - - return null; - } - - private PlaylistItem GetPlaylistItem(BaseItem item, List mediaSources, DeviceProfile profile, string deviceId) - { - var video = item as Video; - - if (video != null) - { - return new PlaylistItem - { - StreamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions - { - ItemId = item.Id.ToString("N"), - MediaSources = mediaSources, - Profile = profile, - DeviceId = deviceId - }), - - Profile = profile - }; - } - - var audio = item as Audio; - - if (audio != null) - { - return new PlaylistItem - { - StreamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions - { - ItemId = item.Id.ToString("N"), - MediaSources = mediaSources, - Profile = profile, - DeviceId = deviceId - }), - - Profile = profile - }; - } - - var photo = item as Photo; - - if (photo != null) - { - return new PlaylistItemFactory().Create(photo, profile); - } - - throw new ArgumentException("Unrecognized item type."); - } - - /// - /// Plays the items. - /// - /// The items. - /// - private async Task PlayItems(IEnumerable items) - { - Playlist.Clear(); - Playlist.AddRange(items); - await SetNext(); - return true; - } - - private async Task SetNext() - { - if (!Playlist.Any() || Playlist.All(i => i.PlayState != 0)) - { - return; - } - - var currentitem = Playlist.FirstOrDefault(i => i.PlayState == 1); - - if (currentitem != null) - { - currentitem.PlayState = 2; - } - - var nextTrack = Playlist.FirstOrDefault(i => i.PlayState == 0); - if (nextTrack == null) - { - await _device.SetStop(); - return; - } - - nextTrack.PlayState = 1; - - var dlnaheaders = GetDlnaHeaders(nextTrack); - - _logger.Debug("{0} - SetAvTransport Uri: {1} DlnaHeaders: {2}", _device.Properties.Name, nextTrack.StreamUrl, dlnaheaders); - - await _device.SetAvTransport(nextTrack.StreamUrl, dlnaheaders, nextTrack.Didl); - - var streamInfo = nextTrack.StreamInfo; - if (streamInfo.StartPositionTicks > 0 && streamInfo.IsDirectStream) - await _device.Seek(TimeSpan.FromTicks(streamInfo.StartPositionTicks)); - } - - public Task SetPrevious() - { - if (!Playlist.Any() || Playlist.All(i => i.PlayState != 2)) - return Task.FromResult(false); - - var currentitem = Playlist.FirstOrDefault(i => i.PlayState == 1); - - var prevTrack = Playlist.LastOrDefault(i => i.PlayState == 2); - - if (currentitem != null) - { - currentitem.PlayState = 0; - } - - if (prevTrack == null) - return Task.FromResult(false); - - prevTrack.PlayState = 1; - return _device.SetAvTransport(prevTrack.StreamInfo.ToDlnaUrl(GetServerAddress()), GetDlnaHeaders(prevTrack), prevTrack.Didl); - } - - #endregion - - private bool _disposed; - - public void Dispose() - { - if (!_disposed) - { - _disposed = true; - - _device.PlaybackStart -= _device_PlaybackStart; - _device.PlaybackProgress -= _device_PlaybackProgress; - _device.PlaybackStopped -= _device_PlaybackStopped; - _ssdpHandler.MessageReceived -= _SsdpHandler_MessageReceived; - - DisposeUpdateTimer(); - - _device.Dispose(); - } - } - - private void DisposeUpdateTimer() - { - if (_updateTimer != null) - { - _updateTimer.Dispose(); - _updateTimer = null; - } - } - - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken) - { - GeneralCommandType commandType; - - if (Enum.TryParse(command.Name, true, out commandType)) - { - switch (commandType) - { - case GeneralCommandType.VolumeDown: - return _device.VolumeDown(); - case GeneralCommandType.VolumeUp: - return _device.VolumeUp(); - case GeneralCommandType.Mute: - return _device.Mute(); - case GeneralCommandType.Unmute: - return _device.Unmute(); - case GeneralCommandType.ToggleMute: - return _device.ToggleMute(); - case GeneralCommandType.SetVolume: - { - string volumeArg; - - if (command.Arguments.TryGetValue("Volume", out volumeArg)) - { - int volume; - - if (int.TryParse(volumeArg, NumberStyles.Any, _usCulture, out volume)) - { - return _device.SetVolume(volume); - } - - throw new ArgumentException("Unsupported volume value supplied."); - } - - throw new ArgumentException("Volume argument cannot be null"); - } - default: - return Task.FromResult(true); - } - } - - return Task.FromResult(true); - } - } -} diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs new file mode 100644 index 000000000..ab342d635 --- /dev/null +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -0,0 +1,650 @@ +using MediaBrowser.Controller.Dlna; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Session; +using MediaBrowser.Dlna.Didl; +using MediaBrowser.Dlna.Ssdp; +using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Session; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Dlna.PlayTo +{ + public class PlayToController : ISessionController, IDisposable + { + private Device _device; + private readonly SessionInfo _session; + private readonly ISessionManager _sessionManager; + private readonly IItemRepository _itemRepository; + private readonly ILibraryManager _libraryManager; + private readonly ILogger _logger; + private readonly IDlnaManager _dlnaManager; + private readonly IUserManager _userManager; + private readonly IDtoService _dtoService; + private readonly IImageProcessor _imageProcessor; + + private readonly SsdpHandler _ssdpHandler; + private readonly string _serverAddress; + + public bool SupportsMediaRemoteControl + { + get { return true; } + } + + public bool IsSessionActive + { + get + { + return _device != null; + } + } + + private Timer _updateTimer; + + public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IDtoService dtoService, IImageProcessor imageProcessor, SsdpHandler ssdpHandler, string serverAddress) + { + _session = session; + _itemRepository = itemRepository; + _sessionManager = sessionManager; + _libraryManager = libraryManager; + _dlnaManager = dlnaManager; + _userManager = userManager; + _dtoService = dtoService; + _imageProcessor = imageProcessor; + _ssdpHandler = ssdpHandler; + _serverAddress = serverAddress; + _logger = logger; + } + + public void Init(Device device) + { + _device = device; + _device.PlaybackStart += _device_PlaybackStart; + _device.PlaybackProgress += _device_PlaybackProgress; + _device.PlaybackStopped += _device_PlaybackStopped; + _device.Start(); + + _ssdpHandler.MessageReceived += _SsdpHandler_MessageReceived; + + _updateTimer = new Timer(updateTimer_Elapsed, null, 60000, 60000); + } + + private async void updateTimer_Elapsed(object state) + { + if (DateTime.UtcNow >= _device.DateLastActivity.AddSeconds(60)) + { + try + { + // Session is inactive, mark it for Disposal and don't start the elapsed timer. + await _sessionManager.ReportSessionEnded(_session.Id).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error in ReportSessionEnded", ex); + } + } + } + + private string GetServerAddress() + { + return _serverAddress; + } + + async void _SsdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e) + { + string nts; + e.Headers.TryGetValue("NTS", out nts); + + string usn; + if (!e.Headers.TryGetValue("USN", out usn)) usn = string.Empty; + + string nt; + 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) && + usn.IndexOf(_device.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1 && + !_disposed) + { + if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) != -1 || + nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) != -1) + { + try + { + await _sessionManager.ReportSessionEnded(_session.Id).ConfigureAwait(false); + } + catch + { + // Could throw if the session is already gone + } + } + } + } + + async void _device_PlaybackStopped(object sender, PlaybackStoppedEventArgs e) + { + try + { + await _sessionManager.OnPlaybackStopped(new PlaybackStopInfo + { + ItemId = e.MediaInfo.Id, + SessionId = _session.Id, + PositionTicks = _device.Position.Ticks + + }).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error reporting progress", ex); + } + + await SetNext().ConfigureAwait(false); + } + + async void _device_PlaybackStart(object sender, PlaybackStartEventArgs e) + { + var playlistItem = Playlist.FirstOrDefault(p => p.PlayState == 1); + + if (playlistItem != null) + { + 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); + } + } + } + + async void _device_PlaybackProgress(object sender, PlaybackProgressEventArgs e) + { + var playlistItem = Playlist.FirstOrDefault(p => p.PlayState == 1); + + if (playlistItem != null) + { + 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); + } + } + } + + private PlaybackStartInfo GetProgressInfo(StreamInfo streamInfo, uBaseObject mediaInfo) + { + var ticks = _device.Position.Ticks; + + if (!streamInfo.IsDirectStream) + { + ticks += streamInfo.StartPositionTicks; + } + + return new PlaybackStartInfo + { + ItemId = mediaInfo.Id, + SessionId = _session.Id, + PositionTicks = ticks, + IsMuted = _device.IsMuted, + IsPaused = _device.IsPaused, + MediaSourceId = streamInfo.MediaSourceId, + AudioStreamIndex = streamInfo.AudioStreamIndex, + SubtitleStreamIndex = streamInfo.SubtitleStreamIndex, + VolumeLevel = _device.Volume, + CanSeek = streamInfo.RunTimeTicks.HasValue, + PlayMethod = streamInfo.IsDirectStream ? PlayMethod.DirectStream : PlayMethod.Transcode, + QueueableMediaTypes = new List { mediaInfo.MediaType } + }; + } + + #region SendCommands + + public async Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken) + { + _logger.Debug("{0} - Received PlayRequest: {1}", this._session.DeviceName, command.PlayCommand); + + var items = new List(); + foreach (string id in command.ItemIds) + { + AddItemFromId(Guid.Parse(id), items); + } + + var playlist = new List(); + var isFirst = true; + + var serverAddress = GetServerAddress(); + + foreach (var item in items) + { + if (isFirst && command.StartPositionTicks.HasValue) + { + playlist.Add(CreatePlaylistItem(item, command.StartPositionTicks.Value, serverAddress)); + isFirst = false; + } + else + { + playlist.Add(CreatePlaylistItem(item, 0, serverAddress)); + } + } + + _logger.Debug("{0} - Playlist created", _session.DeviceName); + + if (command.PlayCommand == PlayCommand.PlayLast) + { + Playlist.AddRange(playlist); + } + if (command.PlayCommand == PlayCommand.PlayNext) + { + Playlist.AddRange(playlist); + } + + _logger.Debug("{0} - Playing {1} items", _session.DeviceName, playlist.Count); + + if (!string.IsNullOrWhiteSpace(command.ControllingUserId)) + { + var userId = new Guid(command.ControllingUserId); + + var user = _userManager.GetUserById(userId); + + await _sessionManager.LogSessionActivity(_session.Client, _session.ApplicationVersion, _session.DeviceId, + _session.DeviceName, _session.RemoteEndPoint, user).ConfigureAwait(false); + } + + await PlayItems(playlist).ConfigureAwait(false); + } + + public Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken) + { + switch (command.Command) + { + case PlaystateCommand.Stop: + Playlist.Clear(); + return _device.SetStop(); + + case PlaystateCommand.Pause: + return _device.SetPause(); + + case PlaystateCommand.Unpause: + 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); + + //} + return _device.Seek(TimeSpan.FromTicks(command.SeekPositionTicks ?? 0)); + + + case PlaystateCommand.NextTrack: + return SetNext(); + + case PlaystateCommand.PreviousTrack: + return SetPrevious(); + } + + return Task.FromResult(true); + } + + public Task SendUserDataChangeInfo(UserDataChangeInfo info, CancellationToken cancellationToken) + { + return Task.FromResult(true); + } + + public Task SendRestartRequiredNotification(CancellationToken cancellationToken) + { + return Task.FromResult(true); + } + + public Task SendServerRestartNotification(CancellationToken cancellationToken) + { + return Task.FromResult(true); + } + + public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) + { + return Task.FromResult(true); + } + + public Task SendPlaybackStartNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) + { + return Task.FromResult(true); + } + + public Task SendPlaybackStoppedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) + { + return Task.FromResult(true); + } + + public Task SendServerShutdownNotification(CancellationToken cancellationToken) + { + return Task.FromResult(true); + } + + public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken) + { + return Task.FromResult(true); + } + + #endregion + + #region Playlist + + private readonly List _playlist = new List(); + private List Playlist + { + get + { + return _playlist; + } + } + + private void AddItemFromId(Guid id, List list) + { + var item = _libraryManager.GetItemById(id); + if (item.IsFolder) + { + foreach (var childId in _itemRepository.GetChildren(item.Id)) + { + AddItemFromId(childId, list); + } + } + else + { + if (item.MediaType == MediaType.Audio || item.MediaType == MediaType.Video) + { + list.Add(item); + } + } + } + + private PlaylistItem CreatePlaylistItem(BaseItem item, long startPostionTicks, string serverAddress) + { + var deviceInfo = _device.Properties; + + var profile = _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification()) ?? + _dlnaManager.GetDefaultProfile(); + + var mediaSources = item is Audio || item is Video + ? _dtoService.GetMediaSources(item) + : new List(); + + var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId); + playlistItem.StreamInfo.StartPositionTicks = startPostionTicks; + + playlistItem.StreamUrl = playlistItem.StreamInfo.ToUrl(serverAddress); + + var itemXml = + new DidlBuilder(profile, _imageProcessor, serverAddress, _dtoService).GetItemDidl(item, _session.DeviceId, + new Filter()); + + playlistItem.Didl = itemXml; + + return playlistItem; + } + + private string GetDlnaHeaders(PlaylistItem item) + { + var profile = item.Profile; + var streamInfo = item.StreamInfo; + + if (streamInfo.MediaType == DlnaProfileType.Audio) + { + return new ContentFeatureBuilder(profile) + .BuildAudioHeader(streamInfo.Container, + streamInfo.AudioCodec, + streamInfo.TargetAudioBitrate, + streamInfo.TargetAudioSampleRate, + streamInfo.TargetAudioChannels, + streamInfo.IsDirectStream, + streamInfo.RunTimeTicks, + streamInfo.TranscodeSeekInfo); + } + + if (streamInfo.MediaType == DlnaProfileType.Video) + { + return new ContentFeatureBuilder(profile) + .BuildVideoHeader(streamInfo.Container, + streamInfo.VideoCodec, + streamInfo.AudioCodec, + streamInfo.TargetWidth, + streamInfo.TargetHeight, + streamInfo.TargetVideoBitDepth, + streamInfo.TargetVideoBitrate, + streamInfo.TargetAudioChannels, + streamInfo.TargetAudioBitrate, + streamInfo.TargetTimestamp, + streamInfo.IsDirectStream, + streamInfo.RunTimeTicks, + streamInfo.TargetVideoProfile, + streamInfo.TargetVideoLevel, + streamInfo.TargetFramerate, + streamInfo.TargetPacketLength, + streamInfo.TranscodeSeekInfo); + } + + return null; + } + + private PlaylistItem GetPlaylistItem(BaseItem item, List mediaSources, DeviceProfile profile, string deviceId) + { + var video = item as Video; + + if (video != null) + { + return new PlaylistItem + { + StreamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions + { + ItemId = item.Id.ToString("N"), + MediaSources = mediaSources, + Profile = profile, + DeviceId = deviceId + }), + + Profile = profile + }; + } + + var audio = item as Audio; + + if (audio != null) + { + return new PlaylistItem + { + StreamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions + { + ItemId = item.Id.ToString("N"), + MediaSources = mediaSources, + Profile = profile, + DeviceId = deviceId + }), + + Profile = profile + }; + } + + var photo = item as Photo; + + if (photo != null) + { + return new PlaylistItemFactory().Create(photo, profile); + } + + throw new ArgumentException("Unrecognized item type."); + } + + /// + /// Plays the items. + /// + /// The items. + /// + private async Task PlayItems(IEnumerable items) + { + Playlist.Clear(); + Playlist.AddRange(items); + await SetNext(); + return true; + } + + private async Task SetNext() + { + if (!Playlist.Any() || Playlist.All(i => i.PlayState != 0)) + { + return; + } + + var currentitem = Playlist.FirstOrDefault(i => i.PlayState == 1); + + if (currentitem != null) + { + currentitem.PlayState = 2; + } + + var nextTrack = Playlist.FirstOrDefault(i => i.PlayState == 0); + if (nextTrack == null) + { + await _device.SetStop(); + return; + } + + nextTrack.PlayState = 1; + + var dlnaheaders = GetDlnaHeaders(nextTrack); + + _logger.Debug("{0} - SetAvTransport Uri: {1} DlnaHeaders: {2}", _device.Properties.Name, nextTrack.StreamUrl, dlnaheaders); + + await _device.SetAvTransport(nextTrack.StreamUrl, dlnaheaders, nextTrack.Didl); + + var streamInfo = nextTrack.StreamInfo; + if (streamInfo.StartPositionTicks > 0 && streamInfo.IsDirectStream) + await _device.Seek(TimeSpan.FromTicks(streamInfo.StartPositionTicks)); + } + + public Task SetPrevious() + { + if (!Playlist.Any() || Playlist.All(i => i.PlayState != 2)) + return Task.FromResult(false); + + var currentitem = Playlist.FirstOrDefault(i => i.PlayState == 1); + + var prevTrack = Playlist.LastOrDefault(i => i.PlayState == 2); + + if (currentitem != null) + { + currentitem.PlayState = 0; + } + + if (prevTrack == null) + return Task.FromResult(false); + + prevTrack.PlayState = 1; + return _device.SetAvTransport(prevTrack.StreamInfo.ToDlnaUrl(GetServerAddress()), GetDlnaHeaders(prevTrack), prevTrack.Didl); + } + + #endregion + + private bool _disposed; + + public void Dispose() + { + if (!_disposed) + { + _disposed = true; + + _device.PlaybackStart -= _device_PlaybackStart; + _device.PlaybackProgress -= _device_PlaybackProgress; + _device.PlaybackStopped -= _device_PlaybackStopped; + _ssdpHandler.MessageReceived -= _SsdpHandler_MessageReceived; + + DisposeUpdateTimer(); + + _device.Dispose(); + } + } + + private void DisposeUpdateTimer() + { + if (_updateTimer != null) + { + _updateTimer.Dispose(); + _updateTimer = null; + } + } + + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + + public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken) + { + GeneralCommandType commandType; + + if (Enum.TryParse(command.Name, true, out commandType)) + { + switch (commandType) + { + case GeneralCommandType.VolumeDown: + return _device.VolumeDown(); + case GeneralCommandType.VolumeUp: + return _device.VolumeUp(); + case GeneralCommandType.Mute: + return _device.Mute(); + case GeneralCommandType.Unmute: + return _device.Unmute(); + case GeneralCommandType.ToggleMute: + return _device.ToggleMute(); + case GeneralCommandType.SetVolume: + { + string volumeArg; + + if (command.Arguments.TryGetValue("Volume", out volumeArg)) + { + int volume; + + if (int.TryParse(volumeArg, NumberStyles.Any, _usCulture, out volume)) + { + return _device.SetVolume(volume); + } + + throw new ArgumentException("Unsupported volume value supplied."); + } + + throw new ArgumentException("Volume argument cannot be null"); + } + default: + return Task.FromResult(true); + } + } + + return Task.FromResult(true); + } + } +} diff --git a/MediaBrowser.Dlna/PlayTo/PlaybackProgressEventArgs.cs b/MediaBrowser.Dlna/PlayTo/PlaybackProgressEventArgs.cs new file mode 100644 index 000000000..104697166 --- /dev/null +++ b/MediaBrowser.Dlna/PlayTo/PlaybackProgressEventArgs.cs @@ -0,0 +1,9 @@ +using System; + +namespace MediaBrowser.Dlna.PlayTo +{ + public class PlaybackProgressEventArgs : EventArgs + { + public uBaseObject MediaInfo { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Dlna/PlayTo/PlaybackStartEventArgs.cs b/MediaBrowser.Dlna/PlayTo/PlaybackStartEventArgs.cs new file mode 100644 index 000000000..772eba55b --- /dev/null +++ b/MediaBrowser.Dlna/PlayTo/PlaybackStartEventArgs.cs @@ -0,0 +1,9 @@ +using System; + +namespace MediaBrowser.Dlna.PlayTo +{ + public class PlaybackStartEventArgs : EventArgs + { + public uBaseObject MediaInfo { get; set; } + } +} diff --git a/MediaBrowser.Dlna/PlayTo/PlaybackStoppedEventArgs.cs b/MediaBrowser.Dlna/PlayTo/PlaybackStoppedEventArgs.cs new file mode 100644 index 000000000..aac08cd6f --- /dev/null +++ b/MediaBrowser.Dlna/PlayTo/PlaybackStoppedEventArgs.cs @@ -0,0 +1,9 @@ +using System; + +namespace MediaBrowser.Dlna.PlayTo +{ + public class PlaybackStoppedEventArgs : EventArgs + { + public uBaseObject MediaInfo { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Dlna/PlayTo/TRANSPORTSTATE.cs b/MediaBrowser.Dlna/PlayTo/TRANSPORTSTATE.cs new file mode 100644 index 000000000..d58c4413c --- /dev/null +++ b/MediaBrowser.Dlna/PlayTo/TRANSPORTSTATE.cs @@ -0,0 +1,11 @@ +namespace MediaBrowser.Dlna.PlayTo +{ + public enum TRANSPORTSTATE + { + STOPPED, + PLAYING, + TRANSITIONING, + PAUSED_PLAYBACK, + PAUSED + } +} \ No newline at end of file diff --git a/MediaBrowser.Dlna/PlayTo/uParser.cs b/MediaBrowser.Dlna/PlayTo/uParser.cs index a9ebd4fb0..838ddfc31 100644 --- a/MediaBrowser.Dlna/PlayTo/uParser.cs +++ b/MediaBrowser.Dlna/PlayTo/uParser.cs @@ -44,9 +44,4 @@ namespace MediaBrowser.Dlna.PlayTo return UpnpContainer.Create(uItem.Element); } } - - public class uParserObject - { - public XElement Element { get; set; } - } } diff --git a/MediaBrowser.Dlna/PlayTo/uParserObject.cs b/MediaBrowser.Dlna/PlayTo/uParserObject.cs new file mode 100644 index 000000000..265ef7f8d --- /dev/null +++ b/MediaBrowser.Dlna/PlayTo/uParserObject.cs @@ -0,0 +1,9 @@ +using System.Xml.Linq; + +namespace MediaBrowser.Dlna.PlayTo +{ + public class uParserObject + { + public XElement Element { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs index 9283f4ba4..409c646d9 100644 --- a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs +++ b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs @@ -19,8 +19,8 @@ namespace MediaBrowser.Dlna.Profiles ModelDescription = "Media Browser"; ModelName = "Media Browser"; ModelNumber = "Media Browser"; - ModelUrl = "http://mediabrowser3.com/"; - ManufacturerUrl = "http://mediabrowser3.com/"; + ModelUrl = "http://mediabrowser.tv/"; + ManufacturerUrl = "http://mediabrowser.tv/"; AlbumArtPn = "JPEG_SM"; diff --git a/MediaBrowser.Dlna/Profiles/Xml/Default.xml b/MediaBrowser.Dlna/Profiles/Xml/Default.xml index f556e8504..f6b52a727 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Default.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Default.xml @@ -3,11 +3,11 @@ Generic Device Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ Media Browser Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ false false Audio,Photo,Video diff --git a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml index 56a55ba02..22df1501d 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml @@ -8,11 +8,11 @@ Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ Media Browser Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ false false Audio,Photo,Video diff --git a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml index f449d5dee..49d45687f 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml @@ -9,11 +9,11 @@ Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ Media Browser Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ false false Audio,Photo,Video diff --git a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml index 9c2fb22e8..5476159f0 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml @@ -7,11 +7,11 @@ Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ Media Browser Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ false false Audio,Photo,Video diff --git a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml index bc661d439..2a54860b6 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml @@ -10,11 +10,11 @@ Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ Media Browser Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ false false Audio,Photo,Video diff --git a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml index 7b281abd1..a35f9b413 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml @@ -9,11 +9,11 @@ Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ Media Browser Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ false true Audio,Photo,Video diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml index 352299e0f..3a7e99eaa 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml @@ -9,11 +9,11 @@ Media Browser Microsoft Corporation - http://mediabrowser3.com/ + http://mediabrowser.tv/ Windows Media Player Sharing Media Browser 3.0 - http://mediabrowser3.com/ + http://mediabrowser.tv/ false false Audio,Photo,Video diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml index af35b5f1a..61b5d1a05 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml @@ -11,11 +11,11 @@ Media Browser Microsoft Corporation - http://mediabrowser3.com/ + http://mediabrowser.tv/ Windows Media Player Sharing Media Browser 3.0 - http://mediabrowser3.com/ + http://mediabrowser.tv/ false false Audio,Photo,Video diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml index f870ac1b4..04768020c 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml @@ -10,11 +10,11 @@ Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ Media Browser Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ false false Audio,Photo,Video diff --git a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml index 3605003e1..5c28c4e38 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml @@ -10,11 +10,11 @@ Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ Media Browser Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ true false Audio,Photo,Video diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml index bbe2d5bcf..fc8d7692d 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml @@ -8,11 +8,11 @@ Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ Media Browser Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ false false Audio,Photo,Video diff --git a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml index 0b7e10c01..1d1b2375e 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml @@ -9,11 +9,11 @@ Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ Media Browser Media Browser Media Browser - http://mediabrowser3.com/ + http://mediabrowser.tv/ false false Audio diff --git a/MediaBrowser.Model/Dlna/CodecProfile.cs b/MediaBrowser.Model/Dlna/CodecProfile.cs index 61eb2f639..3e67b49f9 100644 --- a/MediaBrowser.Model/Dlna/CodecProfile.cs +++ b/MediaBrowser.Model/Dlna/CodecProfile.cs @@ -22,7 +22,12 @@ namespace MediaBrowser.Model.Dlna public List GetCodecs() { - return (Codec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList(); + List list = new List(); + foreach (string i in (Codec ?? string.Empty).Split(',')) + { + if (!string.IsNullOrEmpty(i)) list.Add(i); + } + return list; } public bool ContainsCodec(string codec) diff --git a/MediaBrowser.Model/Dlna/ContainerProfile.cs b/MediaBrowser.Model/Dlna/ContainerProfile.cs index 3a5fe3bd5..931194dd3 100644 --- a/MediaBrowser.Model/Dlna/ContainerProfile.cs +++ b/MediaBrowser.Model/Dlna/ContainerProfile.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using System.Xml.Serialization; namespace MediaBrowser.Model.Dlna @@ -20,7 +19,12 @@ namespace MediaBrowser.Model.Dlna public List GetContainers() { - return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList(); + List list = new List(); + foreach (string i in (Container ?? string.Empty).Split(',')) + { + if (!string.IsNullOrEmpty(i)) list.Add(i); + } + return list; } } } diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index e0b682e4a..2b2453a23 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -105,7 +105,12 @@ namespace MediaBrowser.Model.Dlna public List GetSupportedMediaTypes() { - return (SupportedMediaTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList(); + List list = new List(); + foreach (string i in (SupportedMediaTypes ?? string.Empty).Split(',')) + { + if (!string.IsNullOrEmpty(i)) list.Add(i); + } + return list; } public TranscodingProfile GetAudioTranscodingProfile(string container, string audioCodec) diff --git a/MediaBrowser.Model/Dlna/DirectPlayProfile.cs b/MediaBrowser.Model/Dlna/DirectPlayProfile.cs index 5cfcafca4..183299425 100644 --- a/MediaBrowser.Model/Dlna/DirectPlayProfile.cs +++ b/MediaBrowser.Model/Dlna/DirectPlayProfile.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using System.Xml.Serialization; namespace MediaBrowser.Model.Dlna @@ -20,17 +19,32 @@ namespace MediaBrowser.Model.Dlna public List GetContainers() { - return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList(); + List list = new List(); + foreach (string i in (Container ?? string.Empty).Split(',')) + { + if (!string.IsNullOrEmpty(i)) list.Add(i); + } + return list; } public List GetAudioCodecs() { - return (AudioCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList(); + List list = new List(); + foreach (string i in (AudioCodec ?? string.Empty).Split(',')) + { + if (!string.IsNullOrEmpty(i)) list.Add(i); + } + return list; } public List GetVideoCodecs() { - return (VideoCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList(); + List list = new List(); + foreach (string i in (VideoCodec ?? string.Empty).Split(',')) + { + if (!string.IsNullOrEmpty(i)) list.Add(i); + } + return list; } } } diff --git a/MediaBrowser.Model/Dlna/ResponseProfile.cs b/MediaBrowser.Model/Dlna/ResponseProfile.cs index e84095ffe..c1735f3b7 100644 --- a/MediaBrowser.Model/Dlna/ResponseProfile.cs +++ b/MediaBrowser.Model/Dlna/ResponseProfile.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using System.Xml.Serialization; namespace MediaBrowser.Model.Dlna @@ -33,17 +32,32 @@ namespace MediaBrowser.Model.Dlna public List GetContainers() { - return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList(); + List list = new List(); + foreach (string i in (Container ?? string.Empty).Split(',')) + { + if (!string.IsNullOrEmpty(i)) list.Add(i); + } + return list; } - + public List GetAudioCodecs() { - return (AudioCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList(); + List list = new List(); + foreach (string i in (AudioCodec ?? string.Empty).Split(',')) + { + if (!string.IsNullOrEmpty(i)) list.Add(i); + } + return list; } public List GetVideoCodecs() { - return (VideoCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList(); + List list = new List(); + foreach (string i in (VideoCodec ?? string.Empty).Split(',')) + { + if (!string.IsNullOrEmpty(i)) list.Add(i); + } + return list; } } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 02cee0dce..9acec20aa 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -24,12 +24,17 @@ namespace MediaBrowser.Model.Dlna // Avoid implicitly captured closure string mediaSourceId = options.MediaSourceId; - mediaSources = mediaSources - .Where(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)) - .ToList(); + mediaSources = new List(); + foreach (MediaSourceInfo i in mediaSources) + { + if (string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)) + mediaSources.Add(i); + } } - List streams = mediaSources.Select(i => BuildAudioItem(i, options)).ToList(); + List streams = new List(); + foreach (MediaSourceInfo i in mediaSources) + streams.Add(BuildAudioItem(i, options)); foreach (StreamInfo stream in streams) { @@ -52,12 +57,17 @@ namespace MediaBrowser.Model.Dlna // Avoid implicitly captured closure string mediaSourceId = options.MediaSourceId; - mediaSources = mediaSources - .Where(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)) - .ToList(); + mediaSources = new List(); + foreach (MediaSourceInfo i in mediaSources) + { + if (string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)) + mediaSources.Add(i); + } } - List streams = mediaSources.Select(i => BuildVideoItem(i, options)).ToList(); + List streams = new List(); + foreach (MediaSourceInfo i in mediaSources) + streams.Add(BuildVideoItem(i, options)); foreach (StreamInfo stream in streams) { @@ -72,8 +82,19 @@ namespace MediaBrowser.Model.Dlna { // Grab the first one that can be direct streamed // If that doesn't produce anything, just take the first - return streams.FirstOrDefault(i => i.IsDirectStream) ?? - streams.FirstOrDefault(); + foreach (StreamInfo i in streams) + { + if (i.IsDirectStream) + { + return i; + } + } + + foreach (StreamInfo stream in streams) + { + return stream; + } + return null; } private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options) @@ -191,8 +212,15 @@ namespace MediaBrowser.Model.Dlna } // Can't direct play, find the transcoding profile - TranscodingProfile transcodingProfile = options.Profile.TranscodingProfiles - .FirstOrDefault(i => i.Type == playlistItem.MediaType); + TranscodingProfile transcodingProfile = null; + foreach (TranscodingProfile i in options.Profile.TranscodingProfiles) + { + if (i.Type == playlistItem.MediaType) + { + transcodingProfile = i; + break; + } + } if (transcodingProfile != null) { @@ -200,7 +228,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.Container = transcodingProfile.Container; playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength; playlistItem.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; - playlistItem.AudioCodec = transcodingProfile.AudioCodec.Split(',').FirstOrDefault(); + playlistItem.AudioCodec = transcodingProfile.AudioCodec.Split(',')[0]; playlistItem.VideoCodec = transcodingProfile.VideoCodec; playlistItem.Protocol = transcodingProfile.Protocol; playlistItem.AudioStreamIndex = options.AudioStreamIndex; @@ -261,8 +289,15 @@ namespace MediaBrowser.Model.Dlna MediaStream audioStream) { // See if it can be direct played - DirectPlayProfile directPlay = profile.DirectPlayProfiles - .FirstOrDefault(i => i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream)); + DirectPlayProfile directPlay = null; + foreach (DirectPlayProfile i in profile.DirectPlayProfiles) + { + if (i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream)) + { + directPlay = i; + break; + } + } if (directPlay == null) { diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 9af3689b2..ba3005950 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -1,11 +1,10 @@ using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.MediaInfo; using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; -using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna { @@ -134,14 +133,23 @@ namespace MediaBrowser.Model.Dlna { if (MediaSource != null) { - IEnumerable audioStreams = MediaSource.MediaStreams.Where(i => i.Type == MediaStreamType.Audio); - if (AudioStreamIndex.HasValue) { - return audioStreams.FirstOrDefault(i => i.Index == AudioStreamIndex.Value); + foreach (MediaStream i in MediaSource.MediaStreams) + { + if (i.Index == AudioStreamIndex.Value && i.Type == MediaStreamType.Audio) + return i; + } + return null; + } + + foreach (MediaStream stream in MediaSource.MediaStreams) + { + if (stream.Type == MediaStreamType.Audio) + return stream; } - return audioStreams.FirstOrDefault(); + return null; } return null; @@ -157,8 +165,12 @@ namespace MediaBrowser.Model.Dlna { if (MediaSource != null) { - return MediaSource.MediaStreams - .FirstOrDefault(i => i.Type == MediaStreamType.Video && (i.Codec ?? string.Empty).IndexOf("jpeg", StringComparison.OrdinalIgnoreCase) == -1); + foreach (MediaStream i in MediaSource.MediaStreams) + { + if (i.Type == MediaStreamType.Video && (i.Codec ?? string.Empty).IndexOf("jpeg", StringComparison.OrdinalIgnoreCase) == -1) + return i; + } + return null; } return null; diff --git a/MediaBrowser.Model/Dlna/TranscodingProfile.cs b/MediaBrowser.Model/Dlna/TranscodingProfile.cs index 162d62718..bee5f2a69 100644 --- a/MediaBrowser.Model/Dlna/TranscodingProfile.cs +++ b/MediaBrowser.Model/Dlna/TranscodingProfile.cs @@ -35,7 +35,12 @@ namespace MediaBrowser.Model.Dlna public List GetAudioCodecs() { - return (AudioCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList(); + List list = new List(); + foreach (string i in (AudioCodec ?? string.Empty).Split(',')) + { + if (!string.IsNullOrEmpty(i)) list.Add(i); + } + return list; } } } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index 9d2de0f6d..7607ec98a 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -138,7 +138,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications var notification = new NotificationRequest { - Description = "Please see mediabrowser3.com for details.", + Description = "Please see mediabrowser.tv for details.", NotificationType = type }; diff --git a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs index 39beee563..77a543ad7 100644 --- a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs +++ b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs @@ -45,7 +45,7 @@ namespace MediaBrowser.ServerApplication.Native /// The logger. public static void OpenCommunity(ILogger logger) { - OpenUrl("http://mediabrowser3.com/community", logger); + OpenUrl("http://mediabrowser.tv/community", logger); } /// -- cgit v1.2.3