Simplified scrobbler code

This commit is contained in:
Krateng 2018-11-29 13:43:45 +01:00
parent ce5e342212
commit 9bcd701287
6 changed files with 108 additions and 46 deletions

View File

@ -6,15 +6,15 @@ Simple self-hosted music scrobble database to create personal listening statisti
### Why not Last.fm / Libre.fm?
Maloja is self-hosted. You will always be able to access your data, and not have to trust anyone to provide an API for it. Your library is not synced with any public of official music database, so you can follow your own tagging schema or even group acts together for the purpose of artist charts (e.g. HyunA, 4Minute and Trouble Maker).
Maloja is self-hosted. You will always be able to access your data, and not have to trust anyone to provide an API for it. Your library is not synced with any public or official music database, so you can follow your own tagging schema or even group associated artists together in your charts.
### Why not GNU FM?
Maloja gets rid of all the extra stuff: social networking, radios, recommendations, etc. It only keeps track of your listening history and lets you analyze it. This focus on its core allow it to potentially implement much better database features. One example: Maloja supports multiple artists per track. This means artists like Laura Brehm who are often just "featuring" in the track title get a place in your charts, and collaborations between several of your favorite artists finally get credited to all participants.
Maloja gets rid of all the extra stuff: social networking, radios, recommendations, etc. It only keeps track of your listening history and lets you analyze it. This focus on its core allows it to potentially implement much better database features. One example: Maloja supports multiple artists per track. This means artists who are often just "featuring" in the track title get a place in your charts, and collaborations between several artists finally get credited to all participants.
### Why not use the established API?
Compatibility creates overhead effort. I only made this for myself, so I have no need to support lots of music players and scrobblers. Maloja has a significantly smaller API that allows it to be much simpler.
Compatibility creates overhead effort. I only made this for myself, so I have no need to support lots of music players and scrobblers. Maloja has a significantly smaller API that allows it to be much simpler and implement its additional features.
### Why Maloja?
@ -31,7 +31,11 @@ I wouldn't recommend it yet. But if you want to test Maloja, it's fairly easy:
1) Put it anywhere and start server.py
2) (Recommended) Put your server behind a reverse proxy for SSL encryption. Configure that proxy to rewrite /db/ requests to the database port. In nginx this would look as follows:
location / {
proxy_pass http://yoururl:42010;
}
location /db {
rewrite ^/db(.*)$ $1 break;
proxy_pass http://yoururl:12349;
proxy_pass http://yoururl:42011;
}

View File

@ -3,7 +3,7 @@ from cleanup import *
log = open(sys.argv[1])
outputlog = open(sys.argv[2],"a")
outputlog = open(sys.argv[2],"w")
c = CleanerAgent()

View File

@ -43,7 +43,7 @@ function party(tab) {
function onPlaybackUpdate(request,sender) {
//console.log("Got update from Plex Web!")
if (request.type == "stopPlayback" && currentlyPlaying) {
stopPlayback();
stopPlayback(request.artist,request.title);
}
else if (request.type == "startPlayback") {
startPlayback(request.artist,request.title,request.duration);
@ -60,6 +60,88 @@ var alreadyScrobbled = false;
function startPlayback(artist,title,seconds) {
// CASE 1: Resuming playback of previously played title
if (artist == currentArtist && title == currentTitle && !currentlyPlaying) {
console.log("Resuming playback")
// Already played full song
while (alreadyPlayed > currentLength) {
alreadyPlayed = alreadyPlayed - currentLength
scrobble(currentArtist,currentTitle,currentLength)
}
setUpdate()
currentlyPlaying = true
}
// CASE 2: New track is being played
else if (artist != currentArtist || title != currentTitle) {
//first inform ourselves that the previous track has now been stopped for good
stopPlayback(artist,title)
//then initialize new playback
console.log("New track")
setUpdate()
alreadyPlayed = 0
currentTitle = title
currentArtist = artist
currentLength = seconds
console.log(artist + " - " + title + " is playing!")
currentlyPlaying = true
}
}
// the artist and title arguments are not attributes of the track being stopped, but of the track active now
// they are here to recognize whether the playback has been paused or completely ended / replaced
function stopPlayback(artist,title) {
//CASE 1: Playback just paused OR CASE 2: Playback ended
if (currentlyPlaying) {
d = setUpdate()
alreadyPlayed = alreadyPlayed + d
console.log(d + " seconds played since last update, " + alreadyPlayed + " seconds played overall")
}
// Already played full song
while (alreadyPlayed > currentLength) {
alreadyPlayed = alreadyPlayed - currentLength
scrobble(currentArtist,currentTitle,currentLength)
}
currentlyPlaying = false
//ONLY CASE 2: Playback ended
if (artist != currentArtist || title != currentTitle) {
if (alreadyPlayed > currentLength / 2) {
scrobble(currentArtist,currentTitle,alreadyPlayed)
alreadyPlayed = 0
}
}
}
function ostopPlayback(artist,title) {
currentlyPlaying = false
console.log("Playback stopped!")
d = new Date()
t = Math.floor(d.getTime()/1000)
delta = t - lastUpdate
console.log("Since the last update, " + delta + " seconds of music have been played")
alreadyPlayed = alreadyPlayed + delta
console.log(alreadyPlayed + " seconds of this track have been played overall")
if ((alreadyPlayed > currentLength/2) && !alreadyScrobbled) {
console.log("Enough to scrobble: " + currentArtist + " - " + currentTitle)
scrobble(currentArtist,currentTitle)
alreadyScrobbled = true
}
}
function ostartPlayback(artist,title,seconds) {
console.log("Playback started!")
if (artist == currentArtist && title == currentTitle && !currentlyPlaying) {
@ -116,26 +198,21 @@ function startPlayback(artist,title,seconds) {
}
}
function stopPlayback() {
currentlyPlaying = false
console.log("Playback stopped!")
d = new Date()
t = Math.floor(d.getTime()/1000)
delta = t - lastUpdate
console.log("Since the last update, " + delta + " seconds of music have been played")
alreadyPlayed = alreadyPlayed + delta
console.log(alreadyPlayed + " seconds of this track have been played overall")
if ((alreadyPlayed > currentLength/2) && !alreadyScrobbled) {
console.log("Enough to scrobble: " + currentArtist + " - " + currentTitle)
scrobble(currentArtist,currentTitle)
alreadyScrobbled = true
}
}
function scrobble(artist,title) {
function scrobble(artist,title,seconds) {
console.log("Scrobbling " + artist + " - " + title + "; " + seconds + " seconds playtime")
artiststring = encodeURIComponent(artist)
titlestring = encodeURIComponent(title)
var xhttp = new XMLHttpRequest();
xhttp.open("GET","http://localhost:12345/db/newscrobble?artist=" + artiststring + "&title=" + titlestring,true);
xhttp.open("GET","http://localhost:42010/db/newscrobble?artist=" + artiststring + "&title=" + titlestring,true);
xhttp.send()
}
function setUpdate() {
d = new Date()
t = Math.floor(d.getTime()/1000)
delta = t - lastUpdate
lastUpdate = t
return delta
}

View File

@ -1,7 +1,7 @@
bar = document.querySelector("div[class*=PlayerControls]")
if (bar == null) {
console.log("Nothing playing right now!")
chrome.runtime.sendMessage({type:"stopPlayback"})
chrome.runtime.sendMessage({type:"stopPlayback",artist:"",title:""})
exit()
}
@ -15,7 +15,7 @@ durationSeconds = parseInt(duration.split(":")[0]) * 60 + parseInt(duration.spli
control = bar.querySelector("div[class*=PlayerControls-buttonGroupCenter] > button:nth-child(2)").getAttribute("title")
if (control == "Play") {
console.log("Not playing right now")
chrome.runtime.sendMessage({type:"stopPlayback"})
chrome.runtime.sendMessage({type:"stopPlayback",artist:artist,title:title})
//stopPlayback()
}
else if (control == "Pause") {

View File

@ -11,26 +11,7 @@
"background.js"
]
},
"content_scripts":
[
{
"matches":
[
"http://app.plex.tv/*",
"https://app.plex.tv/*"
],
"include_globs":
[
"http://plex.*",
"https://plex.*"
],
"js":
[
"contentScript.js"
]
}
],
"browser_action":
{

View File

@ -8,8 +8,8 @@ import sys
import signal
MAIN_PORT = 12345
DATABASE_PORT = 12349
MAIN_PORT = 42010
DATABASE_PORT = 42011
@route("")