diff --git a/src/routes/subsonic.js b/src/routes/subsonic.js
index 113aabe..15d2747 100644
--- a/src/routes/subsonic.js
+++ b/src/routes/subsonic.js
@@ -383,6 +383,132 @@ router.get('/getAlbum.view', authenticateSubsonic, async (req, res) => {
}
});
+// Get album list
+router.get('/getAlbumList.view', authenticateSubsonic, async (req, res) => {
+ try {
+ const { type, size, offset } = req.query;
+ const limit = parseInt(size) || 500;
+ const skip = parseInt(offset) || 0;
+
+ let orderBy = 'year DESC, album';
+
+ switch(type) {
+ case 'random':
+ orderBy = 'RANDOM()';
+ break;
+ case 'newest':
+ orderBy = 'created_at DESC';
+ break;
+ case 'frequent':
+ case 'recent':
+ orderBy = 'album';
+ break;
+ case 'alphabeticalByName':
+ orderBy = 'album';
+ break;
+ case 'alphabeticalByArtist':
+ orderBy = 'album_artist, album';
+ break;
+ }
+
+ const albums = await all(`
+ SELECT DISTINCT album, album_artist, year,
+ (SELECT artwork_path FROM tracks t2 WHERE t2.album = tracks.album LIMIT 1) as artwork_path,
+ COUNT(*) as track_count
+ FROM tracks
+ WHERE is_single = 0
+ GROUP BY album, album_artist
+ ORDER BY ${orderBy}
+ LIMIT ? OFFSET ?
+ `, [limit, skip]);
+
+ let albumListXml = '\n';
+
+ albums.forEach(album => {
+ const albumId = crypto.createHash('md5').update(`album-${album.album}-${album.album_artist}`).digest('hex');
+ const artistId = crypto.createHash('md5').update(`artist-${album.album_artist}`).digest('hex');
+ const coverArt = album.artwork_path ? albumId : '';
+
+ albumListXml += ` \n`;
+ });
+
+ albumListXml += '';
+
+ sendSubsonicResponse(res, albumListXml);
+ } catch (error) {
+ console.error('Error in getAlbumList:', error);
+ sendSubsonicError(res, 0, error.message);
+ }
+});
+
+// Get album list 2 (ID3)
+router.get('/getAlbumList2.view', authenticateSubsonic, async (req, res) => {
+ try {
+ const { type, size, offset } = req.query;
+ const limit = parseInt(size) || 500;
+ const skip = parseInt(offset) || 0;
+
+ let orderBy = 'year DESC, album';
+
+ switch(type) {
+ case 'random':
+ orderBy = 'RANDOM()';
+ break;
+ case 'newest':
+ orderBy = 'created_at DESC';
+ break;
+ case 'alphabeticalByName':
+ orderBy = 'album';
+ break;
+ case 'alphabeticalByArtist':
+ orderBy = 'album_artist, album';
+ break;
+ }
+
+ const albums = await all(`
+ SELECT DISTINCT album, album_artist, year,
+ (SELECT artwork_path FROM tracks t2 WHERE t2.album = tracks.album LIMIT 1) as artwork_path,
+ COUNT(*) as track_count
+ FROM tracks
+ WHERE is_single = 0
+ GROUP BY album, album_artist
+ ORDER BY ${orderBy}
+ LIMIT ? OFFSET ?
+ `, [limit, skip]);
+
+ let albumListXml = '\n';
+
+ albums.forEach(album => {
+ const albumId = crypto.createHash('md5').update(`album-${album.album}-${album.album_artist}`).digest('hex');
+ const artistId = crypto.createHash('md5').update(`artist-${album.album_artist}`).digest('hex');
+ const coverArt = album.artwork_path ? albumId : '';
+
+ albumListXml += ` \n`;
+ });
+
+ albumListXml += '';
+
+ sendSubsonicResponse(res, albumListXml);
+ } catch (error) {
+ console.error('Error in getAlbumList2:', error);
+ sendSubsonicError(res, 0, error.message);
+ }
+});
+
// Get random songs
router.get('/getRandomSongs.view', authenticateSubsonic, async (req, res) => {
try {