Skip to content

Commit

Permalink
fixed eq and types
Browse files Browse the repository at this point in the history
  • Loading branch information
0PandaDEV committed Aug 6, 2024
1 parent 3c61343 commit f8fbe31
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 71 deletions.
28 changes: 18 additions & 10 deletions components/Player.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@

<script lang="ts" setup>
import { invoke } from "@tauri-apps/api/core";
import { Howl } from 'howler';
import type { Song } from '~/types/types';
const { $music, $settings } = useNuxtApp();
Expand All @@ -56,17 +58,19 @@ const progress = ref(0)
const volume = ref($settings.getVolume());
const coverUrl = ref('/cover.png');
const currentSong = computed(() => {
const song = $music.getCurrentSong();
return song ? {
const currentSong = ref<Partial<Song> | null>(null);
watch($music.getCurrentSong, async (songPromise) => {
const song = await songPromise;
currentSong.value = song ? {
id: song.id,
title: song.title,
artist: song.artist,
cover: song.cover,
} : null;
});
}, { immediate: true });
watch(() => $music.howl, (newHowl) => {
watch(() => $music.howl, (newHowl: Howl | null) => {
if (newHowl) {
newHowl.on('play', onPlay);
newHowl.on('pause', onPause);
Expand Down Expand Up @@ -121,11 +125,15 @@ function formatTime(secs: number) {
async function updateDiscordActivity() {
try {
if (!currentSong.value) return;
let thumbnail;
try {
const response = await fetch(`https://api.wireway.ch/wave/thumbnail/${encodeURIComponent(currentSong.value.id)}`);
const data = await response.json();
thumbnail = data.items[0].thumbnail;
if (currentSong.value?.id) {
const response = await fetch(`https://api.wireway.ch/wave/thumbnail/${encodeURIComponent(currentSong.value.id)}`);
const data = await response.json();
thumbnail = data.items[0].thumbnail;
}
} catch (error) {
thumbnail = "https://discussions.apple.com/content/attachment/592590040"
console.error("Failed to fetch song thumbnail:", error);
Expand Down Expand Up @@ -181,14 +189,14 @@ function toggleLoop() {
}
watch(currentSong, async (newSong, oldSong) => {
if (newSong.id && newSong.id !== (oldSong ? oldSong.id : null)) {
if (newSong && newSong.id && newSong.id !== (oldSong ? oldSong.id : null)) {
try {
coverUrl.value = await $music.getCoverURLFromID(newSong.id);
} catch (error) {
console.error('Error fetching cover URL:', error);
coverUrl.value = '/cover.png';
}
} else if (!newSong.id) {
} else if (newSong && !newSong.id) {
coverUrl.value = '/cover.png';
}
}, { immediate: true });
Expand Down
2 changes: 1 addition & 1 deletion pages/search.vue
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ let searchTimeout: ReturnType<typeof setTimeout>;
const hoveredSongId = ref("");
const currentSong = computed(() => {
return $music.getCurrentSong() || { id: 0 };
return $music.getCurrentSong() || { id: '' };
});
watch(currentSong, () => { });
Expand Down
34 changes: 26 additions & 8 deletions pages/songs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -142,17 +142,35 @@ function startVisualizer() {
});
}
const audio = $music.getAudio();
audio.addEventListener('play', draw);
audio.addEventListener('pause', stop);
audio.addEventListener('ended', stop);
let isPlaying = false;
function toggleVisualizer(play: boolean) {
isPlaying = play;
if (isPlaying) {
draw();
} else {
stop();
}
}
return {
start: () => toggleVisualizer(true),
stop: () => toggleVisualizer(false)
};
}
if (!audio.paused) {
draw();
const visualizer = startVisualizer();
watch(() => $music.isPlaying(), (isPlaying) => {
console.log('Music playing state changed:', isPlaying);
if (isPlaying) {
console.log('Starting visualizer');
visualizer.start();
} else {
stop();
console.log('Stopping visualizer');
visualizer.stop();
}
}
});
</script>

<style scoped lang="scss">
Expand Down
50 changes: 26 additions & 24 deletions plugins/music.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import {
remove,
} from "@tauri-apps/plugin-fs";
import type { Song, SongsConfig, Playlist } from "~/types/types";
import Database from "@tauri-apps/plugin-sql";

export default defineNuxtPlugin(async (nuxtApp) => {
const db = await Database.load("sqlite:data.db");
const musicStore = useMusicStore();
const settingsStore = useSettingsStore();

Expand Down Expand Up @@ -159,7 +157,8 @@ export default defineNuxtPlugin(async (nuxtApp) => {
Howler.volume(volume / 100);
},
async getCurrentSong(): Promise<Song | null> {
return await musicStore.getCurrentSong();
const currentSongId = musicStore.getCurrentSong();
return currentSongId ? await musicStore.getSongByID(currentSongId) : null;
},
async applyEqSettings() {
const eqSettings = settingsStore.getEq();
Expand Down Expand Up @@ -241,32 +240,35 @@ export default defineNuxtPlugin(async (nuxtApp) => {
setupEqualizer() {
if (!this.howl) return;

const node = this.howl._sounds[0]._node; // HTMLAudioElement
const node = (this.howl as any)._sounds[0]._node;
const ctx = Howler.ctx;

this.analyzer = ctx.createAnalyser();
const sourceNode = ctx.createMediaElementSource(node);
if (!node.sourceNode) {
this.analyzer = ctx.createAnalyser();
node.sourceNode = ctx.createMediaElementSource(node);

// Create equalizer bands
const frequencies = [32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000];
this.equalizer = frequencies.map(freq => {
const filter = ctx.createBiquadFilter();
filter.type = 'peaking';
filter.frequency.value = freq;
filter.Q.value = 1;
filter.gain.value = 0;
return filter;
});
const frequencies = [32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000];
this.equalizer = frequencies.map(freq => {
const filter = ctx.createBiquadFilter();
filter.type = 'peaking';
filter.frequency.value = freq;
filter.Q.value = 1;
filter.gain.value = 0;
return filter;
});

// Connect nodes
sourceNode.connect(this.equalizer[0]);
this.equalizer.reduce((prev, curr) => {
prev.connect(curr);
return curr;
});
this.equalizer[this.equalizer.length - 1].connect(this.analyzer);
this.analyzer.connect(ctx.destination);
node.sourceNode.connect(this.equalizer[0]);
this.equalizer.reduce((prev, curr) => {
prev.connect(curr);
return curr;
});
this.equalizer[this.equalizer.length - 1].connect(this.analyzer);
this.analyzer.connect(ctx.destination);
}
},
isPlaying(): boolean {
return this.howl ? this.howl.playing() : false;
}
};

return {
Expand Down
45 changes: 28 additions & 17 deletions stores/music.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { computed } from 'vue';
export const useMusicStore = defineStore("musicStore", {
state: () => ({
songsConfig: {
songs: {},
playlists: {},
songs: {} as Record<string, Song>,
playlists: {} as Record<string, Playlist>,
},
player: {
currentSongId: "",
Expand Down Expand Up @@ -44,16 +44,15 @@ export const useMusicStore = defineStore("musicStore", {

const playlists = await this.db.select<Playlist[]>("SELECT * FROM playlists");
playlists.forEach(playlist => {
this.songsConfig.playlists[playlist.id] = {
...playlist,
songs: playlist.songs.split(',')
};
this.songsConfig.playlists[playlist.id] = playlist;
});
},
async addSongData(song: Song) {
await this.db.execute("INSERT INTO songs (id, title, artist, length, cover, date_added, last_played) VALUES (?, ?, ?, ?, ?, ?, ?)", [
song.id, song.title, song.artist, song.length, song.cover, song.date_added, song.lastPlayed
]);
if (this.db) {
await this.db.execute("INSERT INTO songs (id, title, artist, length, cover, date_added, last_played) VALUES (?, ?, ?, ?, ?, ?, ?)", [
song.id, song.title, song.artist, song.length, song.cover, song.date_added, song.lastPlayed
]);
}
this.songsConfig.songs[song.id] = song;
this.lastUpdated = Date.now();
},
Expand All @@ -64,29 +63,37 @@ export const useMusicStore = defineStore("musicStore", {
return this.songsConfig.songs[id] ?? null;
},
async updateLastPlayed(songId: string, lastPlayed: string) {
await this.db.execute("UPDATE songs SET last_played = ? WHERE id = ?", [lastPlayed, songId]);
if (this.db) {
await this.db.execute("UPDATE songs SET last_played = ? WHERE id = ?", [lastPlayed, songId]);
}
if (this.songsConfig.songs[songId]) {
this.songsConfig.songs[songId].lastPlayed = lastPlayed;
}
},
async createPlaylist(playlist: Playlist) {
await this.db.execute("INSERT INTO playlists (id, name, cover, songs) VALUES (?, ?, ?, ?)", [
playlist.id, playlist.name, playlist.cover, playlist.songs.join(',')
]);
if (this.db) {
await this.db.execute("INSERT INTO playlists (id, name, cover, songs) VALUES (?, ?, ?, ?)", [
playlist.id, playlist.name, playlist.cover, playlist.songs.join(',')
]);
}
this.songsConfig.playlists[playlist.id] = playlist;
this.lastUpdated = Date.now();
},
getPlaylistByID(id: string): Playlist {
return this.songsConfig.playlists[id] ?? null;
},
async renamePlaylist(playlistId: string, newName: string) {
await this.db.execute("UPDATE playlists SET name = ? WHERE id = ?", [newName, playlistId]);
if (this.db) {
await this.db.execute("UPDATE playlists SET name = ? WHERE id = ?", [newName, playlistId]);
}
if (this.songsConfig.playlists[playlistId]) {
this.songsConfig.playlists[playlistId].name = newName;
}
},
async updatePlaylistCover(playlistId: string, newCoverPath: string) {
await this.db.execute("UPDATE playlists SET cover = ? WHERE id = ?", [newCoverPath, playlistId]);
if (this.db) {
await this.db.execute("UPDATE playlists SET cover = ? WHERE id = ?", [newCoverPath, playlistId]);
}
if (this.songsConfig.playlists[playlistId]) {
this.songsConfig.playlists[playlistId].cover = newCoverPath;
}
Expand All @@ -95,7 +102,9 @@ export const useMusicStore = defineStore("musicStore", {
const playlist = this.songsConfig.playlists[playlistId];
if (playlist && this.songsConfig.songs[songId]) {
playlist.songs.push(songId);
await this.db.execute("UPDATE playlists SET songs = ? WHERE id = ?", [playlist.songs.join(','), playlistId]);
if (this.db) {
await this.db.execute("UPDATE playlists SET songs = ? WHERE id = ?", [playlist.songs.join(','), playlistId]);
}
}
this.lastUpdated = Date.now();
},
Expand All @@ -105,7 +114,9 @@ export const useMusicStore = defineStore("musicStore", {
async setSong(id: string) {
this.player.currentSongId = id;
const currentTime = new Date().toISOString();
await this.db.execute("UPDATE songs SET last_played = ? WHERE id = ?", [currentTime, id]);
if (this.db) {
await this.db.execute("UPDATE songs SET last_played = ? WHERE id = ?", [currentTime, id]);
}
if (this.songsConfig.songs[id]) {
this.songsConfig.songs[id].lastPlayed = currentTime;
}
Expand Down
10 changes: 5 additions & 5 deletions stores/settings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { defineStore } from 'pinia';
import Database from '@tauri-apps/plugin-sql';
import { invoke } from '@tauri-apps/api/core';
import type { EQSettings } from "~/types/types";

export const useSettingsStore = defineStore("settingsStore", {
Expand Down Expand Up @@ -31,9 +32,9 @@ export const useSettingsStore = defineStore("settingsStore", {
const results = await db.select<any[]>("SELECT key, value FROM settings");
results.forEach(({ key, value }) => {
try {
this.settings[key] = JSON.parse(value);
(this.settings as any)[key] = JSON.parse(value);
} catch {
this.settings[key] = value;
(this.settings as any)[key] = value;
}
});
},
Expand Down Expand Up @@ -95,7 +96,7 @@ export const useSettingsStore = defineStore("settingsStore", {
const instances = await response.json();
const urls = instances.map((instance: { api_url: string }) => instance.api_url);

const results = await window.__TAURI__.core.invoke('ping_urls', { urls });
const results = await invoke<string[][]>('ping_urls', { urls });
this.setApiURL(results[0][0]);
return results;
} catch (error) {
Expand All @@ -115,5 +116,4 @@ export const useSettingsStore = defineStore("settingsStore", {
}
},
},
});

});
11 changes: 5 additions & 6 deletions types/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Database from "@tauri-apps/plugin-sql";
import { Howl } from 'howler';

export interface Song {
id: string;
Expand All @@ -25,19 +26,17 @@ export interface SongsConfig {
}

export interface Player {
audio: HTMLAudioElement;
currentSongId: string;
audioContext: AudioContext | null;
sourceNode: MediaElementAudioSourceNode | null;
analyser: AnalyserNode | null;
eqFilters: BiquadFilterNode[];
howl: Howl | null;
}

export interface MusicStore {
songsConfig: SongsConfig;
player: Player;
lastUpdated: number;
db: Database;
db: Database | null;
queue: string[];
currentQueueIndex: number;
}

export interface MusicSearchResponseItem {
Expand Down

0 comments on commit f8fbe31

Please sign in to comment.