jellyfin-web/dashboard-ui/voice/voice.js

383 lines
11 KiB
JavaScript
Raw Normal View History

2015-06-01 22:46:06 -07:00
(function () {
var currentRecognition;
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;
}
function getSampleCommands() {
2015-12-14 08:43:03 -07:00
return new Promise(function (resolve, reject) {
2015-06-01 22:46:06 -07:00
2015-12-14 08:43:03 -07:00
var commands = [];
2015-06-01 22:46:06 -07:00
2015-12-14 08:43:03 -07:00
//commands.push('show my movies');
//commands.push('pull up my tv shows');
2015-06-01 22:46:06 -07:00
2015-12-14 08:43:03 -07:00
commands.push('play my latest episodes');
commands.push('play next up');
commands.push('shuffle my favorite songs');
2015-06-01 22:46:06 -07:00
2015-12-14 08:43:03 -07:00
commands.push('show my tv guide');
commands.push('pull up my recordings');
commands.push('control chromecast');
commands.push('control [device name]');
commands.push('turn on display mirroring');
commands.push('turn off display mirroring');
commands.push('toggle display mirroring');
2015-06-01 22:46:06 -07:00
2015-12-14 08:43:03 -07:00
resolve(shuffleArray(commands));
});
2015-06-01 22:46:06 -07:00
}
function processText(text) {
2015-12-14 08:43:03 -07:00
return new Promise(function (resolve, reject) {
require(['voice/textprocessor-en-us.js'], function (parseText) {
var result = parseText(text);
switch (result.action) {
case 'show':
showCommand(result);
break;
case 'play':
playCommand(result);
break;
case 'shuffle':
playCommand(result, true);
break;
case 'search':
playCommand(result);
break;
case 'control':
controlCommand(result);
break;
case 'enable':
enableCommand(result);
break;
case 'disable':
disableCommand(result);
break;
case 'toggle':
toggleCommand(result);
break;
default:
reject();
return;
}
var dlg = currentDialog;
if (dlg) {
PaperDialogHelper.close(dlg);
}
resolve();
});
2015-09-13 17:29:04 -07:00
});
2015-06-01 22:46:06 -07:00
}
function showCommand(result) {
if (result.category == 'tvguide') {
2015-08-04 11:14:16 -07:00
Dashboard.navigate('livetv.html?tab=1');
2015-06-01 22:46:06 -07:00
return;
}
if (result.category == 'recordings') {
2015-08-04 11:14:16 -07:00
Dashboard.navigate('livetv.html?tab=3');
2015-06-01 22:46:06 -07:00
return;
}
}
2015-08-01 14:17:46 -07:00
function enableCommand(result) {
var what = result.what.toLowerCase();
if (what.indexOf('mirror') != -1) {
MediaController.enableDisplayMirroring(true);
}
}
function disableCommand(result) {
var what = result.what.toLowerCase();
if (what.indexOf('mirror') != -1) {
MediaController.enableDisplayMirroring(false);
}
}
function toggleCommand(result) {
var what = result.what.toLowerCase();
if (what.indexOf('mirror') != -1) {
MediaController.toggleDisplayMirroring();
}
}
function controlCommand(result) {
MediaController.trySetActiveDeviceName(result.what);
}
2015-06-01 22:46:06 -07:00
function playCommand(result, shuffle) {
var query = {
Limit: result.limit || 100,
UserId: result.userId,
ExcludeLocationTypes: "Virtual"
};
if (result.category == 'nextup') {
2015-12-14 08:43:03 -07:00
ApiClient.getNextUpEpisodes(query).then(function (queryResult) {
2015-06-01 22:46:06 -07:00
playItems(queryResult.Items, shuffle);
});
return;
}
if (shuffle) {
result.sortby = result.sortby ? 'Random,' + result.sortby : 'Random';
}
query.SortBy = result.sortby;
query.SortOrder = result.sortorder;
query.Recursive = true;
if (result.filters.indexOf('unplayed') != -1) {
query.IsPlayed = false;
}
if (result.filters.indexOf('played') != -1) {
query.IsPlayed = true;
}
if (result.filters.indexOf('favorite') != -1) {
query.Filters = 'IsFavorite';
}
if (result.itemType) {
query.IncludeItemTypes = result.itemType;
}
2015-12-14 08:43:03 -07:00
ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function (queryResult) {
2015-06-01 22:46:06 -07:00
playItems(queryResult.Items, shuffle);
});
}
function playItems(items, shuffle) {
if (shuffle) {
items = shuffleArray(items);
}
2015-06-04 22:32:14 -07:00
items = items.map(function (i) {
2015-06-01 22:46:06 -07:00
return i.Id;
});
if (items.length) {
MediaController.play({
ids: items
});
} else {
Dashboard.alert({
message: Globalize.translate('MessageNoItemsFound')
});
}
}
function searchCommand(result) {
}
function renderSampleCommands(elem, commands) {
commands.length = Math.min(commands.length, 4);
commands = commands.map(function (c) {
2015-12-14 08:43:03 -07:00
return '<div class="exampleCommand"><span class="exampleCommandText">"' + c + '"</span></div>';
2015-06-01 22:46:06 -07:00
}).join('');
$('.exampleCommands', elem).html(commands);
}
2015-12-14 08:43:03 -07:00
var currentDialog;
function showVoiceHelp(paperDialogHelper) {
2015-06-01 22:46:06 -07:00
2015-12-14 08:43:03 -07:00
var dlg = paperDialogHelper.createDialog({
size: 'medium',
removeOnClose: true
});
2015-08-28 08:02:22 -07:00
2015-06-01 22:46:06 -07:00
var html = '';
2015-12-14 08:43:03 -07:00
html += '<h2 class="dialogHeader">';
html += '<paper-fab icon="arrow-back" mini class="btnCancelVoiceInput"></paper-fab>';
html += '</h2>';
2015-06-01 22:46:06 -07:00
2015-12-14 08:43:03 -07:00
html += '<div>';
2015-06-01 22:46:06 -07:00
2015-12-14 08:43:03 -07:00
var getCommandsPromise = getSampleCommands();
2015-06-01 22:46:06 -07:00
html += '<div class="voiceHelpContent">';
html += '<div class="defaultVoiceHelp">';
html += '<h1>' + Globalize.translate('HeaderSaySomethingLike') + '</h1>';
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 14:17:46 -07:00
html += '<paper-button raised class="submit block btnRetry"><iron-icon icon="mic"></iron-icon><span>' + Globalize.translate('ButtonTryAgain') + '</span></paper-button>';
2015-06-01 22:46:06 -07:00
html += '<p class="blockedMessage" style="display:none;">' + Globalize.translate('MessageIfYouBlockedVoice') + '<br/><br/></p>';
html += '</div>';
2015-12-14 08:43:03 -07: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-01 22:46:06 -07:00
// voiceHelpContent
html += '</div>';
html += '</div>';
2015-12-14 08:43:03 -07:00
dlg.innerHTML = html;
document.body.appendChild(dlg);
2015-06-01 22:46:06 -07:00
2015-12-14 08:43:03 -07:00
paperDialogHelper.open(dlg);
currentDialog = dlg;
2015-06-01 22:46:06 -07:00
2015-12-14 08:43:03 -07:00
dlg.addEventListener('iron-overlay-closed', function () {
currentDialog = null;
});
2015-06-01 22:46:06 -07:00
2015-12-14 08:43:03 -07:00
$('.btnCancelVoiceInput', dlg).on('click', function () {
destroyCurrentRecognition();
paperDialogHelper.close(dlg);
2015-06-01 22:46:06 -07:00
});
2015-12-14 08:43:03 -07:00
$('.btnRetry', dlg).on('click', function () {
$('.unrecognizedCommand').hide();
$('.defaultVoiceHelp').show();
startListening(false);
});
getCommandsPromise.then(function (commands) {
renderSampleCommands(dlg.querySelector('.voiceHelpContent'), commands);
});
2015-06-01 22:46:06 -07:00
}
function showUnrecognizedCommandHelp() {
$('.unrecognizedCommand').show();
$('.defaultVoiceHelp').hide();
}
function destroyCurrentRecognition() {
var recognition = currentRecognition;
if (recognition) {
2015-12-14 08:43:03 -07:00
recognition.cancelled = true;
2015-06-01 22:46:06 -07:00
recognition.abort();
currentRecognition = null;
}
}
2015-12-14 08:43:03 -07:00
function processTranscript(text, isCancelled) {
2015-06-01 22:46:06 -07:00
$('.voiceInputText').html(text);
2015-06-04 22:32:14 -07:00
if (text || AppInfo.isNativeApp) {
2015-06-01 22:46:06 -07:00
$('.blockedMessage').hide();
} else {
$('.blockedMessage').show();
}
2015-12-14 08:43:03 -07:00
if (text) {
processText(text).catch(showUnrecognizedCommandHelp);
} else if (!isCancelled) {
showUnrecognizedCommandHelp();
}
2015-06-01 22:46:06 -07:00
}
2015-12-14 08:43:03 -07:00
function startListening(createUI) {
2015-06-01 22:46:06 -07:00
destroyCurrentRecognition();
var recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
//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 08:43:03 -07:00
processTranscript('', recognition.cancelled);
2015-06-01 22:46:06 -07:00
};
recognition.onnomatch = function () {
2015-12-14 08:43:03 -07:00
processTranscript('', recognition.cancelled);
2015-06-01 22:46:06 -07:00
};
recognition.start();
currentRecognition = recognition;
2015-12-14 08:43:03 -07:00
if (createUI !== false) {
require(['components/paperdialoghelper', 'paper-fab', 'css!voice/voice.css'], showVoiceHelp);
}
2015-06-01 22:46:06 -07:00
}
window.VoiceInputManager = {
isSupported: function () {
2015-06-02 10:46:44 -07:00
2015-12-14 08:43:03 -07:00
if (AppInfo.isNativeApp) {
// Crashes on some amazon devices
if (window.device && (device.platform || '').toLowerCase().indexOf('amazon') != -1) {
return false;
}
}
2015-06-01 22:46:06 -07:00
return window.SpeechRecognition || window.webkitSpeechRecognition;
},
startListening: startListening
};
})();