PageRenderTime 27ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/xbmc_alshain.php

https://bitbucket.org/kaigoh/xbmc-php
PHP | 312 lines | 165 code | 31 blank | 116 comment | 19 complexity | e39353e0859af8482a26745ea56779ae MD5 | raw file
  1. <?php
  2. /**
  3. +-----------------------------------------------+
  4. | XBMC PHP Library - (C) Kai Gohegan, 2010 |
  5. +-----------------------------------------------+
  6. A PHP library for interacting with XBMC using
  7. JSON-RPC and XBMC's HTTP-API. Inspiration was
  8. drawn from Jason Bryant-Greene's php-json-rpc
  9. (https://bitbucket.org/jbg/php-json-rpc/src).
  10. +-----------------------------------------------+
  11. | License |
  12. +-----------------------------------------------+
  13. Copyright (c) 2010, Kai Gohegan
  14. All rights reserved.
  15. Redistribution and use in source and binary forms, with or without
  16. modification, are permitted provided that the following conditions
  17. are met:
  18. Redistributions of source code must retain the above copyright
  19. notice, this list of conditions and the following disclaimer.
  20. Redistributions in binary form must reproduce the above copyright
  21. notice, this list of conditions and the following disclaimer in the
  22. documentation and/or other materials provided with the distribution.
  23. Neither the name of Kai Gohegan nor the names of its contributors may
  24. be used to endorse or promote products derived from this software
  25. without specific prior written permission.
  26. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  27. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  28. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  29. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  30. HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  31. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  32. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  33. OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  34. AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
  36. WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37. POSSIBILITY OF SUCH DAMAGE.
  38. +-----------------------------------------------+
  39. | Usage |
  40. +-----------------------------------------------+
  41. Clases:
  42. XbmcHost
  43. XbmcJson
  44. XbmcHttp
  45. The XbmcHost-Class represents a computer running an instance of XBMC
  46. An instance thereof must be passed to the constructor. API-Classes
  47. XbmcJson and XbmcHttp. The XbmcHost-Class accepts two parameter
  48. formats:
  49. * A string:
  50. 'username:password@host:port'
  51. * an array with the keys:
  52. user, pass, host, port
  53. Usage:
  54. $xbmcJson->NAMESPACE->COMMAND(
  55. array(PARAM1 => VALUE1, PARAM2 => VALUE2, etc..)
  56. );
  57. $xbmcJson->VideoLibrary->GetRecentlyAddedMovies();
  58. $xbmcHttp->COMMAND('arg1,arg2');
  59. $xbmcHttp->ExecBuiltIn("Notification(XBMC-PHP, Hello!)");
  60. The arguments may also be passed as array. The values will be joined
  61. recursively and wrapped with parenthenses. All parameters will be
  62. urlencoded properly, regardless of the of the way the arguments are
  63. being passed.
  64. $xbmcHttp->ExecBuiltIn("Notification", array("XBMC-PHP", "Hello!"));
  65. References:
  66. http://wiki.xbmc.org/index.php?title=JSON_RPC
  67. http://wiki.xbmc.org/index.php?title=Web_Server_HTTP_API
  68. **/
  69. class XbmcException extends Exception{
  70. }
  71. class XbmcHost{
  72. private $_url = null;
  73. public function __construct(){
  74. // we con't know how many arguments we will get.
  75. $config = call_user_func_array(
  76. array($this, 'parseConfig'),
  77. func_get_args()
  78. );
  79. $config = $this->validateAndCleanConfig($config);
  80. $this->_url = $this->buildUrl($config);
  81. $this->assertReachableXbmc();
  82. }
  83. /**
  84. * Throw XbmcException if XBMC cannot be reached.
  85. */
  86. protected function assertReachableXbmc(){
  87. if(!$this->isXbmcReachable()){
  88. throw new XbmcException("Host could not be reached.");
  89. }
  90. }
  91. /**
  92. * Build an URL(string) from a config array
  93. */
  94. protected function buildUrl($config){
  95. $port = 8080;
  96. extract($config);
  97. $url = '';
  98. if(!empty($user)){
  99. $url = $user;
  100. $url .= (!empty($pass)) ? ":${pass}": "";
  101. $url .= '@';
  102. }
  103. return $url."${host}:${port}";
  104. }
  105. /**
  106. * Remove unnecessary pairs from array
  107. * and ensure the requierd host key exists.
  108. */
  109. protected function validateAndCleanConfig($config){
  110. $valid_keys = array("user", "pass", "host", "port");
  111. $required_keys = array("host");
  112. foreach($required_keys as $key){
  113. if(!array_key_exists($key, $config)){
  114. throw new XbmcException("Missing config key: ".$key);
  115. }
  116. }
  117. $subset = array_fill_keys($valid_keys, null);
  118. $cleaned = array_intersect_key($config, $subset);
  119. return $cleaned;
  120. }
  121. /**
  122. * Process the constructor argument and try returning
  123. * a well formed configuration array containing the
  124. * following indexes: user, password, host, port
  125. *
  126. * Added 01/01/2011 - Suggestion from robweber
  127. * http://forum.xbmc.org/showpost.php?p=678465&postcount=11
  128. * Check how the URL, port, username and password is being passed in,
  129. * via array or string.
  130. */
  131. protected function parseConfig($config){
  132. if(is_string($config)){
  133. $config = parse_url($config);
  134. if($config === false){
  135. throw new XbmcException('Bad URL parameters!');
  136. }
  137. }
  138. return $config;
  139. }
  140. /**
  141. * Check whether the XBMC with specified config can be
  142. * reached.
  143. */
  144. public function isXbmcReachable(){
  145. $ch = curl_init();
  146. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  147. curl_setopt($ch, CURLOPT_URL, $this->url);
  148. curl_exec($ch);
  149. $info = curl_getinfo($ch);
  150. return ($info['http_code'] == "200" || $info['http_code'] == "401");
  151. }
  152. /**
  153. * Implements url property.
  154. */
  155. public function __get($name){
  156. if($name == 'url'){
  157. return $this->_url;
  158. }
  159. }
  160. public function __set($name, $value){
  161. if($name == "url"){
  162. throw new XbmcException("Property is read-only!");
  163. }
  164. throw new XbmcException("Undefined property");
  165. }
  166. }
  167. class XbmcJson{
  168. protected $_xbmc;
  169. public function __construct($xbmc){
  170. $this->_xbmc = $xbmc;
  171. $this->populateCommands($this->rpc("JSONRPC.Introspect")->commands);
  172. }
  173. private function populateCommands($remoteCommands){
  174. foreach($remoteCommands as $remoteCommand){
  175. $rpcCommand = explode(".", $remoteCommand->command);
  176. if(!class_exists($rpcCommand[0])){
  177. $this->$rpcCommand[0] = new XbmcJsonCommand(
  178. $rpcCommand[0],
  179. $this);
  180. }
  181. }
  182. }
  183. public function rpc($method, $params = NULL){
  184. $uid = rand(1, 9999999);
  185. $json = array(
  186. 'jsonrpc' => '2.0',
  187. 'method' => $method,
  188. 'params' => $params,
  189. 'id' => $uid
  190. );
  191. $request = json_encode($json);
  192. $ch = curl_init();
  193. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  194. curl_setopt($ch, CURLOPT_POST, 1);
  195. curl_setopt($ch, CURLOPT_URL, "http://".$this->_xbmc->url."/jsonrpc");
  196. curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
  197. $responseRaw = curl_exec($ch);
  198. $response = json_decode($responseRaw);
  199. if ($response->id != $uid){
  200. throw new XbmcException('JSON-RPC ID Mismatch');
  201. }
  202. if (property_exists($response, 'error')){
  203. throw new XbmcException(
  204. $response->error->message,
  205. $response->error->code
  206. );
  207. }
  208. else if (property_exists($response, 'result')){
  209. return $response->result;
  210. }
  211. else{
  212. throw new XbmcException('Bad JSON-RPC response');
  213. }
  214. }
  215. }
  216. class XbmcJsonCommand{
  217. private $_name;
  218. private $_xbmcJson;
  219. public function __construct($name, xbmcJson $xbmcJson){
  220. $this->_name = $name;
  221. $this->_xbmcJson = $xbmcJson;
  222. }
  223. public function __call($method, $args = array()){
  224. return $this->_xbmcJson->rpc($this->_name.".".$method, $args);
  225. }
  226. }
  227. class XbmcHttp{
  228. protected $_xbmc;
  229. public function __construct(XbmcHost $xbmc){
  230. $this->_xbmc = $xbmc;
  231. }
  232. public function __call($command, $args = array()){
  233. $ch = curl_init();
  234. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  235. curl_setopt($ch, CURLOPT_URL, $this->buildUrl($command, $args));
  236. $response = curl_exec($ch);
  237. return strip_tags($response);
  238. }
  239. public function buildUrl($command, $args = array(), $params = array()){
  240. $args = (array) $args;
  241. $command .= $this->arrayToParamString($args);
  242. $params['command'] = $command;
  243. $result = "http://";
  244. $result .= $this->_xbmc->url;
  245. $result .= '/xbmcCmds/xbmcHttp?';
  246. $result .= http_build_query($params);
  247. return $result;
  248. }
  249. protected function arrayToParamString($array){
  250. $result = array();
  251. foreach($array as $arg){
  252. if(is_array($arg)){
  253. $arg = $this->arrayToParamString($arg);
  254. }
  255. $result[] = $arg;
  256. }
  257. return "(".implode(",", $result).")";
  258. }
  259. }
  260. ?>