From e73db75f5474190399ab6d340cc9c8e0a8e78d6c Mon Sep 17 00:00:00 2001 From: Michael Olson Date: Thu, 7 Dec 2006 14:19:00 +0000 Subject: Rename emms-mp3tag.el to emms-tag-editor.el darcs-hash:20061207141945-1bfb2-bec40763ab0162499c3829e073717915ba509653.gz --- emms-mp3tag.el | 400 ----------------------------------------------------- emms-tag-editor.el | 400 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 400 insertions(+), 400 deletions(-) delete mode 100644 emms-mp3tag.el create mode 100644 emms-tag-editor.el diff --git a/emms-mp3tag.el b/emms-mp3tag.el deleted file mode 100644 index 8580393..0000000 --- a/emms-mp3tag.el +++ /dev/null @@ -1,400 +0,0 @@ -;;; emms-mp3tag.el --- Edit track tags. - -;; Copyright 2006 Ye Wenbin -;; -;; Author: wenbinye@163.com -;; Keywords: -;; X-URL: not distributed yet - -;; This program 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 program 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 this program; if not, write to the Free Software -;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; - -;; Put this file into your load-path and the following into your ~/.emacs: -;; (require 'emms-mp3tag) - -;;; Code: - -(provide 'emms-mp3tag) -(eval-when-compile - (require 'cl)) -(require 'emms) -(require 'emms-info-mp3info) -(require 'emms-playlist-mode) -(require 'emms-mark) -(require 'format-spec) - -(defvar emms-mp3tag-tags - '((info-artist . "a") - (info-title . "t") - (info-album . "l") - (info-tracknumber . "n") - (info-year . "y") - (info-genre . "g") - (info-date . "d") - (info-note . "c")) -"A list to setup format.") - -(defvar emms-mp3tag-edit-buffer "*EMMS-TAGS*" - "Buffer name to edit mp3 tags") -(defvar emms-mp3tag-log-buffer "*EMMS-LOG*" - "Buffer name of mp3tag edit log") - -(defun emms-mp3tag-make-format (tags) - (format "%%m\n%-16s = %%f\n%s\n\n" "name" - (mapconcat - (lambda (tag) - (concat (propertize (format "%-16s = " (symbol-name tag)) - 'read-only t 'rear-nonsticky t 'face 'bold) - "%" (cdr (assoc tag emms-mp3tag-tags)))) - tags "\n"))) - -(defvar emms-mp3tag-formats - (let* ((tags (mapcar 'car emms-mp3tag-tags)) - (default (emms-mp3tag-make-format (remove 'info-date tags)))) - `(("mp3" . ,default) - ("ogg" . ,(emms-mp3tag-make-format (remove 'info-year tags))) - ("default" . ,default))) - "Format to insert the track. The CAR part is the extension of the -track name, and the CDR part is the format template. The format -specification is like: - m -- Track description - f -- Track name - a -- Track info-artist - t -- Track info-title - l -- Track info-album - n -- Track info-tracknumber - y -- Track info-year - g -- Track info-genre - c -- Track info-note - -You can add new specification in `emms-mp3tag-tags' and use -`emms-mp3tag-make-format' to help create a new format. - -The CDR part also can be a function, which accept one parameter, the -track, and should return a string to insert to `emms-mp3tag-edit-buffer'. -") - -(defvar emms-mp3tag-get-format-function 'emms-mp3tag-get-format - "Function to decide which format to use for format the track.") - -(defvar emms-mp3tag-parse-function 'emms-mp3tag-default-parser - "Function to parse tags in `emms-mp3tag-edit-buffer'. It should find -all modified tags, and return all the tracks. The tracks which tag has -been modified should set a property 'tag-modified to t, and if the -track name have been change, the function should set a new property -'newname instead set the 'name directly. - -See also `emms-mp3tag-default-parser'.") - -(defvar emms-mp3tag-tagfile-functions - '(("mp3" "mp3info" - ((info-artist . "a") - (info-title . "t") - (info-album . "l") - (info-tracknumber . "n") - (info-year . "y") - (info-genre . "g") - (info-note . "c"))) - ("ogg" . emms-mp3tag-tag-ogg)) - "A List for change tag in files. If the extern program set tag by -command line options one by one such as mp3info, the list should like: - (EXTENSION PROGRAM COMMAND_LINE_OPTIONS) - -Otherwise, a function that accept a parameter, the track, should be -given. - -See also `emms-mp3tag-tag-file' and `emms-mp3tag-tag-ogg'. -") - -(defun emms-mp3tag-tag-ogg (track) - (call-process "vorbiscomment" nil nil nil - "-w" "-t" - (mapconcat - (lambda (tag) - (concat tag "=" - (emms-track-get track (intern (concat "info-" tag))))) - '("artist" "title" "album" "tracknumber" "date" "genre" "note") - "\n\t") - (emms-track-name track))) - -(defun emms-mp3tag-tag-file (track program tags) - "Change tag in FILE use PROGRAM. The TAGS is given in `emms-mp3tag-tagfile-functions'." - (let (args val) - (mapc (lambda (tag) - (when (> (length (setq val (emms-track-get track (car tag)))) 0) - (setq args (append args (list (concat "-" (cdr tag)) val))))) - tags) - (apply 'call-process program - nil nil nil - filename args))) - -(defun emms-mp3tag-get-format (track) - (let ((format - (assoc (file-name-extension (emms-track-name track)) - emms-mp3tag-formats))) - (if format - (cdr format) - (cdr (assoc "default" emms-mp3tag-formats))))) - -(defun emms-mp3tag-format-track (track) - (let ((format (funcall emms-mp3tag-get-format-function track))) - (if (functionp format) - (funcall format track) - (format-spec - format - (apply 'format-spec-make - ?m (emms-propertize (emms-track-force-description track) - 'face 'emms-playlist-track-face - 'emms-track (copy-sequence track)) - ?f (emms-track-name track) - (apply 'append - (mapcar (lambda (tag) - (list (string-to-char (cdr tag)) - (or (emms-track-get track (car tag)) ""))) - emms-mp3tag-tags))))))) - -(defun emms-mp3tag-track-at (&optional pos) - (let ((track (emms-playlist-track-at pos)) - newtrack) - (when track - (setq newtrack (copy-sequence track)) - (emms-track-set newtrack 'position (point-marker)) - (emms-track-set newtrack 'orig-track track) - newtrack))) - -(defsubst emms-mp3tag-erase-buffer (&optional buf) - (let ((inhibit-read-only t)) - (save-excursion - (set-buffer (get-buffer-create buf)) - (erase-buffer)))) - -(defsubst emms-mp3tag-insert-track (track) - (and track - (insert (emms-mp3tag-format-track track)))) - -(defsubst emms-mp3tag-display-log-buffer-maybe () - (if (> (buffer-size (get-buffer emms-mp3tag-log-buffer)) 0) - (display-buffer emms-mp3tag-log-buffer))) - -(defun emms-mp3tag-insert-tracks (tracks) - (save-excursion - (emms-mp3tag-erase-buffer emms-mp3tag-log-buffer) - (emms-mp3tag-erase-buffer emms-mp3tag-edit-buffer) - (set-buffer (get-buffer emms-mp3tag-edit-buffer)) - (mapc 'emms-mp3tag-insert-track tracks) - (emms-mp3tag-mode) - (pop-to-buffer (current-buffer)) - (goto-char (point-min)) - (emms-mp3tag-display-log-buffer-maybe))) - -(defun emms-mp3tag-edit-track (track) - (interactive (list (emms-mp3tag-track-at))) - (if (null track) - (message "No track at point!") - (emms-mp3tag-insert-tracks (list track)))) - -(defun emms-mp3tag-edit-marked-tracks () - (interactive) - (let ((tracks (emms-mark-mapcar-marked-track 'emms-mp3tag-track-at t))) - (if (null tracks) - (message "No track marked!") - (emms-mp3tag-insert-tracks tracks)))) - -(defun emms-mp3tag-edit () - "Edit tags of track at point or marked tracks" - (interactive) - (if (emms-mark-has-markedp) - (emms-mp3tag-edit-marked-tracks) - (emms-mp3tag-edit-track (emms-mp3tag-track-at)))) - -(defvar emms-mp3tag-mode-map - (let ((map (make-sparse-keymap))) - (define-key map [tab] 'emms-mp3tag-next-field) - (define-key map [backtab] 'emms-mp3tag-prev-field) - (define-key map "\C-c\C-n" 'emms-mp3tag-next-track) - (define-key map "\C-c\C-p" 'emms-mp3tag-prev-track) - (define-key map "\C-c\C-c" 'emms-mp3tag-submit-and-exit) - (define-key map "\C-c\C-s" 'emms-mp3tag-submit) - (define-key map "\C-c\C-r" 'emms-mp3tag-replace-all) - map)) -(define-key emms-playlist-mode-map "E" 'emms-mp3tag-edit) - -(define-derived-mode emms-mp3tag-mode text-mode "Mp3tag" - "Major mode to edit track tags. -\\{emms-mp3tag-mode-map}") - -(defun emms-mp3tag-replace-all (name value) - "Replace all track's NAME to VALUE. If turn transient-mark-mode on, -you can apply the command to a selected region." - (interactive - (list (completing-read "Replace tag: " - emms-mp3tag-tags nil t) - (read-from-minibuffer "Set tag to: "))) - (save-excursion - (save-restriction - (if (and mark-active transient-mark-mode) - (narrow-to-region (region-beginning) (region-end))) - (goto-char (point-min)) - (while (re-search-forward (concat "^" (regexp-quote name)) nil t) - (skip-chars-forward " \t=") - (delete-region (point) (line-end-position)) - (insert value))))) - -(defun emms-mp3tag-next-field (arg) - (interactive "p") - (if (> arg 0) - (re-search-forward "\\s-*=[ \t]*" nil nil arg) - (emms-mp3tag-prev-field (- arg)))) - -(defun emms-mp3tag-prev-field (arg) - (interactive "p") - (if (< arg 0) - (emms-mp3tag-next-field (- arg)) - (skip-chars-backward " \t=") - (re-search-backward "\\s-*=[ \t]*" nil nil arg) - (skip-chars-forward " \t="))) - -(defun emms-mp3tag-prev-track () - (interactive) - (let ((prev (previous-single-property-change (point) - 'emms-track))) - (when (not prev) - (error "No previous track")) - (when (not (get-text-property prev 'emms-track)) - (setq prev (or (previous-single-property-change prev 'emms-track) - (point-min)))) - (when (or (not prev) - (not (get-text-property prev 'emms-track))) - (error "No previous track")) - (goto-char prev))) - -(defun emms-mp3tag-next-track () - (interactive) - (let ((next (next-single-property-change (point) - 'emms-track))) - (when (not next) - (error "No next track")) - (when (not (get-text-property next 'emms-track)) - (setq next (next-single-property-change next 'emms-track))) - (when (or (not next) - (= next (point-max))) - (error "No next track")) - (goto-char next))) - -(defun emms-mp3tag-submit (arg) - "Make modified tags take affect. With prefiex argument, bury tag -edit buffer." - (interactive "P") - (let ((tracks (funcall emms-mp3tag-parse-function)) - filename func exit old pos val need-sync) - (if (not (and tracks (y-or-n-p "Submit changes? "))) - (message "Nothing have to do!") - (emms-mp3tag-erase-buffer emms-mp3tag-log-buffer) - (message "Wait while set tags...") - (save-excursion - (dolist (track tracks) - (when (emms-track-get track 'tag-modified) - (setq filename (emms-track-name track) - old (emms-track-get track 'orig-track)) - ;; rename local file - (when (and (emms-track-get track 'newname) - (eq (emms-track-get track 'type) 'file) - (file-writable-p (emms-track-name track))) - (setq filename (emms-track-get track 'newname)) - (rename-file (emms-track-name track) filename) - (emms-track-set old 'name filename) - ;; for re-enter this function - (emms-track-set track 'newname nil) - (emms-track-set track 'name filename) - (setq need-sync t) - ;; register to emms-cache-db - (funcall emms-cache-modified-function) - (funcall emms-cache-set-function filename 'file old)) - ;; set tags to original track - (dolist (tag emms-mp3tag-tags) - (when (setq val (emms-track-get track (car tag))) - (emms-track-set old (car tag) val))) - ;; use mp3info to change tag in mp3 file - (when (and (eq (emms-track-get track 'type) 'file) - (file-writable-p (emms-track-name track)) - (setq func (assoc (file-name-extension filename) emms-mp3tag-tagfile-functions))) - (setq exit - (if (functionp (cdr func)) - (funcall (cdr func) track) - (emms-mp3tag-tag-file track (cadr func) (nth 2 func)))) - (if (zerop exit) - (emms-track-get track 'info-mtime (butlast (current-time))) - (emms-mp3tag-log "Change tags of %s failed with exit value %d" filename exit))) - ;; update track in playlist - (when (and (setq pos (emms-track-get track 'position)) - (marker-position pos)) - (set-buffer (marker-buffer pos)) - (goto-char pos) - (funcall emms-playlist-update-track-function)) - ;; clear modified tag - (emms-track-set track 'tag-modified nil)))) - (if (and need-sync (y-or-n-p "You have change some track names, sync the cache? ")) - (emms-cache-sync)) - (emms-mp3tag-display-log-buffer-maybe) - (message "Set all mp3 tag done!"))) - (if arg (bury-buffer))) - -(defun emms-mp3tag-submit-and-exit () - (interactive) - (emms-mp3tag-submit t)) - -(defun emms-mp3tag-default-parser () - (let (next tracks track key val) - (goto-char (point-min)) - (if (get-text-property (point) 'emms-track) - (setq next (point)) - (setq next (next-single-property-change (point) - 'emms-track))) - (when next - (while - (progn - (goto-char next) - (setq track (get-text-property (point) 'emms-track)) - (forward-line 1) - (mapc (lambda (pair) - (when (string-match "\\s-*=\\s-*" pair) - (setq key (intern-soft (substring pair 0 (match-beginning 0))) - val (substring pair (match-end 0))) - (when (and key - (> (length val) 0) - (not (string= val (emms-track-get track key)))) - (if (eq key 'name) - (emms-track-set track 'newname val) - (emms-track-set track key val)) - (emms-track-set track 'tag-modified t)))) - (split-string (buffer-substring (point) - (or - (setq next (next-single-property-change (point) 'emms-track)) - (point-max))) - "\n")) - (if (emms-track-get track 'tag-modified) - (push track tracks)) - next)) - tracks))) - -(defun emms-mp3tag-log (&rest args) - (with-current-buffer (get-buffer-create emms-mp3tag-log-buffer) - (goto-char (point-max)) - (insert (apply 'format args) "\n"))) - -;;; emms-mp3tagedit.el ends here diff --git a/emms-tag-editor.el b/emms-tag-editor.el new file mode 100644 index 0000000..8580393 --- /dev/null +++ b/emms-tag-editor.el @@ -0,0 +1,400 @@ +;;; emms-mp3tag.el --- Edit track tags. + +;; Copyright 2006 Ye Wenbin +;; +;; Author: wenbinye@163.com +;; Keywords: +;; X-URL: not distributed yet + +;; This program 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 program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +;;; Commentary: + +;; + +;; Put this file into your load-path and the following into your ~/.emacs: +;; (require 'emms-mp3tag) + +;;; Code: + +(provide 'emms-mp3tag) +(eval-when-compile + (require 'cl)) +(require 'emms) +(require 'emms-info-mp3info) +(require 'emms-playlist-mode) +(require 'emms-mark) +(require 'format-spec) + +(defvar emms-mp3tag-tags + '((info-artist . "a") + (info-title . "t") + (info-album . "l") + (info-tracknumber . "n") + (info-year . "y") + (info-genre . "g") + (info-date . "d") + (info-note . "c")) +"A list to setup format.") + +(defvar emms-mp3tag-edit-buffer "*EMMS-TAGS*" + "Buffer name to edit mp3 tags") +(defvar emms-mp3tag-log-buffer "*EMMS-LOG*" + "Buffer name of mp3tag edit log") + +(defun emms-mp3tag-make-format (tags) + (format "%%m\n%-16s = %%f\n%s\n\n" "name" + (mapconcat + (lambda (tag) + (concat (propertize (format "%-16s = " (symbol-name tag)) + 'read-only t 'rear-nonsticky t 'face 'bold) + "%" (cdr (assoc tag emms-mp3tag-tags)))) + tags "\n"))) + +(defvar emms-mp3tag-formats + (let* ((tags (mapcar 'car emms-mp3tag-tags)) + (default (emms-mp3tag-make-format (remove 'info-date tags)))) + `(("mp3" . ,default) + ("ogg" . ,(emms-mp3tag-make-format (remove 'info-year tags))) + ("default" . ,default))) + "Format to insert the track. The CAR part is the extension of the +track name, and the CDR part is the format template. The format +specification is like: + m -- Track description + f -- Track name + a -- Track info-artist + t -- Track info-title + l -- Track info-album + n -- Track info-tracknumber + y -- Track info-year + g -- Track info-genre + c -- Track info-note + +You can add new specification in `emms-mp3tag-tags' and use +`emms-mp3tag-make-format' to help create a new format. + +The CDR part also can be a function, which accept one parameter, the +track, and should return a string to insert to `emms-mp3tag-edit-buffer'. +") + +(defvar emms-mp3tag-get-format-function 'emms-mp3tag-get-format + "Function to decide which format to use for format the track.") + +(defvar emms-mp3tag-parse-function 'emms-mp3tag-default-parser + "Function to parse tags in `emms-mp3tag-edit-buffer'. It should find +all modified tags, and return all the tracks. The tracks which tag has +been modified should set a property 'tag-modified to t, and if the +track name have been change, the function should set a new property +'newname instead set the 'name directly. + +See also `emms-mp3tag-default-parser'.") + +(defvar emms-mp3tag-tagfile-functions + '(("mp3" "mp3info" + ((info-artist . "a") + (info-title . "t") + (info-album . "l") + (info-tracknumber . "n") + (info-year . "y") + (info-genre . "g") + (info-note . "c"))) + ("ogg" . emms-mp3tag-tag-ogg)) + "A List for change tag in files. If the extern program set tag by +command line options one by one such as mp3info, the list should like: + (EXTENSION PROGRAM COMMAND_LINE_OPTIONS) + +Otherwise, a function that accept a parameter, the track, should be +given. + +See also `emms-mp3tag-tag-file' and `emms-mp3tag-tag-ogg'. +") + +(defun emms-mp3tag-tag-ogg (track) + (call-process "vorbiscomment" nil nil nil + "-w" "-t" + (mapconcat + (lambda (tag) + (concat tag "=" + (emms-track-get track (intern (concat "info-" tag))))) + '("artist" "title" "album" "tracknumber" "date" "genre" "note") + "\n\t") + (emms-track-name track))) + +(defun emms-mp3tag-tag-file (track program tags) + "Change tag in FILE use PROGRAM. The TAGS is given in `emms-mp3tag-tagfile-functions'." + (let (args val) + (mapc (lambda (tag) + (when (> (length (setq val (emms-track-get track (car tag)))) 0) + (setq args (append args (list (concat "-" (cdr tag)) val))))) + tags) + (apply 'call-process program + nil nil nil + filename args))) + +(defun emms-mp3tag-get-format (track) + (let ((format + (assoc (file-name-extension (emms-track-name track)) + emms-mp3tag-formats))) + (if format + (cdr format) + (cdr (assoc "default" emms-mp3tag-formats))))) + +(defun emms-mp3tag-format-track (track) + (let ((format (funcall emms-mp3tag-get-format-function track))) + (if (functionp format) + (funcall format track) + (format-spec + format + (apply 'format-spec-make + ?m (emms-propertize (emms-track-force-description track) + 'face 'emms-playlist-track-face + 'emms-track (copy-sequence track)) + ?f (emms-track-name track) + (apply 'append + (mapcar (lambda (tag) + (list (string-to-char (cdr tag)) + (or (emms-track-get track (car tag)) ""))) + emms-mp3tag-tags))))))) + +(defun emms-mp3tag-track-at (&optional pos) + (let ((track (emms-playlist-track-at pos)) + newtrack) + (when track + (setq newtrack (copy-sequence track)) + (emms-track-set newtrack 'position (point-marker)) + (emms-track-set newtrack 'orig-track track) + newtrack))) + +(defsubst emms-mp3tag-erase-buffer (&optional buf) + (let ((inhibit-read-only t)) + (save-excursion + (set-buffer (get-buffer-create buf)) + (erase-buffer)))) + +(defsubst emms-mp3tag-insert-track (track) + (and track + (insert (emms-mp3tag-format-track track)))) + +(defsubst emms-mp3tag-display-log-buffer-maybe () + (if (> (buffer-size (get-buffer emms-mp3tag-log-buffer)) 0) + (display-buffer emms-mp3tag-log-buffer))) + +(defun emms-mp3tag-insert-tracks (tracks) + (save-excursion + (emms-mp3tag-erase-buffer emms-mp3tag-log-buffer) + (emms-mp3tag-erase-buffer emms-mp3tag-edit-buffer) + (set-buffer (get-buffer emms-mp3tag-edit-buffer)) + (mapc 'emms-mp3tag-insert-track tracks) + (emms-mp3tag-mode) + (pop-to-buffer (current-buffer)) + (goto-char (point-min)) + (emms-mp3tag-display-log-buffer-maybe))) + +(defun emms-mp3tag-edit-track (track) + (interactive (list (emms-mp3tag-track-at))) + (if (null track) + (message "No track at point!") + (emms-mp3tag-insert-tracks (list track)))) + +(defun emms-mp3tag-edit-marked-tracks () + (interactive) + (let ((tracks (emms-mark-mapcar-marked-track 'emms-mp3tag-track-at t))) + (if (null tracks) + (message "No track marked!") + (emms-mp3tag-insert-tracks tracks)))) + +(defun emms-mp3tag-edit () + "Edit tags of track at point or marked tracks" + (interactive) + (if (emms-mark-has-markedp) + (emms-mp3tag-edit-marked-tracks) + (emms-mp3tag-edit-track (emms-mp3tag-track-at)))) + +(defvar emms-mp3tag-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [tab] 'emms-mp3tag-next-field) + (define-key map [backtab] 'emms-mp3tag-prev-field) + (define-key map "\C-c\C-n" 'emms-mp3tag-next-track) + (define-key map "\C-c\C-p" 'emms-mp3tag-prev-track) + (define-key map "\C-c\C-c" 'emms-mp3tag-submit-and-exit) + (define-key map "\C-c\C-s" 'emms-mp3tag-submit) + (define-key map "\C-c\C-r" 'emms-mp3tag-replace-all) + map)) +(define-key emms-playlist-mode-map "E" 'emms-mp3tag-edit) + +(define-derived-mode emms-mp3tag-mode text-mode "Mp3tag" + "Major mode to edit track tags. +\\{emms-mp3tag-mode-map}") + +(defun emms-mp3tag-replace-all (name value) + "Replace all track's NAME to VALUE. If turn transient-mark-mode on, +you can apply the command to a selected region." + (interactive + (list (completing-read "Replace tag: " + emms-mp3tag-tags nil t) + (read-from-minibuffer "Set tag to: "))) + (save-excursion + (save-restriction + (if (and mark-active transient-mark-mode) + (narrow-to-region (region-beginning) (region-end))) + (goto-char (point-min)) + (while (re-search-forward (concat "^" (regexp-quote name)) nil t) + (skip-chars-forward " \t=") + (delete-region (point) (line-end-position)) + (insert value))))) + +(defun emms-mp3tag-next-field (arg) + (interactive "p") + (if (> arg 0) + (re-search-forward "\\s-*=[ \t]*" nil nil arg) + (emms-mp3tag-prev-field (- arg)))) + +(defun emms-mp3tag-prev-field (arg) + (interactive "p") + (if (< arg 0) + (emms-mp3tag-next-field (- arg)) + (skip-chars-backward " \t=") + (re-search-backward "\\s-*=[ \t]*" nil nil arg) + (skip-chars-forward " \t="))) + +(defun emms-mp3tag-prev-track () + (interactive) + (let ((prev (previous-single-property-change (point) + 'emms-track))) + (when (not prev) + (error "No previous track")) + (when (not (get-text-property prev 'emms-track)) + (setq prev (or (previous-single-property-change prev 'emms-track) + (point-min)))) + (when (or (not prev) + (not (get-text-property prev 'emms-track))) + (error "No previous track")) + (goto-char prev))) + +(defun emms-mp3tag-next-track () + (interactive) + (let ((next (next-single-property-change (point) + 'emms-track))) + (when (not next) + (error "No next track")) + (when (not (get-text-property next 'emms-track)) + (setq next (next-single-property-change next 'emms-track))) + (when (or (not next) + (= next (point-max))) + (error "No next track")) + (goto-char next))) + +(defun emms-mp3tag-submit (arg) + "Make modified tags take affect. With prefiex argument, bury tag +edit buffer." + (interactive "P") + (let ((tracks (funcall emms-mp3tag-parse-function)) + filename func exit old pos val need-sync) + (if (not (and tracks (y-or-n-p "Submit changes? "))) + (message "Nothing have to do!") + (emms-mp3tag-erase-buffer emms-mp3tag-log-buffer) + (message "Wait while set tags...") + (save-excursion + (dolist (track tracks) + (when (emms-track-get track 'tag-modified) + (setq filename (emms-track-name track) + old (emms-track-get track 'orig-track)) + ;; rename local file + (when (and (emms-track-get track 'newname) + (eq (emms-track-get track 'type) 'file) + (file-writable-p (emms-track-name track))) + (setq filename (emms-track-get track 'newname)) + (rename-file (emms-track-name track) filename) + (emms-track-set old 'name filename) + ;; for re-enter this function + (emms-track-set track 'newname nil) + (emms-track-set track 'name filename) + (setq need-sync t) + ;; register to emms-cache-db + (funcall emms-cache-modified-function) + (funcall emms-cache-set-function filename 'file old)) + ;; set tags to original track + (dolist (tag emms-mp3tag-tags) + (when (setq val (emms-track-get track (car tag))) + (emms-track-set old (car tag) val))) + ;; use mp3info to change tag in mp3 file + (when (and (eq (emms-track-get track 'type) 'file) + (file-writable-p (emms-track-name track)) + (setq func (assoc (file-name-extension filename) emms-mp3tag-tagfile-functions))) + (setq exit + (if (functionp (cdr func)) + (funcall (cdr func) track) + (emms-mp3tag-tag-file track (cadr func) (nth 2 func)))) + (if (zerop exit) + (emms-track-get track 'info-mtime (butlast (current-time))) + (emms-mp3tag-log "Change tags of %s failed with exit value %d" filename exit))) + ;; update track in playlist + (when (and (setq pos (emms-track-get track 'position)) + (marker-position pos)) + (set-buffer (marker-buffer pos)) + (goto-char pos) + (funcall emms-playlist-update-track-function)) + ;; clear modified tag + (emms-track-set track 'tag-modified nil)))) + (if (and need-sync (y-or-n-p "You have change some track names, sync the cache? ")) + (emms-cache-sync)) + (emms-mp3tag-display-log-buffer-maybe) + (message "Set all mp3 tag done!"))) + (if arg (bury-buffer))) + +(defun emms-mp3tag-submit-and-exit () + (interactive) + (emms-mp3tag-submit t)) + +(defun emms-mp3tag-default-parser () + (let (next tracks track key val) + (goto-char (point-min)) + (if (get-text-property (point) 'emms-track) + (setq next (point)) + (setq next (next-single-property-change (point) + 'emms-track))) + (when next + (while + (progn + (goto-char next) + (setq track (get-text-property (point) 'emms-track)) + (forward-line 1) + (mapc (lambda (pair) + (when (string-match "\\s-*=\\s-*" pair) + (setq key (intern-soft (substring pair 0 (match-beginning 0))) + val (substring pair (match-end 0))) + (when (and key + (> (length val) 0) + (not (string= val (emms-track-get track key)))) + (if (eq key 'name) + (emms-track-set track 'newname val) + (emms-track-set track key val)) + (emms-track-set track 'tag-modified t)))) + (split-string (buffer-substring (point) + (or + (setq next (next-single-property-change (point) 'emms-track)) + (point-max))) + "\n")) + (if (emms-track-get track 'tag-modified) + (push track tracks)) + next)) + tracks))) + +(defun emms-mp3tag-log (&rest args) + (with-current-buffer (get-buffer-create emms-mp3tag-log-buffer) + (goto-char (point-max)) + (insert (apply 'format args) "\n"))) + +;;; emms-mp3tagedit.el ends here -- cgit v1.2.3