From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Thien-Thi Nguyen Newsgroups: gmane.emacs.devel Subject: Re: Sound in Emacs Date: Sat, 08 Oct 2011 16:22:11 +0200 Message-ID: <87pqi7d0mk.fsf@ambire.localdomain> References: <4E8AAF3E.7050600@swipnet.se> <878vp0z3oz.fsf@gnus.org> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: dough.gmane.org 1318083870 27196 80.91.229.12 (8 Oct 2011 14:24:30 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Sat, 8 Oct 2011 14:24:30 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat Oct 08 16:24:27 2011 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1RCXpB-00074W-K0 for ged-emacs-devel@m.gmane.org; Sat, 08 Oct 2011 16:24:25 +0200 Original-Received: from localhost ([::1]:35306 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RCXpB-00070P-7D for ged-emacs-devel@m.gmane.org; Sat, 08 Oct 2011 10:24:25 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:52087) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RCXp8-00070K-SX for emacs-devel@gnu.org; Sat, 08 Oct 2011 10:24:23 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RCXp5-000703-GG for emacs-devel@gnu.org; Sat, 08 Oct 2011 10:24:22 -0400 Original-Received: from smtp205.alice.it ([82.57.200.101]:46323) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RCXp5-0006xv-3Y for emacs-devel@gnu.org; Sat, 08 Oct 2011 10:24:19 -0400 Original-Received: from ambire.localdomain (79.50.71.227) by smtp205.alice.it (8.5.124.08) id 4E8575B700D5E856 for emacs-devel@gnu.org; Sat, 8 Oct 2011 16:23:56 +0200 Original-Received: from ttn by ambire.localdomain with local (Exim 4.69) (envelope-from ) id 1RCXn1-0000us-MM for emacs-devel@gnu.org; Sat, 08 Oct 2011 16:22:11 +0200 In-Reply-To: <878vp0z3oz.fsf@gnus.org> (Lars Ingebrigtsen's message of "Wed, 05 Oct 2011 02:23:40 +0200") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 82.57.200.101 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:144747 Archived-At: --=-=-= Content-Type: text/plain () Lars Ingebrigtsen () Wed, 05 Oct 2011 02:23:40 +0200 then playing music though Emacs would Just Work instead of being something you'd have to work at to get. Are you sure? I get the impression sound reproduction is more timing sensitive than, say, image display. But it's like ImageMagick support. Does displaying images inside Emacs give you a better experience? I think it does. And I have a feeling the same would be the case with sound support. Hmmm. FWIW, here is a heavily modified TRAT, originally by Vikas Gorur. There are other playlist manglers of course... --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=trat.el Content-Transfer-Encoding: quoted-printable ;;; trat.el ;; (C) 2007 Vikas Gorur ;; ;; 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 3 of ;; the License, 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., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301 USA ;;; Commentary: ;; TRAT (Tail Recursive Acronym: TRAT) is a music player for Emacs ;; that uses xmms2 as its backend ;; ;; Trat is also the capital of the Trat province in Thailand. ;;; Code: (require 'cl) (defconst trat-minute-string ".........:.........:.........:.........:.........:.........:") (defvar *trat-volume* 24) (defvar trat-mode-map nil "Keymap for the trat major mode.") (defun trat-numeric (string) (let ((sec (string-to-number (substring string -2)))) (setq string (substring string 0 -3)) (list (if (< 2 (length string)) (+ (* 60 (string-to-number (substring string 0 -3))) (string-to-number (substring string -2))) (string-to-number string)) sec))) (defun trat-compute-disp (full) (destructuring-bind (min sec) (trat-numeric full) (append (mapcar (lambda (n) (format "%s %3d:00\n" trat-minute-string (1+ n))) (number-sequence 0 (1- min))) (list (format "%s%s %3d:%02d\n" (substring trat-minute-string 0 sec) (make-string (- 60 sec) ?\s) min sec))))) (defun trat-process-filter (proc string) (with-current-buffer (get-buffer "*trat*") (let ((orig (point)) (buffer-read-only nil) (start 0)) (goto-char (process-mark proc)) (let (seen) (while (string-match "\r" string start) (setq seen t start (match-end 0))) (setq string (substring string start)) (when seen (delete-region (process-get proc 'pos) (point)))) (subst-char-in-string ?\n ?\s string t) (insert-before-markers string) (when (string-match "^[^:]+: \\(.+\\): \\([0-9:]+\\) of \\([0-9:]+\\)= " string) (let* ((what (match-string 1 string)) (part (match-string 2 string)) (full (match-string 3 string)) (prev (process-get proc 'prev)) (same (equal what prev)) (ov (process-get proc 'ov))) (unless same (let ((end (process-get proc 'end))) (delete-region (process-mark proc) end) (insert "\n") (mapc 'insert (trat-compute-disp full)) (set-marker end (point))) (when (search-forward "Playlist:\n" nil t) (call-process "xmms2" nil t nil "list") (delete-region (point) (point-max)) (re-search-backward "^->" nil t) (setq orig (point)))) (process-put proc 'prev what) (destructuring-bind (min sec) (trat-numeric part) (let ((ofs (+ (process-mark proc) (* 68 min) sec))) (when (and (zerop sec) (not (zerop min))) (setq ofs (- ofs 8))) (if (zerop (+ min sec)) (delete-overlay ov) (move-overlay ov ofs (1+ ofs))) ' (message "%s %S" (if same 'SAME 'DIFF) string))))) (goto-char orig)))) (defun trat-update-buffer () (let ((buf (get-buffer-create "*trat*"))) (set-buffer buf) (let ((buffer-read-only nil) (title "Tail Recursive Acronym: TRAT")) (erase-buffer) (add-text-properties 0 (length title) '(face (:weight bold :foreground "yellow")) title) (insert title) (center-line) (insert "\n") (insert (format "Volume: %3d/100\n" *trat-volume*)) (unless (get-process "trat") (let* ((pos (point)) (ov (make-overlay pos pos)) (proc (start-process "trat" buf "xmms2" "status"))) (process-put proc 'pos pos) (overlay-put ov 'display "o") (process-put proc 'ov ov) (set-marker (process-mark proc) pos) (process-put proc 'end (set-marker (make-marker) pos)) (set-process-filter proc 'trat-process-filter))) (insert (propertize "\n\nPlaylist:\n" 'face '(:weight bold :foreground "blue"))) (call-process "xmms2" nil t nil "list") (re-search-backward "^->" nil t)) (setq buffer-read-only t))) (defun trat-do (command &rest args) (apply 'call-process "xmms2" nil nil nil command args)) (defun trat-zonk () "Stop playing and clear the playlist." (interactive) (trat-do "stop") (trat-do "clear") (trat-update-buffer)) (defun trat-jump (idx) "Jump to IDX and start playing." (interactive "nJump to: ") (trat-do "stop") (trat-do "jump" (if (numberp idx) (number-to-string idx) idx)) (trat-do "play")) (defun trat-idx () "Return the index number (as a string) if on an entry, else nil." (beginning-of-line) (if (looking-at "\\(->\\| \\).\\([0-9]+\\)") (match-string 2) (message "(No playlist entry here.)") nil)) (defun trat-jump-here () "Jump to the entry at point and start playing it." (interactive) (let ((idx (trat-idx))) (when idx (trat-jump idx)))) (defun trat-enqueue (path) "Enqueue the song (or songs if given a directory) in the playlist." (interactive "fEnqueue: ") (trat-do (if (file-directory-p path) "radd" "add") (expand-file-name path)) (trat-update-buffer)) (defun trat-enqueue-url (url) "Same as =E2=80=98trat-enqueue=E2=80=99 except completion is not attempte= d." (interactive "sURL to enqueue: ") (trat-do "add" url) (trat-update-buffer)) (defun trat-remove () "Remove an entry from the playlist." (interactive) (let ((idx (trat-idx)) (p (point))) (when idx (trat-do "remove" idx) (trat-update-buffer) (goto-char p) (when (eolp) (forward-line -1)) (message "Removed entry %s" idx)))) (defun trat-next () "Skip the current song and play next song in playlist." (interactive) (trat-do "next") (trat-update-buffer)) (defun trat-toggleplay () "Pause or unpause playing." (interactive) (trat-do "toggleplay") (message "Pause toggled")) (defun trat-stop () "Stop playing." (interactive) (trat-do "stop")) (defun trat-shuffle () "Shuffle the playlist." (interactive) (trat-do "shuffle") (trat-update-buffer)) (defun trat-change-volume (n) "Add N to the volume, clamping to [0,100]." (let ((new (+ *trat-volume* n))) (when (> 0 new) (setq new 0)) (when (< 100 new) (setq new 100)) (call-process "xmms2" nil nil nil "volume" (number-to-string new)) (with-current-buffer (get-buffer "*trat*") (save-excursion (goto-char (point-min)) (forward-line 1) (forward-char 8) (let (buffer-read-only) (delete-char 3) (insert (format "%3d" new))))) (setq *trat-volume* new))) (defun trat-decrease-volume () "Decrease the volume by 4." (interactive) (trat-change-volume -4)) (defun trat-increase-volume () "Increase the volume by 4." (interactive) (trat-change-volume 4)) (defun trat-quit () "Kill the *trat* buffer." (interactive) (kill-buffer (get-buffer "*trat*"))) (defun trat-mode () "Tail Recursive Acronym: TRAT is a music player that runs inside Emacs, using xmms2(1) to do the actual playing. The following commands work in the *trat* buffer: \\{trat-mode-map}" (interactive) (kill-all-local-variables) (setq major-mode 'trat-mode mode-name "TRAT") (set (make-local-variable 'kill-buffer-query-functions) nil) (use-local-map trat-mode-map)) (defun trat () (interactive) (trat-update-buffer) (switch-to-buffer (get-buffer "*trat*")) (trat-mode)) (defun trat-dwim () "Run ttn's version of Tail Recursive Acronym TRAT (or not). If the current buffer is the *trat* buffer, quit it. If there is a *trat* buffer, switch to it. If there is no *trat* buffer, start it." (interactive) (let ((prev (get-buffer "*trat*"))) (cond ((eq (current-buffer) prev) (trat-quit)) (prev (switch-to-buffer prev)) (t (trat))))) (unless trat-mode-map (setq trat-mode-map (let ((m (make-sparse-keymap)) (init '("[" previous-line "]" next-line "z" trat-zonk "j" trat-jump "\C-m" trat-jump-here "e" trat-enqueue "\M-e" trat-enqueue-url "d" trat-remove "n" trat-next " " trat-toggleplay "s" trat-stop [f9] trat-shuffle [f10] trat-decrease-volume [f11] trat-increase-volume "q" trat-quit))) (while init (define-key m (car init) (cadr init)) (setq init (cddr init))) m))) (provide 'trat) ;;; trat.el ends here --=-=-=--