From f47307dd053f8457e7cad556cbc2933881427bbd Mon Sep 17 00:00:00 2001 From: forcer Date: Fri, 16 Sep 2005 13:40:00 +0000 Subject: Added emms-playlist-mode.el darcs-hash:20050916134001-2189f-4dc12e4e9c599b50784cc115a07da94675e8c990.gz --- emms-playlist-mode.el | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 emms-playlist-mode.el diff --git a/emms-playlist-mode.el b/emms-playlist-mode.el new file mode 100644 index 0000000..32292fe --- /dev/null +++ b/emms-playlist-mode.el @@ -0,0 +1,290 @@ +;;; emms-playlist-mode.el --- Playlist mode for Emms. + +;;; Copyright Yoni Rabkin under the GNU General Public License. + +;;; Commentary: +;;; +;;; Jorgen has the following to say about playlist-mode: +;;; +;;; Playlist Mode +;;; ============= +;;; This should be a file named emms-playlist-mode.el, providing said +;;; mode, which is a suitable value for `emms-playlist-default-major-mode'. +;;; +;;; The mode should probably set `emms-playlist-buffer-name' and +;;; `emms-playlist-insert-track-function', and add something to +;;; `emms-playlist-selection-changed-hook' and +;;; `emms-playlist-cleared-hook'. +;;; +;;; When this is done, emms-pbi.el, emms-pbi-filter.el, +;;; emms-pbi-mark.el, emms-pbi-popup.el and emms-pl-manip.el can be +;;; removed. +;;; +;;; ...and when Jorgen says (require 'jump) we say how-high.el. +;;; +;;; I'm designing this as a method of displaying and manipulating the +;;; different Emms playlist buffers defined by the user. +;;; + +;;; Feature requests: +;;; +;;; (1) Lukhas wants `emms-list-playlist-buffers' to list all the +;;; playlist buffers. +;;; +;;; (2) Add emms-info support which re-writes the track titles. +;;; +;;; (3) Add multi-line formatting and arbitrary comment entry (via a +;;; null-track type [Lukhas]?). + +;;; -------------------------------------------------------- +;;; Variables +;;; -------------------------------------------------------- + +(defvar emms-playlist-mode-hook nil + "Emms playlist mode hook.") + +(defvar emms-playlist-mode-selected-overlay-marker nil) + +;; Is this needed at all? +(defvar emms-playlist-mode-prepend-show-string + "Now Playling:") + +(defgroup emms-playlist-mode nil + "*The Emacs Multimedia System playlist mode." + :prefix "emms-playlist-mode-" + :group 'multimedia) + +;;; -------------------------------------------------------- +;;; Faces and font locking +;;; -------------------------------------------------------- + +;; change the eye-gouging colors before release +(defface emms-playlist-track-face + '((((class color) (background dark)) + :background "yellow") + (((type tty) (class mono)) + :inverse-video t) + (t :background "red")) + "Basic face for highlighting the selected track." + :group 'emms-playlist-mode) + +(defface emms-playlist-selected-face + '((((class color) (background dark)) + :background "blue1") + (((type tty) (class mono)) + :inverse-video t) + (t :background "blue3")) + "Basic face for highlighting the region of the track." + :group 'emms-playlist-mode) + +;; FIXME: automatic font-locking does not work. See below. +(defvar emms-playlist-mode-font-lock-keywords + '(("\\(.*\\)" (1 emms-playlist-track-face))) + "Keyword highlighting specification for `emms-playlist-mode'.") + +;;; -------------------------------------------------------- +;;; Keys +;;; -------------------------------------------------------- + +(defconst emms-playlist-mode-map + (let ((emms-playlist-mode-map (make-sparse-keymap))) + (set-keymap-parent emms-playlist-mode-map text-mode-map) + (define-key emms-playlist-mode-map (kbd "n") 'emms-next) + (define-key emms-playlist-mode-map (kbd "p") 'emms-previous) + (define-key emms-playlist-mode-map (kbd "C-x C-s") 'emms-playlist-save) + (define-key emms-playlist-mode-map (kbd "C-k") 'emms-playlist-mode-kill-track) + (define-key emms-playlist-mode-map (kbd "d") 'emms-playlist-mode-kill-track) + (define-key emms-playlist-mode-map (kbd "s") 'emms-stop) + (define-key emms-playlist-mode-map (kbd "f") 'emms-playlist-mode-show-current-track) + (define-key emms-playlist-mode-map (kbd "F") 'emms-playlist-mode-show-current-track-clean) + (define-key emms-playlist-mode-map (kbd "RET") 'emms-playlist-mode-play-current-track) + (define-key emms-playlist-mode-map (kbd "q") 'bury-buffer) + (define-key emms-playlist-mode-map (kbd "") 'emms-playlist-mode-play-current-track) + (define-key emms-playlist-mode-map (kbd "?") 'describe-mode) + (define-key emms-playlist-mode-map (kbd "M-<") 'emms-playlist-mode-first) + (define-key emms-playlist-mode-map (kbd "M->") 'emms-playlist-mode-last) + (define-key emms-playlist-mode-map (kbd "C-n") 'emms-playlist-mode-select-next) + (define-key emms-playlist-mode-map (kbd "C-p") 'emms-playlist-mode-select-previous) + (define-key emms-playlist-mode-map (kbd "r") 'emms-playlist-mode-play-random) + emms-playlist-mode-map) + "Keymap for emms-playlist-mode.") + +;; We will add to this wrapper boundry checking as needed later. +(defmacro emms-playlist-mode-move-wrapper (name fun) + `(defun ,name () + ,(format "Interactive wrapper around `%s' for playlist-mode." + fun) + (interactive) + (,fun))) + +(defmacro emms-playlist-mode-when-playing-p (&rest body) + `(lambda () + (if emms-player-playing-p + ,@body + (error "No track is currently playing")))) + +(emms-playlist-mode-move-wrapper emms-playlist-mode-first + emms-playlist-first) + +(emms-playlist-mode-move-wrapper emms-playlist-mode-last + emms-playlist-last) + +(emms-playlist-mode-move-wrapper emms-playlist-mode-select-next + emms-playlist-next) + +(emms-playlist-mode-move-wrapper emms-playlist-mode-select-previous + emms-playlist-previous) + +(emms-playlist-mode-move-wrapper emms-playlist-mode-select-random + emms-playlist-select-random) + +(defun emms-playlist-mode-play-random () + (interactive) + (emms-stop) + (emms-playlist-mode-select-random) + (emms-start)) + +(defun emms-playlist-mode-show-current-track () + (interactive) + (funcall + (emms-playlist-mode-when-playing-p + (message "%s %s" + emms-playlist-mode-prepend-show-string + (emms-track-description + (emms-playlist-selected-track)))))) + +(defun emms-playlist-mode-show-current-track-clean () + (interactive) + (funcall + (emms-playlist-mode-when-playing-p + (message "%s" + (emms-track-description + (emms-playlist-selected-track)))))) + +(defun emms-playlist-mode-selected-at () + (eq (emms-playlist-track-at) + (emms-playlist-selected-track))) + +(defun emms-playlist-mode-play-current-track () + (interactive) + (emms-playlist-select (point)) + (when emms-player-playing-p + (emms-stop)) + (emms-start)) + +;; The logic for killing tracks in an interactive manner is +;; suprisingly annoying +(defun emms-playlist-mode-kill-track () + (interactive) + (let ((region (emms-property-region (point) 'emms-track))) + (cond ((not (emms-playlist-track-at)) + (kill-line 1)) ; Purposfully kills only one line + ((and (not (emms-playlist-mode-selected-at)) + (emms-playlist-track-at)) + (kill-region (car region) + (cdr region)) + (emms-playlist-mode-kill-track)) + ((and emms-player-playing-p + (emms-playlist-mode-selected-at)) + (emms-stop) + (emms-next-noerror) + (kill-region (car region) + (cdr region)) + (emms-playlist-mode-kill-track)) + ((and (not emms-player-playing-p) + (emms-playlist-mode-selected-at)) + (kill-region (car region) + (cdr region)) + (emms-playlist-mode-kill-track)) + (t (error "Cannot kill content at point"))))) + +;;; -------------------------------------------------------- +;;; Overlay +;;; -------------------------------------------------------- + +(defun emms-playlist-mode-overlay-track (start end face) + (let ((o (make-overlay start end))) + (overlay-put o 'track t) + (overlay-put o 'face face))) + +(defun emms-playlist-mode-overlay-at (face) + (let ((o (make-overlay (point-at-bol) (point-at-eol)))) + (overlay-put o 'track t) + (overlay-put o 'face face))) + +;; Selected track overlaying track in constant time. +(defun emms-playlist-mode-overlay-selected () + (unless (null emms-playlist-mode-selected-overlay-marker) + (save-excursion + (goto-char emms-playlist-mode-selected-overlay-marker) + (remove-overlays (point) + (point-at-eol)))) + (save-excursion + (goto-char emms-playlist-selected-marker) + (setq emms-playlist-mode-selected-overlay-marker + (point-marker)) + (emms-playlist-mode-overlay-at + 'emms-playlist-selected-face)) + nil) + +;;; -------------------------------------------------------- +;;; Hooks +;;; -------------------------------------------------------- + +(add-hook 'emms-playlist-selection-changed-hook + 'emms-playlist-mode-overlay-selected) + +;;; -------------------------------------------------------- +;;; Entry +;;; -------------------------------------------------------- + +;; FIXME: everything is wrong here, implement non-twisted logic and an +;; interactive manner of selecting/creating a different playlist to +;; the current/default one. +(defun emms-playlist-mode-go (&optional pl-buffer) + (interactive) + (when (null pl-buffer) + (setq pl-buffer emms-playlist-buffer-name) + (when (not pl-buffer) + (setq pl-buffer (emms-playlist-new)))) + (switch-to-buffer pl-buffer) + (unless (eq major-mode 'emms-playlist-mode) + (emms-playlist-mode))) + +(defun emms-playlist-mode-startup () + (unless (or emms-playlist-selected-marker + emms-player-playing-p) + (emms-stop) + (emms-playlist-select-first)) + (when emms-playlist-selected-marker + (emms-playlist-mode-overlay-selected) + (goto-char (or emms-playlist-mode-selected-overlay-marker + (point-min))))) + +;;;###autoload +(defun emms-playlist-mode () + "A major mode for Emms playlists." + (interactive) + (kill-all-local-variables) + + ;; Even though Stefan Monnier warns against this, in this case I + ;; know what I'm doing. + (make-variable-buffer-local + 'emms-playlist-mode-selected-overlay-marker) + + (use-local-map emms-playlist-mode-map) + (setq major-mode 'emms-playlist-mode + mode-name "Emms-Playlist") + + ;; FIXME: *automatic* font-locking does not work and I have no idea + ;; why. Anyone who wants to fix it is more than welcomed to it. + (set (make-local-variable 'font-lock-defaults) + '(emms-playlist-mode-font-lock-keywords)) + + (emms-playlist-mode-startup) + + (run-hooks 'emms-playlist-mode-hooks)) + +(provide 'emms-playlist-mode) + +;;; emms-playlist-mode.el ends here. -- cgit v1.2.3