branch: externals/listen
commit 5b456c2e6793b3149a4edff2a30b4cf632073f4c
Author: Adam Porter <[email protected]>
Commit: Adam Porter <[email protected]>
Change: (listen-queue-add-tracks) Use a hash table for deduplication
This is much, much faster (especially noticeable, e.g. when adding
5,000 tracks to a queue already containing those tracks).
---
README.org | 3 +++
docs/README.org | 3 +++
listen-lib.el | 25 +++++++++++++++++++++++++
listen-queue.el | 5 +----
4 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/README.org b/README.org
index 3afd3bfb19..38f3e00668 100644
--- a/README.org
+++ b/README.org
@@ -206,6 +206,9 @@ The ~listen-mode~ minor mode runs a timer which plays the
next track in the curr
- Option ~listen-backend~, which sets the backend to use: MPV or VLC. (The
default is to auto-detect which is available at load time, with MPV being
preferred due to more robust IPC support.)
- Faces for parts of mode line lighter.
+*Changes*
+- Improve performance of adding large numbers of tracks to large queues (using
a hash table for deduplication).
+
*Fixes*
- Playing next track in queue after current track has been removed.
- Updating vtables for Emacs versions before 30.
diff --git a/docs/README.org b/docs/README.org
index 7a62cb9767..10ced3139e 100644
--- a/docs/README.org
+++ b/docs/README.org
@@ -243,6 +243,9 @@ The ~listen-mode~ minor mode runs a timer which plays the
next track in the curr
+ Option ~listen-backend~, which sets the backend to use: MPV or VLC. (The
default is to auto-detect which is available at load time, with MPV being
preferred due to more robust IPC support.)
+ Faces for parts of mode line lighter.
+*Changes*
++ Improve performance of adding large numbers of tracks to large queues (using
a hash table for deduplication).
+
*Fixes*
+ Playing next track in queue after current track has been removed.
+ Updating vtables for Emacs versions before 30.
diff --git a/listen-lib.el b/listen-lib.el
index 0cb45c786c..852b5beed6 100644
--- a/listen-lib.el
+++ b/listen-lib.el
@@ -154,6 +154,31 @@ return a list of values; otherwise return the sole value."
"Return SECONDS formatted as an hour:minute:second-style duration."
(format-seconds "%h:%z%m:%.2s" seconds))
+(define-hash-table-test
+ 'listen-track-equal
+ #'equal
+ (lambda (track)
+ (sxhash-equal (expand-file-name (listen-track-filename track)))))
+
+(cl-defun listen-delete-dups (list &optional (test 'listen-track-equal))
+ "Return LIST having destructively removed duplicates.
+Similar to `delete-dups', but TEST may be specified.
+Unlike `delete-dups', this function always uses a hash table to find
+duplicates; therefore TEST should be compatible with `make-hash-table',
+which see."
+ ;; Copies the body of `delete-dups', passing through TEST, and removing the
length-based
+ ;; non-hash-table case..
+ (let ((hash (make-hash-table :test test))
+ (tail list) retail)
+ (puthash (car list) t hash)
+ (while (setq retail (cdr tail))
+ (let ((elt (car retail)))
+ (if (gethash elt hash)
+ (setcdr tail (cdr retail))
+ (puthash elt t hash)
+ (setq tail retail))))
+ list))
+
;;;; Methods
(cl-defgeneric listen--elapsed (player)
diff --git a/listen-queue.el b/listen-queue.el
index ea1203ebae..189aaa7261 100644
--- a/listen-queue.el
+++ b/listen-queue.el
@@ -473,10 +473,7 @@ the queue's buffer is updated, if any."
(cl-callf append (listen-queue-tracks queue) tracks)
;; TODO: Consider updating the metadata of any duplicate tracks.
(setf (listen-queue-tracks queue)
- (cl-delete-duplicates (listen-queue-tracks queue)
- :key (lambda (track)
- (expand-file-name (listen-track-filename
track)))
- :test #'file-equal-p))
+ (listen-delete-dups (listen-queue-tracks queue) 'listen-track-equal))
(listen-queue--update-buffer queue))
(cl-defun listen-queue-add-from-playlist-file (filename queue)