branch: externals/emms commit e361ea85013d1e54f459487d784328f526d8b406 Author: Erica Lina <erical...@proton.me> Commit: Erica Lina <erical...@proton.me>
Make emms-filters agnostic; refilter now uses hooks. --- doc/emms.texinfo | 54 ++++++++++++++++++++++++- emms-browser.el | 72 +++++++++++++++++++++++++++++++-- emms-filters.el | 120 +++++++++++++++++++++---------------------------------- 3 files changed, 166 insertions(+), 80 deletions(-) diff --git a/doc/emms.texinfo b/doc/emms.texinfo index 778f1866f1..d36ed15c56 100644 --- a/doc/emms.texinfo +++ b/doc/emms.texinfo @@ -2406,7 +2406,9 @@ artist->album->track when you switch to the 'singles' filter: (ad-activate 'emms-browser-next-mapping-type) (ad-deactivate 'emms-browser-next-mapping-type))) -(add-hook 'emms-browser-filter-changed-hook 'toggle-album-display) +;; Deprecated use the emms-filters hook instead. +;; (add-hook 'emms-browser-filter-changed-hook 'toggle-album-display) +(add-hook 'emms-filters-filter-changed-hook 'toggle-album-display) @end lisp Furthermore, you can customize @@ -2676,11 +2678,59 @@ could work against anything but the Emms-cache-db. The equivalent to the emms-browser search-by is just a one shot interactive 'new fields-search' filter factory that saves a cache and then removes itself. +Emms-Filters is agnostic about the renderer. Currently there has been a +lot of effor to maintain backward compatibity with the Emms-browser as +its functionality was replaced. There are the following hooks that any +renderer could use in order to leverage Emms-Filters. + +To maintain independence there are three hook variables which allow +emms-filters to interact with the Emms-Browsers functionality. + +The first is a defcustom hook to mirror the browser's deprecated hook +of the same name. +The second hook happens just after, and is for any renderer +that wishes to re-render when a filter changes. +The third hook is to tell any renderer to expand its render if there is +a filter or cache stack entry present. + +This a defcustom hook that is run anytime the filters change +@var{emms-filters-filter-changed-hook} + +@lisp +(add-hook 'emms-filters-filter-changed-hook 'my-filters-have-changed-function) +@end lisp + +The following two hooks are for the renderers which is currently +just the Emms-Browser. These hooks are the mechanism used to +actually filter and render the tracks. + +When the filter or cache changes Emms-Filters needs to +tell the renderer to re-build its hash and display it. +For this purpose there is another hook, the +@var{emms-filters-make-and-render-hash-hook}. + +The Emms-browser function for this is emms-browse-by. +This function applies the filters, creates a hash, +and then populates and renders a tree of data. +@lisp +(add-hook 'emms-filters-make-and-render-hash-hook 'emms-browse-by) +@end lisp + +The last hook is the @var{emms-filters-expand-render-hook}. +This is just so that Emms-Filters can tell the renderer to +expand its tree when there is a filter or cache stack present +and something has changed. +For Emms-Browser this is the function emms-browser-expand-all + +@lisp +;; (add-hook 'emms-filters-expand-render-hook 'emms-browser-expand-all) +@end lisp + The filter system is much more powerful than the previous system of filtering and searching and is much easier to use both in code and interactively while searching your tracks. -A summary of differences and features of the filter system. +Here is a summary of differences and features of the filter system. @itemize @bullet @item Filters, no matter the complexity, are defined entirely as data. diff --git a/emms-browser.el b/emms-browser.el index 343c675f82..4ddc042b7a 100644 --- a/emms-browser.el +++ b/emms-browser.el @@ -106,7 +106,7 @@ ;; (ad-activate 'emms-browser-next-mapping-type) ;; (ad-deactivate 'emms-browser-next-mapping-type))) -;; (add-hook 'emms-browser-filter-changed-hook 'toggle-album-display) +;; (add-hook 'emms-filters-filter-changed-hook 'toggle-album-display) ;; Changing display format ;; ------------------------------------------------------------------- @@ -191,7 +191,6 @@ ;;; Code: -(require 'cl-lib) (require 'emms) (require 'emms-cache) (require 'emms-volume) @@ -199,6 +198,7 @@ (require 'emms-playlist-sort) (require 'sort) (require 'seq) +(require 'emms-filters) ;; -------------------------------------------------- @@ -296,6 +296,7 @@ Use nil for no sorting." "Given a track, return t if the track should be ignored." :type 'hook) +;; Deprecated. See emms-filters-filter-changed-hook. (defcustom emms-browser-filter-changed-hook nil "Hook run after the filter has changed." :type 'hook) @@ -322,6 +323,14 @@ Called once for each directory." (defvar emms-browser-current-indent nil "Used to override the current indent, for the playlist, etc.") +;; Set the hooks for Emms-filters to say when to re-render. +;; this is just a variable to mirror the browser's hook. +;; It should probably just be set directly, and the browser's +;; hook be deprecated. It will have to be set if anyone changes it... +;; Potential problem if someone us using this hook. +(add-hook 'emms-filters-make-and-render-hash-hook 'emms-browse-by) +(add-hook 'emms-filters-expand-render-hook 'emms-browser-expand-all) + (defvar emms-browser-tree-node-map-default '((info-albumartist . info-artist) (info-artist . info-album) @@ -357,6 +366,7 @@ Called once for each directory." (defvar emms-browser-mode-map (let ((map (make-sparse-keymap))) + (define-key map (kbd "Q") #'emms-filters-pop-cache) (define-key map (kbd "q") #'emms-browser-bury-buffer) (define-key map (kbd "/") #'emms-isearch-buffer) (define-key map (kbd "r") #'emms-browser-goto-random) @@ -393,6 +403,55 @@ Called once for each directory." (define-key map (kbd "W a w") #'emms-browser-lookup-album-on-wikipedia) (define-key map (kbd "+") #'emms-volume-raise) (define-key map (kbd "-") #'emms-volume-lower) + + (define-key map (kbd ">") #'emms-filters-next-ring-filter) + (define-key map (kbd "<") #'emms-filters-previous-ring-filter) + (define-key map (kbd "f !") #'emms-filters-clear-ring-filter) + (define-key map (kbd "f >") #'emms-filters-next-ring-filter) + (define-key map (kbd "f <") #'emms-filters-previous-ring-filter) + + (define-key map (kbd "i s") #'emms-filters-status-print) + (define-key map (kbd "i f") #'emms-filters-show-filters) + (define-key map (kbd "i m") #'emms-filters-show-filter-menu) + (define-key map (kbd "i F") #'emms-filters-show-filter-factories) + (define-key map (kbd "i r") #'emms-filters-show-filter-ring) + (define-key map (kbd "i c") #'emms-filters-show-cache-stack) + (define-key map (kbd "i S") #'emms-filters-show-cache-stash) + + (define-key map (kbd "f q") #'emms-filters-pop) + (define-key map (kbd "f h") #'emms-filters-hard-filter) + (define-key map (kbd "f r") #'emms-filters-swap) ; rotate ? + (define-key map (kbd "f R") #'emms-filters-swap-pop) ; rotate-eject, ,pop-previous + (define-key map (kbd "f f") #'emms-filters-squash) ;flatten + (define-key map (kbd "f k") #'emms-filters-keep) + (define-key map (kbd "f C") #'emms-filters-clear-all) + (define-key map (kbd "f c") #'emms-filters-clear) + (define-key map (kbd "f p") #'emms-filters-push) + (define-key map (kbd "f s") #'emms-filters-smash) + (define-key map (kbd "f o") #'emms-filters-or) + (define-key map (kbd "f a") #'emms-filters-and) + (define-key map (kbd "f n") #'emms-filters-and-not) + + (define-key map (kbd "c p") #'emms-filters-push-cache) + (define-key map (kbd "c z") #'emms-filters-stash-pop-cache) + (define-key map (kbd "c Z") #'emms-filters-stash-cache) + (define-key map (kbd "c q") #'emms-filters-pop-cache) + (define-key map (kbd "c h") #'emms-filters-hard-filter) + (define-key map (kbd "c r") #'emms-filters-swap-cache) + (define-key map (kbd "c R") #'emms-filters-swap-pop-cache) + (define-key map (kbd "c S") #'emms-filters-squash-caches) + (define-key map (kbd "c c") #'emms-filters-clear-caches) + + (define-key map (kbd "s o") #'emms-filters-search-by-albumartist) + (define-key map (kbd "s a") #'emms-filters-search-by-artist) + (define-key map (kbd "s c") #'emms-filters-search-by-composer) + (define-key map (kbd "s p") #'emms-filters-search-by-performer) + (define-key map (kbd "s A") #'emms-filters-search-by-album) + (define-key map (kbd "s t") #'emms-filters-search-by-title) + (define-key map (kbd "s T") #'emms-filters-search-by-titles) + (define-key map (kbd "s n") #'emms-filters-search-by-names) + (define-key map (kbd "s s") #'emms-filters-search-by-names-and-titles) + (define-key map (kbd "s e") #'emms-filters-search-by-all-text) ;everything. map) "Keymap for `emms-browser-mode'.") @@ -519,8 +578,13 @@ Does not set the browser buffer to current unless NO-UPDATE is set. (interactive) (emms-browse-by ,type)))) -(defun emms-browse-by (type) - "Render a top level buffer based on TYPE." +(defun emms-browse-by (&optional type) + "Render a top level buffer based on TYPE. +If TYPE is not given default to top-level-type +or the default-browse-type" + (if (not type) + (setq type (or emms-browser-top-level-type + emms-browser-default-browse-type))) ;; FIXME: assumes we only browse by info-* (let* ((name (substring (symbol-name type) 5)) (modedesc (concat "Browsing by: " name)) diff --git a/emms-filters.el b/emms-filters.el index 2b035e08fa..97f210bc4a 100644 --- a/emms-filters.el +++ b/emms-filters.el @@ -481,7 +481,6 @@ ;;; Code: (require 'cl-lib) ; for lexical-let -(require 'emms-browser) (defvar emms-filters-stack nil "A history of multi-filters. Our working stack.") @@ -513,9 +512,34 @@ (defvar emms-filters-filter-menu '("no filter" "new filter") "A list of available filters grouped by factory.") -;; for backwards compatibility with emms-browser -(defvar emms-filters-filter-changed-hook emms-browser-filter-changed-hook - "Hook to run after the filter has changed.") +(defgroup emms-filters nil + "*The Emacs Multimedia System filter system" + :prefix "emms-filters-" + :group 'multimedia + :group 'applications) + +;; For backwards compatibility with emms-browser +;; This is really just a mirror of the browser's hook. +(defcustom emms-filters-filter-changed-hook nil + "Hook to run after the filter has changed." + :type 'hook) + +;; Emms-filters is agnostic about the renderer. +;; +;; These are to be set by the rendererer so that emms-filters +;; can ask for a new render of the results when +;; new a new filter has been created. + +(defvar emms-filters-make-and-render-hash-hook nil + "This function applies the filters, creates a hash, +and then populates and renders a tree of data, +For the Emms-browser this should be emms-browse-by.") + +;; emms-filters-expand-render-hook +(defvar emms-filters-expand-render-hook nil + "To be set by the renderer so that the results tree +can be expanded when a filter or search exists, +For the Emms-Browser this is the emms-browser-expand-all function.") (defvar emms-filters-multi-filter-save-file nil "A file name to write the kept meta-filters from the session to.") @@ -556,7 +580,7 @@ then we combine with the result of the emms-filters-current-filter." (defun emms-filters-add-to-filter-menu-from-filter-list (folder filters) "Add a FOLDER and FILTERS to the filter select list menu." - (emms-filters-add-to-filter-menu folder (mapcar 'cadr tango-filters))) + (emms-filters-add-to-filter-menu folder (mapcar 'cadr filters))) (defun emms-filters-add-to-filter-menu (folder-name filter-or-list) "Add to a FOLDER-NAME in the filter select menu creating it as needed. @@ -1327,24 +1351,26 @@ Filter should be a filter cons in the form of '(name . function)." (setq emms-filters-current-filter-name (car filter)) (setq emms-filters-current-filter filter)) -(defun emms-filters-browse-by () - "The single interface to emms-browser. Re-render please. -Uses the top level type, or the default browse type." - (emms-browse-by (or emms-browser-top-level-type - emms-browser-default-browse-type))) +;; (defun emms-filters-browse-by () +;; "The single interface to emms-browser. Re-render please. +;; Uses the top level type, or the default browse type." +;; (emms-browse-by (or emms-browser-top-level-type +;; emms-browser-default-browse-type))) (defun emms-filters-refilter () "Make a multi-filter function from the current meta-filter and set it. -Run the filter changed hook. Ask the browser to re-render." +Run the filter changed hooks. Ask the Browser/renderer to re-render with +the render and expand hooks." (emms-filters-set-filter (cons (caar emms-filters-stack) (emms-filters-make-multi-filter (cdar emms-filters-stack)))) + + ;; filter-changed-hook is a defcustom for users. (run-hooks 'emms-filters-filter-changed-hook) - ;; emms-filters-make-and-render-hash - (emms-filters-browse-by) - ;; If it is a search or a filter expand the results. + ;; this hook is for renderers. + (run-hooks 'emms-filters-make-and-render-hash-hook) + ;; If it is a search ora filter expand the results. (when (or emms-filters-stack emms-filters-search-caches) - ;; emms-filters-expand-render - (emms-browser-expand-all))) + (run-hooks 'emms-filters-expand-render-hook))) (defun emms-filters-ensure-metafilter (filter) "Ensure that FILTER is a meta-filter." @@ -1594,7 +1620,6 @@ Creates a new 'AND-NOT' list of filters." (defun emms-filters-full-name () "Give a full name for the current filtering. -Used by emms-browser mode description. Includes the ring filter name plus current filter name. Does not show the current cache name. Only show the ring filter name if its function is not nil. @@ -1681,9 +1706,8 @@ Use the current filter name so that 'no filter' shows." (defun emms-filters-browser-search (fields) "Search track FIELDS in the cache for a compare string. -An exact replacement for emms-browser-search. Prompt for the value to search, emulate -the behavior of emms-browser-search using the filter and cache stacks +the behavior of former emms-browser-search using the filter and cache stacks with the 'fields search' filter factory. 1. Make a filter function, @@ -1829,7 +1853,7 @@ and cache the results to the cache stack." (interactive) (emms-filters-quick-one-shot filter-factory-name)) -;; replacements for emms-browser and then some. +;; replacements for emms-browser search and then some. (defun emms-filters-search-by-albumartist () "A fields search quick one shot for Album Artist." (interactive) @@ -1880,60 +1904,6 @@ and cache the results to the cache stack." (interactive) (emms-filters-quick-one-shot "All text")) -(setq emms-browser-mode-map - (let ((map emms-browser-mode-map)) - (define-key map (kbd "Q") #'emms-filters-pop-cache) - ;; (define-key map (kbd "h") #'hydra-emms/body) - (define-key map (kbd ">") #'emms-filters-next-ring-filter) - (define-key map (kbd "<") #'emms-filters-previous-ring-filter) - (define-key map (kbd "f !") #'emms-filters-clear-ring-filter) - (define-key map (kbd "f >") #'emms-filters-next-ring-filter) - (define-key map (kbd "f <") #'emms-filters-previous-ring-filter) - - (define-key map (kbd "i s") #'emms-filters-status-print) - (define-key map (kbd "i f") #'emms-filters-show-filters) - (define-key map (kbd "i m") #'emms-filters-show-filter-menu) - (define-key map (kbd "i F") #'emms-filters-show-filter-factories) - (define-key map (kbd "i r") #'emms-filters-show-filter-ring) - (define-key map (kbd "i c") #'emms-filters-show-cache-stack) - (define-key map (kbd "i S") #'emms-filters-show-cache-stash) - - (define-key map (kbd "f q") #'emms-filters-pop) - (define-key map (kbd "f h") #'emms-filters-hard-filter) - ;; (define-key map (kbd "f H") #'hydra-emms-filters/body) - (define-key map (kbd "f r") #'emms-filters-swap) ; rotate ? - (define-key map (kbd "f R") #'emms-filters-swap-pop) ; rotate-eject, ,pop-previous - (define-key map (kbd "f f") #'emms-filters-squash) ;flatten - (define-key map (kbd "f k") #'emms-filters-keep) - (define-key map (kbd "f C") #'emms-filters-clear-all) - (define-key map (kbd "f c") #'emms-filters-clear) - (define-key map (kbd "f p") #'emms-filters-push) - (define-key map (kbd "f s") #'emms-filters-smash) - (define-key map (kbd "f o") #'emms-filters-or) - (define-key map (kbd "f a") #'emms-filters-and) - (define-key map (kbd "f n") #'emms-filters-and-not) - - (define-key map (kbd "c p") #'emms-filters-push-cache) - (define-key map (kbd "c z") #'emms-filters-stash-pop-cache) - (define-key map (kbd "c Z") #'emms-filters-stash-cache) - (define-key map (kbd "c q") #'emms-filters-pop-cache) - (define-key map (kbd "c h") #'emms-filters-hard-filter) - (define-key map (kbd "c r") #'emms-filters-swap-cache) - (define-key map (kbd "c R") #'emms-filters-swap-pop-cache) - (define-key map (kbd "c S") #'emms-filters-squash-caches) - (define-key map (kbd "c c") #'emms-filters-clear-caches) - - (define-key map (kbd "s o") #'emms-filters-search-by-albumartist) - (define-key map (kbd "s a") #'emms-filters-search-by-artist) - (define-key map (kbd "s c") #'emms-filters-search-by-composer) - (define-key map (kbd "s p") #'emms-filters-search-by-performer) - (define-key map (kbd "s A") #'emms-filters-search-by-album) - (define-key map (kbd "s t") #'emms-filters-search-by-title) - (define-key map (kbd "s T") #'emms-filters-search-by-titles) - (define-key map (kbd "s n") #'emms-filters-search-by-names) - (define-key map (kbd "s s") #'emms-filters-search-by-names-and-titles) - (define-key map (kbd "s e") #'emms-filters-search-by-all-text) ;everything. - map)) ;;; Testing ;;; ------------------------------------------------------------------- @@ -2112,6 +2082,8 @@ Returns a list of cons with the filter result and the track." (emms-filters-test-factory-interactive "Genre" first-test-track) (emms-filters-test-factory-interactive "Titles" first-test-track))) +;; Testing Backward compatibility with the emms-browser. +;; ------------------------------------------------------- ;; Make some old style browser filters to test ;; the filter-ring backward compatibility. ;; Steps to test: