From 26697284e8baee110b9b4ca21e0f6e0ed74cc738 Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 25 Nov 2024 15:34:57 +0100 Subject: [PATCH 1/8] Feat: synchronize with DSP types from models --- src/plugins/api/interfaces.ts | 47 +++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/plugins/api/interfaces.ts b/src/plugins/api/interfaces.ts index e4759269..9a556ed5 100644 --- a/src/plugins/api/interfaces.ts +++ b/src/plugins/api/interfaces.ts @@ -5,6 +5,53 @@ export const SECURE_STRING_SUBSTITUTE = "this_value_is_encrypted"; export const MASS_LOGO_ONLINE = "https://github.com/home-assistant/brands/raw/master/custom_integrations/mass/icon%402x.png"; +/// dsp + +export enum DSPFilterType { + PARAMETRIC_EQ = "parametric_eq", +} + +export enum ParametricEQBandType { + PEAK = "peak", + HIGH_SHELF = "high_shelf", + LOW_SHELF = "low_shelf", + HIGH_PASS = "high_pass", + LOW_PASS = "low_pass", + NOTCH = "notch", +} + +// Base interface for all DSP filters +export interface DSPFilterBase { + type: DSPFilterType; + enabled: boolean; +} + +export interface ParametricEQBand { + frequency: number; + q: number; + gain: number; + type: ParametricEQBandType; + enabled: boolean; +} + +// Specific filter types +export interface ParametricEQFilter extends DSPFilterBase { + type: DSPFilterType.PARAMETRIC_EQ; + bands: Array; +} + +// Union type for all possible filters +export type DSPFilter = ParametricEQFilter; + +// Main DSP chain configuration +export interface DSPConfig { + enabled: boolean; + filters: DSPFilter[]; + input_gain: number; + output_gain: number; + output_limiter: boolean; +} + /// enums export enum MediaType { From 3928587b199852586e5cdb704192e12097055dc1 Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 25 Nov 2024 15:37:46 +0100 Subject: [PATCH 2/8] Feat: add DSP link to Players --- src/translations/en.json | 1 + src/views/settings/Players.vue | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/translations/en.json b/src/translations/en.json index 05aca5ff..7726cec3 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -537,6 +537,7 @@ "power_off_player": "Power off", "sync_player_with": "Synchronize with another player", "open_player_settings": "Open settings", + "open_dsp_settings": "Open DSP settings", "powered_off_players": "Unpowered players", "dont_stop_the_music_enable": "Enable 'Don't stop the music!'", "dont_stop_the_music_disable": "Disable 'Don't stop the music!'" diff --git a/src/views/settings/Players.vue b/src/views/settings/Players.vue index ebee3591..6eaa3209 100644 --- a/src/views/settings/Players.vue +++ b/src/views/settings/Players.vue @@ -127,6 +127,10 @@ const editPlayer = function (playerId: string, provider: string) { } }; +const editPlayerDsp = function (playerId: string) { + router.push(`/settings/editplayer/${playerId}/dsp`); +}; + const addPlayerGroup = function (provider: string) { router.push("/settings/addgroup"); }; @@ -160,6 +164,14 @@ const onMenu = function (evt: Event, playerConfig: PlayerConfig) { icon: "mdi-cog", disabled: !api.getProvider(playerConfig!.provider), }, + { + label: "open_dsp_settings", + labelArgs: [], + action: () => { + editPlayerDsp(playerConfig.player_id); + }, + icon: "mdi-equalizer", + }, { label: playerConfig.enabled ? "settings.disable" : "settings.enable", labelArgs: [], From fdc6a55eb55b5dbd35acef13e256b69d6005b2af Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 25 Nov 2024 15:38:41 +0100 Subject: [PATCH 3/8] Feat: add DSP link from player settings --- src/helpers/player_menu_items.ts | 12 ++++++++++++ src/views/settings/EditPlayer.vue | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/src/helpers/player_menu_items.ts b/src/helpers/player_menu_items.ts index da0bd2b5..5bbd6cd7 100644 --- a/src/helpers/player_menu_items.ts +++ b/src/helpers/player_menu_items.ts @@ -178,5 +178,17 @@ export const getPlayerMenuItems = ( icon: "mdi-cog-outline", }); + // add shortcut to dsp settings + menuItems.push({ + label: "open_dsp_settings", + labelArgs: [], + action: () => { + store.showFullscreenPlayer = false; + store.showPlayersMenu = false; + router.push(`/settings/editplayer/${player.player_id}/dsp`); + }, + icon: "mdi-equalizer", + }); + return menuItems; }; diff --git a/src/views/settings/EditPlayer.vue b/src/views/settings/EditPlayer.vue index 723453e0..c13f6288 100644 --- a/src/views/settings/EditPlayer.vue +++ b/src/views/settings/EditPlayer.vue @@ -72,6 +72,11 @@ color="primary" :disabled="api.getProviderManifest(config.provider)?.builtin" /> + + + + {{ $t("open_dsp_settings") }} +
@@ -121,6 +126,10 @@ const onSubmit = async function (values: Record) { api.savePlayerConfig(props.playerId!, values); router.push({ name: "playersettings" }); }; + +const openDspConfig = function () { + router.push(`/settings/editplayer/${props.playerId}/dsp`); +}; From 246ed5a5130c9dca09fc5ed5fc2531cfbebdcf5b Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 25 Nov 2024 15:47:38 +0100 Subject: [PATCH 4/8] Feat: Add helper functions to get and save DSP Configuration --- src/plugins/api/index.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/plugins/api/index.ts b/src/plugins/api/index.ts index 7ad624f7..3c13d702 100644 --- a/src/plugins/api/index.ts +++ b/src/plugins/api/index.ts @@ -43,6 +43,7 @@ import { CoreConfig, ItemMapping, AlbumType, + DSPConfig, } from "./interfaces"; const DEBUG = process.env.NODE_ENV === "development"; @@ -1049,6 +1050,24 @@ export class MusicAssistantApi { }); } + // DSP related functions + + public async getDSPConfig(player_id: string): Promise { + // Return the DSP configuration for a player. + return this.sendCommand("config/players/dsp/get", { player_id }); + } + + public async saveDSPConfig( + player_id: string, + config: DSPConfig, + ): Promise { + // Save/update the DSP configuration for a player. + return this.sendCommand("config/players/dsp/save", { + player_id, + config, + }); + } + // Core Config related functions public async getCoreConfigs(): Promise { From ca0cd8a19ee75dc79af1c85f74b0ee066df85629 Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 25 Nov 2024 15:48:21 +0100 Subject: [PATCH 5/8] Feat: Add DSP Editor This commit adds a graphical editor for configuring the DSP Pipeline of a Player with support for a Parametric Equalizer. --- src/components/dsp/DSPParametricEQ.vue | 452 +++++++++++++++++++++++++ src/components/dsp/DSPPipeline.vue | 203 +++++++++++ src/components/dsp/DSPSlider.vue | 94 +++++ src/plugins/router.ts | 9 + src/translations/en.json | 40 ++- src/views/settings/EditPlayerDsp.vue | 280 +++++++++++++++ 6 files changed, 1077 insertions(+), 1 deletion(-) create mode 100644 src/components/dsp/DSPParametricEQ.vue create mode 100644 src/components/dsp/DSPPipeline.vue create mode 100644 src/components/dsp/DSPSlider.vue create mode 100644 src/views/settings/EditPlayerDsp.vue diff --git a/src/components/dsp/DSPParametricEQ.vue b/src/components/dsp/DSPParametricEQ.vue new file mode 100644 index 00000000..efb2fc13 --- /dev/null +++ b/src/components/dsp/DSPParametricEQ.vue @@ -0,0 +1,452 @@ + + + + diff --git a/src/components/dsp/DSPPipeline.vue b/src/components/dsp/DSPPipeline.vue new file mode 100644 index 00000000..af3b4646 --- /dev/null +++ b/src/components/dsp/DSPPipeline.vue @@ -0,0 +1,203 @@ + + + + + diff --git a/src/components/dsp/DSPSlider.vue b/src/components/dsp/DSPSlider.vue new file mode 100644 index 00000000..5faf026e --- /dev/null +++ b/src/components/dsp/DSPSlider.vue @@ -0,0 +1,94 @@ + + + diff --git a/src/plugins/router.ts b/src/plugins/router.ts index 6f846b18..124c7bc4 100644 --- a/src/plugins/router.ts +++ b/src/plugins/router.ts @@ -225,6 +225,15 @@ const routes = [ ), props: true, }, + { + path: "editplayer/:playerId/dsp", + name: "editplayerdsp", + component: () => + import( + /* webpackChunkName: "editdsp" */ "@/views/settings/EditPlayerDsp.vue" + ), + props: true, + }, { path: "editcore/:domain", name: "editcore", diff --git a/src/translations/en.json b/src/translations/en.json index 7726cec3..c002b51a 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -420,6 +420,44 @@ "dynamic_members": { "label": "Dynamic group members", "description": "Allow members to (temporary) join/leave the group dynamically, so the group more or less behaves the same like manually syncing players together, with the main difference being that the groupplayer will hold the queue." + }, + "dsp": { + "configure_on": "Configuring DSP on: {name}", + "disabled_message": "DSP is currently disabled. Enable it using the switch above", + "input": "Input", + "output": "Output", + "enable_output_limiter": "Enable Output Limiter to prevent clipping", + "filter": { + "add": "Add Filter", + "type": "Filter Type", + "new": "New {type}" + }, + "move_up": "Move Up", + "move_down": "Move Down", + "delete_filter": "Delete Filter", + "parametric_eq": { + "add_band": "Add Band", + "delete_band": "Delete Band", + "filter_type": "Filter Type", + "band": "Band {index}", + "enable_band": "Enable Band", + "filter_types": { + "peak": "Peak", + "low_shelf": "Low Shelf", + "high_shelf": "High Shelf", + "low_pass": "Low Pass", + "high_pass": "High Pass", + "notch": "Notch" + } + }, + "parameter": { + "frequency": "Frequency", + "gain": "Gain", + "q_factor": "Q Factor" + }, + "types": { + "parametric_eq": "Parametric EQ" + } } }, "show_info": "Show info", @@ -541,4 +579,4 @@ "powered_off_players": "Unpowered players", "dont_stop_the_music_enable": "Enable 'Don't stop the music!'", "dont_stop_the_music_disable": "Disable 'Don't stop the music!'" -} +} \ No newline at end of file diff --git a/src/views/settings/EditPlayerDsp.vue b/src/views/settings/EditPlayerDsp.vue new file mode 100644 index 00000000..d3840ce8 --- /dev/null +++ b/src/views/settings/EditPlayerDsp.vue @@ -0,0 +1,280 @@ + + + From 6a98d72559d01b612e876e98b0d162152f6789ba Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Wed, 27 Nov 2024 14:01:33 +0100 Subject: [PATCH 6/8] Feat: Add support for the ToneControl DSP Filter This is a simple 3 band equalizer that replaces the old CONF_EQ_BASS, CONF_EQ_MID and CONF_EQ_TREBLE options. --- src/components/dsp/DSPToneControl.vue | 44 +++++++++++++++++++++++++++ src/plugins/api/interfaces.ts | 10 +++++- src/translations/en.json | 8 ++++- src/views/settings/EditPlayerDsp.vue | 21 +++++++++++-- 4 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 src/components/dsp/DSPToneControl.vue diff --git a/src/components/dsp/DSPToneControl.vue b/src/components/dsp/DSPToneControl.vue new file mode 100644 index 00000000..d5e9ea4f --- /dev/null +++ b/src/components/dsp/DSPToneControl.vue @@ -0,0 +1,44 @@ + + diff --git a/src/plugins/api/interfaces.ts b/src/plugins/api/interfaces.ts index 9a556ed5..11e12d59 100644 --- a/src/plugins/api/interfaces.ts +++ b/src/plugins/api/interfaces.ts @@ -9,6 +9,7 @@ export const MASS_LOGO_ONLINE = export enum DSPFilterType { PARAMETRIC_EQ = "parametric_eq", + TONE_CONTROL = "tone_control", } export enum ParametricEQBandType { @@ -40,8 +41,15 @@ export interface ParametricEQFilter extends DSPFilterBase { bands: Array; } +export interface ToneControlFilter extends DSPFilterBase { + type: DSPFilterType.TONE_CONTROL; + bass_level: number; + mid_level: number; + treble_level: number; +} + // Union type for all possible filters -export type DSPFilter = ParametricEQFilter; +export type DSPFilter = ParametricEQFilter | ToneControlFilter; // Main DSP chain configuration export interface DSPConfig { diff --git a/src/translations/en.json b/src/translations/en.json index c002b51a..cfe90638 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -450,13 +450,19 @@ "notch": "Notch" } }, + "tone_control": { + "bass_level": "Bass Level", + "mid_level": "Mid Level", + "treble_level": "Treble Level" + }, "parameter": { "frequency": "Frequency", "gain": "Gain", "q_factor": "Q Factor" }, "types": { - "parametric_eq": "Parametric EQ" + "parametric_eq": "Parametric EQ", + "tone_control": "Tone Control" } } }, diff --git a/src/views/settings/EditPlayerDsp.vue b/src/views/settings/EditPlayerDsp.vue index d3840ce8..a3b89fcb 100644 --- a/src/views/settings/EditPlayerDsp.vue +++ b/src/views/settings/EditPlayerDsp.vue @@ -102,7 +102,13 @@ v-if=" dsp.filters[selectedStage].type === DSPFilterType.PARAMETRIC_EQ " - v-model="dsp.filters[selectedStage]" + v-model="dsp.filters[selectedStage] as ParametricEQFilter" + /> + @@ -142,11 +148,14 @@ import { ParametricEQBandType, DSPFilter, DSPFilterType, + ParametricEQFilter, + ToneControlFilter, } from "@/plugins/api/interfaces"; import { getPlayerName } from "@/helpers/utils"; import DSPPipeline from "@/components/dsp/DSPPipeline.vue"; import DSPSlider from "@/components/dsp/DSPSlider.vue"; import DSPParametricEQ from "@/components/dsp/DSPParametricEQ.vue"; +import DSPToneControl from "@/components/dsp/DSPToneControl.vue"; const { t } = useI18n(); const router = useRouter(); @@ -193,7 +202,15 @@ const addFilter = () => { bands: [], }; break; - + case DSPFilterType.TONE_CONTROL: + filter = { + enabled: true, + type: DSPFilterType.TONE_CONTROL, + bass_level: 0, + mid_level: 0, + treble_level: 0, + }; + break; default: return; } From 2f06d50df801030193ccc52b663875775756d593 Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 2 Dec 2024 10:09:56 +0100 Subject: [PATCH 7/8] Fix: Increase responsiveness of DSP Editor on smaller screens --- src/components/dsp/DSPParametricEQ.vue | 3 ++- src/views/settings/EditPlayerDsp.vue | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/dsp/DSPParametricEQ.vue b/src/components/dsp/DSPParametricEQ.vue index efb2fc13..32b5c945 100644 --- a/src/components/dsp/DSPParametricEQ.vue +++ b/src/components/dsp/DSPParametricEQ.vue @@ -399,7 +399,8 @@ const drawGrid = (ctx: CanvasRenderingContext2D, viewport: Viewport) => { // Draw gain lines const gains = []; - const gainStep = (viewport.max_gain - viewport.min_gain) / 10; + const gainRange = viewport.max_gain - viewport.min_gain; + const gainStep = Math.ceil(gainRange / (viewport.height / 30)); for ( let gain = viewport.min_gain; diff --git a/src/views/settings/EditPlayerDsp.vue b/src/views/settings/EditPlayerDsp.vue index a3b89fcb..9a6a4444 100644 --- a/src/views/settings/EditPlayerDsp.vue +++ b/src/views/settings/EditPlayerDsp.vue @@ -7,11 +7,11 @@ }} - + {{ $t("settings.dsp.disabled_message") }} - + - + Date: Mon, 2 Dec 2024 10:37:16 +0100 Subject: [PATCH 8/8] Refactor: Use vuetifys builtin method for mobile detection --- src/views/settings/EditPlayerDsp.vue | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/views/settings/EditPlayerDsp.vue b/src/views/settings/EditPlayerDsp.vue index 9a6a4444..329d7275 100644 --- a/src/views/settings/EditPlayerDsp.vue +++ b/src/views/settings/EditPlayerDsp.vue @@ -11,12 +11,12 @@ {{ $t("settings.dsp.disabled_message") }} - + (null); const showAddFilterDialog = ref(false); const newFilterType = ref(DSPFilterType.PARAMETRIC_EQ); const windowWidth = ref(window.innerWidth); -const isMobile = computed(() => windowWidth.value < 1300); +const { mobile } = useDisplay(); const filterTypes = Object.values(DSPFilterType).map((value) => { return { @@ -244,16 +245,8 @@ const removeFilter = (index: number) => { // Watchers -const handleResize = () => { - windowWidth.value = window.innerWidth; -}; -window.addEventListener("resize", handleResize); -onUnmounted(() => { - window.removeEventListener("resize", handleResize); -}); - watch( - isMobile, + mobile, (mobile) => { if (!mobile && selectedStage.value === null) { selectStage("input");