aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Elmes <emms@repose.cx>2006-06-29 13:24:00 +0000
committerDamien Elmes <emms@repose.cx>2006-06-29 13:24:00 +0000
commit7636b83b39c4d020b6324bebccc7b62965369d3b (patch)
tree67ceb22bcc23beae17f5cb28d72d680218e7fd22
parent69abf5b78ac67197dfedc1f15c49eaaddbce297a (diff)
browser: cover display, compilation support,more
- added optional rendering of cover images in the browser and playlist (see http://repose.cx/dump/browser-images.png) - display artist name if browsing by album - add `emms-browser-get-track-field-function', which allows you to customise the way the browser sorts the cache into various albums, artists, etc. includes a function (not on by default) which finds the artist name by the directory, not tag info - this prevents making lots of top level artist entries for artists who only appear on a compilation darcs-hash:20060629132444-4e3e3-142af90538863a1f655494b24de89ef39ea2a4dc.gz
-rw-r--r--emms-browser.el168
1 files changed, 144 insertions, 24 deletions
diff --git a/emms-browser.el b/emms-browser.el
index 519b9e9..f468b73 100644
--- a/emms-browser.el
+++ b/emms-browser.el
@@ -97,6 +97,27 @@ are displayed. It is called with two arguments - track and type."
:group 'emms-browser
:type 'function)
+(defcustom emms-browser-get-track-field-function
+ 'emms-browser-get-track-field-simple
+ "*A function to get an element from a track.
+Change this to customize the way data is organized in the
+browser. For example,
+`emms-browser-get-track-field-use-directory-name' uses the
+directory name to determine the artist. This means that
+soundtracks, compilations and so on don't populate the artist
+view with lots of 1-track elements."
+ :group 'emms-browser
+ :type 'function)
+
+(defcustom emms-browser-covers
+ '("cover_small.jpg" "cover_med.jpg" "cover_large.jpg")
+ "*Control how cover images are found.
+Can be either a list of small, medium and large images (large
+currently not used), a function which takes a directory, and should
+return a path to the cover, or nil to turn off cover loading."
+ :group 'emms-browser
+ :type '(choice list function boolean))
+
(defcustom emms-browser-insert-track-function
'emms-browser-insert-track-standard
"*A function to insert a track into the playlist.
@@ -346,13 +367,37 @@ example function is `emms-browse-by-artist'."
(emms-browser-add-category "genre" 'info-genre)
(emms-browser-add-category "year" 'info-year)
+(defun emms-browser-get-track-field (track type)
+ "Return TYPE from TRACK.
+This can be customized to group different artists into one for
+compilations, etc."
+ (funcall emms-browser-get-track-field-function track type))
+
+(defun emms-browser-get-track-field-simple (track type)
+ (emms-track-get track type "misc"))
+
+(defun emms-browser-get-track-field-use-directory-name (track type)
+ (if (eq type 'info-artist)
+ (emms-browser-get-artist-from-path
+ track)
+ (emms-track-get track type "misc")))
+
+(defun emms-browser-get-artist-from-path (track)
+ (let* ((path (emms-track-get track 'name))
+ (dir (file-name-directory path))
+ (basedir
+ (file-name-nondirectory
+ (directory-file-name
+ (file-name-directory dir)))))
+ (car (split-string basedir " - "))))
+
(defun emms-browser-make-hash-by (type)
"Make a hash, mapping with TYPE, eg artist -> tracks."
(let ((hash (make-hash-table
:test emms-browser-comparison-test))
field existing-entry)
(maphash (lambda (path track)
- (setq field (emms-track-get track type "misc"))
+ (setq field (emms-browser-get-track-field track type))
(setq existing-entry (gethash field hash))
(if existing-entry
(puthash field (cons track existing-entry) hash)
@@ -381,13 +426,29 @@ example function is `emms-browse-by-artist'."
(defun emms-browser-insert-top-level-entry (name tracks type)
"Insert a single top level entry into the buffer."
(emms-browser-ensure-browser-buffer)
- (emms-with-inhibit-read-only-t
- (insert (emms-propertize
- name
- 'emms-browser-bdata
- (emms-browser-make-bdata-tree
- type 1 tracks)
- 'face 'emms-browser-tracks-face) "\n")))
+ (let ((bdata (emms-browser-make-bdata-tree
+ type 1 tracks)))
+ ;; this code duplication is ugly, but necessary at the moment
+ ;; because the top level data is stored differently
+ (emms-with-inhibit-read-only-t
+ (if (eq (emms-browser-bdata-type bdata) 'info-album)
+ (let ((cover (emms-browser-get-cover-from-album
+ bdata 'small)))
+ (when cover
+ (emms-browser-insert-cover cover))
+ ;; if the album is a top-level element, display the artist
+ ;; name, too
+ (insert name
+ " ("
+ (emms-browser-get-track-field (car tracks)
+ 'info-artist)
+ ")"))
+ (insert name))
+ (add-text-properties (line-beginning-position) (point)
+ (list
+ 'emms-browser-bdata bdata
+ 'face 'emms-browser-tracks-face))
+ (insert "\n"))))
;; --------------------------------------------------
;; Building a subitem tree
@@ -395,7 +456,7 @@ example function is `emms-browse-by-artist'."
(defun emms-browser-next-mapping-type (current-mapping)
"Return the next sensible mapping.
-Eg. if current-mapping is currently 'info-artist, return 'info-album."
+Eg. if CURRENT-MAPPING is currently 'info-artist, return 'info-album."
(cond
((eq current-mapping 'info-artist) 'info-album)
((eq current-mapping 'info-album) 'info-title)
@@ -500,7 +561,7 @@ LEVEL is the number of the sublevel the db item will be placed in."
Items with no metadata for TYPE will be placed in 'misc'"
(let (db key existing tracknum)
(dolist (track tracks)
- (setq key (emms-track-get track type "misc"))
+ (setq key (emms-browser-get-track-field track type))
(when (eq type 'info-title)
;; try and make every track unique
(setq tracknum (emms-browser-track-number track))
@@ -651,11 +712,18 @@ information."
(indent (emms-browser-make-indent-for-level level)))
(emms-with-inhibit-read-only-t
(insert
- (emms-propertize
- (concat indent name)
- 'emms-browser-bdata data-item
- 'face (emms-browser-face-from-level level))
- "\n"))))
+ indent)
+ (when (eq (emms-browser-bdata-type data-item) 'info-album)
+ (let ((cover (emms-browser-get-cover-from-album
+ data-item 'small)))
+ (when cover
+ (emms-browser-insert-cover cover))))
+ (insert name)
+ (add-text-properties (line-beginning-position) (point)
+ (list
+ 'emms-browser-bdata data-item
+ 'face (emms-browser-face-from-level level)))
+ (insert "\n"))))
(defun emms-browser-make-indent-for-level (level)
(make-string (* 2 (1- level)) ?\ ))
@@ -745,15 +813,25 @@ Stops at the next line at the same level, or EOF."
;; Dealing with the playlist (queuing songs, etc)
;; --------------------------------------------------
-(defun emms-browser-insert-playlist-group (type group level)
+(defun emms-browser-insert-playlist-group (type bdata level)
"Insert a group description into the playlist buffer.
Eg. [album] foo bar"
- (let ((short-type (substring (symbol-name type) 5)))
+ (let ((short-type (substring (symbol-name type) 5))
+ (group (emms-browser-bdata-name bdata))
+ cover)
(with-current-emms-playlist
(goto-char (point-max))
(insert
- (emms-browser-make-indent-for-level level)
- (format "[%s] %s\n" short-type group)))))
+ (emms-browser-make-indent-for-level level))
+ (if (eq type 'info-album)
+ (progn
+ (setq cover
+ (emms-browser-get-cover-from-album bdata 'medium))
+ (when cover
+ (emms-browser-insert-cover cover))
+ (insert " " group "\n"))
+ (insert
+ (format "[%s] %s\n" short-type group))))))
(defun emms-browser-insert-track (track name level)
"Insert a track into the playlist buffer, called NAME.
@@ -811,7 +889,7 @@ LEVEL is used to control indentation."
(unless (eq type 'info-title)
(emms-browser-insert-playlist-group
- type name level))
+ type bdata level))
(dolist (item (emms-browser-bdata-data bdata))
(if (not (eq type 'info-title))
@@ -929,6 +1007,10 @@ After expanding, jump to the currently marked entry."
(list 'emms-browser-mark))))
(message "No mark saved!"))))
+(defun emms-browser-goto-random ()
+ (interactive)
+ (goto-line (random (count-lines (point-min) (point-max)))))
+
;; --------------------------------------------------
;; Linked browser and playlist windows
;; --------------------------------------------------
@@ -1124,9 +1206,47 @@ included."
(interactive)
(emms-browser-search '(info-artist info-title info-album)))
-(defun emms-browser-goto-random ()
- (interactive)
- (goto-line (random (count-lines (point-min) (point-max)))))
+;; --------------------------------------------------
+;; Album covers
+;; --------------------------------------------------
-(provide 'emms-browser)
+(defun emms-browser-get-cover-from-album (bdata &optional size)
+ (assert (eq (emms-browser-bdata-type bdata) 'info-album))
+ (let* ((track1data (emms-browser-bdata-data bdata))
+ (track1 (car (emms-browser-bdata-data (car track1data))))
+ (path (emms-track-get track1 'name)))
+ (emms-browser-get-cover-from-path path size)))
+
+(defun emms-browser-get-cover-from-path (path &optional size)
+ "Return a cover filename, if it exists."
+ (unless size
+ (setq size 'medium))
+ (let ((cover
+ (cond
+ ((functionp emms-browser-covers)
+ (funcall emms-browser-covers path size))
+ ((listp emms-browser-covers)
+ (concat (file-name-directory path)
+ (cond
+ ((eq size 'small)
+ (nth 0 emms-browser-covers))
+ ((eq size 'medium)
+ (nth 1 emms-browser-covers))
+ ((eq size 'large)
+ (nth 2 emms-browser-covers))))))))
+ (when (file-readable-p cover)
+ cover)))
+
+(defun emms-browser-insert-cover (path)
+ (insert (emms-browser-make-cover path)))
+
+(defun emms-browser-make-cover (path)
+ (emms-propertize " "
+ 'display `(image
+ :type jpeg
+ :margin 5
+ :file ,path)
+ 'rear-nonsticky '(display)))
+
+ (provide 'emms-browser)
;;; emms-browser.el ends here