-
Lucio Zambon authored0922a540
talk.js 15.43 KiB
// jshint esversion: 6
const machine = document.location.search.indexOf('machine=')>-1? document.location.search.split('machine=')[1].split('&')[0]: 'fermi';
initSearch('../' + machine + '_lattice.json');
window.openData = [];
const t0 = + new Date();
let mode = '';
const launcherSrc = 'https://puma-01.elettra.eu/knob/launcher.php';
const lang = document.location.search.indexOf('lang=')>-1 && document.location.search.split('lang=')[1].split('&')[0]=='en'? 'en-US': 'it-IT'; // BCP 47 language
const host = document.location.search.indexOf('talk=')>-1? document.location.search.split('talk=')[1].split('&')[0].replace('ee', 'pcl-elettra-cre-0').replace('ef','pcl-elettra-crf-0'): '';
function switchLocale(newlang) {document.location = './talk.php?lang='+newlang+(host.length>0? '&talk='+host: '');}
let locale = {};
function myload() {
fetch('./talk_locale.json').then((response) => {return response.json();}).then((rlocale) => {
locale = rlocale;
$('#title').html(rlocale[lang].talkto + host);
$('#micna').attr('title', rlocale[lang].micna);
$('#miclabel').html(rlocale[lang].miclabel + ' ');
if (document.location.search.indexOf('background=')>-1) {
const a = document.location.search.split('background=')[1].split('&')[0];
console.log(a);
// $('body').css('background-color', +a > 0? '#'+a: a);
$('#search').hide(); $('#open').hide();
}
});
}
// https://stackoverflow.com/questions/64405532/why-speechsynthesisutterance-is-not-working-on-chrome
// It's because in Chrome speech synthasis requires user interaction before it speaks e.g. a button click.
// https://stackoverflow.com/questions/50490304/how-to-make-audio-autoplay-on-chrome
const synth = window.speechSynthesis;
const voices = synth.getVoices();
const voiceLocale = {'it-IT': false, 'en-US': false};
for (let i=voices.length-1; i>=0; i--) {
if (voices[i].lang=='it-IT') voiceLocale['it-IT'] = voices[i];
if (voices[i].lang=='en-US') voiceLocale['en-US'] = voices[i];
}
let oldText = '';
let oldTime = 0;
function speakGenerated(textValue) {
if (textValue !== '') {
stopRec();
if (synth.speaking) {console.error(locale.lang.speaking);showLog(locale.lang.speaking2);return;}
const utterThis = new SpeechSynthesisUtterance(textValue);
utterThis.onend = function (event) {startRec(); console.log('SpeechSynthesisUtterance.onend');showLog('..');};
utterThis.onerror = function (event) {console.error('SpeechSynthesisUtterance.onerror', event.error, event);showLog(locale[lang].onerror+JSON.stringify(event.error));};
utterThis.voice = voiceLocale[lang]===false? voices[0]: voiceLocale[lang];
utterThis.pitch = 0.1;
utterThis.rate = 1;
utterThis.lang = lang;
showLog(lang);
synth.speak(utterThis);
}
}
let keepAlive = false;
const names = [];
let aliveTimer = -1;
function startRec() {
keepAlive = true;
aliveTimer = -1;
showLog('start');
recognition.start();
showLog('started');
document.getElementById('micstart').style.display = 'inline';
document.getElementById('micstop').style.display = 'none';
$('#search').hide();
$('#open').hide();
console.log($('#search'));
}
function naClick() {
$("#micstart").show();
$("#micna").hide();
$("#miclabel").hide();
if (window.parent && window.parent.document.getElementById("talk")) {
window.parent.document.getElementById("talk").style.height = "250px";
window.parent.document.getElementById("talk").style.position = "absolute";
window.parent.document.getElementById("talk").style.right = ((window.parent.innerWidth-250)/2)+"px";
window.parent.document.getElementById("talk").style.top = ((window.parent.innerHeight-250)/2)+"px";
}
}
function stopRec() {
if (window.parent && window.parent.document.getElementById("talk")) {
window.parent.document.getElementById("talk").style.height = "30px";
window.parent.document.getElementById("talk").style.position = "unset";
}
if (typeof window.SpeechRecognition == 'undefined') {$("#micstart").hide();$("#micna").show();}
keepAlive = false;
recognition.stop();
}
function commandlistinfo() {
alert(locale[lang].commandlistinfo);
}
if (document.location.search.indexOf('debug')==-1) $('#log').hide();
let speechStat = '';
let firstRun = true;
function showLog(currentToken, p) {
if (typeof p != 'undefined') console.log(p);
console.trace(currentToken);
// Show log in console and UI.
$('#log').html(currentToken);
// const logElement = document.querySelector('#log');
// logElement.textContent = logElement.textContent+'\n'+JSON.stringify(currentToken);
}
let finalTranscript = '';
const SpeechRecognition = window.speechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();
recognition.maxAlternatives = 10;
recognition.continuous = true;
recognition.interimResults = true;
recognition.lang = lang;
recognition.maxAlternatives = 3;
showLog('starting...'+'\n');
recognition.onerror = function(event) {
showLog(locale[lang].errorname + event.error+', '+event.message+', '+event.lineno+'\n');
showLog(locale[lang].errormessage + JSON.stringify(event.error));
console.log(event);
startRec();
};
recognition.onend = function(event) {
showLog('.');
// document.getElementById('miclabel').style.display = 'none';
document.getElementById('micna').style.display = 'none';
document.getElementById('micstart').style.display = 'none';
document.getElementById('micstop').style.display = 'inline';
if (keepAlive && aliveTimer==-1) aliveTimer = setTimeout(startRec, 200);
};
recognition.onstart = function(event) {
if (document.location.search.indexOf('debug')==-1) $('#log').hide();
if (firstRun) {
firstRun = false;
recognition.stop();
return;
}
showLog('-');
document.getElementById('miclabel').style.display = 'none';
document.getElementById('micna').style.display = 'none';
document.getElementById('micstart').style.display = 'inline';
document.getElementById('micstop').style.display = 'none';
};
function detect_token(transcript, token) {
const t = token.split(';');
for (let i in t) {
if (transcript.indexOf(t[i])>-1) return transcript.indexOf(t[i]) + t[i].length+1;
}
return -1;
}
function detectTranscript(transcript) {
const t = + new Date();
if ((transcript==oldText || (transcript=='te' && oldText.indexOf('te')>-1)) && t-oldTime<1500) return;
oldTime = t;
oldText = transcript;
speechStat = '';
let txt = transcript.toLowerCase();
if (txt.length>0) {
const tok = txt.split(' ')[0];
if (locale[lang].open.indexOf(tok)>-1) {
mode = 'open';
$('#search').hide();
$('#open').show();
txt = txt.replace(tok, '').replace(' ', '');
}
if (mode=='open' && txt.length>0) {
const token = document.location.search.indexOf('?d=')>-1? '&token='+document.location.search.split('?d=')[1].split('&')[0]: '';
const snd = './talk.php?open='+txt.toLowerCase().replace('.', '')+token+"&lang="+lang+"&host="+document.location.search.split('host=')[1].split('&')[0];
showLog(snd);
showLog(' host: '+host);
fetch(snd).then((response) => {return response.json();}).then((rlocale) => {
if (rlocale.length>=3 && rlocale[0].ws) {
$('#openTable').html('<tr><td colspan="5">' + locale[lang].openSelect + '</td></tr>');
for (let i=0; i<3; i++) {
$('#openTable').html($('#openTable').html()+'<tr><td>'+(i+1)+'</td><td>'+rlocale[i].title+'</td><td>'+rlocale[i].description+'</td><td>'+rlocale[i].exename+'</td></tr>');
window.openData.push(rlocale[i]);
}
}
$('#openTable').html('<tr><td>'+txt+'</td><td><input id="oname" class="oname"></input></td><td><button class="btn btn-primary" onClick="findPanel($(\"#oname\").val)">'+locale[lang].searchSubmit+'</button></td></tr>');
$(function() {$(".oname").autocomplete({source: launcher, select: function(event, ui) {findPanel(ui.item.value, txt); return false;}});});
window.openData.push(txt);
showLog('window.openData1');
showLog(window.openData);
mode = 'openTable';
$('#search').hide();
$('#open').show();
txt = '';
});
}
if (mode=='openTable' && txt.length>0) {
showLog('window.openData2');
showLog(window.openData);
showLog(txt);
txt = txt.replace('numero ', '');
let num = -1;
if (txt.indexOf(locale[lang].zero)>-1) num = -1;
if (txt.indexOf(locale[lang].one)>-1) num = 0;
if (txt.indexOf(locale[lang].two)>-1) num = 1;
if (txt.indexOf(locale[lang].three)>-1) num = 2;
if (!isNaN(txt)) num = txt - 1;
showLog(num);
if (num>-1) {
const exe = (window.openData[num].path? window.openData[num].path: '/runtime/bin/')+ window.openData[num].exename + '&host=' + document.location.search.split('host=')[1].split('&')[0];
showLog(exe);
showLog(launcherSrc+"?open="+exe+"&speech="+window.openData[3]+"&lang="+lang+"&id="+window.openData[num].id);
fetch(launcherSrc+"?open="+exe+"&speech="+window.openData[3]+"&lang="+lang+"&id="+window.openData[num].id)
.then((response) => {return response.json();})
.then((rlocale) => {showLog(rlocale);});
/*showLog("./talk.php?speech="+window.openData[3]+"&lang="+lang+"&id="+window.openData[num].id);
fetch("./talk.php?speech="+window.openData[3]+"&lang="+lang+"&id="+window.openData[num].id)
.then((response) => {return response.json();})
.then((rlocale) => {showLog(rlocale);});*/
}
mode = '';
$('#search').hide();
$('#open').hide();
$('#openTable').html('');
}
if (locale[lang].search.indexOf(tok)>-1) {
mode = 'search';
$('#search').show(); $('#open').hide();
// txt = txt.replace(tok+' ', '').replace('ing', 'inj').replace('inch', 'inj').split(' ').join('_').split('.').join('_').toUpperCase();
txt = txt.replace(tok+' ', '').split(' ').join('_').split('.').join('_').split('-').join('_').toUpperCase();
const token = document.location.search.indexOf('?d=')>-1? '&token='+document.location.search.split('?d=')[1].split('&')[0]: '';
const snd = './talk.php?search='+txt+token+"&lang="+lang+"&speech="+tok;
$('#openTable').html('<tr><td colspan="5">' + locale[lang].searchCorrect + '</td></tr><tr><td>'+txt+'</td><td><input id="sname" class="sname"></input></td><td><button class="btn btn-primary" onClick="findComponent($(\"#sname\").val)">'+locale[lang].searchSubmit+'</button></td></tr>');
$(function() {$(".sname").autocomplete({source: names, select: function(event, ui) {findComponent(ui.item.value, txt); return false;}});});
showLog(snd);
fetch(snd).then((response) => {return response.text();}).then((rlocale) => {
showLog(rlocale); /*alert(rlocale);*/
if (rlocale=='OK') $('#openTable').html('');
});
// mode = '';
// $('#search').hide(); $('#open').hide();
}
if (locale[lang].list.indexOf(tok)>-1) {
mode = 'list';
txt = txt.replace(tok, '').replace(' ', '');
}
if (mode=='list') {
const token = document.location.search.indexOf('?d=')>-1? '&token='+document.location.search.split('?d=')[1].split('&')[0]: '';
const snd = './talk.php?list='+tok+token;
fetch(snd).then((response) => {return response.json();}).then((rlocale) => {showLog(rlocale); alert(rlocale);});
mode = '';
$('#search').hide(); $('#open').hide();
}
showLog('mode: '+mode+', tok: '+tok);
}
return;
// transcript.replace('sky ','');
}
function findPanel(txt, speech) {
console.log(txt);
const token = document.location.search.indexOf('?d=')>-1? '&token='+document.location.search.split('?d=')[1].split('&')[0]: '';
const snd = './talk.php?open='+txt+token+"&lang="+lang+"&speech="+speech;
showLog(snd);
fetch(snd).then((response) => {return response.text();}).then((rlocale) => {showLog(rlocale); /*alert(rlocale);*/});
}
function findComponent(txt, speech) {
showLog(txt);
showLog(speech);
const token = document.location.search.indexOf('?d=')>-1? '&token='+document.location.search.split('?d=')[1].split('&')[0]: '';
const snd = './talk.php?search='+txt+token+"&lang="+lang+"&speech="+speech;
showLog(snd);
fetch(snd).then((response) => {return response.text();}).then((rlocale) => {showLog(rlocale); alert(rlocale);$('#openTable').html('');});
$(".sname").val(txt);
}
if (!String.prototype.replaceAll) {
String.prototype.replaceAll = function(search, replace) {
return this.split(search).join(replace);
};
}
function extractId(name) {
if (name.indexOf('(')>-1) {
let tok = name.split('(');
return [tok[0].replaceAll('.','_').replaceAll(' ','_').replace(/_+$/, ''), tok[1].replaceAll('.','_').replaceAll(' ','_').replaceAll(')','').replace(/_+$/, '')];
}
return [name.replaceAll('.','_').replaceAll(' ','_').replace(/_+$/, ''), false];
}
function initLattice(sections) {
for (let j=0; j<sections.length; j++) { // if(i>1) break;
const components = sections[j].components;
if (components) for (let i=0; i<components.length; i++) {
const id = extractId(components[i].name);
names.push(id[0]);
if (components[i].embedded) {
for (let j=0; j<components[i].embedded.length; j++) {names.push(components[i].embedded[j]);}
}
}
}
}
function initSearch(latticeFile) {
fetch(latticeFile).then((response) => {return response.json();}).then((flattice) => {
lattice = flattice;
if (Object.keys(lattice).length>0) {
for (let i in lattice) {
if (lattice[i].sections) initLattice(lattice[i].sections);
}
}
});
}
/* recognition.onresult = (event) => {
// The SpeechRecognitionEvent results property returns a SpeechRecognitionResultList object
// The SpeechRecognitionResultList object contains SpeechRecognitionResult objects.
// It has a getter so it can be accessed like an array
// The first [0] returns the SpeechRecognitionResult at position 0.
// Each SpeechRecognitionResult object contains SpeechRecognitionAlternative objects
// that contain individual results.
// These also have getters so they can be accessed like arrays.
// The second [0] returns the SpeechRecognitionAlternative at position 0.
// We then return the transcript property of the SpeechRecognitionAlternative object
const color = event.results[0][0].transcript;
diagnostic.textContent = `Result received: ${color}.`;
bg.style.backgroundColor = color;
};*/
recognition.onresult = (event) => {
let interimTranscript = '';
for (let i = event.resultIndex, len = event.results.length; i < len; i++) {
let transcript = event.results[i][0].transcript;
// const dt = + new Time() - t0;
if (event.results[i][0].transcript.length) showLog(' mode '+mode+', i: '+i+', transcripts: '+event.results[i][0].transcript+(event.results[i][1]? ', transcripts: '+event.results[i][1].transcript:'')+'\n');
if (event.results[i].isFinal) {
detectTranscript(transcript.toLowerCase());
var meno = transcript.toLowerCase().indexOf('meno ');
console.log(meno, transcript.substring(meno+5,meno+6), transcript.substring(meno+5,meno+6) % 1);
if (meno>-1 && transcript.substring(meno+5,meno+6) % 1 === 0) {
console.log('replace');
transcript = transcript.replace(transcript.substring(meno,meno+5), '-');
}
// finalTranscript += transcript+'<br>\\n';
if (transcript.length>0) finalTranscript = transcript;
} else {
interimTranscript += transcript+'<br>\\n';
}
document.getElementById('transcriptDiv').innerHTML = '<i style=\"color:#ddd;\">' + interimTranscript + '</i>';
}
// document.getElementById('transcriptDiv').innerHTML = finalTranscript + '<i style=\"color:#00d;\">' + interimTranscript + '</i>';
document.getElementById('transcriptDiv').innerHTML = '<i style=\"color:#00d;\">' + finalTranscript + '</i>';
};
recognition.start();