jsonrpc: add support for reading and writing settings
authormontellese <montellese@xbmc.org>
Fri, 25 Oct 2013 14:39:05 +0000 (16:39 +0200)
committermontellese <montellese@xbmc.org>
Mon, 11 Nov 2013 19:33:18 +0000 (20:33 +0100)
addons/xbmc.json/addon.xml
xbmc/interfaces/json-rpc/JSONServiceDescription.cpp
xbmc/interfaces/json-rpc/Makefile
xbmc/interfaces/json-rpc/ServiceDescription.h
xbmc/interfaces/json-rpc/SettingsOperations.cpp [new file with mode: 0644]
xbmc/interfaces/json-rpc/SettingsOperations.h [new file with mode: 0644]
xbmc/interfaces/json-rpc/methods.json
xbmc/interfaces/json-rpc/types.json

index 6886782..a1088af 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<addon id="xbmc.json" version="6.12.0" provider-name="Team XBMC">
+<addon id="xbmc.json" version="6.13.0" provider-name="Team XBMC">
   <backwards-compatibility abi="6.0.0"/>
   <requires>
     <import addon="xbmc.core" version="0.1.0"/>
index 247cd29..e6bccb2 100644 (file)
@@ -39,6 +39,7 @@
 #include "ProfilesOperations.h"
 #include "FavouritesOperations.h"
 #include "TextureOperations.h"
+#include "SettingsOperations.h"
 
 using namespace std;
 using namespace JSONRPC;
@@ -214,6 +215,14 @@ JsonRpcMethodMap CJSONServiceDescription::m_methodMaps[] = {
   { "Textures.GetTextures",                         CTextureOperations::GetTextures },
   { "Textures.RemoveTexture",                       CTextureOperations::RemoveTexture },
 
+// Settings operations
+  { "Settings.GetSections",                         CSettingsOperations::GetSections },
+  { "Settings.GetCategories",                       CSettingsOperations::GetCategories },
+  { "Settings.GetSettings",                         CSettingsOperations::GetSettings },
+  { "Settings.GetSettingValue",                     CSettingsOperations::GetSettingValue },
+  { "Settings.SetSettingValue",                     CSettingsOperations::SetSettingValue },
+  { "Settings.ResetSettingValue",                   CSettingsOperations::ResetSettingValue },
+
 // XBMC operations
   { "XBMC.GetInfoLabels",                           CXBMCOperations::GetInfoLabels },
   { "XBMC.GetInfoBooleans",                         CXBMCOperations::GetInfoBooleans }
index a44307a..21d472c 100644 (file)
@@ -12,6 +12,7 @@ SRCS=AddonsOperations.cpp \
      PlaylistOperations.cpp \
      ProfilesOperations.cpp \
      PVROperations.cpp \
+     SettingsOperations.cpp \
      SystemOperations.cpp \
      TextureOperations.cpp \
      VideoLibrary.cpp \
index 07ba88c..59d7708 100644 (file)
@@ -22,7 +22,7 @@
 namespace JSONRPC
 {
   const char* const JSONRPC_SERVICE_ID          = "http://xbmc.org/jsonrpc/ServiceDescription.json";
-  const char* const JSONRPC_SERVICE_VERSION     = "6.12.1";
+  const char* const JSONRPC_SERVICE_VERSION     = "6.13.0";
   const char* const JSONRPC_SERVICE_DESCRIPTION = "JSON-RPC API of XBMC";
 
   const char* const JSONRPC_SERVICE_TYPES[] = {  
@@ -1388,6 +1388,251 @@ namespace JSONRPC
         "\"thumbnail\": { \"type\": \"string\" }"
       "},"
       "\"additionalProperties\": false"
+    "}",
+    "\"Setting.Type\": {"
+      "\"type\": \"string\","
+      "\"enum\": ["
+        "\"boolean\", \"integer\", \"number\", \"string\", \"action\", \"list\","
+        "\"path\", \"addon\""
+      "]"
+    "}",
+    "\"Setting.Level\": {"
+      "\"type\": \"string\","
+      "\"enum\": [ \"basic\", \"standard\", \"advanced\", \"expert\" ]"
+    "}",
+    "\"Setting.Value\": {"
+      "\"type\": ["
+        "{ \"type\": \"boolean\", \"required\": true },"
+        "{ \"type\": \"integer\", \"required\": true },"
+        "{ \"type\": \"number\", \"required\": true },"
+        "{ \"type\": \"string\", \"required\": true }"
+      "]"
+    "}",
+    "\"Setting.Value.List\": {"
+      "\"type\": \"array\","
+      "\"items\": { \"$ref\": \"Setting.Value\" }"
+    "}",
+    "\"Setting.Value.Extended\": {"
+      "\"type\": ["
+        "{ \"type\": \"boolean\", \"required\": true },"
+        "{ \"type\": \"integer\", \"required\": true },"
+        "{ \"type\": \"number\", \"required\": true },"
+        "{ \"type\": \"string\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Value.List\", \"required\": true }"
+      "]"
+    "}",
+    "\"Setting.Details.ControlBase\": {"
+      "\"type\": \"object\","
+      "\"properties\": {"
+        "\"type\": { \"type\": \"string\", \"required\": true },"
+        "\"format\": { \"type\": \"string\", \"required\": true },"
+        "\"delayed\": { \"type\": \"boolean\", \"required\": true }"
+      "}"
+    "}",
+    "\"Setting.Details.ControlCheckmark\": {"
+      "\"extends\": \"Setting.Details.ControlBase\","
+      "\"properties\": {"
+        "\"type\": { \"type\": \"string\", \"required\": true, \"enum\": [ \"toggle\" ] },"
+        "\"format\": { \"type\": \"string\", \"required\": true, \"enum\": [ \"boolean\" ] }"
+      "}"
+    "}",
+    "\"Setting.Details.ControlSpinner\": {"
+      "\"extends\": \"Setting.Details.ControlBase\","
+      "\"properties\": {"
+        "\"type\": { \"type\": \"string\", \"required\": true, \"enum\": [ \"spinner\" ] },"
+        "\"formatlabel\": { \"type\": \"string\" },"
+        "\"minimumlabel\": { \"type\": \"string\" }"
+      "}"
+    "}",
+    "\"Setting.Details.ControlHeading\": {"
+      "\"extends\": \"Setting.Details.ControlBase\","
+      "\"properties\": {"
+        "\"heading\": { \"type\": \"string\" }"
+      "}"
+    "}",
+    "\"Setting.Details.ControlEdit\": {"
+      "\"extends\": \"Setting.Details.ControlHeading\","
+      "\"properties\": {"
+        "\"type\": { \"type\": \"string\", \"required\": true, \"enum\": [ \"edit\" ] },"
+        "\"hidden\": { \"type\": \"boolean\", \"required\": true },"
+        "\"verifynewvalue\": { \"type\": \"boolean\", \"required\": true }"
+      "}"
+    "}",
+    "\"Setting.Details.ControlButton\": {"
+      "\"extends\": \"Setting.Details.ControlHeading\","
+      "\"properties\": {"
+        "\"type\": { \"type\": \"string\", \"required\": true, \"enum\": [ \"button\" ] }"
+      "}"
+    "}",
+    "\"Setting.Details.ControlList\": {"
+      "\"extends\": \"Setting.Details.ControlHeading\","
+      "\"properties\": {"
+        "\"type\": { \"type\": \"string\", \"required\": true, \"enum\": [ \"list\" ] },"
+        "\"multiselect\": { \"type\": \"boolean\", \"required\": true }"
+      "}"
+    "}",
+    "\"Setting.Details.Control\": {"
+      "\"type\": ["
+        "{ \"$ref\": \"Setting.Details.ControlCheckmark\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Details.ControlSpinner\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Details.ControlEdit\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Details.ControlButton\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Details.ControlList\", \"required\": true }"
+      "]"
+    "}",
+    "\"Setting.Details.Base\": {"
+      "\"type\": \"object\","
+      "\"properties\": {"
+        "\"id\": { \"type\": \"string\", \"required\": true, \"minLength\": 1 },"
+        "\"label\": { \"type\": \"string\", \"required\": true },"
+        "\"help\": { \"type\": \"string\" }"
+      "}"
+    "}",
+    "\"Setting.Details.SettingBase\": {"
+      "\"extends\": \"Setting.Details.Base\","
+      "\"properties\": {"
+        "\"type\": { \"$ref\": \"Setting.Type\", \"required\": true },"
+        "\"enabled\": { \"type\": \"boolean\", \"required\": true },"
+        "\"level\": { \"type\": \"integer\", \"required\": true },"
+        "\"parent\": { \"type\": \"string\" },"
+        "\"control\": { \"$ref\": \"Setting.Details.Control\" }"
+      "},"
+      "\"additionalProperties\": false"
+    "}",
+    "\"Setting.Details.SettingBool\": {"
+      "\"extends\": \"Setting.Details.SettingBase\","
+      "\"properties\": {"
+        "\"value\": { \"type\": \"boolean\", \"required\": true },"
+        "\"default\": { \"type\": \"boolean\", \"required\": true }"
+      "},"
+      "\"additionalProperties\": false"
+    "}",
+    "\"Setting.Details.SettingInt\": {"
+      "\"extends\": \"Setting.Details.SettingBase\","
+      "\"properties\": {"
+        "\"value\": { \"type\": \"integer\", \"required\": true },"
+        "\"default\": { \"type\": \"integer\", \"required\": true },"
+        "\"minimum\": { \"type\": \"integer\" },"
+        "\"step\": { \"type\": \"integer\" },"
+        "\"maximum\": { \"type\": \"integer\" },"
+        "\"options\": { \"type\": \"array\","
+          "\"items\": { \"type\": \"object\","
+            "\"properties\": {"
+              "\"label\": { \"type\": \"string\", \"required\": true },"
+              "\"value\": { \"type\": \"integer\", \"required\": true }"
+            "}"
+          "}"
+        "}"
+      "},"
+      "\"additionalProperties\": false"
+    "}",
+    "\"Setting.Details.SettingNumber\": {"
+      "\"extends\": \"Setting.Details.SettingBase\","
+      "\"properties\": {"
+        "\"value\": { \"type\": \"number\", \"required\": true },"
+        "\"default\": { \"type\": \"number\", \"required\": true },"
+        "\"minimum\": { \"type\": \"number\", \"required\": true },"
+        "\"step\": { \"type\": \"number\", \"required\": true },"
+        "\"maximum\": { \"type\": \"number\", \"required\": true }"
+      "},"
+      "\"additionalProperties\": false"
+    "}",
+    "\"Setting.Details.SettingString\": {"
+      "\"extends\": \"Setting.Details.SettingBase\","
+      "\"properties\": {"
+        "\"value\": { \"type\": \"string\", \"required\": true },"
+        "\"default\": { \"type\": \"string\", \"required\": true },"
+        "\"allowempty\": { \"type\": \"boolean\", \"required\": true },"
+        "\"options\": { \"type\": \"array\","
+          "\"items\": { \"type\": \"object\","
+            "\"properties\": {"
+              "\"label\": { \"type\": \"string\", \"required\": true },"
+              "\"value\": { \"type\": \"string\", \"required\": true }"
+            "}"
+          "}"
+        "}"
+      "}"
+    "}",
+    "\"Setting.Details.SettingAction\": {"
+      "\"extends\": \"Setting.Details.SettingBase\","
+      "\"additionalProperties\": false"
+    "}",
+    "\"Setting.Details.SettingList\": {"
+      "\"extends\": \"Setting.Details.SettingBase\","
+      "\"properties\": {"
+        "\"value\": { \"$ref\": \"Setting.Value.List\", \"required\": true },"
+        "\"default\": { \"$ref\": \"Setting.Value.List\", \"required\": true },"
+        "\"elementtype\": { \"$ref\": \"Setting.Type\", \"required\": true },"
+        "\"definition\": { \"$ref\": \"Setting.Details.Setting\", \"required\": true },"
+        "\"delimiter\": { \"type\": \"string\", \"required\": true },"
+        "\"minimum\": { \"type\": \"integer\" },"
+        "\"maximum\": { \"type\": \"integer\" }"
+      "},"
+      "\"additionalProperties\": false"
+    "}",
+    "\"Setting.Details.SettingPath\": {"
+      "\"extends\": \"Setting.Details.SettingString\","
+      "\"properties\": {"
+        "\"writable\": { \"type\": \"boolean\", \"required\": true },"
+        "\"sources\": { \"type\": \"array\", \"items\": { \"type\": \"string\" } }"
+      "},"
+      "\"additionalProperties\": false"
+    "}",
+    "\"Setting.Details.SettingAddon\": {"
+      "\"extends\": \"Setting.Details.SettingString\","
+      "\"properties\": {"
+        "\"addontype\": { \"$ref\": \"Addon.Types\", \"required\": true }"
+      "},"
+      "\"additionalProperties\": false"
+    "}",
+    "\"Setting.Details.Setting\": {"
+      "\"type\": ["
+        "{ \"$ref\": \"Setting.Details.SettingBool\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Details.SettingInt\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Details.SettingNumber\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Details.SettingString\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Details.SettingAction\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Details.SettingList\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Details.SettingPath\", \"required\": true },"
+        "{ \"$ref\": \"Setting.Details.SettingAddon\", \"required\": true }"
+      "]"
+    "}",
+    "\"Setting.Details.Group\": {"
+      "\"type\": \"object\","
+      "\"properties\": {"
+        "\"id\": { \"type\": \"string\", \"required\": true, \"minLength\": 1 },"
+        "\"settings\": {"
+          "\"type\": \"array\","
+          "\"items\": { \"$ref\": \"Setting.Details.Setting\" },"
+          "\"minItems\": 1,"
+          "\"uniqueItems\": true"
+        "}"
+      "},"
+      "\"additionalProperties\": false"
+    "}",
+    "\"Setting.Details.Category\": {"
+      "\"extends\": \"Setting.Details.Base\","
+      "\"properties\": {"
+        "\"groups\": {"
+          "\"type\": \"array\","
+          "\"items\": { \"$ref\": \"Setting.Details.Group\" },"
+          "\"minItems\": 1,"
+          "\"uniqueItems\": true"
+        "}"
+      "},"
+      "\"additionalProperties\": false"
+    "}",
+    "\"Setting.Details.Section\": {"
+      "\"extends\": \"Setting.Details.Base\","
+      "\"properties\": {"
+        "\"categories\": {"
+          "\"type\": \"array\","
+          "\"items\": { \"$ref\": \"Setting.Details.Category\" },"
+          "\"minItems\": 1,"
+          "\"uniqueItems\": true"
+        "}"
+      "},"
+      "\"additionalProperties\": false"
     "}"
   };
 
@@ -3501,6 +3746,116 @@ namespace JSONRPC
         "{ \"name\": \"thumbnail\", \"$ref\": \"Optional.String\" }"
       "],"
       "\"returns\": \"string\""
+    "}",
+    "\"Settings.GetSections\": {"
+      "\"type\": \"method\","
+      "\"description\": \"Retrieves all setting sections\","
+      "\"transport\": \"Response\","
+      "\"permission\": \"ReadData\","
+      "\"params\": ["
+        "{ \"name\": \"level\", \"$ref\": \"Setting.Level\", \"default\": \"standard\" },"
+        "{ \"name\": \"properties\", \"extends\": \"Item.Fields.Base\","
+          "\"items\": { \"type\": \"string\","
+            "\"enum\": [ \"categories\" ]"
+          "}"
+        "}"
+      "],"
+      "\"returns\": {"
+        "\"type\": \"object\","
+        "\"properties\": {"
+          "\"sections\": { \"type\": \"array\","
+            "\"items\": { \"$ref\": \"Setting.Details.Section\" }"
+          "}"
+        "}"
+      "}"
+    "}",
+    "\"Settings.GetCategories\": {"
+      "\"type\": \"method\","
+      "\"description\": \"Retrieves all setting categories\","
+      "\"transport\": \"Response\","
+      "\"permission\": \"ReadData\","
+      "\"params\": ["
+        "{ \"name\": \"level\", \"$ref\": \"Setting.Level\", \"default\": \"standard\" },"
+        "{ \"name\": \"section\", \"type\": \"string\", \"default\": \"\" },"
+        "{ \"name\": \"properties\", \"extends\": \"Item.Fields.Base\","
+          "\"items\": { \"type\": \"string\","
+            "\"enum\": [ \"settings\" ]"
+          "}"
+        "}"
+      "],"
+      "\"returns\": {"
+        "\"type\": \"object\","
+        "\"properties\": {"
+          "\"categories\": { \"type\": \"array\","
+            "\"items\": { \"$ref\": \"Setting.Details.Category\" }"
+          "}"
+        "}"
+      "}"
+    "}",
+    "\"Settings.GetSettings\": {"
+      "\"type\": \"method\","
+      "\"description\": \"Retrieves all settings\","
+      "\"transport\": \"Response\","
+      "\"permission\": \"ReadData\","
+      "\"params\": ["
+        "{ \"name\": \"level\", \"$ref\": \"Setting.Level\", \"default\": \"standard\" },"
+        "{ \"name\": \"filter\", \"type\": ["
+            "{ \"type\": \"object\","
+              "\"properties\": {"
+                "\"section\": { \"type\": \"string\", \"required\": true, \"minLength\": 1 },"
+                "\"category\": { \"type\": \"string\", \"required\": true, \"minLength\": 1 }"
+              "},"
+              "\"additionalProperties\": false,"
+              "\"required\": true"
+            "}"
+          "],"
+          "\"default\": null"
+        "}"
+      "],"
+      "\"returns\": {"
+        "\"type\": \"object\","
+        "\"properties\": {"
+          "\"settings\": { \"type\": \"array\","
+            "\"items\": { \"$ref\": \"Setting.Details.Setting\" }"
+          "}"
+        "}"
+      "}"
+    "}",
+    "\"Settings.GetSettingValue\": {"
+      "\"type\": \"method\","
+      "\"description\": \"Retrieves the value of a setting\","
+      "\"transport\": \"Response\","
+      "\"permission\": \"ReadData\","
+      "\"params\": ["
+        "{ \"name\": \"setting\", \"type\": \"string\", \"required\": true, \"minLength\": 1 }"
+      "],"
+      "\"returns\": {"
+        "\"type\": \"object\","
+        "\"properties\": {"
+          "\"value\": { \"$ref\": \"Setting.Value.Extended\", \"required\": true }"
+        "}"
+      "}"
+    "}",
+    "\"Settings.SetSettingValue\": {"
+      "\"type\": \"method\","
+      "\"description\": \"Changes the value of a setting\","
+      "\"transport\": \"Response\","
+      "\"permission\": \"WriteSetting\","
+      "\"params\": ["
+        "{ \"name\": \"setting\", \"type\": \"string\", \"required\": true, \"minLength\": 1 },"
+        "{ \"name\": \"value\", \"$ref\": \"Setting.Value.Extended\", \"required\": true }"
+      "],"
+      "\"returns\": \"boolean\""
+    "}",
+    "\"Settings.ResetSettingValue\": {"
+      "\"type\": \"method\","
+      "\"description\": \"Resets the value of a setting\","
+      "\"transport\": \"Response\","
+      "\"permission\": \"WriteSetting\","
+      "\"params\": ["
+        "{ \"name\": \"setting\", \"type\": \"string\", \"required\": true, \"minLength\": 1 }"
+      "],"
+      "\"returns\": \"string\""
     "}"
   };
 
diff --git a/xbmc/interfaces/json-rpc/SettingsOperations.cpp b/xbmc/interfaces/json-rpc/SettingsOperations.cpp
new file mode 100644 (file)
index 0000000..09dbe04
--- /dev/null
@@ -0,0 +1,689 @@
+/*
+ *      Copyright (C) 2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "SettingsOperations.h"
+#include "addons/Addon.h"
+#include "settings/SettingAddon.h"
+#include "settings/Setting.h"
+#include "settings/SettingControl.h"
+#include "settings/SettingPath.h"
+#include "settings/Settings.h"
+#include "settings/SettingSection.h"
+#include "guilib/LocalizeStrings.h"
+#include "utils/StringUtils.h"
+
+using namespace std;
+using namespace JSONRPC;
+
+JSONRPC_STATUS CSettingsOperations::GetSections(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+  SettingLevel level = (SettingLevel)ParseSettingLevel(parameterObject["level"].asString());
+  bool listCategories = !parameterObject["properties"].empty() && parameterObject["properties"][0].asString() == "categories";
+  vector<CSettingSection*> sections;
+
+  result["sections"] = CVariant(CVariant::VariantTypeArray);
+
+  // apply the level filter
+  vector<CSettingSection*> allSections = CSettings::Get().GetSections();
+  for (vector<CSettingSection*>::const_iterator itSection = allSections.begin(); itSection != allSections.end(); ++itSection)
+  {
+    SettingCategoryList categories = (*itSection)->GetCategories(level);
+    if (categories.empty())
+      continue;
+
+    CVariant varSection(CVariant::VariantTypeObject);
+    if (!SerializeSettingSection(*itSection, varSection))
+      continue;
+
+    if (listCategories)
+    {
+      varSection["categories"] = CVariant(CVariant::VariantTypeArray);
+      for (SettingCategoryList::const_iterator itCategory = categories.begin(); itCategory != categories.end(); ++itCategory)
+      {
+        CVariant varCategory(CVariant::VariantTypeObject);
+        if (!SerializeSettingCategory(*itCategory, varCategory))
+          continue;
+
+        varSection["categories"].push_back(varCategory);
+      }
+    }
+
+    result["sections"].push_back(varSection);
+  }
+
+  return OK;
+}
+
+JSONRPC_STATUS CSettingsOperations::GetCategories(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+  SettingLevel level = (SettingLevel)ParseSettingLevel(parameterObject["level"].asString());
+  std::string strSection = parameterObject["section"].asString();
+  bool listSettings = !parameterObject["properties"].empty() && parameterObject["properties"][0].asString() == "settings";
+
+  vector<CSettingSection*> sections;
+  if (!strSection.empty())
+  {
+    CSettingSection *section = CSettings::Get().GetSection(strSection);
+    if (section == NULL)
+      return InvalidParams;
+
+    sections.push_back(section);
+  }
+  else
+    sections = CSettings::Get().GetSections();
+
+  result["categories"] = CVariant(CVariant::VariantTypeArray);
+
+  for (vector<CSettingSection*>::const_iterator itSection = sections.begin(); itSection != sections.end(); ++itSection)
+  {
+    SettingCategoryList categories = (*itSection)->GetCategories(level);
+    for (SettingCategoryList::const_iterator itCategory = categories.begin(); itCategory != categories.end(); ++itCategory)
+    {
+      CVariant varCategory(CVariant::VariantTypeObject);
+      if (!SerializeSettingCategory(*itCategory, varCategory))
+        continue;
+
+      if (listSettings)
+      {
+        varCategory["groups"] = CVariant(CVariant::VariantTypeArray);
+
+        SettingGroupList groups = (*itCategory)->GetGroups(level);
+        for (SettingGroupList::const_iterator itGroup = groups.begin(); itGroup != groups.end(); ++itGroup)
+        {
+          CVariant varGroup(CVariant::VariantTypeObject);
+          if (!SerializeSettingGroup(*itGroup, varGroup))
+            continue;
+
+          varGroup["settings"] = CVariant(CVariant::VariantTypeArray);
+          SettingList settings = (*itGroup)->GetSettings(level);
+          for (SettingList::const_iterator itSetting = settings.begin(); itSetting != settings.end(); ++itSetting)
+          {
+            CVariant varSetting(CVariant::VariantTypeObject);
+            if (!SerializeSetting(*itSetting, varSetting))
+              continue;
+
+            varGroup["settings"].push_back(varSetting);
+          }
+
+          varCategory["groups"].push_back(varGroup);
+        }
+      }
+      
+      result["categories"].push_back(varCategory);
+    }
+  }
+
+  return OK;
+}
+
+JSONRPC_STATUS CSettingsOperations::GetSettings(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+  SettingLevel level = (SettingLevel)ParseSettingLevel(parameterObject["level"].asString());
+  const CVariant &filter = parameterObject["filter"];
+  bool doFilter = filter.isObject() && filter.isMember("section") && filter.isMember("category");
+  string strSection, strCategory;
+  if (doFilter)
+  {
+    strSection = filter["section"].asString();
+    strCategory = filter["category"].asString();
+  }
+  vector<CSettingSection*> sections;
+
+  if (doFilter)
+  {
+    CSettingSection *section = CSettings::Get().GetSection(strSection);
+    if (section == NULL)
+      return InvalidParams;
+
+    sections.push_back(section);
+  }
+  else
+    sections = CSettings::Get().GetSections();
+
+  result["settings"] = CVariant(CVariant::VariantTypeArray);
+
+  for (vector<CSettingSection*>::const_iterator itSection = sections.begin(); itSection != sections.end(); ++itSection)
+  {
+    SettingCategoryList categories = (*itSection)->GetCategories(level);
+    bool found = !doFilter;
+    for (SettingCategoryList::const_iterator itCategory = categories.begin(); itCategory != categories.end(); ++itCategory)
+    {
+      if (!doFilter || StringUtils::EqualsNoCase((*itCategory)->GetId(), strCategory))
+      {
+        SettingGroupList groups = (*itCategory)->GetGroups(level);
+        for (SettingGroupList::const_iterator itGroup = groups.begin(); itGroup != groups.end(); ++itGroup)
+        {
+          SettingList settings = (*itGroup)->GetSettings(level);
+          for (SettingList::const_iterator itSetting = settings.begin(); itSetting != settings.end(); ++itSetting)
+          {
+            CVariant varSetting(CVariant::VariantTypeObject);
+            if (!SerializeSetting(*itSetting, varSetting))
+              continue;
+
+            result["settings"].push_back(varSetting);
+          }
+        }
+        found = true;
+
+        if (doFilter)
+          break;
+      }
+    }
+
+    if (doFilter && !found)
+      return InvalidParams;
+  }
+
+  return OK;
+}
+
+JSONRPC_STATUS CSettingsOperations::GetSettingValue(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+  string settingId = parameterObject["setting"].asString();
+
+  CSetting* setting = CSettings::Get().GetSetting(settingId);
+  if (setting == NULL)
+    return InvalidParams;
+
+  CVariant value;
+  switch (setting->GetType())
+  {
+  case SettingTypeBool:
+    value = static_cast<CSettingBool*>(setting)->GetValue();
+    break;
+
+  case SettingTypeInteger:
+    value = static_cast<CSettingInt*>(setting)->GetValue();
+    break;
+
+  case SettingTypeNumber:
+    value = static_cast<CSettingNumber*>(setting)->GetValue();
+    break;
+
+  case SettingTypeString:
+    value = static_cast<CSettingString*>(setting)->GetValue();
+    break;
+
+  case SettingTypeList:
+  {
+    SerializeSettingListValues(CSettings::Get().GetList(settingId), value);
+    break;
+  }
+
+  case SettingTypeNone:
+  case SettingTypeAction:
+  default:
+    return InvalidParams;
+  }
+
+  result["value"] = value;
+
+  return OK;
+}
+
+JSONRPC_STATUS CSettingsOperations::SetSettingValue(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+  string settingId = parameterObject["setting"].asString();
+  CVariant value = parameterObject["value"];
+
+  CSetting* setting = CSettings::Get().GetSetting(settingId);
+  if (setting == NULL)
+    return InvalidParams;
+
+  switch (setting->GetType())
+  {
+  case SettingTypeBool:
+    if (!value.isBoolean())
+      return InvalidParams;
+
+    result = static_cast<CSettingBool*>(setting)->SetValue(value.asBoolean());
+    break;
+
+  case SettingTypeInteger:
+    if (!value.isInteger() && !value.isUnsignedInteger())
+      return InvalidParams;
+
+    result = static_cast<CSettingInt*>(setting)->SetValue((int)value.asInteger());
+    break;
+
+  case SettingTypeNumber:
+    if (!value.isDouble())
+      return InvalidParams;
+
+    result = static_cast<CSettingNumber*>(setting)->SetValue(value.asDouble());
+    break;
+
+  case SettingTypeString:
+    if (!value.isString())
+      return InvalidParams;
+
+    result = static_cast<CSettingString*>(setting)->SetValue(value.asString());
+    break;
+
+  case SettingTypeList:
+  {
+    if (!value.isArray())
+      return InvalidParams;
+
+    std::vector<CVariant> values;
+    for (CVariant::const_iterator_array itValue = value.begin_array(); itValue != value.end_array(); ++itValue)
+      values.push_back(*itValue);
+
+    result = CSettings::Get().SetList(settingId, values);
+    break;
+  }
+
+  case SettingTypeNone:
+  case SettingTypeAction:
+  default:
+    return InvalidParams;
+  }
+
+  return OK;
+}
+
+JSONRPC_STATUS CSettingsOperations::ResetSettingValue(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+  string settingId = parameterObject["setting"].asString();
+
+  CSetting* setting = CSettings::Get().GetSetting(settingId);
+  if (setting == NULL)
+    return InvalidParams;
+
+  switch (setting->GetType())
+  {
+  case SettingTypeBool:
+  case SettingTypeInteger:
+  case SettingTypeNumber:
+  case SettingTypeString:
+  case SettingTypeList:
+    setting->Reset();
+    break;
+
+  case SettingTypeNone:
+  case SettingTypeAction:
+  default:
+    return InvalidParams;
+  }
+
+  return ACK;
+}
+
+int CSettingsOperations::ParseSettingLevel(const std::string &strLevel)
+{
+  if (StringUtils::EqualsNoCase(strLevel, "basic"))
+    return SettingLevelBasic;
+  if (StringUtils::EqualsNoCase(strLevel, "advanced"))
+    return SettingLevelAdvanced;
+  if (StringUtils::EqualsNoCase(strLevel, "expert"))
+    return SettingLevelExpert;
+
+  return SettingLevelStandard;
+}
+
+bool CSettingsOperations::SerializeISetting(const ISetting* setting, CVariant &obj)
+{
+  if (setting == NULL)
+    return false;
+
+  obj["id"] = setting->GetId();
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingSection(const CSettingSection* setting, CVariant &obj)
+{
+  if (!SerializeISetting(setting, obj))
+    return false;
+
+  obj["label"] = g_localizeStrings.Get(setting->GetLabel());
+  if (setting->GetHelp() >= 0)
+    obj["help"] = g_localizeStrings.Get(setting->GetHelp());
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingCategory(const CSettingCategory* setting, CVariant &obj)
+{
+  if (!SerializeISetting(setting, obj))
+    return false;
+
+  obj["label"] = g_localizeStrings.Get(setting->GetLabel());
+  if (setting->GetHelp() >= 0)
+    obj["help"] = g_localizeStrings.Get(setting->GetHelp());
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingGroup(const CSettingGroup* setting, CVariant &obj)
+{
+  return SerializeISetting(setting, obj);
+}
+
+bool CSettingsOperations::SerializeSetting(const CSetting* setting, CVariant &obj)
+{
+  if (!SerializeISetting(setting, obj))
+    return false;
+
+  obj["label"] = g_localizeStrings.Get(setting->GetLabel());
+  if (setting->GetHelp() >= 0)
+    obj["help"] = g_localizeStrings.Get(setting->GetHelp());
+
+  switch (setting->GetLevel())
+  {
+    case SettingLevelBasic:
+      obj["level"] = "basic";
+      break;
+
+    case SettingLevelStandard:
+      obj["level"] = "standard";
+      break;
+
+    case SettingLevelAdvanced:
+      obj["level"] = "advanced";
+      break;
+
+    case SettingLevelExpert:
+      obj["level"] = "expert";
+      break;
+
+    default:
+      return false;
+  }
+
+  obj["enabled"] = setting->IsEnabled();
+  obj["parent"] = setting->GetParent();
+
+  obj["control"] = CVariant(CVariant::VariantTypeObject);
+  if (!SerializeSettingControl(setting->GetControl(), obj["control"]))
+    return false;
+
+  switch (setting->GetType())
+  {
+    case SettingTypeBool:
+      obj["type"] = "boolean";
+      if (!SerializeSettingBool(static_cast<const CSettingBool*>(setting), obj))
+        return false;
+      break;
+
+    case SettingTypeInteger:
+      obj["type"] = "integer";
+      if (!SerializeSettingInt(static_cast<const CSettingInt*>(setting), obj))
+        return false;
+      break;
+
+    case SettingTypeNumber:
+      obj["type"] = "number";
+      if (!SerializeSettingNumber(static_cast<const CSettingNumber*>(setting), obj))
+        return false;
+      break;
+
+    case SettingTypeString:
+      obj["type"] = "string";
+      if (!SerializeSettingString(static_cast<const CSettingString*>(setting), obj))
+        return false;
+      break;
+
+    case SettingTypeAction:
+      obj["type"] = "action";
+      if (!SerializeSettingAction(static_cast<const CSettingAction*>(setting), obj))
+        return false;
+      break;
+
+    case SettingTypeList:
+      obj["type"] = "list";
+      if (!SerializeSettingList(static_cast<const CSettingList*>(setting), obj))
+        return false;
+      break;
+
+    default:
+      return false;
+  }
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingBool(const CSettingBool* setting, CVariant &obj)
+{
+  if (setting == NULL)
+    return false;
+
+  obj["value"] = setting->GetValue();
+  obj["default"] = setting->GetDefault();
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingInt(const CSettingInt* setting, CVariant &obj)
+{
+  if (setting == NULL)
+    return false;
+
+  obj["value"] = setting->GetValue();
+  obj["default"] = setting->GetDefault();
+
+  switch (setting->GetOptionsType())
+  {
+    case SettingOptionsTypeStatic:
+    {
+      obj["options"] = CVariant(CVariant::VariantTypeArray);
+      const StaticIntegerSettingOptions& options = setting->GetOptions();
+      for (StaticIntegerSettingOptions::const_iterator itOption = options.begin(); itOption != options.end(); ++itOption)
+      {
+        CVariant varOption(CVariant::VariantTypeObject);
+        varOption["label"] = g_localizeStrings.Get(itOption->first);
+        varOption["value"] = itOption->second;
+        obj["options"].push_back(varOption);
+      }
+      break;
+    }
+
+    case SettingOptionsTypeDynamic:
+    {
+      obj["options"] = CVariant(CVariant::VariantTypeArray);
+      DynamicIntegerSettingOptions options = const_cast<CSettingInt*>(setting)->UpdateDynamicOptions();
+      for (DynamicIntegerSettingOptions::const_iterator itOption = options.begin(); itOption != options.end(); ++itOption)
+      {
+        CVariant varOption(CVariant::VariantTypeObject);
+        varOption["label"] = itOption->first;
+        varOption["value"] = itOption->second;
+        obj["options"].push_back(varOption);
+      }
+      break;
+    }
+
+    case SettingOptionsTypeNone:
+    default:
+      obj["minimum"] = setting->GetMinimum();
+      obj["step"] = setting->GetStep();
+      obj["maximum"] = setting->GetMaximum();
+      break;
+  }
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingNumber(const CSettingNumber* setting, CVariant &obj)
+{
+  if (setting == NULL)
+    return false;
+
+  obj["value"] = setting->GetValue();
+  obj["default"] = setting->GetDefault();
+
+  obj["minimum"] = setting->GetMinimum();
+  obj["step"] = setting->GetStep();
+  obj["maximum"] = setting->GetMaximum();
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingString(const CSettingString* setting, CVariant &obj)
+{
+  if (setting == NULL)
+    return false;
+
+  obj["value"] = setting->GetValue();
+  obj["default"] = setting->GetDefault();
+
+  obj["allowempty"] = setting->AllowEmpty();
+
+  if (setting->GetOptionsType() == SettingOptionsTypeDynamic)
+  {
+    obj["options"] = CVariant(CVariant::VariantTypeArray);
+    DynamicStringSettingOptions options = const_cast<CSettingString*>(setting)->UpdateDynamicOptions();
+    for (DynamicStringSettingOptions::const_iterator itOption = options.begin(); itOption != options.end(); ++itOption)
+    {
+      CVariant varOption(CVariant::VariantTypeObject);
+      varOption["label"] = itOption->first;
+      varOption["value"] = itOption->second;
+      obj["options"].push_back(varOption);
+    }
+  }
+
+  const ISettingControl* control = setting->GetControl();
+  if (control->GetFormat() == "path")
+  {
+    if (!SerializeSettingPath(static_cast<const CSettingPath*>(setting), obj))
+      return false;
+  }
+  if (control->GetFormat() == "addon")
+  {
+    if (!SerializeSettingAddon(static_cast<const CSettingAddon*>(setting), obj))
+      return false;
+  }
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingAction(const CSettingAction* setting, CVariant &obj)
+{
+  if (setting == NULL)
+    return false;
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingList(const CSettingList* setting, CVariant &obj)
+{
+  if (setting == NULL ||
+      !SerializeSetting(setting->GetDefinition(), obj["definition"]))
+    return false;
+
+  SerializeSettingListValues(CSettings::Get().GetList(setting->GetId()), obj["value"]);
+  SerializeSettingListValues(CSettings::ListToValues(setting, setting->GetDefault()), obj["default"]);
+
+  obj["elementtype"] = obj["definition"]["type"];
+  obj["delimiter"] = setting->GetDelimiter();
+  obj["minimum"] = setting->GetMinimum();
+  obj["maximum"] = setting->GetMaximum();
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingPath(const CSettingPath* setting, CVariant &obj)
+{
+  if (setting == NULL)
+    return false;
+
+  obj["type"] = "path";
+  obj["writable"] = setting->Writable();
+  obj["sources"] = setting->GetSources();
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingAddon(const CSettingAddon* setting, CVariant &obj)
+{
+  if (setting == NULL)
+    return false;
+
+  obj["type"] = "addon";
+  obj["addontype"] = ADDON::TranslateType(setting->GetAddonType());
+
+  return true;
+}
+
+bool CSettingsOperations::SerializeSettingControl(const ISettingControl* control, CVariant &obj)
+{
+  if (control == NULL)
+    return false;
+  
+  const std::string& type = control->GetType();
+  obj["type"] = type;
+  obj["format"] = control->GetFormat();
+  obj["delayed"] = control->GetDelayed();
+
+  if (type == "spinner")
+  {
+    const CSettingControlSpinner* spinner = static_cast<const CSettingControlSpinner*>(control);
+    if (spinner == NULL)
+      return false;
+
+    if (spinner->GetFormatLabel() >= 0)
+      obj["formatlabel"] = g_localizeStrings.Get(spinner->GetFormatLabel());
+    else if (!spinner->GetFormatString().empty() && spinner->GetFormatString() != "%i")
+      obj["formatlabel"] = spinner->GetFormatString();
+    if (spinner->GetMinimumLabel() >= 0)
+      obj["minimumlabel"] = g_localizeStrings.Get(spinner->GetMinimumLabel());
+  }
+  else if (type == "edit")
+  {
+    const CSettingControlEdit* edit = static_cast<const CSettingControlEdit*>(control);
+    if (edit == NULL)
+      return false;
+
+    obj["hidden"] = edit->IsHidden();
+    obj["verifynewvalue"] = edit->VerifyNewValue();
+    if (edit->GetHeading() >= 0)
+      obj["heading"] = g_localizeStrings.Get(edit->GetHeading());
+  }
+  else if (type == "button")
+  {
+    const CSettingControlButton* button = static_cast<const CSettingControlButton*>(control);
+    if (button == NULL)
+      return false;
+
+    if (button->GetHeading() >= 0)
+      obj["heading"] = g_localizeStrings.Get(button->GetHeading());
+  }
+  else if (type == "list")
+  {
+    const CSettingControlList* list = static_cast<const CSettingControlList*>(control);
+    if (list == NULL)
+      return false;
+
+    if (list->GetHeading() >= 0)
+      obj["heading"] = g_localizeStrings.Get(list->GetHeading());
+    obj["multiselect"] = list->CanMultiSelect();
+  }
+  else if (type != "toggle")
+    return false;
+
+  return true;
+}
+
+void CSettingsOperations::SerializeSettingListValues(const std::vector<CVariant> &values, CVariant &obj)
+{
+  obj = CVariant(CVariant::VariantTypeArray);
+  for (std::vector<CVariant>::const_iterator itValue = values.begin(); itValue != values.end(); ++itValue)
+    obj.push_back(*itValue);
+}
diff --git a/xbmc/interfaces/json-rpc/SettingsOperations.h b/xbmc/interfaces/json-rpc/SettingsOperations.h
new file mode 100644 (file)
index 0000000..cee669c
--- /dev/null
@@ -0,0 +1,73 @@
+#pragma once
+/*
+ *      Copyright (C) 2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "utils/StdString.h"
+#include "JSONRPC.h"
+
+class ISetting;
+class CSettingSection;
+class CSettingCategory;
+class CSettingGroup;
+class CSetting;
+class CSettingBool;
+class CSettingInt;
+class CSettingNumber;
+class CSettingString;
+class CSettingAction;
+class CSettingList;
+class CSettingPath;
+class CSettingAddon;
+class ISettingControl;
+
+namespace JSONRPC
+{
+  class CSettingsOperations
+  {
+  public:
+    static JSONRPC_STATUS GetSections(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+    static JSONRPC_STATUS GetCategories(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+    static JSONRPC_STATUS GetSettings(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+    
+    static JSONRPC_STATUS GetSettingValue(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+    static JSONRPC_STATUS SetSettingValue(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+    static JSONRPC_STATUS ResetSettingValue(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+
+  private:
+    static int ParseSettingLevel(const std::string &strLevel);
+
+    static bool SerializeISetting(const ISetting* setting, CVariant &obj);
+    static bool SerializeSettingSection(const CSettingSection* setting, CVariant &obj);
+    static bool SerializeSettingCategory(const CSettingCategory* setting, CVariant &obj);
+    static bool SerializeSettingGroup(const CSettingGroup* setting, CVariant &obj);
+    static bool SerializeSetting(const CSetting* setting, CVariant &obj);
+    static bool SerializeSettingBool(const CSettingBool* setting, CVariant &obj);
+    static bool SerializeSettingInt(const CSettingInt* setting, CVariant &obj);
+    static bool SerializeSettingNumber(const CSettingNumber* setting, CVariant &obj);
+    static bool SerializeSettingString(const CSettingString* setting, CVariant &obj);
+    static bool SerializeSettingAction(const CSettingAction* setting, CVariant &obj);
+    static bool SerializeSettingList(const CSettingList* setting, CVariant &obj);
+    static bool SerializeSettingPath(const CSettingPath* setting, CVariant &obj);
+    static bool SerializeSettingAddon(const CSettingAddon* setting, CVariant &obj);
+    static bool SerializeSettingControl(const ISettingControl* control, CVariant &obj);
+
+    static void SerializeSettingListValues(const std::vector<CVariant> &values, CVariant &obj);
+  };
+}
index 3e97f84..1ffaa48 100644 (file)
       { "name": "thumbnail", "$ref": "Optional.String" }
     ],
     "returns": "string"
+  },
+  "Settings.GetSections": {
+    "type": "method",
+    "description": "Retrieves all setting sections",
+    "transport": "Response",
+    "permission": "ReadData",
+    "params": [
+      { "name": "level", "$ref": "Setting.Level", "default": "standard" },
+      { "name": "properties", "extends": "Item.Fields.Base",
+        "items": { "type": "string",
+          "enum": [ "categories" ]
+        }
+      }
+    ],
+    "returns": {
+      "type": "object",
+      "properties": {
+        "sections": { "type": "array",
+          "items": { "$ref": "Setting.Details.Section" }
+        }
+      }
+    }
+  },
+  "Settings.GetCategories": {
+    "type": "method",
+    "description": "Retrieves all setting categories",
+    "transport": "Response",
+    "permission": "ReadData",
+    "params": [
+      { "name": "level", "$ref": "Setting.Level", "default": "standard" },
+      { "name": "section", "type": "string", "default": "" },
+      { "name": "properties", "extends": "Item.Fields.Base",
+        "items": { "type": "string",
+          "enum": [ "settings" ]
+        }
+      }
+    ],
+    "returns": {
+      "type": "object",
+      "properties": {
+        "categories": { "type": "array",
+          "items": { "$ref": "Setting.Details.Category" }
+        }
+      }
+    }
+  },
+  "Settings.GetSettings": {
+    "type": "method",
+    "description": "Retrieves all settings",
+    "transport": "Response",
+    "permission": "ReadData",
+    "params": [
+      { "name": "level", "$ref": "Setting.Level", "default": "standard" },
+      { "name": "filter", "type": [
+          { "type": "object",
+            "properties": {
+              "section": { "type": "string", "required": true, "minLength": 1 },
+              "category": { "type": "string", "required": true, "minLength": 1 }
+            },
+            "additionalProperties": false,
+            "required": true
+          }
+        ],
+        "default": null
+      }
+    ],
+    "returns": {
+      "type": "object",
+      "properties": {
+        "settings": { "type": "array",
+          "items": { "$ref": "Setting.Details.Setting" }
+        }
+      }
+    }
+  },
+  "Settings.GetSettingValue": {
+    "type": "method",
+    "description": "Retrieves the value of a setting",
+    "transport": "Response",
+    "permission": "ReadData",
+    "params": [
+      { "name": "setting", "type": "string", "required": true, "minLength": 1 }
+    ],
+    "returns": {
+      "type": "object",
+      "properties": {
+        "value": { "$ref": "Setting.Value.Extended", "required": true }
+      }
+    }
+  },
+  "Settings.SetSettingValue": {
+    "type": "method",
+    "description": "Changes the value of a setting",
+    "transport": "Response",
+    "permission": "WriteSetting",
+    "params": [
+      { "name": "setting", "type": "string", "required": true, "minLength": 1 },
+      { "name": "value", "$ref": "Setting.Value.Extended", "required": true }
+    ],
+    "returns": "boolean"
+  },
+  "Settings.ResetSettingValue": {
+    "type": "method",
+    "description": "Resets the value of a setting",
+    "transport": "Response",
+    "permission": "WriteSetting",
+    "params": [
+      { "name": "setting", "type": "string", "required": true, "minLength": 1 }
+    ],
+    "returns": "string"
   }
 }
\ No newline at end of file
index cefd097..1bba2ea 100644 (file)
       "thumbnail": { "type": "string" }
     },
     "additionalProperties": false
+  },
+  "Setting.Type": {
+    "type": "string",
+    "enum": [
+      "boolean", "integer", "number", "string", "action", "list",
+      "path", "addon"
+    ]
+  },
+  "Setting.Level": {
+    "type": "string",
+    "enum": [ "basic", "standard", "advanced", "expert" ]
+  },
+  "Setting.Value": {
+    "type": [
+      { "type": "boolean", "required": true },
+      { "type": "integer", "required": true },
+      { "type": "number", "required": true },
+      { "type": "string", "required": true }
+    ]
+  },
+  "Setting.Value.List": {
+    "type": "array",
+    "items": { "$ref": "Setting.Value" }
+  },
+  "Setting.Value.Extended": {
+    "type": [
+      { "type": "boolean", "required": true },
+      { "type": "integer", "required": true },
+      { "type": "number", "required": true },
+      { "type": "string", "required": true },
+      { "$ref": "Setting.Value.List", "required": true }
+    ]
+  },
+  "Setting.Details.ControlBase": {
+    "type": "object",
+    "properties": {
+      "type": { "type": "string", "required": true },
+      "format": { "type": "string", "required": true },
+      "delayed": { "type": "boolean", "required": true }
+    }
+  },
+  "Setting.Details.ControlCheckmark": {
+    "extends": "Setting.Details.ControlBase",
+    "properties": {
+      "type": { "type": "string", "required": true, "enum": [ "toggle" ] },
+      "format": { "type": "string", "required": true, "enum": [ "boolean" ] }
+    }
+  },
+  "Setting.Details.ControlSpinner": {
+    "extends": "Setting.Details.ControlBase",
+    "properties": {
+      "type": { "type": "string", "required": true, "enum": [ "spinner" ] },
+      "formatlabel": { "type": "string" },
+      "minimumlabel": { "type": "string" }
+    }
+  },
+  "Setting.Details.ControlHeading": {
+    "extends": "Setting.Details.ControlBase",
+    "properties": {
+      "heading": { "type": "string" }
+    }
+  },
+  "Setting.Details.ControlEdit": {
+    "extends": "Setting.Details.ControlHeading",
+    "properties": {
+      "type": { "type": "string", "required": true, "enum": [ "edit" ] },
+      "hidden": { "type": "boolean", "required": true },
+      "verifynewvalue": { "type": "boolean", "required": true }
+    }
+  },
+  "Setting.Details.ControlButton": {
+    "extends": "Setting.Details.ControlHeading",
+    "properties": {
+      "type": { "type": "string", "required": true, "enum": [ "button" ] }
+    }
+  },
+  "Setting.Details.ControlList": {
+    "extends": "Setting.Details.ControlHeading",
+    "properties": {
+      "type": { "type": "string", "required": true, "enum": [ "list" ] },
+      "multiselect": { "type": "boolean", "required": true }
+    }
+  },
+  "Setting.Details.Control": {
+    "type": [
+      { "$ref": "Setting.Details.ControlCheckmark", "required": true },
+      { "$ref": "Setting.Details.ControlSpinner", "required": true },
+      { "$ref": "Setting.Details.ControlEdit", "required": true },
+      { "$ref": "Setting.Details.ControlButton", "required": true },
+      { "$ref": "Setting.Details.ControlList", "required": true }
+    ]
+  },
+  "Setting.Details.Base": {
+    "type": "object",
+    "properties": {
+      "id": { "type": "string", "required": true, "minLength": 1 },
+      "label": { "type": "string", "required": true },
+      "help": { "type": "string" }
+    }
+  },
+  "Setting.Details.SettingBase": {
+    "extends": "Setting.Details.Base",
+    "properties": {
+      "type": { "$ref": "Setting.Type", "required": true },
+      "enabled": { "type": "boolean", "required": true },
+      "level": { "type": "integer", "required": true },
+      "parent": { "type": "string" },
+      "control": { "$ref": "Setting.Details.Control" }
+    },
+    "additionalProperties": false
+  },
+  "Setting.Details.SettingBool": {
+    "extends": "Setting.Details.SettingBase",
+    "properties": {
+      "value": { "type": "boolean", "required": true },
+      "default": { "type": "boolean", "required": true }
+    },
+    "additionalProperties": false
+  },
+  "Setting.Details.SettingInt": {
+    "extends": "Setting.Details.SettingBase",
+    "properties": {
+      "value": { "type": "integer", "required": true },
+      "default": { "type": "integer", "required": true },
+      "minimum": { "type": "integer" },
+      "step": { "type": "integer" },
+      "maximum": { "type": "integer" },
+      "options": { "type": "array",
+        "items": { "type": "object",
+          "properties": {
+            "label": { "type": "string", "required": true },
+            "value": { "type": "integer", "required": true }
+          }
+        }
+      }
+    },
+    "additionalProperties": false
+  },
+  "Setting.Details.SettingNumber": {
+    "extends": "Setting.Details.SettingBase",
+    "properties": {
+      "value": { "type": "number", "required": true },
+      "default": { "type": "number", "required": true },
+      "minimum": { "type": "number", "required": true },
+      "step": { "type": "number", "required": true },
+      "maximum": { "type": "number", "required": true }
+    },
+    "additionalProperties": false
+  },
+  "Setting.Details.SettingString": {
+    "extends": "Setting.Details.SettingBase",
+    "properties": {
+      "value": { "type": "string", "required": true },
+      "default": { "type": "string", "required": true },
+      "allowempty": { "type": "boolean", "required": true },
+      "options": { "type": "array",
+        "items": { "type": "object",
+          "properties": {
+            "label": { "type": "string", "required": true },
+            "value": { "type": "string", "required": true }
+          }
+        }
+      }
+    }
+  },
+  "Setting.Details.SettingAction": {
+    "extends": "Setting.Details.SettingBase",
+    "additionalProperties": false
+  },
+  "Setting.Details.SettingList": {
+    "extends": "Setting.Details.SettingBase",
+    "properties": {
+      "value": { "$ref": "Setting.Value.List", "required": true },
+      "default": { "$ref": "Setting.Value.List", "required": true },
+      "elementtype": { "$ref": "Setting.Type", "required": true },
+      "definition": { "$ref": "Setting.Details.Setting", "required": true },
+      "delimiter": { "type": "string", "required": true },
+      "minimum": { "type": "integer" },
+      "maximum": { "type": "integer" }
+    },
+    "additionalProperties": false
+  },
+  "Setting.Details.SettingPath": {
+    "extends": "Setting.Details.SettingString",
+    "properties": {
+      "writable": { "type": "boolean", "required": true },
+      "sources": { "type": "array", "items": { "type": "string" } }
+    },
+    "additionalProperties": false
+  },
+  "Setting.Details.SettingAddon": {
+    "extends": "Setting.Details.SettingString",
+    "properties": {
+      "addontype": { "$ref": "Addon.Types", "required": true }
+    },
+    "additionalProperties": false
+  },
+  "Setting.Details.Setting": {
+    "type": [
+      { "$ref": "Setting.Details.SettingBool", "required": true },
+      { "$ref": "Setting.Details.SettingInt", "required": true },
+      { "$ref": "Setting.Details.SettingNumber", "required": true },
+      { "$ref": "Setting.Details.SettingString", "required": true },
+      { "$ref": "Setting.Details.SettingAction", "required": true },
+      { "$ref": "Setting.Details.SettingList", "required": true },
+      { "$ref": "Setting.Details.SettingPath", "required": true },
+      { "$ref": "Setting.Details.SettingAddon", "required": true }
+    ]
+  },
+  "Setting.Details.Group": {
+    "type": "object",
+    "properties": {
+      "id": { "type": "string", "required": true, "minLength": 1 },
+      "settings": {
+        "type": "array",
+        "items": { "$ref": "Setting.Details.Setting" },
+        "minItems": 1,
+        "uniqueItems": true
+      }
+    },
+    "additionalProperties": false
+  },
+  "Setting.Details.Category": {
+    "extends": "Setting.Details.Base",
+    "properties": {
+      "groups": {
+        "type": "array",
+        "items": { "$ref": "Setting.Details.Group" },
+        "minItems": 1,
+        "uniqueItems": true
+      }
+    },
+    "additionalProperties": false
+  },
+  "Setting.Details.Section": {
+    "extends": "Setting.Details.Base",
+    "properties": {
+      "categories": {
+        "type": "array",
+        "items": { "$ref": "Setting.Details.Category" },
+        "minItems": 1,
+        "uniqueItems": true
+      }
+    },
+    "additionalProperties": false
   }
 }