aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--emms-cache.el79
-rw-r--r--emms-info.el88
-rw-r--r--emms-setup.el11
-rw-r--r--emms.el17
4 files changed, 113 insertions, 82 deletions
diff --git a/emms-cache.el b/emms-cache.el
new file mode 100644
index 0000000..dcda390
--- /dev/null
+++ b/emms-cache.el
@@ -0,0 +1,79 @@
+;;; emms-cache.el --- persistence for emms-track
+
+;; Copyright (C) 2006 Damien Elmes <resolve@repose.cx>
+
+;; Author: Damien Elmes <damien@repose.cx>
+;; Keywords: emms, mp3, mpeg, multimedia
+
+;; 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., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; The cache is a mapping of a full path name to information, and so
+;; it is invalidated when you rename or move files about. It also does
+;; not differentiate between file or uri tracks.
+
+;; Because cache lookups are much faster than disk access, this works
+;; much better with a later-do-interval of something like 0.001. Also
+;; consider using synchronous mode, as it's quite fast now.
+
+;; This code is activated by (emms-standard) and above.
+
+;;; Code:
+
+(define-hash-table-test 'string-hash 'string= 'sxhash)
+(defvar emms-cache-db (make-hash-table :test 'string-hash)
+ "A mapping of paths to file info.
+This is used to cache over emacs sessions.")
+
+(defvar emms-cache-file "~/.emms-cache"
+ "A file used to store cached file info information over sessions")
+
+(defvar emms-cache-dirty nil
+ "True if the cache has been updated since init.")
+
+(defun emms-cache-get (path)
+ "Return a cache element for PATH, or nil."
+ (gethash path emms-cache-db))
+
+(defun emms-cache-set (path track)
+ "Set PATH to TRACK in the cache."
+ (puthash path track emms-cache-db)
+ (setq emms-cache-dirty t))
+
+(defun emms-cache-save ()
+ "Save the track cache to a file."
+ (when emms-cache-dirty
+ (message "Saving emms track cache...")
+ (set-buffer (get-buffer-create " emms-cache "))
+ (erase-buffer)
+ (maphash (lambda (k v)
+ (insert (format
+ "(puthash %S '%S emms-cache-db)\n" k v)))
+ emms-cache-db)
+ (set-buffer-file-coding-system 'mule-utf-8)
+ (write-region (point-min) (point-max) emms-cache-file)
+ (kill-buffer (current-buffer))
+ (message "Saving emms track cache...done")
+ (setq emms-cache-dirty nil)))
+
+(defun emms-cache-restore ()
+ "Restore the track cache from a file."
+ (load emms-cache-file t nil t)
+ (setq emms-cache-dirty nil))
+
+(provide 'emms-cache)
+;;; emms-cache.el ends here
diff --git a/emms-info.el b/emms-info.el
index c4533bd..0edeb85 100644
--- a/emms-info.el
+++ b/emms-info.el
@@ -67,33 +67,6 @@ Each is called with a track as argument."
(defvar emms-info-asynchronous-tracks 0
"Number of tracks we're waiting for to be done.")
-;; cache support (break into a separate file and make
-;; emms-info-really-initialize-track into a variable controlling which
-;; function to use)?
-
-;; The cache is invalidated when track names are changed. It also does
-;; not differenciate between file or uri tracks, and relies on the
-;; uniqueness of the name.
-
-;; usage - in your .emacs
-
-;; (add-hook 'after-init-hook 'emms-info-cache-restore)
-;; (add-hook 'kill-emacs-hook 'emms-info-cache-save)
-
-;; this is works much better with a later-do-interval of something
-;; like 0.001
-
-(define-hash-table-test 'string-hash 'string= 'sxhash)
-(defvar emms-info-cache (make-hash-table :test 'string-hash)
- "A mapping of paths to file info.
-This is used to cache file info over emacs sessions.")
-
-(defvar emms-info-cache-file "~/.emms-cache"
- "A file used to store cached file info information over sessions")
-
-(defvar emms-info-cache-dirty nil
- "True if the cache has been updated since init.")
-
(defun emms-info-initialize-track (track)
"Initialize TRACK with emms-info information.
This is a suitable value for `emms-track-initialize-functions'."
@@ -107,34 +80,18 @@ This is a suitable value for `emms-track-initialize-functions'."
Return t when the track got changed."
(let ((file-mtime (when emms-info-auto-update
(emms-info-track-file-mtime track)))
- (name (emms-track-get track 'name))
- cached-track
- updated)
-
- (when (setq cached-track (gethash name emms-info-cache))
- ;; We need to modify TRACK. This way we lose information already
- ;; present in TRACK, which is not necessarily what we want, but
- ;; it's efficient.
- (setcar track (car cached-track))
- (setcdr track (cdr cached-track)))
-
- ;; if uncached, or cached and the time has changed
- (when (or (not cached-track)
- (and cached-track
- emms-info-auto-update
- (let ((info-mtime (emms-track-get track 'info-mtime)))
- (or (not (consp info-mtime))
- (emms-time-less-p info-mtime file-mtime)))))
- (setq updated t)
- (run-hook-with-args 'emms-info-functions track))
-
- (emms-track-set track 'info-mtime file-mtime)
- (emms-track-updated track)
-
- (when (or (not cached-track)
- updated)
- (puthash name track emms-info-cache)
- (setq emms-info-cache-dirty t))
+ (info-mtime (emms-track-get track 'info-mtime))
+ (name (emms-track-get track 'name)))
+
+ ;; if the file's been modified or is new
+ (when (or (not info-mtime)
+ (emms-time-less-p
+ info-mtime file-mtime))
+ (run-hook-with-args 'emms-info-functions track)
+ ;; not set by info functions
+ (emms-track-set track 'info-mtime file-mtime)
+ (funcall emms-cache-set-function name track)
+ (emms-track-updated track))
(when emms-info-asynchronously
(setq emms-info-asynchronous-tracks (1- emms-info-asynchronous-tracks))
@@ -142,27 +99,6 @@ Return t when the track got changed."
(message "EMMS: All track information loaded.")))
t))
-(defun emms-info-cache-save ()
- "Save the info cache to a file."
- (when emms-info-cache-dirty
- (message "Saving emms info cache...")
- (set-buffer (get-buffer-create " emms-info-cache "))
- (erase-buffer)
- (maphash (lambda (k v)
- (insert (format
- "(puthash %S '%S emms-info-cache)\n" k v)))
- emms-info-cache)
- (set-buffer-file-coding-system 'mule-utf-8)
- (write-region (point-min) (point-max) emms-info-cache-file)
- (kill-buffer (current-buffer))
- (message "Saving emms info cache...done")
- (setq emms-info-cache-dirty nil)))
-
-(defun emms-info-cache-restore ()
- "Restore the info cache from a file."
- (load emms-info-cache-file t nil t)
- (setq emms-info-cache-dirty nil))
-
(defun emms-info-track-file-mtime (track)
"Return the mtime of the file of TRACK, if any.
Return zero otherwise."
diff --git a/emms-setup.el b/emms-setup.el
index b6fbd1d..b6fd534 100644
--- a/emms-setup.el
+++ b/emms-setup.el
@@ -64,8 +64,8 @@ Invisible playlists and all the basics for playing media."
(defun emms-standard ()
"An Emms setup script.
Everything included in the `emms-minimalistic' setup, the Emms
-interactive playlist mode and reading information from tagged
-audio files."
+interactive playlist mode, reading information from tagged
+audio files, and a metadata cache."
;; include
(emms-minimalistic)
;; define
@@ -73,12 +73,17 @@ audio files."
(require 'emms-info)
(require 'emms-info-mp3info)
(require 'emms-info-ogginfo)
+ (require 'emms-cache)
;; setup
(setq emms-playlist-default-major-mode 'emms-playlist-mode)
(add-to-list 'emms-track-initialize-functions 'emms-info-initialize-track)
(add-to-list 'emms-info-functions 'emms-info-mp3info)
(add-to-list 'emms-info-functions 'emms-info-ogginfo)
- (setq emms-track-description-function 'emms-info-track-description))
+ (setq emms-track-description-function 'emms-info-track-description)
+ (add-hook 'after-init-hook 'emms-cache-restore)
+ (add-hook 'kill-emacs-hook 'emms-cache-save)
+ (setq emms-cache-get-function 'emms-cache-get)
+ (setq emms-cache-set-function 'emms-cache-set))
(defun emms-all ()
"An Emms setup script.
diff --git a/emms.el b/emms.el
index 42f5f8f..1070b23 100644
--- a/emms.el
+++ b/emms.el
@@ -223,6 +223,11 @@ seconds the player did seek."
This can be used if the source depends on the current buffer not
being the playlist buffer.")
+(defvar emms-cache-get-function (lambda (path))
+ "A function to retrieve a track entry from the cache.")
+(defvar emms-cache-set-function (lambda (path track))
+ "A function to add/set a track entry from the cache.")
+
;;; User Interface
@@ -453,9 +458,15 @@ whenever possible."
(defun emms-track (type name)
"Create an EMMS track with type TYPE and name NAME."
- (let ((track (emms-dictionary '*track*)))
- (emms-track-set track 'type type)
- (emms-track-set track 'name name)
+ (let (track)
+ ;; we assume that name is unique across types, so type is not used
+ ;; if we find name in the cache
+ (unless (setq track (funcall emms-cache-get-function name))
+ (setq track (emms-dictionary '*track*))
+ (emms-track-set track 'type type)
+ (emms-track-set track 'name name))
+ ;; run any hooks regardless of a cache hit, as the entry may be
+ ;; old
(run-hook-with-args 'emms-track-initialize-functions track)
track))