emby.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. <?php
  2. trait EmbyHomepageItem
  3. {
  4. public function embySettingsArray($infoOnly = false)
  5. {
  6. $homepageInformation = [
  7. 'name' => 'Emby',
  8. 'enabled' => strpos('personal', $this->config['license']) !== false,
  9. 'image' => 'plugins/images/tabs/emby.png',
  10. 'category' => 'Media Server',
  11. 'settingsArray' => __FUNCTION__
  12. ];
  13. if ($infoOnly) {
  14. return $homepageInformation;
  15. }
  16. $homepageSettings = array(
  17. 'settings' => array(
  18. 'Enable' => array(
  19. array(
  20. 'type' => 'switch',
  21. 'name' => 'homepageEmbyEnabled',
  22. 'label' => 'Enable',
  23. 'value' => $this->config['homepageEmbyEnabled']
  24. ),
  25. array(
  26. 'type' => 'select',
  27. 'name' => 'homepageEmbyAuth',
  28. 'label' => 'Minimum Authentication',
  29. 'value' => $this->config['homepageEmbyAuth'],
  30. 'options' => $this->groupOptions
  31. )
  32. ),
  33. 'Connection' => array(
  34. array(
  35. 'type' => 'input',
  36. 'name' => 'embyURL',
  37. 'label' => 'URL',
  38. 'value' => $this->config['embyURL'],
  39. 'help' => 'Please make sure to use local IP address and port - You also may use local dns name too.',
  40. 'placeholder' => 'http(s)://hostname:port'
  41. ),
  42. array(
  43. 'type' => 'password-alt',
  44. 'name' => 'embyToken',
  45. 'label' => 'Token',
  46. 'value' => $this->config['embyToken']
  47. )
  48. ),
  49. 'Active Streams' => array(
  50. array(
  51. 'type' => 'switch',
  52. 'name' => 'homepageEmbyStreams',
  53. 'label' => 'Enable',
  54. 'value' => $this->config['homepageEmbyStreams']
  55. ),
  56. array(
  57. 'type' => 'select',
  58. 'name' => 'homepageEmbyStreamsAuth',
  59. 'label' => 'Minimum Authorization',
  60. 'value' => $this->config['homepageEmbyStreamsAuth'],
  61. 'options' => $this->groupOptions
  62. ),
  63. array(
  64. 'type' => 'switch',
  65. 'name' => 'homepageShowStreamNames',
  66. 'label' => 'User Information',
  67. 'value' => $this->config['homepageShowStreamNames']
  68. ),
  69. array(
  70. 'type' => 'select',
  71. 'name' => 'homepageShowStreamNamesAuth',
  72. 'label' => 'Minimum Authorization',
  73. 'value' => $this->config['homepageShowStreamNamesAuth'],
  74. 'options' => $this->groupOptions
  75. ),
  76. array(
  77. 'type' => 'select',
  78. 'name' => 'homepageStreamRefresh',
  79. 'label' => 'Refresh Seconds',
  80. 'value' => $this->config['homepageStreamRefresh'],
  81. 'options' => $this->timeOptions()
  82. ),
  83. ),
  84. 'Recent Items' => array(
  85. array(
  86. 'type' => 'switch',
  87. 'name' => 'homepageEmbyRecent',
  88. 'label' => 'Enable',
  89. 'value' => $this->config['homepageEmbyRecent']
  90. ),
  91. array(
  92. 'type' => 'select',
  93. 'name' => 'homepageEmbyRecentAuth',
  94. 'label' => 'Minimum Authorization',
  95. 'value' => $this->config['homepageEmbyRecentAuth'],
  96. 'options' => $this->groupOptions
  97. ),
  98. array(
  99. 'type' => 'number',
  100. 'name' => 'homepageRecentLimit',
  101. 'label' => 'Item Limit',
  102. 'value' => $this->config['homepageRecentLimit'],
  103. ),
  104. array(
  105. 'type' => 'select',
  106. 'name' => 'homepageRecentRefresh',
  107. 'label' => 'Refresh Seconds',
  108. 'value' => $this->config['homepageRecentRefresh'],
  109. 'options' => $this->timeOptions()
  110. ),
  111. ),
  112. 'Misc Options' => array(
  113. array(
  114. 'type' => 'input',
  115. 'name' => 'homepageEmbyLink',
  116. 'label' => 'Emby Homepage Link URL',
  117. 'value' => $this->config['homepageEmbyLink'],
  118. 'help' => 'Available variables: {id} {serverId}'
  119. ),
  120. array(
  121. 'type' => 'input',
  122. 'name' => 'embyTabName',
  123. 'label' => 'Emby Tab Name',
  124. 'value' => $this->config['embyTabName'],
  125. 'placeholder' => 'Only use if you have Emby in a reverse proxy'
  126. ),
  127. array(
  128. 'type' => 'input',
  129. 'name' => 'embyTabURL',
  130. 'label' => 'Emby Tab WAN URL',
  131. 'value' => $this->config['embyTabURL'],
  132. 'placeholder' => 'http(s)://hostname:port'
  133. ),
  134. array(
  135. 'type' => 'select',
  136. 'name' => 'cacheImageSize',
  137. 'label' => 'Image Cache Size',
  138. 'value' => $this->config['cacheImageSize'],
  139. 'options' => array(
  140. array(
  141. 'name' => 'Low',
  142. 'value' => '.5'
  143. ),
  144. array(
  145. 'name' => '1x',
  146. 'value' => '1'
  147. ),
  148. array(
  149. 'name' => '2x',
  150. 'value' => '2'
  151. ),
  152. array(
  153. 'name' => '3x',
  154. 'value' => '3'
  155. )
  156. )
  157. )
  158. ),
  159. 'Test Connection' => array(
  160. array(
  161. 'type' => 'blank',
  162. 'label' => 'Please Save before Testing'
  163. ),
  164. array(
  165. 'type' => 'button',
  166. 'label' => '',
  167. 'icon' => 'fa fa-flask',
  168. 'class' => 'pull-right',
  169. 'text' => 'Test Connection',
  170. 'attr' => 'onclick="testAPIConnection(\'emby\')"'
  171. ),
  172. )
  173. )
  174. );
  175. return array_merge($homepageInformation, $homepageSettings);
  176. }
  177. public function testConnectionEmby()
  178. {
  179. if (empty($this->config['embyURL'])) {
  180. $this->setAPIResponse('error', 'Emby URL is not defined', 422);
  181. return false;
  182. }
  183. if (empty($this->config['embyToken'])) {
  184. $this->setAPIResponse('error', 'Emby Token is not defined', 422);
  185. return false;
  186. }
  187. $url = $this->qualifyURL($this->config['embyURL']);
  188. $url = $url . "/Users?api_key=" . $this->config['embyToken'];
  189. $options = ($this->localURL($url)) ? array('verify' => false) : array();
  190. try {
  191. $response = Requests::get($url, array(), $options);
  192. if ($response->success) {
  193. $this->setAPIResponse('success', 'API Connection succeeded', 200);
  194. return true;
  195. } else {
  196. $this->setAPIResponse('error', 'Emby Connection Error', 500);
  197. return true;
  198. }
  199. } catch (Requests_Exception $e) {
  200. $this->setAPIResponse('error', $e->getMessage(), 500);
  201. return false;
  202. }
  203. }
  204. public function embyHomepagePermissions($key = null)
  205. {
  206. $permissions = [
  207. 'streams' => [
  208. 'enabled' => [
  209. 'homepageEmbyEnabled',
  210. 'homepageEmbyStreams'
  211. ],
  212. 'auth' => [
  213. 'homepageEmbyAuth',
  214. 'homepageEmbyStreamsAuth'
  215. ],
  216. 'not_empty' => [
  217. 'embyURL',
  218. 'embyToken'
  219. ]
  220. ],
  221. 'recent' => [
  222. 'enabled' => [
  223. 'homepageEmbyEnabled',
  224. 'homepageEmbyRecent'
  225. ],
  226. 'auth' => [
  227. 'homepageEmbyAuth',
  228. 'homepageEmbyRecentAuth'
  229. ],
  230. 'not_empty' => [
  231. 'embyURL',
  232. 'embyToken'
  233. ]
  234. ],
  235. 'metadata' => [
  236. 'enabled' => [
  237. 'homepageEmbyEnabled'
  238. ],
  239. 'auth' => [
  240. 'homepageEmbyAuth'
  241. ],
  242. 'not_empty' => [
  243. 'embyURL',
  244. 'embyToken'
  245. ]
  246. ]
  247. ];
  248. if (array_key_exists($key, $permissions)) {
  249. return $permissions[$key];
  250. } elseif ($key == 'all') {
  251. return $permissions;
  252. } else {
  253. return [];
  254. }
  255. }
  256. public function homepageOrderembynowplaying()
  257. {
  258. if ($this->homepageItemPermissions($this->embyHomepagePermissions('streams'))) {
  259. return '
  260. <div id="' . __FUNCTION__ . '">
  261. <div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Now Playing...</h2></div>
  262. <script>
  263. // Emby Stream
  264. homepageStream("emby", "' . $this->config['homepageStreamRefresh'] . '");
  265. // End Emby Stream
  266. </script>
  267. </div>
  268. ';
  269. }
  270. }
  271. public function homepageOrderembyrecent()
  272. {
  273. if ($this->homepageItemPermissions($this->embyHomepagePermissions('recent'))) {
  274. return '
  275. <div id="' . __FUNCTION__ . '">
  276. <div class="white-box homepage-loading-box"><h2 class="text-center" lang="en">Loading Recent...</h2></div>
  277. <script>
  278. // Emby Recent
  279. homepageRecent("emby", "' . $this->config['homepageRecentRefresh'] . '");
  280. // End Emby Recent
  281. </script>
  282. </div>
  283. ';
  284. }
  285. }
  286. public function getEmbyHomepageStreams()
  287. {
  288. if (!$this->homepageItemPermissions($this->embyHomepagePermissions('streams'), true)) {
  289. return false;
  290. }
  291. $url = $this->qualifyURL($this->config['embyURL']);
  292. $url = $url . '/Sessions?api_key=' . $this->config['embyToken'] . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
  293. $options = ($this->localURL($url)) ? array('verify' => false) : array();
  294. try {
  295. $response = Requests::get($url, array(), $options);
  296. if ($response->success) {
  297. $items = array();
  298. $emby = json_decode($response->body, true);
  299. foreach ($emby as $child) {
  300. if (isset($child['NowPlayingItem']) || isset($child['Name'])) {
  301. $items[] = $this->resolveEmbyItem($child);
  302. }
  303. }
  304. $api['content'] = array_filter($items);
  305. $this->setAPIResponse('success', null, 200, $api);
  306. return $api;
  307. } else {
  308. $this->setAPIResponse('error', 'Emby Error Occurred', 500);
  309. return false;
  310. }
  311. } catch (Requests_Exception $e) {
  312. $this->writeLog('error', 'Emby Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  313. $this->setAPIResponse('error', $e->getMessage(), 500);
  314. return false;
  315. }
  316. }
  317. public function getEmbyHomepageRecent()
  318. {
  319. if (!$this->homepageItemPermissions($this->embyHomepagePermissions('recent'), true)) {
  320. return false;
  321. }
  322. $url = $this->qualifyURL($this->config['embyURL']);
  323. $options = ($this->localURL($url)) ? array('verify' => false) : array();
  324. $username = false;
  325. $showPlayed = false;
  326. $userId = 0;
  327. try {
  328. if (isset($this->user['username'])) {
  329. $username = strtolower($this->user['username']);
  330. }
  331. // Get A User
  332. $userIds = $url . "/Users?api_key=" . $this->config['embyToken'];
  333. $response = Requests::get($userIds, array(), $options);
  334. if ($response->success) {
  335. $emby = json_decode($response->body, true);
  336. foreach ($emby as $value) { // Scan for admin user
  337. if (isset($value['Policy']) && isset($value['Policy']['IsAdministrator']) && $value['Policy']['IsAdministrator']) {
  338. $userId = $value['Id'];
  339. }
  340. if ($username && strtolower($value['Name']) == $username) {
  341. $userId = $value['Id'];
  342. $showPlayed = false;
  343. break;
  344. }
  345. }
  346. $url = $url . '/Users/' . $userId . '/Items/Latest?EnableImages=true&Limit=' . $this->config['homepageRecentLimit'] . '&api_key=' . $this->config['embyToken'] . ($showPlayed ? '' : '&IsPlayed=false') . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines&IncludeItemTypes=Series,Episode,MusicAlbum,Audio,Movie,Video';
  347. } else {
  348. $this->setAPIResponse('error', 'Emby Error Occurred', 500);
  349. return false;
  350. }
  351. $response = Requests::get($url, array(), $options);
  352. if ($response->success) {
  353. $items = array();
  354. $emby = json_decode($response->body, true);
  355. foreach ($emby as $child) {
  356. if (isset($child['NowPlayingItem']) || isset($child['Name'])) {
  357. $items[] = $this->resolveEmbyItem($child);
  358. }
  359. }
  360. $api['content'] = array_filter($items);
  361. $this->setAPIResponse('success', null, 200, $api);
  362. return $api;
  363. } else {
  364. $this->setAPIResponse('error', 'Emby Error Occurred', 500);
  365. return false;
  366. }
  367. } catch (Requests_Exception $e) {
  368. $this->writeLog('error', 'Emby Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  369. $this->setAPIResponse('error', $e->getMessage(), 500);
  370. return false;
  371. }
  372. }
  373. public function getEmbyHomepageMetadata($array)
  374. {
  375. if (!$this->homepageItemPermissions($this->embyHomepagePermissions('metadata'), true)) {
  376. return false;
  377. }
  378. $key = $array['key'] ?? null;
  379. if (!$key) {
  380. $this->setAPIResponse('error', 'Emby Metadata key is not defined', 422);
  381. return false;
  382. }
  383. $url = $this->qualifyURL($this->config['embyURL']);
  384. $options = ($this->localURL($url)) ? array('verify' => false) : array();
  385. $username = false;
  386. $showPlayed = false;
  387. $userId = 0;
  388. try {
  389. if (isset($this->user['username'])) {
  390. $username = strtolower($this->user['username']);
  391. }
  392. // Get A User
  393. $userIds = $url . "/Users?api_key=" . $this->config['embyToken'];
  394. $response = Requests::get($userIds, array(), $options);
  395. if ($response->success) {
  396. $emby = json_decode($response->body, true);
  397. foreach ($emby as $value) { // Scan for admin user
  398. if (isset($value['Policy']) && isset($value['Policy']['IsAdministrator']) && $value['Policy']['IsAdministrator']) {
  399. $userId = $value['Id'];
  400. }
  401. if ($username && strtolower($value['Name']) == $username) {
  402. $userId = $value['Id'];
  403. $showPlayed = false;
  404. break;
  405. }
  406. }
  407. $url = $url . '/Users/' . $userId . '/Items/' . $key . '?EnableImages=true&Limit=' . $this->config['homepageRecentLimit'] . '&api_key=' . $this->config['embyToken'] . ($showPlayed ? '' : '&IsPlayed=false') . '&Fields=Overview,People,Genres,CriticRating,Studios,Taglines';
  408. } else {
  409. $this->setAPIResponse('error', 'Emby Error Occurred', 500);
  410. return false;
  411. }
  412. $response = Requests::get($url, array(), $options);
  413. if ($response->success) {
  414. $items = array();
  415. $emby = json_decode($response->body, true);
  416. if (isset($emby['NowPlayingItem']) || isset($emby['Name'])) {
  417. $items[] = $this->resolveEmbyItem($emby);
  418. }
  419. $api['content'] = array_filter($items);
  420. $this->setAPIResponse('success', null, 200, $api);
  421. return $api;
  422. } else {
  423. $this->setAPIResponse('error', 'Emby Error Occurred', 500);
  424. return false;
  425. }
  426. } catch (Requests_Exception $e) {
  427. $this->writeLog('error', 'Emby Connect Function - Error: ' . $e->getMessage(), 'SYSTEM');
  428. $this->setAPIResponse('error', $e->getMessage(), 500);
  429. return false;
  430. }
  431. }
  432. public function resolveEmbyItem($itemDetails)
  433. {
  434. $item = isset($itemDetails['NowPlayingItem']['Id']) ? $itemDetails['NowPlayingItem'] : $itemDetails;
  435. // Static Height & Width
  436. $height = $this->getCacheImageSize('h');
  437. $width = $this->getCacheImageSize('w');
  438. $nowPlayingHeight = $this->getCacheImageSize('nph');
  439. $nowPlayingWidth = $this->getCacheImageSize('npw');
  440. $actorHeight = 450;
  441. $actorWidth = 300;
  442. // Cache Directories
  443. $cacheDirectory = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;
  444. $cacheDirectoryWeb = 'plugins/images/cache/';
  445. // Types
  446. //$embyItem['array-item'] = $item;
  447. //$embyItem['array-itemdetails'] = $itemDetails;
  448. switch (@$item['Type']) {
  449. case 'Series':
  450. $embyItem['type'] = 'tv';
  451. $embyItem['title'] = $item['Name'];
  452. $embyItem['secondaryTitle'] = '';
  453. $embyItem['summary'] = '';
  454. $embyItem['ratingKey'] = $item['Id'];
  455. $embyItem['thumb'] = $item['Id'];
  456. $embyItem['key'] = $item['Id'] . "-list";
  457. $embyItem['nowPlayingThumb'] = $item['Id'];
  458. $embyItem['nowPlayingKey'] = $item['Id'] . "-np";
  459. $embyItem['metadataKey'] = $item['Id'];
  460. $embyItem['nowPlayingImageType'] = isset($item['ImageTags']['Thumb']) ? 'Thumb' : (isset($item['BackdropImageTags'][0]) ? 'Backdrop' : '');
  461. break;
  462. case 'Episode':
  463. $embyItem['type'] = 'tv';
  464. $embyItem['title'] = $item['SeriesName'];
  465. $embyItem['secondaryTitle'] = '';
  466. $embyItem['summary'] = '';
  467. $embyItem['ratingKey'] = $item['Id'];
  468. $embyItem['thumb'] = (isset($item['SeriesId']) ? $item['SeriesId'] : $item['Id']);
  469. $embyItem['key'] = (isset($item['SeriesId']) ? $item['SeriesId'] : $item['Id']) . "-list";
  470. $embyItem['nowPlayingThumb'] = isset($item['ParentThumbItemId']) ? $item['ParentThumbItemId'] : (isset($item['ParentBackdropItemId']) ? $item['ParentBackdropItemId'] : false);
  471. $embyItem['nowPlayingKey'] = isset($item['ParentThumbItemId']) ? $item['ParentThumbItemId'] . '-np' : (isset($item['ParentBackdropItemId']) ? $item['ParentBackdropItemId'] . '-np' : false);
  472. $embyItem['metadataKey'] = $item['Id'];
  473. $embyItem['nowPlayingImageType'] = isset($item['ImageTags']['Thumb']) ? 'Thumb' : (isset($item['ParentBackdropImageTags'][0]) ? 'Backdrop' : '');
  474. $embyItem['nowPlayingTitle'] = @$item['SeriesName'] . ' - ' . @$item['Name'];
  475. $embyItem['nowPlayingBottom'] = 'S' . @$item['ParentIndexNumber'] . ' · E' . @$item['IndexNumber'];
  476. break;
  477. case 'MusicAlbum':
  478. case 'Audio':
  479. $embyItem['type'] = 'music';
  480. $embyItem['title'] = $item['Name'];
  481. $embyItem['secondaryTitle'] = '';
  482. $embyItem['summary'] = '';
  483. $embyItem['ratingKey'] = $item['Id'];
  484. $embyItem['thumb'] = $item['Id'];
  485. $embyItem['key'] = $item['Id'] . "-list";
  486. $embyItem['nowPlayingThumb'] = (isset($item['AlbumId']) ? $item['AlbumId'] : @$item['ParentBackdropItemId']);
  487. $embyItem['nowPlayingKey'] = $item['Id'] . "-np";
  488. $embyItem['metadataKey'] = isset($item['AlbumId']) ? $item['AlbumId'] : $item['Id'];
  489. $embyItem['nowPlayingImageType'] = (isset($item['ParentBackdropItemId']) ? "Primary" : "Backdrop");
  490. $embyItem['nowPlayingTitle'] = @$item['AlbumArtist'] . ' - ' . @$item['Name'];
  491. $embyItem['nowPlayingBottom'] = @$item['Album'];
  492. break;
  493. case 'Movie':
  494. $embyItem['type'] = 'movie';
  495. $embyItem['title'] = $item['Name'];
  496. $embyItem['secondaryTitle'] = '';
  497. $embyItem['summary'] = '';
  498. $embyItem['ratingKey'] = $item['Id'];
  499. $embyItem['thumb'] = $item['Id'];
  500. $embyItem['key'] = $item['Id'] . "-list";
  501. $embyItem['nowPlayingThumb'] = $item['Id'];
  502. $embyItem['nowPlayingKey'] = $item['Id'] . "-np";
  503. $embyItem['metadataKey'] = $item['Id'];
  504. $embyItem['nowPlayingImageType'] = isset($item['ImageTags']['Thumb']) ? "Thumb" : (isset($item['BackdropImageTags']) ? "Backdrop" : false);
  505. $embyItem['nowPlayingTitle'] = @$item['Name'];
  506. $embyItem['nowPlayingBottom'] = @$item['ProductionYear'];
  507. break;
  508. case 'Video':
  509. $embyItem['type'] = 'video';
  510. $embyItem['title'] = $item['Name'];
  511. $embyItem['secondaryTitle'] = '';
  512. $embyItem['summary'] = '';
  513. $embyItem['ratingKey'] = $item['Id'];
  514. $embyItem['thumb'] = $item['Id'];
  515. $embyItem['key'] = $item['Id'] . "-list";
  516. $embyItem['nowPlayingThumb'] = $item['Id'];
  517. $embyItem['nowPlayingKey'] = $item['Id'] . "-np";
  518. $embyItem['metadataKey'] = $item['Id'];
  519. $embyItem['nowPlayingImageType'] = isset($item['ImageTags']['Thumb']) ? "Thumb" : (isset($item['BackdropImageTags']) ? "Backdrop" : false);
  520. $embyItem['nowPlayingTitle'] = @$item['Name'];
  521. $embyItem['nowPlayingBottom'] = @$item['ProductionYear'];
  522. break;
  523. default:
  524. return false;
  525. }
  526. $embyItem['uid'] = $item['Id'];
  527. $embyItem['imageType'] = (isset($item['ImageTags']['Primary']) ? "Primary" : false);
  528. $embyItem['elapsed'] = isset($itemDetails['PlayState']['PositionTicks']) && $itemDetails['PlayState']['PositionTicks'] !== '0' ? (int)$itemDetails['PlayState']['PositionTicks'] : null;
  529. $embyItem['duration'] = isset($itemDetails['NowPlayingItem']['RunTimeTicks']) ? (int)$itemDetails['NowPlayingItem']['RunTimeTicks'] : (int)(isset($item['RunTimeTicks']) ? $item['RunTimeTicks'] : '');
  530. $embyItem['watched'] = ($embyItem['elapsed'] && $embyItem['duration'] ? floor(($embyItem['elapsed'] / $embyItem['duration']) * 100) : 0);
  531. $embyItem['transcoded'] = isset($itemDetails['TranscodingInfo']['CompletionPercentage']) ? floor((int)$itemDetails['TranscodingInfo']['CompletionPercentage']) : 100;
  532. $embyItem['stream'] = @$itemDetails['PlayState']['PlayMethod'];
  533. $embyItem['id'] = $item['ServerId'];
  534. $embyItem['session'] = @$itemDetails['DeviceId'];
  535. $embyItem['bandwidth'] = isset($itemDetails['TranscodingInfo']['Bitrate']) ? $itemDetails['TranscodingInfo']['Bitrate'] / 1000 : '';
  536. $embyItem['bandwidthType'] = 'wan';
  537. $embyItem['sessionType'] = (@$itemDetails['PlayState']['PlayMethod'] == 'Transcode') ? 'Transcoding' : 'Direct Playing';
  538. $embyItem['state'] = ((@(string)$itemDetails['PlayState']['IsPaused'] == '1') ? "pause" : "play");
  539. $embyItem['user'] = ($this->config['homepageShowStreamNames'] && $this->qualifyRequest($this->config['homepageShowStreamNamesAuth'])) ? @(string)$itemDetails['UserName'] : "";
  540. $embyItem['userThumb'] = '';
  541. $embyItem['userAddress'] = (isset($itemDetails['RemoteEndPoint']) ? $itemDetails['RemoteEndPoint'] : "x.x.x.x");
  542. $embyVariablesForLink = [
  543. '{id}' => $embyItem['uid'],
  544. '{serverId}' => $embyItem['id']
  545. ];
  546. $embyItem['address'] = $this->userDefinedIdReplacementLink($this->config['homepageEmbyLink'], $embyVariablesForLink);
  547. $embyItem['nowPlayingOriginalImage'] = 'api/v2/homepage/image?source=emby&type=' . $embyItem['nowPlayingImageType'] . '&img=' . $embyItem['nowPlayingThumb'] . '&height=' . $nowPlayingHeight . '&width=' . $nowPlayingWidth . '&key=' . $embyItem['nowPlayingKey'] . '$' . $this->randString();
  548. $embyItem['originalImage'] = 'api/v2/homepage/image?source=emby&type=' . $embyItem['imageType'] . '&img=' . $embyItem['thumb'] . '&height=' . $height . '&width=' . $width . '&key=' . $embyItem['key'] . '$' . $this->randString();
  549. $embyItem['openTab'] = $this->config['embyTabURL'] && $this->config['embyTabName'] ? true : false;
  550. $embyItem['tabName'] = $this->config['embyTabName'] ? $this->config['embyTabName'] : '';
  551. // Stream info
  552. $embyItem['userStream'] = array(
  553. 'platform' => @(string)$itemDetails['Client'],
  554. 'product' => @(string)$itemDetails['Client'],
  555. 'device' => @(string)$itemDetails['DeviceName'],
  556. 'stream' => @$itemDetails['PlayState']['PlayMethod'],
  557. 'videoResolution' => isset($itemDetails['NowPlayingItem']['MediaStreams'][0]['Width']) ? $itemDetails['NowPlayingItem']['MediaStreams'][0]['Width'] : '',
  558. 'throttled' => false,
  559. 'sourceVideoCodec' => isset($itemDetails['NowPlayingItem']['MediaStreams'][0]) ? $itemDetails['NowPlayingItem']['MediaStreams'][0]['Codec'] : '',
  560. 'videoCodec' => @$itemDetails['TranscodingInfo']['VideoCodec'],
  561. 'audioCodec' => @$itemDetails['TranscodingInfo']['AudioCodec'],
  562. 'sourceAudioCodec' => isset($itemDetails['NowPlayingItem']['MediaStreams'][1]) ? $itemDetails['NowPlayingItem']['MediaStreams'][1]['Codec'] : (isset($itemDetails['NowPlayingItem']['MediaStreams'][0]) ? $itemDetails['NowPlayingItem']['MediaStreams'][0]['Codec'] : ''),
  563. 'videoDecision' => $this->streamType(@$itemDetails['PlayState']['PlayMethod']),
  564. 'audioDecision' => $this->streamType(@$itemDetails['PlayState']['PlayMethod']),
  565. 'container' => isset($itemDetails['NowPlayingItem']['Container']) ? $itemDetails['NowPlayingItem']['Container'] : '',
  566. 'audioChannels' => @$itemDetails['TranscodingInfo']['AudioChannels']
  567. );
  568. // Genre catch all
  569. if (isset($item['Genres'])) {
  570. $genres = array();
  571. foreach ($item['Genres'] as $genre) {
  572. $genres[] = $genre;
  573. }
  574. }
  575. // Actor catch all
  576. if (isset($item['People'])) {
  577. $actors = array();
  578. foreach ($item['People'] as $key => $value) {
  579. if (@$value['PrimaryImageTag'] && @$value['Role']) {
  580. if (file_exists($cacheDirectory . (string)$value['Id'] . '-cast.jpg')) {
  581. $actorImage = $cacheDirectoryWeb . (string)$value['Id'] . '-cast.jpg';
  582. }
  583. if (file_exists($cacheDirectory . (string)$value['Id'] . '-cast.jpg') && (time() - 604800) > filemtime($cacheDirectory . (string)$value['Id'] . '-cast.jpg') || !file_exists($cacheDirectory . (string)$value['Id'] . '-cast.jpg')) {
  584. $actorImage = 'api/v2/homepage/image?source=emby&type=Primary&img=' . (string)$value['Id'] . '&height=' . $actorHeight . '&width=' . $actorWidth . '&key=' . (string)$value['Id'] . '-cast';
  585. }
  586. $actors[] = array(
  587. 'name' => (string)$value['Name'],
  588. 'role' => (string)$value['Role'],
  589. 'thumb' => $actorImage
  590. );
  591. }
  592. }
  593. }
  594. // Metadata information
  595. $embyItem['metadata'] = array(
  596. 'guid' => $item['Id'],
  597. 'summary' => @(string)$item['Overview'],
  598. 'rating' => @(string)$item['CommunityRating'],
  599. 'duration' => @(string)$item['RunTimeTicks'],
  600. 'originallyAvailableAt' => @(string)$item['PremiereDate'],
  601. 'year' => (string)isset($item['ProductionYear']) ? $item['ProductionYear'] : '',
  602. //'studio' => (string)$item['studio'],
  603. 'tagline' => @(string)$item['Taglines'][0],
  604. 'genres' => (isset($item['Genres'])) ? $genres : '',
  605. 'actors' => (isset($item['People'])) ? $actors : ''
  606. );
  607. if (file_exists($cacheDirectory . $embyItem['nowPlayingKey'] . '.jpg')) {
  608. $embyItem['nowPlayingImageURL'] = $cacheDirectoryWeb . $embyItem['nowPlayingKey'] . '.jpg';
  609. }
  610. if (file_exists($cacheDirectory . $embyItem['key'] . '.jpg')) {
  611. $embyItem['imageURL'] = $cacheDirectoryWeb . $embyItem['key'] . '.jpg';
  612. }
  613. if (file_exists($cacheDirectory . $embyItem['nowPlayingKey'] . '.jpg') && (time() - 604800) > filemtime($cacheDirectory . $embyItem['nowPlayingKey'] . '.jpg') || !file_exists($cacheDirectory . $embyItem['nowPlayingKey'] . '.jpg')) {
  614. $embyItem['nowPlayingImageURL'] = 'api/v2/homepage/image?source=emby&type=' . $embyItem['nowPlayingImageType'] . '&img=' . $embyItem['nowPlayingThumb'] . '&height=' . $nowPlayingHeight . '&width=' . $nowPlayingWidth . '&key=' . $embyItem['nowPlayingKey'] . '';
  615. }
  616. if (file_exists($cacheDirectory . $embyItem['key'] . '.jpg') && (time() - 604800) > filemtime($cacheDirectory . $embyItem['key'] . '.jpg') || !file_exists($cacheDirectory . $embyItem['key'] . '.jpg')) {
  617. $embyItem['imageURL'] = 'api/v2/homepage/image?source=emby&type=' . $embyItem['imageType'] . '&img=' . $embyItem['thumb'] . '&height=' . $height . '&width=' . $width . '&key=' . $embyItem['key'] . '';
  618. }
  619. if (!$embyItem['nowPlayingThumb']) {
  620. $embyItem['nowPlayingOriginalImage'] = $embyItem['nowPlayingImageURL'] = "plugins/images/cache/no-np.png";
  621. $embyItem['nowPlayingKey'] = "no-np";
  622. }
  623. if (!$embyItem['thumb']) {
  624. $embyItem['originalImage'] = $embyItem['imageURL'] = "plugins/images/cache/no-list.png";
  625. $embyItem['key'] = "no-list";
  626. }
  627. if (isset($useImage)) {
  628. $embyItem['useImage'] = $useImage;
  629. }
  630. return $embyItem;
  631. }
  632. }