Skip to content

Commit

Permalink
added eq and volume restoring from config
Browse files Browse the repository at this point in the history
  • Loading branch information
0PandaDEV committed Apr 13, 2024
1 parent afb32d7 commit 44d2afc
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 114 deletions.
83 changes: 58 additions & 25 deletions components/Player.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<p class="element-title">Player</p>
<div class="top">
<div class="info">
<img :src="cover || '/cover.png'" class="cover"></img>
<img :src="cover || '/cover.png'" class="cover" />
<div class="h">
<div class="title">{{ title }}</div>
<div class="artist">{{ artist }}</div>
Expand All @@ -22,34 +22,50 @@
<IconsVolumeMid v-else-if="volume > 0" />
<IconsVolumeMute v-else />

<input class="volume" @input="setVolume" v-model="volume" step="1" min="0" max="100" type="range" name="" id="">
<input
class="volume"
@input="setVolume"
v-model="volume"
step="1"
min="0"
max="100"
type="range"
name=""
id=""
/>
</div>
</div>
<div class="bottom">
<input type="range" class="progress" v-model="progress" @input="seekTo" min="0" max="100" step=".1">
<input
type="range"
class="progress"
v-model="progress"
@input="seekTo"
min="0"
max="100"
step=".1"
/>
<div class="progress-indicator" :style="{ width: progress + '%' }"></div>
<div class="numbers">
{{ time }} / {{ duration }}
</div>
<div class="numbers">{{ time }} / {{ duration }}</div>
</div>
</div>
</template>

<script>
import Player from '@/lib/Player.ts';
import Player from "@/lib/Player.ts";
export default {
data() {
return {
player: Player.getInstance(),
title: 'Title',
artist: 'Artist',
title: "Title",
artist: "Artist",
cover: "",
volume: 100,
time: "0:00",
duration: "0:00",
progress: 0,
playing: false
playing: false,
};
},
methods: {
Expand All @@ -65,8 +81,9 @@ export default {
this.player.pause();
this.playing = false;
},
setVolume() {
this.player.setVolume(this.volume / 100);
async setVolume() {
await this.player.updateVolumeSetting(this.volume);
await this.player.setVolume(this.volume);
},
async rewind() {
await this.player.rewind();
Expand All @@ -85,33 +102,49 @@ export default {
},
},
watch: {
'player.currentTime': function(newTime) {
"player.currentTime": function (newTime) {
this.progress = (newTime / this.player.getDuration()) * 100;
}
},
},
mounted() {
this.player.audio.addEventListener('timeupdate', () => {
this.player.audio.addEventListener("timeupdate", () => {
const time = this.player.getCurrentTime();
this.time = time > 0 ? new Date(time * 1000).toISOString().substr(14, 5) : '0:00';
this.progress = (this.player.getCurrentTime() / this.player.getDuration()) * 100;
this.time =
time > 0 ? new Date(time * 1000).toISOString().substr(14, 5) : "0:00";
this.progress =
(this.player.getCurrentTime() / this.player.getDuration()) * 100;
});
this.player.audio.addEventListener('loadedmetadata', async () => {
this.player.audio.addEventListener("loadedmetadata", async () => {
const duration = this.player.getDuration();
this.duration = duration > 0 ? new Date(duration * 1000).toISOString().substr(14, 5) : '0:00';
this.duration =
duration > 0
? new Date(duration * 1000).toISOString().substr(14, 5)
: "0:00";
await this.getTitle();
await this.getArtist();
await this.getCover();
});
this.player.audio.addEventListener('play', () => {
this.player.audio.addEventListener("play", () => {
this.playing = true;
});
this.player.audio.addEventListener('pause', () => {
this.player.audio.addEventListener("pause", () => {
this.playing = false;
});
}
}
this.player
.ensureVolumeInitialized()
.then(() => {
const volume = this.player.getVolume();
this.volume = volume;
console.log("Volume initialized to:", volume);
})
.catch((error) => {
console.error("Error initializing volume:", error);
});
},
};
</script>

<style lang="scss">
@import '~/assets/styles/components/player.scss';
</style>
@import "~/assets/styles/components/player.scss";
</style>
26 changes: 17 additions & 9 deletions lib/Settings.ts → lib/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,38 @@ interface EQSettings {
[key: string]: string;
}

class Settings {
export class Config {
static async readSettings(): Promise<Map<string, string>> {
try {
const settings: { [key: string]: string } = await window.__TAURI__.invoke('read_settings');
const settings: { [key: string]: string } = await window.__TAURI__.core.invoke('read_settings');
return new Map(Object.entries(settings));
} catch (error) {
console.error('Error reading settings:', error);
throw error;
}
}

static async readEQSettings(): Promise<Map<string, string>> {
static async readEQSettings(): Promise<Map<string, number>> {
try {
const eqSettings: { [key: string]: string } = await window.__TAURI__.invoke('read_eq_settings');
return new Map(Object.entries(eqSettings));
const eqSettings: { [key: string]: string } = await window.__TAURI__.core.invoke('read_eq_settings');
const eqSettingsNum: { [key: string]: number } = {};
for (const key in eqSettings) {
eqSettingsNum[key] = parseFloat(eqSettings[key]);
}
return new Map(Object.entries(eqSettingsNum));
} catch (error) {
console.error('Error reading EQ settings:', error);
throw error;
}
}

static async writeEQSettings(eqSettings: EQSettings): Promise<void> {
static async writeEQSettings(eqSettings: Map<string, number>): Promise<void> {
try {
await window.__TAURI__.invoke('write_eq_settings', { eqSettings });
const eqSettingsObj: { [key: string]: string } = {};
eqSettings.forEach((value, key) => {
eqSettingsObj[key] = value.toString();
});
await window.__TAURI__.core.invoke('write_eq_settings', { eqSettings: eqSettingsObj });
} catch (error) {
console.error('Error writing EQ settings:', error);
throw error;
Expand All @@ -34,12 +42,12 @@ class Settings {

static async updateUserSetting(key: string, value: string): Promise<void> {
try {
await window.__TAURI__.invoke('update_user_setting', { key, value });
await window.__TAURI__.core.invoke('update_user_setting', { key, value });
} catch (error) {
console.error('Error updating user setting:', error);
throw error;
}
}
}

export default Settings;
export default Config;
88 changes: 56 additions & 32 deletions lib/Player.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { readSongs } from './Songs';
import Config from './Config';

class Player {
private static instance: Player;
Expand All @@ -7,20 +8,64 @@ class Player {
private audioContext: AudioContext;
private sourceNode: MediaElementAudioSourceNode;
private eqFilters: BiquadFilterNode[];
private volumeInitialized: Promise<void>;

private constructor() {
if (!Player.instance) {
this.audio = new Audio();
this.audio.volume = 1;
this.audio.preload = 'auto';
this.currentSongId = '';
this.audioContext = new AudioContext();
this.sourceNode = this.audioContext.createMediaElementSource(this.audio);
this.eqFilters = this.createEqFilters();
this.connectEqFilters();
Player.instance = this;
this.audio = new Audio();
this.audio.preload = 'auto';
this.currentSongId = '';
this.audioContext = new AudioContext();
this.sourceNode = this.audioContext.createMediaElementSource(this.audio);
this.eqFilters = this.createEqFilters();
this.connectEqFilters();
this.volumeInitialized = this.initVolume();
}

private async initVolume() {
const settings = await Config.readSettings();
const volume = settings.get('volume');
this.setVolume(volume);
}

public async ensureVolumeInitialized() {
await this.volumeInitialized;
}

public setVolume(volume: number) {
const minVolume = 0;
const maxVolume = 100;
volume = Math.max(minVolume, Math.min(maxVolume, volume));

const minp = 0;
const maxp = 100;
const minv = Math.log(0.01);
const maxv = Math.log(1);
const scale = (maxv - minv) / (maxp - minp);
const volumeFraction = Math.exp(minv + scale * (volume - minp));

this.audio.volume = volumeFraction;
}

public async updateVolumeSetting(volume: number) {
await Config.updateUserSetting('volume', volume.toString());
}

public getVolume(): number {
const minp = 0;
const maxp = 100;
const minv = Math.log(0.01);
const maxv = Math.log(1);
const scale = (maxv - minv) / (maxp - minp);

const volumeFraction = this.audio.volume;

if (volumeFraction === 0) {
return 0;
}
return Player.instance;

const volume = (Math.log(volumeFraction) - minv) / scale + minp;

return Math.round(volume);
}

private createEqFilters(): BiquadFilterNode[] {
Expand Down Expand Up @@ -108,27 +153,6 @@ class Player {
await this.setSong(songIds[prevIndex]);
}

public setVolume(volume: number) {
if (volume == 0) {
this.audio.volume = 0;
return;
}

const minVolume = 1;
const maxVolume = 100;
volume = Math.max(minVolume, Math.min(maxVolume, volume));

const minp = 0;
const maxp = 100;

const minv = Math.log(0.01);
const maxv = Math.log(1);

const scale = (maxv - minv) / (maxp - minp);

this.audio.volume = Math.exp(minv + scale * (volume - minp));
}

public seek(percentage: number) {
const seekTime = this.audio.duration * (percentage / 100);
this.audio.currentTime = seekTime;
Expand Down
31 changes: 24 additions & 7 deletions pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
type="range"
min="-12"
max="12"
step="1"
v-model="eqGains[index]"
@input="updateEqGain(index, $event.target.value)"
step="0.1"
v-model.number="eqGains[index]"
@input="updateEqGain(index, $event.target.valueAsNumber)"
/>
<label>{{ freq }} Hz</label>
<span>{{ eqGains[index] }}</span>
<span>{{ eqGains[index].toFixed(1) }}</span>
</div>
</div>
<li v-for="song in songs" :key="song.id" class="song-item">
Expand All @@ -29,21 +29,38 @@
</template>

<script setup>
import { onMounted, ref } from "vue";
import { onMounted, ref, watch } from "vue";
import Config from "~/lib/Config.ts";
import { readSongs } from "~/lib/Songs.ts";
import Player from "~/lib/Player.ts";
const songs = ref([]);
const player = Player.getInstance();
const frequencies = [32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000];
const eqGains = reactive(new Array(frequencies.length).fill(0));
const eqGains = ref(new Array(frequencies.length).fill(0));
async function loadEqSettings() {
const eqSettings = await Config.readEQSettings();
frequencies.forEach((freq, index) => {
const gain = eqSettings.get(freq.toString());
if (gain !== undefined) {
eqGains.value[index] = gain;
}
});
}
function updateEqGain(filterIndex, gain) {
player.setEqGain(filterIndex, parseFloat(gain));
player.setEqGain(filterIndex, gain); // No need to parseFloat as it's already a number
const eqSettingsMap = new Map();
frequencies.forEach((freq, index) => {
eqSettingsMap.set(freq.toString(), eqGains.value[index]);
});
Config.writeEQSettings(eqSettingsMap);
}
onMounted(async () => {
try {
await loadEqSettings();
const songsConfig = await readSongs();
songs.value = await Promise.all(
Object.entries(songsConfig.songs).map(async ([id, song]) => {
Expand Down
Loading

0 comments on commit 44d2afc

Please sign in to comment.