26 Sep 2021

# Listen to a random album and generate a log entry (all with Emacs, of course)

When I was young, and vinyl records were not a cool thing but just the usual thing, I used to sit down and listen to music. Actually, I used to listen to albums, which is a forgotten concept that has been replaced by playlists. Anyway.

The fact of just listening to music and not doing anything else has been a luxury for years, but two years ago, I decided that I would sit down and listen again to music with full attention. Unfortunately, I don't have my vinyl collection anymore. All my music has been digitized and lives in the hard disk drive of my laptop. This has the great advantage of being available everywhere I go.

I of course use Emacs as my media player. And I use EMMS because it was the only solution available when I started and I like it. EMMS allows to browse the available music by album, artist, song, etc. So, when I want to listen to an album, I can just do M-x emms-browse-by-album and choose one album. This is what the buffer with the albums looks like:

So for a couple of years I have had a weekly ritual, on Sunday afternoons, where I choose an album, put my comfortable headphones and listen to a full album, track by track, in the order they were defined by the artists. Then, I log the album to an org-mode file, so that I can keep track of what I listen.

The issue I have had is of course choosing what to listen to. One year in this new habit, I decided that I would choose the album randomly. So I started using M-: to type (random 1077)1, then M-x goto-line with the result of the random choice.

Of course, after several weeks, this became tedious and I had to automate it. I also decided that I did not want to write the log entry by hand. This is what I came up with:

(defun my/emms-play-random-album ()
"Play a random album from the EMMS music database.
Generate an org entry with album artist and listened date for my records."
(interactive)
(emms-browse-by-album)
(let ((nlines (count-lines (point-min) (point-max))))
(goto-line (random nlines))
(let* ((album (alist-get 'info-album  (emms-playlist-current-selected-track)))
(artist (alist-get 'info-artist (emms-playlist-current-selected-track)))
(org-entry
(format "* %s\n:PROPERTIES:\n:ARTIST: %s\n:LISTEN_DATE: %s\n:END:\n"
album artist (format-time-string "[%Y-%m-%d %a]"))))
(kill-new org-entry)
(message org-entry)))


The function is easy to understand. I start by opening the album browser. Then, I count the number of lines in the buffer, and jump to a random line. The call to (emms-browser-add-tracks-and-play) just does what it says. This is just automating what I was doing by hand, but calls the same commands I was using.

I am more proud of what follows, which allows me to generate the bit of org-mode text that I need for my logs. Here, I get the name of the album and the artist of the track that just started playing using the appropriate EMMS internal function. Then I format the string with an org headline containing the album title and a property drawer with the artist and the date. It looks like this:

* Undercover
:PROPERTIES:
:ARTIST: Rolling Stones, The
:LISTEN_DATE: [2021-09-26 Sun]
:END:


I don't automatically put the entry in the log file, because sometimes I play a random album without wanting to log it. What I do here is put the entry in the kill ring so I can yank it in the appropriate place. And I also display it in the echo area.

This is yet another example of how powerful living in Emacs is. You can bridge packages that were not designed to work together (here EMMS and org-mode) to automate things. In other operating systems, if the apps are not from the same vendor and that they have not foreseen to use them together, you can't do that.

Another nice thing here is that the EMMS buffer (the album list here, but it is the same with the playlists, or any other buffer) is just text, so you can move around as in any other buffer (with goto-line in this example).

Finally, being able to use any internal function or variable of a package (emms-playlist-current-selected-track in my case) is very handy. As always, in Emacs, everything (the code, the documentation, etc.) is always available for the users to do whatever they need.

## Footnotes:

1

yes I have that many albums