Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
| const unzipper = require('unzipper') | |
| const er = require('@electron/remote') | |
| /** | |
| * String.prototype.replaceAll() polyfill | |
| * https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/ | |
| * @author Chris Ferdinandi | |
| * @license MIT | |
| */ | |
| if (!String.prototype.replaceAll) { | |
| String.prototype.replaceAll = function(str, newStr){ | |
| // If a regex pattern | |
| if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') { | |
| return this.replace(str, newStr); | |
| } | |
| // If a string | |
| return this.replace(new RegExp(str, 'g'), newStr); | |
| }; | |
| } | |
| window.toggleSpinnerButtons = (spinnerVisible=undefined) => { | |
| if (spinnerVisible===undefined) { | |
| spinnerVisible = window.getComputedStyle(spinner).display == "block" | |
| } | |
| spinner.style.display = spinnerVisible ? "none" : "block" | |
| keepSampleButton.style.display = spinnerVisible ? "block" : "none" | |
| generateVoiceButton.style.display = spinnerVisible ? "block" : "none" | |
| samplePlayPause.style.display = spinnerVisible ? "flex" : "none" | |
| } | |
| window.infoModal = message => new Promise(resolve => resolve(createModal("info", message))) | |
| window.confirmModal = message => new Promise(resolve => resolve(createModal("confirm", message))) | |
| window.spinnerModal = message => new Promise(resolve => resolve(createModal("spinner", message))) | |
| window.errorModal = message => { | |
| window.errorModalHasOpened = true | |
| if (window.userSettings.useErrorSound) { | |
| const audioPreview = createElem("audio", {autoplay: false}, createElem("source", { | |
| src: window.userSettings.errorSoundFile | |
| })) | |
| audioPreview.setSinkId(window.userSettings.base_speaker) | |
| } | |
| window.electronBrowserWindow.setProgressBar(window.batch_state.taskBarPercent?window.batch_state.taskBarPercent:1, {mode: "error"}) | |
| return new Promise(topResolve => { | |
| createModal("error", message).then(() => { | |
| window.electronBrowserWindow.setProgressBar(window.batch_state.taskBarPercent?window.batch_state.taskBarPercent:-1, {mode: window.batch_state.state?"normal":"paused"}) | |
| topResolve() | |
| }) | |
| }) | |
| } | |
| window.createModal = (type, message) => { | |
| dialogueInput.blur() | |
| return new Promise(resolve => { | |
| modalContainer.innerHTML = "" | |
| const displayMessage = message.prompt ? message.prompt : message | |
| const modal = createElem("div.modal#activeModal", {style: {opacity: 0}}, createElem("span.createModalContents", displayMessage)) | |
| modal.dataset.type = type | |
| if (type=="confirm") { | |
| const yesButton = createElem("button", {style: {background: `#${themeColour}`}}) | |
| yesButton.innerHTML = window.i18n.YES | |
| const noButton = createElem("button", {style: {background: `#${themeColour}`}}) | |
| noButton.innerHTML = window.i18n.NO | |
| modal.appendChild(createElem("div", yesButton, noButton)) | |
| yesButton.addEventListener("click", () => { | |
| closeModal(modalContainer).then(() => { | |
| resolve(true) | |
| }) | |
| }) | |
| noButton.addEventListener("click", () => { | |
| closeModal(modalContainer).then(() => { | |
| resolve(false) | |
| }) | |
| }) | |
| } else if (type=="error" || type=="info") { | |
| const closeButton = createElem("button", {style: {background: `#${themeColour}`}}) | |
| closeButton.innerHTML = window.i18n.CLOSE | |
| modal.appendChild(createElem("div", closeButton)) | |
| closeButton.addEventListener("click", () => { | |
| closeModal(modalContainer).then(() => { | |
| resolve(false) | |
| }) | |
| }) | |
| } else if (type=="prompt") { | |
| const closeButton = createElem("button", {style: {background: `#${themeColour}`}}) | |
| closeButton.innerHTML = window.i18n.SUBMIT | |
| const inputElem = createElem("input", {type: "text", value: message.value}) | |
| modal.appendChild(createElem("div", inputElem)) | |
| modal.appendChild(createElem("div", closeButton)) | |
| closeButton.addEventListener("click", () => { | |
| closeModal(modalContainer).then(() => { | |
| resolve(inputElem.value) | |
| }) | |
| }) | |
| } else { | |
| modal.appendChild(createElem("div.spinner", {style: {borderLeftColor: document.querySelector("button").style.background}})) | |
| } | |
| modalContainer.appendChild(modal) | |
| modalContainer.style.opacity = 0 | |
| modalContainer.style.display = "flex" | |
| requestAnimationFrame(() => requestAnimationFrame(() => modalContainer.style.opacity = 1)) | |
| requestAnimationFrame(() => requestAnimationFrame(() => chromeBar.style.opacity = 1)) | |
| }) | |
| } | |
| window.closeModal = (container=undefined, notThisOne=undefined, skipIfErrorOpen=false) => { | |
| return new Promise(resolve => { | |
| if (window.errorModalHasOpened && skipIfErrorOpen) { | |
| return resolve() | |
| } | |
| window.errorModalHasOpened = false | |
| const allContainers = [batchGenerationContainer, gameSelectionContainer, updatesContainer, infoContainer, settingsContainer, patreonContainer, pluginsContainer, modalContainer, nexusContainer, embeddingsContainer, totdContainer, nexusReposContainer, EULAContainer, arpabetContainer, styleEmbeddingsContainer, workbenchContainer] | |
| const containers = container==undefined ? allContainers : (Array.isArray(container) ? container.filter(c=>c!=undefined) : [container]) | |
| notThisOne = Array.isArray(notThisOne) ? notThisOne : (notThisOne==undefined ? [] : [notThisOne]) | |
| containers.forEach(cont => { | |
| // Fade out the containers except the exceptions | |
| if (cont!=undefined && !notThisOne.includes(cont)) { | |
| cont.style.opacity = 0 | |
| } | |
| }) | |
| const someOpenContainer = allContainers.filter(c=>c!=undefined).find(cont => cont.style.opacity==1 && cont.style.display!="none" && cont!=modalContainer) | |
| if (!someOpenContainer || someOpenContainer==container) { | |
| chromeBar.style.opacity = 0.88 | |
| } | |
| setTimeout(() => { | |
| if (window.errorModalHasOpened && skipIfErrorOpen) { | |
| } else { | |
| containers.forEach(cont => { | |
| // Hide the containers except the exceptions | |
| if (cont!=undefined && !notThisOne.includes(cont)) { | |
| cont.style.display = "none" | |
| const someOpenContainer2 = allContainers.filter(c=>c!=undefined).find(cont => cont.style.opacity==1 && cont.style.display!="none" && cont!=modalContainer) | |
| if (!someOpenContainer2 || someOpenContainer2==container) { | |
| chromeBar.style.opacity = 0.88 | |
| } | |
| } | |
| }) | |
| window.errorModalHasOpened = false | |
| } | |
| // resolve() | |
| }, 200) | |
| try { | |
| activeModal.remove() | |
| } catch (e) {} | |
| resolve() | |
| }) | |
| } | |
| window.setTheme = (meta) => { | |
| const primaryColour = meta.themeColourPrimary | |
| const secondaryColour = meta.themeColourSecondary | |
| const gameName = meta.gameName | |
| if (window.userSettings.showDiscordStatus) { | |
| ipcRenderer.send('updateDiscord', {details: gameName}) | |
| } | |
| // Change batch panel colours, if it is initialized | |
| try { | |
| Array.from(batchRecordsHeader.children).forEach(item => item.style.backgroundColor = `#${primaryColour}`) | |
| } catch (e) {} | |
| try { | |
| Array.from(pluginsRecordsHeader.children).forEach(item => item.style.backgroundColor = `#${primaryColour}`) | |
| } catch (e) {} | |
| try { | |
| Array.from(styleembsRecordsHeader.children).forEach(item => item.style.backgroundColor = `#${primaryColour}`) | |
| } catch (e) {} | |
| try { | |
| Array.from(nexusRecordsHeader.children).forEach(item => item.style.backgroundColor = `#${primaryColour}`) | |
| } catch (e) {} | |
| try { | |
| Array.from(nexusSearchHeader.children).forEach(item => item.style.backgroundColor = `#${primaryColour}`) | |
| } catch (e) {} | |
| try { | |
| Array.from(nexusReposUsedHeader.children).forEach(item => item.style.backgroundColor = `#${primaryColour}`) | |
| } catch (e) {} | |
| try { | |
| Array.from(embeddingsRecordsHeader.children).forEach(item => item.style.backgroundColor = `#${primaryColour}`) | |
| } catch (e) {} | |
| try { | |
| Array.from(arpabetWordsListHeader.children).forEach(item => item.style.backgroundColor = `#${primaryColour}`) | |
| } catch (e) {} | |
| try { | |
| window.sequenceEditor.grabbers.forEach(grabber => grabber.fillStyle = `#${primaryColour}`) | |
| window.sequenceEditor.energyGrabbers.forEach(grabber => grabber.fillStyle = `#${primaryColour}`) | |
| } catch (e) {} | |
| const background = `linear-gradient(0deg, rgba(128,128,128,${window.userSettings.bg_gradient_opacity}) 0px, rgba(0,0,0,0)), url("assets/${meta.assetFile}")` | |
| Array.from(document.querySelectorAll("button:not(.fixedColour)")).forEach(e => e.style.background = `#${primaryColour}`) | |
| Array.from(document.querySelectorAll(".voiceType")).forEach(e => e.style.background = `#${primaryColour}`) | |
| Array.from(document.querySelectorAll(".spinner")).forEach(e => e.style.borderLeftColor = `#${primaryColour}`) | |
| Array.from(document.querySelectorAll(".checkbox")).forEach(e => e.style.accentColor = `#${primaryColour}`) | |
| Array.from(document.querySelectorAll(".input[type=range]")).forEach(e => e.style.accentColor = `#${primaryColour}`) | |
| if (secondaryColour) { | |
| Array.from(document.querySelectorAll("button:not(.fixedColour)")).forEach(e => e.style.color = `#${secondaryColour}`) | |
| Array.from(document.querySelectorAll(".voiceType")).forEach(e => e.style.color = `#${secondaryColour}`) | |
| Array.from(document.querySelectorAll("button")).forEach(e => e.style.textShadow = `none`) | |
| Array.from(document.querySelectorAll(".voiceType")).forEach(e => e.style.textShadow = `none`) | |
| } else { | |
| Array.from(document.querySelectorAll("button:not(.fixedColour)")).forEach(e => e.style.color = `white`) | |
| Array.from(document.querySelectorAll(".voiceType")).forEach(e => e.style.color = `white`) | |
| Array.from(document.querySelectorAll("button")).forEach(e => e.style.textShadow = `0 0 2px black`) | |
| Array.from(document.querySelectorAll(".voiceType")).forEach(e => e.style.textShadow = `0 0 2px black`) | |
| } | |
| if (window.wavesurfer) { | |
| window.wavesurfer.setWaveColor(`#${window.currentGame.themeColourPrimary}`) | |
| } | |
| // Fade the background image transition | |
| rightBG1.style.background = background | |
| rightBG2.style.opacity = 0 | |
| setTimeout(() => { | |
| rightBG2.style.background = rightBG1.style.background | |
| rightBG2.style.opacity = 1 | |
| }, 1000) | |
| cssHack.innerHTML = `::selection { | |
| background: #${primaryColour}; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background-color: #${primaryColour} !important; | |
| } | |
| .slider::-webkit-slider-thumb { | |
| background-color: #${primaryColour} !important; | |
| } | |
| input[type=checkbox], input[type=range] {accent-color: #${primaryColour} !important;} | |
| a {color: #${primaryColour}}; | |
| #batchRecordsHeader > div {background-color: #${primaryColour} !important;} | |
| #pluginsRecordsHeader > div {background-color: #${primaryColour} !important;} | |
| .invertedButton { | |
| background: none !important; | |
| border: 2px solid #${primaryColour} !important; | |
| } | |
| ` | |
| if (secondaryColour) { | |
| cssHack.innerHTML += ` | |
| #batchRecordsHeader > div {color: #${secondaryColour} !important;text-shadow: none} | |
| #pluginsRecordsHeader > div {color: #${secondaryColour} !important;text-shadow: none} | |
| ` | |
| } else { | |
| cssHack.innerHTML += ` | |
| #batchRecordsHeader > div {color: white !important;text-shadow: 0 0 2px black;} | |
| #pluginsRecordsHeader > div {color: white !important;text-shadow: 0 0 2px black;} | |
| ` | |
| } | |
| } | |
| window.getAudioPlayTriangleSVG = () => { | |
| const div = createElem("div", `<svg class="renameSVG" version="1.0" xmlns="http://www.w3.org/2000/svg" width="770.000000pt" height="980.000000pt" viewBox="0 0 770.000000 980.000000" | |
| preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,980.000000) scale(0.100000,-0.100000)"fill="#555555" stroke="none"> | |
| <path d="M26 9718 c-3 -46 -9 -2249 -12 -4897 -5 -4085 -4 -4813 8 -4809 8 3 | |
| 389 244 848 535 459 291 1598 1013 2530 1603 2872 1819 3648 2311 4182 2656 | |
| 60 38 108 75 108 81 0 55 -595 448 -2855 1886 -1259 801 -4552 2877 -4792 | |
| 3020 -8 5 -13 -16 -17 -75z"/> | |
| </g> | |
| </svg>`) | |
| return div | |
| } | |
| window.addEventListener("resize", e => { | |
| window.userSettings.customWindowSize = `${window.innerHeight},${window.innerWidth}` | |
| saveUserSettings() | |
| }) | |
| // Keyboard actions | |
| // ================ | |
| window.addEventListener("keyup", event => { | |
| if (!event.ctrlKey) { | |
| window.ctrlKeyIsPressed = false | |
| } | |
| if (!event.shiftKey) { | |
| window.shiftKeyIsPressed = false | |
| } | |
| }) | |
| dialogueInput.addEventListener("keydown", event => { | |
| if (event.target==dialogueInput || event.target==letterPitchNumb || event.target==letterLengthNumb) { | |
| // Enter: Generate sample | |
| if (event.key=="Enter") { | |
| generateVoiceButton.click() | |
| event.preventDefault() | |
| } | |
| return | |
| } | |
| }) | |
| window.addEventListener("click", event => { | |
| if (event.target.id!="dialogueInput") { | |
| window.hideAutocomplete() | |
| } | |
| }) | |
| window.addEventListener("keydown", event => { | |
| if (event.ctrlKey) { | |
| window.ctrlKeyIsPressed = true | |
| } | |
| if (event.shiftKey) { | |
| window.shiftKeyIsPressed = true | |
| } | |
| if (event.ctrlKey && event.key.toLowerCase()=="r") { | |
| location.reload() | |
| } | |
| if (event.ctrlKey && event.shiftKey && event.key.toLowerCase()=="i") { | |
| window.electron = require("electron") | |
| er.BrowserWindow.getFocusedWindow().webContents.openDevTools() | |
| return | |
| } | |
| if (event.ctrlKey) { | |
| window.ctrlKeyIsPressed = true | |
| } | |
| // Re-gen the line if the user presses CTRL-ENTER, evne outside the prompt box | |
| if (event.key=="Enter" && window.ctrlKeyIsPressed) { | |
| generateVoiceButton.click() | |
| } | |
| // The Enter key to submit text input prompts in modals | |
| if (event.key=="Enter" && modalContainer.style.display!="none" && event.target.tagName=="INPUT") { | |
| activeModal.querySelector("button").click() | |
| } | |
| const key = event.key.toLowerCase() | |
| // CTRL-S: Keep sample | |
| if (key=="s" && event.ctrlKey && !event.shiftKey) { | |
| keepSampleFunction(false) | |
| } | |
| // CTRL-SHIFT-S: Keep sample (but with rename prompt) | |
| if (key=="s" && event.ctrlKey && event.shiftKey) { | |
| keepSampleFunction(true) | |
| } | |
| // Disable keyboard controls while in a text input | |
| if (event.target.tagName=="INPUT" && event.target.tagName!=dialogueInput || event.target.tagName=="TEXTAREA") { | |
| return | |
| } | |
| if (event.target==dialogueInput || event.target==letterPitchNumb || event.target==letterLengthNumb) { | |
| // Enter: Generate sample | |
| if (event.key=="Enter") { | |
| generateVoiceButton.click() | |
| event.preventDefault() | |
| } | |
| return | |
| } | |
| // Escape: close modals | |
| if (key=="escape") { | |
| closeModal() | |
| } | |
| // Space: bring focus to the input textarea | |
| if (key==" ") { | |
| setTimeout(() => dialogueInput.focus(), 0) | |
| } | |
| // Create selection for all of the editor letters | |
| if (key=="a" && event.ctrlKey && !event.shiftKey) { | |
| window.sequenceEditor.letterFocus = [] | |
| window.sequenceEditor.sliderBoxes.forEach((_,i) => { | |
| window.sequenceEditor.letterFocus.push(i) | |
| window.sequenceEditor.setLetterFocus(i, true) | |
| }) | |
| event.preventDefault() | |
| return | |
| } | |
| // Y/N for prompt modals | |
| if (key=="y" || key=="n" || key==" ") { | |
| if (document.querySelector("#activeModal")) { | |
| const buttons = Array.from(document.querySelector("#activeModal").querySelectorAll("button")) | |
| const yesBtn = buttons.find(btn => btn.innerHTML.toLowerCase()=="yes") | |
| const noBtn = buttons.find(btn => btn.innerHTML.toLowerCase()=="no") | |
| if (key=="y") yesBtn.click() | |
| if (key==" ") yesBtn.click() | |
| if (key=="n") noBtn.click() | |
| } | |
| } | |
| // Left/Right arrows: Move between letter focused (clears multi-select, picks the min(0,first-1) if left, max($L, last+1) if right) | |
| // SHIFT-Left/Right: multi-letter create selection range | |
| if ((key=="arrowleft" || key=="arrowright") && !event.ctrlKey) { | |
| event.preventDefault() | |
| if (window.sequenceEditor.letterFocus.length==0) { | |
| window.sequenceEditor.setLetterFocus(0) | |
| } else if (window.sequenceEditor.letterFocus.length==1) { | |
| const curr_l = window.sequenceEditor.letterFocus[0] | |
| const newIndex = key=="arrowleft" ? Math.max(0, curr_l-1) : Math.min(curr_l+1, window.sequenceEditor.letters.length-1) | |
| window.sequenceEditor.setLetterFocus(newIndex, event.shiftKey) | |
| } else { | |
| if (key=="arrowleft") { | |
| window.sequenceEditor.setLetterFocus(Math.max(0, Math.min(...window.sequenceEditor.letterFocus)-1), event.shiftKey) | |
| } else { | |
| window.sequenceEditor.setLetterFocus(Math.min(Math.max(...window.sequenceEditor.letterFocus)+1, window.sequenceEditor.letters.length-1), event.shiftKey) | |
| } | |
| } | |
| } | |
| // Up/Down arrows: Move pitch up/down for the letter(s) selected | |
| if ((key=="arrowup" || key=="arrowdown") && !event.ctrlKey) { | |
| event.preventDefault() | |
| if (window.sequenceEditor.letterFocus.length) { | |
| window.sequenceEditor.letterFocus.forEach(li => { | |
| window.sequenceEditor.pitchNew[li] += (key=="arrowup" ? 0.1 : -0.1) | |
| window.sequenceEditor.grabbers[li].setValueFromValue(window.sequenceEditor.pitchNew[li]) | |
| window.sequenceEditor.hasChanged = true | |
| }) | |
| if (window.sequenceEditor.autoInferTimer != null) { | |
| clearTimeout(window.sequenceEditor.autoInferTimer) | |
| window.sequenceEditor.autoInferTimer = null | |
| } | |
| if (autoplay_ckbx.checked) { | |
| window.sequenceEditor.autoInferTimer = setTimeout(infer, 500) | |
| } | |
| if (window.sequenceEditor.letterFocus.length==1) { | |
| letterPitchNumb.value = window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]] | |
| } | |
| } | |
| } | |
| // CTRL+Left/Right arrows: change the sequence-wide pacing | |
| if ((key=="arrowleft" || key=="arrowright") && event.ctrlKey) { | |
| if (event.altKey) { | |
| window.sequenceEditor.letterFocus.forEach(li => { | |
| window.sequenceEditor.dursNew[li] = window.sequenceEditor.dursNew[li] + (key=="arrowleft"? -0.1 : 0.1) | |
| window.sequenceEditor.hasChanged = true | |
| }) | |
| if (window.sequenceEditor.autoInferTimer != null) { | |
| clearTimeout(window.sequenceEditor.autoInferTimer) | |
| window.sequenceEditor.autoInferTimer = null | |
| } | |
| if (autoplay_ckbx.checked) { | |
| window.sequenceEditor.autoInferTimer = setTimeout(infer, 500) | |
| } | |
| window.sequenceEditor.sliderBoxes.forEach((box, i) => box.setValueFromValue(window.sequenceEditor.dursNew[i])) | |
| if (window.sequenceEditor.letterFocus.length==1) { | |
| letterLengthNumb.value = parseInt(window.sequenceEditor.dursNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
| } | |
| } else { | |
| pace_slid.value = parseFloat(pace_slid.value) + (key=="arrowleft"? -0.01 : 0.01) | |
| paceNumbInput.value = pace_slid.value | |
| const new_lengths = window.sequenceEditor.dursNew.map((v,l) => v * pace_slid.value) | |
| window.sequenceEditor.sliderBoxes.forEach((box, i) => box.setValueFromValue(window.sequenceEditor.dursNew[i])) | |
| window.sequenceEditor.pacing = parseFloat(pace_slid.value) | |
| window.sequenceEditor.init() | |
| } | |
| } | |
| // CTRL+Up/Down arrows: increase/decrease buttons | |
| if (key=="arrowup" && event.ctrlKey && !event.shiftKey) { | |
| increase_btn.click() | |
| } | |
| if (key=="arrowdown" && event.ctrlKey && !event.shiftKey) { | |
| decrease_btn.click() | |
| } | |
| // CTRL+SHIFT+Up/Down arrows: amplify/flatten buttons | |
| if (key=="arrowup" && event.ctrlKey && event.shiftKey) { | |
| amplify_btn.click() | |
| } | |
| if (key=="arrowdown" && event.ctrlKey && event.shiftKey) { | |
| flatten_btn.click() | |
| } | |
| }) | |
| window.setupModal = (openingButton, modalContainerElem, callback, exitCallback) => { | |
| if (openingButton) { | |
| openingButton.addEventListener("click", () => { | |
| closeModal(undefined, modalContainerElem).then(() => { | |
| modalContainerElem.style.opacity = 0 | |
| modalContainerElem.style.display = "flex" | |
| requestAnimationFrame(() => requestAnimationFrame(() => { | |
| modalContainerElem.style.opacity = 1 | |
| chromeBar.style.opacity = 1 | |
| requestAnimationFrame(() => { | |
| setTimeout(() => { | |
| if (callback) { | |
| callback() | |
| } | |
| }, 250) | |
| }) | |
| })) | |
| }) | |
| }) | |
| } | |
| modalContainerElem.addEventListener("click", event => { | |
| if (event.target==modalContainerElem) { | |
| if (exitCallback) { | |
| exitCallback() | |
| } | |
| window.closeModal(modalContainerElem) | |
| } | |
| }) | |
| } | |
| window.checkVersionRequirements = (requirements, appVersion, checkMax=false) => { | |
| if (!requirements) { | |
| return true | |
| } | |
| const appVersionRequirement = requirements.toString().split(".").map(v=>parseInt(v)) | |
| const appVersionInts = appVersion.replace("v", "").split(".").map(v=>parseInt(v)) | |
| let appVersionOk = true | |
| if (checkMax) { | |
| if (appVersionRequirement[0] >= appVersionInts[0] ) { | |
| if (appVersionRequirement.length>1 && parseInt(appVersionRequirement[0]) == appVersionInts[0]) { | |
| if (appVersionRequirement[1] >= appVersionInts[1] ) { | |
| if (appVersionRequirement.length>2 && parseInt(appVersionRequirement[1]) == appVersionInts[1]) { | |
| if (appVersionRequirement[2] >= appVersionInts[2] ) { | |
| } else { | |
| appVersionOk = false | |
| } | |
| } | |
| } else { | |
| appVersionOk = false | |
| } | |
| } | |
| } else { | |
| appVersionOk = false | |
| } | |
| } else { | |
| if (appVersionRequirement[0] <= appVersionInts[0] ) { | |
| if (appVersionRequirement.length>1 && parseInt(appVersionRequirement[0]) == appVersionInts[0]) { | |
| if (appVersionRequirement[1] <= appVersionInts[1] ) { | |
| if (appVersionRequirement.length>2 && parseInt(appVersionRequirement[1]) == appVersionInts[1]) { | |
| if (appVersionRequirement[2] <= appVersionInts[2] ) { | |
| } else { | |
| appVersionOk = false | |
| } | |
| } | |
| } else { | |
| appVersionOk = false | |
| } | |
| } | |
| } else { | |
| appVersionOk = false | |
| } | |
| } | |
| return appVersionOk | |
| } | |
| // https://stackoverflow.com/questions/18052762/remove-directory-which-is-not-empty | |
| const path = require('path') | |
| window.deleteFolderRecursive = function (directoryPath, keepRoot=false) { | |
| if (fs.existsSync(directoryPath)) { | |
| fs.readdirSync(directoryPath).forEach((file, index) => { | |
| const curPath = path.join(directoryPath, file); | |
| if (fs.lstatSync(curPath).isDirectory()) { | |
| // recurse | |
| window.deleteFolderRecursive(curPath); | |
| } else { | |
| // delete file | |
| fs.unlinkSync(curPath); | |
| } | |
| }); | |
| if (!keepRoot) { | |
| fs.rmdirSync(directoryPath); | |
| } | |
| } | |
| }; | |
| window.createFolderRecursive = (pathToMake) => { | |
| console.log("createFolderRecursive", pathToMake) | |
| pathToMake.split('/').reduce((directories, directory) => { | |
| directories += `${directory}/` | |
| if (!fs.existsSync(directories)) { | |
| fs.mkdirSync(directories) | |
| } | |
| return directories | |
| }, '') | |
| } | |
| window.uuidv4 = () => { | |
| return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { | |
| var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8) | |
| return v.toString(16) | |
| }) | |
| } | |
| // https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array | |
| window.shuffle = (array) => { | |
| var currentIndex = array.length, randomIndex; | |
| // While there remain elements to shuffle... | |
| while (0 !== currentIndex) { | |
| // Pick a remaining element... | |
| randomIndex = Math.floor(Math.random() * currentIndex); | |
| currentIndex--; | |
| // And swap it with the current element. | |
| [array[currentIndex], array[randomIndex]] = [ | |
| array[randomIndex], array[currentIndex]]; | |
| } | |
| return array; | |
| } | |
| // Just for easier packaging of the voice models for publishing - yes, lazy | |
| window.packageVoice_variantIndex = 0 | |
| window.packageVoice = (doVoicePreviewCreate, variants, {modelsPath, gameId}={}) => { | |
| const {voiceId, hifi} = variants[window.packageVoice_variantIndex] | |
| if (doVoicePreviewCreate) { | |
| const files = fs.readdirSync(`./output`).filter(fname => fname.includes("temp-") && fname.includes(".wav")) | |
| if (files.length) { | |
| const options = { | |
| hz: window.userSettings.audio.hz, | |
| padStart: window.userSettings.audio.padStart, | |
| padEnd: window.userSettings.audio.padEnd, | |
| bit_depth: window.userSettings.audio.bitdepth, | |
| amplitude: window.userSettings.audio.amplitude, | |
| pitchMult: window.userSettings.audio.pitchMult, | |
| tempo: window.userSettings.audio.tempo | |
| } | |
| doFetch(`http://localhost:8008/outputAudio`, { | |
| method: "Post", | |
| body: JSON.stringify({ | |
| input_path: `./output/${files[0]}`, | |
| isBatchMode: false, | |
| output_path: `${modelsPath}/${voiceId}_raw.wav`, | |
| options: JSON.stringify(options) | |
| }) | |
| }).then(r=>r.text()).then(() => { | |
| try { | |
| fs.unlinkSync(`${modelsPath}/${voiceId}.wav`) | |
| } catch (e) {} | |
| doFetch(`http://localhost:8008/normalizeAudio`, { | |
| method: "Post", | |
| body: JSON.stringify({ | |
| input_path: `${modelsPath}/${voiceId}_raw.wav`, | |
| output_path: `${modelsPath}/${voiceId}.wav` | |
| }) | |
| }).then(r=>r.text()).then((resp) => { | |
| console.log(resp) | |
| fs.unlinkSync(`${modelsPath}/${voiceId}_raw.wav`) | |
| }) | |
| }) | |
| } | |
| } else { | |
| fs.mkdirSync(`./build/${voiceId}`) | |
| fs.mkdirSync(`./build/${voiceId}/resources`) | |
| fs.mkdirSync(`./build/${voiceId}/resources/app`) | |
| fs.mkdirSync(`./build/${voiceId}/resources/app/models`) | |
| fs.mkdirSync(`./build/${voiceId}/resources/app/models/${gameId}`) | |
| fs.copyFileSync(`${modelsPath}/${voiceId}.json`, `./build/${voiceId}/resources/app/models/${gameId}/${voiceId}.json`) | |
| fs.copyFileSync(`${modelsPath}/${voiceId}.wav`, `./build/${voiceId}/resources/app/models/${gameId}/${voiceId}.wav`) | |
| fs.copyFileSync(`${modelsPath}/${voiceId}.pt`, `./build/${voiceId}/resources/app/models/${gameId}/${voiceId}.pt`) | |
| // if (hifi) { | |
| // fs.copyFileSync(`${modelsPath}/${voiceId}.hg.pt`, `./build/${voiceId}/resources/app/models/${gameId}/${voiceId}.hg.pt`) | |
| // } | |
| zipdir(`./build/${voiceId}`, {saveTo: `./build/${voiceId}.zip`}, (err, buffer) => deleteFolderRecursive(`./build/${voiceId}`)) | |
| } | |
| } | |
| const assetFiles = fs.readdirSync(`${window.path}/assets`) | |
| const jsonFiles = fs.readdirSync(`${window.path}/assets`).filter(fn => fn.endsWith(".json")) | |
| const missingAssetFiles = jsonFiles.filter(jsonFile => !(assetFiles.includes(jsonFile.replace(".json", ".png"))||assetFiles.includes(jsonFile.replace(".json", ".jpg"))) ) | |
| if (missingAssetFiles.length) { | |
| noAssetFilesFoundMessage.style.display = "block" | |
| assetDirLink.addEventListener("click", () => { | |
| // shell.showItemInFolder((require("path")).resolve(`${window.path}/assets/other.jpg`)) | |
| er.shell.showItemInFolder((require("path")).resolve(`${window.path}/assets/other.jpg`)) | |
| spawn(`explorer`, [(require("path")).resolve(`${window.path}/assets`)], {stdio: "ignore"}) | |
| }) | |
| } | |
| window.getSpeakerEmbeddingFromFilePath = (filePath) => { | |
| spinnerModal(`${window.i18n.GETTING_SPEAKER_EMBEDDING}`) | |
| return new Promise(resolve => { | |
| doFetch(`http://localhost:8008/getWavV3StyleEmb`, { | |
| method: "Post", | |
| body: JSON.stringify({wav_path: filePath}) | |
| }).then(r=>r.text()).then(v => { | |
| closeModal(undefined, [styleEmbeddingsContainer, workbenchContainer]) | |
| if (v=="ENOENT") { | |
| window.errorModal(`${window.i18n.SOMETHING_WENT_WRONG}<br><br>ENOENT`) | |
| } else { | |
| resolve(v) | |
| } | |
| }).catch(() => { | |
| window.errorModal(`${window.i18n.SOMETHING_WENT_WRONG}`) | |
| }) | |
| }) | |
| } | |
| window.unzipFileTo = (zipPath, outputFolder) => { | |
| return fs.createReadStream(zipPath).pipe(unzipper.Parse()).on("entry", entry => { | |
| const fileName = entry.path | |
| const dirOrFile = entry.type | |
| if (/\/$/.test(fileName)) { // It's a directory | |
| return | |
| } | |
| let fileContainerFolderPath = fileName.split("/").reverse() | |
| const justFileName = fileContainerFolderPath[0] | |
| entry.pipe(fs.createWriteStream(`${outputFolder}/${justFileName}`)) | |
| }) | |
| .promise() | |
| } |