diff --git a/js/app.js b/js/app.js index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8fa1b1715175d4e92f418b39ad7b3b9f1d5e0365 100644 --- a/js/app.js +++ b/js/app.js @@ -0,0 +1,9 @@ +function docReady(fn) { + // see if DOM is already available + if (document.readyState === "complete" || document.readyState === "interactive") { + // call on next available tick + setTimeout(fn, 1); + } else { + document.addEventListener("DOMContentLoaded", fn); + } +} \ No newline at end of file diff --git a/js/voice.js b/js/voice.js index 6db4aeff3ea94708077cb86a3673a1e25bc50ace..28159dcff89a5bc07f6f792d5ec396e2ce18f06a 100644 --- a/js/voice.js +++ b/js/voice.js @@ -2,21 +2,67 @@ var voiceBtn = document.getElementById("voiceBtn"); var voiceDiv = document.getElementById("voiceDiv"); var voiceSpan = document.getElementById("voiceSpan"); var heardSpan = document.getElementById("heardSpan"); +var commandSpan = document.getElementById("commandSpan"); + +const voiceSelect = document.getElementById("selectVoice"); + +let voices = []; + +const synth = window.speechSynthesis; var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition; var SpeechGrammarList = SpeechGrammarList || webkitSpeechGrammarList; var SpeechRecognitionEvent = SpeechRecognitionEvent || webkitSpeechRecognitionEvent; +function populateVoiceList() { + voices = synth.getVoices().sort(function (a, b) { + const aname = a.name.toUpperCase(); + const bname = b.name.toUpperCase(); + + if (aname < bname) { + return -1; + } else if (aname == bname) { + return 0; + } else { + return +1; + } + }); + + const selectedIndex = voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex; + + for (let i = 0; i < voices.length; i++) { + const option = document.createElement("option"); + option.textContent = `${voices[i].name} (${voices[i].lang})`; + + if (voices[i].default) { + option.textContent += " -- DEFAULT"; + } + + option.setAttribute("data-lang", voices[i].lang); + option.setAttribute("data-name", voices[i].name); + voiceSelect.appendChild(option); + } + voiceSelect.selectedIndex = selectedIndex; +} + voiceBtn.addEventListener("click", startListening); +if ('speechSynthesis' in window) { + +}else{ + // Speech Synthesis Not Supported + alert("Sorry, your browser doesn't support text to speech!"); +} + function startListening(){ voiceBtn.disabled = true; voiceSpan.innerText = 'Dites "Cristo !" pour commencer a donner votre requete'; voiceSpan.style.display = ""; heardSpan.innerText = ""; heardSpan.style.display = "none"; + commandSpan.innerText = ""; + commandSpan.style.display = "none"; voiceBtn.innerText = "Ecoute en cours"; - listenForCristo(); } @@ -36,34 +82,31 @@ function listenForCristo(){ recognition.lang = 'fr-FR'; recognition.interimResults = false; recognition.maxAlternatives = 1; - + speak("Dites cristeaux pour donner votre requete"); recognition.start(); - console.log('Started listening'); + console.log('Started first listening'); recognition.onresult = function(event) { console.log('Listened'); - /* if(heard.toLowerCase().includes("cristo")){ - - } */ var speechResult = event.results[0][0].transcript.toLowerCase(); console.log(speechResult); heardSpan.innerText += " A entendu = " + speechResult; heardSpan.style.display = ""; + voiceSpan.style.display = "none"; + console.log('Confidence: ' + event.results[0][0].confidence); if(speechResult.toLowerCase().includes("cristaux")){ + speak("Veuillez me donner votre requete"); console.log('Heard Cristo ! (or Cristaux)'); + listenForCommand(); } else { + speak("Je n'ai pas entendu Cristeaux"); console.log('Heard nothing'); + enableBtn(); } - voiceSpan.style.display = "none"; - console.log('Confidence: ' + event.results[0][0].confidence); } recognition.onspeechend = function() { recognition.stop(); - voiceBtn.disabled = false; - voiceBtn.textContent = 'Ecouter a nouveau'; - voiceSpan.style.display = "none"; } - recognition.onerror = function(event) { voiceBtn.disabled = false; voiceBtn.textContent = 'Ecouter a nouveau'; @@ -72,39 +115,119 @@ function listenForCristo(){ heardSpan.innerText += " Erreur "; heardSpan.style.display = ""; } - recognition.onaudiostart = function(event) { //Fired when the user agent has started to capture audio. console.log('SpeechRecognition.onaudiostart'); - } - + } recognition.onaudioend = function(event) { //Fired when the user agent has finished capturing audio. console.log('SpeechRecognition.onaudioend'); - } - + } recognition.onend = function(event) { //Fired when the speech recognition service has disconnected. - console.log('SpeechRecognition.onend'); - console.log("A entendu = " + event.results); + /* console.log('SpeechRecognition.onend'); */ + /* console.log("A entendu = " + event.results); */ voiceSpan.style.display = "none"; } - recognition.onnomatch = function(event) { //Fired when the speech recognition service returns a final result with no significant recognition. This may involve some degree of recognition, which doesn't meet or exceed the confidence threshold. console.log('SpeechRecognition.onnomatch'); } - recognition.onsoundstart = function(event) { //Fired when any sound — recognisable speech or not — has been detected. console.log('SpeechRecognition.onsoundstart'); + } + recognition.onsoundend = function(event) { + //Fired when any sound — recognisable speech or not — has stopped being detected. + /* console.log('SpeechRecognition.onsoundend'); */ } - + recognition.onspeechstart = function (event) { + //Fired when sound that is recognised by the speech recognition service as speech has been detected. + console.log('SpeechRecognition.onspeechstart'); + } + recognition.onstart = function(event) { + //Fired when the speech recognition service has begun listening to incoming audio with intent to recognize grammars associated with the current SpeechRecognition. + console.log('SpeechRecognition.onstart'); + } +} + +function listenForCommand(){ + var grammar = '#JSGF V1.0; grammar phrase; public <phrase> = descends | descend | remonte | monte | recette | aleatoire | suivante | precedente;'; + var recognition = new SpeechRecognition(); + var speechRecognitionList = new SpeechGrammarList(); + speechRecognitionList.addFromString(grammar, 1); + recognition.grammars = speechRecognitionList; + recognition.lang = 'fr-FR'; + recognition.interimResults = false; + recognition.maxAlternatives = 1; + recognition.start(); + console.log('Started first listening'); + recognition.onresult = function(event) { + console.log('Listened'); + var speechResult = event.results[0][0].transcript.toLowerCase(); + console.log(speechResult); + heardSpan.innerText += " A entendu = " + speechResult; + heardSpan.style.display = ""; + voiceSpan.style.display = "none"; + console.log('Confidence: ' + event.results[0][0].confidence); + if(speechResult.toLowerCase().includes("descend")){ + speak("Je vais descendre dans la page"); + } + else if(speechResult.toLowerCase().includes("monte")){ + speak("Je vais monter dans la page"); + } + else if(speechResult.toLowerCase().includes("recette")){ + if(speechResult.toLowerCase().includes("précédente")){ + speak("Voici la recette precedente"); + } + else if(speechResult.toLowerCase().includes("suivante")){ + speak("Voici la prochaine recette"); + } + else if(speechResult.toLowerCase().includes("aléatoire")){ + speak("Voici une recette aleatoire"); + } + } + else { + speak("Je n'ai rien entendu ou je n'ai pas reconnu la requete"); + } + enableBtn(); + } + + recognition.onspeechend = function() { + recognition.stop(); + } + recognition.onerror = function(event) { + enableBtn(); + diagnosticPara.textContent = 'Error occurred in recognition: ' + event.error; + heardSpan.innerText += " Erreur "; + heardSpan.style.display = ""; + } + recognition.onaudiostart = function(event) { + //Fired when the user agent has started to capture audio. + console.log('SpeechRecognition.onaudiostart'); + } + recognition.onaudioend = function(event) { + //Fired when the user agent has finished capturing audio. + console.log('SpeechRecognition.onaudioend'); + } + recognition.onend = function(event) { + //Fired when the speech recognition service has disconnected. + /* console.log('SpeechRecognition.onend'); */ + /* console.log("A entendu = " + event.results); */ + voiceSpan.style.display = "none"; + } + recognition.onnomatch = function(event) { + //Fired when the speech recognition service returns a final result with no significant recognition. This may involve some degree of recognition, which doesn't meet or exceed the confidence threshold. + console.log('SpeechRecognition.onnomatch'); + } + recognition.onsoundstart = function(event) { + //Fired when any sound — recognisable speech or not — has been detected. + console.log('SpeechRecognition.onsoundstart'); + } recognition.onsoundend = function(event) { //Fired when any sound — recognisable speech or not — has stopped being detected. - console.log('SpeechRecognition.onsoundend'); + /* console.log('SpeechRecognition.onsoundend'); */ } - recognition.onspeechstart = function (event) { //Fired when sound that is recognised by the speech recognition service as speech has been detected. console.log('SpeechRecognition.onspeechstart'); @@ -114,4 +237,45 @@ function listenForCristo(){ console.log('SpeechRecognition.onstart'); } } - \ No newline at end of file + +function speak(text){ + if (synth.speaking) { + console.error("speechSynthesis.speaking"); + return; + } + + const utterThis = new SpeechSynthesisUtterance(text); + utterThis.onend = function (event) { + console.log("SpeechSynthesisUtterance.onend"); + }; + utterThis.onerror = function (event) { + console.error("SpeechSynthesisUtterance.onerror"); + }; + + for (let i = 0; i < voices.length; i++) { + if (voices[i].name === voiceSelect.selectedOptions[0].getAttribute("data-name")) { + utterThis.voice = voices[i]; + break; + } + } + + utterThis.pitch = 1; + utterThis.rate = 1; + + synth.speak(utterThis); +} + +function enableBtn(){ + voiceBtn.disabled = false; + voiceBtn.textContent = 'Ecouter a nouveau'; + voiceSpan.style.display = "none"; +} + +function scrollDown(){ + +} + +docReady(function() { + populateVoiceList(); + voiceSelect.value= "Microsoft Paul - French (France) (fr-FR)"; +}); \ No newline at end of file diff --git a/pages/accueil.php b/pages/accueil.php index ddaffff6737e975c613b752e47f79dfcbeedca90..ac191813f546df708da81dac2fc4394ecbf8ef92 100644 --- a/pages/accueil.php +++ b/pages/accueil.php @@ -16,13 +16,14 @@ <h1 class="logo">Crist'o </h1> <h1> Trouvez les recettes parfaites pour vous, sans lever le petit doigt ! </h1> - <div class="input-part d-flex flex-column"> <form action="/action_page.php" method="get" class="d-flex gap-3"> <div class="d-flex flex-column gap-3 flex-grow-1"> <input class="form-control rounded-pill" type="text" placeholder="Chercher quelque chose" name="search"> <span class="text-uppercase text-center">ou</span> - <span class="fw-bold text-center"><i class="fa fa-microphone"></i> Demandez à Crist'o</span> + <?php + require('voice.php'); + ?> </div> <div> <button class="btn btn-light rounded-pill" type="submit"><i class="fa fa-search"></i></button> @@ -36,7 +37,11 @@ <div class="votrerecette"> <p> Vous souhaitez ajouter votre recette ? Cliquez ici</p> </div> + <div style="background-color:lightgray;height:3000px;"> + </div> + Cela etais un test pour le scroll + Bas de la page <?php //include "footer.php"; ?> </body> </html> \ No newline at end of file diff --git a/pages/voice.php b/pages/voice.php index bbda79537a59400b39a7b143a8ca44949bc90b8f..fb299c964bd197b3365cc7f2e1f5e93484ea1e0b 100644 --- a/pages/voice.php +++ b/pages/voice.php @@ -1,5 +1,9 @@ <div id="voiceDiv"> - <i class="fa-solid fa-microphone"></i><button id="voiceBtn">Commencer l'ecoute du micro</button><span id="voiceSpan" style="display:none"></span> + <!-- <span class="fw-bold"><i class="fa fa-microphone"></i>Demandez à Crist'o</span> --> + <i class="fa fa-microphone"></i><button id="voiceBtn">Commencer l'ecoute du micro</button><span id="voiceSpan" style="display:none"></span> <br> <span id="heardSpan" style="display:none"></span> + <span id="commandSpan" style="display:none"></span> + <select id="selectVoice" style="display:none;"></select> + <p>Voici les commandes : -Descend -Remonte -recette suivante - recette precedente -recette aleatoire</p> </div> \ No newline at end of file diff --git a/styles/scss/app.scss b/styles/scss/app.scss index 97197fa60a5d673c507c97e9a65b2531d9457b6a..06804f77eaf5f6fceb102a188171c8ff944dd53c 100644 --- a/styles/scss/app.scss +++ b/styles/scss/app.scss @@ -1,6 +1,10 @@ @import url('https://fonts.googleapis.com/css2?family=Jacques+Francois+Shadow&family=Roboto:wght@500&display=swap'); @import "../bootstrap/bootstrap"; +html { + scroll-behavior: smooth; +} + body { font-family: 'Roboto', sans-serif; }