Actually, also this one:
emms-player-extensions.el v0.21:
;; v 0.21 [2005/07/18 16:42:51] In function `emms-seek', add a call for
;; `emms-lyric-seek' (defined in `emms-lyric.el').
emms-lyric.el v0.3
;; v 0.3 [2005/07/19 17:53:25] Add `emms-lyric-find-lyric' for find
;; lyric files in local repository `emms-lyric-dir'. Rewrite
;; `emms-lyric-setup' to support more lyric formats.
;; v 0.2 [2005/07/18 16:10:02] Fix `emms-lyric-pause' bug. Now it works
;; fine. Add `emms-lyric-seek', but which does not work very well
;; currently.
--
William
;;; emms-lyric.el --- Display lyrics synchronically
;; Copyright (C) 2005 William XWL
;; Author: William XWL <[EMAIL PROTECTED]>
;; Maintainer: William XWL <[EMAIL PROTECTED]>
;; Created: 2005/07/17 15:08:18
;; Version: v 0.3
;; Keywords: emms music lyric
;; Last updated: 2005/07/19 23:32:26
;; This file is not part of GNU Emacs.
;;{{{ GPL
;; 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:
;; This package enables you to play music files and display lyrics
;; synchronically! :-) Note, you have to install emms package and
;; emms-player-extensions.el(written by me as well) first.
;; Put this file into your load-path and the following into your
;; ~/.emacs:
;; (require 'emms-lyric)
;; Take a look at the "User Customizable" part for possible personal
;; customizations.
;;; Change Log:
;; v 0.3 [2005/07/19 17:53:25] Add `emms-lyric-find-lyric' for find
;; lyric files in local repository `emms-lyric-dir'. Rewrite
;; `emms-lyric-setup' to support more lyric formats.
;; v 0.2 [2005/07/18 16:10:02] Fix `emms-lyric-pause' bug. Now it works
;; fine. Add `emms-lyric-seek', but which does not work very well
;; currently.
;; v 0.1 [2005/07/17 20:07:30] Initial version.
;;; Known bugs:
;; 1. Sometimes music playing would be blocked by some process, like
;; startup Gnus, while emms-lyric still goes on, thus make music and
;; lyrics asynchronical.
;; 2. `emms-lyric-seek' does work, but not very well. I've no idea
;; currently.
;;; Todo:
;; 1. Fix bugs in `emms-lyric-seek'.
;; 2. Maybe the lyric setup should run before `emms-start'.
;; 3. Give a user a chance to choose when finding out multiple lyrics.
;; 4. Search lyrics from internet ?
;;; Code:
(require 'emms)
(require 'emms-player-extensions)
(require 'emms-source-file)
;;; User Customizations
(defvar emms-lyric-display-lyric-p t
"Whether to diplay lyrics or not.")
(defvar emms-lyric-display-lyric-on-mode-line t
"Display lyrics on mode line.")
(defvar emms-lyric-display-lyric-on-minibuffer nil
"Display lyrics on minibuffer.")
(defvar emms-lyric-dir ""
"The directory of local Lyric files. `emms-lyric-find-lyric' will look
for lyrics here.")
;;; User Interfaces
(defun emms-lyric-stop ()
"Stop displaying lyrics."
(interactive)
(when emms-lyric-display-lyric-p
(cancel-function-timers 'emms-lyric-display)
(unless emms-player-paused-p
(setq emms-lyric-alist nil
emms-lyric-timers nil
emms-lyric-mode-line-string ""))))
(add-hook 'emms-player-stopped-hook 'emms-lyric-stop)
(add-hook 'emms-player-finished-hook 'emms-lyric-stop)
;;; Variables:
(defvar emms-lyric-alist nil
"a list of the form: '((time0 lyric0) (time1 lyric1)...)). In short,
at time-i, display lyric-i.")
(defvar emms-lyric-timers nil
"timers for displaying lyric.")
(defvar emms-lyric-start-time nil
"emms lyric start time.")
(defvar emms-lyric-pause-time nil
"emms lyric pause time.")
(defvar emms-lyric-elapsed-time 0
"How long time has emms lyric played.")
(defvar emms-lyric-mode-line-string ""
"current lyric.")
;;; Functions:
(defun emms-lyric-setup (file)
"Read FILE's lyric file (LRC format) if found. The lyric file should
end up with \".lrc\", its contents looks like:
[00:39.67]I love you, Emacs!
or
[00:39]I love you, Emacs!
e.g,
foo.mp3 foo.lrc
FILE is foo.mp3 here. To find foo.lrc, first looks up in current
directory, if not found, continue looking up in `emms-lyric-dir'."
(let ((lrc-file
(replace-regexp-in-string "\\.mp3$" ".lrc" file)))
(unless (file-exists-p lrc-file)
(setq lrc-file (emms-lyric-find-lyric file)))
(if (and lrc-file
(file-exists-p lrc-file)
(not (string= lrc-file "")))
(with-temp-buffer
(insert-file-contents lrc-file)
(while (search-forward-regexp "\\[[0-9:.]+\\].*" nil t)
(let ((lyric-string (match-string 0))
(time 0)
(lyric ""))
(setq lyric
(replace-regexp-in-string ".*\\]" "" lyric-string))
(while (string-match "\\[[0-9:.]+\\]" lyric-string)
(let ((time-string (match-string 0 lyric-string)))
(setq time (+ (* (string-to-number
(substring time-string 1 3))
60)
(string-to-number
(substring
time-string 4 (1- (length time-string)))))
lyric-string (substring lyric-string (length
time-string))
emms-lyric-alist (append emms-lyric-alist `((,time
,lyric))))
(setq time 0)))))
t)
(setq emms-lyric-alist nil)
;; (message "Lyric file not found.")
nil)))
(defun emms-lyric-start ()
"Start displaying lryics on the mode line at right time. User should
not call this interactively. But together with `emms-start'."
(when (and emms-lyric-display-lyric-p
(emms-lyric-setup
(cdaddr (emms-playlist-current-track))))
(setq emms-lyric-timers
(mapcar '(lambda (arg)
(let ((time (car arg))
(lyric (cadr arg)))
(run-at-time
(concat (number-to-string time) " sec")
nil 'emms-lyric-display lyric)))
emms-lyric-alist))
(setq emms-lyric-start-time (current-time)
emms-lyric-pause-time nil
emms-lyric-elapsed-time 0)))
(add-hook 'emms-player-started-hook 'emms-lyric-start)
(defun emms-lyric-pause ()
"Pause displaying lyrics. User should not call this interactively. But
called by `emms-pause'."
(when emms-lyric-display-lyric-p
(if emms-player-paused-p
(progn
(emms-lyric-stop)
(setq emms-lyric-pause-time (current-time)))
(when emms-lyric-pause-time
(setq emms-lyric-elapsed-time
(+ (time-to-seconds
(time-subtract emms-lyric-pause-time
emms-lyric-start-time))
emms-lyric-elapsed-time)))
(emms-lyric-do-continue))))
(add-hook 'emms-player-paused-hook 'emms-lyric-pause)
(defun emms-lyric-do-continue ()
"Continue displaying lyrics. Will be called by `emms-lyric-pause', and
that's why it has a do-continue name."
(setq emms-lyric-start-time (current-time))
(setq emms-lyric-timers
(mapcar
'(lambda (arg)
(let ((time (- (car arg) emms-lyric-elapsed-time))
(lyric (cadr arg)))
(when (>= time 0)
(run-at-time
(concat (number-to-string time) " sec")
nil 'emms-lyric-display lyric))))
emms-lyric-alist)))
(defun emms-lyric-seek (sec)
"Seek forward or backward lyrics.
SEC is a second string. e.g., \"+10\", \"-5\"."
(when emms-lyric-display-lyric-p
(let ((paused-orig emms-player-paused-p))
(setq emms-player-paused-p t)
(emms-lyric-stop)
(setq emms-player-paused-p paused-orig))
(let ((sec-num (string-to-number sec)))
(setq emms-lyric-elapsed-time
(+ emms-lyric-elapsed-time
(time-to-seconds
(time-subtract (current-time)
emms-lyric-start-time))
sec-num))
(when (< emms-lyric-elapsed-time 0) ; back to start point
(setq emms-lyric-elapsed-time 0))
(if (> sec-num 0) ; ajust a bit, why?
(setq sec-num (+ sec-num 4))
(setq sec-num (- sec-num 4))))
(emms-lyric-do-continue)))
(defun emms-lyric-mode-line ()
"Add lyric to the mode line."
(unless (member 'emms-lyric-mode-line-string
global-mode-string)
(setq global-mode-string
(append global-mode-string
'(emms-lyric-mode-line-string)))))
(defun emms-lyric-display (lyric)
"Display lyric.
LYRIC is current playing lyric.
See `emms-lyric-display-lyric-on-mode-line' and
`emms-lyric-display-lyric-on-minibuffer' on how to config where to
display."
(when emms-lyric-display-lyric-p
(when emms-lyric-display-lyric-on-mode-line
(emms-lyric-mode-line)
(setq emms-lyric-mode-line-string lyric)
(force-mode-line-update))
(when emms-lyric-display-lyric-on-minibuffer
(message lyric))))
(defun emms-lyric-find-lyric (file)
"Given a mp3 file, use `emms-source-file-gnu-find' to look for the
right lrc file for it. You should specify a valid `emms-lyric-dir'.
FILE is a mp3 file."
(unless (string= emms-lyric-dir "")
;; If find two or more lyric files, only return the first one. Good
;; luck! :-)
(car (split-string
(shell-command-to-string
(concat emms-source-file-gnu-find " "
emms-lyric-dir " -name "
(replace-regexp-in-string
"\\.mp3$" ".lrc"
(file-name-nondirectory file))))
"\n"))))
(provide 'emms-lyric)
;;; emms-lyric.el ends here
;;; emms-player-extensions.el - Add more user control functions for EMMS
;; Copyright (C) 2005 William XWL
;; Author: William XWL <[EMAIL PROTECTED]>
;; Version: v 0.21
;; Keywords: emms music mp3
;; Last updated: 2005/07/19 23:31:40
;; This file is not part of GNU Emacs.
;;{{{ GPL
;; 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:
;; This package add some more user control functions to EMMS, including
;; pause, seek, repeat. When "repeat", an or two extra stars will be
;; inserted in front of the `emms-mode-line-string', stands for
;; repeating current track and all tracks respectively.
;; Note: pause and seek only works with mplayer's slave mode. Put
;; something like this to your .emacs first:
;;
;; (setq emms-player-mplayer-command-name "mplayer"
;; emms-player-mplayer-parameters '("-slave")
;; emms-player-list
;; '(emms-player-mplayer
;; emms-player-mplayer-playlist
;; emms-player-mpg321
;; emms-player-ogg123))
;; To use, put this file to your load-path and the following(together
;; with your other emms's settings) to your .emacs:
;;
;; (require 'emms-player-extensions)
;;; Change Log
;; v 0.21 [2005/07/18 16:42:51] In function `emms-seek', add a call for
;; `emms-lyric-seek' (defined in `emms-lyric.el').
;; v 0.2 [2005/07/17 20:22:53] And `emms-player-paused-p',
;; `emms-player-player-paused-hook', and some modifications to
;; cooperate with another package(`emms-lyric.el'). Rename this
;; file from emms-patch.el to emms-player-extensions.el.
;; v 0.1 The initial version. Add `emms-pause', `emms-seek',
;; `emms-repeat-curr', `emms-unrepeat-curr', `emms-repeat-all',
;; `emms-unrepeat-all'.
;;; Todo:
;; Hopefully, this package will change synchronically with
;; `emms-lyric.el' for cooperations.
;;; Codes:
(require 'emms)
;;; Variables:
(defvar emms-player-paused-p nil
"The EMMS player paused.")
(defvar emms-player-paused-hook nil
"*Hook run when an EMMS player pauses playing.")
;; how to pass parameters to a hook ?
;; (defvar emms-player-seeked-hook nil
;; "*Hook run when an EMMS player seeks forward or backward.")
;;; User Interfaces:
(defun emms-pause ()
"Pause the current player."
(interactive)
(when emms-player-playing-p
(if (equal emms-player-playing-p
'emms-player-mplayer)
(funcall (emms-player-get emms-player-playing-p 'pause))
(message "Pause is only available for mplayer."))))
(defun emms-seek (second)
"Seek forward/backward.
SECOND is a string like \"-10\"."
(interactive)
(when emms-player-playing-p
(if (equal emms-player-playing-p
'emms-player-mplayer)
(funcall (emms-player-get emms-player-playing-p 'seek) second)
(message "Seek is only available for mplayer."))))
(defun emms-repeat-curr ()
"Repeat current track."
(interactive)
(when emms-player-playing-p
(funcall (emms-player-get emms-player-playing-p 'repeat-curr))))
(defun emms-unrepeat-curr ()
"Stop repeating current track."
(interactive)
(when emms-player-playing-p
(funcall (emms-player-get emms-player-playing-p 'unrepeat-curr))))
(defun emms-repeat-all ()
"Repeat all tracks."
(interactive)
(when emms-player-playing-p
(funcall (emms-player-get emms-player-playing-p 'repeat-all))))
(defun emms-unrepeat-all ()
"Stop repeating all tracks."
(interactive)
(when emms-player-playing-p
(funcall (emms-player-get emms-player-playing-p 'unrepeat-all))))
;;; Functions:
;; pause, seek(mplayer only)
(emms-player-set emms-player-mplayer
'pause
'emms-player-mplayer-pause)
(emms-player-set emms-player-mplayer
'seek
'emms-player-mplayer-seek)
(defun emms-player-mplayer-pause ()
"Depends on mplayer's -slave mode."
(process-send-string
emms-player-simple-process-name "pause\n")
(if emms-player-paused-p
(setq emms-player-paused-p nil)
(setq emms-player-paused-p t))
(run-hooks 'emms-player-paused-hook))
(defun emms-player-mplayer-seek (sec)
"Depends on mplayer's -slave mode."
(process-send-string
emms-player-simple-process-name
(concat "seek " sec "\n"))
(emms-lyric-seek sec))
;; repeat(any player)
(mapcar '(lambda (player) ; set up
(mapcar* '(lambda (name value)
(emms-player-set player
name
value))
'(repeat-curr
unrepeat-curr
repeat-all
unrepeat-all)
'(emms-player-any-repeat-curr
emms-player-any-unrepeat-curr
emms-player-any-repeat-all
emms-player-any-unrepeat-curr)))
emms-player-list)
(setq emms-repeat-curr-track nil) ; *new* - repeat current track
(setq emms-repeat-playlist nil) ; repeat all tracks
(defun emms-next-noerror () ; redefine this function
"Start playing the next track in the EMMS playlist.
Unlike `emms-next', this function doesn't signal an error when called
at the end of the playlist.
This function should only be called when no player is playing.
This is a good function to put in `emms-player-finished-hook'."
(interactive)
(when emms-player-playing-p
(error "A track is already being played"))
(cond (emms-repeat-curr-track ; repeat current track only.
(emms-start))
((emms-playlist-next)
(emms-start))
(emms-repeat-playlist
(setq emms-playlist-current 0)
(emms-start))
(t
(message "No next track in playlist"))))
(defun emms-player-any-repeat-curr ()
(setq emms-repeat-curr-track t)
(emms-set-repeat-curr-mark)
(message "Repeat current track."))
(defun emms-player-any-unrepeat-curr ()
(setq emms-repeat-curr-track nil)
(emms-set-unrepeat-curr-mark)
(message "Stop repeating current track."))
(defun emms-player-any-repeat-all ()
(setq emms-repeat-curr-track nil
emms-repeat-playlist t)
(emms-set-repeat-all-mark)
(message "Repeat all tracks."))
(defun emms-player-any-unrepeat-all ()
(setq emms-repeat-curr-track nil
emms-repeat-playlist nil)
(emms-set-unrepeat-all-mark)
(message "Stop Repeating all tracks."))
(defun emms-set-repeat-curr-mark ()
"Add a star at front indicating repeats."
(setq emms-mode-line-format " [ * %s ] "
emms-mode-line-string
(funcall emms-mode-line-mode-line-function)))
(defun emms-set-unrepeat-curr-mark ()
"Remove star mark at front."
(setq emms-mode-line-format " [ %s ] "
emms-mode-line-string
(funcall emms-mode-line-mode-line-function)))
(defun emms-set-repeat-all-mark ()
"Add a star at front indicating repeats."
(setq emms-mode-line-format " [ ** %s ] "
emms-mode-line-string
(funcall emms-mode-line-mode-line-function)))
(defun emms-set-unrepeat-all-mark ()
"Remove star mark at front."
(setq emms-mode-line-format " [ %s ] "
emms-mode-line-string
(funcall emms-mode-line-mode-line-function)))
(provide 'emms-player-extensions)
;;; emms-player-extensions.el ends here
_______________________________________________
Emms-help mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/emms-help