"use strict" const spawn = require("child_process").spawn window.outputFilesState = { paginationIndex: 0, records: [], totalPages: 0 } window.initMainPagePagination = (directory) => { window.outputFilesState.records = [] window.outputFilesState.totalPages = 0 window.resetPagination() if (!fs.existsSync(directory)) { return } const records = [] const files = fs.readdirSync(directory) files.forEach(file => { if (!["wav", "mp3", "ogg", "opus", "wma", "xwm"].includes(file.split(".").reverse()[0].toLowerCase())) { return } let jsonData if (fs.existsSync(`${directory}/${file}.json`)) { try { const lineMeta = fs.readFileSync(`${directory}/${file}.json`, "utf8") jsonData = JSON.parse(lineMeta) } catch (e) { // console.log(e) } } const record = {} record.fileName = file record.lastChanged = fs.statSync(`${directory}/${file}`).mtime record.jsonPath = `${directory}/${file}` records.push([record, jsonData]) }) window.outputFilesState.records = records window.reOrderMainPageRecords() } window.resetPagination = () => { window.outputFilesState.paginationIndex = 0 const numPages = Math.ceil(window.outputFilesState.records.length/window.userSettings.output_files_pagination_size) main_total_pages.innerHTML = window.i18n.PAGINATION_TOTAL_OF.replace("_1", numPages) window.outputFilesState.totalPages = numPages main_pageNum.value = 1 } window.reOrderMainPageRecords = () => { const reverse = window.userSettings.voiceRecordsOrderByOrder=="ascending" const sortBy = window.userSettings.voiceRecordsOrderBy window.outputFilesState.records = window.outputFilesState.records.sort((a,b) => { if (sortBy=="name") { return a[0].fileName.toLowerCase() { const fileName = src.split("/").reverse()[0].split("%20").join(" ") const fileFormat = fileName.split(".").reverse()[0] const fileNameElem = createElem("div", fileName) const promptText = createElem("div.samplePromptText") if (fs.existsSync(src+".json")) { try { const lineMeta = fs.readFileSync(src+".json", "utf8") promptText.innerHTML = JSON.parse(lineMeta).inputSequence if (promptText.innerHTML.length > 130) { promptText.innerHTML = promptText.innerHTML.slice(0, 130)+"..." } } catch (e) { // console.log(e) } } const sample = createElem("div.sample", createElem("div", fileNameElem, promptText)) const audioControls = createElem("div.sampleAudioControls") const audio = createElem("audio", {controls: true}, createElem("source", { src: src, type: `audio/${fileFormat}` })) audio.addEventListener("play", () => { if (window.ctrlKeyIsPressed) { audio.setSinkId(window.userSettings.alt_speaker) } else { audio.setSinkId(window.userSettings.base_speaker) } }) audio.setSinkId(window.userSettings.base_speaker) const audioSVG = window.getAudioPlayTriangleSVG() audioSVG.addEventListener("click", () => { audio.play() }) const openFileLocationButton = createElem("div", {title: window.i18n.OPEN_CONTAINING_FOLDER}) openFileLocationButton.innerHTML = `` openFileLocationButton.addEventListener("click", () => { const containingFolder = src.split("/").slice(0, -1).join("/").replaceAll("/", "\\") // shell.showItemInFolder(src) // er.shell.showItemInFolder(src) // Electron suddenly isn't working anymore, to open folders, since updating from v2 to v19 // Couldn't figure it out, so I'm just gonna do it myself, manually. It doesn't show the file, but at least it opens the folder er.shell.showItemInFolder(src) spawn(`explorer`, [containingFolder], {stdio: "ignore"}) }) if (fs.existsSync(`${src}.json`)) { const editButton = createElem("div", {title: window.i18n.ADJUST_SAMPLE_IN_EDITOR}) editButton.innerHTML = `` editButton.addEventListener("click", () => { const doTheRest = () => { let editData = fs.readFileSync(`${src}.json`, "utf8") editData = JSON.parse(editData) generateVoiceButton.dataset.modelIDLoaded = editData.pitchEditor ? editData.pitchEditor.currentVoice : editData.currentVoice window.sequenceEditor.historyState.push(editData.inputSequence.trim()) window.sequenceEditor.isEditingFromFile = true window.sequenceEditor.inputSequence = editData.inputSequence window.sequenceEditor.pacing = editData.pacing window.sequenceEditor.letters = editData.pitchEditor ? editData.pitchEditor.letters : editData.letters window.sequenceEditor.currentVoice = editData.pitchEditor ? editData.pitchEditor.currentVoice : editData.currentVoice window.sequenceEditor.resetEnergy = (editData.pitchEditor && editData.pitchEditor.resetEnergy) ? editData.pitchEditor.resetEnergy : editData.resetEnergy window.sequenceEditor.resetPitch = editData.pitchEditor ? editData.pitchEditor.resetPitch : editData.resetPitch window.sequenceEditor.resetDurs = editData.pitchEditor ? editData.pitchEditor.resetDurs : editData.resetDurs window.sequenceEditor.resetEmAngry = editData.resetEmAngry window.sequenceEditor.resetEmHappy = editData.resetEmHappy window.sequenceEditor.resetEmSad = editData.resetEmSad window.sequenceEditor.resetEmSurprise = editData.resetEmSurprise window.sequenceEditor.letterFocus = [] window.sequenceEditor.ampFlatCounter = 0 window.sequenceEditor.hasChanged = false window.sequenceEditor.sequence = editData.pitchEditor ? editData.pitchEditor.sequence : editData.sequence window.sequenceEditor.energyNew = (editData.pitchEditor && editData.pitchEditor.energyNew) ? editData.pitchEditor.energyNew : editData.energyNew window.sequenceEditor.pitchNew = editData.pitchEditor ? editData.pitchEditor.pitchNew : editData.pitchNew window.sequenceEditor.dursNew = editData.pitchEditor ? editData.pitchEditor.dursNew : editData.dursNew window.sequenceEditor.emAngryNew = editData.emAngryNew window.sequenceEditor.emHappyNew = editData.emHappyNew window.sequenceEditor.emSadNew = editData.emSadNew window.sequenceEditor.emSurpriseNew = editData.emSurpriseNew if (editData.styleValuesReset) { window.sequenceEditor.loadStylesData() window.sequenceEditor.registeredStyleKeys.forEach(styleKey => { window.sequenceEditor.styleValuesReset[styleKey] = editData.styleValuesReset[styleKey] window.sequenceEditor.styleValuesNew[styleKey] = editData.styleValuesNew[styleKey] }) } window.sequenceEditor.init() window.sequenceEditor.update(window.currentModel.modelType) window.sequenceEditor.autoInferTimer = null dialogueInput.value = editData.inputSequence window.refreshText() paceNumbInput.value = editData.pacing pace_slid.value = editData.pacing window.sequenceEditor.sliderBoxes.forEach((box, i) => {box.setValueFromValue(window.sequenceEditor.dursNew[i])}) window.sequenceEditor.update(window.currentModel.modelType) if (!window.wavesurfer) { window.initWaveSurfer(src) } else { window.wavesurfer.load(src) } samplePlayPause.style.display = "block" } if (window.currentModel.loaded) { doTheRest() } else { window.loadModel().then(() => { doTheRest() }) } }) audioControls.appendChild(editButton) } const renameButton = createElem("div", {title: window.i18n.RENAME_THE_FILE}) renameButton.innerHTML = ` ` renameButton.addEventListener("click", () => { createModal("prompt", { prompt: window.i18n.ENTER_NEW_FILENAME_UNCHANGED_CANCEL, value: sample.querySelector("div").innerHTML }).then(newFileName => { if (newFileName!=fileName) { const oldPath = src.split("/").reverse() const newPath = src.split("/").reverse() oldPath[0] = sample.querySelector("div").innerHTML newPath[0] = newFileName const oldPathComposed = oldPath.reverse().join("/") const newPathComposed = newPath.reverse().join("/") fs.renameSync(oldPathComposed, newPathComposed) if (fs.existsSync(`${oldPathComposed}.json`)) { fs.renameSync(oldPathComposed+".json", newPathComposed+".json") } if (fs.existsSync(`${oldPathComposed.replace(/\.wav$/, "")}.lip`)) { fs.renameSync(oldPathComposed.replace(/\.wav$/, "")+".lip", newPathComposed.replace(/\.wav$/, "")+".lip") } if (fs.existsSync(`${oldPathComposed.replace(/\.wav$/, "")}.fuz`)) { fs.renameSync(oldPathComposed.replace(/\.wav$/, "")+".fuz", newPathComposed.replace(/\.wav$/, "")+".fuz") } oldPath.reverse() oldPath.splice(0,1) refreshRecordsList(oldPath.reverse().join("/")) } }) }) const editInProgramButton = createElem("div", {title: window.i18n.EDIT_IN_EXTERNAL_PROGRAM}) editInProgramButton.innerHTML = ` ` editInProgramButton.addEventListener("click", () => { if (window.userSettings.externalAudioEditor && window.userSettings.externalAudioEditor.length) { const fileName = audio.children[0].src.split("file:///")[1].split("%20").join(" ") const sp = spawn(window.userSettings.externalAudioEditor, [fileName], {'detached': true}, (err, data) => { if (err) { console.log(err) console.log(err.message) window.errorModal(err.message) } }) sp.on("error", err => { if (err.message.includes("ENOENT")) { window.errorModal(`${window.i18n.FOLLOWING_PATH_NOT_VALID}:

${window.userSettings.externalAudioEditor}`) } else { window.errorModal(err.message) } }) } else { window.errorModal(window.i18n.SPECIFY_EDIT_TOOL) } }) const deleteFileButton = createElem("div", {title: window.i18n.DELETE_FILE}) deleteFileButton.innerHTML = "❌" deleteFileButton.addEventListener("click", () => { confirmModal(`${window.i18n.SURE_DELETE}

${fileName}`).then(confirmation => { if (confirmation) { window.appLogger.log(`${newSample?window.i18n.DELETING_NEW_FILE:window.i18n.DELETING}: ${src}`) if (fs.existsSync(src)) { fs.unlinkSync(src) } sample.remove() if (fs.existsSync(`${src}.json`)) { fs.unlinkSync(`${src}.json`) } } }) }) audioControls.appendChild(renameButton) audioControls.appendChild(audioSVG) audioControls.appendChild(editInProgramButton) audioControls.appendChild(openFileLocationButton) audioControls.appendChild(deleteFileButton) sample.appendChild(audioControls) return sample } window.refreshRecordsList = () => { voiceSamples.innerHTML = "" const outputFilesPaginationSize = window.userSettings.output_files_pagination_size const filteredRecords = window.outputFilesState.records.filter(recordAndJson => { if (!recordAndJson[0].fileName.toLowerCase().includes(voiceSamplesSearch.value.toLowerCase().trim())) { return } if (voiceSamplesSearchPrompt.value.length) { if (!recordAndJson[1] || !recordAndJson[1].inputSequence.toLowerCase().includes(voiceSamplesSearchPrompt.value.toLowerCase().trim())) { return } } return recordAndJson }) const startIndex = (window.outputFilesState.paginationIndex*outputFilesPaginationSize) const endIndex = Math.min(startIndex+outputFilesPaginationSize, filteredRecords.length) for (let ri=startIndex; ri { main_pageNum.value = Math.max(1, parseInt(main_pageNum.value)-1) window.outputFilesState.paginationIndex = main_pageNum.value-1 window.refreshRecordsList() }) main_paginationNext.addEventListener("click", () => { main_pageNum.value = Math.min(parseInt(main_pageNum.value)+1, window.outputFilesState.totalPages) window.outputFilesState.paginationIndex = main_pageNum.value-1 window.refreshRecordsList() }) // Delete all output files for a voice voiceRecordsDeleteAllButton.addEventListener("click", () => { if (window.currentModel) { const outDir = window.userSettings[`outpath_${window.currentGame.gameId}`]+`/${currentModel.voiceId}` const files = fs.readdirSync(outDir) if (files.length) { window.confirmModal(window.i18n.DELETE_ALL_FILES_CONFIRM.replace("_1", files.length).replace("_2", outDir)).then(resp => { if (resp) { window.deleteFolderRecursive(outDir, true) window.initMainPagePagination(outDir) window.refreshRecordsList() } }) } else { window.errorModal(window.i18n.DELETE_ALL_FILES_ERR_NO_FILES.replace("_1", outDir)) } } }) voiceRecordsOrderByButton.addEventListener("click", () => { window.userSettings.voiceRecordsOrderBy = window.userSettings.voiceRecordsOrderBy=="name" ? "time" : "name" saveUserSettings() const labels = { "name": window.i18n.NAME, "time": window.i18n.TIME } voiceRecordsOrderByButton.innerHTML = labels[window.userSettings.voiceRecordsOrderBy] if (window.currentModel) { const voiceRecordsList = window.userSettings[`outpath_${window.currentGame.gameId}`]+`/${window.currentModel.voiceId}` window.reOrderMainPageRecords() window.refreshRecordsList() } }) voiceRecordsOrderByOrderButton.addEventListener("click", () => { window.userSettings.voiceRecordsOrderByOrder = window.userSettings.voiceRecordsOrderByOrder=="ascending" ? "descending" : "ascending" saveUserSettings() const labels = { "ascending": window.i18n.ASCENDING, "descending": window.i18n.DESCENDING } voiceRecordsOrderByOrderButton.innerHTML = labels[window.userSettings.voiceRecordsOrderByOrder] if (window.currentModel) { const voiceRecordsList = window.userSettings[`outpath_${window.currentGame.gameId}`]+`/${window.currentModel.voiceId}` window.reOrderMainPageRecords() window.refreshRecordsList() } }) voiceSamplesSearch.addEventListener("keyup", () => { if (window.currentModel) { window.outputFilesState.paginationIndex = 0 main_pageNum.value = 1 const voiceRecordsList = window.userSettings[`outpath_${window.currentGame.gameId}`]+`/${window.currentModel.voiceId}` window.refreshRecordsList() } }) voiceSamplesSearchPrompt.addEventListener("keyup", () => { if (window.currentModel) { window.outputFilesState.paginationIndex = 0 main_pageNum.value = 1 const voiceRecordsList = window.userSettings[`outpath_${window.currentGame.gameId}`]+`/${window.currentModel.voiceId}` window.refreshRecordsList() } }) if (Object.keys(window.userSettings).includes("voiceRecordsOrderBy")) { const labels = { "name": window.i18n.NAME, "time": window.i18n.TIME } voiceRecordsOrderByButton.innerHTML = labels[window.userSettings.voiceRecordsOrderBy] } else { window.userSettings.voiceRecordsOrderBy = "name" saveUserSettings() } if (Object.keys(window.userSettings).includes("voiceRecordsOrderByOrder")) { const labels = { "ascending": window.i18n.ASCENDING, "descending": window.i18n.DESCENDING } voiceRecordsOrderByOrderButton.innerHTML = labels[window.userSettings.voiceRecordsOrderByOrder] } else { window.userSettings.voiceRecordsOrderByOrder = "ascending" saveUserSettings() }