From 02d490dbf84bdc098dab3d7e76f37663530ee2f4 Mon Sep 17 00:00:00 2001 From: Frederik Vanrenterghem Date: Wed, 19 Mar 2025 20:59:08 +0800 Subject: [PATCH] Add post about using Lisp to submit Listenbrainz listens. --- source/posts/lisp_listenbrainz.org | 48 ++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 source/posts/lisp_listenbrainz.org diff --git a/source/posts/lisp_listenbrainz.org b/source/posts/lisp_listenbrainz.org new file mode 100644 index 0000000..1e1fc30 --- /dev/null +++ b/source/posts/lisp_listenbrainz.org @@ -0,0 +1,48 @@ +#+date: <2025-01-25 Sat 23:50> +#+title: Using Lisp to submit listens. +#+filetags: :elisp:music:open_web:emacs: +#+OPTIONS: \n:t + +#+BEGIN_PREVIEW +~cum mortuis in lingua mortua~ + +Tracking music listening habits doesn't need to be hard. My local radio station [[https://rtrfm.com.au/][RTRFM]] publishes playlists for most of its shows (subject to the presenter's interest in doing so of course - most of them are volunteers after all). It's trivial to copy-paste these into [[https://www.gnu.org/software/emacs/][an Emacs Lisp interpreter]], making everything possible. + +A quick fork of [[http://git.vanrenterghem.biz/musicbrainz.git][listenbrainz.el]] and a few updates to its code later, we've got a tool to submit a playlist of a show we've listened to. In a Lisp dialect even, rumours of the language's demise notwithstanding. +#+END_PREVIEW + +First we adjust the time the tracks were originally aired to the time we're listening to the show - re-streaming is possible for some weeks after the original air date. + +#+BEGIN_SRC emacs-lisp + (setq starttime (date-to-time "Sat 25 Jan 2025 15:10")) +#+END_SRC + +We're grabbing the playlist from an org mode headline and put each line in a list (of course). + +#+BEGIN_SRC emacs-lisp + (setq playlist (let ((playlist + (save-excursion + (goto-char (search-forward "Playlist data" nil t)) + (let ((el (org-element-at-point-no-context))) + (split-string + (buffer-substring-no-properties + (org-element-property :contents-begin el) + (org-element-property :contents-end el)) + "\n"))))) + playlist)) +#+END_SRC + +And next we can parse and submit our listens. The data is provided in groups of 3 lines, with the first line the relative time in HH:MM after the show started, the second the track title and the third line the performer. I've included a basic rate limit of 30 calls per minute to not overload the ListenBrainz servers. + +#+BEGIN_SRC emacs-lisp + (while playlist + (let* ((songrelstart (split-string (pop playlist) ":")) + (starthour (string-to-number (pop songrelstart))) + (startminute (string-to-number (pop songrelstart))) + (songrelstartf (format-time-string "%F %R" (time-add starttime (* (+ (* starthour 60) startminute) 60)))) + (title (pop playlist)) + (performer (pop playlist))) + (progn + (listenbrainz-submit-historic-listen performer title (listenbrainz-timestamp (date-to-time songrelstartf))) + (sleep-for 2)))) +#+END_SRC -- 2.39.5