Don't like ads? PRO users don't see any ads ;-)
Guest

AWX

By: a guest on Oct 13th, 2011  |  syntax: JavaScript  |  size: 37.55 KB  |  hits: 49  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2.  *  AWX - Ajax based Webinterface for XBMC
  3.  *  Copyright (C) 2010  MKay
  4.  *
  5.  *  This program is free software: you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation, either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program.  If not, see <http://www.gnu.org/licenses/>
  17.  */
  18.  
  19.  
  20. // TODO remove debug function
  21. function objToStr(obj, indent) {
  22.         var out = '';
  23.         for (var e in obj) {
  24.                 if (typeof obj[e] == 'object') {
  25.                         out += indent + e + ":\n" + objToStr(obj[e], indent+'     ') + "\n";
  26.  
  27.                 } else {
  28.                         out += indent + e + ": " + obj[e] + "\n";
  29.                 }
  30.         }
  31.         return out;
  32. };
  33.  
  34.  
  35.  
  36. var xbmc = {};
  37.  
  38.  
  39.  
  40. (function($) {
  41.  
  42.         /* ########################### *\
  43.          |  xbmc-lib
  44.          |
  45.         \* ########################### */
  46.         $.extend(xbmc, {
  47.  
  48.                 movieThumbType: 'Poster',
  49.                 tvshowThumbType: 'Banner',
  50.  
  51.                 xbmcHasQuit: false,
  52.                 timeout: 10000,
  53.  
  54.                 input: function(options) {
  55.                         var settings = {
  56.                                 type: 'select',
  57.                                 onSuccess: null,
  58.                                 onError: null
  59.                         };
  60.                        
  61.                         $.extend(settings, options);           
  62.                         var commands = {left: 1, right: 2, up: 3, down: 4, select: 7, back: 9, home: 10 };
  63.  
  64.                         xbmc.httpapi(
  65.                                 'action', commands[ settings.type] ,
  66.                                 settings.onSuccess,
  67.                                 settings.Error
  68.                         );
  69.  
  70.                         return true;
  71.                 },
  72.                 httpapi: function(command, parameter, onError, onComplete, asyncRequest) {
  73.                         if (typeof asyncRequest === 'undefined')
  74.                                 asyncRequest = true;
  75.  
  76.                         if (!this.xbmcHasQuit) {
  77.                                 $.ajax({
  78.                                         async: asyncRequest,
  79.                                         type: 'GET',
  80.                                         url: './xbmcCmds/xbmcHttp',            
  81.                                         data: {
  82.                                                 "command": command,
  83.                                                 "parameter": parameter
  84.                                         },
  85.                                         dataType: 'text',
  86.                                         cache: false,
  87.                                         timeout: this.timeout,
  88.                                         success: function(result, textStatus, XMLHttpRequest) {
  89.                                        
  90.                                                 // its possible to get here on timeouts. --> error
  91.                                                 if (XMLHttpRequest.readyState==4 && XMLHttpRequest.status==0) {
  92.                                                         if (onError) {
  93.                                                                 onError({"error" : { "ajaxFailed" : true, "xhr" : XMLHttpRequest, "status" : textStatus }});
  94.                                                         }
  95.                                                         return;
  96.                                                 }
  97.                                                
  98.                                                 // Example Error-Response: { "error" : { "code" : -32601, "message" : "Method not found." } }
  99.                                                 if (result.error) {
  100.                                                         if (onError) { onError(result); }
  101.                                                         return;
  102.                                                 }
  103.                                                        
  104.                                                 if (onSuccess) { onSuccess(result); }
  105.                                         },
  106.                                         error: function(XMLHttpRequest, textStatus, errorThrown) {
  107.                                                 if (onError) {
  108.                                                         onError({"error" : { "ajaxFailed" : true, "xhr" : XMLHttpRequest, "status" : textStatus, "errorThrown" : errorThrown }});
  109.                                                 }
  110.                                         },
  111.                                         complete: function(XMLHttpRequest, textStatus) {
  112.                                                 if (onComplete) { onComplete(); }
  113.                                         }
  114.                                 });
  115.                         }
  116.                 },             
  117.  
  118.  
  119.                 init: function(initContainer, callback) {
  120.                         xbmc.periodicUpdater.start();
  121.                         var timeout = parseInt(mkf.cookieSettings.get('timeout'));
  122.                         this.timeout = (isNaN(timeout) || timeout < 5 || timeout > 120)? 10000: timeout*1000;
  123.                         this.detectThumbTypes(initContainer, callback);
  124.                 },
  125.  
  126.  
  127.  
  128.                 sendCommand: function(command, onSuccess, onError, onComplete, asyncRequest) {
  129.                         if (typeof asyncRequest === 'undefined')
  130.                                 asyncRequest = true;
  131.  
  132.                         if (!this.xbmcHasQuit) {
  133.                                 $.ajax({
  134.                                         async: asyncRequest,
  135.                                         type: 'POST',
  136.                                         url: './jsonrpc?awx',
  137.                                         data: command,
  138.                                         dataType: 'json',
  139.                                         cache: false,
  140.                                         timeout: this.timeout,
  141.                                         success: function(result, textStatus, XMLHttpRequest) {
  142.  
  143.                                                 // its possible to get here on timeouts. --> error
  144.                                                 if (XMLHttpRequest.readyState==4 && XMLHttpRequest.status==0) {
  145.                                                         if (onError) {
  146.                                                                 onError({"error" : { "ajaxFailed" : true, "xhr" : XMLHttpRequest, "status" : textStatus }});
  147.                                                         }
  148.                                                         return;
  149.                                                 }
  150.  
  151.                                                 // Example Error-Response: { "error" : { "code" : -32601, "message" : "Method not found." } }
  152.                                                 if (result.error) {
  153.                                                         if (onError) { onError(result); }
  154.                                                         return;
  155.                                                 }
  156.  
  157.                                                 if (onSuccess) { onSuccess(result); }
  158.                                         },
  159.                                         error: function(XMLHttpRequest, textStatus, errorThrown) {
  160.                                                 if (onError) {
  161.                                                         onError({"error" : { "ajaxFailed" : true, "xhr" : XMLHttpRequest, "status" : textStatus, "errorThrown" : errorThrown }});
  162.                                                 }
  163.                                         },
  164.                                         complete: function(XMLHttpRequest, textStatus) {
  165.                                                 if (onComplete) { onComplete(); }
  166.                                         }
  167.                                 });
  168.                         }
  169.                 },
  170.  
  171.  
  172.  
  173.                 getMovieThumbType: function() {
  174.                         return this.movieThumbType;
  175.                 },
  176.  
  177.  
  178.  
  179.                 getTvShowThumbType: function() {
  180.                         return this.tvshowThumbType;
  181.                 },
  182.  
  183.  
  184.  
  185.                 hasQuit: function() {
  186.                         return this.xbmcHasQuit;
  187.                 },
  188.  
  189.  
  190.  
  191.                 setHasQuit: function() {
  192.                         this.xbmcHasQuit = true;
  193.                 },
  194.  
  195.  
  196.  
  197.                 formatTime: function (seconds) {
  198.                         var hh = Math.floor(seconds / 3600);
  199.                         var mm = Math.floor((seconds - hh*3600) / 60);
  200.                         var ss = seconds - hh*3600 - mm*60;
  201.                         var result = '';
  202.                         if (hh > 0)
  203.                                 result = (hh<10 ? '0' : '') + hh + ':';
  204.                         return  result + (mm<10 ? '0' : '') + mm + ':' + (ss<10 ? '0' : '') + ss ;
  205.                 },
  206.  
  207.  
  208.  
  209.                 getSeconds: function (time) {
  210.                         var seconds = 0;
  211.                         var i = 0;
  212.                         while (time.length > 0) {
  213.                                 var next = time.substr(time.length-2);
  214.                                 seconds += Math.pow(60, i) * parseInt(next); // works for hours, minutes, seconds
  215.                                 if (time.length > 0) {
  216.                                         time = time.substr(0, time.length-3);
  217.                                 }
  218.                                 ++i;
  219.                         }
  220.  
  221.                         return seconds;
  222.                 },
  223.  
  224.  
  225.  
  226.                 getThumbUrl: function(url) {
  227.                         return './vfs/' + encodeURI(url);
  228.                 },
  229.  
  230.  
  231.  
  232.                 detectThumbTypes: function(initContainer, callback) {
  233.                         xbmc.sendCommand(
  234.                                 //'{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "id": 1}',
  235.                                 '{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": {"properties" : ["thumbnail"]}, "id": 1}',
  236.  
  237.                                 function (response) {
  238.                                         if (response.result.tvshows) {
  239.                                                 var $img = $('<img />').appendTo(initContainer);
  240.                                                 $.each(response.result.tvshows, function(i, tvshow) {
  241.                                                         if (tvshow.thumbnail) {
  242.                                                                 $img
  243.                                                                         .bind('load', function() {
  244.                                                                                 if (this.width/this.height < 5) {
  245.                                                                                         xbmc.tvshowThumbType = 'Poster';
  246.                                                                                 } // else 'Banner'
  247.                                                                                 callback();
  248.                                                                         })
  249.                                                                         .bind('error', function() {
  250.                                                                                 // use default: 'Banner'
  251.                                                                                 callback(mkf.lang.get('message_failed_detect_thumb_type'));
  252.                                                                         })
  253.                                                                         .attr('src', xbmc.getThumbUrl(tvshow.thumbnail));
  254.  
  255.                                                                 return false;
  256.                                                         }
  257.                                                 });
  258.                                         } else {
  259.                                                 // no tv shows
  260.                                                 callback();
  261.                                         }
  262.                                 },
  263.  
  264.                                 function (response) {
  265.                                         callback(mkf.lang.get('message_failed_detect_thumb_type'));
  266.                                 },
  267.  
  268.                                 null,
  269.                                 false // not async
  270.                         );
  271.                 },
  272.  
  273.  
  274.  
  275.                 setVolume: function(options) {
  276.                         var settings = {
  277.                                 volume: 50,
  278.                                 onSuccess: null,
  279.                                 onError: null
  280.                         };
  281.                         $.extend(settings, options);
  282.  
  283.                         xbmc.sendCommand(
  284.                                 '{"jsonrpc": "2.0", "method": "XBMC.SetVolume", "params": ' + settings.volume + ', "id": 1}',
  285.                                 settings.onSuccess,
  286.                                 settings.onError
  287.                         );
  288.                 },
  289.  
  290.  
  291.  
  292.                 shutdown: function(options) {
  293.                         var settings = {
  294.                                 type: 'shutdown',
  295.                                 onSuccess: null,
  296.                                 onError: null
  297.                         };
  298.                         $.extend(settings, options);
  299.  
  300.                         var commands = {shutdown: 'System.Shutdown', quit: 'Application.Quit', suspend: 'System.Suspend', reboot: 'System.Reboot'};
  301.  
  302.                         if (commands[settings.type]) {
  303.                                 xbmc.sendCommand(
  304.                                         '{"jsonrpc": "2.0", "method": "' + commands[settings.type] + '", "id": 1}',
  305.                                         function () {
  306.                                                 xbmc.setHasQuit();
  307.                                                 settings.onSuccess();
  308.                                         },
  309.                                         settings.onError
  310.                                 );
  311.                                 return true;
  312.                         }
  313.  
  314.                         return false;
  315.                 },
  316.  
  317.  
  318.  
  319.                 control: function(options) {
  320.                         var settings = {
  321.                                 type: 'play',
  322.                                 onSuccess: null,
  323.                                 onError: null
  324.                         };
  325.                         $.extend(settings, options);
  326.  
  327.                         var commands = {play: 'PlayPause', stop: 'Stop', prev: 'SkipPrevious', next: 'SkipNext', shuffle: 'Shuffle', unshuffle: 'Unshuffle'};
  328.  
  329.                         if (commands[settings.type]) {
  330.                                 xbmc.sendCommand(
  331.                                         '{"jsonrpc": "2.0", "method": "Player.GetActivePlayers", "id": 1}',
  332.  
  333.                                         function (response) {
  334.                                                 var playerResult = response.result;
  335.                                                 var currentPlayer = '';
  336.                                                 var playeridis = '';
  337.  
  338.                                                 if (playerResult.audio)                 currentPlayer = 'Audio';
  339.                                                 else if (playerResult.video)    currentPlayer = 'Video';
  340.                                                 else if (playerResult.picture)  currentPlayer = 'Picture';
  341.                                                
  342.                                                 if (playerResult.audio)                 playeridis = 0;
  343.                                                 else if (playerResult.video)    playeridis = 1;
  344.                                                 else if (playerResult.picture)  playeridis = 2;
  345.  
  346.                                                 if (currentPlayer != '') {
  347.                                                         var tmp = (settings.type=='shuffle' || settings.type=='unshuffle'?
  348.                                                                                 'Playlist': 'Player');
  349.                                                         xbmc.sendCommand(
  350.                                                                 //'{"jsonrpc": "2.0", "method": "' + currentPlayer + tmp + '.' + commands[settings.type] + '", "id": 1}',
  351.                                                                 '{"jsonrpc": "2.0", "method": "Player.' + commands[settings.type] + '", "params": { "playerid": ' + playeridis + ' }, "id": 1}',
  352.                                                                 settings.onSuccess,
  353.                                                                 settings.onError
  354.                                                         );
  355.                                                 }
  356.                                         },
  357.                                         settings.onError
  358.                                 );
  359.                                 return true;
  360.                         }
  361.                         return false;
  362.                 },
  363.  
  364.  
  365.  
  366.                 seekPercentage: function(options) {
  367.                         var settings = {
  368.                                 percentage: 0,
  369.                                 onSuccess: null,
  370.                                 onError: null
  371.                         };
  372.                         $.extend(settings, options);
  373.  
  374.                         xbmc.sendCommand(
  375.                                 '{"jsonrpc": "2.0", "method": "Player.GetActivePlayers", "id": 1}',
  376.  
  377.                                 function (response) {
  378.                                         var playerResult = response.result;
  379.                                         var player = '';
  380.  
  381.                                         if (playerResult.audio) {
  382.                                                 player = 'Audio';
  383.  
  384.                                         } else if (playerResult.video) {
  385.                                                 player = 'Video';
  386.  
  387.                                         } else {
  388.                                                 // No player is active
  389.                                                 return;
  390.                                         }
  391.  
  392.                                         xbmc.sendCommand(
  393.                                                 '{"jsonrpc": "2.0", "method": "' + player + 'Player.SeekPercentage", "params": ' + settings.percentage + ', "id": 1}',
  394.  
  395.                                                 settings.onSuccess,
  396.                                                 settings.onError
  397.                                         );
  398.                                 },
  399.  
  400.                                 settings.onError
  401.                         );
  402.                 },
  403.  
  404.  
  405.  
  406.                 getArtists: function(options) {
  407.                         var settings = {
  408.                                 onSuccess: null,
  409.                                 onError: null
  410.                         };
  411.                         $.extend(settings, options);
  412.  
  413.                         xbmc.sendCommand(
  414.                                 '{"jsonrpc": "2.0", "method": "AudioLibrary.GetArtists", "params": {"sort": { "order": "ascending", "method": "artist" } }, "id": 1}',
  415.  
  416.                                 function(response) {
  417.                                         settings.onSuccess(response.result);
  418.                                 },
  419.  
  420.                                 settings.onError
  421.                         );
  422.                 },
  423.  
  424.  
  425.  
  426.                 getArtistsAlbums: function(options) {
  427.                         var settings = {
  428.                                 artistid: 0,
  429.                                 onSuccess: null,
  430.                                 onError: null
  431.                         };
  432.                         $.extend(settings, options);
  433.  
  434.                         xbmc.sendCommand(
  435.                                 '{"jsonrpc": "2.0", "method": "AudioLibrary.GetAlbums", "params": { "artistid" : ' + settings.artistid + ', "properties": ["artist", "genre", "rating", "thumbnail"] }, "id": 1}',
  436.  
  437.                                 function(response) {
  438.                                         settings.onSuccess(response.result);
  439.                                 },
  440.  
  441.                                 settings.onError
  442.                         );
  443.                 },
  444.  
  445.  
  446.  
  447.                 getAlbums: function(options) {
  448.                         var settings = {
  449.                                 onSuccess: null,
  450.                                 onError: null
  451.                         };
  452.                         $.extend(settings, options);
  453.  
  454.                         var order = mkf.cookieSettings.get('albumOrder')=='album'? 'label' : 'artist';
  455.  
  456.                         xbmc.sendCommand(
  457.                                 '{"jsonrpc": "2.0", "method": "AudioLibrary.GetAlbums", "params": {"properties": ["artist", "genre", "rating", "thumbnail"], "sort": { "order": "ascending", "method": "' + order + '" } }, "id": 1}',
  458.  
  459.                                 function(response) {
  460.                                         settings.onSuccess(response.result);
  461.                                 },
  462.  
  463.                                 settings.onError
  464.                         );
  465.                 },
  466.  
  467.  
  468.  
  469.                 addSongToPlaylist: function(options) {
  470.                         var settings = {
  471.                                 songid: 0,
  472.                                 onSuccess: null,
  473.                                 onError: null,
  474.                                 async: true
  475.                         };
  476.                         $.extend(settings, options);
  477.  
  478.                         xbmc.sendCommand(
  479.                                 '{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"item": {"songid": ' + settings.songid + '}, "playlistid": 0}, "id": 1}',
  480.                                 settings.onSuccess,
  481.                                 settings.onError,
  482.                                 null,
  483.                                 settings.async
  484.                         );
  485.                 },
  486.  
  487.  
  488.  
  489.                 addAudioFileToPlaylist: function(options) {
  490.                         var settings = {
  491.                                 file: '',
  492.                                 onSuccess: null,
  493.                                 onError: null,
  494.                                 async: true
  495.                         };
  496.                         $.extend(settings, options);
  497.  
  498.                         xbmc.sendCommand(
  499.                                 //'{"jsonrpc": "2.0", "method": "Playlist.Add", "params": { "item": {"file": "' + settings.file.replace(/\\/g, "\\\\") + '"} }, "id": 1}',
  500.                                 '{"jsonrpc": "2.0", "method": "Playlist.Add", "params": { "item": {"file": "' + settings.file.replace(/\\/g, "\\\\") + '"}, "playlistid": 0 }, "id": 1}',
  501.                                 settings.onSuccess,
  502.                                 settings.onError,
  503.                                 null,
  504.                                 settings.async
  505.                         );
  506.                 },
  507.  
  508.  
  509.  
  510.                 addAudioFolderToPlaylist: function(options) {
  511.                         var settings = {
  512.                                 folder: '',
  513.                                 onSuccess: null,
  514.                                 onError: null
  515.                         };
  516.                         $.extend(settings, options);
  517.  
  518.                         xbmc.getDirectory({
  519.                                 media: 'Audio',
  520.                                 directory: settings.folder.replace(/\\/g, "\\\\"),
  521.  
  522.                                 onSuccess: function(result) {
  523.                                         var error = false;
  524.                                         var files = result.files;
  525.                                         if (files) {
  526.                                                 files.sort(function(a, b) {
  527.                                                         if (a.file < b.file) return -1;
  528.                                                         if (a.file > b.file) return 1;
  529.                                                         return 0;
  530.                                                 });
  531.                                                 $.each(files, function(i, file)  {
  532.                                                         xbmc.addAudioFileToPlaylist({
  533.                                                                 'file': file.file,
  534.                                                                 onError: function() {
  535.                                                                         error = true;
  536.                                                                 },
  537.                                                                 async: false
  538.                                                         });
  539.                                                 });
  540.                                         }
  541.                                         if (error) {
  542.                                                 settings.onError(mkf.lang.get('message_failed_add_files_to_playlist'));
  543.                                         } else {
  544.                                                 settings.onSuccess();
  545.                                         }
  546.                                 },
  547.  
  548.                                 onError: function() {
  549.                                         settings.onError(mkf.lang.get('message_failed_folders_content'));
  550.                                 }
  551.                         });
  552.                 },
  553.  
  554.  
  555.  
  556.                 addAlbumToPlaylist: function(options) {
  557.                         var settings = {
  558.                                 albumid: 0,
  559.                                 onSuccess: null,
  560.                                 onError: null
  561.                         };
  562.                         $.extend(settings, options);
  563.  
  564.                         // Comparator to sort albums by tracknumber ASC
  565.                         var songComparator = function(a, b) {
  566.                                 return a.tracknumber - b.tracknumber;
  567.                         }
  568.  
  569.                         xbmc.sendCommand(
  570.                                 '{"jsonrpc": "2.0", "method": "AudioLibrary.GetSongs", "params": {"albumid": ' + settings.albumid + ', "properties": ["track"]}, "id": 1}',
  571.  
  572.                                 function(response) {
  573.                                         if (!response.result || !response.result.songs) {
  574.                                                 settings.onError(mkf.lang.get('message_album_not_found'));
  575.                                                 return;
  576.                                         }
  577.  
  578.                                         var songs = response.result.songs;
  579.                                         songs.sort(songComparator); // sort by tracknumber ASC
  580.                                         var errors = 0;
  581.  
  582.                                         // add each song of the album to the playlist
  583.                                         $.each(songs, function(i, song)  {
  584.                                                 // add Song to playlist ... max. 2 retries if add failed
  585.                                                 xbmc.addSongToPlaylist({songid: song.songid, async: false, onError: function() {
  586.                                                         xbmc.addSongToPlaylist({songid: song.songid, async: false, onError: function() {
  587.                                                                 xbmc.addSongToPlaylist({songid: song.songid, async: false, onError: function() {
  588.                                                                         errors += 1;
  589.                                                                 }});
  590.                                                         }});
  591.                                                 }});
  592.                                         });
  593.  
  594.                                         if (errors != 0) {
  595.                                                 settings.onError(mkf.lang.get('message_failed_add_songs_to_playlist', [errors]));
  596.                                         } else {
  597.                                                 settings.onSuccess();
  598.                                         }
  599.                                 },
  600.  
  601.                                 function(response) {
  602.                                         settings.onError(mkf.lang.get('message_failed_albums_songs'));
  603.                                 }
  604.                         );
  605.                 },
  606.  
  607.  
  608.  
  609.                 clearAudioPlaylist: function(options) {
  610.                         var settings = {
  611.                                 onSuccess: null,
  612.                                 onError: null,
  613.                         };
  614.                         $.extend(settings, options);
  615.  
  616.                         xbmc.sendCommand(
  617.                                 '{"jsonrpc": "2.0", "method": "Playlist.Clear", "params": { "playlistid": 0 }, "id": 1}',
  618.                                 settings.onSuccess,
  619.                                 settings.onError
  620.                         );
  621.                 },
  622.  
  623.  
  624.  
  625.                 playAudio: function(options) {
  626.                         var settings = {
  627.                                 item: 0,
  628.                                 onSuccess: null,
  629.                                 onError: null,
  630.                         };
  631.                         $.extend(settings, options);
  632.  
  633.                         xbmc.sendCommand(
  634.                                 // '{"jsonrpc": "2.0", "method": "Player.Open", "params": {"item": ' + settings.item + '}, "id": 1}',
  635.                                 '{"jsonrpc": "2.0", "method": "Player.Open", "params" : { "item" : { "playlistid" : 0, "position": ' + settings.item + ' } }, "id": 1}',
  636.                                 settings.onSuccess,
  637.                                 function(response) {
  638.                                         settings.onError(mkf.lang.get('message_failed_play' + 'settings.item'));
  639.                                 }
  640.                         );
  641.                 },
  642.  
  643.  
  644.  
  645.                 playAlbum: function(options) {
  646.                         var settings = {
  647.                                 albumid: 0,
  648.                                 onSuccess: null,
  649.                                 onError: null,
  650.                         };
  651.                         $.extend(settings, options);
  652.  
  653.                         this.clearAudioPlaylist({
  654.                                 onSuccess: function() {
  655.                                         xbmc.addAlbumToPlaylist({
  656.                                                 albumid: settings.albumid,
  657.  
  658.                                                 onSuccess: function() {
  659.                                                         xbmc.playAudio({
  660.                                                                 onSuccess: settings.onSuccess,
  661.                                                                 onError: function(errorText) {
  662.                                                                         settings.onError(errorText);
  663.                                                                 }
  664.                                                         });
  665.                                                 },
  666.  
  667.                                                 onError: function(errorText) {
  668.                                                         settings.onError(errorText);
  669.                                                 }
  670.                                         });
  671.                                 },
  672.  
  673.                                 onError: function() {
  674.                                         settings.onError(mkf.lang.get('message_failed_clear_playlist'));
  675.                                 }
  676.                         });
  677.                 },
  678.  
  679.  
  680.  
  681.                 playSong: function(options) {
  682.                         var settings = {
  683.                                 songid: 0,
  684.                                 onSuccess: null,
  685.                                 onError: null,
  686.                         };
  687.                         $.extend(settings, options);
  688.  
  689.                         this.clearAudioPlaylist({
  690.                                 onSuccess: function() {
  691.                                         xbmc.addSongToPlaylist({
  692.                                                 songid: settings.songid,
  693.  
  694.                                                 onSuccess: function() {
  695.                                                         xbmc.playAudio({
  696.                                                                 onSuccess: settings.onSuccess,
  697.                                                                 onError: function(errorText) {
  698.                                                                         settings.onError(errorText);
  699.                                                                 }
  700.                                                         });
  701.                                                 },
  702.  
  703.                                                 onError: function() {
  704.                                                         settings.onError(mkf.lang.get('message_failed_add_song_to_playlist'));
  705.                                                 }
  706.                                         });
  707.                                 },
  708.  
  709.                                 onError: function() {
  710.                                         settings.onError(mkf.lang.get('message_failed_clear_playlist'));
  711.                                 }
  712.                         });
  713.                 },
  714.  
  715.  
  716.  
  717.                 playAudioFile: function(options) {
  718.                         var settings = {
  719.                                 file: '',
  720.                                 onSuccess: null,
  721.                                 onError: null,
  722.                         };
  723.                         $.extend(settings, options);
  724.  
  725.                         this.clearAudioPlaylist({
  726.                                 onSuccess: function() {
  727.                                         xbmc.addAudioFileToPlaylist({
  728.                                                 file: settings.file,
  729.  
  730.                                                 onSuccess: function() {
  731.                                                         xbmc.playAudio({
  732.                                                                 onSuccess: settings.onSuccess,
  733.                                                                 onError: function(errorText) {
  734.                                                                         settings.onError(errorText);
  735.                                                                 }
  736.                                                         });
  737.                                                 },
  738.  
  739.                                                 onError: function() {
  740.                                                         settings.onError(mkf.lang.get('message_failed_add_file_to_playlist'));
  741.                                                 }
  742.                                         });
  743.                                 },
  744.  
  745.                                 onError: function() {
  746.                                         settings.onError(mkf.lang.get('message_failed_clear_playlist'));
  747.                                 }
  748.                         });
  749.                 },
  750.  
  751.  
  752.  
  753.                 playAudioFolder: function(options) {
  754.                         var settings = {
  755.                                 folder: '',
  756.                                 onSuccess: null,
  757.                                 onError: null,
  758.                         };
  759.                         $.extend(settings, options);
  760.  
  761.                         this.clearAudioPlaylist({
  762.                                 onSuccess: function() {
  763.                                         xbmc.addAudioFolderToPlaylist({
  764.                                                 folder: settings.folder,
  765.  
  766.                                                 onSuccess: function() {
  767.                                                         xbmc.playAudio({
  768.                                                                 onSuccess: settings.onSuccess,
  769.                                                                 onError: function(errorText) {
  770.                                                                         settings.onError(errorText);
  771.                                                                 }
  772.                                                         });
  773.                                                 },
  774.  
  775.                                                 onError: function(errorText) {
  776.                                                         settings.onError(errorText);
  777.                                                 }
  778.                                         });
  779.                                 },
  780.  
  781.                                 onError: function() {
  782.                                         settings.onError(mkf.lang.get('message_failed_clear_playlist'));
  783.                                 }
  784.                         });
  785.                 },
  786.  
  787.  
  788.  
  789.                 getAlbumsSongs: function(options) {
  790.                         var settings = {
  791.                                 albumid: 0,
  792.                                 onSuccess: null,
  793.                                 onError: null,
  794.                         };
  795.                         $.extend(settings, options);
  796.  
  797.                         xbmc.sendCommand(
  798.                                 '{"jsonrpc": "2.0", "method": "AudioLibrary.GetSongs", "params": { "albumid": ' + settings.albumid + ', "properties": ["artist", "track"] }, "id": 1}',
  799.  
  800.                                 function(response) {
  801.                                         settings.onSuccess(response.result);
  802.                                 },
  803.  
  804.                                 settings.onError
  805.                         );
  806.                 },
  807.  
  808.  
  809.  
  810.                 getAudioPlaylist: function(options) {
  811.                         var settings = {
  812.                                 onSuccess: null,
  813.                                 onError: null,
  814.                         };
  815.                         $.extend(settings, options);
  816.  
  817.                         xbmc.sendCommand(
  818.                                 '{"jsonrpc": "2.0", "method": "Playlist.GetItems", "params": { "properties": ["title", "album", "artist", "duration"], "playlistid": 0 }, "id": 1}',
  819.  
  820.                                 function(response) {
  821.                                         settings.onSuccess(response.result);
  822.                                 },
  823.  
  824.                                 settings.onError
  825.                         );
  826.                 },
  827.  
  828.  
  829.  
  830.                 clearVideoPlaylist: function(options) {
  831.                         var settings = {
  832.                                 onSuccess: null,
  833.                                 onError: null,
  834.                         };
  835.                         $.extend(settings, options);
  836.  
  837.                         xbmc.sendCommand(
  838.                                 '{"jsonrpc": "2.0", "method": "Playlist.Clear", "params": { "playlistid": 1 }, "id": 1}',
  839.                                 settings.onSuccess,
  840.                                 settings.onError
  841.                         );
  842.                 },
  843.  
  844.  
  845.  
  846.                 playVideo: function(options) {
  847.                         var settings = {
  848.                                 item: 0,
  849.                                 onSuccess: null,
  850.                                 onError: null,
  851.                         };
  852.                         $.extend(settings, options);
  853.  
  854.                         xbmc.sendCommand(
  855.                                 // '{"jsonrpc": "2.0", "method": "Player.Open", "params": {"item": ' + settings.item + '}, "id": 1}',
  856.                                 '{"jsonrpc": "2.0", "method": "Player.Open", "params" : { "item" : { "playlistid" : 1, "position": ' + settings.item + ' } }, "id": 1}',
  857.                                 settings.onSuccess,
  858.                                 function(response) {
  859.                                         settings.onError(mkf.lang.get('message_failed_play'));
  860.                                 }
  861.                         );
  862.                 },
  863.  
  864.  
  865.  
  866.                 addVideoFileToPlaylist: function(options) {
  867.                         var settings = {
  868.                                 file: '',
  869.                                 onSuccess: null,
  870.                                 onError: null,
  871.                                 async: true
  872.                         };
  873.                         $.extend(settings, options);
  874.  
  875.                         xbmc.sendCommand(
  876.                                 '{"jsonrpc": "2.0", "method": "Playlist.Add", "params": { "file": "' + settings.file.replace(/\\/g, "\\\\") + '", "playlistid": 1 }, "id": 1}',
  877.                                 settings.onSuccess,
  878.                                 settings.onError,
  879.                                 null,
  880.                                 settings.async
  881.                         );
  882.                 },
  883.  
  884.  
  885.  
  886.                 addVideoFolderToPlaylist: function(options) {
  887.                         var settings = {
  888.                                 folder: '',
  889.                                 onSuccess: null,
  890.                                 onError: null
  891.                         };
  892.                         $.extend(settings, options);
  893.  
  894.  
  895.                         xbmc.getDirectory({
  896.                                 media: 'Video',
  897.                                 directory: settings.folder.replace(/\\/g, "\\\\"),
  898.  
  899.                                 onSuccess: function(result) {
  900.                                         var error = false;
  901.                                         var files = result.files;
  902.                                         if (files) {
  903.                                                 files.sort(function(a, b) {
  904.                                                         if (a.file < b.file) return -1;
  905.                                                         if (a.file > b.file) return 1;
  906.                                                         return 0;
  907.                                                 });
  908.                                                 alert(objToStr(files,''));
  909.                                                 $.each(files, function(i, file)  {
  910.                                                         xbmc.addVideoFileToPlaylist({
  911.                                                                 'file': file.file,
  912.                                                                 onError: function() {
  913.                                                                         error = true;
  914.                                                                 },
  915.                                                                 async: false
  916.                                                         });
  917.                                                 });
  918.                                         }
  919.                                         if (error) {
  920.                                                 settings.onError(mkf.lang.get('message_failed_add_files_to_playlist'));
  921.                                         } else {
  922.                                                 settings.onSuccess();
  923.                                         }
  924.                                 },
  925.  
  926.                                 onError: function() {
  927.                                         settings.onError(mkf.lang.get('message_failed_folders_content'));
  928.                                 }
  929.                         });
  930.                 },
  931.  
  932.  
  933.  
  934.                 addMovieToPlaylist: function(options) {
  935.                         var settings = {
  936.                                 movieid: 0,
  937.                                 onSuccess: null,
  938.                                 onError: null,
  939.                         };
  940.                         $.extend(settings, options);
  941.                 /*
  942.                         function myobject(){
  943.                         this.movieid = 0;
  944.                         }
  945.                         var args = new myobject();
  946.                         args.movieid = settings.movieid;
  947.                 */
  948.                         xbmc.sendCommand(
  949.                                 //'{"jsonrpc": "2.0", "method": "VideoPlaylist.Add", "params": {"movieid": ' + settings.movieid + '}, "id": 1}',
  950.                                 '{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"item": {"movieid": ' + settings.movieid + '}, "playlistid": 1}, "id": 1}',
  951.                                 settings.onSuccess,
  952.                                 settings.onError,
  953.                                 null,
  954.                                 settings.async
  955.                         );
  956.                 },
  957.  
  958.  
  959.  
  960.                 playMovie: function(options) {
  961.                         var settings = {
  962.                                 movieid: 0,
  963.                                 onSuccess: null,
  964.                                 onError: null,
  965.                         };
  966.                         $.extend(settings, options);
  967.  
  968.                         this.clearVideoPlaylist({
  969.                                 onSuccess: function() {
  970.                                         xbmc.addMovieToPlaylist({
  971.                                                 movieid: settings.movieid,
  972.  
  973.                                                 onSuccess: function() {
  974.                                                         xbmc.playVideo({
  975.                                                                 onSuccess: settings.onSuccess,
  976.                                                                 onError: function(errorText) {
  977.                                                                         settings.onError(errorText);
  978.                                                                 }
  979.                                                         });
  980.                                                 },
  981.  
  982.                                                 onError: function() {
  983.                                                         settings.onError(mkf.lang.get('message_failed_add_movie_to_playlist'));
  984.                                                 }
  985.                                         });
  986.                                 },
  987.  
  988.                                 onError: function() {
  989.                                         settings.onError(mkf.lang.get('message_failed_clear_playlist'));
  990.                                 }
  991.                         });
  992.                 },
  993.  
  994.  
  995.  
  996.                 playVideoFile: function(options) {
  997.                         var settings = {
  998.                                 file: '',
  999.                                 onSuccess: null,
  1000.                                 onError: null,
  1001.                         };
  1002.                         $.extend(settings, options);
  1003.  
  1004.                         this.clearVideoPlaylist({
  1005.                                 onSuccess: function() {
  1006.                                         xbmc.addVideoFileToPlaylist({
  1007.                                                 file: settings.file,
  1008.  
  1009.                                                 onSuccess: function() {
  1010.                                                         xbmc.playVideo({
  1011.                                                                 onSuccess: settings.onSuccess,
  1012.                                                                 onError: function(errorText) {
  1013.                                                                         settings.onError(errorText);
  1014.                                                                 }
  1015.                                                         });
  1016.                                                 },
  1017.  
  1018.                                                 onError: function() {
  1019.                                                         settings.onError(mkf.lang.get('message_failed_add_file_to_playlist'));
  1020.                                                 }
  1021.                                         });
  1022.                                 },
  1023.  
  1024.                                 onError: function() {
  1025.                                         settings.onError(mkf.lang.get('message_failed_clear_playlist'));
  1026.                                 }
  1027.                         });
  1028.                 },
  1029.  
  1030.  
  1031.  
  1032.                 playVideoFolder: function(options) {
  1033.                         var settings = {
  1034.                                 folder: '',
  1035.                                 onSuccess: null,
  1036.                                 onError: null,
  1037.                         };
  1038.                         $.extend(settings, options);
  1039.  
  1040.                         this.clearVideoPlaylist({
  1041.                                 onSuccess: function() {
  1042.                                         xbmc.addVideoFolderToPlaylist({
  1043.                                                 folder: settings.folder,
  1044.  
  1045.                                                 onSuccess: function() {
  1046.                                                         xbmc.playVideo({
  1047.                                                                 onSuccess: settings.onSuccess,
  1048.                                                                 onError: function(errorText) {
  1049.                                                                         settings.onError(errorText);
  1050.                                                                 }
  1051.                                                         });
  1052.                                                 },
  1053.  
  1054.                                                 onError: function(errorText) {
  1055.                                                         settings.onError(errorText);
  1056.                                                 }
  1057.                                         });
  1058.                                 },
  1059.  
  1060.                                 onError: function() {
  1061.                                         settings.onError(mkf.lang.get('message_failed_clear_playlist'));
  1062.                                 }
  1063.                         });
  1064.                 },
  1065.  
  1066.  
  1067.  
  1068.                 /*getMovieInfo: function(options) {
  1069.                         var settings = {
  1070.                                 movieid: 0,
  1071.                                 onSuccess: null,
  1072.                                 onError: null,
  1073.                         };
  1074.                         $.extend(settings, options);
  1075.  
  1076.                         // TODO better: do not get all movies
  1077.                         xbmc.sendCommand(
  1078.                                 '{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies", "params": { "properties" : ["genre", "director", "plot", "title", "originaltitle", "runtime", "year", "rating"] }, "id": 1}',
  1079.  
  1080.                                 function (response) {
  1081.                                         var movies = response.result.movies;
  1082.                                         var result = null;
  1083.  
  1084.                                         if (response.result.total > 0) {
  1085.                                                 $.each(movies, function(i, movie)  {
  1086.                                                         if (movie.movieid == settings.movieid) {
  1087.                                                                 result = movie;
  1088.                                                                 return false;
  1089.                                                         }
  1090.                                                 });
  1091.                                         }
  1092.  
  1093.                                         settings.onSuccess(result);
  1094.                                 },
  1095.  
  1096.                                 settings.onError
  1097.                         );
  1098.                 },*/
  1099.  
  1100.  
  1101.  
  1102.                 getMovies: function(options) {
  1103.                         var settings = {
  1104.                                 onSuccess: null,
  1105.                                 onError: null,
  1106.                         };
  1107.                         $.extend(settings, options);
  1108.  
  1109.                         xbmc.sendCommand(
  1110.                                 //'{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies", "params": { "start": 0, "properties" : ["genre", "director", "plot", "title", "originaltitle", "runtime", "year", "rating"], "sort": { "order": "ascending", "method": "label" } }, "id": 1}',
  1111.                                 '{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies", "params": {"properties" : ["genre", "director", "plot", "title", "originaltitle", "runtime", "year", "rating", "thumbnail"], "sort": { "order": "ascending", "method": "label" } }, "id": 1}',
  1112.                                 function(response) {
  1113.                                         settings.onSuccess(response.result);
  1114.                                 },
  1115.                                 settings.onError
  1116.                         );
  1117.                 },
  1118.  
  1119.  
  1120.  
  1121.                 addEpisodeToPlaylist: function(options) {
  1122.                         var settings = {
  1123.                                 episodeid: 0,
  1124.                                 onSuccess: null,
  1125.                                 onError: null,
  1126.                         };
  1127.                         $.extend(settings, options);
  1128.  
  1129.                         xbmc.sendCommand(
  1130.                                 //'{"jsonrpc": "2.0", "method": "VideoPlaylist.Add", "params": {"episodeid": ' + settings.episodeid + '}, "id": 1}',
  1131.                                 '{"jsonrpc": "2.0", "method": "Playlist.Add", "params": {"item": {"episodeid": ' + settings.episodeid + '}, "playlistid": 1}, "id": 1}',
  1132.                                 settings.onSuccess,
  1133.                                 settings.onError,
  1134.                                 null,
  1135.                                 settings.async
  1136.                         );
  1137.                 },
  1138.  
  1139.  
  1140.  
  1141.                 playEpisode: function(options) {
  1142.                         var settings = {
  1143.                                 episodeid: 0,
  1144.                                 onSuccess: null,
  1145.                                 onError: null,
  1146.                         };
  1147.                         $.extend(settings, options);
  1148.  
  1149.                         this.clearVideoPlaylist({
  1150.                                 onSuccess: function() {
  1151.                                         xbmc.addEpisodeToPlaylist({
  1152.                                                 episodeid: settings.episodeid,
  1153.  
  1154.                                                 onSuccess: function() {
  1155.                                                         xbmc.playVideo({
  1156.                                                                 onSuccess: settings.onSuccess,
  1157.                                                                 onError: function(errorText) {
  1158.                                                                         settings.onError(errorText);
  1159.                                                                 }
  1160.                                                         });
  1161.                                                 },
  1162.  
  1163.                                                 onError: function() {
  1164.                                                         settings.onError(mkf.lang.get('message_failed_add_episode_to_playlist'));
  1165.                                                 }
  1166.                                         });
  1167.                                 },
  1168.  
  1169.                                 onError: function() {
  1170.                                         settings.onError(mkf.lang.get('message_failed_clear_playlist'));
  1171.                                 }
  1172.                         });
  1173.                 },
  1174.  
  1175.  
  1176.  
  1177.                 getTvShows: function(options) {
  1178.                         var settings = {
  1179.                                 onSuccess: null,
  1180.                                 onError: null,
  1181.                         };
  1182.                         $.extend(settings, options);
  1183.  
  1184.                         xbmc.sendCommand(
  1185.                                 //'{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": { "start": 0, "properties": ["genre", "director", "plot", "title", "originaltitle", "runtime", "year", "rating"] }, "id": 1}',
  1186.                                 '{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": { "properties": ["genre", "plot", "title", "originaltitle", "year", "rating", "thumbnail"] }, "id": 1}',
  1187.                                 function(response) {
  1188.                                         settings.onSuccess(response.result);
  1189.                                 },
  1190.                                 settings.onError
  1191.                         );
  1192.                 },
  1193.  
  1194.  
  1195.  
  1196.                 getSeasons: function(options) {
  1197.                         var settings = {
  1198.                                 tvshowid: 0,
  1199.                                 onSuccess: null,
  1200.                                 onError: null,
  1201.                         };
  1202.                         $.extend(settings, options);
  1203.  
  1204.                         xbmc.sendCommand(
  1205.                                 '{"jsonrpc": "2.0", "method": "VideoLibrary.GetSeasons", "params": { "tvshowid": ' + settings.tvshowid + ', "properties": ["season"]}, "id": 1}',
  1206.                                 function(response) {
  1207.                                         settings.onSuccess(response.result);
  1208.                                 },
  1209.                                 settings.onError
  1210.                         );
  1211.                 },
  1212.  
  1213.  
  1214.  
  1215.                 getEpisodes: function(options) {
  1216.                         var settings = {
  1217.                                 tvshowid: 0,
  1218.                                 season: 0,
  1219.                                 onSuccess: null,
  1220.                                 onError: null,
  1221.                         };
  1222.                         $.extend(settings, options);
  1223.  
  1224.                         xbmc.sendCommand(
  1225.                                 '{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": { "tvshowid": ' + settings.tvshowid + ', "season" : ' + settings.season + ', "properties": ["episode"], "sort": { "order": "ascending", "method": "episode" } }, "id": 1}',
  1226.                                 function(response) {
  1227.                                         settings.onSuccess(response.result);
  1228.                                 },
  1229.                                 settings.onError
  1230.                         );
  1231.                 },
  1232.  
  1233.  
  1234.  
  1235.                 getVideoPlaylist: function(options) {
  1236.                         var settings = {
  1237.                                 onSuccess: null,
  1238.                                 onError: null,
  1239.                         };
  1240.                         $.extend(settings, options);
  1241.  
  1242.                         xbmc.sendCommand(
  1243.                                 '{"jsonrpc": "2.0", "method": "Playlist.GetItems", "params": { "playlistid": 1}, "id": 1}',
  1244.  
  1245.                                 function(response) {
  1246.                                         settings.onSuccess(response.result);
  1247.                                 },
  1248.  
  1249.                                 settings.onError
  1250.                         );
  1251.                 },
  1252.  
  1253.  
  1254.  
  1255.                 getSources: function(options) {
  1256.                         var settings = {
  1257.                                 media: 'Audio',
  1258.                                 onSuccess: null,
  1259.                                 onError: null,
  1260.                                 async: true
  1261.                         };
  1262.                         $.extend(settings, options);
  1263.  
  1264.                         xbmc.sendCommand(
  1265.                                 '{"jsonrpc": "2.0", "method": "Files.GetSources", "params" : { "media" : "' + (settings.media=='Audio'? 'music' : 'video') + '" }, "id": 1}',
  1266.  
  1267.                                 function(response) {
  1268.                                         settings.onSuccess(response.result);
  1269.                                 },
  1270.  
  1271.                                 settings.onError,
  1272.                                 null,
  1273.                                 settings.async
  1274.                         );
  1275.                 },
  1276.  
  1277.  
  1278.  
  1279.                 getDirectory: function(options) {
  1280.                         var settings = {
  1281.                                 media: 'Audio',
  1282.                                 directory: '',
  1283.                                 onSuccess: null,
  1284.                                 onError: null,
  1285.                                 async: true
  1286.                         };
  1287.                         $.extend(settings, options);
  1288.  
  1289.                         xbmc.sendCommand(
  1290.                                 '{"jsonrpc": "2.0", "method": "Files.GetDirectory", "params" : { "directory" : "' + settings.directory.replace(/\\/g, "\\\\") + '", "media" : "' + (settings.media=='Audio'? 'music' : 'video') +'", "sort": { "order": "ascending", "method": "file" } }, "id": 1}',
  1291.  
  1292.                                 function(response) {
  1293.                                         settings.onSuccess(response.result);
  1294.                                 },
  1295.  
  1296.                                 settings.onError,
  1297.                                 null,
  1298.                                 settings.async
  1299.                         );
  1300.                 }
  1301.  
  1302.  
  1303.  
  1304.         }); // END xbmc
  1305.  
  1306.  
  1307.  
  1308.         $.extend(xbmc, {
  1309.                 periodicUpdater: {
  1310.                         volumeChangedListener: [],
  1311.                         currentlyPlayingChangedListener: [],
  1312.                         playerStatusChangedListener: [],
  1313.                         progressChangedListener: [],
  1314.  
  1315.                         lastVolume: -1,
  1316.                         currentlyPlayingFile: null,
  1317.                         progress: '',
  1318.                         playerStatus: 'stopped',
  1319.                         shuffleStatus: false,
  1320.  
  1321.                         addVolumeChangedListener: function(fn) {
  1322.                                 this.volumeChangedListener.push(fn);
  1323.                         },
  1324.  
  1325.                         addCurrentlyPlayingChangedListener: function(fn) {
  1326.                                 this.currentlyPlayingChangedListener.push(fn);
  1327.                         },
  1328.  
  1329.                         addPlayerStatusChangedListener: function(fn) {
  1330.                                 this.playerStatusChangedListener.push(fn);
  1331.                         },
  1332.  
  1333.                         addProgressChangedListener: function(fn) {
  1334.                                 this.progressChangedListener.push(fn);
  1335.                         },
  1336.  
  1337.                         firePlayerStatusChanged: function(status) {
  1338.                                 $.each(xbmc.periodicUpdater.playerStatusChangedListener, function(i, listener)  {
  1339.                                         listener(status);
  1340.                                 });
  1341.                         },
  1342.  
  1343.                         fireCurrentlyPlayingChanged: function(file) {
  1344.                                 $.each(xbmc.periodicUpdater.currentlyPlayingChangedListener, function(i, listener)  {
  1345.                                         listener(file);
  1346.                                 });
  1347.                         },
  1348.  
  1349.                         fireProgressChanged: function(progress) {
  1350.                                 $.each(xbmc.periodicUpdater.progressChangedListener, function(i, listener)  {
  1351.                                         listener(progress);
  1352.                                 });
  1353.                         },
  1354.  
  1355.                         start: function() {
  1356.                                 setTimeout($.proxy(this, "periodicStep"), 10);
  1357.                         },
  1358.  
  1359.                         periodicStep: function() {
  1360.  
  1361.                                 var curPlayData = {};
  1362.                                 var shuffle = false;
  1363.                                 var time = '';
  1364.                                 var file = '';
  1365.                                 var volume = 0;
  1366.  
  1367.                                 // ---------------------------------
  1368.                                 // ---      Volume Changes       ---
  1369.                                 // ---------------------------------
  1370.                                 // --- Currently Playing Changes ---
  1371.                                 // ---------------------------------
  1372.                                 if ((this.volumeChangedListener &&
  1373.                                         this.volumeChangedListener.length) ||
  1374.                                         (this.currentlyPlayingChangedListener &&
  1375.                                         this.currentlyPlayingChangedListener.length) ||
  1376.                                         (this.playerStatusChangedListener &&
  1377.                                         this.playerStatusChangedListener.length) ||
  1378.                                         (this.progressChangedListener &&
  1379.                                         this.progressChangedListener.length)) {
  1380.  
  1381.                                         var activePlayer = '';
  1382.  
  1383.                                         xbmc.sendCommand(
  1384.                                                 '{"jsonrpc": "2.0", "method": "XBMC.GetInfoLabels", "params" : {"labels": ["MusicPlayer.Title", "MusicPlayer.Album", "MusicPlayer.Artist", "Player.Time", "Player.Duration", "Player.Volume", "Playlist.Random", "VideoPlayer.Title", "VideoPlayer.TVShowTitle", "Player.Filenameandpath"]}, "id": 1}',
  1385.  
  1386.                                                 function (response) {
  1387.                                                         var infoResult = response.result;
  1388.  
  1389.                                                         shuffle = (infoResult['Playlist.Random']=="Random"? true: false);
  1390.                                                         time = infoResult['Player.Time'];
  1391.                                                         file = infoResult['Player.Filenameandpath'];
  1392.  
  1393.                                                         var tmp = parseFloat(infoResult['Player.Volume']);
  1394.                                                         volume = (isNaN(tmp)? 0: (tmp+60)/60*100); // -60 dB to 0 dB (--> 0% to 100%)
  1395.  
  1396.                                                         curPlayData.duration = infoResult['Player.Duration'];
  1397.                                                         curPlayData.file = infoResult['Player.Filenameandpath'];
  1398.  
  1399.                                                         if (infoResult['MusicPlayer.Title'] != "") {
  1400.                                                                 activePlayer = 'audio';
  1401.                                                                 curPlayData.title = infoResult['MusicPlayer.Title'];
  1402.                                                                 curPlayData.album = infoResult['MusicPlayer.Album'];
  1403.                                                                 curPlayData.artist = infoResult['MusicPlayer.Artist'];
  1404.  
  1405.                                                         } else if (infoResult['VideoPlayer.Title'] != "") {
  1406.                                                                 activePlayer = 'video';
  1407.                                                                 curPlayData.title = infoResult['VideoPlayer.Title'];
  1408.                                                                 curPlayData.showtitle = infoResult['VideoPlayer.TVShowTitle'];
  1409.  
  1410.                                                         } else {
  1411.                                                                 activePlayer = 'none';
  1412.                                                         }
  1413.                                                 },
  1414.  
  1415.                                                 function(response) {
  1416.                                                         activePlayer = 'none'; // ERROR
  1417.                                                 },
  1418.  
  1419.                                                 null, false // not async
  1420.                                         );
  1421.  
  1422.                                         // has volume changed?
  1423.                                         if (volume != xbmc.periodicUpdater.lastVolume) {
  1424.                                                 $.each(xbmc.periodicUpdater.volumeChangedListener, function(i, listener)  {
  1425.                                                         listener(volume);
  1426.                                                 });
  1427.                                         }
  1428.  
  1429.                                         if (activePlayer == 'none' &&
  1430.                                                 this.playerStatus != 'stopped') {
  1431.  
  1432.                                                 this.playerStatus = 'stopped';
  1433.                                                 this.firePlayerStatusChanged('stopped');
  1434.                                         }
  1435.  
  1436.                                         // shuffle status changed?
  1437.                                         if (this.shuffleStatus != shuffle) {
  1438.                                                 this.shuffleStatus = shuffle;
  1439.                                                 this.firePlayerStatusChanged(shuffle? 'shuffleOn': 'shuffleOff');
  1440.                                         }
  1441.  
  1442.                                         // is playing
  1443.                                         if (activePlayer != 'none') {
  1444.                                                 var request = '';
  1445.  
  1446.                                                 if (activePlayer == 'audio') {
  1447.                                                         request = '{"jsonrpc": "2.0", "method": "Playlist.GetItems", "params": { "properties": ["title", "album", "artist", "duration"], "playlistid": 0 }, "id": 1}';
  1448.  
  1449.                                                 } else if (activePlayer == 'video') {
  1450.                                                         request = '{"jsonrpc": "2.0", "method": "Playlist.GetItems", "params": { "properties": ["title", "season", "episode", "duration", "showtitle"], "playlistid": 1 }, "id": 1}';
  1451.                                                 }
  1452.  
  1453.                                                 xbmc.sendCommand(
  1454.                                                         request,
  1455.  
  1456.                                                         function (response) {
  1457.                                                                 var currentPlayer = response.result;
  1458.                                                                 var currentItem;
  1459.  
  1460.                                                                 // playlist may be cleared. Use data retrieved by GetInfoLabels
  1461.                                                                 if (!currentPlayer.items || !currentPlayer.items[currentPlayer.current]) {
  1462.                                                                         currentItem = curPlayData;
  1463.  
  1464.                                                                 } else {
  1465.                                                                         currentItem = currentPlayer.items[currentPlayer.current];
  1466.                                                                         $.extend(currentItem, curPlayData);
  1467.                                                                 }
  1468.  
  1469.  
  1470.                                                                 if (!currentPlayer.playing) {
  1471.                                                                         // not playing
  1472.                                                                         if (xbmc.periodicUpdater.playerStatus != 'stopped') {
  1473.                                                                                 xbmc.periodicUpdater.playerStatus = 'stopped';
  1474.                                                                                 xbmc.periodicUpdater.firePlayerStatusChanged('stopped');
  1475.                                                                         }
  1476.  
  1477.                                                                 } else if (currentPlayer.paused && xbmc.periodicUpdater.playerStatus != 'paused') {
  1478.                                                                         xbmc.periodicUpdater.playerStatus = 'paused';
  1479.                                                                         xbmc.periodicUpdater.firePlayerStatusChanged('paused');
  1480.  
  1481.                                                                 } else if (!currentPlayer.paused && xbmc.periodicUpdater.playerStatus != 'playing') {
  1482.                                                                         xbmc.periodicUpdater.playerStatus = 'playing';
  1483.                                                                         xbmc.periodicUpdater.firePlayerStatusChanged('playing');
  1484.                                                                 }
  1485.  
  1486.                                                                 // has current file changed?
  1487.                                                                 if (xbmc.periodicUpdater.currentlyPlayingFile != currentItem.file) {
  1488.                                                                         xbmc.periodicUpdater.currentlyPlayingFile = currentItem.file;
  1489.                                                                         $.extend(currentItem, {
  1490.                                                                                 xbmcMediaType: activePlayer
  1491.                                                                         });
  1492.                                                                         xbmc.periodicUpdater.fireCurrentlyPlayingChanged(currentItem);
  1493.                                                                 }
  1494.  
  1495.                                                                 // current time
  1496.                                                                 if (xbmc.periodicUpdater.progress != time) {
  1497.                                                                         xbmc.periodicUpdater.fireProgressChanged({"time": time, total: currentItem.duration});
  1498.                                                                         xbmc.periodicUpdater.progress = time;
  1499.                                                                 }
  1500.                                                         },
  1501.  
  1502.                                                         null, null, false // not async
  1503.                                                 );
  1504.                                         }
  1505.  
  1506.                                 }
  1507.  
  1508.                                 setTimeout($.proxy(this, "periodicStep"), 5000);
  1509.                         }
  1510.                 } // END xbmc.periodicUpdater
  1511.         }); // END xbmc
  1512.  
  1513. })(jQuery);
  1514.  
  1515.