1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00
jellyfin-web/dashboard-ui/voice/voice.js

375 lines
12 KiB
JavaScript
Raw Normal View History

2016-02-17 07:58:07 +01:00
define(['paperdialoghelper'], function (paperDialogHelper) {
2015-06-02 01:46:06 -04:00
var currentRecognition;
2016-02-23 12:53:04 -05:00
var lang = 'en-US';
2015-06-02 01:46:06 -04:00
2016-02-23 12:53:04 -05:00
var commandgroups;
function getCommandGroups() {
if (commandgroups) {
return Promise.resolve(commandgroups);
}
return new Promise(function (resolve, reject) {
var file = "grammar";
//if (language && language.length > 0)
// file = language;
var xhr = new XMLHttpRequest();
xhr.open('GET', "voice/grammar/" + file + ".json", true);
xhr.onload = function (e) {
commandgroups = JSON.parse(this.response);
resolve(commandgroups);
}
xhr.onerror = reject;
xhr.send();
});
}
2016-02-17 07:58:07 +01:00
/// <summary> Shuffle array. </summary>
/// <param name="array"> The array. </param>
/// <returns> array </returns>
2015-06-02 01:46:06 -04:00
function shuffleArray(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
2016-02-17 07:58:07 +01:00
/// <summary> Gets sample commands. </summary>
/// <returns> The sample commands. </returns>
function getSampleCommands(groupid) {
2015-06-02 01:46:06 -04:00
2016-02-23 12:53:04 -05:00
return getCommandGroups().then(function (commandGroups) {
2016-02-17 07:58:07 +01:00
groupid = typeof (groupid) !== 'undefined' ? groupid : '';
2015-06-02 01:46:06 -04:00
2016-02-17 07:58:07 +01:00
var commands = [];
2016-02-23 12:53:04 -05:00
commandGroups.map(function (group) {
2016-02-17 07:58:07 +01:00
if ((group.items && group.items.length > 0) && (groupid == group.groupid || groupid == '')) {
2015-06-02 01:46:06 -04:00
2016-02-17 07:58:07 +01:00
group.items.map(function (item) {
2015-06-02 01:46:06 -04:00
2016-02-17 07:58:07 +01:00
if (item.commandtemplates && item.commandtemplates.length > 0) {
2015-12-14 10:43:03 -05:00
2016-02-17 07:58:07 +01:00
item.commandtemplates.map(function (templates) {
commands.push(templates);
});
}
2015-12-14 10:43:03 -05:00
2016-02-17 07:58:07 +01:00
});
2015-12-14 10:43:03 -05:00
}
2015-06-02 01:46:06 -04:00
});
2016-02-23 12:53:04 -05:00
return shuffleArray(commands);
2015-06-02 01:46:06 -04:00
});
}
2016-02-17 07:58:07 +01:00
/// <summary> Gets command group. </summary>
/// <param name="groupid"> The groupid. </param>
/// <returns> The command group. </returns>
function getCommandGroup(groupid) {
if (commandgroups) {
var idx = -1;
idx = commandgroups.map(function (e) { return e.groupid; }).indexOf(groupid);
if (idx > -1)
return commandgroups[idx];
else
return null;
}
else
return null;
2015-06-02 01:46:06 -04:00
}
2016-02-17 07:58:07 +01:00
/// <summary> Renders the sample commands. </summary>
/// <param name="elem"> The element. </param>
/// <param name="commands"> The commands. </param>
/// <returns> . </returns>
2015-06-02 01:46:06 -04:00
function renderSampleCommands(elem, commands) {
2016-02-23 12:53:04 -05:00
commands.length = Math.min(commands.length, 4);
2015-06-02 01:46:06 -04:00
commands = commands.map(function (c) {
2015-12-14 10:43:03 -05:00
return '<div class="exampleCommand"><span class="exampleCommandText">"' + c + '"</span></div>';
2015-06-02 01:46:06 -04:00
}).join('');
$('.exampleCommands', elem).html(commands);
}
2015-12-14 10:43:03 -05:00
var currentDialog;
2016-02-17 07:58:07 +01:00
/// <summary> Shows the voice help. </summary>
/// <returns> . </returns>
function showVoiceHelp(groupid, title) {
2015-06-02 01:46:06 -04:00
2015-12-14 10:43:03 -05:00
var dlg = paperDialogHelper.createDialog({
size: 'medium',
removeOnClose: true
});
2015-08-28 11:02:22 -04:00
2016-01-30 15:59:09 -05:00
dlg.classList.add('ui-body-b');
dlg.classList.add('background-theme-b');
2015-06-02 01:46:06 -04:00
var html = '';
2015-12-14 10:43:03 -05:00
html += '<h2 class="dialogHeader">';
2016-02-17 07:58:07 +01:00
html += '<paper-fab icon="arrow-back" mini class="btnCancelVoiceInput"></paper-fab>';
if (groupid) {
var grp = getCommandGroup(groupid);
if (grp)
html += ' ' + grp.name;
}
2015-12-14 10:43:03 -05:00
html += '</h2>';
2015-06-02 01:46:06 -04:00
2015-12-14 10:43:03 -05:00
html += '<div>';
2015-06-02 01:46:06 -04:00
2016-02-17 07:58:07 +01:00
var getCommandsPromise = getSampleCommands(groupid);
2015-06-02 01:46:06 -04:00
html += '<div class="voiceHelpContent">';
html += '<div class="defaultVoiceHelp">';
2016-02-23 12:53:04 -05:00
html += '<h1 style="margin-bottom:1.25em;">' + Globalize.translate('HeaderSaySomethingLike') + '</h1>';
2015-06-02 01:46:06 -04:00
html += '<div class="exampleCommands">';
html += '</div>';
// defaultVoiceHelp
html += '</div>';
html += '<div class="unrecognizedCommand" style="display:none;">';
html += '<h1>' + Globalize.translate('HeaderYouSaid') + '</h1>';
html += '<p class="exampleCommand voiceInputContainer"><i class="fa fa-quote-left"></i><span class="voiceInputText exampleCommandText"></span><i class="fa fa-quote-right"></i></p>';
html += '<p>' + Globalize.translate('MessageWeDidntRecognizeCommand') + '</p>';
html += '<br/>';
2015-08-01 17:17:46 -04:00
html += '<paper-button raised class="submit block btnRetry"><iron-icon icon="mic"></iron-icon><span>' + Globalize.translate('ButtonTryAgain') + '</span></paper-button>';
2015-06-02 01:46:06 -04:00
html += '<p class="blockedMessage" style="display:none;">' + Globalize.translate('MessageIfYouBlockedVoice') + '<br/><br/></p>';
html += '</div>';
2015-12-14 10:43:03 -05:00
html += '<paper-button raised class="block btnCancelVoiceInput" style="background-color:#444;"><iron-icon icon="close"></iron-icon><span>' + Globalize.translate('ButtonCancel') + '</span></paper-button>';
2015-06-02 01:46:06 -04:00
// voiceHelpContent
html += '</div>';
html += '</div>';
2015-12-14 10:43:03 -05:00
dlg.innerHTML = html;
document.body.appendChild(dlg);
2015-06-02 01:46:06 -04:00
2015-12-14 10:43:03 -05:00
paperDialogHelper.open(dlg);
currentDialog = dlg;
2015-06-02 01:46:06 -04:00
2015-12-14 10:43:03 -05:00
dlg.addEventListener('iron-overlay-closed', function () {
currentDialog = null;
});
2015-06-02 01:46:06 -04:00
2015-12-14 10:43:03 -05:00
$('.btnCancelVoiceInput', dlg).on('click', function () {
destroyCurrentRecognition();
paperDialogHelper.close(dlg);
2015-06-02 01:46:06 -04:00
});
2015-12-14 10:43:03 -05:00
$('.btnRetry', dlg).on('click', function () {
$('.unrecognizedCommand').hide();
$('.defaultVoiceHelp').show();
startListening(false);
});
getCommandsPromise.then(function (commands) {
renderSampleCommands(dlg.querySelector('.voiceHelpContent'), commands);
});
2015-06-02 01:46:06 -04:00
}
2016-02-17 07:58:07 +01:00
/// <summary> Hides the voice help. </summary>
/// <returns> . </returns>
function hideVoiceHelp() {
2015-06-02 01:46:06 -04:00
2016-02-17 07:58:07 +01:00
$('.voiceInputHelp').remove();
2015-06-02 01:46:06 -04:00
}
2016-02-17 07:58:07 +01:00
/// <summary> Shows the unrecognized command help. </summary>
/// <returns> . </returns>
function showUnrecognizedCommandHelp() {
//speak("I don't understend this command");
$('.unrecognizedCommand').show();
$('.defaultVoiceHelp').hide();
2015-06-02 01:46:06 -04:00
}
2016-02-17 07:58:07 +01:00
/// <summary> Process the transcript described by text. </summary>
/// <param name="text"> The text. </param>
/// <returns> . </returns>
2015-12-14 10:43:03 -05:00
function processTranscript(text, isCancelled) {
2015-06-02 01:46:06 -04:00
$('.voiceInputText').html(text);
2015-06-05 01:32:14 -04:00
if (text || AppInfo.isNativeApp) {
2015-06-02 01:46:06 -04:00
$('.blockedMessage').hide();
2016-02-17 07:58:07 +01:00
}
else {
2015-06-02 01:46:06 -04:00
$('.blockedMessage').show();
}
2015-12-14 10:43:03 -05:00
if (text) {
2016-02-17 07:58:07 +01:00
require(['voice/voicecommands.js', 'voice/grammarprocessor.js'], function (voicecommands, grammarprocessor) {
var processor = grammarprocessor(commandgroups, text);
if (processor && processor.command) {
voicecommands(processor)
.then(function (result) {
if (result.item.actionid === 'show' && result.item.sourceid === 'group') {
var dlg = currentDialog;
if (dlg)
showCommands(false, result)
else
showCommands(true, result)
}
})
.catch(showUnrecognizedCommandHelp);
}
else
showUnrecognizedCommandHelp();
var dlg = currentDialog;
if (dlg) {
2016-02-23 12:54:49 -05:00
paperDialogHelper.close(dlg);
2016-02-17 07:58:07 +01:00
}
});
}
else if (!isCancelled) {
2015-12-14 10:43:03 -05:00
showUnrecognizedCommandHelp();
}
2015-06-02 01:46:06 -04:00
}
2016-02-17 07:58:07 +01:00
/// <summary> Starts listening internal. </summary>
/// <returns> . </returns>
2015-12-14 10:43:03 -05:00
function startListening(createUI) {
2015-06-02 01:46:06 -04:00
destroyCurrentRecognition();
2016-02-17 07:58:07 +01:00
var recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition || window.mozSpeechRecognition || window.oSpeechRecognition || window.msSpeechRecognition)();
recognition.lang = lang;
var groupid = '';
2015-06-02 01:46:06 -04:00
//recognition.continuous = true;
//recognition.interimResults = true;
recognition.onresult = function (event) {
if (event.results.length > 0) {
processTranscript(event.results[0][0].transcript || '');
}
};
recognition.onerror = function () {
2015-12-14 10:43:03 -05:00
processTranscript('', recognition.cancelled);
2015-06-02 01:46:06 -04:00
};
recognition.onnomatch = function () {
2015-12-14 10:43:03 -05:00
processTranscript('', recognition.cancelled);
2015-06-02 01:46:06 -04:00
};
recognition.start();
currentRecognition = recognition;
2016-02-17 07:58:07 +01:00
showCommands(createUI);
}
/// <summary> Destroys the current recognition. </summary>
/// <returns> . </returns>
function destroyCurrentRecognition() {
var recognition = currentRecognition;
if (recognition) {
recognition.abort();
currentRecognition = null;
}
}
/// <summary> Cancel listener. </summary>
/// <returns> . </returns>
function cancelListener() {
destroyCurrentRecognition();
hideVoiceHelp();
}
2015-12-14 10:43:03 -05:00
2016-02-17 07:58:07 +01:00
/// <summary> Shows the commands. </summary>
/// <param name="createUI"> The create user interface. </param>
/// <returns> . </returns>
function showCommands(createUI, result) {
2015-12-14 10:43:03 -05:00
if (createUI !== false) {
2016-02-17 07:58:07 +01:00
//speak('Hello, what can I do for you?');
require(['paper-fab', 'css!voice/voice.css'], function () {
if (result)
showVoiceHelp(result.groupid, result.name);
else
showVoiceHelp();
});
}
}
/// <summary> Speaks the given text. </summary>
/// <param name="text"> The text. </param>
/// <returns> . </returns>
function speak(text) {
if (!SpeechSynthesisUtterance) {
console.log('API not supported');
2015-12-14 10:43:03 -05:00
}
2016-02-17 07:58:07 +01:00
var utterance = new SpeechSynthesisUtterance(text);
utterance.lang = lang;
utterance.rate = 0.9;
utterance.pitch = 1;
utterance.addEventListener('end', function () {
console.log('Synthesizing completed');
});
utterance.addEventListener('error', function (event) {
console.log('Synthesizing error');
});
console.log('Synthesizing the text: ' + text);
speechSynthesis.speak(utterance);
2015-06-02 01:46:06 -04:00
}
2016-02-17 07:58:07 +01:00
/// <summary> An enum constant representing the window. voice input manager option. </summary>
2016-02-23 12:53:04 -05:00
return {
2015-06-02 01:46:06 -04:00
isSupported: function () {
2015-06-02 13:46:44 -04:00
2015-12-14 10:43:03 -05:00
if (AppInfo.isNativeApp) {
2016-02-17 07:58:07 +01:00
// Crashes on some amazon devices
if (window.device && (device.platform || '').toLowerCase().indexOf('amazon') != -1) {
return false;
}
2015-12-14 10:43:03 -05:00
}
2016-02-17 07:58:07 +01:00
return window.SpeechRecognition ||
window.webkitSpeechRecognition ||
window.mozSpeechRecognition ||
window.oSpeechRecognition ||
window.msSpeechRecognition;
2015-06-02 01:46:06 -04:00
},
2016-02-23 12:53:04 -05:00
startListening: startListening
2015-06-02 01:46:06 -04:00
};
2016-01-30 14:31:22 -05:00
});