dotsong
- 11 Devlogs
- 26 Total hours
scrobble and share your music from anywhere to anywhere. show discord presence and scrobble to last.fm, libre.fm, and any listenbrainz-compatible scrobbler
scrobble and share your music from anywhere to anywhere. show discord presence and scrobble to last.fm, libre.fm, and any listenbrainz-compatible scrobbler
started rewriting the entire pipeline. main changes:
complete MediaCenter::process_event rewrite
rewritten completely from scratch. now takes up 40 less lines, skips invalid tracks earlier, and is much simpler to understand
ticking logic improvement
the app used to tick every 5 s to check track duration, which means 12/min. instead, i now calculate how far the 50% mark is and sleep for only that long; when we’re past it, it’ll just idle until the next track. the app now only wakes once per event, rather than 12 times/min
use unicase crate to avoid unnecessary allocationsmost of the String allocations i make in the program are to_lowercase() calls for comparisons. the unicase crate allows me to make case-insensitive comparisons without extra allocations.
all of this SHOULD mean less CPU and memory usage (i’m a bit obsessed with that, if you can’t tell yet), but i havent benched anything yet
this PR edits like 500 lines but there’s only like 20 lines more than there were originally lol
i had been initializing a whole new last.fm/libre.fm client on every now playing request/scrobble, which was unnecessary and clunky. so i now:
static CLIENT_POOL: LazyLock<DashMap<String, Client>> where the keys are the Scrobbler idsi’ve never used drop logic before but i think its like the coolest thing ever, so i was excuted about that
originally, i had written two completely separate track detection pipelines for macOS and windows/linux, but i realized that it resulted in a lot of redundant logic, and making changes to that logic required testing on both macOS and windows for things that shouldnt have (e.g. cover art uploading), so i decided to unify it into one processing pipeline, and the platform-specific parts are just getting it to be a MediaInfo type as soon as possible.
by the end of it, there were only 20 more lines than there were before, but there is now only one processing pipeline which is a huge help for implementing stuff in the future!
also, some more tangible things:
finally merged the cover art uploading feature! works on all platforms (linux is untested, but… we’ll get there)
fixed a really obnoxious bug i’ve been dealing with pretty much the whole time. on macOS apple music, when you pick a new track, it’ll broadcast a pause event and THEN a play event immediately after.
for whatever reason, pause events always LOSE the race against the play event, and therefore overwrite the play event. it probably has to do with deezer caching.
the fix was just short circuiting; check early if this is a pause event and we alr have the info; if so, dont worry about processing anything else
published another two versions today!
first update contained a lot of those optimization fixes from before, but the second one was me testing with a user on windows (i normally use macOS, so testing on windows isn’t the easiest)
now i’m doing testing on debian which is not working in any way at all </3
created a litterbox mock api with bun so i can test against image uploading against it
compliant-ish. enough that it only accepts valid parameters and returns realistic URL responses.
and its only 57 lines! i <3 bun forever
the source is here https://gist.github.com/thrzl/22cde52746d4febf2c513b7fc7b829eb
more subtle improvements
in this session, i removed some unnecessary ui elements (like a redundant separator and useless buttons)
the more interesting thing is i fixed a bug where i was loading stale states, which cause it to spam
now, i’m about to test AppImage builds, whenever i feel comfortable enough to put out another release
spent a LOT longer than 20 minutes trying to debug this weird memory leak that happens whenever i even ACCEPT image data on track events
i literally gain a whole 200 MB PER EVENT, an “event” being any time the track info doesn’t stay the same. so if you pause it, play it, or the track changes for any reason, that’s an event, and it stacks
so its totally unreasonable rn for me to get the images cus bro?? and i know its not in my code because i didn’t even add the handling yet i literally just accept the image data and it does that
so i just filed an issue in the upstream crate pray for me guys
today i was trying to implement scrobble retries but i ended up not liking the current shape. i was gonna write to a file and send scrobbles later next time the host succeeds, but that was super annoying to implement
i think i might end up trying a threads based approach where i just spawn a new thread whenever a scrobble fails; but that wouldnt handle network conditions as well.
i think ima take a break from that and look at getting image support working tomorrow. that needs me to fix the upstream media-remote crate to fix a memory leak, first and foremost; then i’d want to lazy load images cus 70 MB just for getting a track is absurd
lots of code cleanup
learned today that you can’t just use Arc<Mutex<...>> everywhere (well you can but its not necessarily a good thing) so i’m now using RwLock and ArcSwap which makes things a lot easier. i ended up changing tons of internal stuff in basically every file and still my PR only added like 30 something lines