From e5beab412bc06197c77b902c4939758b2a246684 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Wed, 7 Jun 2006 12:53:00 +0000 Subject: refactor caching code into emms-cache.el * caching support is now provided via two function vars in emms.el, emms-cache-get-function and emms-cache-set-function * (emms-standard) or above will enable caching support * you'll need to remove .emms-cache or s/emms-info-cache/emms-cache-db/ darcs-hash:20060607125345-4e3e3-7d9ad8d243a395f2f2a5eea004e58ac9e239855b.gz --- emms-cache.el | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ emms-info.el | 88 ++++++++--------------------------------------------------- emms-setup.el | 11 ++++++-- emms.el | 17 ++++++++++-- 4 files changed, 113 insertions(+), 82 deletions(-) create mode 100644 emms-cache.el 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 + +;; Author: Damien Elmes +;; 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)) -- cgit v1.2.3