diff --git a/frontend/songs.json b/frontend/songs.json deleted file mode 100644 index 11428b0..0000000 --- a/frontend/songs.json +++ /dev/null @@ -1,717 +0,0 @@ -{ - "0": { - "artist": "Ballroom Dance Orchestra & Marc Reift", - "title": "Emperor's Dream", - "year": "2013-12-05", - "genre": [ "Easy Listening" ], - "duration": 183, - "filename": "i.b1JvdXPf09kp30", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "0", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music114/v4/31/9a/e8/319ae8b2-0269-bb27-514e-200d9cf12bc0/888608304733.jpg/1200x1200bb.jpg" - }, - "1": { - "artist": "Studio Dance Band", - "title": "The Blue Danube", - "year": "2000-01-01", - "genre": [ "Pop" ], - "duration": 135, - "filename": "i.XMD6RDPH9x1ea9", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "1", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music/b8/d9/1a/mzi.mkymfljn.jpg/1200x1200bb.jpg" - }, - "2": { - "artist": "Los del Río", - "title": "Macarena", - "year": "1993-12-13", - "genre": [ "Pop Latino" ], - "duration": 250, - "filename": "macarena.wav", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "2", - "origin": "disk", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music114/v4/a1/2d/6a/a12d6a7b-6173-ed2e-9682-a30d245ed7fe/mzi.ndplymif.jpg/1200x1200bb.jpg" - }, - "3": { - "artist": "Spice Girls", - "title": "Wannabe", - "year": "1996-06-26", - "genre": [ "Pop" ], - "duration": 173, - "filename": "i.WmYQX3PtgOa5Wg", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "3", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music125/v4/01/05/18/0105189c-9608-fb39-975c-a4dbc066da7e/21UMGIM57237.rgb.jpg/1200x1200bb.jpg" - }, - "4": { - "artist": "ABBA", - "title": "Dancing Queen", - "year": "1974-01-01", - "genre": [ "Pop" ], - "duration": 230, - "filename": "i.eoDz5v7hWx1grW", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "4", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music114/v4/b5/b0/0b/b5b00b45-e209-9d03-4656-4117eec98a01/17UM1IM10690.rgb.jpg/1200x1200bb.jpg" - }, - "5": { - "artist": "Bobby Darin", - "title": "Splish Splash", - "year": "1958-09-01", - "genre": [ "Rock & Roll" ], - "duration": 132, - "filename": "i.GEG7XKkS2eOXN2", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "5", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/0c/86/fb/0c86fb9b-cb59-3b45-7d06-9c49827e541c/s05.eccxgemi.jpg/1200x1200bb.jpg" - }, - "6": { - "artist": "Bill Haley and His Comets", - "title": "See You Later, Alligator (Remastered)", - "year": "1956-06-01", - "genre": [ "Rock" ], - "duration": 164, - "filename": "i.RBrMvlofWv3A9W", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "6", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music126/v4/14/24/c8/1424c885-f3a6-73d0-3fae-1bf9e4554165/5056321621139.png/1200x1200bb.jpg" - }, - "7": { - "artist": "Pedro Garcia & His Del Prado Orchestra", - "title": "Rico Vacilon", - "year": "2009-01-05", - "genre": [ "Latin" ], - "duration": 174, - "filename": "i.mmpYZ5aFkvAK9k", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "7", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music/1d/c3/8a/mzi.cpscarsp.jpg/1200x1200bb.jpg" - }, - "8": { - "artist": "Rey Ruiz", - "title": "El Diablo Anda Suelto", - "year": "1999-08-11", - "genre": [ "Música tropical" ], - "duration": 254, - "filename": "i.JL1Yx2rSgGlDPg", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "8", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Features114/v4/81/f5/cf/81f5cf3e-3514-4428-affe-55d3e5f0e315/dj.ffashngb.jpg/1200x1200bb.jpg" - }, - "9": { - "artist": "Shakira", - "title": "Hips Don't Lie (feat. Wyclef Jean)", - "year": "2006-02-28", - "genre": [ "Pop" ], - "duration": 218, - "filename": "i.b1JvdpPC09kp30", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "9", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Features114/v4/2a/33/9a/2a339a01-28f3-3ddd-f9e7-30c837f046cc/dj.bvmymfoa.jpg/1200x1200bb.jpg" - }, - "10": { - "artist": "Luis Enrique", - "title": "Como Volver a Ser Feliz", - "year": "2009-05-19", - "genre": [ "Pop Latino" ], - "duration": 252, - "filename": "i.RBrMvr3TWv3A9W", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "10", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music/5d/91/9a/mzi.jihxnatg.tif/1200x1200bb.jpg" - }, - "11": { - "artist": "The New 101 Strings Orchestra", - "title": "Moon River (From \"Breakfast at Tiffany's\")", - "year": "2000-01-01", - "genre": [ "Easy Listening" ], - "duration": 174, - "filename": "i.4YBelRxUdMLQOd", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "11", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music126/v4/30/a3/d9/30a3d94e-1d6c-d807-fc28-58aa1759a8ac/0056775070120.jpg/1200x1200bb.jpg" - }, - "12": { - "artist": "Cat Stevens", - "title": "Morning Has Broken", - "year": "1971-10-01", - "genre": [ "Pop" ], - "duration": 201, - "filename": "i.ldDOmY9SR3XvxR", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "12", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music113/v4/3e/2e/7d/3e2e7dee-b278-7830-e286-38a815d02fa4/21UMGIM78164.rgb.jpg/1200x1200bb.jpg" - }, - "13": { - "artist": "Graham Dalby & The Grahamophones", - "title": "Jeepers Creepers (Quickstep)", - "year": "1995-01-01", - "genre": [ "Dance" ], - "duration": 179, - "filename": "i.DVEXQaPFzD5QMz", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "13", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music/4e/03/33/mzi.cehftcpg.jpg/1200x1200bb.jpg" - }, - "14": { - "artist": "Britney Spears", - "title": "...Baby One More Time", - "year": "1998-09-29", - "genre": [ "Pop" ], - "duration": 211, - "filename": "i.eoDz5b8fWx1grW", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "14", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music125/v4/7b/f7/0e/7bf70ecc-b16b-01d8-b14c-00ccae5062c7/dj.wvceujiz.jpg/1200x1200bb.jpg" - }, - "15": { - "artist": "Justin Timberlake", - "title": "CAN'T STOP THE FEELING! (Original Song From DreamWorks Animation's \"Trolls\")", - "year": "2016-05-06", - "genre": [ "Pop" ], - "duration": 236, - "filename": "i.XMD6R9zh9x1ea9", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "15", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/52/d0/02/52d002d7-1f7f-8d91-4791-ed04c460ec93/886445894653.jpg/1200x1200bb.jpg" - }, - "16": { - "artist": "Tommy Dorsey and His Orchestra", - "title": "Tea For Two Cha Cha (from the Isme Christmas TV advert)", - "year": "2005-01-01", - "genre": [ "Soundtrack" ], - "duration": 188, - "filename": "i.eoDz5LBcWx1grW", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "16", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/7d/05/bb/7d05bb15-2379-4bf8-ca9b-6fbf10ceaba8/nfm309.jpg/1200x1200bb.jpg" - }, - "17": { - "artist": "Rey Ruiz", - "title": "Muevelo", - "year": "2000-05-02", - "genre": [ "Música tropical" ], - "duration": 258, - "filename": "i.DVEXQE1tzD5QMz", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "17", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music122/v4/58/15/0d/58150db1-0e74-dd19-f7eb-3f15e8a04b56/197187182459.jpg/1200x1200bb.jpg" - }, - "18": { - "artist": "James Brown", - "title": "I Feel Good (I Got You)", - "year": "2008-05-05", - "genre": [ "Rock" ], - "duration": 166, - "filename": "i.GEG7XLRf2eOXN2", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "18", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/a7/57/51/a7575132-3206-fb87-82d8-7b71498c4772/mzi.icplsaoj.tif/1200x1200bb.jpg" - }, - "19": { - "artist": "Elvis Presley", - "title": "Jailhouse Rock", - "year": "1957-09-24", - "genre": [ "Rock" ], - "duration": 147, - "filename": "i.WmYQXBBTgOa5Wg", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "19", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music122/v4/e8/0a/4e/e80a4eb4-256d-50e8-615e-217436cf6bfb/196589185921.jpg/1200x1200bb.jpg" - }, - "20": { - "artist": "Elvis Presley", - "title": "Are You Lonesome Tonight?", - "year": "1960-11-01", - "genre": [ "Rock" ], - "duration": 187, - "filename": "i.ldDOmoESR3XvxR", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "20", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music115/v4/ec/14/ea/ec14ea7c-7886-5757-5837-6ea26c0e4e7d/dj.qusytvtz.jpg/1200x1200bb.jpg" - }, - "21": { - "artist": "Span", - "title": "Louenesee", - "year": "2006-09-08", - "genre": [ "Pop" ], - "duration": 255, - "filename": "i.ldDOmEmFR3XvxR", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "21", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music112/v4/73/7e/4d/737e4dd9-c379-a078-0743-ede62a9af5f0/cover.jpg/1200x1200bb.jpg" - }, - "22": { - "artist": "Michael Bublé", - "title": "Something Stupid (feat. Reese Witherspoon)", - "year": "2013-04-15", - "genre": [ "Pop" ], - "duration": 178, - "filename": "i.RBrMvmvSWv3A9W", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "22", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music/v4/27/75/f5/2775f5b3-8f62-aaf8-9743-46be49cbbc1b/093624944799.jpg/1200x1200bb.jpg" - }, - "23": { - "artist": "Bee Gees", - "title": "Stayin' Alive (From \"Saturday Night Fever\" Soundtrack)", - "year": "1977-01-01", - "genre": [ "Pop" ], - "duration": 284, - "filename": "i.ldDQRqBFR3XvxR", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "23", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music113/v4/45/db/1d/45db1dac-fe00-3681-b216-266deea6e4cc/17UM1IM26789.rgb.jpg/1200x1200bb.jpg" - }, - "24": { - "artist": "Mark Ronson", - "title": "Uptown Funk (feat. Bruno Mars)", - "year": "2015-01-13", - "genre": [ "Pop" ], - "duration": 270, - "filename": "i.JL1Yx1KUgGlDPg", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "24", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music5/v4/43/03/57/430357e0-e142-8d4d-ca56-87f4bd41e017/886444976145.jpg/1200x1200bb.jpg" - }, - "25": { - "artist": "Ballroom Orchestra & Singers", - "title": "Suelta la Cintura ( Chachacha / 32 Bpm )", - "year": "2009-09-21", - "genre": [ "Pop" ], - "duration": 155, - "filename": "i.RBrMvVgSWv3A9W", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "25", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music/4c/31/28/mzi.vrcubdmd.jpg/1200x1200bb.jpg" - }, - "26": { - "artist": "Michael Bublé", - "title": "Come Dance With Me", - "year": "2013-04-15", - "genre": [ "Pop" ], - "duration": 166, - "filename": "i.DVEXQJgtzD5QMz", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "26", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music/v4/27/75/f5/2775f5b3-8f62-aaf8-9743-46be49cbbc1b/093624944799.jpg/1200x1200bb.jpg" - }, - "27": { - "artist": "Sixpence None the Richer", - "title": "Kiss Me", - "year": "1989-09-01", - "genre": [ "Pop" ], - "duration": 209, - "filename": "i.XMD6R5QT9x1ea9", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "27", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music113/v4/3c/c5/b1/3cc5b1fc-828b-984a-ca75-76c139be37f6/080688702861.png/1200x1200bb.jpg" - }, - "28": { - "artist": "Surf Mesa", - "title": "ily (i love you baby) [feat. Emilee]", - "year": "2019-11-26", - "genre": [ "Dance" ], - "duration": 177, - "filename": "i.b1JvdDAF09kp30", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "28", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music115/v4/00/2c/31/002c3175-9261-aee9-2e41-5af229cb2703/20UMGIM14423.rgb.jpg/1200x1200bb.jpg" - }, - "29": { - "artist": "Queen", - "title": "Crazy Little Thing Called Love", - "year": "1979-01-01", - "genre": [ "Rock" ], - "duration": 163, - "filename": "i.WmYQXZXfgOa5Wg", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "29", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music125/v4/e8/f1/51/e8f151ae-0f87-a2fd-b981-807a01b24504/18UMGIM55031.rgb.jpg/1200x1200bb.jpg" - }, - "30": { - "artist": "Jerry Lee Lewis", - "title": "Great Balls Of Fire (Remastered 2022)", - "year": "1957-01-01", - "genre": [ "Rock" ], - "duration": 112, - "filename": "i.mmpYZGEHkvAK9k", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "30", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music123/v4/33/d0/88/33d0885f-0981-e55b-0983-fbc0180b332b/23UMGIM00418.rgb.jpg/1200x1200bb.jpg" - }, - "31": { - "artist": "Ritchie Valens", - "title": "La Bamba (Bonus Track)", - "year": "1958-06-25", - "genre": [ "Pop" ], - "duration": 126, - "filename": "i.4YBel4zcdMLQOd", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "31", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music114/v4/52/62/27/5262275c-2998-3dd2-f226-b2ca4a08987c/cover.jpg/1200x1200bb.jpg" - }, - "32": { - "artist": "Charles Fox", - "title": "Macho", - "year": "2010-12-01", - "genre": [ "Música tropical" ], - "duration": 187, - "filename": "i.DVEXQzNFzD5QMz", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "32", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music112/v4/68/50/cf/6850cf4a-4db1-73bb-f4e6-d8d1c986970e/197187621828.jpg/1200x1200bb.jpg" - }, - "33": { - "artist": "Engelbert Humperdinck", - "title": "The Last Waltz", - "year": "1967-01-01", - "genre": [ "Pop" ], - "duration": 184, - "filename": "i.WmYQXYqigOa5Wg", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "33", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music118/v4/62/58/ff/6258ffd9-cda3-ba4d-e700-04d919a744bd/00602557548235.rgb.jpg/1200x1200bb.jpg" - }, - "34": { - "artist": "Johann Strauss Orchestra", - "title": "An Der Schönen Blauen Donau", - "year": "2007-10-01", - "genre": [ "Classical" ], - "duration": 432, - "filename": "i.eoDz5r7iWx1grW", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "34", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music/62/07/a6/mzi.aucttxtk.tif/1200x1200bb.jpg" - }, - "35": { - "artist": "Dua Lipa", - "title": "Dance The Night", - "year": "2023-05-27", - "genre": [ "Pop" ], - "duration": 177, - "filename": "i.eoDz5LPIWx1grW", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "35", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music116/v4/c0/54/97/c05497aa-c19f-bf4f-de29-71edf30fbefb/075679688767.jpg/1200x1200bb.jpg" - }, - "36": { - "artist": "Justin Wellington", - "title": "Iko Iko (My Bestie) [feat. Small Jam]", - "year": "2017-03-21", - "genre": [ "Reggae" ], - "duration": 183, - "filename": "i.4YBelBNFdMLQOd", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "36", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music115/v4/49/47/12/49471204-6605-e350-d4fb-9803f9105c57/886449208111.jpg/1200x1200bb.jpg" - }, - "37": { - "artist": "Michael Jackson", - "title": "Beat It", - "year": "1982-11-30", - "genre": [ "Pop" ], - "duration": 258, - "filename": "i.4YBNDgVsdMLQOd", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "37", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music115/v4/32/4f/fd/324ffda2-9e51-8f6a-0c2d-c6fd2b41ac55/074643811224.jpg/1200x1200bb.jpg" - }, - "38": { - "artist": "Nicki Minaj", - "title": "Super Freaky Girl", - "year": "2022-08-12", - "genre": [ "Hip-Hop/Rap" ], - "duration": 171, - "filename": "i.JL1Yxd2HgGlDPg", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "38", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music112/v4/74/d9/a8/74d9a88e-9641-df34-401a-506b739bd824/22UMGIM87047.rgb.jpg/1200x1200bb.jpg" - }, - "39": { - "artist": "Katy Perry", - "title": "California Gurls (feat. Snoop Dogg)", - "year": "2010-05-07", - "genre": [ "Pop" ], - "duration": 235, - "filename": "i.ldDOmLEUR3XvxR", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "39", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music116/v4/31/57/b3/3157b3d9-6551-e44e-46c0-488686998a05/13UABIM58339.rgb.jpg/1200x1200bb.jpg" - }, - "40": { - "artist": "Los del Río", - "title": "Macarena (Original Version)", - "year": "1993-12-13", - "genre": [ "Pop Latino" ], - "duration": 250, - "filename": "i.4YBepzRFdMLQOd", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "40", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music114/v4/a1/2d/6a/a12d6a7b-6173-ed2e-9682-a30d245ed7fe/mzi.ndplymif.jpg/1200x1200bb.jpg" - }, - "41": { - "artist": "Rey Ruiz", - "title": "Ay Mujer", - "year": "2000-01-01", - "genre": [ "Música tropical" ], - "duration": 220, - "filename": "i.mmpYZvBtkvAK9k", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "41", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music122/v4/58/15/0d/58150db1-0e74-dd19-f7eb-3f15e8a04b56/197187182459.jpg/1200x1200bb.jpg" - }, - "42": { - "artist": "Jennifer Lopez", - "title": "Let's Get Loud", - "year": "1999-06-01", - "genre": [ "Pop" ], - "duration": 239, - "filename": "i.eoD8NG8TWx1grW", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "42", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music125/v4/c7/f4/6d/c7f46dbd-bc8d-7a7a-cf66-4b96dc59e105/888880316592.jpg/1200x1200bb.jpg" - }, - "43": { - "artist": "Riton & Nightcrawlers", - "title": "Friday (feat. Mufasa & Hypeman) [Dopamine Re-Edit]", - "year": "2021-01-15", - "genre": [ "Dance" ], - "duration": 169, - "filename": "i.eoDz5QWSWx1grW", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "43", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music115/v4/f8/a5/5f/f8a55f83-f755-524c-aa9e-fd6a039e34e7/886448989318.jpg/1200x1200bb.jpg" - }, - "44": { - "artist": "a-ha", - "title": "Take On Me (2015 Remastered Version)", - "year": "1985-06-01", - "genre": [ "Pop" ], - "duration": 228, - "filename": "i.DVENx5mTzD5QMz", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "44", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music115/v4/0b/5b/69/0b5b6991-cd46-7222-fca7-680b17318721/603497888191.jpg/1200x1200bb.jpg" - }, - "45": { - "artist": "ABBA", - "title": "Gimme! Gimme! Gimme! (A Man After Midnight)", - "year": "1979-04-23", - "genre": [ "Pop" ], - "duration": 290, - "filename": "i.DVEN9pGtzD5QMz", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "45", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music115/v4/60/f8/a6/60f8a6bc-e875-238d-f2f8-f34a6034e6d2/14UMGIM07615.rgb.jpg/1200x1200bb.jpg" - }, - "46": { - "artist": "Black Eyed Peas", - "title": "I Gotta Feeling", - "year": "2009-01-01", - "genre": [ "Pop" ], - "duration": 289, - "filename": "i.b1Jvde0u09kp30", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "46", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music116/v4/b1/d1/ae/b1d1ae62-12dd-eb84-3e46-643c444da662/09UMGIM13833.rgb.jpg/1200x1200bb.jpg" - }, - "47": { - "artist": "Robbie Williams", - "title": "Angels", - "year": "1997-12-01", - "genre": [ "Pop" ], - "duration": 265, - "filename": "i.GEG7XL1t2eOXN2", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "47", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/cf/86/e7/cf86e787-2177-6366-a5c3-2180c3031015/13ULAIM49472.rgb.jpg/1200x1200bb.jpg" - }, - "48": { - "artist": "Taio Cruz", - "title": "Hangover (feat. Flo Rida)", - "year": "2011-01-01", - "genre": [ "Pop" ], - "duration": 245, - "filename": "i.XMD6Rlxt9x1ea9", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "48", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/2e/fa/e2/2efae20b-7287-f437-f453-40ee0fd597f6/00602527869728.rgb.jpg/1200x1200bb.jpg" - }, - "49": { - "artist": "Eminem", - "title": "The Real Slim Shady", - "year": "2000-01-01", - "genre": [ "Hip-Hop/Rap" ], - "duration": 285, - "filename": "i.ldDOm09FR3XvxR", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "49", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music116/v4/8a/a6/b5/8aa6b52a-d879-72c7-4289-85f8a9e5c535/06UMGIM17280.rgb.jpg/1200x1200bb.jpg" - }, - "50": { - "artist": "Icona Pop", - "title": "I Love It (feat. Charli XCX)", - "year": "2012-05-09", - "genre": [ "Pop" ], - "duration": 156, - "filename": "i.ldDOmElUR3XvxR", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "50", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music4/v4/cb/77/44/cb7744e2-5afe-3984-dbe6-bbbc2065cfd3/075678683800.jpg/1200x1200bb.jpg" - }, - "51": { - "artist": "Village People", - "title": "YMCA", - "year": "1978-01-01", - "genre": [ "Pop" ], - "duration": 287, - "filename": "i.GEGNom2H2eOXN2", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "51", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/92/cf/51/92cf5148-2b66-504a-8f6f-4b24e45c5195/mzi.hpkpognq.jpg/1200x1200bb.jpg" - }, - "52": { - "artist": "Rednex", - "title": "Cotton Eye Joe", - "year": "1994-01-01", - "genre": [ "Pop" ], - "duration": 194, - "filename": "i.mmpeN8JFkvAK9k", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "52", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music115/v4/98/b2/f0/98b2f0fa-2964-3e8a-ffc2-bddff8fa8a42/38518.jpg/1200x1200bb.jpg" - }, - "53": { - "artist": "Sinéad O'Connor", - "title": "Nothing Compares 2 U (Edit)", - "year": "1990-03-12", - "genre": [ "Pop" ], - "duration": 307, - "filename": "i.mmpYZXEukvAK9k", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "53", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music126/v4/a9/1e/a9/a91ea9bf-d6f3-8f96-3b95-f2bebf7c15c8/14ULAIM03937.rgb.jpg/1200x1200bb.jpg" - }, - "54": { - "artist": "Udo Lindenberg & Apache 207", - "title": "Komet", - "year": "2023-01-19", - "genre": [ "Pop" ], - "duration": 167, - "filename": "i.GEG7XxkF2eOXN2", - "coverArtOrigin": "api", - "hasCoverArt": true, - "queuePos": "54", - "origin": "apple-music", - "coverArtURL": "https://is1-ssl.mzstatic.com/image/thumb/Music123/v4/50/49/17/50491796-e488-a0ae-03ff-cab5afb4aef1/5054197494963.jpg/1200x1200bb.jpg" - } -} \ No newline at end of file diff --git a/frontend/src/app.js b/frontend/src/app.js index 74ce66e..3f6bad9 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -234,7 +234,12 @@ app.get( '/indexDirs', ( req, res ) => { } ); app.get( '/loadPlaylist', ( req, res ) => { - res.send( JSON.parse( fs.readFileSync( dialog.showOpenDialogSync( { properties: [ 'openFile' ], title: 'Open file with playlist' } )[ 0 ] ) ) ); + const selFile = dialog.showOpenDialogSync( { properties: [ 'openFile' ], title: 'Open file with playlist' } )[ 0 ]; + res.send( { 'data': JSON.parse( fs.readFileSync( selFile ) ), 'path': selFile } ); +} ); + +app.get( '/getMetadata', async ( req, res ) => { + res.send( await indexer.analyzeFile( req.query.file ) ); } ); app.post( '/savePlaylist', ( req, res ) => { @@ -249,7 +254,6 @@ app.post( '/savePlaylist', ( req, res ) => { ], defaultPath: 'songs.json' } ), beautify( req.body, null, 2, 50 ) ); - console.log( req.body ); res.send( 'ok' ); } ); diff --git a/frontend/src/client/appleMusic/index.html b/frontend/src/client/appleMusic/index.html index f8afceb..6f35934 100644 --- a/frontend/src/client/appleMusic/index.html +++ b/frontend/src/client/appleMusic/index.html @@ -38,6 +38,7 @@
+
@@ -53,8 +54,8 @@ repeat repeat_one_on repeat_on - upload - ios_share + upload + ios_share
info
@@ -62,6 +63,7 @@

{{ localIP }}:8081

+
diff --git a/frontend/src/client/appleMusic/index.js b/frontend/src/client/appleMusic/index.js index 4de6302..0cd951e 100644 --- a/frontend/src/client/appleMusic/index.js +++ b/frontend/src/client/appleMusic/index.js @@ -1,3 +1,17 @@ +/* +* MusicPlayerV2 - index.js +* +* Created by Janis Hutz 11/20/2023, Licensed under the GPL V3 License +* https://janishutz.com, development@janishutz.com +* +* +*/ + +/* + Quick side note here: This is terribly ugly code, but I was in a hurry to finish it, + so I had no time to clean it up. I will do that at some point -jh +*/ + const app = Vue.createApp( { data() { return { @@ -29,6 +43,8 @@ const app = Vue.createApp( { // local drive isUsingCustomPlaylist: false, rawLoadedPlaylistData: {}, + basePath: '', + audioPlayer: null, // slider offset: 0, @@ -73,42 +89,6 @@ const app = Vue.createApp( { this.config.userToken = this.musicKit.musicUserToken; } this.musicKit.shuffleMode = MusicKit.PlayerShuffleMode.off; - this.musicKit.addEventListener( 'nowPlayingItemDidChange', ( e ) => { - this.control( 'play' ); - this.hasFinishedInit = true; - // Assemble this.playingSong - // TODO: Also add additional items to queue if there are new - // items that weren't previously shown (limitation of MusicKitJS). - // TODO: Load from disk and stop MusicKit playback if next item in queue is - // to be loaded from disk - // TODO: Consideration: array with offsets to check if songs is correct - if ( e.item ) { - this.playingSong = this.songQueue[ this.musicKit.nowPlayingItemIndex ]; - let url = e.item.attributes.artwork.url; - url = url.replace( '{w}', e.item.attributes.artwork.width ); - url = url.replace( '{h}', e.item.attributes.artwork.height ); - this.playingSong[ 'coverArtURL' ] = url; - this.queuePos = this.musicKit.nowPlayingItemIndex; - this.sendUpdate( 'playingSong' ); - this.sendUpdate( 'pos' ); - this.sendUpdate( 'isPlaying' ); - this.sendUpdate( 'queuePos' ); - setTimeout( () => { - this.sendUpdate( 'pos' ); - }, 500 ); - const minuteCounts = Math.floor( ( this.playingSong.duration ) / 60 ); - this.durationBeautified = String( minuteCounts ) + ':'; - if ( ( '' + minuteCounts ).length === 1 ) { - this.durationBeautified = '0' + minuteCounts + ':'; - } - const secondCounts = Math.floor( ( this.playingSong.duration ) - minuteCounts * 60 ); - if ( ( '' + secondCounts ).length === 1 ) { - this.durationBeautified += '0' + secondCounts; - } else { - this.durationBeautified += secondCounts; - } - } - } ); this.apiGetRequest( 'https://api.music.apple.com/v1/me/library/playlists', this.playlistHandler ); } ); } ); @@ -223,7 +203,11 @@ const app = Vue.createApp( { this.originalPos = e.offsetX; this.calcProgressPos(); this.calcPlaybackPos(); - this.musicKit.seekToTime( this.pos ); + if ( this.playingSong.origin === 'apple-music' ) { + this.musicKit.seekToTime( this.pos ); + } else { + this.audioPlayer.currentTime = this.pos; + } this.sendUpdate( 'pos' ); } }, @@ -245,7 +229,6 @@ const app = Vue.createApp( { } else if ( update === 'songQueue' ) { data = this.songQueue; } else if ( update === 'queuePos' ) { - this.queuePos = this.musicKit.nowPlayingItemIndex >= 0 ? this.musicKit.nowPlayingItemIndex : 0; data = this.queuePos; } else if ( update === 'posReset' ) { data = 0; @@ -288,58 +271,83 @@ const app = Vue.createApp( { }, control( action ) { if ( action === 'play' ) { - if( !this.musicKit || !this.isPlaying ) { - this.musicKit.play().then( () => { - this.sendUpdate( 'pos' ); - } ).catch( err => { - console.log( 'player failed to start' ); - console.log( err ); - } ); + if ( !this.playingSong.origin ) { + this.play( this.songQueue[ 0 ] ); + this.isPlaying = true; } else { - this.musicKit.pause().then( () => { - this.musicKit.play().catch( err => { - console.log( 'player failed to start' ); - console.log( err ); - } ); - } ); - } - this.isPlaying = true; - try { - clearInterval( this.progressTracker ); - } catch( err ) {}; - this.progressTracker = setInterval( () => { - this.pos = parseInt( this.musicKit.currentPlaybackTime ); - - const minuteCount = Math.floor( this.pos / 60 ); - this.playbackPosBeautified = minuteCount + ':'; - if ( ( '' + minuteCount ).length === 1 ) { - this.playbackPosBeautified = '0' + minuteCount + ':'; - } - const secondCount = Math.floor( this.pos - minuteCount * 60 ); - if ( ( '' + secondCount ).length === 1 ) { - this.playbackPosBeautified += '0' + secondCount; - } else { - this.playbackPosBeautified += secondCount; - } - - if ( this.isShowingRemainingTime ) { - const minuteCounts = Math.floor( ( this.playingSong.duration - this.pos ) / 60 ); - this.durationBeautified = '-' + String( minuteCounts ) + ':'; - if ( ( '' + minuteCounts ).length === 1 ) { - this.durationBeautified = '-0' + minuteCounts + ':'; - } - const secondCounts = Math.floor( ( this.playingSong.duration - this.pos ) - minuteCounts * 60 ); - if ( ( '' + secondCounts ).length === 1 ) { - this.durationBeautified += '0' + secondCounts; + if ( this.playingSong.origin === 'apple-music' ) { + if( !this.musicKit || !this.isPlaying ) { + this.musicKit.play().then( () => { + this.sendUpdate( 'pos' ); + } ).catch( err => { + console.log( 'player failed to start' ); + console.log( err ); + } ); } else { - this.durationBeautified += secondCounts; + this.musicKit.pause().then( () => { + this.musicKit.play().catch( err => { + console.log( 'player failed to start' ); + console.log( err ); + } ); + } ); } + this.audioPlayer.pause(); + } else { + this.audioPlayer.play(); + this.musicKit.pause(); } - }, 200 ); - this.sendUpdate( 'pos' ); - this.sendUpdate( 'isPlaying' ); + this.isPlaying = true; + try { + clearInterval( this.progressTracker ); + } catch( err ) {}; + this.progressTracker = setInterval( () => { + if ( this.playingSong.origin === 'apple-music' ) { + this.pos = parseInt( this.musicKit.currentPlaybackTime ); + } else { + this.pos = parseInt( this.audioPlayer.currentTime ); + } + + if ( this.pos > this.playingSong.duration - 1 ) { + this.control( 'next' ); + } + + const minuteCount = Math.floor( this.pos / 60 ); + this.playbackPosBeautified = minuteCount + ':'; + if ( ( '' + minuteCount ).length === 1 ) { + this.playbackPosBeautified = '0' + minuteCount + ':'; + } + const secondCount = Math.floor( this.pos - minuteCount * 60 ); + if ( ( '' + secondCount ).length === 1 ) { + this.playbackPosBeautified += '0' + secondCount; + } else { + this.playbackPosBeautified += secondCount; + } + + // TODO: Check playback duration with backend analysis + + if ( this.isShowingRemainingTime ) { + const minuteCounts = Math.floor( ( this.playingSong.duration - this.pos ) / 60 ); + this.durationBeautified = '-' + String( minuteCounts ) + ':'; + if ( ( '' + minuteCounts ).length === 1 ) { + this.durationBeautified = '-0' + minuteCounts + ':'; + } + const secondCounts = Math.floor( ( this.playingSong.duration - this.pos ) - minuteCounts * 60 ); + if ( ( '' + secondCounts ).length === 1 ) { + this.durationBeautified += '0' + secondCounts; + } else { + this.durationBeautified += secondCounts; + } + } + }, 50 ); + this.sendUpdate( 'pos' ); + this.sendUpdate( 'isPlaying' ); + } } else if ( action === 'pause' ) { - this.musicKit.pause(); + if ( this.playingSong.origin === 'apple-music' ) { + this.musicKit.pause(); + } else { + this.audioPlayer.pause(); + } this.sendUpdate( 'pos' ); try { clearInterval( this.progressTracker ); @@ -348,63 +356,99 @@ const app = Vue.createApp( { this.isPlaying = false; this.sendUpdate( 'isPlaying' ); } else if ( action === 'replay10' ) { - this.musicKit.seekToTime( this.musicKit.currentPlaybackTime > 10 ? musicPlayer.player.currentPlaybackTime - 10 : 0 ); - this.pos = this.musicKit.currentPlaybackTime; + if ( this.playingSong.origin === 'apple-music' ) { + this.musicKit.seekToTime( this.musicKit.currentPlaybackTime > 10 ? this.musicKit.currentPlaybackTime - 10 : 0 ); + this.pos = this.musicKit.currentPlaybackTime; + } else { + this.audioPlayer.currentTime = this.audioPlayer.currentTime > 10 ? this.audioPlayer.currentTime - 10 : 0; + this.pos = this.audioPlayer.currentTime; + } this.sendUpdate( 'pos' ); } else if ( action === 'forward10' ) { - if ( this.musicKit.currentPlaybackTime < ( this.playingSong.duration - 10 ) ) { - this.musicKit.seekToTime( this.musicKit.currentPlaybackTime + 10 ); - this.pos = this.musicKit.currentPlaybackTime; - this.sendUpdate( 'pos' ); - // Get currently playing song and get duration from there - } else { - if ( this.repeatMode !== 'one' ) { - this.control( 'next' ); - } else { - this.musicKit.seekToTime( 0 ); + if ( this.playingSong.origin === 'apple-music' ) { + if ( this.musicKit.currentPlaybackTime < ( this.playingSong.duration - 10 ) ) { + this.musicKit.seekToTime( this.musicKit.currentPlaybackTime + 10 ); this.pos = this.musicKit.currentPlaybackTime; this.sendUpdate( 'pos' ); + } else { + if ( this.repeatMode !== 'one' ) { + this.control( 'next' ); + } else { + this.musicKit.seekToTime( 0 ); + this.pos = this.musicKit.currentPlaybackTime; + this.sendUpdate( 'pos' ); + } + } + } else { + if ( this.audioPlayer.currentTime < ( this.playingSong.duration - 10 ) ) { + this.audioPlayer.currentTime = this.audioPlayer.currentTime + 10; + this.pos = this.audioPlayer.currentTime; + this.sendUpdate( 'pos' ); + } else { + if ( this.repeatMode !== 'one' ) { + this.control( 'next' ); + } else { + this.audioPlayer.currentTime = 0; + this.pos = this.audioPlayer.currentTime; + this.sendUpdate( 'pos' ); + } } } } else if ( action === 'reset' ) { clearInterval( this.progressTracker ); this.pos = 0; - this.musicKit.seekToTime( 0 ); + if ( this.playingSong.origin === 'apple-music' ) { + this.musicKit.seekToTime( 0 ); + } else { + this.audioPlayer.currentTime = 0; + } this.sendUpdate( 'pos' ); } else if ( action === 'next' ) { - this.musicKit.skipToNextItem().then( () => { - this.sendUpdate( 'queuePos' ); - this.pos = 0; - this.sendUpdate( 'posReset' ); - } ); + if ( this.queuePos < parseInt( Object.keys( this.songQueue ).length ) - 1 ) { + this.queuePos = parseInt( this.queuePos ) + 1; + this.play( this.songQueue[ this.queuePos ] ); + } else { + if ( this.repeatMode === 'all' ) { + this.queuePos = 0; + this.play( this.songQueue[ 0 ] ); + } else { + this.control( 'pause' ); + } + } } else if ( action === 'previous' ) { if ( this.pos > 3 ) { this.pos = 0; - this.musicKit.seekToTime( 0 ).then( () => { + if ( this.isUsingCustomPlaylist ) { + this.audioPlayer.currentTime = 0; this.sendUpdate( 'pos' ); - this.sendUpdate( 'queuePos' ); - this.control( 'play' ); - } ); + } else { + this.musicKit.seekToTime( 0 ).then( () => { + this.sendUpdate( 'pos' ); + this.control( 'play' ); + } ); + } } else { - this.musicKit.skipToPreviousItem().then( () => { - this.sendUpdate( 'queuePos' ); - this.pos = 0; - this.sendUpdate( 'posReset' ); - } ); + if ( this.queuePos > 0 ) { + this.queuePos = parseInt( this.queuePos ) - 1; + this.play( this.songQueue[ this.queuePos ] ); + } else { + this.queuePos = parseInt( Object.keys( this.songQueue ).length ) - 1; + this.play[ this.songQueue[ this.queuePos ] ]; + } } + } else if ( action === 'shuffleOff' ) { + // TODO: Make shuffle function this.isShuffleEnabled = false; - this.musicKit.shuffleMode = MusicKit.PlayerShuffleMode.off; - this.loadPlaylist(); + // this.loadPlaylist(); + alert( 'not implemented yet' ); } else if ( action === 'shuffleOn' ) { - this.musicKit.shuffleMode = MusicKit.PlayerShuffleMode.songs; this.isShuffleEnabled = true; - this.loadPlaylist(); + alert( 'not implemented yet' ); + // this.loadPlaylist(); } else if ( action === 'repeatOne' ) { this.repeatMode = 'one'; - this.musicKit.repeatMode = MusicKit.PlayerRepeatMode.one; } else if ( action === 'repeatAll' ) { - this.musicKit.repeatMode = MusicKit.PlayerRepeatMode.all; this.repeatMode = 'all'; } else if ( action === 'repeatOff' ) { this.musicKit.repeatMode = MusicKit.PlayerRepeatMode.none; @@ -421,14 +465,37 @@ const app = Vue.createApp( { } } - // TODO: Update as well - this.musicKit.changeToMediaItem( this.musicKit.queue.items[ foundSong ] ).then( () => { - this.sendUpdate( 'queuePos' ); - this.pos = 0; - this.sendUpdate( 'posReset' ); - } ).catch( ( err ) => { - console.log( err ); - } ); + this.queuePos = foundSong; + this.sendUpdate( 'queuePos' ); + this.pos = 0; + this.sendUpdate( 'posReset' ); + this.playingSong = song; + this.sendUpdate( 'playingSong' ); + if ( song.origin === 'apple-music' ) { + this.musicKit.setQueue( { 'song': song.filename } ).then( () => { + setTimeout( () => { + this.control( 'play' ); + }, 500 ); + } ).catch( ( err ) => { + console.log( err ); + } ); + } else { + setTimeout( () => { + this.control( 'play' ); + }, 500 ); + } + const minuteCounts = Math.floor( ( this.playingSong.duration ) / 60 ); + this.durationBeautified = String( minuteCounts ) + ':'; + if ( ( '' + minuteCounts ).length === 1 ) { + this.durationBeautified = '0' + minuteCounts + ':'; + } + const secondCounts = Math.floor( ( this.playingSong.duration ) - minuteCounts * 60 ); + if ( ( '' + secondCounts ).length === 1 ) { + this.durationBeautified += '0' + secondCounts; + } else { + this.durationBeautified += secondCounts; + } + this.hasFinishedInit = true; }, toggleShowMode() { this.isShowingRemainingTime = !this.isShowingRemainingTime; @@ -453,10 +520,11 @@ const app = Vue.createApp( { let playlistSongs = []; fetch( '/loadPlaylist' ).then( res => { res.json().then( data => { - this.rawLoadedPlaylistData = data; - for ( let song in data ) { - if ( data[ song ].origin === 'apple-music' ) { - playlistSongs.push( data[ song ].filename ); + this.rawLoadedPlaylistData = data.data; + this.basePath = data.path.slice( 0, data.path.lastIndexOf( '/' ) ); + for ( let song in this.rawLoadedPlaylistData ) { + if ( this.rawLoadedPlaylistData[ song ].origin === 'apple-music' ) { + playlistSongs.push( this.rawLoadedPlaylistData[ song ].filename ); } } this.musicKit.setQueue( { songs: playlistSongs } ).then( () => { @@ -493,6 +561,7 @@ const app = Vue.createApp( { 'hasCoverArt': true, 'queuePos': item, 'origin': 'apple-music', + 'offset': offset, } let url = songQueue[ item - offset ].attributes.artwork.url; url = url.replace( '{w}', songQueue[ item - offset ].attributes.artwork.width ); @@ -504,23 +573,28 @@ const app = Vue.createApp( { term: ( this.rawLoadedPlaylistData[ item ].artist ?? '' ) + ' ' + ( this.rawLoadedPlaylistData[ item ].title ?? '' ), types: [ 'songs' ], }; - // TODO: Make sure that playback duration is correct (get from backend with analysis?) // TODO: Make storefront adjustable const result = await this.musicKit.api.music( '/v1/catalog/ch/search', queryParameters ); + let json; + try { + const res = await fetch( '/getMetadata?file=' + this.basePath + '/' + this.rawLoadedPlaylistData[ item ].filename ); + json = await res.json(); + } catch( err ) {} if ( result.data ) { if ( result.data.results.songs ) { - const dat = result.data.results.songs.data[ 0 ] + const dat = result.data.results.songs.data[ 0 ]; + console.log( json ); this.songQueue[ item ] = { 'artist': dat.attributes.artistName, 'title': dat.attributes.name, 'year': dat.attributes.releaseDate, 'genre': dat.attributes.genreNames, - 'duration': Math.round( dat.attributes.durationInMillis / 1000 ), + 'duration': json ? Math.round( json.duration ) : undefined, 'filename': this.rawLoadedPlaylistData[ item ].filename, 'coverArtOrigin': 'api', 'hasCoverArt': true, 'queuePos': item, - 'origin': 'apple-music', + 'origin': 'local', } let url = dat.attributes.artwork.url; url = url.replace( '{w}', dat.attributes.artwork.width ); @@ -533,6 +607,21 @@ const app = Vue.createApp( { this.sendUpdate( 'songQueue' ); } } )(); + setTimeout( () => { + this.audioPlayer = document.getElementById( 'audio-player' ); + }, 1000 ); + }, + search() { + ( async() => { + const searchTerm = prompt( 'Enter search term...' ) + const queryParameters = { + term: ( searchTerm ), + types: [ 'songs' ], + }; + // TODO: Make storefront adjustable + const result = await this.musicKit.api.music( '/v1/catalog/ch/search', queryParameters ); + console.log( result ); + } )(); } }, watch: { diff --git a/frontend/src/indexer.js b/frontend/src/indexer.js index 1ddeeed..39110af 100644 --- a/frontend/src/indexer.js +++ b/frontend/src/indexer.js @@ -74,6 +74,24 @@ const parseExistingData = ( dat, dir ) => { } ); } +module.exports.analyzeFile = async ( filepath ) => { + let metadata = await musicMetadata.parseFile( filepath ); + return { + 'artist': metadata[ 'common' ][ 'artist' ], + 'title': metadata[ 'common' ][ 'title' ], + 'year': metadata[ 'common' ][ 'year' ], + 'bpm': metadata[ 'common' ][ 'bpm' ], + 'genre': metadata[ 'common' ][ 'genre' ], + 'duration': Math.round( metadata[ 'format' ][ 'duration' ] ), + 'isLossless': metadata[ 'format' ][ 'lossless' ], + 'sampleRate': metadata[ 'format' ][ 'sampleRate' ], + 'bitrate': metadata[ 'format' ][ 'bitrate' ], + 'numberOfChannels': metadata[ 'format' ][ 'numberOfChannels' ], + 'container': metadata[ 'format' ][ 'container' ], + 'filename': filepath, + } +} + hasCompletedFetching = {}; let files = {}; const parseDir = ( dat, req, existingData ) => {