From 968d30897eb5d704d91d5a69a4df6e10439ac453 Mon Sep 17 00:00:00 2001 From: Kristy Fournier <124598538+kristy-fournier@users.noreply.github.com> Date: Wed, 5 Mar 2025 11:07:55 -0500 Subject: [PATCH 1/6] New JSON layout --- Server/databaseGenerator.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Server/databaseGenerator.py b/Server/databaseGenerator.py index a504848..109ffbe 100644 --- a/Server/databaseGenerator.py +++ b/Server/databaseGenerator.py @@ -27,20 +27,19 @@ if args.mode == "update": with open('songDatabase.json', 'r') as handle: songDatabaseList = json.load(handle) except: - songDatabaseList=[] + songDatabaseList={"songDirectory":soundLocation,'songData':{}} - for i in songDatabaseList: + for i in songDatabaseList["songData"]: try: - songFiles.index(i["file"]) != -1 + songFiles.index(i) != -1 except: - print("deleted: " + i["file"] + " from database") + print("deleted: " + i + " from database") songDatabaseList.remove(i) - for i in songDatabaseList: - songFiles.pop(songFiles.index(i["file"])) + for i in songDatabaseList["songData"]: + songFiles.remove(i) print("new songs: " + str(songFiles)) elif args.mode=="new": - songDatabaseList = [] - + songDatabaseList={"songDirectory":soundLocation,'songData':{}} if args.art.lower() == "true": x = len(songFiles)*0.25 if x > 60: @@ -85,7 +84,7 @@ for i in songFiles: index = (songFiles.index(i))%4 print("\r" + str(loading[index] + str(math.floor((songFiles.index(i)/(len(songFiles)-1))*100))+ "%"), end='', flush=True) # each "song" is stored as a dictionary containing the below stuff, and each dictionary is put into a list - songDatabaseList.append({"file":i,"title":title,"artist":artist,"art":image,"length":length}) + songDatabaseList["songData"][i] = ({"title":title,"artist":artist,"art":image,"length":length}) with open('songDatabase.json', 'w') as handle: json.dump(songDatabaseList, handle) From 9a3008b29e2bf0efb79eea1027240639f2072db0 Mon Sep 17 00:00:00 2001 From: Kristy Fournier <124598538+kristy-fournier@users.noreply.github.com> Date: Wed, 5 Mar 2025 11:15:33 -0500 Subject: [PATCH 2/6] Update readme to match new generator use --- readme.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/readme.md b/readme.md index 02b7058..0eb0171 100644 --- a/readme.md +++ b/readme.md @@ -49,18 +49,19 @@ These are specific details on each section of the app, and how to use them - Running with `--directory (directoryOfmp3s)` allows for sound files to be in a different place - Default `"./sound"` - _This setting might be kinda iffy on Linux. You're on Linux just go and edit it if you have issues_ - - __Make certain you only use forward slashes in your directory, even on Windows__ + - ~~__Make certain you only use forward slashes in your directory, even on Windows__~~ I think this should be fine now i'll check later - `songDatabase.json` stores all the information about each song in this format: ``` -[ - { - "file": "The Search_NF.mp3", - "title": "The Search", - "artist": "NF", - "art": "https://lastfm.freetls.fastly.net/i/u/64s/03125956378d531a44e1b7da89aae795.png", - "length": 292 +{ + "songDirectory": "./sound/", + "songData": { + "Circus_Fox Szn.mp3": + {"title": "Circus", + "artist": "Fox Szn", + "art": null, + "length": 141} } -] +} ``` - `webbyBits.py` imports the database, runs all music playing, and accepts all commands from clients - Searches return matching songs From cf8796a3a12784bf09dd1be7d12ddc13abf61e17 Mon Sep 17 00:00:00 2001 From: Kristy Fournier <124598538+kristy-fournier@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:18:05 -0500 Subject: [PATCH 3/6] Playlist mode, adding songs work in new format --- Client/scripts.js | 46 ++++++++++++++++++------------------ Server/webbyBits.py | 57 +++++++++++++++++++-------------------------- 2 files changed, 47 insertions(+), 56 deletions(-) diff --git a/Client/scripts.js b/Client/scripts.js index 3f43bbc..d52b8e6 100644 --- a/Client/scripts.js +++ b/Client/scripts.js @@ -98,35 +98,33 @@ async function searchSongs(searchTerm){ document.getElementById("songlist").innerHTML = "" searchResults = await getFromServer({search:searchTerm},"search").then() - for (let index in searchResults) { - optionslist.push([index,searchResults[index][0],searchResults[index][1],searchResults[index][2]]); - } //generate the visual song list - for(let i = 0; i < optionslist.length; i++) { + for(var fileName in searchResults) { + let currentSongInJSON = searchResults[fileName] let newItem = document.createElement("div"); newItem.className = "item"; - newItem.id = optionslist[i][3]; + newItem.id = fileName; let image = document.createElement("img"); try { - if (optionslist[i][2] == null) { + if (currentSongInJSON["art"] == null) { throw "no image lolz" } - image.src = optionslist[i][2]; + image.src = currentSongInJSON["art"]; } catch(err){ image.src = "./images/placeholder.png"; } - image.id = String(optionslist[i][3])+" image"; + image.id = String(fileName)+" image"; let head3 = document.createElement("h3"); - head3.innerText = optionslist[i][0]; + head3.innerText = currentSongInJSON["title"]; let head4 = document.createElement("h4"); - head4.innerText=optionslist[i][1]; + head4.innerText = currentSongInJSON["artist"]; newItem.appendChild(image); newItem.appendChild(head3); newItem.appendChild(head4); document.getElementById("songlist").appendChild(newItem); } - if (optionslist.length == 0) { + if (searchResults.length == 0) { //display error if no results document.getElementById("songlist").innerHTML = "

We might not have that one...

"; } @@ -211,29 +209,30 @@ async function generateVisualPlaylist(conditions="") { document.getElementById("playlist-alert").innerHTML = "Nothing's Queued..." } else { if (conditions=="skip-button") { - playlist.shift() + delete playlist[0] if (playlist.length==0){ document.getElementById("playlist-alert").innerHTML = "Nothing's Queued..." } } - for (i in playlist) { + for (let i in playlist) { + let fileName = Object.keys(playlist[i])[0] let newItem = document.createElement("div"); newItem.className = "item"; - newItem.id = playlist[i]["file"]; + newItem.id = fileName; let image = document.createElement("img"); try { - if (playlist[i]["art"] == null) { + if (playlist[i][fileName]["art"] == null) { throw "no image lolz" } - image.src = playlist[i]["art"]; + image.src = playlist[i][fileName]["art"]; } catch(err){ image.src = "./images/placeholder.png"; } - image.id = String(playlist[i]["file"])+" image"; + image.id = String(fileName)+" image"; let head3 = document.createElement("h3"); - head3.innerText = playlist[i]["title"]; + head3.innerText = playlist[i][fileName]["title"]; let head4 = document.createElement("h4"); - head4.innerText=playlist[i]["artist"]; + head4.innerText=playlist[i][fileName]["artist"]; let head5 = document.createElement("h5"); let timeLeft =document.createElement("h5"); timeLeft.style.fontWeight = 100; @@ -241,10 +240,10 @@ async function generateVisualPlaylist(conditions="") { if (i == 0) { head5.innerHTML="Playing"; if ((conditions != "skip-button")) { - let mins = Math.floor(playlist[i]["time"]/60); - let secs = Math.floor(playlist[i]["time"]%60); - let durMins = Math.floor(playlist[i]["length"]/60); - let durSecs = Math.floor(playlist[i]["length"]%60); + let mins = Math.floor(playlist[i][fileName]["time"]/60); + let secs = Math.floor(playlist[i][fileName]["time"]%60); + let durMins = Math.floor(playlist[i][fileName]["length"]/60); + let durSecs = Math.floor(playlist[i][fileName]["length"]%60); timeLeft.innerHTML = mins.toString() +":"+ secs.toLocaleString('en-US', {minimumIntegerDigits: 2,useGrouping: false}) + "/"+ durMins.toString()+":"+durSecs.toLocaleString('en-US', {minimumIntegerDigits: 2,useGrouping: false}); } } @@ -270,6 +269,7 @@ async function submitSong(songid) { } function checkWhatSongWasClicked(e) { itemId = e.srcElement.id; + console.log(itemId) if ((itemId.length-itemId.lastIndexOf("image") == 5) && itemId.lastIndexOf("image")!=-1) { itemId = itemId.slice(0,-6) } diff --git a/Server/webbyBits.py b/Server/webbyBits.py index 537542c..edc637c 100644 --- a/Server/webbyBits.py +++ b/Server/webbyBits.py @@ -4,12 +4,16 @@ from flask_cors import CORS import json,vlc,threading,time,random, argparse # Argparse Stuff parser=argparse.ArgumentParser(description="Options for the Webby Bits") -parser.add_argument('-d','--directory',help="Directory of the song files (make sure this matches the directory used for the databaseGenerator)", default="./sound/") +# this is no longer needed assuming my file works correctly with the generator +# parser.add_argument('-d','--directory',help="Directory of the song files (make sure this matches the directory used for the databaseGenerator)", default="./sound/") parser.add_argument('-p','--port',help="Port to host on, not the same as the web (client) port",default='19054') portTheUserPicked=parser.parse_args().port -soundLocation = parser.parse_args().directory -# To set the directory permenantly just uncomment the next line -# soundLocation = "/example/directory/here/" + +# open the json file as a dictionary +with open('./songDatabase.json', 'r') as handle: + songDatabaseList = json.load(handle) +soundLocation = songDatabaseList["songDirectory"] + if soundLocation[-1] == "/" or soundLocation[-1] == "\\": pass elif "/" in soundLocation: @@ -33,9 +37,6 @@ player.audio_set_volume(100) app = Flask(__name__) # because you are posting from another domain to this one, you need CORS CORS(app) -# open the json file as a dictionary -with open('./songDatabase.json', 'r') as handle: - songDatabaseList = json.load(handle) def queueSong(song): with playlistLock: @@ -116,16 +117,16 @@ def searchSongDB(): # the way i put the data in a list was really dumb looking back, i could and should have used a list of dictioaries like i was before # i might try to change it but this layout is embedded deep in the client tempData = {} - for i in songDatabaseList: - if ((i["title"].lower().find(recieveData['search'].lower())) > -1) or (recieveData['search'] == ""): - # In future i would change this to index based on the filename so that it is definately unique - tempData[i["title"]] = [i["artist"],i["art"],i["file"]] + for i in songDatabaseList["songData"]: + if ((songDatabaseList["songData"][i]["title"].lower().find(recieveData['search'].lower())) > -1) or (recieveData['search'] == ""): + tempData[i] = songDatabaseList["songData"][i] + try: - if (i["artist"].lower().find(recieveData['search'].lower()) > -1): - tempData[i["title"]] = [i["artist"],i["art"],i["file"]] + if (songDatabaseList["songData"][i]["artist"].lower().find(recieveData['search'].lower()) > -1): + tempData[i] = songDatabaseList["songData"][i] except: pass - + print(tempData) return tempData @app.route("/songadd", methods=["POST"]) @@ -137,26 +138,16 @@ def songadd(): def getPlaylist(): global songNext tempPlaylist = [] - # what went through my head to make past-me think this is a good idea??? - # i mean actually looping through once still shouldn't ever take that long - # but like a binary search must exist in python and be faster - # wait no binary search only helps if they're sorted - # i mean i guess i could sort them and make searching faster - for k in songDatabaseList: - if k["file"] == songNext: - temp = k.copy() - temp["playing"] = True - temp["time"] = player.get_time()/1000 - tempPlaylist.append(temp) + if songNext != None: + # Adds the currently playing song + k = songDatabaseList["songData"][songNext] + temp = k.copy() + temp["playing"] = True + temp["time"] = player.get_time()/1000 + tempPlaylist.append({songNext:temp}) for i in playlist: - # oh my goodness i did it again - # i seriously need to rewrite the databaseGenerator and this code - # wait isn't this literally useless code??? - # oh no the playlist only contains names - # i should really have used an object for this. - for j in songDatabaseList: - if j["file"] == i: - tempPlaylist.append(j) + tempPlaylist.append({i:songDatabaseList["songData"][i]}) + print(tempPlaylist) return tempPlaylist if __name__ == "__main__": From 03bb05955894d27f9905570eeee0ec9f772ee268 Mon Sep 17 00:00:00 2001 From: Kristy Fournier <124598538+kristy-fournier@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:34:28 -0500 Subject: [PATCH 4/6] Fixed the freaking bug in ordering i went from array, to json, to realising json can't have duplicates, to now converting the json back to an array (with the help of chatgpt D: ) Its fine though it works now --- Client/scripts.js | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Client/scripts.js b/Client/scripts.js index d52b8e6..497d58e 100644 --- a/Client/scripts.js +++ b/Client/scripts.js @@ -205,34 +205,41 @@ async function checkSettings(skipServer=false) { async function generateVisualPlaylist(conditions="") { document.getElementById("playlist").innerHTML = "

"; playlist = await getFromServer(null, "playlist"); + playlist = Object.values(playlist).map(obj => { + const filename = Object.keys(obj)[0]; // Get the filename + const songData = obj[filename]; // Get the song metadata + return { filename, ...songData }; // Merge filename with song data + }); + console.log(playlist) if (playlist.length==0){ document.getElementById("playlist-alert").innerHTML = "Nothing's Queued..." } else { if (conditions=="skip-button") { - delete playlist[0] + playlist.shift() if (playlist.length==0){ document.getElementById("playlist-alert").innerHTML = "Nothing's Queued..." } } for (let i in playlist) { - let fileName = Object.keys(playlist[i])[0] + console.log(i) + let fileName = playlist[i]["filename"] let newItem = document.createElement("div"); newItem.className = "item"; newItem.id = fileName; let image = document.createElement("img"); try { - if (playlist[i][fileName]["art"] == null) { + if (playlist[i]["art"] == null) { throw "no image lolz" } - image.src = playlist[i][fileName]["art"]; + image.src = playlist[i]["art"]; } catch(err){ image.src = "./images/placeholder.png"; } image.id = String(fileName)+" image"; let head3 = document.createElement("h3"); - head3.innerText = playlist[i][fileName]["title"]; + head3.innerText = playlist[i]["title"]; let head4 = document.createElement("h4"); - head4.innerText=playlist[i][fileName]["artist"]; + head4.innerText=playlist[i]["artist"]; let head5 = document.createElement("h5"); let timeLeft =document.createElement("h5"); timeLeft.style.fontWeight = 100; @@ -240,10 +247,10 @@ async function generateVisualPlaylist(conditions="") { if (i == 0) { head5.innerHTML="Playing"; if ((conditions != "skip-button")) { - let mins = Math.floor(playlist[i][fileName]["time"]/60); - let secs = Math.floor(playlist[i][fileName]["time"]%60); - let durMins = Math.floor(playlist[i][fileName]["length"]/60); - let durSecs = Math.floor(playlist[i][fileName]["length"]%60); + let mins = Math.floor(playlist[i]["time"]/60); + let secs = Math.floor(playlist[i]["time"]%60); + let durMins = Math.floor(playlist[i]["length"]/60); + let durSecs = Math.floor(playlist[i]["length"]%60); timeLeft.innerHTML = mins.toString() +":"+ secs.toLocaleString('en-US', {minimumIntegerDigits: 2,useGrouping: false}) + "/"+ durMins.toString()+":"+durSecs.toLocaleString('en-US', {minimumIntegerDigits: 2,useGrouping: false}); } } From b0c1fa979fc937709e6cf0dc88d41e2938cf0100 Mon Sep 17 00:00:00 2001 From: Kristy Fournier <124598538+kristy-fournier@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:37:32 -0500 Subject: [PATCH 5/6] removed some unnecesary console logs --- Client/scripts.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Client/scripts.js b/Client/scripts.js index 497d58e..fe09161 100644 --- a/Client/scripts.js +++ b/Client/scripts.js @@ -210,7 +210,6 @@ async function generateVisualPlaylist(conditions="") { const songData = obj[filename]; // Get the song metadata return { filename, ...songData }; // Merge filename with song data }); - console.log(playlist) if (playlist.length==0){ document.getElementById("playlist-alert").innerHTML = "Nothing's Queued..." } else { @@ -221,7 +220,6 @@ async function generateVisualPlaylist(conditions="") { } } for (let i in playlist) { - console.log(i) let fileName = playlist[i]["filename"] let newItem = document.createElement("div"); newItem.className = "item"; @@ -255,6 +253,7 @@ async function generateVisualPlaylist(conditions="") { } } }catch(err){ + // i dont know why there's a try catch here but i'm leaving it i dont want to break something console.log(err) } let textdiv = document.createElement("div") @@ -276,7 +275,6 @@ async function submitSong(songid) { } function checkWhatSongWasClicked(e) { itemId = e.srcElement.id; - console.log(itemId) if ((itemId.length-itemId.lastIndexOf("image") == 5) && itemId.lastIndexOf("image")!=-1) { itemId = itemId.slice(0,-6) } From 018fc7579dbf841d0866d64ac96e55a04ff8afa4 Mon Sep 17 00:00:00 2001 From: Kristy Fournier <124598538+kristy-fournier@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:50:14 -0500 Subject: [PATCH 6/6] changed some prints --- Server/webbyBits.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/webbyBits.py b/Server/webbyBits.py index edc637c..d645bb2 100644 --- a/Server/webbyBits.py +++ b/Server/webbyBits.py @@ -126,7 +126,7 @@ def searchSongDB(): tempData[i] = songDatabaseList["songData"][i] except: pass - print(tempData) + # print(tempData) return tempData @app.route("/songadd", methods=["POST"]) @@ -147,7 +147,7 @@ def getPlaylist(): tempPlaylist.append({songNext:temp}) for i in playlist: tempPlaylist.append({i:songDatabaseList["songData"][i]}) - print(tempPlaylist) + # print(tempPlaylist) return tempPlaylist if __name__ == "__main__":