Thu Jun 15 01:00:48 JST 2006 Damien Elmes <[EMAIL PROTECTED]> * browser: refactor data format, bugfixes; emms: add emms-track-p Subitems are now stored in a tree of "bdata" objects, which is generated when initially displaying the buffer. This makes rendering simpler and also fixes some bugs where tracks were not being sorted correctly in the browser and/or the playlist. Adding items to the playlist now inserts 'group' names when you add a whole album, artist, etc at a time. These names will be thrown away if you run emms-shuffle. The sorting routines will correctly sort the buffer, throwing away the group tags, but then throw an error because the buffer is not the size they expected it to be. Other playlist manipulation routines like next/previous should skip over the group names - if they don't, it's a bug in the playlist code. An example of the new interface is at: http://repose.cx/dump/emms-browser.png
New patches:
[browser: refactor data format, bugfixes; emms: add emms-track-p Damien Elmes <[EMAIL PROTECTED]>**20060614160048 Subitems are now stored in a tree of "bdata" objects, which is generated when initially displaying the buffer. This makes rendering simpler and also fixes some bugs where tracks were not being sorted correctly in the browser and/or the playlist. Adding items to the playlist now inserts 'group' names when you add a whole album, artist, etc at a time. These names will be thrown away if you run emms-shuffle. The sorting routines will correctly sort the buffer, throwing away the group tags, but then throw an error because the buffer is not the size they expected it to be. Other playlist manipulation routines like next/previous should skip over the group names - if they don't, it's a bug in the playlist code. An example of the new interface is at: http://repose.cx/dump/emms-browser.png ] { hunk ./emms-browser.el 55 -;; year. +;; year. These commands can also be used while smart browsing to +;; change the browsing category. hunk ./emms-browser.el 63 +;; Note this code is very new and is still prone to big changes in the +;; API and breakage. Bug reports are welcome. + hunk ./emms-browser.el 72 +(eval-when-compile + (require 'cl)) + hunk ./emms-browser.el 91 +(defcustom emms-browser-make-name-function + 'emms-browser-make-name-standard + "A function to make names for entries and subentries. +Overriding this function allows you to customise how various elements +are displayed. It is called with two arguments - track and type." + :group 'emms-browser + :type 'function) + +(defcustom emms-browser-insert-track-function + 'emms-browser-insert-track-standard + "A function to insert a track into the playlist. +The default behaviour indents tracks depending on whether you're +adding an album, artist, etc." + :group 'emms-browser + :type 'function) + hunk ./emms-browser.el 149 -(defvar emms-browser-current-mapping nil +(defvar emms-browser-top-level-hash nil hunk ./emms-browser.el 151 -(make-variable-buffer-local 'emms-browser-current-mapping) - -(defvar emms-browser-current-mapping-type nil - "The current mapping type, eg. 'info-artist") -(make-variable-buffer-local 'emms-browser-current-mapping-type) +(make-variable-buffer-local 'emms-browser-top-level-hash) hunk ./emms-browser.el 289 -;; Browsing methods - by artist/album/etc +;; Top-level browsing methods - by artist/album/etc hunk ./emms-browser.el 292 -(defmacro emms-browser-add-category (name track-type &optional expand-func) +;; Since the number of tracks may be rather large, we use a hash to +;; sort the top level elements into various categories. All +;; subelements will be stored in a bdata alist structure. + +(defmacro emms-browser-add-category (name type) hunk ./emms-browser.el 304 - (emms-browser-clear) - (rename-buffer ,modedesc) - (emms-browser-display-by ,track-type ,expand-func) - (goto-char (point-min))))) + (let ((hash (emms-browser-make-hash-by ,type))) + (emms-browser-clear) + (rename-buffer ,modedesc) + (emms-browser-render-hash hash ,type) + (setq emms-browser-top-level-hash hash) + (goto-char (point-min)))))) hunk ./emms-browser.el 311 -(emms-browser-add-category "artist" 'info-artist 'emms-browser-show-albums) -(emms-browser-add-category "album" 'info-album 'emms-browser-show-titles) -(emms-browser-add-category "genre" 'info-genre 'emms-browser-show-artists) -(emms-browser-add-category "year" 'info-year 'emms-browser-show-artists) +(emms-browser-add-category "artist" 'info-artist) +(emms-browser-add-category "album" 'info-album) +(emms-browser-add-category "genre" 'info-genre) +(emms-browser-add-category "year" 'info-year) hunk ./emms-browser.el 316 -(defun emms-browser-make-by (field-type) - "Make a mapping with FIELD-TYPE, eg artist -> tracks." - (let ((db (make-hash-table +(defun emms-browser-make-hash-by (type) + "Make a hash, mapping with TYPE, eg artist -> tracks." + (let ((hash (make-hash-table hunk ./emms-browser.el 322 - (setq field (emms-track-get track field-type "misc")) - (setq existing-entry (gethash field db)) + (setq field (emms-track-get track type "misc")) + (setq existing-entry (gethash field hash)) hunk ./emms-browser.el 325 - (puthash field (cons track existing-entry) db) - (puthash field (list track) db))) + (puthash field (cons track existing-entry) hash) + (puthash field (list track) hash))) hunk ./emms-browser.el 328 - db)) + hash)) hunk ./emms-browser.el 330 -(defun emms-browser-display-by (field-type &optional expand-func) - "Render a mapping into a browser buffer. -Optional EXPAND-FUNC is a function to call when expanding a -line." - (let ((db (emms-browser-make-by field-type))) - (maphash (lambda (desc data) - (emms-browser-insert-entry desc data expand-func)) - db) - ;; sort - (setq emms-browser-current-mapping db) - ;; FIXME: currently we use a hash for the 'level 1' information, - ;; and an alist for subinfo. that means that this sorting is done - ;; differently to subinfo.. - ;; should we use emms-browser-alpha-sort-function instead? - (emms-with-inhibit-read-only-t - (let ((sort-fold-case t)) - (sort-lines nil (point-min) (point-max)))))) +(defun emms-browser-render-hash (db type) + "Render a mapping (DB) into a browser buffer." + (maphash (lambda (desc data) + ;; reverse the entries so that unsorted tracks are displayed in + ;; ascending order + (emms-browser-insert-top-level-entry desc (nreverse data) type)) + db) + (emms-with-inhibit-read-only-t + (let ((sort-fold-case t)) + (sort-lines nil (point-min) (point-max))))) hunk ./emms-browser.el 350 +(defun emms-browser-insert-top-level-entry (entry 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 + entry + 'emms-browser-bdata + (emms-browser-make-bdata-tree + type 1 tracks) + 'face 'emms-browser-tracks-face) "\n"))) + hunk ./emms-browser.el 362 -;; Operations on individual lines +;; Building a subitem tree hunk ./emms-browser.el 365 -(defun emms-browser-insert-entry (entry tracks &optional expand-func) - "Add a single ENTRY -> TRACKS mapping to the buffer. -EXPAND-FUNC is an optional func to call when expanding a line." - (emms-browser-ensure-browser-buffer) - (emms-with-inhibit-read-only-t - (insert (emms-propertize entry - 'emms-browser-data tracks - 'emms-browser-level 1 - 'emms-browser-expand-func expand-func - 'face 'emms-browser-tracks-face) "\n"))) +(defun emms-browser-next-mapping-type (current-mapping) + "Return the next sensible mapping. +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) + ((eq current-mapping 'info-genre) 'info-artist) + ((eq current-mapping 'info-year) 'info-artist))) hunk ./emms-browser.el 374 -(defun emms-browser-add-tracks () - "Add all the tracks on the current line to the playlist." - (interactive) - (let ((tracks (emms-browser-data-at)) - (count 0) - old-max new-max type name) - (unless tracks - (error "No tracks on current line!")) - (with-current-emms-playlist - (setq old-max (point-max))) - ;; add each of the tracks +(defun emms-browser-make-bdata-tree (type level tracks) + "Build a tree of browser DB elements for tracks." + (emms-browser-make-bdata + (emms-browser-make-bdata-tree-recurse + type level tracks) + ;; with the current hash code, we're guaranteed to have only one + ;; element at the top + (emms-track-get (car tracks) type) + type level)) + +(defun emms-browser-make-bdata-tree-recurse (type level tracks) + "Build a tree of alists based on a list of tracks, TRACKS. +For example, if TYPE is 'info-year, return an alist like: +artist1 -> album1 -> *track* 1.." + (let* ((next-type (emms-browser-next-mapping-type type)) + (next-level (1+ level)) + alist name new-db new-tracks) + ;; if we're at a leaf, the db data is a list of tracks + (if (eq type 'info-title) + tracks + ;; otherwise, make DBs from the sub elements + (setq alist + (emms-browser-make-sorted-alist + next-type tracks)) + (mapcar (lambda (entry) + (setq name (emms-browser-make-name + entry next-type)) + (setq new-tracks (cdr entry)) + (emms-browser-make-bdata + (emms-browser-make-bdata-tree-recurse + next-type next-level new-tracks) + name next-type next-level)) + alist)))) + +(defun emms-browser-make-name (entry type) + "Return a name for ENTRY, used for making a bdata object. +This uses `emms-browser-make-name-function'" + ;; we use cadr because we are guaranteed only one track in entry. + (funcall emms-browser-make-name-function entry type)) + +(defun emms-browser-make-name-standard (entry type) + "Add track numbers to track names. +Apart from tracks, names are displayed without modification." + (if (eq type 'info-title) + (emms-browser-make-name-with-track-number (cadr entry)) + (car entry))) + +(defun emms-browser-make-name-with-track-number (track) + "Concat a track number to the name of track, if one exists." + (let ((tracknum (emms-track-get track 'info-tracknumber))) + (concat + (if (string= tracknum "0") + "" + (concat + (if (eq (length tracknum) 1) + (concat "0" tracknum) + tracknum) + ". ")) + (emms-track-get track 'info-title)))) + +(defun emms-browser-make-bdata (data name type level) + "Return a browser data item from ALIST. +DATA should be a list of DB items, or a list of tracks. +NAME is a name for the DB item. +TYPE is a category the data is organised by, such as 'info-artist. +LEVEL is the number of the sublevel the db item will be placed in." + (list (cons 'type type) + (cons 'level level) + (cons 'name name) + (cons 'data data))) + +(defun emms-browser-make-alist (type tracks) + "Make an alist mapping of TYPE -> TRACKS. +Items with no metadata for TYPE will be placed in 'misc'" + (let (db key existing) hunk ./emms-browser.el 450 - (setq type (emms-track-get track 'type)) - (setq name (emms-track-get track 'name)) - (cond - ((eq type 'file) - (emms-add-file name)) - ((eq type 'url) - (emms-add-url name))) - (setq count (1+ count))) - (run-mode-hooks 'emms-browser-tracks-added-hook) - (message "Added %d tracks." count))) + (setq key (emms-track-get track type "misc")) + (setq existing (assoc key db)) + (if existing + (setcdr existing (cons track (cdr existing))) + (push (cons key (list track)) db))) + ;; sort the entries we've built + (dolist (item db) + (setcdr item (nreverse (cdr item)))) + db)) hunk ./emms-browser.el 460 -(defun emms-browser-add-tracks-and-play () - "Add all the tracks on the current line, play the first file." - (interactive) - (let (old-pos) - (with-current-emms-playlist - (setq old-pos (point-max))) - (emms-browser-add-tracks) - (with-current-emms-playlist - (goto-char old-pos) - (emms-playlist-select (point))) - ;; FIXME: is there a better way of doing this? - (emms-stop) - (emms-start))) +(defun emms-browser-make-sorted-alist (type tracks) + "Return a sorted alist of TRACKS. +TYPE is the metadata to make the alist by - eg. if it's +'info-artist, an alist of artists will be made." + (emms-browser-sort-alist + (emms-browser-make-alist type tracks) + type)) hunk ./emms-browser.el 468 -(defun emms-browser-data-at (&optional pos) - "Return the tracks at POS (point if not given), or nil if none." - (emms-browser-ensure-browser-buffer) - (save-excursion - ;; move the point to the start of the line, since the trailing new - ;; line is not propertized - (move-beginning-of-line nil) - (emms-with-widened-buffer - (get-text-property (or pos (point)) - 'emms-browser-data)))) +;; -------------------------------------------------- +;; BDATA accessors and predicates +;; -------------------------------------------------- hunk ./emms-browser.el 472 -(defun emms-isearch-buffer () - "Isearch through the buffer." - (interactive) - (goto-char (point-min)) - (when (isearch-forward) - (unless (emms-browser-subitems-visible) - (emms-browser-show-subitems) - (next-line)))) +(defun emms-browser-bdata-level (bdata) + (cdr (assq 'level bdata))) + +(defun emms-browser-bdata-name (bdata) + (cdr (assq 'name bdata))) + +(defun emms-browser-bdata-type (bdata) + (cdr (assq 'type bdata))) + +(defun emms-browser-bdata-data (bdata) + (cdr (assq 'data bdata))) + +(defun emms-browser-bdata-p (obj) + "True if obj is a BDATA object." + (consp (assq 'data obj))) hunk ./emms-browser.el 489 -;; Expansion/subitem support (experimental) +;; Sorting expanded entries hunk ./emms-browser.el 492 -(defmacro emms-browser-add-show-category (name field-type &optional - expand-func sort-func) - "Create an interactive function emms-browser-show-FIELD-TYPE. -EXPAND-FUNC is used to further expand subitems if not already -expanded. -SORT-FUNC is called to sort retrieved data." - (let ((fname (intern (concat "emms-browser-show-" name))) - (fdesc (concat "Show " name " under current line"))) - `(defun ,fname () - ,fdesc - (interactive) - (unless (emms-browser-subitems-visible) - (let ((data (emms-browser-make-alist-from-field - ,field-type - (emms-browser-data-at)))) - (when ,sort-func - (setq data (funcall ,sort-func data))) - (emms-browser-insert-subitems data ,expand-func)))))) +(defmacro emms-browser-sort-cadr (sort-func) + "Return a function to sort an alist using SORT-FUNC. +This sorting predicate will compare the cadr of each entry. +SORT-FUNC should be a playlist sorting predicate like +`emms-playlist-sort-by-natural-order'." + `(lambda (a b) + (funcall ,sort-func (cadr a) (cadr b)))) hunk ./emms-browser.el 500 -;; -;; create emms-browser-show-* -;; -(emms-browser-add-show-category - "albums" 'info-album - 'emms-browser-show-titles - 'emms-browser-sort-by-name) +(defmacro emms-browser-sort-car (sort-func) + "Return a function to sort an alist using SORT-FUNC. +This sorting predicate will compare the car of each entry. +SORT-FUNC should be a playlist sorting predicate like +`emms-playlist-sort-by-natural-order'." + `(lambda (a b) + (funcall ,sort-func (car a) (car b)))) hunk ./emms-browser.el 508 -(emms-browser-add-show-category - "artists" 'info-artist - 'emms-browser-show-albums - 'emms-browser-sort-by-name) +(defun emms-browser-sort-by-track (alist) + "Sort an ALIST by the tracks in each entry. +Uses `emms-browser-track-sort-function'." + (if emms-browser-track-sort-function + (sort alist (emms-browser-sort-cadr + emms-browser-track-sort-function)) + alist)) hunk ./emms-browser.el 516 -(emms-browser-add-show-category - "titles" 'info-title - nil - 'emms-browser-sort-by-tracks) +(defun emms-browser-sort-by-name (alist) + "Sort ALIST by keys alphabetically. +Uses `emms-browser-alpha-sort-function'." + (if emms-browser-alpha-sort-function + (sort alist (emms-browser-sort-car + emms-browser-alpha-sort-function)) + alist)) + +(defun emms-browser-sort-alist (alist type) + "Sort ALIST using the sorting function for TYPE." + (let ((sort-func + (cond + ((or + (eq type 'info-album) + (eq type 'info-artist) + (eq type 'info-year) + (eq type 'info-genre)) + 'emms-browser-sort-by-name) + ((eq type 'info-title) + 'emms-browser-sort-by-track) + (t (message "Can't sort unknown mapping!"))))) + (funcall sort-func alist))) + +;; -------------------------------------------------- +;; Subitem operations on the buffer +;; -------------------------------------------------- + +(defun emms-browser-bdata-at-point () + "Return the bdata object at point. +Includes information at point (such as album name), and metadata." + (get-text-property (line-beginning-position) + 'emms-browser-bdata)) + +(defun emms-browser-data-at-point () + "Return the data stored under point. +This will be a list of DB items." + (emms-browser-bdata-data (emms-browser-bdata-at-point))) hunk ./emms-browser.el 555 - "Return the current level at point. -Actually this function returns the value of the first character -on the line, because if point is on a trailing \n it will fail. -Returns 0 if the current line is not an entry." - (let ((val - (get-text-property (line-beginning-position) - 'emms-browser-level))) - (if val - val - 0))) + "Return the current level at point." + (emms-browser-bdata-level (emms-browser-bdata-at-point))) + +(defun emms-browser-expand-one-level () + "Expand the current line by one sublevel." + (interactive) + (let* ((data (emms-browser-data-at-point))) + (save-excursion + (next-line) + (beginning-of-line) + (dolist (data-item data) + (emms-browser-insert-data-item data-item))))) + +(defun emms-browser-insert-data-item (data-item) + "Insert DATA-ITEM into the buffer. +This checks DATA-ITEM's level to determine how much to indent. +The line will have a property emms-browser-bdata storing subitem +information." + (let* ((level (emms-browser-bdata-level data-item)) + (name (emms-browser-bdata-name data-item)) + (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")))) + +(defun emms-browser-make-indent-for-level (level) + (make-string (* 2 (1- level)) ?\ )) + +(defun emms-browser-face-from-level (level) + "Return a face appropriate for LEVEL." + (intern + (concat "emms-browser-tracks-sub-face-" + (int-to-string (1- level))))) hunk ./emms-browser.el 599 - (re-search-forward "\n" nil t) - (if (> (emms-browser-level-at-point) level) + (forward-line 1) + (setq level-at-point (emms-browser-level-at-point)) + (if (and level-at-point + (> level-at-point level)) hunk ./emms-browser.el 608 - "True if there are any subentries under point." + "True if there are any subentries visible point." hunk ./emms-browser.el 616 +(defun emms-browser-subitems-exist () + "True if it's possible to expand the current line." + (not (eq (emms-browser-bdata-type + (emms-browser-bdata-at-point)) + 'info-title))) + +(defun emms-browser-move-up-level () + "Move up one level if possible. +Return true if we were able to move up." + (let ((moved nil) + (continue t) + (current-level (emms-browser-level-at-point))) + (while (and + continue + (zerop (forward-line -1))) + (when (> current-level (emms-browser-level-at-point)) + (setq moved t) + (setq continue nil))) + moved)) + hunk ./emms-browser.el 641 - (emms-browser-show-subitems))) + (if (emms-browser-subitems-exist) + (emms-browser-show-subitems) + (assert (emms-browser-move-up-level)) + (emms-browser-kill-subitems)))) hunk ./emms-browser.el 648 - (let ((func (get-text-property (line-beginning-position) - 'emms-browser-expand-func))) - (if func - (funcall func) - (message "Can't expand further!")))) + (emms-browser-expand-one-level)) hunk ./emms-browser.el 654 - (kill-whole-line t)) - (save-excursion - (emms-with-inhibit-read-only-t - (while (emms-browser-find-entry-more-than-level current-level) - (kill-line) - (previous-line)))))) - -(defun emms-browser-insert-subitems (subitems &optional expand-func) - "Insert SUBITEMS under the current item. -SUBITEMS is a list of cons cells (desc . data). -emms-browser-level will be set to 1 more than the current level. -Don't add anything if there are already subitems below." - (let ((new-level (1+ (emms-browser-level-at-point))) - desc data) - (save-excursion - (next-line) - (beginning-of-line) - (emms-with-inhibit-read-only-t - (dolist (item subitems) - (setq desc (car item)) - (setq data (cdr item)) - (insert - (emms-propertize (concat (make-string (* 2 (1- new-level)) ?\ ) desc) - 'emms-browser-data data - 'emms-browser-level new-level - 'emms-browser-expand-func expand-func - 'face - (intern - (concat - "emms-browser-tracks-sub-face-" - (int-to-string - (1- new-level))))) - "\n")))))) + (next-line (line-beginning-position 2))) + (emms-with-inhibit-read-only-t + (delete-region next-line + (save-excursion + (while + (emms-browser-find-entry-more-than-level + current-level)) + (line-beginning-position 2)))))) hunk ./emms-browser.el 663 -(defun emms-browser-make-alist-from-field (field-type tracks) - "Make an alist mapping of FIELD-TYPE -> TRACKS. -Items with no metadata for FIELD-TYPE will be placed in 'misc'" - (let (db key existing) - (dolist (track tracks) - (setq key (emms-track-get track field-type "misc")) - (setq existing (assoc key db)) - (if existing - (setcdr existing (cons track (cdr existing))) - (push (cons key (list track)) db))) - db)) hunk ./emms-browser.el 665 -;; Sorting expanded entries +;; Dealing with the playlist (queuing songs, etc) hunk ./emms-browser.el 668 -(defmacro emms-browser-sort-cadr (sort-func) - "Return a function to sort an alist using SORT-FUNC. -This sorting predicate will compare the cadr of each entry. -SORT-FUNC should be a playlist sorting predicate like -`emms-playlist-sort-by-natural-order'." - `(lambda (a b) - (funcall ,sort-func (cadr a) (cadr b)))) +(defun emms-browser-insert-playlist-group (type group level) + "Insert a group description into the playlist buffer. +Eg. [album] foo bar" + (let ((short-type (substring (symbol-name type) 5))) + (with-current-emms-playlist + (goto-char (point-max)) + (insert + (emms-browser-make-indent-for-level level) + (format "[%s] %s\n" short-type group))))) hunk ./emms-browser.el 678 -(defmacro emms-browser-sort-car (sort-func) - "Return a function to sort an alist using SORT-FUNC. -This sorting predicate will compare the car of each entry. -SORT-FUNC should be a playlist sorting predicate like -`emms-playlist-sort-by-natural-order'." - `(lambda (a b) - (funcall ,sort-func (car a) (car b)))) +(defun emms-browser-insert-track (track name level) + "Insert a track into the playlist buffer, called NAME. +LEVEL is used to control indentation." + (funcall emms-browser-insert-track-function track name level)) hunk ./emms-browser.el 683 -(defun emms-browser-sort-by-tracks (data) - "Sort an alist DATA by the tracks in each entry. -Uses `emms-browser-track-sort-function'." - (if emms-browser-track-sort-function - (sort data (emms-browser-sort-cadr - emms-browser-track-sort-function)) - data)) +(defun emms-browser-insert-track-standard (track name level) + (with-current-emms-playlist + (goto-char (point-max)) + (insert (emms-propertize + (concat + (emms-browser-make-indent-for-level level) + name) + 'face 'emms-playlist-track-face + 'emms-track track) + "\n"))) hunk ./emms-browser.el 694 -(defun emms-browser-sort-by-name (data) - "Sort an alist DATA by keys. -Uses `emms-browser-alpha-sort-function'." - (if emms-browser-alpha-sort-function - (sort data (emms-browser-sort-car - emms-browser-alpha-sort-function)) - data)) +(defun emms-browser-add-tracks () + "Add all tracks at point." + (interactive) + (let ((bdata (emms-browser-bdata-at-point))) + (emms-browser-add-bdata-to-playlist + bdata (emms-browser-bdata-level bdata))) + (run-hooks 'emms-browser-tracks-added-hook)) + +(defun emms-browser-add-tracks-and-play () + "Add all tracks at point, and play the first added track." + (interactive) + (let (old-pos) + (with-current-emms-playlist + (setq old-pos (point-max))) + (emms-browser-add-tracks) + (with-current-emms-playlist + (goto-char old-pos) + (emms-playlist-next) + (emms-playlist-select (point))) + ;; FIXME: is there a better way of doing this? + (emms-stop) + (emms-start))) + +(defun emms-browser-add-bdata-to-playlist (bdata starting-level) + "Add all tracks in BDATA to the playlist." + (let ((type (emms-browser-bdata-type bdata)) + (name (emms-browser-bdata-name bdata)) + (level (emms-browser-bdata-level bdata))) + + ;; adjust the indentation relative to the starting level + (when starting-level + (setq level (- level (1- starting-level)))) + + (unless (eq type 'info-title) + (emms-browser-insert-playlist-group + type name level)) + + (dolist (item (emms-browser-bdata-data bdata)) + (if (not (eq type 'info-title)) + (emms-browser-add-bdata-to-playlist item starting-level) + ;; add full track name as there may not be enough context + (setq name (concat (emms-track-get item 'info-artist) + " - " + ;; track numbers don't make much sense + ;; for individual files + (or (and (> level 1) + name) + (emms-track-get item 'info-title)))) + (emms-browser-insert-track + item name level))))) + +(defun emms-isearch-buffer () + "Isearch through the buffer." + (interactive) + (goto-char (point-min)) + (when (isearch-forward) + (unless (emms-browser-subitems-visible) + (emms-browser-show-subitems)))) hunk ./emms-browser.el 754 -;; Linked browser and playlist windows (experimental) +;; Linked browser and playlist windows hunk ./emms-browser.el 866 -;(defun emms hunk ./emms.el 506 + +(defun emms-track-p (obj) + "True if OBJ is an emms track." + (and (listp obj) + (eq (car obj) '*track*))) } Context: [emms-lyrics.el: Fix file-exists-p error when finding lyrics file for [EMAIL PROTECTED] streams. At present, will just take care of tracks with 'file type. ] [added the section "Finding files and speed" to the manual [EMAIL PROTECTED] [fix bug in emms-playlist-mode-center-current [EMAIL PROTECTED] [removed superfluous comment (actually testing darcs send) [EMAIL PROTECTED] [debian: add changelog for 2.0-2 [EMAIL PROTECTED] [debian: Install info file as well [EMAIL PROTECTED] [browser: sorting, bugfixes Damien Elmes <[EMAIL PROTECTED]>**20060612051800 - add sorting for subitems (albums, tracks, etc) - make isearching expand the current entry automatically - rename subitems-exist to subitems-visible (clearer) ] [updated manual about emms-foobar-file prefix toggling [EMAIL PROTECTED] [emms-cache: add pruning support, make save/load interactive Damien Elmes <[EMAIL PROTECTED]>**20060611095400] [Use better exclude regexp, so that people can load music files with '#' in the middle of the name. Michael Olson <[EMAIL PROTECTED]>**20060610230507] [emms-info: Never return 0 for info-mtime, since emms-time-less-p does not like this. Use nil instead. Michael Olson <[EMAIL PROTECTED]>**20060610230409] [Add mpd volume settings to custom Martin Schoenmakers <[EMAIL PROTECTED]>**20060609231150 Small patchlet so mpd users can use custom to change the volume setting backend to use the appropriate volume functions. ] [browse subcategories (eg artist->album->title) Damien Elmes <[EMAIL PROTECTED]>**20060609185950 - subcategories can now be expanded and contracted, and added to playlist - see the new keybindings at the top of the file - add new faces for the various sublevels (only the dark background colours are useful at the moment - any light background users want to fix that?) - fix a bug in emms-smart-browse with (recenter) ] [update emms-cache.el commentary Damien Elmes <[EMAIL PROTECTED]>**20060609064935] [emms-player-mpd: Add functionality to dump MusicPD data into the EMMS cache. This allows for easy integration with emms-browser.el. Michael Olson <[EMAIL PROTECTED]>**20060609043831] [emms-player-mpd: Rename volume functions to better match the namespace created by emms-volume.el. Michael Olson <[EMAIL PROTECTED]>**20060609043643] [emms-player-mpd: Fix minor bug when importing the current MusicPD playlist into EMMS. Michael Olson <[EMAIL PROTECTED]>**20060609043538] [emms-setup: Get rid of pointless compiler warning. Michael Olson <[EMAIL PROTECTED]>**20060609042002] [emms-cache: Small compiler fix. Michael Olson <[EMAIL PROTECTED]>**20060609041606] [emms-cache: Add standard enable/disable/toggle interface and do a docfix for emms-cache-set-function. Michael Olson <[EMAIL PROTECTED]>**20060609040108] [Standardize copyright notices. Add COPYING file. Mention license in README. Michael Olson <[EMAIL PROTECTED]>**20060608194123] [Fix compiler warnings in emms-cache.el. Michael Olson <[EMAIL PROTECTED]>**20060608184612] [emms-metaplaylist-mode: Fix bug introduced by the recent emms-playlist-mode overhaul. Add faces for light backgrounds. Michael Olson <[EMAIL PROTECTED]>**20060608143846] [NEWS is new [EMAIL PROTECTED] [emms-playlist-mode: Facify tracks on startup. [EMAIL PROTECTED] [refactor browser mode creation code Damien Elmes <[EMAIL PROTECTED]>**20060608123618 - make the rendering function (browse-by-artist, etc) responsible for the mode name - fix a bug where the wrong buffer is used ] [browser sorting, and bug fixes Damien Elmes <[EMAIL PROTECTED]>**20060608105253 - sort tracks when they're added to the playlist - fix a bug where we didn't uniquify the buffer - distinguish between files and urls - modify emms-playlist-sort to accept an optional region ] [update modeline when changing browsing method Damien Elmes <[EMAIL PROTECTED]>**20060608094037] [avoid rebuilding the browser window each time Damien Elmes <[EMAIL PROTECTED]>**20060608092623] [fix RET on trailing \n Damien Elmes <[EMAIL PROTECTED]>**20060608090703 \n isn't propertized which means hitting RET on a playlist or browser entry fails. this patch moves the point before trying to read the properties. ] [add a metadata browser - emms-browser.el Damien Elmes <[EMAIL PROTECTED]>**20060608084400 * preliminary work on a metadata browser - still alpha, but it's useable for me * also updated my email address in emms-cache.el (whoops) ] [small typo fix Damien Elmes <[EMAIL PROTECTED]>**20060608032546] [emms.el: Change directory to / before starting the player. [EMAIL PROTECTED] [emms-playlist-mode: When making new overlays, do not allow the rear to advance. This prevents some display issues. If we really need to modify the text there, we should be using (insert-before-markers). Michael Olson <[EMAIL PROTECTED]>**20060607215212] [Make emms-property-region bulletproof. Michael Olson <[EMAIL PROTECTED]>**20060607215113] [Fix typo in emms-property-region [EMAIL PROTECTED] [emms.el, simplified emms-property-region considerably. [EMAIL PROTECTED] [Very basic support for recording the time you last played a track. [EMAIL PROTECTED] * emms-last-played.el: New file. Nothing fancy right now, more to come soon. * emms-setup.el: emms-devel now requires and setups emms-last-played. ] [Mark the cache as dirty for each modification. [EMAIL PROTECTED] [emms.el: The currently playing marker now should stay where it is, even for yanks [EMAIL PROTECTED] [emms-playlist-mode: Stop overlay from being attached to text inserted before it [EMAIL PROTECTED] [fix damien elmes's email address Damien Elmes <[EMAIL PROTECTED]>**20060607154000] [emms sources now switch add/play behavior when a prefix argument is supplied. [EMAIL PROTECTED] [Add autoloads to emms-setup.el [EMAIL PROTECTED] [Typo, defvar => defcustom for emms-cache-set-function [EMAIL PROTECTED] [Cleaned up the cached code in emms.el a bit [EMAIL PROTECTED] [refactor caching code into emms-cache.el Damien Elmes <[EMAIL PROTECTED]>**20060607125345 * caching support is now provided via two function vars in emms.el, emms-cache-get-function and emms-cache-set-function * (emms-standard) or above will enable caching support * you'll need to remove .emms-cache or s/emms-info-cache/emms-cache-db/ ] [emms-info: Fix bug that occurs after clearing the current playlist and trying to re-add songs to it. Michael Olson <[EMAIL PROTECTED]>**20060606144439] [emms-playlist-mode doesn't need overlay compatibility anymore [EMAIL PROTECTED] [emms-playlist-mode.el - now with less overlay! [EMAIL PROTECTED] [AUTHORS: fixed Lucas' e-mail address [EMAIL PROTECTED] [AUTHORS: Damien Elmes address updated [EMAIL PROTECTED] [info-cache-dirty/coding Damien Elmes <[EMAIL PROTECTED]>**20060605163339 * mark the info cache as dirty when it's modified, so we don't have to write it out all the time * save the cache as mule-utf-8 - comments? i'm not sure if this is correct ] [emms-info caching (thanks to Damien Elmes) [EMAIL PROTECTED] [Sort file names from `emms-source-file-directory-tree-function'. [EMAIL PROTECTED] [Add some sources for inserting playlists without inserting their contents, and likewise for directories of playlist files. Exclude some files and directories from being added when walking directories. Michael Olson <[EMAIL PROTECTED]>**20060604195602] [emms-player-mpd: Differentiate between files and URLs when it makes sense to do so. Michael Olson <[EMAIL PROTECTED]>**20060604195449] [Miscellaneous minor cleanups. Michael Olson <[EMAIL PROTECTED]>**20060604195311] [Make sure we never have an empty track description when inserting a song into a playlist buffer. Michael Olson <[EMAIL PROTECTED]>**20060604194940] [Remove debian-extras package as requested by ftpmasters (debian) [EMAIL PROTECTED] [Put volume options in their own customize group. Martin Schoenmakers <[EMAIL PROTECTED]>**20060601193853 Added a separate emms-volume group for customize and put things there instead of in the main thing. ] [Make handling of multiple playlist buffers less error-prone. Michael Olson <[EMAIL PROTECTED]>**20060531203810] [emms-volume.el: Cosmetic stuff, defvar -> defcustom [EMAIL PROTECTED] [emms-volume.el: Minor cosmetic cleanup [EMAIL PROTECTED] [emms-volme.el: Add some requires. [EMAIL PROTECTED] [emms-volume-amixer.el: Provide a way to set the control for amixer [EMAIL PROTECTED] [AUTHORS: Add Martin Schoenmakers. Welcome! :-) [EMAIL PROTECTED] [Add emms-volume and emms-volume-amixer. Martin Schoenmakers <[EMAIL PROTECTED]>**20060530223500 New files: emms-volume.el provides some general volume changing things, including a minor mode to more easily change volume when not in the EMMS buffer. emms-volume-amixer.el is a backend using amixer. ] [emms-streams: Re-add space after prompt and use completion for type. Michael Olson <[EMAIL PROTECTED]>**20060530190620] [emms-streams: When the user wants emms-streams to play the selected stream instead of add it, create our own playlist buffer. When quitting, if we own the current playlist buffer, kill it. Michael Olson <[EMAIL PROTECTED]>**20060530144243] [allow nonzero ogginfo exit plus some reindenting Martin Schoenmakers <[EMAIL PROTECTED]>**20060530130411 When ogginfo gave a nonzero value on exit, any valid data would get tossed if there was any. This prevented emms from showing info for files that are tagged but a bit odd. Also reindented emms-info-ogginfo accordingly, which incidentally removed some tabs in favour of spaces. ] [emms-streams: Re-implement yank and kill so that they do the right thing with emms-stream-list. Michael Olson <[EMAIL PROTECTED]>**20060530045429] [emms-streams: Implement kill and yank. Michael Olson <[EMAIL PROTECTED]>**20060530040114] [emms-streams: Make hitting RET on a URL do the right thing, improve cursor movement, and mark the buffer as unmodified after performing a save. Michael Olson <[EMAIL PROTECTED]>**20060529030043] [emms-player-mpd: Make seek work correctly. Michael Olson <[EMAIL PROTECTED]>**20060525033120] [emms-player-mpd: Use more robust method of detecting whether we need to force-feed MusicPD our playlist. Michael Olson <[EMAIL PROTECTED]>**20060525014253] [emms-playlist-mode: Make "d" kill the entire line. This seems to be a good compromise of those who use C-k and those who want more standard object-killing behavior. foo**20060524200008] [emms-player-mpd: When showing the currently-playing song, prepend the name of the radio station, if it exists. foo**20060524195911] [emms-player-mpd: Fix bug that caused unconditional reloading of the entire MusicPD playlist whenever the track was changed manually. Michael Olson <[EMAIL PROTECTED]>**20060524061655] [emms-player-mpd: Overhaul for streamlist support, and fix a few miscellaneous issues. Michael Olson <[EMAIL PROTECTED]>**20060524055707] [emms-player-mpd: Add a few checks to make sure that the given buffer exists before trying to do anything with it. Michael Olson <[EMAIL PROTECTED]>**20060517035419] [emms-source-playlist: Do not expand names of files in playlists, as this can cause problems with emms-player-mpd in some configurations. Michael Olson <[EMAIL PROTECTED]>**20060516081257] [emms-playlist-mode: Implement the option (disabled by default) of opening a new EMMS buffer for a playlist, when hitting RET on one. Michael Olson <[EMAIL PROTECTED]>**20060510040730] [emms-playlist-mode.el: Don't put a period after the mode map. This hangs 21.4 on display. [EMAIL PROTECTED] [TAG 2.0 [EMAIL PROTECTED] Patch bundle hash: 744c99dc067b09df9c335ad15dd957e3501ac7e2
_______________________________________________ Emms-patches mailing list [email protected] http://lists.gnu.org/mailman/listinfo/emms-patches
