Hello Ross support,
I know how to make an selection on table, but wonder if it is possible to perform multiple selections, and get all selected indexes. Pretty sure i saw something like this in ultrix UI, on ‘create new panel’, when you choose sources, destinations,and levels.
Thanks for help!
Alex.
Hi Alex
If you are using a parameter to store the selection (the w.selectionparam config property), you will get multi-select if that parameter is an INT16_ARRAY or INT32_ARRAY as opposed to simply INT16 or INT32. There will be one element in the array for each selected row.
Cheers
James
Hello James,
Thanks! After change my selection parameter from INT16 to INT16_ARRAY it’s started to work just as i wanted.
Other question, is there any chance to script thumbnails or icons insertion in specific cell in the table?
Thanks!
Something like this:
Here is the panel:
myText a2 b2 c2 d2 e2 f2 g2 h2 i2 j2 k2 l2 a3 b3 c3 d3 e3 f3 g3 h3 i3 j3 k3 l3 params.c1 params.c2 params.c3Here are the 2 icons I used:
![]()
![]()
Thanks Ben, thats exactly what i wanted, im working on panel that checks cliplist inventory from grassvalley K2 summit (AMP protocol), and represent it in table which have “lock” attribute, so my idea was to place lock
icon instead writing the word. Other option that i found useful, is utf8 characters, that have many icons. The only thing, iits needs to be decoded with decodeURI.
https://www.utf8icons.com/amp/character/128274/lock
The panel idea is to find clips that older then 24 (or any other number)hours, and if they are not locked, delete them. Its runs every night with schedulere function .
If anybody interested in that, i can share it here.
Alex.
Yes please do, it would be interesting to see your integration with amp
Hello Antony,
I will publish it here, but without working Grassvalley K2 summit , and AMP protocol basics knowledge it will be hard to understand how the panel works.
If you have K2 summit server - then just point his ip adress and click ‘connect’ - you will get all the inventory + delete scheduler for specific bin (summit folder).
I doesn’t delete all the temp data from the inventory and log parameters, so when you will open it you will see the panel with data amount.
Also, using config key i show only clips in cliplist table, but there are also other columns (date, duration,lock/under construction status).
Let me know if you need addition info.
<?xml version="1.0" encoding="UTF-8"?> var listener = ogscript.getListenerById('listener1');var ip = params.getValue(‘ip’, 0);
if(listener.isStarted()){
listener.stop();
} else {
listener.connectTo(ip, 3811);
}
if(clips.length==0&&status==‘’){
var bin = params.getValueAsString(‘binList’, 0);
setBin(bin);
} else {
ogscript.debug(‘busy,retry in 1 sec..’);
ogscript.asyncExec(changeBin,1000);
}
}
changeBin();
updateScheduler(); params.setValue('binList', 0, params.getValue('binListCopy', 0));ogscript.asyncExec(oldClipsListMaker,100);
var now = new Date();
var delay = time.getTime() - now.getTime();
if (delay > 0) {
ogscript.asyncExec(runGPI(functionName), delay);
}
}
function scheduleToday(functionName, time)
{
var today = new Date();
var newTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds());
if (newTime.getTime() - today.getTime() < 0) //IF we are too late for today
{
ogscript.debug(“Too late for today.”);
scheduleTomorrow(functionName, time);
}
else
{
ogscript.debug("Scheduled task for today: " + newTime);
runAtTime(functionName, newTime);
}
}
function scheduleTomorrow(functionName, time)
{
var today = new Date();
var newTime = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1, time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds());
ogscript.debug("Scheduling for " + newTime);
runAtTime(functionName, newTime);
}
function updateScheduler(){
//task 1
var h1 = params.getValue(‘h1’, 0);
var m1 = params.getValue(‘m1’, 0);
var s1 = params.getValue(‘s1’, 0);
var task1Time = new Date()
task1Time.setHours(h1);
task1Time.setMinutes(m1);
task1Time.setSeconds(s1);
task1Time.setMilliseconds(0);
scheduleToday(“delete1”, task1Time);
}
/*
task1Time.setHours(h2);
task1Time.setMinutes(m2);
task1Time.setSeconds(s2);
scheduleToday(“delete2”, task1Time);
task1Time.setHours(h3);
task1Time.setMinutes(m3);
task1Time.setSeconds(s3);
scheduleToday(“delete3”, task1Time);
task1Time.setHours(h4);
task1Time.setMinutes(m4);
task1Time.setSeconds(s4);
scheduleToday(“114”, task1Time);
task1Time.setHours(h5);
task1Time.setMinutes(m5);
task1Time.setSeconds(s5);
scheduleToday(“115”, task1Time);
*/
var empty = ; // blank string for reset clips object
ogscript.putObject(‘clips’,empty); // reset clips object
ogscript.putObject(‘idStatusCounter’,empty); // reset idstatus object
ogscript.putObject(‘busy’, 0); // reset busy flag
ogscript.putObject(‘eraseList’, null); // reset busy flag
var eraseList = null;
params.setValue(‘led’, 0, ‘<#red>’);
updateScheduler();
var lockIcon = decodeURI(‘%F0%9F%94%92’);
var recordIcon = decodeURI(‘%E2%9A%99’);
var listFirstFolderALIAS = ‘CMDS0004A02A’ + ‘\n’;
var listNextFoldersALIAS = ‘CMDS0004A02B’ + ‘\n’;
var listFirstIdALIAS = ‘CMDS0008A2140000’ + ‘\n’;
var listNextIdALIAS = ‘CMDS0006a115FF’ + ‘\n’;
var getWorkingBinALIAS = ‘CMDS0004A00F’ + ‘\n’;
var getIdCountALIAS = ‘CMDS0004A026’ + ‘\n’;
var setDefaultBinALIAS = ‘CMDS0026a20e0009000764656661756c74’ + ‘\n’;
var channellessConnectionALIAS = ‘CRAT00014\n’;
var stopALIAS = ‘STOP0000\n’;
var setBinALIAS = ‘a20e’;
var eraseIdALIAS = ‘aa10’;
var ackALIAS = “1001”;
var nakALIAS = “1111”;
var error = “1112”;
var listFirstFolderReturnALIAS = ‘822a’;
var listNextFolderReturnALIAS = ‘822b’;
var binListCompleteALIAS = ‘802b’;
var idReturnALIAS = ‘8a14’;
var noMoreIdALIAS = ‘8014’;
var IdInfoReturnALIAS = ‘8a13’;
function firstIdRequest(){
ogscript.debug(‘firstIdRequest fired’);
ogscript.putObject(‘clips’,empty); // reset clips object
ogscript.putObject(‘busy’,1);
var server = ogscript.getObject(‘channel-less’);
server.writeString(listFirstIdALIAS, false);
}
function nextIdRequest(){
ogscript.debug(‘nextIdRequest fired’);
var server = ogscript.getObject(‘channel-less’);
server.writeString(listNextIdALIAS, false);
}
function firstFolderRequest(){
ogscript.putObject(‘busy’,1);
var server = ogscript.getObject(‘channel-less’);
server.writeString(listFirstFolderALIAS, false);
}
function nextFolderRequest(){
var server = ogscript.getObject(‘channel-less’);
server.writeString(listNextFoldersALIAS, false);
}
function setBin(binName){
ogscript.putObject(‘busy’,1); // set busy flag to true
var server = ogscript.getObject(‘channel-less’);
server.writeString(ampMessageBuilder(binName,setBinALIAS), false);
ogscript.putObject(‘ack’,‘setBin’);
}
//++++++++++++++++++++ Sending Part +++++++++++++++++++++
// Triggered from clipListFinilize(), when the cliplist done.
function clipStatusRequest(){
var counter = ogscript.getObject(‘idStatusCounter’);
var structCount = params.getElementCount(‘clipTable’); // 700/100 350
if (counter == ‘’){ //if this is request for first item in the cliplist
counter=0;
}
if(counter<structCount){
var clipname = params.getValue(‘clipTable.’ + counter + ‘.clipname’, 0);
var cmd = idInfoMessageBuilder(clipname,‘aa13’);
var server = ogscript.getObject(‘channel-less’);
server.writeString(cmd, false);
ogscript.putObject(‘idStatusCounter’,counter+1);
ogscript.rename(‘totalClips’, ’ '+ ((counter*100)/structCount).toFixed(0) + ‘%’ );
}
if(counter == structCount ){
ogscript.putObject(‘idStatusCounter’,empty);
ogscript.rename(‘totalClips’, 'Total clips: '+structCount );
ogscript.putObject(‘busy’,0);
}
}
function idInfoMessageBuilder(string,cmdType){
var clipNameLen = (‘0000’ + (string.length).toString(16)).slice(-4);
var actualCountByte = (‘0000’ + (string.length+3).toString(16)).slice(-4);
var totalCmdCounter = (‘0000’+(string.length*2+14).toString(10)).slice(-4);
var hex = string.charCodeAt(0).toString(16);
for (i = 1; i < string.length; i++) {
hex += string.charCodeAt(i).toString(16);
}
return ‘CMDS’ + totalCmdCounter + cmdType + actualCountByte + ‘43’+ clipNameLen + hex + ‘\n’ ;
}
//++++++++++++++++++++ Recieve Part +++++++++++++++++++++
function fileTimeToDate( fileTime ) {
var date = new Date ( fileTime / 10000 - 11644473600000);
return date.getUTCFullYear()+ ‘-’ + (‘0’+(date.getUTCMonth()+1)).slice(-2) +‘-’ + (‘0’+date.getUTCDate()).slice(-2) + ’ ‘+ (‘0’+date.getUTCHours()).slice(-2) +’:’
- (‘0’+date.getUTCMinutes()).slice(-2) +‘:’ + (‘0’+date.getUTCSeconds()).slice(-2) ;
}
function dateConvertor(windowsFileTime,dur,status){
var lock;var construction;
status = ‘0000’ + parseInt(status,16).toString(2);
dur = dur.slice(6) + ‘:’ + dur.slice(4,6) + ‘:’ + dur.slice(2,4)+ ‘:’ + dur.slice(0,2);
var decimal = parseInt(String(windowsFileTime), 16);
var counter = ogscript.getObject(‘idStatusCounter’) ;
if(status.slice(-4,-3) == 1){lock =lockIcon; } else {lock=‘’;}
if(status.slice(-2,-1) == 1){construction = recordIcon; } else {construction=‘’;}
params.setValue(‘clipTable.’ + (counter-1) + ‘.date’,0,fileTimeToDate(decimal)); // update date,
params.setValue(‘clipTable.’ + (counter-1) + ‘.length’,0,dur); // duration,
params.setValue(‘clipTable.’ + (counter-1) + ‘.lock’,0, ‘’ +lock+construction +‘’); // and lock/under construction status
clipStatusRequest();
}
function oldClipsListMaker(){
var erase = ogscript.getObject(‘eraseList’);
var busy = ogscript.getObject(‘busy’);
ogscript.debug(‘busy list status:’ + busy + ', Eraselist; '+erase);
if(busy==0){ // this condition makes sure that the table data building is finished, if not, it will try again in 0.5 secs
var clipDate, difference, createdDate, nowtime, structCount,hoursLimit,lock,i;
var eraseList = ;
nowtime = new Date();
structCount = params.getElementCount(‘clipTable’);
hoursLimit = Number(params.getValue(‘hourslimit’, 0));
for(i=0;i<structCount;i++){
lock = params.getValue(‘clipTable.’ + i + ‘.lock’, 0).slice(28,30);
createdDate = params.getValue(‘clipTable.’ + i + ‘.date’, 0); // example date format: 2020-02-02 09:01:02
clipDate = new Date(createdDate.slice(0,4), createdDate.slice(5,7)-1, createdDate.slice(8,10), createdDate.slice(12,14), createdDate.slice(15,17), createdDate.slice(19,21), 0);
difference = (nowtime.getTime() - clipDate.getTime())/3600000; // difference in hours
if (difference>hoursLimit&&lock!==lockIcon){ // if file older then hourLimit, and doesn’t locked -
eraseList.push(params.getValue(‘clipTable.’ + i + ‘.clipname’, 0)); // then add this clip to eraseList
}
}
if(eraseList.length!==0){
// ogscript.putObject(‘eraseList’, null);
ogscript.putObject(‘eraseList’, eraseList);
eraseOldClips();
}
}else {
ogscript.debug(‘busy list, restarting’);
ogscript.asyncExec(oldClipsListMaker,500)
}
}
function eraseOldClips(){
var list = ogscript.getObject(‘eraseList’);
var server = ogscript.getObject(‘channel-less’);
server.writeString(ampMessageBuilder(list[list.length-1],eraseIdALIAS), false);
var date = new Date();
date = date.getUTCFullYear()+ ‘-’ + (‘0’+(date.getUTCMonth()+1)).slice(-2) +‘-’ + (‘0’+date.getUTCDate()).slice(-2) + ’ ‘+ (‘0’+date.getUTCHours()).slice(-2) +’:’
- (‘0’+date.getUTCMinutes()).slice(-2) +‘:’ + (‘0’+date.getUTCSeconds()).slice(-2);
params.setValue(‘log’, 0, date + ’ Removed: ’ + params.getValueAsString(‘binListCopy’, 0) + ’ / ’ + list[list.length-1] + ‘\n’ +params.getValue(‘log’, 0) );
list.pop(); // Remove the last element of an array
ogscript.putObject(‘eraseList’, list);
if(list.length==0){
ogscript.putObject(‘eraseList’, ‘lastRemoveClip’);
}
}
// msg argument should be without CMD-TYPE,BC, and CMD CODE. It should starts from CLIPNAME-LEN(2 bytes)–>CLIP NAME and so on.
// totalLength argument it’s an msg length.
// examle cmd: 000e 535f564f5f425245534c4156494d 000c 5a2d57494e4e455233313038
function dataConvertor(msg,totalLength){
var list = ;
var itemName,i,result,x;
while(totalLength>0){
result = ‘’;
countAndNameNumber = 4 + parseInt(msg.slice(0,4),16) * 2; // number of CLIPNAME-LEN + CLIP NAME
itemName = msg.slice( 4 , countAndNameNumber);
msg = msg.slice(countAndNameNumber);
itemName = itemName.match(/.{1,2}/g); // create array of hex strings
for (i=0; i<itemName.length; i++) {
x = parseInt(itemName[i], 16); // convert hex to dec numbers
result += String.fromCharCode(x);
}
list.push(result);
totalLength -= countAndNameNumber;
}
return list;
}
function ampMessageBuilder(string,cmdType){ //CMDS0026 a20e 0009 0007 64656661756c74
var clipNameLen = (‘0000’ + (string.length).toString(16)).slice(-4);
var actualCountByte = (‘0000’ + (string.length+2).toString(16)).slice(-4);
var totalCmdCounter = (‘0000’+(string.length*2+12).toString(10)).slice(-4);
var hex = string.charCodeAt(0).toString(16);
for (i = 1; i < string.length; i++) {
hex += string.charCodeAt(i).toString(16);
}
return ‘CMDS’ + totalCmdCounter + cmdType + actualCountByte + clipNameLen + hex + ‘\n’ ;
}
function clipListFinilize(){
var clips = ogscript.getObject(‘clips’); // get array object with all cliplist.
var structCount = 0;
var newValue;
params.setAllValues(‘clipTable’, [{‘clipname’:‘’, ‘date’:‘’,‘lock’:‘’,‘length’:‘’}]);
var binName =‘/’ + params.getValueAsString(‘binList’, 0) + ‘/’;
for(i=0; clips.length>i; i++){
newValue = { ‘clipname’: clips[i], ‘date’: ‘’,‘lock’:‘’,‘length’:‘’ };
params.setValue(‘clipTable’, structCount, newValue);
structCount = params.getElementCount(‘clipTable’);
}
ogscript.rename(‘totalClips’,'Total clips: '+ clips.length);
ogscript.putObject(‘clips’,empty); // reset clips object
if(clips.length>0){
clipStatusRequest();
} else {
ogscript.putObject(‘busy’,0); // reset busy object
}
}
// this func copy binlist values to its copy - binlistcopy dropmenu.
function copyFolderNames() {
var list = ;
var x = params.getConstraint(“binList”);
var choices = x.getChoices();
for(i=0; i<choices.length ;i++){
list.push({“key”: i, “value”: choices[i].getName() });
}
var choiceConstraint = params.createIntChoiceConstraint(list);
params.replaceConstraint(“binListCopy”, choiceConstraint);
}
function messageRouter(msg){
// ogscript.debug('recieved msg from k2: ’ + msg );
if (msg.slice(0,4) == listFirstFolderReturnALIAS){ // first folder return (822a)
list1Folder(msg.slice(8));
}
if (msg.slice(0,4) == listNextFolderReturnALIAS){ // next folder return (822b)
listNextBin(msg.slice(8));
}
if (msg == binListCompleteALIAS){ // folder list comlete (802b)
binListFinilize();
}
if (msg.slice(0,4) == idReturnALIAS ){ // ID list (or single if it is the first id) return (8a14)
nextId(msg.slice(8));
ogscript.putObject(‘ack’,‘’);
}
if (msg == noMoreIdALIAS){ // No more id found (8014)
ogscript.debug(‘8014 recieved - no more id present!’ );
ogscript.putObject(‘ack’,‘’);
clipListFinilize();
}
if (msg.slice(0,4) == IdInfoReturnALIAS){ // Id info return (8a13)
dateConvertor(msg.slice(8,24),msg.slice(40,48),msg.slice(60,68)); // send date created, duration ,statusdata
}
if (msg == ackALIAS && ogscript.getObject(‘ack’) == ‘setBin’ ){ // if recieved ack (1001) and ack flag was from setDefaulBin
ogscript.asyncExec(firstIdRequest,150);
ogscript.putObject(‘ack’,‘’);
}
if (msg == ackALIAS && ogscript.getObject(‘eraseList’) !== null&&ogscript.getObject(‘eraseList’) !== ‘lastRemoveClip’ ){ // if recieved ack (1001) for clip remove
ogscript.debug(‘recieved ack for clip removed,sending request for next delete’);
ogscript.asyncExec(eraseOldClips,500);
}
if (msg == error && ogscript.getObject(‘eraseList’) !== null&&ogscript.getObject(‘eraseList’) !== ‘lastRemoveClip’ ){ // if recieved ack (1001) for clip remove
ogscript.debug(‘error,skipping,sending request for next delete’);
ogscript.asyncExec(eraseOldClips,500);
}
if (msg == ackALIAS && ogscript.getObject(‘eraseList’) == ‘lastRemoveClip’ ){ // if recieved ack (1001) for last clip remove
ogscript.debug(‘Clips erasing done. Updating list..’);
ogscript.putObject(‘eraseList’,null);
ogscript.asyncExec(refreshBinList,100);
}
}
function list1Folder(msg){
ogscript.debug(‘listfirsFolder fired’);
var binList = dataConvertor(msg,msg.length); // Pass msg to dataConvertor() and get first folder name string
ogscript.putObject(‘binList’,binList); // Overwrite ‘binList’ array object with the first folder name.
nextFolderRequest();
}
function listNextBin(msg){
ogscript.debug(‘listnextBin fired’);
var binList = ogscript.getObject(‘binList’); // get array object with first bin name from list1Folder func.
binList = binList.concat(dataConvertor(msg,msg.length)); // add list returned from dataConvertor() to binList
ogscript.putObject(‘binList’,binList);
nextFolderRequest();
}
function binListFinilize(){
ogscript.debug(‘folderlist finalize fired’);
var binList = ogscript.getObject(‘binList’); // get array object with first bin name from list1Folder func.
var choiceConstraint = params.createIntChoiceConstraint(binList);
params.replaceConstraint(“binList”, choiceConstraint);
copyFolderNames(); // this will copy the list also to binListCopy parameter
}
function nextId(msg){
var clips = ogscript.getObject(‘clips’); // get array object with first bin name from list1Folder func.
clips = clips.concat(dataConvertor(msg,msg.length)); // add list returned from dataConvertor() to binList
ogscript.putObject(‘clips’,clips);
nextIdRequest();
}
function refreshBinList(){
params.setValue(‘binList’, 0, params.getValue(‘binListCopy’, 0));
}
if (event.isConnectEvent())
{
ogscript.putObject(‘channel-less’, this);
this.writeString(channellessConnectionALIAS, false);
ogscript.putObject(‘firstConnection’, true);
params.setValue(‘led’, 0, ‘<#green>’);
}
if (event.isMessageEvent())
{
var messageReader = ogscript.createMessageParser(this.getInputStream());
var response = event.getBytesAsString();
var bytesArr = messageReader.readBytes(3);
var i; var ampLen = “”;
for (i = 0; i < 3; i++) {
response += String.fromCharCode(bytesArr[i]);
}
ogscript.debug('FROM LISTENER: ’ + response);
if(response == ackALIAS||response == nakALIAS || response == binListCompleteALIAS || response == noMoreIdALIAS||response == error ){
messageRouter(response);
if(ogscript.getObject(‘firstConnection’) == true){ // This condition runs if the ack was
firstFolderRequest(); // recieved for the first time connection,
ogscript.putObject(‘firstConnection’, false); } // if so he fires ‘listFirstFolder’
} else {
var bytesArr = messageReader.readBytes(4); // 00090007646 for example
for (i = 0; i < 4; i++) {
ampLen += String.fromCharCode(bytesArr[i]);
}
response += ampLen;
var finalMsg = messageReader.readBytes(parseInt(ampLen,16)*2);
for (i = 0; i < parseInt(ampLen,16)*2; i++) {
response += String.fromCharCode(finalMsg[i]);
}
messageRouter(response);
}
}
else if (event.isDisconnectEvent())
{
var x = ogscript.getObject(‘channel-less’);
if (x == this)
{
params.setValue(‘led’, 0, ‘<#red>’);
}
}
#DashBoard
