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__":