Your Universal Remote Control Center
RemoteCentral.com
Philips Pronto Professional Forum - View Post
Up level
Up level
The following page was printed from RemoteCentral.com:

Login:
Pass:
 
 

Original thread:
Post 3 made on August 11, 2026 at 21:41
M
mpg7321
Long Time Member
Joined:
Posts:
RC XP:
June 2020
183
175⭐︎
New code with cover art and fixed the resuming from prolong idol.

// ============================================================
// KODI TCP + COVER ART
//
// Kodi IP : 192.168.1.47
// Kodi TCP : 9090
// Kodi HTTP : 8080
//
// WIDGETS:
//
// KODI_TITLE
// KODI_SHOW
// KODI_EPISODE
// KODI_TOTAL
// KODI_REMAINING
// KODI_PROGRESS
// KODI_COVER
//
// KODI_COVER : 60 x 80
//
// Requires:
// com.philips.HttpLibrary
//
// ============================================================


var KodiTCP = {};

KodiTCP.socket = null;
KodiTCP.buffer = "";
KodiTCP.connected = false;
KodiTCP.requestID = 0;

KodiTCP.timePolling = false;
KodiTCP.timeRequestPending = false;
KodiTCP.timeRequestTime = 0;

KodiTCP.progressMaxWidth = 595;

KodiTCP.reconnectScheduled = false;

KodiTCP.watchdogRunning = false;
KodiTCP.watchdogRequestPending = false;
KodiTCP.watchdogRequestTime = 0;

KodiTCP.httpLib =
com.philips.HttpLibrary;


// ============================================================
// COVER PANEL
// ============================================================

CF.widget("KODI_COVER").stretchImage = true;


// ============================================================
// FORMAT HH:MM:SS
// ============================================================

KodiTCP.formatTime = function(seconds)
{
seconds = Math.floor(seconds);

if (seconds < 0)
seconds = 0;

var hours =
Math.floor(seconds / 3600);

var minutes =
Math.floor((seconds % 3600) / 60);

var secs =
seconds % 60;

var h = hours.toString();
var m = minutes.toString();
var s = secs.toString();

if (h.length < 2)
h = "0" + h;

if (m.length < 2)
m = "0" + m;

if (s.length < 2)
s = "0" + s;

return h + ":" + m + ":" + s;
};


// ============================================================
// CLEAR DISPLAY
//
// IMPORTANT:
// Also clears the cover artwork so the previous movie
// does not remain displayed after playback stops.
// ============================================================

KodiTCP.clearDisplay = function()
{
CF.widget("KODI_TITLE").label = "";
CF.widget("KODI_SHOW").label = "";
CF.widget("KODI_EPISODE").label = "";
CF.widget("KODI_TOTAL").label = "";
CF.widget("KODI_REMAINING").label = "";

CF.widget("KODI_PROGRESS").width = 1;

CF.widget("KODI_TITLE").visible = false;
CF.widget("KODI_SHOW").visible = false;
CF.widget("KODI_EPISODE").visible = false;

// Clear previous cover artwork.
try
{
CF.widget("KODI_COVER").setImage(null);
}
catch(e)
{
}
};


// ============================================================
// SHOW COVER
// ============================================================

KodiTCP.showCover = function(poster)
{
if (poster == "")
return;


var imageURL =
"http://192.168.1.47:8080/image/" +
encodeURIComponent(
poster
);


KodiTCP.httpLib.getHTTPBinary(
imageURL,
function(binary)
{
if (!binary)
return;


try
{
var image =
new Image(binary);


CF.widget(
"KODI_COVER"
).setImage(
image
);
}
catch(e)
{
}
}
);
};


// ============================================================
// START TIME POLLING
// ============================================================

KodiTCP.startTimePolling = function()
{
if (!KodiTCP.connected)
return;

KodiTCP.timePolling = true;
KodiTCP.timeRequestPending = false;
KodiTCP.timeRequestTime = 0;

KodiTCP.getTime();
};


// ============================================================
// STOP TIME POLLING
// ============================================================

KodiTCP.stopTimePolling = function()
{
KodiTCP.timePolling = false;
KodiTCP.timeRequestPending = false;
KodiTCP.timeRequestTime = 0;
};


// ============================================================
// SCHEDULE NEXT TIME REQUEST
// ============================================================

KodiTCP.scheduleNextTime = function()
{
if (!KodiTCP.connected)
return;

if (!KodiTCP.timePolling)
return;

scheduleAfter(
1000,
KodiTCP.timePoll
);
};


// ============================================================
// TIME POLL CALLBACK
// ============================================================

KodiTCP.timePoll = function()
{
if (!KodiTCP.connected)
return;

if (!KodiTCP.timePolling)
return;


// --------------------------------------------------------
// If a previous request has been waiting too long,
// consider it lost.
//
// This prevents the polling system from becoming
// permanently stuck.
// --------------------------------------------------------

if (KodiTCP.timeRequestPending)
{
if (
(new Date().getTime() -
KodiTCP.timeRequestTime) > 5000
)
{
KodiTCP.timeRequestPending = false;
KodiTCP.timeRequestTime = 0;
}
else
{
KodiTCP.scheduleNextTime();
return;
}
}


KodiTCP.getTime();
};


// ============================================================
// CONNECT
// ============================================================

KodiTCP.connect = function()
{
if (KodiTCP.socket != null)
return;


KodiTCP.socket =
new TCPSocket(false);


KodiTCP.socket.onConnect = function()
{
KodiTCP.connected = true;
KodiTCP.buffer = "";
KodiTCP.timeRequestPending = false;
KodiTCP.timeRequestTime = 0;

KodiTCP.watchdogRequestPending = false;
KodiTCP.watchdogRequestTime = 0;

KodiTCP.reconnectScheduled = false;

// Always get the current Kodi state after connecting.
KodiTCP.getCurrentItem();
};


KodiTCP.socket.onData = function()
{
KodiTCP.buffer +=
KodiTCP.socket.read();

KodiTCP.processBuffer();
};


KodiTCP.socket.onClose = function()
{
KodiTCP.handleDisconnect();
};


KodiTCP.socket.onIOError = function()
{
KodiTCP.handleDisconnect();
};


KodiTCP.socket.connect(
"192.168.1.47",
9090,
5000
);
};


// ============================================================
// HANDLE DISCONNECT
//
// Previously a dead socket could leave the script stuck.
// Now we automatically reconnect.
// ============================================================

KodiTCP.handleDisconnect = function()
{
KodiTCP.stopTimePolling();

KodiTCP.connected = false;

KodiTCP.watchdogRequestPending = false;
KodiTCP.watchdogRequestTime = 0;

KodiTCP.buffer = "";


try
{
if (KodiTCP.socket != null)
KodiTCP.socket.close();
}
catch(e)
{
}


KodiTCP.socket = null;

KodiTCP.clearDisplay();

KodiTCP.scheduleReconnect();
};


// ============================================================
// SCHEDULE RECONNECT
// ============================================================

KodiTCP.scheduleReconnect = function()
{
if (KodiTCP.reconnectScheduled)
return;

KodiTCP.reconnectScheduled = true;


scheduleAfter(
5000,
function()
{
KodiTCP.reconnectScheduled = false;

if (!KodiTCP.connected &&
KodiTCP.socket == null)
{
KodiTCP.connect();
}
}
);
};


// ============================================================
// GET CURRENT ITEM
// ============================================================

KodiTCP.getCurrentItem = function()
{
if (!KodiTCP.connected)
return;


KodiTCP.requestID++;


var request =
'{"jsonrpc":"2.0",' +
'"method":"Player.GetItem",' +
'"params":{' +
'"properties":[' +
'"title",' +
'"showtitle",' +
'"season",' +
'"episode",' +
'"art"' +
'],' +
'"playerid":1' +
'},' +
'"id":' +
KodiTCP.requestID +
'}';


try
{
KodiTCP.socket.write(
request
);
}
catch(e)
{
KodiTCP.handleDisconnect();
}
};


// ============================================================
// GET CURRENT TIME
// ============================================================

KodiTCP.getTime = function()
{
if (!KodiTCP.connected)
return;

if (KodiTCP.timeRequestPending)
return;


KodiTCP.timeRequestPending = true;

KodiTCP.timeRequestTime =
new Date().getTime();


KodiTCP.requestID++;


var request =
'{"jsonrpc":"2.0",' +
'"method":"Player.GetProperties",' +
'"params":{' +
'"playerid":1,' +
'"properties":[' +
'"time",' +
'"totaltime"' +
']' +
'},' +
'"id":' +
KodiTCP.requestID +
'}';


try
{
KodiTCP.socket.write(
request
);
}
catch(e)
{
KodiTCP.timeRequestPending = false;
KodiTCP.timeRequestTime = 0;

KodiTCP.handleDisconnect();
}
};


// ============================================================
// WATCHDOG
//
// This is independent of movie playback.
//
// It periodically asks Kodi if the TCP connection is still
// alive. This is important after the Shield has been idle
// for a long period.
//
// ============================================================

KodiTCP.startWatchdog = function()
{
if (KodiTCP.watchdogRunning)
return;

KodiTCP.watchdogRunning = true;

KodiTCP.watchdogPoll();
};


// ============================================================
// WATCHDOG POLL
// ============================================================

KodiTCP.watchdogPoll = function()
{
if (!KodiTCP.watchdogRunning)
return;


// --------------------------------------------------------
// If disconnected, make sure reconnect is attempted.
// --------------------------------------------------------

if (!KodiTCP.connected)
{
if (KodiTCP.socket == null)
KodiTCP.scheduleReconnect();

scheduleAfter(
15000,
KodiTCP.watchdogPoll
);

return;
}


// --------------------------------------------------------
// If a watchdog request has been pending too long,
// assume the connection is stale.
// --------------------------------------------------------

if (KodiTCP.watchdogRequestPending)
{
if (
(new Date().getTime() -
KodiTCP.watchdogRequestTime) > 8000
)
{
KodiTCP.watchdogRequestPending = false;

KodiTCP.handleDisconnect();

scheduleAfter(
15000,
KodiTCP.watchdogPoll
);

return;
}
}
else
{
KodiTCP.sendWatchdog();
}


scheduleAfter(
15000,
KodiTCP.watchdogPoll
);
};


// ============================================================
// SEND WATCHDOG
//
// Player.GetActivePlayers is lightweight and does not
// interfere with the normal time polling.
// ============================================================

KodiTCP.sendWatchdog = function()
{
if (!KodiTCP.connected)
return;

if (KodiTCP.watchdogRequestPending)
return;


KodiTCP.watchdogRequestPending = true;

KodiTCP.watchdogRequestTime =
new Date().getTime();


KodiTCP.requestID++;


var request =
'{"jsonrpc":"2.0",' +
'"method":"Player.GetActivePlayers",' +
'"id":' +
KodiTCP.requestID +
'}';


try
{
KodiTCP.socket.write(
request
);
}
catch(e)
{
KodiTCP.watchdogRequestPending = false;

KodiTCP.handleDisconnect();
}
};


// ============================================================
// PROCESS TCP BUFFER
// ============================================================

KodiTCP.processBuffer = function()
{
while (true)
{
var depth = 0;
var start = -1;
var inString = false;
var escaped = false;
var found = false;


for (
var i = 0;
i < KodiTCP.buffer.length;
i++
)
{
var c =
KodiTCP.buffer.charAt(i);


if (escaped)
{
escaped = false;
continue;
}


if (c == "\\")
{
if (inString)
escaped = true;

continue;
}


if (c == '"')
{
inString = !inString;
continue;
}


if (inString)
continue;


if (c == "{")
{
if (depth == 0)
start = i;

depth++;
}


if (c == "}")
{
depth--;


if (
depth == 0 &&
start >= 0
)
{
var json =
KodiTCP.buffer.substring(
start,
i + 1
);


KodiTCP.buffer =
KodiTCP.buffer.substring(
i + 1
);


found = true;


KodiTCP.processJSON(
json
);


break;
}
}
}


if (!found)
break;
}
};


// ============================================================
// PROCESS JSON
// ============================================================

KodiTCP.processJSON = function(json)
{
// --------------------------------------------------------
// Any response means Kodi is alive.
// --------------------------------------------------------

if (
KodiTCP.watchdogRequestPending &&
json.indexOf('"result"') >= 0
)
{
KodiTCP.watchdogRequestPending = false;
KodiTCP.watchdogRequestTime = 0;
}


// --------------------------------------------------------
// PLAYBACK STOPPED
// --------------------------------------------------------

if (
json.indexOf(
'"method":"Player.OnStop"'
) >= 0
)
{
KodiTCP.stopTimePolling();

KodiTCP.clearDisplay();

return;
}


// --------------------------------------------------------
// NEW MEDIA STARTED
// --------------------------------------------------------

if (
json.indexOf(
'"method":"Player.OnPlay"'
) >= 0
)
{
// Make absolutely sure the old information is removed
// before loading the new movie/show.
KodiTCP.clearDisplay();

KodiTCP.getCurrentItem();

return;
}


// --------------------------------------------------------
// PLAYBACK RESUMED
// --------------------------------------------------------

if (
json.indexOf(
'"method":"Player.OnResume"'
) >= 0
)
{
KodiTCP.startTimePolling();

return;
}


// --------------------------------------------------------
// CURRENT ITEM RESPONSE
// --------------------------------------------------------

if (
json.indexOf('"title"') >= 0
)
{
KodiTCP.parseItem(json);

return;
}


// --------------------------------------------------------
// TIME RESPONSE
// --------------------------------------------------------

if (
json.indexOf('"time"') >= 0 &&
json.indexOf('"totaltime"') >= 0
)
{
KodiTCP.parseTime(json);

return;
}
};


// ============================================================
// PARSE MOVIE / TV INFORMATION
// ============================================================

KodiTCP.parseItem = function(json)
{
var title =
KodiTCP.getString(
json,
"title"
);


var show =
KodiTCP.getString(
json,
"showtitle"
);


// ========================================================
// ARTWORK
// ========================================================

var artObject =
KodiTCP.getObject(
json,
"art"
);


var poster = "";


if (artObject != "")
{
// ----------------------------------------------------
// MOVIE
// ----------------------------------------------------

if (show == "")
{
poster =
KodiTCP.getString(
artObject,
"poster"
);
}


// ----------------------------------------------------
// TV SHOW
// ----------------------------------------------------

else
{
poster =
KodiTCP.getString(
artObject,
"tvshow.poster"
);


if (poster == "")
{
poster =
KodiTCP.getString(
artObject,
"poster"
);
}
}
}


// ========================================================
// DISPLAY COVER
// ========================================================

if (poster != "")
{
KodiTCP.showCover(
poster
);
}


// ========================================================
// MOVIE
// ========================================================

if (show == "")
{
CF.widget("KODI_TITLE").visible =
true;

CF.widget("KODI_SHOW").visible =
false;

CF.widget("KODI_EPISODE").visible =
false;


CF.widget("KODI_TITLE").label =
title;

CF.widget("KODI_SHOW").label =
"";

CF.widget("KODI_EPISODE").label =
"";
}


// ========================================================
// TV SHOW
// ========================================================

else
{
CF.widget("KODI_TITLE").visible =
false;

CF.widget("KODI_SHOW").visible =
true;

CF.widget("KODI_EPISODE").visible =
true;


CF.widget("KODI_TITLE").label =
"";

CF.widget("KODI_SHOW").label =
show;

CF.widget("KODI_EPISODE").label =
title;
}


KodiTCP.startTimePolling();
};


// ============================================================
// PARSE TIME
// ============================================================

KodiTCP.parseTime = function(json)
{
KodiTCP.timeRequestPending = false;
KodiTCP.timeRequestTime = 0;


var timeObject =
KodiTCP.getObject(
json,
"time"
);


var totalObject =
KodiTCP.getObject(
json,
"totaltime"
);


if (
timeObject == "" |
totalObject == ""
)
{
KodiTCP.scheduleNextTime();

return;
}


var currentHours =
KodiTCP.getNumber(
timeObject,
"hours"
);


var currentMinutes =
KodiTCP.getNumber(
timeObject,
"minutes"
);


var currentSeconds =
KodiTCP.getNumber(
timeObject,
"seconds"
);


var current =
(currentHours * 3600) +
(currentMinutes * 60) +
currentSeconds;


var totalHours =
KodiTCP.getNumber(
totalObject,
"hours"
);


var totalMinutes =
KodiTCP.getNumber(
totalObject,
"minutes"
);


var totalSeconds =
KodiTCP.getNumber(
totalObject,
"seconds"
);


var total =
(totalHours * 3600) +
(totalMinutes * 60) +
totalSeconds;


CF.widget("KODI_TOTAL").label =
KodiTCP.formatTime(
total
);


var remaining =
total - current;


if (remaining < 0)
remaining = 0;


CF.widget("KODI_REMAINING").label =
KodiTCP.formatTime(
remaining
);


var progressWidth = 1;


if (total > 0)
{
progressWidth =
Math.round(
(current / total) *
KodiTCP.progressMaxWidth
);
}


if (progressWidth < 1)
progressWidth = 1;


if (
progressWidth >
KodiTCP.progressMaxWidth
)
{
progressWidth =
KodiTCP.progressMaxWidth;
}


CF.widget("KODI_PROGRESS").width =
progressWidth;


KodiTCP.scheduleNextTime();
};


// ============================================================
// GET JSON OBJECT
// ============================================================

KodiTCP.getObject = function(json, key)
{
var p =
json.indexOf(
'"' + key + '"'
);


if (p < 0)
return "";


p =
json.indexOf(
"{",
p
);


if (p < 0)
return "";


var depth = 0;
var inString = false;
var escaped = false;


for (
var i = p;
i < json.length;
i++
)
{
var c =
json.charAt(i);


if (escaped)
{
escaped = false;
continue;
}


if (c == "\\")
{
if (inString)
escaped = true;

continue;
}


if (c == '"')
{
inString = !inString;
continue;
}


if (inString)
continue;


if (c == "{")
depth++;


if (c == "}")
{
depth--;


if (depth == 0)
{
return json.substring(
p,
i + 1
);
}
}
}


return "";
};


// ============================================================
// GET STRING
// ============================================================

KodiTCP.getString = function(json, key)
{
var p =
json.indexOf(
'"' + key + '"'
);


if (p < 0)
return "";


p =
json.indexOf(
":",
p
);


if (p < 0)
return "";


p++;


while (
p < json.length &&
json.charAt(p) == " "
)
{
p++;
}


if (json.charAt(p) != '"')
return "";


p++;


var end = p;


while (end < json.length)
{
if (
json.charAt(end) == '"' &&
json.charAt(end - 1) != "\\"
)
{
break;
}


end++;
}


if (end >= json.length)
return "";


return json.substring(
p,
end
);
};


// ============================================================
// GET NUMBER
// ============================================================

KodiTCP.getNumber = function(json, key)
{
var p =
json.indexOf(
'"' + key + '"'
);


if (p < 0)
return 0;


p =
json.indexOf(
":",
p
);


if (p < 0)
return 0;


p++;


while (
p < json.length &&
json.charAt(p) == " "
)
{
p++;
}


var end = p;


while (
end < json.length &&
json.charAt(end) >= "0" &&
json.charAt(end) <= "9"
)
{
end++;
}


if (end == p)
return 0;


return parseInt(
json.substring(
p,
end
),
10
);
};


// ============================================================
// INITIALIZE
// ============================================================

KodiTCP.clearDisplay();


// ============================================================
// START
// ============================================================

KodiTCP.connect();

KodiTCP.startWatchdog();