aboutsummaryrefslogtreecommitdiff
path: root/emms-source-file.el
diff options
context:
space:
mode:
Diffstat (limited to 'emms-source-file.el')
-rw-r--r--emms-source-file.el314
1 files changed, 314 insertions, 0 deletions
diff --git a/emms-source-file.el b/emms-source-file.el
new file mode 100644
index 0000000..2be6538
--- /dev/null
+++ b/emms-source-file.el
@@ -0,0 +1,314 @@
+;;; emms-source-file.el --- EMMS sources from the filesystem.
+
+;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008,
+;; 2009 Free Software Foundation, Inc.
+
+;; Author: Jorgen Schäfer <forcer@forcix.cx>
+;; Keywords: emms, mp3, mpeg, multimedia
+
+;; This file is part of EMMS.
+
+;; EMMS 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 3, or (at your option)
+;; any later version.
+;;
+;; EMMS 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 EMMS; 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 contains a track source for EMMS that is based on the
+;; file system. You can retrieve single files or whole directories.
+;; Also, this file offers the commands to play from these sources.
+
+;;; Code:
+
+;; Version control
+(defvar emms-source-file-version "0.2 $Revision: 1.30 $"
+ "emms-source-file.el version string")
+;; $Id: emms-source-file.el,v 1.30 2005/08/11 06:16:15 yonirabkin Exp $
+
+;;; User Customization
+
+(require 'emms)
+(require 'dired)
+(require 'locate)
+(eval-when-compile
+ (condition-case nil
+ (require 'locate)
+ (error nil)))
+(require 'dired)
+
+(defgroup emms-source-file nil
+ "*Sources for EMMS that use the file system."
+ :prefix "emms-source-file-"
+ :group 'emms-source)
+
+(defcustom emms-source-file-default-directory nil
+ "*The default directory to look for media files."
+ :type '(choice (const :tag "None" nil) file)
+ :group 'emms-source-file)
+
+(defcustom emms-source-file-directory-tree-function
+ 'emms-source-file-directory-tree-internal
+ "*A function to call that searches in a given directory all files
+that match a given regex. DIR and REGEX are the only arguments passed
+to this function.
+You have two build-in options:
+`emms-source-file-directory-tree-internal' will work always, but might
+be slow.
+`emms-source-file-directory-tree-find' will work only if you have GNU
+find, but it's faster."
+ :type 'function
+ :options '(emms-source-file-directory-tree-internal
+ emms-source-file-directory-tree-find)
+ :group 'emms-source-file)
+
+(defcustom emms-source-file-exclude-regexp
+ (concat "\\`\\(#.*#\\|.*,v\\|.*~\\|\\.\\.?\\|\\.#.*\\|,.*\\)\\'\\|"
+ "/\\(CVS\\|RCS\\|\\.arch-ids\\|{arch}\\|,.*\\|\\.svn\\|"
+ "_darcs\\)\\(/\\|\\'\\)")
+ "A regexp matching files to be ignored when adding directories.
+
+You should set case-fold-search to nil before using this regexp
+in code."
+ :type 'regexp
+ :group 'emms-source-file)
+
+(defcustom emms-source-file-gnu-find "find"
+ "*The program name for GNU find."
+ :type 'string
+ :group 'emms-source-file)
+
+(defcustom emms-source-file-directory-hint-p t
+ "*When non-nil, guess the directory based on a track at point."
+ :type 'boolean
+ :group 'emms-source-file)
+
+;; The `read-directory-name' function is not available in Emacs 21.
+(defalias 'emms-read-directory-name
+ (if (fboundp 'read-directory-name)
+ #'read-directory-name
+ #'read-file-name))
+
+(defun emms-source-file-directory-hint ()
+ (if (and emms-source-file-directory-hint-p
+ emms-playlist-buffer-p
+ (emms-playlist-track-at))
+ (let ((name (emms-track-get (emms-playlist-track-at) 'name))
+ (type (emms-track-get (emms-playlist-track-at) 'type)))
+ (when (eq type 'file)
+ (file-name-directory name)))
+ emms-source-file-default-directory))
+
+
+;;; Sources
+
+;;;###autoload (autoload 'emms-play-file "emms-source-file" nil t)
+;;;###autoload (autoload 'emms-add-file "emms-source-file" nil t)
+(define-emms-source file (file)
+ "An EMMS source for a single file - either FILE, or queried from the
+user."
+ (interactive (list (read-file-name "Play file: "
+ (emms-source-file-directory-hint)
+ emms-source-file-default-directory
+ t)))
+ (if (file-directory-p file)
+ (emms-source-directory file)
+ (emms-playlist-insert-track
+ (emms-track 'file (expand-file-name file)))))
+
+;;;###autoload (autoload 'emms-play-directory "emms-source-file" nil t)
+;;;###autoload (autoload 'emms-add-directory "emms-source-file" nil t)
+(define-emms-source directory (dir)
+ "An EMMS source for a whole directory tree - either DIR, or queried
+from the user."
+ (interactive (list
+ (emms-read-directory-name "Play directory: "
+ (emms-source-file-directory-hint)
+ emms-source-file-default-directory
+ t)))
+ (mapc (lambda (file)
+ (unless (or (let ((case-fold-search nil))
+ (string-match emms-source-file-exclude-regexp file))
+ (file-directory-p file))
+ (emms-playlist-insert-track
+ (emms-track 'file (expand-file-name file)))))
+ (directory-files dir t (emms-source-file-regex))))
+
+;;;###autoload (autoload 'emms-play-directory-tree "emms-source-file" nil t)
+;;;###autoload (autoload 'emms-add-directory-tree "emms-source-file" nil t)
+(define-emms-source directory-tree (dir)
+ "An EMMS source for multiple directory trees - either DIR, or the
+value of `emms-source-file-default-directory'."
+ (interactive (list
+ (emms-read-directory-name "Play directory tree: "
+ (emms-source-file-directory-hint)
+ emms-source-file-default-directory
+ t)))
+ (let ((files (emms-source-file-directory-tree (expand-file-name dir)
+ (emms-source-file-regex)))
+ (case-fold-search nil))
+ (emms-playlist-ensure-playlist-buffer)
+ (mapc (lambda (file)
+ (unless (string-match emms-source-file-exclude-regexp file)
+ (funcall emms-playlist-insert-track-function
+ (emms-track 'file file))))
+ files)))
+
+;;;###autoload (autoload 'emms-play-find "emms-source-file" nil t)
+;;;###autoload (autoload 'emms-add-find "emms-source-file" nil t)
+(define-emms-source find (dir regex)
+ "An EMMS source that will find files in DIR or
+`emms-source-file-default-directory' that match REGEX."
+ (interactive (list
+ (emms-read-directory-name "Find in directory: "
+ emms-source-file-default-directory
+ emms-source-file-default-directory
+ t)
+ (read-from-minibuffer "Find files matching: ")))
+ (mapc (lambda (file)
+ (unless (let ((case-fold-search nil))
+ (string-match emms-source-file-exclude-regexp file))
+ (emms-playlist-insert-track
+ (emms-track 'file file))))
+ (emms-source-file-directory-tree (expand-file-name dir) regex)))
+
+;;;###autoload (autoload 'emms-play-dired "emms-source-file" nil t)
+;;;###autoload (autoload 'emms-add-dired "emms-source-file" nil t)
+(define-emms-source dired ()
+ "Return all marked files of a dired buffer"
+ (interactive)
+ (mapc (lambda (file)
+ (if (file-directory-p file)
+ (emms-source-directory-tree file)
+ (emms-source-file file)))
+ (with-current-buffer emms-source-old-buffer
+ (dired-get-marked-files))))
+
+
+;;; Helper functions
+
+;;;###autoload
+(defun emms-source-file-directory-tree (dir regex)
+ "Return a list of all files under DIR that match REGEX.
+This function uses `emms-source-file-directory-tree-function'."
+ (message "Building playlist...")
+ (let ((pl (sort (funcall emms-source-file-directory-tree-function
+ dir
+ regex)
+ 'string<)))
+ (message "Building playlist...done")
+ pl))
+
+(defun emms-source-file-directory-tree-internal (dir regex)
+ "Return a list of all files under DIR that match REGEX.
+This function uses only emacs functions, so it might be a bit slow."
+ (let ((files '())
+ (dirs (list dir)))
+ (while dirs
+ (cond
+ ((file-directory-p (car dirs))
+ (if (or (string-match "/\\.\\.?$" (car dirs))
+ (let ((symlink (file-symlink-p (car dirs))))
+ (and symlink
+ (string-equal dir (substring symlink 0 (string-width dir))))))
+ (setq dirs (cdr dirs))
+ (setq dirs
+ (condition-case nil
+ (append (cdr dirs)
+ (directory-files (car dirs)
+ t nil t))
+ (error
+ (cdr dirs))))))
+ ((string-match regex (car dirs))
+ (setq files (cons (car dirs) files)
+ dirs (cdr dirs)))
+ (t
+ (setq dirs (cdr dirs)))))
+ files))
+
+(defun emms-source-file-directory-tree-find (dir regex)
+ "Return a list of all files under DIR that match REGEX.
+This function uses the external find utility. The name for GNU find
+may be supplied using `emms-source-file-gnu-find'."
+ (with-temp-buffer
+ (call-process emms-source-file-gnu-find
+ nil t nil
+ "-L" ; follow symlinks
+ (expand-file-name dir)
+ "-type" "f"
+ "-iregex" (concat ".*\\(" regex "\\).*"))
+ (delete ""
+ (split-string (buffer-substring (point-min)
+ (point-max))
+ "\n"))))
+
+(defmacro emms-with-excluded-directories (directory-list &rest body)
+ "Run BODY while excluding DIRECTORY-LIST."
+ `(let ((emms-source-file-exclude-regexp
+ (concat (or ,emms-source-file-exclude-regexp "")
+ "\\|\\("
+ (or (regexp-opt ,directory-list) "")
+ "\\)")))
+ ,@body))
+
+;;;###autoload
+(defun emms-source-file-regex ()
+ "Return a regexp that matches everything any player (that supports
+files) can play."
+ (mapconcat (lambda (player)
+ (or (emms-player-get player 'regex)
+ ""))
+ emms-player-list
+ "\\|"))
+
+;; emms-locate should be part of a once to be emms-dired, with maybe
+;; file rename after tag functions and so on, but till then i park it
+;; here... :)
+
+;;;###autoload
+(defun emms-locate (regexp)
+ "Search for REGEXP and display the results in a locate buffer"
+ (interactive "sRegexp to search for: ")
+ (require 'locate)
+ (save-window-excursion
+ (set-buffer (get-buffer-create "*EMMS Find*"))
+ (locate-mode)
+ (erase-buffer)
+ (mapc (lambda (elt) (insert (cdr (assoc 'name elt)) "\n"))
+ (emms-source-find emms-source-file-default-directory regexp))
+ (locate-do-setup regexp))
+ (and (not (string-equal (buffer-name) "*EMMS Find*"))
+ (switch-to-buffer-other-window "*EMMS Find*"))
+ (run-hooks 'dired-mode-hook)
+ (dired-next-line 2))
+
+;; Strictly speaking, this does not belong in this file (URLs are not
+;; real files), but it's close enough :-)
+
+;;;###autoload (autoload 'emms-play-url "emms-source-file" nil t)
+;;;###autoload (autoload 'emms-add-url "emms-source-file" nil t)
+(define-emms-source url (url)
+ "An EMMS source for an URL - for example, for streaming."
+ (interactive "sPlay URL: ")
+ (emms-playlist-insert-track (emms-track 'url url)))
+
+;;;###autoload (autoload 'emms-play-streamlist "emms-source-file" nil t)
+;;;###autoload (autoload 'emms-add-streamlist "emms-source-file" nil t)
+(define-emms-source streamlist (streamlist)
+ "An EMMS source for streaming playlists (usually URLs ending in .pls)."
+ (interactive "sPlay streamlist URL: ")
+ (emms-playlist-insert-track (emms-track 'streamlist streamlist)))
+
+
+(provide 'emms-source-file)
+;;; emms-source-file.el ends here