Commit d6b1adc454af
Changed files (1)
dots
config
emacs
dots/config/emacs/init.el
@@ -3440,11 +3440,11 @@ With \\[universal-argument] \\[universal-argument]: always prompt with completio
:commands (empv-subsonic-search
empv-subsonic-artists
empv-subsonic-albums
- empv-subsonic-playlists
empv-subsonic-songs)
:bind (("C-c M s" . empv-subsonic-search)
("C-c M a" . empv-subsonic-albums)
("C-c M P" . empv-subsonic-playlists)
+ ("C-c M R" . empv-subsonic-radios)
("C-c M SPC" . empv-toggle)
("C-c M i" . empv-display-current)
("C-c M n" . empv-playlist-next)
@@ -3516,7 +3516,59 @@ With \\[universal-argument] \\[universal-argument]: always prompt with completio
(interactive)
(empv--subsonic-request
"getPlaylists.view"
- (empv--subsonic-result-handler "Select playlist:"))))
+ (empv--subsonic-result-handler "Select playlist:")))
+
+ ;; Subsonic internet radio support
+ ;; Uses getInternetRadioStations Subsonic API endpoint.
+
+ (defun empv--subsonic-format-radio (cand)
+ "Format a Subsonic radio candidate for display."
+ (format "%s %s"
+ (propertize (alist-get 'name cand) 'face 'bold)
+ (propertize (or (alist-get 'homePageUrl cand) "") 'face 'italic)))
+
+ ;; Extend the formatter to handle radio kind
+ (advice-add 'empv--subsonic-format-candidate :around
+ (lambda (orig cand)
+ (if (eq (alist-get 'kind cand) 'radio)
+ (empv--with-text-properties
+ (empv--subsonic-format-radio cand)
+ :item cand)
+ (funcall orig cand))))
+
+ ;; Extend act-on-candidate to handle radio kind
+ ;; Radio stations have a direct streamUrl, no need to fetch sub-items
+ (advice-add 'empv--subsonic-act-on-candidate :around
+ (lambda (orig selected)
+ (if (eq (alist-get 'kind selected) 'radio)
+ (let ((url (alist-get 'streamUrl selected)))
+ (if url
+ (empv-play url)
+ (message "Radio '%s' has no stream URL" (alist-get 'name selected))))
+ (funcall orig selected))))
+
+ (defun empv-subsonic-radios ()
+ "List Subsonic internet radio stations and play selection."
+ (interactive)
+ (empv--subsonic-request
+ "getInternetRadioStations.view"
+ (lambda (response)
+ ;; empv's result-fields doesn't include internetRadioStation,
+ ;; so we extract manually from the raw response info.
+ (let* ((raw (alist-get 'internetRadioStation response))
+ (stations (mapcar (lambda (s)
+ (thread-first s
+ (map-insert 'kind 'radio)
+ (map-insert 'type 'subsonic)))
+ raw)))
+ (if stations
+ (empv--subsonic-act-on-candidate
+ (empv--completing-read-object
+ "Select radio:"
+ stations
+ :formatter #'empv--subsonic-format-candidate
+ :category 'empv-subsonic-item))
+ (message "No internet radio stations found")))))))
(use-package ready-player
:init