From b747db6b93695fe89089c2756e41d536af02095f Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Thu, 13 Dec 2012 13:52:54 -0800 Subject: [PATCH] Version number parsing for XBMC Frodo --- NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 1 + .../ProviderTests/XbmcProviderTest.cs | 32 +++-- NzbDrone.Core.Test/XbmcVersionTests.cs | 94 +++++++++++++ NzbDrone.Core/Model/Xbmc/XbmcJsonResult.cs | 14 ++ NzbDrone.Core/Model/Xbmc/XbmcVersion.cs | 123 ++++++++++++++++++ NzbDrone.Core/NzbDrone.Core.csproj | 2 + NzbDrone.Core/Providers/XbmcProvider.cs | 49 +++++-- 7 files changed, 295 insertions(+), 20 deletions(-) create mode 100644 NzbDrone.Core.Test/XbmcVersionTests.cs create mode 100644 NzbDrone.Core/Model/Xbmc/XbmcJsonResult.cs create mode 100644 NzbDrone.Core/Model/Xbmc/XbmcVersion.cs diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 27be2f100..01459ee65 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -241,6 +241,7 @@ + diff --git a/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs index 79a96ab33..dc3692270 100644 --- a/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/XbmcProviderTest.cs @@ -93,11 +93,8 @@ namespace NzbDrone.Core.Test.ProviderTests [TestCase(3)] [TestCase(2)] [TestCase(0)] - public void GetJsonVersion(int number) + public void GetJsonVersionIntOnly(int number) { - //Setup - - var message = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"version\":" + number + "}}"; var fakeHttp = Mocker.GetMock(); @@ -108,15 +105,32 @@ namespace NzbDrone.Core.Test.ProviderTests var result = Mocker.Resolve().GetJsonVersion("localhost:8080", "xbmc", "xbmc"); //Assert - Assert.AreEqual(number, result); + result.Should().Be(new XbmcVersion(number)); + } + + [TestCase(5, 0, 0)] + [TestCase(6, 0, 0)] + [TestCase(6, 1, 0)] + [TestCase(6, 0, 23)] + [TestCase(0, 0, 0)] + public void GetJsonVersionFrodo(int major, int minor, int patch) + { + var message = "{\"id\":10,\"jsonrpc\":\"2.0\",\"result\":{\"version\":{\"major\":" + major + ",\"minor\":" + minor + ",\"patch\":" + patch + "}}}"; + + var fakeHttp = Mocker.GetMock(); + fakeHttp.Setup(s => s.PostCommand("localhost:8080", "xbmc", "xbmc", It.IsAny())) + .Returns(message); + + //Act + var result = Mocker.Resolve().GetJsonVersion("localhost:8080", "xbmc", "xbmc"); + + //Assert + result.Should().Be(new XbmcVersion(major, minor, patch)); } [Test] public void GetJsonVersion_error() { - //Setup - - var message = "{\"error\":{\"code\":-32601,\"message\":\"Method not found.\"},\"id\":10,\"jsonrpc\":\"2.0\"}"; var fakeHttp = Mocker.GetMock(); @@ -127,7 +141,7 @@ namespace NzbDrone.Core.Test.ProviderTests var result = Mocker.Resolve().GetJsonVersion("localhost:8080", "xbmc", "xbmc"); //Assert - Assert.AreEqual(0, result); + result.Should().Be(new XbmcVersion(0)); } [TestCase(false, false, false)] diff --git a/NzbDrone.Core.Test/XbmcVersionTests.cs b/NzbDrone.Core.Test/XbmcVersionTests.cs new file mode 100644 index 000000000..65b986400 --- /dev/null +++ b/NzbDrone.Core.Test/XbmcVersionTests.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Model.Xbmc; +using NzbDrone.Core.Repository.Quality; + +namespace NzbDrone.Core.Test +{ + public class XbmcVersionTests + { + [TestCase(6, 0, 0)] + [TestCase(5, 1, 0)] + [TestCase(5, 0, 1)] + public void Icomparer_greater_test(int major, int minor, int patch) + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(major, minor, patch); + + second.Should().BeGreaterThan(first); + } + + [TestCase(4, 5, 5)] + [TestCase(5, 4, 5)] + [TestCase(5, 5, 4)] + public void Icomparer_lesser_test(int major, int minor, int patch) + { + var first = new XbmcVersion(5, 5, 5); + var second = new XbmcVersion(major, minor, patch); + + second.Should().BeLessThan(first); + } + + [Test] + public void equal_operand() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(5, 0, 0); + + (first == second).Should().BeTrue(); + (first >= second).Should().BeTrue(); + (first <= second).Should().BeTrue(); + } + + [Test] + public void equal_operand_false() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(6, 0, 0); + + (first == second).Should().BeFalse(); + } + + [Test] + public void not_equal_operand_false() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(5, 0, 0); + + (first != second).Should().BeFalse(); + } + + [Test] + public void not_equal_operand_true() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(6, 0, 0); + + (first != second).Should().BeTrue(); + } + + [Test] + public void greater_operand() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(6, 0, 0); + + (first < second).Should().BeTrue(); + (first <= second).Should().BeTrue(); + } + + [Test] + public void lesser_operand() + { + var first = new XbmcVersion(5, 0, 0); + var second = new XbmcVersion(6, 0, 0); + + (second > first).Should().BeTrue(); + (second >= first).Should().BeTrue(); + } + } +} diff --git a/NzbDrone.Core/Model/Xbmc/XbmcJsonResult.cs b/NzbDrone.Core/Model/Xbmc/XbmcJsonResult.cs new file mode 100644 index 000000000..be4ed1d88 --- /dev/null +++ b/NzbDrone.Core/Model/Xbmc/XbmcJsonResult.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Model.Xbmc +{ + public class XbmcJsonResult + { + public string Id { get; set; } + public string JsonRpc { get; set; } + public T Result { get; set; } + } +} diff --git a/NzbDrone.Core/Model/Xbmc/XbmcVersion.cs b/NzbDrone.Core/Model/Xbmc/XbmcVersion.cs new file mode 100644 index 000000000..b5ad93ead --- /dev/null +++ b/NzbDrone.Core/Model/Xbmc/XbmcVersion.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Model.Xbmc +{ + public class XbmcVersion : IComparable + { + public XbmcVersion() + { + } + + public XbmcVersion(int major) + { + Major = major; + } + + public XbmcVersion(int major, int minor, int patch) + { + Major = major; + Minor = minor; + Patch = patch; + } + + public int Major { get; set; } + public int Minor { get; set; } + public int Patch { get; set; } + + public int CompareTo(XbmcVersion other) + { + if(other.Major > Major) + return -1; + + if(other.Major < Major) + return 1; + + if (other.Minor > Minor) + return -1; + + if (other.Minor < Minor) + return 1; + + if (other.Patch > Patch) + return -1; + + if (other.Patch < Patch) + return 1; + + return 0; + } + + public static bool operator !=(XbmcVersion x, XbmcVersion y) + { + return !(x == y); + } + + public static bool operator ==(XbmcVersion x, XbmcVersion y) + { + var xObj = (Object)x; + var yObj = (object)y; + + if (xObj == null || yObj == null) + { + return xObj == yObj; + } + + return x.CompareTo(y) == 0; + } + + public static bool operator >(XbmcVersion x, XbmcVersion y) + { + return x.CompareTo(y) > 0; + } + + public static bool operator <(XbmcVersion x, XbmcVersion y) + { + return x.CompareTo(y) < 0; + } + + public static bool operator <=(XbmcVersion x, XbmcVersion y) + { + return x.CompareTo(y) <= 0; + } + + public static bool operator >=(XbmcVersion x, XbmcVersion y) + { + return x.CompareTo(y) >= 0; + } + + public override string ToString() + { + return String.Format("{0}.{1}.{2}", Major, Minor, Patch); + } + + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hash = 17; + hash = hash * 23 + Major.GetHashCode(); + hash = hash * 23 + Minor.GetHashCode(); + hash = hash * 23 + Patch.GetHashCode(); + return hash; + } + } + + public bool Equals(XbmcVersion other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return (Equals(other.Major, Major) && Equals(other.Minor, Minor) && Equals(other.Patch, Patch)); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != typeof(XbmcVersion)) return false; + return Equals((XbmcVersion)obj); + } + } +} diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index c1f0181e6..360b57ed2 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -299,6 +299,8 @@ + + diff --git a/NzbDrone.Core/Providers/XbmcProvider.cs b/NzbDrone.Core/Providers/XbmcProvider.cs index 6e7f6e867..c4cc4aa8d 100644 --- a/NzbDrone.Core/Providers/XbmcProvider.cs +++ b/NzbDrone.Core/Providers/XbmcProvider.cs @@ -60,7 +60,7 @@ namespace NzbDrone.Core.Providers var version = GetJsonVersion(host, username, password); //If Dharma - if (version == 2) + if (version == new XbmcVersion(2)) { //Check for active player only when we should skip updates when playing if (!_configProvider.XbmcUpdateWhenPlaying) @@ -80,7 +80,7 @@ namespace NzbDrone.Core.Providers } //If Eden or newer (attempting to make it future compatible) - else if (version >= 3) + else if (version == new XbmcVersion(3) || version == new XbmcVersion(4)) { //Check for active player only when we should skip updates when playing if (!_configProvider.XbmcUpdateWhenPlaying) @@ -99,6 +99,25 @@ namespace NzbDrone.Core.Providers UpdateWithJson(series, host, username, password); } + else if (version >= new XbmcVersion(5)) + { + //Check for active player only when we should skip updates when playing + if (!_configProvider.XbmcUpdateWhenPlaying) + { + 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, host, username, password); + } + //Log Version zero if check failed else Logger.Trace("Unknown version: [{0}], skipping.", version); @@ -239,12 +258,11 @@ namespace NzbDrone.Core.Providers return field.Value; } - public virtual int GetJsonVersion(string host, string username, string password) + public virtual XbmcVersion GetJsonVersion(string host, string username, string password) { //2 = Dharma - //3 = Eden/Nightly (as of July 2011) - - var version = 0; + //3 & 4 = Eden + //5 & 6 = Frodo try { @@ -256,11 +274,20 @@ namespace NzbDrone.Core.Providers var response = _httpProvider.PostCommand(host, username, password, postJson.ToString()); if (CheckForJsonError(response)) - return version; + return new XbmcVersion(); Logger.Trace("Getting version from response"); - var result = JsonConvert.DeserializeObject(response); - result.Result.TryGetValue("version", out version); + var result = JsonConvert.DeserializeObject>(response); + + var versionObject = result.Result.Property("version"); + + if (versionObject.Value.Type == JTokenType.Integer) + return new XbmcVersion((int)versionObject.Value); + + if(versionObject.Value.Type == JTokenType.Object) + return JsonConvert.DeserializeObject(versionObject.Value.ToString()); + + throw new InvalidCastException("Unknown Version structure!: " + versionObject); } catch (Exception ex) @@ -268,7 +295,7 @@ namespace NzbDrone.Core.Providers Logger.DebugException(ex.Message, ex); } - return version; + return new XbmcVersion(); } public virtual Dictionary GetActivePlayersDharma(string host, string username, string password) @@ -391,7 +418,7 @@ namespace NzbDrone.Core.Providers { Logger.Trace("Sending Test Notifcation to XBMC Host: {0}", host); var version = GetJsonVersion(host, username, password); - if (version == 0) + if (version == new XbmcVersion()) throw new Exception("Failed to get JSON version in test"); } }