Skip to content

Commit

Permalink
複数エンジン対応:Engine manifestによるUI無効化 (#919)
Browse files Browse the repository at this point in the history
* (PR用の空白コミット)

* Add: engineManifestのstoreを追加

* Fix: prettierの警告を修正

* Revert "Add: engineManifestのstoreを追加"

This reverts commit 73656a1.

* Add: 初期火事にマニフェストを読み込むように

* Add: AudioInfoの有効化・無効化を実装

* Add: 無効化時に半透明になるように

* Change: styleの記法を変更

* Fix: Prettierの警告を修正

* Delete: デバッグ用の残りを削除

* Add: イントネーション/長さの無効化を実装

* Update: Vuexのstoreを更新

* Revert: 不必要な変更を取り消し

* Add: コメントを追加

* Change: テキストの無効化表示にdisabledクラスを使うように

* Add: TODOコメントを追加

* Delete: engineManifestを削除

* Change: FETCH_AND_SET_ENGINE_MANIFESTSに変更

* Delete: engineManifestを作らずsupportedFeaturesを設定するように

* Change: supportedFeaturesをSupportedFeatures | undefinedに

* Update src/components/AudioDetail.vue

* Update src/components/AudioDetail.vue

Co-authored-by: Hiroshiba <hihokaruta@gmail.com>
  • Loading branch information
sevenc-nanashi and Hiroshiba authored Sep 13, 2022
1 parent 15fee8e commit b14c460
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 14 deletions.
45 changes: 42 additions & 3 deletions src/components/AudioDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,20 @@
<div class="detail-selector">
<q-tabs dense vertical class="text-display" v-model="selectedDetail">
<q-tab name="accent" label="アクセント" />
<q-tab name="pitch" label="イントネーション" />
<q-tab name="length" label="長さ" />
<q-tab
name="pitch"
label="イントネーション"
:disable="
!(supportedFeatures && supportedFeatures.adjustMoraPitch)
"
/>
<q-tab
name="length"
label="長さ"
:disable="
!(supportedFeatures && supportedFeatures.adjustPhonemeLength)
"
/>
</q-tabs>
</div>
<div class="play-button-wrapper">
Expand Down Expand Up @@ -260,7 +272,7 @@ import AudioAccent from "./AudioAccent.vue";
import AudioParameter from "./AudioParameter.vue";
import { HotkeyAction, HotkeyReturnType, MoraDataType } from "@/type/preload";
import { setHotkeyFunctions } from "@/store/setting";
import { Mora } from "@/openapi/models";
import { EngineManifest, Mora } from "@/openapi/models";
export default defineComponent({
components: { AudioAccent, AudioParameter, Tip },
Expand Down Expand Up @@ -349,6 +361,32 @@ export default defineComponent({
const query = computed(() => audioItem.value?.query);
const accentPhrases = computed(() => query.value?.accentPhrases);
const supportedFeatures = computed(
() =>
(audioItem.value?.engineId &&
store.state.engineManifests[audioItem.value?.engineId]
.supportedFeatures) as
| EngineManifest["supportedFeatures"]
| undefined
);
// エンジンが変わったとき、selectedDetailが対応していないものを選択している場合はaccentに戻す
// TODO: 連続再生するとアクセントに移動してしまうため、タブの中身を全てdisabledにする、半透明divをかぶせるなど
// タブ自体の無効化&移動以外の方法で無効化する
watch(
supportedFeatures,
(newFeatures) => {
if (
(!newFeatures?.adjustMoraPitch && selectedDetail.value === "pitch") ||
(!newFeatures?.adjustPhonemeLength &&
selectedDetail.value === "length")
) {
selectedDetail.value = "accent";
}
},
{ immediate: true }
);
const activePointScrollMode = computed(
() => store.state.activePointScrollMode
);
Expand Down Expand Up @@ -767,6 +805,7 @@ export default defineComponent({
activePoint,
setPlayAndStartPoint,
uiLocked,
supportedFeatures,
audioItem,
query,
accentPhrases,
Expand Down
59 changes: 49 additions & 10 deletions src/components/AudioInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,11 @@
</div>

<div class="q-mx-md">
<span class="text-body1 q-mb-xs"
<span
class="text-body1 q-mb-xs"
:class="{
disabled: speedScaleSlider.qSliderProps.disable.value,
}"
>話速 {{ speedScaleSlider.state.currentValue.value?.toFixed(2) }}</span
>
<q-slider
Expand All @@ -187,7 +191,11 @@
/>
</div>
<div class="q-px-md">
<span class="text-body1 q-mb-xs"
<span
class="text-body1 q-mb-xs"
:class="{
disabled: pitchScaleSlider.qSliderProps.disable.value,
}"
>音高 {{ pitchScaleSlider.state.currentValue.value?.toFixed(2) }}</span
>
<q-slider
Expand All @@ -209,7 +217,11 @@
/>
</div>
<div class="q-px-md">
<span class="text-body1 q-mb-xs"
<span
class="text-body1 q-mb-xs"
:class="{
disabled: intonationScaleSlider.qSliderProps.disable.value,
}"
>抑揚
{{ intonationScaleSlider.state.currentValue.value?.toFixed(2) }}</span
>
Expand All @@ -232,7 +244,11 @@
/>
</div>
<div class="q-px-md">
<span class="text-body1 q-mb-xs"
<span
class="text-body1 q-mb-xs"
:class="{
disabled: volumeScaleSlider.qSliderProps.disable.value,
}"
>音量 {{ volumeScaleSlider.state.currentValue.value?.toFixed(2) }}</span
>
<q-slider
Expand All @@ -254,7 +270,11 @@
/>
</div>
<div class="q-px-md">
<span class="text-body1 q-mb-xs"
<span
class="text-body1 q-mb-xs"
:class="{
disabled: prePhonemeLengthSlider.qSliderProps.disable.value,
}"
>開始無音
{{ prePhonemeLengthSlider.state.currentValue.value?.toFixed(2) }}</span
>
Expand All @@ -277,7 +297,11 @@
/>
</div>
<div class="q-px-md">
<span class="text-body1 q-mb-xs"
<span
class="text-body1 q-mb-xs"
:class="{
disabled: postPhonemeLengthSlider.qSliderProps.disable.value,
}"
>終了無音
{{ postPhonemeLengthSlider.state.currentValue.value?.toFixed(2) }}</span
>
Expand Down Expand Up @@ -310,6 +334,7 @@ import { useStore } from "@/store";
import { Preset } from "@/type/preload";
import { previewSliderHelper } from "@/helpers/previewSliderHelper";
import PresetManageDialog from "./PresetManageDialog.vue";
import { EngineManifest } from "@/openapi";
export default defineComponent({
name: "AudioInfo",
Expand All @@ -333,6 +358,15 @@ export default defineComponent({
);
const query = computed(() => audioItem.value?.query);
const supportedFeatures = computed(
() =>
(audioItem.value?.engineId &&
store.state.engineManifests[audioItem.value?.engineId]
.supportedFeatures) as
| EngineManifest["supportedFeatures"]
| undefined
);
const applyPreset = () => {
store.dispatch("COMMAND_APPLY_AUDIO_PRESET", {
audioKey: props.activeAudioKey,
Expand Down Expand Up @@ -383,7 +417,8 @@ export default defineComponent({
const speedScaleSlider = previewSliderHelper({
modelValue: () => query.value?.speedScale ?? null,
disable: () => uiLocked.value,
disable: () =>
uiLocked.value || supportedFeatures.value?.adjustSpeedScale === false,
onChange: setAudioSpeedScale,
max: () => 2,
min: () => 0.5,
Expand All @@ -393,7 +428,8 @@ export default defineComponent({
});
const pitchScaleSlider = previewSliderHelper({
modelValue: () => query.value?.pitchScale ?? null,
disable: () => uiLocked.value,
disable: () =>
uiLocked.value || supportedFeatures.value?.adjustPitchScale === false,
onChange: setAudioPitchScale,
max: () => 0.15,
min: () => -0.15,
Expand All @@ -402,7 +438,9 @@ export default defineComponent({
});
const intonationScaleSlider = previewSliderHelper({
modelValue: () => query.value?.intonationScale ?? null,
disable: () => uiLocked.value,
disable: () =>
uiLocked.value ||
supportedFeatures.value?.adjustIntonationScale === false,
onChange: setAudioIntonationScale,
max: () => 2,
min: () => 0,
Expand All @@ -412,7 +450,8 @@ export default defineComponent({
});
const volumeScaleSlider = previewSliderHelper({
modelValue: () => query.value?.volumeScale ?? null,
disable: () => uiLocked.value,
disable: () =>
uiLocked.value || supportedFeatures.value?.adjustVolumeScale === false,
onChange: setAudioVolumeScale,
max: () => 2,
min: () => 0,
Expand Down
1 change: 1 addition & 0 deletions src/store/setting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const settingStoreState: SettingStoreState = {
toolbarSetting: [],
engineIds: [],
engineInfos: {},
engineManifests: {},
themeSetting: {
currentTheme: "Default",
availableThemes: [],
Expand Down
14 changes: 13 additions & 1 deletion src/store/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import {
StoreOptions,
} from "./vuex";
import { Patch } from "immer";
import { AccentPhrase, AudioQuery, UserDictWord } from "@/openapi";
import {
AccentPhrase,
AudioQuery,
EngineManifest,
UserDictWord,
} from "@/openapi";
import { createCommandMutationTree, PayloadRecipeTree } from "./command";
import {
CharacterInfo,
Expand Down Expand Up @@ -843,6 +848,7 @@ export type SettingStoreState = {
toolbarSetting: ToolbarSetting;
engineIds: string[];
engineInfos: Record<string, EngineInfo>;
engineManifests: Record<string, EngineManifest>;
themeSetting: ThemeSetting;
acceptRetrieveTelemetry: AcceptRetrieveTelemetryStatus;
experimentalSetting: ExperimentalSetting;
Expand Down Expand Up @@ -1042,6 +1048,12 @@ type UiStoreTypes = {

SET_ENGINE_INFOS: { mutation: { engineInfos: EngineInfo[] } };

SET_ENGINE_MANIFESTS: {
mutation: { engineManifests: Record<string, EngineManifest> };
};

FETCH_AND_SET_ENGINE_MANIFESTS: { action(): void };

SET_INHERIT_AUDIOINFO: {
mutation: { inheritAudioInfo: boolean };
action(payload: { inheritAudioInfo: boolean }): void;
Expand Down
26 changes: 26 additions & 0 deletions src/store/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
VoiceVoxStoreOptions,
} from "./type";
import { ActivePointScrollMode, EngineInfo } from "@/type/preload";
import { EngineManifest } from "@/openapi";

export function createUILockAction<S, A extends ActionsBase, K extends keyof A>(
action: (
Expand Down Expand Up @@ -147,6 +148,12 @@ export const uiStore: VoiceVoxStoreOptions<UiGetters, UiActions, UiMutations> =
engineInfos.map((engineInfo) => [engineInfo.uuid, "STARTING"])
);
},
SET_ENGINE_MANIFESTS(
state,
{ engineManifests }: { engineManifests: Record<string, EngineManifest> }
) {
state.engineManifests = engineManifests;
},
SET_INHERIT_AUDIOINFO(
state,
{ inheritAudioInfo }: { inheritAudioInfo: boolean }
Expand Down Expand Up @@ -387,6 +394,25 @@ export const uiStore: VoiceVoxStoreOptions<UiGetters, UiActions, UiMutations> =
engineInfos: await window.electron.engineInfos(),
});
},
async FETCH_AND_SET_ENGINE_MANIFESTS({ state, commit }) {
commit("SET_ENGINE_MANIFESTS", {
engineManifests: Object.fromEntries(
await Promise.all(
state.engineIds.map(
async (engineId) =>
await this.dispatch("INSTANTIATE_ENGINE_CONNECTOR", {
engineId,
}).then(async (instance) => [
engineId,
await instance.invoke("engineManifestEngineManifestGet")(
{}
),
])
)
)
),
});
},
async SET_INHERIT_AUDIOINFO(
{ commit },
{ inheritAudioInfo }: { inheritAudioInfo: boolean }
Expand Down
1 change: 1 addition & 0 deletions src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ export default defineComponent({
const isCompletedInitialStartup = ref(false);
onMounted(async () => {
await store.dispatch("GET_ENGINE_INFOS");
await store.dispatch("FETCH_AND_SET_ENGINE_MANIFESTS");
await store.dispatch("START_WAITING_ENGINE_ALL");
await store.dispatch("LOAD_CHARACTER_ALL");
Expand Down
22 changes: 22 additions & 0 deletions tests/unit/store/Vuex.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,28 @@ describe("store/vuex.js test", () => {
host: "http://127.0.0.1",
},
},
engineManifests: {
"88022f86-c823-436e-85a3-500c629749c4": {
manifestVersion: "0.13.0",
name: "DUMMY VOICEVOX ENGINE",
uuid: "c7b58856-bd56-4aa1-afb7-b8415f824b06",
url: "https://github.com/VOICEVOX/voicevox_engine",
icon: "engine_manifest_assets/icon.png",
defaultSamplingRate: 24000,
termsOfService: "engine_manifest_assets/terms_of_service.md",
updateInfos: [],
dependencyLicenses: [],
supportedFeatures: {
adjustMoraPitch: true,
adjustPhonemeLength: true,
adjustSpeedScale: true,
adjustPitchScale: true,
adjustIntonationScale: true,
adjustVolumeScale: true,
interrogativeUpspeak: true,
},
},
},
experimentalSetting: {
enablePreset: false,
enableInterrogativeUpspeak: false,
Expand Down

0 comments on commit b14c460

Please sign in to comment.