diff options
Diffstat (limited to 'elisp/emms-metaplaylist-mode.el')
| -rw-r--r-- | elisp/emms-metaplaylist-mode.el | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/elisp/emms-metaplaylist-mode.el b/elisp/emms-metaplaylist-mode.el new file mode 100644 index 0000000..d980888 --- /dev/null +++ b/elisp/emms-metaplaylist-mode.el @@ -0,0 +1,242 @@ +;;; emms-metaplaylist-mode.el --- A major mode for lists of Emms playlists -*- lexical-binding: t; -*- + +;; Copyright (C) 2006-2021 Free Software Foundation, Inc. + +;; Author: Yoni Rabkin <[email protected]> + +;; This file is part of EMMS. + +;; EMMS is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License +;; as published by the Free Software Foundation; either version 3 +;; of the License, or (at your option) any later version. + +;; EMMS is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with EMMS; if not, write to the Free Software +;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +;; 02110-1301, USA. + +;;; Commentary: +;; +;; `emms-metaplaylist-mode' creates an interactive list of all the +;; Emms playlist buffers. The currently active buffer is +;; highlighted. You can choose a buffer from the list with RET and get +;; taken there. + +;;; Code: + +(require 'emms) +(require 'emms-playlist-mode) + +;;; -------------------------------------------------------- +;;; Variables, customisation and faces +;;; -------------------------------------------------------- + +(defgroup emms-metaplaylist-mode nil + "*The Emacs Multimedia System meta-playlist mode." + :prefix "emms-metaplaylist-mode-" + :group 'multimedia) + +(defcustom emms-metaplaylist-mode-buffer-name "*Emms Playlist Buffers*" + "Name of the buffer in which Emms playlists will be listed." + :type 'string) + +(defcustom emms-metaplaylist-mode-hooks nil + "List of hooks to run on entry to emms-metaplaylist-mode." + :type 'list) + +(defface emms-metaplaylist-mode-face + '((((class color) (background dark)) + (:foreground "AntiqueWhite3")) + (((class color) (background light)) + (:foreground "red3")) + (((type tty) (class mono)) + (:inverse-video t)) + (t (:background "WhiteSmoke"))) + "Face for the buffer names in the playlists buffer.") + +(defface emms-metaplaylist-mode-current-face + '((((class color) (background dark)) + (:foreground "red2")) + (((class color) (background light)) + (:background "red3" :foreground "white")) + (((type tty) (class mono)) + (:inverse-video t)) + (t (:background "red3"))) + "Face for the current buffer name in the playlists buffer.") + +;;; -------------------------------------------------------- +;;; Keymap +;;; -------------------------------------------------------- + +(defvar emms-metaplaylist-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map text-mode-map) + (define-key map (kbd "n") #'next-line) + (define-key map (kbd "p") #'previous-line) + (define-key map (kbd "RET") #'emms-metaplaylist-mode-goto-current) + (define-key map (kbd "SPC") #'emms-metaplaylist-mode-set-active) + (define-key map (kbd "g") #'emms-metaplaylist-mode-update) + (define-key map (kbd "C") #'emms-metaplaylist-mode-new-buffer) + (define-key map (kbd "C-k") #'emms-metaplaylist-mode-kill-buffer) + (define-key map (kbd "c") #'emms-metaplaylist-mode-center-current) + (define-key map (kbd "q") #'kill-this-buffer) + (define-key map (kbd "?") #'describe-mode) + map) + "Keymap for `emms-metaplaylist-mode'.") + +;;; -------------------------------------------------------- +;;; Metaplaylist +;;; -------------------------------------------------------- + +(defun emms-metaplaylist-mode-goto-current () + "Switch to the buffer at point." + (interactive) + (let ((buffer (get-buffer + (buffer-substring (line-beginning-position) + (line-end-position))))) + (emms-playlist-set-playlist-buffer buffer) + (switch-to-buffer buffer))) + +(defun emms-metaplaylist-mode-write (playlists) + "Print the sorted list of PLAYLISTS." + (delete-region (point-min) (point-max)) + (mapc (lambda (buf) + (let ((inhibit-read-only t)) + (insert (buffer-name buf)) + (add-text-properties + (line-beginning-position) (line-end-position) + (list 'face + (if (eq buf emms-playlist-buffer) + 'emms-metaplaylist-mode-current-face + 'emms-metaplaylist-mode-face))) + (newline))) + playlists)) + +;; Emms' list changes order, and that's OK, but we want something +;; stable for display purposes. +(defun emms-metaplaylist-mode-sorted-buffer-list () + "Return a sorted list of playlist buffers." + (sort + (copy-tree + (emms-playlist-buffer-list)) + #'(lambda (a b) + (string< (buffer-name a) + (buffer-name b))))) + +(defun emms-metaplaylist-mode-center-current () + "Center on the current playlist buffer" + (interactive) + (when (buffer-name emms-playlist-buffer) + (let ((p nil)) + (save-excursion + (goto-char (point-min)) + (setq p (search-forward-regexp (regexp-quote + (buffer-name emms-playlist-buffer)) + (point-max) t))) + (when (not p) (error "cannot not find the current playlist buffer")) + (goto-char p) + (goto-char (line-beginning-position))))) + +(defun emms-metaplaylist-mode-create () + "Create the meta-playlist buffer." + (let ((name emms-metaplaylist-mode-buffer-name) + (playlists (emms-metaplaylist-mode-sorted-buffer-list))) + (if playlists + (with-current-buffer (get-buffer-create name) + (emms-metaplaylist-mode) + (emms-metaplaylist-mode-write playlists) + (emms-metaplaylist-mode-center-current) + (current-buffer)) + (error "No Emms playlist buffers")))) + +(defun emms-metaplaylist-mode-assert-buffer () + "Assert that we are in the metaplaylist mode buffer." + (when (not (eq (current-buffer) + (get-buffer emms-metaplaylist-mode-buffer-name))) + (error "not the metalplaylist buffer"))) + +(defun emms-metaplaylist-mode-update () + "Update the metalplaylist display." + (interactive) + (emms-metaplaylist-mode-assert-buffer) + (let ((inhibit-read-only t)) + (emms-metaplaylist-mode-write + (emms-metaplaylist-mode-sorted-buffer-list))) + (emms-metaplaylist-mode-center-current)) + +(defun emms-metaplaylist-mode-kill-buffer () + "Kill the buffer at point" + (interactive) + (let ((buffer (get-buffer + (buffer-substring (line-beginning-position) + (line-end-position))))) + (when (not buffer) + (error "can't find buffer at point")) + (if (y-or-n-p (format "kill playlist buffer \"%s\"?" + (buffer-name buffer))) + (kill-buffer buffer) + (message "Buffer kill aborted.")) + (emms-metaplaylist-mode-update))) + + +;;; -------------------------------------------------------- +;;; Playlist Management +;;; -------------------------------------------------------- + +(defun emms-metaplaylist-mode-new-buffer (buffer-name) + "Creates a new buffer playlist buffer BUFFER-NAME." + (interactive "sBuffer Name: ") + (if (get-buffer buffer-name) + (error "Buffer must not exist.") + (let ((buf (get-buffer-create buffer-name))) + (with-current-buffer buf + (emms-playlist-mode) + (setq emms-playlist-buffer-p t))) + (emms-metaplaylist-mode-update))) + +(defun emms-metaplaylist-mode-set-active () + "Set the buffer at point to be the active playlist." + (interactive) + (emms-playlist-set-playlist-buffer + (get-buffer (buffer-substring (line-beginning-position) (line-end-position)))) + (emms-metaplaylist-mode-update)) + + +;;; -------------------------------------------------------- +;;; Mode entry +;;; -------------------------------------------------------- + +(defun emms-metaplaylist-mode-go () + "Single entry point to the metaplaylist interface." + (interactive) + (let ((mpm-buffer (get-buffer emms-metaplaylist-mode-buffer-name))) + (if mpm-buffer + (with-current-buffer mpm-buffer + (emms-metaplaylist-mode-update)) + (setq mpm-buffer (emms-metaplaylist-mode-create))) + (switch-to-buffer mpm-buffer))) + +(defun emms-metaplaylist-mode () + "A major mode for Emms playlists. + +\\{emms-metaplaylist-mode-map}" + ;; (interactive) + (kill-all-local-variables) + + (use-local-map emms-metaplaylist-mode-map) + (setq major-mode 'emms-metaplaylist-mode + mode-name "Emms-MetaPlaylist") + + (setq buffer-read-only t) + + (run-hooks 'emms-metaplaylist-mode-hooks)) + +(provide 'emms-metaplaylist-mode) + +;;; emms-metaplaylist-mode.el ends here |
