diff --git a/desktop/src/main/kotlin/com/github/wakingrufus/jamm/desktop/JfxMediaPlayerController.kt b/desktop/src/main/kotlin/com/github/wakingrufus/jamm/desktop/JfxMediaPlayerController.kt index 0e7b3aa..cf5dfe9 100644 --- a/desktop/src/main/kotlin/com/github/wakingrufus/jamm/desktop/JfxMediaPlayerController.kt +++ b/desktop/src/main/kotlin/com/github/wakingrufus/jamm/desktop/JfxMediaPlayerController.kt @@ -105,7 +105,7 @@ class JfxMediaPlayerController( private fun playNext() { queue.firstOrNull()?.also { track -> - if(!track.file.exists()){ + if (!track.file.exists()) { library.removeTrack(track) playNext() } @@ -147,6 +147,10 @@ class JfxMediaPlayerController( scrobbledProperty.set(false) GlobalScope.launch(Dispatchers.Default) { lastFm.value?.nowPlaying(track) + val lastFmCount = lastFm.value.getPlaycount(track) ?: 0 + if (lastFmCount > track.playCount) { + library.updatePlayCount(track, lastFmCount) + } } GlobalScope.launch(Dispatchers.JavaFx) { nowPlayingProperty.set(track) diff --git a/desktop/src/main/kotlin/com/github/wakingrufus/jamm/desktop/ObservableLibrary.kt b/desktop/src/main/kotlin/com/github/wakingrufus/jamm/desktop/ObservableLibrary.kt index 28ecf44..c73ed88 100644 --- a/desktop/src/main/kotlin/com/github/wakingrufus/jamm/desktop/ObservableLibrary.kt +++ b/desktop/src/main/kotlin/com/github/wakingrufus/jamm/desktop/ObservableLibrary.kt @@ -19,8 +19,8 @@ import org.jaudiotagger.audio.AudioFileIO import org.jaudiotagger.audio.mp3.MP3File import org.jaudiotagger.tag.FieldKey import org.jaudiotagger.tag.datatype.DataTypes -import org.jaudiotagger.tag.id3.* -import org.jaudiotagger.tag.id3.framebody.AbstractFrameBodyTextInfo +import org.jaudiotagger.tag.id3.ID3v23Frames +import org.jaudiotagger.tag.id3.ID3v23Tag import java.io.File import java.io.FileReader import java.io.FileWriter @@ -136,7 +136,11 @@ class ObservableLibrary(val rootDir: File) : Logging { } fun countPlay(track: Track) { - track.playCount++ + updatePlayCount(track, track.playCount + 1) + } + + fun updatePlayCount(track: Track, count: Int) { + track.playCount = count val audioFile = AudioFileIO.read(track.file) if (audioFile is MP3File) { if (audioFile.hasID3v2Tag()) { @@ -144,7 +148,7 @@ class ObservableLibrary(val rootDir: File) : Logging { val countFrame = v2tag.getFirstField(ID3v23Frames.FRAME_ID_V3_PLAY_COUNTER) ?: v2tag.createFrame(ID3v23Frames.FRAME_ID_V3_PLAY_COUNTER) val body = countFrame.body - body.setObjectValue(DataTypes.OBJ_NUMBER, track.playCount) + body.setObjectValue(DataTypes.OBJ_NUMBER, count) v2tag.setFrame(countFrame) AudioFileIO.write(audioFile) createCSVFile() diff --git a/desktop/src/main/kotlin/com/github/wakingrufus/jamm/lastfm/LastFmClient.kt b/desktop/src/main/kotlin/com/github/wakingrufus/jamm/lastfm/LastFmClient.kt index a7092c7..dc5cabd 100644 --- a/desktop/src/main/kotlin/com/github/wakingrufus/jamm/lastfm/LastFmClient.kt +++ b/desktop/src/main/kotlin/com/github/wakingrufus/jamm/lastfm/LastFmClient.kt @@ -1,14 +1,18 @@ package com.github.wakingrufus.jamm.lastfm import com.github.kittinunf.fuel.core.ResponseResultOf +import com.github.kittinunf.fuel.json.responseJson +import com.github.kittinunf.result.Result import com.github.wakingrufus.jamm.common.Track import com.github.wakingrufus.jamm.desktop.Logging +import com.github.wakingrufus.jamm.desktop.globalLogger import com.github.wakingrufus.jamm.desktop.logger import org.slf4j.Logger import java.nio.charset.StandardCharsets import java.time.Instant class LastFmClient(val sessionKey: String) : Logging { + var username: String? = null fun scrobble(time: Instant, track: Track) { val args = mutableListOf( "artist" to track.artist.name, @@ -45,6 +49,53 @@ class LastFmClient(val sessionKey: String) : Logging { it.logError(logger()) } } + + fun getUserName(): String? { + val result = signedPost("user.getInfo", sessionKey, emptyList()).responseJson() + return when (result.third) { + is Result.Success -> result.third.get().obj().getJSONObject("user").getString("name") + is Result.Failure -> { + globalLogger().warn(result.second.responseMessage) + globalLogger().warn(result.second.body().toByteArray().toString(StandardCharsets.UTF_8)) + null + } + } + } + + fun getPlaycount(track: Track): Int? { + if (username == null) { + username = getUserName() + logger().debug("user=$username") + } + val args = mutableListOf>() + username?.also { + args.add("username" to it) + } + args.add("artist" to track.artist.name) + args.add("track" to track.title) +// track.musicBrainzTrackId?.takeIf { it.isNotBlank() }.also { +// if (it != null) { +// args.add("mbid" to it) +// } else { +// args.add("artist" to track.artist.name) +// args.add("track" to track.title) +// } +// } + val result = unAuthedSignedCall("track.getInfo", args).responseJson() + return if (result.third is Result.Failure) { + globalLogger().warn(result.second.responseMessage) + globalLogger().warn(result.second.body().toByteArray().toString(StandardCharsets.UTF_8)) + null + } else { + val jsonObj = result.third.get().obj() + if (jsonObj.has("error")) { + logger().warn(result.third.get().obj().toString()) + null + } else { + result.third.get().obj().getJSONObject("track").getInt("userplaycount") + } + } + } } fun ResponseResultOf.logError(logger: Logger) {