diff --git a/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs index 2672bd049..ea9c049ec 100644 --- a/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs @@ -1,7 +1,7 @@ // ReSharper disable RedundantUsingDirective using System; - +using System.Linq; using FizzWare.NBuilder; using FluentAssertions; using Moq; @@ -20,6 +20,33 @@ namespace NzbDrone.Core.Test.ProviderTests // ReSharper disable InconsistentNaming public class XbmcProviderTest : CoreTest { + private string EdenActivePlayers; + + private void WithNoActivePlayers() + { + EdenActivePlayers = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[]}"; + } + + private void WithVideoPlayerActive() + { + EdenActivePlayers = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"video\"}]}"; + } + + private void WithAudioPlayerActive() + { + EdenActivePlayers = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"audio\"}]}"; + } + + private void WithPicturePlayerActive() + { + EdenActivePlayers = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"picture\"}]}"; + } + + private void WithAllPlayersActive() + { + EdenActivePlayers = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":[{\"playerid\":1,\"type\":\"audio\"},{\"playerid\":2,\"type\":\"picture\"},{\"playerid\":3,\"type\":\"video\"}]}"; + } + [Test] public void JsonError_true() { @@ -110,11 +137,9 @@ namespace NzbDrone.Core.Test.ProviderTests [TestCase(false, true, true)] [TestCase(false, false, true)] [TestCase(true, false, true)] - public void GetActivePlayers(bool audio, bool picture, bool video) + public void GetActivePlayersDharma(bool audio, bool picture, bool video) { //Setup - - var message = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"audio\":" + audio.ToString().ToLower() + ",\"picture\":" @@ -128,7 +153,7 @@ namespace NzbDrone.Core.Test.ProviderTests .Returns(message); //Act - var result = Mocker.Resolve().GetActivePlayers("localhost:8080", "xbmc", "xbmc"); + var result = Mocker.Resolve().GetActivePlayersDharma("localhost:8080", "xbmc", "xbmc"); //Assert Assert.AreEqual(audio, result["audio"]); @@ -136,6 +161,96 @@ namespace NzbDrone.Core.Test.ProviderTests Assert.AreEqual(video, result["video"]); } + [Test] + public void GetActivePlayersEden_should_be_empty_when_no_active_players() + { + //Setup + WithNoActivePlayers(); + + var fakeHttp = Mocker.GetMock(); + fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny())) + .Returns(EdenActivePlayers); + + //Act + var result = Mocker.Resolve().GetActivePlayersEden("localhost:8080", "xbmc", "xbmc"); + + //Assert + result.Should().BeEmpty(); + } + + [Test] + public void GetActivePlayersEden_should_have_active_video_player() + { + //Setup + WithVideoPlayerActive(); + + var fakeHttp = Mocker.GetMock(); + fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny())) + .Returns(EdenActivePlayers); + + //Act + var result = Mocker.Resolve().GetActivePlayersEden("localhost:8080", "xbmc", "xbmc"); + + //Assert + result.Should().HaveCount(1); + result.First().Type.Should().Be("video"); + } + + [Test] + public void GetActivePlayersEden_should_have_active_audio_player() + { + //Setup + WithAudioPlayerActive(); + + var fakeHttp = Mocker.GetMock(); + fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny())) + .Returns(EdenActivePlayers); + + //Act + var result = Mocker.Resolve().GetActivePlayersEden("localhost:8080", "xbmc", "xbmc"); + + //Assert + result.Should().HaveCount(1); + result.First().Type.Should().Be("audio"); + } + + [Test] + public void GetActivePlayersEden_should_have_active_picture_player() + { + //Setup + WithPicturePlayerActive(); + + var fakeHttp = Mocker.GetMock(); + fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny())) + .Returns(EdenActivePlayers); + + //Act + var result = Mocker.Resolve().GetActivePlayersEden("localhost:8080", "xbmc", "xbmc"); + + //Assert + result.Should().HaveCount(1); + result.First().Type.Should().Be("picture"); + } + + [Test] + public void GetActivePlayersEden_should_have_all_players_active() + { + //Setup + WithAllPlayersActive(); + + var fakeHttp = Mocker.GetMock(); + fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny())) + .Returns(EdenActivePlayers); + + //Act + var result = Mocker.Resolve().GetActivePlayersEden("localhost:8080", "xbmc", "xbmc"); + + //Assert + result.Should().HaveCount(3); + result.Select(a => a.PlayerId).Distinct().Should().HaveCount(3); + result.Select(a => a.Type).Distinct().Should().HaveCount(3); + } + [Test] public void GetTvShowsJson() { diff --git a/NzbDrone.Core/Model/Xbmc/ActivePlayersResult.cs b/NzbDrone.Core/Model/Xbmc/ActivePlayersDharmaResult.cs similarity index 86% rename from NzbDrone.Core/Model/Xbmc/ActivePlayersResult.cs rename to NzbDrone.Core/Model/Xbmc/ActivePlayersDharmaResult.cs index 5c00c296b..df91f0083 100644 --- a/NzbDrone.Core/Model/Xbmc/ActivePlayersResult.cs +++ b/NzbDrone.Core/Model/Xbmc/ActivePlayersDharmaResult.cs @@ -4,7 +4,7 @@ using System.Text; namespace NzbDrone.Core.Model.Xbmc { - public class ActivePlayersResult + public class ActivePlayersDharmaResult { public string Id { get; set; } public string JsonRpc { get; set; } diff --git a/NzbDrone.Core/Model/Xbmc/ActivePlayersEdenResult.cs b/NzbDrone.Core/Model/Xbmc/ActivePlayersEdenResult.cs new file mode 100644 index 000000000..af4a4c7f8 --- /dev/null +++ b/NzbDrone.Core/Model/Xbmc/ActivePlayersEdenResult.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NzbDrone.Core.Model.Xbmc +{ + public class ActivePlayersEdenResult + { + public string Id { get; set; } + public string JsonRpc { get; set; } + public List Result { get; set; } + } + + public class ActivePlayer + { + public int PlayerId { get; set; } + public string Type { get; set; } + } +} diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 6284fe3b4..2368aec7c 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -232,7 +232,8 @@ - + + diff --git a/NzbDrone.Core/Providers/XbmcProvider.cs b/NzbDrone.Core/Providers/XbmcProvider.cs index 76de9579f..0bcbf0784 100644 --- a/NzbDrone.Core/Providers/XbmcProvider.cs +++ b/NzbDrone.Core/Providers/XbmcProvider.cs @@ -56,25 +56,39 @@ namespace NzbDrone.Core.Providers Logger.Trace("Determining version of XBMC Host: {0}", host); var version = GetJsonVersion(host, username, password); - Logger.Trace("Determining if there are any active players on XBMC host: {0}", host); - var activePlayers = GetActivePlayers(host, username, password); - - //If video is currently playing, then skip update - if (activePlayers["video"]) - { - Logger.Debug("Video is currently playing, skipping library update"); - continue; - } - Logger.Trace("No video playing, proceeding with library update"); //If Dharma if (version == 2) + { + Logger.Trace("Determining if there are any active players on XBMC host: {0}", host); + var activePlayers = GetActivePlayersDharma(host, username, password); + + //If video is currently playing, then skip update + if (activePlayers["video"]) + { + Logger.Debug("Video is currently playing, skipping library update"); + continue; + } + UpdateWithHttp(series, host, username, password); + } //If Eden or newer (attempting to make it future compatible) else if (version >= 3) + { + Logger.Trace("Determining if there are any active players on XBMC host: {0}", host); + var activePlayers = GetActivePlayersEden(host, username, password); + + //If video is currently playing, then skip update + if (activePlayers.Any(a => a.Type.Equals("video"))) + { + Logger.Debug("Video is currently playing, skipping library update"); + continue; + } + UpdateWithJson(series, password, host, username); + } } } @@ -231,11 +245,8 @@ namespace NzbDrone.Core.Providers return version; } - public virtual Dictionary GetActivePlayers(string host, string username, string password) + public virtual Dictionary GetActivePlayersDharma(string host, string username, string password) { - //2 = Dharma - //3 = Eden/Nightly (as of July 2011) - try { var command = new Command { id = 10, method = "Player.GetActivePlayers" }; @@ -246,7 +257,32 @@ namespace NzbDrone.Core.Providers if (CheckForJsonError(response)) return null; - var result = serializer.Deserialize(response); + var result = serializer.Deserialize(response); + + return result.Result; + } + + catch (Exception ex) + { + Logger.DebugException(ex.Message, ex); + } + + return null; + } + + public virtual List GetActivePlayersEden(string host, string username, string password) + { + try + { + var command = new Command { id = 10, method = "Player.GetActivePlayers" }; + var serializer = new JavaScriptSerializer(); + var serialized = serializer.Serialize(command); + var response = _httpProvider.PostCommand(host, username, password, serialized); + + if (CheckForJsonError(response)) + return null; + + var result = serializer.Deserialize(response); return result.Result; }