Skip to content

Commit

Permalink
initial port of danielfm#65
Browse files Browse the repository at this point in the history
  • Loading branch information
echawk committed Feb 1, 2024
1 parent a847e34 commit 025cec8
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 71 deletions.
21 changes: 21 additions & 0 deletions smudge-api.el
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,19 @@ Call CALLBACK with the parsed JSON response."
"Return the owner id of the given playlist JSON object."
(smudge-api-get-item-id (gethash 'owner json)))

(defun smudge-api-get-song-art-url (song)
"Return the medium sized image url for a SONG."
(let* ((album (gethash 'album song))
(image (and album (nth 2 (gethash 'images album)))))
(and image (gethash 'url image))))

(defun smudge-api-get-playlist-art-url (playlist)
"Return the smallest possible image url for PLAYLIST (we only need 64x64 and it gets scaled)."
(let* ((images (gethash 'images playlist))
(image (and images
(or (nth 3 images) (nth 2 images) (first images)))))
(and image (gethash 'url image))))

(defun smudge-api-search (type query page callback)
"Search artists, albums, tracks or playlists.
Call CALLBACK with PAGE of items that match QUERY, depending on TYPE."
Expand Down Expand Up @@ -480,6 +493,14 @@ Call CALLBACK with results."
nil
callback)))

(defun smudge-api-album (album-id callback)
"Call CALLBACK with info for album with ALBUM-ID."
(smudge-api-call-async
"GET"
(format "/albums/%s" (url-hexify-string album-id))
nil
callback))

(defun smudge-api-album-tracks (album page callback)
"Call CALLBACK with PAGE of tracks for ALBUM."
(let ((album-id (smudge-api-get-item-id album))
Expand Down
78 changes: 78 additions & 0 deletions smudge-image.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
;;; smudge-image.el --- Smudge image support library -*- lexical-binding: t; -*-

;; Copyright (C) 2021 Jason Dufair

;;; Commentary:

;; This library implements methods that support image display for smudge

;;; Code:

(defcustom smudge-show-artwork t
"Whether to show artwork when searching for tracks."
:type 'boolean
:group 'smudge)

(defvar smudge-artwork-fetch-target-count 0)
(defvar smudge-artwork-fetch-count 0)

(defun smudge-image-increment-count ()
"Increment count of fetched (or the absence of) images. Handle redisplay."
(setq smudge-artwork-fetch-count (1+ smudge-artwork-fetch-count))
(when (= smudge-artwork-fetch-count smudge-artwork-fetch-target-count)
(setq inhibit-redisplay nil)))

(defun smudge-image-tabulated-list-print-entry (id cols)
"Insert a Tabulated List entry at point.
This implementation asynchronously inserts album images in the
table buffer after the rows are printed. It reimplements most of
the `tabulated-list-print-entry' function but depends on a url
being the first column's data. It does not print that url in the
column. ID is a Lisp object identifying the entry to print, and
COLS is a vector of column descriptors."
(let ((beg (point))
(x (max tabulated-list-padding 0))
(ncols (length tabulated-list-format))
(inhibit-read-only t)
(cb (current-buffer))
(image-url (aref cols 0)))
(if (> tabulated-list-padding 0)
(insert (make-string x ?\s)))
(if image-url
(url-retrieve image-url
(lambda (_)
(let ((img (create-image
(progn
(goto-char (point-min))
(re-search-forward "^$")
(forward-char)
(delete-region (point) (point-min))
(buffer-substring-no-properties (point-min) (point-max)))
nil t :width 64)))
;; kill the image data buffer. We have the data now
(kill-buffer)
;; switch to the table buffer
(set-buffer cb)
(let ((inhibit-read-only t))
(save-excursion
(goto-char beg)
(put-image img (point) "track image" 'left-margin)))
(smudge-image-increment-count))))
(smudge-image-increment-count))
(insert ?\s)
(let ((tabulated-list--near-rows ; Bind it if not bound yet (Bug#25506).
(or (bound-and-true-p tabulated-list--near-rows)
(list (or (tabulated-list-get-entry (point-at-bol 0))
cols)
cols))))
;; don't print the URL column
(dotimes (n (- ncols 1))
(setq x (tabulated-list-print-col (+ n 1) (aref cols (+ n 1)) x))))
(insert ?\n)
;; Ever so slightly faster than calling `put-text-property' twice.
(add-text-properties
beg (point)
`(tabulated-list-id ,id tabulated-list-entry ,cols))))

(provide 'smudge-image)
;;; smudge-image.el ends here
33 changes: 27 additions & 6 deletions smudge-playlist.el
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
(require 'smudge-api)
(require 'smudge-controller)
(require 'smudge-track)
(require 'smudge-image)

(defvar smudge-user-id)
(defvar smudge-current-page)
(defvar smudge-browse-message)
(defvar smudge-selected-playlist)
(defvar smudge-query)
(defvar smudge-artwork-fetch-target-count 0)
(defvar smudge-artwork-fetch-count 0)

(defvar smudge-playlist-search-mode-map
(let ((map (make-sparse-keymap)))
Expand Down Expand Up @@ -142,11 +145,13 @@
(defun smudge-playlist-set-list-format ()
"Configures the column data for the typical playlist view."
(setq tabulated-list-format
(vector `("Playlist Name" ,(- (window-width) 45) t)
'("Owner Id" 30 t)
'("# Tracks" 8 (lambda (row-1 row-2)
(< (smudge-api-get-playlist-track-count (car row-1))
(smudge-api-get-playlist-track-count (car row-2)))) :right-align t))))
(vector
`("" -1) ;; image url column - do not display
`("Playlist Name" ,(- (window-width) 45) t)
'("Owner Id" 30 t)
'("# Tracks" 8 (lambda (row-1 row-2)
(< (smudge-api-get-playlist-track-count (car row-1))
(smudge-api-get-playlist-track-count (car row-2)))) :right-align t))))

(defun smudge-playlist-search-print (playlists page)
"Append PLAYLISTS to PAGE of the current playlist view."
Expand All @@ -155,7 +160,8 @@
(let ((user-id (smudge-api-get-playlist-owner-id playlist))
(playlist-name (smudge-api-get-item-name playlist)))
(push (list playlist
(vector (cons playlist-name
(vector (if smudge-show-artwork (smudge-api-get-playlist-art-url playlist) "")
(cons playlist-name
(list 'face 'link
'follow-link t
'action `(lambda (_) (smudge-playlist-tracks))
Expand All @@ -167,6 +173,21 @@
'help-echo (format "Show %s's public playlists" user-id)))
(number-to-string (smudge-api-get-playlist-track-count playlist))))
entries)))
(setq tabulated-list-printer #'tabulated-list-print-entry)
(when smudge-show-artwork
(setq tabulated-list-printer #'smudge-image-tabulated-list-print-entry)
(setq smudge-artwork-fetch-target-count
(+ (length playlists) (if (eq 1 page) 0 (count-lines (point-min) (point-max)))))
(setq smudge-artwork-fetch-count 0)
(setq line-spacing 10)
(message "Fetching playlists...")
;; in case the fetch chokes somehow, don't lock up all of emacs forever
(run-at-time "3 sec" nil (lambda () (setq inhibit-redisplay nil)))
;; Undocumented function. Could be dangerous if there's a bug
(setq inhibit-redisplay t)
(message "inhibit-redisplay: %s" inhibit-redisplay)
(setq left-margin-width 6)
(set-window-buffer (selected-window) (current-buffer)))
(when (eq 1 page) (setq-local tabulated-list-entries nil))
(smudge-playlist-set-list-format)
(setq-local tabulated-list-entries (append tabulated-list-entries (nreverse entries)))
Expand Down
Loading

0 comments on commit 025cec8

Please sign in to comment.