emms-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emms-patches] darcs patch: browser: refactor data format, bugfixes; em


From: Damien Elmes
Subject: [Emms-patches] darcs patch: browser: refactor data format, bugfixes; emms: add emm...
Date: Thu, 15 Jun 2006 01:17:50 +0900 (JST)

Thu Jun 15 01:00:48 JST 2006  Damien Elmes <address@hidden>
  * 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 <address@hidden>**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
address@hidden
 streams. At present, will just take care of tracks with 'file type.
] 
[added the section "Finding files and speed" to the manual
address@hidden 
[fix bug in emms-playlist-mode-center-current
address@hidden 
[removed superfluous comment (actually testing darcs send)
address@hidden 
[debian: add changelog for 2.0-2
address@hidden 
[debian: Install info file as well
address@hidden 
[browser: sorting, bugfixes
Damien Elmes <address@hidden>**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
address@hidden 
[emms-cache: add pruning support, make save/load interactive
Damien Elmes <address@hidden>**20060611095400] 
[Use better exclude regexp, so that people can load music files with '#' in the 
middle of the name.
Michael Olson <address@hidden>**20060610230507] 
[emms-info: Never return 0 for info-mtime, since emms-time-less-p does not like 
this.  Use nil instead.
Michael Olson <address@hidden>**20060610230409] 
[Add mpd volume settings to custom
Martin Schoenmakers <address@hidden>**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 <address@hidden>**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 <address@hidden>**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 <address@hidden>**20060609043831] 
[emms-player-mpd: Rename volume functions to better match the namespace created 
by emms-volume.el.
Michael Olson <address@hidden>**20060609043643] 
[emms-player-mpd: Fix minor bug when importing the current MusicPD playlist 
into EMMS.
Michael Olson <address@hidden>**20060609043538] 
[emms-setup: Get rid of pointless compiler warning.
Michael Olson <address@hidden>**20060609042002] 
[emms-cache: Small compiler fix.
Michael Olson <address@hidden>**20060609041606] 
[emms-cache: Add standard enable/disable/toggle interface and do a docfix for 
emms-cache-set-function.
Michael Olson <address@hidden>**20060609040108] 
[Standardize copyright notices.  Add COPYING file.  Mention license in README.
Michael Olson <address@hidden>**20060608194123] 
[Fix compiler warnings in emms-cache.el.
Michael Olson <address@hidden>**20060608184612] 
[emms-metaplaylist-mode: Fix bug introduced by the recent emms-playlist-mode 
overhaul.  Add faces for light backgrounds.
Michael Olson <address@hidden>**20060608143846] 
[NEWS is new
address@hidden 
[emms-playlist-mode: Facify tracks on startup.
address@hidden 
[refactor browser mode creation code
Damien Elmes <address@hidden>**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 <address@hidden>**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 <address@hidden>**20060608094037] 
[avoid rebuilding the browser window each time
Damien Elmes <address@hidden>**20060608092623] 
[fix RET on trailing \n
Damien Elmes <address@hidden>**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 <address@hidden>**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 <address@hidden>**20060608032546] 
[emms.el: Change directory to / before starting the player.
address@hidden 
[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 <address@hidden>**20060607215212] 
[Make emms-property-region bulletproof.
Michael Olson <address@hidden>**20060607215113] 
[Fix typo in emms-property-region
address@hidden 
[emms.el, simplified emms-property-region considerably.
address@hidden 
[Very basic support for recording the time you last played a track.
address@hidden
 
 * 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.
address@hidden 
[emms.el: The currently playing marker now should stay where it is, even for 
yanks
address@hidden 
[emms-playlist-mode: Stop overlay from being attached to text inserted before it
address@hidden 
[fix damien elmes's email address
Damien Elmes <address@hidden>**20060607154000] 
[emms sources now switch add/play behavior when a prefix argument is supplied.
address@hidden 
[Add autoloads to emms-setup.el
address@hidden 
[Typo, defvar => defcustom for emms-cache-set-function
address@hidden 
[Cleaned up the cached code in emms.el a bit
address@hidden 
[refactor caching code into emms-cache.el
Damien Elmes <address@hidden>**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 <address@hidden>**20060606144439] 
[emms-playlist-mode doesn't need overlay compatibility anymore
address@hidden 
[emms-playlist-mode.el - now with less overlay!
address@hidden 
[AUTHORS: fixed Lucas' e-mail address
address@hidden 
[AUTHORS: Damien Elmes address updated
address@hidden 
[info-cache-dirty/coding
Damien Elmes <address@hidden>**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)
address@hidden 
[Sort file names from `emms-source-file-directory-tree-function'.
address@hidden 
[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 <address@hidden>**20060604195602] 
[emms-player-mpd: Differentiate between files and URLs when it makes sense to 
do so.
Michael Olson <address@hidden>**20060604195449] 
[Miscellaneous minor cleanups.
Michael Olson <address@hidden>**20060604195311] 
[Make sure we never have an empty track description when inserting a song into 
a playlist buffer.
Michael Olson <address@hidden>**20060604194940] 
[Remove debian-extras package as requested by ftpmasters (debian)
address@hidden 
[Put volume options in their own customize group.
Martin Schoenmakers <address@hidden>**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 <address@hidden>**20060531203810] 
[emms-volume.el: Cosmetic stuff, defvar -> defcustom
address@hidden 
[emms-volume.el: Minor cosmetic cleanup
address@hidden 
[emms-volme.el: Add some requires.
address@hidden 
[emms-volume-amixer.el: Provide a way to set the control for amixer
address@hidden 
[AUTHORS: Add Martin Schoenmakers. Welcome! :-)
address@hidden 
[Add emms-volume and emms-volume-amixer.
Martin Schoenmakers <address@hidden>**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 <address@hidden>**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 <address@hidden>**20060530144243] 
[allow nonzero ogginfo exit plus some reindenting
Martin Schoenmakers <address@hidden>**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 <address@hidden>**20060530045429] 
[emms-streams: Implement kill and yank.
Michael Olson <address@hidden>**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 <address@hidden>**20060529030043] 
[emms-player-mpd: Make seek work correctly.
Michael Olson <address@hidden>**20060525033120] 
[emms-player-mpd: Use more robust method of detecting whether we need to 
force-feed MusicPD our playlist.
Michael Olson <address@hidden>**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 <address@hidden>**20060524061655] 
[emms-player-mpd: Overhaul for streamlist support, and fix a few miscellaneous 
issues.
Michael Olson <address@hidden>**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 <address@hidden>**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 <address@hidden>**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 <address@hidden>**20060510040730] 
[emms-playlist-mode.el: Don't put a period after the mode map. This hangs 21.4 
on display.
address@hidden 
[TAG 2.0
address@hidden 
Patch bundle hash:
744c99dc067b09df9c335ad15dd957e3501ac7e2

reply via email to

[Prev in Thread] Current Thread [Next in Thread]