diff --git a/src/routes/subsonic.js b/src/routes/subsonic.js index 327f741..6f1c407 100644 --- a/src/routes/subsonic.js +++ b/src/routes/subsonic.js @@ -98,6 +98,110 @@ router.get('/getMusicFolders.view', authenticateSubsonic, async (req, res) => { `); }); +// Get music directory (for browsing by folder structure) +router.get('/getMusicDirectory.view', authenticateSubsonic, async (req, res) => { + try { + const { id } = req.query; + + // Root folder - return all artists + if (id === '1') { + const artists = await all(` + SELECT DISTINCT artist + FROM tracks + ORDER BY artist + `); + + let dirXml = '\n'; + + artists.forEach(artist => { + const artistId = crypto.createHash('md5').update(`artist-${artist.artist}`).digest('hex'); + dirXml += ` \n`; + }); + + dirXml += ''; + return sendSubsonicResponse(res, dirXml); + } + + // Artist folder - return albums for this artist + const artists = await all(`SELECT DISTINCT artist FROM tracks`); + let targetArtist = null; + + for (const artist of artists) { + const testId = crypto.createHash('md5').update(`artist-${artist.artist}`).digest('hex'); + if (testId === id) { + targetArtist = artist.artist; + break; + } + } + + if (targetArtist) { + const albums = await all(` + SELECT DISTINCT album, album_artist, year, + (SELECT artwork_path FROM tracks t2 WHERE t2.album = tracks.album AND t2.artist = ? LIMIT 1) as artwork_path, + COUNT(*) as track_count + FROM tracks + WHERE artist = ? + GROUP BY album, album_artist + ORDER BY year DESC, album + `, [targetArtist, targetArtist]); + + let dirXml = `\n`; + + albums.forEach(album => { + const albumId = crypto.createHash('md5').update(`album-${album.album}-${album.album_artist}`).digest('hex'); + const coverArt = album.artwork_path ? albumId : ''; + dirXml += ` \n`; + }); + + dirXml += ''; + return sendSubsonicResponse(res, dirXml); + } + + // Album folder - return tracks + const allAlbums = await all(`SELECT DISTINCT album, album_artist FROM tracks`); + let targetAlbum = null; + let targetAlbumArtist = null; + + for (const album of allAlbums) { + const testId = crypto.createHash('md5').update(`album-${album.album}-${album.album_artist}`).digest('hex'); + if (testId === id) { + targetAlbum = album.album; + targetAlbumArtist = album.album_artist; + break; + } + } + + if (targetAlbum) { + const tracks = await all(` + SELECT * FROM tracks + WHERE album = ? AND album_artist = ? + ORDER BY disc_number, track_number, title + `, [targetAlbum, targetAlbumArtist]); + + if (tracks.length === 0) { + return sendSubsonicError(res, 70, 'Album not found'); + } + + const firstTrack = tracks[0]; + let dirXml = `\n`; + + tracks.forEach(track => { + dirXml += buildSongXml(track, req); + }); + + dirXml += ''; + return sendSubsonicResponse(res, dirXml); + } + + sendSubsonicError(res, 70, 'Directory not found'); + } catch (error) { + console.error('Error in getMusicDirectory:', error); + sendSubsonicError(res, 0, error.message); + } +}); + // Get indexes (artists) router.get('/getIndexes.view', authenticateSubsonic, async (req, res) => { try {