aboutsummaryrefslogtreecommitdiff
path: root/emms-tageditor.el
diff options
context:
space:
mode:
Diffstat (limited to 'emms-tageditor.el')
-rw-r--r--emms-tageditor.el449
1 files changed, 0 insertions, 449 deletions
diff --git a/emms-tageditor.el b/emms-tageditor.el
deleted file mode 100644
index 54832d5..0000000
--- a/emms-tageditor.el
+++ /dev/null
@@ -1,449 +0,0 @@
-;;; emms-tageditor.el --- Info-editor for EMMS
-
-;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
-
-;; Author: Ulrik Jensen <terryp@daimi.au.dk>
-;; Keywords:
-
-;; This file 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 2, or (at your option)
-;; any later version.
-
-;; This file 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 GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
-;; Boston, MA 02110-1301 USA
-
-;;; Commentary:
-
-;; This file provides an info-editor for EMMS. It also provides, as an
-;; option, functions for integrating this with the
-;; playlist-buffer-interface as well as the mark-module for the pbi.
-
-;; To activate the basic editor, use this in your EMMS-configuration:
-
-;; (require 'emms-tageditor)
-
-;; And call M-x emms-tageditor-edit-current RET, when you find a song
-;; with a tag that needs to be changed.
-
-;; To use the pbi-functionality, add the following to your
-;; configuration:
-
-;; (emms-tageditor-pbi-mode 1)
-
-;; Which will add 'e' as a key, to edit the track under the point in
-;; the pbi.
-
-;; To use the extended pbi-functionality, with `emms-pbi-mark', use:
-
-;; (emms-tageditor-pbi-mark-mode 1)
-
-;; Which likewise will bind 'E' to edit all the tracks marked as a
-;; whole, in a way that allows you to set the "album"-tag of each
-;; track, or f.ex. to match the filename to a regexp, and set a group
-;; from that regexp as the title-tag, or any other.
-
-;;; Code:
-
-(require 'emms)
-(require 'emms-info)
-(require 'emms-pbi)
-(require 'emms-pbi-mark)
-(require 'widget)
-(require 'wid-edit)
-
-;; Custom
-(defgroup emms-tageditor nil
- "*A wizard-style tageditor for EMMS."
- :group 'emms
- :prefix "emms-tageditor-")
-
-(defcustom emms-tageditor-buffer-name "*emms-tageditor*"
- "The name of the buffer used for tag-editing."
- :type 'string
- :group 'emms-tageditor)
-
-;; Variables
-(defvar emms-tageditor-current-tracks []
- "A vector of the tracks currently being edited.")
-
-(defvar emms-tageditor-current-infos []
- "A vector of the info-ojects currently being edited.")
-
-(defvar emms-tageditor-message nil
- "A message to show with the form, if non-nil.")
-
-(defvar emms-tageditor-widgets nil
- "A hash map of the widgets on the screen.")
-
-;; Hashtable interface
-(defun emms-tageditor-get-widget (trackidx fieldname)
- "Return the widget of FIELDNAME, for the track with TRACKIDX"
- (let ((symbol (emms-tageditor-get-widget-id trackidx fieldname)))
- (gethash symbol emms-tageditor-widgets)))
-
-(defun emms-tageditor-set-widget (trackidx fieldname widget)
- "Save a reference to WIDGET, as FIELDNAME of the track with TRACKIDX."
- (let ((symbol (emms-tageditor-get-widget-id trackidx fieldname)))
- (puthash symbol widget emms-tageditor-widgets)))
-
-;; Helper function for the hashtable
-(defun emms-tageditor-get-widget-id (trackidx fieldname)
- "Get a symbol ID of the FIELDNAME widget of TRACKIDX."
- (intern (concat "-trackidx-" (number-to-string trackidx)
- "-" (symbol-name fieldname))))
-
-(defun emms-tageditor-read-tag (trackidx)
- "Read the form for a single track, and parse it into an info-object."
- (let ((info (aref emms-tageditor-current-infos trackidx))
- (track (aref emms-tageditor-current-tracks trackidx))
- (tags '(title artist album note)))
- (while tags
- (let* ((tag (car tags))
- (infotag (intern (concat "emms-info-" (symbol-name tag)))))
- (eval `(setf (,infotag ,info)
- ,(widget-value (emms-tageditor-get-widget
- trackidx
- tag)))))
- (setq tags (cdr tags)))
- info))
-
-;; Parsing the form
-(defun emms-tageditor-read-tags (tracks)
- "Create a new list of info-object from the form, and return it."
- (mapcar 'emms-tageditor-read-tag tracks))
-
-;; Event-handling
-(defun emms-tageditor-save (widget &rest ignore)
- "Save the info of a single tag."
- ;; This function only saves a single form. Figure out which track
- ;; this is bound to, by extracting the trackidx from the
- (let* ((trackidx (widget-get widget :trackidx))
- (track (aref emms-tageditor-current-tracks trackidx)))
- ;; Let's make sure we have an info-source capable of writing tags.
- (if (funcall (emms-info-method-for track) 'set)
- (progn
- ;; we have an info-method for it, let's set it.
- (emms-info-set track
- (emms-tageditor-read-tag trackidx))
- (when (and (featurep 'emms-pbi)
- (get-buffer emms-pbi-playlist-buffer-name))
- ;; If a playlist is available, it's info might need to be updated
- ;; for this track.
- (emms-pbi-entry-update-track track)
- (when (= (length emms-tageditor-current-tracks) 1)
- ;; pressing save should kill the buffer when only one track is
- ;; being edited.
- (emms-tageditor-cleanup))))
- ;; if the above returned nil, no function to save info for this
- ;; track has been made! signal an error and escape!
- (message (format (concat "Track %s doesn't have an associated info-method "
- " capable of saving data")
- (emms-track-name track))))))
-
-(defun emms-tageditor-save-all ()
- "Save all entries currently being edited."
- ;; Loop through all forms, and save them
- (let ((idx 0))
- (while (< idx (length emms-tageditor-current-tracks))
- (emms-tageditor-save (emms-tageditor-get-widget idx 'save))
- (setq idx (1+ idx))))
- ;; Always cleanup when saving everything
- (emms-tageditor-cleanup))
-
-(defun emms-tageditor-cancel (&rest ignore)
- (emms-tageditor-cleanup))
-
-(defun emms-tageditor-create-string (rep times)
- "Concat TIMES occurances of REP into a string and return it."
- (if (> times 1)
- (concat (emms-tageditor-create-string rep (1- times)) rep)
- rep))
-
-;; Setting up the form, and destroying it
-(defun emms-tageditor-create-widgets (trackidx info)
- "Create widgets for a single track-form"
- (let ((inhibit-read-only t)
- (track (aref emms-tageditor-current-tracks trackidx))
- (info (aref emms-tageditor-current-infos trackidx)))
- (goto-char (point-min))
- (widget-insert (format "Editing tag for track: %s (%s)\n"
- (emms-track-name track)
- (symbol-name
- (emms-track-type track))))
- (widget-insert (concat "----------------------------------------"
- "----------------------------------------"
- "\n"))
- ;; Insert the tags
- (let ((tags '(title artist album note)))
- (while tags
- (let* ((tag (car tags))
- (info-tag (intern (concat "emms-info-" (symbol-name tag))))
- (tag-name
- (concat (upcase-initials (symbol-name tag)) ":"
- (emms-tageditor-create-string " "
- (- 10 (1+ (length (symbol-name tag))))))))
- (widget-insert tag-name)
- (eval `(emms-tageditor-set-widget
- trackidx (quote ,tag)
- (widget-create 'editable-field
- :size 69
- :trackidx trackidx
- :value (,info-tag ,info))))
- (when (not (= (length tags) 1))
- (widget-insert "\n")))
- (setq tags (cdr tags))))
- ;; Insert the rest
- (widget-insert (concat "\n"
- "----------------------------------------"
- "----------------------------------------"
- "\n"))
- (emms-tageditor-set-widget
- trackidx 'save
- (widget-create 'push-button
- :notify 'emms-tageditor-save
- :trackidx trackidx
- :help-echo "Save changes to this tag"
- "Save"))
- (widget-insert " ")
- (widget-create 'push-button
- :notify 'emms-tageditor-cancel
- :help-echo "Cancel changes"
- "Cancel")))
-
-(defun emms-tageditor-cleanup ()
- "Clean up and exit the tageditor."
- ;; delete all widgets
- (let ((idx 0))
- (while (< idx (length emms-tageditor-current-tracks))
- (when emms-tageditor-widgets
- (let ((tags '(title artist album note save)))
- (while tags
- (let ((tag (car tags)))
- (eval `(widget-delete (emms-tageditor-get-widget idx tag))))
- (setq tags (cdr tags)))))
- ;; continue idx loop
- (setq idx (1+ idx))))
- ;; kill the buffer & delete the hashmap
- (setq emms-tageditor-widgets nil)
- (kill-buffer (get-buffer-create emms-tageditor-buffer-name)))
-
-(defun emms-tageditor-replace-create-replacement (replace-with trackidx)
- (let ((info (aref emms-tageditor-current-infos trackidx))
- (track (aref emms-tageditor-current-tracks trackidx)))
- (setq replace-with (emms-replace-regexp-in-string "$TITLE" (emms-info-title info) replace-with))
- (setq replace-with (emms-replace-regexp-in-string "$ALBUM" (emms-info-album info) replace-with))
- (setq replace-with (emms-replace-regexp-in-string "$ARTIST" (emms-info-artist info) replace-with))
- (setq replace-with (emms-replace-regexp-in-string "$NOTE" (emms-info-note info) replace-with))
- (setq replace-with (emms-replace-regexp-in-string "$TRACKNAME" (emms-track-name track) replace-with)))
- replace-with)
-
-(defun emms-tageditor-replace-tag (field regexp replace-with)
- "Replace REGEXP with REPLACE-WITH in all fields of type FIELD."
- (let ((idx 0))
- (while (< idx (length emms-tageditor-current-tracks))
- ;; Find the widget for the current track
- (let ((widget (emms-tageditor-get-widget idx field)))
- (let* ((str (widget-value widget))
- (str (emms-replace-regexp-in-string regexp replace-with str)))
- (if (string= "$SET" regexp)
- (widget-value-set
- widget
- (emms-tageditor-replace-create-replacement replace-with idx))
- (widget-value-set
- widget
- (emms-tageditor-replace-create-replacement str idx)))))
- (setq idx (1+ idx)))))
-
-(defun emms-tageditor-replace-tags (&optional field regexp replace-with)
- "Replace REGEXP with REPLACE-WITH in the widgets matching FIELD."
- (interactive)
- (setq field (or field (intern (completing-read
- "Select which tags to replace in: "
- '(("all" . all) ("title" . title)
- ("artist" . artist) ("album" . album)
- ("note" . note))
- nil t "title"))))
- (setq regexp (or regexp (read-from-minibuffer "Regexp to replace: ")))
- (setq replace-with (or replace-with (read-from-minibuffer (concat "Replace regexp " regexp " with: "))))
- ;; Having all input, let's continue to act on it.
- (when (and field regexp replace-with)
- ;; two cases, 'all or something else
- (if (equal field 'all)
- (progn
- ;; We need a sweep-search of all tag-fields
- (let ((tags '(title artist album note)))
- (while tags
- (emms-tageditor-replace-tag (car tags) regexp replace-with)
- (setq tags (cdr tags)))))
- ;; only search the field called field
- (emms-tageditor-replace-tag field regexp replace-with))
- ;; we've probably changed some widget values, so we need to make
- ;; them count.
- (widget-setup)))
-
-;; Setting up the buffer
-(defun emms-tageditor-edit (tracks &optional infos)
- "Open an editor for the vector TRACKS.
-
-Optionally, use the vector INFOS as the default info for each track,
-and use the function SAVEFUNCTION as the event-handler for each
-save-button."
- ;; Save variables
- (setq emms-tageditor-current-tracks tracks)
- (if infos
- (setq emms-tageditor-current-infos infos)
- ;; Otherwise, create the vector of infos by loading them.
- (setq emms-tageditor-current-infos
- (make-vector (length emms-tageditor-current-tracks)
- nil))
- (let ((idx 0))
- (while (< idx (length emms-tageditor-current-tracks))
- (setf (aref emms-tageditor-current-infos idx)
- ;; should we allow cache here?
- (emms-info-get (aref emms-tageditor-current-tracks idx)))
- (setq idx (1+ idx)))))
- ;; Kill the buffer, then recreate it. Otherwise, everything will be
- ;; in one big widget.
- (kill-buffer (get-buffer-create emms-tageditor-buffer-name))
- (switch-to-buffer (get-buffer-create emms-tageditor-buffer-name))
- ;; Initialise buffer
- (kill-all-local-variables)
- (widget-minor-mode 1)
- ;; Setup widget hashmap,
- (setq emms-tageditor-widgets (make-hash-table :test 'equal))
- ;; and create the widgets
- (let ((idx 0))
- (while (< idx (length emms-tageditor-current-tracks))
- (emms-tageditor-create-widgets idx
- (aref emms-tageditor-current-infos idx))
- (widget-insert "\n\n")
- (setq idx (1+ idx)))
- ;; Create the save _all_ widget?
- ;; setup the help-message
- (when emms-tageditor-message
- (goto-char (point-max))
- (widget-insert (concat "\n"
- "........................................"
- "........................................"
- "\n"))
- (widget-insert emms-tageditor-message)
- (setq emms-tageditor-message nil))
- (use-local-map widget-keymap)
- ;; Bind some additional keys
- (widget-setup)
- (local-set-key (kbd "C-x C-s") (lambda () (interactive) (emms-tageditor-save-all)))
- (local-set-key (kbd "C-c C-r") 'emms-tageditor-replace-tags)
- (local-set-key (kbd "ESC") (lambda () (interactive) (emms-tageditor-cancel)))))
-
-;; Entry function
-(defun emms-tageditor-edit-current ()
- "Edit the info of the currently playing track"
- (interactive)
- (emms-tageditor-edit (vconcat (list (emms-playlist-current-track)))))
-
-;; Integrating with emms-pbi
-(defvar emms-tageditor-pbi-mark-message
- "When editing multiple files, some things works a bit
-differently. First of all, to save *all* changes made to tracks, use
-C-x C-s.
-
-The changes to each individual track, can be saved by using the
-corresponding Save-buttons.
-
-To utilize the full power of this mode of editing, you should use
-M-x emms-tageditor-replace-tags RET, bound to C-c C-r.
-
-When using `emms-tageditor-replace-tags', you have the following
-special keyword available:
-
-For matching:
-
- $SET -- Attempting to replace this value with anything, will tell
- the function to simply override the previous value.
-
-For what to replace with:
-
- $TRACKNAME -- The trackname (for file-type tracks, the full filename)
- $TITLE -- The (saved) title of this track.
- $ARTIST -- Likewise, with the artist
- $ALBUM -- Likewise, with the album
- $ALBUM -- Likewise, with the note.
-
-NOT IMPLEMENTED YET:
-If the power of that function doesn't fit your needs, you can use M-x
-emms-tageditor-toggle-read-only RET, bound to C-c C-t. This function
-will make the buffer read-only, which means you can use the regular
-editing functions on the entire buffer. This means that doing an M-x
-replace-regexp RET, won't halt if it matches any of the text outsie
-widgets, as it would otherwise.")
-
-(defun emms-tageditor-pbi-mode (&optional arg)
- "Register the intergration with the playlist-buffer interface for EMMS.
-
-Turn the registration on, if and only if ARG is a positive integer,
-off otherwise."
- (interactive "p")
- (if (not (featurep 'emms-pbi))
- (message "You need `emms-pbi' loaded to use this!")
- (if (and (numberp arg) (< 0 arg))
- (add-hook 'emms-pbi-mode-hook 'emms-tageditor-pbi-register)
- (remove-hook 'emms-pbi-mode-hook 'emms-tageditor-pbi-register))))
-
-(defun emms-tageditor-pbi-register ()
- "Register keybindings for the playlist-buffer interface.
-
-Should be run in `emms-pbi-mode-hook'."
- (local-set-key (kbd "e")
- 'emms-tageditor-pbi-edit-current-line))
-
-(defun emms-tageditor-pbi-edit-current-line ()
- "Edit the track under point."
- (interactive)
- (if (not (featurep 'emms-pbi))
- (message "You need `emms-pbi' loaded to use this!")
- ;; Fetch track under current line
- (let ((curidx (emms-pbi-return-current-line-index)))
- (when (emms-pbi-valid-index-p curidx)
- (other-window 1)
- (emms-tageditor-edit (vconcat (list (emms-playlist-get-track curidx))))))))
-
-;; Integrating with pbi-mark
-(defun emms-tageditor-pbi-mark-mode (&optional arg)
- "Register the intergration with the playlist-buffer-marks for EMMS.
-
-Turn the integration on, if and only if ARG is a positive integer, off
-otherwise."
- (interactive "p")
- (if (not (featurep 'emms-pbi-mark))
- (message "You need `emms-pbi-mark' loaded to use this!")
- (if (and (numberp arg) (< 0 arg))
- (add-hook 'emms-pbi-mode-hook 'emms-tageditor-pbi-mark-register)
- (remove-hook 'emms-pbi-mode-hook 'emms-tageditor-pbi-mark-register))))
-
-(defun emms-tageditor-pbi-mark-register ()
- "Register keybindings for the playlist-buffer interface marking functions.
-
-Should be run in `emms-pbi-mode-hook'."
- (local-set-key (kbd "E")
- 'emms-tageditor-pbi-mark-edit-marked-entries))
-
-(defun emms-tageditor-pbi-mark-edit-marked-entries ()
- "Edit all marked entries as one, using a special editor."
- (interactive)
- (if (not (featurep 'emms-pbi-mark))
- (message "You need `emms-pbi-mark' loaded to use this!")
- (other-window 1)
- (setq emms-tageditor-message emms-tageditor-pbi-mark-message)
- (emms-tageditor-edit (vconcat (emms-pbi-mark-get-marked)))
- (goto-char (point-min))))
-
-(provide 'emms-tageditor)
-;;; emms-tageditor.el ends here